summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c38
-rw-r--r--bgpd/bgp_nexthop.c4
-rw-r--r--bgpd/bgp_nexthop.h1
-rw-r--r--bgpd/bgp_nht.c3
-rw-r--r--bgpd/bgp_packet.c17
-rw-r--r--bgpd/bgp_route.c17
-rw-r--r--bgpd/bgp_updgrp_adv.c10
-rw-r--r--bgpd/bgp_zebra.c6
-rw-r--r--doc/user/bgp.rst2
-rw-r--r--doc/user/isisd.rst10
-rw-r--r--isisd/isis_adjacency.c4
-rw-r--r--isisd/isis_lfa.c5
-rw-r--r--isisd/isis_sr.c7
-rw-r--r--isisd/isis_sr.h2
-rw-r--r--isisd/isis_zebra.c2
-rw-r--r--lib/srv6.c4
-rw-r--r--tests/topotests/bfd_topo3/test_bfd_topo3.py2
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py6
-rw-r--r--tests/topotests/bgp_peer_group/r1/bgpd.conf4
-rw-r--r--tests/topotests/bgp_peer_group/r1/zebra.conf3
-rw-r--r--tests/topotests/bgp_peer_group/r2/bgpd.conf4
-rw-r--r--tests/topotests/bgp_peer_group/r2/zebra.conf3
-rw-r--r--tests/topotests/bgp_peer_group/test_bgp_peer-group.py49
-rw-r--r--tests/topotests/lib/topotest.py2
-rw-r--r--zebra/interface.c3
-rw-r--r--zebra/zebra_mpls.c6
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);