diff options
40 files changed, 1375 insertions, 98 deletions
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 14ff5f2e11..af6068cb1f 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -53,14 +53,23 @@ static void bfd_session_status_update(struct bfd_session_params *bsp, peer->host); return; } - peer->last_reset = PEER_DOWN_BFD_DOWN; - /* rfc9384 */ - if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) - bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, - BGP_NOTIFY_CEASE_BFD_DOWN); - - BGP_EVENT_ADD(peer->connection, BGP_Stop); + /* Once the BFD session is UP, and later BGP session is UP, + * BFD notices that peer->su_local changed, and BFD session goes down. + * We should trigger BGP session reset if BFD session is UP + * only when BGP session is UP already. + * Otherwise, we end up resetting BGP session when BFD session is UP, + * when the source address is changed, e.g. 0.0.0.0 -> 10.0.0.1. + */ + if (bss->last_event > peer->uptime) { + peer->last_reset = PEER_DOWN_BFD_DOWN; + /* rfc9384 */ + if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->connection->status)) + bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, + BGP_NOTIFY_CEASE_BFD_DOWN); + + BGP_EVENT_ADD(peer->connection, BGP_Stop); + } } if (bss->state == BSS_UP && bss->previous_state != BSS_UP && diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index df32d75103..065f4fef37 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -361,16 +361,22 @@ static void ecommunity_color_str(char *buf, size_t bufsz, uint8_t *ptr) { /* * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x03 | Sub-Type(0x0b) | Flags | + * | 0x03 | Sub-Type(0x0b) | CO| Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Color Value | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * https://datatracker.ietf.org/doc/rfc9256/, Section 8.8.1 + * The CO bits can have 4 different values: 00 01 10 11 */ uint32_t colorid; + uint8_t color_type; + /* get the color type */ + ptr++; + color_type = (*ptr) >> 6; - memcpy(&colorid, ptr + 3, 4); + memcpy(&colorid, ptr + 2, 4); colorid = ntohl(colorid); - snprintf(buf, bufsz, "Color:%d", colorid); + snprintf(buf, bufsz, "Color:%d%d:%d", (color_type & 0x2) >> 1, color_type & 0x1, colorid); } /* Initialize Extended Comminities related hash. */ @@ -531,7 +537,7 @@ static int ecommunity_encode_internal(uint8_t type, uint8_t sub_type, eval6->val[19] = val & 0xff; } else if (type == ECOMMUNITY_ENCODE_OPAQUE && sub_type == ECOMMUNITY_COLOR) { - encode_color(val, eval); + encode_color(val, as, eval); } else { encode_route_target_as4(as, val, eval, trans); } @@ -739,6 +745,13 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr, */ if (!asn_str2asn(buf, &as)) goto error; + } else if (type == ECOMMUNITY_COLOR) { + /* If extcommunity is color, only support 00/01/10/11, max value is 3 */ + /* color value */ + as = strtoul(buf, &endptr, 2); + if (*endptr != '\0' || as > 3) + goto error; + val_color = 0; } else { /* Parsing A AS number in A:MN */ errno = 0; @@ -753,6 +766,8 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr, if (*endptr != '\0' || tmp_as > BGP_AS4_MAX || errno) goto error; + if (*token == ecommunity_token_color && as > 3) + goto error; as = (as_t)tmp_as; } } else if (*p == '.') { @@ -791,13 +806,15 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr, /* Encode result into extended community for AS format or color. */ if (as > BGP_AS_MAX) ecomm_type = ECOMMUNITY_ENCODE_AS4; - else if (as > 0) - ecomm_type = ECOMMUNITY_ENCODE_AS; - else if (val_color) { + else if (type == ECOMMUNITY_COLOR) { ecomm_type = ECOMMUNITY_ENCODE_OPAQUE; sub_type = ECOMMUNITY_COLOR; - val = val_color; - } + if (val_color) { + val = val_color; + as = 1; + } + } else if (as > 0) + ecomm_type = ECOMMUNITY_ENCODE_AS; } if (ecommunity_encode(ecomm_type, sub_type, 1, as, ip, val, eval)) goto error; @@ -1419,7 +1436,15 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) else if (sub_type == ECOMMUNITY_EXTENDED_LINK_BANDWIDTH) ipv6_ecommunity_lb_str(encbuf, sizeof(encbuf), pnt, len); - else + else if (sub_type == ECOMMUNITY_OPAQUE_SUBTYPE_COLOR) { + uint32_t color; + /* get the color type */ + uint8_t color_type = (*pnt) >> 6; + memcpy(&color, pnt + 2, 4); + color = ntohl(color); + snprintf(encbuf, sizeof(encbuf), "Color:%d%d:%u", + (color_type & 0x2) >> 1, color_type & 0x1, color); + } else unk_ecom = true; } else if (CHECK_FLAG(type, ECOMMUNITY_ENCODE_IP_NON_TRANS)) { sub_type = *pnt++; @@ -1439,6 +1464,7 @@ unknown: sub_type); int r = strlcat(str_buf, encbuf, str_size); + assert(r < str_size); } diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index 0544cbd316..af9d481c19 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -85,6 +85,7 @@ /* Low-order octet of the Extended Communities type field for OPAQUE types */ #define ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP 0x0c +#define ECOMMUNITY_OPAQUE_SUBTYPE_COLOR 0x0b /* Extended communities attribute string format. */ #define ECOMMUNITY_FORMAT_ROUTE_MAP 0 @@ -328,26 +329,25 @@ static inline void encode_node_target(struct in_addr *node_id, /* * Encode BGP Color extended community - * is's a transitive opaque Extended community (RFC 9012 4.3) + * is's a transitive opaque Extended community (RFC 9256 8.8.1) * flag is set to 0 - * RFC 9012 14.10: No values have currently been registered. - * 4.3: this field MUST be set to zero by the originator - * and ignored by the receiver; * */ -static inline void encode_color(uint32_t color_id, struct ecommunity_val *eval) +static inline void encode_color(uint32_t color_id, uint32_t flags, struct ecommunity_val *eval) { /* * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | 0x03 | Sub-Type(0x0b) | Flags | + * | 0x03 | Sub-Type(0x0b) |CO | Flags | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Color Value | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * https://datatracker.ietf.org/doc/rfc9256/, Section 8.8.1 + * The CO bits can have 4 different values: 00 01 10 11 */ memset(eval, 0, sizeof(*eval)); eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE; eval->val[1] = ECOMMUNITY_COLOR; - eval->val[2] = 0x00; + eval->val[2] = (flags << 6) & 0xff; eval->val[3] = 0x00; eval->val[4] = (color_id >> 24) & 0xff; eval->val[5] = (color_id >> 16) & 0xff; diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index b3518ac696..58e1ffa500 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -689,6 +689,11 @@ static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi) COMMUNITY_NO_LLGR)) continue; + if (bgp_attr_get_community(pi->attr) && + community_include(bgp_attr_get_community(pi->attr), + COMMUNITY_LLGR_STALE)) + continue; + if (bgp_debug_neighbor_events(peer)) zlog_debug( "%pBP Long-lived set stale community (LLGR_STALE) for: %pFX", @@ -699,7 +704,6 @@ static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi) pi->attr = bgp_attr_intern(&attr); bgp_process(peer->bgp, rm, pi, afi, safi); - break; } } } else { @@ -716,6 +720,11 @@ static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi) COMMUNITY_NO_LLGR)) continue; + if (bgp_attr_get_community(pi->attr) && + community_include(bgp_attr_get_community(pi->attr), + COMMUNITY_LLGR_STALE)) + continue; + if (bgp_debug_neighbor_events(peer)) zlog_debug( "%pBP Long-lived set stale community (LLGR_STALE) for: %pFX", @@ -725,7 +734,6 @@ static void bgp_set_llgr_stale(struct peer *peer, afi_t afi, safi_t safi) bgp_attr_add_llgr_community(&attr); pi->attr = bgp_attr_intern(&attr); bgp_process(peer->bgp, dest, pi, afi, safi); - break; } } } diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 401549c4e8..357d5292da 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -1001,7 +1001,7 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp, if (bnc->is_evpn_gwip_nexthop) json_object_boolean_true_add(json_nexthop, "isEvpnGatewayIp"); - json_object_string_addf(json, "resolvedPrefix", "%pFX", + json_object_string_addf(json_nexthop, "resolvedPrefix", "%pFX", &bnc->resolved_prefix); } else { vty_out(vty, " %s valid [IGP metric %d], #paths %d", diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 7a87739479..988be7f4de 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -4388,12 +4388,9 @@ void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi, bgp_process(peer->bgp, dest, pi, afi, safi); } -static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi, - struct peer *peer, afi_t afi, safi_t safi, - struct prefix_rd *prd) +static void bgp_rib_withdraw(const struct prefix *p, struct bgp_dest *dest, struct bgp_path_info *pi, + struct peer *peer, afi_t afi, safi_t safi, struct prefix_rd *prd) { - const struct prefix *p = bgp_dest_get_prefix(dest); - /* apply dampening, if result is suppressed, we'll be retaining * the bgp_path_info in the RIB for historical reference. */ @@ -5038,7 +5035,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, if (get_active_bdc_from_pi(pi, afi, safi) && peer->sort == BGP_PEER_EBGP && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) { - if (bgp_debug_update(peer, p, NULL, 1)) { + if (unlikely(bgp_debug_update(peer, p, NULL, 1))) { bgp_debug_rdpfxpath2str( afi, safi, prd, p, label, num_labels, addpath_id ? 1 : 0, @@ -5056,7 +5053,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, } } else /* Duplicate - odd */ { - if (bgp_debug_update(peer, p, NULL, 1)) { + if (unlikely(bgp_debug_update(peer, p, NULL, 1))) { if (!peer->rcvd_attr_printed) { zlog_debug( "%pBP rcvd UPDATE w/ attr: %s", @@ -5092,7 +5089,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, /* Withdraw/Announce before we fully processed the withdraw */ if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) { - if (bgp_debug_update(peer, p, NULL, 1)) { + if (unlikely(bgp_debug_update(peer, p, NULL, 1))) { bgp_debug_rdpfxpath2str( afi, safi, prd, p, label, num_labels, addpath_id ? 1 : 0, addpath_id, evpn, @@ -5120,7 +5117,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, } /* Received Logging. */ - if (bgp_debug_update(peer, p, NULL, 1)) { + if (unlikely(bgp_debug_update(peer, p, NULL, 1))) { bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels, addpath_id ? 1 : 0, addpath_id, evpn, pfx_buf, @@ -5191,7 +5188,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, bgp_attr_get_ecommunity(pi->attr), bgp_attr_get_ecommunity(attr_new)); if (!cmp) { - if (bgp_debug_update(peer, p, NULL, 1)) + if (unlikely(bgp_debug_update(peer, p, NULL, 1))) zlog_debug( "Change in EXT-COMM, existing %s new %s", ecommunity_str( @@ -5301,7 +5298,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, * EVPN nexthop is decremented appropriately. */ else if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)) { - if (BGP_DEBUG(nht, NHT)) + if (unlikely(BGP_DEBUG(nht, NHT))) zlog_debug("%s unimport EVPN %pFX as pi %p is not VALID", __func__, p, pi); bgp_evpn_unimport_route(bgp, afi, safi, p, pi); @@ -5341,7 +5338,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, } // End of implicit withdraw /* Received Logging. */ - if (bgp_debug_update(peer, p, NULL, 1)) { + if (unlikely(bgp_debug_update(peer, p, NULL, 1))) { if (!peer->rcvd_attr_printed) { zlog_debug("%pBP rcvd UPDATE w/ attr: %s", peer, peer->rcvd_attr_str); @@ -5558,7 +5555,7 @@ void bgp_withdraw(struct peer *peer, const struct prefix *p, break; /* Logging. */ - if (bgp_debug_update(peer, p, NULL, 1)) { + if (unlikely(bgp_debug_update(peer, p, NULL, 1))) { bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels, addpath_id ? 1 : 0, addpath_id, NULL, pfx_buf, sizeof(pfx_buf)); @@ -5568,18 +5565,14 @@ void bgp_withdraw(struct peer *peer, const struct prefix *p, /* Withdraw specified route from routing table. */ if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) { - bgp_rib_withdraw(dest, pi, peer, afi, safi, prd); + bgp_rib_withdraw(p, dest, pi, peer, afi, safi, prd); if (SAFI_UNICAST == safi && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi); - } - if ((SAFI_MPLS_VPN == safi) - && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { - + } else if ((SAFI_MPLS_VPN == safi) && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) vpn_leak_to_vrf_withdraw(pi); - } - } else if (bgp_debug_update(peer, p, NULL, 1)) { + } else if (unlikely(bgp_debug_update(peer, p, NULL, 1))) { bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels, addpath_id ? 1 : 0, addpath_id, NULL, pfx_buf, sizeof(pfx_buf)); @@ -6292,7 +6285,6 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) vpn_leak_to_vrf_withdraw(pi); bgp_rib_remove(rm, pi, peer, afi, safi); - break; } } } else { @@ -6321,7 +6313,6 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) pi); bgp_rib_remove(dest, pi, peer, afi, safi); - break; } } } @@ -9056,6 +9047,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, memset(&rmap_path, 0, sizeof(rmap_path)); rmap_path.peer = bgp->peer_self; rmap_path.attr = &attr_new; + rmap_path.type = type; SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index ecb45ff697..e86d1dc656 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -18732,7 +18732,7 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp, } /* TCP max segment size */ - if (CHECK_FLAG(peer->flags, PEER_FLAG_TCP_MSS)) + if (peergroup_flag_check(peer, PEER_FLAG_TCP_MSS)) vty_out(vty, " neighbor %s tcp-mss %d\n", addr, peer->tcp_mss); /* passive */ diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 22f1cf8414..7e98735c14 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3031,6 +3031,9 @@ static void peer_group2peer_config_copy(struct peer_group *group, bgp_peer_configure_bfd(peer, false); bgp_peer_config_apply(peer, group); } + /* peer tcp-mss */ + if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_TCP_MSS)) + PEER_ATTR_INHERIT(peer, group, tcp_mss); } /* Peer group's remote AS configuration. */ @@ -4796,6 +4799,7 @@ static const struct peer_flag_action peer_flag_action_list[] = { {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}, + {PEER_FLAG_TCP_MSS, 0, peer_change_none}, {0, 0, 0}}; static const struct peer_flag_action peer_af_flag_action_list[] = { @@ -6097,9 +6101,27 @@ void peer_port_unset(struct peer *peer) */ void peer_tcp_mss_set(struct peer *peer, uint32_t tcp_mss) { + struct peer *member; + struct listnode *node, *nnode; + + peer_flag_set(peer, PEER_FLAG_TCP_MSS); peer->tcp_mss = tcp_mss; - SET_FLAG(peer->flags, PEER_FLAG_TCP_MSS); - bgp_tcp_mss_set(peer); + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + bgp_tcp_mss_set(peer); + return; + } + + for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) { + /* Skip peers with overridden configuration. */ + if (CHECK_FLAG(member->flags_override, PEER_FLAG_TCP_MSS)) + continue; + + /* Set flag and configuration on peer-group member. */ + SET_FLAG(member->flags, PEER_FLAG_TCP_MSS); + PEER_ATTR_INHERIT(member, peer->group, tcp_mss); + bgp_tcp_mss_set(member); + } } /* Reset the TCP-MSS value in the peer structure, @@ -6108,9 +6130,39 @@ void peer_tcp_mss_set(struct peer *peer, uint32_t tcp_mss) */ void peer_tcp_mss_unset(struct peer *peer) { - UNSET_FLAG(peer->flags, PEER_FLAG_TCP_MSS); - peer->tcp_mss = 0; - bgp_tcp_mss_set(peer); + struct peer *member; + struct listnode *node, *nnode; + + /* Inherit configuration from peer-group if peer is member. */ + if (peer_group_active(peer)) { + peer_flag_inherit(peer, PEER_FLAG_TCP_MSS); + PEER_ATTR_INHERIT(peer, peer->group, tcp_mss); + } else { + /* Otherwise remove flag and configuration from peer. */ + peer_flag_unset(peer, PEER_FLAG_TCP_MSS); + peer->tcp_mss = 0; + } + + /* Skip peer-group mechanics for regular peers. */ + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + bgp_tcp_mss_set(peer); + return; + } + + /* + * Remove flag and configuration from all peer-group members, unless + * they are explicitely overriding peer-group configuration. + */ + for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) { + /* Skip peers with overridden configuration. */ + if (CHECK_FLAG(member->flags_override, PEER_FLAG_TCP_MSS)) + continue; + + /* Remove flag and configuration on peer-group member. */ + UNSET_FLAG(member->flags, PEER_FLAG_TCP_MSS); + member->tcp_mss = 0; + bgp_tcp_mss_set(member); + } } /* diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 20a9ef84fa..0c7fcecb9b 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -2928,6 +2928,23 @@ BGP Extended Communities in Route Map This command sets colors values. +:rfc:`9256`. + +``CO:COLOR`` + This is a format to define colors value. ``CO`` part is always 00 (default), + it can be used to support the requirements of Color-Only steering when using + a Null Endpoint in the SR-TE Policy as specified in Section 8.8 of [RFC9256]. + The below shows in detail what the different combinations of ``CO`` bits can + match on to for the purpose of determining what type of SR-TE Policy Tunnel + a BGP route can resolve over, and it also shows the order for resolving the + BGP route if there are different tunnels. + - ``00`` Can match on a specific endpoint only which should be the nexthop + of the route(Default Setting). + - ``01`` Can match on a specific endpoint or a null endpoint. + - ``10`` Can match on a specific endpoint, null endpoint or any endpoint. + - ``11`` Reserved for future use and shuould not be used. + + .. clicmd:: set extcommunity bandwidth <(1-25600) | cumulative | num-multipaths> [non-transitive] This command sets the BGP link-bandwidth extended community for the prefix diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst index 02d674dff0..1481a1bbe8 100644 --- a/doc/user/routemap.rst +++ b/doc/user/routemap.rst @@ -101,9 +101,10 @@ cont .. clicmd:: clear route-map counter [WORD] - Clear counters that are being stored about the route-map utilization - so that subsuquent show commands will indicate since the last clear. - If WORD is specified clear just that particular route-map's counters. + Clear counters as well as cpu time spent that are being stored about + the route-map utilization so that subsequent show commands will indicate + since the last clear. If WORD is specified clear just that particular + route-map's counters. .. _route-map-command: diff --git a/lib/routemap.c b/lib/routemap.c index ea917ebd8c..120731fa61 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -941,11 +941,12 @@ static void vty_show_route_map_entry(struct vty *vty, struct route_map *map, json_object_boolean_add(json_rmap, "processedChange", map->to_be_processed); json_object_object_add(json_rmap, "rules", json_rules); + json_object_int_add(json_rmap, "cpuTimeMS", map->cputime / 1000); } else { vty_out(vty, "route-map: %s Invoked: %" PRIu64 - " Optimization: %s Processed Change: %s\n", - map->name, map->applied - map->applied_clear, + " (%zu milliseconds total) Optimization: %s Processed Change: %s\n", + map->name, map->applied - map->applied_clear, map->cputime / 1000, map->optimization_disabled ? "disabled" : "enabled", map->to_be_processed ? "true" : "false"); } @@ -967,6 +968,7 @@ static void vty_show_route_map_entry(struct vty *vty, struct route_map *map, json_object_int_add(json_rule, "invoked", index->applied - index->applied_clear); + json_object_int_add(json_rule, "cpuTimeMS", index->cputime / 1000); /* Description */ if (index->description) @@ -1018,9 +1020,10 @@ static void vty_show_route_map_entry(struct vty *vty, struct route_map *map, json_object_string_add(json_rule, "action", action); } else { - vty_out(vty, " %s, sequence %d Invoked %" PRIu64 "\n", + vty_out(vty, + " %s, sequence %d Invoked %" PRIu64 " (%zu milliseconds total)\n", route_map_type_str(index->type), index->pref, - index->applied - index->applied_clear); + index->applied - index->applied_clear, index->cputime / 1000); /* Description */ if (index->description) @@ -2548,6 +2551,9 @@ route_map_result_t route_map_apply_ext(struct route_map *map, struct route_map_index *index = NULL; struct route_map_rule *set = NULL; bool skip_match_clause = false; + RUSAGE_T mbefore, mafter; + RUSAGE_T ibefore, iafter; + unsigned long cputime; if (recursion > RMAP_RECURSION_LIMIT) { if (map) @@ -2570,6 +2576,9 @@ route_map_result_t route_map_apply_ext(struct route_map *map, map->applied++; + GETRUSAGE(&mbefore); + ibefore = mbefore; + if (prefix->family == AF_EVPN) { index = map->head; } else { @@ -2580,6 +2589,12 @@ route_map_result_t route_map_apply_ext(struct route_map *map, if (index) { index->applied++; + + GETRUSAGE(&iafter); + event_consumed_time(&iafter, &ibefore, &cputime); + index->cputime += cputime; + ibefore = iafter; + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug( "Best match route-map: %s, sequence: %d for pfx: %pFX, result: %s", @@ -2718,6 +2733,10 @@ route_map_result_t route_map_apply_ext(struct route_map *map, goto route_map_apply_end; } } + GETRUSAGE(&iafter); + event_consumed_time(&iafter, &ibefore, &cputime); + index->cputime += cputime; + ibefore = iafter; } route_map_apply_end: @@ -2733,6 +2752,13 @@ route_map_apply_end: *pref = 65536; } + if (map) { + GETRUSAGE(&mbefore); + GETRUSAGE(&mafter); + event_consumed_time(&mafter, &mbefore, &cputime); + map->cputime += cputime; + } + return (ret); } @@ -3090,8 +3116,11 @@ static void clear_route_map_helper(struct route_map *map) struct route_map_index *index; map->applied_clear = map->applied; - for (index = map->head; index; index = index->next) + map->cputime = 0; + for (index = map->head; index; index = index->next) { index->applied_clear = index->applied; + index->cputime = 0; + } } DEFPY (rmap_clear_counters, diff --git a/lib/routemap.h b/lib/routemap.h index ef9b3cb160..e0f738502b 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -176,6 +176,7 @@ struct route_map_index { /* Keep track how many times we've try to apply */ uint64_t applied; uint64_t applied_clear; + size_t cputime; /* List of match/sets contexts. */ TAILQ_HEAD(, routemap_hook_context) rhclist; @@ -210,6 +211,7 @@ struct route_map { /* How many times have we applied this route-map */ uint64_t applied; uint64_t applied_clear; + size_t cputime; /* Counter to track active usage of this route-map */ uint16_t use_count; diff --git a/tests/topotests/all_protocol_startup/r1/show_route_map.ref b/tests/topotests/all_protocol_startup/r1/show_route_map.ref index 612d0a729d..894ea59677 100644 --- a/tests/topotests/all_protocol_startup/r1/show_route_map.ref +++ b/tests/topotests/all_protocol_startup/r1/show_route_map.ref @@ -1,6 +1,6 @@ ZEBRA: -route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false - deny, sequence 10 Invoked 0 +route-map: LIES Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + deny, sequence 10 Invoked 0 (X milliseconds total) Match clauses: interface notpresent Set clauses: @@ -8,8 +8,8 @@ route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false Action: Exit routemap RIP: -route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false - deny, sequence 10 Invoked 0 +route-map: LIES Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + deny, sequence 10 Invoked 0 (X milliseconds total) Match clauses: interface notpresent Set clauses: @@ -17,8 +17,8 @@ route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false Action: Exit routemap RIPNG: -route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false - deny, sequence 10 Invoked 0 +route-map: LIES Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + deny, sequence 10 Invoked 0 (X milliseconds total) Match clauses: interface notpresent Set clauses: @@ -26,8 +26,8 @@ route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false Action: Exit routemap OSPF: -route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false - deny, sequence 10 Invoked 0 +route-map: LIES Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + deny, sequence 10 Invoked 0 (X milliseconds total) Match clauses: interface notpresent Set clauses: @@ -35,8 +35,8 @@ route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false Action: Exit routemap OSPF6: -route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false - deny, sequence 10 Invoked 0 +route-map: LIES Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + deny, sequence 10 Invoked 0 (X milliseconds total) Match clauses: interface notpresent Set clauses: @@ -44,16 +44,16 @@ route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false Action: Exit routemap BGP: -route-map: LIES Invoked: 0 Optimization: enabled Processed Change: false - deny, sequence 10 Invoked 0 +route-map: LIES Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + deny, sequence 10 Invoked 0 (X milliseconds total) Match clauses: interface notpresent Set clauses: Call clause: Action: Exit routemap -route-map: bgp-map Invoked: 0 Optimization: enabled Processed Change: false - permit, sequence 10 Invoked 0 +route-map: bgp-map Invoked: 0 (X milliseconds total) Optimization: enabled Processed Change: false + permit, sequence 10 Invoked 0 (X milliseconds total) Match clauses: Set clauses: community 100:100 additive @@ -61,7 +61,7 @@ route-map: bgp-map Invoked: 0 Optimization: enabled Processed Change: false Call clause: Action: Exit routemap - permit, sequence 20 Invoked 0 + permit, sequence 20 Invoked 0 (X milliseconds total) Match clauses: Set clauses: metric 10 diff --git a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py index 80bd2505a7..0ffd762734 100644 --- a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py +++ b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py @@ -37,6 +37,7 @@ from lib.topogen import Topogen, get_topogen from lib.common_config import ( required_linux_kernel_version, ) +from lib.topolog import logger import json import functools @@ -1422,6 +1423,7 @@ def test_route_map(): .cmd('vtysh -c "show route-map" 2> /dev/null') .rstrip() ) + actual = re.sub(r"\([0-9].* milli", "(X milli", actual) actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1) diff = topotest.get_textdiff( diff --git a/tests/topotests/bgp_addpath_graceful_restart/__init__.py b/tests/topotests/bgp_addpath_graceful_restart/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_addpath_graceful_restart/__init__.py diff --git a/tests/topotests/bgp_addpath_graceful_restart/r1/frr.conf b/tests/topotests/bgp_addpath_graceful_restart/r1/frr.conf new file mode 100644 index 0000000000..0644cf63a8 --- /dev/null +++ b/tests/topotests/bgp_addpath_graceful_restart/r1/frr.conf @@ -0,0 +1,23 @@ +! +int r1-eth0 + ip address 192.168.1.1/24 +! +int r1-eth1 + ip address 192.168.2.1/24 +! +router bgp 65001 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 192.168.1.2 remote-as auto + neighbor 192.168.1.2 timers 1 3 + neighbor 192.168.1.2 timers connect 1 + neighbor 192.168.2.2 remote-as auto + neighbor 192.168.2.2 timers 1 3 + neighbor 192.168.2.2 timers connect 1 + neighbor r1-eth1 interface remote-as auto + neighbor r1-eth1 timers 1 3 + neighbor r1-eth1 timers connect 1 + address-family ipv4 unicast + network 10.0.0.1/32 + exit-address-family +! diff --git a/tests/topotests/bgp_addpath_graceful_restart/r2/frr.conf b/tests/topotests/bgp_addpath_graceful_restart/r2/frr.conf new file mode 100644 index 0000000000..ad236e0680 --- /dev/null +++ b/tests/topotests/bgp_addpath_graceful_restart/r2/frr.conf @@ -0,0 +1,28 @@ +! +int r2-eth0 + ip address 192.168.1.2/24 +! +int r2-eth1 + ip address 192.168.2.2/24 +! +int r2-eth2 + ip address 192.168.3.2/24 +! +router bgp 65002 + bgp graceful-restart + bgp graceful-restart preserve-fw-state + bgp graceful-restart restart-time 10 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as auto + neighbor 192.168.1.1 timers 1 3 + neighbor 192.168.1.1 timers connect 1 + neighbor 192.168.2.1 remote-as auto + neighbor 192.168.2.1 timers 1 3 + neighbor 192.168.2.1 timers connect 1 + neighbor 192.168.3.3 remote-as auto + neighbor 192.168.3.3 timers 1 3 + neighbor 192.168.3.3 timers connect 1 + address-family ipv4 unicast + neighbor 192.168.3.3 addpath-tx-all-paths + exit-address-family +! diff --git a/tests/topotests/bgp_addpath_graceful_restart/r3/frr.conf b/tests/topotests/bgp_addpath_graceful_restart/r3/frr.conf new file mode 100644 index 0000000000..e864003f25 --- /dev/null +++ b/tests/topotests/bgp_addpath_graceful_restart/r3/frr.conf @@ -0,0 +1,13 @@ +! +int r3-eth0 + ip address 192.168.3.3/24 +! +router bgp 65003 + bgp graceful-restart + bgp graceful-restart preserve-fw-state + bgp graceful-restart restart-time 10 + no bgp ebgp-requires-policy + neighbor 192.168.3.2 remote-as auto + neighbor 192.168.3.2 timers 1 3 + neighbor 192.168.3.2 timers connect 1 +! diff --git a/tests/topotests/bgp_addpath_graceful_restart/test_bgp_addpath_graceful_restart.py b/tests/topotests/bgp_addpath_graceful_restart/test_bgp_addpath_graceful_restart.py new file mode 100644 index 0000000000..9088c44bdb --- /dev/null +++ b/tests/topotests/bgp_addpath_graceful_restart/test_bgp_addpath_graceful_restart.py @@ -0,0 +1,132 @@ +#!/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, get_topogen +from lib.common_config import kill_router_daemons + +pytestmark = [pytest.mark.bgpd] + + +def setup_module(mod): + topodef = {"s1": ("r1", "r2"), "s2": ("r1", "r2"), "s3": ("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_addpath_graceful_restart(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r2 = tgen.gears["r2"] + r3 = tgen.gears["r3"] + + def _bgp_converge(): + output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast summary json")) + expected = { + "peers": { + "192.168.1.1": { + "hostname": "r1", + "remoteAs": 65001, + "localAs": 65002, + "pfxRcd": 1, + "state": "Established", + }, + "192.168.2.1": { + "hostname": "r1", + "remoteAs": 65001, + "localAs": 65002, + "pfxRcd": 1, + "state": "Established", + }, + "192.168.3.3": { + "hostname": "r3", + "remoteAs": 65003, + "localAs": 65002, + "pfxSnt": 2, + "state": "Established", + }, + } + } + 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, "Initial peering failed" + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + def _bgp_check_stale_routes(): + output = json.loads(r3.vtysh_cmd("show bgp ipv4 unicast json")) + expected = { + "routes": { + "10.0.0.1/32": [ + { + "stale": True, + "valid": True, + }, + { + "stale": True, + "valid": True, + "multipath": True, + }, + ] + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_check_stale_routes, + ) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Can't see stale routes" + + def _bgp_check_stale_routes_cleared(): + output = json.loads(r3.vtysh_cmd("show bgp ipv4 unicast json")) + expected = { + "routes": { + "10.0.0.1/32": None, + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_check_stale_routes_cleared, + ) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Can't see stale routes" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_addpath_llgr/__init__.py b/tests/topotests/bgp_addpath_llgr/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_addpath_llgr/__init__.py diff --git a/tests/topotests/bgp_addpath_llgr/r1/frr.conf b/tests/topotests/bgp_addpath_llgr/r1/frr.conf new file mode 100644 index 0000000000..0644cf63a8 --- /dev/null +++ b/tests/topotests/bgp_addpath_llgr/r1/frr.conf @@ -0,0 +1,23 @@ +! +int r1-eth0 + ip address 192.168.1.1/24 +! +int r1-eth1 + ip address 192.168.2.1/24 +! +router bgp 65001 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 192.168.1.2 remote-as auto + neighbor 192.168.1.2 timers 1 3 + neighbor 192.168.1.2 timers connect 1 + neighbor 192.168.2.2 remote-as auto + neighbor 192.168.2.2 timers 1 3 + neighbor 192.168.2.2 timers connect 1 + neighbor r1-eth1 interface remote-as auto + neighbor r1-eth1 timers 1 3 + neighbor r1-eth1 timers connect 1 + address-family ipv4 unicast + network 10.0.0.1/32 + exit-address-family +! diff --git a/tests/topotests/bgp_addpath_llgr/r2/frr.conf b/tests/topotests/bgp_addpath_llgr/r2/frr.conf new file mode 100644 index 0000000000..7f6fff0fda --- /dev/null +++ b/tests/topotests/bgp_addpath_llgr/r2/frr.conf @@ -0,0 +1,29 @@ +! +int r2-eth0 + ip address 192.168.1.2/24 +! +int r2-eth1 + ip address 192.168.2.2/24 +! +int r2-eth2 + ip address 192.168.3.2/24 +! +router bgp 65002 + bgp graceful-restart + bgp graceful-restart preserve-fw-state + bgp graceful-restart restart-time 0 + bgp long-lived-graceful-restart stale-time 10 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as auto + neighbor 192.168.1.1 timers 1 3 + neighbor 192.168.1.1 timers connect 1 + neighbor 192.168.2.1 remote-as auto + neighbor 192.168.2.1 timers 1 3 + neighbor 192.168.2.1 timers connect 1 + neighbor 192.168.3.3 remote-as auto + neighbor 192.168.3.3 timers 1 3 + neighbor 192.168.3.3 timers connect 1 + address-family ipv4 unicast + neighbor 192.168.3.3 addpath-tx-all-paths + exit-address-family +! diff --git a/tests/topotests/bgp_addpath_llgr/r3/frr.conf b/tests/topotests/bgp_addpath_llgr/r3/frr.conf new file mode 100644 index 0000000000..f36492d7e0 --- /dev/null +++ b/tests/topotests/bgp_addpath_llgr/r3/frr.conf @@ -0,0 +1,14 @@ +! +int r3-eth0 + ip address 192.168.3.3/24 +! +router bgp 65003 + bgp graceful-restart + bgp graceful-restart preserve-fw-state + bgp graceful-restart restart-time 0 + bgp long-lived-graceful-restart stale-time 10 + no bgp ebgp-requires-policy + neighbor 192.168.3.2 remote-as auto + neighbor 192.168.3.2 timers 1 3 + neighbor 192.168.3.2 timers connect 1 +! diff --git a/tests/topotests/bgp_addpath_llgr/test_bgp_addpath_llgr.py b/tests/topotests/bgp_addpath_llgr/test_bgp_addpath_llgr.py new file mode 100644 index 0000000000..fa0314304b --- /dev/null +++ b/tests/topotests/bgp_addpath_llgr/test_bgp_addpath_llgr.py @@ -0,0 +1,131 @@ +#!/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, get_topogen +from lib.common_config import kill_router_daemons + +pytestmark = [pytest.mark.bgpd] + + +def setup_module(mod): + topodef = {"s1": ("r1", "r2"), "s2": ("r1", "r2"), "s3": ("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_addpath_llgr(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r2 = tgen.gears["r2"] + r3 = tgen.gears["r3"] + + def _bgp_converge(): + output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast summary json")) + expected = { + "peers": { + "192.168.1.1": { + "hostname": "r1", + "remoteAs": 65001, + "localAs": 65002, + "pfxRcd": 1, + "state": "Established", + }, + "192.168.2.1": { + "hostname": "r1", + "remoteAs": 65001, + "localAs": 65002, + "pfxRcd": 1, + "state": "Established", + }, + "192.168.3.3": { + "hostname": "r3", + "remoteAs": 65003, + "localAs": 65002, + "pfxSnt": 2, + "state": "Established", + }, + } + } + 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, "Initial peering failed" + + kill_router_daemons(tgen, "r2", ["bgpd"]) + + def _bgp_check_stale_llgr_routes(): + output = json.loads(r3.vtysh_cmd("show bgp ipv4 unicast 10.0.0.1/32 json")) + expected = { + "paths": [ + { + "stale": True, + "valid": True, + "community": {"string": "llgr-stale", "list": ["llgrStale"]}, + }, + { + "stale": True, + "valid": True, + "community": {"string": "llgr-stale", "list": ["llgrStale"]}, + }, + ] + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_check_stale_llgr_routes, + ) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Can't see stale LLGR routes" + + def _bgp_check_stale_routes_cleared(): + output = json.loads(r3.vtysh_cmd("show bgp ipv4 unicast json")) + expected = { + "routes": { + "10.0.0.1/32": None, + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_check_stale_routes_cleared, + ) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Can't see stale routes" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_color_extcommunities/r1/bgpd.conf b/tests/topotests/bgp_color_extcommunities/r1/bgpd.conf index d4ca392b1a..30cb6647ae 100644 --- a/tests/topotests/bgp_color_extcommunities/r1/bgpd.conf +++ b/tests/topotests/bgp_color_extcommunities/r1/bgpd.conf @@ -11,7 +11,7 @@ router bgp 65001 exit-address-family ! route-map rmap permit 10 - set extcommunity color 1 + set extcommunity color 01:1 set extcommunity rt 80:987 - set extcommunity color 100 55555 200 + set extcommunity color 01:100 01:55555 01:200 exit diff --git a/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py b/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py index 09091198a8..94a444d5c5 100644 --- a/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py +++ b/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py @@ -105,7 +105,7 @@ def test_bgp_color_extended_communities(): { "valid": True, "extendedCommunity": { - "string": "RT:80:987 Color:100 Color:200 Color:55555" + "string": "RT:80:987 Color:01:100 Color:01:200 Color:01:55555" }, } ], diff --git a/tests/topotests/bgp_route_map_match_source_protocol/test_bgp_route_map_match_source_protocol.py b/tests/topotests/bgp_route_map_match_source_protocol/test_bgp_route_map_match_source_protocol.py index 7116deaea4..f7b69f21c1 100644 --- a/tests/topotests/bgp_route_map_match_source_protocol/test_bgp_route_map_match_source_protocol.py +++ b/tests/topotests/bgp_route_map_match_source_protocol/test_bgp_route_map_match_source_protocol.py @@ -22,7 +22,7 @@ sys.path.append(os.path.join(CWD, "../")) # pylint: disable=C0413 from lib import topotest -from lib.topogen import Topogen, get_topogen +from lib.topogen import Topogen, TopoRouter, get_topogen pytestmark = [pytest.mark.bgpd] @@ -47,7 +47,14 @@ def setup_module(mod): 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))) + router.load_frr_config( + os.path.join(CWD, "{}/frr.conf".format(rname)), + [ + (TopoRouter.RD_ZEBRA, None), + (TopoRouter.RD_SHARP, None), + (TopoRouter.RD_BGP, None), + ], + ) tgen.start_router() @@ -109,6 +116,68 @@ def test_bgp_route_map_match_source_protocol(): _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) assert result is None, "Failed to filter routes by source-protocol for r3" + def _bgp_check_advertised_routes_r4(): + # Remove match source-protocol towards Nbr out policy for Nbr 192.168.1.2 so it receives all routes + tgen.gears["r1"].vtysh_cmd( + """ + configure terminal + route-map r2 permit 10 + no match source-protocol + """ + ) + + tgen.gears["r1"].vtysh_cmd( + "sharp install route 192.168.11.0 nexthop 172.16.255.1 5" + ) + + # Configure a r4 with source protocol sharp and apply it to all redistribute cmds + tgen.gears["r1"].vtysh_cmd( + """ + configure terminal + route-map r4 permit 10 + match source-protocol sharp + router bgp 65001 + address-family ipv4 unicast + redistribute connected route-map r4 + redistribute static route-map r4 + redistribute sharp route-map r4 + """ + ) + + # Since match protocol is sharp, only sharp protocol routes are to be advertised + output = json.loads( + tgen.gears["r1"].vtysh_cmd( + "show bgp ipv4 unicast neighbors 192.168.1.2 advertised-routes json" + ) + ) + + expected = { + "advertisedRoutes": { + "192.168.11.0/32": { + "valid": True, + }, + "192.168.11.1/32": { + "valid": True, + }, + "192.168.11.2/32": { + "valid": True, + }, + "192.168.11.3/32": { + "valid": True, + }, + "192.168.11.4/32": { + "valid": True, + }, + }, + "totalPrefixCounter": 5, + } + + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_check_advertised_routes_r4) + _, result = topotest.run_and_expect(test_func, None, count=30, wait=1) + assert result is None, "Failed to match the source-protocol for redistribute cmds" + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] diff --git a/tests/topotests/bgp_tcp_mss/r1/bgpd.conf b/tests/topotests/bgp_tcp_mss/r1/bgpd.conf index 07cfe2e2f1..12e5df28ee 100644 --- a/tests/topotests/bgp_tcp_mss/r1/bgpd.conf +++ b/tests/topotests/bgp_tcp_mss/r1/bgpd.conf @@ -1,5 +1,8 @@ router bgp 65000 no bgp ebgp-requires-policy + neighbor aaa peer-group + neighbor aaa remote-as 65001 + neighbor 192.168.254.2 peer-group aaa neighbor 192.168.255.2 remote-as 65001 neighbor 192.168.255.2 timers 3 10 exit-address-family diff --git a/tests/topotests/bgp_tcp_mss/r1/zebra.conf b/tests/topotests/bgp_tcp_mss/r1/zebra.conf index 6e9b0b4a7e..57958c4420 100644 --- a/tests/topotests/bgp_tcp_mss/r1/zebra.conf +++ b/tests/topotests/bgp_tcp_mss/r1/zebra.conf @@ -2,5 +2,8 @@ interface r1-eth0 ip address 192.168.255.1/24 ! +interface r1-eth1 + ip address 192.168.254.1/24 +! ip forwarding ! diff --git a/tests/topotests/bgp_tcp_mss/r2/bgpd.conf b/tests/topotests/bgp_tcp_mss/r2/bgpd.conf index b2d945583c..8a5a4062a4 100644 --- a/tests/topotests/bgp_tcp_mss/r2/bgpd.conf +++ b/tests/topotests/bgp_tcp_mss/r2/bgpd.conf @@ -1,5 +1,8 @@ router bgp 65001 no bgp ebgp-requires-policy + neighbor aaa peer-group + neighbor aaa remote-as 65000 + neighbor 192.168.254.1 peer-group aaa neighbor 192.168.255.1 remote-as 65000 neighbor 192.168.255.1 timers 3 10 exit-address-family diff --git a/tests/topotests/bgp_tcp_mss/r2/zebra.conf b/tests/topotests/bgp_tcp_mss/r2/zebra.conf index 6c14de583b..f2daa523ac 100644 --- a/tests/topotests/bgp_tcp_mss/r2/zebra.conf +++ b/tests/topotests/bgp_tcp_mss/r2/zebra.conf @@ -2,5 +2,8 @@ interface r2-eth0 ip address 192.168.255.2/24 ! +interface r2-eth1 + ip address 192.168.254.2/24 +! ip forwarding ! diff --git a/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py b/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py index 37949cdc99..30449a3920 100644 --- a/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py +++ b/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py @@ -45,6 +45,10 @@ def build_topo(tgen): switch.add_link(tgen.gears["r1"]) switch.add_link(tgen.gears["r2"]) + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + def setup_module(mod): tgen = Topogen(build_topo, mod.__name__) @@ -78,12 +82,16 @@ def test_bgp_tcp_mss(): router2 = tgen.gears["r2"] def _bgp_converge(router): - output = json.loads(router.vtysh_cmd("show ip bgp neighbor 192.168.255.2 json")) + output = json.loads(router.vtysh_cmd("show ip bgp neighbor json")) expected = { "192.168.255.2": { "bgpState": "Established", "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 0}}, - } + }, + "192.168.254.2": { + "bgpState": "Established", + "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 0}}, + }, } return topotest.json_cmp(output, expected) @@ -108,7 +116,7 @@ def test_bgp_tcp_mss(): logger.info("Check if neighbor sessions are up in {}".format(router1.name)) test_func = functools.partial(_bgp_converge, router1) - _, result = topotest.run_and_expect(test_func, None, count=15, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=15, wait=1) assert result is None, 'Failed to see BGP convergence in "{}"'.format(router1.name) logger.info("BGP neighbor session is up in {}".format(router1.name)) @@ -117,19 +125,21 @@ def test_bgp_tcp_mss(): "Configure tcp-mss 500 on {} and reset the session".format(router1.name) ) _bgp_conf_tcp_mss(router1, "65000", "192.168.255.2") + _bgp_conf_tcp_mss(router1, "65000", "aaa") _bgp_clear_session(router1) logger.info( "Configure tcp-mss 500 on {} and reset the session".format(router2.name) ) _bgp_conf_tcp_mss(router2, "65001", "192.168.255.1") + _bgp_conf_tcp_mss(router2, "65001", "aaa") _bgp_clear_session(router2) logger.info( "Check if neighbor session is up after reset in {}".format(router1.name) ) test_func = functools.partial(_bgp_converge, router1) - _, result = topotest.run_and_expect(test_func, None, count=15, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=15, wait=1) assert result is None, 'Failed to see BGP convergence after reset in "{}"'.format( router1.name ) @@ -138,7 +148,13 @@ def test_bgp_tcp_mss(): "Verify if TCP MSS value is synced with neighbor in {}".format(router1.name) ) test_func = functools.partial(_bgp_check_neighbor_tcp_mss, router1, "192.168.255.2") - _, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=15, wait=1) + assert ( + result is None + ), 'Failed to sync TCP MSS value over BGP session in "{}"'.format(router1.name) + + test_func = functools.partial(_bgp_check_neighbor_tcp_mss, router1, "192.168.254.2") + success, result = topotest.run_and_expect(test_func, None, count=15, wait=1) assert ( result is None ), 'Failed to sync TCP MSS value over BGP session in "{}"'.format(router1.name) @@ -148,7 +164,13 @@ def test_bgp_tcp_mss(): "Verify if TCP MSS value is synced with neighbor in {}".format(router2.name) ) test_func = functools.partial(_bgp_check_neighbor_tcp_mss, router2, "192.168.255.1") - _, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=15, wait=1) + assert ( + result is None + ), 'Failed to sync TCP MSS value over BGP session in "{}"'.format(router2.name) + + test_func = functools.partial(_bgp_check_neighbor_tcp_mss, router2, "192.168.254.1") + success, result = topotest.run_and_expect(test_func, None, count=15, wait=1) assert ( result is None ), 'Failed to sync TCP MSS value over BGP session in "{}"'.format(router2.name) diff --git a/tests/topotests/high_ecmp/r1/frr.conf b/tests/topotests/high_ecmp/r1/frr.conf new file mode 100644 index 0000000000..4382f94cf1 --- /dev/null +++ b/tests/topotests/high_ecmp/r1/frr.conf @@ -0,0 +1,267 @@ +int lo + ip addr 192.168.1.1/32 +router bgp 1001 + timers bgp 5 20 + no bgp ebgp-requires-policy + neighbor r1-eth0 interface remote-as external + neighbor r1-eth1 interface remote-as external + neighbor r1-eth2 interface remote-as external + neighbor r1-eth3 interface remote-as external + neighbor r1-eth4 interface remote-as external + neighbor r1-eth5 interface remote-as external + neighbor r1-eth6 interface remote-as external + neighbor r1-eth7 interface remote-as external + neighbor r1-eth8 interface remote-as external + neighbor r1-eth9 interface remote-as external + neighbor r1-eth10 interface remote-as external + neighbor r1-eth11 interface remote-as external + neighbor r1-eth12 interface remote-as external + neighbor r1-eth13 interface remote-as external + neighbor r1-eth14 interface remote-as external + neighbor r1-eth15 interface remote-as external + neighbor r1-eth16 interface remote-as external + neighbor r1-eth17 interface remote-as external + neighbor r1-eth18 interface remote-as external + neighbor r1-eth19 interface remote-as external + neighbor r1-eth20 interface remote-as external + neighbor r1-eth21 interface remote-as external + neighbor r1-eth22 interface remote-as external + neighbor r1-eth23 interface remote-as external + neighbor r1-eth24 interface remote-as external + neighbor r1-eth25 interface remote-as external + neighbor r1-eth26 interface remote-as external + neighbor r1-eth27 interface remote-as external + neighbor r1-eth28 interface remote-as external + neighbor r1-eth29 interface remote-as external + neighbor r1-eth30 interface remote-as external + neighbor r1-eth31 interface remote-as external + neighbor r1-eth32 interface remote-as external + neighbor r1-eth33 interface remote-as external + neighbor r1-eth34 interface remote-as external + neighbor r1-eth35 interface remote-as external + neighbor r1-eth36 interface remote-as external + neighbor r1-eth37 interface remote-as external + neighbor r1-eth38 interface remote-as external + neighbor r1-eth39 interface remote-as external + neighbor r1-eth40 interface remote-as external + neighbor r1-eth41 interface remote-as external + neighbor r1-eth42 interface remote-as external + neighbor r1-eth43 interface remote-as external + neighbor r1-eth44 interface remote-as external + neighbor r1-eth45 interface remote-as external + neighbor r1-eth46 interface remote-as external + neighbor r1-eth47 interface remote-as external + neighbor r1-eth48 interface remote-as external + neighbor r1-eth49 interface remote-as external + neighbor r1-eth50 interface remote-as external + neighbor r1-eth51 interface remote-as external + neighbor r1-eth52 interface remote-as external + neighbor r1-eth53 interface remote-as external + neighbor r1-eth54 interface remote-as external + neighbor r1-eth55 interface remote-as external + neighbor r1-eth56 interface remote-as external + neighbor r1-eth57 interface remote-as external + neighbor r1-eth58 interface remote-as external + neighbor r1-eth59 interface remote-as external + neighbor r1-eth60 interface remote-as external + neighbor r1-eth61 interface remote-as external + neighbor r1-eth62 interface remote-as external + neighbor r1-eth63 interface remote-as external + neighbor r1-eth64 interface remote-as external + neighbor r1-eth65 interface remote-as external + neighbor r1-eth66 interface remote-as external + neighbor r1-eth67 interface remote-as external + neighbor r1-eth68 interface remote-as external + neighbor r1-eth69 interface remote-as external + neighbor r1-eth70 interface remote-as external + neighbor r1-eth71 interface remote-as external + neighbor r1-eth72 interface remote-as external + neighbor r1-eth73 interface remote-as external + neighbor r1-eth74 interface remote-as external + neighbor r1-eth75 interface remote-as external + neighbor r1-eth76 interface remote-as external + neighbor r1-eth77 interface remote-as external + neighbor r1-eth78 interface remote-as external + neighbor r1-eth79 interface remote-as external + neighbor r1-eth80 interface remote-as external + neighbor r1-eth81 interface remote-as external + neighbor r1-eth82 interface remote-as external + neighbor r1-eth83 interface remote-as external + neighbor r1-eth84 interface remote-as external + neighbor r1-eth85 interface remote-as external + neighbor r1-eth86 interface remote-as external + neighbor r1-eth87 interface remote-as external + neighbor r1-eth88 interface remote-as external + neighbor r1-eth89 interface remote-as external + neighbor r1-eth90 interface remote-as external + neighbor r1-eth91 interface remote-as external + neighbor r1-eth92 interface remote-as external + neighbor r1-eth93 interface remote-as external + neighbor r1-eth94 interface remote-as external + neighbor r1-eth95 interface remote-as external + neighbor r1-eth96 interface remote-as external + neighbor r1-eth97 interface remote-as external + neighbor r1-eth98 interface remote-as external + neighbor r1-eth99 interface remote-as external + neighbor r1-eth100 interface remote-as external + neighbor r1-eth101 interface remote-as external + neighbor r1-eth102 interface remote-as external + neighbor r1-eth103 interface remote-as external + neighbor r1-eth104 interface remote-as external + neighbor r1-eth105 interface remote-as external + neighbor r1-eth106 interface remote-as external + neighbor r1-eth107 interface remote-as external + neighbor r1-eth108 interface remote-as external + neighbor r1-eth109 interface remote-as external + neighbor r1-eth110 interface remote-as external + neighbor r1-eth111 interface remote-as external + neighbor r1-eth112 interface remote-as external + neighbor r1-eth113 interface remote-as external + neighbor r1-eth114 interface remote-as external + neighbor r1-eth115 interface remote-as external + neighbor r1-eth116 interface remote-as external + neighbor r1-eth117 interface remote-as external + neighbor r1-eth118 interface remote-as external + neighbor r1-eth119 interface remote-as external + neighbor r1-eth120 interface remote-as external + neighbor r1-eth121 interface remote-as external + neighbor r1-eth122 interface remote-as external + neighbor r1-eth123 interface remote-as external + neighbor r1-eth124 interface remote-as external + neighbor r1-eth125 interface remote-as external + neighbor r1-eth126 interface remote-as external + neighbor r1-eth127 interface remote-as external + neighbor r1-eth128 interface remote-as external + neighbor r1-eth129 interface remote-as external + neighbor r1-eth130 interface remote-as external + neighbor r1-eth131 interface remote-as external + neighbor r1-eth132 interface remote-as external + neighbor r1-eth133 interface remote-as external + neighbor r1-eth134 interface remote-as external + neighbor r1-eth135 interface remote-as external + neighbor r1-eth136 interface remote-as external + neighbor r1-eth137 interface remote-as external + neighbor r1-eth138 interface remote-as external + neighbor r1-eth139 interface remote-as external + neighbor r1-eth140 interface remote-as external + neighbor r1-eth141 interface remote-as external + neighbor r1-eth142 interface remote-as external + neighbor r1-eth143 interface remote-as external + neighbor r1-eth144 interface remote-as external + neighbor r1-eth145 interface remote-as external + neighbor r1-eth146 interface remote-as external + neighbor r1-eth147 interface remote-as external + neighbor r1-eth148 interface remote-as external + neighbor r1-eth149 interface remote-as external + neighbor r1-eth150 interface remote-as external + neighbor r1-eth151 interface remote-as external + neighbor r1-eth152 interface remote-as external + neighbor r1-eth153 interface remote-as external + neighbor r1-eth154 interface remote-as external + neighbor r1-eth155 interface remote-as external + neighbor r1-eth156 interface remote-as external + neighbor r1-eth157 interface remote-as external + neighbor r1-eth158 interface remote-as external + neighbor r1-eth159 interface remote-as external + neighbor r1-eth160 interface remote-as external + neighbor r1-eth161 interface remote-as external + neighbor r1-eth162 interface remote-as external + neighbor r1-eth163 interface remote-as external + neighbor r1-eth164 interface remote-as external + neighbor r1-eth165 interface remote-as external + neighbor r1-eth166 interface remote-as external + neighbor r1-eth167 interface remote-as external + neighbor r1-eth168 interface remote-as external + neighbor r1-eth169 interface remote-as external + neighbor r1-eth170 interface remote-as external + neighbor r1-eth171 interface remote-as external + neighbor r1-eth172 interface remote-as external + neighbor r1-eth173 interface remote-as external + neighbor r1-eth174 interface remote-as external + neighbor r1-eth175 interface remote-as external + neighbor r1-eth176 interface remote-as external + neighbor r1-eth177 interface remote-as external + neighbor r1-eth178 interface remote-as external + neighbor r1-eth179 interface remote-as external + neighbor r1-eth180 interface remote-as external + neighbor r1-eth181 interface remote-as external + neighbor r1-eth182 interface remote-as external + neighbor r1-eth183 interface remote-as external + neighbor r1-eth184 interface remote-as external + neighbor r1-eth185 interface remote-as external + neighbor r1-eth186 interface remote-as external + neighbor r1-eth187 interface remote-as external + neighbor r1-eth188 interface remote-as external + neighbor r1-eth189 interface remote-as external + neighbor r1-eth190 interface remote-as external + neighbor r1-eth191 interface remote-as external + neighbor r1-eth192 interface remote-as external + neighbor r1-eth193 interface remote-as external + neighbor r1-eth194 interface remote-as external + neighbor r1-eth195 interface remote-as external + neighbor r1-eth196 interface remote-as external + neighbor r1-eth197 interface remote-as external + neighbor r1-eth198 interface remote-as external + neighbor r1-eth199 interface remote-as external + neighbor r1-eth200 interface remote-as external + neighbor r1-eth201 interface remote-as external + neighbor r1-eth202 interface remote-as external + neighbor r1-eth203 interface remote-as external + neighbor r1-eth204 interface remote-as external + neighbor r1-eth205 interface remote-as external + neighbor r1-eth206 interface remote-as external + neighbor r1-eth207 interface remote-as external + neighbor r1-eth208 interface remote-as external + neighbor r1-eth209 interface remote-as external + neighbor r1-eth210 interface remote-as external + neighbor r1-eth211 interface remote-as external + neighbor r1-eth212 interface remote-as external + neighbor r1-eth213 interface remote-as external + neighbor r1-eth214 interface remote-as external + neighbor r1-eth215 interface remote-as external + neighbor r1-eth216 interface remote-as external + neighbor r1-eth217 interface remote-as external + neighbor r1-eth218 interface remote-as external + neighbor r1-eth219 interface remote-as external + neighbor r1-eth220 interface remote-as external + neighbor r1-eth221 interface remote-as external + neighbor r1-eth222 interface remote-as external + neighbor r1-eth223 interface remote-as external + neighbor r1-eth224 interface remote-as external + neighbor r1-eth225 interface remote-as external + neighbor r1-eth226 interface remote-as external + neighbor r1-eth227 interface remote-as external + neighbor r1-eth228 interface remote-as external + neighbor r1-eth229 interface remote-as external + neighbor r1-eth230 interface remote-as external + neighbor r1-eth231 interface remote-as external + neighbor r1-eth232 interface remote-as external + neighbor r1-eth233 interface remote-as external + neighbor r1-eth234 interface remote-as external + neighbor r1-eth235 interface remote-as external + neighbor r1-eth236 interface remote-as external + neighbor r1-eth237 interface remote-as external + neighbor r1-eth238 interface remote-as external + neighbor r1-eth239 interface remote-as external + neighbor r1-eth240 interface remote-as external + neighbor r1-eth241 interface remote-as external + neighbor r1-eth242 interface remote-as external + neighbor r1-eth243 interface remote-as external + neighbor r1-eth244 interface remote-as external + neighbor r1-eth245 interface remote-as external + neighbor r1-eth246 interface remote-as external + neighbor r1-eth247 interface remote-as external + neighbor r1-eth248 interface remote-as external + neighbor r1-eth249 interface remote-as external + neighbor r1-eth250 interface remote-as external + neighbor r1-eth251 interface remote-as external + neighbor r1-eth252 interface remote-as external + neighbor r1-eth253 interface remote-as external + neighbor r1-eth254 interface remote-as external + neighbor r1-eth255 interface remote-as external + neighbor r1-eth256 interface remote-as external + neighbor r1-eth257 interface remote-as external + neighbor r1-eth258 interface remote-as external + neighbor r1-eth259 interface remote-as external + address-family ipv4 uni + redistribute sharp diff --git a/tests/topotests/high_ecmp/r2/frr.conf b/tests/topotests/high_ecmp/r2/frr.conf new file mode 100644 index 0000000000..a9d65360f5 --- /dev/null +++ b/tests/topotests/high_ecmp/r2/frr.conf @@ -0,0 +1,267 @@ +int lo + ip addr 192.168.1.2/32 +! +router bgp 1002 + timers bgp 5 20 + no bgp ebgp-requires-policy + read-quanta 1 + neighbor r2-eth0 interface remote-as external + neighbor r2-eth1 interface remote-as external + neighbor r2-eth2 interface remote-as external + neighbor r2-eth3 interface remote-as external + neighbor r2-eth4 interface remote-as external + neighbor r2-eth5 interface remote-as external + neighbor r2-eth6 interface remote-as external + neighbor r2-eth7 interface remote-as external + neighbor r2-eth8 interface remote-as external + neighbor r2-eth9 interface remote-as external + neighbor r2-eth10 interface remote-as external + neighbor r2-eth11 interface remote-as external + neighbor r2-eth12 interface remote-as external + neighbor r2-eth13 interface remote-as external + neighbor r2-eth14 interface remote-as external + neighbor r2-eth15 interface remote-as external + neighbor r2-eth16 interface remote-as external + neighbor r2-eth17 interface remote-as external + neighbor r2-eth18 interface remote-as external + neighbor r2-eth19 interface remote-as external + neighbor r2-eth20 interface remote-as external + neighbor r2-eth21 interface remote-as external + neighbor r2-eth22 interface remote-as external + neighbor r2-eth23 interface remote-as external + neighbor r2-eth24 interface remote-as external + neighbor r2-eth25 interface remote-as external + neighbor r2-eth26 interface remote-as external + neighbor r2-eth27 interface remote-as external + neighbor r2-eth28 interface remote-as external + neighbor r2-eth29 interface remote-as external + neighbor r2-eth30 interface remote-as external + neighbor r2-eth31 interface remote-as external + neighbor r2-eth32 interface remote-as external + neighbor r2-eth33 interface remote-as external + neighbor r2-eth34 interface remote-as external + neighbor r2-eth35 interface remote-as external + neighbor r2-eth36 interface remote-as external + neighbor r2-eth37 interface remote-as external + neighbor r2-eth38 interface remote-as external + neighbor r2-eth39 interface remote-as external + neighbor r2-eth40 interface remote-as external + neighbor r2-eth41 interface remote-as external + neighbor r2-eth42 interface remote-as external + neighbor r2-eth43 interface remote-as external + neighbor r2-eth44 interface remote-as external + neighbor r2-eth45 interface remote-as external + neighbor r2-eth46 interface remote-as external + neighbor r2-eth47 interface remote-as external + neighbor r2-eth48 interface remote-as external + neighbor r2-eth49 interface remote-as external + neighbor r2-eth50 interface remote-as external + neighbor r2-eth51 interface remote-as external + neighbor r2-eth52 interface remote-as external + neighbor r2-eth53 interface remote-as external + neighbor r2-eth54 interface remote-as external + neighbor r2-eth55 interface remote-as external + neighbor r2-eth56 interface remote-as external + neighbor r2-eth57 interface remote-as external + neighbor r2-eth58 interface remote-as external + neighbor r2-eth59 interface remote-as external + neighbor r2-eth60 interface remote-as external + neighbor r2-eth61 interface remote-as external + neighbor r2-eth62 interface remote-as external + neighbor r2-eth63 interface remote-as external + neighbor r2-eth64 interface remote-as external + neighbor r2-eth65 interface remote-as external + neighbor r2-eth66 interface remote-as external + neighbor r2-eth67 interface remote-as external + neighbor r2-eth68 interface remote-as external + neighbor r2-eth69 interface remote-as external + neighbor r2-eth70 interface remote-as external + neighbor r2-eth71 interface remote-as external + neighbor r2-eth72 interface remote-as external + neighbor r2-eth73 interface remote-as external + neighbor r2-eth74 interface remote-as external + neighbor r2-eth75 interface remote-as external + neighbor r2-eth76 interface remote-as external + neighbor r2-eth77 interface remote-as external + neighbor r2-eth78 interface remote-as external + neighbor r2-eth79 interface remote-as external + neighbor r2-eth80 interface remote-as external + neighbor r2-eth81 interface remote-as external + neighbor r2-eth82 interface remote-as external + neighbor r2-eth83 interface remote-as external + neighbor r2-eth84 interface remote-as external + neighbor r2-eth85 interface remote-as external + neighbor r2-eth86 interface remote-as external + neighbor r2-eth87 interface remote-as external + neighbor r2-eth88 interface remote-as external + neighbor r2-eth89 interface remote-as external + neighbor r2-eth90 interface remote-as external + neighbor r2-eth91 interface remote-as external + neighbor r2-eth92 interface remote-as external + neighbor r2-eth93 interface remote-as external + neighbor r2-eth94 interface remote-as external + neighbor r2-eth95 interface remote-as external + neighbor r2-eth96 interface remote-as external + neighbor r2-eth97 interface remote-as external + neighbor r2-eth98 interface remote-as external + neighbor r2-eth99 interface remote-as external + neighbor r2-eth100 interface remote-as external + neighbor r2-eth101 interface remote-as external + neighbor r2-eth102 interface remote-as external + neighbor r2-eth103 interface remote-as external + neighbor r2-eth104 interface remote-as external + neighbor r2-eth105 interface remote-as external + neighbor r2-eth106 interface remote-as external + neighbor r2-eth107 interface remote-as external + neighbor r2-eth108 interface remote-as external + neighbor r2-eth109 interface remote-as external + neighbor r2-eth110 interface remote-as external + neighbor r2-eth111 interface remote-as external + neighbor r2-eth112 interface remote-as external + neighbor r2-eth113 interface remote-as external + neighbor r2-eth114 interface remote-as external + neighbor r2-eth115 interface remote-as external + neighbor r2-eth116 interface remote-as external + neighbor r2-eth117 interface remote-as external + neighbor r2-eth118 interface remote-as external + neighbor r2-eth119 interface remote-as external + neighbor r2-eth120 interface remote-as external + neighbor r2-eth121 interface remote-as external + neighbor r2-eth122 interface remote-as external + neighbor r2-eth123 interface remote-as external + neighbor r2-eth124 interface remote-as external + neighbor r2-eth125 interface remote-as external + neighbor r2-eth126 interface remote-as external + neighbor r2-eth127 interface remote-as external + neighbor r2-eth128 interface remote-as external + neighbor r2-eth129 interface remote-as external + neighbor r2-eth130 interface remote-as external + neighbor r2-eth131 interface remote-as external + neighbor r2-eth132 interface remote-as external + neighbor r2-eth133 interface remote-as external + neighbor r2-eth134 interface remote-as external + neighbor r2-eth135 interface remote-as external + neighbor r2-eth136 interface remote-as external + neighbor r2-eth137 interface remote-as external + neighbor r2-eth138 interface remote-as external + neighbor r2-eth139 interface remote-as external + neighbor r2-eth140 interface remote-as external + neighbor r2-eth141 interface remote-as external + neighbor r2-eth142 interface remote-as external + neighbor r2-eth143 interface remote-as external + neighbor r2-eth144 interface remote-as external + neighbor r2-eth145 interface remote-as external + neighbor r2-eth146 interface remote-as external + neighbor r2-eth147 interface remote-as external + neighbor r2-eth148 interface remote-as external + neighbor r2-eth149 interface remote-as external + neighbor r2-eth150 interface remote-as external + neighbor r2-eth151 interface remote-as external + neighbor r2-eth152 interface remote-as external + neighbor r2-eth153 interface remote-as external + neighbor r2-eth154 interface remote-as external + neighbor r2-eth155 interface remote-as external + neighbor r2-eth156 interface remote-as external + neighbor r2-eth157 interface remote-as external + neighbor r2-eth158 interface remote-as external + neighbor r2-eth159 interface remote-as external + neighbor r2-eth160 interface remote-as external + neighbor r2-eth161 interface remote-as external + neighbor r2-eth162 interface remote-as external + neighbor r2-eth163 interface remote-as external + neighbor r2-eth164 interface remote-as external + neighbor r2-eth165 interface remote-as external + neighbor r2-eth166 interface remote-as external + neighbor r2-eth167 interface remote-as external + neighbor r2-eth168 interface remote-as external + neighbor r2-eth169 interface remote-as external + neighbor r2-eth170 interface remote-as external + neighbor r2-eth171 interface remote-as external + neighbor r2-eth172 interface remote-as external + neighbor r2-eth173 interface remote-as external + neighbor r2-eth174 interface remote-as external + neighbor r2-eth175 interface remote-as external + neighbor r2-eth176 interface remote-as external + neighbor r2-eth177 interface remote-as external + neighbor r2-eth178 interface remote-as external + neighbor r2-eth179 interface remote-as external + neighbor r2-eth180 interface remote-as external + neighbor r2-eth181 interface remote-as external + neighbor r2-eth182 interface remote-as external + neighbor r2-eth183 interface remote-as external + neighbor r2-eth184 interface remote-as external + neighbor r2-eth185 interface remote-as external + neighbor r2-eth186 interface remote-as external + neighbor r2-eth187 interface remote-as external + neighbor r2-eth188 interface remote-as external + neighbor r2-eth189 interface remote-as external + neighbor r2-eth190 interface remote-as external + neighbor r2-eth191 interface remote-as external + neighbor r2-eth192 interface remote-as external + neighbor r2-eth193 interface remote-as external + neighbor r2-eth194 interface remote-as external + neighbor r2-eth195 interface remote-as external + neighbor r2-eth196 interface remote-as external + neighbor r2-eth197 interface remote-as external + neighbor r2-eth198 interface remote-as external + neighbor r2-eth199 interface remote-as external + neighbor r2-eth200 interface remote-as external + neighbor r2-eth201 interface remote-as external + neighbor r2-eth202 interface remote-as external + neighbor r2-eth203 interface remote-as external + neighbor r2-eth204 interface remote-as external + neighbor r2-eth205 interface remote-as external + neighbor r2-eth206 interface remote-as external + neighbor r2-eth207 interface remote-as external + neighbor r2-eth208 interface remote-as external + neighbor r2-eth209 interface remote-as external + neighbor r2-eth210 interface remote-as external + neighbor r2-eth211 interface remote-as external + neighbor r2-eth212 interface remote-as external + neighbor r2-eth213 interface remote-as external + neighbor r2-eth214 interface remote-as external + neighbor r2-eth215 interface remote-as external + neighbor r2-eth216 interface remote-as external + neighbor r2-eth217 interface remote-as external + neighbor r2-eth218 interface remote-as external + neighbor r2-eth219 interface remote-as external + neighbor r2-eth220 interface remote-as external + neighbor r2-eth221 interface remote-as external + neighbor r2-eth222 interface remote-as external + neighbor r2-eth223 interface remote-as external + neighbor r2-eth224 interface remote-as external + neighbor r2-eth225 interface remote-as external + neighbor r2-eth226 interface remote-as external + neighbor r2-eth227 interface remote-as external + neighbor r2-eth228 interface remote-as external + neighbor r2-eth229 interface remote-as external + neighbor r2-eth230 interface remote-as external + neighbor r2-eth231 interface remote-as external + neighbor r2-eth232 interface remote-as external + neighbor r2-eth233 interface remote-as external + neighbor r2-eth234 interface remote-as external + neighbor r2-eth235 interface remote-as external + neighbor r2-eth236 interface remote-as external + neighbor r2-eth237 interface remote-as external + neighbor r2-eth238 interface remote-as external + neighbor r2-eth239 interface remote-as external + neighbor r2-eth240 interface remote-as external + neighbor r2-eth241 interface remote-as external + neighbor r2-eth242 interface remote-as external + neighbor r2-eth243 interface remote-as external + neighbor r2-eth244 interface remote-as external + neighbor r2-eth245 interface remote-as external + neighbor r2-eth246 interface remote-as external + neighbor r2-eth247 interface remote-as external + neighbor r2-eth248 interface remote-as external + neighbor r2-eth249 interface remote-as external + neighbor r2-eth250 interface remote-as external + neighbor r2-eth251 interface remote-as external + neighbor r2-eth252 interface remote-as external + neighbor r2-eth253 interface remote-as external + neighbor r2-eth254 interface remote-as external + neighbor r2-eth255 interface remote-as external + neighbor r2-eth256 interface remote-as external + neighbor r2-eth257 interface remote-as external + neighbor r2-eth258 interface remote-as external + neighbor r2-eth259 interface remote-as external diff --git a/tests/topotests/high_ecmp/test_high_ecmp.py b/tests/topotests/high_ecmp/test_high_ecmp.py new file mode 100644 index 0000000000..d28a1ee069 --- /dev/null +++ b/tests/topotests/high_ecmp/test_high_ecmp.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# +# test_high_ecmp.py +# +# Copyright (c) 2024 by +# Nvidia Corporation +# Donald Sharp +# + +""" +test_high_ecmp.py: Testing two routers with 256 interfaces and BGP setup + on it. + +""" + +import os +import re +import sys +import pytest +import json + +pytestmark = [pytest.mark.bgpd] + +# Save the Current Working Directory to find configuration files. +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 + +# Required to instantiate the topology builder class. + +##################################################### +## +## Network Topology Definition +## +##################################################### + + +def build_topo(tgen): + + tgen.add_router("r1") + tgen.add_router("r2") + + r1 = tgen.gears["r1"] + r2 = tgen.gears["r2"] + + # Let's create 257 interfaces between the two switches + for switch in range(1, 257): + switch = tgen.add_switch("sw{}".format(switch)) + switch.add_link(r1) + switch.add_link(r2) + + +##################################################### +## +## Tests starting +## +##################################################### + + +def setup_module(module): + "Setup topology" + tgen = Topogen(build_topo, module.__name__) + tgen.start_topology() + + # This is a sample of configuration loading. + router_list = tgen.routers() + for rname, router in router_list.items(): + router.load_frr_config( + os.path.join(CWD, "{}/frr.conf".format(rname)), + [ + (TopoRouter.RD_ZEBRA, "-s 180000000"), + (TopoRouter.RD_BGP, None), + (TopoRouter.RD_SHARP, None), + ], + ) + + tgen.start_router() + + +def teardown_module(_mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # This function tears down the whole topology. + tgen.stop_topology() + + +def test_nothing(): + "Do Nothing" + + tgen = get_topogen() + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/pytest.ini b/tests/topotests/pytest.ini index b234a84252..ef95ea1b95 100644 --- a/tests/topotests/pytest.ini +++ b/tests/topotests/pytest.ini @@ -32,7 +32,7 @@ log_file_date_format = %Y-%m-%d %H:%M:%S junit_logging = all junit_log_passing_tests = true -norecursedirs = .git example_munet example_test example_topojson_test lib munet docker +norecursedirs = .git example_munet example_test example_topojson_test lib munet docker high_ecmp # Directory to store test results and run logs in, default shown # rundir = /tmp/topotests diff --git a/tests/topotests/zebra_rib/r1/sharp_rmap.ref b/tests/topotests/zebra_rib/r1/sharp_rmap.ref index 47a9eb6a49..d80a5f661e 100644 --- a/tests/topotests/zebra_rib/r1/sharp_rmap.ref +++ b/tests/topotests/zebra_rib/r1/sharp_rmap.ref @@ -1,6 +1,6 @@ ZEBRA: -route-map: sharp Invoked: 500 Optimization: enabled Processed Change: false - permit, sequence 10 Invoked 244 +route-map: sharp Invoked: 500 (X milliseconds total) Optimization: enabled Processed Change: false + permit, sequence 10 Invoked 244 (X milliseconds total) Match clauses: ip address 10 Set clauses: @@ -8,7 +8,7 @@ route-map: sharp Invoked: 500 Optimization: enabled Processed Change: false Call clause: Action: Exit routemap - permit, sequence 20 Invoked 256 + permit, sequence 20 Invoked 256 (X milliseconds total) Match clauses: Set clauses: src 192.168.213.1 diff --git a/tests/topotests/zebra_rib/r1/static_rmap.ref b/tests/topotests/zebra_rib/r1/static_rmap.ref index 2de98bd514..68e4a5f7b6 100644 --- a/tests/topotests/zebra_rib/r1/static_rmap.ref +++ b/tests/topotests/zebra_rib/r1/static_rmap.ref @@ -1,6 +1,6 @@ ZEBRA: -route-map: static Invoked: 2 Optimization: enabled Processed Change: false - permit, sequence 10 Invoked 2 +route-map: static Invoked: 2 (X milliseconds total) Optimization: enabled Processed Change: false + permit, sequence 10 Invoked 2 (X milliseconds total) Match clauses: Set clauses: src 192.168.215.1 diff --git a/tests/topotests/zebra_rib/test_zebra_rib.py b/tests/topotests/zebra_rib/test_zebra_rib.py index c0a79ed79d..d1aee46b40 100644 --- a/tests/topotests/zebra_rib/test_zebra_rib.py +++ b/tests/topotests/zebra_rib/test_zebra_rib.py @@ -246,6 +246,7 @@ def test_route_map_usage(): def check_static_map_correct_runs(): actual = r1.vtysh_cmd("show route-map static") + actual = re.sub(r"\([0-9].* milli", "(X milli", actual) actual = ("\n".join(actual.splitlines()) + "\n").rstrip() return topotest.get_textdiff( actual, @@ -266,6 +267,7 @@ def test_route_map_usage(): def check_sharp_map_correct_runs(): actual = r1.vtysh_cmd("show route-map sharp") + actual = re.sub(r"\([0-9].* milli", "(X milli", actual) actual = ("\n".join(actual.splitlines()) + "\n").rstrip() return topotest.get_textdiff( actual, diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang index 4ed80d7d07..5f701d514c 100644 --- a/yang/frr-bgp-route-map.yang +++ b/yang/frr-bgp-route-map.yang @@ -532,7 +532,7 @@ identity set-extcommunity-color { typedef color-list { type string { - pattern '((429496729[0-5]|42949672[0-8][0-9]|' + pattern '((00|01|10|11):(429496729[0-5]|42949672[0-8][0-9]|' + '4294967[0-1][0-9]{2}|429496[0-6][0-9]{3}|' + '42949[0-5][0-9]{4}|4294[0-8][0-9]{5}|' + '429[0-3][0-9]{6}|42[0-8][0-9]{7}|' @@ -540,10 +540,11 @@ identity set-extcommunity-color { + '[1-9][0-9]{0,8})(\s*))+'; } description - "The color-list type represent a set of colors of value (1..4294967295) + "The color-list type represent a set of colors of value (examples 00:200 01:200 10:200) values are separated by white spaces"; reference - "RFC 9012 - The BGP Tunnel Encapsulation Attribute"; + "RFC 9012 - The BGP Tunnel Encapsulation Attribute. + RFC 9256 - Segment Routing Policy Architecture."; } augment "/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:rmap-match-condition/frr-route-map:match-condition" { |
