diff options
| -rw-r--r-- | bgpd/bgp_attr.c | 38 | ||||
| -rw-r--r-- | bgpd/bgp_nexthop.c | 4 | ||||
| -rw-r--r-- | bgpd/bgp_nexthop.h | 1 | ||||
| -rw-r--r-- | bgpd/bgp_nht.c | 3 | ||||
| -rw-r--r-- | bgpd/bgp_packet.c | 17 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 17 | ||||
| -rw-r--r-- | bgpd/bgp_updgrp_adv.c | 10 | ||||
| -rw-r--r-- | bgpd/bgp_zebra.c | 6 | ||||
| -rw-r--r-- | doc/user/bgp.rst | 2 | ||||
| -rw-r--r-- | doc/user/isisd.rst | 10 | ||||
| -rw-r--r-- | isisd/isis_adjacency.c | 4 | ||||
| -rw-r--r-- | isisd/isis_lfa.c | 5 | ||||
| -rw-r--r-- | isisd/isis_sr.c | 7 | ||||
| -rw-r--r-- | isisd/isis_sr.h | 2 | ||||
| -rw-r--r-- | isisd/isis_zebra.c | 2 | ||||
| -rw-r--r-- | lib/srv6.c | 4 | ||||
| -rw-r--r-- | tests/topotests/bfd_topo3/test_bfd_topo3.py | 2 | ||||
| -rw-r--r-- | tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py | 6 | ||||
| -rw-r--r-- | tests/topotests/bgp_peer_group/r1/bgpd.conf | 4 | ||||
| -rw-r--r-- | tests/topotests/bgp_peer_group/r1/zebra.conf | 3 | ||||
| -rw-r--r-- | tests/topotests/bgp_peer_group/r2/bgpd.conf | 4 | ||||
| -rw-r--r-- | tests/topotests/bgp_peer_group/r2/zebra.conf | 3 | ||||
| -rw-r--r-- | tests/topotests/bgp_peer_group/test_bgp_peer-group.py | 49 | ||||
| -rw-r--r-- | tests/topotests/lib/topotest.py | 2 | ||||
| -rw-r--r-- | zebra/interface.c | 3 | ||||
| -rw-r--r-- | zebra/zebra_mpls.c | 6 |
26 files changed, 155 insertions, 59 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 5320a5f57e..e2321ad296 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1389,6 +1389,15 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode, (args->startp - STREAM_DATA(BGP_INPUT(peer))) + args->total); + /* Partial optional attributes that are malformed should not cause + * the whole session to be reset. Instead treat it as a withdrawal + * of the routes, if possible. + */ + if (CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS) && + CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL) && + CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL)) + return BGP_ATTR_PARSE_WITHDRAW; + switch (args->type) { /* where an attribute is relatively inconsequential, e.g. it does not * affect route selection, and can be safely ignored, then any such @@ -1398,6 +1407,7 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode, case BGP_ATTR_AS4_AGGREGATOR: case BGP_ATTR_AGGREGATOR: case BGP_ATTR_ATOMIC_AGGREGATE: + case BGP_ATTR_PREFIX_SID: return BGP_ATTR_PARSE_PROCEED; /* Core attributes, particularly ones which may influence route @@ -1425,19 +1435,21 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode, BGP_NOTIFY_UPDATE_ERR, subcode, notify_datap, length); return BGP_ATTR_PARSE_ERROR; + default: + /* Unknown attributes, that are handled by this function + * should be treated as withdraw, to prevent one more CVE + * from being introduced. + * RFC 7606 says: + * The "treat-as-withdraw" approach is generally preferred + * and the "session reset" approach is discouraged. + */ + flog_err(EC_BGP_ATTR_FLAG, + "%s(%u) attribute received, while it is not known how to handle it, treating as withdraw", + lookup_msg(attr_str, args->type, NULL), args->type); + break; } - /* Partial optional attributes that are malformed should not cause - * the whole session to be reset. Instead treat it as a withdrawal - * of the routes, if possible. - */ - if (CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS) - && CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL) - && CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL)) - return BGP_ATTR_PARSE_WITHDRAW; - - /* default to reset */ - return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; + return BGP_ATTR_PARSE_WITHDRAW; } /* Find out what is wrong with the path attribute flag bits and log the error. @@ -3163,8 +3175,6 @@ enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args) struct attr *const attr = args->attr; enum bgp_attr_parse_ret ret; - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID); - uint8_t type; uint16_t length; size_t headersz = sizeof(type) + sizeof(length); @@ -3214,6 +3224,8 @@ enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args) } } + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)); + return BGP_ATTR_PARSE_PROCEED; } diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index d12dc22330..98eb9565bf 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -1003,6 +1003,8 @@ 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", + &bnc->resolved_prefix); } else { vty_out(vty, " %s valid [IGP metric %d], #paths %d", buf, bnc->metric, bnc->path_count); @@ -1010,6 +1012,8 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp, vty_out(vty, ", peer %s", peer->host); if (bnc->is_evpn_gwip_nexthop) vty_out(vty, " EVPN Gateway IP"); + vty_out(vty, "\n Resolved prefix %pFX", + &bnc->resolved_prefix); vty_out(vty, "\n"); } bgp_show_nexthops_detail(vty, bgp, bnc, json_nexthop); diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h index 830883872e..430c8f17e8 100644 --- a/bgpd/bgp_nexthop.h +++ b/bgpd/bgp_nexthop.h @@ -90,6 +90,7 @@ struct bgp_nexthop_cache { struct bgp_nexthop_cache_head *tree; struct prefix prefix; + struct prefix resolved_prefix; void *nht_info; /* In BGP, peer session */ LIST_HEAD(path_list, bgp_path_info) paths; unsigned int path_count; diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 786d07c5a9..20a285b9d9 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -626,6 +626,8 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc, } else if (nhr->nexthop_num) { struct peer *peer = bnc->nht_info; + prefix_copy(&bnc->resolved_prefix, &nhr->prefix); + /* notify bgp fsm if nbr ip goes from invalid->valid */ if (!bnc->nexthop_num) UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED); @@ -731,6 +733,7 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc, } } } else { + memset(&bnc->resolved_prefix, 0, sizeof(bnc->resolved_prefix)); bnc->flags &= ~BGP_NEXTHOP_EVPN_INCOMPLETE; bnc->flags &= ~BGP_NEXTHOP_VALID; bnc->flags &= ~BGP_NEXTHOP_LABELED_VALID; diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 78878013f8..78554893ff 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -3734,6 +3734,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, zlog_err("%pBP: Capability length error", peer); bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC); + pnt += length; return BGP_Stop; } action = *pnt; @@ -3746,7 +3747,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, action); bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC); - return BGP_Stop; + goto done; } if (bgp_debug_neighbor_events(peer)) @@ -3758,12 +3759,13 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, zlog_err("%pBP: Capability length error", peer); bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC); + pnt += length; return BGP_Stop; } /* Ignore capability when override-capability is set. */ if (CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) - continue; + goto done; capability = lookup_msg(capcode_str, hdr->code, "Unknown"); @@ -3778,7 +3780,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, peer, capability, sizeof(struct capability_mp_data), hdr->length); - return BGP_Stop; + goto done; } memcpy(&mpc, pnt + 3, sizeof(struct capability_mp_data)); @@ -3793,7 +3795,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, peer, capability, iana_afi2str(pkt_afi), iana_safi2str(pkt_safi)); - continue; + goto done; } /* Address family check. */ @@ -3820,7 +3822,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, if (peer_active_nego(peer)) bgp_clear_route(peer, afi, safi); else - return BGP_Stop; + goto done; } break; case CAPABILITY_CODE_RESTART: @@ -3830,7 +3832,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC); - return BGP_Stop; + goto done; } bgp_dynamic_capability_graceful_restart(pnt, action, @@ -3866,7 +3868,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE, BGP_NOTIFY_SUBCODE_UNSPECIFIC); - return BGP_Stop; + goto done; } uint8_t role; @@ -3888,6 +3890,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, break; } +done: pnt += hdr->length + 3; } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 88baa53510..a9c630f8c1 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3498,14 +3498,6 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, } #endif - group_announce_route(bgp, afi, safi, dest, new_select); - - /* unicast routes must also be annouced to labeled-unicast update-groups - */ - if (safi == SAFI_UNICAST) - group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest, - new_select); - /* FIB update. */ if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW) && !bgp_option_check(BGP_OPT_NO_FIB)) { @@ -3537,6 +3529,15 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, } } + group_announce_route(bgp, afi, safi, dest, new_select); + + /* unicast routes must also be annouced to labeled-unicast update-groups + */ + if (safi == SAFI_UNICAST) + group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest, + new_select); + + bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select, old_select); diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 989dbe43a3..5d7a8b2ba1 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -532,7 +532,7 @@ bool bgp_adj_out_set_subgroup(struct bgp_dest *dest, struct peer *adv_peer; struct peer_af *paf; struct bgp *bgp; - uint32_t attr_hash = attrhash_key_make(attr); + uint32_t attr_hash = 0; peer = SUBGRP_PEER(subgrp); afi = SUBGRP_AFI(subgrp); @@ -567,9 +567,11 @@ bool bgp_adj_out_set_subgroup(struct bgp_dest *dest, * the route wasn't changed actually. * Do not suppress BGP UPDATES for route-refresh. */ - if (CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_DUPLICATES) - && !CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES) - && adj->attr_hash == attr_hash) { + if (likely(CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_DUPLICATES))) + attr_hash = attrhash_key_make(attr); + + if (!CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES) && + attr_hash && adj->attr_hash == attr_hash) { if (BGP_DEBUG(update, UPDATE_OUT)) { char attr_str[BUFSIZ] = {0}; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 04d520a923..fda92270a8 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -2749,8 +2749,12 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient, /* Find the bgp route node */ dest = bgp_safi_node_lookup(bgp->rib[afi][safi], safi, &p, &bgp->vrf_prd); - if (!dest) + if (!dest) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: %pFX does not exist in the BGP table, nothing to do for %u", + __func__, &p, note); return -1; + } switch (note) { case ZAPI_ROUTE_INSTALLED: diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 3b8591fd52..4619fec6a7 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -1059,7 +1059,7 @@ BGP GR Global Mode Commands This command will enable BGP graceful restart functionality at the global level. -.. clicmd:: bgp graceful-restart disable +.. clicmd:: bgp graceful-restart-disable This command will disable both the functionality graceful restart and helper mode. diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst index d442faf0c1..40669a3c02 100644 --- a/doc/user/isisd.rst +++ b/doc/user/isisd.rst @@ -123,7 +123,7 @@ ISIS Timer Set LSP refresh interval in seconds, globally, for an area (level-1) or a domain (level-2). -.. clicmd:: max-lsp-lifetime [level-1 | level-2] (360-65535) +.. clicmd:: max-lsp-lifetime [level-1 | level-2] (350-65535) Set LSP maximum LSP lifetime in seconds, globally, for an area (level-1) or a domain (level-2). @@ -301,7 +301,7 @@ Showing ISIS information Show summary information about ISIS. -.. clicmd:: show isis hostname +.. clicmd:: show isis [vrf <NAME|all>] hostname Show information about ISIS node. @@ -320,17 +320,17 @@ Showing ISIS information Show the ISIS database globally, for a specific LSP id without or with details. -.. clicmd:: show isis topology [level-1|level-2] [algorithm [(128-255)]] +.. clicmd:: show isis [vrf <NAME|all>] topology [level-1|level-2] [algorithm [(128-255)]] Show topology IS-IS paths to Intermediate Systems, globally, in area (level-1) or domain (level-2). -.. clicmd:: show isis route [level-1|level-2] [prefix-sid|backup] [algorithm [(128-255)]] +.. clicmd:: show isis [vrf <NAME|all>] route [level-1|level-2] [prefix-sid|backup] [algorithm [(128-255)]] Show the ISIS routing table, as determined by the most recent SPF calculation. -.. clicmd:: show isis fast-reroute summary [level-1|level-2] +.. clicmd:: show isis [vrf <NAME|all>] fast-reroute summary [level-1|level-2] Show information about the number of prefixes having LFA protection, and network-wide LFA coverage. diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index cba1b91fae..7acd3a2b4e 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -687,7 +687,7 @@ void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json, default: continue; } - backup = (sra->type == ISIS_SR_LAN_BACKUP) ? " (backup)" + backup = (sra->type == ISIS_SR_ADJ_BACKUP) ? " (backup)" : ""; json_object_string_add(adj_sid_json, "nexthop", @@ -862,7 +862,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty, default: continue; } - backup = (sra->type == ISIS_SR_LAN_BACKUP) ? " (backup)" + backup = (sra->type == ISIS_SR_ADJ_BACKUP) ? " (backup)" : ""; vty_out(vty, " %s %s%s: %u\n", diff --git a/isisd/isis_lfa.c b/isisd/isis_lfa.c index 6f21f4cea2..4eb57aefb0 100644 --- a/isisd/isis_lfa.c +++ b/isisd/isis_lfa.c @@ -916,9 +916,8 @@ int isis_tilfa_check(struct isis_spftree *spftree_pc, adj = isis_adj_find(spftree_pc->area, spftree_pc->level, vertex->N.id); - if (adj - && isis_sr_adj_sid_find(adj, spftree_pc->family, - ISIS_SR_LAN_BACKUP)) { + if (adj && isis_sr_adj_sid_find(adj, spftree_pc->family, + ISIS_SR_ADJ_BACKUP)) { if (IS_DEBUG_LFA) zlog_debug( "ISIS-LFA: %s %s already covered by node protection", diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c index e8354fdf92..af22f56f8b 100644 --- a/isisd/isis_sr.c +++ b/isisd/isis_sr.c @@ -462,8 +462,7 @@ void isis_area_delete_backup_adj_sids(struct isis_area *area, int level) struct listnode *node, *nnode; for (ALL_LIST_ELEMENTS(area->srdb.adj_sids, node, nnode, sra)) - if (sra->type == ISIS_SR_LAN_BACKUP - && (sra->adj->level & level)) + if (sra->type == ISIS_SR_ADJ_BACKUP && (sra->adj->level & level)) sr_adj_sid_del(sra); } @@ -689,7 +688,7 @@ void sr_adj_sid_add_single(struct isis_adjacency *adj, int family, bool backup, circuit->ext = isis_alloc_ext_subtlvs(); sra = XCALLOC(MTYPE_ISIS_SR_INFO, sizeof(*sra)); - sra->type = backup ? ISIS_SR_LAN_BACKUP : ISIS_SR_ADJ_NORMAL; + sra->type = backup ? ISIS_SR_ADJ_BACKUP : ISIS_SR_ADJ_NORMAL; sra->input_label = input_label; sra->nexthop.family = family; sra->nexthop.address = nexthop; @@ -819,7 +818,7 @@ static void sr_adj_sid_del(struct sr_adjacency *sra) exit(1); } - if (sra->type == ISIS_SR_LAN_BACKUP && sra->backup_nexthops) { + if (sra->type == ISIS_SR_ADJ_BACKUP && sra->backup_nexthops) { sra->backup_nexthops->del = (void (*)(void *))isis_nexthop_delete; list_delete(&sra->backup_nexthops); diff --git a/isisd/isis_sr.h b/isisd/isis_sr.h index 4378760299..76f776825d 100644 --- a/isisd/isis_sr.h +++ b/isisd/isis_sr.h @@ -82,7 +82,7 @@ struct sr_local_block { /* Segment Routing Adjacency-SID type. */ enum sr_adj_type { ISIS_SR_ADJ_NORMAL = 0, - ISIS_SR_LAN_BACKUP, + ISIS_SR_ADJ_BACKUP, }; /* Segment Routing Adjacency. */ diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c index 18a0c49ceb..2412ec5e84 100644 --- a/isisd/isis_zebra.c +++ b/isisd/isis_zebra.c @@ -454,7 +454,7 @@ void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra) znh->labels[0] = MPLS_LABEL_IMPLICIT_NULL; /* Set backup nexthops. */ - if (sra->type == ISIS_SR_LAN_BACKUP) { + if (sra->type == ISIS_SR_ADJ_BACKUP) { int count; count = isis_zebra_add_nexthops(isis, sra->backup_nexthops, diff --git a/lib/srv6.c b/lib/srv6.c index dceb6ab48b..a82103e423 100644 --- a/lib/srv6.c +++ b/lib/srv6.c @@ -94,9 +94,11 @@ const char *seg6local_context2str(char *str, size_t size, snprintf(str, size, "table %u", ctx->table); return str; - case ZEBRA_SEG6_LOCAL_ACTION_END_DX2: case ZEBRA_SEG6_LOCAL_ACTION_END_B6: case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP: + snprintfrr(str, size, "nh6 %pI6", &ctx->nh6); + return str; + case ZEBRA_SEG6_LOCAL_ACTION_END_DX2: case ZEBRA_SEG6_LOCAL_ACTION_END_BM: case ZEBRA_SEG6_LOCAL_ACTION_END_S: case ZEBRA_SEG6_LOCAL_ACTION_END_AS: diff --git a/tests/topotests/bfd_topo3/test_bfd_topo3.py b/tests/topotests/bfd_topo3/test_bfd_topo3.py index f767b0e7b9..d7b2542f9f 100644 --- a/tests/topotests/bfd_topo3/test_bfd_topo3.py +++ b/tests/topotests/bfd_topo3/test_bfd_topo3.py @@ -189,7 +189,7 @@ def test_wait_bfd_convergence(): "show bfd peers json", bfd_config, ) - _, result = topotest.run_and_expect(test_func, None, count=130, wait=1) + _, result = topotest.run_and_expect(test_func, None, count=200, wait=1) assertmsg = '"{}" BFD configuration failure'.format(router) assert result is None, assertmsg diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py index c98d837069..489c59fa40 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py @@ -1,13 +1,13 @@ from lib.lutil import luCommand luCommand( - "r1", 'vtysh -c "show bgp next"', "99.0.0.. valid", "wait", "See CE static NH" + "r1", 'vtysh -c "show bgp nexthop"', "99.0.0.. valid", "wait", "See CE static NH" ) luCommand( - "r3", 'vtysh -c "show bgp next"', "99.0.0.. valid", "wait", "See CE static NH" + "r3", 'vtysh -c "show bgp nexthop"', "99.0.0.. valid", "wait", "See CE static NH" ) luCommand( - "r4", 'vtysh -c "show bgp next"', "99.0.0.. valid", "wait", "See CE static NH" + "r4", 'vtysh -c "show bgp nexthop"', "99.0.0.. valid", "wait", "See CE static NH" ) luCommand("r1", 'vtysh -c "show bgp ipv4 uni"', "i 5.*i 5", "wait", "See CE routes") luCommand("r3", 'vtysh -c "show bgp ipv4 uni"', "i 5.*i 5", "wait", "See CE routes") diff --git a/tests/topotests/bgp_peer_group/r1/bgpd.conf b/tests/topotests/bgp_peer_group/r1/bgpd.conf index 19b490a359..68d8e61a59 100644 --- a/tests/topotests/bgp_peer_group/r1/bgpd.conf +++ b/tests/topotests/bgp_peer_group/r1/bgpd.conf @@ -5,4 +5,8 @@ router bgp 65001 neighbor PG timers 3 10 neighbor 192.168.255.3 peer-group PG neighbor r1-eth0 interface peer-group PG + neighbor PG1 peer-group + neighbor PG1 remote-as external + neighbor PG1 timers 3 20 + neighbor 192.168.251.2 peer-group PG1 ! diff --git a/tests/topotests/bgp_peer_group/r1/zebra.conf b/tests/topotests/bgp_peer_group/r1/zebra.conf index e2c399e536..16fd8c538c 100644 --- a/tests/topotests/bgp_peer_group/r1/zebra.conf +++ b/tests/topotests/bgp_peer_group/r1/zebra.conf @@ -2,5 +2,8 @@ interface r1-eth0 ip address 192.168.255.1/24 ! +interface r1-eth1 + ip address 192.168.251.1/30 +! ip forwarding ! diff --git a/tests/topotests/bgp_peer_group/r2/bgpd.conf b/tests/topotests/bgp_peer_group/r2/bgpd.conf index 0880ee9fae..d0e8f017d1 100644 --- a/tests/topotests/bgp_peer_group/r2/bgpd.conf +++ b/tests/topotests/bgp_peer_group/r2/bgpd.conf @@ -4,4 +4,8 @@ router bgp 65002 neighbor PG remote-as external neighbor PG timers 3 10 neighbor r2-eth0 interface peer-group PG + neighbor PG1 peer-group + neighbor PG1 remote-as external + neighbor PG1 timers 3 20 + neighbor 192.168.251.1 peer-group PG1 ! diff --git a/tests/topotests/bgp_peer_group/r2/zebra.conf b/tests/topotests/bgp_peer_group/r2/zebra.conf index 606c17bec9..c2ad956c9c 100644 --- a/tests/topotests/bgp_peer_group/r2/zebra.conf +++ b/tests/topotests/bgp_peer_group/r2/zebra.conf @@ -2,5 +2,8 @@ interface r2-eth0 ip address 192.168.255.2/24 ! +interface r2-eth1 + ip address 192.168.251.2/30 +! ip forwarding ! diff --git a/tests/topotests/bgp_peer_group/test_bgp_peer-group.py b/tests/topotests/bgp_peer_group/test_bgp_peer-group.py index a91fade049..5cbcd19be9 100644 --- a/tests/topotests/bgp_peer_group/test_bgp_peer-group.py +++ b/tests/topotests/bgp_peer_group/test_bgp_peer-group.py @@ -22,7 +22,7 @@ sys.path.append(os.path.join(CWD, "../")) # pylint: disable=C0413 from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen - +from lib.topolog import logger pytestmark = [pytest.mark.bgpd] @@ -36,6 +36,10 @@ def build_topo(tgen): switch.add_link(tgen.gears["r2"]) switch.add_link(tgen.gears["r3"]) + 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__) @@ -70,6 +74,7 @@ def test_bgp_peer_group(): expected = { "r1-eth0": {"peerGroup": "PG", "bgpState": "Established"}, "192.168.255.3": {"peerGroup": "PG", "bgpState": "Established"}, + "192.168.251.2": {"peerGroup": "PG1", "bgpState": "Established"}, } return topotest.json_cmp(output, expected) @@ -96,6 +101,48 @@ def test_bgp_peer_group(): assert result is None, "Failed checking advertised routes from r3" +def test_bgp_peer_group_remote_as_del_readd(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r1 = tgen.gears["r1"] + logger.info("Remove bgp peer-group PG1 remote-as neighbor should be retained") + r1.cmd( + 'vtysh -c "config t" -c "router bgp 65001" ' + + ' -c "no neighbor PG1 remote-as external" ' + ) + + def _bgp_peer_group_remoteas_del(): + output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp neighbor json")) + expected = { + "192.168.251.2": {"peerGroup": "PG1", "bgpState": "Active"}, + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_peer_group_remoteas_del) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Failed bgp convergence in r1" + + logger.info("Re-add bgp peer-group PG1 remote-as neighbor should be established") + r1.cmd( + 'vtysh -c "config t" -c "router bgp 65001" ' + + ' -c "neighbor PG1 remote-as external" ' + ) + + def _bgp_peer_group_remoteas_add(): + output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp neighbor json")) + expected = { + "192.168.251.2": {"peerGroup": "PG1", "bgpState": "Established"}, + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_bgp_peer_group_remoteas_add) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assert result is None, "Failed bgp convergence in r1" + + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] sys.exit(pytest.main(args)) diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py index 2f69f7364b..985ba536dd 100644 --- a/tests/topotests/lib/topotest.py +++ b/tests/topotests/lib/topotest.py @@ -1296,6 +1296,8 @@ def fix_netns_limits(ns): sysctl_assure(ns, "net.ipv4.conf.all.ignore_routes_with_linkdown", 1) sysctl_assure(ns, "net.ipv6.conf.all.ignore_routes_with_linkdown", 1) + sysctl_assure(ns, "net.ipv4.conf.default.ignore_routes_with_linkdown", 1) + sysctl_assure(ns, "net.ipv6.conf.default.ignore_routes_with_linkdown", 1) # igmp sysctl_atleast(ns, "net.ipv4.igmp_max_memberships", 1000) diff --git a/zebra/interface.c b/zebra/interface.c index 94b86569b2..b824977f9e 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1745,6 +1745,9 @@ interface_bridge_vxlan_vlan_vni_map_update(struct zebra_dplane_ctx *ctx, vlanid_t vid; int i; + if (vniarray == NULL) + return; + memset(&vni_start, 0, sizeof(vni_start)); memset(&vni_end, 0, sizeof(vni_end)); diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 90695261eb..cc2cf9b9ff 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -2291,7 +2291,7 @@ int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p, new_client = true; } else { /* Check if the FEC has been statically defined in the config */ - is_configured_fec = fec->flags & FEC_FLAG_CONFIGURED; + is_configured_fec = CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED); /* Client may register same FEC with different label index. */ new_client = (listnode_lookup(fec->client_list, client) == NULL); @@ -2382,8 +2382,8 @@ int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p, /* If not a configured entry, delete the FEC if no other clients. Before * deleting, see if any LSP needs to be uninstalled. */ - if (!(fec->flags & FEC_FLAG_CONFIGURED) - && list_isempty(fec->client_list)) { + if (!CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED) && + 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); |
