Merge pull request #6783 from opensourcerouting/feature/sr-te

lib, zebra: Add SR-TE policy infrastructure to zebra
This commit is contained in:
Russ White 2020-08-10 15:31:35 -04:00 committed by GitHub
commit 271ac28499
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 1273 additions and 50 deletions

View File

@ -367,6 +367,8 @@ struct cmd_node {
#define SHOW_STR "Show running system information\n" #define SHOW_STR "Show running system information\n"
#define IP_STR "IP information\n" #define IP_STR "IP information\n"
#define IPV6_STR "IPv6 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 NO_STR "Negate a command or set its defaults\n"
#define REDIST_STR "Redistribute information from another routing protocol\n" #define REDIST_STR "Redistribute information from another routing protocol\n"
#define CLEAR_STR "Reset functions\n" #define CLEAR_STR "Reset functions\n"

View File

@ -25,6 +25,8 @@
#include <zebra.h> #include <zebra.h>
#include "lib/log.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -59,6 +61,18 @@ struct ipaddr {
#define IPADDRSZ(p) \ #define IPADDRSZ(p) \
(IS_IPADDR_V4((p)) ? sizeof(struct in_addr) : sizeof(struct in6_addr)) (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) static inline int str2ipaddr(const char *str, struct ipaddr *ip)
{ {
int ret; int ret;
@ -131,6 +145,31 @@ static inline bool ipaddr_isset(struct ipaddr *ip)
return (0 != memcmp(&a, ip, sizeof(struct ipaddr))); return (0 != memcmp(&a, ip, sizeof(struct ipaddr)));
} }
/*
* generic ordering comparison between IP addresses
*/
static inline int ipaddr_cmp(const struct ipaddr *a, const struct ipaddr *b)
{
uint32_t va, vb;
va = a->ipa_type;
vb = b->ipa_type;
if (va != vb)
return (va < vb) ? -1 : 1;
switch (a->ipa_type) {
case IPADDR_V4:
va = ntohl(a->ipaddr_v4.s_addr);
vb = ntohl(b->ipaddr_v4.s_addr);
if (va != vb)
return (va < vb) ? -1 : 1;
return 0;
case IPADDR_V6:
return memcmp((void *)&a->ipaddr_v6, (void *)&b->ipaddr_v6,
sizeof(a->ipaddr_v6));
default:
return 0;
}
}
#ifdef _FRR_ATTRIBUTE_PRINTFRR #ifdef _FRR_ATTRIBUTE_PRINTFRR
#pragma FRR printfrr_ext "%pIA" (struct ipaddr *) #pragma FRR printfrr_ext "%pIA" (struct ipaddr *)
#endif #endif

View File

@ -384,6 +384,9 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD), DESC_ENTRY(ZEBRA_MPLS_LABELS_ADD),
DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE), DESC_ENTRY(ZEBRA_MPLS_LABELS_DELETE),
DESC_ENTRY(ZEBRA_MPLS_LABELS_REPLACE), 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_IPMR_ROUTE_STATS),
DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT), DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT),
DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT_ASYNC), DESC_ENTRY(ZEBRA_LABEL_MANAGER_CONNECT_ASYNC),

View File

@ -129,6 +129,7 @@ enum lsp_types_t {
ZEBRA_LSP_OSPF_SR = 4,/* OSPF Segment Routing LSP. */ ZEBRA_LSP_OSPF_SR = 4,/* OSPF Segment Routing LSP. */
ZEBRA_LSP_ISIS_SR = 5,/* IS-IS Segment Routing LSP. */ ZEBRA_LSP_ISIS_SR = 5,/* IS-IS Segment Routing LSP. */
ZEBRA_LSP_SHARP = 6, /* Identifier for test protocol */ ZEBRA_LSP_SHARP = 6, /* Identifier for test protocol */
ZEBRA_LSP_SRTE = 7, /* SR-TE LSP */
}; };
/* Functions for basic label operations. */ /* Functions for basic label operations. */

View File

@ -152,6 +152,11 @@ static int _nexthop_cmp_no_labels(const struct nexthop *next1,
break; 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); ret = _nexthop_source_cmp(next1, next2);
if (ret != 0) if (ret != 0)
goto done; goto done;
@ -643,6 +648,7 @@ void nexthop_copy_no_recurse(struct nexthop *copy,
if (copy->backup_num > 0) if (copy->backup_num > 0)
memcpy(copy->backup_idx, nexthop->backup_idx, copy->backup_num); 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->gate, &nexthop->gate, sizeof(nexthop->gate));
memcpy(&copy->src, &nexthop->src, sizeof(nexthop->src)); memcpy(&copy->src, &nexthop->src, sizeof(nexthop->src));
memcpy(&copy->rmap_src, &nexthop->rmap_src, sizeof(nexthop->rmap_src)); memcpy(&copy->rmap_src, &nexthop->rmap_src, sizeof(nexthop->rmap_src));

View File

@ -98,6 +98,7 @@ struct nexthop {
*/ */
#define NEXTHOP_FLAG_RNH_FILTERED (1 << 5) /* rmap filtered, used by rnh */ #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_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) \ #define NEXTHOP_IS_ACTIVE(flags) \
(CHECK_FLAG(flags, NEXTHOP_FLAG_ACTIVE) \ (CHECK_FLAG(flags, NEXTHOP_FLAG_ACTIVE) \
@ -141,6 +142,9 @@ struct nexthop {
union { union {
vni_t vni; vni_t vni;
} nh_encap; } nh_encap;
/* SR-TE color used for matching SR-TE policies */
uint32_t srte_color;
}; };
/* Utility to append one nexthop to another. */ /* Utility to append one nexthop to another. */

View File

@ -2046,18 +2046,21 @@ void *nb_running_unset_entry(const struct lyd_node *dnode)
return entry; return entry;
} }
void *nb_running_get_entry(const struct lyd_node *dnode, const char *xpath, static void *nb_running_get_entry_worker(const struct lyd_node *dnode,
bool abort_if_not_found) const char *xpath,
bool abort_if_not_found,
bool rec_search)
{ {
const struct lyd_node *orig_dnode = dnode; const struct lyd_node *orig_dnode = dnode;
char xpath_buf[XPATH_MAXLEN]; char xpath_buf[XPATH_MAXLEN];
bool rec_flag = true;
assert(dnode || xpath); assert(dnode || xpath);
if (!dnode) if (!dnode)
dnode = yang_dnode_get(running_config->dnode, xpath); dnode = yang_dnode_get(running_config->dnode, xpath);
while (dnode) { while (rec_flag && dnode) {
struct nb_config_entry *config, s; struct nb_config_entry *config, s;
yang_dnode_get_path(dnode, s.xpath, sizeof(s.xpath)); yang_dnode_get_path(dnode, s.xpath, sizeof(s.xpath));
@ -2065,6 +2068,8 @@ void *nb_running_get_entry(const struct lyd_node *dnode, const char *xpath,
if (config) if (config)
return config->entry; return config->entry;
rec_flag = rec_search;
dnode = dnode->parent; dnode = dnode->parent;
} }
@ -2078,6 +2083,20 @@ void *nb_running_get_entry(const struct lyd_node *dnode, const char *xpath,
abort(); abort();
} }
void *nb_running_get_entry(const struct lyd_node *dnode, const char *xpath,
bool abort_if_not_found)
{
return nb_running_get_entry_worker(dnode, xpath, abort_if_not_found,
true);
}
void *nb_running_get_entry_non_rec(const struct lyd_node *dnode,
const char *xpath, bool abort_if_not_found)
{
return nb_running_get_entry_worker(dnode, xpath, abort_if_not_found,
false);
}
/* Logging functions. */ /* Logging functions. */
const char *nb_event_name(enum nb_event event) const char *nb_event_name(enum nb_event event)
{ {

View File

@ -1164,6 +1164,14 @@ extern void *nb_running_unset_entry(const struct lyd_node *dnode);
extern void *nb_running_get_entry(const struct lyd_node *dnode, extern void *nb_running_get_entry(const struct lyd_node *dnode,
const char *xpath, bool abort_if_not_found); const char *xpath, bool abort_if_not_found);
/*
* Same as 'nb_running_get_entry', but doesn't search within parent nodes
* recursively if an user point is not found.
*/
extern void *nb_running_get_entry_non_rec(const struct lyd_node *dnode,
const char *xpath,
bool abort_if_not_found);
/* /*
* Return a human-readable string representing a northbound event. * Return a human-readable string representing a northbound event.
* *

View File

@ -24,6 +24,7 @@
#define _ZEBRA_PRIVS_H #define _ZEBRA_PRIVS_H
#include <pthread.h> #include <pthread.h>
#include <stdint.h>
#include "lib/queue.h" #include "lib/queue.h"
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -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_OPENFABRIC, openfabric, fabricd, 'f', 1, 1, 1, "OpenFabric"
ZEBRA_ROUTE_VRRP, vrrp, vrrpd, '-', 0, 0, 0, "VRRP" ZEBRA_ROUTE_VRRP, vrrp, vrrpd, '-', 0, 0, 0, "VRRP"
ZEBRA_ROUTE_NHG, nhg, none, '-', 0, 0, 0, "Nexthop Group" 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, "-" ZEBRA_ROUTE_ALL, wildcard, none, '-', 0, 0, 0, "-"

View File

@ -263,6 +263,24 @@ void route_map_no_match_tag_hook(int (*func)(
rmap_match_set_hook.no_match_tag = 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 */ /* set ip nexthop */
void route_map_set_ip_nexthop_hook(int (*func)(struct vty *vty, void route_map_set_ip_nexthop_hook(int (*func)(struct vty *vty,
struct route_map_index *index, 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); 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) static void *route_map_dep_hash_alloc(void *p)
{ {
char *dep_name = (char *)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, &routemap_optimization_cmd);
install_element(RMAP_NODE, &no_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); install_element(ENABLE_NODE, &show_route_map_pfx_tbl_cmd);
} }

View File

@ -424,6 +424,14 @@ extern void route_map_match_tag_hook(int (*func)(
extern void route_map_no_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, struct vty *vty, struct route_map_index *index, const char *command,
const char *arg, route_map_event_t type)); 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 */ /* set ip nexthop */
extern void route_map_set_ip_nexthop_hook( extern void route_map_set_ip_nexthop_hook(
int (*func)(struct vty *vty, struct route_map_index *index, 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, const char *command, const char *arg,
route_map_event_t type); 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 */ /* set ip nexthop */
int (*set_ip_nexthop)(struct vty *vty, struct route_map_index *index, int (*set_ip_nexthop)(struct vty *vty, struct route_map_index *index,
const char *command, const char *arg); const char *command, const char *arg);

56
lib/srte.h Normal file
View File

@ -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 */

View File

@ -586,6 +586,43 @@ uint32_t stream_get_ipv4(struct stream *s)
return l; 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) float stream_getf(struct stream *s)
{ {
union { union {
@ -852,6 +889,27 @@ int stream_put_in_addr(struct stream *s, const struct in_addr *addr)
return sizeof(uint32_t); 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. */ /* Put in_addr at location in the stream. */
int stream_put_in_addr_at(struct stream *s, size_t putp, int stream_put_in_addr_at(struct stream *s, size_t putp,
const struct in_addr *addr) const struct in_addr *addr)

View File

@ -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_putq_at(struct stream *, size_t, uint64_t);
extern int stream_put_ipv4(struct stream *, uint32_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 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, extern int stream_put_in_addr_at(struct stream *s, size_t putp,
const struct in_addr *addr); const struct in_addr *addr);
extern int stream_put_in6_addr_at(struct stream *s, size_t putp, 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); extern uint64_t stream_getq_from(struct stream *, size_t);
bool stream_getq2(struct stream *s, uint64_t *q); bool stream_getq2(struct stream *s, uint64_t *q);
extern uint32_t stream_get_ipv4(struct stream *); extern uint32_t stream_get_ipv4(struct stream *);
extern bool stream_get_ipaddr(struct stream *s, struct ipaddr *ip);
/* IEEE-754 floats */ /* IEEE-754 floats */
extern float stream_getf(struct stream *); 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; \ (P) = _pval; \
} while (0) } 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) \ #define STREAM_GET(P, STR, SIZE) \
do { \ do { \
if (!stream_get2((P), (STR), (SIZE))) \ if (!stream_get2((P), (STR), (SIZE))) \

View File

@ -242,6 +242,7 @@ pkginclude_HEADERS += \
lib/sockunion.h \ lib/sockunion.h \
lib/spf_backoff.h \ lib/spf_backoff.h \
lib/srcdest_table.h \ lib/srcdest_table.h \
lib/srte.h \
lib/stream.h \ lib/stream.h \
lib/systemd.h \ lib/systemd.h \
lib/table.h \ lib/table.h \

View File

@ -39,6 +39,7 @@
#include "pbr.h" #include "pbr.h"
#include "nexthop_group.h" #include "nexthop_group.h"
#include "lib_errors.h" #include "lib_errors.h"
#include "srte.h"
DEFINE_MTYPE_STATIC(LIB, ZCLIENT, "Zclient") DEFINE_MTYPE_STATIC(LIB, ZCLIENT, "Zclient")
DEFINE_MTYPE_STATIC(LIB, REDIST_INST, "Redistribution instance IDs") DEFINE_MTYPE_STATIC(LIB, REDIST_INST, "Redistribution instance IDs")
@ -900,7 +901,7 @@ static void zapi_nexthop_group_sort(struct zapi_nexthop *nh_grp,
* Encode a single zapi nexthop * Encode a single zapi nexthop
*/ */
int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, 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 i, ret = 0;
int nh_flags = api_nh->flags; int nh_flags = api_nh->flags;
@ -964,6 +965,10 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
stream_put(s, &(api_nh->rmac), stream_put(s, &(api_nh->rmac),
sizeof(struct ethaddr)); 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 */ /* Index of backup nexthop */
if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) { if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
/* Validate backup count */ /* Validate backup count */
@ -1000,7 +1005,7 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
stream_putw(s, api->instance); stream_putw(s, api->instance);
stream_putl(s, api->flags); stream_putl(s, api->flags);
stream_putc(s, api->message); stream_putl(s, api->message);
if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) { if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) {
flog_err(EC_LIB_ZAPI_ENCODE, flog_err(EC_LIB_ZAPI_ENCODE,
@ -1061,7 +1066,9 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
return -1; 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; return -1;
} }
} }
@ -1105,7 +1112,9 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
return -1; 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; return -1;
} }
} }
@ -1132,7 +1141,7 @@ int zapi_route_encode(uint8_t cmd, struct stream *s, struct zapi_route *api)
* Decode a single zapi nexthop object * Decode a single zapi nexthop object
*/ */
static int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh, 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; int i, ret = -1;
@ -1185,6 +1194,10 @@ static int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
STREAM_GET(&(api_nh->rmac), s, STREAM_GET(&(api_nh->rmac), s,
sizeof(struct ethaddr)); 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 */ /* Backup nexthop index */
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) { if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
STREAM_GETC(s, api_nh->backup_num); STREAM_GETC(s, api_nh->backup_num);
@ -1222,7 +1235,7 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
STREAM_GETW(s, api->instance); STREAM_GETW(s, api->instance);
STREAM_GETL(s, api->flags); STREAM_GETL(s, api->flags);
STREAM_GETC(s, api->message); STREAM_GETL(s, api->message);
STREAM_GETC(s, api->safi); STREAM_GETC(s, api->safi);
if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) { if (api->safi < SAFI_UNICAST || api->safi >= SAFI_MAX) {
flog_err(EC_LIB_ZAPI_ENCODE, flog_err(EC_LIB_ZAPI_ENCODE,
@ -1297,7 +1310,9 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
for (i = 0; i < api->nexthop_num; i++) { for (i = 0; i < api->nexthop_num; i++) {
api_nh = &api->nexthops[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; return -1;
} }
} }
@ -1315,7 +1330,9 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
for (i = 0; i < api->backup_nexthop_num; i++) { for (i = 0; i < api->backup_nexthop_num; i++) {
api_nh = &api->backup_nexthops[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; return -1;
} }
} }
@ -1502,6 +1519,7 @@ struct nexthop *nexthop_from_zapi_nexthop(const struct zapi_nexthop *znh)
n->vrf_id = znh->vrf_id; n->vrf_id = znh->vrf_id;
n->ifindex = znh->ifindex; n->ifindex = znh->ifindex;
n->gate = znh->gate; n->gate = znh->gate;
n->srte_color = znh->srte_color;
/* /*
* This function currently handles labels * This function currently handles labels
@ -1619,6 +1637,7 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
memset(nhr, 0, sizeof(*nhr)); memset(nhr, 0, sizeof(*nhr));
STREAM_GETL(s, nhr->message);
STREAM_GETW(s, nhr->prefix.family); STREAM_GETW(s, nhr->prefix.family);
STREAM_GETC(s, nhr->prefix.prefixlen); STREAM_GETC(s, nhr->prefix.prefixlen);
switch (nhr->prefix.family) { switch (nhr->prefix.family) {
@ -1631,6 +1650,8 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
default: default:
break; break;
} }
if (CHECK_FLAG(nhr->message, ZAPI_MESSAGE_SRTE))
STREAM_GETL(s, nhr->srte_color);
STREAM_GETC(s, nhr->type); STREAM_GETC(s, nhr->type);
STREAM_GETW(s, nhr->instance); STREAM_GETW(s, nhr->instance);
@ -1639,7 +1660,7 @@ bool zapi_nexthop_update_decode(struct stream *s, struct zapi_route *nhr)
STREAM_GETC(s, nhr->nexthop_num); STREAM_GETC(s, nhr->nexthop_num);
for (i = 0; i < nhr->nexthop_num; i++) { 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; return -1;
} }
@ -2835,6 +2856,92 @@ int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
return zclient_send_message(zclient); 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, int zebra_send_mpls_labels(struct zclient *zclient, int cmd,
struct zapi_labels *zl) struct zapi_labels *zl)
{ {
@ -2874,7 +2981,7 @@ int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
for (int i = 0; i < zl->nexthop_num; i++) { for (int i = 0; i < zl->nexthop_num; i++) {
znh = &zl->nexthops[i]; znh = &zl->nexthops[i];
if (zapi_nexthop_encode(s, znh, 0) < 0) if (zapi_nexthop_encode(s, znh, 0, 0) < 0)
return -1; return -1;
} }
@ -2893,7 +3000,7 @@ int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
for (int i = 0; i < zl->backup_nexthop_num; i++) { for (int i = 0; i < zl->backup_nexthop_num; i++) {
znh = &zl->backup_nexthops[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; return -1;
} }
@ -2969,7 +3076,7 @@ int zapi_labels_decode(struct stream *s, struct zapi_labels *zl)
for (int i = 0; i < zl->nexthop_num; i++) { for (int i = 0; i < zl->nexthop_num; i++) {
znh = &zl->nexthops[i]; znh = &zl->nexthops[i];
if (zapi_nexthop_decode(s, znh, 0) < 0) if (zapi_nexthop_decode(s, znh, 0, 0) < 0)
return -1; return -1;
} }
@ -2990,7 +3097,7 @@ int zapi_labels_decode(struct stream *s, struct zapi_labels *zl)
for (int i = 0; i < zl->backup_nexthop_num; i++) { for (int i = 0; i < zl->backup_nexthop_num; i++) {
znh = &zl->backup_nexthops[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; return -1;
} }
} }
@ -3657,6 +3764,10 @@ static int zclient_read(struct thread *thread)
(*zclient->opaque_unregister_handler)(command, zclient, (*zclient->opaque_unregister_handler)(command, zclient,
length, vrf_id); length, vrf_id);
break; break;
case ZEBRA_SR_POLICY_NOTIFY_STATUS:
if (zclient->sr_policy_notify_status)
(*zclient->sr_policy_notify_status)(command, zclient,
length, vrf_id);
default: default:
break; break;
} }

View File

@ -37,6 +37,7 @@
#include "pw.h" #include "pw.h"
#include "mlag.h" #include "mlag.h"
#include "srte.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -89,6 +90,8 @@ enum zserv_client_capabilities {
/* Macro to check if there GR enabled. */ /* Macro to check if there GR enabled. */
#define ZEBRA_CLIENT_GR_ENABLED(X) (X == ZEBRA_CLIENT_GR_CAPABILITIES) #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 struct sockaddr_storage zclient_addr;
extern socklen_t zclient_addr_len; extern socklen_t zclient_addr_len;
@ -143,6 +146,9 @@ typedef enum {
ZEBRA_MPLS_LABELS_ADD, ZEBRA_MPLS_LABELS_ADD,
ZEBRA_MPLS_LABELS_DELETE, ZEBRA_MPLS_LABELS_DELETE,
ZEBRA_MPLS_LABELS_REPLACE, ZEBRA_MPLS_LABELS_REPLACE,
ZEBRA_SR_POLICY_SET,
ZEBRA_SR_POLICY_DELETE,
ZEBRA_SR_POLICY_NOTIFY_STATUS,
ZEBRA_IPMR_ROUTE_STATS, ZEBRA_IPMR_ROUTE_STATS,
ZEBRA_LABEL_MANAGER_CONNECT, ZEBRA_LABEL_MANAGER_CONNECT,
ZEBRA_LABEL_MANAGER_CONNECT_ASYNC, ZEBRA_LABEL_MANAGER_CONNECT_ASYNC,
@ -351,6 +357,7 @@ struct zclient {
int (*opaque_msg_handler)(ZAPI_CALLBACK_ARGS); int (*opaque_msg_handler)(ZAPI_CALLBACK_ARGS);
int (*opaque_register_handler)(ZAPI_CALLBACK_ARGS); int (*opaque_register_handler)(ZAPI_CALLBACK_ARGS);
int (*opaque_unregister_handler)(ZAPI_CALLBACK_ARGS); int (*opaque_unregister_handler)(ZAPI_CALLBACK_ARGS);
int (*sr_policy_notify_status)(ZAPI_CALLBACK_ARGS);
}; };
/* Zebra API message flag. */ /* Zebra API message flag. */
@ -368,7 +375,8 @@ struct zclient {
* the table being used is not in the VRF. You must pass the * the table being used is not in the VRF. You must pass the
* default vrf, else this will be ignored. * 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 #define ZSERV_VERSION 6
/* Zserv protocol message header */ /* Zserv protocol message header */
@ -403,6 +411,9 @@ struct zapi_nexthop {
/* Backup nexthops, for IP-FRR, TI-LFA, etc */ /* Backup nexthops, for IP-FRR, TI-LFA, etc */
uint8_t backup_num; uint8_t backup_num;
uint8_t backup_idx[NEXTHOP_MAX_BACKUPS]; 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 #define ZEBRA_FLAG_RR_USE_DISTANCE 0x40
/* The older XXX_MESSAGE flags live here */ /* 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 * 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; vrf_id_t vrf_id;
uint32_t tableid; uint32_t tableid;
/* SR-TE color (used for nexthop updates only). */
uint32_t srte_color;
}; };
struct zapi_labels { struct zapi_labels {
@ -516,6 +530,21 @@ struct zapi_labels {
struct zapi_nexthop backup_nexthops[MULTIPATH_NUM]; 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 { struct zapi_pw {
char ifname[IF_NAMESIZE]; char ifname[IF_NAMESIZE];
ifindex_t ifindex; ifindex_t ifindex;
@ -778,6 +807,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, extern int tm_release_table_chunk(struct zclient *zclient, uint32_t start,
uint32_t end); 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, extern int zebra_send_mpls_labels(struct zclient *zclient, int cmd,
struct zapi_labels *zl); struct zapi_labels *zl);
extern int zapi_labels_encode(struct stream *s, int cmd, extern int zapi_labels_encode(struct stream *s, int cmd,
@ -794,7 +831,7 @@ extern int zclient_send_rnh(struct zclient *zclient, int command,
const struct prefix *p, bool exact_match, const struct prefix *p, bool exact_match,
vrf_id_t vrf_id); vrf_id_t vrf_id);
int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, 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_encode(uint8_t, struct stream *, struct zapi_route *);
extern int zapi_route_decode(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, bool zapi_route_notify_decode(struct stream *s, struct prefix *p,

View File

@ -6,6 +6,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true "installed":true
} }
@ -18,6 +21,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.1.2" "nexthop":"10.0.1.2"
@ -38,6 +44,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":8300, "outLabel":8300,
"outLabelStack":[
8300
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.1.2" "nexthop":"10.0.1.2"
@ -58,6 +67,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":8400, "outLabel":8400,
"outLabelStack":[
8400
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.1.2" "nexthop":"10.0.1.2"
@ -104,6 +116,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.1.2" "nexthop":"10.0.1.2"
@ -117,6 +132,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.1.2" "nexthop":"10.0.1.2"

View File

@ -6,6 +6,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":20100, "outLabel":20100,
"outLabelStack":[
20100
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.1.1" "nexthop":"10.0.1.1"
@ -26,6 +29,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.3.1" "nexthop":"10.0.3.1"
@ -39,6 +45,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":10400, "outLabel":10400,
"outLabelStack":[
10400
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.4.1" "nexthop":"10.0.4.1"
@ -52,6 +61,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.4.1" "nexthop":"10.0.4.1"
@ -65,6 +77,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.4.1" "nexthop":"10.0.4.1"
@ -78,6 +93,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.0.1" "nexthop":"10.0.0.1"
@ -91,6 +109,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.0.1" "nexthop":"10.0.0.1"
@ -104,6 +125,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.1.1" "nexthop":"10.0.1.1"
@ -117,6 +141,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.1.1" "nexthop":"10.0.1.1"

View File

@ -6,6 +6,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":8100, "outLabel":8100,
"outLabelStack":[
8100
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.3.2" "nexthop":"10.0.3.2"
@ -19,6 +22,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.3.2" "nexthop":"10.0.3.2"
@ -32,6 +38,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":8400, "outLabel":8400,
"outLabelStack":[
8400
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.3.2" "nexthop":"10.0.3.2"
@ -45,6 +54,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.3.2" "nexthop":"10.0.3.2"
@ -58,6 +70,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.3.2" "nexthop":"10.0.3.2"

View File

@ -6,6 +6,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":8100, "outLabel":8100,
"outLabelStack":[
8100
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.4.2" "nexthop":"10.0.4.2"
@ -19,6 +22,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.4.2" "nexthop":"10.0.4.2"
@ -32,6 +38,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":8300, "outLabel":8300,
"outLabelStack":[
8300
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.4.2" "nexthop":"10.0.4.2"
@ -45,6 +54,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true "installed":true
} }
@ -57,6 +69,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.4.2" "nexthop":"10.0.4.2"
@ -70,6 +85,9 @@
{ {
"type":"SR (OSPF)", "type":"SR (OSPF)",
"outLabel":3, "outLabel":3,
"outLabelStack":[
3
],
"distance":150, "distance":150,
"installed":true, "installed":true,
"nexthop":"10.0.4.2" "nexthop":"10.0.4.2"

View File

@ -240,7 +240,7 @@ assign_specific_label_chunk(uint8_t proto, unsigned short instance,
if (lmc->proto != NO_PROTO) if (lmc->proto != NO_PROTO)
return NULL; return NULL;
if (end < lmc->end) { if (end <= lmc->end) {
last_node = node; last_node = node;
break; break;
} }

View File

@ -57,6 +57,7 @@
#include "zebra/zebra_routemap.h" #include "zebra/zebra_routemap.h"
#include "zebra/zebra_nb.h" #include "zebra/zebra_nb.h"
#include "zebra/zebra_opaque.h" #include "zebra/zebra_opaque.h"
#include "zebra/zebra_srte.h"
#if defined(HANDLE_NETLINK_FUZZING) #if defined(HANDLE_NETLINK_FUZZING)
#include "zebra/kernel_netlink.h" #include "zebra/kernel_netlink.h"
@ -438,9 +439,10 @@ int main(int argc, char **argv)
zebra_pw_vty_init(); zebra_pw_vty_init();
zebra_pbr_init(); zebra_pbr_init();
zebra_opaque_init(); zebra_opaque_init();
zebra_srte_init();
/* For debug purpose. */ /* For debug purpose. */
/* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */ /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
/* Process the configuration file. Among other configuration /* Process the configuration file. Among other configuration
* directives we can meet those installing static routes. Such * directives we can meet those installing static routes. Such

View File

@ -179,7 +179,8 @@ static inline bool is_selfroute(int proto)
|| (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP) || (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP)
|| (proto == RTPROT_LDP) || (proto == RTPROT_BABEL) || (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)
|| (proto == RTPROT_RIP) || (proto == RTPROT_SHARP) || (proto == RTPROT_RIP) || (proto == RTPROT_SHARP)
|| (proto == RTPROT_PBR) || (proto == RTPROT_OPENFABRIC)) { || (proto == RTPROT_PBR) || (proto == RTPROT_OPENFABRIC)
|| (proto == RTPROT_SRTE)) {
return true; return true;
} }
@ -229,6 +230,9 @@ static inline int zebra2proto(int proto)
case ZEBRA_ROUTE_OPENFABRIC: case ZEBRA_ROUTE_OPENFABRIC:
proto = RTPROT_OPENFABRIC; proto = RTPROT_OPENFABRIC;
break; break;
case ZEBRA_ROUTE_SRTE:
proto = RTPROT_SRTE;
break;
case ZEBRA_ROUTE_TABLE: case ZEBRA_ROUTE_TABLE:
case ZEBRA_ROUTE_NHG: case ZEBRA_ROUTE_NHG:
proto = RTPROT_ZEBRA; proto = RTPROT_ZEBRA;
@ -294,6 +298,9 @@ static inline int proto2zebra(int proto, int family, bool is_nexthop)
case RTPROT_OPENFABRIC: case RTPROT_OPENFABRIC:
proto = ZEBRA_ROUTE_OPENFABRIC; proto = ZEBRA_ROUTE_OPENFABRIC;
break; break;
case RTPROT_SRTE:
proto = ZEBRA_ROUTE_SRTE;
break;
case RTPROT_ZEBRA: case RTPROT_ZEBRA:
if (is_nexthop) { if (is_nexthop) {
proto = ZEBRA_ROUTE_NHG; proto = ZEBRA_ROUTE_NHG;

View File

@ -60,6 +60,7 @@ extern "C" {
#define RTPROT_PBR 195 #define RTPROT_PBR 195
#define RTPROT_ZSTATIC 196 #define RTPROT_ZSTATIC 196
#define RTPROT_OPENFABRIC 197 #define RTPROT_OPENFABRIC 197
#define RTPROT_SRTE 198
void rt_netlink_init(void); void rt_netlink_init(void);

View File

@ -106,6 +106,7 @@ zebra_zebra_SOURCES = \
zebra/zebra_router.c \ zebra/zebra_router.c \
zebra/zebra_rnh.c \ zebra/zebra_rnh.c \
zebra/zebra_routemap.c \ zebra/zebra_routemap.c \
zebra/zebra_srte.c \
zebra/zebra_vrf.c \ zebra/zebra_vrf.c \
zebra/zebra_vty.c \ zebra/zebra_vty.c \
zebra/zebra_vxlan.c \ zebra/zebra_vxlan.c \
@ -167,6 +168,7 @@ noinst_HEADERS += \
zebra/zebra_rnh.h \ zebra/zebra_rnh.h \
zebra/zebra_routemap.h \ zebra/zebra_routemap.h \
zebra/zebra_router.h \ zebra/zebra_router.h \
zebra/zebra_srte.h \
zebra/zebra_vrf.h \ zebra/zebra_vrf.h \
zebra/zebra_vxlan.h \ zebra/zebra_vxlan.h \
zebra/zebra_vxlan_private.h \ zebra/zebra_vxlan_private.h \

View File

@ -60,6 +60,7 @@
#include "zebra/zebra_mlag.h" #include "zebra/zebra_mlag.h"
#include "zebra/connected.h" #include "zebra/connected.h"
#include "zebra/zebra_opaque.h" #include "zebra/zebra_opaque.h"
#include "zebra/zebra_srte.h"
/* Encoding helpers -------------------------------------------------------- */ /* Encoding helpers -------------------------------------------------------- */
@ -1651,6 +1652,11 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
return; return;
} }
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRTE)) {
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_SRTE);
nexthop->srte_color = api_nh->srte_color;
}
/* MPLS labels for BGP-LU or Segment Routing */ /* MPLS labels for BGP-LU or Segment Routing */
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL) if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL)
&& api_nh->type != NEXTHOP_TYPE_IFINDEX && api_nh->type != NEXTHOP_TYPE_IFINDEX
@ -1730,6 +1736,11 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
nexthop->backup_num = 0; nexthop->backup_num = 0;
} }
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRTE)) {
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_SRTE);
nexthop->srte_color = api_nh->srte_color;
}
/* MPLS labels for BGP-LU or Segment Routing */ /* MPLS labels for BGP-LU or Segment Routing */
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL) if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL)
&& api_nh->type != NEXTHOP_TYPE_IFINDEX && api_nh->type != NEXTHOP_TYPE_IFINDEX
@ -2209,6 +2220,107 @@ static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS)
mpls_zapi_labels_process(true, zvrf, &zl); mpls_zapi_labels_process(true, zvrf, &zl);
} }
static void zread_sr_policy_set(ZAPI_HANDLER_ARGS)
{
struct stream *s;
struct zapi_sr_policy zp;
struct zapi_srte_tunnel *zt;
struct zebra_sr_policy *policy;
/* Get input stream. */
s = msg;
if (zapi_sr_policy_decode(s, &zp) < 0) {
if (IS_ZEBRA_DEBUG_RECV)
zlog_debug("%s: Unable to decode zapi_sr_policy sent",
__PRETTY_FUNCTION__);
return;
}
zt = &zp.segment_list;
if (zt->label_num < 1) {
if (IS_ZEBRA_DEBUG_RECV)
zlog_debug(
"%s: SR-TE tunnel must contain at least one label",
__PRETTY_FUNCTION__);
return;
}
if (!mpls_enabled)
return;
policy = zebra_sr_policy_find(zp.color, &zp.endpoint);
if (!policy)
policy = zebra_sr_policy_add(zp.color, &zp.endpoint, zp.name);
/* TODO: per-VRF list of SR-TE policies. */
policy->zvrf = zvrf;
zebra_sr_policy_validate(policy, &zp.segment_list);
}
static void zread_sr_policy_delete(ZAPI_HANDLER_ARGS)
{
struct stream *s;
struct zapi_sr_policy zp;
struct zebra_sr_policy *policy;
/* Get input stream. */
s = msg;
if (zapi_sr_policy_decode(s, &zp) < 0) {
if (IS_ZEBRA_DEBUG_RECV)
zlog_debug("%s: Unable to decode zapi_sr_policy sent",
__PRETTY_FUNCTION__);
return;
}
if (!mpls_enabled)
return;
policy = zebra_sr_policy_find(zp.color, &zp.endpoint);
if (!policy) {
if (IS_ZEBRA_DEBUG_RECV)
zlog_debug("%s: Unable to find SR-TE policy",
__PRETTY_FUNCTION__);
return;
}
zebra_sr_policy_del(policy);
}
int zsend_sr_policy_notify_status(uint32_t color, struct ipaddr *endpoint,
char *name, int status)
{
struct zserv *client;
struct stream *s;
client = zserv_find_client(ZEBRA_ROUTE_SRTE, 0);
if (!client) {
if (IS_ZEBRA_DEBUG_PACKET)
zlog_debug(
"Not notifying pathd about policy %s"
" status change to %d",
name, status);
return 0;
}
if (IS_ZEBRA_DEBUG_PACKET)
zlog_debug(
"Notifying pathd about policy %s status change"
" to %d",
name, status);
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
zclient_create_header(s, ZEBRA_SR_POLICY_NOTIFY_STATUS, VRF_DEFAULT);
stream_putl(s, color);
stream_put_ipaddr(s, endpoint);
stream_write(s, name, SRTE_POLICY_NAME_MAX_LENGTH);
stream_putl(s, status);
stream_putw_at(s, 0, stream_get_endp(s));
return zserv_send_message(client, s);
}
/* Send response to a table manager connect request to client */ /* Send response to a table manager connect request to client */
static void zread_table_manager_connect(struct zserv *client, static void zread_table_manager_connect(struct zserv *client,
struct stream *msg, vrf_id_t vrf_id) struct stream *msg, vrf_id_t vrf_id)
@ -2908,6 +3020,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_BFD_CLIENT_REGISTER] = zebra_ptm_bfd_client_register, [ZEBRA_BFD_CLIENT_REGISTER] = zebra_ptm_bfd_client_register,
[ZEBRA_INTERFACE_ENABLE_RADV] = zebra_interface_radv_enable, [ZEBRA_INTERFACE_ENABLE_RADV] = zebra_interface_radv_enable,
[ZEBRA_INTERFACE_DISABLE_RADV] = zebra_interface_radv_disable, [ZEBRA_INTERFACE_DISABLE_RADV] = zebra_interface_radv_disable,
[ZEBRA_SR_POLICY_SET] = zread_sr_policy_set,
[ZEBRA_SR_POLICY_DELETE] = zread_sr_policy_delete,
[ZEBRA_MPLS_LABELS_ADD] = zread_mpls_labels_add, [ZEBRA_MPLS_LABELS_ADD] = zread_mpls_labels_add,
[ZEBRA_MPLS_LABELS_DELETE] = zread_mpls_labels_delete, [ZEBRA_MPLS_LABELS_DELETE] = zread_mpls_labels_delete,
[ZEBRA_MPLS_LABELS_REPLACE] = zread_mpls_labels_replace, [ZEBRA_MPLS_LABELS_REPLACE] = zread_mpls_labels_replace,

View File

@ -100,7 +100,9 @@ extern int zsend_assign_label_chunk_response(struct zserv *client,
extern int zsend_label_manager_connect_response(struct zserv *client, extern int zsend_label_manager_connect_response(struct zserv *client,
vrf_id_t vrf_id, vrf_id_t vrf_id,
unsigned short result); unsigned short result);
extern int zsend_sr_policy_notify_status(uint32_t color,
struct ipaddr *endpoint, char *name,
int status);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -47,6 +47,7 @@
#include "zebra/zebra_memory.h" #include "zebra/zebra_memory.h"
#include "zebra/zebra_vrf.h" #include "zebra/zebra_vrf.h"
#include "zebra/zebra_mpls.h" #include "zebra/zebra_mpls.h"
#include "zebra/zebra_srte.h"
#include "zebra/zebra_errors.h" #include "zebra/zebra_errors.h"
DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object") DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object")
@ -1505,6 +1506,7 @@ static json_object *nhlfe_json(zebra_nhlfe_t *nhlfe)
char buf[BUFSIZ]; char buf[BUFSIZ];
json_object *json_nhlfe = NULL; json_object *json_nhlfe = NULL;
json_object *json_backups = NULL; json_object *json_backups = NULL;
json_object *json_label_stack;
struct nexthop *nexthop = nhlfe->nexthop; struct nexthop *nexthop = nhlfe->nexthop;
int i; int i;
@ -1512,6 +1514,14 @@ static json_object *nhlfe_json(zebra_nhlfe_t *nhlfe)
json_object_string_add(json_nhlfe, "type", nhlfe_type2str(nhlfe->type)); json_object_string_add(json_nhlfe, "type", nhlfe_type2str(nhlfe->type));
json_object_int_add(json_nhlfe, "outLabel", json_object_int_add(json_nhlfe, "outLabel",
nexthop->nh_label->label[0]); nexthop->nh_label->label[0]);
json_label_stack = json_object_new_array();
json_object_object_add(json_nhlfe, "outLabelStack", json_label_stack);
for (i = 0; i < nexthop->nh_label->num_labels; i++)
json_object_array_add(
json_label_stack,
json_object_new_int(nexthop->nh_label->label[i]));
json_object_int_add(json_nhlfe, "distance", nhlfe->distance); json_object_int_add(json_nhlfe, "distance", nhlfe->distance);
if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED)) if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED))
@ -1916,14 +1926,13 @@ static int mpls_processq_init(void)
} }
/* Public functions */
/* /*
* Process LSP update results from zebra dataplane. * Process LSP update results from zebra dataplane.
*/ */
void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx) void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
{ {
struct zebra_vrf *zvrf; struct zebra_vrf *zvrf;
mpls_label_t label;
zebra_ile_t tmp_ile; zebra_ile_t tmp_ile;
struct hash *lsp_table; struct hash *lsp_table;
zebra_lsp_t *lsp; zebra_lsp_t *lsp;
@ -1931,6 +1940,7 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
struct nexthop *nexthop; struct nexthop *nexthop;
enum dplane_op_e op; enum dplane_op_e op;
enum zebra_dplane_result status; enum zebra_dplane_result status;
enum zebra_sr_policy_update_label_mode update_mode;
op = dplane_ctx_get_op(ctx); op = dplane_ctx_get_op(ctx);
status = dplane_ctx_get_status(ctx); status = dplane_ctx_get_status(ctx);
@ -1941,6 +1951,8 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
dplane_ctx_get_in_label(ctx), dplane_ctx_get_in_label(ctx),
dplane_res2str(status)); dplane_res2str(status));
label = dplane_ctx_get_in_label(ctx);
switch (op) { switch (op) {
case DPLANE_OP_LSP_INSTALL: case DPLANE_OP_LSP_INSTALL:
case DPLANE_OP_LSP_UPDATE: case DPLANE_OP_LSP_UPDATE:
@ -1951,7 +1963,7 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
lsp_table = zvrf->lsp_table; lsp_table = zvrf->lsp_table;
tmp_ile.in_label = dplane_ctx_get_in_label(ctx); tmp_ile.in_label = label;
lsp = hash_lookup(lsp_table, &tmp_ile); lsp = hash_lookup(lsp_table, &tmp_ile);
if (lsp == NULL) { if (lsp == NULL) {
if (IS_ZEBRA_DEBUG_DPLANE) if (IS_ZEBRA_DEBUG_DPLANE)
@ -1985,14 +1997,22 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
} }
} }
update_mode = (op == DPLANE_OP_LSP_INSTALL)
? ZEBRA_SR_POLICY_LABEL_CREATED
: ZEBRA_SR_POLICY_LABEL_UPDATED;
zebra_sr_policy_label_update(label, update_mode);
break; break;
case DPLANE_OP_LSP_DELETE: case DPLANE_OP_LSP_DELETE:
if (status != ZEBRA_DPLANE_REQUEST_SUCCESS) if (status != ZEBRA_DPLANE_REQUEST_SUCCESS) {
flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE, flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE,
"LSP Deletion Failure: in-label %u", "LSP Deletion Failure: in-label %u",
dplane_ctx_get_in_label(ctx)); dplane_ctx_get_in_label(ctx));
break; break;
}
zebra_sr_policy_label_update(label,
ZEBRA_SR_POLICY_LABEL_REMOVED);
break;
default: default:
break; break;
@ -3419,6 +3439,21 @@ static int lsp_backup_znh_install(zebra_lsp_t *lsp, enum lsp_types_t type,
return 0; return 0;
} }
zebra_lsp_t *mpls_lsp_find(struct zebra_vrf *zvrf, mpls_label_t in_label)
{
struct hash *lsp_table;
zebra_ile_t tmp_ile;
/* Lookup table. */
lsp_table = zvrf->lsp_table;
if (!lsp_table)
return NULL;
/* If entry is not present, exit. */
tmp_ile.in_label = in_label;
return hash_lookup(lsp_table, &tmp_ile);
}
/* /*
* Uninstall a particular NHLFE in the forwarding table. If this is * Uninstall a particular NHLFE in the forwarding table. If this is
* the only NHLFE, the entire LSP forwarding entry has to be deleted. * the only NHLFE, the entire LSP forwarding entry has to be deleted.

View File

@ -33,6 +33,7 @@
#include "mpls.h" #include "mpls.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
#include "zebra/zebra_vrf.h" #include "zebra/zebra_vrf.h"
#include "hook.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -325,6 +326,11 @@ int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
const mpls_label_t *out_labels, enum nexthop_types_t gtype, const mpls_label_t *out_labels, enum nexthop_types_t gtype,
const union g_addr *gate, ifindex_t ifindex); const union g_addr *gate, ifindex_t ifindex);
/*
* Lookup LSP by its input label.
*/
zebra_lsp_t *mpls_lsp_find(struct zebra_vrf *zvrf, mpls_label_t in_label);
/* /*
* Uninstall a particular NHLFE in the forwarding table. If this is * Uninstall a particular NHLFE in the forwarding table. If this is
* the only NHLFE, the entire LSP forwarding entry has to be deleted. * the only NHLFE, the entire LSP forwarding entry has to be deleted.
@ -461,6 +467,7 @@ static inline uint8_t lsp_distance(enum lsp_types_t type)
case ZEBRA_LSP_SHARP: case ZEBRA_LSP_SHARP:
case ZEBRA_LSP_OSPF_SR: case ZEBRA_LSP_OSPF_SR:
case ZEBRA_LSP_ISIS_SR: case ZEBRA_LSP_ISIS_SR:
case ZEBRA_LSP_SRTE:
return 150; return 150;
} }
@ -492,6 +499,8 @@ static inline enum lsp_types_t lsp_type_from_re_type(int re_type)
return ZEBRA_LSP_ISIS_SR; return ZEBRA_LSP_ISIS_SR;
case ZEBRA_ROUTE_SHARP: case ZEBRA_ROUTE_SHARP:
return ZEBRA_LSP_SHARP; return ZEBRA_LSP_SHARP;
case ZEBRA_ROUTE_SRTE:
return ZEBRA_LSP_SRTE;
default: default:
return ZEBRA_LSP_NONE; return ZEBRA_LSP_NONE;
} }
@ -517,6 +526,8 @@ static inline int re_type_from_lsp_type(enum lsp_types_t lsp_type)
return ZEBRA_ROUTE_KERNEL; return ZEBRA_ROUTE_KERNEL;
case ZEBRA_LSP_SHARP: case ZEBRA_LSP_SHARP:
return ZEBRA_ROUTE_SHARP; return ZEBRA_ROUTE_SHARP;
case ZEBRA_LSP_SRTE:
return ZEBRA_ROUTE_SRTE;
} }
/* /*
@ -544,6 +555,8 @@ static inline const char *nhlfe_type2str(enum lsp_types_t lsp_type)
return "SR (IS-IS)"; return "SR (IS-IS)";
case ZEBRA_LSP_SHARP: case ZEBRA_LSP_SHARP:
return "SHARP"; return "SHARP";
case ZEBRA_LSP_SRTE:
return "SR-TE";
case ZEBRA_LSP_NONE: case ZEBRA_LSP_NONE:
return "Unknown"; return "Unknown";
} }

View File

@ -28,6 +28,7 @@
#include "lib/mpls.h" #include "lib/mpls.h"
#include "lib/jhash.h" #include "lib/jhash.h"
#include "lib/debug.h" #include "lib/debug.h"
#include "lib/lib_errors.h"
#include "zebra/connected.h" #include "zebra/connected.h"
#include "zebra/debug.h" #include "zebra/debug.h"
@ -36,6 +37,7 @@
#include "zebra/zebra_rnh.h" #include "zebra/zebra_rnh.h"
#include "zebra/zebra_routemap.h" #include "zebra/zebra_routemap.h"
#include "zebra/zebra_memory.h" #include "zebra/zebra_memory.h"
#include "zebra/zebra_srte.h"
#include "zebra/zserv.h" #include "zebra/zserv.h"
#include "zebra/rt.h" #include "zebra/rt.h"
#include "zebra_errors.h" #include "zebra_errors.h"
@ -1620,7 +1622,8 @@ void zebra_nhg_increment_ref(struct nhg_hash_entry *nhe)
} }
static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop, static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop,
struct nexthop *nexthop) struct nexthop *nexthop,
struct zebra_sr_policy *policy)
{ {
struct nexthop *resolved_hop; struct nexthop *resolved_hop;
uint8_t num_labels = 0; uint8_t num_labels = 0;
@ -1684,7 +1687,21 @@ static void nexthop_set_resolved(afi_t afi, const struct nexthop *newhop,
resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
/* Copy labels of the resolved route and the parent resolving to it */ /* Copy labels of the resolved route and the parent resolving to it */
if (newhop->nh_label) { if (policy) {
int i = 0;
/*
* Don't push the first SID if the corresponding action in the
* LFIB is POP.
*/
if (!newhop->nh_label || !newhop->nh_label->num_labels
|| newhop->nh_label->label[0] == MPLS_LABEL_IMPLICIT_NULL)
i = 1;
for (; i < policy->segment_list.label_num; i++)
labels[num_labels++] = policy->segment_list.labels[i];
label_type = policy->segment_list.type;
} else if (newhop->nh_label) {
for (i = 0; i < newhop->nh_label->num_labels; i++) { for (i = 0; i < newhop->nh_label->num_labels; i++) {
/* Be a bit picky about overrunning the local array */ /* Be a bit picky about overrunning the local array */
if (num_labels >= MPLS_MAX_LABELS) { if (num_labels >= MPLS_MAX_LABELS) {
@ -1771,11 +1788,13 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
struct route_node *rn; struct route_node *rn;
struct route_entry *match = NULL; struct route_entry *match = NULL;
int resolved; int resolved;
zebra_nhlfe_t *nhlfe;
struct nexthop *newhop; struct nexthop *newhop;
struct interface *ifp; struct interface *ifp;
rib_dest_t *dest; rib_dest_t *dest;
struct zebra_vrf *zvrf; struct zebra_vrf *zvrf;
struct in_addr ipv4; struct in_addr local_ipv4;
struct in_addr *ipv4;
if ((nexthop->type == NEXTHOP_TYPE_IPV4) if ((nexthop->type == NEXTHOP_TYPE_IPV4)
|| nexthop->type == NEXTHOP_TYPE_IPV6) || nexthop->type == NEXTHOP_TYPE_IPV6)
@ -1839,6 +1858,51 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
/* Validation for ipv4 mapped ipv6 nexthop. */ /* Validation for ipv4 mapped ipv6 nexthop. */
if (IS_MAPPED_IPV6(&nexthop->gate.ipv6)) { if (IS_MAPPED_IPV6(&nexthop->gate.ipv6)) {
afi = AFI_IP; afi = AFI_IP;
ipv4 = &local_ipv4;
ipv4_mapped_ipv6_to_ipv4(&nexthop->gate.ipv6, ipv4);
} else {
ipv4 = &nexthop->gate.ipv4;
}
if (nexthop->srte_color) {
struct ipaddr endpoint = {0};
struct zebra_sr_policy *policy;
switch (afi) {
case AFI_IP:
endpoint.ipa_type = IPADDR_V4;
endpoint.ipaddr_v4 = *ipv4;
break;
case AFI_IP6:
endpoint.ipa_type = IPADDR_V6;
endpoint.ipaddr_v6 = nexthop->gate.ipv6;
break;
default:
flog_err(EC_LIB_DEVELOPMENT,
"%s: unknown address-family: %u", __func__,
afi);
exit(1);
}
policy = zebra_sr_policy_find(nexthop->srte_color, &endpoint);
if (policy && policy->status == ZEBRA_SR_POLICY_UP) {
resolved = 0;
frr_each_safe (nhlfe_list, &policy->lsp->nhlfe_list,
nhlfe) {
if (!CHECK_FLAG(nhlfe->flags,
NHLFE_FLAG_SELECTED)
|| CHECK_FLAG(nhlfe->flags,
NHLFE_FLAG_DELETED))
continue;
SET_FLAG(nexthop->flags,
NEXTHOP_FLAG_RECURSIVE);
nexthop_set_resolved(afi, nhlfe->nexthop,
nexthop, policy);
resolved = 1;
}
if (resolved)
return 1;
}
} }
/* Make lookup prefix. */ /* Make lookup prefix. */
@ -1847,12 +1911,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
case AFI_IP: case AFI_IP:
p.family = AF_INET; p.family = AF_INET;
p.prefixlen = IPV4_MAX_PREFIXLEN; p.prefixlen = IPV4_MAX_PREFIXLEN;
if (IS_MAPPED_IPV6(&nexthop->gate.ipv6)) { p.u.prefix4 = *ipv4;
ipv4_mapped_ipv6_to_ipv4(&nexthop->gate.ipv6, &ipv4);
p.u.prefix4 = ipv4;
} else {
p.u.prefix4 = nexthop->gate.ipv4;
}
break; break;
case AFI_IP6: case AFI_IP6:
p.family = AF_INET6; p.family = AF_INET6;
@ -1978,7 +2037,8 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
SET_FLAG(nexthop->flags, SET_FLAG(nexthop->flags,
NEXTHOP_FLAG_RECURSIVE); NEXTHOP_FLAG_RECURSIVE);
nexthop_set_resolved(afi, newhop, nexthop); nexthop_set_resolved(afi, newhop, nexthop,
NULL);
resolved = 1; resolved = 1;
} }
@ -2001,7 +2061,8 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
SET_FLAG(nexthop->flags, SET_FLAG(nexthop->flags,
NEXTHOP_FLAG_RECURSIVE); NEXTHOP_FLAG_RECURSIVE);
nexthop_set_resolved(afi, newhop, nexthop); nexthop_set_resolved(afi, newhop, nexthop,
NULL);
resolved = 1; resolved = 1;
} }
done_with_match: done_with_match:

View File

@ -106,7 +106,8 @@ static const struct {
[ZEBRA_ROUTE_PBR] = {ZEBRA_ROUTE_PBR, 200, 5}, [ZEBRA_ROUTE_PBR] = {ZEBRA_ROUTE_PBR, 200, 5},
[ZEBRA_ROUTE_BFD] = {ZEBRA_ROUTE_BFD, 255, 5}, [ZEBRA_ROUTE_BFD] = {ZEBRA_ROUTE_BFD, 255, 5},
[ZEBRA_ROUTE_OPENFABRIC] = {ZEBRA_ROUTE_OPENFABRIC, 115, 3}, [ZEBRA_ROUTE_OPENFABRIC] = {ZEBRA_ROUTE_OPENFABRIC, 115, 3},
[ZEBRA_ROUTE_VRRP] = {ZEBRA_ROUTE_VRRP, 255, 5} [ZEBRA_ROUTE_VRRP] = {ZEBRA_ROUTE_VRRP, 255, 5},
[ZEBRA_ROUTE_SRTE] = {ZEBRA_ROUTE_SRTE, 255, 5},
/* Any new route type added to zebra, should be mirrored here */ /* Any new route type added to zebra, should be mirrored here */
/* no entry/default: 150 */ /* no entry/default: 150 */

View File

@ -46,6 +46,7 @@
#include "zebra/debug.h" #include "zebra/debug.h"
#include "zebra/zebra_rnh.h" #include "zebra/zebra_rnh.h"
#include "zebra/zebra_routemap.h" #include "zebra/zebra_routemap.h"
#include "zebra/zebra_srte.h"
#include "zebra/interface.h" #include "zebra/interface.h"
#include "zebra/zebra_memory.h" #include "zebra/zebra_memory.h"
#include "zebra/zebra_errors.h" #include "zebra/zebra_errors.h"
@ -57,8 +58,6 @@ static void free_state(vrf_id_t vrf_id, struct route_entry *re,
static void copy_state(struct rnh *rnh, const struct route_entry *re, static void copy_state(struct rnh *rnh, const struct route_entry *re,
struct route_node *rn); struct route_node *rn);
static int compare_state(struct route_entry *r1, struct route_entry *r2); static int compare_state(struct route_entry *r1, struct route_entry *r2);
static int send_client(struct rnh *rnh, struct zserv *client,
enum rnh_type type, vrf_id_t vrf_id);
static void print_rnh(struct route_node *rn, struct vty *vty); static void print_rnh(struct route_node *rn, struct vty *vty);
static int zebra_client_cleanup_rnh(struct zserv *client); static int zebra_client_cleanup_rnh(struct zserv *client);
@ -305,7 +304,7 @@ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
* We always need to respond with known information, * We always need to respond with known information,
* currently multiple daemons expect this behavior * currently multiple daemons expect this behavior
*/ */
send_client(rnh, client, type, vrf_id); zebra_send_rnh_update(rnh, client, type, vrf_id, 0);
} }
void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client,
@ -531,8 +530,9 @@ static void zebra_rnh_eval_import_check_entry(struct zebra_vrf *zvrf, afi_t afi,
} }
/* state changed, notify clients */ /* state changed, notify clients */
for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) { for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) {
send_client(rnh, client, zebra_send_rnh_update(rnh, client,
RNH_IMPORT_CHECK_TYPE, zvrf->vrf->vrf_id); RNH_IMPORT_CHECK_TYPE,
zvrf->vrf->vrf_id, 0);
} }
} }
} }
@ -594,7 +594,8 @@ static void zebra_rnh_notify_protocol_clients(struct zebra_vrf *zvrf, afi_t afi,
zebra_route_string(client->proto)); zebra_route_string(client->proto));
} }
send_client(rnh, client, RNH_NEXTHOP_TYPE, zvrf->vrf->vrf_id); zebra_send_rnh_update(rnh, client, RNH_NEXTHOP_TYPE,
zvrf->vrf->vrf_id, 0);
} }
if (re) if (re)
@ -1107,8 +1108,9 @@ static int compare_state(struct route_entry *r1, struct route_entry *r2)
return 0; return 0;
} }
static int send_client(struct rnh *rnh, struct zserv *client, int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client,
enum rnh_type type, vrf_id_t vrf_id) enum rnh_type type, vrf_id_t vrf_id,
uint32_t srte_color)
{ {
struct stream *s = NULL; struct stream *s = NULL;
struct route_entry *re; struct route_entry *re;
@ -1117,6 +1119,7 @@ static int send_client(struct rnh *rnh, struct zserv *client,
struct nexthop *nh; struct nexthop *nh;
struct route_node *rn; struct route_node *rn;
int ret; int ret;
uint32_t message = 0;
int cmd = (type == RNH_IMPORT_CHECK_TYPE) ? ZEBRA_IMPORT_CHECK_UPDATE int cmd = (type == RNH_IMPORT_CHECK_TYPE) ? ZEBRA_IMPORT_CHECK_UPDATE
: ZEBRA_NEXTHOP_UPDATE; : ZEBRA_NEXTHOP_UPDATE;
@ -1128,6 +1131,11 @@ static int send_client(struct rnh *rnh, struct zserv *client,
zclient_create_header(s, cmd, vrf_id); zclient_create_header(s, cmd, vrf_id);
/* Message flags. */
if (srte_color)
SET_FLAG(message, ZAPI_MESSAGE_SRTE);
stream_putl(s, message);
stream_putw(s, rn->p.family); stream_putw(s, rn->p.family);
switch (rn->p.family) { switch (rn->p.family) {
case AF_INET: case AF_INET:
@ -1144,6 +1152,9 @@ static int send_client(struct rnh *rnh, struct zserv *client,
__func__, rn->p.family); __func__, rn->p.family);
goto failure; goto failure;
} }
if (srte_color)
stream_putl(s, srte_color);
if (re) { if (re) {
struct zapi_nexthop znh; struct zapi_nexthop znh;
struct nexthop_group *nhg; struct nexthop_group *nhg;
@ -1160,7 +1171,7 @@ static int send_client(struct rnh *rnh, struct zserv *client,
for (ALL_NEXTHOPS_PTR(nhg, nh)) for (ALL_NEXTHOPS_PTR(nhg, nh))
if (rnh_nexthop_valid(re, nh)) { if (rnh_nexthop_valid(re, nh)) {
zapi_nexthop_from_nexthop(&znh, nh); zapi_nexthop_from_nexthop(&znh, nh);
ret = zapi_nexthop_encode(s, &znh, 0/*flags*/); ret = zapi_nexthop_encode(s, &znh, 0, message);
if (ret < 0) if (ret < 0)
goto failure; goto failure;
@ -1173,7 +1184,8 @@ static int send_client(struct rnh *rnh, struct zserv *client,
if (rnh_nexthop_valid(re, nh)) { if (rnh_nexthop_valid(re, nh)) {
zapi_nexthop_from_nexthop(&znh, nh); zapi_nexthop_from_nexthop(&znh, nh);
ret = zapi_nexthop_encode( ret = zapi_nexthop_encode(
s, &znh, 0 /* flags */); s, &znh, 0 /* flags */,
0 /* message */);
if (ret < 0) if (ret < 0)
goto failure; goto failure;

View File

@ -50,6 +50,9 @@ extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
extern void zebra_free_rnh(struct rnh *rnh); extern void zebra_free_rnh(struct rnh *rnh);
extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
enum rnh_type type, vrf_id_t vrfid); enum rnh_type type, vrf_id_t vrfid);
extern int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client,
enum rnh_type type, vrf_id_t vrf_id,
uint32_t srte_color);
extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *, bool *); extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *, bool *);
extern void zebra_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *); extern void zebra_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *);
extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client,

378
zebra/zebra_srte.c Normal file
View File

@ -0,0 +1,378 @@
/* Zebra SR-TE code
* Copyright (C) 2020 NetDEF, Inc.
*
* 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
*/
#include <zebra.h>
#include "lib/zclient.h"
#include "lib/lib_errors.h"
#include "zebra/zebra_srte.h"
#include "zebra/zebra_memory.h"
#include "zebra/zebra_mpls.h"
#include "zebra/zebra_rnh.h"
#include "zebra/zapi_msg.h"
DEFINE_MTYPE_STATIC(ZEBRA, ZEBRA_SR_POLICY, "SR Policy")
static void zebra_sr_policy_deactivate(struct zebra_sr_policy *policy);
/* Generate rb-tree of SR Policy instances. */
static inline int
zebra_sr_policy_instance_compare(const struct zebra_sr_policy *a,
const struct zebra_sr_policy *b)
{
return sr_policy_compare(&a->endpoint, &b->endpoint, a->color,
b->color);
}
RB_GENERATE(zebra_sr_policy_instance_head, zebra_sr_policy, entry,
zebra_sr_policy_instance_compare)
struct zebra_sr_policy_instance_head zebra_sr_policy_instances =
RB_INITIALIZER(&zebra_sr_policy_instances);
struct zebra_sr_policy *zebra_sr_policy_add(uint32_t color,
struct ipaddr *endpoint, char *name)
{
struct zebra_sr_policy *policy;
policy = XCALLOC(MTYPE_ZEBRA_SR_POLICY, sizeof(*policy));
policy->color = color;
policy->endpoint = *endpoint;
strlcpy(policy->name, name, sizeof(policy->name));
policy->status = ZEBRA_SR_POLICY_DOWN;
RB_INSERT(zebra_sr_policy_instance_head, &zebra_sr_policy_instances,
policy);
return policy;
}
void zebra_sr_policy_del(struct zebra_sr_policy *policy)
{
if (policy->status == ZEBRA_SR_POLICY_UP)
zebra_sr_policy_deactivate(policy);
RB_REMOVE(zebra_sr_policy_instance_head, &zebra_sr_policy_instances,
policy);
XFREE(MTYPE_ZEBRA_SR_POLICY, policy);
}
struct zebra_sr_policy *zebra_sr_policy_find(uint32_t color,
struct ipaddr *endpoint)
{
struct zebra_sr_policy policy = {};
policy.color = color;
policy.endpoint = *endpoint;
return RB_FIND(zebra_sr_policy_instance_head,
&zebra_sr_policy_instances, &policy);
}
struct zebra_sr_policy *zebra_sr_policy_find_by_name(char *name)
{
struct zebra_sr_policy *policy;
// TODO: create index for policy names
RB_FOREACH (policy, zebra_sr_policy_instance_head,
&zebra_sr_policy_instances) {
if (strcmp(policy->name, name) == 0)
return policy;
}
return NULL;
}
static int zebra_sr_policy_notify_update_client(struct zebra_sr_policy *policy,
struct zserv *client)
{
const zebra_nhlfe_t *nhlfe;
struct stream *s;
uint32_t message = 0;
unsigned long nump = 0;
uint8_t num;
struct zapi_nexthop znh;
int ret;
/* Get output stream. */
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_NEXTHOP_UPDATE, zvrf_id(policy->zvrf));
/* Message flags. */
SET_FLAG(message, ZAPI_MESSAGE_SRTE);
stream_putl(s, message);
switch (policy->endpoint.ipa_type) {
case IPADDR_V4:
stream_putw(s, AF_INET);
stream_putc(s, IPV4_MAX_BITLEN);
stream_put_in_addr(s, &policy->endpoint.ipaddr_v4);
break;
case IPADDR_V6:
stream_putw(s, AF_INET6);
stream_putc(s, IPV6_MAX_BITLEN);
stream_put(s, &policy->endpoint.ipaddr_v6, IPV6_MAX_BYTELEN);
break;
default:
flog_warn(EC_LIB_DEVELOPMENT,
"%s: unknown policy endpoint address family: %u",
__func__, policy->endpoint.ipa_type);
exit(1);
}
stream_putl(s, policy->color);
num = 0;
frr_each (nhlfe_list_const, &policy->lsp->nhlfe_list, nhlfe) {
if (!CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
|| CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED))
continue;
if (num == 0) {
stream_putc(s, re_type_from_lsp_type(nhlfe->type));
stream_putw(s, 0); /* instance - not available */
stream_putc(s, nhlfe->distance);
stream_putl(s, 0); /* metric - not available */
nump = stream_get_endp(s);
stream_putc(s, 0);
}
zapi_nexthop_from_nexthop(&znh, nhlfe->nexthop);
ret = zapi_nexthop_encode(s, &znh, 0, message);
if (ret < 0)
goto failure;
num++;
}
stream_putc_at(s, nump, num);
stream_putw_at(s, 0, stream_get_endp(s));
client->nh_last_upd_time = monotime(NULL);
client->last_write_cmd = ZEBRA_NEXTHOP_UPDATE;
return zserv_send_message(client, s);
failure:
stream_free(s);
return -1;
}
static void zebra_sr_policy_notify_update(struct zebra_sr_policy *policy)
{
struct rnh *rnh;
struct prefix p = {};
struct zebra_vrf *zvrf;
struct listnode *node;
struct zserv *client;
zvrf = policy->zvrf;
switch (policy->endpoint.ipa_type) {
case IPADDR_V4:
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
p.u.prefix4 = policy->endpoint.ipaddr_v4;
break;
case IPADDR_V6:
p.family = AF_INET6;
p.prefixlen = IPV6_MAX_BITLEN;
p.u.prefix6 = policy->endpoint.ipaddr_v6;
break;
default:
flog_warn(EC_LIB_DEVELOPMENT,
"%s: unknown policy endpoint address family: %u",
__func__, policy->endpoint.ipa_type);
exit(1);
}
rnh = zebra_lookup_rnh(&p, zvrf_id(zvrf), RNH_NEXTHOP_TYPE);
if (!rnh)
return;
for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) {
if (policy->status == ZEBRA_SR_POLICY_UP)
zebra_sr_policy_notify_update_client(policy, client);
else
/* Fallback to the IGP shortest path. */
zebra_send_rnh_update(rnh, client, RNH_NEXTHOP_TYPE,
zvrf_id(zvrf), policy->color);
}
}
static void zebra_sr_policy_activate(struct zebra_sr_policy *policy,
zebra_lsp_t *lsp)
{
policy->status = ZEBRA_SR_POLICY_UP;
policy->lsp = lsp;
(void)zebra_sr_policy_bsid_install(policy);
zsend_sr_policy_notify_status(policy->color, &policy->endpoint,
policy->name, ZEBRA_SR_POLICY_UP);
zebra_sr_policy_notify_update(policy);
}
static void zebra_sr_policy_update(struct zebra_sr_policy *policy,
zebra_lsp_t *lsp,
struct zapi_srte_tunnel *old_tunnel)
{
bool bsid_changed;
bool segment_list_changed;
policy->lsp = lsp;
bsid_changed =
policy->segment_list.local_label != old_tunnel->local_label;
segment_list_changed =
policy->segment_list.label_num != old_tunnel->label_num
|| memcmp(policy->segment_list.labels, old_tunnel->labels,
sizeof(mpls_label_t)
* policy->segment_list.label_num);
/* Re-install label stack if necessary. */
if (bsid_changed || segment_list_changed) {
zebra_sr_policy_bsid_uninstall(policy, old_tunnel->local_label);
(void)zebra_sr_policy_bsid_install(policy);
}
zsend_sr_policy_notify_status(policy->color, &policy->endpoint,
policy->name, ZEBRA_SR_POLICY_UP);
/* Handle segment-list update. */
if (segment_list_changed)
zebra_sr_policy_notify_update(policy);
}
static void zebra_sr_policy_deactivate(struct zebra_sr_policy *policy)
{
policy->status = ZEBRA_SR_POLICY_DOWN;
policy->lsp = NULL;
zebra_sr_policy_bsid_uninstall(policy,
policy->segment_list.local_label);
zsend_sr_policy_notify_status(policy->color, &policy->endpoint,
policy->name, ZEBRA_SR_POLICY_DOWN);
zebra_sr_policy_notify_update(policy);
}
int zebra_sr_policy_validate(struct zebra_sr_policy *policy,
struct zapi_srte_tunnel *new_tunnel)
{
struct zapi_srte_tunnel old_tunnel = policy->segment_list;
zebra_lsp_t *lsp;
if (new_tunnel)
policy->segment_list = *new_tunnel;
/* Try to resolve the Binding-SID nexthops. */
lsp = mpls_lsp_find(policy->zvrf, policy->segment_list.labels[0]);
if (!lsp || !lsp->best_nhlfe
|| lsp->addr_family != ipaddr_family(&policy->endpoint)) {
if (policy->status == ZEBRA_SR_POLICY_UP)
zebra_sr_policy_deactivate(policy);
return -1;
}
/* First label was resolved successfully. */
if (policy->status == ZEBRA_SR_POLICY_DOWN)
zebra_sr_policy_activate(policy, lsp);
else
zebra_sr_policy_update(policy, lsp, &old_tunnel);
return 0;
}
int zebra_sr_policy_bsid_install(struct zebra_sr_policy *policy)
{
struct zapi_srte_tunnel *zt = &policy->segment_list;
zebra_nhlfe_t *nhlfe;
if (zt->local_label == MPLS_LABEL_NONE)
return 0;
frr_each_safe (nhlfe_list, &policy->lsp->nhlfe_list, nhlfe) {
uint8_t num_out_labels;
mpls_label_t *out_labels;
mpls_label_t null_label = MPLS_LABEL_IMPLICIT_NULL;
if (!CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED)
|| CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED))
continue;
/*
* Don't push the first SID if the corresponding action in the
* LFIB is POP.
*/
if (!nhlfe->nexthop->nh_label
|| !nhlfe->nexthop->nh_label->num_labels
|| nhlfe->nexthop->nh_label->label[0]
== MPLS_LABEL_IMPLICIT_NULL) {
if (zt->label_num > 1) {
num_out_labels = zt->label_num - 1;
out_labels = &zt->labels[1];
} else {
num_out_labels = 1;
out_labels = &null_label;
}
} else {
num_out_labels = zt->label_num;
out_labels = zt->labels;
}
if (mpls_lsp_install(
policy->zvrf, zt->type, zt->local_label,
num_out_labels, out_labels, nhlfe->nexthop->type,
&nhlfe->nexthop->gate, nhlfe->nexthop->ifindex)
< 0)
return -1;
}
return 0;
}
void zebra_sr_policy_bsid_uninstall(struct zebra_sr_policy *policy,
mpls_label_t old_bsid)
{
struct zapi_srte_tunnel *zt = &policy->segment_list;
mpls_lsp_uninstall_all_vrf(policy->zvrf, zt->type, old_bsid);
}
int zebra_sr_policy_label_update(mpls_label_t label,
enum zebra_sr_policy_update_label_mode mode)
{
struct zebra_sr_policy *policy;
RB_FOREACH (policy, zebra_sr_policy_instance_head,
&zebra_sr_policy_instances) {
mpls_label_t next_hop_label;
next_hop_label = policy->segment_list.labels[0];
if (next_hop_label != label)
continue;
switch (mode) {
case ZEBRA_SR_POLICY_LABEL_CREATED:
case ZEBRA_SR_POLICY_LABEL_UPDATED:
case ZEBRA_SR_POLICY_LABEL_REMOVED:
zebra_sr_policy_validate(policy, NULL);
break;
}
}
return 0;
}
void zebra_srte_init(void)
{
}

74
zebra/zebra_srte.h Normal file
View File

@ -0,0 +1,74 @@
/* Zebra's client header.
* Copyright (C) 2020 Netdef, Inc.
*
* 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 _ZEBRA_SRTE_H
#define _ZEBRA_SRTE_H
#include "zebra/zebra_mpls.h"
#include "lib/zclient.h"
#include "lib/srte.h"
#ifdef __cplusplus
extern "C" {
#endif
enum zebra_sr_policy_update_label_mode {
ZEBRA_SR_POLICY_LABEL_CREATED = 1,
ZEBRA_SR_POLICY_LABEL_UPDATED = 2,
ZEBRA_SR_POLICY_LABEL_REMOVED = 3,
};
struct zebra_sr_policy {
RB_ENTRY(zebra_sr_policy) entry;
uint32_t color;
struct ipaddr endpoint;
char name[SRTE_POLICY_NAME_MAX_LENGTH];
enum zebra_sr_policy_status status;
struct zapi_srte_tunnel segment_list;
zebra_lsp_t *lsp;
struct zebra_vrf *zvrf;
};
RB_HEAD(zebra_sr_policy_instance_head, zebra_sr_policy);
RB_PROTOTYPE(zebra_sr_policy_instance_head, zebra_sr_policy, entry,
zebra_sr_policy_instance_compare)
extern struct zebra_sr_policy_instance_head zebra_sr_policy_instances;
struct zebra_sr_policy *
zebra_sr_policy_add(uint32_t color, struct ipaddr *endpoint, char *name);
void zebra_sr_policy_del(struct zebra_sr_policy *policy);
struct zebra_sr_policy *zebra_sr_policy_find(uint32_t color,
struct ipaddr *endpoint);
struct zebra_sr_policy *zebra_sr_policy_find_by_name(char *name);
int zebra_sr_policy_validate(struct zebra_sr_policy *policy,
struct zapi_srte_tunnel *new_tunnel);
int zebra_sr_policy_bsid_install(struct zebra_sr_policy *policy);
void zebra_sr_policy_bsid_uninstall(struct zebra_sr_policy *policy,
mpls_label_t old_bsid);
void zebra_srte_init(void);
int zebra_sr_policy_label_update(mpls_label_t label,
enum zebra_sr_policy_update_label_mode mode);
#ifdef __cplusplus
}
#endif
#endif /* _ZEBRA_SRTE_H */

View File

@ -562,6 +562,10 @@ static void show_route_nexthop_helper(struct vty *vty,
if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
sizeof(buf))) sizeof(buf)))
vty_out(vty, ", src %s", buf); vty_out(vty, ", src %s", buf);
/* SR-TE information */
if (nexthop->srte_color)
vty_out(vty, ", SR-TE color %u",
nexthop->srte_color);
} }
break; break;
case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6:
@ -781,6 +785,9 @@ static void show_nexthop_json_helper(json_object *json_nexthop,
json_object_int_add(json_nexthop, "weight", json_object_int_add(json_nexthop, "weight",
nexthop->weight); nexthop->weight);
if (nexthop->srte_color)
json_object_int_add(json_nexthop, "srteColor",
nexthop->srte_color);
} }
static void vty_show_ip_route(struct vty *vty, struct route_node *rn, static void vty_show_ip_route(struct vty *vty, struct route_node *rn,