diff options
| -rw-r--r-- | bgpd/bgp_mplsvpn.c | 376 | ||||
| -rw-r--r-- | bgpd/bgp_mplsvpn.h | 20 | ||||
| -rw-r--r-- | bgpd/bgp_packet.c | 8 | ||||
| -rw-r--r-- | bgpd/bgp_updgrp.c | 26 | ||||
| -rw-r--r-- | bgpd/bgp_updgrp.h | 7 | ||||
| -rw-r--r-- | bgpd/bgp_updgrp_adv.c | 48 | ||||
| -rw-r--r-- | bgpd/bgp_updgrp_packet.c | 14 | ||||
| -rw-r--r-- | bgpd/bgpd.c | 24 | ||||
| -rw-r--r-- | configure.ac | 7 | ||||
| -rwxr-xr-x | debian/rules | 7 | ||||
| -rw-r--r-- | doc/developer/packaging-debian.rst | 4 | ||||
| -rw-r--r-- | lib/routemap.c | 12 | ||||
| -rw-r--r-- | lib/routemap.h | 4 | ||||
| -rw-r--r-- | pimd/pim_bsm.c | 17 | ||||
| -rw-r--r-- | pimd/pim_cmd.c | 28 | ||||
| -rw-r--r-- | pimd/pim_rp.c | 10 | ||||
| -rw-r--r-- | pimd/subdir.am | 10 | ||||
| -rw-r--r-- | redhat/frr.spec.in | 18 | ||||
| -rw-r--r-- | tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py | 2102 | ||||
| -rwxr-xr-x | tools/frrcommon.sh.in | 4 | ||||
| -rw-r--r-- | zebra/zebra_evpn_neigh.c | 5 |
21 files changed, 2474 insertions, 277 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index cc4ff57f4e..52180b3e48 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -767,23 +767,74 @@ static void unsetsids(struct bgp_path_info *bpi) memset(extra->sid, 0, sizeof(extra->sid)); } +static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn, + struct attr *new_attr, afi_t afi, + safi_t safi, + struct bgp_path_info *source_bpi, + struct bgp_path_info *bpi, + struct bgp *bgp_orig, + const struct prefix *p, int debug) +{ + struct bgp_path_info *bpi_ultimate; + struct bgp *bgp_nexthop; + bool nh_valid; + + bpi_ultimate = bgp_get_imported_bpi_ultimate(source_bpi); + + if (bpi->extra && bpi->extra->bgp_orig) + bgp_nexthop = bpi->extra->bgp_orig; + else + bgp_nexthop = bgp_orig; + + /* + * No nexthop tracking for redistributed routes or for + * EVPN-imported routes that get leaked. + */ + if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE || + is_pi_family_evpn(bpi_ultimate)) + nh_valid = 1; + else + /* + * TBD do we need to do anything about the + * 'connected' parameter? + */ + nh_valid = bgp_find_or_add_nexthop(to_bgp, bgp_nexthop, afi, + safi, bpi, NULL, 0, p); + + /* + * If you are using SRv6 VPN instead of MPLS, it need to check + * the SID allocation. If the sid is not allocated, the rib + * will be invalid. + */ + if (to_bgp->srv6_enabled && + (!new_attr->srv6_l3vpn && !new_attr->srv6_vpn)) { + nh_valid = false; + } + + if (debug) + zlog_debug("%s: %pFX nexthop is %svalid (in vrf %s)", __func__, + p, (nh_valid ? "" : "not "), + bgp_nexthop->name_pretty); + + return nh_valid; +} + /* * returns pointer to new bgp_path_info upon success */ static struct bgp_path_info * -leak_update(struct bgp *bgp, /* destination bgp instance */ - struct bgp_dest *bn, struct attr *new_attr, /* already interned */ +leak_update(struct bgp *to_bgp, struct bgp_dest *bn, + struct attr *new_attr, /* already interned */ afi_t afi, safi_t safi, struct bgp_path_info *source_bpi, - mpls_label_t *label, uint32_t num_labels, void *parent, - struct bgp *bgp_orig, struct prefix *nexthop_orig, - int nexthop_self_flag, int debug) + mpls_label_t *label, uint32_t num_labels, struct bgp *bgp_orig, + struct prefix *nexthop_orig, int nexthop_self_flag, int debug) { const struct prefix *p = bgp_dest_get_prefix(bn); struct bgp_path_info *bpi; - struct bgp_path_info *bpi_ultimate; struct bgp_path_info *new; struct bgp_path_info_extra *extra; uint32_t num_sids = 0; + void *parent = source_bpi; if (new_attr->srv6_l3vpn || new_attr->srv6_vpn) num_sids = 1; @@ -791,7 +842,7 @@ leak_update(struct bgp *bgp, /* destination bgp instance */ if (debug) zlog_debug( "%s: entry: leak-to=%s, p=%pBD, type=%d, sub_type=%d", - __func__, bgp->name_pretty, bn, source_bpi->type, + __func__, to_bgp->name_pretty, bn, source_bpi->type, source_bpi->sub_type); /* @@ -809,7 +860,6 @@ leak_update(struct bgp *bgp, /* destination bgp instance */ * schemes that could be implemented in the future. * */ - bpi_ultimate = bgp_get_imported_bpi_ultimate(source_bpi); /* * match parent @@ -827,7 +877,7 @@ leak_update(struct bgp *bgp, /* destination bgp instance */ if (debug) { zlog_debug( "%s: ->%s(s_flags: 0x%x b_flags: 0x%x): %pFX: Found route, being removed, not leaking", - __func__, bgp->name_pretty, + __func__, to_bgp->name_pretty, source_bpi->flags, bpi->flags, p); } return NULL; @@ -840,7 +890,7 @@ leak_update(struct bgp *bgp, /* destination bgp instance */ if (debug) zlog_debug( "%s: ->%s: %pBD: Found route, no change", - __func__, bgp->name_pretty, bn); + __func__, to_bgp->name_pretty, bn); return NULL; } @@ -858,8 +908,9 @@ leak_update(struct bgp *bgp, /* destination bgp instance */ if (!ecommunity_cmp( bgp_attr_get_ecommunity(bpi->attr), bgp_attr_get_ecommunity(new_attr))) { - vpn_leak_to_vrf_withdraw(bgp, bpi); - bgp_aggregate_decrement(bgp, p, bpi, afi, safi); + vpn_leak_to_vrf_withdraw(to_bgp, bpi); + bgp_aggregate_decrement(to_bgp, p, bpi, afi, + safi); bgp_path_info_delete(bn, bpi); } } @@ -871,7 +922,7 @@ leak_update(struct bgp *bgp, /* destination bgp instance */ if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) bgp_path_info_restore(bn, bpi); else - bgp_aggregate_decrement(bgp, p, bpi, afi, safi); + bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi); bgp_attr_unintern(&bpi->attr); bpi->attr = new_attr; bpi->uptime = bgp_clock(); @@ -914,54 +965,21 @@ leak_update(struct bgp *bgp, /* destination bgp instance */ if (nexthop_self_flag) bgp_path_info_set_flag(bn, bpi, BGP_PATH_ANNC_NH_SELF); - struct bgp *bgp_nexthop = bgp; - int nh_valid; - - if (bpi->extra && bpi->extra->bgp_orig) - bgp_nexthop = bpi->extra->bgp_orig; - - /* - * No nexthop tracking for redistributed routes or for - * EVPN-imported routes that get leaked. - */ - if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE || - is_pi_family_evpn(bpi_ultimate)) - nh_valid = 1; + if (leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi, + source_bpi, bpi, bgp_orig, p, + debug)) + bgp_path_info_set_flag(bn, bpi, BGP_PATH_VALID); else - /* - * TBD do we need to do anything about the - * 'connected' parameter? - */ - nh_valid = bgp_find_or_add_nexthop( - bgp, bgp_nexthop, afi, safi, bpi, NULL, 0, p); - - /* - * If you are using SRv6 VPN instead of MPLS, it need to check - * the SID allocation. If the sid is not allocated, the rib - * will be invalid. - */ - if (bgp->srv6_enabled - && (!new_attr->srv6_l3vpn && !new_attr->srv6_vpn)) { bgp_path_info_unset_flag(bn, bpi, BGP_PATH_VALID); - nh_valid = false; - } - - if (debug) - zlog_debug("%s: nexthop is %svalid (in vrf %s)", - __func__, (nh_valid ? "" : "not "), - bgp_nexthop->name_pretty); - - if (nh_valid) - bgp_path_info_set_flag(bn, bpi, BGP_PATH_VALID); /* Process change. */ - bgp_aggregate_increment(bgp, p, bpi, afi, safi); - bgp_process(bgp, bn, afi, safi); + bgp_aggregate_increment(to_bgp, p, bpi, afi, safi); + bgp_process(to_bgp, bn, afi, safi); bgp_dest_unlock_node(bn); if (debug) zlog_debug("%s: ->%s: %pBD Found route, changed attr", - __func__, bgp->name_pretty, bn); + __func__, to_bgp->name_pretty, bn); return bpi; } @@ -970,14 +988,14 @@ leak_update(struct bgp *bgp, /* destination bgp instance */ if (debug) { zlog_debug( "%s: ->%s(s_flags: 0x%x): %pFX: New route, being removed, not leaking", - __func__, bgp->name_pretty, + __func__, to_bgp->name_pretty, source_bpi->flags, p); } return NULL; } new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0, - bgp->peer_self, new_attr, bn); + to_bgp->peer_self, new_attr, bn); if (nexthop_self_flag) bgp_path_info_set_flag(bn, new, BGP_PATH_ANNC_NH_SELF); @@ -1019,67 +1037,28 @@ leak_update(struct bgp *bgp, /* destination bgp instance */ if (nexthop_orig) new->extra->nexthop_orig = *nexthop_orig; - /* - * nexthop tracking for unicast routes - */ - struct bgp *bgp_nexthop = bgp; - int nh_valid; - - if (new->extra->bgp_orig) - bgp_nexthop = new->extra->bgp_orig; - - /* - * No nexthop tracking for redistributed routes because - * their originating protocols will do the tracking and - * withdraw those routes if the nexthops become unreachable - * This also holds good for EVPN-imported routes that get - * leaked. - */ - if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE || - is_pi_family_evpn(bpi_ultimate)) - nh_valid = 1; + if (leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi, + source_bpi, new, bgp_orig, p, debug)) + bgp_path_info_set_flag(bn, new, BGP_PATH_VALID); else - /* - * TBD do we need to do anything about the - * 'connected' parameter? - */ - nh_valid = bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, safi, - new, NULL, 0, p); - - /* - * If you are using SRv6 VPN instead of MPLS, it need to check - * the SID allocation. If the sid is not allocated, the rib - * will be invalid. - */ - if (bgp->srv6_enabled - && (!new->attr->srv6_l3vpn && !new->attr->srv6_vpn)) { bgp_path_info_unset_flag(bn, new, BGP_PATH_VALID); - nh_valid = false; - } - - if (debug) - zlog_debug("%s: nexthop is %svalid (in vrf %s)", - __func__, (nh_valid ? "" : "not "), - bgp_nexthop->name_pretty); - if (nh_valid) - bgp_path_info_set_flag(bn, new, BGP_PATH_VALID); - bgp_aggregate_increment(bgp, p, new, afi, safi); + bgp_aggregate_increment(to_bgp, p, new, afi, safi); bgp_path_info_add(bn, new); bgp_dest_unlock_node(bn); - bgp_process(bgp, bn, afi, safi); + bgp_process(to_bgp, bn, afi, safi); if (debug) zlog_debug("%s: ->%s: %pBD: Added new route", __func__, - bgp->name_pretty, bn); + to_bgp->name_pretty, bn); return new; } /* cf vnc_import_bgp_add_route_mode_nvegroup() and add_vnc_route() */ -void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ - struct bgp *bgp_vrf, /* from */ +void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */ + struct bgp *from_bgp, /* from */ struct bgp_path_info *path_vrf) /* route */ { int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF); @@ -1095,7 +1074,7 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ int nexthop_self_flag = 0; if (debug) - zlog_debug("%s: from vrf %s", __func__, bgp_vrf->name_pretty); + zlog_debug("%s: from vrf %s", __func__, from_bgp->name_pretty); if (debug && bgp_attr_get_ecommunity(path_vrf->attr)) { char *s = ecommunity_ecom2str( @@ -1103,11 +1082,11 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ ECOMMUNITY_FORMAT_ROUTE_MAP, 0); zlog_debug("%s: %s path_vrf->type=%d, EC{%s}", __func__, - bgp_vrf->name, path_vrf->type, s); + from_bgp->name, path_vrf->type, s); XFREE(MTYPE_ECOMMUNITY_STR, s); } - if (!bgp_vpn) + if (!to_bgp) return; if (!afi) { @@ -1120,10 +1099,10 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ if (!is_route_injectable_into_vpn(path_vrf)) return; - if (!vpn_leak_to_vpn_active(bgp_vrf, afi, &debugmsg)) { + if (!vpn_leak_to_vpn_active(from_bgp, afi, &debugmsg)) { if (debug) zlog_debug("%s: %s skipping: %s", __func__, - bgp_vrf->name, debugmsg); + from_bgp->name, debugmsg); return; } @@ -1133,23 +1112,23 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ /* * route map handling */ - if (bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN]) { + if (from_bgp->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN]) { struct bgp_path_info info; route_map_result_t ret; memset(&info, 0, sizeof(info)); - info.peer = bgp_vpn->peer_self; + info.peer = to_bgp->peer_self; info.attr = &static_attr; - ret = route_map_apply( - bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN], - p, &info); + ret = route_map_apply(from_bgp->vpn_policy[afi] + .rmap[BGP_VPN_POLICY_DIR_TOVPN], + p, &info); if (RMAP_DENYMATCH == ret) { bgp_attr_flush(&static_attr); /* free any added parts */ if (debug) zlog_debug( "%s: vrf %s route map \"%s\" says DENY, returning", - __func__, bgp_vrf->name_pretty, - bgp_vrf->vpn_policy[afi] + __func__, from_bgp->name_pretty, + from_bgp->vpn_policy[afi] .rmap[BGP_VPN_POLICY_DIR_TOVPN] ->name); return; @@ -1177,17 +1156,17 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ old_ecom = bgp_attr_get_ecommunity(&static_attr); if (old_ecom) { new_ecom = ecommunity_dup(old_ecom); - if (CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST], - BGP_CONFIG_VRF_TO_VRF_EXPORT)) + if (CHECK_FLAG(from_bgp->af_flags[afi][SAFI_UNICAST], + BGP_CONFIG_VRF_TO_VRF_EXPORT)) ecommunity_strip_rts(new_ecom); - new_ecom = ecommunity_merge(new_ecom, - bgp_vrf->vpn_policy[afi] - .rtlist[BGP_VPN_POLICY_DIR_TOVPN]); + new_ecom = ecommunity_merge( + new_ecom, from_bgp->vpn_policy[afi] + .rtlist[BGP_VPN_POLICY_DIR_TOVPN]); if (!old_ecom->refcnt) ecommunity_free(&old_ecom); } else { new_ecom = ecommunity_dup( - bgp_vrf->vpn_policy[afi] + from_bgp->vpn_policy[afi] .rtlist[BGP_VPN_POLICY_DIR_TOVPN]); } bgp_attr_set_ecommunity(&static_attr, new_ecom); @@ -1204,10 +1183,10 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ /* Nexthop */ /* if policy nexthop not set, use 0 */ - if (CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags, + if (CHECK_FLAG(from_bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_NEXTHOP_SET)) { struct prefix *nexthop = - &bgp_vrf->vpn_policy[afi].tovpn_nexthop; + &from_bgp->vpn_policy[afi].tovpn_nexthop; switch (nexthop->family) { case AF_INET: @@ -1228,7 +1207,7 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ assert(0); } } else { - if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST], + if (!CHECK_FLAG(from_bgp->af_flags[afi][SAFI_UNICAST], BGP_CONFIG_VRF_TO_VRF_EXPORT)) { if (afi == AFI_IP) { /* @@ -1266,7 +1245,7 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ nexthop_self_flag = 1; } - label_val = bgp_vrf->vpn_policy[afi].tovpn_label; + label_val = from_bgp->vpn_policy[afi].tovpn_label; if (label_val == MPLS_LABEL_NONE) { encode_label(MPLS_LABEL_IMPLICIT_NULL, &label); } else { @@ -1275,12 +1254,13 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ /* Set originator ID to "me" */ SET_FLAG(static_attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)); - static_attr.originator_id = bgp_vpn->router_id; + static_attr.originator_id = to_bgp->router_id; /* Set SID for SRv6 VPN */ - if (bgp_vrf->vpn_policy[afi].tovpn_sid_locator) { - encode_label(bgp_vrf->vpn_policy[afi].tovpn_sid_transpose_label, - &label); + if (from_bgp->vpn_policy[afi].tovpn_sid_locator) { + encode_label( + from_bgp->vpn_policy[afi].tovpn_sid_transpose_label, + &label); static_attr.srv6_l3vpn = XCALLOC(MTYPE_BGP_SRV6_L3VPN, sizeof(struct bgp_attr_srv6_l3vpn)); static_attr.srv6_l3vpn->sid_flags = 0x00; @@ -1298,7 +1278,7 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ static_attr.srv6_l3vpn->transposition_offset = BGP_PREFIX_SID_SRV6_TRANSPOSITION_OFFSET; memcpy(&static_attr.srv6_l3vpn->sid, - bgp_vrf->vpn_policy[afi].tovpn_sid_locator, + from_bgp->vpn_policy[afi].tovpn_sid_locator, sizeof(struct in6_addr)); } @@ -1317,14 +1297,14 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ /* Now new_attr is an allocated interned attr */ - bn = bgp_afi_node_get(bgp_vpn->rib[afi][safi], afi, safi, p, - &(bgp_vrf->vpn_policy[afi].tovpn_rd)); + bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p, + &(from_bgp->vpn_policy[afi].tovpn_rd)); struct bgp_path_info *new_info; - new_info = leak_update(bgp_vpn, bn, new_attr, afi, safi, path_vrf, - &label, 1, path_vrf, bgp_vrf, NULL, - nexthop_self_flag, debug); + new_info = + leak_update(to_bgp, bn, new_attr, afi, safi, path_vrf, &label, + 1, from_bgp, NULL, nexthop_self_flag, debug); /* * Routes actually installed in the vpn RIB must also be @@ -1336,11 +1316,11 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ * because of loop checking. */ if (new_info) - vpn_leak_to_vrf_update(bgp_vrf, new_info); + vpn_leak_to_vrf_update(from_bgp, new_info); } -void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */ - struct bgp *bgp_vrf, /* from */ +void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp, /* to */ + struct bgp *from_bgp, /* from */ struct bgp_path_info *path_vrf) /* route */ { int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF); @@ -1354,11 +1334,11 @@ void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */ if (debug) { zlog_debug( "%s: entry: leak-from=%s, p=%pBD, type=%d, sub_type=%d", - __func__, bgp_vrf->name_pretty, path_vrf->net, + __func__, from_bgp->name_pretty, path_vrf->net, path_vrf->type, path_vrf->sub_type); } - if (!bgp_vpn) + if (!to_bgp) return; if (!afi) { @@ -1371,7 +1351,7 @@ void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */ if (!is_route_injectable_into_vpn(path_vrf)) return; - if (!vpn_leak_to_vpn_active(bgp_vrf, afi, &debugmsg)) { + if (!vpn_leak_to_vpn_active(from_bgp, afi, &debugmsg)) { if (debug) zlog_debug("%s: skipping: %s", __func__, debugmsg); return; @@ -1380,8 +1360,8 @@ void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */ if (debug) zlog_debug("%s: withdrawing (path_vrf=%p)", __func__, path_vrf); - bn = bgp_afi_node_get(bgp_vpn->rib[afi][safi], afi, safi, p, - &(bgp_vrf->vpn_policy[afi].tovpn_rd)); + bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p, + &(from_bgp->vpn_policy[afi].tovpn_rd)); if (!bn) return; @@ -1397,17 +1377,16 @@ void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */ if (bpi) { /* withdraw from looped vrfs as well */ - vpn_leak_to_vrf_withdraw(bgp_vpn, bpi); + vpn_leak_to_vrf_withdraw(to_bgp, bpi); - bgp_aggregate_decrement(bgp_vpn, p, bpi, afi, safi); + bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi); bgp_path_info_delete(bn, bpi); - bgp_process(bgp_vpn, bn, afi, safi); + bgp_process(to_bgp, bn, afi, safi); } bgp_dest_unlock_node(bn); } -void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */ - struct bgp *bgp_vrf, /* from */ +void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp, afi_t afi) { int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF); @@ -1415,9 +1394,9 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */ safi_t safi = SAFI_MPLS_VPN; /* - * Walk vpn table, delete bpi with bgp_orig == bgp_vrf + * Walk vpn table, delete bpi with bgp_orig == from_bgp */ - for (pdest = bgp_table_top(bgp_vpn->rib[afi][safi]); pdest; + for (pdest = bgp_table_top(to_bgp->rib[afi][safi]); pdest; pdest = bgp_route_next(pdest)) { struct bgp_table *table; @@ -1446,28 +1425,26 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */ continue; if (!bpi->extra) continue; - if ((struct bgp *)bpi->extra->bgp_orig - == bgp_vrf) { + if ((struct bgp *)bpi->extra->bgp_orig == + from_bgp) { /* delete route */ if (debug) zlog_debug("%s: deleting it", __func__); /* withdraw from leak-to vrfs as well */ - vpn_leak_to_vrf_withdraw(bgp_vpn, bpi); + vpn_leak_to_vrf_withdraw(to_bgp, bpi); bgp_aggregate_decrement( - bgp_vpn, - bgp_dest_get_prefix(bn), bpi, - afi, safi); + to_bgp, bgp_dest_get_prefix(bn), + bpi, afi, safi); bgp_path_info_delete(bn, bpi); - bgp_process(bgp_vpn, bn, afi, safi); + bgp_process(to_bgp, bn, afi, safi); } } } } } -void vpn_leak_from_vrf_update_all(struct bgp *bgp_vpn, /* to */ - struct bgp *bgp_vrf, /* from */ +void vpn_leak_from_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp, afi_t afi) { struct bgp_dest *bn; @@ -1476,9 +1453,9 @@ void vpn_leak_from_vrf_update_all(struct bgp *bgp_vpn, /* to */ if (debug) zlog_debug("%s: entry, afi=%d, vrf=%s", __func__, afi, - bgp_vrf->name_pretty); + from_bgp->name_pretty); - for (bn = bgp_table_top(bgp_vrf->rib[afi][SAFI_UNICAST]); bn; + for (bn = bgp_table_top(from_bgp->rib[afi][SAFI_UNICAST]); bn; bn = bgp_route_next(bn)) { if (debug) @@ -1490,14 +1467,14 @@ void vpn_leak_from_vrf_update_all(struct bgp *bgp_vpn, /* to */ zlog_debug( "%s: calling vpn_leak_from_vrf_update", __func__); - vpn_leak_from_vrf_update(bgp_vpn, bgp_vrf, bpi); + vpn_leak_from_vrf_update(to_bgp, from_bgp, bpi); } } } static void -vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ - struct bgp *bgp_vpn, /* from */ +vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */ + struct bgp *from_bgp, /* from */ struct bgp_path_info *path_vpn) /* route */ { const struct prefix *p = bgp_dest_get_prefix(path_vpn->net); @@ -1518,7 +1495,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF); - if (!vpn_leak_from_vpn_active(bgp_vrf, afi, &debugmsg)) { + if (!vpn_leak_from_vpn_active(to_bgp, afi, &debugmsg)) { if (debug) zlog_debug("%s: skipping: %s", __func__, debugmsg); return; @@ -1526,18 +1503,18 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ /* Check for intersection of route targets */ if (!ecom_intersect( - bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN], + to_bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN], bgp_attr_get_ecommunity(path_vpn->attr))) { if (debug) zlog_debug( "from vpn (%s) to vrf (%s), skipping after no intersection of route targets", - bgp_vpn->name_pretty, bgp_vrf->name_pretty); + from_bgp->name_pretty, to_bgp->name_pretty); return; } if (debug) zlog_debug("%s: updating %pFX to vrf %s", __func__, p, - bgp_vrf->name_pretty); + to_bgp->name_pretty); /* shallow copy */ static_attr = *path_vpn->attr; @@ -1547,8 +1524,8 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ /* If doing VRF-to-VRF leaking, strip RTs. */ old_ecom = bgp_attr_get_ecommunity(&static_attr); - if (old_ecom && CHECK_FLAG(bgp_vrf->af_flags[afi][safi], - BGP_CONFIG_VRF_TO_VRF_IMPORT)) { + if (old_ecom && CHECK_FLAG(to_bgp->af_flags[afi][safi], + BGP_CONFIG_VRF_TO_VRF_IMPORT)) { new_ecom = ecommunity_dup(old_ecom); ecommunity_strip_rts(new_ecom); bgp_attr_set_ecommunity(&static_attr, new_ecom); @@ -1580,7 +1557,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ nexthop_orig.u.prefix4 = path_vpn->attr->mp_nexthop_global_in; nexthop_orig.prefixlen = IPV4_MAX_BITLEN; - if (CHECK_FLAG(bgp_vrf->af_flags[afi][safi], + if (CHECK_FLAG(to_bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_VRF_IMPORT)) { static_attr.nexthop.s_addr = nexthop_orig.u.prefix4.s_addr; @@ -1597,7 +1574,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ nexthop_orig.u.prefix6 = path_vpn->attr->mp_nexthop_global; nexthop_orig.prefixlen = IPV6_MAX_BITLEN; - if (CHECK_FLAG(bgp_vrf->af_flags[afi][safi], + if (CHECK_FLAG(to_bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_VRF_IMPORT)) { static_attr.mp_nexthop_global = nexthop_orig.u.prefix6; } @@ -1607,15 +1584,15 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ /* * route map handling */ - if (bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN]) { + if (to_bgp->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN]) { struct bgp_path_info info; route_map_result_t ret; memset(&info, 0, sizeof(info)); - info.peer = bgp_vrf->peer_self; + info.peer = to_bgp->peer_self; info.attr = &static_attr; info.extra = path_vpn->extra; /* Used for source-vrf filter */ - ret = route_map_apply(bgp_vrf->vpn_policy[afi] + ret = route_map_apply(to_bgp->vpn_policy[afi] .rmap[BGP_VPN_POLICY_DIR_FROMVPN], p, &info); if (RMAP_DENYMATCH == ret) { @@ -1623,8 +1600,8 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ if (debug) zlog_debug( "%s: vrf %s vpn-policy route map \"%s\" says DENY, returning", - __func__, bgp_vrf->name_pretty, - bgp_vrf->vpn_policy[afi] + __func__, to_bgp->name_pretty, + to_bgp->vpn_policy[afi] .rmap[BGP_VPN_POLICY_DIR_FROMVPN] ->name); return; @@ -1640,7 +1617,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ new_attr = bgp_attr_intern(&static_attr); bgp_attr_flush(&static_attr); - bn = bgp_afi_node_get(bgp_vrf->rib[afi][safi], afi, safi, p, NULL); + bn = bgp_afi_node_get(to_bgp->rib[afi][safi], afi, safi, p, NULL); /* * ensure labels are copied @@ -1654,7 +1631,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ * labels for these routes enables the non-labeled nexthops * from the originating VRF to be considered valid for this route. */ - if (!CHECK_FLAG(bgp_vrf->af_flags[afi][safi], + if (!CHECK_FLAG(to_bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_VRF_IMPORT)) { /* work back to original route */ bpi_ultimate = bgp_get_imported_bpi_ultimate(path_vpn); @@ -1692,14 +1669,14 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ if (path_vpn->extra && path_vpn->extra->bgp_orig) src_vrf = path_vpn->extra->bgp_orig; else - src_vrf = bgp_vpn; + src_vrf = from_bgp; - leak_update(bgp_vrf, bn, new_attr, afi, safi, path_vpn, pLabels, - num_labels, path_vpn, /* parent */ - src_vrf, &nexthop_orig, nexthop_self_flag, debug); + leak_update(to_bgp, bn, new_attr, afi, safi, path_vpn, pLabels, + num_labels, src_vrf, &nexthop_orig, nexthop_self_flag, + debug); } -void vpn_leak_to_vrf_update(struct bgp *bgp_vpn, /* from */ +void vpn_leak_to_vrf_update(struct bgp *from_bgp, /* from */ struct bgp_path_info *path_vpn) /* route */ { struct listnode *mnode, *mnnode; @@ -1715,12 +1692,12 @@ void vpn_leak_to_vrf_update(struct bgp *bgp_vpn, /* from */ if (!path_vpn->extra || path_vpn->extra->bgp_orig != bgp) { /* no loop */ - vpn_leak_to_vrf_update_onevrf(bgp, bgp_vpn, path_vpn); + vpn_leak_to_vrf_update_onevrf(bgp, from_bgp, path_vpn); } } } -void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */ +void vpn_leak_to_vrf_withdraw(struct bgp *from_bgp, /* from */ struct bgp_path_info *path_vpn) /* route */ { const struct prefix *p; @@ -1804,8 +1781,7 @@ void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */ } } -void vpn_leak_to_vrf_withdraw_all(struct bgp *bgp_vrf, /* to */ - afi_t afi) +void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi) { struct bgp_dest *bn; struct bgp_path_info *bpi; @@ -1817,40 +1793,38 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *bgp_vrf, /* to */ /* * Walk vrf table, delete bpi with bgp_orig in a different vrf */ - for (bn = bgp_table_top(bgp_vrf->rib[afi][safi]); bn; + for (bn = bgp_table_top(to_bgp->rib[afi][safi]); bn; bn = bgp_route_next(bn)) { for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) { - if (bpi->extra - && bpi->extra->bgp_orig != bgp_vrf - && bpi->extra->parent - && is_pi_family_vpn(bpi->extra->parent)) { + if (bpi->extra && bpi->extra->bgp_orig != to_bgp && + bpi->extra->parent && + is_pi_family_vpn(bpi->extra->parent)) { /* delete route */ - bgp_aggregate_decrement(bgp_vrf, + bgp_aggregate_decrement(to_bgp, bgp_dest_get_prefix(bn), bpi, afi, safi); bgp_path_info_delete(bn, bpi); - bgp_process(bgp_vrf, bn, afi, safi); + bgp_process(to_bgp, bn, afi, safi); } } } } -void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, /* to */ - struct bgp *bgp_vpn, /* from */ +void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *vpn_from, afi_t afi) { struct bgp_dest *pdest; safi_t safi = SAFI_MPLS_VPN; - assert(bgp_vpn); + assert(vpn_from); /* * Walk vpn table */ - for (pdest = bgp_table_top(bgp_vpn->rib[afi][safi]); pdest; + for (pdest = bgp_table_top(vpn_from->rib[afi][safi]); pdest; pdest = bgp_route_next(pdest)) { struct bgp_table *table; struct bgp_dest *bn; @@ -1867,11 +1841,11 @@ void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, /* to */ for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) { - if (bpi->extra - && bpi->extra->bgp_orig == bgp_vrf) + if (bpi->extra && + bpi->extra->bgp_orig == to_bgp) continue; - vpn_leak_to_vrf_update_onevrf(bgp_vrf, bgp_vpn, + vpn_leak_to_vrf_update_onevrf(to_bgp, vpn_from, bpi); } } diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 8c2eae279c..fcabb16435 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -53,27 +53,27 @@ extern int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd, enum bgp_show_type type, void *output_arg, int tags, bool use_json); -extern void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, struct bgp *bgp_vrf, +extern void vpn_leak_from_vrf_update(struct bgp *to_bgp, struct bgp *from_bgp, struct bgp_path_info *path_vrf); -extern void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, struct bgp *bgp_vrf, +extern void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp, struct bgp *from_bgp, struct bgp_path_info *path_vrf); -extern void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, - struct bgp *bgp_vrf, afi_t afi); +extern void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, + struct bgp *from_bgp, afi_t afi); -extern void vpn_leak_from_vrf_update_all(struct bgp *bgp_vpn, - struct bgp *bgp_vrf, afi_t afi); +extern void vpn_leak_from_vrf_update_all(struct bgp *to_bgp, + struct bgp *from_bgp, afi_t afi); -extern void vpn_leak_to_vrf_withdraw_all(struct bgp *bgp_vrf, afi_t afi); +extern void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi); -extern void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, struct bgp *bgp_vpn, +extern void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *from_bgp, afi_t afi); -extern void vpn_leak_to_vrf_update(struct bgp *bgp_vpn, +extern void vpn_leak_to_vrf_update(struct bgp *from_bgp, struct bgp_path_info *path_vpn); -extern void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, +extern void vpn_leak_to_vrf_withdraw(struct bgp *from_bgp, struct bgp_path_info *path_vpn); extern void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi); diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 9def9622d9..7613ccc7df 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -780,7 +780,7 @@ struct bgp_notify bgp_notify_decapsulate_hard_reset(struct bgp_notify *notify) bn.subcode = notify->raw_data[1]; bn.length = notify->length - 2; - bn.raw_data = XCALLOC(MTYPE_BGP_NOTIFICATION, bn.length); + bn.raw_data = XMALLOC(MTYPE_BGP_NOTIFICATION, bn.length); memcpy(bn.raw_data, notify->raw_data + 2, bn.length); return bn; @@ -2121,6 +2121,12 @@ static int bgp_notify_receive(struct peer *peer, bgp_size_t size) if (outer.length) { XFREE(MTYPE_BGP_NOTIFICATION, outer.data); XFREE(MTYPE_BGP_NOTIFICATION, outer.raw_data); + + /* If this is a Hard Reset notification, we MUST free + * the inner (encapsulated) notification too. + */ + if (hard_reset) + XFREE(MTYPE_BGP_NOTIFICATION, inner.raw_data); outer.length = 0; } } diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c index adde379fb0..ea8d2330c5 100644 --- a/bgpd/bgp_updgrp.c +++ b/bgpd/bgp_updgrp.c @@ -1479,7 +1479,24 @@ static int updgrp_policy_update_walkcb(struct update_group *updgrp, void *arg) "u%" PRIu64 ":s%" PRIu64" announcing default upon default routemap %s change", updgrp->id, subgrp->id, ctx->policy_name); - subgroup_default_originate(subgrp, 0); + if (route_map_lookup_by_name(ctx->policy_name)) { + /* + * When there is change in routemap, this flow + * is triggered. the routemap is still present + * in lib, hence its a update flow. The flag + * needs to be unset. + */ + UNSET_FLAG(subgrp->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE); + subgroup_default_originate(subgrp, 0); + } else { + /* + * This is a explicit withdraw, since the + * routemap is not present in routemap lib. need + * to pass 1 for withdraw arg. + */ + subgroup_default_originate(subgrp, 1); + } } update_subgroup_set_needs_refresh(subgrp, 0); } @@ -1857,6 +1874,13 @@ update_group_default_originate_route_map_walkcb(struct update_group *updgrp, safi = SUBGRP_SAFI(subgrp); if (peer->default_rmap[afi][safi].name) { + /* + * When there is change in routemap this flow will + * be triggered. We need to unset the Flag to ensure + * the update flow gets triggered. + */ + UNSET_FLAG(subgrp->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE); subgroup_default_originate(subgrp, 0); } } diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h index e3309ab7c5..473017c809 100644 --- a/bgpd/bgp_updgrp.h +++ b/bgpd/bgp_updgrp.h @@ -252,6 +252,13 @@ struct update_subgroup { #define SUBGRP_STATUS_DEFAULT_ORIGINATE (1 << 0) #define SUBGRP_STATUS_FORCE_UPDATES (1 << 1) #define SUBGRP_STATUS_TABLE_REPARSING (1 << 2) +/* + * This flag has been added to ensure that the SNT counters + * gets incremented and decremented only during the creation + * and deletion workflows of default originate, + * not during the update workflow. + */ +#define SUBGRP_STATUS_PEER_DEFAULT_ORIGINATED (1 << 3) uint16_t flags; #define SUBGRP_FLAG_NEEDS_REFRESH (1 << 0) diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 518ce485af..0f7f2f4c02 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -796,8 +796,11 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) struct peer *peer; struct bgp_adj_out *adj; route_map_result_t ret = RMAP_DENYMATCH; + route_map_result_t new_ret = RMAP_DENYMATCH; afi_t afi; safi_t safi; + int pref = 65536; + int new_pref = 0; if (!subgrp) return; @@ -853,34 +856,45 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) tmp_pi.attr = &tmp_attr; - ret = route_map_apply_ext( + new_ret = route_map_apply_ext( peer->default_rmap[afi][safi].map, - bgp_dest_get_prefix(dest), pi, &tmp_pi); - - if (ret == RMAP_DENYMATCH) { - bgp_attr_flush(&tmp_attr); - continue; - } else { - new_attr = bgp_attr_intern(&tmp_attr); - + bgp_dest_get_prefix(dest), pi, &tmp_pi, + &new_pref); + + if (new_ret == RMAP_PERMITMATCH) { + if (new_pref < pref) { + pref = new_pref; + bgp_attr_flush(new_attr); + new_attr = bgp_attr_intern( + tmp_pi.attr); + bgp_attr_flush(tmp_pi.attr); + } subgroup_announce_reset_nhop( (peer_cap_enhe(peer, afi, safi) ? AF_INET6 : AF_INET), new_attr); - - break; - } - } - if (ret == RMAP_PERMITMATCH) { - bgp_dest_unlock_node(dest); - break; + ret = new_ret; + } else + bgp_attr_flush(&tmp_attr); } } bgp->peer_self->rmap_type = 0; - if (ret == RMAP_DENYMATCH) + if (ret == RMAP_DENYMATCH) { + /* + * If its a implicit withdraw due to routemap + * deny operation need to set the flag back. + * This is a convertion of update flow to + * withdraw flow. + */ + if (!withdraw && + (!CHECK_FLAG(subgrp->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE))) + SET_FLAG(subgrp->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE); withdraw = 1; + } } /* Check if the default route is in local BGP RIB which is diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index c4a3ca7500..88a81f255d 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -1142,7 +1142,12 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp, (void)bpacket_queue_add(SUBGRP_PKTQ(subgrp), s, &vecarr); subgroup_trigger_write(subgrp); - subgrp->scount++; + + if (!CHECK_FLAG(subgrp->sflags, + SUBGRP_STATUS_PEER_DEFAULT_ORIGINATED)) { + subgrp->scount++; + SET_FLAG(subgrp->sflags, SUBGRP_STATUS_PEER_DEFAULT_ORIGINATED); + } } void subgroup_default_withdraw_packet(struct update_subgroup *subgrp) @@ -1235,7 +1240,12 @@ void subgroup_default_withdraw_packet(struct update_subgroup *subgrp) (void)bpacket_queue_add(SUBGRP_PKTQ(subgrp), s, NULL); subgroup_trigger_write(subgrp); - subgrp->scount--; + + if (CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_PEER_DEFAULT_ORIGINATED)) { + subgrp->scount--; + UNSET_FLAG(subgrp->sflags, + SUBGRP_STATUS_PEER_DEFAULT_ORIGINATED); + } } static void diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 0bfcf5163f..122830343c 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -5275,9 +5275,13 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, { struct peer *member; struct listnode *node, *nnode; + struct update_subgroup *subgrp; /* Set flag and configuration on peer. */ peer_af_flag_set(peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE); + + subgrp = peer_subgroup(peer, afi, safi); + if (rmap) { if (!peer->default_rmap[afi][safi].name || strcmp(rmap, peer->default_rmap[afi][safi].name) != 0) { @@ -5285,6 +5289,17 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); + /* + * When there is a change in route-map policy, + * this flow gets triggered. Since, the default + * route is already originated, the flag is set. + * The flag should be unset here, + * to trigger the flow of sending update message. + */ + if (subgrp) + UNSET_FLAG(subgrp->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE); + route_map_counter_decrement(peer->default_rmap[afi][safi].map); peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); @@ -5296,6 +5311,15 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name); + /* + * This is triggered in case of route-map deletion. + * The flag needs to be unset, to trigger the flow + * of sending an update message. + */ + if (subgrp) + UNSET_FLAG(subgrp->sflags, + SUBGRP_STATUS_DEFAULT_ORIGINATE); + route_map_counter_decrement(peer->default_rmap[afi][safi].map); peer->default_rmap[afi][safi].name = NULL; peer->default_rmap[afi][safi].map = NULL; diff --git a/configure.ac b/configure.ac index 330752a79f..b7e17d3565 100644 --- a/configure.ac +++ b/configure.ac @@ -635,6 +635,8 @@ AC_ARG_ENABLE([isisd], AS_HELP_STRING([--disable-isisd], [do not build isisd])) AC_ARG_ENABLE([pimd], AS_HELP_STRING([--disable-pimd], [do not build pimd])) +AC_ARG_ENABLE([pim6d], + AS_HELP_STRING([--enable-pim6d], [build pim6d])) AC_ARG_ENABLE([pbrd], AS_HELP_STRING([--disable-pbrd], [do not build pbrd])) AC_ARG_ENABLE([sharpd], @@ -1751,6 +1753,10 @@ AS_IF([test "$enable_pimd" != "no"], [ AC_DEFINE([HAVE_PIMD], [1], [pimd]) ]) +AS_IF([test "$enable_pim6d" = "yes"], [ + AC_DEFINE([HAVE_PIM6D], [1], [pim6d]) +]) + AS_IF([test "$enable_pbrd" != "no"], [ AC_DEFINE([HAVE_PBRD], [1], [pbrd]) ]) @@ -2711,6 +2717,7 @@ AM_CONDITIONAL([BABELD], [test "$enable_babeld" != "no"]) AM_CONDITIONAL([OSPF6D], [test "$enable_ospf6d" != "no"]) AM_CONDITIONAL([ISISD], [test "$enable_isisd" != "no"]) AM_CONDITIONAL([PIMD], [test "$enable_pimd" != "no"]) +AM_CONDITIONAL([PIM6D], [test "$enable_pim6d" = "yes"]) AM_CONDITIONAL([PBRD], [test "$enable_pbrd" != "no"]) AM_CONDITIONAL([SHARPD], [test "$enable_sharpd" = "yes"]) AM_CONDITIONAL([STATICD], [test "$enable_staticd" != "no"]) diff --git a/debian/rules b/debian/rules index 7a719b7c60..fdb458e6a8 100755 --- a/debian/rules +++ b/debian/rules @@ -27,6 +27,12 @@ else CONF_LUA=--enable-scripting endif +ifeq ($(filter pkg.frr.pim6d,$(DEB_BUILD_PROFILES)),) + CONF_PIM6=--disable-pim6d +else + CONF_PIM6=--enable-pim6d +endif + export PYTHON=python3 %: @@ -46,6 +52,7 @@ override_dh_auto_configure: \ $(CONF_RPKI) \ $(CONF_LUA) \ + $(CONF_PIM6) \ --with-libpam \ --enable-doc \ --enable-doc-html \ diff --git a/doc/developer/packaging-debian.rst b/doc/developer/packaging-debian.rst index a81e052490..9aeb78c4fd 100644 --- a/doc/developer/packaging-debian.rst +++ b/doc/developer/packaging-debian.rst @@ -64,6 +64,10 @@ buster.) +================+===================+=========================================+ | pkg.frr.rtrlib | pkg.frr.nortrlib | builds frr-rpki-rtrlib package (or not) | +----------------+-------------------+-----------------------------------------+ + | pkg.frr.lua | pkg.frr.nolua | builds lua scripting extension | + +----------------+-------------------+-----------------------------------------+ + | pkg.frr.pim6d | pkg.frr.nopim6d | builds pim6d (work in progress) | + +----------------+-------------------+-----------------------------------------+ * the ``-uc -us`` options to disable signing the packages with your GPG key diff --git a/lib/routemap.c b/lib/routemap.c index 7fd5a96e5b..9529b79419 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -2540,7 +2540,8 @@ void route_map_notify_pentry_dependencies(const char *affected_name, */ route_map_result_t route_map_apply_ext(struct route_map *map, const struct prefix *prefix, - void *match_object, void *set_object) + void *match_object, void *set_object, + int *pref) { static int recursion = 0; enum route_map_cmd_result_t match_ret = RMAP_NOMATCH; @@ -2676,7 +2677,7 @@ route_map_result_t route_map_apply_ext(struct route_map *map, ret = route_map_apply_ext( nextrm, prefix, match_object, - set_object); + set_object, NULL); recursion--; } @@ -2721,6 +2722,13 @@ route_map_apply_end: (map ? map->name : "null"), prefix, route_map_result_str(ret)); + if (pref) { + if (index != NULL && ret == RMAP_PERMITMATCH) + *pref = index->pref; + else + *pref = 65536; + } + return (ret); } diff --git a/lib/routemap.h b/lib/routemap.h index 13dafe6849..ad391981e0 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -482,9 +482,9 @@ struct route_map *route_map_lookup_warn_noexist(struct vty *vty, const char *nam extern route_map_result_t route_map_apply_ext(struct route_map *map, const struct prefix *prefix, void *match_object, - void *set_object); + void *set_object, int *pref); #define route_map_apply(map, prefix, object) \ - route_map_apply_ext(map, prefix, object, object) + route_map_apply_ext(map, prefix, object, object, NULL) extern void route_map_add_hook(void (*func)(const char *)); extern void route_map_delete_hook(void (*func)(const char *)); diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c index 1a13f79e71..1f7dd2f3f9 100644 --- a/pimd/pim_bsm.c +++ b/pimd/pim_bsm.c @@ -1280,6 +1280,7 @@ int pim_bsm_process(struct interface *ifp, pim_sgaddr *sg, uint8_t *buf, struct bsm_frag *bsfrag; struct pim_instance *pim; uint16_t frag_tag; + pim_addr bsr_addr; bool empty_bsm = false; /* BSM Packet acceptance validation */ @@ -1330,6 +1331,8 @@ int pim_bsm_process(struct interface *ifp, pim_sgaddr *sg, uint8_t *buf, } pim->global_scope.hashMasklen = bshdr->hm_len; frag_tag = ntohs(bshdr->frag_tag); + /* NB: bshdr->bsr_addr.addr is packed/unaligned => memcpy */ + memcpy(&bsr_addr, &bshdr->bsr_addr.addr, sizeof(bsr_addr)); /* Identify empty BSM */ if ((buf_size - PIM_BSM_HDR_LEN - PIM_MSG_HEADER_LEN) < PIM_BSM_GRP_LEN) @@ -1351,7 +1354,7 @@ int pim_bsm_process(struct interface *ifp, pim_sgaddr *sg, uint8_t *buf, } /* Drop if bsr is not preferred bsr */ - if (!is_preferred_bsr(pim, bshdr->bsr_addr.addr, bshdr->bsr_prio)) { + if (!is_preferred_bsr(pim, bsr_addr, bshdr->bsr_prio)) { if (PIM_DEBUG_BSM) zlog_debug("%s : Received a non-preferred BSM", __func__); @@ -1368,8 +1371,7 @@ int pim_bsm_process(struct interface *ifp, pim_sgaddr *sg, uint8_t *buf, if (PIM_DEBUG_BSM) zlog_debug( "%s : nofwd_bsm received on %pPAs when accpt_nofwd_bsm false", - __func__, - (pim_addr *)&bshdr->bsr_addr.addr); + __func__, &bsr_addr); pim->bsm_dropped++; pim_ifp->pim_ifstat_ucast_bsm_cfg_miss++; return -1; @@ -1381,13 +1383,12 @@ int pim_bsm_process(struct interface *ifp, pim_sgaddr *sg, uint8_t *buf, * match RPF towards the BSR's IP address, or they have * no-forward set */ - if (!no_fwd && !pim_nht_bsr_rpf_check(pim, bshdr->bsr_addr.addr, - ifp, sg->src)) { + if (!no_fwd && + !pim_nht_bsr_rpf_check(pim, bsr_addr, ifp, sg->src)) { if (PIM_DEBUG_BSM) zlog_debug( "BSM check: RPF to BSR %pPAs is not %pPA%%%s", - (pim_addr *)&bshdr->bsr_addr.addr, - &sg->src, ifp->name); + &bsr_addr, &sg->src, ifp->name); pim->bsm_dropped++; return -1; } @@ -1446,7 +1447,7 @@ int pim_bsm_process(struct interface *ifp, pim_sgaddr *sg, uint8_t *buf, } /* update the scope information from bsm */ - pim_bsm_update(pim, bshdr->bsr_addr.addr, bshdr->bsr_prio); + pim_bsm_update(pim, bsr_addr, bshdr->bsr_prio); if (!no_fwd) { pim_bsm_fwd_whole_sz(pim_ifp->pim, buf, buf_size, sz); diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 813ef4ca37..843b24efde 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -864,6 +864,7 @@ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) struct bsmmsg_rpinfo *bsm_rpinfo; struct prefix grp; struct bsm_hdr *hdr; + pim_addr bsr_addr; uint32_t offset = 0; uint8_t *buf; uint32_t len = 0; @@ -877,15 +878,16 @@ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) len -= PIM_MSG_HEADER_LEN; hdr = (struct bsm_hdr *)buf; + /* NB: bshdr->bsr_addr.addr is packed/unaligned => memcpy */ + memcpy(&bsr_addr, &hdr->bsr_addr.addr, sizeof(bsr_addr)); /* BSM starts with bsr header */ buf += sizeof(struct bsm_hdr); len -= sizeof(struct bsm_hdr); if (uj) { - json_object_string_addf( - json, "BSR address", "%pPA", - (pim_addr *)&hdr->bsr_addr.addr); + json_object_string_addf(json, "BSR address", "%pPA", + &bsr_addr); json_object_int_add(json, "BSR priority", hdr->bsr_prio); json_object_int_add(json, "Hashmask Length", @@ -897,9 +899,9 @@ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) vty_out(vty, "------------------\n"); vty_out(vty, "%-15s %-15s %-15s %-15s\n", "BSR-Address", "BSR-Priority", "Hashmask-len", "Fragment-Tag"); - vty_out(vty, "%-15pPA %-15d %-15d %-15d\n", - (pim_addr *)&hdr->bsr_addr.addr, hdr->bsr_prio, - hdr->hm_len, ntohs(hdr->frag_tag)); + vty_out(vty, "%-15pPA %-15d %-15d %-15d\n", &bsr_addr, + hdr->bsr_prio, hdr->hm_len, + ntohs(hdr->frag_tag)); } vty_out(vty, "\n"); @@ -957,7 +959,12 @@ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) "RpAddress HoldTime Priority\n"); while (frag_rp_cnt--) { + pim_addr rp_addr; + bsm_rpinfo = (struct bsmmsg_rpinfo *)buf; + /* unaligned, again */ + memcpy(&rp_addr, &bsm_rpinfo->rpaddr, + sizeof(rp_addr)); buf += sizeof(struct bsmmsg_rpinfo); offset += sizeof(struct bsmmsg_rpinfo); @@ -966,8 +973,7 @@ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) json_row = json_object_new_object(); json_object_string_addf( json_row, "Rp Address", "%pPA", - (pim_addr *)&bsm_rpinfo->rpaddr - .addr); + &rp_addr); json_object_int_add( json_row, "Rp HoldTime", ntohs(bsm_rpinfo->rp_holdtime)); @@ -976,12 +982,10 @@ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj) bsm_rpinfo->rp_pri); json_object_object_addf( json_group, json_row, "%pPA", - (pim_addr *)&bsm_rpinfo->rpaddr - .addr); + &rp_addr); } else { vty_out(vty, "%-15pPA %-12d %d\n", - (pim_addr *)&bsm_rpinfo->rpaddr - .addr, + &rp_addr, ntohs(bsm_rpinfo->rp_holdtime), bsm_rpinfo->rp_pri); } diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index aa31a67036..783c9b97e7 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -339,9 +339,7 @@ static int pim_rp_check_interface_addrs(struct rp_info *rp_info, { struct listnode *node; struct pim_secondary_addr *sec_addr; - struct prefix rpf_addr; - - pim_addr_to_prefix(&rpf_addr, rp_info->rp.rpf_addr); + pim_addr sec_paddr; if (!pim_addr_cmp(pim_ifp->primary_address, rp_info->rp.rpf_addr)) return 1; @@ -351,9 +349,11 @@ static int pim_rp_check_interface_addrs(struct rp_info *rp_info, } for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) { - if (prefix_same(&sec_addr->addr, &rpf_addr)) { + sec_paddr = pim_addr_from_prefix(&sec_addr->addr); + /* If an RP-address is self, It should be enough to say + * I am RP the prefix-length should not matter here */ + if (!pim_addr_cmp(sec_paddr, rp_info->rp.rpf_addr)) return 1; - } } return 0; diff --git a/pimd/subdir.am b/pimd/subdir.am index 9546a7776e..aa06b86479 100644 --- a/pimd/subdir.am +++ b/pimd/subdir.am @@ -170,17 +170,11 @@ clippy_scan += \ pimd_pimd_CFLAGS = $(AM_CFLAGS) -DPIM_IPV=4 pimd_pimd_LDADD = lib/libfrr.la $(LIBCAP) -if PIMD -if DEV_BUILD -# -# pim6d is only enabled for --enable-dev-build, and NOT installed currently -# (change noinst_ to sbin_ below to install it.) -# -noinst_PROGRAMS += pimd/pim6d +if PIM6D +sbin_PROGRAMS += pimd/pim6d pimd_pim6d_CFLAGS = $(AM_CFLAGS) -DPIM_IPV=6 pimd_pim6d_LDADD = lib/libfrr.la $(LIBCAP) endif -endif pimd_test_igmpv3_join_LDADD = lib/libfrr.la pimd_test_igmpv3_join_SOURCES = pimd/test_igmpv3_join.c diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in index 9d3d2b0643..135c065b15 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -24,6 +24,7 @@ %{!?with_pam: %global with_pam 0 } %{!?with_pbrd: %global with_pbrd 1 } %{!?with_pimd: %global with_pimd 1 } +%{!?with_pim6d: %global with_pim6d 0 } %{!?with_vrrpd: %global with_vrrpd 1 } %{!?with_rtadv: %global with_rtadv 1 } %{!?with_watchfrr: %global with_watchfrr 1 } @@ -81,6 +82,7 @@ # if CentOS / RedHat and version < 7, then disable PIMd (too old, won't work) %if 0%{?rhel} && 0%{?rhel} < 7 %global with_pimd 0 + %global with_pim6d 0 %endif # misc internal defines @@ -102,6 +104,12 @@ %define daemon_pimd "" %endif +%if %{with_pim6d} + %define daemon_pim6d pim6d +%else + %define daemon_pim6d "" +%endif + %if %{with_pbrd} %define daemon_pbrd pbrd %else @@ -150,7 +158,7 @@ %define daemon_pathd "" %endif -%define all_daemons %{daemon_list} %{daemon_ldpd} %{daemon_pimd} %{daemon_nhrpd} %{daemon_eigrpd} %{daemon_babeld} %{daemon_watchfrr} %{daemon_pbrd} %{daemon_bfdd} %{daemon_vrrpd} %{daemon_pathd} +%define all_daemons %{daemon_list} %{daemon_ldpd} %{daemon_pimd} %{daemon_pim6d} %{daemon_nhrpd} %{daemon_eigrpd} %{daemon_babeld} %{daemon_watchfrr} %{daemon_pbrd} %{daemon_bfdd} %{daemon_vrrpd} %{daemon_pathd} #release sub-revision (the two digits after the CONFDATE) %{!?release_rev: %global release_rev 01 } @@ -342,6 +350,11 @@ routing state through standard SNMP MIBs. %else --disable-pimd \ %endif +%if %{with_pim6d} + --enable-pim6d \ +%else + --disable-pim6d \ +%endif %if %{with_pbrd} --enable-pbrd \ %else @@ -666,6 +679,9 @@ fi %if %{with_pimd} %{_sbindir}/pimd %endif +%if %{with_pim6d} + %{_sbindir}/pim6d +%endif %if %{with_pbrd} %{_sbindir}/pbrd %endif diff --git a/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py b/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py new file mode 100644 index 0000000000..272a7fe291 --- /dev/null +++ b/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py @@ -0,0 +1,2102 @@ +#!/usr/bin/env python +# +# Copyright (c) 2022 by VMware, Inc. ("VMware") +# Used Copyright (c) 2018 by Network Device Education Foundation, Inc. ("NetDEF") +# in this file. +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# Shreenidhi A R <rshreenidhi@vmware.com> +# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# +""" +Following scenerios are covered. +1. When there is change in route-map policy associated with default-originate, changes does not reflect. +2. When route-map associated with default-originate is deleted, default route doesn't get withdrawn +3. Update message is not being sent when only route-map is removed from the default-originate config. +4. SNT counter gets incremented on change of every policy associated with default-originate +5. Route-map with multiple match clauses causes inconsistencies with default-originate. +6. BGP-Default originate behaviour with BGP attributes +""" +import os +import sys +import time +import pytest +from copy import deepcopy +from lib.topolog import logger + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib.topogen import Topogen, get_topogen +from lib.topojson import build_config_from_json +from lib.topolog import logger + +from lib.bgp import ( + verify_bgp_convergence, + create_router_bgp, + get_prefix_count_route, + modify_as_number, + verify_bgp_rib, + get_dut_as_number, + verify_rib_default_route, + verify_fib_default_route, +) +from lib.common_config import ( + verify_fib_routes, + step, + required_linux_kernel_version, + create_route_maps, + interface_status, + create_prefix_lists, + get_frr_ipv6_linklocal, + start_topology, + write_test_header, + verify_prefix_lists, + check_address_types, + write_test_footer, + reset_config_on_routers, + create_static_routes, + check_router_status, + delete_route_maps, +) + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) +sys.path.append(os.path.join(CWD, "../lib/")) + +# Required to instantiate the topology builder class. + +# pylint: disable=C0413 +# Import topogen and topotest helpers + +# Global variables +topo = None +NETWORK1_1 = {"ipv4": "198.51.1.1/32", "ipv6": "2001:DB8::1:1/128"} +DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"} +NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"} + +def setup_module(mod): + """ + Sets up the pytest environment + + * `mod`: module name + """ + + # Required linux kernel version for this suite to run. + result = required_linux_kernel_version("4.15") + if result is not True: + pytest.skip("Kernel requirements are not met") + + testsuite_run_time = time.asctime(time.localtime(time.time())) + logger.info("Testsuite start time: {}".format(testsuite_run_time)) + logger.info("=" * 40) + + logger.info("Running setup_module to create topology") + + # This function initiates the topology build with Topogen... + json_file = "{}/bgp_default_originate_topo1.json".format(CWD) + tgen = Topogen(json_file, mod.__name__) + global topo + topo = tgen.json_topo + # ... and here it calls Mininet initialization functions. + + # Starting topology, create tmp files which are loaded to routers + # to start daemons and then start routers + start_topology(tgen) + + # Creating configuration from JSON + build_config_from_json(tgen, topo) + + global ADDR_TYPES + global BGP_CONVERGENCE + global DEFAULT_ROUTES + global DEFAULT_ROUTE_NXT_HOP_R1, DEFAULT_ROUTE_NXT_HOP_R3 + ADDR_TYPES = check_address_types() + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format( + BGP_CONVERGENCE + ) + + DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"} + + interface = topo["routers"]["r1"]["links"]["r2"]["interface"] + ipv6_link_local = get_frr_ipv6_linklocal(tgen, "r1", intf=interface) + ipv4_nxt_hop = topo["routers"]["r1"]["links"]["r2"]["ipv4"].split("/")[0] + ipv6_nxt_hop = topo["routers"]["r1"]["links"]["r2"]["ipv6"].split("/")[0] + DEFAULT_ROUTE_NXT_HOP_R1 = {"ipv4": ipv4_nxt_hop, "ipv6": ipv6_link_local} + + interface = topo["routers"]["r3"]["links"]["r2"]["interface"] + ipv6_link_local = get_frr_ipv6_linklocal(tgen, "r3", intf=interface) + ipv4_nxt_hop = topo["routers"]["r3"]["links"]["r2"]["ipv4"].split("/")[0] + ipv6_nxt_hop = topo["routers"]["r3"]["links"]["r2"]["ipv6"].split("/")[0] + DEFAULT_ROUTE_NXT_HOP_R3 = {"ipv4": ipv4_nxt_hop, "ipv6": ipv6_link_local} + + logger.info("Running setup_module() done") + + +def teardown_module(): + """Teardown the pytest environment""" + + logger.info("Running teardown_module to delete topology") + + tgen = get_topogen() + + # Stop toplogy and Remove tmp files + tgen.stop_topology() + + logger.info( + "Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))) + ) + logger.info("=" * 40) + + +##################################################### +# +# Testcases +# +##################################################### + + +def test_default_originate_delete_conditional_routemap(request): + """ + "scenerio covered": + 1. When there is change in route-map policy associated with default-originate, changes does not reflect. + 2. When route-map associated with default-originate is deleted, default route doesn't get withdrawn + 3. Update message is not being sent when only route-map is removed from the default-originate config. + 4. SNT counter gets incremented on change of every policy associated with default-originate + 5. Route-map with multiple match clauses causes inconsistencies with default-originate. + """ + tgen = get_topogen() + global BGP_CONVERGENCE + global topo + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() + if tgen.routers_have_failure(): + check_router_status(tgen) + reset_config_on_routers(tgen) + + if BGP_CONVERGENCE != True: + pytest.skip("skipped because of BGP Convergence failure") + + step("Configure IPv4 and IPv6 , IBGP neighbor between R1 and R2") + step("Configure IPv4 and IPv6 , EBGP neighbor between R1 and R0") + input_dict = { + "r0": { + "bgp": { + "local_as": 999, + } + }, + "r1": { + "bgp": { + "local_as": 1000, + } + }, + "r2": { + "bgp": { + "local_as": 1000, + } + }, + "r3": { + "bgp": { + "local_as": 2000, + } + }, + "r4": { + "bgp": { + "local_as": 3000, + } + }, + } + result = modify_as_number(tgen, topo, input_dict) + try: + assert result is True + except AssertionError: + logger.info("Expected behaviour: {}".format(result)) + logger.info("BGP config is not created because of invalid ASNs") + + step("After changing the BGP remote as , Verify the BGP Convergence") + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert ( + BGP_CONVERGENCE is True + ), "Complete convergence is expected after changing ASN ....! ERROR :Failed \n Error: {}".format( + BGP_CONVERGENCE + ) + + step("Configure 1 IPv4 and 1 IPv6 Static route on R0 with next-hop as Null0") + for addr_type in ADDR_TYPES: + static_routes_input = { + "r0": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + } + ] + } + } + result = create_static_routes(tgen, static_routes_input) + assert ( + result is True + ), "Testcase {} : Failed to configure the static route \n Error: {}".format( + tc_name, result + ) + + step("verify IPv4 and IPv6 static route are configured and up on R0") + for addr_type in ADDR_TYPES: + static_routes_input = { + "r0": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + }, + ] + } + } + result = verify_fib_routes(tgen, addr_type, "r0", static_routes_input) + assert ( + result is True + ), "Testcase {} : routes {} not found in R0 FIB \n Error: {}".format( + tc_name, static_routes_input, result + ) + + step( + "Configure redistribute static on IPv4 and IPv6 address family on R0 for R0 to R1 neighbor " + ) + redistribute_static = { + "r0": { + "bgp": { + "address_family": { + "ipv4": {"unicast": {"redistribute": [{"redist_type": "static"}]}}, + "ipv6": {"unicast": {"redistribute": [{"redist_type": "static"}]}}, + } + } + } + } + result = create_router_bgp(tgen, topo, redistribute_static) + assert ( + result is True + ), "Testcase {} : Failed to configure redistribute configuration....! \n Error: {}".format( + tc_name, result + ) + + step("verify IPv4 and IPv6 static route are received on R1") + for addr_type in ADDR_TYPES: + static_routes_input = { + "r0": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + }, + ] + } + } + result = verify_fib_routes(tgen, addr_type, "r1", static_routes_input) + assert ( + result is True + ), "Testcase {} : Failed... Routes {} expected in r1 FIB after configuring the redistribute config on R0 \n Error: {}".format( + tc_name, static_routes_input, result + ) + + result = verify_bgp_rib(tgen, addr_type, "r1", static_routes_input) + assert ( + result is True + ), "Testcase {} : Failed... Routes {} expected in r1 RIB after configuring the redistribute config on R0\n Error: {}".format( + tc_name, static_routes_input, result + ) + + step( + "Configure IPv4 prefix-list 'Pv4' and and IPv6 prefix-list 'Pv6' on R1 to match BGP route Sv41, IPv6 route Sv61 permit " + ) + input_dict_3 = { + "r1": { + "prefix_lists": { + "ipv4": { + "Pv4": [ + { + "seqid": "1", + "network": NETWORK1_1["ipv4"], + "action": "permit", + }, + ] + }, + "ipv6": { + "Pv6": [ + { + "seqid": "1", + "network": NETWORK1_1["ipv6"], + "action": "permit", + }, + ] + }, + } + } + } + result = create_prefix_lists(tgen, input_dict_3) + assert ( + result is True + ), "Testcase {} : Failed to configure the prefix list \n Error: {}".format( + tc_name, result + ) + + step( + "Configure IPV4 and IPv6 route-map (RMv4 and RMv6) matching prefix-list (Pv4 and Pv6) respectively on R1" + ) + input_dict_3 = { + "r1": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "1", + "match": {"ipv4": {"prefix_lists": "Pv4"}}, + "set": { + "path": { + "as_num": "5555", + "as_action": "prepend", + } + }, + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "1", + "match": {"ipv6": {"prefix_lists": "Pv6"}}, + "set": { + "path": { + "as_num": "5555", + "as_action": "prepend", + } + }, + }, + ], + } + } + } + result = create_route_maps(tgen, input_dict_3) + assert ( + result is True + ), "Testcase {} : Failed to configure the route map \n Error: {}".format( + tc_name, result + ) + + step( + "Configure default-originate with route-map (RMv4 and RMv6) on R1, on BGP IPv4 and IPv6 address family " + ) + local_as = get_dut_as_number(tgen, dut="r1") + default_originate_config = { + "r1": { + "bgp": { + "local_as": local_as, + "address_family": { + "ipv4": { + "unicast": {"default_originate": {"r2": {"route_map": "RMv4"}}} + }, + "ipv6": { + "unicast": {"default_originate": {"r2": {"route_map": "RMv6"}}} + }, + }, + } + } + } + result = create_router_bgp(tgen, topo, default_originate_config) + assert ( + result is True + ), "Testcase {} : Failed to configure the default originate \n Error: {}".format( + tc_name, result + ) + + step( + "After configuring default-originate command , verify default routes are advertised on R2 " + ) + DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"} + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R1, + metric=0, + expected_aspath="5555", + ) + assert ( + result is True + ), "Testcase {} : Failed to configure the default originate \n Error: {}".format( + tc_name, result + ) + + result = verify_fib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R1, + expected=True, + ) + assert ( + result is True + ), "Testcase {} : Failed to configure the default originate \n Error: {}".format( + tc_name, result + ) + + step("Changing the as-path policy of the existing route-map") + input_dict_3 = { + "r1": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "1", + "match": {"ipv4": {"prefix_lists": "Pv4"}}, + "set": { + "path": { + "as_num": "6666", + "as_action": "prepend", + } + }, + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "1", + "match": {"ipv6": {"prefix_lists": "Pv6"}}, + "set": { + "path": { + "as_num": "6666", + "as_action": "prepend", + } + }, + }, + ], + } + } + } + result = create_route_maps(tgen, input_dict_3) + assert ( + result is True + ), "Testcase {} : Failed to configure the route map \n Error: {}".format( + tc_name, result + ) + + step( + "Verify prefix sent count on R1 towards R2 \n Send count shoud not be incremented on change of existing (AS-path) policy " + ) + snapshot = get_prefix_count_route( + tgen, topo, dut="r1", peer="r2", link="r1", sent=True, received=False + ) + + ipv4_prefix_count = False + ipv6_prefix_count = False + if snapshot["ipv4_count"] == 2: + ipv4_prefix_count = True + if snapshot["ipv6_count"] == 2: + ipv6_prefix_count = True + + assert ( + ipv4_prefix_count is True + ), "Testcase {} : Failed Error: Expected sent Prefix is 2 but obtained {} ".format( + tc_name, ipv4_prefix_count + ) + assert ( + ipv6_prefix_count is True + ), "Testcase {} : Failed Error: Expected sent Prefix is 2 but obtained {} ".format( + tc_name, ipv6_prefix_count + ) + + step( + "After changing the as-path policy verify the new policy is advertised to router R2" + ) + DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"} + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R1, + metric=0, + expected_aspath="6666", + ) + assert ( + result is True + ), "Testcase {} : Default route with expected attributes is not found in BGP RIB \n Error: {}".format( + tc_name, result + ) + + result = verify_fib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R1, + expected=True, + ) + assert ( + result is True + ), "Testcase {} : Default route with expected attributes is not found in BGP FIB \n Error: {}".format( + tc_name, result + ) + + step("Remove the as-path policy from the route-map") + input_dict_3 = { + "r1": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "1", + "match": {"ipv4": {"prefix_lists": "Pv4"}}, + "set": { + "path": { + "as_num": "6666", + "as_action": "prepend", + "delete": True, + } + }, + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "1", + "match": {"ipv6": {"prefix_lists": "Pv6"}}, + "set": { + "path": { + "as_num": "6666", + "as_action": "prepend", + "delete": True, + } + }, + }, + ], + } + } + } + result = create_route_maps(tgen, input_dict_3) + assert ( + result is True + ), "Testcase {} : Failed to configure the route map \n Error: {}".format( + tc_name, result + ) + + step( + "After removing the route policy (AS-Path) verify that as-path is removed in r2 " + ) + DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"} + + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R1, + ) + assert result is True, "Testcase {} : Failed ... ! \n Error: {}".format( + tc_name, result + ) + + result = verify_fib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R1, + expected=True, + ) + assert result is True, "Testcase {} : Failed .... !\n Error: {}".format( + tc_name, result + ) + + step("Delete the route-map ") + + delete_routemap = {"r1": {"route_maps": ["RMv4", "RMv6"]}} + result = delete_route_maps(tgen, delete_routemap) + assert ( + result is True + ), "Testcase {} : Failed to delete the route-map\n Error: {}".format( + tc_name, result + ) + + step( + "After deleting route-map , verify the default route in FIB and RIB are removed " + ) + DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"} + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R1, + metric=0, + expected=False, + ) + assert ( + result is not True + ), "Testcase {} : After removing the route-map the default-route is not removed from R2 RIB\n Error: {}".format( + tc_name, result + ) + + result = verify_fib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R1, + expected=False, + ) + assert ( + result is not True + ), "Testcase {} : After removing the route-map the default-route is not removed from R2 FIB \n Error: {}".format( + tc_name, result + ) + + step("Create route-map with with sequnce number 10 ") + input_dict_3 = { + "r1": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "10", + "match": {"ipv4": {"prefix_lists": "Pv4"}}, + "set": { + "path": { + "as_num": "9999", + "as_action": "prepend", + } + }, + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "10", + "match": {"ipv6": {"prefix_lists": "Pv6"}}, + "set": { + "path": { + "as_num": "9999", + "as_action": "prepend", + } + }, + }, + ], + } + } + } + result = create_route_maps(tgen, input_dict_3) + assert ( + result is True + ), "Testcase {} : Failed to configure the route map \n Error: {}".format( + tc_name, result + ) + + step( + "After Configuring the route-map the dut is expected to receive the route policy (as-path) as 99999" + ) + DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"} + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R1, + metric=0, + expected_aspath="9999", + ) + assert result is True, "Testcase {} : Failed...! \n Error: {}".format( + tc_name, result + ) + + result = verify_fib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R1, + expected=True, + ) + assert result is True, "Testcase {} : Failed ...!\n Error: {}".format( + tc_name, result + ) + + step("Create another route-map with seq number less than the previous i. <10 ") + input_dict_3 = { + "r1": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "5", + "match": {"ipv4": {"prefix_lists": "Pv4"}}, + "set": { + "path": { + "as_num": "7777", + "as_action": "prepend", + } + }, + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "5", + "match": {"ipv6": {"prefix_lists": "Pv6"}}, + "set": { + "path": { + "as_num": "7777", + "as_action": "prepend", + } + }, + }, + ], + } + } + } + result = create_route_maps(tgen, input_dict_3) + assert ( + result is True + ), "Testcase {} : Failed to configure the route map \n Error: {}".format( + tc_name, result + ) + + step( + "On creating new route-map the route-map with lower seq id should be considered " + ) + DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"} + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R1, + metric=0, + expected_aspath="7777", + ) + assert ( + result is True + ), "Testcase {} : Route-map with lowest prefix is not considered \n Error: {}".format( + tc_name, result + ) + + result = verify_fib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R1, + expected=True, + ) + assert ( + result is True + ), "Testcase {} : Route-map with lowest prefix is not considered \n Error: {}".format( + tc_name, result + ) + + write_test_footer(tc_name) + + +def test_verify_default_originate_after_BGP_attributes_p1(request): + """ + "Verify different BGP attributes with default-originate route " + """ + tgen = get_topogen() + global BGP_CONVERGENCE + global topo + # test case name + tc_name = request.node.name + write_test_header(tc_name) + # Don't run this test if we have any failure. + if tgen.routers_have_failure(): + check_router_status(tgen) + reset_config_on_routers(tgen) + + if BGP_CONVERGENCE != True: + pytest.skip("skipped because of BGP Convergence failure") + + step("Configure IPv4 and IPv6 , EBGP neighbor between R3 and R2") + step("Configure IPv4 and IPv6 IBGP neighbor between R3 and R4") + r0_local_as = topo['routers']['r0']['bgp']['local_as'] + r1_local_as = topo['routers']['r1']['bgp']['local_as'] + r2_local_as = topo['routers']['r2']['bgp']['local_as'] + r3_local_as = topo['routers']['r3']['bgp']['local_as'] + r4_local_as = topo['routers']['r4']['bgp']['local_as'] + input_dict = { + "r0": { + "bgp": { + "local_as": r0_local_as, + } + }, + "r1": { + "bgp": { + "local_as": r1_local_as, + } + }, + "r2": { + "bgp": { + "local_as": r2_local_as, + } + }, + "r3": { + "bgp": { + "local_as": 4000, + } + }, + "r4": { + "bgp": { + "local_as": 4000, + } + }, + } + result = modify_as_number(tgen, topo, input_dict) + + try: + assert result is True + except AssertionError: + logger.info("Expected behaviour: {}".format(result)) + logger.info("BGP config is not created because of invalid ASNs") + step("After changing the BGP AS Path Verify the BGP Convergence") + + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format( + BGP_CONVERGENCE + ) + + step( + "Configure one IPv4 and one IPv6, Static route on R4 with next-hop as Null0 IPv4 route Sv41, IPv6 route Sv61 " + ) + for addr_type in ADDR_TYPES: + static_routes_input = { + "r4": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + } + ] + } + } + result = create_static_routes(tgen, static_routes_input) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + step("Verify IPv4 and IPv6 static routes configured on R4 in FIB") + for addr_type in ADDR_TYPES: + static_routes_input = { + "r4": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + } + ] + } + } + result = verify_fib_routes(tgen, addr_type, "r4", static_routes_input) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure redistribute static knob on R4 , for R4 to R3 neighbor for IPv4 and IPv6 address family " + ) + redistribute_static = { + "r4": { + "bgp": { + "address_family": { + "ipv4": {"unicast": {"redistribute": [{"redist_type": "static"}]}}, + "ipv6": {"unicast": {"redistribute": [{"redist_type": "static"}]}}, + } + } + } + } + result = create_router_bgp(tgen, topo, redistribute_static) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify After configuring redistribute static , verify route received in BGP table of R3" + ) + for addr_type in ADDR_TYPES: + static_routes_input = { + "r3": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + } + ] + } + } + result = verify_fib_routes(tgen, addr_type, "r3", static_routes_input) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_bgp_rib(tgen, addr_type, "r3", static_routes_input) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + NOTE = """Configure 2 IPv4 prefix-list Pv41 Pv42 and and 2 IPv6 prefix-list Pv61 Pv62 on R3 to match BGP IPv4 route Sv41, 200.1.1.1/24 , IPv6 route Sv61 and 200::1/64""" + step(NOTE) + input_dict_3 = { + "r3": { + "prefix_lists": { + "ipv4": { + "Pv41": [ + { + "seqid": "1", + "network": NETWORK1_1["ipv4"], + "action": "permit", + } + ], + "Pv42": [ + {"seqid": "1", "network": "200.1.1.1/24", "action": "permit"} + ], + }, + "ipv6": { + "Pv61": [ + { + "seqid": "1", + "network": NETWORK1_1["ipv6"], + "action": "permit", + } + ], + "Pv62": [ + {"seqid": " 1", "network": "200::1/64", "action": "permit"} + ], + }, + } + } + } + result = create_prefix_lists(tgen, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("verify IPv4 and IPv6 Prefix list got configured on R3") + input_dict = {"r3": {"prefix_lists": ["Pv41", "Pv61", "Pv42", "Pv62"]}} + result = verify_prefix_lists(tgen, input_dict) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Configure 2 sequence of route-map for IPv4 seq1 permit Pv41 and seq2 permit Pv42 and for IPv6 seq1 permit Pv61 , seq2 permit Pv62 on R3" + ) + input_dict_3 = { + "r3": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "1", + "match": {"ipv4": {"prefix_lists": "Pv41"}}, + }, + { + "action": "permit", + "seq_id": "2", + "match": {"ipv4": {"prefix_lists": "Pv42"}}, + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "1", + "match": {"ipv6": {"prefix_lists": "Pv61"}}, + }, + { + "action": "permit", + "seq_id": "2", + "match": {"ipv6": {"prefix_lists": "Pv62"}}, + }, + ], + } + } + } + result = create_route_maps(tgen, input_dict_3) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Apply on route-map seq1 set as-path prepend to 200 and route-map seq2 set as-path prepend to 300 for IPv4 and IPv6 route-map " + ) + route_map = { + "r3": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "1", + "set": { + "path": { + "as_num": "200", + "as_action": "prepend", + } + } + + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "path": { + "as_num": "300", + "as_action": "prepend", + } + } + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "1", + "set": { + "path": { + "as_num": "200", + "as_action": "prepend", + } + } + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "path": { + "as_num": "300", + "as_action": "prepend", + } + } + }, + ], + } + } + } + + result = create_route_maps(tgen, route_map) + assert result is True, "Test case {} : Failed \n Error: {}".format(tc_name, result) + + step( + " Configure default-originate with IPv4 and IPv6 route-map on R3 for R3-R2 IPv4 and IPv6 BGP neighbor" + ) + + local_as = get_dut_as_number(tgen, dut="r3") + default_originate_config = { + "r3": { + "bgp": { + "local_as": local_as, + "address_family": { + "ipv4": { + "unicast": {"default_originate": {"r2": {"route_map": "RMv4"}}} + }, + "ipv6": { + "unicast": {"default_originate": {"r2": {"route_map": "RMv6"}}} + }, + }, + } + } + } + result = create_router_bgp(tgen, topo, default_originate_config) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify IPv4 and IPv6 default route received on R2 with both the AS path on R2" + ) + DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"} + + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + metric=0, + expected_aspath="4000 200", + ) + + step( + "Modify AS prepend path adding one more value 500 in route-map sequence 1 and 600 for route-map sequence 2 for IPv4 and IPv6 route-map" + ) + route_map = { + "r3": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "1", + "set": { + "path": { + "as_num": "500", + "as_action": "prepend", + } + } + + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "path": { + "as_num": "600", + "as_action": "prepend", + } + } + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "1", + "set": { + "path": { + "as_num": "500", + "as_action": "prepend", + } + } + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "path": { + "as_num": "600", + "as_action": "prepend", + } + } + }, + ], + } + } + } + + result = create_route_maps(tgen, route_map) + assert result is True, "Test case {} : Failed \n Error: {}".format(tc_name, result) + assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) + + + step("As path 500 added to IPv4 and IPv6 default -originate route received on R2") + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + metric=0, + expected_aspath="4000 500", + ) + assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) + + step( + "Apply on route-map seq1 set metric value to 70 and route-map seq2 set metric 80 IPv4 and IPv6 route-map" + ) + route_map = { + "r3": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "1", + "set": { + "metric": 70, + }, + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "metric": 80, + }, + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "1", + "set": { + "metric": 70, + }, + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "metric": 80, + }, + }, + ], + } + } + } + + result = create_route_maps(tgen, route_map) + assert result is True, "Test case {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify Configured metric value received on R2 along with as-path for IPv4 and IPv6 default routes " + ) + + + DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "::/0"} + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + metric=70, + expected_aspath="4000 500", + ) + + + step( + "Modify route-map seq1 configure metric 50 and route-map seq2 configure metric 100 IPv4 and IPv6 route-map " + ) + route_map = { + "r3": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "1", + "set": { + "metric": 50, + }, + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "metric": 100, + }, + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "1", + "set": { + "metric": 50, + }, + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "metric": 100, + }, + }, + ], + } + } + } + + result = create_route_maps(tgen, route_map) + assert result is True, "Test case {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify Configured metric value received on R2 along with as-path for IPv4 and IPv6 default routes " + ) + + + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + metric=50, + expected_aspath="4000 500", + ) + assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) + + step("Delete AS-prepend from IP4 and IPv6 route-map configured on R3 ") + route_map = { + "r3": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "1", + + "set": { + "path": { + "as_num": "500", + "as_action": "prepend", + "delete": True, + }, + "delete": True, + }, + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "path": { + "as_num": "600", + "as_action": "prepend", + "delete": True, + }, + "delete": True, + }, + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "1", + "set": { + "path": { + "as_num": "500", + "as_action": "prepend", + "delete": True, + }, + "delete": True, + }, + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "path": { + "as_num": "600", + "as_action": "prepend", + "delete": True, + }, + "delete": True, + }, + }, + ], + } + } + } + + result = create_route_maps(tgen, route_map) + assert result is True, "Test case {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify AS-prepend is deleted from default originate route and metric value only present on R2 for IPv4 and IPv6 default routes " + ) + + + + + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + metric=50, + expected_aspath="4000", + ) + assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) + + + step("Delete metric value from IP4 and IPv6 route-map configured on R3 ") + route_map = { + "r3": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "1", + "set": {"metric": 50, "delete": True}, + }, + { + "action": "permit", + "seq_id": "2", + "set": {"metric": 100, "delete": True}, + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "1", + "set": {"metric": 50, "delete": True}, + }, + { + "action": "permit", + "seq_id": "2", + "set": {"metric": 100, "delete": True}, + }, + ], + } + } + } + + result = create_route_maps(tgen, route_map) + assert result is True, "Test case {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify Metric value deleted from IPv4 and IPv6 default route on R2 ,verify default routes " + ) + + + + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + metric=0, + expected_aspath="4000", + ) + + assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) + step("Change IPv4 and IPv6 , EBGP to IBGP neighbor between R3 and R2") + step("Change IPv4 and IPv6 IBGP to EBGP neighbor between R3 and R4") + r0_local_as = topo['routers']['r0']['bgp']['local_as'] + r1_local_as = topo['routers']['r1']['bgp']['local_as'] + r2_local_as = topo['routers']['r2']['bgp']['local_as'] + r3_local_as = topo['routers']['r3']['bgp']['local_as'] + r4_local_as = topo['routers']['r4']['bgp']['local_as'] + input_dict = { + "r0": { + "bgp": { + "local_as": r0_local_as, + } + }, + "r1": { + "bgp": { + "local_as": r1_local_as, + } + }, + + "r2": { + "bgp": { + "local_as": 1111, + } + }, + "r3": { + "bgp": { + "local_as": 1111, + } + }, + "r4": { + "bgp": { + "local_as": 5555, + } + }, + } + result = modify_as_number(tgen, topo, input_dict) + try: + assert result is True + except AssertionError: + logger.info("Expected behaviour: {}".format(result)) + logger.info("BGP config is not created because of invalid ASNs") + step("After changing the BGP AS Path Verify the BGP Convergence") + BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo) + assert BGP_CONVERGENCE is True, "setup_module :Failed \n Error: {}".format( + BGP_CONVERGENCE + ) + step( + "Configure one IPv4 and one IPv6, Static route on R4 with next-hop as Null0 IPv4 route Sv41, IPv6 route Sv61 " + ) + for addr_type in ADDR_TYPES: + static_routes_input = { + "r4": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + } + ] + } + } + result = create_static_routes(tgen, static_routes_input) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + step("Verify IPv4 and IPv6 static routes configured on R4 in FIB") + for addr_type in ADDR_TYPES: + static_routes_input = { + "r4": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + } + ] + } + } + result = verify_fib_routes(tgen, addr_type, "r4", static_routes_input) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step( + "Configure redistribute static knob on R4 , for R4 to R3 neighbor for IPv4 and IPv6 address family " + ) + redistribute_static = { + "r4": { + "bgp": { + "address_family": { + "ipv4": {"unicast": {"redistribute": [{"redist_type": "static"}]}}, + "ipv6": {"unicast": {"redistribute": [{"redist_type": "static"}]}}, + } + } + } + } + result = create_router_bgp(tgen, topo, redistribute_static) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify After configuring redistribute static , verify route received in BGP table of R3" + ) + for addr_type in ADDR_TYPES: + static_routes_input = { + "r3": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + } + ] + } + } + result = verify_fib_routes(tgen, addr_type, "r3", static_routes_input) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + result = verify_bgp_rib(tgen, addr_type, "r3", static_routes_input) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + step( + " Configure default-originate with IPv4 and IPv6 route-map on R3 for R3-R2 IPv4 and IPv6 BGP neighbor" + ) + local_as = get_dut_as_number(tgen, dut="r3") + default_originate_config = { + "r3": { + "bgp": { + "local_as": local_as, + "address_family": { + "ipv4": { + "unicast": {"default_originate": {"r2": {"route_map": "RMv4"}}} + }, + "ipv6": { + "unicast": {"default_originate": {"r2": {"route_map": "RMv6"}}} + }, + }, + } + } + } + result = create_router_bgp(tgen, topo, default_originate_config) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify IPv4 and IPv6 default route received on R2 with both the AS path on R2" + ) + DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"} + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + ) + assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) + + step( + "Configure local -preference to 50 on IPv4 and IPv6 route map seq1 and 60 on seq2" + ) + route_map = { + "r3": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "1", + "set": { + "locPrf": 50, + }, + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "locPrf": 60, + }, + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "1", + "set": { + "locPrf": 50, + }, + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "locPrf": 60, + }, + }, + ], + } + } + } + + result = create_route_maps(tgen, route_map) + assert result is True, "Test case {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify Configured metric value received on R2 along with as-path for IPv4 and IPv6 default routes " + ) + + + + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + locPrf=50, + ) + + + assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) + + step( + "Modify local preference value to 150 on IPv4 and IPv6 route map seq1 and 160 on seq2" + ) + route_map = { + "r3": { + "route_maps": { + "RMv4": [ + { + "action": "permit", + "seq_id": "1", + "set": { + "locPrf": 150, + }, + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "locPrf": 160, + }, + }, + ], + "RMv6": [ + { + "action": "permit", + "seq_id": "1", + "set": { + "locPrf": 150, + }, + }, + { + "action": "permit", + "seq_id": "2", + "set": { + "locPrf": 160, + }, + }, + ], + } + } + } + + result = create_route_maps(tgen, route_map) + assert result is True, "Test case {} : Failed \n Error: {}".format(tc_name, result) + + step( + "Verify Modified local-preference value received on R2 for IPv4 and IPv6 default routes " + ) + + + + + DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "::/0"} + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + locPrf=150, + ) + + assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result) + # updating the topology with the updated AS-Number to avoid conflict in con configuring the AS + updated_topo = topo + updated_topo['routers']['r0']['bgp']['local_as']=get_dut_as_number(tgen,"r0") + updated_topo['routers']['r1']['bgp']['local_as']=get_dut_as_number(tgen,"r1") + updated_topo['routers']['r2']['bgp']['local_as']=get_dut_as_number(tgen,"r2") + updated_topo['routers']['r3']['bgp']['local_as']=get_dut_as_number(tgen,"r3") + updated_topo['routers']['r4']['bgp']['local_as']=get_dut_as_number(tgen,"r4") + + step("Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command ") + local_as = get_dut_as_number(tgen, dut="r4") + shut_neighbor = { + "r4": { + "bgp": { + "local_as": local_as, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4": {"shutdown":True} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4": {"shutdown":True} + } + } + } + } + } + } + } + } + } + result = create_router_bgp(tgen, updated_topo, shut_neighbor) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + interface = topo['routers']['r3']['links']['r4']['interface'] + input_dict = { + "r1": { + "interface_list": [interface], + "status": "down" + } + } + + result = interface_status(tgen, topo, input_dict) + assert result is True, "Testcase {} : Shut down the interface failed ! \n Error: {}".format(tc_name, result) + + step("After shutting the interface verify the BGP convergence") + result = verify_bgp_convergence(tgen,topo,expected=False) + assert result is not True, "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format(tc_name, result) + + step("verify default route deleted from R2 ") + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + expected=False) + assert result is not True, "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in RIB -> {}".format( tc_name, result) + + result = verify_fib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + expected=False) + assert result is not True, "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in FIB -> {}".format( tc_name, result) + + + step("no Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command ") + local_as = get_dut_as_number(tgen, dut="r4") + shut_neighbor = { + "r4": { + "bgp": { + "local_as": local_as, + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4": {"shutdown":False} + } + } + } + } + }, + "ipv6": { + "unicast": { + "neighbor": { + "r3": { + "dest_link": { + "r4": {"shutdown":False} + } + } + } + } + } + } + } + } + } + result = create_router_bgp(tgen, updated_topo, shut_neighbor) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + interface = topo['routers']['r3']['links']['r4']['interface'] + input_dict = { + "r1": { + "interface_list": [interface], + "status": "up" + } + } + + result = interface_status(tgen, topo, input_dict) + assert result is True, "Testcase {} : Bring up interface failed ! \n Error: {}".format(tc_name, result) + + step("After no shutting the interface verify the BGP convergence") + result = verify_bgp_convergence(tgen,topo,expected=True) + assert result is True, "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format(tc_name, result) + + step("After no shut neighbor , verify default route relearn on R2") + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + expected=True) + assert result is True, "Testcase {} : Failed \n Error: After no Shut down interface the default route is expected but found in RIB -> {}".format( tc_name, result) + + result = verify_fib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + expected=True) + assert result is True, "Testcase {} : Failed \n Error: After Shut down interface the default route is expected but found in FIB -> {}".format( tc_name, result) + + + + step("Remove IPv4/IPv6 static route configure on R4") + for addr_type in ADDR_TYPES: + static_routes_input = { + "r4": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + "delete": True + } + ] + } + } + result = create_static_routes(tgen, static_routes_input) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + step("Verify IPv4 and IPv6 static routes removed on R4 in FIB") + for addr_type in ADDR_TYPES: + static_routes_input = { + "r4": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + } + ] + } + } + result = verify_fib_routes(tgen, addr_type, "r4", static_routes_input, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + result = verify_bgp_rib(tgen, addr_type, "r4", static_routes_input, expected=False) + assert result is not True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("After removing static route , verify default route removed on R2") + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + expected= False) + assert result is not True, "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in RIB -> {}".format( tc_name, result) + + result = verify_fib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + expected= False) + assert result is not True, "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in FIB -> {}".format( tc_name, result) + + + step("Configuring the static route back in r4") + for addr_type in ADDR_TYPES: + static_routes_input = { + "r4": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + } + ] + } + } + result = create_static_routes(tgen, static_routes_input) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + step("Verify IPv4 and IPv6 static routes configured on R4 in FIB") + for addr_type in ADDR_TYPES: + static_routes_input = { + "r4": { + "static_routes": [ + { + "network": [NETWORK1_1[addr_type]], + "next_hop": NEXT_HOP_IP[addr_type], + } + ] + } + } + result = verify_fib_routes(tgen, addr_type, "r4", static_routes_input, expected=True) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + result = verify_bgp_rib(tgen, addr_type, "r4", static_routes_input, expected=True) + assert result is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, result + ) + + step("After adding static route back , verify default route learned on R2") + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + expected= True) + assert result is True, "Testcase {} : Failed \n Error: After removing static the default route is expected but found in RIB -> {}".format( tc_name, result) + + result = verify_fib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + expected= True) + assert result is True, "Testcase {} : Failed \n Error: After removing static the default route is expected but found in FIB -> {}".format( tc_name, result) + + step("Deactivate IPv4 and IPv6 neighbor configured from R4 ( R4-R3)") + + configure_bgp_on_r1 = { + "r4": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r4": {"deactivate": "ipv4"}}} + } + }, + + },"ipv6": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r4": {"deactivate": "ipv6"}}} + } + }, + + } + } + } + } + } + result = create_router_bgp(tgen, updated_topo, configure_bgp_on_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("After deactivating the BGP neighbor , verify default route removed on R2") + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + expected= False) + assert result is not True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in RIB -> {}".format( tc_name, result) + + result = verify_fib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + expected= False) + assert result is not True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in FIB -> {}".format( tc_name, result) + + step("Activate IPv4 and IPv6 neighbor configured from R4 ( R4-R3)") + + configure_bgp_on_r1 = { + "r4": { + "bgp": { + "address_family": { + "ipv4": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r4": {"activate": "ipv4"}}} + } + }, + + },"ipv6": { + "unicast": { + "neighbor": { + "r3": {"dest_link": {"r4": {"activate": "ipv6"}}} + } + }, + + } + } + } + } + } + result = create_router_bgp(tgen, updated_topo, configure_bgp_on_r1) + assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result) + + step("Verify bgp convergence.") + bgp_convergence = verify_bgp_convergence(tgen, updated_topo) + assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format( + tc_name, bgp_convergence + ) + step("After Activating the BGP neighbor , verify default route learned on R2") + result = verify_rib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + expected= True) + assert result is True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in RIB -> {}".format( tc_name, result) + + result = verify_fib_default_route( + tgen, + topo, + dut="r2", + routes=DEFAULT_ROUTES, + expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3, + expected= True) + assert result is True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in FIB -> {}".format( tc_name, result) + write_test_footer(tc_name) + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tools/frrcommon.sh.in b/tools/frrcommon.sh.in index 3344ff4954..6eb3223faa 100755 --- a/tools/frrcommon.sh.in +++ b/tools/frrcommon.sh.in @@ -208,7 +208,7 @@ daemon_stop() { [ -r "$pidfile" ] || fail="pid file not found" $all && [ -n "$fail" ] && return 0 - [ -z "$fail" ] && pid="$(cat \"$pidfile\")" + [ -z "$fail" ] && pid="$(cat "$pidfile")" [ -z "$fail" -a -z "$pid" ] && fail="pid file is empty" [ -n "$fail" ] || kill -0 "$pid" 2>/dev/null || fail="pid $pid not running" @@ -242,7 +242,7 @@ daemon_status() { pidfile="$V_PATH/$daemon${inst:+-$inst}.pid" [ -r "$pidfile" ] || return 3 - pid="$(cat \"$pidfile\")" + pid="$(cat "$pidfile")" [ -z "$pid" ] && return 1 kill -0 "$pid" 2>/dev/null || return 1 return 0 diff --git a/zebra/zebra_evpn_neigh.c b/zebra/zebra_evpn_neigh.c index d463411dea..6d90a603f7 100644 --- a/zebra/zebra_evpn_neigh.c +++ b/zebra/zebra_evpn_neigh.c @@ -702,11 +702,6 @@ struct zebra_neigh *zebra_evpn_proc_sync_neigh_update( n->flags |= ZEBRA_NEIGH_LOCAL_INACTIVE; } - if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT)) - SET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_PROXY); - else - SET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_ACTIVE); - if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT)) { SET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_PROXY); /* if the neigh was peer-active previously we |
