diff options
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, ¬e, 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 |
