summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorSebastien Merle <sebastien@netdef.org>2020-07-20 13:43:54 +0200
committerSebastien Merle <sebastien@netdef.org>2020-08-07 11:08:49 +0200
commit31f937fb43f4920d14de6193de440279fbd5d99e (patch)
tree166a67318cfb4177398a40baca7d8fb4029fd10b /lib
parentlib: add possibility to search non-recursively for NB node entries (diff)
downloadfrr-31f937fb43f4920d14de6193de440279fbd5d99e.tar.xz
frr-31f937fb43f4920d14de6193de440279fbd5d99e.zip
lib, zebra: Add SR-TE policy infrastructure to zebra
For the sake of Segment Routing (SR) and Traffic Engineering (TE) Policies there's a need for additional infrastructure within zebra. The infrastructure in this PR is supposed to manage such policies in terms of installing binding SIDs and LSPs. Also it is capable of managing MPLS labels using the label manager, keeping track of nexthops (for resolving labels) and notifying interested parties about changes of a policy/LSP state. Further it enables a route map mechanism for BGP and SR-TE colors such that learned BGP routes can be mapped onto SR-TE Policies. This PR does not introduce any usable features by now, it is just infrastructure for other upcoming PRs which will introduce 'pathd', a new SR-TE daemon. Co-authored-by: Renato Westphal <renato@opensourcerouting.org> Co-authored-by: GalaxyGorilla <sascha@netdef.org> Signed-off-by: Sebastien Merle <sebastien@netdef.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/command.h2
-rw-r--r--lib/ipaddr.h14
-rw-r--r--lib/log.c3
-rw-r--r--lib/mpls.h1
-rw-r--r--lib/nexthop.c6
-rw-r--r--lib/nexthop.h4
-rw-r--r--lib/privs.h1
-rw-r--r--lib/route_types.txt1
-rw-r--r--lib/routemap.c62
-rw-r--r--lib/routemap.h16
-rw-r--r--lib/srte.h56
-rw-r--r--lib/stream.c58
-rw-r--r--lib/stream.h8
-rw-r--r--lib/subdir.am1
-rw-r--r--lib/zclient.c137
-rw-r--r--lib/zclient.h43
16 files changed, 397 insertions, 16 deletions
diff --git a/lib/command.h b/lib/command.h
index a7a2eaf86..e20bfe331 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -367,6 +367,8 @@ struct cmd_node {
#define SHOW_STR "Show running system information\n"
#define IP_STR "IP information\n"
#define IPV6_STR "IPv6 information\n"
+#define SRTE_STR "SR-TE information\n"
+#define SRTE_COLOR_STR "SR-TE Color information\n"
#define NO_STR "Negate a command or set its defaults\n"
#define REDIST_STR "Redistribute information from another routing protocol\n"
#define CLEAR_STR "Reset functions\n"
diff --git a/lib/ipaddr.h b/lib/ipaddr.h
index aa5b4a321..730c7ce13 100644
--- a/lib/ipaddr.h
+++ b/lib/ipaddr.h
@@ -25,6 +25,8 @@
#include <zebra.h>
+#include "lib/log.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -59,6 +61,18 @@ struct ipaddr {
#define IPADDRSZ(p) \
(IS_IPADDR_V4((p)) ? sizeof(struct in_addr) : sizeof(struct in6_addr))
+static inline int ipaddr_family(const struct ipaddr *ip)
+{
+ switch (ip->ipa_type) {
+ case IPADDR_V4:
+ return AF_INET;
+ case IPADDR_V6:
+ return AF_INET6;
+ default:
+ return AF_UNSPEC;
+ }
+}
+
static inline int str2ipaddr(const char *str, struct ipaddr *ip)
{
int ret;
diff --git a/lib/log.c b/lib/log.c
index bbce4eb79..202d6d858 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -384,6 +384,9 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD),
DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE),
DESC_ENTRY(ZEBRA_MPLS_LABELS_REPLACE),
+ DESC_ENTRY(ZEBRA_SR_POLICY_SET),
+ DESC_ENTRY(ZEBRA_SR_POLICY_DELETE),
+ DESC_ENTRY(ZEBRA_SR_POLICY_NOTIFY_STATUS),
DESC_ENTRY(ZEBRA_IPMR_ROUTE_STATS),
DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT),
DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT_ASYNC),
diff --git a/lib/mpls.h b/lib/mpls.h
index 126dbf753..8922a3666 100644
--- a/lib/mpls.h
+++ b/lib/mpls.h
@@ -129,6 +129,7 @@ enum lsp_types_t {
ZEBRA_LSP_OSPF_SR = 4,/* OSPF Segment Routing LSP. */
ZEBRA_LSP_ISIS_SR = 5,/* IS-IS Segment Routing LSP. */
ZEBRA_LSP_SHARP = 6, /* Identifier for test protocol */
+ ZEBRA_LSP_SRTE = 7, /* SR-TE LSP */
};
/* Functions for basic label operations. */
diff --git a/lib/nexthop.c b/lib/nexthop.c
index 28d96a539..0ea72d03e 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -152,6 +152,11 @@ static int _nexthop_cmp_no_labels(const struct nexthop *next1,
break;
}
+ if (next1->srte_color < next2->srte_color)
+ return -1;
+ if (next1->srte_color > next2->srte_color)
+ return 1;
+
ret = _nexthop_source_cmp(next1, next2);
if (ret != 0)
goto done;
@@ -643,6 +648,7 @@ void nexthop_copy_no_recurse(struct nexthop *copy,
if (copy->backup_num > 0)
memcpy(copy->backup_idx, nexthop->backup_idx, copy->backup_num);
+ copy->srte_color = nexthop->srte_color;
memcpy(&copy->gate, &nexthop->gate, sizeof(nexthop->gate));
memcpy(&copy->src, &nexthop->src, sizeof(nexthop->src));
memcpy(&copy->rmap_src, &nexthop->rmap_src, sizeof(nexthop->rmap_src));
diff --git a/lib/nexthop.h b/lib/nexthop.h
index ed40cc7ee..cadcea1f4 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -98,6 +98,7 @@ struct nexthop {
*/
#define NEXTHOP_FLAG_RNH_FILTERED (1 << 5) /* rmap filtered, used by rnh */
#define NEXTHOP_FLAG_HAS_BACKUP (1 << 6) /* Backup nexthop index is set */
+#define NEXTHOP_FLAG_SRTE (1 << 7) /* SR-TE color used for BGP traffic */
#define NEXTHOP_IS_ACTIVE(flags) \
(CHECK_FLAG(flags, NEXTHOP_FLAG_ACTIVE) \
@@ -141,6 +142,9 @@ struct nexthop {
union {
vni_t vni;
} nh_encap;
+
+ /* SR-TE color used for matching SR-TE policies */
+ uint32_t srte_color;
};
/* Utility to append one nexthop to another. */
diff --git a/lib/privs.h b/lib/privs.h
index db5707d67..18ba8e888 100644
--- a/lib/privs.h
+++ b/lib/privs.h
@@ -24,6 +24,7 @@
#define _ZEBRA_PRIVS_H
#include <pthread.h>
+#include <stdint.h>
#include "lib/queue.h"
#ifdef __cplusplus
diff --git a/lib/route_types.txt b/lib/route_types.txt
index 71d0a4644..b549c11cf 100644
--- a/lib/route_types.txt
+++ b/lib/route_types.txt
@@ -85,6 +85,7 @@ ZEBRA_ROUTE_BFD, bfd, bfdd, '-', 0, 0, 0, "BFD"
ZEBRA_ROUTE_OPENFABRIC, openfabric, fabricd, 'f', 1, 1, 1, "OpenFabric"
ZEBRA_ROUTE_VRRP, vrrp, vrrpd, '-', 0, 0, 0, "VRRP"
ZEBRA_ROUTE_NHG, nhg, none, '-', 0, 0, 0, "Nexthop Group"
+ZEBRA_ROUTE_SRTE, srte, none, '-', 0, 0, 0, "SR-TE"
ZEBRA_ROUTE_ALL, wildcard, none, '-', 0, 0, 0, "-"
diff --git a/lib/routemap.c b/lib/routemap.c
index df9a6a33e..fb7086002 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -263,6 +263,24 @@ void route_map_no_match_tag_hook(int (*func)(
rmap_match_set_hook.no_match_tag = func;
}
+/* set sr-te color */
+void route_map_set_srte_color_hook(int (*func)(struct vty *vty,
+ struct route_map_index *index,
+ const char *command,
+ const char *arg))
+{
+ rmap_match_set_hook.set_srte_color = func;
+}
+
+/* no set sr-te color */
+void route_map_no_set_srte_color_hook(int (*func)(struct vty *vty,
+ struct route_map_index *index,
+ const char *command,
+ const char *arg))
+{
+ rmap_match_set_hook.no_set_srte_color = func;
+}
+
/* set ip nexthop */
void route_map_set_ip_nexthop_hook(int (*func)(struct vty *vty,
struct route_map_index *index,
@@ -2613,6 +2631,47 @@ static unsigned int route_map_dep_data_hash_make_key(const void *p)
return string_hash_make(dep_data->rname);
}
+DEFUN (set_srte_color,
+ set_srte_color_cmd,
+ "set sr-te color [(1-4294967295)]",
+ SET_STR
+ SRTE_STR
+ SRTE_COLOR_STR
+ "Color of the SR-TE Policies to match with\n")
+{
+ VTY_DECLVAR_CONTEXT(route_map_index, index);
+ int idx = 0;
+ char *arg = argv_find(argv, argc, "(1-4294967295)", &idx)
+ ? argv[idx]->arg
+ : NULL;
+
+ if (rmap_match_set_hook.set_srte_color)
+ return rmap_match_set_hook.set_srte_color(vty, index,
+ "sr-te color", arg);
+ return CMD_SUCCESS;
+}
+
+DEFUN (no_set_srte_color,
+ no_set_srte_color_cmd,
+ "no set sr-te color [(1-4294967295)]",
+ NO_STR
+ SET_STR
+ SRTE_STR
+ SRTE_COLOR_STR
+ "Color of the SR-TE Policies to match with\n")
+{
+ VTY_DECLVAR_CONTEXT(route_map_index, index);
+ int idx = 0;
+ char *arg = argv_find(argv, argc, "(1-4294967295)", &idx)
+ ? argv[idx]->arg
+ : NULL;
+
+ if (rmap_match_set_hook.no_set_srte_color)
+ return rmap_match_set_hook.no_set_srte_color(
+ vty, index, "sr-te color", arg);
+ return CMD_SUCCESS;
+}
+
static void *route_map_dep_hash_alloc(void *p)
{
char *dep_name = (char *)p;
@@ -3237,5 +3296,8 @@ void route_map_init(void)
install_element(RMAP_NODE, &routemap_optimization_cmd);
install_element(RMAP_NODE, &no_routemap_optimization_cmd);
+ install_element(RMAP_NODE, &set_srte_color_cmd);
+ install_element(RMAP_NODE, &no_set_srte_color_cmd);
+
install_element(ENABLE_NODE, &show_route_map_pfx_tbl_cmd);
}
diff --git a/lib/routemap.h b/lib/routemap.h
index 62195b834..64da4b87e 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -424,6 +424,14 @@ extern void route_map_match_tag_hook(int (*func)(
extern void route_map_no_match_tag_hook(int (*func)(
struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type));
+/* set sr-te color */
+extern void route_map_set_srte_color_hook(
+ int (*func)(struct vty *vty, struct route_map_index *index,
+ const char *command, const char *arg));
+/* no set sr-te color */
+extern void route_map_no_set_srte_color_hook(
+ int (*func)(struct vty *vty, struct route_map_index *index,
+ const char *command, const char *arg));
/* set ip nexthop */
extern void route_map_set_ip_nexthop_hook(
int (*func)(struct vty *vty, struct route_map_index *index,
@@ -606,6 +614,14 @@ struct route_map_match_set_hooks {
const char *command, const char *arg,
route_map_event_t type);
+ /* set sr-te color */
+ int (*set_srte_color)(struct vty *vty, struct route_map_index *index,
+ const char *command, const char *arg);
+
+ /* no set sr-te color */
+ int (*no_set_srte_color)(struct vty *vty, struct route_map_index *index,
+ const char *command, const char *arg);
+
/* set ip nexthop */
int (*set_ip_nexthop)(struct vty *vty, struct route_map_index *index,
const char *command, const char *arg);
diff --git a/lib/srte.h b/lib/srte.h
new file mode 100644
index 000000000..d468c1cac
--- /dev/null
+++ b/lib/srte.h
@@ -0,0 +1,56 @@
+/*
+ * SR-TE definitions
+ * Copyright 2020 NetDef Inc.
+ * Sascha Kattelmann
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _FRR_SRTE_H
+#define _FRR_SRTE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SRTE_POLICY_NAME_MAX_LENGTH 64
+
+enum zebra_sr_policy_status {
+ ZEBRA_SR_POLICY_UP = 0,
+ ZEBRA_SR_POLICY_DOWN,
+};
+
+static inline int sr_policy_compare(const struct ipaddr *a_endpoint,
+ const struct ipaddr *b_endpoint,
+ uint32_t a_color, uint32_t b_color)
+{
+ int ret;
+
+ ret = ipaddr_cmp(a_endpoint, b_endpoint);
+ if (ret < 0)
+ return -1;
+ if (ret > 0)
+ return 1;
+
+ return a_color - b_color;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FRR_SRTE_H */
diff --git a/lib/stream.c b/lib/stream.c
index d3afebbf1..768114e69 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -586,6 +586,43 @@ uint32_t stream_get_ipv4(struct stream *s)
return l;
}
+bool stream_get_ipaddr(struct stream *s, struct ipaddr *ip)
+{
+ uint16_t ipa_len;
+
+ STREAM_VERIFY_SANE(s);
+
+ /* Get address type. */
+ if (STREAM_READABLE(s) < sizeof(uint16_t)) {
+ STREAM_BOUND_WARN2(s, "get ipaddr");
+ return false;
+ }
+ ip->ipa_type = stream_getw(s);
+
+ /* Get address value. */
+ switch (ip->ipa_type) {
+ case IPADDR_V4:
+ ipa_len = IPV4_MAX_BYTELEN;
+ break;
+ case IPADDR_V6:
+ ipa_len = IPV6_MAX_BYTELEN;
+ break;
+ default:
+ flog_err(EC_LIB_DEVELOPMENT,
+ "%s: unknown ip address-family: %u", __func__,
+ ip->ipa_type);
+ return false;
+ }
+ if (STREAM_READABLE(s) < ipa_len) {
+ STREAM_BOUND_WARN2(s, "get ipaddr");
+ return false;
+ }
+ memcpy(&ip->ip, s->data + s->getp, ipa_len);
+ s->getp += ipa_len;
+
+ return true;
+}
+
float stream_getf(struct stream *s)
{
union {
@@ -852,6 +889,27 @@ int stream_put_in_addr(struct stream *s, const struct in_addr *addr)
return sizeof(uint32_t);
}
+bool stream_put_ipaddr(struct stream *s, struct ipaddr *ip)
+{
+ stream_putw(s, ip->ipa_type);
+
+ switch (ip->ipa_type) {
+ case IPADDR_V4:
+ stream_put_in_addr(s, &ip->ipaddr_v4);
+ break;
+ case IPADDR_V6:
+ stream_write(s, (uint8_t *)&ip->ipaddr_v6, 16);
+ break;
+ default:
+ flog_err(EC_LIB_DEVELOPMENT,
+ "%s: unknown ip address-family: %u", __func__,
+ ip->ipa_type);
+ return false;
+ }
+
+ return true;
+}
+
/* Put in_addr at location in the stream. */
int stream_put_in_addr_at(struct stream *s, size_t putp,
const struct in_addr *addr)
diff --git a/lib/stream.h b/lib/stream.h
index 245f35db5..1250b6944 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -189,6 +189,7 @@ extern int stream_putq(struct stream *, uint64_t);
extern int stream_putq_at(struct stream *, size_t, uint64_t);
extern int stream_put_ipv4(struct stream *, uint32_t);
extern int stream_put_in_addr(struct stream *s, const struct in_addr *addr);
+extern bool stream_put_ipaddr(struct stream *s, struct ipaddr *ip);
extern int stream_put_in_addr_at(struct stream *s, size_t putp,
const struct in_addr *addr);
extern int stream_put_in6_addr_at(struct stream *s, size_t putp,
@@ -219,6 +220,7 @@ extern uint64_t stream_getq(struct stream *);
extern uint64_t stream_getq_from(struct stream *, size_t);
bool stream_getq2(struct stream *s, uint64_t *q);
extern uint32_t stream_get_ipv4(struct stream *);
+extern bool stream_get_ipaddr(struct stream *s, struct ipaddr *ip);
/* IEEE-754 floats */
extern float stream_getf(struct stream *);
@@ -439,6 +441,12 @@ static inline const uint8_t *ptr_get_be32(const uint8_t *ptr, uint32_t *out)
(P) = _pval; \
} while (0)
+#define STREAM_GET_IPADDR(S, P) \
+ do { \
+ if (!stream_get_ipaddr((S), (P))) \
+ goto stream_failure; \
+ } while (0)
+
#define STREAM_GET(P, STR, SIZE) \
do { \
if (!stream_get2((P), (STR), (SIZE))) \
diff --git a/lib/subdir.am b/lib/subdir.am
index 34ad30f96..1feaa56d1 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -242,6 +242,7 @@ pkginclude_HEADERS += \
lib/sockunion.h \
lib/spf_backoff.h \
lib/srcdest_table.h \
+ lib/srte.h \
lib/stream.h \
lib/systemd.h \
lib/table.h \
diff --git a/lib/zclient.c b/lib/zclient.c
index eb62350f4..da9a7087f 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -39,6 +39,7 @@
#include "pbr.h"
#include "nexthop_group.h"
#include "lib_errors.h"
+#include "srte.h"
DEFINE_MTYPE_STATIC(LIB, ZCLIENT, "Zclient")
DEFINE_MTYPE_STATIC(LIB, REDIST_INST, "Redistribution instance IDs")
@@ -886,7 +887,7 @@ static void zapi_nexthop_group_sort(struct zapi_nexthop *nh_grp,
* Encode a single zapi nexthop
*/
int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
- uint32_t api_flags)
+ uint32_t api_flags, uint32_t api_message)
{
int i, ret = 0;
int nh_flags = api_nh->flags;
@@ -950,6 +951,10 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
stream_put(s, &(api_nh->rmac),
sizeof(struct ethaddr));
+ /* Color for Segment Routing TE. */
+ if (CHECK_FLAG(api_message, ZAPI_MESSAGE_SRTE))
+ stream_putl(s, api_nh->srte_color);
+
/* Index of backup nexthop */
if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
/* Validate backup count */
@@ -986,7 +991,7 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
stream_putw(s, api->instance);
stream_putl(s, api->flags);
- stream_putc(s, api->message);
+ stream_putl(s, api->message);
if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) {
flog_err(EC_LIB_ZAPI_ENCODE,
@@ -1047,7 +1052,9 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
return -1;
}
- if (zapi_nexthop_encode(s, api_nh, api->flags) != 0)
+ if (zapi_nexthop_encode(s, api_nh, api->flags,
+ api->message)
+ != 0)
return -1;
}
}
@@ -1091,7 +1098,9 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
return -1;
}
- if (zapi_nexthop_encode(s, api_nh, api->flags) != 0)
+ if (zapi_nexthop_encode(s, api_nh, api->flags,
+ api->message)
+ != 0)
return -1;
}
}
@@ -1118,7 +1127,7 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
* Decode a single zapi nexthop object
*/
static int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
- uint32_t api_flags)
+ uint32_t api_flags, uint32_t api_message)
{
int i, ret = -1;
@@ -1171,6 +1180,10 @@ static int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
STREAM_GET(&(api_nh->rmac), s,
sizeof(struct ethaddr));
+ /* Color for Segment Routing TE. */
+ if (CHECK_FLAG(api_message, ZAPI_MESSAGE_SRTE))
+ STREAM_GETL(s, api_nh->srte_color);
+
/* Backup nexthop index */
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
STREAM_GETC(s, api_nh->backup_num);
@@ -1208,7 +1221,7 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
STREAM_GETW(s, api->instance);
STREAM_GETL(s, api->flags);
- STREAM_GETC(s, api->message);
+ STREAM_GETL(s, api->message);
STREAM_GETC(s, api->safi);
if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) {
flog_err(EC_LIB_ZAPI_ENCODE,
@@ -1283,7 +1296,9 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
for (i = 0; i < api->nexthop_num; i++) {
api_nh = &api->nexthops[i];
- if (zapi_nexthop_decode(s, api_nh, api->flags) != 0)
+ if (zapi_nexthop_decode(s, api_nh, api->flags,
+ api->message)
+ != 0)
return -1;
}
}
@@ -1301,7 +1316,9 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
for (i = 0; i < api->backup_nexthop_num; i++) {
api_nh = &api->backup_nexthops[i];
- if (zapi_nexthop_decode(s, api_nh, api->flags) != 0)
+ if (zapi_nexthop_decode(s, api_nh, api->flags,
+ api->message)
+ != 0)
return -1;
}
}
@@ -1488,6 +1505,7 @@ struct nexthop *nexthop_from_zapi_nexthop(const struct zapi_nexthop *znh)
n->vrf_id = znh->vrf_id;
n->ifindex = znh->ifindex;
n->gate = znh->gate;
+ n->srte_color = znh->srte_color;
/*
* This function currently handles labels
@@ -1605,6 +1623,7 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
memset(nhr, 0, sizeof(*nhr));
+ STREAM_GETL(s, nhr->message);
STREAM_GETW(s, nhr->prefix.family);
STREAM_GETC(s, nhr->prefix.prefixlen);
switch (nhr->prefix.family) {
@@ -1617,6 +1636,8 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
default:
break;
}
+ if (CHECK_FLAG(nhr->message, ZAPI_MESSAGE_SRTE))
+ STREAM_GETL(s, nhr->srte_color);
STREAM_GETC(s, nhr->type);
STREAM_GETW(s, nhr->instance);
@@ -1625,7 +1646,7 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
STREAM_GETC(s, nhr->nexthop_num);
for (i = 0; i < nhr->nexthop_num; i++) {
- if (zapi_nexthop_decode(s, &(nhr->nexthops[i]), 0) != 0)
+ if (zapi_nexthop_decode(s, &(nhr->nexthops[i]), 0, 0) != 0)
return -1;
}
@@ -2821,6 +2842,92 @@ int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
return zclient_send_message(zclient);
}
+int zebra_send_sr_policy(struct zclient *zclient, int cmd,
+ struct zapi_sr_policy *zp)
+{
+ if (zapi_sr_policy_encode(zclient->obuf, cmd, zp) < 0)
+ return -1;
+ return zclient_send_message(zclient);
+}
+
+int zapi_sr_policy_encode(struct stream *s, int cmd, struct zapi_sr_policy *zp)
+{
+ struct zapi_srte_tunnel *zt = &zp->segment_list;
+
+ stream_reset(s);
+
+ zclient_create_header(s, cmd, VRF_DEFAULT);
+ stream_putl(s, zp->color);
+ stream_put_ipaddr(s, &zp->endpoint);
+ stream_write(s, &zp->name, SRTE_POLICY_NAME_MAX_LENGTH);
+
+ stream_putc(s, zt->type);
+ stream_putl(s, zt->local_label);
+
+ if (zt->label_num > MPLS_MAX_LABELS) {
+ flog_err(EC_LIB_ZAPI_ENCODE,
+ "%s: label %u: can't encode %u labels (maximum is %u)",
+ __func__, zt->local_label, zt->label_num,
+ MPLS_MAX_LABELS);
+ return -1;
+ }
+ stream_putw(s, zt->label_num);
+
+ for (int i = 0; i < zt->label_num; i++)
+ stream_putl(s, zt->labels[i]);
+
+ /* Put length at the first point of the stream. */
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return 0;
+}
+
+int zapi_sr_policy_decode(struct stream *s, struct zapi_sr_policy *zp)
+{
+ memset(zp, 0, sizeof(*zp));
+
+ struct zapi_srte_tunnel *zt = &zp->segment_list;
+
+ STREAM_GETL(s, zp->color);
+ STREAM_GET_IPADDR(s, &zp->endpoint);
+ STREAM_GET(&zp->name, s, SRTE_POLICY_NAME_MAX_LENGTH);
+
+ /* segment list of active candidate path */
+ STREAM_GETC(s, zt->type);
+ STREAM_GETL(s, zt->local_label);
+ STREAM_GETW(s, zt->label_num);
+ if (zt->label_num > MPLS_MAX_LABELS) {
+ flog_err(EC_LIB_ZAPI_ENCODE,
+ "%s: label %u: can't decode %u labels (maximum is %u)",
+ __func__, zt->local_label, zt->label_num,
+ MPLS_MAX_LABELS);
+ return -1;
+ }
+ for (int i = 0; i < zt->label_num; i++)
+ STREAM_GETL(s, zt->labels[i]);
+
+ return 0;
+
+stream_failure:
+ return -1;
+}
+
+int zapi_sr_policy_notify_status_decode(struct stream *s,
+ struct zapi_sr_policy *zp)
+{
+ memset(zp, 0, sizeof(*zp));
+
+ STREAM_GETL(s, zp->color);
+ STREAM_GET_IPADDR(s, &zp->endpoint);
+ STREAM_GET(&zp->name, s, SRTE_POLICY_NAME_MAX_LENGTH);
+ STREAM_GETL(s, zp->status);
+
+ return 0;
+
+stream_failure:
+ return -1;
+}
+
int zebra_send_mpls_labels(struct zclient *zclient, int cmd,
struct zapi_labels *zl)
{
@@ -2860,7 +2967,7 @@ int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
for (int i = 0; i < zl->nexthop_num; i++) {
znh = &zl->nexthops[i];
- if (zapi_nexthop_encode(s, znh, 0) < 0)
+ if (zapi_nexthop_encode(s, znh, 0, 0) < 0)
return -1;
}
@@ -2879,7 +2986,7 @@ int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
for (int i = 0; i < zl->backup_nexthop_num; i++) {
znh = &zl->backup_nexthops[i];
- if (zapi_nexthop_encode(s, znh, 0) < 0)
+ if (zapi_nexthop_encode(s, znh, 0, 0) < 0)
return -1;
}
@@ -2955,7 +3062,7 @@ int zapi_labels_decode(struct stream *s, struct zapi_labels *zl)
for (int i = 0; i < zl->nexthop_num; i++) {
znh = &zl->nexthops[i];
- if (zapi_nexthop_decode(s, znh, 0) < 0)
+ if (zapi_nexthop_decode(s, znh, 0, 0) < 0)
return -1;
}
@@ -2976,7 +3083,7 @@ int zapi_labels_decode(struct stream *s, struct zapi_labels *zl)
for (int i = 0; i < zl->backup_nexthop_num; i++) {
znh = &zl->backup_nexthops[i];
- if (zapi_nexthop_decode(s, znh, 0) < 0)
+ if (zapi_nexthop_decode(s, znh, 0, 0) < 0)
return -1;
}
}
@@ -3643,6 +3750,10 @@ static int zclient_read(struct thread *thread)
(*zclient->opaque_unregister_handler)(command, zclient,
length, vrf_id);
break;
+ case ZEBRA_SR_POLICY_NOTIFY_STATUS:
+ if (zclient->sr_policy_notify_status)
+ (*zclient->sr_policy_notify_status)(command, zclient,
+ length, vrf_id);
default:
break;
}
diff --git a/lib/zclient.h b/lib/zclient.h
index da06239d0..bcd8954dd 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -37,6 +37,7 @@
#include "pw.h"
#include "mlag.h"
+#include "srte.h"
#ifdef __cplusplus
extern "C" {
@@ -89,6 +90,8 @@ enum zserv_client_capabilities {
/* Macro to check if there GR enabled. */
#define ZEBRA_CLIENT_GR_ENABLED(X) (X == ZEBRA_CLIENT_GR_CAPABILITIES)
+#define ZEBRA_SR_POLICY_NAME_MAX_LENGTH 100
+
extern struct sockaddr_storage zclient_addr;
extern socklen_t zclient_addr_len;
@@ -143,6 +146,9 @@ typedef enum {
ZEBRA_MPLS_LABELS_ADD,
ZEBRA_MPLS_LABELS_DELETE,
ZEBRA_MPLS_LABELS_REPLACE,
+ ZEBRA_SR_POLICY_SET,
+ ZEBRA_SR_POLICY_DELETE,
+ ZEBRA_SR_POLICY_NOTIFY_STATUS,
ZEBRA_IPMR_ROUTE_STATS,
ZEBRA_LABEL_MANAGER_CONNECT,
ZEBRA_LABEL_MANAGER_CONNECT_ASYNC,
@@ -351,6 +357,7 @@ struct zclient {
int (*opaque_msg_handler)(ZAPI_CALLBACK_ARGS);
int (*opaque_register_handler)(ZAPI_CALLBACK_ARGS);
int (*opaque_unregister_handler)(ZAPI_CALLBACK_ARGS);
+ int (*sr_policy_notify_status)(ZAPI_CALLBACK_ARGS);
};
/* Zebra API message flag. */
@@ -368,7 +375,8 @@ struct zclient {
* the table being used is not in the VRF. You must pass the
* default vrf, else this will be ignored.
*/
-#define ZAPI_MESSAGE_TABLEID 0x80
+#define ZAPI_MESSAGE_TABLEID 0x0080
+#define ZAPI_MESSAGE_SRTE 0x0100
#define ZSERV_VERSION 6
/* Zserv protocol message header */
@@ -403,6 +411,9 @@ struct zapi_nexthop {
/* Backup nexthops, for IP-FRR, TI-LFA, etc */
uint8_t backup_num;
uint8_t backup_idx[NEXTHOP_MAX_BACKUPS];
+
+ /* SR-TE color. */
+ uint32_t srte_color;
};
/*
@@ -465,7 +476,7 @@ struct zapi_route {
#define ZEBRA_FLAG_RR_USE_DISTANCE 0x40
/* The older XXX_MESSAGE flags live here */
- uint8_t message;
+ uint32_t message;
/*
* This is an enum but we are going to treat it as a uint8_t
@@ -494,6 +505,9 @@ struct zapi_route {
vrf_id_t vrf_id;
uint32_t tableid;
+
+ /* SR-TE color (used for nexthop updates only). */
+ uint32_t srte_color;
};
struct zapi_labels {
@@ -516,6 +530,21 @@ struct zapi_labels {
struct zapi_nexthop backup_nexthops[MULTIPATH_NUM];
};
+struct zapi_srte_tunnel {
+ enum lsp_types_t type;
+ mpls_label_t local_label;
+ uint8_t label_num;
+ mpls_label_t labels[MPLS_MAX_LABELS];
+};
+
+struct zapi_sr_policy {
+ uint32_t color;
+ struct ipaddr endpoint;
+ char name[SRTE_POLICY_NAME_MAX_LENGTH];
+ struct zapi_srte_tunnel segment_list;
+ int status;
+};
+
struct zapi_pw {
char ifname[IF_NAMESIZE];
ifindex_t ifindex;
@@ -775,6 +804,14 @@ extern int tm_get_table_chunk(struct zclient *zclient, uint32_t chunk_size,
extern int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
uint32_t end);
+extern int zebra_send_sr_policy(struct zclient *zclient, int cmd,
+ struct zapi_sr_policy *zp);
+extern int zapi_sr_policy_encode(struct stream *s, int cmd,
+ struct zapi_sr_policy *zp);
+extern int zapi_sr_policy_decode(struct stream *s, struct zapi_sr_policy *zp);
+extern int zapi_sr_policy_notify_status_decode(struct stream *s,
+ struct zapi_sr_policy *zp);
+
extern int zebra_send_mpls_labels(struct zclient *zclient, int cmd,
struct zapi_labels *zl);
extern int zapi_labels_encode(struct stream *s, int cmd,
@@ -791,7 +828,7 @@ extern int zclient_send_rnh(struct zclient *zclient, int command,
const struct prefix *p, bool exact_match,
vrf_id_t vrf_id);
int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
- uint32_t api_flags);
+ uint32_t api_flags, uint32_t api_message);
extern int zapi_route_encode(uint8_t, struct stream *, struct zapi_route *);
extern int zapi_route_decode(struct stream *, struct zapi_route *);
bool zapi_route_notify_decode(struct stream *s, struct prefix *p,