mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-04-29 12:18:12 +00:00
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>
This commit is contained in:
parent
b112b1abb4
commit
31f937fb43
@ -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"
|
||||
|
14
lib/ipaddr.h
14
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;
|
||||
|
@ -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),
|
||||
|
@ -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. */
|
||||
|
@ -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(©->gate, &nexthop->gate, sizeof(nexthop->gate));
|
||||
memcpy(©->src, &nexthop->src, sizeof(nexthop->src));
|
||||
memcpy(©->rmap_src, &nexthop->rmap_src, sizeof(nexthop->rmap_src));
|
||||
|
@ -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. */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define _ZEBRA_PRIVS_H
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include "lib/queue.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -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, "-"
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
56
lib/srte.h
Normal file
56
lib/srte.h
Normal 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 */
|
58
lib/stream.c
58
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)
|
||||
|
@ -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))) \
|
||||
|
@ -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 \
|
||||
|
137
lib/zclient.c
137
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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -6,6 +6,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true
|
||||
}
|
||||
@ -18,6 +21,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.1.2"
|
||||
@ -38,6 +44,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8300,
|
||||
"outLabelStack":[
|
||||
8300
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.1.2"
|
||||
@ -58,6 +67,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8400,
|
||||
"outLabelStack":[
|
||||
8400
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.1.2"
|
||||
@ -104,6 +116,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.1.2"
|
||||
@ -117,6 +132,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.1.2"
|
||||
|
@ -6,6 +6,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":20100,
|
||||
"outLabelStack":[
|
||||
20100
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.1.1"
|
||||
@ -26,6 +29,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.3.1"
|
||||
@ -39,6 +45,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":10400,
|
||||
"outLabelStack":[
|
||||
10400
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.4.1"
|
||||
@ -52,6 +61,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.4.1"
|
||||
@ -65,6 +77,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.4.1"
|
||||
@ -78,6 +93,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.0.1"
|
||||
@ -91,6 +109,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.0.1"
|
||||
@ -104,6 +125,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.1.1"
|
||||
@ -117,6 +141,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.1.1"
|
||||
|
@ -6,6 +6,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8100,
|
||||
"outLabelStack":[
|
||||
8100
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.3.2"
|
||||
@ -19,6 +22,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.3.2"
|
||||
@ -32,6 +38,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8400,
|
||||
"outLabelStack":[
|
||||
8400
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.3.2"
|
||||
@ -45,6 +54,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.3.2"
|
||||
@ -58,6 +70,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.3.2"
|
||||
|
@ -6,6 +6,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8100,
|
||||
"outLabelStack":[
|
||||
8100
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.4.2"
|
||||
@ -19,6 +22,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.4.2"
|
||||
@ -32,6 +38,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":8300,
|
||||
"outLabelStack":[
|
||||
8300
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.4.2"
|
||||
@ -45,6 +54,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true
|
||||
}
|
||||
@ -57,6 +69,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.4.2"
|
||||
@ -70,6 +85,9 @@
|
||||
{
|
||||
"type":"SR (OSPF)",
|
||||
"outLabel":3,
|
||||
"outLabelStack":[
|
||||
3
|
||||
],
|
||||
"distance":150,
|
||||
"installed":true,
|
||||
"nexthop":"10.0.4.2"
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include "zebra/zebra_routemap.h"
|
||||
#include "zebra/zebra_nb.h"
|
||||
#include "zebra/zebra_opaque.h"
|
||||
#include "zebra/zebra_srte.h"
|
||||
|
||||
#if defined(HANDLE_NETLINK_FUZZING)
|
||||
#include "zebra/kernel_netlink.h"
|
||||
@ -438,9 +439,10 @@ int main(int argc, char **argv)
|
||||
zebra_pw_vty_init();
|
||||
zebra_pbr_init();
|
||||
zebra_opaque_init();
|
||||
zebra_srte_init();
|
||||
|
||||
/* For debug purpose. */
|
||||
/* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
|
||||
/* For debug purpose. */
|
||||
/* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */
|
||||
|
||||
/* Process the configuration file. Among other configuration
|
||||
* directives we can meet those installing static routes. Such
|
||||
|
@ -179,7 +179,8 @@ static inline bool is_selfroute(int proto)
|
||||
|| (proto == RTPROT_NHRP) || (proto == RTPROT_EIGRP)
|
||||
|| (proto == RTPROT_LDP) || (proto == RTPROT_BABEL)
|
||||
|| (proto == RTPROT_RIP) || (proto == RTPROT_SHARP)
|
||||
|| (proto == RTPROT_PBR) || (proto == RTPROT_OPENFABRIC)) {
|
||||
|| (proto == RTPROT_PBR) || (proto == RTPROT_OPENFABRIC)
|
||||
|| (proto == RTPROT_SRTE)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -229,6 +230,9 @@ static inline int zebra2proto(int proto)
|
||||
case ZEBRA_ROUTE_OPENFABRIC:
|
||||
proto = RTPROT_OPENFABRIC;
|
||||
break;
|
||||
case ZEBRA_ROUTE_SRTE:
|
||||
proto = RTPROT_SRTE;
|
||||
break;
|
||||
case ZEBRA_ROUTE_TABLE:
|
||||
case ZEBRA_ROUTE_NHG:
|
||||
proto = RTPROT_ZEBRA;
|
||||
@ -294,6 +298,9 @@ static inline int proto2zebra(int proto, int family, bool is_nexthop)
|
||||
case RTPROT_OPENFABRIC:
|
||||
proto = ZEBRA_ROUTE_OPENFABRIC;
|
||||
break;
|
||||
case RTPROT_SRTE:
|
||||
proto = ZEBRA_ROUTE_SRTE;
|
||||
break;
|
||||
case RTPROT_ZEBRA:
|
||||
if (is_nexthop) {
|
||||
proto = ZEBRA_ROUTE_NHG;
|
||||
|
@ -60,6 +60,7 @@ extern "C" {
|
||||
#define RTPROT_PBR 195
|
||||
#define RTPROT_ZSTATIC 196
|
||||
#define RTPROT_OPENFABRIC 197
|
||||
#define RTPROT_SRTE 198
|
||||
|
||||
void rt_netlink_init(void);
|
||||
|
||||
|
@ -106,6 +106,7 @@ zebra_zebra_SOURCES = \
|
||||
zebra/zebra_router.c \
|
||||
zebra/zebra_rnh.c \
|
||||
zebra/zebra_routemap.c \
|
||||
zebra/zebra_srte.c \
|
||||
zebra/zebra_vrf.c \
|
||||
zebra/zebra_vty.c \
|
||||
zebra/zebra_vxlan.c \
|
||||
@ -167,6 +168,7 @@ noinst_HEADERS += \
|
||||
zebra/zebra_rnh.h \
|
||||
zebra/zebra_routemap.h \
|
||||
zebra/zebra_router.h \
|
||||
zebra/zebra_srte.h \
|
||||
zebra/zebra_vrf.h \
|
||||
zebra/zebra_vxlan.h \
|
||||
zebra/zebra_vxlan_private.h \
|
||||
|
114
zebra/zapi_msg.c
114
zebra/zapi_msg.c
@ -60,6 +60,7 @@
|
||||
#include "zebra/zebra_mlag.h"
|
||||
#include "zebra/connected.h"
|
||||
#include "zebra/zebra_opaque.h"
|
||||
#include "zebra/zebra_srte.h"
|
||||
|
||||
/* Encoding helpers -------------------------------------------------------- */
|
||||
|
||||
@ -1650,6 +1651,11 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
|
||||
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 */
|
||||
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL)
|
||||
&& api_nh->type != NEXTHOP_TYPE_IFINDEX
|
||||
@ -1729,6 +1735,11 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
|
||||
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 */
|
||||
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL)
|
||||
&& api_nh->type != NEXTHOP_TYPE_IFINDEX
|
||||
@ -2180,6 +2191,107 @@ static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS)
|
||||
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 */
|
||||
static void zread_table_manager_connect(struct zserv *client,
|
||||
struct stream *msg, vrf_id_t vrf_id)
|
||||
@ -2879,6 +2991,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
|
||||
[ZEBRA_BFD_CLIENT_REGISTER] = zebra_ptm_bfd_client_register,
|
||||
[ZEBRA_INTERFACE_ENABLE_RADV] = zebra_interface_radv_enable,
|
||||
[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_DELETE] = zread_mpls_labels_delete,
|
||||
[ZEBRA_MPLS_LABELS_REPLACE] = zread_mpls_labels_replace,
|
||||
|
@ -100,7 +100,9 @@ extern int zsend_assign_label_chunk_response(struct zserv *client,
|
||||
extern int zsend_label_manager_connect_response(struct zserv *client,
|
||||
vrf_id_t vrf_id,
|
||||
unsigned short result);
|
||||
|
||||
extern int zsend_sr_policy_notify_status(uint32_t color,
|
||||
struct ipaddr *endpoint, char *name,
|
||||
int status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "zebra/zebra_memory.h"
|
||||
#include "zebra/zebra_vrf.h"
|
||||
#include "zebra/zebra_mpls.h"
|
||||
#include "zebra/zebra_srte.h"
|
||||
#include "zebra/zebra_errors.h"
|
||||
|
||||
DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object")
|
||||
@ -1505,6 +1506,7 @@ static json_object *nhlfe_json(zebra_nhlfe_t *nhlfe)
|
||||
char buf[BUFSIZ];
|
||||
json_object *json_nhlfe = NULL;
|
||||
json_object *json_backups = NULL;
|
||||
json_object *json_label_stack;
|
||||
struct nexthop *nexthop = nhlfe->nexthop;
|
||||
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_int_add(json_nhlfe, "outLabel",
|
||||
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);
|
||||
|
||||
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.
|
||||
*/
|
||||
void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
|
||||
{
|
||||
struct zebra_vrf *zvrf;
|
||||
mpls_label_t label;
|
||||
zebra_ile_t tmp_ile;
|
||||
struct hash *lsp_table;
|
||||
zebra_lsp_t *lsp;
|
||||
@ -1931,6 +1940,7 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
|
||||
struct nexthop *nexthop;
|
||||
enum dplane_op_e op;
|
||||
enum zebra_dplane_result status;
|
||||
enum zebra_sr_policy_update_label_mode update_mode;
|
||||
|
||||
op = dplane_ctx_get_op(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_res2str(status));
|
||||
|
||||
label = dplane_ctx_get_in_label(ctx);
|
||||
|
||||
switch (op) {
|
||||
case DPLANE_OP_LSP_INSTALL:
|
||||
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;
|
||||
|
||||
tmp_ile.in_label = dplane_ctx_get_in_label(ctx);
|
||||
tmp_ile.in_label = label;
|
||||
lsp = hash_lookup(lsp_table, &tmp_ile);
|
||||
if (lsp == NULL) {
|
||||
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;
|
||||
|
||||
case DPLANE_OP_LSP_DELETE:
|
||||
if (status != ZEBRA_DPLANE_REQUEST_SUCCESS)
|
||||
if (status != ZEBRA_DPLANE_REQUEST_SUCCESS) {
|
||||
flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE,
|
||||
"LSP Deletion Failure: in-label %u",
|
||||
dplane_ctx_get_in_label(ctx));
|
||||
break;
|
||||
}
|
||||
zebra_sr_policy_label_update(label,
|
||||
ZEBRA_SR_POLICY_LABEL_REMOVED);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -3419,6 +3439,21 @@ static int lsp_backup_znh_install(zebra_lsp_t *lsp, enum lsp_types_t type,
|
||||
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
|
||||
* the only NHLFE, the entire LSP forwarding entry has to be deleted.
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "mpls.h"
|
||||
#include "zebra/zserv.h"
|
||||
#include "zebra/zebra_vrf.h"
|
||||
#include "hook.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
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 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
|
||||
* 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_OSPF_SR:
|
||||
case ZEBRA_LSP_ISIS_SR:
|
||||
case ZEBRA_LSP_SRTE:
|
||||
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;
|
||||
case ZEBRA_ROUTE_SHARP:
|
||||
return ZEBRA_LSP_SHARP;
|
||||
case ZEBRA_ROUTE_SRTE:
|
||||
return ZEBRA_LSP_SRTE;
|
||||
default:
|
||||
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;
|
||||
case ZEBRA_LSP_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)";
|
||||
case ZEBRA_LSP_SHARP:
|
||||
return "SHARP";
|
||||
case ZEBRA_LSP_SRTE:
|
||||
return "SR-TE";
|
||||
case ZEBRA_LSP_NONE:
|
||||
return "Unknown";
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "lib/mpls.h"
|
||||
#include "lib/jhash.h"
|
||||
#include "lib/debug.h"
|
||||
#include "lib/lib_errors.h"
|
||||
|
||||
#include "zebra/connected.h"
|
||||
#include "zebra/debug.h"
|
||||
@ -36,6 +37,7 @@
|
||||
#include "zebra/zebra_rnh.h"
|
||||
#include "zebra/zebra_routemap.h"
|
||||
#include "zebra/zebra_memory.h"
|
||||
#include "zebra/zebra_srte.h"
|
||||
#include "zebra/zserv.h"
|
||||
#include "zebra/rt.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,
|
||||
struct nexthop *nexthop)
|
||||
struct nexthop *nexthop,
|
||||
struct zebra_sr_policy *policy)
|
||||
{
|
||||
struct nexthop *resolved_hop;
|
||||
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;
|
||||
|
||||
/* 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++) {
|
||||
/* Be a bit picky about overrunning the local array */
|
||||
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_entry *match = NULL;
|
||||
int resolved;
|
||||
zebra_nhlfe_t *nhlfe;
|
||||
struct nexthop *newhop;
|
||||
struct interface *ifp;
|
||||
rib_dest_t *dest;
|
||||
struct zebra_vrf *zvrf;
|
||||
struct in_addr ipv4;
|
||||
struct in_addr local_ipv4;
|
||||
struct in_addr *ipv4;
|
||||
|
||||
if ((nexthop->type == NEXTHOP_TYPE_IPV4)
|
||||
|| 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. */
|
||||
if (IS_MAPPED_IPV6(&nexthop->gate.ipv6)) {
|
||||
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. */
|
||||
@ -1847,12 +1911,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
||||
case AFI_IP:
|
||||
p.family = AF_INET;
|
||||
p.prefixlen = IPV4_MAX_PREFIXLEN;
|
||||
if (IS_MAPPED_IPV6(&nexthop->gate.ipv6)) {
|
||||
ipv4_mapped_ipv6_to_ipv4(&nexthop->gate.ipv6, &ipv4);
|
||||
p.u.prefix4 = ipv4;
|
||||
} else {
|
||||
p.u.prefix4 = nexthop->gate.ipv4;
|
||||
}
|
||||
p.u.prefix4 = *ipv4;
|
||||
break;
|
||||
case AFI_IP6:
|
||||
p.family = AF_INET6;
|
||||
@ -1978,7 +2037,8 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
||||
|
||||
SET_FLAG(nexthop->flags,
|
||||
NEXTHOP_FLAG_RECURSIVE);
|
||||
nexthop_set_resolved(afi, newhop, nexthop);
|
||||
nexthop_set_resolved(afi, newhop, nexthop,
|
||||
NULL);
|
||||
resolved = 1;
|
||||
}
|
||||
|
||||
@ -2001,7 +2061,8 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
||||
|
||||
SET_FLAG(nexthop->flags,
|
||||
NEXTHOP_FLAG_RECURSIVE);
|
||||
nexthop_set_resolved(afi, newhop, nexthop);
|
||||
nexthop_set_resolved(afi, newhop, nexthop,
|
||||
NULL);
|
||||
resolved = 1;
|
||||
}
|
||||
done_with_match:
|
||||
|
@ -106,7 +106,8 @@ static const struct {
|
||||
[ZEBRA_ROUTE_PBR] = {ZEBRA_ROUTE_PBR, 200, 5},
|
||||
[ZEBRA_ROUTE_BFD] = {ZEBRA_ROUTE_BFD, 255, 5},
|
||||
[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 */
|
||||
|
||||
/* no entry/default: 150 */
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include "zebra/debug.h"
|
||||
#include "zebra/zebra_rnh.h"
|
||||
#include "zebra/zebra_routemap.h"
|
||||
#include "zebra/zebra_srte.h"
|
||||
#include "zebra/interface.h"
|
||||
#include "zebra/zebra_memory.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,
|
||||
struct route_node *rn);
|
||||
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 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,
|
||||
* 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,
|
||||
@ -531,8 +530,9 @@ static void zebra_rnh_eval_import_check_entry(struct zebra_vrf *zvrf, afi_t afi,
|
||||
}
|
||||
/* state changed, notify clients */
|
||||
for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) {
|
||||
send_client(rnh, client,
|
||||
RNH_IMPORT_CHECK_TYPE, zvrf->vrf->vrf_id);
|
||||
zebra_send_rnh_update(rnh, client,
|
||||
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));
|
||||
}
|
||||
|
||||
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)
|
||||
@ -1107,8 +1108,9 @@ static int compare_state(struct route_entry *r1, struct route_entry *r2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_client(struct rnh *rnh, struct zserv *client,
|
||||
enum rnh_type type, vrf_id_t vrf_id)
|
||||
int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client,
|
||||
enum rnh_type type, vrf_id_t vrf_id,
|
||||
uint32_t srte_color)
|
||||
{
|
||||
struct stream *s = NULL;
|
||||
struct route_entry *re;
|
||||
@ -1117,6 +1119,7 @@ static int send_client(struct rnh *rnh, struct zserv *client,
|
||||
struct nexthop *nh;
|
||||
struct route_node *rn;
|
||||
int ret;
|
||||
uint32_t message = 0;
|
||||
int cmd = (type == RNH_IMPORT_CHECK_TYPE) ? ZEBRA_IMPORT_CHECK_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);
|
||||
|
||||
/* Message flags. */
|
||||
if (srte_color)
|
||||
SET_FLAG(message, ZAPI_MESSAGE_SRTE);
|
||||
stream_putl(s, message);
|
||||
|
||||
stream_putw(s, rn->p.family);
|
||||
switch (rn->p.family) {
|
||||
case AF_INET:
|
||||
@ -1144,6 +1152,9 @@ static int send_client(struct rnh *rnh, struct zserv *client,
|
||||
__func__, rn->p.family);
|
||||
goto failure;
|
||||
}
|
||||
if (srte_color)
|
||||
stream_putl(s, srte_color);
|
||||
|
||||
if (re) {
|
||||
struct zapi_nexthop znh;
|
||||
struct nexthop_group *nhg;
|
||||
@ -1160,7 +1171,7 @@ static int send_client(struct rnh *rnh, struct zserv *client,
|
||||
for (ALL_NEXTHOPS_PTR(nhg, nh))
|
||||
if (rnh_nexthop_valid(re, 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)
|
||||
goto failure;
|
||||
|
||||
@ -1173,7 +1184,8 @@ static int send_client(struct rnh *rnh, struct zserv *client,
|
||||
if (rnh_nexthop_valid(re, nh)) {
|
||||
zapi_nexthop_from_nexthop(&znh, nh);
|
||||
ret = zapi_nexthop_encode(
|
||||
s, &znh, 0 /* flags */);
|
||||
s, &znh, 0 /* flags */,
|
||||
0 /* message */);
|
||||
if (ret < 0)
|
||||
goto failure;
|
||||
|
||||
|
@ -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_add_rnh_client(struct rnh *rnh, struct zserv *client,
|
||||
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_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *);
|
||||
extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client,
|
||||
|
378
zebra/zebra_srte.c
Normal file
378
zebra/zebra_srte.c
Normal 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
74
zebra/zebra_srte.h
Normal 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 */
|
@ -562,6 +562,10 @@ static void show_route_nexthop_helper(struct vty *vty,
|
||||
if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
|
||||
sizeof(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;
|
||||
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",
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user