summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--babeld/babel_interface.c2
-rw-r--r--babeld/babeld.c6
-rw-r--r--babeld/message.c16
-rw-r--r--babeld/util.c9
-rw-r--r--babeld/util.h8
-rw-r--r--bgpd/bgp_attr.c197
-rw-r--r--bgpd/bgp_clist.c4
-rw-r--r--bgpd/bgp_community.c7
-rw-r--r--bgpd/bgp_debug.c4
-rw-r--r--bgpd/bgp_fsm.c9
-rw-r--r--bgpd/bgp_mplsvpn.c293
-rw-r--r--bgpd/bgp_mplsvpn.h2
-rw-r--r--bgpd/bgp_nexthop.h1
-rw-r--r--bgpd/bgp_nht.c17
-rw-r--r--bgpd/bgp_route.c17
-rw-r--r--bgpd/bgp_routemap.c17
-rw-r--r--bgpd/bgp_updgrp.c2
-rw-r--r--bgpd/bgp_vty.c54
-rw-r--r--bgpd/bgp_zebra.c405
-rw-r--r--bgpd/bgp_zebra.h7
-rw-r--r--bgpd/bgpd.c18
-rw-r--r--bgpd/bgpd.h12
-rw-r--r--doc/developer/topotests.rst2
-rw-r--r--doc/user/bgp.rst3
-rw-r--r--doc/user/zebra.rst10
-rw-r--r--lib/nexthop.c9
-rw-r--r--lib/nexthop.h2
-rw-r--r--lib/northbound_oper.c38
-rw-r--r--ospfd/ospf_flood.c10
-rwxr-xr-xtests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py6
-rw-r--r--tests/topotests/bgp_peer_group_solo/__init__.py0
-rw-r--r--tests/topotests/bgp_peer_group_solo/r1/frr.conf21
-rw-r--r--tests/topotests/bgp_peer_group_solo/r2/frr.conf10
-rw-r--r--tests/topotests/bgp_peer_group_solo/r3/frr.conf10
-rw-r--r--tests/topotests/bgp_peer_group_solo/test_bgp_peer_group_solo.py102
-rw-r--r--tests/topotests/bgp_vpn_import_nexthop_default_vrf/__init__.py0
-rw-r--r--tests/topotests/bgp_vpn_import_nexthop_default_vrf/r1/frr.conf29
-rw-r--r--tests/topotests/bgp_vpn_import_nexthop_default_vrf/r2/frr.conf34
-rw-r--r--tests/topotests/bgp_vpn_import_nexthop_default_vrf/test_bgp_vpn_import_nexthop_default_vrf.py145
-rw-r--r--tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_init.json6
-rw-r--r--tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r1_vrf1.json6
-rw-r--r--tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r2_vrf2.json9
-rw-r--r--tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r2_vrf3.json9
-rw-r--r--tests/topotests/lib/common_config.py10
-rw-r--r--tests/topotests/mgmt_oper/oper.py20
-rw-r--r--tests/topotests/nhrp_redundancy/host/frr.conf (renamed from tests/topotests/nhrp_redundancy/host/zebra.conf)0
-rw-r--r--tests/topotests/nhrp_redundancy/nhc1/frr.conf (renamed from tests/topotests/nhrp_redundancy/nhc1/zebra.conf)11
-rw-r--r--tests/topotests/nhrp_redundancy/nhc1/nhrpd.conf11
-rw-r--r--tests/topotests/nhrp_redundancy/nhc2/frr.conf (renamed from tests/topotests/nhrp_redundancy/nhc2/zebra.conf)9
-rw-r--r--tests/topotests/nhrp_redundancy/nhc2/nhrpd.conf11
-rw-r--r--tests/topotests/nhrp_redundancy/nhs1/frr.conf (renamed from tests/topotests/nhrp_redundancy/nhs1/zebra.conf)7
-rw-r--r--tests/topotests/nhrp_redundancy/nhs1/nhrpd.conf9
-rw-r--r--tests/topotests/nhrp_redundancy/nhs2/frr.conf (renamed from tests/topotests/nhrp_redundancy/nhs2/zebra.conf)7
-rw-r--r--tests/topotests/nhrp_redundancy/nhs2/nhrpd.conf9
-rw-r--r--tests/topotests/nhrp_redundancy/nhs3/frr.conf (renamed from tests/topotests/nhrp_redundancy/nhs3/zebra.conf)7
-rw-r--r--tests/topotests/nhrp_redundancy/nhs3/nhrpd.conf9
-rw-r--r--tests/topotests/nhrp_redundancy/router/frr.conf (renamed from tests/topotests/nhrp_redundancy/router/zebra.conf)0
-rw-r--r--tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py76
-rw-r--r--tests/topotests/pytest.ini1
-rw-r--r--tests/topotests/srv6_sid_manager/ce1/bgpd.conf8
-rw-r--r--tests/topotests/srv6_sid_manager/ce1/ipv6_rib.json58
-rw-r--r--tests/topotests/srv6_sid_manager/ce1/zebra.conf14
-rw-r--r--tests/topotests/srv6_sid_manager/ce2/bgpd.conf8
-rw-r--r--tests/topotests/srv6_sid_manager/ce2/ipv6_rib.json58
-rw-r--r--tests/topotests/srv6_sid_manager/ce2/zebra.conf14
-rw-r--r--tests/topotests/srv6_sid_manager/ce3/bgpd.conf8
-rw-r--r--tests/topotests/srv6_sid_manager/ce3/ipv6_rib.json58
-rw-r--r--tests/topotests/srv6_sid_manager/ce3/zebra.conf14
-rw-r--r--tests/topotests/srv6_sid_manager/ce4/bgpd.conf8
-rw-r--r--tests/topotests/srv6_sid_manager/ce4/ipv6_rib.json58
-rw-r--r--tests/topotests/srv6_sid_manager/ce4/zebra.conf14
-rw-r--r--tests/topotests/srv6_sid_manager/ce5/bgpd.conf8
-rw-r--r--tests/topotests/srv6_sid_manager/ce5/ipv6_rib.json58
-rw-r--r--tests/topotests/srv6_sid_manager/ce5/zebra.conf14
-rw-r--r--tests/topotests/srv6_sid_manager/ce6/bgpd.conf8
-rw-r--r--tests/topotests/srv6_sid_manager/ce6/ipv6_rib.json58
-rw-r--r--tests/topotests/srv6_sid_manager/ce6/zebra.conf14
-rw-r--r--tests/topotests/srv6_sid_manager/dst/sharpd.conf0
-rw-r--r--tests/topotests/srv6_sid_manager/dst/zebra.conf22
-rw-r--r--tests/topotests/srv6_sid_manager/rt1/bgpd.conf67
-rw-r--r--tests/topotests/srv6_sid_manager/rt1/isisd.conf35
-rw-r--r--tests/topotests/srv6_sid_manager/rt1/sharpd.conf0
-rw-r--r--tests/topotests/srv6_sid_manager/rt1/show_ip_route.ref276
-rw-r--r--tests/topotests/srv6_sid_manager/rt1/show_ipv6_route.ref314
-rw-r--r--tests/topotests/srv6_sid_manager/rt1/show_srv6_locator_table.ref15
-rw-r--r--tests/topotests/srv6_sid_manager/rt1/show_yang_interface_isis_adjacencies.ref32
-rw-r--r--tests/topotests/srv6_sid_manager/rt1/vpnv6_rib.ref169
-rw-r--r--tests/topotests/srv6_sid_manager/rt1/vrf10_rib.ref86
-rw-r--r--tests/topotests/srv6_sid_manager/rt1/vrf20_rib.ref92
-rw-r--r--tests/topotests/srv6_sid_manager/rt1/zebra.conf37
-rw-r--r--tests/topotests/srv6_sid_manager/rt2/isisd.conf48
-rw-r--r--tests/topotests/srv6_sid_manager/rt2/show_ip_route.ref320
-rw-r--r--tests/topotests/srv6_sid_manager/rt2/show_ipv6_route.ref346
-rw-r--r--tests/topotests/srv6_sid_manager/rt2/show_srv6_locator_table.ref15
-rw-r--r--tests/topotests/srv6_sid_manager/rt2/show_yang_interface_isis_adjacencies.ref70
-rw-r--r--tests/topotests/srv6_sid_manager/rt2/zebra.conf34
-rw-r--r--tests/topotests/srv6_sid_manager/rt3/isisd.conf48
-rw-r--r--tests/topotests/srv6_sid_manager/rt3/show_ip_route.ref320
-rw-r--r--tests/topotests/srv6_sid_manager/rt3/show_ipv6_route.ref346
-rw-r--r--tests/topotests/srv6_sid_manager/rt3/show_srv6_locator_table.ref15
-rw-r--r--tests/topotests/srv6_sid_manager/rt3/show_yang_interface_isis_adjacencies.ref70
-rw-r--r--tests/topotests/srv6_sid_manager/rt3/zebra.conf33
-rw-r--r--tests/topotests/srv6_sid_manager/rt4/isisd.conf56
-rw-r--r--tests/topotests/srv6_sid_manager/rt4/show_ip_route.ref296
-rw-r--r--tests/topotests/srv6_sid_manager/rt4/show_ipv6_route.ref346
-rw-r--r--tests/topotests/srv6_sid_manager/rt4/show_srv6_locator_table.ref15
-rw-r--r--tests/topotests/srv6_sid_manager/rt4/show_yang_interface_isis_adjacencies.ref82
-rw-r--r--tests/topotests/srv6_sid_manager/rt4/zebra.conf36
-rw-r--r--tests/topotests/srv6_sid_manager/rt5/isisd.conf56
-rw-r--r--tests/topotests/srv6_sid_manager/rt5/show_ip_route.ref296
-rw-r--r--tests/topotests/srv6_sid_manager/rt5/show_ipv6_route.ref346
-rw-r--r--tests/topotests/srv6_sid_manager/rt5/show_srv6_locator_table.ref15
-rw-r--r--tests/topotests/srv6_sid_manager/rt5/show_yang_interface_isis_adjacencies.ref82
-rw-r--r--tests/topotests/srv6_sid_manager/rt5/zebra.conf36
-rw-r--r--tests/topotests/srv6_sid_manager/rt6/bgpd.conf68
-rw-r--r--tests/topotests/srv6_sid_manager/rt6/isisd.conf42
-rw-r--r--tests/topotests/srv6_sid_manager/rt6/sharpd.conf0
-rw-r--r--tests/topotests/srv6_sid_manager/rt6/show_ip_route.ref273
-rw-r--r--tests/topotests/srv6_sid_manager/rt6/show_ipv6_route.ref312
-rw-r--r--tests/topotests/srv6_sid_manager/rt6/show_srv6_locator_table.ref15
-rw-r--r--tests/topotests/srv6_sid_manager/rt6/show_yang_interface_isis_adjacencies.ref44
-rw-r--r--tests/topotests/srv6_sid_manager/rt6/vpnv6_rib.ref169
-rw-r--r--tests/topotests/srv6_sid_manager/rt6/vrf10_rib.ref92
-rw-r--r--tests/topotests/srv6_sid_manager/rt6/vrf20_rib.ref86
-rw-r--r--tests/topotests/srv6_sid_manager/rt6/zebra.conf45
-rw-r--r--tests/topotests/srv6_sid_manager/test_srv6_sid_manager.py421
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/__init__.py0
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r1/bgpd.conf24
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r1/ospfd.conf.after25
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r1/zebra.conf13
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r2/bgpd.conf23
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r2/isisd.conf25
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r2/ospfd.conf.after32
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r2/zebra.conf16
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r3/bgpd.conf23
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r3/isisd.conf25
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r3/ospfd.conf.after26
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r3/zebra.conf19
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r4/bgpd.conf24
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r4/isisd.conf31
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r4/ospfd.conf19
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r4/zebra.conf16
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r5/bgpd.conf23
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r5/isisd.conf26
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r5/ospfd.conf.after26
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r5/zebra.conf19
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r6/ospfd.conf.after32
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r6/zebra.conf22
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r7/bgpd.conf24
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r7/ospfd.conf.after26
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/r7/zebra.conf14
-rw-r--r--tests/topotests/zebra_fec_nexthop_resolution/test_zebra_fec_nexthop_resolution.py259
-rw-r--r--yang/frr-zebra.yang10
-rw-r--r--zebra/dplane_fpm_nl.c19
-rw-r--r--zebra/rib.h5
-rw-r--r--zebra/zebra_cli.c38
-rw-r--r--zebra/zebra_dplane.c165
-rw-r--r--zebra/zebra_mpls.c132
-rw-r--r--zebra/zebra_mpls.h8
-rw-r--r--zebra/zebra_nb.c7
-rw-r--r--zebra/zebra_nb.h4
-rw-r--r--zebra/zebra_nb_config.c53
-rw-r--r--zebra/zebra_rib.c15
-rw-r--r--zebra/zebra_vrf.h1
164 files changed, 9010 insertions, 543 deletions
diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c
index 943ae9def1..b83c7b1908 100644
--- a/babeld/babel_interface.c
+++ b/babeld/babel_interface.c
@@ -1351,7 +1351,7 @@ babel_interface_allocate (void)
/* All flags are unset */
babel_ifp->bucket_time = babel_now.tv_sec;
babel_ifp->bucket = BUCKET_TOKENS_MAX;
- babel_ifp->hello_seqno = (frr_weak_random() & 0xFFFF);
+ babel_ifp->hello_seqno = CHECK_FLAG(frr_weak_random(), 0xFFFF);
babel_ifp->rtt_decay = BABEL_DEFAULT_RTT_DECAY;
babel_ifp->rtt_min = BABEL_DEFAULT_RTT_MIN;
babel_ifp->rtt_max = BABEL_DEFAULT_RTT_MAX;
diff --git a/babeld/babeld.c b/babeld/babeld.c
index 73deb1dd92..b562f0b70c 100644
--- a/babeld/babeld.c
+++ b/babeld/babeld.c
@@ -204,7 +204,7 @@ static void babel_read_protocol(struct event *thread)
making these inits have sense. */
static void babel_init_routing_process(struct event *thread)
{
- myseqno = (frr_weak_random() & 0xFFFF);
+ myseqno = CHECK_FLAG(frr_weak_random(), 0xFFFF);
babel_get_myid();
babel_load_state_file();
debugf(BABEL_DEBUG_COMMON, "My ID is : %s.", format_eui64(myid));
@@ -443,8 +443,8 @@ babel_fill_with_next_timeout(struct timeval *tv)
#if (defined NO_DEBUG)
#define printIfMin(a,b,c,d)
#else
-#define printIfMin(a, b, c, d) \
- if (unlikely(debug & BABEL_DEBUG_TIMEOUT)) { \
+#define printIfMin(a, b, c, d) \
+ if (unlikely(CHECK_FLAG(debug, BABEL_DEBUG_TIMEOUT))) { \
printIfMin(a, b, c, d); \
}
diff --git a/babeld/message.c b/babeld/message.c
index 1b83eb9ebb..5a33d5c288 100644
--- a/babeld/message.c
+++ b/babeld/message.c
@@ -324,8 +324,8 @@ parse_request_subtlv(int ae, const unsigned char *a, int alen,
have_src_prefix = 1;
} else {
debugf(BABEL_DEBUG_COMMON,"Received unknown%s Route Request sub-TLV %d.",
- ((type & 0x80) != 0) ? " mandatory" : "", type);
- if((type & 0x80) != 0)
+ (CHECK_FLAG(type, 0x80) != 0) ? " mandatory" : "", type);
+ if(CHECK_FLAG(type, 0x80) != 0)
return -1;
}
@@ -588,7 +588,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
else
rc = -1;
if(rc < 0) {
- if(message[3] & 0x80)
+ if(CHECK_FLAG(message[3], 0x80))
have_v4_prefix = have_v6_prefix = 0;
goto fail;
}
@@ -596,7 +596,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
plen = message[4] + (message[2] == 1 ? 96 : 0);
- if(message[3] & 0x80) {
+ if(CHECK_FLAG(message[3], 0x80)) {
if(message[2] == 1) {
memcpy(v4_prefix, prefix, 16);
have_v4_prefix = 1;
@@ -605,7 +605,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
have_v6_prefix = 1;
}
}
- if(message[3] & 0x40) {
+ if(CHECK_FLAG(message[3], 0x40)) {
if(message[2] == 1) {
memset(router_id, 0, 4);
memcpy(router_id + 4, prefix + 12, 4);
@@ -620,8 +620,8 @@ parse_packet(const unsigned char *from, struct interface *ifp,
goto fail;
}
debugf(BABEL_DEBUG_COMMON,"Received update%s%s for %s from %s on %s.",
- (message[3] & 0x80) ? "/prefix" : "",
- (message[3] & 0x40) ? "/id" : "",
+ ((CHECK_FLAG(message[3], 0x80)) ? "/prefix" : ""),
+ ((CHECK_FLAG(message[3], 0x40)) ? "/id" : ""),
format_prefix(prefix, plen),
format_address(from), ifp->name);
@@ -1059,7 +1059,7 @@ void send_hello_noupdate(struct interface *ifp, unsigned interval)
babel_ifp->hello_seqno, interval, ifp->name);
start_message(ifp, MESSAGE_HELLO,
- (babel_ifp->flags & BABEL_IF_TIMESTAMPS) ? 12 : 6);
+ (CHECK_FLAG(babel_ifp->flags, BABEL_IF_TIMESTAMPS) ? 12 : 6));
babel_ifp->buffered_hello = babel_ifp->buffered - 2;
accumulate_short(ifp, 0);
accumulate_short(ifp, babel_ifp->hello_seqno);
diff --git a/babeld/util.c b/babeld/util.c
index 4facdabbc6..f5edb0ed1f 100644
--- a/babeld/util.c
+++ b/babeld/util.c
@@ -211,8 +211,8 @@ mask_prefix(unsigned char *restrict ret,
memset(ret, 0, 16);
memcpy(ret, prefix, plen / 8);
if(plen % 8 != 0)
- ret[plen / 8] =
- (prefix[plen / 8] & ((0xFF << (8 - (plen % 8))) & 0xFF));
+ ret[plen / 8] = CHECK_FLAG(prefix[plen / 8],
+ CHECK_FLAG((0xFF << (8 - (plen % 8))), 0xFF));
return ret;
}
@@ -353,12 +353,13 @@ martian_prefix(const unsigned char *prefix, int plen)
{
return
(plen >= 8 && prefix[0] == 0xFF) ||
- (plen >= 10 && prefix[0] == 0xFE && (prefix[1] & 0xC0) == 0x80) ||
+ (plen >= 10 && prefix[0] == 0xFE &&
+ (CHECK_FLAG(prefix[1], 0xC0) == 0x80)) ||
(plen >= 128 && memcmp(prefix, zeroes, 15) == 0 &&
(prefix[15] == 0 || prefix[15] == 1)) ||
(plen >= 96 && v4mapped(prefix) &&
((plen >= 104 && (prefix[12] == 127 || prefix[12] == 0)) ||
- (plen >= 100 && (prefix[12] & 0xE0) == 0xE0)));
+ (plen >= 100 && CHECK_FLAG(prefix[12], 0xE0) == 0xE0)));
}
int
diff --git a/babeld/util.h b/babeld/util.h
index ddc6a70d43..2242032c4b 100644
--- a/babeld/util.h
+++ b/babeld/util.h
@@ -47,19 +47,19 @@ seqno_compare(unsigned short s1, unsigned short s2)
if(s1 == s2)
return 0;
else
- return ((s2 - s1) & 0x8000) ? 1 : -1;
+ return (CHECK_FLAG((s2 - s1), 0x8000)) ? 1 : -1;
}
static inline short
seqno_minus(unsigned short s1, unsigned short s2)
{
- return (short)((s1 - s2) & 0xFFFF);
+ return (short)(CHECK_FLAG((s1 - s2), 0xFFFF));
}
static inline unsigned short
seqno_plus(unsigned short s, int plus)
{
- return ((s + plus) & 0xFFFF);
+ return CHECK_FLAG((s + plus), 0xFFFF);
}
/* Returns a time in microseconds on 32 bits (thus modulo 2^32,
@@ -130,7 +130,7 @@ is_default(const unsigned char *prefix, int plen)
#define debugf(level, ...) \
do { \
- if (unlikely(debug & level)) \
+ if (unlikely(CHECK_FLAG(debug, level))) \
zlog_debug(__VA_ARGS__); \
} while (0)
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index d79ccf9644..7cdf98cba7 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -892,19 +892,16 @@ bool attrhash_cmp(const void *p1, const void *p2)
const struct attr *attr1 = p1;
const struct attr *attr2 = p2;
- if (attr1->flag == attr2->flag && attr1->origin == attr2->origin
- && attr1->nexthop.s_addr == attr2->nexthop.s_addr
- && attr1->aspath == attr2->aspath
- && bgp_attr_get_community(attr1)
- == bgp_attr_get_community(attr2)
- && attr1->med == attr2->med
- && attr1->local_pref == attr2->local_pref
- && attr1->rmap_change_flags == attr2->rmap_change_flags) {
+ if (attr1->flag == attr2->flag && attr1->origin == attr2->origin &&
+ attr1->nexthop.s_addr == attr2->nexthop.s_addr &&
+ attr1->aspath == attr2->aspath &&
+ bgp_attr_get_community(attr1) == bgp_attr_get_community(attr2) &&
+ attr1->med == attr2->med && attr1->local_pref == attr2->local_pref &&
+ attr1->rmap_change_flags == attr2->rmap_change_flags) {
if (attr1->aggregator_as == attr2->aggregator_as &&
attr1->aggregator_addr.s_addr ==
attr2->aggregator_addr.s_addr &&
- attr1->weight == attr2->weight &&
- attr1->tag == attr2->tag &&
+ attr1->weight == attr2->weight && attr1->tag == attr2->tag &&
attr1->label_index == attr2->label_index &&
attr1->mp_nexthop_len == attr2->mp_nexthop_len &&
bgp_attr_get_ecommunity(attr1) ==
@@ -913,10 +910,8 @@ bool attrhash_cmp(const void *p1, const void *p2)
bgp_attr_get_ipv6_ecommunity(attr2) &&
bgp_attr_get_lcommunity(attr1) ==
bgp_attr_get_lcommunity(attr2) &&
- bgp_attr_get_cluster(attr1) ==
- bgp_attr_get_cluster(attr2) &&
- bgp_attr_get_transit(attr1) ==
- bgp_attr_get_transit(attr2) &&
+ bgp_attr_get_cluster(attr1) == bgp_attr_get_cluster(attr2) &&
+ bgp_attr_get_transit(attr1) == bgp_attr_get_transit(attr2) &&
bgp_attr_get_aigp_metric(attr1) ==
bgp_attr_get_aigp_metric(attr2) &&
attr1->rmap_table_id == attr2->rmap_table_id &&
@@ -948,8 +943,7 @@ bool attrhash_cmp(const void *p1, const void *p2)
srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn) &&
attr1->srte_color == attr2->srte_color &&
attr1->nh_type == attr2->nh_type &&
- attr1->bh_type == attr2->bh_type &&
- attr1->otc == attr2->otc)
+ attr1->bh_type == attr2->bh_type && attr1->otc == attr2->otc)
return true;
}
@@ -1161,14 +1155,14 @@ struct attr *bgp_attr_default_set(struct attr *attr, struct bgp *bgp,
memset(attr, 0, sizeof(struct attr));
attr->origin = origin;
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN));
attr->aspath = aspath_empty(bgp->asnotation);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
attr->weight = BGP_ATTR_DEFAULT_WEIGHT;
attr->tag = 0;
attr->label_index = BGP_INVALID_LABEL_INDEX;
attr->label = MPLS_INVALID_LABEL;
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP));
attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
attr->local_pref = bgp->default_local_pref;
@@ -1190,18 +1184,18 @@ struct attr *bgp_attr_aggregate_intern(
/* Origin attribute. */
attr.origin = origin;
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN));
/* MED */
attr.med = 0;
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
/* AS path attribute. */
if (aspath)
attr.aspath = aspath_intern(aspath);
else
attr.aspath = aspath_empty(bgp->asnotation);
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
if (community) {
uint32_t gshut = COMMUNITY_GSHUT;
@@ -1231,8 +1225,8 @@ struct attr *bgp_attr_aggregate_intern(
attr.weight = BGP_ATTR_DEFAULT_WEIGHT;
attr.mp_nexthop_len = IPV6_MAX_BYTELEN;
if (!aggregate->as_set || atomic_aggregate)
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE));
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR));
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
attr.aggregator_as = bgp->confed_id;
else
@@ -1250,7 +1244,7 @@ struct attr *bgp_attr_aggregate_intern(
*/
if (p->family == AF_INET) {
/* Next hop attribute. */
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
+ SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP));
attr.mp_nexthop_len = IPV4_MAX_BYTELEN;
}
@@ -1567,8 +1561,8 @@ bgp_attr_flags_diagnose(struct bgp_attr_parser_args *args,
uint8_t real_flags = args->flags;
const uint8_t attr_code = args->type;
- desired_flags &= ~BGP_ATTR_FLAG_EXTLEN;
- real_flags &= ~BGP_ATTR_FLAG_EXTLEN;
+ UNSET_FLAG(desired_flags, BGP_ATTR_FLAG_EXTLEN);
+ UNSET_FLAG(real_flags, BGP_ATTR_FLAG_EXTLEN);
for (i = 0; i <= 2; i++) /* O,T,P, but not E */
if (CHECK_FLAG(desired_flags, attr_flag_str[i].key)
!= CHECK_FLAG(real_flags, attr_flag_str[i].key)) {
@@ -1682,7 +1676,7 @@ static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args)
&& CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS))
SET_FLAG(mask, BGP_ATTR_FLAG_PARTIAL);
- if ((flags & ~mask) == attr_flags_values[attr_code])
+ if (CHECK_FLAG(flags, ~mask) == attr_flags_values[attr_code])
return false;
bgp_attr_flags_diagnose(args, attr_flags_values[attr_code]);
@@ -1724,7 +1718,7 @@ bgp_attr_origin(struct bgp_attr_parser_args *args)
}
/* Set oring attribute flag. */
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGIN);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN));
return 0;
}
@@ -1774,7 +1768,7 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
}
/* Set aspath attribute flag. */
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH));
return BGP_ATTR_PARSE_PROCEED;
}
@@ -1878,7 +1872,7 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
}
/* Set aspath attribute flag. */
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH));
return BGP_ATTR_PARSE_PROCEED;
}
@@ -1928,7 +1922,7 @@ bgp_attr_nexthop(struct bgp_attr_parser_args *args)
}
attr->nexthop.s_addr = stream_get_ipv4(peer->curr);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP));
return BGP_ATTR_PARSE_PROCEED;
}
@@ -1951,7 +1945,7 @@ static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args)
attr->med = stream_getl(peer->curr);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
return BGP_ATTR_PARSE_PROCEED;
}
@@ -1989,7 +1983,7 @@ bgp_attr_local_pref(struct bgp_attr_parser_args *args)
STREAM_GETL(peer->curr, attr->local_pref);
/* Set the local-pref flag. */
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF));
return BGP_ATTR_PARSE_PROCEED;
@@ -2018,7 +2012,7 @@ static int bgp_attr_atomic(struct bgp_attr_parser_args *args)
goto atomic_ignore;
/* Set atomic aggregate flag. */
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE));
return BGP_ATTR_PARSE_PROCEED;
@@ -2076,7 +2070,7 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
zlog_debug("%s: attributes: %s", __func__, attr_str);
}
} else {
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR));
}
return BGP_ATTR_PARSE_PROCEED;
@@ -2127,7 +2121,7 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
zlog_debug("%s: attributes: %s", __func__, attr_str);
}
} else {
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR));
}
return BGP_ATTR_PARSE_PROCEED;
@@ -2166,12 +2160,13 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
* should not send them
*/
if (BGP_DEBUG(as4, AS4)) {
- if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))
+ if (CHECK_FLAG(attr->flag,
+ (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH))))
zlog_debug("[AS4] %s %s AS4_PATH", peer->host,
"AS4 capable peer, yet it sent");
- if (attr->flag
- & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))
+ if (CHECK_FLAG(attr->flag,
+ (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))))
zlog_debug("[AS4] %s %s AS4_AGGREGATOR",
peer->host,
"AS4 capable peer, yet it sent");
@@ -2183,8 +2178,9 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
/* We have a asn16 peer. First, look for AS4_AGGREGATOR
* because that may override AS4_PATH
*/
- if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))) {
- if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
+ if (CHECK_FLAG(attr->flag, (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR)))) {
+ if (CHECK_FLAG(attr->flag,
+ (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)))) {
/* received both.
* if the as_number in aggregator is not AS_TRANS,
* then AS4_AGGREGATOR and AS4_PATH shall be ignored
@@ -2224,13 +2220,14 @@ bgp_attr_munge_as4_attrs(struct peer *const peer, struct attr *const attr,
attr->aggregator_as = as4_aggregator;
/* sweep it under the carpet and simulate a "good"
* AGGREGATOR */
- attr->flag |= (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR));
+ SET_FLAG(attr->flag,
+ (ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)));
}
}
/* need to reconcile NEW_AS_PATH and AS_PATH */
- if (!ignore_as4_path
- && (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH)))) {
+ if (!ignore_as4_path &&
+ (CHECK_FLAG(attr->flag, (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH))))) {
newpath = aspath_reconcile_as4(attr->aspath, as4_path);
if (!newpath)
return BGP_ATTR_PARSE_ERROR;
@@ -2315,7 +2312,7 @@ bgp_attr_originator_id(struct bgp_attr_parser_args *args)
attr->originator_id.s_addr = stream_get_ipv4(peer->curr);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID));
return BGP_ATTR_PARSE_PROCEED;
@@ -2573,7 +2570,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
stream_forward_getp(s, nlri_len);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_REACH_NLRI));
return BGP_ATTR_PARSE_PROCEED;
#undef LEN_LEFT
@@ -2625,7 +2622,7 @@ int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
stream_forward_getp(s, withdraw_len);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MP_UNREACH_NLRI));
return BGP_ATTR_PARSE_PROCEED;
}
@@ -2685,10 +2682,9 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
args->total);
}
- ecomm = ecommunity_parse(
- stream_pnt(peer->curr), length,
- CHECK_FLAG(peer->flags,
- PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
+ ecomm = ecommunity_parse(stream_pnt(peer->curr), length,
+ CHECK_FLAG(peer->flags,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
bgp_attr_set_ecommunity(attr, ecomm);
/* XXX: fix ecommunity_parse to use stream API */
stream_forward_getp(peer->curr, length);
@@ -2719,7 +2715,7 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
/* Check EVPN Neighbor advertisement flags, R-bit */
bgp_attr_evpn_na_flag(attr, &proxy);
if (proxy)
- attr->es_flags |= ATTR_ES_PROXY_ADVERT;
+ SET_FLAG(attr->es_flags, ATTR_ES_PROXY_ADVERT);
/* Extract the Rmac, if any */
if (bgp_attr_rmac(attr, &attr->rmac)) {
@@ -3410,7 +3406,7 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
}
}
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL));
bgp_attr_set_pmsi_tnl_type(attr, tnl_type);
stream_get(&attr->label, peer->curr, BGP_LABEL_BYTES);
@@ -3493,7 +3489,7 @@ static enum bgp_attr_parse_ret bgp_attr_otc(struct bgp_attr_parser_args *args)
args->total);
}
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_OTC);
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_OTC));
return BGP_ATTR_PARSE_PROCEED;
@@ -3690,18 +3686,17 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
* unused. They MUST be zero when sent and MUST be ignored when
* received.
*/
- flag = 0xF0 & stream_getc(BGP_INPUT(peer));
+ flag = CHECK_FLAG(0xF0, stream_getc(BGP_INPUT(peer)));
type = stream_getc(BGP_INPUT(peer));
/* Check whether Extended-Length applies and is in bounds */
if (CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN)
&& ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) {
- flog_warn(
- EC_BGP_EXT_ATTRIBUTE_TOO_SMALL,
- "%s: Extended length set, but just %lu bytes of attr header",
- peer->host,
- (unsigned long)(endp
- - stream_pnt(BGP_INPUT(peer))));
+ flog_warn(EC_BGP_EXT_ATTRIBUTE_TOO_SMALL,
+ "%s: Extended length set, but just %lu bytes of attr header",
+ peer->host,
+ (unsigned long)(endp -
+ stream_pnt(BGP_INPUT(peer))));
if (peer->sort != BGP_PEER_EBGP) {
bgp_notify_send(peer->connection,
@@ -4048,7 +4043,7 @@ enum bgp_attr_parse_ret bgp_attr_parse(struct peer *peer, struct attr *attr,
* Finally do the checks on the aspath we did not do yet
* because we waited for a potentially synthesized aspath.
*/
- if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) {
+ if (CHECK_FLAG(attr->flag, (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))) {
ret = bgp_attr_aspath_check(peer, attr);
if (ret != BGP_ATTR_PARSE_PROCEED)
goto done;
@@ -4226,8 +4221,8 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
case SAFI_MULTICAST:
case SAFI_LABELED_UNICAST:
case SAFI_EVPN: {
- if (attr->mp_nexthop_len
- == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+ if (attr->mp_nexthop_len ==
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
stream_putc(s,
BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL);
stream_put(s, &attr->mp_nexthop_global,
@@ -4448,12 +4443,12 @@ static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer,
BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL
| BGP_ATTR_FLAG_EXTLEN);
stream_putc(s, attrtype);
- stream_putw(s, attrlenfield & 0xffff);
+ stream_putw(s, CHECK_FLAG(attrlenfield, 0xffff));
} else {
/* 1-octet length field */
stream_putc(s, BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL);
stream_putc(s, attrtype);
- stream_putc(s, attrlenfield & 0xff);
+ stream_putc(s, CHECK_FLAG(attrlenfield, 0xff));
}
if (attrtype == BGP_ATTR_ENCAP) {
@@ -4695,15 +4690,15 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
&& !peer_cap_enhe(peer, afi, safi)) {
afi_t nh_afi = BGP_NEXTHOP_AFI_FROM_NHLEN(attr->mp_nexthop_len);
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP))) {
stream_putc(s, BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_NEXT_HOP);
bpacket_attr_vec_arr_set_vec(vecarr, BGP_ATTR_VEC_NH, s,
attr);
stream_putc(s, 4);
stream_put_ipv4(s, attr->nexthop.s_addr);
- } else if (peer_cap_enhe(from, afi, safi)
- || (nh_afi == AFI_IP6)) {
+ } else if (peer_cap_enhe(from, afi, safi) ||
+ (nh_afi == AFI_IP6)) {
/*
* Likely this is the case when an IPv4 prefix was
* received with Extended Next-hop capability in this
@@ -4725,8 +4720,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* MED attribute. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)
- || bgp->maxmed_active) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) ||
+ bgp->maxmed_active) {
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
stream_putc(s, 4);
@@ -4744,14 +4739,14 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* Atomic aggregate. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))) {
stream_putc(s, BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
stream_putc(s, 0);
}
/* Aggregator. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
/* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_AGGREGATOR);
@@ -4782,8 +4777,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* Community attribute. */
- if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY)
- && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
+ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) &&
+ CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
struct community *comm = NULL;
comm = bgp_attr_get_community(attr);
@@ -4807,8 +4802,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
* Large Community attribute.
*/
if (CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_SEND_LARGE_COMMUNITY)
- && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
+ PEER_FLAG_SEND_LARGE_COMMUNITY) &&
+ CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
@@ -4838,7 +4833,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
stream_putc(s, BGP_ATTR_ORIGINATOR_ID);
stream_putc(s, 4);
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
+ if (CHECK_FLAG(attr->flag,
+ ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))
stream_put_in_addr(s, &attr->originator_id);
else
stream_put_in_addr(s, &from->remote_id);
@@ -4851,7 +4847,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
stream_putc(s, cluster->length + 4);
/* If this peer configuration's parent BGP has
* cluster_id. */
- if (bgp->config & BGP_CONFIG_CLUSTER_ID)
+ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID))
stream_put_in_addr(s, &bgp->cluster_id);
else
stream_put_in_addr(s, &bgp->router_id);
@@ -4860,7 +4856,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
stream_putc(s, 4);
/* If this peer configuration's parent BGP has
* cluster_id. */
- if (bgp->config & BGP_CONFIG_CLUSTER_ID)
+ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID))
stream_put_in_addr(s, &bgp->cluster_id);
else
stream_put_in_addr(s, &bgp->router_id);
@@ -5028,7 +5024,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* PMSI Tunnel */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL))) {
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_PMSI_TUNNEL);
stream_putc(s, 9); // Length
@@ -5041,7 +5037,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* OTC */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_OTC))) {
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_OTC);
stream_putc(s, 4);
@@ -5049,7 +5045,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* AIGP */
- if (bpi && attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP) &&
+ if (bpi && CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
(CHECK_FLAG(peer->flags, PEER_FLAG_AIGP) ||
peer->sub_sort == BGP_PEER_EBGP_OAD ||
peer->sort != BGP_PEER_EBGP)) {
@@ -5192,7 +5188,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* MED attribute. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))) {
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc(s, BGP_ATTR_MULTI_EXIT_DISC);
stream_putc(s, 4);
@@ -5200,7 +5196,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* Local preference. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) {
stream_putc(s, BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_LOCAL_PREF);
stream_putc(s, 4);
@@ -5208,14 +5204,14 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* Atomic aggregate. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))) {
stream_putc(s, BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_ATOMIC_AGGREGATE);
stream_putc(s, 0);
}
/* Aggregator. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR))) {
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_AGGREGATOR);
stream_putc(s, 8);
@@ -5224,7 +5220,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* Community attribute. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES))) {
struct community *comm = NULL;
comm = bgp_attr_get_community(attr);
@@ -5235,9 +5231,8 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
stream_putc(s, BGP_ATTR_COMMUNITIES);
stream_putw(s, comm->size * 4);
} else {
- stream_putc(s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS);
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_COMMUNITIES);
stream_putc(s, comm->size * 4);
}
@@ -5245,7 +5240,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* Large Community attribute. */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES))) {
if (lcom_length(bgp_attr_get_lcommunity(attr)) > 255) {
stream_putc(s,
BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS
@@ -5254,9 +5249,8 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
stream_putw(s,
lcom_length(bgp_attr_get_lcommunity(attr)));
} else {
- stream_putc(s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS);
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_LARGE_COMMUNITIES);
stream_putc(s,
lcom_length(bgp_attr_get_lcommunity(attr)));
@@ -5300,11 +5294,10 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* Prefix SID */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID))) {
if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
- stream_putc(s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS);
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_PREFIX_SID);
stream_putc(s, 10);
stream_putc(s, BGP_PREFIX_SID_LABEL_INDEX);
@@ -5316,7 +5309,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* OTC */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_OTC)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_OTC))) {
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS);
stream_putc(s, BGP_ATTR_OTC);
stream_putc(s, 4);
@@ -5324,7 +5317,7 @@ void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
}
/* AIGP */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_AIGP)) {
+ if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP))) {
/* At the moment only AIGP Metric TLV exists for AIGP
* attribute. If more comes in, do not forget to update
* attr_len variable to include new ones.
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index 153cbd6e50..ad154e638b 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -496,8 +496,8 @@ static char *community_str_get(struct community *com, int i)
break;
default:
str = XSTRDUP(MTYPE_COMMUNITY_STR, "65536:65535");
- as = (comval >> 16) & 0xFFFF;
- val = comval & 0xFFFF;
+ as = CHECK_FLAG((comval >> 16), 0xFFFF);
+ val = CHECK_FLAG(comval, 0xFFFF);
snprintf(str, strlen(str), "%u:%d", as, val);
break;
}
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index 8e4c430555..602c1437af 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -416,13 +416,12 @@ static void set_community_string(struct community *com, bool make_json,
}
break;
default:
- as = (comval >> 16) & 0xFFFF;
- val = comval & 0xFFFF;
+ as = CHECK_FLAG((comval >> 16), 0xFFFF);
+ val = CHECK_FLAG(comval, 0xFFFF);
char buf[32];
snprintf(buf, sizeof(buf), "%u:%d", as, val);
const char *com2alias =
- translate_alias ? bgp_community2alias(buf)
- : buf;
+ translate_alias ? bgp_community2alias(buf) : buf;
strlcat(str, com2alias, len);
if (make_json) {
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index 6228432bd2..97c3e5740f 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -2558,7 +2558,7 @@ static int bgp_debug_per_prefix(const struct prefix *p,
struct bgp_debug_filter *filter;
struct listnode *node, *nnode;
- if (term_bgp_debug_type & BGP_DEBUG_TYPE) {
+ if (CHECK_FLAG(term_bgp_debug_type, BGP_DEBUG_TYPE)) {
/* We are debugging all prefixes so return true */
if (!per_prefix_list || list_isempty(per_prefix_list))
return 1;
@@ -2591,7 +2591,7 @@ static bool bgp_debug_per_peer(char *host, const struct prefix *p,
struct bgp_debug_filter *filter;
struct listnode *node, *nnode;
- if (term_bgp_debug_type & BGP_DEBUG_TYPE) {
+ if (CHECK_FLAG(term_bgp_debug_type, BGP_DEBUG_TYPE)) {
/* We are debugging all peers so return true */
if (!per_peer_list || list_isempty(per_peer_list))
return true;
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 42ba54ab7b..74ad65f1ec 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -696,9 +696,8 @@ static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi)
attr = *pi->attr;
bgp_attr_add_llgr_community(&attr);
pi->attr = bgp_attr_intern(&attr);
- bgp_recalculate_afi_safi_bestpaths(
- peer->bgp, afi, safi);
-
+ bgp_process(peer->bgp, rm, pi, afi,
+ safi);
break;
}
}
@@ -724,9 +723,7 @@ static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi)
attr = *pi->attr;
bgp_attr_add_llgr_community(&attr);
pi->attr = bgp_attr_intern(&attr);
- bgp_recalculate_afi_safi_bestpaths(peer->bgp,
- afi, safi);
-
+ bgp_process(peer->bgp, dest, pi, afi, safi);
break;
}
}
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index ad774b2b00..432ead7936 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -474,6 +474,7 @@ void vpn_leak_zebra_vrf_sid_update(struct bgp *bgp, afi_t afi)
void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
{
int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
+ struct srv6_sid_ctx ctx = {};
if (bgp->vrf_id == VRF_UNKNOWN) {
if (debug)
@@ -492,6 +493,11 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
XFREE(MTYPE_BGP_SRV6_SID,
bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent);
bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent = NULL;
+
+ ctx.vrf_id = bgp->vrf_id;
+ ctx.behavior = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4
+ : ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
+ bgp_zebra_release_srv6_sid(&ctx);
}
/*
@@ -501,6 +507,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp)
{
int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
+ struct srv6_sid_ctx ctx = {};
if (bgp->vrf_id == VRF_UNKNOWN) {
if (debug)
@@ -519,6 +526,10 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp)
NULL);
XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent);
bgp->tovpn_zebra_vrf_sid_last_sent = NULL;
+
+ ctx.vrf_id = bgp->vrf_id;
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
+ bgp_zebra_release_srv6_sid(&ctx);
}
/*
@@ -595,8 +606,8 @@ int vpn_leak_label_callback(
return 0;
}
-static void sid_register(struct bgp *bgp, const struct in6_addr *sid,
- const char *locator_name)
+void sid_register(struct bgp *bgp, const struct in6_addr *sid,
+ const char *locator_name)
{
struct bgp_srv6_function *func;
func = XCALLOC(MTYPE_BGP_SRV6_FUNCTION,
@@ -635,108 +646,97 @@ static bool sid_exist(struct bgp *bgp, const struct in6_addr *sid)
return false;
}
-/*
- * This function generates a new SID based on bgp->srv6_locator_chunks and
- * index. The locator and generated SID are stored in arguments sid_locator
- * and sid, respectively.
+/**
+ * Return the SRv6 SID value obtained by composing the LOCATOR and FUNCTION.
*
- * if index != 0: try to allocate as index-mode
- * else: try to allocate as auto-mode
+ * @param sid_value SRv6 SID value returned
+ * @param locator Parent locator of the SRv6 SID
+ * @param sid_func Function part of the SID
+ * @return True if success, False otherwise
*/
-static uint32_t alloc_new_sid(struct bgp *bgp, uint32_t index,
- struct srv6_locator_chunk *sid_locator_chunk,
- struct in6_addr *sid)
+static bool srv6_sid_compose(struct in6_addr *sid_value,
+ struct srv6_locator *locator, uint32_t sid_func)
{
int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
- struct listnode *node;
- struct srv6_locator_chunk *chunk;
- bool alloced = false;
int label = 0;
uint8_t offset = 0;
uint8_t func_len = 0, shift_len = 0;
- uint32_t index_max = 0;
+ uint32_t sid_func_max = 0;
- if (!bgp || !sid_locator_chunk || !sid)
+ if (!locator || !sid_value)
return false;
- for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, chunk)) {
- if (chunk->function_bits_length >
- BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH) {
- if (debug)
- zlog_debug(
- "%s: invalid SRv6 Locator chunk (%pFX): Function Length must be less or equal to %d",
- __func__, &chunk->prefix,
- BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH);
- continue;
- }
+ if (locator->function_bits_length >
+ BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH) {
+ if (debug)
+ zlog_debug("%s: invalid SRv6 Locator (%pFX): Function Length must be less or equal to %d",
+ __func__, &locator->prefix,
+ BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH);
+ return false;
+ }
- index_max = (1 << chunk->function_bits_length) - 1;
+ /* Max value that can be encoded in the Function part of the SID */
+ sid_func_max = (1 << locator->function_bits_length) - 1;
- if (index > index_max) {
- if (debug)
- zlog_debug(
- "%s: skipped SRv6 Locator chunk (%pFX): Function Length is too short to support specified index (%u)",
- __func__, &chunk->prefix, index);
- continue;
- }
+ if (sid_func > sid_func_max) {
+ if (debug)
+ zlog_debug("%s: invalid SRv6 Locator (%pFX): Function Length is too short to support specified function (%u)",
+ __func__, &locator->prefix, sid_func);
+ return false;
+ }
- *sid = chunk->prefix.prefix;
- *sid_locator_chunk = *chunk;
- offset = chunk->block_bits_length + chunk->node_bits_length;
- func_len = chunk->function_bits_length;
- shift_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH - func_len;
+ /**
+ * Let's build the SID value.
+ * sid_value = LOC:FUNC::
+ */
- if (index != 0) {
- label = index << shift_len;
- if (label < MPLS_LABEL_UNRESERVED_MIN) {
- if (debug)
- zlog_debug(
- "%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use",
- __func__, &chunk->prefix,
- label);
- continue;
- }
+ /* First, we put the locator (LOC) in the most significant bits of sid_value */
+ *sid_value = locator->prefix.prefix;
- transpose_sid(sid, label, offset, func_len);
- if (sid_exist(bgp, sid))
- continue;
- alloced = true;
- break;
- }
+ /*
+ * Then, we compute the offset at which we have to place the function (FUNC).
+ * FUNC will be placed immediately after LOC, i.e. at block_bits_length + node_bits_length
+ */
+ offset = locator->block_bits_length + locator->node_bits_length;
- for (uint32_t i = 1; i < index_max; i++) {
- label = i << shift_len;
- if (label < MPLS_LABEL_UNRESERVED_MIN) {
- if (debug)
- zlog_debug(
- "%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use",
- __func__, &chunk->prefix,
- label);
- continue;
- }
- transpose_sid(sid, label, offset, func_len);
- if (sid_exist(bgp, sid))
- continue;
- alloced = true;
- break;
- }
+ /*
+ * The FUNC part of the SID is advertised in the label field of SRv6 Service TLV.
+ * (see SID Transposition Scheme, RFC 9252 section #4).
+ * Therefore, we need to encode the FUNC in the most significant bits of the
+ * 20-bit label.
+ */
+ func_len = locator->function_bits_length;
+ shift_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH - func_len;
+
+ label = sid_func << shift_len;
+ if (label < MPLS_LABEL_UNRESERVED_MIN) {
+ if (debug)
+ zlog_debug("%s: skipped to allocate SRv6 SID (%pFX): Label (%u) is too small to use",
+ __func__, &locator->prefix, label);
+ return false;
}
- if (!alloced)
- return 0;
+ if (sid_exist(bgp_get_default(), sid_value)) {
+ zlog_warn("%s: skipped to allocate SRv6 SID (%pFX): SID %pI6 already in use",
+ __func__, &locator->prefix, sid_value);
+ return false;
+ }
- sid_register(bgp, sid, bgp->srv6_locator_name);
- return label;
+ /* Finally, we put the FUNC in sid_value at the computed offset */
+ transpose_sid(sid_value, label, offset, func_len);
+
+ return true;
}
void ensure_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
afi_t afi)
{
int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
- struct srv6_locator_chunk *tovpn_sid_locator;
- struct in6_addr *tovpn_sid;
- uint32_t tovpn_sid_index = 0, tovpn_sid_transpose_label;
+ struct in6_addr tovpn_sid = {};
+ uint32_t tovpn_sid_index = 0;
bool tovpn_sid_auto = false;
+ struct srv6_sid_ctx ctx = {};
+ uint32_t sid_func;
if (debug)
zlog_debug("%s: try to allocate new SID for vrf %s: afi %s",
@@ -748,10 +748,17 @@ void ensure_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
/*
* skip when bgp vpn instance ins't allocated
- * or srv6 locator chunk isn't allocated
+ * or srv6 locator isn't allocated
*/
- if (!bgp_vpn || !bgp_vpn->srv6_locator_chunks)
+ if (!bgp_vpn || !bgp_vpn->srv6_locator)
+ return;
+
+ if (bgp_vrf->vrf_id == VRF_UNKNOWN) {
+ if (debug)
+ zlog_debug("%s: vrf %s: vrf_id not set, can't set zebra vrf SRv6 SID",
+ __func__, bgp_vrf->name_pretty);
return;
+ }
tovpn_sid_index = bgp_vrf->vpn_policy[afi].tovpn_sid_index;
tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
@@ -768,40 +775,34 @@ void ensure_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
return;
}
- tovpn_sid_locator = srv6_locator_chunk_alloc();
- tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
-
- tovpn_sid_transpose_label = alloc_new_sid(bgp_vpn, tovpn_sid_index,
- tovpn_sid_locator, tovpn_sid);
+ if (!tovpn_sid_auto) {
+ if (!srv6_sid_compose(&tovpn_sid, bgp_vpn->srv6_locator,
+ tovpn_sid_index)) {
+ zlog_err("%s: failed to compose sid for vrf %s: afi %s",
+ __func__, bgp_vrf->name_pretty, afi2str(afi));
+ return;
+ }
+ }
- if (tovpn_sid_transpose_label == 0) {
- if (debug)
- zlog_debug(
- "%s: not allocated new sid for vrf %s: afi %s",
- __func__, bgp_vrf->name_pretty, afi2str(afi));
- srv6_locator_chunk_free(&tovpn_sid_locator);
- XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid);
+ ctx.vrf_id = bgp_vrf->vrf_id;
+ ctx.behavior = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4
+ : ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
+ if (!bgp_zebra_request_srv6_sid(&ctx, &tovpn_sid,
+ bgp_vpn->srv6_locator_name, &sid_func)) {
+ zlog_err("%s: failed to request sid for vrf %s: afi %s",
+ __func__, bgp_vrf->name_pretty, afi2str(afi));
return;
}
-
- if (debug)
- zlog_debug("%s: new sid %pI6 allocated for vrf %s: afi %s",
- __func__, tovpn_sid, bgp_vrf->name_pretty,
- afi2str(afi));
-
- bgp_vrf->vpn_policy[afi].tovpn_sid = tovpn_sid;
- bgp_vrf->vpn_policy[afi].tovpn_sid_locator = tovpn_sid_locator;
- bgp_vrf->vpn_policy[afi].tovpn_sid_transpose_label =
- tovpn_sid_transpose_label;
}
void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
{
int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
- struct srv6_locator_chunk *tovpn_sid_locator;
- struct in6_addr *tovpn_sid;
- uint32_t tovpn_sid_index = 0, tovpn_sid_transpose_label;
+ struct in6_addr tovpn_sid = {};
+ uint32_t tovpn_sid_index = 0;
bool tovpn_sid_auto = false;
+ struct srv6_sid_ctx ctx = {};
+ uint32_t sid_func;
if (debug)
zlog_debug("%s: try to allocate new SID for vrf %s", __func__,
@@ -813,11 +814,18 @@ void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
/*
* skip when bgp vpn instance ins't allocated
- * or srv6 locator chunk isn't allocated
+ * or srv6 locator isn't allocated
*/
- if (!bgp_vpn || !bgp_vpn->srv6_locator_chunks)
+ if (!bgp_vpn || !bgp_vpn->srv6_locator)
return;
+ if (bgp_vrf->vrf_id == VRF_UNKNOWN) {
+ if (debug)
+ zlog_debug("%s: vrf %s: vrf_id not set, can't set zebra vrf SRv6 SID",
+ __func__, bgp_vrf->name_pretty);
+ return;
+ }
+
tovpn_sid_index = bgp_vrf->tovpn_sid_index;
tovpn_sid_auto = CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_TOVPN_SID_AUTO);
@@ -832,28 +840,23 @@ void ensure_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
return;
}
- tovpn_sid_locator = srv6_locator_chunk_alloc();
- tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
-
- tovpn_sid_transpose_label = alloc_new_sid(bgp_vpn, tovpn_sid_index,
- tovpn_sid_locator, tovpn_sid);
+ if (!tovpn_sid_auto) {
+ if (!srv6_sid_compose(&tovpn_sid, bgp_vpn->srv6_locator,
+ bgp_vrf->tovpn_sid_index)) {
+ zlog_err("%s: failed to compose new sid for vrf %s",
+ __func__, bgp_vrf->name_pretty);
+ return;
+ }
+ }
- if (tovpn_sid_transpose_label == 0) {
- if (debug)
- zlog_debug("%s: not allocated new sid for vrf %s",
- __func__, bgp_vrf->name_pretty);
- srv6_locator_chunk_free(&tovpn_sid_locator);
- XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid);
+ ctx.vrf_id = bgp_vrf->vrf_id;
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
+ if (!bgp_zebra_request_srv6_sid(&ctx, &tovpn_sid,
+ bgp_vpn->srv6_locator_name, &sid_func)) {
+ zlog_err("%s: failed to request new sid for vrf %s", __func__,
+ bgp_vrf->name_pretty);
return;
}
-
- if (debug)
- zlog_debug("%s: new sid %pI6 allocated for vrf %s", __func__,
- tovpn_sid, bgp_vrf->name_pretty);
-
- bgp_vrf->tovpn_sid = tovpn_sid;
- bgp_vrf->tovpn_sid_locator = tovpn_sid_locator;
- bgp_vrf->tovpn_sid_transpose_label = tovpn_sid_transpose_label;
}
void ensure_vrf_tovpn_sid(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi)
@@ -876,6 +879,7 @@ void delete_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
uint32_t tovpn_sid_index = 0;
bool tovpn_sid_auto = false;
+ struct srv6_sid_ctx ctx = {};
if (debug)
zlog_debug("%s: try to remove SID for vrf %s: afi %s", __func__,
@@ -889,9 +893,22 @@ void delete_vrf_tovpn_sid_per_af(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
if (tovpn_sid_index != 0 || tovpn_sid_auto)
return;
- srv6_locator_chunk_free(&bgp_vrf->vpn_policy[afi].tovpn_sid_locator);
+ if (bgp_vrf->vrf_id == VRF_UNKNOWN) {
+ if (debug)
+ zlog_debug("%s: vrf %s: vrf_id not set, can't set zebra vrf label",
+ __func__, bgp_vrf->name_pretty);
+ return;
+ }
+
+ srv6_locator_free(bgp_vrf->vpn_policy[afi].tovpn_sid_locator);
+ bgp_vrf->vpn_policy[afi].tovpn_sid_locator = NULL;
if (bgp_vrf->vpn_policy[afi].tovpn_sid) {
+ ctx.vrf_id = bgp_vrf->vrf_id;
+ ctx.behavior = afi == AFI_IP ? ZEBRA_SEG6_LOCAL_ACTION_END_DT4
+ : ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
+ bgp_zebra_release_srv6_sid(&ctx);
+
sid_unregister(bgp_vpn, bgp_vrf->vpn_policy[afi].tovpn_sid);
XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->vpn_policy[afi].tovpn_sid);
}
@@ -903,6 +920,7 @@ void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF);
uint32_t tovpn_sid_index = 0;
bool tovpn_sid_auto = false;
+ struct srv6_sid_ctx ctx = {};
if (debug)
zlog_debug("%s: try to remove SID for vrf %s", __func__,
@@ -916,9 +934,21 @@ void delete_vrf_tovpn_sid_per_vrf(struct bgp *bgp_vpn, struct bgp *bgp_vrf)
if (tovpn_sid_index != 0 || tovpn_sid_auto)
return;
- srv6_locator_chunk_free(&bgp_vrf->tovpn_sid_locator);
+ if (bgp_vrf->vrf_id == VRF_UNKNOWN) {
+ if (debug)
+ zlog_debug("%s: vrf %s: vrf_id not set, can't set zebra vrf label",
+ __func__, bgp_vrf->name_pretty);
+ return;
+ }
+
+ srv6_locator_free(bgp_vrf->tovpn_sid_locator);
+ bgp_vrf->tovpn_sid_locator = NULL;
if (bgp_vrf->tovpn_sid) {
+ ctx.vrf_id = bgp_vrf->vrf_id;
+ ctx.behavior = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
+ bgp_zebra_release_srv6_sid(&ctx);
+
sid_unregister(bgp_vpn, bgp_vrf->tovpn_sid);
XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
}
@@ -1763,8 +1793,9 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
/* Set SID for SRv6 VPN */
if (from_bgp->vpn_policy[afi].tovpn_sid_locator) {
- struct srv6_locator_chunk *locator =
+ struct srv6_locator *locator =
from_bgp->vpn_policy[afi].tovpn_sid_locator;
+
encode_label(
from_bgp->vpn_policy[afi].tovpn_sid_transpose_label,
&label);
@@ -1805,8 +1836,8 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
.tovpn_sid_locator->prefix.prefix,
sizeof(struct in6_addr));
} else if (from_bgp->tovpn_sid_locator) {
- struct srv6_locator_chunk *locator =
- from_bgp->tovpn_sid_locator;
+ struct srv6_locator *locator = from_bgp->tovpn_sid_locator;
+
encode_label(from_bgp->tovpn_sid_transpose_label, &label);
static_attr.srv6_l3vpn =
XCALLOC(MTYPE_BGP_SRV6_L3VPN,
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
index 92a9fba887..39fed66781 100644
--- a/bgpd/bgp_mplsvpn.h
+++ b/bgpd/bgp_mplsvpn.h
@@ -419,6 +419,8 @@ struct bgp_mplsvpn_nh_label_bind_cache *bgp_mplsvpn_nh_label_bind_find(
struct bgp_mplsvpn_nh_label_bind_cache_head *tree, struct prefix *p,
mpls_label_t orig_label);
void bgp_mplsvpn_nexthop_init(void);
+extern void sid_register(struct bgp *bgp, const struct in6_addr *sid,
+ const char *locator_name);
extern void sid_unregister(struct bgp *bgp, const struct in6_addr *sid);
#endif /* _QUAGGA_BGP_MPLSVPN_H */
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 430c8f17e8..0280960da8 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -66,6 +66,7 @@ struct bgp_nexthop_cache {
#define BGP_STATIC_ROUTE (1 << 4)
#define BGP_STATIC_ROUTE_EXACT_MATCH (1 << 5)
#define BGP_NEXTHOP_LABELED_VALID (1 << 6)
+#define BGP_NEXTHOP_ULTIMATE (1 << 7)
/*
* This flag is added for EVPN gateway IP nexthops.
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 0259da06dd..c89ccc9792 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -405,12 +405,11 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
peer);
} else {
if (BGP_DEBUG(nht, NHT))
- zlog_debug(
- "Found existing bnc %pFX(%d)(%s) flags 0x%x ifindex %d #paths %d peer %p",
- &bnc->prefix, bnc->ifindex_ipv6_ll,
- bnc->bgp->name_pretty, bnc->flags,
- bnc->ifindex_ipv6_ll, bnc->path_count,
- bnc->nht_info);
+ zlog_debug("Found existing bnc %pFX(%d)(%s) flags 0x%x ifindex %d #paths %d peer %p, resolved prefix %pFX",
+ &bnc->prefix, bnc->ifindex_ipv6_ll,
+ bnc->bgp->name_pretty, bnc->flags,
+ bnc->ifindex_ipv6_ll, bnc->path_count,
+ bnc->nht_info, &bnc->resolved_prefix);
}
if (pi && is_route_parent_evpn(pi))
@@ -485,6 +484,8 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
bnc->metric;
else if (bpi_ultimate->extra)
bpi_ultimate->extra->igpmetric = 0;
+
+ SET_FLAG(bnc->flags, BGP_NEXTHOP_ULTIMATE);
} else if (peer) {
/*
* Let's not accidentally save the peer data for a peer
@@ -505,6 +506,10 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
return 1;
else if (safi == SAFI_UNICAST && pi &&
pi->sub_type == BGP_ROUTE_IMPORTED &&
+ CHECK_FLAG(bnc->flags, BGP_NEXTHOP_ULTIMATE))
+ return bgp_isvalid_nexthop(bnc);
+ else if (safi == SAFI_UNICAST && pi &&
+ pi->sub_type == BGP_ROUTE_IMPORTED &&
BGP_PATH_INFO_NUM_LABELS(pi) && !bnc->is_evpn_gwip_nexthop)
return bgp_isvalid_nexthop_for_l3vpn(bnc, pi);
else if (safi == SAFI_MPLS_VPN && pi &&
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 8fcbcb5775..3c0f0c8b53 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -4634,7 +4634,22 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (aspath_get_last_as(attr->aspath) == bgp->as)
do_loop_check = 0;
- if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT))
+ /* When using bgp ipv4 labeled session, the local prefix is
+ * received by a peer, and finds out that the proposed prefix
+ * and its next-hop are the same. To avoid a route loop locally,
+ * no nexthop entry is referenced for that prefix, and the route
+ * will not be selected.
+ *
+ * As it has been done for ipv4-unicast, apply the following fix
+ * for labeled address families: when the received peer is
+ * a route reflector, the prefix has to be selected, even if the
+ * route can not be installed locally.
+ */
+ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT) ||
+ (safi == SAFI_UNICAST && !peer->afc[afi][safi] &&
+ peer->afc[afi][SAFI_LABELED_UNICAST] &&
+ CHECK_FLAG(peer->af_flags[afi][SAFI_LABELED_UNICAST],
+ PEER_FLAG_REFLECTOR_CLIENT)))
bgp_nht_param_prefix = NULL;
else
bgp_nht_param_prefix = p;
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index d0b65a7426..d37b171063 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -1992,10 +1992,9 @@ route_set_ip_nexthop(void *rule, const struct prefix *prefix, void *object)
SET_FLAG(path->attr->rmap_change_flags,
BATTR_RMAP_NEXTHOP_UNCHANGED);
} else if (rins->peer_address) {
- if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
- || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
- && peer->su_remote
- && sockunion_family(peer->su_remote) == AF_INET) {
+ if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)) &&
+ peer->su_remote &&
+ sockunion_family(peer->su_remote) == AF_INET) {
path->attr->nexthop.s_addr =
sockunion2ip(peer->su_remote);
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
@@ -3950,8 +3949,7 @@ route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
path = object;
peer = path->peer;
- if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
- || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
+ if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)) {
/* Set next hop preference to global */
SET_FLAG(path->attr->nh_flags, BGP_ATTR_NH_MP_PREFER_GLOBAL);
SET_FLAG(path->attr->rmap_change_flags,
@@ -4077,10 +4075,8 @@ route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
path = object;
peer = path->peer;
- if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
- || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
- && peer->su_remote
- && sockunion_family(peer->su_remote) == AF_INET6) {
+ if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)) &&
+ peer->su_remote && sockunion_family(peer->su_remote) == AF_INET6) {
peer_address = peer->su_remote->sin6.sin6_addr;
/* Set next hop value and length in attribute. */
if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
@@ -4095,7 +4091,6 @@ route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
path->attr->mp_nexthop_len =
BGP_ATTR_NHLEN_IPV6_GLOBAL;
}
-
} else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
/* The next hop value will be set as part of packet
* rewrite.
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index b717793a45..115bc35cdc 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -2016,6 +2016,8 @@ int update_group_adjust_soloness(struct peer *peer, int set)
struct peer_group *group;
struct listnode *node, *nnode;
+ peer_flag_set(peer, PEER_FLAG_LONESOUL);
+
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
peer_lonesoul_or_not(peer, set);
if (peer_established(peer->connection))
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index c9c7b80496..f669564bb8 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -302,18 +302,11 @@ static const char *get_afi_safi_json_str(afi_t afi, safi_t safi)
/* unset srv6 locator */
static int bgp_srv6_locator_unset(struct bgp *bgp)
{
- int ret;
struct listnode *node, *nnode;
struct srv6_locator_chunk *chunk;
struct bgp_srv6_function *func;
struct bgp *bgp_vrf;
- /* release chunk notification via ZAPI */
- ret = bgp_zebra_srv6_manager_release_locator_chunk(
- bgp->srv6_locator_name);
- if (ret < 0)
- return -1;
-
/* refresh chunks */
for (ALL_LIST_ELEMENTS(bgp->srv6_locator_chunks, node, nnode, chunk)) {
listnode_delete(bgp->srv6_locator_chunks, chunk);
@@ -352,20 +345,28 @@ static int bgp_srv6_locator_unset(struct bgp *bgp)
continue;
/* refresh vpnv4 tovpn_sid_locator */
- srv6_locator_chunk_free(
- &bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator);
+ srv6_locator_free(bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator);
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator = NULL;
/* refresh vpnv6 tovpn_sid_locator */
- srv6_locator_chunk_free(
- &bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator);
+ srv6_locator_free(
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator);
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator = NULL;
/* refresh per-vrf tovpn_sid_locator */
- srv6_locator_chunk_free(&bgp_vrf->tovpn_sid_locator);
+ srv6_locator_free(bgp_vrf->tovpn_sid_locator);
+ bgp_vrf->tovpn_sid_locator = NULL;
}
/* clear locator name */
memset(bgp->srv6_locator_name, 0, sizeof(bgp->srv6_locator_name));
+ /* clear SRv6 locator */
+ if (bgp->srv6_locator) {
+ srv6_locator_free(bgp->srv6_locator);
+ bgp->srv6_locator = NULL;
+ }
+
return 0;
}
@@ -10878,7 +10879,7 @@ DEFPY (bgp_srv6_locator,
snprintf(bgp->srv6_locator_name,
sizeof(bgp->srv6_locator_name), "%s", name);
- ret = bgp_zebra_srv6_manager_get_locator_chunk(name);
+ ret = bgp_zebra_srv6_manager_get_locator(name);
if (ret < 0)
return CMD_WARNING_CONFIG_FAILED;
@@ -10929,6 +10930,17 @@ DEFPY (show_bgp_srv6,
return CMD_SUCCESS;
vty_out(vty, "locator_name: %s\n", bgp->srv6_locator_name);
+ if (bgp->srv6_locator) {
+ vty_out(vty, " prefix: %pFX\n", &bgp->srv6_locator->prefix);
+ vty_out(vty, " block-length: %d\n",
+ bgp->srv6_locator->block_bits_length);
+ vty_out(vty, " node-length: %d\n",
+ bgp->srv6_locator->node_bits_length);
+ vty_out(vty, " func-length: %d\n",
+ bgp->srv6_locator->function_bits_length);
+ vty_out(vty, " arg-length: %d\n",
+ bgp->srv6_locator->argument_bits_length);
+ }
vty_out(vty, "locator_chunks:\n");
for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, chunk)) {
vty_out(vty, "- %pFX\n", &chunk->prefix);
@@ -17072,8 +17084,13 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group,
vty_out(vty, "\nBGP peer-group %s\n", group->name);
}
- if ((group->bgp->as == conf->as) ||
- CHECK_FLAG(conf->as_type, AS_INTERNAL)) {
+ if (CHECK_FLAG(conf->as_type, AS_AUTO)) {
+ if (json)
+ json_object_string_add(json_peer_group, "type", "auto");
+ else
+ vty_out(vty, " Peer-group type is auto\n");
+ } else if ((group->bgp->as == conf->as) ||
+ CHECK_FLAG(conf->as_type, AS_INTERNAL)) {
if (json)
json_object_string_add(json_peer_group, "type",
"internal");
@@ -18678,11 +18695,8 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
peer->password);
/* neighbor solo */
- if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) {
- if (!peer_group_active(peer)) {
- vty_out(vty, " neighbor %s solo\n", addr);
- }
- }
+ if (peergroup_flag_check(peer, PEER_FLAG_LONESOUL))
+ vty_out(vty, " neighbor %s solo\n", addr);
/* BGP port */
if (peer->port != BGP_PORT_DEFAULT) {
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 6e2efabf8f..19f26e9c75 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -3379,11 +3379,278 @@ static int bgp_zebra_process_srv6_locator_chunk(ZAPI_CALLBACK_ARGS)
return 0;
}
+/**
+ * Internal function to process an SRv6 locator
+ *
+ * @param locator The locator to be processed
+ */
+static int bgp_zebra_process_srv6_locator_internal(struct srv6_locator *locator)
+{
+ struct bgp *bgp = bgp_get_default();
+
+ if (!bgp || !bgp->srv6_enabled || !locator)
+ return -1;
+
+ /*
+ * Check if the main BGP instance is configured to use the received
+ * locator
+ */
+ if (strcmp(bgp->srv6_locator_name, locator->name) != 0) {
+ zlog_err("%s: SRv6 Locator name unmatch %s:%s", __func__,
+ bgp->srv6_locator_name, locator->name);
+ return 0;
+ }
+
+ zlog_info("%s: Received SRv6 locator %s %pFX, loc-block-len=%u, loc-node-len=%u func-len=%u, arg-len=%u",
+ __func__, locator->name, &locator->prefix,
+ locator->block_bits_length, locator->node_bits_length,
+ locator->function_bits_length, locator->argument_bits_length);
+
+ /* Store the locator in the main BGP instance */
+ bgp->srv6_locator = srv6_locator_alloc(locator->name);
+ srv6_locator_copy(bgp->srv6_locator, locator);
+
+ /*
+ * Process VPN-to-VRF and VRF-to-VPN leaks to advertise new locator
+ * and SIDs.
+ */
+ vpn_leak_postchange_all();
+
+ return 0;
+}
+
+static int bgp_zebra_srv6_sid_notify(ZAPI_CALLBACK_ARGS)
+{
+ struct bgp *bgp = bgp_get_default();
+ struct srv6_locator *locator;
+ struct srv6_sid_ctx ctx;
+ struct in6_addr sid_addr;
+ enum zapi_srv6_sid_notify note;
+ struct bgp *bgp_vrf;
+ struct vrf *vrf;
+ struct listnode *node, *nnode;
+ char buf[256];
+ struct in6_addr *tovpn_sid;
+ struct prefix_ipv6 tmp_prefix;
+ uint32_t sid_func;
+ bool found = false;
+
+ if (!bgp || !bgp->srv6_enabled)
+ return -1;
+
+ if (!bgp->srv6_locator) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: ignoring SRv6 SID notify: locator not set",
+ __func__);
+ return -1;
+ }
+
+ /* Decode the received notification message */
+ if (!zapi_srv6_sid_notify_decode(zclient->ibuf, &ctx, &sid_addr,
+ &sid_func, NULL, &note, NULL)) {
+ zlog_err("%s : error in msg decode", __func__);
+ return -1;
+ }
+
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: received SRv6 SID notify: ctx %s sid_value %pI6 %s",
+ __func__, srv6_sid_ctx2str(buf, sizeof(buf), &ctx),
+ &sid_addr, zapi_srv6_sid_notify2str(note));
+
+ /* Get the BGP instance for which the SID has been requested, if any */
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp_vrf)) {
+ vrf = vrf_lookup_by_id(bgp_vrf->vrf_id);
+ if (!vrf)
+ continue;
+
+ if (vrf->vrf_id == ctx.vrf_id) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: ignoring SRv6 SID notify: No VRF suitable for received SID ctx %s sid_value %pI6",
+ __func__,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx),
+ &sid_addr);
+ return -1;
+ }
+
+ /* Handle notification */
+ switch (note) {
+ case ZAPI_SRV6_SID_ALLOCATED:
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("SRv6 SID %pI6 %s : ALLOCATED", &sid_addr,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
+
+ /* Verify that the received SID belongs to the configured locator */
+ tmp_prefix.family = AF_INET6;
+ tmp_prefix.prefixlen = IPV6_MAX_BITLEN;
+ tmp_prefix.prefix = sid_addr;
+
+ if (!prefix_match((struct prefix *)&bgp->srv6_locator->prefix,
+ (struct prefix *)&tmp_prefix))
+ return -1;
+
+ /* Get label */
+ uint8_t func_len = bgp->srv6_locator->function_bits_length;
+ uint8_t shift_len = BGP_PREFIX_SID_SRV6_MAX_FUNCTION_LENGTH -
+ func_len;
+
+ int label = sid_func << shift_len;
+
+ /* Un-export VPN to VRF routes */
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp,
+ bgp_vrf);
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6, bgp,
+ bgp_vrf);
+
+ locator = srv6_locator_alloc(bgp->srv6_locator_name);
+ srv6_locator_copy(locator, bgp->srv6_locator);
+
+ /* Store SID, locator, and label */
+ tovpn_sid = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
+ *tovpn_sid = sid_addr;
+ if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT6) {
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
+ srv6_locator_free(
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator);
+ sid_unregister(bgp,
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
+
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid = tovpn_sid;
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator = locator;
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_transpose_label =
+ label;
+ } else if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT4) {
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
+ srv6_locator_free(
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator);
+ sid_unregister(bgp,
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
+
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid = tovpn_sid;
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator = locator;
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_transpose_label =
+ label;
+ } else if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT46) {
+ XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
+ srv6_locator_free(bgp_vrf->tovpn_sid_locator);
+ sid_unregister(bgp, bgp_vrf->tovpn_sid);
+
+ bgp_vrf->tovpn_sid = tovpn_sid;
+ bgp_vrf->tovpn_sid_locator = locator;
+ bgp_vrf->tovpn_sid_transpose_label = label;
+ } else {
+ srv6_locator_free(locator);
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Unsupported behavior. Not assigned SRv6 SID: %s %pI6",
+ srv6_sid_ctx2str(buf, sizeof(buf),
+ &ctx),
+ &sid_addr);
+ return -1;
+ }
+
+ /* Register the new SID */
+ sid_register(bgp, tovpn_sid, bgp->srv6_locator_name);
+
+ /* Export VPN to VRF routes */
+ vpn_leak_postchange_all();
+
+ break;
+ case ZAPI_SRV6_SID_RELEASED:
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("SRv6 SID %pI6 %s: RELEASED", &sid_addr,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
+
+ /* Un-export VPN to VRF routes */
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp,
+ bgp_vrf);
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6, bgp,
+ bgp_vrf);
+
+ /* Remove SID, locator, and label */
+ if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT6) {
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
+ if (bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator) {
+ srv6_locator_free(bgp->vpn_policy[AFI_IP6]
+ .tovpn_sid_locator);
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator =
+ NULL;
+ }
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_transpose_label =
+ 0;
+
+ /* Unregister the SID */
+ sid_unregister(bgp,
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid);
+ } else if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT4) {
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
+ if (bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator) {
+ srv6_locator_free(bgp->vpn_policy[AFI_IP]
+ .tovpn_sid_locator);
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator =
+ NULL;
+ }
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_transpose_label =
+ 0;
+
+ /* Unregister the SID */
+ sid_unregister(bgp,
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid);
+ } else if (ctx.behavior == ZEBRA_SEG6_LOCAL_ACTION_END_DT46) {
+ XFREE(MTYPE_BGP_SRV6_SID, bgp_vrf->tovpn_sid);
+ if (bgp_vrf->tovpn_sid_locator) {
+ srv6_locator_free(bgp_vrf->tovpn_sid_locator);
+ bgp_vrf->tovpn_sid_locator = NULL;
+ }
+ bgp_vrf->tovpn_sid_transpose_label = 0;
+
+ /* Unregister the SID */
+ sid_unregister(bgp, bgp_vrf->tovpn_sid);
+ } else {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Unsupported behavior. Not assigned SRv6 SID: %s %pI6",
+ srv6_sid_ctx2str(buf, sizeof(buf),
+ &ctx),
+ &sid_addr);
+ return -1;
+ }
+
+ /* Export VPN to VRF routes*/
+ vpn_leak_postchange_all();
+ break;
+ case ZAPI_SRV6_SID_FAIL_ALLOC:
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("SRv6 SID %pI6 %s: Failed to allocate",
+ &sid_addr,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
+
+ /* Error will be logged by zebra module */
+ break;
+ case ZAPI_SRV6_SID_FAIL_RELEASE:
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: SRv6 SID %pI6 %s failure to release",
+ __func__, &sid_addr,
+ srv6_sid_ctx2str(buf, sizeof(buf), &ctx));
+
+ /* Error will be logged by zebra module */
+ break;
+ }
+
+ return 0;
+}
+
static int bgp_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS)
{
struct srv6_locator loc = {};
struct bgp *bgp = bgp_get_default();
- const char *loc_name = bgp->srv6_locator_name;
if (!bgp || !bgp->srv6_enabled)
return 0;
@@ -3391,10 +3658,7 @@ static int bgp_zebra_process_srv6_locator_add(ZAPI_CALLBACK_ARGS)
if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0)
return -1;
- if (bgp_zebra_srv6_manager_get_locator_chunk(loc_name) < 0)
- return -1;
-
- return 0;
+ return bgp_zebra_process_srv6_locator_internal(&loc);
}
static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
@@ -3402,7 +3666,8 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
struct srv6_locator loc = {};
struct bgp *bgp = bgp_get_default();
struct listnode *node, *nnode;
- struct srv6_locator_chunk *chunk, *tovpn_sid_locator;
+ struct srv6_locator_chunk *chunk;
+ struct srv6_locator *tovpn_sid_locator;
struct bgp_srv6_function *func;
struct bgp *bgp_vrf;
struct in6_addr *tovpn_sid;
@@ -3414,6 +3679,12 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0)
return -1;
+ // clear SRv6 locator
+ if (bgp->srv6_locator) {
+ srv6_locator_free(bgp->srv6_locator);
+ bgp->srv6_locator = NULL;
+ }
+
// refresh chunks
for (ALL_LIST_ELEMENTS(bgp->srv6_locator_chunks, node, nnode, chunk))
if (prefix_match((struct prefix *)&loc.prefix,
@@ -3490,10 +3761,12 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
tmp_prefi.prefixlen = IPV6_MAX_BITLEN;
tmp_prefi.prefix = tovpn_sid_locator->prefix.prefix;
if (prefix_match((struct prefix *)&loc.prefix,
- (struct prefix *)&tmp_prefi))
- srv6_locator_chunk_free(
- &bgp_vrf->vpn_policy[AFI_IP]
- .tovpn_sid_locator);
+ (struct prefix *)&tmp_prefi)) {
+ srv6_locator_free(bgp_vrf->vpn_policy[AFI_IP]
+ .tovpn_sid_locator);
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator =
+ NULL;
+ }
}
/* refresh vpnv6 tovpn_sid_locator */
@@ -3504,10 +3777,12 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
tmp_prefi.prefixlen = IPV6_MAX_BITLEN;
tmp_prefi.prefix = tovpn_sid_locator->prefix.prefix;
if (prefix_match((struct prefix *)&loc.prefix,
- (struct prefix *)&tmp_prefi))
- srv6_locator_chunk_free(
- &bgp_vrf->vpn_policy[AFI_IP6]
- .tovpn_sid_locator);
+ (struct prefix *)&tmp_prefi)) {
+ srv6_locator_free(bgp_vrf->vpn_policy[AFI_IP6]
+ .tovpn_sid_locator);
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator =
+ NULL;
+ }
}
/* refresh per-vrf tovpn_sid_locator */
@@ -3517,9 +3792,10 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
tmp_prefi.prefixlen = IPV6_MAX_BITLEN;
tmp_prefi.prefix = tovpn_sid_locator->prefix.prefix;
if (prefix_match((struct prefix *)&loc.prefix,
- (struct prefix *)&tmp_prefi))
- srv6_locator_chunk_free(
- &bgp_vrf->tovpn_sid_locator);
+ (struct prefix *)&tmp_prefi)) {
+ srv6_locator_free(bgp_vrf->tovpn_sid_locator);
+ bgp_vrf->tovpn_sid_locator = NULL;
+ }
}
}
@@ -3556,6 +3832,7 @@ static zclient_handler *const bgp_handlers[] = {
[ZEBRA_SRV6_LOCATOR_DELETE] = bgp_zebra_process_srv6_locator_delete,
[ZEBRA_SRV6_MANAGER_GET_LOCATOR_CHUNK] =
bgp_zebra_process_srv6_locator_chunk,
+ [ZEBRA_SRV6_SID_NOTIFY] = bgp_zebra_srv6_sid_notify,
};
static int bgp_if_new_hook(struct interface *ifp)
@@ -3583,14 +3860,17 @@ void bgp_if_init(void)
hook_register_prio(if_del, 0, bgp_if_delete_hook);
}
-static void bgp_start_label_manager(struct event *start)
+static bool bgp_zebra_label_manager_ready(void)
{
- bgp_zebra_label_manager_connect();
+ return (zclient_sync->sock > 0);
}
-static bool bgp_zebra_label_manager_ready(void)
+static void bgp_start_label_manager(struct event *start)
{
- return (zclient_sync->sock > 0);
+ if (!bgp_zebra_label_manager_ready() &&
+ !bgp_zebra_label_manager_connect())
+ event_add_timer(bm->master, bgp_start_label_manager, NULL, 1,
+ &bm->t_bgp_start_label_manager);
}
static bool bgp_zebra_label_manager_connect(void)
@@ -4090,6 +4370,89 @@ int bgp_zebra_srv6_manager_release_locator_chunk(const char *name)
return srv6_manager_release_locator_chunk(zclient, name);
}
+/**
+ * Ask the SRv6 Manager (zebra) about a specific locator
+ *
+ * @param name Locator name
+ * @return 0 on success, -1 otherwise
+ */
+int bgp_zebra_srv6_manager_get_locator(const char *name)
+{
+ if (!name)
+ return -1;
+
+ /*
+ * Send the Get Locator request to the SRv6 Manager and return the
+ * result
+ */
+ return srv6_manager_get_locator(zclient, name);
+}
+
+/**
+ * Ask the SRv6 Manager (zebra) to allocate a SID.
+ *
+ * Optionally, it is possible to provide an IPv6 address (sid_value parameter).
+ *
+ * When sid_value is provided, the SRv6 Manager allocates the requested SID
+ * address, if the request can be satisfied (explicit allocation).
+ *
+ * When sid_value is not provided, the SRv6 Manager allocates any available SID
+ * from the provided locator (dynamic allocation).
+ *
+ * @param ctx Context to be associated with the request SID
+ * @param sid_value IPv6 address to be associated with the requested SID (optional)
+ * @param locator_name Name of the locator from which the SID must be allocated
+ * @param sid_func SID Function allocated by the SRv6 Manager.
+ */
+bool bgp_zebra_request_srv6_sid(const struct srv6_sid_ctx *ctx,
+ struct in6_addr *sid_value,
+ const char *locator_name, uint32_t *sid_func)
+{
+ int ret;
+
+ if (!ctx || !locator_name)
+ return false;
+
+ /*
+ * Send the Get SRv6 SID request to the SRv6 Manager and check the
+ * result
+ */
+ ret = srv6_manager_get_sid(zclient, ctx, sid_value, locator_name,
+ sid_func);
+ if (ret < 0) {
+ zlog_warn("%s: error getting SRv6 SID!", __func__);
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Ask the SRv6 Manager (zebra) to release a previously allocated SID.
+ *
+ * This function is used to tell the SRv6 Manager that BGP no longer intends
+ * to use the SID.
+ *
+ * @param ctx Context to be associated with the SID to be released
+ */
+void bgp_zebra_release_srv6_sid(const struct srv6_sid_ctx *ctx)
+{
+ int ret;
+
+ if (!ctx)
+ return;
+
+ /*
+ * Send the Release SRv6 SID request to the SRv6 Manager and check the
+ * result
+ */
+ ret = srv6_manager_release_sid(zclient, ctx);
+ if (ret < 0) {
+ zlog_warn("%s: error releasing SRv6 SID!", __func__);
+ return;
+ }
+}
+
void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
ifindex_t ifindex, vrf_id_t vrf_id,
enum lsp_types_t ltype, struct prefix *p,
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index 55a4185bde..8deecba747 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -117,6 +117,13 @@ extern int bgp_zebra_update(struct bgp *bgp, afi_t afi, safi_t safi,
extern int bgp_zebra_stale_timer_update(struct bgp *bgp);
extern int bgp_zebra_srv6_manager_get_locator_chunk(const char *name);
extern int bgp_zebra_srv6_manager_release_locator_chunk(const char *name);
+extern int bgp_zebra_srv6_manager_get_locator(const char *name);
+extern bool bgp_zebra_request_srv6_sid(const struct srv6_sid_ctx *ctx,
+ struct in6_addr *sid_value,
+ const char *locator_name,
+ uint32_t *sid_func);
+extern void bgp_zebra_release_srv6_sid(const struct srv6_sid_ctx *ctx);
+
extern void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
ifindex_t index, vrf_id_t vrfid,
enum lsp_types_t ltype,
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index a88de651f5..9d36ed9008 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -1497,9 +1497,11 @@ static void bgp_srv6_init(struct bgp *bgp)
static void bgp_srv6_cleanup(struct bgp *bgp)
{
for (afi_t afi = AFI_IP; afi < AFI_MAX; afi++) {
- if (bgp->vpn_policy[afi].tovpn_sid_locator != NULL)
- srv6_locator_chunk_free(
- &bgp->vpn_policy[afi].tovpn_sid_locator);
+ if (bgp->vpn_policy[afi].tovpn_sid_locator != NULL) {
+ srv6_locator_free(
+ bgp->vpn_policy[afi].tovpn_sid_locator);
+ bgp->vpn_policy[afi].tovpn_sid_locator = NULL;
+ }
if (bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent != NULL)
XFREE(MTYPE_BGP_SRV6_SID,
bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent);
@@ -1510,8 +1512,10 @@ static void bgp_srv6_cleanup(struct bgp *bgp)
}
}
- if (bgp->tovpn_sid_locator != NULL)
- srv6_locator_chunk_free(&bgp->tovpn_sid_locator);
+ if (bgp->tovpn_sid_locator != NULL) {
+ srv6_locator_free(bgp->tovpn_sid_locator);
+ bgp->tovpn_sid_locator = NULL;
+ }
if (bgp->tovpn_zebra_vrf_sid_last_sent != NULL)
XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent);
if (bgp->tovpn_sid != NULL) {
@@ -1523,6 +1527,9 @@ static void bgp_srv6_cleanup(struct bgp *bgp)
list_delete(&bgp->srv6_locator_chunks);
if (bgp->srv6_functions)
list_delete(&bgp->srv6_functions);
+
+ srv6_locator_free(bgp->srv6_locator);
+ bgp->srv6_locator = NULL;
}
/* Allocate new peer object, implicitely locked. */
@@ -4701,6 +4708,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_CAPABILITY_FQDN, 0, peer_change_none},
{PEER_FLAG_AS_LOOP_DETECTION, 0, peer_change_none},
{PEER_FLAG_EXTENDED_LINK_BANDWIDTH, 0, peer_change_none},
+ {PEER_FLAG_LONESOUL, 0, peer_change_reset_out},
{0, 0, 0}};
static const struct peer_flag_action peer_af_flag_action_list[] = {
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 7f1b82d9c7..def12ee642 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -270,7 +270,7 @@ struct vpn_policy {
*/
uint32_t tovpn_sid_index; /* unset => set to 0 */
struct in6_addr *tovpn_sid;
- struct srv6_locator_chunk *tovpn_sid_locator;
+ struct srv6_locator *tovpn_sid_locator;
uint32_t tovpn_sid_transpose_label;
struct in6_addr *tovpn_zebra_vrf_sid_last_sent;
};
@@ -836,11 +836,12 @@ struct bgp {
/* BGP VPN SRv6 backend */
bool srv6_enabled;
char srv6_locator_name[SRV6_LOCNAME_SIZE];
+ struct srv6_locator *srv6_locator;
struct list *srv6_locator_chunks;
struct list *srv6_functions;
uint32_t tovpn_sid_index; /* unset => set to 0 */
struct in6_addr *tovpn_sid;
- struct srv6_locator_chunk *tovpn_sid_locator;
+ struct srv6_locator *tovpn_sid_locator;
uint32_t tovpn_sid_transpose_label;
struct in6_addr *tovpn_zebra_vrf_sid_last_sent;
@@ -1827,16 +1828,13 @@ struct peer {
struct stream *last_reset_cause;
/* The kind of route-map Flags.*/
- uint16_t rmap_type;
+ uint8_t rmap_type;
#define PEER_RMAP_TYPE_IN (1U << 0) /* neighbor route-map in */
#define PEER_RMAP_TYPE_OUT (1U << 1) /* neighbor route-map out */
#define PEER_RMAP_TYPE_NETWORK (1U << 2) /* network route-map */
#define PEER_RMAP_TYPE_REDISTRIBUTE (1U << 3) /* redistribute route-map */
#define PEER_RMAP_TYPE_DEFAULT (1U << 4) /* default-originate route-map */
-#define PEER_RMAP_TYPE_NOSET (1U << 5) /* not allow to set commands */
-#define PEER_RMAP_TYPE_IMPORT (1U << 6) /* neighbor route-map import */
-#define PEER_RMAP_TYPE_EXPORT (1U << 7) /* neighbor route-map export */
-#define PEER_RMAP_TYPE_AGGREGATE (1U << 8) /* aggregate-address route-map */
+#define PEER_RMAP_TYPE_AGGREGATE (1U << 5) /* aggregate-address route-map */
/** Peer overwrite configuration. */
struct bfd_session_config {
diff --git a/doc/developer/topotests.rst b/doc/developer/topotests.rst
index 72de7b3bc9..4f9c94ca03 100644
--- a/doc/developer/topotests.rst
+++ b/doc/developer/topotests.rst
@@ -37,7 +37,7 @@ Installing Topotest Requirements
tshark \
valgrind
python3 -m pip install wheel
- python3 -m pip install 'pytest>=6.2.4' 'pytest-xdist>=2.3.0'
+ python3 -m pip install 'pytest>=8.3.2' 'pytest-asyncio>=0.24.0' 'pytest-xdist>=3.6.1'
python3 -m pip install 'scapy>=2.4.5'
python3 -m pip install xmltodict
python3 -m pip install git+https://github.com/Exa-Networks/exabgp@0659057837cd6c6351579e9f0fa47e9fb7de7311
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index aa62d274f0..b6d289fac9 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -2191,8 +2191,7 @@ and will share updates.
.. clicmd:: neighbor PEER solo
This command is used to indicate that routes advertised by the peer
- should not be reflected back to the peer. This command only is only
- meaningful when there is a single peer defined in the peer-group.
+ should not be reflected back to the peer.
.. clicmd:: show [ip] bgp peer-group [json]
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index b008eaf722..06a19a6139 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -815,6 +815,16 @@ Allocated label chunks table can be dumped using the command
range is configured, static label requests that match that
range are not accepted.
+FEC nexthop entry resolution over MPLS networks
+-----------------------------------------------
+
+The LSP associated with a BGP labeled route is normally restricted to
+directly-connected nexthops. If connected nexthops are not available,
+the LSP entry will not be installed. This command permits the use of
+recursive resolution for LSPs, similar to that available for IP routes.
+
+.. clicmd:: mpls fec nexthop-resolution
+
.. _zebra-srv6:
Segment-Routing IPv6
diff --git a/lib/nexthop.c b/lib/nexthop.c
index ac22e7ec84..98b05295b9 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -713,6 +713,15 @@ struct nexthop *nexthop_next(const struct nexthop *nexthop)
return NULL;
}
+struct nexthop *nexthop_next_resolution(const struct nexthop *nexthop,
+ bool nexthop_resolution)
+{
+ if (nexthop_resolution)
+ return nexthop_next(nexthop);
+ /* no resolution attempt */
+ return nexthop->next;
+}
+
/* Return the next nexthop in the tree that is resolved and active */
struct nexthop *nexthop_next_active_resolved(const struct nexthop *nexthop)
{
diff --git a/lib/nexthop.h b/lib/nexthop.h
index 15cfb26d82..02ea4d96f2 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -225,6 +225,8 @@ extern bool nexthop_labels_match(const struct nexthop *nh1,
extern const char *nexthop2str(const struct nexthop *nexthop,
char *str, int size);
extern struct nexthop *nexthop_next(const struct nexthop *nexthop);
+extern struct nexthop *nexthop_next_resolution(const struct nexthop *nexthop,
+ bool nexthop_resolution);
extern struct nexthop *
nexthop_next_active_resolved(const struct nexthop *nexthop);
extern unsigned int nexthop_level(const struct nexthop *nexthop);
diff --git a/lib/northbound_oper.c b/lib/northbound_oper.c
index 5f38c970c7..e95f99a2bd 100644
--- a/lib/northbound_oper.c
+++ b/lib/northbound_oper.c
@@ -751,8 +751,8 @@ static const struct lysc_node *nb_op_sib_next(struct nb_op_yield_state *ys,
/*
* If the node info stack is shorter than the schema path then we are
- * doign specific query still on the node from the schema path (should
- * match) so just return NULL (i.e., don't process siblings)
+ * working our way down the specific query path so just return NULL
+ * (i.e., don't process siblings)
*/
if (darr_len(ys->schema_path) > darr_len(ys->node_infos))
return NULL;
@@ -760,21 +760,21 @@ static const struct lysc_node *nb_op_sib_next(struct nb_op_yield_state *ys,
* If sib is on top of the node info stack then
* 1) it's a container node -or-
* 2) it's a list node that we were walking and we've reach the last entry
- * 3) if sib is a list and the list was empty we never would have
+ *
+ * If sib is a list and the list was empty we never would have
* pushed sib on the stack so the top of the stack is the parent
*
* If the query string included this node then we do not process any
* siblings as we are not walking all the parent's children just this
* specified one give by the query string.
*/
- if (sib == darr_last(ys->node_infos)->schema &&
- darr_len(ys->schema_path) >= darr_len(ys->node_infos))
- return NULL;
- /* case (3) */
- else if (sib->nodetype == LYS_LIST &&
- parent == darr_last(ys->node_infos)->schema &&
- darr_len(ys->schema_path) > darr_len(ys->node_infos))
- return NULL;
+ if (darr_len(ys->schema_path) == darr_len(ys->node_infos)) {
+ struct nb_op_node_info *node_infos = darr_last(ys->node_infos);
+
+ assert(node_infos);
+ if (sib == node_infos->schema)
+ return NULL;
+ }
sib = __sib_next(yn, sib->next);
if (sib)
@@ -801,6 +801,7 @@ static const struct lysc_node *nb_op_sib_first(struct nb_op_yield_state *ys,
{
const struct lysc_node *sib = lysc_node_child(parent);
const struct lysc_node *first_sib;
+ struct nb_op_node_info *last = darr_last(ys->node_infos);
/*
* NOTE: when we want to handle root level walks we will need to use
@@ -817,10 +818,9 @@ static const struct lysc_node *nb_op_sib_first(struct nb_op_yield_state *ys,
* base of the user query, return the next schema node from the query
* string (schema_path).
*/
- if (darr_last(ys->node_infos) != NULL &&
- !CHECK_FLAG(darr_last(ys->node_infos)->schema->nodetype,
- LYS_CASE | LYS_CHOICE))
- assert(darr_last(ys->node_infos)->schema == parent);
+ if (last != NULL &&
+ !CHECK_FLAG(last->schema->nodetype, LYS_CASE | LYS_CHOICE))
+ assert(last->schema == parent);
if (darr_lasti(ys->node_infos) < ys->query_base_level)
return ys->schema_path[darr_lasti(ys->node_infos) + 1];
@@ -908,9 +908,10 @@ static enum nb_error __walk(struct nb_op_yield_state *ys, bool is_resume)
* Otherwise get the first child of the container we are walking,
* starting with non-yielding children.
*/
- if (is_resume)
+ if (is_resume) {
+ assert(darr_last(ys->node_infos) != NULL);
sib = darr_last(ys->node_infos)->schema;
- else {
+ } else {
/*
* Start with non-yielding children first.
*
@@ -1477,7 +1478,8 @@ static void nb_op_walk_continue(struct event *thread)
goto finish;
/* otherwise we are at a resumable node */
- assert(darr_last(ys->node_infos)->has_lookup_next);
+ assert(darr_last(ys->node_infos) &&
+ darr_last(ys->node_infos)->has_lookup_next);
ret = __walk(ys, true);
if (ret == NB_YIELD) {
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index 2af4ae3170..40a76a0a34 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -1094,8 +1094,13 @@ void ospf_ls_retransmit_add(struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
if (ls_rxmt_node->lsa_list_entry ==
ospf_lsa_list_first(&nbr->ls_rxmt_list))
rxmt_head_replaced = true;
+
+ /* Keep SA happy */
+ assert(ls_rxmt_node->lsa_list_entry != NULL);
+
ospf_lsa_list_del(&nbr->ls_rxmt_list,
ls_rxmt_node->lsa_list_entry);
+
XFREE(MTYPE_OSPF_LSA_LIST, ls_rxmt_node->lsa_list_entry);
ospf_lsdb_delete(&nbr->ls_rxmt, old);
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
@@ -1163,8 +1168,13 @@ void ospf_ls_retransmit_delete(struct ospf_neighbor *nbr, struct ospf_lsa *lsa)
rxmt_timer_reset = false;
lsa->retransmit_counter--;
+
+ /* Keep SA happy */
+ assert(ls_rxmt_node->lsa_list_entry != NULL);
+
ospf_lsa_list_del(&nbr->ls_rxmt_list,
ls_rxmt_node->lsa_list_entry);
+
XFREE(MTYPE_OSPF_LSA_LIST, ls_rxmt_node->lsa_list_entry);
ospf_lsdb_delete(&nbr->ls_rxmt, lsa);
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py
index 60d959fd1e..5347604250 100755
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py
@@ -84,6 +84,9 @@ def test_check_scale_up():
CliOnFail = None
# For debugging, uncomment the next line
# CliOnFail = 'tgen.mininet_cli'
+ # Skip test on 32bit platforms (limited memory)
+ if sys.maxsize <= 2**32:
+ pytest.skip("skipped because of limited memory on 32bit platforms")
CheckFunc = "ltemplateVersionCheck('4.1', iproute2='4.9')"
# uncomment next line to start cli *before* script is run
# CheckFunc = 'ltemplateVersionCheck(\'4.1\', cli=True, iproute2=\'4.9\')'
@@ -94,6 +97,9 @@ def test_check_scale_down():
CliOnFail = None
# For debugging, uncomment the next line
# CliOnFail = 'tgen.mininet_cli'
+ # Skip test on 32bit platforms (limited memory)
+ if sys.maxsize <= 2**32:
+ pytest.skip("skipped because of limited memory on 32bit platforms")
CheckFunc = "ltemplateVersionCheck('4.1', iproute2='4.9')"
# uncomment next line to start cli *before* script is run
# CheckFunc = 'ltemplateVersionCheck(\'4.1\', cli=True, iproute2=\'4.9\')'
diff --git a/tests/topotests/bgp_peer_group_solo/__init__.py b/tests/topotests/bgp_peer_group_solo/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_peer_group_solo/__init__.py
diff --git a/tests/topotests/bgp_peer_group_solo/r1/frr.conf b/tests/topotests/bgp_peer_group_solo/r1/frr.conf
new file mode 100644
index 0000000000..53959aa134
--- /dev/null
+++ b/tests/topotests/bgp_peer_group_solo/r1/frr.conf
@@ -0,0 +1,21 @@
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
+int r1-eth1
+ ip address 192.168.14.1/24
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor pg peer-group
+ neighbor pg remote-as external
+ neighbor pg solo
+ neighbor pg timers 1 3
+ neighbor pg timers connect 1
+ neighbor 192.168.1.2 peer-group pg
+ neighbor 192.168.1.3 peer-group pg
+ address-family ipv4 unicast
+ network 10.0.0.1/32
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_peer_group_solo/r2/frr.conf b/tests/topotests/bgp_peer_group_solo/r2/frr.conf
new file mode 100644
index 0000000000..ba99827a47
--- /dev/null
+++ b/tests/topotests/bgp_peer_group_solo/r2/frr.conf
@@ -0,0 +1,10 @@
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
+!
diff --git a/tests/topotests/bgp_peer_group_solo/r3/frr.conf b/tests/topotests/bgp_peer_group_solo/r3/frr.conf
new file mode 100644
index 0000000000..ed06170bf2
--- /dev/null
+++ b/tests/topotests/bgp_peer_group_solo/r3/frr.conf
@@ -0,0 +1,10 @@
+!
+int r3-eth0
+ ip address 192.168.1.3/24
+!
+router bgp 65003
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
+!
diff --git a/tests/topotests/bgp_peer_group_solo/test_bgp_peer_group_solo.py b/tests/topotests/bgp_peer_group_solo/test_bgp_peer_group_solo.py
new file mode 100644
index 0000000000..cdbc1e02a7
--- /dev/null
+++ b/tests/topotests/bgp_peer_group_solo/test_bgp_peer_group_solo.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import re
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def setup_module(mod):
+ topodef = {"s1": ("r1", "r2", "r3")}
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_remote_as_auto():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
+ def _bgp_converge():
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast summary json"))
+ expected = {
+ "peers": {
+ "192.168.1.2": {
+ "remoteAs": 65002,
+ "state": "Established",
+ "peerState": "OK",
+ },
+ "192.168.1.3": {
+ "remoteAs": 65003,
+ "state": "Established",
+ "peerState": "OK",
+ },
+ },
+ "totalPeers": 2,
+ }
+
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_converge,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't converge initial state"
+
+ def _bgp_update_groups():
+ actual = []
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast update-groups json"))
+ expected = [
+ {"subGroup": [{"adjListCount": 1, "peers": ["192.168.1.2"]}]},
+ {"subGroup": [{"adjListCount": 1, "peers": ["192.168.1.3"]}]},
+ ]
+
+ # update-group's number can be random and it's not deterministic,
+ # so we need to normalize the data a bit before checking.
+ # We care here about the `peers` array only actually.
+ for updgrp in output["default"].keys():
+ actual.append(output["default"][updgrp])
+
+ return topotest.json_cmp(actual, expected)
+
+ test_func = functools.partial(
+ _bgp_update_groups,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't see separate update-groups"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vpn_import_nexthop_default_vrf/__init__.py b/tests/topotests/bgp_vpn_import_nexthop_default_vrf/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_vpn_import_nexthop_default_vrf/__init__.py
diff --git a/tests/topotests/bgp_vpn_import_nexthop_default_vrf/r1/frr.conf b/tests/topotests/bgp_vpn_import_nexthop_default_vrf/r1/frr.conf
new file mode 100644
index 0000000000..2a2288cf05
--- /dev/null
+++ b/tests/topotests/bgp_vpn_import_nexthop_default_vrf/r1/frr.conf
@@ -0,0 +1,29 @@
+!
+interface r1-eth0
+ ip address 192.168.179.4/24
+exit
+!
+router bgp 65001
+ bgp router-id 192.168.179.4
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 192.168.179.5 remote-as auto
+!
+ address-family ipv4 vpn
+ neighbor 192.168.179.5 activate
+ neighbor 192.168.179.5 next-hop-self
+ exit-address-family
+!
+router bgp 65001 vrf CUSTOMER-A
+ bgp router-id 192.168.0.1
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+!
+ address-family ipv4 unicast
+ label vpn export auto
+ rd vpn export 100:1
+ rt vpn both 100:1
+ export vpn
+ import vpn
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_vpn_import_nexthop_default_vrf/r2/frr.conf b/tests/topotests/bgp_vpn_import_nexthop_default_vrf/r2/frr.conf
new file mode 100644
index 0000000000..6fe07f5622
--- /dev/null
+++ b/tests/topotests/bgp_vpn_import_nexthop_default_vrf/r2/frr.conf
@@ -0,0 +1,34 @@
+!
+interface r2-eth0
+ ip address 192.168.179.5/24
+exit
+!
+interface r2-eth1
+ ip address 192.168.2.2/24
+exit
+!
+router bgp 65002
+ bgp router-id 192.168.179.5
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 192.168.179.4 remote-as auto
+!
+ address-family ipv4 vpn
+ neighbor 192.168.179.4 activate
+ neighbor 192.168.179.4 next-hop-self
+ exit-address-family
+!
+router bgp 65002 vrf CUSTOMER-A
+ bgp router-id 192.168.0.2
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+!
+ address-family ipv4 unicast
+ redistribute connected
+ label vpn export auto
+ rd vpn export 100:1
+ rt vpn both 100:1
+ export vpn
+ import vpn
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_vpn_import_nexthop_default_vrf/test_bgp_vpn_import_nexthop_default_vrf.py b/tests/topotests/bgp_vpn_import_nexthop_default_vrf/test_bgp_vpn_import_nexthop_default_vrf.py
new file mode 100644
index 0000000000..ccea88b211
--- /dev/null
+++ b/tests/topotests/bgp_vpn_import_nexthop_default_vrf/test_bgp_vpn_import_nexthop_default_vrf.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ tgen.add_router("r1")
+ tgen.add_router("r2")
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r1"])
+
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["r2"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ r1.run("ip link add CUSTOMER-A type vrf table 1001")
+ r1.run("ip link set up dev CUSTOMER-A")
+ r1.run("ip link set r1-eth1 master CUSTOMER-A")
+
+ r2.run("ip link add CUSTOMER-A type vrf table 1001")
+ r2.run("ip link set up dev CUSTOMER-A")
+ r2.run("ip link set r2-eth1 master CUSTOMER-A")
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_issue_12502():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
+ def _bgp_converge():
+ output = json.loads(r1.vtysh_cmd("show bgp vrf CUSTOMER-A ipv4 unicast json"))
+ expected = {
+ "routes": {
+ "192.168.2.0/24": [
+ {
+ "valid": True,
+ "pathFrom": "external",
+ "prefix": "192.168.2.0",
+ "prefixLen": 24,
+ "path": "65002",
+ "nhVrfName": "default",
+ "nexthops": [
+ {
+ "ip": "192.168.179.5",
+ "hostname": "r1",
+ "afi": "ipv4",
+ "used": True,
+ }
+ ],
+ }
+ ]
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Failed to see 192.168.2.0/24 with a valid next-hop"
+
+ def _vrf_route_imported_to_zebra():
+ output = json.loads(
+ r1.vtysh_cmd("show ip route vrf CUSTOMER-A 192.168.2.0/24 json")
+ )
+ expected = {
+ "192.168.2.0/24": [
+ {
+ "prefix": "192.168.2.0/24",
+ "protocol": "bgp",
+ "vrfName": "CUSTOMER-A",
+ "selected": True,
+ "installed": True,
+ "table": 1001,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "fib": True,
+ "ip": "192.168.179.5",
+ "afi": "ipv4",
+ "interfaceName": "r1-eth0",
+ "vrf": "default",
+ "active": True,
+ }
+ ],
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_vrf_route_imported_to_zebra)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert (
+ result is None
+ ), "Failed to see 192.168.2.0/24 to be imported into default VRF (Zebra)"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_init.json b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_init.json
index 2769c6eb3f..cb072e3c60 100644
--- a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_init.json
+++ b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_init.json
@@ -7,6 +7,9 @@
"routes": {
"10.204.0.0/24": [
{
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
"pathFrom": "external",
"prefix": "10.204.0.0",
"prefixLen": 24,
@@ -63,6 +66,9 @@
],
"10.201.0.0/24": [
{
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
"pathFrom": "external",
"prefix": "10.201.0.0",
"prefixLen": 24,
diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r1_vrf1.json b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r1_vrf1.json
index 488dc4aab9..43100aad2d 100644
--- a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r1_vrf1.json
+++ b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r1_vrf1.json
@@ -7,6 +7,9 @@
"routes": {
"10.204.0.0/24": [
{
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
"pathFrom": "external",
"prefix": "10.204.0.0",
"prefixLen": 24,
@@ -63,6 +66,9 @@
],
"10.201.0.0/24": [
{
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
"pathFrom": "external",
"prefix": "10.201.0.0",
"prefixLen": 24,
diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r2_vrf2.json b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r2_vrf2.json
index b751756fce..b11b16bca2 100644
--- a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r2_vrf2.json
+++ b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r2_vrf2.json
@@ -7,6 +7,9 @@
"routes": {
"10.204.0.0/24": [
{
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
"pathFrom": "external",
"prefix": "10.204.0.0",
"prefixLen": 24,
@@ -63,6 +66,9 @@
],
"10.201.0.0/24": [
{
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
"pathFrom": "external",
"prefix": "10.201.0.0",
"prefixLen": 24,
@@ -161,6 +167,9 @@
"routes": {
"10.202.0.0/24": [
{
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
"pathFrom": "external",
"prefix": "10.202.0.0",
"prefixLen": 24,
diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r2_vrf3.json b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r2_vrf3.json
index 49d4066e19..643aae401d 100644
--- a/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r2_vrf3.json
+++ b/tests/topotests/bgp_vpnv4_noretain/r1/ipv4_vrf_all_routes_plus_r2_vrf3.json
@@ -7,6 +7,9 @@
"routes": {
"10.204.0.0/24": [
{
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
"pathFrom": "external",
"prefix": "10.204.0.0",
"prefixLen": 24,
@@ -63,6 +66,9 @@
],
"10.201.0.0/24": [
{
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
"pathFrom": "external",
"prefix": "10.201.0.0",
"prefixLen": 24,
@@ -161,6 +167,9 @@
"routes": {
"10.203.0.0/24": [
{
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
"pathFrom": "external",
"prefix": "10.203.0.0",
"prefixLen": 24,
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index e856c23d36..540a627c65 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -1847,7 +1847,13 @@ def retry(retry_timeout, initial_wait=0, expected=True, diag_pct=0.75):
while True:
seconds_left = (retry_until - datetime.now()).total_seconds()
try:
- ret = func(*args, **kwargs)
+ try:
+ ret = func(*args, seconds_left=seconds_left, **kwargs)
+ except TypeError as error:
+ if "seconds_left" not in str(error):
+ raise
+ ret = func(*args, **kwargs)
+
logger.debug("Function returned %s", ret)
negative_result = ret is False or is_string(ret)
@@ -1868,7 +1874,7 @@ def retry(retry_timeout, initial_wait=0, expected=True, diag_pct=0.75):
return saved_failure
except Exception as error:
- logger.info("Function raised exception: %s", str(error))
+ logger.info('Function raised exception: "%s"', repr(error))
ret = error
if seconds_left < 0 and saved_failure:
diff --git a/tests/topotests/mgmt_oper/oper.py b/tests/topotests/mgmt_oper/oper.py
index 9fc504569d..f54e64ae18 100644
--- a/tests/topotests/mgmt_oper/oper.py
+++ b/tests/topotests/mgmt_oper/oper.py
@@ -63,7 +63,7 @@ def disable_debug(router):
@retry(retry_timeout=30, initial_wait=1)
-def _do_oper_test(tgen, qr):
+def _do_oper_test(tgen, qr, seconds_left=None):
r1 = tgen.gears["r1"].net
qcmd = (
@@ -80,6 +80,8 @@ def _do_oper_test(tgen, qr):
expected = open(qr[1], encoding="ascii").read()
output = r1.cmd_nostatus(qcmd.format(qr[0], qr[2] if len(qr) > 2 else ""))
+ diag = logging.debug if seconds_left else logging.warning
+
try:
ojson = json.loads(output)
except json.decoder.JSONDecodeError as error:
@@ -92,31 +94,31 @@ def _do_oper_test(tgen, qr):
logging.error(
"Error decoding json exp result: %s\noutput:\n%s", error, expected
)
- logging.warning("FILE: {}".format(qr[1]))
+ diag("FILE: {}".format(qr[1]))
raise
if dd_json_cmp:
cmpout = json_cmp(ojson, ejson, exact_match=True)
if cmpout:
- logging.warning(
+ diag(
"-------DIFF---------\n%s\n---------DIFF----------",
pprint.pformat(cmpout),
)
else:
cmpout = tt_json_cmp(ojson, ejson, exact=True)
if cmpout:
- logging.warning(
+ diag(
"-------EXPECT--------\n%s\n------END-EXPECT------",
json.dumps(ejson, indent=4),
)
- logging.warning(
+ diag(
"--------GOT----------\n%s\n-------END-GOT--------",
json.dumps(ojson, indent=4),
)
- logging.warning("----diff---\n{}".format(cmpout))
- logging.warning("Command: {}".format(qcmd.format(qr[0], qr[2] if len(qr) > 2 else "")))
- logging.warning("File: {}".format(qr[1]))
- assert cmpout is None
+ diag("----diff---\n{}".format(cmpout))
+ diag("Command: {}".format(qcmd.format(qr[0], qr[2] if len(qr) > 2 else "")))
+ diag("File: {}".format(qr[1]))
+ return cmpout
def do_oper_test(tgen, query_results):
diff --git a/tests/topotests/nhrp_redundancy/host/zebra.conf b/tests/topotests/nhrp_redundancy/host/frr.conf
index 8bb7da0ad6..8bb7da0ad6 100644
--- a/tests/topotests/nhrp_redundancy/host/zebra.conf
+++ b/tests/topotests/nhrp_redundancy/host/frr.conf
diff --git a/tests/topotests/nhrp_redundancy/nhc1/zebra.conf b/tests/topotests/nhrp_redundancy/nhc1/frr.conf
index 07d9175418..98e848bccf 100644
--- a/tests/topotests/nhrp_redundancy/nhc1/zebra.conf
+++ b/tests/topotests/nhrp_redundancy/nhc1/frr.conf
@@ -1,4 +1,5 @@
ip forwarding
+!debug nhrp all
interface nhc1-eth0
ip address 192.168.2.4/24
!
@@ -7,10 +8,18 @@ interface nhc1-gre0
ip address 172.16.1.4/32
no link-detect
ipv6 nd suppress-ra
+ ip nhrp holdtime 10
+ ip nhrp network-id 42
+ ip nhrp registration no-unique
+ ip nhrp nhs dynamic nbma 192.168.1.1
+ ip nhrp nhs dynamic nbma 192.168.1.2
+ ip nhrp nhs dynamic nbma 192.168.1.3
+ ip nhrp shortcut
+ tunnel source nhc1-eth0
!
interface nhc1-eth1
ip address 10.4.4.4/24
!
ip route 0.0.0.0/0 172.16.1.1 50
ip route 0.0.0.0/0 172.16.1.2 60
-ip route 0.0.0.0/0 172.16.1.3 70 \ No newline at end of file
+ip route 0.0.0.0/0 172.16.1.3 70
diff --git a/tests/topotests/nhrp_redundancy/nhc1/nhrpd.conf b/tests/topotests/nhrp_redundancy/nhc1/nhrpd.conf
deleted file mode 100644
index a0862f77ef..0000000000
--- a/tests/topotests/nhrp_redundancy/nhc1/nhrpd.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-!debug nhrp all
-interface nhc1-gre0
- ip nhrp holdtime 10
- ip nhrp network-id 42
- ip nhrp registration no-unique
- ip nhrp nhs dynamic nbma 192.168.1.1
- ip nhrp nhs dynamic nbma 192.168.1.2
- ip nhrp nhs dynamic nbma 192.168.1.3
- ip nhrp shortcut
- tunnel source nhc1-eth0
-exit
diff --git a/tests/topotests/nhrp_redundancy/nhc2/zebra.conf b/tests/topotests/nhrp_redundancy/nhc2/frr.conf
index 30ea6d4d1d..818dd48251 100644
--- a/tests/topotests/nhrp_redundancy/nhc2/zebra.conf
+++ b/tests/topotests/nhrp_redundancy/nhc2/frr.conf
@@ -1,4 +1,5 @@
ip forwarding
+!debug nhrp all
interface nhc2-eth0
ip address 192.168.2.5/24
!
@@ -7,6 +8,14 @@ interface nhc2-gre0
ip address 172.16.1.5/32
no link-detect
ipv6 nd suppress-ra
+ ip nhrp holdtime 10
+ ip nhrp network-id 42
+ ip nhrp nhs dynamic nbma 192.168.1.1
+ ip nhrp nhs dynamic nbma 192.168.1.2
+ ip nhrp nhs dynamic nbma 192.168.1.3
+ ip nhrp registration no-unique
+ ip nhrp shortcut
+ tunnel source nhc2-eth0
!
interface nhc2-eth1
ip address 10.5.5.5/24
diff --git a/tests/topotests/nhrp_redundancy/nhc2/nhrpd.conf b/tests/topotests/nhrp_redundancy/nhc2/nhrpd.conf
deleted file mode 100644
index 16a6d87c27..0000000000
--- a/tests/topotests/nhrp_redundancy/nhc2/nhrpd.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-!debug nhrp all
-interface nhc2-gre0
- ip nhrp holdtime 10
- ip nhrp network-id 42
- ip nhrp nhs dynamic nbma 192.168.1.1
- ip nhrp nhs dynamic nbma 192.168.1.2
- ip nhrp nhs dynamic nbma 192.168.1.3
- ip nhrp registration no-unique
- ip nhrp shortcut
- tunnel source nhc2-eth0
-exit
diff --git a/tests/topotests/nhrp_redundancy/nhs1/zebra.conf b/tests/topotests/nhrp_redundancy/nhs1/frr.conf
index 718e01b991..583d014348 100644
--- a/tests/topotests/nhrp_redundancy/nhs1/zebra.conf
+++ b/tests/topotests/nhrp_redundancy/nhs1/frr.conf
@@ -1,12 +1,19 @@
ip forwarding
+!debug nhrp all
interface nhs1-eth0
ip address 192.168.1.1/24
!
ip route 192.168.2.0/24 192.168.1.6
+nhrp nflog-group 1
interface nhs1-gre0
ip address 172.16.1.1/32
no link-detect
ipv6 nd suppress-ra
+ ip nhrp holdtime 10
+ ip nhrp network-id 42
+ ip nhrp registration no-unique
+ ip nhrp redirect
+ tunnel source nhs1-eth0
!
ip route 10.4.4.0/24 172.16.1.4
ip route 10.5.5.0/24 172.16.1.5
diff --git a/tests/topotests/nhrp_redundancy/nhs1/nhrpd.conf b/tests/topotests/nhrp_redundancy/nhs1/nhrpd.conf
deleted file mode 100644
index c0c8c28f94..0000000000
--- a/tests/topotests/nhrp_redundancy/nhs1/nhrpd.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-!debug nhrp all
-nhrp nflog-group 1
-interface nhs1-gre0
- ip nhrp holdtime 10
- ip nhrp network-id 42
- ip nhrp registration no-unique
- ip nhrp redirect
- tunnel source nhs1-eth0
-exit
diff --git a/tests/topotests/nhrp_redundancy/nhs2/zebra.conf b/tests/topotests/nhrp_redundancy/nhs2/frr.conf
index 6001bf21c0..a6e0a98e6b 100644
--- a/tests/topotests/nhrp_redundancy/nhs2/zebra.conf
+++ b/tests/topotests/nhrp_redundancy/nhs2/frr.conf
@@ -1,12 +1,19 @@
ip forwarding
+!debug nhrp all
interface nhs2-eth0
ip address 192.168.1.2/24
!
ip route 192.168.2.0/24 192.168.1.6
+nhrp nflog-group 1
interface nhs2-gre0
ip address 172.16.1.2/32
no link-detect
ipv6 nd suppress-ra
+ ip nhrp holdtime 10
+ ip nhrp network-id 42
+ ip nhrp registration no-unique
+ ip nhrp redirect
+ tunnel source nhs2-eth0
!
ip route 10.4.4.0/24 172.16.1.4
ip route 10.5.5.0/24 172.16.1.5
diff --git a/tests/topotests/nhrp_redundancy/nhs2/nhrpd.conf b/tests/topotests/nhrp_redundancy/nhs2/nhrpd.conf
deleted file mode 100644
index df86d2798e..0000000000
--- a/tests/topotests/nhrp_redundancy/nhs2/nhrpd.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-!debug nhrp all
-nhrp nflog-group 1
-interface nhs2-gre0
- ip nhrp holdtime 10
- ip nhrp network-id 42
- ip nhrp registration no-unique
- ip nhrp redirect
- tunnel source nhs2-eth0
-exit
diff --git a/tests/topotests/nhrp_redundancy/nhs3/zebra.conf b/tests/topotests/nhrp_redundancy/nhs3/frr.conf
index 7c15438817..e965baf327 100644
--- a/tests/topotests/nhrp_redundancy/nhs3/zebra.conf
+++ b/tests/topotests/nhrp_redundancy/nhs3/frr.conf
@@ -1,12 +1,19 @@
ip forwarding
+!debug nhrp all
interface nhs3-eth0
ip address 192.168.1.3/24
!
ip route 192.168.2.0/24 192.168.1.6
+nhrp nflog-group 1
interface nhs3-gre0
ip address 172.16.1.3/32
no link-detect
ipv6 nd suppress-ra
+ ip nhrp holdtime 10
+ ip nhrp network-id 42
+ ip nhrp registration no-unique
+ ip nhrp redirect
+ tunnel source nhs3-eth0
!
ip route 10.4.4.0/24 172.16.1.4
ip route 10.5.5.0/24 172.16.1.5 \ No newline at end of file
diff --git a/tests/topotests/nhrp_redundancy/nhs3/nhrpd.conf b/tests/topotests/nhrp_redundancy/nhs3/nhrpd.conf
deleted file mode 100644
index e7c3504f65..0000000000
--- a/tests/topotests/nhrp_redundancy/nhs3/nhrpd.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-!debug nhrp all
-nhrp nflog-group 1
-interface nhs3-gre0
- ip nhrp holdtime 10
- ip nhrp network-id 42
- ip nhrp registration no-unique
- ip nhrp redirect
- tunnel source nhs3-eth0
-exit
diff --git a/tests/topotests/nhrp_redundancy/router/zebra.conf b/tests/topotests/nhrp_redundancy/router/frr.conf
index c0eb19ca40..c0eb19ca40 100644
--- a/tests/topotests/nhrp_redundancy/router/zebra.conf
+++ b/tests/topotests/nhrp_redundancy/router/frr.conf
diff --git a/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py
index 06777aaa23..d4cf98596c 100644
--- a/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py
+++ b/tests/topotests/nhrp_redundancy/test_nhrp_redundancy.py
@@ -29,38 +29,38 @@ test_nhrp_redundancy.py: Test NHS redundancy for NHRP
"""
TOPOLOGY = """
-+------------+ +------------+ +------------+
-| | | | | |
-| | | | | |
-| NHS 1 | | NHS 2 | | NHS 3 |
-| | | | | |
-+-----+------+ +-----+------+ +-----+------+
- |.1 |.2 |.3
- | | |
- | | 192.168.1.0/24 |
-------+-------------------------------+------------------+-------------+------
- |
- |.6
- GRE P2MP between all NHS and NHC +-----+------+
- 172.16.1.x/32 | |
- | |
- | Router |
- | |
- +-----+------+
- |
- |
- ---------+----------------+-------------+------
- | 192.168.2.0/24 |
- | |
- | |.4 |.5
-+------------+ | +-------+----+ +------+-----+ |
-| | | | | | | |
-| | +--------+ | | | |
++------------+ +------------+ +------------+
+| | | | | |
+| | | | | |
+| NHS 1 | | NHS 2 | | NHS 3 |
+| | | | | |
++-----+------+ +-----+------+ +-----+------+
+ |.1 |.2 |.3
+ | | |
+ | | 192.168.1.0/24 |
+------+-------------------------------+------------------+-------------+------
+ |
+ |.6
+ GRE P2MP between all NHS and NHC +-----+------+
+ 172.16.1.x/32 | |
+ | |
+ | Router |
+ | |
+ +-----+------+
+ |
+ |
+ ---------+----------------+-------------+------
+ | 192.168.2.0/24 |
+ | |
+ | |.4 |.5
++------------+ | +-------+----+ +------+-----+ |
+| | | | | | | |
+| | +--------+ | | | |
| Host |.7 | | NHC 1 | | NHC 2 +-----+10.5.5.0/24
-| +---------+ | | | | |
-+------------+ | +------------+ +------------+ |
- | |
- 10.4.4.0/24
+| +---------+ | | | | |
++------------+ | +------------+ +------------+ |
+ | |
+ 10.4.4.0/24
"""
# Save the Current Working Directory to find configuration files.
@@ -148,8 +148,8 @@ def _populate_iface():
def _verify_iptables():
tgen = get_topogen()
# Verify iptables is installed. Required for shortcuts
- rc, _, _ = tgen.net["nhs1"].cmd_status("iptables")
- return False if rc == 127 else True
+ rc, _, _ = tgen.net["nhs1"].cmd_status("iptables -V")
+ return True if rc == 0 else False
def setup_module(mod):
@@ -167,14 +167,8 @@ def setup_module(mod):
_populate_iface()
for rname, router in router_list.items():
- router.load_config(
- TopoRouter.RD_ZEBRA,
- os.path.join(CWD, "{}/zebra.conf".format(rname)),
- )
- if rname in ("nhs1", "nhs2", "nhs3", "nhc1", "nhc2"):
- router.load_config(
- TopoRouter.RD_NHRP, os.path.join(CWD, "{}/nhrpd.conf".format(rname))
- )
+ logger.info("Loading router %s" % rname)
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
# Initialize all routers.
tgen.start_router()
diff --git a/tests/topotests/pytest.ini b/tests/topotests/pytest.ini
index 9f33917c6b..b234a84252 100644
--- a/tests/topotests/pytest.ini
+++ b/tests/topotests/pytest.ini
@@ -2,6 +2,7 @@
[pytest]
asyncio_mode = auto
+asyncio_default_fixture_loop_scope = module
# NEEDS_EXABGP_4_2_11_FRR
diff --git a/tests/topotests/srv6_sid_manager/ce1/bgpd.conf b/tests/topotests/srv6_sid_manager/ce1/bgpd.conf
new file mode 100644
index 0000000000..3459796629
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce1/bgpd.conf
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce1
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/srv6_sid_manager/ce1/ipv6_rib.json b/tests/topotests/srv6_sid_manager/ce1/ipv6_rib.json
new file mode 100644
index 0000000000..a35e2b1b3d
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce1/ipv6_rib.json
@@ -0,0 +1,58 @@
+{
+ "::/0": [
+ {
+ "prefix": "::/0",
+ "protocol": "static",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 1,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 73,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "2001:1::1",
+ "afi": "ipv6",
+ "interfaceName": "eth-rt1",
+ "active": true,
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "2001:1::/64": [
+ {
+ "prefix": "2001:1::/64",
+ "protocol": "connected",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth-rt1",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/ce1/zebra.conf b/tests/topotests/srv6_sid_manager/ce1/zebra.conf
new file mode 100644
index 0000000000..0dea0c5751
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce1/zebra.conf
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce1
+!
+interface eth-rt1
+ ipv6 address 2001:1::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:1::1
+!
+line vty
+!
diff --git a/tests/topotests/srv6_sid_manager/ce2/bgpd.conf b/tests/topotests/srv6_sid_manager/ce2/bgpd.conf
new file mode 100644
index 0000000000..8ed9978749
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce2/bgpd.conf
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce2
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/srv6_sid_manager/ce2/ipv6_rib.json b/tests/topotests/srv6_sid_manager/ce2/ipv6_rib.json
new file mode 100644
index 0000000000..b4594d1c57
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce2/ipv6_rib.json
@@ -0,0 +1,58 @@
+{
+ "::/0": [
+ {
+ "prefix": "::/0",
+ "protocol": "static",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 1,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 73,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "2001:2::1",
+ "afi": "ipv6",
+ "interfaceName": "eth-rt6",
+ "active": true,
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "2001:2::/64": [
+ {
+ "prefix": "2001:2::/64",
+ "protocol": "connected",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth-rt6",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/ce2/zebra.conf b/tests/topotests/srv6_sid_manager/ce2/zebra.conf
new file mode 100644
index 0000000000..c4755f8485
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce2/zebra.conf
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce2
+!
+interface eth-rt6
+ ipv6 address 2001:2::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:2::1
+!
+line vty
+!
diff --git a/tests/topotests/srv6_sid_manager/ce3/bgpd.conf b/tests/topotests/srv6_sid_manager/ce3/bgpd.conf
new file mode 100644
index 0000000000..a85d9701c7
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce3/bgpd.conf
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce3
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/srv6_sid_manager/ce3/ipv6_rib.json b/tests/topotests/srv6_sid_manager/ce3/ipv6_rib.json
new file mode 100644
index 0000000000..3a50cb0199
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce3/ipv6_rib.json
@@ -0,0 +1,58 @@
+{
+ "::/0": [
+ {
+ "prefix": "::/0",
+ "protocol": "static",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 1,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 73,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "2001:3::1",
+ "afi": "ipv6",
+ "interfaceName": "eth-rt1",
+ "active": true,
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "2001:3::/64": [
+ {
+ "prefix": "2001:3::/64",
+ "protocol": "connected",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth-rt1",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/ce3/zebra.conf b/tests/topotests/srv6_sid_manager/ce3/zebra.conf
new file mode 100644
index 0000000000..046bcb6af8
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce3/zebra.conf
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce3
+!
+interface eth-rt1
+ ipv6 address 2001:3::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:3::1
+!
+line vty
+!
diff --git a/tests/topotests/srv6_sid_manager/ce4/bgpd.conf b/tests/topotests/srv6_sid_manager/ce4/bgpd.conf
new file mode 100644
index 0000000000..93fb32fd1b
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce4/bgpd.conf
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce4
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/srv6_sid_manager/ce4/ipv6_rib.json b/tests/topotests/srv6_sid_manager/ce4/ipv6_rib.json
new file mode 100644
index 0000000000..f6484355ba
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce4/ipv6_rib.json
@@ -0,0 +1,58 @@
+{
+ "::/0": [
+ {
+ "prefix": "::/0",
+ "protocol": "static",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 1,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 73,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "2001:4::1",
+ "afi": "ipv6",
+ "interfaceName": "eth-rt6",
+ "active": true,
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "2001:4::/64": [
+ {
+ "prefix": "2001:4::/64",
+ "protocol": "connected",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth-rt6",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/ce4/zebra.conf b/tests/topotests/srv6_sid_manager/ce4/zebra.conf
new file mode 100644
index 0000000000..7913d6f397
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce4/zebra.conf
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce4
+!
+interface eth-rt6
+ ipv6 address 2001:4::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:4::1
+!
+line vty
+!
diff --git a/tests/topotests/srv6_sid_manager/ce5/bgpd.conf b/tests/topotests/srv6_sid_manager/ce5/bgpd.conf
new file mode 100644
index 0000000000..2ab6f2d2a7
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce5/bgpd.conf
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce5
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/srv6_sid_manager/ce5/ipv6_rib.json b/tests/topotests/srv6_sid_manager/ce5/ipv6_rib.json
new file mode 100644
index 0000000000..a88df73c5a
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce5/ipv6_rib.json
@@ -0,0 +1,58 @@
+{
+ "::/0": [
+ {
+ "prefix": "::/0",
+ "protocol": "static",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 1,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 73,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "2001:5::1",
+ "afi": "ipv6",
+ "interfaceName": "eth-rt1",
+ "active": true,
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "2001:5::/64": [
+ {
+ "prefix": "2001:5::/64",
+ "protocol": "connected",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth-rt1",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/ce5/zebra.conf b/tests/topotests/srv6_sid_manager/ce5/zebra.conf
new file mode 100644
index 0000000000..21414ffcbc
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce5/zebra.conf
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce5
+!
+interface eth-rt1
+ ipv6 address 2001:5::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:5::1
+!
+line vty
+!
diff --git a/tests/topotests/srv6_sid_manager/ce6/bgpd.conf b/tests/topotests/srv6_sid_manager/ce6/bgpd.conf
new file mode 100644
index 0000000000..e0b6540514
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce6/bgpd.conf
@@ -0,0 +1,8 @@
+frr defaults traditional
+!
+hostname ce6
+password zebra
+!
+log stdout notifications
+log commands
+log file bgpd.log
diff --git a/tests/topotests/srv6_sid_manager/ce6/ipv6_rib.json b/tests/topotests/srv6_sid_manager/ce6/ipv6_rib.json
new file mode 100644
index 0000000000..ab6dfc9e13
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce6/ipv6_rib.json
@@ -0,0 +1,58 @@
+{
+ "::/0": [
+ {
+ "prefix": "::/0",
+ "protocol": "static",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 1,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 73,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "2001:6::1",
+ "afi": "ipv6",
+ "interfaceName": "eth-rt6",
+ "active": true,
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "2001:6::/64": [
+ {
+ "prefix": "2001:6::/64",
+ "protocol": "connected",
+ "vrfId": 0,
+ "vrfName": "default",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 254,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth-rt6",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/ce6/zebra.conf b/tests/topotests/srv6_sid_manager/ce6/zebra.conf
new file mode 100644
index 0000000000..ebe8556092
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/ce6/zebra.conf
@@ -0,0 +1,14 @@
+log file zebra.log
+!
+hostname ce6
+!
+interface eth-rt6
+ ipv6 address 2001:6::2/64
+!
+ip forwarding
+ipv6 forwarding
+!
+ipv6 route ::/0 2001:6::1
+!
+line vty
+!
diff --git a/tests/topotests/srv6_sid_manager/dst/sharpd.conf b/tests/topotests/srv6_sid_manager/dst/sharpd.conf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/dst/sharpd.conf
diff --git a/tests/topotests/srv6_sid_manager/dst/zebra.conf b/tests/topotests/srv6_sid_manager/dst/zebra.conf
new file mode 100644
index 0000000000..80741856cb
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/dst/zebra.conf
@@ -0,0 +1,22 @@
+log file zebra.log
+!
+hostname dst
+!
+! debug zebra kernel
+! debug zebra packet
+! debug zebra mpls
+!
+interface lo
+ ip address 9.9.9.2/32
+ ipv6 address fc00:0:9::1/128
+!
+interface eth-rt6
+ ip address 10.0.10.2/24
+ ipv6 address 2001:db8:10::2/64
+!
+ip forwarding
+!
+ip route 2001:db8:1::1 2001:db8:10::1
+!
+line vty
+!
diff --git a/tests/topotests/srv6_sid_manager/rt1/bgpd.conf b/tests/topotests/srv6_sid_manager/rt1/bgpd.conf
new file mode 100644
index 0000000000..461e9023f0
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt1/bgpd.conf
@@ -0,0 +1,67 @@
+frr defaults traditional
+!
+bgp send-extra-data zebra
+!
+hostname rt1
+password zebra
+!
+log stdout notifications
+log monitor notifications
+log commands
+!
+!debug bgp neighbor-events
+!debug bgp zebra
+!debug bgp vnc verbose
+!debug bgp update-groups
+!debug bgp updates in
+!debug bgp updates out
+!debug bgp vpn label
+!debug bgp vpn leak-from-vrf
+!debug bgp vpn leak-to-vrf
+!debug bgp vpn rmap-event
+!
+router bgp 1
+ bgp router-id 1.1.1.1
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ neighbor fc00:0:6::1 remote-as 6
+ neighbor fc00:0:6::1 timers 3 10
+ neighbor fc00:0:6::1 timers connect 1
+ neighbor fc00:0:6::1 ttl-security hops 20
+ !
+ address-family ipv6 vpn
+ neighbor fc00:0:6::1 activate
+ exit-address-family
+ !
+ segment-routing srv6
+ locator loc1
+ !
+!
+router bgp 1 vrf vrf10
+ bgp router-id 1.1.1.1
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ !
+ address-family ipv6 unicast
+ sid vpn export 65024
+ rd vpn export 1:10
+ rt vpn both 99:99
+ import vpn
+ export vpn
+ redistribute connected
+ exit-address-family
+!
+router bgp 1 vrf vrf20
+ bgp router-id 1.1.1.1
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ !
+ address-family ipv6 unicast
+ sid vpn export 65025
+ rd vpn export 1:20
+ rt vpn both 88:88
+ import vpn
+ export vpn
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/srv6_sid_manager/rt1/isisd.conf b/tests/topotests/srv6_sid_manager/rt1/isisd.conf
new file mode 100644
index 0000000000..29e1a31171
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt1/isisd.conf
@@ -0,0 +1,35 @@
+password 1
+hostname rt1
+log file isisd.log
+!
+! debug isis events
+! debug isis route-events
+! debug isis spf-events
+! debug isis sr-events
+! debug isis lsp-gen
+!
+interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+interface eth-sw1
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+router isis 1
+ lsp-gen-interval 2
+ net 49.0000.0000.0000.0001.00
+ is-type level-1
+ topology ipv6-unicast
+ segment-routing srv6
+ locator loc1
+ node-msd
+ max-segs-left 3
+ max-end-pop 3
+ max-h-encaps 2
+ max-end-d 5
+ interface sr0
+!
diff --git a/tests/topotests/srv6_sid_manager/rt1/sharpd.conf b/tests/topotests/srv6_sid_manager/rt1/sharpd.conf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt1/sharpd.conf
diff --git a/tests/topotests/srv6_sid_manager/rt1/show_ip_route.ref b/tests/topotests/srv6_sid_manager/rt1/show_ip_route.ref
new file mode 100644
index 0000000000..590d75afbf
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt1/show_ip_route.ref
@@ -0,0 +1,276 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt1/show_ipv6_route.ref b/tests/topotests/srv6_sid_manager/rt1/show_ipv6_route.ref
new file mode 100644
index 0000000000..cdbec3f2c1
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt1/show_ipv6_route.ref
@@ -0,0 +1,314 @@
+{
+ "fc00:0:2::1\/128":[
+ {
+ "prefix":"fc00:0:2::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:3::1\/128":[
+ {
+ "prefix":"fc00:0:3::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:4::1\/128":[
+ {
+ "prefix":"fc00:0:4::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:5::1\/128":[
+ {
+ "prefix":"fc00:0:5::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:6::1\/128":[
+ {
+ "prefix":"fc00:0:6::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:2::\/48":[
+ {
+ "prefix":"fc00:0:2::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:3::\/48":[
+ {
+ "prefix":"fc00:0:3::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:4::\/48":[
+ {
+ "prefix":"fc00:0:4::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:5::\/48":[
+ {
+ "prefix":"fc00:0:5::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:6::\/48":[
+ {
+ "prefix":"fc00:0:6::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:1::\/48":[
+ {
+ "prefix":"fc00:0:1::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"sr0",
+ "active":true,
+ "seg6local":{
+ "action":"End"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:1:e000::\/64":[
+ {
+ "prefix":"fc00:0:1:e000::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:1:e001::\/64":[
+ {
+ "prefix":"fc00:0:1:e001::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:1:fe00::\/128":[
+ {
+ "prefix":"fc00:0:1:fe00::\/128",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"vrf10",
+ "active":true,
+ "seg6local":{
+ "action":"End.DT6"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:1:fe01::\/128":[
+ {
+ "prefix":"fc00:0:1:fe01::\/128",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"vrf20",
+ "active":true,
+ "seg6local":{
+ "action":"End.DT6"
+ }
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt1/show_srv6_locator_table.ref b/tests/topotests/srv6_sid_manager/rt1/show_srv6_locator_table.ref
new file mode 100644
index 0000000000..c4a5d7507b
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt1/show_srv6_locator_table.ref
@@ -0,0 +1,15 @@
+{
+ "locators":[
+ {
+ "name":"loc1",
+ "prefix":"fc00:0:1::/48",
+ "blockBitsLength":32,
+ "nodeBitsLength":16,
+ "functionBitsLength":16,
+ "argumentBitsLength":0,
+ "statusUp":true,
+ "chunks":[
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt1/show_yang_interface_isis_adjacencies.ref b/tests/topotests/srv6_sid_manager/rt1/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..9c5901b90f
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt1/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,32 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "eth-sw1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0003",
+ "hold-timer": 10,
+ "neighbor-priority": 64,
+ "state": "up"
+ },
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0002",
+ "hold-timer": 10,
+ "neighbor-priority": 64,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/srv6_sid_manager/rt1/vpnv6_rib.ref b/tests/topotests/srv6_sid_manager/rt1/vpnv6_rib.ref
new file mode 100644
index 0000000000..52bc589a7f
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt1/vpnv6_rib.ref
@@ -0,0 +1,169 @@
+{
+ "vrfId": 0,
+ "vrfName": "default",
+ "routerId": "1.1.1.1",
+ "defaultLocPrf": 100,
+ "localAS": 1,
+ "routes": {
+ "routeDistinguishers": {
+ "1:10": {
+ "2001:1::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:1::",
+ "prefixLen": 64,
+ "network": "2001:1::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf10",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "rt1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "2001:3::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:3::",
+ "prefixLen": 64,
+ "network": "2001:3::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf10",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "rt1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
+ "1:20": {
+ "2001:5::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:5::",
+ "prefixLen": 64,
+ "network": "2001:5::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf20",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "rt1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
+ "6:10": {
+ "2001:2::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:2::",
+ "prefixLen": 64,
+ "network": "2001:2::/64",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "fc00:0:6::1",
+ "path": "6",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "fc00:0:6::1",
+ "hostname": "rt6",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
+ "6:20": {
+ "2001:4::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:4::",
+ "prefixLen": 64,
+ "network": "2001:4::/64",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "fc00:0:6::1",
+ "path": "6",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "fc00:0:6::1",
+ "hostname": "rt6",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "2001:6::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:6::",
+ "prefixLen": 64,
+ "network": "2001:6::/64",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "fc00:0:6::1",
+ "path": "6",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "fc00:0:6::1",
+ "hostname": "rt6",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/tests/topotests/srv6_sid_manager/rt1/vrf10_rib.ref b/tests/topotests/srv6_sid_manager/rt1/vrf10_rib.ref
new file mode 100644
index 0000000000..2aae3497f4
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt1/vrf10_rib.ref
@@ -0,0 +1,86 @@
+{
+ "2001:1::/64": [
+ {
+ "prefix": "2001:1::/64",
+ "protocol": "connected",
+ "vrfName": "vrf10",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 10,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth-ce1",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "2001:2::/64": [
+ {
+ "prefix": "2001:2::/64",
+ "protocol": "bgp",
+ "vrfName": "vrf10",
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "installed": true,
+ "table": 10,
+ "internalStatus": 16,
+ "internalFlags": 9,
+ "internalNextHopNum": 3,
+ "internalNextHopActiveNum": 3,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "afi": "ipv6",
+ "interfaceName": "eth-sw1",
+ "vrf": "default",
+ "active": true,
+ "weight": 1,
+ "seg6": {
+ "segs": "fc00:0:6:fe00::"
+ }
+ }
+ ],
+ "asPath": "6"
+ }
+ ],
+ "2001:3::/64": [
+ {
+ "prefix": "2001:3::/64",
+ "protocol": "connected",
+ "vrfName": "vrf10",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 10,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth-ce3",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt1/vrf20_rib.ref b/tests/topotests/srv6_sid_manager/rt1/vrf20_rib.ref
new file mode 100644
index 0000000000..de9e450cf6
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt1/vrf20_rib.ref
@@ -0,0 +1,92 @@
+{
+ "2001:4::/64": [
+ {
+ "prefix": "2001:4::/64",
+ "protocol": "bgp",
+ "vrfName": "vrf20",
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "installed": true,
+ "table": 20,
+ "internalStatus": 16,
+ "internalFlags": 9,
+ "internalNextHopNum": 3,
+ "internalNextHopActiveNum": 3,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "afi": "ipv6",
+ "interfaceName": "eth-sw1",
+ "vrf": "default",
+ "active": true,
+ "weight": 1,
+ "seg6": {
+ "segs": "fc00:0:6:fe01::"
+ }
+ }
+ ],
+ "asPath": "6"
+ }
+ ],
+ "2001:5::/64": [
+ {
+ "prefix": "2001:5::/64",
+ "protocol": "connected",
+ "vrfName": "vrf20",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 20,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth-ce5",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "2001:6::/64": [
+ {
+ "prefix": "2001:6::/64",
+ "protocol": "bgp",
+ "vrfName": "vrf20",
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "installed": true,
+ "table": 20,
+ "internalStatus": 16,
+ "internalFlags": 9,
+ "internalNextHopNum": 3,
+ "internalNextHopActiveNum": 3,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "afi": "ipv6",
+ "interfaceName": "eth-sw1",
+ "vrf": "default",
+ "active": true,
+ "weight": 1,
+ "seg6": {
+ "segs": "fc00:0:6:fe01::"
+ }
+ }
+ ],
+ "asPath": "6"
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt1/zebra.conf b/tests/topotests/srv6_sid_manager/rt1/zebra.conf
new file mode 100644
index 0000000000..ef7fb78eed
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt1/zebra.conf
@@ -0,0 +1,37 @@
+log file zebra.log
+!
+hostname rt1
+!
+! debug zebra kernel
+! debug zebra packet
+!
+interface lo
+ ip address 1.1.1.1/32
+ ipv6 address fc00:0:1::1/128
+!
+interface eth-sw1
+ ip address 10.0.1.1/24
+ ipv6 address 2001:db8:1::1/64
+!
+interface eth-ce1 vrf vrf10
+ ipv6 address 2001:1::1/64
+!
+interface eth-ce3 vrf vrf10
+ ipv6 address 2001:3::1/64
+!
+interface eth-ce5 vrf vrf20
+ ipv6 address 2001:5::1/64
+!
+segment-routing
+ srv6
+ locators
+ locator loc1
+ prefix fc00:0:1::/48
+ format usid-f3216
+ !
+ !
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/srv6_sid_manager/rt2/isisd.conf b/tests/topotests/srv6_sid_manager/rt2/isisd.conf
new file mode 100644
index 0000000000..b095f04910
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt2/isisd.conf
@@ -0,0 +1,48 @@
+hostname rt2
+log file isisd.log
+!
+! debug isis events
+! debug isis route-events
+! debug isis spf-events
+! debug isis sr-events
+! debug isis lsp-gen
+!
+interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+interface eth-sw1
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+interface eth-rt4-1
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+interface eth-rt4-2
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+router isis 1
+ lsp-gen-interval 2
+ net 49.0000.0000.0000.0002.00
+ is-type level-1
+ topology ipv6-unicast
+ segment-routing srv6
+ locator loc1
+ node-msd
+ max-segs-left 3
+ max-end-pop 3
+ max-h-encaps 2
+ max-end-d 5
+ interface sr0
+!
diff --git a/tests/topotests/srv6_sid_manager/rt2/show_ip_route.ref b/tests/topotests/srv6_sid_manager/rt2/show_ip_route.ref
new file mode 100644
index 0000000000..1d4a9e9a25
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt2/show_ip_route.ref
@@ -0,0 +1,320 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1"
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2"
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt2/show_ipv6_route.ref b/tests/topotests/srv6_sid_manager/rt2/show_ipv6_route.ref
new file mode 100644
index 0000000000..fc0f1d3bcc
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt2/show_ipv6_route.ref
@@ -0,0 +1,346 @@
+{
+ "fc00:0:1::1\/128":[
+ {
+ "prefix":"fc00:0:1::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:3::1\/128":[
+ {
+ "prefix":"fc00:0:3::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:4::1\/128":[
+ {
+ "prefix":"fc00:0:4::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:5::1\/128":[
+ {
+ "prefix":"fc00:0:5::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:6::1\/128":[
+ {
+ "prefix":"fc00:0:6::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:1::\/48":[
+ {
+ "prefix":"fc00:0:1::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:3::\/48":[
+ {
+ "prefix":"fc00:0:3::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:4::\/48":[
+ {
+ "prefix":"fc00:0:4::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:5::\/48":[
+ {
+ "prefix":"fc00:0:5::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:6::\/48":[
+ {
+ "prefix":"fc00:0:6::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:2::\/48":[
+ {
+ "prefix":"fc00:0:2::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"sr0",
+ "active":true,
+ "seg6local":{
+ "action":"End"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:2:e000::\/64":[
+ {
+ "prefix":"fc00:0:2:e000::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:2:e001::\/64":[
+ {
+ "prefix":"fc00:0:2:e001::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:2:e002::\/64":[
+ {
+ "prefix":"fc00:0:2:e002::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:2:e003::\/64":[
+ {
+ "prefix":"fc00:0:2:e003::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt2/show_srv6_locator_table.ref b/tests/topotests/srv6_sid_manager/rt2/show_srv6_locator_table.ref
new file mode 100644
index 0000000000..f8a5d93f3c
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt2/show_srv6_locator_table.ref
@@ -0,0 +1,15 @@
+{
+ "locators":[
+ {
+ "name":"loc1",
+ "prefix":"fc00:0:2::/48",
+ "blockBitsLength":32,
+ "nodeBitsLength":16,
+ "functionBitsLength":16,
+ "argumentBitsLength":0,
+ "statusUp":true,
+ "chunks":[
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt2/show_yang_interface_isis_adjacencies.ref b/tests/topotests/srv6_sid_manager/rt2/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..5e46ddf728
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt2/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,70 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "eth-rt4-1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0004",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "eth-rt4-2",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0004",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "eth-sw1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0003",
+ "hold-timer": 10,
+ "neighbor-priority": 64,
+ "state": "up"
+ },
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0001",
+ "hold-timer": 10,
+ "neighbor-priority": 64,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/srv6_sid_manager/rt2/zebra.conf b/tests/topotests/srv6_sid_manager/rt2/zebra.conf
new file mode 100644
index 0000000000..32737dfcd6
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt2/zebra.conf
@@ -0,0 +1,34 @@
+log file zebra.log
+!
+hostname rt2
+!
+! debug zebra kernel
+! debug zebra packet
+!
+interface lo
+ ip address 2.2.2.2/32
+ ipv6 address fc00:0:2::1/128
+!
+interface eth-sw1
+ ip address 10.0.1.2/24
+ ipv6 address 2001:db8:1::2/64
+!
+interface eth-rt4-1
+ ip address 10.0.2.2/24
+!
+interface eth-rt4-2
+ ip address 10.0.3.2/24
+!
+segment-routing
+ srv6
+ locators
+ locator loc1
+ prefix fc00:0:2::/48
+ format usid-f3216
+ !
+ !
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/srv6_sid_manager/rt3/isisd.conf b/tests/topotests/srv6_sid_manager/rt3/isisd.conf
new file mode 100644
index 0000000000..e237db2f49
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt3/isisd.conf
@@ -0,0 +1,48 @@
+hostname rt3
+log file isisd.log
+!
+! debug isis events
+! debug isis route-events
+! debug isis spf-events
+! debug isis sr-events
+! debug isis lsp-gen
+!
+interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+interface eth-sw1
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+interface eth-rt5-1
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+interface eth-rt5-2
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+router isis 1
+ lsp-gen-interval 2
+ net 49.0000.0000.0000.0003.00
+ is-type level-1
+ topology ipv6-unicast
+ segment-routing srv6
+ locator loc1
+ node-msd
+ max-segs-left 3
+ max-end-pop 3
+ max-h-encaps 2
+ max-end-d 5
+ interface sr0
+!
diff --git a/tests/topotests/srv6_sid_manager/rt3/show_ip_route.ref b/tests/topotests/srv6_sid_manager/rt3/show_ip_route.ref
new file mode 100644
index 0000000000..6ce5760e4f
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt3/show_ip_route.ref
@@ -0,0 +1,320 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1"
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2"
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt3/show_ipv6_route.ref b/tests/topotests/srv6_sid_manager/rt3/show_ipv6_route.ref
new file mode 100644
index 0000000000..c590fcfdbc
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt3/show_ipv6_route.ref
@@ -0,0 +1,346 @@
+{
+ "fc00:0:1::1\/128":[
+ {
+ "prefix":"fc00:0:1::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:2::1\/128":[
+ {
+ "prefix":"fc00:0:2::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:4::1\/128":[
+ {
+ "prefix":"fc00:0:4::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:5::1\/128":[
+ {
+ "prefix":"fc00:0:5::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:6::1\/128":[
+ {
+ "prefix":"fc00:0:6::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:1::\/48":[
+ {
+ "prefix":"fc00:0:1::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:2::\/48":[
+ {
+ "prefix":"fc00:0:2::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:4::\/48":[
+ {
+ "prefix":"fc00:0:4::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:5::\/48":[
+ {
+ "prefix":"fc00:0:5::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:6::\/48":[
+ {
+ "prefix":"fc00:0:6::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:3::\/48":[
+ {
+ "prefix":"fc00:0:3::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"sr0",
+ "active":true,
+ "seg6local":{
+ "action":"End"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:3:e000::\/64":[
+ {
+ "prefix":"fc00:0:3:e000::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:3:e001::\/64":[
+ {
+ "prefix":"fc00:0:3:e001::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:3:e002::\/64":[
+ {
+ "prefix":"fc00:0:3:e002::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:3:e003::\/64":[
+ {
+ "prefix":"fc00:0:3:e003::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt3/show_srv6_locator_table.ref b/tests/topotests/srv6_sid_manager/rt3/show_srv6_locator_table.ref
new file mode 100644
index 0000000000..c62870587b
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt3/show_srv6_locator_table.ref
@@ -0,0 +1,15 @@
+{
+ "locators":[
+ {
+ "name":"loc1",
+ "prefix":"fc00:0:3::/48",
+ "blockBitsLength":32,
+ "nodeBitsLength":16,
+ "functionBitsLength":16,
+ "argumentBitsLength":0,
+ "statusUp":true,
+ "chunks":[
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt3/show_yang_interface_isis_adjacencies.ref b/tests/topotests/srv6_sid_manager/rt3/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..a284240d24
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt3/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,70 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "eth-rt5-1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0005",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "eth-rt5-2",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0005",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "eth-sw1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0001",
+ "hold-timer": 10,
+ "neighbor-priority": 64,
+ "state": "up"
+ },
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0002",
+ "hold-timer": 10,
+ "neighbor-priority": 64,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/srv6_sid_manager/rt3/zebra.conf b/tests/topotests/srv6_sid_manager/rt3/zebra.conf
new file mode 100644
index 0000000000..73cf6b08f4
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt3/zebra.conf
@@ -0,0 +1,33 @@
+log file zebra.log
+!
+hostname rt3
+!
+! debug zebra kernel
+! debug zebra packet
+!
+interface lo
+ ip address 3.3.3.3/32
+ ipv6 address fc00:0:3::1/128
+!
+interface eth-sw1
+ ip address 10.0.1.3/24
+!
+interface eth-rt5-1
+ ip address 10.0.4.3/24
+!
+interface eth-rt5-2
+ ip address 10.0.5.3/24
+!
+segment-routing
+ srv6
+ locators
+ locator loc1
+ prefix fc00:0:3::/48
+ format usid-f3216
+ !
+ !
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/srv6_sid_manager/rt4/isisd.conf b/tests/topotests/srv6_sid_manager/rt4/isisd.conf
new file mode 100644
index 0000000000..b4c92146a1
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt4/isisd.conf
@@ -0,0 +1,56 @@
+hostname rt4
+log file isisd.log
+!
+! debug isis events
+! debug isis route-events
+! debug isis spf-events
+! debug isis sr-events
+! debug isis lsp-gen
+!
+interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+interface eth-rt2-1
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+interface eth-rt2-2
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+interface eth-rt5
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+interface eth-rt6
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+router isis 1
+ lsp-gen-interval 2
+ net 49.0000.0000.0000.0004.00
+ is-type level-1
+ topology ipv6-unicast
+ segment-routing srv6
+ locator loc1
+ node-msd
+ max-segs-left 3
+ max-end-pop 3
+ max-h-encaps 2
+ max-end-d 5
+ interface sr0
+!
diff --git a/tests/topotests/srv6_sid_manager/rt4/show_ip_route.ref b/tests/topotests/srv6_sid_manager/rt4/show_ip_route.ref
new file mode 100644
index 0000000000..0f26fa5d7a
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt4/show_ip_route.ref
@@ -0,0 +1,296 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1"
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2"
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5"
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6"
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt4/show_ipv6_route.ref b/tests/topotests/srv6_sid_manager/rt4/show_ipv6_route.ref
new file mode 100644
index 0000000000..7b575f1888
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt4/show_ipv6_route.ref
@@ -0,0 +1,346 @@
+{
+ "fc00:0:1::1\/128":[
+ {
+ "prefix":"fc00:0:1::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:2::1\/128":[
+ {
+ "prefix":"fc00:0:2::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:3::1\/128":[
+ {
+ "prefix":"fc00:0:3::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:5::1\/128":[
+ {
+ "prefix":"fc00:0:5::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:6::1\/128":[
+ {
+ "prefix":"fc00:0:6::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:1::\/48":[
+ {
+ "prefix":"fc00:0:1::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:2::\/48":[
+ {
+ "prefix":"fc00:0:2::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:3::\/48":[
+ {
+ "prefix":"fc00:0:3::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:5::\/48":[
+ {
+ "prefix":"fc00:0:5::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:6::\/48":[
+ {
+ "prefix":"fc00:0:6::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:4::\/48":[
+ {
+ "prefix":"fc00:0:4::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"sr0",
+ "active":true,
+ "seg6local":{
+ "action":"End"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:4:e000::\/64":[
+ {
+ "prefix":"fc00:0:4:e000::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:4:e001::\/64":[
+ {
+ "prefix":"fc00:0:4:e001::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:4:e002::\/64":[
+ {
+ "prefix":"fc00:0:4:e002::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:4:e003::\/64":[
+ {
+ "prefix":"fc00:0:4:e003::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/tests/topotests/srv6_sid_manager/rt4/show_srv6_locator_table.ref b/tests/topotests/srv6_sid_manager/rt4/show_srv6_locator_table.ref
new file mode 100644
index 0000000000..cb052dbbb5
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt4/show_srv6_locator_table.ref
@@ -0,0 +1,15 @@
+{
+ "locators":[
+ {
+ "name":"loc1",
+ "prefix":"fc00:0:4::/48",
+ "blockBitsLength":32,
+ "nodeBitsLength":16,
+ "functionBitsLength":16,
+ "argumentBitsLength":0,
+ "statusUp":true,
+ "chunks":[
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt4/show_yang_interface_isis_adjacencies.ref b/tests/topotests/srv6_sid_manager/rt4/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..0ca7a76bd4
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt4/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,82 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "eth-rt2-1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0002",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "eth-rt2-2",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0002",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "eth-rt5",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0005",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "eth-rt6",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0006",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/srv6_sid_manager/rt4/zebra.conf b/tests/topotests/srv6_sid_manager/rt4/zebra.conf
new file mode 100644
index 0000000000..266db7c53a
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt4/zebra.conf
@@ -0,0 +1,36 @@
+log file zebra.log
+!
+hostname rt4
+!
+! debug zebra kernel
+! debug zebra packet
+!
+interface lo
+ ip address 4.4.4.4/32
+ ipv6 address fc00:0:4::1/128
+!
+interface eth-rt2-1
+ ip address 10.0.2.4/24
+!
+interface eth-rt2-2
+ ip address 10.0.3.4/24
+!
+interface eth-rt5
+ ip address 10.0.6.4/24
+!
+interface eth-rt6
+ ip address 10.0.7.4/24
+!
+segment-routing
+ srv6
+ locators
+ locator loc1
+ prefix fc00:0:4::/48
+ format usid-f3216
+ !
+ !
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/srv6_sid_manager/rt5/isisd.conf b/tests/topotests/srv6_sid_manager/rt5/isisd.conf
new file mode 100644
index 0000000000..26f895dd82
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt5/isisd.conf
@@ -0,0 +1,56 @@
+hostname rt5
+log file isisd.log
+!
+! debug isis events
+! debug isis route-events
+! debug isis spf-events
+! debug isis sr-events
+! debug isis lsp-gen
+!
+interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+interface eth-rt3-1
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+interface eth-rt3-2
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+interface eth-rt4
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+interface eth-rt6
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+router isis 1
+ lsp-gen-interval 2
+ net 49.0000.0000.0000.0005.00
+ is-type level-1
+ topology ipv6-unicast
+ segment-routing srv6
+ locator loc1
+ node-msd
+ max-segs-left 3
+ max-end-pop 3
+ max-h-encaps 2
+ max-end-d 5
+ interface sr0
+!
diff --git a/tests/topotests/srv6_sid_manager/rt5/show_ip_route.ref b/tests/topotests/srv6_sid_manager/rt5/show_ip_route.ref
new file mode 100644
index 0000000000..65beaa5998
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt5/show_ip_route.ref
@@ -0,0 +1,296 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1"
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2"
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4"
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt5/show_ipv6_route.ref b/tests/topotests/srv6_sid_manager/rt5/show_ipv6_route.ref
new file mode 100644
index 0000000000..a7b3262f86
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt5/show_ipv6_route.ref
@@ -0,0 +1,346 @@
+{
+ "fc00:0:1::1\/128":[
+ {
+ "prefix":"fc00:0:1::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:2::1\/128":[
+ {
+ "prefix":"fc00:0:2::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:3::1\/128":[
+ {
+ "prefix":"fc00:0:3::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:4::1\/128":[
+ {
+ "prefix":"fc00:0:4::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:6::1\/128":[
+ {
+ "prefix":"fc00:0:6::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:1::\/48":[
+ {
+ "prefix":"fc00:0:1::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:2::\/48":[
+ {
+ "prefix":"fc00:0:2::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:3::\/48":[
+ {
+ "prefix":"fc00:0:3::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:4::\/48":[
+ {
+ "prefix":"fc00:0:4::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:6::\/48":[
+ {
+ "prefix":"fc00:0:6::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:5::\/48":[
+ {
+ "prefix":"fc00:0:5::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"sr0",
+ "active":true,
+ "seg6local":{
+ "action":"End"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:5:e000::\/64":[
+ {
+ "prefix":"fc00:0:5:e000::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:5:e001::\/64":[
+ {
+ "prefix":"fc00:0:5:e001::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:5:e002::\/64":[
+ {
+ "prefix":"fc00:0:5:e002::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:5:e003::\/64":[
+ {
+ "prefix":"fc00:0:5:e003::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt5/show_srv6_locator_table.ref b/tests/topotests/srv6_sid_manager/rt5/show_srv6_locator_table.ref
new file mode 100644
index 0000000000..ec55f24d7b
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt5/show_srv6_locator_table.ref
@@ -0,0 +1,15 @@
+{
+ "locators":[
+ {
+ "name":"loc1",
+ "prefix":"fc00:0:5::/48",
+ "blockBitsLength":32,
+ "nodeBitsLength":16,
+ "functionBitsLength":16,
+ "argumentBitsLength":0,
+ "statusUp":true,
+ "chunks":[
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt5/show_yang_interface_isis_adjacencies.ref b/tests/topotests/srv6_sid_manager/rt5/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..f40b0d353d
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt5/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,82 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "eth-rt3-1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0003",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "eth-rt3-2",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0003",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "eth-rt4",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0004",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "eth-rt6",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0006",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/srv6_sid_manager/rt5/zebra.conf b/tests/topotests/srv6_sid_manager/rt5/zebra.conf
new file mode 100644
index 0000000000..901103554b
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt5/zebra.conf
@@ -0,0 +1,36 @@
+log file zebra.log
+!
+hostname rt5
+!
+! debug zebra kernel
+! debug zebra packet
+!
+interface lo
+ ip address 5.5.5.5/32
+ ipv6 address fc00:0:5::1/128
+!
+interface eth-rt3-1
+ ip address 10.0.4.5/24
+!
+interface eth-rt3-2
+ ip address 10.0.5.5/24
+!
+interface eth-rt4
+ ip address 10.0.6.5/24
+!
+interface eth-rt6
+ ip address 10.0.8.5/24
+!
+segment-routing
+ srv6
+ locators
+ locator loc1
+ prefix fc00:0:5::/48
+ format usid-f3216
+ !
+ !
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/srv6_sid_manager/rt6/bgpd.conf b/tests/topotests/srv6_sid_manager/rt6/bgpd.conf
new file mode 100644
index 0000000000..fe82feece4
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt6/bgpd.conf
@@ -0,0 +1,68 @@
+frr defaults traditional
+!
+bgp send-extra-data zebra
+!
+hostname rt6
+password zebra
+!
+log stdout notifications
+log monitor notifications
+log commands
+!
+!debug bgp neighbor-events
+!debug bgp zebra
+!debug bgp vnc verbose
+!debug bgp update-groups
+!debug bgp updates in
+!debug bgp updates out
+!debug bgp updates
+!debug bgp vpn label
+!debug bgp vpn leak-from-vrf
+!debug bgp vpn leak-to-vrf
+!!debug bgp vpn rmap-event
+!
+router bgp 6
+ bgp router-id 6.6.6.6
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ neighbor fc00:0:1::1 remote-as 1
+ neighbor fc00:0:1::1 timers 3 10
+ neighbor fc00:0:1::1 timers connect 1
+ neighbor fc00:0:1::1 ttl-security hops 20
+ !
+ address-family ipv6 vpn
+ neighbor fc00:0:1::1 activate
+ exit-address-family
+ !
+ segment-routing srv6
+ locator loc1
+ !
+!
+router bgp 6 vrf vrf10
+ bgp router-id 6.6.6.6
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ !
+ address-family ipv6 unicast
+ sid vpn export 65024
+ rd vpn export 6:10
+ rt vpn both 99:99
+ import vpn
+ export vpn
+ redistribute connected
+ exit-address-family
+!
+router bgp 6 vrf vrf20
+ bgp router-id 6.6.6.6
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ !
+ address-family ipv6 unicast
+ sid vpn export 65025
+ rd vpn export 6:20
+ rt vpn both 88:88
+ import vpn
+ export vpn
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/srv6_sid_manager/rt6/isisd.conf b/tests/topotests/srv6_sid_manager/rt6/isisd.conf
new file mode 100644
index 0000000000..f8816db43a
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt6/isisd.conf
@@ -0,0 +1,42 @@
+hostname rt6
+log file isisd.log
+!
+! debug isis events
+! debug isis route-events
+! debug isis spf-events
+! debug isis sr-events
+! debug isis lsp-gen
+!
+interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+interface eth-rt4
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+interface eth-rt5
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+router isis 1
+ lsp-gen-interval 2
+ net 49.0000.0000.0000.0006.00
+ is-type level-1
+ topology ipv6-unicast
+ segment-routing srv6
+ locator loc1
+ node-msd
+ max-segs-left 3
+ max-end-pop 3
+ max-h-encaps 2
+ max-end-d 5
+ interface sr0
+!
diff --git a/tests/topotests/srv6_sid_manager/rt6/sharpd.conf b/tests/topotests/srv6_sid_manager/rt6/sharpd.conf
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt6/sharpd.conf
diff --git a/tests/topotests/srv6_sid_manager/rt6/show_ip_route.ref b/tests/topotests/srv6_sid_manager/rt6/show_ip_route.ref
new file mode 100644
index 0000000000..5fc293b6d8
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt6/show_ip_route.ref
@@ -0,0 +1,273 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4"
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt6/show_ipv6_route.ref b/tests/topotests/srv6_sid_manager/rt6/show_ipv6_route.ref
new file mode 100644
index 0000000000..d06354b872
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt6/show_ipv6_route.ref
@@ -0,0 +1,312 @@
+{
+ "fc00:0:1::1\/128":[
+ {
+ "prefix":"fc00:0:1::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:2::1\/128":[
+ {
+ "prefix":"fc00:0:2::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:3::1\/128":[
+ {
+ "prefix":"fc00:0:3::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:4::1\/128":[
+ {
+ "prefix":"fc00:0:4::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:5::1\/128":[
+ {
+ "prefix":"fc00:0:5::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:1::\/48":[
+ {
+ "prefix":"fc00:0:1::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:2::\/48":[
+ {
+ "prefix":"fc00:0:2::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:3::\/48":[
+ {
+ "prefix":"fc00:0:3::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:4::\/48":[
+ {
+ "prefix":"fc00:0:4::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:5::\/48":[
+ {
+ "prefix":"fc00:0:5::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "fc00:0:6::\/48":[
+ {
+ "prefix":"fc00:0:6::\/48",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"sr0",
+ "active":true,
+ "seg6local":{
+ "action":"End"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:6:e000::\/64":[
+ {
+ "prefix":"fc00:0:6:e000::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:6:e001::\/64":[
+ {
+ "prefix":"fc00:0:6:e001::\/64",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "active":true,
+ "seg6local":{
+ "action":"End.X"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:6:fe00::\/128":[
+ {
+ "prefix":"fc00:0:6:fe00::\/128",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"vrf10",
+ "active":true,
+ "seg6local":{
+ "action":"End.DT6"
+ }
+ }
+ ]
+ }
+ ],
+ "fc00:0:6:fe01::\/128":[
+ {
+ "prefix":"fc00:0:6:fe01::\/128",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"vrf20",
+ "active":true,
+ "seg6local":{
+ "action":"End.DT6"
+ }
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt6/show_srv6_locator_table.ref b/tests/topotests/srv6_sid_manager/rt6/show_srv6_locator_table.ref
new file mode 100644
index 0000000000..abcdeddea4
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt6/show_srv6_locator_table.ref
@@ -0,0 +1,15 @@
+{
+ "locators":[
+ {
+ "name":"loc1",
+ "prefix":"fc00:0:6::/48",
+ "blockBitsLength":32,
+ "nodeBitsLength":16,
+ "functionBitsLength":16,
+ "argumentBitsLength":0,
+ "statusUp":true,
+ "chunks":[
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt6/show_yang_interface_isis_adjacencies.ref b/tests/topotests/srv6_sid_manager/rt6/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..8300ca0b5c
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt6/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,44 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "eth-rt4",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0004",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "eth-rt5",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0005",
+ "hold-timer": 10,
+ "neighbor-priority": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/srv6_sid_manager/rt6/vpnv6_rib.ref b/tests/topotests/srv6_sid_manager/rt6/vpnv6_rib.ref
new file mode 100644
index 0000000000..fe0fa24529
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt6/vpnv6_rib.ref
@@ -0,0 +1,169 @@
+{
+ "vrfId": 0,
+ "vrfName": "default",
+ "routerId": "6.6.6.6",
+ "defaultLocPrf": 100,
+ "localAS": 6,
+ "routes": {
+ "routeDistinguishers": {
+ "1:10": {
+ "2001:1::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:1::",
+ "prefixLen": 64,
+ "network": "2001:1::/64",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "fc00:0:1::1",
+ "path": "1",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "fc00:0:1::1",
+ "hostname": "rt1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "2001:3::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:3::",
+ "prefixLen": 64,
+ "network": "2001:3::/64",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "fc00:0:1::1",
+ "path": "1",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "fc00:0:1::1",
+ "hostname": "rt1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
+ "1:20": {
+ "2001:5::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:5::",
+ "prefixLen": 64,
+ "network": "2001:5::/64",
+ "metric": 0,
+ "weight": 0,
+ "peerId": "fc00:0:1::1",
+ "path": "1",
+ "origin": "incomplete",
+ "nexthops": [
+ {
+ "ip": "fc00:0:1::1",
+ "hostname": "rt1",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
+ "6:10": {
+ "2001:2::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:2::",
+ "prefixLen": 64,
+ "network": "2001:2::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf10",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "rt6",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ },
+ "6:20": {
+ "2001:4::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:4::",
+ "prefixLen": 64,
+ "network": "2001:4::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf20",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "rt6",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "2001:6::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "selectionReason": "First path received",
+ "pathFrom": "external",
+ "prefix": "2001:6::",
+ "prefixLen": 64,
+ "network": "2001:6::/64",
+ "metric": 0,
+ "weight": 32768,
+ "peerId": "(unspec)",
+ "path": "",
+ "origin": "incomplete",
+ "announceNexthopSelf": true,
+ "nhVrfName": "vrf20",
+ "nexthops": [
+ {
+ "ip": "::",
+ "hostname": "rt6",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/tests/topotests/srv6_sid_manager/rt6/vrf10_rib.ref b/tests/topotests/srv6_sid_manager/rt6/vrf10_rib.ref
new file mode 100644
index 0000000000..87ff5a9902
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt6/vrf10_rib.ref
@@ -0,0 +1,92 @@
+{
+ "2001:1::/64": [
+ {
+ "prefix": "2001:1::/64",
+ "protocol": "bgp",
+ "vrfName": "vrf10",
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "installed": true,
+ "table": 10,
+ "internalStatus": 16,
+ "internalFlags": 9,
+ "internalNextHopNum": 3,
+ "internalNextHopActiveNum": 3,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "afi": "ipv6",
+ "interfaceName": "eth-rt5",
+ "vrf": "default",
+ "active": true,
+ "weight": 1,
+ "seg6": {
+ "segs": "fc00:0:1:fe00::"
+ }
+ }
+ ],
+ "asPath": "1"
+ }
+ ],
+ "2001:2::/64": [
+ {
+ "prefix": "2001:2::/64",
+ "protocol": "connected",
+ "vrfName": "vrf10",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 10,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth-ce2",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "2001:3::/64": [
+ {
+ "prefix": "2001:3::/64",
+ "protocol": "bgp",
+ "vrfName": "vrf10",
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "installed": true,
+ "table": 10,
+ "internalStatus": 16,
+ "internalFlags": 9,
+ "internalNextHopNum": 3,
+ "internalNextHopActiveNum": 3,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "afi": "ipv6",
+ "interfaceName": "eth-rt5",
+ "vrf": "default",
+ "active": true,
+ "weight": 1,
+ "seg6": {
+ "segs": "fc00:0:1:fe00::"
+ }
+ }
+ ],
+ "asPath": "1"
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt6/vrf20_rib.ref b/tests/topotests/srv6_sid_manager/rt6/vrf20_rib.ref
new file mode 100644
index 0000000000..95d7d4412b
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt6/vrf20_rib.ref
@@ -0,0 +1,86 @@
+{
+ "2001:4::/64": [
+ {
+ "prefix": "2001:4::/64",
+ "protocol": "connected",
+ "vrfName": "vrf20",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 20,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth-ce4",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "2001:5::/64": [
+ {
+ "prefix": "2001:5::/64",
+ "protocol": "bgp",
+ "vrfName": "vrf20",
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "installed": true,
+ "table": 20,
+ "internalStatus": 16,
+ "internalFlags": 9,
+ "internalNextHopNum": 3,
+ "internalNextHopActiveNum": 3,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "afi": "ipv6",
+ "interfaceName": "eth-rt5",
+ "vrf": "default",
+ "active": true,
+ "weight": 1,
+ "seg6": {
+ "segs": "fc00:0:1:fe01::"
+ }
+ }
+ ],
+ "asPath": "1"
+ }
+ ],
+ "2001:6::/64": [
+ {
+ "prefix": "2001:6::/64",
+ "protocol": "connected",
+ "vrfName": "vrf20",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "table": 20,
+ "internalStatus": 16,
+ "internalFlags": 8,
+ "internalNextHopNum": 1,
+ "internalNextHopActiveNum": 1,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth-ce6",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/srv6_sid_manager/rt6/zebra.conf b/tests/topotests/srv6_sid_manager/rt6/zebra.conf
new file mode 100644
index 0000000000..8ac64c559e
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/rt6/zebra.conf
@@ -0,0 +1,45 @@
+log file zebra.log
+!
+hostname rt6
+!
+! debug zebra kernel
+! debug zebra packet
+!
+interface lo
+ ip address 6.6.6.6/32
+ ipv6 address fc00:0:6::1/128
+!
+interface eth-rt4
+ ip address 10.0.7.6/24
+!
+interface eth-rt5
+ ip address 10.0.8.6/24
+!
+interface eth-dst
+ ip address 10.0.10.1/24
+ ip address 2001:db8:10::1/64
+!
+interface eth-ce2 vrf vrf10
+ ipv6 address 2001:2::1/64
+!
+interface eth-ce4 vrf vrf20
+ ipv6 address 2001:4::1/64
+!
+interface eth-ce6 vrf vrf20
+ ipv6 address 2001:6::1/64
+!
+segment-routing
+ srv6
+ locators
+ locator loc1
+ prefix fc00:0:6::/48
+ format usid-f3216
+ !
+ !
+!
+ip forwarding
+!
+ipv6 route fc00:0:9::1/128 2001:db8:10::2 vrf vrf10
+!
+line vty
+!
diff --git a/tests/topotests/srv6_sid_manager/test_srv6_sid_manager.py b/tests/topotests/srv6_sid_manager/test_srv6_sid_manager.py
new file mode 100644
index 0000000000..31f22d9900
--- /dev/null
+++ b/tests/topotests/srv6_sid_manager/test_srv6_sid_manager.py
@@ -0,0 +1,421 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# Copyright (c) 2023 by Carmine Scarpitta <cscarpit@cisco.com>
+#
+
+"""
+test_srv6_sid_manager.py:
+
+ +---------+
+ | |
+ | RT1 |
+ | 1.1.1.1 |
+ | |
+ +---------+
+ |eth-sw1
+ |
+ |
+ |
+ +---------+ | +---------+
+ | | | | |
+ | RT2 |eth-sw1 | eth-sw1| RT3 |
+ | 2.2.2.2 +----------+----------+ 3.3.3.3 |
+ | | 10.0.1.0/24 | |
+ +---------+ +---------+
+ eth-rt4-1| |eth-rt4-2 eth-rt5-1| |eth-rt5-2
+ | | | |
+ 10.0.2.0/24| |10.0.3.0/24 10.0.4.0/24| |10.0.5.0/24
+ | | | |
+ eth-rt2-1| |eth-rt2-2 eth-rt3-1| |eth-rt3-2
+ +---------+ +---------+
+ | | | |
+ | RT4 | 10.0.6.0/24 | RT5 |
+ | 4.4.4.4 +---------------------+ 5.5.5.5 |
+ | |eth-rt5 eth-rt4| |
+ +---------+ +---------+
+ eth-rt6| |eth-rt6
+ | |
+ 10.0.7.0/24| |10.0.8.0/24
+ | +---------+ |
+ | | | |
+ | | RT6 | |
+ +----------+ 6.6.6.6 +-----------+
+ eth-rt4| |eth-rt5
+ +---------+
+ |eth-dst (.1)
+ |
+ |10.0.10.0/24
+ |
+ |eth-rt6 (.2)
+ +---------+
+ | |
+ | DST |
+ | 9.9.9.2 |
+ | |
+ +---------+
+
+"""
+
+import os
+import re
+import sys
+import json
+import functools
+import pytest
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from lib.common_config import (
+ required_linux_kernel_version,
+ create_interface_in_kernel,
+)
+from lib.checkping import check_ping
+
+pytestmark = [pytest.mark.isisd, pytest.mark.sharpd]
+
+
+def build_topo(tgen):
+ """Build function"""
+
+ # Define FRR Routers
+ tgen.add_router("rt1")
+ tgen.add_router("rt2")
+ tgen.add_router("rt3")
+ tgen.add_router("rt4")
+ tgen.add_router("rt5")
+ tgen.add_router("rt6")
+ tgen.add_router("dst")
+ tgen.add_router("ce1")
+ tgen.add_router("ce2")
+ tgen.add_router("ce3")
+ tgen.add_router("ce4")
+ tgen.add_router("ce5")
+ tgen.add_router("ce6")
+
+ # Define connections
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["rt1"], nodeif="eth-sw1")
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-sw1")
+ switch.add_link(tgen.gears["rt3"], nodeif="eth-sw1")
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4-1")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2-1")
+
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4-2")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2-2")
+
+ switch = tgen.add_switch("s4")
+ switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5-1")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3-1")
+
+ switch = tgen.add_switch("s5")
+ switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5-2")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3-2")
+
+ switch = tgen.add_switch("s6")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt5")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt4")
+
+ switch = tgen.add_switch("s7")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt6")
+ switch.add_link(tgen.gears["rt6"], nodeif="eth-rt4")
+
+ switch = tgen.add_switch("s8")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt6")
+ switch.add_link(tgen.gears["rt6"], nodeif="eth-rt5")
+
+ switch = tgen.add_switch("s9")
+ switch.add_link(tgen.gears["rt6"], nodeif="eth-dst")
+ switch.add_link(tgen.gears["dst"], nodeif="eth-rt6")
+
+ tgen.add_link(tgen.gears["ce1"], tgen.gears["rt1"], "eth-rt1", "eth-ce1")
+ tgen.add_link(tgen.gears["ce2"], tgen.gears["rt6"], "eth-rt6", "eth-ce2")
+ tgen.add_link(tgen.gears["ce3"], tgen.gears["rt1"], "eth-rt1", "eth-ce3")
+ tgen.add_link(tgen.gears["ce4"], tgen.gears["rt6"], "eth-rt6", "eth-ce4")
+ tgen.add_link(tgen.gears["ce5"], tgen.gears["rt1"], "eth-rt1", "eth-ce5")
+ tgen.add_link(tgen.gears["ce6"], tgen.gears["rt6"], "eth-rt6", "eth-ce6")
+
+ tgen.gears["rt1"].run("ip link add vrf10 type vrf table 10")
+ tgen.gears["rt1"].run("ip link set vrf10 up")
+ tgen.gears["rt1"].run("ip link add vrf20 type vrf table 20")
+ tgen.gears["rt1"].run("ip link set vrf20 up")
+ tgen.gears["rt1"].run("ip link set eth-ce1 master vrf10")
+ tgen.gears["rt1"].run("ip link set eth-ce3 master vrf10")
+ tgen.gears["rt1"].run("ip link set eth-ce5 master vrf20")
+
+ tgen.gears["rt6"].run("ip link add vrf10 type vrf table 10")
+ tgen.gears["rt6"].run("ip link set vrf10 up")
+ tgen.gears["rt6"].run("ip link add vrf20 type vrf table 20")
+ tgen.gears["rt6"].run("ip link set vrf20 up")
+ tgen.gears["rt6"].run("ip link set eth-ce2 master vrf10")
+ tgen.gears["rt6"].run("ip link set eth-ce4 master vrf20")
+ tgen.gears["rt6"].run("ip link set eth-ce6 master vrf20")
+
+ # Add dummy interface for SRv6
+ create_interface_in_kernel(
+ tgen,
+ "rt1",
+ "sr0",
+ "2001:db8::1",
+ netmask="128",
+ create=True,
+ )
+ create_interface_in_kernel(
+ tgen,
+ "rt2",
+ "sr0",
+ "2001:db8::2",
+ netmask="128",
+ create=True,
+ )
+ create_interface_in_kernel(
+ tgen,
+ "rt3",
+ "sr0",
+ "2001:db8::3",
+ netmask="128",
+ create=True,
+ )
+ create_interface_in_kernel(
+ tgen,
+ "rt4",
+ "sr0",
+ "2001:db8::4",
+ netmask="128",
+ create=True,
+ )
+ create_interface_in_kernel(
+ tgen,
+ "rt5",
+ "sr0",
+ "2001:db8::5",
+ netmask="128",
+ create=True,
+ )
+ create_interface_in_kernel(
+ tgen,
+ "rt6",
+ "sr0",
+ "2001:db8::6",
+ netmask="128",
+ create=True,
+ )
+
+
+def setup_module(mod):
+ """Sets up the pytest environment"""
+
+ # Verify if kernel requirements are satisfied
+ result = required_linux_kernel_version("4.10")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ # Build the topology
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ # For all registered routers, load the zebra and isis configuration files
+ for rname, router in tgen.routers().items():
+ router.load_config(TopoRouter.RD_ZEBRA,
+ os.path.join(CWD, '{}/zebra.conf'.format(rname)))
+ router.load_config(TopoRouter.RD_ISIS,
+ os.path.join(CWD, '{}/isisd.conf'.format(rname)))
+ router.load_config(TopoRouter.RD_BGP,
+ os.path.join(CWD, '{}/bgpd.conf'.format(rname)))
+ if (os.path.exists('{}/sharpd.conf'.format(rname))):
+ router.load_config(TopoRouter.RD_SHARP,
+ os.path.join(CWD, '{}/sharpd.conf'.format(rname)))
+
+ # Start routers
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ "Teardown the pytest environment"
+
+ # Teardown the topology
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def router_compare_json_output(rname, command, reference):
+ "Compare router JSON output"
+
+ logger.info('Comparing router "%s" "%s" output', rname, command)
+
+ tgen = get_topogen()
+ filename = "{}/{}/{}".format(CWD, rname, reference)
+ expected = json.loads(open(filename).read())
+
+ # Run test function until we get an result. Wait at most 60 seconds.
+ test_func = functools.partial(topotest.router_json_cmp, tgen.gears[rname], command, expected)
+ _, diff = topotest.run_and_expect(test_func, None, count=120, wait=0.5)
+ assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
+ assert diff is None, assertmsg
+
+
+def check_ping6(name, dest_addr, expect_connected):
+ def _check(name, dest_addr, match):
+ tgen = get_topogen()
+ output = tgen.gears[name].run("ping6 {} -c 1 -w 1".format(dest_addr))
+ logger.info(output)
+ if match not in output:
+ return "ping fail"
+
+ match = "{} packet loss".format("0%" if expect_connected else "100%")
+ logger.info("[+] check {} {} {}".format(name, dest_addr, match))
+ tgen = get_topogen()
+ func = functools.partial(_check, name, dest_addr, match)
+ success, result = topotest.run_and_expect(func, None, count=10, wait=1)
+ assert result is None, "Failed"
+
+
+def open_json_file(filename):
+ try:
+ with open(filename, "r") as f:
+ return json.load(f)
+ except IOError:
+ assert False, "Could not read file {}".format(filename)
+
+
+def check_rib(name, cmd, expected_file):
+ def _check(name, cmd, expected_file):
+ logger.info("polling")
+ tgen = get_topogen()
+ router = tgen.gears[name]
+ output = json.loads(router.vtysh_cmd(cmd))
+ expected = open_json_file("{}/{}".format(CWD, expected_file))
+ return topotest.json_cmp(output, expected)
+
+ logger.info('[+] check {} "{}" {}'.format(name, cmd, expected_file))
+ tgen = get_topogen()
+ func = functools.partial(_check, name, cmd, expected_file)
+ success, result = topotest.run_and_expect(func, None, count=10, wait=0.5)
+ assert result is None, "Failed"
+
+
+#
+# Step 1
+#
+# Test initial network convergence
+#
+def test_isis_adjacencies():
+ logger.info("Test: check IS-IS adjacencies")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname,
+ "show yang operational-data /frr-interface:lib isisd",
+ "show_yang_interface_isis_adjacencies.ref",
+ )
+
+
+def test_rib_ipv4():
+ logger.info("Test: verify IPv4 RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show ip route isis json", "show_ip_route.ref"
+ )
+
+
+def test_rib_ipv6():
+ logger.info("Test: verify IPv6 RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show ipv6 route json", "show_ipv6_route.ref"
+ )
+
+
+def test_srv6_locator():
+ logger.info("Test: verify SRv6 Locator")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show segment-routing srv6 locator json", "show_srv6_locator_table.ref"
+ )
+
+
+def test_vpn_rib():
+ check_rib("rt1", "show bgp ipv6 vpn json", "rt1/vpnv6_rib.ref")
+ check_rib("rt6", "show bgp ipv6 vpn json", "rt6/vpnv6_rib.ref")
+ check_rib("rt1", "show ipv6 route vrf vrf10 json", "rt1/vrf10_rib.ref")
+ check_rib("rt1", "show ipv6 route vrf vrf20 json", "rt1/vrf20_rib.ref")
+ check_rib("rt6", "show ipv6 route vrf vrf10 json", "rt6/vrf10_rib.ref")
+ check_rib("rt6", "show ipv6 route vrf vrf20 json", "rt6/vrf20_rib.ref")
+ check_rib("ce1", "show ipv6 route json", "ce1/ipv6_rib.json")
+ check_rib("ce2", "show ipv6 route json", "ce2/ipv6_rib.json")
+ check_rib("ce3", "show ipv6 route json", "ce3/ipv6_rib.json")
+ check_rib("ce4", "show ipv6 route json", "ce4/ipv6_rib.json")
+ check_rib("ce5", "show ipv6 route json", "ce5/ipv6_rib.json")
+ check_rib("ce6", "show ipv6 route json", "ce6/ipv6_rib.json")
+
+
+def test_ping():
+ logger.info("Test: verify ping")
+ tgen = get_topogen()
+
+ # Required linux kernel version for this suite to run.
+ result = required_linux_kernel_version("6.1")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met, kernel version should be >=6.1")
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Setup encap route on rt1, decap route on rt2
+ # tgen.gears["rt1"].vtysh_cmd("sharp install seg6-routes fc00:0:9::1 nexthop-seg6 2001:db8:1::2 encap fc00:0:2:6:fe00:: 1")
+ tgen.gears["rt1"].cmd("ip -6 r a fc00:0:9::1/128 encap seg6 mode encap segs fc00:0:2:6:fe00:: via 2001:db8:1::2")
+ # tgen.gears["rt6"].vtysh_cmd("sharp install seg6local-routes fc00:0:f00d:: nexthop-seg6local eth-dst End_DT6 254 1")
+ tgen.gears["rt6"].cmd("ip -6 r a fc00:0:9::1/128 via 2001:db8:10::2 vrf vrf10")
+ tgen.gears["dst"].cmd("ip -6 r a 2001:db8:1::1/128 via 2001:db8:10::1")
+
+ # Try to ping dst from rt1
+ check_ping("rt1", "fc00:0:9::1", True, 10, 1)
+
+
+# Memory leak test template
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/__init__.py b/tests/topotests/zebra_fec_nexthop_resolution/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/__init__.py
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r1/bgpd.conf b/tests/topotests/zebra_fec_nexthop_resolution/r1/bgpd.conf
new file mode 100644
index 0000000000..9d28957d99
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r1/bgpd.conf
@@ -0,0 +1,24 @@
+!
+router bgp 65500
+ bgp router-id 192.0.2.1
+ neighbor 192.0.2.3 remote-as 65500
+ neighbor 192.0.2.3 update-source lo
+ neighbor 192.0.2.7 remote-as 65500
+ neighbor 192.0.2.7 ttl-security hops 10
+ neighbor 192.0.2.7 disable-connected-check
+ neighbor 192.0.2.7 update-source lo
+ !
+ address-family ipv4 unicast
+ network 192.0.2.1/32
+ no neighbor 192.0.2.3 activate
+ neighbor 192.0.2.7 activate
+ exit-address-family
+ !
+ address-family ipv4 labeled-unicast
+ neighbor 192.0.2.3 activate
+ neighbor 192.0.2.3 route-reflector-client
+ neighbor 192.0.2.3 next-hop-self force
+ exit-address-family
+ !
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r1/ospfd.conf.after b/tests/topotests/zebra_fec_nexthop_resolution/r1/ospfd.conf.after
new file mode 100644
index 0000000000..3bb8cf8ac5
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r1/ospfd.conf.after
@@ -0,0 +1,25 @@
+log stdout
+!
+interface lo
+ ip ospf passive
+exit
+!
+interface r1-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 1
+exit
+!
+router ospf
+ ospf router-id 192.0.2.1
+ network 192.0.2.1/32 area 0.0.0.0
+ network 192.168.1.0/24 area 0.0.0.0
+ passive-interface lo
+ capability opaque
+ mpls-te on
+ mpls-te router-address 192.0.2.1
+ segment-routing on
+ segment-routing global-block 1000 10000 local-block 32000 32999
+ segment-routing node-msd 8
+ segment-routing prefix 192.0.2.1/32 index 11
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r1/zebra.conf b/tests/topotests/zebra_fec_nexthop_resolution/r1/zebra.conf
new file mode 100644
index 0000000000..1522e90398
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r1/zebra.conf
@@ -0,0 +1,13 @@
+interface lo
+ ip address 192.0.2.1/32
+ mpls enable
+exit
+!
+interface r1-eth0
+ ip address 192.168.1.1/24
+ mpls enable
+ link-params
+ enable
+ exit-link-params
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r2/bgpd.conf b/tests/topotests/zebra_fec_nexthop_resolution/r2/bgpd.conf
new file mode 100644
index 0000000000..46d2c9a01d
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r2/bgpd.conf
@@ -0,0 +1,23 @@
+router bgp 65500
+ bgp router-id 192.0.2.2
+ neighbor 192.0.2.1 remote-as 65500
+ neighbor 192.0.2.1 update-source lo
+ neighbor 192.0.2.3 remote-as 65500
+ neighbor 192.0.2.3 update-source lo
+ !
+ address-family ipv4 unicast
+ network 192.0.2.2/32
+ no neighbor 192.0.2.1 activate
+ no neighbor 192.0.2.3 activate
+ exit-address-family
+ !
+ address-family ipv4 labeled-unicast
+ neighbor 192.0.2.1 activate
+ neighbor 192.0.2.1 route-reflector-client
+ neighbor 192.0.2.1 next-hop-self force
+ neighbor 192.0.2.3 activate
+ neighbor 192.0.2.3 route-reflector-client
+ neighbor 192.0.2.3 next-hop-self force
+ exit-address-family
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r2/isisd.conf b/tests/topotests/zebra_fec_nexthop_resolution/r2/isisd.conf
new file mode 100644
index 0000000000..add181ddae
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r2/isisd.conf
@@ -0,0 +1,25 @@
+!
+interface lo
+ ip router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+exit
+!
+interface r2-eth1
+ ip router isis 2
+ isis hello-interval 1
+ isis hello-multiplier 3
+exit
+!
+router isis 1
+ is-type level-1
+ net 49.0000.0007.e901.2223.00
+ lsp-timers gen-interval 1 refresh-interval 900 max-lifetime 1200
+ mpls-te on
+ mpls-te router-address 192.0.2.2
+ segment-routing on
+ segment-routing global-block 11000 20000 local-block 36000 36999
+ segment-routing node-msd 8
+ segment-routing prefix 192.0.2.2/32 index 22 no-php-flag
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r2/ospfd.conf.after b/tests/topotests/zebra_fec_nexthop_resolution/r2/ospfd.conf.after
new file mode 100644
index 0000000000..8b02669862
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r2/ospfd.conf.after
@@ -0,0 +1,32 @@
+log stdout
+!
+interface lo
+ ip ospf network point-to-point
+ ip ospf passive
+exit
+!
+interface r2-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 1
+exit
+!
+interface r2-eth1
+ ip ospf network point-to-point
+ ip ospf hello-interval 1
+exit
+!
+router ospf
+ ospf router-id 192.0.2.2
+ network 192.0.2.2/32 area 0.0.0.0
+ network 192.168.1.0/24 area 0.0.0.0
+ network 192.168.2.0/24 area 0.0.0.0
+ passive-interface lo
+ capability opaque
+ mpls-te on
+ mpls-te router-address 192.0.2.2
+ segment-routing on
+ segment-routing global-block 1000 10000 local-block 36000 36999
+ segment-routing node-msd 8
+ segment-routing prefix 192.0.2.2/32 index 22
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r2/zebra.conf b/tests/topotests/zebra_fec_nexthop_resolution/r2/zebra.conf
new file mode 100644
index 0000000000..af0d1eb7fe
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r2/zebra.conf
@@ -0,0 +1,16 @@
+!
+interface lo
+ ip address 192.0.2.2/32
+ mpls enable
+exit
+!
+interface r2-eth0
+ ip address 192.168.1.2/24
+ mpls enable
+exit
+!
+interface r2-eth1
+ ip address 192.168.2.2/24
+ mpls enable
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r3/bgpd.conf b/tests/topotests/zebra_fec_nexthop_resolution/r3/bgpd.conf
new file mode 100644
index 0000000000..060777e7fe
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r3/bgpd.conf
@@ -0,0 +1,23 @@
+router bgp 65500
+ bgp router-id 192.0.2.3
+ neighbor 192.0.2.1 remote-as 65500
+ neighbor 192.0.2.1 update-source lo
+ neighbor 192.0.2.5 remote-as 65500
+ neighbor 192.0.2.5 update-source lo
+ !
+ address-family ipv4 unicast
+ network 192.0.2.3/32
+ no neighbor 192.0.2.1 activate
+ no neighbor 192.0.2.5 activate
+ exit-address-family
+ !
+ address-family ipv4 labeled-unicast
+ neighbor 192.0.2.1 activate
+ neighbor 192.0.2.1 route-reflector-client
+ neighbor 192.0.2.1 next-hop-self force
+ neighbor 192.0.2.5 activate
+ neighbor 192.0.2.5 route-reflector-client
+ neighbor 192.0.2.5 next-hop-self force
+ exit-address-family
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r3/isisd.conf b/tests/topotests/zebra_fec_nexthop_resolution/r3/isisd.conf
new file mode 100644
index 0000000000..db6a503bb2
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r3/isisd.conf
@@ -0,0 +1,25 @@
+!
+interface lo
+ ip router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+exit
+!
+interface r3-eth1
+ ip router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+exit
+!
+router isis 1
+ is-type level-1
+ net 49.0000.0007.e901.3333.00
+ lsp-timers gen-interval 1 refresh-interval 900 max-lifetime 1200
+ mpls-te on
+ mpls-te router-address 192.0.2.3
+ segment-routing on
+ segment-routing global-block 11000 12000 local-block 36000 36999
+ segment-routing node-msd 8
+ segment-routing prefix 192.0.2.3/32 index 33
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r3/ospfd.conf.after b/tests/topotests/zebra_fec_nexthop_resolution/r3/ospfd.conf.after
new file mode 100644
index 0000000000..a3f5ae54f0
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r3/ospfd.conf.after
@@ -0,0 +1,26 @@
+log stdout
+!
+interface lo
+ ip ospf network point-to-point
+ ip ospf passive
+exit
+!
+interface r3-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 1
+exit
+!
+router ospf
+ ospf router-id 192.0.2.3
+ network 192.0.2.3/32 area 0.0.0.0
+ network 192.168.2.0/24 area 0.0.0.0
+ passive-interface lo
+ capability opaque
+ mpls-te on
+ mpls-te router-address 192.0.2.3
+ segment-routing on
+ segment-routing global-block 1000 10000 local-block 30000 30999
+ segment-routing node-msd 8
+ segment-routing prefix 192.0.2.3/32 index 33
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r3/zebra.conf b/tests/topotests/zebra_fec_nexthop_resolution/r3/zebra.conf
new file mode 100644
index 0000000000..b309e15afa
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r3/zebra.conf
@@ -0,0 +1,19 @@
+!
+interface lo
+ ip address 192.0.2.3/32
+ mpls enable
+exit
+!
+interface r3-eth0
+ ip address 192.168.2.3/24
+ mpls enable
+ link-params
+ enable
+ exit-link-params
+exit
+!
+interface r3-eth1
+ ip address 192.168.3.3/24
+ mpls enable
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r4/bgpd.conf b/tests/topotests/zebra_fec_nexthop_resolution/r4/bgpd.conf
new file mode 100644
index 0000000000..dc052da863
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r4/bgpd.conf
@@ -0,0 +1,24 @@
+!
+router bgp 65500
+ bgp router-id 192.0.2.4
+ neighbor 192.0.2.1 remote-as 65500
+ neighbor 192.0.2.1 ttl-security hops 10
+ neighbor 192.0.2.1 disable-connected-check
+ neighbor 192.0.2.1 update-source lo
+ neighbor 192.0.2.3 remote-as 65500
+ neighbor 192.0.2.3 update-source lo
+ !
+ address-family ipv4 unicast
+ network 192.0.2.4/32
+ neighbor 192.0.2.1 activate
+ no neighbor 192.0.2.3 activate
+ exit-address-family
+ !
+ address-family ipv4 labeled-unicast
+ neighbor 192.0.2.3 activate
+ neighbor 192.0.2.3 route-reflector-client
+ neighbor 192.0.2.3 next-hop-self force
+ exit-address-family
+ !
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r4/isisd.conf b/tests/topotests/zebra_fec_nexthop_resolution/r4/isisd.conf
new file mode 100644
index 0000000000..7096ce081e
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r4/isisd.conf
@@ -0,0 +1,31 @@
+!
+interface lo
+ ip router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+exit
+!
+interface r4-eth0
+ ip router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+exit
+!
+interface r4-eth1
+ ip router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+exit
+!
+router isis 1
+ is-type level-1
+ net 49.0000.0007.e901.4444.00
+ lsp-timers gen-interval 1 refresh-interval 900 max-lifetime 1200
+ mpls-te on
+ mpls-te router-address 192.0.2.4
+ segment-routing on
+ segment-routing global-block 11000 12000 local-block 37000 37999
+ segment-routing node-msd 8
+ segment-routing prefix 192.0.2.4/32 index 44
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r4/ospfd.conf b/tests/topotests/zebra_fec_nexthop_resolution/r4/ospfd.conf
new file mode 100644
index 0000000000..c160049675
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r4/ospfd.conf
@@ -0,0 +1,19 @@
+!
+interface lo
+ ip ospf area 0
+ ip ospf passive
+exit
+!
+interface r4-eth0
+ ip ospf area 0
+exit
+!
+router ospf
+ mpls-te on
+ mpls-te router-address 192.0.2.4
+ segment-routing on
+ segment-routing global-block 21000 29000 local-block 31000 31999
+ segment-routing node-msd 8
+ segment-routing prefix 192.0.2.4/32 index 44 no-php-flag
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r4/zebra.conf b/tests/topotests/zebra_fec_nexthop_resolution/r4/zebra.conf
new file mode 100644
index 0000000000..8591047906
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r4/zebra.conf
@@ -0,0 +1,16 @@
+!
+interface lo
+ ip address 192.0.2.4/32
+ mpls enable
+exit
+!
+interface r4-eth0
+ ip address 192.168.3.4/24
+ mpls enable
+exit
+!
+interface r4-eth1
+ ip address 192.168.4.4/24
+ mpls enable
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r5/bgpd.conf b/tests/topotests/zebra_fec_nexthop_resolution/r5/bgpd.conf
new file mode 100644
index 0000000000..1c73154e27
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r5/bgpd.conf
@@ -0,0 +1,23 @@
+router bgp 65500
+ bgp router-id 192.0.2.5
+ neighbor 192.0.2.3 remote-as 65500
+ neighbor 192.0.2.3 update-source lo
+ neighbor 192.0.2.7 remote-as 65500
+ neighbor 192.0.2.7 update-source lo
+ !
+ address-family ipv4 unicast
+ network 192.0.2.5/32
+ no neighbor 192.0.2.3 activate
+ no neighbor 192.0.2.7 activate
+ exit-address-family
+ !
+ address-family ipv4 labeled-unicast
+ neighbor 192.0.2.3 activate
+ neighbor 192.0.2.3 route-reflector-client
+ neighbor 192.0.2.3 next-hop-self force
+ neighbor 192.0.2.7 activate
+ neighbor 192.0.2.7 route-reflector-client
+ neighbor 192.0.2.7 next-hop-self force
+ exit-address-family
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r5/isisd.conf b/tests/topotests/zebra_fec_nexthop_resolution/r5/isisd.conf
new file mode 100644
index 0000000000..959d5be29b
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r5/isisd.conf
@@ -0,0 +1,26 @@
+!
+interface lo
+ ip router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+ isis passive
+exit
+!
+interface r5-eth0
+ ip router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+exit
+!
+router isis 1
+ is-type level-1
+ net 49.0000.0007.e901.5555.00
+ lsp-timers gen-interval 1 refresh-interval 900 max-lifetime 1200
+ mpls-te on
+ mpls-te router-address 192.0.2.5
+ segment-routing on
+ segment-routing global-block 11000 12000 local-block 33000 33999
+ segment-routing node-msd 8
+ segment-routing prefix 192.0.2.5/32 index 55
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r5/ospfd.conf.after b/tests/topotests/zebra_fec_nexthop_resolution/r5/ospfd.conf.after
new file mode 100644
index 0000000000..868129f890
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r5/ospfd.conf.after
@@ -0,0 +1,26 @@
+log stdout
+!
+interface lo
+ ip ospf network point-to-point
+ ip ospf passive
+exit
+!
+interface r5-eth1
+ ip ospf network point-to-point
+ ip ospf hello-interval 1
+exit
+!
+router ospf
+ ospf router-id 192.0.2.5
+ network 192.0.2.5/32 area 0.0.0.0
+ network 192.168.5.0/24 area 0.0.0.0
+ passive-interface lo
+ capability opaque
+ mpls-te on
+ mpls-te router-address 192.0.2.5
+ segment-routing on
+ segment-routing global-block 21000 22000 local-block 35000 35999
+ segment-routing node-msd 8
+ segment-routing prefix 192.0.2.5/32 index 55
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r5/zebra.conf b/tests/topotests/zebra_fec_nexthop_resolution/r5/zebra.conf
new file mode 100644
index 0000000000..dd519e8d12
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r5/zebra.conf
@@ -0,0 +1,19 @@
+!
+interface lo
+ ip address 192.0.2.5/32
+ mpls enable
+exit
+!
+interface r5-eth0
+ ip address 192.168.4.5/24
+ mpls enable
+exit
+!
+interface r5-eth1
+ ip address 192.168.5.5/24
+ mpls enable
+ link-params
+ enable
+ exit-link-params
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r6/ospfd.conf.after b/tests/topotests/zebra_fec_nexthop_resolution/r6/ospfd.conf.after
new file mode 100644
index 0000000000..60c4928f77
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r6/ospfd.conf.after
@@ -0,0 +1,32 @@
+log stdout
+!
+interface lo
+ ip ospf network point-to-point
+ ip ospf passive
+exit
+!
+interface r6-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 1
+exit
+!
+interface r6-eth1
+ ip ospf network point-to-point
+ ip ospf hello-interval 1
+exit
+!
+router ospf
+ ospf router-id 192.0.2.6
+ segment-routing on
+ segment-routing global-block 21000 22000 local-block 38000 38999
+ network 192.0.2.6/32 area 0.0.0.0
+ network 192.168.5.0/24 area 0.0.0.0
+ network 192.168.6.0/24 area 0.0.0.0
+ passive-interface lo
+ capability opaque
+ mpls-te on
+ mpls-te router-address 192.0.2.6
+ segment-routing node-msd 8
+ segment-routing prefix 192.0.2.6/32 index 66
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r6/zebra.conf b/tests/topotests/zebra_fec_nexthop_resolution/r6/zebra.conf
new file mode 100644
index 0000000000..5e16e3e434
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r6/zebra.conf
@@ -0,0 +1,22 @@
+!
+interface lo
+ ip address 192.0.2.6/32
+ mpls enable
+exit
+!
+interface r6-eth0
+ ip address 192.168.5.6/24
+ mpls enable
+ link-params
+ enable
+ exit-link-params
+exit
+!
+interface r6-eth1
+ ip address 192.168.6.6/24
+ mpls enable
+ link-params
+ enable
+ exit-link-params
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r7/bgpd.conf b/tests/topotests/zebra_fec_nexthop_resolution/r7/bgpd.conf
new file mode 100644
index 0000000000..eeda9d9cfa
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r7/bgpd.conf
@@ -0,0 +1,24 @@
+!
+router bgp 65500
+ bgp router-id 192.0.2.7
+ neighbor 192.0.2.1 remote-as 65500
+ neighbor 192.0.2.1 ttl-security hops 10
+ neighbor 192.0.2.1 disable-connected-check
+ neighbor 192.0.2.1 update-source lo
+ neighbor 192.0.2.5 remote-as 65500
+ neighbor 192.0.2.5 update-source lo
+ !
+ address-family ipv4 unicast
+ network 192.0.2.7/32
+ neighbor 192.0.2.1 activate
+ no neighbor 192.0.2.5 activate
+ exit-address-family
+ !
+ address-family ipv4 labeled-unicast
+ neighbor 192.0.2.5 activate
+ neighbor 192.0.2.5 route-reflector-client
+ neighbor 192.0.2.5 next-hop-self force
+ exit-address-family
+ !
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r7/ospfd.conf.after b/tests/topotests/zebra_fec_nexthop_resolution/r7/ospfd.conf.after
new file mode 100644
index 0000000000..f8e56e1217
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r7/ospfd.conf.after
@@ -0,0 +1,26 @@
+log stdout
+!
+interface lo
+ ip ospf network point-to-point
+ ip ospf passive
+exit
+!
+interface r7-eth0
+ ip ospf network point-to-point
+ ip ospf hello-interval 1
+exit
+!
+router ospf
+ ospf router-id 192.0.2.7
+ network 192.0.2.7/32 area 0.0.0.0
+ network 192.168.6.0/24 area 0.0.0.0
+ passive-interface lo
+ capability opaque
+ mpls-te on
+ mpls-te router-address 192.0.2.7
+ segment-routing on
+ segment-routing global-block 21000 22000 local-block 31000 31999
+ segment-routing node-msd 8
+ segment-routing prefix 192.0.2.7/32 index 77
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/r7/zebra.conf b/tests/topotests/zebra_fec_nexthop_resolution/r7/zebra.conf
new file mode 100644
index 0000000000..f520225476
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/r7/zebra.conf
@@ -0,0 +1,14 @@
+!
+interface lo
+ ip address 192.0.2.7/32
+ mpls enable
+exit
+!
+interface r7-eth0
+ ip address 192.168.6.7/24
+ mpls enable
+ link-params
+ enable
+ exit-link-params
+exit
+!
diff --git a/tests/topotests/zebra_fec_nexthop_resolution/test_zebra_fec_nexthop_resolution.py b/tests/topotests/zebra_fec_nexthop_resolution/test_zebra_fec_nexthop_resolution.py
new file mode 100644
index 0000000000..984ff3c185
--- /dev/null
+++ b/tests/topotests/zebra_fec_nexthop_resolution/test_zebra_fec_nexthop_resolution.py
@@ -0,0 +1,259 @@
+#!/usr/bin/env python
+
+#
+# Copyright 2022 6WIND S.A.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Check if fec nexthop resolution works correctly.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ """
+ r1 ---- r2 ---- r3 ---- r4 ----- r5 ---- r6 ---- r7
+ <--- ospf ----> <---- isis -----> <--- ospf ---->
+ """
+ for routern in range(1, 8):
+ tgen.add_router("r{}".format(routern))
+
+ switch1 = tgen.add_switch("s1")
+ switch1.add_link(tgen.gears["r1"])
+ switch1.add_link(tgen.gears["r2"])
+
+ switch2 = tgen.add_switch("s2")
+ switch2.add_link(tgen.gears["r2"])
+ switch2.add_link(tgen.gears["r3"])
+
+ switch3 = tgen.add_switch("s3")
+ switch3.add_link(tgen.gears["r3"])
+ switch3.add_link(tgen.gears["r4"])
+
+ switch4 = tgen.add_switch("s4")
+ switch4.add_link(tgen.gears["r4"])
+ switch4.add_link(tgen.gears["r5"])
+
+ switch5 = tgen.add_switch("s5")
+ switch5.add_link(tgen.gears["r5"])
+ switch5.add_link(tgen.gears["r6"])
+
+ switch6 = tgen.add_switch("s6")
+ switch6.add_link(tgen.gears["r6"])
+ switch6.add_link(tgen.gears["r7"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ def _enable_mpls_misc(router):
+ router.run("modprobe mpls_router")
+ router.run("echo 100000 > /proc/sys/net/mpls/platform_labels")
+ router.run("echo 1 > /proc/sys/net/mpls/conf/lo/input")
+
+ router = tgen.gears["r1"]
+ _enable_mpls_misc(router)
+
+ router = tgen.gears["r2"]
+ _enable_mpls_misc(router)
+
+ router = tgen.gears["r3"]
+ _enable_mpls_misc(router)
+
+ router = tgen.gears["r4"]
+ _enable_mpls_misc(router)
+
+ router = tgen.gears["r5"]
+ _enable_mpls_misc(router)
+
+ router = tgen.gears["r6"]
+ _enable_mpls_misc(router)
+
+ router = tgen.gears["r7"]
+ _enable_mpls_misc(router)
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ if rname in ("r1", "r3", "r5", "r7"):
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+ if rname in ("r3", "r4", "r5"):
+ router.load_config(
+ TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
+ )
+ if rname in ("r1", "r2", "r3", "r5", "r6", "r7"):
+ router.load_config(
+ TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+# There are some startup issued when initialising OSPF
+# To avoid those issues, load the ospf configuration after zebra started
+def test_zebra_fec_nexthop_resolution_finalise_ospf_config():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ topotest.sleep(2)
+
+ tgen.net["r1"].cmd("vtysh -f {}/r1/ospfd.conf.after".format(CWD))
+ tgen.net["r2"].cmd("vtysh -f {}/r2/ospfd.conf.after".format(CWD))
+ tgen.net["r3"].cmd("vtysh -f {}/r3/ospfd.conf.after".format(CWD))
+ tgen.net["r5"].cmd("vtysh -f {}/r5/ospfd.conf.after".format(CWD))
+ tgen.net["r6"].cmd("vtysh -f {}/r6/ospfd.conf.after".format(CWD))
+ tgen.net["r7"].cmd("vtysh -f {}/r7/ospfd.conf.after".format(CWD))
+
+
+def test_zebra_fec_nexthop_resolution_bgp():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _check_bgp_session():
+ r1 = tgen.gears["r1"]
+
+ tgen.gears["r3"].vtysh_cmd("config \n no mpls fec nexthop-resolution \n end")
+ tgen.gears["r3"].vtysh_cmd("config \n mpls fec nexthop-resolution \n end")
+ tgen.gears["r5"].vtysh_cmd("config \n no mpls fec nexthop-resolution \n end")
+ tgen.gears["r5"].vtysh_cmd("config \n mpls fec nexthop-resolution \n end")
+ output = json.loads(r1.vtysh_cmd("show bgp summary json"))
+
+ if output["ipv4Unicast"]["peers"]["192.0.2.7"]["state"] == "Established":
+ return None
+ return False
+
+ test_func1 = functools.partial(_check_bgp_session)
+ _, result1 = topotest.run_and_expect(test_func1, None, count=60, wait=0.5)
+ assert result1 is None, "Failed to verify the fec_nexthop_resolution: bgp session"
+
+
+def test_zebra_fec_nexthop_resolution_ping():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _check_ping_launch():
+ r1 = tgen.gears["r1"]
+
+ ping_launch = "ping 192.0.2.7 -I 192.0.2.1 -c 1"
+ selected_lines = r1.run(ping_launch).splitlines()[-2:-1]
+ rtx_stats = "".join(selected_lines[0].split(",")[0:3])
+ current = topotest.normalize_text(rtx_stats)
+
+ expected_stats = "1 packets transmitted 1 received 0% packet loss"
+ expected = topotest.normalize_text(expected_stats)
+
+ if current == expected:
+ return None
+
+ return False
+
+ test_func2 = functools.partial(_check_ping_launch)
+ _, result2 = topotest.run_and_expect(test_func2, None, count=60, wait=1)
+ assert result2 is None, "Failed to verify the fec_nexthop_resolution: ping"
+
+
+def test_zebra_fec_nexthop_resolution_table():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _zebra_check_mpls_table():
+ r3 = tgen.gears["r3"]
+ inLabel = 0
+ outLabels = 0
+
+ """
+ Retrieve inLabel from MPLS FEC table
+ """
+ mpls_fec = r3.vtysh_cmd("show mpls fec 192.0.2.7/32")
+ lines = mpls_fec.split("\n")
+ for line in lines:
+ if "Label" in line:
+ inLabel = line.split(": ", 1)[1]
+
+ """
+ Retrieve outLabel from BGP
+ """
+ output = json.loads(r3.vtysh_cmd("show ip route 192.0.2.7/32 json"))
+
+ outLabels = output["192.0.2.7/32"][0]["nexthops"][1]["labels"]
+
+ if (inLabel == 0) or (outLabels == 0):
+ return True
+
+ """
+ Compare expected data with real data
+ """
+ output = json.loads(r3.vtysh_cmd("show mpls table " + str(inLabel) + " json"))
+
+ expected = {
+ "inLabel": int(inLabel),
+ "installed": True,
+ "nexthops": [
+ {
+ "type": "BGP",
+ "outLabel": outLabels[0],
+ "outLabelStack": outLabels,
+ "distance": 20,
+ "installed": True,
+ "nexthop": "192.168.3.4",
+ }
+ ],
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func3 = functools.partial(_zebra_check_mpls_table)
+ _, result3 = topotest.run_and_expect(test_func3, None, count=60, wait=0.5)
+ assert result3 is None, "Failed to verify the fec_nexthop_resolution: mpls table"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/yang/frr-zebra.yang b/yang/frr-zebra.yang
index 1c7d1c8ef4..f97a4cc129 100644
--- a/yang/frr-zebra.yang
+++ b/yang/frr-zebra.yang
@@ -2856,6 +2856,16 @@ module frr-zebra {
}
}
+ container mpls {
+ description
+ "MPLS Configuration.";
+ leaf fec-nexthop-resolution {
+ type boolean;
+ description
+ "Authorise nexthop resolution over all labeled routes.";
+ }
+ }
+
uses ribs;
uses vrf-vni-mapping;
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index eb968bcd37..1d2f9e695f 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -1678,6 +1678,25 @@ static int fpm_nl_process(struct zebra_dplane_provider *prov)
fnc = dplane_provider_get_data(prov);
limit = dplane_provider_get_work_limit(prov);
+
+ frr_with_mutex (&fnc->ctxqueue_mutex) {
+ cur_queue = dplane_ctx_queue_count(&fnc->ctxqueue);
+ }
+
+ if (cur_queue >= (uint64_t)limit) {
+ if (IS_ZEBRA_DEBUG_FPM)
+ zlog_debug("%s: Already at a limit(%" PRIu64
+ ") of internal work, hold off",
+ __func__, cur_queue);
+ limit = 0;
+ } else if (cur_queue != 0) {
+ if (IS_ZEBRA_DEBUG_FPM)
+ zlog_debug("%s: current queue is %" PRIu64
+ ", limiting to lesser amount of %" PRIu64,
+ __func__, cur_queue, limit - cur_queue);
+ limit -= cur_queue;
+ }
+
for (counter = 0; counter < limit; counter++) {
ctx = dplane_provider_dequeue_in_ctx(prov);
if (ctx == NULL)
diff --git a/zebra/rib.h b/zebra/rib.h
index cd6efbfb36..4293b5f240 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -108,8 +108,8 @@ struct route_entry {
uint32_t nexthop_mtu;
/* Flags of this route.
- * This flag's definition is in lib/zebra.h ZEBRA_FLAG_* and is exposed
- * to clients via Zserv
+ * This flag's definition is in lib/zclient.h ZEBRA_FLAG_* and is
+ * exposed to clients via Zserv
*/
uint32_t flags;
@@ -631,6 +631,7 @@ extern int rib_add_gr_run(afi_t afi, vrf_id_t vrf_id, uint8_t proto,
uint8_t instance, time_t restart_time);
extern void zebra_vty_init(void);
+extern uint32_t zebra_rib_dplane_results_count(void);
extern pid_t pid;
diff --git a/zebra/zebra_cli.c b/zebra/zebra_cli.c
index 3e03d74775..6ee0fdbb8d 100644
--- a/zebra/zebra_cli.c
+++ b/zebra/zebra_cli.c
@@ -2221,6 +2221,37 @@ static void lib_vrf_zebra_ipv6_resolve_via_default_cli_write(
}
}
+DEFPY_YANG (mpls_fec_nexthop_resolution, mpls_fec_nexthop_resolution_cmd,
+ "[no$no] mpls fec nexthop-resolution",
+ NO_STR
+ MPLS_STR
+ "MPLS FEC table\n"
+ "Authorise nexthop resolution over all labeled routes.\n")
+{
+ nb_cli_enqueue_change(vty,
+ "./frr-zebra:zebra/mpls/fec-nexthop-resolution",
+ NB_OP_MODIFY, no ? "false" : "true");
+
+ if (vty->node == CONFIG_NODE)
+ return nb_cli_apply_changes(vty, "/frr-vrf:lib/vrf[name='%s']",
+ VRF_DEFAULT_NAME);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static void lib_vrf_mpls_fec_nexthop_resolution_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ bool fec_nexthop_resolution = yang_dnode_get_bool(dnode, NULL);
+
+ if (fec_nexthop_resolution || show_defaults) {
+ zebra_vrf_indent_cli_write(vty, dnode);
+
+ vty_out(vty, "%smpls fec nexthop-resolution\n",
+ fec_nexthop_resolution ? "" : "no ");
+ }
+}
+
DEFPY_YANG (vrf_netns,
vrf_netns_cmd,
"[no] netns ![NAME$netns_name]",
@@ -2852,6 +2883,10 @@ const struct frr_yang_module_info frr_zebra_cli_info = {
.cbs.cli_show = lib_vrf_zebra_netns_table_range_cli_write,
},
{
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/mpls/fec-nexthop-resolution",
+ .cbs.cli_show = lib_vrf_mpls_fec_nexthop_resolution_cli_write,
+ },
+ {
.xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id",
.cbs.cli_show = lib_vrf_zebra_l3vni_id_cli_write,
},
@@ -2957,6 +2992,9 @@ void zebra_cli_init(void)
install_element(VRF_NODE, &ip_nht_default_route_cmd);
install_element(VRF_NODE, &ipv6_nht_default_route_cmd);
+ install_element(CONFIG_NODE, &mpls_fec_nexthop_resolution_cmd);
+ install_element(VRF_NODE, &mpls_fec_nexthop_resolution_cmd);
+
install_element(CONFIG_NODE, &vni_mapping_cmd);
install_element(VRF_NODE, &vni_mapping_cmd);
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 0851666510..75147e7136 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -483,10 +483,8 @@ struct zebra_dplane_provider {
int (*dp_fini)(struct zebra_dplane_provider *prov, bool early_p);
_Atomic uint32_t dp_in_counter;
- _Atomic uint32_t dp_in_queued;
_Atomic uint32_t dp_in_max;
_Atomic uint32_t dp_out_counter;
- _Atomic uint32_t dp_out_queued;
_Atomic uint32_t dp_out_max;
_Atomic uint32_t dp_error_counter;
@@ -6129,35 +6127,45 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed)
struct zebra_dplane_provider *prov;
uint64_t in, in_q, in_max, out, out_q, out_max;
- vty_out(vty, "Zebra dataplane providers:\n");
-
DPLANE_LOCK();
prov = dplane_prov_list_first(&zdplane_info.dg_providers);
+ in = dplane_ctx_queue_count(&zdplane_info.dg_update_list);
DPLANE_UNLOCK();
+ vty_out(vty, "dataplane Incoming Queue from Zebra: %" PRIu64 "\n", in);
+ vty_out(vty, "Zebra dataplane providers:\n");
+
/* Show counters, useful info from each registered provider */
while (prov) {
+ dplane_provider_lock(prov);
+ in_q = dplane_ctx_queue_count(&prov->dp_ctx_in_list);
+ out_q = dplane_ctx_queue_count(&prov->dp_ctx_out_list);
+ dplane_provider_unlock(prov);
in = atomic_load_explicit(&prov->dp_in_counter,
memory_order_relaxed);
- in_q = atomic_load_explicit(&prov->dp_in_queued,
- memory_order_relaxed);
+
in_max = atomic_load_explicit(&prov->dp_in_max,
memory_order_relaxed);
out = atomic_load_explicit(&prov->dp_out_counter,
memory_order_relaxed);
- out_q = atomic_load_explicit(&prov->dp_out_queued,
- memory_order_relaxed);
+
out_max = atomic_load_explicit(&prov->dp_out_max,
memory_order_relaxed);
- vty_out(vty, "%s (%u): in: %"PRIu64", q: %"PRIu64", q_max: %"PRIu64", out: %"PRIu64", q: %"PRIu64", q_max: %"PRIu64"\n",
- prov->dp_name, prov->dp_id, in, in_q, in_max,
- out, out_q, out_max);
+ vty_out(vty,
+ " %s (%u): in: %" PRIu64 ", q: %" PRIu64
+ ", q_max: %" PRIu64 ", out: %" PRIu64 ", q: %" PRIu64
+ ", q_max: %" PRIu64 "\n",
+ prov->dp_name, prov->dp_id, in, in_q, in_max, out,
+ out_q, out_max);
prov = dplane_prov_list_next(&zdplane_info.dg_providers, prov);
}
+ out = zebra_rib_dplane_results_count();
+ vty_out(vty, "dataplane Outgoing Queue to Zebra: %" PRIu64 "\n", out);
+
return CMD_SUCCESS;
}
@@ -6299,10 +6307,6 @@ struct zebra_dplane_ctx *dplane_provider_dequeue_in_ctx(
dplane_provider_lock(prov);
ctx = dplane_ctx_list_pop(&(prov->dp_ctx_in_list));
- if (ctx) {
- atomic_fetch_sub_explicit(&prov->dp_in_queued, 1,
- memory_order_relaxed);
- }
dplane_provider_unlock(prov);
@@ -6330,10 +6334,6 @@ int dplane_provider_dequeue_in_list(struct zebra_dplane_provider *prov,
break;
}
- if (ret > 0)
- atomic_fetch_sub_explicit(&prov->dp_in_queued, ret,
- memory_order_relaxed);
-
dplane_provider_unlock(prov);
return ret;
@@ -6358,10 +6358,7 @@ void dplane_provider_enqueue_out_ctx(struct zebra_dplane_provider *prov,
dplane_ctx_list_add_tail(&(prov->dp_ctx_out_list), ctx);
/* Maintain out-queue counters */
- atomic_fetch_add_explicit(&(prov->dp_out_queued), 1,
- memory_order_relaxed);
- curr = atomic_load_explicit(&prov->dp_out_queued,
- memory_order_relaxed);
+ curr = dplane_ctx_queue_count(&prov->dp_ctx_out_list);
high = atomic_load_explicit(&prov->dp_out_max,
memory_order_relaxed);
if (curr > high)
@@ -6383,9 +6380,6 @@ dplane_provider_dequeue_out_ctx(struct zebra_dplane_provider *prov)
if (!ctx)
return NULL;
- atomic_fetch_sub_explicit(&(prov->dp_out_queued), 1,
- memory_order_relaxed);
-
return ctx;
}
@@ -7331,10 +7325,10 @@ static void dplane_thread_loop(struct event *event)
{
struct dplane_ctx_list_head work_list;
struct dplane_ctx_list_head error_list;
- struct zebra_dplane_provider *prov;
+ struct zebra_dplane_provider *prov, *next_prov;
struct zebra_dplane_ctx *ctx;
int limit, counter, error_counter;
- uint64_t curr, high;
+ uint64_t curr, out_curr, high;
bool reschedule = false;
/* Capture work limit per cycle */
@@ -7358,18 +7352,48 @@ static void dplane_thread_loop(struct event *event)
/* Locate initial registered provider */
prov = dplane_prov_list_first(&zdplane_info.dg_providers);
- /* Move new work from incoming list to temp list */
- for (counter = 0; counter < limit; counter++) {
- ctx = dplane_ctx_list_pop(&zdplane_info.dg_update_list);
- if (ctx) {
- ctx->zd_provider = prov->dp_id;
+ curr = dplane_ctx_queue_count(&prov->dp_ctx_in_list);
+ out_curr = dplane_ctx_queue_count(&prov->dp_ctx_out_list);
- dplane_ctx_list_add_tail(&work_list, ctx);
- } else {
- break;
+ if (curr >= (uint64_t)limit) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("%s: Current first provider(%s) Input queue is %" PRIu64
+ ", holding off work",
+ __func__, prov->dp_name, curr);
+ counter = 0;
+ } else if (out_curr >= (uint64_t)limit) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("%s: Current first provider(%s) Output queue is %" PRIu64
+ ", holding off work",
+ __func__, prov->dp_name, out_curr);
+ counter = 0;
+ } else {
+ int tlimit;
+ /*
+ * Let's limit the work to how what can be put on the
+ * in or out queue without going over
+ */
+ tlimit = limit - MAX(curr, out_curr);
+ /* Move new work from incoming list to temp list */
+ for (counter = 0; counter < tlimit; counter++) {
+ ctx = dplane_ctx_list_pop(&zdplane_info.dg_update_list);
+ if (ctx) {
+ ctx->zd_provider = prov->dp_id;
+
+ dplane_ctx_list_add_tail(&work_list, ctx);
+ } else {
+ break;
+ }
}
}
+ /*
+ * If there is anything still on the two input queues reschedule
+ */
+ if (dplane_ctx_queue_count(&prov->dp_ctx_in_list) > 0 ||
+ dplane_ctx_queue_count(&zdplane_info.dg_update_list) > 0)
+ reschedule = true;
+
DPLANE_UNLOCK();
atomic_fetch_sub_explicit(&zdplane_info.dg_routes_queued, counter,
@@ -7388,8 +7412,9 @@ static void dplane_thread_loop(struct event *event)
* items.
*/
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
- zlog_debug("dplane enqueues %d new work to provider '%s'",
- counter, dplane_provider_get_name(prov));
+ zlog_debug("dplane enqueues %d new work to provider '%s' curr is %" PRIu64,
+ counter, dplane_provider_get_name(prov),
+ curr);
/* Capture current provider id in each context; check for
* error status.
@@ -7422,10 +7447,7 @@ static void dplane_thread_loop(struct event *event)
atomic_fetch_add_explicit(&prov->dp_in_counter, counter,
memory_order_relaxed);
- atomic_fetch_add_explicit(&prov->dp_in_queued, counter,
- memory_order_relaxed);
- curr = atomic_load_explicit(&prov->dp_in_queued,
- memory_order_relaxed);
+ curr = dplane_ctx_queue_count(&prov->dp_ctx_in_list);
high = atomic_load_explicit(&prov->dp_in_max,
memory_order_relaxed);
if (curr > high)
@@ -7450,18 +7472,61 @@ static void dplane_thread_loop(struct event *event)
if (!zdplane_info.dg_run)
break;
+ /* Locate next provider */
+ next_prov = dplane_prov_list_next(&zdplane_info.dg_providers,
+ prov);
+ if (next_prov) {
+ curr = dplane_ctx_queue_count(
+ &next_prov->dp_ctx_in_list);
+ out_curr = dplane_ctx_queue_count(
+ &next_prov->dp_ctx_out_list);
+ } else
+ out_curr = curr = 0;
+
/* Dequeue completed work from the provider */
dplane_provider_lock(prov);
- while (counter < limit) {
- ctx = dplane_provider_dequeue_out_ctx(prov);
- if (ctx) {
- dplane_ctx_list_add_tail(&work_list, ctx);
- counter++;
- } else
- break;
+ if (curr >= (uint64_t)limit) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("%s: Next Provider(%s) Input queue is %" PRIu64
+ ", holding off work",
+ __func__, next_prov->dp_name, curr);
+ counter = 0;
+ } else if (out_curr >= (uint64_t)limit) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("%s: Next Provider(%s) Output queue is %" PRIu64
+ ", holding off work",
+ __func__, next_prov->dp_name,
+ out_curr);
+ counter = 0;
+ } else {
+ int tlimit;
+
+ /*
+ * Let's limit the work to how what can be put on the
+ * in or out queue without going over
+ */
+ tlimit = limit - MAX(curr, out_curr);
+ while (counter < tlimit) {
+ ctx = dplane_provider_dequeue_out_ctx(prov);
+ if (ctx) {
+ dplane_ctx_list_add_tail(&work_list,
+ ctx);
+ counter++;
+ } else
+ break;
+ }
}
+ /*
+ * Let's check if there are still any items on the
+ * input or output queus of the current provider
+ * if so then we know we need to reschedule.
+ */
+ if (dplane_ctx_queue_count(&prov->dp_ctx_in_list) > 0 ||
+ dplane_ctx_queue_count(&prov->dp_ctx_out_list) > 0)
+ reschedule = true;
+
dplane_provider_unlock(prov);
if (counter >= limit)
@@ -7477,7 +7542,7 @@ static void dplane_thread_loop(struct event *event)
}
/* Locate next provider */
- prov = dplane_prov_list_next(&zdplane_info.dg_providers, prov);
+ prov = next_prov;
}
/*
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 086150fb04..9549af5f14 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -37,6 +37,7 @@
DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object");
DEFINE_MTYPE_STATIC(ZEBRA, FEC, "MPLS FEC object");
DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object");
+DEFINE_MTYPE_STATIC(ZEBRA, NH_LABEL, "Nexthop label");
bool mpls_enabled;
bool mpls_pw_reach_strict; /* Strict reachability checking */
@@ -50,7 +51,7 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
struct route_node *rn, struct route_entry *re);
static int lsp_uninstall(struct zebra_vrf *zvrf, mpls_label_t label);
static int fec_change_update_lsp(struct zebra_vrf *zvrf, struct zebra_fec *fec,
- mpls_label_t old_label);
+ mpls_label_t old_label, bool uninstall);
static int fec_send(struct zebra_fec *fec, struct zserv *client);
static void fec_update_clients(struct zebra_fec *fec);
static void fec_print(struct zebra_fec *fec, struct vty *vty);
@@ -161,12 +162,14 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
enum lsp_types_t lsp_type;
char buf[BUFSIZ];
int added, changed;
+ bool zvrf_nexthop_resolution;
/* Lookup table. */
lsp_table = zvrf->lsp_table;
if (!lsp_table)
return -1;
+ zvrf_nexthop_resolution = zvrf->zebra_mpls_fec_nexthop_resolution;
lsp_type = lsp_type_from_re_type(re->type);
added = changed = 0;
@@ -180,13 +183,20 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
* the label advertised by the recursive nexthop (plus we don't have the
* logic yet to push multiple labels).
*/
- for (nexthop = re->nhe->nhg.nexthop;
- nexthop; nexthop = nexthop->next) {
- /* Skip inactive and recursive entries. */
- if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ nexthop = re->nhe->nhg.nexthop;
+ while (nexthop) {
+ if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) {
+ nexthop =
+ nexthop_next_resolution(nexthop,
+ zvrf_nexthop_resolution);
continue;
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ }
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) {
+ nexthop =
+ nexthop_next_resolution(nexthop,
+ zvrf_nexthop_resolution);
continue;
+ }
nhlfe = nhlfe_find(&lsp->nhlfe_list, lsp_type,
nexthop->type, &nexthop->gate,
@@ -194,9 +204,13 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
if (nhlfe) {
/* Clear deleted flag (in case it was set) */
UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED);
- if (nexthop_labels_match(nhlfe->nexthop, nexthop))
+ if (nexthop_labels_match(nhlfe->nexthop, nexthop)) {
/* No change */
+ nexthop =
+ nexthop_next_resolution(nexthop,
+ zvrf_nexthop_resolution);
continue;
+ }
if (IS_ZEBRA_DEBUG_MPLS) {
@@ -221,11 +235,18 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
return -1;
if (IS_ZEBRA_DEBUG_MPLS) {
+ char label_str[MPLS_LABEL_STRLEN];
+
nhlfe2str(nhlfe, buf, BUFSIZ);
- zlog_debug(
- "Add LSP in-label %u type %d nexthop %s out-label %u",
- lsp->ile.in_label, lsp_type, buf,
- nexthop->nh_label->label[0]);
+ zlog_debug("Add LSP in-label %u type %d nexthop %s out-label %s",
+ lsp->ile.in_label, lsp_type, buf,
+ mpls_label2str(nexthop->nh_label
+ ->num_labels,
+ nexthop->nh_label->label,
+ label_str,
+ sizeof(label_str),
+ nexthop->nh_label_type,
+ 0));
}
lsp->addr_family = NHLFE_FAMILY(nhlfe);
@@ -234,6 +255,8 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED);
added++;
}
+ nexthop = nexthop_next_resolution(nexthop,
+ zvrf_nexthop_resolution);
}
/* Queue LSP for processing if necessary. If no NHLFE got added (special
@@ -245,6 +268,8 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
return -1;
} else {
lsp_check_free(lsp_table, &lsp);
+ /* failed to install a new LSP */
+ return -1;
}
return 0;
@@ -353,7 +378,7 @@ static void fec_evaluate(struct zebra_vrf *zvrf)
fec_update_clients(fec);
/* Update label forwarding entries appropriately */
- fec_change_update_lsp(zvrf, fec, old_label);
+ fec_change_update_lsp(zvrf, fec, old_label, false);
}
}
}
@@ -384,7 +409,7 @@ static uint32_t fec_derive_label_from_index(struct zebra_vrf *zvrf,
* entries, as appropriate.
*/
static int fec_change_update_lsp(struct zebra_vrf *zvrf, struct zebra_fec *fec,
- mpls_label_t old_label)
+ mpls_label_t old_label, bool uninstall)
{
struct route_table *table;
struct route_node *rn;
@@ -416,11 +441,17 @@ static int fec_change_update_lsp(struct zebra_vrf *zvrf, struct zebra_fec *fec,
break;
}
- if (!re || !zebra_rib_labeled_unicast(re))
+ if (!re || !zebra_rib_labeled_unicast(re)) {
+ if (uninstall)
+ lsp_uninstall(zvrf, fec->label);
return 0;
+ }
- if (lsp_install(zvrf, fec->label, rn, re))
+ if (lsp_install(zvrf, fec->label, rn, re)) {
+ if (uninstall)
+ lsp_uninstall(zvrf, fec->label);
return -1;
+ }
return 0;
}
@@ -448,6 +479,30 @@ static int fec_send(struct zebra_fec *fec, struct zserv *client)
}
/*
+ * Upon reconfiguring nexthop-resolution updates, update the
+ * lsp entries accordingly.
+ */
+void zebra_mpls_fec_nexthop_resolution_update(struct zebra_vrf *zvrf)
+{
+ int af;
+ struct route_node *rn;
+ struct zebra_fec *fec;
+
+ for (af = AFI_IP; af < AFI_MAX; af++) {
+ if (zvrf->fec_table[af] == NULL)
+ continue;
+ for (rn = route_top(zvrf->fec_table[af]); rn;
+ rn = route_next(rn)) {
+ if (!rn->info)
+ continue;
+ fec = rn->info;
+ fec_change_update_lsp(zvrf, fec, MPLS_INVALID_LABEL,
+ true);
+ }
+ }
+}
+
+/*
* Update all registered clients about this FEC. Caller should've updated
* FEC and ensure no duplicate updates.
*/
@@ -1398,7 +1453,31 @@ static int nhlfe_del(struct zebra_nhlfe *nhlfe)
static void nhlfe_out_label_update(struct zebra_nhlfe *nhlfe,
struct mpls_label_stack *nh_label)
{
- nhlfe->nexthop->nh_label->label[0] = nh_label->label[0];
+ struct mpls_label_stack *nh_label_tmp;
+ int i;
+
+ /* Enforce limit on label stack size */
+ if (nh_label->num_labels > MPLS_MAX_LABELS)
+ nh_label->num_labels = MPLS_MAX_LABELS;
+
+ /* Resize the array to accommodate the new label stack */
+ if (nh_label->num_labels > nhlfe->nexthop->nh_label->num_labels) {
+ nh_label_tmp = XREALLOC(MTYPE_NH_LABEL, nhlfe->nexthop->nh_label,
+ sizeof(struct mpls_label_stack) +
+ nh_label->num_labels *
+ sizeof(mpls_label_t));
+ if (nh_label_tmp) {
+ nhlfe->nexthop->nh_label = nh_label_tmp;
+ nhlfe->nexthop->nh_label->num_labels =
+ nh_label->num_labels;
+ } else
+ nh_label->num_labels =
+ nhlfe->nexthop->nh_label->num_labels;
+ }
+
+ /* Copy the label stack into the array */
+ for (i = 0; i < nh_label->num_labels; i++)
+ nhlfe->nexthop->nh_label->label[i] = nh_label->label[i];
}
static int mpls_lsp_uninstall_all(struct hash *lsp_table, struct zebra_lsp *lsp,
@@ -2117,7 +2196,7 @@ void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx)
/*
* Install dynamic LSP entry.
*/
-int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn,
+void zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn,
struct route_entry *re)
{
struct route_table *table;
@@ -2125,23 +2204,20 @@ int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn,
table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))];
if (!table)
- return -1;
+ return;
/* See if there is a configured label binding for this FEC. */
fec = fec_find(table, &rn->p);
if (!fec || fec->label == MPLS_INVALID_LABEL)
- return 0;
+ return;
/* We cannot install a label forwarding entry if local label is the
* implicit-null label.
*/
if (fec->label == MPLS_LABEL_IMPLICIT_NULL)
- return 0;
-
- if (lsp_install(zvrf, fec->label, rn, re))
- return -1;
+ return;
- return 0;
+ lsp_install(zvrf, fec->label, rn, re);
}
/*
@@ -2345,7 +2421,7 @@ int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p,
}
if (new_client || label_change)
- return fec_change_update_lsp(zvrf, fec, old_label);
+ return fec_change_update_lsp(zvrf, fec, old_label, false);
return 0;
}
@@ -2386,7 +2462,7 @@ int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p,
list_isempty(fec->client_list)) {
mpls_label_t old_label = fec->label;
fec->label = MPLS_INVALID_LABEL; /* reset */
- fec_change_update_lsp(zvrf, fec, old_label);
+ fec_change_update_lsp(zvrf, fec, old_label, false);
fec_del(fec);
}
@@ -2556,7 +2632,7 @@ int zebra_mpls_static_fec_add(struct zebra_vrf *zvrf, struct prefix *p,
fec_update_clients(fec);
/* Update label forwarding entries appropriately */
- ret = fec_change_update_lsp(zvrf, fec, old_label);
+ ret = fec_change_update_lsp(zvrf, fec, old_label, false);
}
return ret;
@@ -2609,7 +2685,7 @@ int zebra_mpls_static_fec_del(struct zebra_vrf *zvrf, struct prefix *p)
fec_update_clients(fec);
/* Update label forwarding entries appropriately */
- return fec_change_update_lsp(zvrf, fec, old_label);
+ return fec_change_update_lsp(zvrf, fec, old_label, false);
}
/*
diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h
index dd6f960146..27f5bdbc46 100644
--- a/zebra/zebra_mpls.h
+++ b/zebra/zebra_mpls.h
@@ -146,7 +146,7 @@ int zebra_mpls_write_label_block_config(struct vty *vty, struct zebra_vrf *vrf);
/*
* Install dynamic LSP entry.
*/
-int zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn,
+void zebra_mpls_lsp_install(struct zebra_vrf *zvrf, struct route_node *rn,
struct route_entry *re);
/*
@@ -257,6 +257,12 @@ void zebra_mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
const struct zapi_labels *zl);
/*
+ * Upon reconfiguring nexthop-resolution updates, update the
+ * lsp entries accordingly.
+ */
+void zebra_mpls_fec_nexthop_resolution_update(struct zebra_vrf *zvrf);
+
+/*
* Uninstall all NHLFEs bound to a single FEC.
*
* mpls_ftn_uninstall -> Called to enqueue into early label processing
diff --git a/zebra/zebra_nb.c b/zebra/zebra_nb.c
index eee9323082..0a7ed5db41 100644
--- a/zebra/zebra_nb.c
+++ b/zebra/zebra_nb.c
@@ -884,6 +884,13 @@ const struct frr_yang_module_info frr_zebra_info = {
}
},
{
+ .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/mpls/fec-nexthop-resolution",
+ .cbs = {
+ .modify = lib_vrf_zebra_mpls_fec_nexthop_resolution_modify,
+ .destroy = lib_vrf_zebra_mpls_fec_nexthop_resolution_destroy,
+ }
+ },
+ {
.xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib",
.cbs = {
.get_next = lib_vrf_zebra_ribs_rib_get_next,
diff --git a/zebra/zebra_nb.h b/zebra/zebra_nb.h
index b40ed68229..785291bc68 100644
--- a/zebra/zebra_nb.h
+++ b/zebra/zebra_nb.h
@@ -309,6 +309,10 @@ int lib_vrf_zebra_netns_table_range_create(struct nb_cb_create_args *args);
int lib_vrf_zebra_netns_table_range_destroy(struct nb_cb_destroy_args *args);
int lib_vrf_zebra_netns_table_range_start_modify(struct nb_cb_modify_args *args);
int lib_vrf_zebra_netns_table_range_end_modify(struct nb_cb_modify_args *args);
+int lib_vrf_zebra_mpls_fec_nexthop_resolution_modify(
+ struct nb_cb_modify_args *args);
+int lib_vrf_zebra_mpls_fec_nexthop_resolution_destroy(
+ struct nb_cb_destroy_args *args);
const void *lib_vrf_zebra_ribs_rib_get_next(struct nb_cb_get_next_args *args);
int lib_vrf_zebra_ribs_rib_get_keys(struct nb_cb_get_keys_args *args);
const void *
diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c
index ae6232a1bb..09c0091ec6 100644
--- a/zebra/zebra_nb_config.c
+++ b/zebra/zebra_nb_config.c
@@ -3781,6 +3781,59 @@ int lib_vrf_zebra_netns_table_range_end_modify(struct nb_cb_modify_args *args)
}
/*
+ * XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/mpls/fec-nexthop-resolution
+ */
+int lib_vrf_zebra_mpls_fec_nexthop_resolution_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct vrf *vrf;
+ struct zebra_vrf *zvrf;
+ bool fec_nexthop_resolution;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+ zvrf = vrf->info;
+
+ fec_nexthop_resolution = yang_dnode_get_bool(args->dnode, NULL);
+
+ if (zvrf->zebra_mpls_fec_nexthop_resolution == fec_nexthop_resolution)
+ return NB_OK;
+
+ zvrf->zebra_mpls_fec_nexthop_resolution = fec_nexthop_resolution;
+
+ zebra_mpls_fec_nexthop_resolution_update(zvrf);
+
+ return NB_OK;
+}
+
+int lib_vrf_zebra_mpls_fec_nexthop_resolution_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct vrf *vrf;
+ struct zebra_vrf *zvrf;
+ bool fec_nexthop_resolution;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ vrf = nb_running_get_entry(args->dnode, NULL, true);
+ zvrf = vrf->info;
+
+ fec_nexthop_resolution = DFLT_ZEBRA_IP_NHT_RESOLVE_VIA_DEFAULT;
+
+ if (zvrf->zebra_mpls_fec_nexthop_resolution == fec_nexthop_resolution)
+ return NB_OK;
+
+ zvrf->zebra_mpls_fec_nexthop_resolution = fec_nexthop_resolution;
+
+ zebra_mpls_fec_nexthop_resolution_update(zvrf);
+
+ return NB_OK;
+}
+
+/*
* XPath: /frr-vrf:lib/vrf/frr-zebra:zebra/l3vni-id
*/
int lib_vrf_zebra_l3vni_id_modify(struct nb_cb_modify_args *args)
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index d53b27a387..8bec32b85d 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -651,8 +651,10 @@ struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p, vrf_id_t vrf_id)
int zebra_rib_labeled_unicast(struct route_entry *re)
{
struct nexthop *nexthop = NULL;
+ struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
- if (re->type != ZEBRA_ROUTE_BGP)
+ if ((re->type != ZEBRA_ROUTE_BGP) &&
+ !zvrf->zebra_mpls_fec_nexthop_resolution)
return 0;
for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
@@ -5108,6 +5110,17 @@ static int rib_dplane_results(struct dplane_ctx_list_head *ctxlist)
return 0;
}
+uint32_t zebra_rib_dplane_results_count(void)
+{
+ uint32_t count;
+
+ frr_with_mutex (&dplane_mutex) {
+ count = dplane_ctx_queue_count(&rib_dplane_q);
+ }
+
+ return count;
+}
+
/*
* Ensure there are no empty slots in the route_info array.
* Every route type in zebra should be present there.
diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h
index 5cbfab1ddc..f97138c811 100644
--- a/zebra/zebra_vrf.h
+++ b/zebra/zebra_vrf.h
@@ -173,6 +173,7 @@ struct zebra_vrf {
bool zebra_rnh_ip_default_route;
bool zebra_rnh_ipv6_default_route;
+ bool zebra_mpls_fec_nexthop_resolution;
};
#define PROTO_RM_NAME(zvrf, afi, rtype) zvrf->proto_rm[afi][rtype].name
#define NHT_RM_NAME(zvrf, afi, rtype) zvrf->nht_rm[afi][rtype].name