summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_aspath.c40
-rw-r--r--bgpd/bgp_aspath.h3
-rw-r--r--bgpd/bgp_evpn.c32
-rw-r--r--bgpd/bgp_evpn.h19
-rw-r--r--bgpd/bgp_evpn_mh.c45
-rw-r--r--bgpd/bgp_evpn_private.h16
-rw-r--r--bgpd/bgp_evpn_vty.c2
-rw-r--r--bgpd/bgp_flowspec_vty.c12
-rw-r--r--bgpd/bgp_main.c43
-rw-r--r--bgpd/bgp_memory.c3
-rw-r--r--bgpd/bgp_memory.h3
-rw-r--r--bgpd/bgp_mpath.c9
-rw-r--r--bgpd/bgp_mplsvpn.c161
-rw-r--r--bgpd/bgp_mplsvpn.h7
-rw-r--r--bgpd/bgp_nht.c5
-rw-r--r--bgpd/bgp_packet.c43
-rw-r--r--bgpd/bgp_pbr.c16
-rw-r--r--bgpd/bgp_route.c165
-rw-r--r--bgpd/bgp_route.h104
-rw-r--r--bgpd/bgp_routemap.c139
-rw-r--r--bgpd/bgp_vty.c104
-rw-r--r--bgpd/bgp_zebra.c61
-rw-r--r--bgpd/bgp_zebra.h7
-rw-r--r--bgpd/bgpd.c6
-rw-r--r--bgpd/bgpd.h2
-rw-r--r--bgpd/rfapi/rfapi_vty.c21
-rw-r--r--doc/user/bgp.rst17
-rw-r--r--doc/user/zebra.rst7
-rw-r--r--lib/bitfield.h6
-rw-r--r--lib/command.c16
-rw-r--r--lib/command_match.h5
-rw-r--r--lib/zclient.c1
-rw-r--r--lib/zclient.h1
-rw-r--r--ospfd/ospf_ti_lfa.c6
-rw-r--r--tests/topotests/babel_topo1/r3/babeld.conf1
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf1
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf1
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf1
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf1
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf1
-rw-r--r--tests/topotests/bgp_addpath_best_selected/r2/bgpd.conf1
-rw-r--r--tests/topotests/bgp_addpath_best_selected/test_bgp_addpath_best_selected.py40
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py130
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py2
-rw-r--r--tests/topotests/bgp_set_aspath_replace/test_bgp_set_aspath_replace.py76
-rwxr-xr-xtests/topotests/bgp_srv6l3vpn_over_ipv6/test_bgp_srv6l3vpn_over_ipv6.py29
-rwxr-xr-xtests/topotests/bgp_srv6l3vpn_sid/test_bgp_srv6l3vpn_sid.py81
-rwxr-xr-xtests/topotests/bgp_srv6l3vpn_to_bgp_vrf/test_bgp_srv6l3vpn_to_bgp_vrf.py61
-rwxr-xr-xtests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/test_bgp_srv6l3vpn_to_bgp_vrf2.py36
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/test_bgp_srv6l3vpn_to_bgp_vrf3.py139
-rw-r--r--tests/topotests/bgp_update_delay/r2/zebra.conf4
-rw-r--r--tests/topotests/bgp_vpnv4_asbr/test_bgp_vpnv4_asbr.py33
-rw-r--r--tests/topotests/bgp_vpnv4_noretain/r1/isisd.conf14
-rw-r--r--tests/topotests/bgp_vpnv4_noretain/r2/isisd.conf14
-rw-r--r--tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py3
-rw-r--r--tests/topotests/config_timing/r1/zebra.conf2
-rw-r--r--tests/topotests/cspf_topo1/r1/sharpd.conf1
-rw-r--r--tests/topotests/isis_snmp/r1/ldpd.conf1
-rw-r--r--tests/topotests/lib/checkping.py33
-rw-r--r--tests/topotests/ospf6_gr_topo1/rt1/ospf6d.conf1
-rw-r--r--vtysh/vtysh_config.c4
-rw-r--r--zebra/main.c63
-rw-r--r--zebra/zapi_msg.c2
-rw-r--r--zebra/zebra_dplane.c210
-rw-r--r--zebra/zebra_dplane.h3
-rw-r--r--zebra/zebra_router.c5
-rw-r--r--zebra/zebra_router.h4
-rw-r--r--zebra/zebra_vty.c3
68 files changed, 1208 insertions, 920 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 4ea81216bf..2e2248cd72 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -1231,6 +1231,46 @@ bool aspath_private_as_check(struct aspath *aspath)
return true;
}
+/* Replace all ASN instances of the regex rule with our own ASN */
+struct aspath *aspath_replace_regex_asn(struct aspath *aspath,
+ struct as_list *acl_list, as_t our_asn)
+{
+ struct aspath *new;
+ struct assegment *cur_seg;
+ struct as_list *cur_as_list;
+ struct as_filter *cur_as_filter;
+ char str_buf[ASPATH_STR_DEFAULT_LEN];
+ uint32_t i;
+
+ new = aspath_dup(aspath);
+ cur_seg = new->segments;
+
+ while (cur_seg) {
+ cur_as_list = acl_list;
+ while (cur_as_list) {
+ cur_as_filter = cur_as_list->head;
+ while (cur_as_filter) {
+ for (i = 0; i < cur_seg->length; i++) {
+ snprintfrr(str_buf,
+ ASPATH_STR_DEFAULT_LEN,
+ ASN_FORMAT(new->asnotation),
+ &cur_seg->as[i]);
+ if (!regexec(cur_as_filter->reg,
+ str_buf, 0, NULL, 0))
+ cur_seg->as[i] = our_asn;
+ }
+ cur_as_filter = cur_as_filter->next;
+ }
+ cur_as_list = cur_as_list->next;
+ }
+ cur_seg = cur_seg->next;
+ }
+
+ aspath_str_update(new, false);
+ return new;
+}
+
+
/* Replace all instances of the target ASN with our own ASN */
struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
as_t target_asn, as_t our_asn)
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index b1a61d5b99..ebfc7d087d 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -107,6 +107,9 @@ extern unsigned int aspath_get_last_as(struct aspath *aspath);
extern int aspath_loop_check(struct aspath *aspath, as_t asno);
extern int aspath_loop_check_confed(struct aspath *aspath, as_t asno);
extern bool aspath_private_as_check(struct aspath *aspath);
+extern struct aspath *aspath_replace_regex_asn(struct aspath *aspath,
+ struct as_list *acl_list,
+ as_t our_asn);
extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
as_t target_asn,
as_t our_asn);
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index a33f59cf5b..35f2438929 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -1924,7 +1924,8 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
/* Mark route as self type-2 route */
if (flags && CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP))
- tmp_pi->extra->af_flags = BGP_EVPN_MACIP_TYPE_SVI_IP;
+ tmp_pi->extra->evpn->af_flags =
+ BGP_EVPN_MACIP_TYPE_SVI_IP;
bgp_path_info_add(dest, tmp_pi);
} else {
tmp_pi = local_pi;
@@ -2390,7 +2391,8 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
attr.router_flag = 1;
}
memcpy(&attr.esi, &local_pi->attr->esi, sizeof(esi_t));
- bgp_evpn_get_rmac_nexthop(vpn, &evp, &attr, local_pi->extra->af_flags);
+ bgp_evpn_get_rmac_nexthop(vpn, &evp, &attr,
+ local_pi->extra->evpn->af_flags);
vni2label(vpn->vni, &(attr.label));
/* Add L3 VNI RTs and RMAC for non IPv6 link-local if
* using L3 VNI for type-2 routes also.
@@ -2829,7 +2831,11 @@ bgp_create_evpn_bgp_path_info(struct bgp_path_info *parent_pi,
attr_new, dest);
SET_FLAG(pi->flags, BGP_PATH_VALID);
bgp_path_info_extra_get(pi);
- pi->extra->parent = bgp_path_info_lock(parent_pi);
+ if (!pi->extra->vrfleak)
+ pi->extra->vrfleak =
+ XCALLOC(MTYPE_BGP_ROUTE_EXTRA_VRFLEAK,
+ sizeof(struct bgp_path_info_extra_vrfleak));
+ pi->extra->vrfleak->parent = bgp_path_info_lock(parent_pi);
bgp_dest_lock_node((struct bgp_dest *)parent_pi->net);
if (parent_pi->extra) {
memcpy(&pi->extra->label, &parent_pi->extra->label,
@@ -2935,8 +2941,9 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
/* Check if route entry is already present. */
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
- if (pi->extra
- && (struct bgp_path_info *)pi->extra->parent == parent_pi)
+ if (pi->extra && pi->extra->vrfleak &&
+ (struct bgp_path_info *)pi->extra->vrfleak->parent ==
+ parent_pi)
break;
if (!pi) {
@@ -3031,8 +3038,9 @@ static int install_evpn_route_entry_in_vni_common(
/* Check if route entry is already present. */
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
- if (pi->extra
- && (struct bgp_path_info *)pi->extra->parent == parent_pi)
+ if (pi->extra && pi->extra->vrfleak &&
+ (struct bgp_path_info *)pi->extra->vrfleak->parent ==
+ parent_pi)
break;
if (!pi) {
@@ -3127,8 +3135,9 @@ static int uninstall_evpn_route_entry_in_vni_common(
/* Find matching route entry. */
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
- if (pi->extra &&
- (struct bgp_path_info *)pi->extra->parent == parent_pi)
+ if (pi->extra && pi->extra->vrfleak &&
+ (struct bgp_path_info *)pi->extra->vrfleak->parent ==
+ parent_pi)
break;
if (!pi)
@@ -3305,8 +3314,9 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
/* Find matching route entry. */
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
- if (pi->extra
- && (struct bgp_path_info *)pi->extra->parent == parent_pi)
+ if (pi->extra && pi->extra->vrfleak &&
+ (struct bgp_path_info *)pi->extra->vrfleak->parent ==
+ parent_pi)
break;
if (!pi) {
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index 076248c9f7..55474464e5 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -51,15 +51,15 @@ get_route_parent_evpn(struct bgp_path_info *ri)
struct bgp_path_info *parent_ri;
/* If not imported (or doesn't have a parent), bail. */
- if (ri->sub_type != BGP_ROUTE_IMPORTED ||
- !ri->extra ||
- !ri->extra->parent)
+ if (ri->sub_type != BGP_ROUTE_IMPORTED || !ri->extra ||
+ !ri->extra->vrfleak || !ri->extra->vrfleak->parent)
return NULL;
/* Determine parent recursively */
- for (parent_ri = ri->extra->parent;
- parent_ri->extra && parent_ri->extra->parent;
- parent_ri = parent_ri->extra->parent)
+ for (parent_ri = ri->extra->vrfleak->parent;
+ parent_ri->extra && parent_ri->extra->vrfleak &&
+ parent_ri->extra->vrfleak->parent;
+ parent_ri = parent_ri->extra->vrfleak->parent)
;
return parent_ri;
@@ -103,12 +103,11 @@ static inline bool is_route_injectable_into_evpn(struct bgp_path_info *pi)
struct bgp_table *table;
struct bgp_dest *dest;
- if (pi->sub_type != BGP_ROUTE_IMPORTED ||
- !pi->extra ||
- !pi->extra->parent)
+ if (pi->sub_type != BGP_ROUTE_IMPORTED || !pi->extra ||
+ !pi->extra->vrfleak || !pi->extra->vrfleak->parent)
return true;
- parent_pi = (struct bgp_path_info *)pi->extra->parent;
+ parent_pi = (struct bgp_path_info *)pi->extra->vrfleak->parent;
dest = parent_pi->net;
if (!dest)
return true;
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index efadda17b8..36bf752d48 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -185,8 +185,9 @@ static int bgp_evpn_es_route_install(struct bgp *bgp,
/* Check if route entry is already present. */
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
- if (pi->extra &&
- (struct bgp_path_info *)pi->extra->parent == parent_pi)
+ if (pi->extra && pi->extra->vrfleak &&
+ (struct bgp_path_info *)pi->extra->vrfleak->parent ==
+ parent_pi)
break;
if (!pi) {
@@ -198,7 +199,11 @@ static int bgp_evpn_es_route_install(struct bgp *bgp,
parent_pi->peer, attr_new, dest);
SET_FLAG(pi->flags, BGP_PATH_VALID);
bgp_path_info_extra_get(pi);
- pi->extra->parent = bgp_path_info_lock(parent_pi);
+ if (!pi->extra->vrfleak)
+ pi->extra->vrfleak =
+ XCALLOC(MTYPE_BGP_ROUTE_EXTRA_VRFLEAK,
+ sizeof(struct bgp_path_info_extra_vrfleak));
+ pi->extra->vrfleak->parent = bgp_path_info_lock(parent_pi);
bgp_dest_lock_node((struct bgp_dest *)parent_pi->net);
bgp_path_info_add(dest, pi);
} else {
@@ -253,9 +258,9 @@ static int bgp_evpn_es_route_uninstall(struct bgp *bgp, struct bgp_evpn_es *es,
/* Find matching route entry. */
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
- if (pi->extra
- && (struct bgp_path_info *)pi->extra->parent ==
- parent_pi)
+ if (pi->extra && pi->extra->vrfleak &&
+ (struct bgp_path_info *)pi->extra->vrfleak->parent ==
+ parent_pi)
break;
if (!pi) {
@@ -1548,10 +1553,11 @@ bgp_evpn_path_es_info_new(struct bgp_path_info *pi, vni_t vni)
e = bgp_path_info_extra_get(pi);
/* If mh_info doesn't exist allocate it */
- mh_info = e->mh_info;
+ mh_info = e->evpn->mh_info;
if (!mh_info)
- e->mh_info = mh_info = XCALLOC(MTYPE_BGP_EVPN_PATH_MH_INFO,
- sizeof(struct bgp_path_mh_info));
+ e->evpn->mh_info = mh_info =
+ XCALLOC(MTYPE_BGP_EVPN_PATH_MH_INFO,
+ sizeof(struct bgp_path_mh_info));
/* If es_info doesn't exist allocate it */
es_info = mh_info->es_info;
@@ -1604,8 +1610,8 @@ void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni, esi_t *esi)
struct bgp_evpn_es *es;
struct bgp *bgp_evpn;
- es_info = (pi->extra && pi->extra->mh_info)
- ? pi->extra->mh_info->es_info
+ es_info = (pi->extra && pi->extra->evpn && pi->extra->evpn->mh_info)
+ ? pi->extra->evpn->mh_info->es_info
: NULL;
/* if the esi is zero just unlink the path from the old es */
if (!esi || !memcmp(esi, zero_esi, sizeof(*esi))) {
@@ -3163,7 +3169,7 @@ bool bgp_evpn_path_es_use_nhg(struct bgp *bgp_vrf, struct bgp_path_info *pi,
*nhg_p = 0;
/* we don't support NHG for routes leaked from another VRF yet */
- if (pi->extra && pi->extra->bgp_orig)
+ if (pi->extra && pi->extra->vrfleak && pi->extra->vrfleak->bgp_orig)
return false;
parent_pi = get_route_parent_evpn(pi);
@@ -4670,10 +4676,11 @@ bgp_evpn_path_nh_info_new(struct bgp_path_info *pi)
e = bgp_path_info_extra_get(pi);
/* If mh_info doesn't exist allocate it */
- mh_info = e->mh_info;
+ mh_info = e->evpn->mh_info;
if (!mh_info)
- e->mh_info = mh_info = XCALLOC(MTYPE_BGP_EVPN_PATH_MH_INFO,
- sizeof(struct bgp_path_mh_info));
+ e->evpn->mh_info = mh_info =
+ XCALLOC(MTYPE_BGP_EVPN_PATH_MH_INFO,
+ sizeof(struct bgp_path_mh_info));
/* If nh_info doesn't exist allocate it */
nh_info = mh_info->nh_info;
@@ -4738,8 +4745,8 @@ static void bgp_evpn_path_nh_link(struct bgp *bgp_vrf, struct bgp_path_info *pi)
return;
}
- nh_info = (pi->extra && pi->extra->mh_info)
- ? pi->extra->mh_info->nh_info
+ nh_info = (pi->extra && pi->extra->evpn && pi->extra->evpn->mh_info)
+ ? pi->extra->evpn->mh_info->nh_info
: NULL;
/* if NHG is not being used for this path we don't need to manage the
@@ -4805,8 +4812,8 @@ void bgp_evpn_path_nh_del(struct bgp *bgp_vrf, struct bgp_path_info *pi)
{
struct bgp_path_evpn_nh_info *nh_info;
- nh_info = (pi->extra && pi->extra->mh_info)
- ? pi->extra->mh_info->nh_info
+ nh_info = (pi->extra && pi->extra->evpn && pi->extra->evpn->mh_info)
+ ? pi->extra->evpn->mh_info->nh_info
: NULL;
if (!nh_info)
diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h
index 8cee048b69..f141ddd6ef 100644
--- a/bgpd/bgp_evpn_private.h
+++ b/bgpd/bgp_evpn_private.h
@@ -581,32 +581,32 @@ evpn_type2_prefix_vni_mac_copy(struct prefix_evpn *vni_p,
static inline struct ethaddr *
evpn_type2_path_info_get_mac(const struct bgp_path_info *local_pi)
{
- assert(local_pi->extra);
- return &local_pi->extra->vni_info.mac;
+ assert(local_pi->extra && local_pi->extra->evpn);
+ return &local_pi->extra->evpn->vni_info.mac;
}
/* Get IP of path_info prefix */
static inline struct ipaddr *
evpn_type2_path_info_get_ip(const struct bgp_path_info *local_pi)
{
- assert(local_pi->extra);
- return &local_pi->extra->vni_info.ip;
+ assert(local_pi->extra && local_pi->extra->evpn);
+ return &local_pi->extra->evpn->vni_info.ip;
}
/* Set MAC of path_info prefix */
static inline void evpn_type2_path_info_set_mac(struct bgp_path_info *local_pi,
const struct ethaddr mac)
{
- assert(local_pi->extra);
- local_pi->extra->vni_info.mac = mac;
+ assert(local_pi->extra && local_pi->extra->evpn);
+ local_pi->extra->evpn->vni_info.mac = mac;
}
/* Set IP of path_info prefix */
static inline void evpn_type2_path_info_set_ip(struct bgp_path_info *local_pi,
const struct ipaddr ip)
{
- assert(local_pi->extra);
- local_pi->extra->vni_info.ip = ip;
+ assert(local_pi->extra && local_pi->extra->evpn);
+ local_pi->extra->evpn->vni_info.ip = ip;
}
/* Is the IP empty for the RT's dest? */
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index 442dd6ff3b..8b4f4509ae 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -389,7 +389,7 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
}
json_object_string_add(json, "advertiseGatewayMacip", "n/a");
json_object_string_add(json, "advertiseSviMacIp", "n/a");
- if (bgp_vrf && bgp_vrf->evpn_info) {
+ if (bgp_vrf->evpn_info) {
json_object_string_add(json, "advertisePip",
bgp_vrf->evpn_info->advertise_pip
? "Enabled"
diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c
index 7df1423e59..a295ec5a14 100644
--- a/bgpd/bgp_flowspec_vty.c
+++ b/bgpd/bgp_flowspec_vty.c
@@ -355,7 +355,8 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
bgp_path_info_extra_get(path);
bool list_began = false;
- if (extra->bgp_fs_pbr && listcount(extra->bgp_fs_pbr)) {
+ if (extra->flowspec && extra->flowspec->bgp_fs_pbr &&
+ listcount(extra->flowspec->bgp_fs_pbr)) {
struct listnode *node;
struct bgp_pbr_match_entry *bpme;
struct bgp_pbr_match *bpm;
@@ -363,8 +364,8 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
list_bpm = list_new();
vty_out(vty, "\tinstalled in PBR");
- for (ALL_LIST_ELEMENTS_RO(extra->bgp_fs_pbr,
- node, bpme)) {
+ for (ALL_LIST_ELEMENTS_RO(extra->flowspec->bgp_fs_pbr, node,
+ bpme)) {
bpm = bpme->backpointer;
if (listnode_lookup(list_bpm, bpm))
continue;
@@ -378,13 +379,14 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
}
list_delete(&list_bpm);
}
- if (extra->bgp_fs_iprule && listcount(extra->bgp_fs_iprule)) {
+ if (extra->flowspec && extra->flowspec->bgp_fs_iprule &&
+ listcount(extra->flowspec->bgp_fs_iprule)) {
struct listnode *node;
struct bgp_pbr_rule *bpr;
if (!list_began)
vty_out(vty, "\tinstalled in PBR");
- for (ALL_LIST_ELEMENTS_RO(extra->bgp_fs_iprule,
+ for (ALL_LIST_ELEMENTS_RO(extra->flowspec->bgp_fs_iprule,
node, bpr)) {
if (!bpr->action)
continue;
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 074059c146..11917c6c4a 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -57,15 +57,17 @@
/* bgpd options, we use GNU getopt library. */
static const struct option longopts[] = {
- {"bgp_port", required_argument, NULL, 'p'},
- {"listenon", required_argument, NULL, 'l'},
- {"no_kernel", no_argument, NULL, 'n'},
- {"skip_runas", no_argument, NULL, 'S'},
- {"ecmp", required_argument, NULL, 'e'},
- {"int_num", required_argument, NULL, 'I'},
- {"no_zebra", no_argument, NULL, 'Z'},
- {"socket_size", required_argument, NULL, 's'},
- {0}};
+ { "bgp_port", required_argument, NULL, 'p' },
+ { "listenon", required_argument, NULL, 'l' },
+ { "no_kernel", no_argument, NULL, 'n' },
+ { "skip_runas", no_argument, NULL, 'S' },
+ { "ecmp", required_argument, NULL, 'e' },
+ { "int_num", required_argument, NULL, 'I' },
+ { "no_zebra", no_argument, NULL, 'Z' },
+ { "socket_size", required_argument, NULL, 's' },
+ { "v6-with-v4-nexthops", no_argument, NULL, 'v' },
+ { 0 }
+};
/* signal definitions */
void sighup(void);
@@ -387,16 +389,16 @@ int main(int argc, char **argv)
addresses->cmp = (int (*)(void *, void *))strcmp;
frr_preinit(&bgpd_di, argc, argv);
- frr_opt_add(
- "p:l:SnZe:I:s:" DEPRECATED_OPTIONS, longopts,
- " -p, --bgp_port Set BGP listen port number (0 means do not listen).\n"
- " -l, --listenon Listen on specified address (implies -n)\n"
- " -n, --no_kernel Do not install route to kernel.\n"
- " -Z, --no_zebra Do not communicate with Zebra.\n"
- " -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n"
- " -e, --ecmp Specify ECMP to use.\n"
- " -I, --int_num Set instance number (label-manager)\n"
- " -s, --socket_size Set BGP peer socket send buffer size\n");
+ frr_opt_add("p:l:SnZe:I:s:" DEPRECATED_OPTIONS, longopts,
+ " -p, --bgp_port Set BGP listen port number (0 means do not listen).\n"
+ " -l, --listenon Listen on specified address (implies -n)\n"
+ " -n, --no_kernel Do not install route to kernel.\n"
+ " -Z, --no_zebra Do not communicate with Zebra.\n"
+ " -S, --skip_runas Skip capabilities checks, and changing user and group IDs.\n"
+ " -e, --ecmp Specify ECMP to use.\n"
+ " -I, --int_num Set instance number (label-manager)\n"
+ " -s, --socket_size Set BGP peer socket send buffer size\n"
+ " , --v6-with-v4-nexthop Allow BGP to form v6 neighbors using v4 nexthops\n");
/* Command line argument treatment. */
while (1) {
@@ -458,6 +460,9 @@ int main(int argc, char **argv)
case 's':
buffer_size = atoi(optarg);
break;
+ case 'v':
+ bm->v6_with_v4_nexthops = true;
+ break;
default:
frr_help_exit(1);
}
diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c
index d7b18de676..edaaef6021 100644
--- a/bgpd/bgp_memory.c
+++ b/bgpd/bgp_memory.c
@@ -37,6 +37,9 @@ DEFINE_MTYPE(BGPD, BGP_TABLE, "BGP table");
DEFINE_MTYPE(BGPD, BGP_NODE, "BGP node");
DEFINE_MTYPE(BGPD, BGP_ROUTE, "BGP route");
DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA, "BGP ancillary route info");
+DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA_EVPN, "BGP extra info for EVPN");
+DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA_FS, "BGP extra info for flowspec");
+DEFINE_MTYPE(BGPD, BGP_ROUTE_EXTRA_VRFLEAK, "BGP extra info for vrf leaking");
DEFINE_MTYPE(BGPD, BGP_CONN, "BGP connected");
DEFINE_MTYPE(BGPD, BGP_STATIC, "BGP static");
DEFINE_MTYPE(BGPD, BGP_ADVERTISE_ATTR, "BGP adv attr");
diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h
index 7b00497714..1256eafd00 100644
--- a/bgpd/bgp_memory.h
+++ b/bgpd/bgp_memory.h
@@ -33,6 +33,9 @@ DECLARE_MTYPE(BGP_TABLE);
DECLARE_MTYPE(BGP_NODE);
DECLARE_MTYPE(BGP_ROUTE);
DECLARE_MTYPE(BGP_ROUTE_EXTRA);
+DECLARE_MTYPE(BGP_ROUTE_EXTRA_EVPN);
+DECLARE_MTYPE(BGP_ROUTE_EXTRA_FS);
+DECLARE_MTYPE(BGP_ROUTE_EXTRA_VRFLEAK);
DECLARE_MTYPE(BGP_CONN);
DECLARE_MTYPE(BGP_STATIC);
DECLARE_MTYPE(BGP_ADVERTISE_ATTR);
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index e920d5753e..f2d1ee0bf3 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -173,10 +173,11 @@ int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1,
* if they belong to same VRF
*/
if (!compare && bpi1->attr->nh_type != NEXTHOP_TYPE_BLACKHOLE) {
- if (bpi1->extra && bpi1->extra->bgp_orig && bpi2->extra
- && bpi2->extra->bgp_orig) {
- if (bpi1->extra->bgp_orig->vrf_id
- != bpi2->extra->bgp_orig->vrf_id) {
+ if (bpi1->extra && bpi1->extra->vrfleak &&
+ bpi1->extra->vrfleak->bgp_orig && bpi2->extra &&
+ bpi2->extra->vrfleak && bpi2->extra->vrfleak->bgp_orig) {
+ if (bpi1->extra->vrfleak->bgp_orig->vrf_id !=
+ bpi2->extra->vrfleak->bgp_orig->vrf_id) {
compare = 1;
}
}
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index da599688ea..ad66720512 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -996,41 +996,6 @@ static void setlabels(struct bgp_path_info *bpi,
extra->num_labels = num_labels;
}
-/*
- * make encoded route SIDs match specified encoded sid set
- */
-static void setsids(struct bgp_path_info *bpi,
- struct in6_addr *sid,
- uint32_t num_sids)
-{
- uint32_t i;
- struct bgp_path_info_extra *extra;
-
- if (num_sids)
- assert(sid);
- assert(num_sids <= BGP_MAX_SIDS);
-
- if (!num_sids) {
- if (bpi->extra)
- bpi->extra->num_sids = 0;
- return;
- }
-
- extra = bgp_path_info_extra_get(bpi);
- for (i = 0; i < num_sids; i++)
- memcpy(&extra->sid[i].sid, &sid[i], sizeof(struct in6_addr));
- extra->num_sids = num_sids;
-}
-
-static void unsetsids(struct bgp_path_info *bpi)
-{
- struct bgp_path_info_extra *extra;
-
- extra = bgp_path_info_extra_get(bpi);
- extra->num_sids = 0;
- 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,
@@ -1045,8 +1010,8 @@ static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
bpi_ultimate = bgp_get_imported_bpi_ultimate(source_bpi);
- if (bpi->extra && bpi->extra->bgp_orig)
- bgp_nexthop = bpi->extra->bgp_orig;
+ if (bpi->extra && bpi->extra->vrfleak && bpi->extra->vrfleak->bgp_orig)
+ bgp_nexthop = bpi->extra->vrfleak->bgp_orig;
else
bgp_nexthop = bgp_orig;
@@ -1098,12 +1063,8 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
struct bgp_path_info *bpi;
struct bgp_path_info *new;
struct bgp_path_info_extra *extra;
- uint32_t num_sids = 0;
struct bgp_path_info *parent = source_bpi;
- if (new_attr->srv6_l3vpn || new_attr->srv6_vpn)
- num_sids = 1;
-
if (debug)
zlog_debug(
"%s: entry: leak-to=%s, p=%pBD, type=%d, sub_type=%d",
@@ -1132,7 +1093,8 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
* match parent
*/
for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
- if (bpi->extra && bpi->extra->parent == parent)
+ if (bpi->extra && bpi->extra->vrfleak &&
+ bpi->extra->vrfleak->parent == parent)
break;
}
@@ -1200,34 +1162,6 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
if (!labelssame)
setlabels(bpi, label, num_labels);
- /*
- * rewrite sid
- */
- if (num_sids) {
- if (new_attr->srv6_l3vpn) {
- setsids(bpi, &new_attr->srv6_l3vpn->sid,
- num_sids);
-
- extra = bgp_path_info_extra_get(bpi);
-
- extra->sid[0].loc_block_len =
- new_attr->srv6_l3vpn->loc_block_len;
- extra->sid[0].loc_node_len =
- new_attr->srv6_l3vpn->loc_node_len;
- extra->sid[0].func_len =
- new_attr->srv6_l3vpn->func_len;
- extra->sid[0].arg_len =
- new_attr->srv6_l3vpn->arg_len;
- extra->sid[0].transposition_len =
- new_attr->srv6_l3vpn->transposition_len;
- extra->sid[0].transposition_offset =
- new_attr->srv6_l3vpn
- ->transposition_offset;
- } else if (new_attr->srv6_vpn)
- setsids(bpi, &new_attr->srv6_vpn->sid,
- num_sids);
- } else
- unsetsids(bpi);
if (nexthop_self_flag)
bgp_path_info_set_flag(bn, bpi, BGP_PATH_ANNC_NH_SELF);
@@ -1267,9 +1201,15 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0,
to_bgp->peer_self, new_attr, bn);
+ bgp_path_info_extra_get(new);
+ if (!new->extra->vrfleak)
+ new->extra->vrfleak =
+ XCALLOC(MTYPE_BGP_ROUTE_EXTRA_VRFLEAK,
+ sizeof(struct bgp_path_info_extra_vrfleak));
+
if (source_bpi->peer) {
extra = bgp_path_info_extra_get(new);
- extra->peer_orig = peer_lock(source_bpi->peer);
+ extra->vrfleak->peer_orig = peer_lock(source_bpi->peer);
}
if (nexthop_self_flag)
@@ -1278,42 +1218,16 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
if (CHECK_FLAG(source_bpi->flags, BGP_PATH_ACCEPT_OWN))
bgp_path_info_set_flag(bn, new, BGP_PATH_ACCEPT_OWN);
- bgp_path_info_extra_get(new);
-
- /*
- * rewrite sid
- */
- if (num_sids) {
- if (new_attr->srv6_l3vpn) {
- setsids(new, &new_attr->srv6_l3vpn->sid, num_sids);
-
- extra = bgp_path_info_extra_get(new);
-
- extra->sid[0].loc_block_len =
- new_attr->srv6_l3vpn->loc_block_len;
- extra->sid[0].loc_node_len =
- new_attr->srv6_l3vpn->loc_node_len;
- extra->sid[0].func_len = new_attr->srv6_l3vpn->func_len;
- extra->sid[0].arg_len = new_attr->srv6_l3vpn->arg_len;
- extra->sid[0].transposition_len =
- new_attr->srv6_l3vpn->transposition_len;
- extra->sid[0].transposition_offset =
- new_attr->srv6_l3vpn->transposition_offset;
- } else if (new_attr->srv6_vpn)
- setsids(new, &new_attr->srv6_vpn->sid, num_sids);
- } else
- unsetsids(new);
-
if (num_labels)
setlabels(new, label, num_labels);
- new->extra->parent = bgp_path_info_lock(parent);
+ new->extra->vrfleak->parent = bgp_path_info_lock(parent);
bgp_dest_lock_node(
(struct bgp_dest *)parent->net);
if (bgp_orig)
- new->extra->bgp_orig = bgp_lock(bgp_orig);
+ new->extra->vrfleak->bgp_orig = bgp_lock(bgp_orig);
if (nexthop_orig)
- new->extra->nexthop_orig = *nexthop_orig;
+ new->extra->vrfleak->nexthop_orig = *nexthop_orig;
if (leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi,
source_bpi, new, bgp_orig, p, debug))
@@ -1554,8 +1468,8 @@ vpn_leak_from_vrf_get_per_nexthop_label(afi_t afi, struct bgp_path_info *pi,
/* Check the next-hop reachability.
* Get the bgp instance where the bgp_path_info originates.
*/
- if (pi->extra && pi->extra->bgp_orig)
- bgp_nexthop = pi->extra->bgp_orig;
+ if (pi->extra && pi->extra->vrfleak && pi->extra->vrfleak->bgp_orig)
+ bgp_nexthop = pi->extra->vrfleak->bgp_orig;
else
bgp_nexthop = from_bgp;
@@ -1986,7 +1900,8 @@ void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp, /* to */
* match original bpi imported from
*/
for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; bpi = bpi->next) {
- if (bpi->extra && bpi->extra->parent == path_vrf) {
+ if (bpi->extra && bpi->extra->vrfleak &&
+ bpi->extra->vrfleak->parent == path_vrf) {
break;
}
}
@@ -2039,9 +1954,9 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp,
bpi->sub_type);
if (bpi->sub_type != BGP_ROUTE_IMPORTED)
continue;
- if (!bpi->extra)
+ if (!bpi->extra || !bpi->extra->vrfleak)
continue;
- if ((struct bgp *)bpi->extra->bgp_orig ==
+ if ((struct bgp *)bpi->extra->vrfleak->bgp_orig ==
from_bgp) {
/* delete route */
if (debug)
@@ -2055,7 +1970,7 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp,
bgp_path_info_delete(bn, bpi);
bgp_process(to_bgp, bn, afi, safi);
bgp_mplsvpn_path_nh_label_unlink(
- bpi->extra->parent);
+ bpi->extra->vrfleak->parent);
}
}
}
@@ -2162,8 +2077,9 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
*/
struct bgp *src_bgp = bgp_lookup_by_rd(path_vpn, prd, afi);
- if (path_vpn->extra && path_vpn->extra->bgp_orig)
- src_vrf = path_vpn->extra->bgp_orig;
+ if (path_vpn->extra && path_vpn->extra->vrfleak &&
+ path_vpn->extra->vrfleak->bgp_orig)
+ src_vrf = path_vpn->extra->vrfleak->bgp_orig;
else if (src_bgp)
src_vrf = src_bgp;
else
@@ -2429,9 +2345,8 @@ void vpn_leak_to_vrf_update(struct bgp *from_bgp,
/* Loop over VRFs */
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
-
- if (!path_vpn->extra
- || path_vpn->extra->bgp_orig != bgp) { /* no loop */
+ if (!path_vpn->extra || !path_vpn->extra->vrfleak ||
+ path_vpn->extra->vrfleak->bgp_orig != bgp) { /* no loop */
vpn_leak_to_vrf_update_onevrf(bgp, from_bgp, path_vpn,
prd);
}
@@ -2504,9 +2419,9 @@ void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn)
for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
bpi = bpi->next) {
- if (bpi->extra
- && (struct bgp_path_info *)bpi->extra->parent
- == path_vpn) {
+ if (bpi->extra && bpi->extra->vrfleak &&
+ (struct bgp_path_info *)bpi->extra->vrfleak->parent ==
+ path_vpn) {
break;
}
}
@@ -2540,10 +2455,10 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi)
for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
bpi = bpi->next) {
- if (bpi->extra && bpi->extra->bgp_orig != to_bgp &&
- bpi->extra->parent &&
- is_pi_family_vpn(bpi->extra->parent)) {
-
+ if (bpi->extra && bpi->extra->vrfleak &&
+ bpi->extra->vrfleak->bgp_orig != to_bgp &&
+ bpi->extra->vrfleak->parent &&
+ is_pi_family_vpn(bpi->extra->vrfleak->parent)) {
/* delete route */
bgp_aggregate_decrement(to_bgp,
bgp_dest_get_prefix(bn),
@@ -2580,9 +2495,8 @@ void vpn_leak_no_retain(struct bgp *to_bgp, struct bgp *vpn_from, afi_t afi)
for (bn = bgp_table_top(table); 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 == to_bgp)
+ if (bpi->extra && bpi->extra->vrfleak &&
+ bpi->extra->vrfleak->bgp_orig == to_bgp)
continue;
if (bpi->sub_type != BGP_ROUTE_NORMAL)
@@ -2627,9 +2541,8 @@ void vpn_leak_to_vrf_update_all(struct bgp *to_bgp, struct bgp *vpn_from,
for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
bpi = bpi->next) {
-
- if (bpi->extra &&
- bpi->extra->bgp_orig == to_bgp)
+ if (bpi->extra && bpi->extra->vrfleak &&
+ bpi->extra->vrfleak->bgp_orig == to_bgp)
continue;
vpn_leak_to_vrf_update_onevrf(to_bgp, vpn_from,
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
index dcde42146c..62748a9e56 100644
--- a/bgpd/bgp_mplsvpn.h
+++ b/bgpd/bgp_mplsvpn.h
@@ -298,12 +298,11 @@ static inline bool is_route_injectable_into_vpn(struct bgp_path_info *pi)
struct bgp_table *table;
struct bgp_dest *dest;
- if (pi->sub_type != BGP_ROUTE_IMPORTED ||
- !pi->extra ||
- !pi->extra->parent)
+ if (pi->sub_type != BGP_ROUTE_IMPORTED || !pi->extra ||
+ !pi->extra->vrfleak || !pi->extra->vrfleak->parent)
return true;
- parent_pi = (struct bgp_path_info *)pi->extra->parent;
+ parent_pi = (struct bgp_path_info *)pi->extra->vrfleak->parent;
dest = parent_pi->net;
if (!dest)
return true;
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 02cfd9c2af..bbc30365c7 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -56,10 +56,11 @@ static int bgp_isvalid_nexthop_for_ebgp(struct bgp_nexthop_cache *bnc,
struct bgp_interface *iifp;
struct peer *peer;
- if (!path->extra || !path->extra->peer_orig)
+ if (!path->extra || !path->extra->vrfleak ||
+ !path->extra->vrfleak->peer_orig)
return false;
- peer = path->extra->peer_orig;
+ peer = path->extra->vrfleak->peer_orig;
/* only connected ebgp peers are valid */
if (peer->sort != BGP_PEER_EBGP || peer->ttl != BGP_DEFAULT_TTL ||
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 7c2c6f616b..327c6b79fd 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1202,6 +1202,13 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
unsigned long cap_len;
uint16_t len;
+ if (!peer_established(peer))
+ return;
+
+ if (!CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV) &&
+ !CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV))
+ return;
+
/* Convert AFI, SAFI to values for packet. */
bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
@@ -1272,7 +1279,15 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
case CAPABILITY_CODE_FQDN:
case CAPABILITY_CODE_ENHE:
case CAPABILITY_CODE_EXT_MESSAGE:
+ break;
case CAPABILITY_CODE_ROLE:
+ if (peer->local_role != ROLE_UNDEFINED) {
+ SET_FLAG(peer->cap, PEER_CAP_ROLE_ADV);
+ stream_putc(s, action);
+ stream_putc(s, CAPABILITY_CODE_ROLE);
+ stream_putc(s, CAPABILITY_CODE_ROLE_LEN);
+ stream_putc(s, peer->local_role);
+ }
break;
default:
break;
@@ -1787,11 +1802,14 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
|| peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
|| peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
|| peer->afc_nego[AFI_IP6][SAFI_ENCAP]) {
- if (IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_global)) {
-#if defined(HAVE_CUMULUS)
- zlog_warn("%s: No local IPv6 address, BGP routing may not work",
- peer->host);
-#endif
+ if (IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_global) &&
+ !bm->v6_with_v4_nexthops) {
+ flog_err(EC_BGP_SND_FAIL,
+"%s: No local IPv6 address, and zebra does not support V6 routing with v4 nexthops, BGP routing for V6 will not work",
+ peer->host);
+ bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ return BGP_Stop;
}
}
peer->rtt = sockopt_tcp_rtt(peer->fd);
@@ -2876,7 +2894,22 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
case CAPABILITY_CODE_FQDN:
case CAPABILITY_CODE_ENHE:
case CAPABILITY_CODE_EXT_MESSAGE:
+ break;
case CAPABILITY_CODE_ROLE:
+ SET_FLAG(peer->cap, PEER_CAP_ROLE_RCV);
+ if (hdr->length != CAPABILITY_CODE_ROLE_LEN) {
+ flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
+ "Role: Received invalid length %d",
+ hdr->length);
+ bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ return BGP_Stop;
+ }
+ uint8_t role;
+
+ memcpy(&role, pnt + 3, sizeof(role));
+
+ peer->remote_role = role;
break;
default:
flog_warn(
diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c
index bc9ecff7d9..43682de413 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -1667,8 +1667,8 @@ static void bgp_pbr_flush_iprule(struct bgp *bgp, struct bgp_pbr_action *bpa,
/* unlink path to bpme */
path = (struct bgp_path_info *)bpr->path;
extra = bgp_path_info_extra_get(path);
- if (extra->bgp_fs_iprule)
- listnode_delete(extra->bgp_fs_iprule, bpr);
+ if (extra->flowspec && extra->flowspec->bgp_fs_iprule)
+ listnode_delete(extra->flowspec->bgp_fs_iprule, bpr);
bpr->path = NULL;
}
}
@@ -1696,8 +1696,8 @@ static void bgp_pbr_flush_entry(struct bgp *bgp, struct bgp_pbr_action *bpa,
/* unlink path to bpme */
path = (struct bgp_path_info *)bpme->path;
extra = bgp_path_info_extra_get(path);
- if (extra->bgp_fs_pbr)
- listnode_delete(extra->bgp_fs_pbr, bpme);
+ if (extra->flowspec && extra->flowspec->bgp_fs_pbr)
+ listnode_delete(extra->flowspec->bgp_fs_pbr, bpme);
bpme->path = NULL;
}
}
@@ -2342,8 +2342,8 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
struct bgp_path_info_extra *extra =
bgp_path_info_extra_get(path);
- if (extra &&
- listnode_lookup_nocheck(extra->bgp_fs_iprule,
+ if (extra && extra->flowspec &&
+ listnode_lookup_nocheck(extra->flowspec->bgp_fs_iprule,
bpr)) {
if (BGP_DEBUG(pbr, PBR_ERROR))
zlog_err("%s: entry %p/%p already installed in bgp pbr iprule",
@@ -2501,8 +2501,8 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
struct bgp_path_info_extra *extra =
bgp_path_info_extra_get(path);
- if (extra &&
- listnode_lookup_nocheck(extra->bgp_fs_pbr, bpme)) {
+ if (extra && extra->flowspec &&
+ listnode_lookup_nocheck(extra->flowspec->bgp_fs_pbr, bpme)) {
if (BGP_DEBUG(pbr, PBR_ERROR))
zlog_err(
"%s: entry %p/%p already installed in bgp pbr",
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 5f923c598f..e104aac870 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -188,8 +188,7 @@ static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
sizeof(struct bgp_path_info_extra));
new->label[0] = MPLS_INVALID_LABEL;
new->num_labels = 0;
- new->bgp_fs_pbr = NULL;
- new->bgp_fs_iprule = NULL;
+ new->flowspec = NULL;
return new;
}
@@ -206,8 +205,9 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
e->damp_info->safi);
e->damp_info = NULL;
- if (e->parent) {
- struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent;
+ if (e->vrfleak && e->vrfleak->parent) {
+ struct bgp_path_info *bpi =
+ (struct bgp_path_info *)e->vrfleak->parent;
if (bpi->net) {
/* FIXME: since multiple e may have the same e->parent
@@ -227,26 +227,34 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
bpi->net = NULL;
bgp_path_info_unlock(bpi);
}
- bgp_path_info_unlock(e->parent);
- e->parent = NULL;
+ bgp_path_info_unlock(e->vrfleak->parent);
+ e->vrfleak->parent = NULL;
}
- if (e->bgp_orig)
- bgp_unlock(e->bgp_orig);
+ if (e->vrfleak && e->vrfleak->bgp_orig)
+ bgp_unlock(e->vrfleak->bgp_orig);
- if (e->peer_orig)
- peer_unlock(e->peer_orig);
+ if (e->vrfleak && e->vrfleak->peer_orig)
+ peer_unlock(e->vrfleak->peer_orig);
if (e->aggr_suppressors)
list_delete(&e->aggr_suppressors);
- if (e->mh_info)
- bgp_evpn_path_mh_info_free(e->mh_info);
+ if (e->evpn && e->evpn->mh_info)
+ bgp_evpn_path_mh_info_free(e->evpn->mh_info);
+
+ if ((*extra)->flowspec && (*extra)->flowspec->bgp_fs_iprule)
+ list_delete(&((*extra)->flowspec->bgp_fs_iprule));
+ if ((*extra)->flowspec && (*extra)->flowspec->bgp_fs_pbr)
+ list_delete(&((*extra)->flowspec->bgp_fs_pbr));
+
+ if (e->evpn)
+ XFREE(MTYPE_BGP_ROUTE_EXTRA_EVPN, e->evpn);
+ if (e->flowspec)
+ XFREE(MTYPE_BGP_ROUTE_EXTRA_FS, e->flowspec);
+ if (e->vrfleak)
+ XFREE(MTYPE_BGP_ROUTE_EXTRA_VRFLEAK, e->vrfleak);
- if ((*extra)->bgp_fs_iprule)
- list_delete(&((*extra)->bgp_fs_iprule));
- if ((*extra)->bgp_fs_pbr)
- list_delete(&((*extra)->bgp_fs_pbr));
XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
}
@@ -257,6 +265,10 @@ struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
{
if (!pi->extra)
pi->extra = bgp_path_info_extra_new();
+ if (!pi->extra->evpn && pi->net && pi->net->p.family == AF_EVPN)
+ pi->extra->evpn =
+ XCALLOC(MTYPE_BGP_ROUTE_EXTRA_EVPN,
+ sizeof(struct bgp_path_info_extra_evpn));
return pi->extra;
}
@@ -570,8 +582,9 @@ struct bgp_path_info *bgp_get_imported_bpi_ultimate(struct bgp_path_info *info)
return info;
for (bpi_ultimate = info;
- bpi_ultimate->extra && bpi_ultimate->extra->parent;
- bpi_ultimate = bpi_ultimate->extra->parent)
+ bpi_ultimate->extra && bpi_ultimate->extra->vrfleak &&
+ bpi_ultimate->extra->vrfleak->parent;
+ bpi_ultimate = bpi_ultimate->extra->vrfleak->parent)
;
return bpi_ultimate;
@@ -4674,49 +4687,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_set_valid_label(&extra->label[0]);
}
- /* Update SRv6 SID */
- if (attr->srv6_l3vpn) {
- extra = bgp_path_info_extra_get(pi);
- if (sid_diff(&extra->sid[0].sid,
- &attr->srv6_l3vpn->sid)) {
- sid_copy(&extra->sid[0].sid,
- &attr->srv6_l3vpn->sid);
- extra->num_sids = 1;
-
- extra->sid[0].loc_block_len = 0;
- extra->sid[0].loc_node_len = 0;
- extra->sid[0].func_len = 0;
- extra->sid[0].arg_len = 0;
- extra->sid[0].transposition_len = 0;
- extra->sid[0].transposition_offset = 0;
-
- if (attr->srv6_l3vpn->loc_block_len != 0) {
- extra->sid[0].loc_block_len =
- attr->srv6_l3vpn->loc_block_len;
- extra->sid[0].loc_node_len =
- attr->srv6_l3vpn->loc_node_len;
- extra->sid[0].func_len =
- attr->srv6_l3vpn->func_len;
- extra->sid[0].arg_len =
- attr->srv6_l3vpn->arg_len;
- extra->sid[0].transposition_len =
- attr->srv6_l3vpn
- ->transposition_len;
- extra->sid[0].transposition_offset =
- attr->srv6_l3vpn
- ->transposition_offset;
- }
- }
- } else if (attr->srv6_vpn) {
- extra = bgp_path_info_extra_get(pi);
- if (sid_diff(&extra->sid[0].sid,
- &attr->srv6_vpn->sid)) {
- sid_copy(&extra->sid[0].sid,
- &attr->srv6_vpn->sid);
- extra->num_sids = 1;
- }
- }
-
#ifdef ENABLE_BGP_VNC
if ((afi == AFI_IP || afi == AFI_IP6)
&& (safi == SAFI_UNICAST)) {
@@ -4771,8 +4741,9 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
struct bgp *bgp_nexthop = bgp;
- if (pi->extra && pi->extra->bgp_orig)
- bgp_nexthop = pi->extra->bgp_orig;
+ if (pi->extra && pi->extra->vrfleak &&
+ pi->extra->vrfleak->bgp_orig)
+ bgp_nexthop = pi->extra->vrfleak->bgp_orig;
nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
@@ -4901,29 +4872,6 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_set_valid_label(&extra->label[0]);
}
- /* Update SRv6 SID */
- if (safi == SAFI_MPLS_VPN) {
- extra = bgp_path_info_extra_get(new);
- if (attr->srv6_l3vpn) {
- sid_copy(&extra->sid[0].sid, &attr->srv6_l3vpn->sid);
- extra->num_sids = 1;
-
- extra->sid[0].loc_block_len =
- attr->srv6_l3vpn->loc_block_len;
- extra->sid[0].loc_node_len =
- attr->srv6_l3vpn->loc_node_len;
- extra->sid[0].func_len = attr->srv6_l3vpn->func_len;
- extra->sid[0].arg_len = attr->srv6_l3vpn->arg_len;
- extra->sid[0].transposition_len =
- attr->srv6_l3vpn->transposition_len;
- extra->sid[0].transposition_offset =
- attr->srv6_l3vpn->transposition_offset;
- } else if (attr->srv6_vpn) {
- sid_copy(&extra->sid[0].sid, &attr->srv6_vpn->sid);
- extra->num_sids = 1;
- }
- }
-
/* Nexthop reachability check. */
if (((afi == AFI_IP || afi == AFI_IP6) &&
(safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST ||
@@ -6145,7 +6093,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
addpath_id = 0;
addpath_capable = bgp_addpath_encode_rx(peer, afi, safi);
- /* RFC4771 6.3 The NLRI field in the UPDATE message is checked for
+ /* RFC4271 6.3 The NLRI field in the UPDATE message is checked for
syntactic validity. If the field is syntactically incorrect,
then the Error Subcode is set to Invalid Network Field. */
for (; pnt < lim; pnt += psize) {
@@ -9167,26 +9115,27 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
* If vrf id of nexthop is different from that of prefix,
* set up printable string to append
*/
- if (path->extra && path->extra->bgp_orig) {
+ if (path->extra && path->extra->vrfleak &&
+ path->extra->vrfleak->bgp_orig) {
const char *self = "";
if (nexthop_self)
self = "<";
nexthop_othervrf = true;
- nexthop_vrfid = path->extra->bgp_orig->vrf_id;
+ nexthop_vrfid = path->extra->vrfleak->bgp_orig->vrf_id;
- if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN)
+ if (path->extra->vrfleak->bgp_orig->vrf_id == VRF_UNKNOWN)
snprintf(vrf_id_str, sizeof(vrf_id_str),
"@%s%s", VRFID_NONE_STR, self);
else
snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s",
- path->extra->bgp_orig->vrf_id, self);
+ path->extra->vrfleak->bgp_orig->vrf_id, self);
- if (path->extra->bgp_orig->inst_type
- != BGP_INSTANCE_TYPE_DEFAULT)
+ if (path->extra->vrfleak->bgp_orig->inst_type !=
+ BGP_INSTANCE_TYPE_DEFAULT)
- nexthop_vrfname = path->extra->bgp_orig->name;
+ nexthop_vrfname = path->extra->vrfleak->bgp_orig->name;
} else {
const char *self = "";
@@ -10301,11 +10250,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, "\n");
- if (path->extra && path->extra->parent && !json_paths) {
+ if (path->extra && path->extra->vrfleak &&
+ path->extra->vrfleak->parent && !json_paths) {
struct bgp_path_info *parent_ri;
struct bgp_dest *dest, *pdest;
- parent_ri = (struct bgp_path_info *)path->extra->parent;
+ parent_ri =
+ (struct bgp_path_info *)path->extra->vrfleak->parent;
dest = parent_ri->net;
if (dest && dest->pdest) {
pdest = dest->pdest;
@@ -10608,17 +10559,18 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
/*
* Note when vrfid of nexthop is different from that of prefix
*/
- if (path->extra && path->extra->bgp_orig) {
- vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id;
+ if (path->extra && path->extra->vrfleak &&
+ path->extra->vrfleak->bgp_orig) {
+ vrf_id_t nexthop_vrfid = path->extra->vrfleak->bgp_orig->vrf_id;
if (json_paths) {
const char *vn;
- if (path->extra->bgp_orig->inst_type
- == BGP_INSTANCE_TYPE_DEFAULT)
+ if (path->extra->vrfleak->bgp_orig->inst_type ==
+ BGP_INSTANCE_TYPE_DEFAULT)
vn = VRF_DEFAULT_NAME;
else
- vn = path->extra->bgp_orig->name;
+ vn = path->extra->vrfleak->bgp_orig->name;
json_object_string_add(json_path, "nhVrfName", vn);
@@ -11013,13 +10965,16 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
}
/* Remote SID */
- if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
+ if ((path->attr->srv6_l3vpn || path->attr->srv6_vpn) &&
+ safi != SAFI_EVPN) {
+ struct in6_addr *sid_tmp =
+ path->attr->srv6_l3vpn ? (&path->attr->srv6_l3vpn->sid)
+ : (&path->attr->srv6_vpn->sid);
if (json_paths)
json_object_string_addf(json_path, "remoteSid", "%pI6",
- &path->extra->sid[0].sid);
+ sid_tmp);
else
- vty_out(vty, " Remote SID: %pI6\n",
- &path->extra->sid[0].sid);
+ vty_out(vty, " Remote SID: %pI6\n", sid_tmp);
}
/* Label Index */
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 265587c424..0a6f535b22 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -145,6 +145,54 @@ struct bgp_sid_info {
uint8_t transposition_offset;
};
+/* new structure for EVPN */
+struct bgp_path_info_extra_evpn {
+#define BGP_EVPN_MACIP_TYPE_SVI_IP (1 << 0)
+ /* af specific flags */
+ uint16_t af_flags;
+ union {
+ struct ethaddr mac; /* MAC set here for VNI IP table */
+ struct ipaddr ip; /* IP set here for VNI MAC table */
+ } vni_info;
+ /* Destination Ethernet Segment links for EVPN MH */
+ struct bgp_path_mh_info *mh_info;
+};
+
+/* new structure for flowspec*/
+struct bgp_path_info_extra_fs {
+ /* presence of FS pbr firewall based entry */
+ struct list *bgp_fs_pbr;
+ /* presence of FS pbr iprule based entry */
+ struct list *bgp_fs_iprule;
+};
+
+/* new structure for vrfleak*/
+struct bgp_path_info_extra_vrfleak {
+ void *parent; /* parent from global table */
+ /*
+ * Original bgp instance for imported routes. Needed for:
+ * 1. Find all routes from a specific vrf for deletion
+ * 2. vrf context of original nexthop
+ *
+ * Store pointer to bgp instance rather than bgp->vrf_id because
+ * bgp->vrf_id is not always valid (or may change?).
+ *
+ * Set to NULL if route is not imported from another bgp instance.
+ */
+ struct bgp *bgp_orig;
+ /*
+ * Original bgp session to know if the session is a
+ * connected EBGP session or not
+ */
+ struct peer *peer_orig;
+ /*
+ * Nexthop in context of original bgp instance. Needed
+ * for label resolution of core mpls routes exported to a vrf.
+ * Set nexthop_orig.family to 0 if not valid.
+ */
+ struct prefix nexthop_orig;
+};
+
/* Ancillary information to struct bgp_path_info,
* used for uncommonly used data (aggregation, MPLS, etc.)
* and lazily allocated to save memory.
@@ -163,13 +211,8 @@ struct bgp_path_info_extra {
mpls_label_t label[BGP_MAX_LABELS];
uint32_t num_labels;
- /* af specific flags */
- uint16_t af_flags;
-#define BGP_EVPN_MACIP_TYPE_SVI_IP (1 << 0)
-
- /* SRv6 SID(s) for SRv6-VPN */
- struct bgp_sid_info sid[BGP_MAX_SIDS];
- uint32_t num_sids;
+ /*For EVPN*/
+ struct bgp_path_info_extra_evpn *evpn;
#ifdef ENABLE_BGP_VNC
union {
@@ -200,50 +243,11 @@ struct bgp_path_info_extra {
} vnc;
#endif
- /*
- * For imported routes into a VNI (or VRF)
- */
- void *parent; /* parent from global table */
- union {
- struct ethaddr mac; /* MAC set here for VNI IP table */
- struct ipaddr ip; /* IP set here for VNI MAC table */
- } vni_info;
-
- /*
- * Some tunnelish parameters follow. Maybe consolidate into an
- * internal tunnel structure?
- */
-
- /*
- * Original bgp instance for imported routes. Needed for:
- * 1. Find all routes from a specific vrf for deletion
- * 2. vrf context of original nexthop
- *
- * Store pointer to bgp instance rather than bgp->vrf_id because
- * bgp->vrf_id is not always valid (or may change?).
- *
- * Set to NULL if route is not imported from another bgp instance.
- */
- struct bgp *bgp_orig;
-
- /*
- * Original bgp session to know if the session is a
- * connected EBGP session or not
- */
- struct peer *peer_orig;
+ /* For flowspec*/
+ struct bgp_path_info_extra_fs *flowspec;
- /*
- * Nexthop in context of original bgp instance. Needed
- * for label resolution of core mpls routes exported to a vrf.
- * Set nexthop_orig.family to 0 if not valid.
- */
- struct prefix nexthop_orig;
- /* presence of FS pbr firewall based entry */
- struct list *bgp_fs_pbr;
- /* presence of FS pbr iprule based entry */
- struct list *bgp_fs_iprule;
- /* Destination Ethernet Segment links for EVPN MH */
- struct bgp_path_mh_info *mh_info;
+ /* For vrf leaking*/
+ struct bgp_path_info_extra_vrfleak *vrfleak;
};
struct bgp_mplsvpn_label_nh {
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index b7ac976e23..1c99495e6c 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -1313,12 +1313,13 @@ route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
return RMAP_NOMATCH;
- if (path->extra == NULL || path->extra->bgp_orig == NULL)
+ if (path->extra == NULL || path->extra->vrfleak == NULL ||
+ path->extra->vrfleak->bgp_orig == NULL)
return RMAP_NOMATCH;
- if (strncmp(vrf_name, vrf_id_to_name(path->extra->bgp_orig->vrf_id),
- VRF_NAMSIZ)
- == 0)
+ if (strncmp(vrf_name,
+ vrf_id_to_name(path->extra->vrfleak->bgp_orig->vrf_id),
+ VRF_NAMSIZ) == 0)
return RMAP_MATCH;
return RMAP_NOMATCH;
@@ -2410,11 +2411,16 @@ route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
as_t configured_asn;
char *buf;
char src_asn[ASN_STRING_MAX_SIZE];
+ char *acl_list_name = NULL;
+ uint32_t acl_list_name_len = 0;
+ char *buf_acl_name = NULL;
+ static const char asp_acl[] = "as-path-access-list";
+ struct as_list *aspath_acl = NULL;
if (path->peer->sort != BGP_PEER_EBGP) {
zlog_warn(
"`set as-path replace` is supported only for EBGP peers");
- return RMAP_NOOP;
+ goto end_ko;
}
buf = strchr(replace, ' ');
@@ -2422,6 +2428,46 @@ route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
configured_asn = path->peer->change_local_as
? path->peer->change_local_as
: path->peer->local_as;
+ } else if (!strncmp(replace, asp_acl, strlen(asp_acl))) {
+ /* its as-path-acl-list command get the access list name */
+ while (*buf == ' ')
+ buf++;
+ buf_acl_name = buf;
+ buf = strchr(buf_acl_name, ' ');
+ if (buf)
+ acl_list_name_len = buf - buf_acl_name;
+ else
+ acl_list_name_len = strlen(buf_acl_name);
+
+ buf_acl_name[acl_list_name_len] = 0;
+ /* get the acl-list */
+ aspath_acl = as_list_lookup(buf_acl_name);
+ if (!aspath_acl) {
+ zlog_warn("`set as-path replace`, invalid as-path-access-list name: %s",
+ buf_acl_name);
+ goto end_ko;
+ }
+ acl_list_name = XSTRDUP(MTYPE_TMP, buf_acl_name);
+ buf_acl_name[acl_list_name_len] = ' ';
+
+ if (!buf) {
+ configured_asn = path->peer->change_local_as
+ ? path->peer->change_local_as
+ : path->peer->local_as;
+ } else {
+ while (*buf == ' ')
+ buf++;
+ /* get the configured asn */
+ if (!asn_str2asn(buf, &configured_asn)) {
+ zlog_warn(
+ "`set as-path replace`, invalid configured AS %s",
+ buf);
+ goto end_ko;
+ }
+ }
+
+ replace = buf;
+
} else {
memcpy(src_asn, replace, (size_t)(buf - replace));
src_asn[(size_t)(buf - replace)] = '\0';
@@ -2431,13 +2477,14 @@ route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
zlog_warn(
"`set as-path replace`, invalid configured AS %s",
buf);
- return RMAP_NOOP;
+ goto end_ko;
}
}
- if (!strmatch(replace, "any") && !asn_str2asn(replace, &replace_asn)) {
+ if (replace && !strmatch(replace, "any") &&
+ !asn_str2asn(replace, &replace_asn)) {
zlog_warn("`set as-path replace`, invalid AS %s", replace);
- return RMAP_NOOP;
+ goto end_ko;
}
if (path->attr->aspath->refcnt)
@@ -2445,16 +2492,29 @@ route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
else
aspath_new = path->attr->aspath;
- if (strmatch(replace, "any")) {
+ if (aspath_acl) {
+ path->attr->aspath = aspath_replace_regex_asn(aspath_new,
+ aspath_acl,
+ configured_asn);
+ } else if (strmatch(replace, "any")) {
path->attr->aspath =
aspath_replace_all_asn(aspath_new, configured_asn);
- } else
+ } else {
path->attr->aspath = aspath_replace_specific_asn(
aspath_new, replace_asn, configured_asn);
-
+ }
aspath_free(aspath_new);
+
+ if (acl_list_name)
+ XFREE(MTYPE_TMP, acl_list_name);
return RMAP_OKAY;
+
+end_ko:
+ if (acl_list_name)
+ XFREE(MTYPE_TMP, acl_list_name);
+ return RMAP_NOOP;
+
}
static const struct route_map_rule_cmd route_set_aspath_replace_cmd = {
@@ -6087,6 +6147,61 @@ DEFPY_YANG(no_set_aspath_replace_asn, no_set_aspath_replace_asn_cmd,
return nb_cli_apply_changes(vty, NULL);
}
+DEFPY_YANG(
+ set_aspath_replace_access_list, set_aspath_replace_access_list_cmd,
+ "set as-path replace as-path-access-list AS_PATH_FILTER_NAME$aspath_filter_name [<ASNUM>$configured_asn]",
+ SET_STR
+ "Transform BGP AS-path attribute\n"
+ "Replace AS number to local or configured AS number\n"
+ "Specify an as path access list name\n"
+ "AS path access list name\n"
+ "Define the configured AS number\n")
+{
+ char *str;
+ const char *xpath =
+ "./set-action[action='frr-bgp-route-map:as-path-replace']";
+ char xpath_value[XPATH_MAXLEN];
+ as_t as_configured_value;
+ char replace_value[ASN_STRING_MAX_SIZE * 2];
+
+ if (configured_asn_str &&
+ !asn_str2asn(configured_asn_str, &as_configured_value)) {
+ vty_out(vty, "%% Invalid AS configured value %s\n",
+ configured_asn_str);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ str = argv_concat(argv, argc, 3);
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+ snprintf(replace_value, sizeof(replace_value), "%s %s", aspath_filter_name, str);
+
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-set-action/frr-bgp-route-map:replace-as-path", xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ no_set_aspath_replace_access_list, no_set_aspath_replace_access_list_cmd,
+ "no set as-path replace as-path-access-list [AS_PATH_FILTER_NAME] [<ASNUM>$configured_asn]",
+ NO_STR
+ SET_STR
+ "Transform BGP AS_PATH attribute\n"
+ "Replace AS number to local or configured AS number\n"
+ "Specify an as path access list name\n"
+ "AS path access list name\n"
+ "Define the configured AS number\n")
+{
+ const char *xpath =
+ "./set-action[action='frr-bgp-route-map:as-path-replace']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
DEFUN_YANG (no_set_aspath_prepend,
no_set_aspath_prepend_cmd,
"no set as-path prepend [ASNUM]",
@@ -7792,12 +7907,14 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &set_aspath_exclude_all_cmd);
install_element(RMAP_NODE, &set_aspath_exclude_access_list_cmd);
install_element(RMAP_NODE, &set_aspath_replace_asn_cmd);
+ install_element(RMAP_NODE, &set_aspath_replace_access_list_cmd);
install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
install_element(RMAP_NODE, &no_set_aspath_exclude_access_list_cmd);
install_element(RMAP_NODE, &no_set_aspath_replace_asn_cmd);
+ install_element(RMAP_NODE, &no_set_aspath_replace_access_list_cmd);
install_element(RMAP_NODE, &set_origin_cmd);
install_element(RMAP_NODE, &no_set_origin_cmd);
install_element(RMAP_NODE, &set_atomic_aggregate_cmd);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 591e0c3969..573abf0cda 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -5738,14 +5738,10 @@ DEFPY(neighbor_capability_software_version,
ret = peer_flag_set_vty(vty, neighbor,
PEER_FLAG_CAPABILITY_SOFT_VERSION);
- if (peer_established(peer)) {
- if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV) &&
- CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV))
- bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
- CAPABILITY_CODE_SOFT_VERSION,
- no ? CAPABILITY_ACTION_UNSET
- : CAPABILITY_ACTION_SET);
- }
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_SOFT_VERSION,
+ no ? CAPABILITY_ACTION_UNSET
+ : CAPABILITY_ACTION_SET);
return ret;
}
@@ -6786,14 +6782,9 @@ static uint8_t get_role_by_name(const char *role_str)
return ROLE_UNDEFINED;
}
-static int peer_role_set_vty(struct vty *vty, const char *ip_str,
+static int peer_role_set_vty(struct vty *vty, struct peer *peer,
const char *role_str, bool strict_mode)
{
- struct peer *peer;
-
- peer = peer_and_group_lookup_vty(vty, ip_str);
- if (!peer)
- return CMD_WARNING_CONFIG_FAILED;
uint8_t role = get_role_by_name(role_str);
if (role == ROLE_UNDEFINED)
@@ -6801,50 +6792,56 @@ static int peer_role_set_vty(struct vty *vty, const char *ip_str,
return bgp_vty_return(vty, peer_role_set(peer, role, strict_mode));
}
-static int peer_role_unset_vty(struct vty *vty, const char *ip_str)
-{
- struct peer *peer;
-
- peer = peer_and_group_lookup_vty(vty, ip_str);
- if (!peer)
- return CMD_WARNING_CONFIG_FAILED;
- return bgp_vty_return(vty, peer_role_unset(peer));
-}
-
DEFPY(neighbor_role,
neighbor_role_cmd,
- "neighbor <A.B.C.D|X:X::X:X|WORD> local-role <provider|rs-server|rs-client|customer|peer>",
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor local-role <provider|rs-server|rs-client|customer|peer>$role",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Set session role\n"
ROLE_STR)
{
- int idx_peer = 1;
- int idx_role = 3;
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
- return peer_role_set_vty(vty, argv[idx_peer]->arg, argv[idx_role]->arg,
- false);
+ ret = peer_role_set_vty(vty, peer, role, false);
+
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, CAPABILITY_CODE_ROLE,
+ CAPABILITY_ACTION_SET);
+
+ return ret;
}
DEFPY(neighbor_role_strict,
neighbor_role_strict_cmd,
- "neighbor <A.B.C.D|X:X::X:X|WORD> local-role <provider|rs-server|rs-client|customer|peer> strict-mode",
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor local-role <provider|rs-server|rs-client|customer|peer>$role strict-mode",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Set session role\n"
ROLE_STR
"Use additional restriction on peer\n")
{
- int idx_peer = 1;
- int idx_role = 3;
+ int ret;
+ struct peer *peer;
- return peer_role_set_vty(vty, argv[idx_peer]->arg, argv[idx_role]->arg,
- true);
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_role_set_vty(vty, peer, role, true);
+
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, CAPABILITY_CODE_ROLE,
+ CAPABILITY_ACTION_SET);
+
+ return ret;
}
DEFPY(no_neighbor_role,
no_neighbor_role_cmd,
- "no neighbor <A.B.C.D|X:X::X:X|WORD> local-role <provider|rs-server|rs-client|customer|peer> [strict-mode]",
+ "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor local-role <provider|rs-server|rs-client|customer|peer> [strict-mode]",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
@@ -6852,9 +6849,19 @@ DEFPY(no_neighbor_role,
ROLE_STR
"Use additional restriction on peer\n")
{
- int idx_peer = 2;
+ int ret;
+ struct peer *peer;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = bgp_vty_return(vty, peer_role_unset(peer));
- return peer_role_unset_vty(vty, argv[idx_peer]->arg);
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, CAPABILITY_CODE_ROLE,
+ CAPABILITY_ACTION_UNSET);
+
+ return ret;
}
/* disable-connected-check */
@@ -10971,6 +10978,29 @@ DEFUN (show_bgp_memory,
memstrbuf, sizeof(memstrbuf),
count * sizeof(struct bgp_path_info_extra)));
+ count = mtype_stats_alloc(MTYPE_BGP_ROUTE_EXTRA_EVPN);
+ if (count)
+ vty_out(vty, "%ld BGP extra info for EVPN, using %s of memory\n",
+ count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_path_info_extra_evpn)));
+
+ count = mtype_stats_alloc(MTYPE_BGP_ROUTE_EXTRA_FS);
+ if (count)
+ vty_out(vty,
+ "%ld BGP extra info for flowspec, using %s of memory\n",
+ count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_path_info_extra_fs)));
+
+ count = mtype_stats_alloc(MTYPE_BGP_ROUTE_EXTRA_VRFLEAK);
+ if (count)
+ vty_out(vty,
+ "%ld BGP extra info for vrf leaking, using %s of memory\n",
+ count,
+ mtype_memstr(memstrbuf, sizeof(memstrbuf),
+ count * sizeof(struct bgp_path_info_extra_vrfleak)));
+
if ((count = mtype_stats_alloc(MTYPE_BGP_STATIC)))
vty_out(vty, "%ld Static routes, using %s of memory\n", count,
mtype_memstr(memstrbuf, sizeof(memstrbuf),
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index becd99167f..ea7168f749 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1308,7 +1308,6 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
struct bgp_path_info local_info;
struct bgp_path_info *mpinfo_cp = &local_info;
route_tag_t tag;
- struct bgp_sid_info *sid_info;
mpls_label_t *labels;
uint32_t num_labels = 0;
mpls_label_t nh_label;
@@ -1348,7 +1347,8 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
/*
* vrf leaking support (will have only one nexthop)
*/
- if (info->extra && info->extra->bgp_orig)
+ if (info->extra && info->extra->vrfleak &&
+ info->extra->vrfleak->bgp_orig)
nh_othervrf = 1;
/* Make Zebra API structure. */
@@ -1364,8 +1364,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
&& info->sub_type == BGP_ROUTE_IMPORTED) {
/* Obtain peer from parent */
- if (info->extra && info->extra->parent)
- peer = ((struct bgp_path_info *)(info->extra->parent))
+ if (info->extra && info->extra->vrfleak &&
+ info->extra->vrfleak->parent)
+ peer = ((struct bgp_path_info *)(info->extra->vrfleak
+ ->parent))
->peer;
}
@@ -1553,15 +1555,21 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
api_nh->weight = nh_weight;
- if (mpinfo->extra && !is_evpn &&
- bgp_is_valid_label(&labels[0]) &&
- !sid_zero(&mpinfo->extra->sid[0].sid)) {
- sid_info = &mpinfo->extra->sid[0];
-
- memcpy(&api_nh->seg6_segs, &sid_info->sid,
+ if (((mpinfo->attr->srv6_l3vpn &&
+ !sid_zero(&mpinfo->attr->srv6_l3vpn->sid)) ||
+ (mpinfo->attr->srv6_vpn &&
+ !sid_zero(&mpinfo->attr->srv6_vpn->sid))) &&
+ !is_evpn && bgp_is_valid_label(&labels[0])) {
+ struct in6_addr *sid_tmp =
+ mpinfo->attr->srv6_l3vpn
+ ? (&mpinfo->attr->srv6_l3vpn->sid)
+ : (&mpinfo->attr->srv6_vpn->sid);
+
+ memcpy(&api_nh->seg6_segs, sid_tmp,
sizeof(api_nh->seg6_segs));
- if (sid_info->transposition_len != 0) {
+ if (mpinfo->attr->srv6_l3vpn &&
+ mpinfo->attr->srv6_l3vpn->transposition_len != 0) {
mpls_lse_decode(labels[0], &nh_label, &ttl,
&exp, &bos);
@@ -1573,8 +1581,10 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
}
transpose_sid(&api_nh->seg6_segs, nh_label,
- sid_info->transposition_offset,
- sid_info->transposition_len);
+ mpinfo->attr->srv6_l3vpn
+ ->transposition_offset,
+ mpinfo->attr->srv6_l3vpn
+ ->transposition_len);
}
SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6);
@@ -2436,8 +2446,14 @@ static int rule_notify_owner(ZAPI_CALLBACK_ARGS)
/* link bgp_info to bgp_pbr */
path = (struct bgp_path_info *)bgp_pbr->path;
extra = bgp_path_info_extra_get(path);
- listnode_add_force(&extra->bgp_fs_iprule,
- bgp_pbr);
+ if (!extra->flowspec) {
+ extra->flowspec =
+ XCALLOC(MTYPE_BGP_ROUTE_EXTRA_FS,
+ sizeof(struct bgp_path_info_extra_fs));
+ extra->flowspec->bgp_fs_iprule = NULL;
+ extra->flowspec->bgp_fs_pbr = NULL;
+ }
+ listnode_add_force(&extra->flowspec->bgp_fs_iprule, bgp_pbr);
}
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("%s: Received RULE_INSTALLED", __func__);
@@ -2539,7 +2555,14 @@ static int ipset_entry_notify_owner(ZAPI_CALLBACK_ARGS)
/* link bgp_path_info to bpme */
path = (struct bgp_path_info *)bgp_pbime->path;
extra = bgp_path_info_extra_get(path);
- listnode_add_force(&extra->bgp_fs_pbr, bgp_pbime);
+ if (!extra->flowspec) {
+ extra->flowspec =
+ XCALLOC(MTYPE_BGP_ROUTE_EXTRA_FS,
+ sizeof(struct bgp_path_info_extra_fs));
+ extra->flowspec->bgp_fs_iprule = NULL;
+ extra->flowspec->bgp_fs_pbr = NULL;
+ }
+ listnode_add_force(&extra->flowspec->bgp_fs_pbr, bgp_pbime);
}
break;
case ZAPI_IPSET_ENTRY_FAIL_REMOVE:
@@ -3455,6 +3478,11 @@ static bool bgp_zebra_label_manager_connect(void)
return true;
}
+static void bgp_zebra_capabilities(struct zclient_capabilities *cap)
+{
+ bm->v6_with_v4_nexthops = cap->v6_with_v4_nexthop;
+}
+
void bgp_zebra_init(struct event_loop *master, unsigned short instance)
{
struct zclient_options options = zclient_options_default;
@@ -3470,6 +3498,7 @@ void bgp_zebra_init(struct event_loop *master, unsigned short instance)
array_size(bgp_handlers));
zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
zclient->zebra_connected = bgp_zebra_connected;
+ zclient->zebra_capabilities = bgp_zebra_capabilities;
zclient->instance = instance;
/* Initialize special zclient for synchronous message exchanges. */
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index a0f7819460..ed2d5e669d 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -10,9 +10,10 @@
/* Macro to update bgp_original based on bpg_path_info */
#define BGP_ORIGINAL_UPDATE(_bgp_orig, _mpinfo, _bgp) \
- ((_mpinfo->extra && _mpinfo->extra->bgp_orig \
- && _mpinfo->sub_type == BGP_ROUTE_IMPORTED) \
- ? (_bgp_orig = _mpinfo->extra->bgp_orig) \
+ ((_mpinfo->extra && _mpinfo->extra->vrfleak && \
+ _mpinfo->extra->vrfleak->bgp_orig && \
+ _mpinfo->sub_type == BGP_ROUTE_IMPORTED) \
+ ? (_bgp_orig = _mpinfo->extra->vrfleak->bgp_orig) \
: (_bgp_orig = _bgp))
/* Default weight for next hop, if doing weighted ECMP. */
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index b72e75d12e..aaf1f41c4b 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -4444,8 +4444,8 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none},
{PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE, 0, peer_change_none},
{PEER_FLAG_EXTENDED_OPT_PARAMS, 0, peer_change_reset},
- {PEER_FLAG_ROLE_STRICT_MODE, 0, peer_change_reset},
- {PEER_FLAG_ROLE, 0, peer_change_reset},
+ {PEER_FLAG_ROLE_STRICT_MODE, 0, peer_change_none},
+ {PEER_FLAG_ROLE, 0, peer_change_none},
{PEER_FLAG_PORT, 0, peer_change_reset},
{PEER_FLAG_AIGP, 0, peer_change_none},
{PEER_FLAG_GRACEFUL_SHUTDOWN, 0, peer_change_none},
@@ -5167,7 +5167,6 @@ int peer_role_set(struct peer *peer, uint8_t role, bool strict_mode)
else
UNSET_FLAG(peer->flags,
PEER_FLAG_ROLE_STRICT_MODE);
- bgp_session_reset(peer);
}
return CMD_SUCCESS;
@@ -5212,7 +5211,6 @@ int peer_role_set(struct peer *peer, uint8_t role, bool strict_mode)
UNSET_FLAG(member->flags,
PEER_FLAG_ROLE_STRICT_MODE);
}
- bgp_session_reset(member);
}
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 5e467bb873..67ee8aa138 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -168,6 +168,8 @@ struct bgp_master {
struct event *t_bgp_sync_label_manager;
struct event *t_bgp_start_label_manager;
+ bool v6_with_v4_nexthops;
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(bgp_master);
diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c
index 29698846c3..252b6d632a 100644
--- a/bgpd/rfapi/rfapi_vty.c
+++ b/bgpd/rfapi/rfapi_vty.c
@@ -420,15 +420,20 @@ void rfapi_vty_out_vncinfo(struct vty *vty, const struct prefix *p,
vty_out(vty, " label=%u",
decode_label(&bpi->extra->label[0]));
- if (bpi->extra->num_sids) {
- vty_out(vty, " sid=%pI6", &bpi->extra->sid[0].sid);
-
- if (bpi->extra->sid[0].loc_block_len != 0) {
+ if (bpi->attr->srv6_l3vpn || bpi->attr->srv6_vpn) {
+ struct in6_addr *sid_tmp =
+ bpi->attr->srv6_l3vpn
+ ? (&bpi->attr->srv6_l3vpn->sid)
+ : (&bpi->attr->srv6_vpn->sid);
+ vty_out(vty, " sid=%pI6", sid_tmp);
+
+ if (bpi->attr->srv6_l3vpn &&
+ bpi->attr->srv6_l3vpn->loc_block_len != 0) {
vty_out(vty, " sid_structure=[%d,%d,%d,%d]",
- bpi->extra->sid[0].loc_block_len,
- bpi->extra->sid[0].loc_node_len,
- bpi->extra->sid[0].func_len,
- bpi->extra->sid[0].arg_len);
+ bpi->attr->srv6_l3vpn->loc_block_len,
+ bpi->attr->srv6_l3vpn->loc_node_len,
+ bpi->attr->srv6_l3vpn->func_len,
+ bpi->attr->srv6_l3vpn->arg_len);
}
}
}
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index ad8f913355..651aa36d0e 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -86,6 +86,15 @@ be specified (:ref:`common-invocation-options`).
be done to see if this is helping or not at the scale you are running
at.
+.. option:: --v6-with-v4-nexthops
+
+ Allow BGP to peer in the V6 afi, when the interface only has v4 addresses.
+ This allows bgp to install the v6 routes with a v6 nexthop that has the
+ v4 address encoded in the nexthop. Zebra's equivalent option currently
+ overrides the bgp setting. This setting is only really usable when
+ the operator has turned off communication to zebra and is running bgpd
+ as a complete standalone process.
+
LABEL MANAGER
-------------
@@ -2133,6 +2142,14 @@ Using AS Path in Route Map
``any`` replaces each AS number in the AS-PATH with either the local AS
number or the configured AS number.
+.. clicmd:: set as-path replace as-path-access-list WORD [<ASN>]
+
+ Replace some AS numbers from the AS_PATH of the BGP path's NLRI. Substituted
+ AS numbers are conformant with the regex defined in as-path access-list
+ WORD. Changed AS numbers are replaced either by the local AS number or the
+ configured AS number.
+ The no form of this command removes this set operation from the route-map.
+
.. clicmd:: set as-path exclude all
Remove all AS numbers from the AS_PATH of the BGP path's NLRI. The no form of
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index d7e768b710..32de3e908f 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -87,6 +87,13 @@ Besides the common invocation options (:ref:`common-invocation-options`), the
Allow zebra to modify the default receive buffer size to SIZE
in bytes. Under \*BSD only the -s option is available.
+.. option:: --v6-with-v4-nexthops
+
+ Signal to zebra that v6 routes with v4 nexthops are accepted
+ by the underlying dataplane. This will be communicated to
+ the upper level daemons that can install v6 routes with v4
+ nexthops.
+
.. _interface-commands:
Configuration Addresses behaviour
diff --git a/lib/bitfield.h b/lib/bitfield.h
index c4e2cbe4e1..cc8c311416 100644
--- a/lib/bitfield.h
+++ b/lib/bitfield.h
@@ -114,7 +114,8 @@ DECLARE_MTYPE(BITFIELD);
(v).n += ((v).data[w] == WORD_MAX); \
if ((v).n == (v).m) { \
(v).m = (v).m + 1; \
- (v).data = realloc((v).data, (v).m * sizeof(word_t)); \
+ (v).data = XREALLOC(MTYPE_BITFIELD, (v).data, \
+ (v).m * sizeof(word_t)); \
} \
} while (0)
@@ -188,7 +189,8 @@ bf_find_next_clear_bit_wrap(bitfield_t *v, word_t start_index, word_t max_index)
* will allocate additional space.
*/
v->m += 1;
- v->data = (word_t *)realloc(v->data, v->m * sizeof(word_t));
+ v->data = (word_t *)XREALLOC(MTYPE_BITFIELD, v->data,
+ v->m * sizeof(word_t));
v->data[v->m - 1] = 0;
return v->m * WORD_SIZE;
}
diff --git a/lib/command.c b/lib/command.c
index 8025ab534f..affb551b45 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -903,8 +903,7 @@ enum node_type node_parent(enum node_type node)
}
/* Execute command by argument vline vector. */
-static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter,
- struct vty *vty,
+static int cmd_execute_command_real(vector vline, struct vty *vty,
const struct cmd_element **cmd,
unsigned int up_level)
{
@@ -1041,8 +1040,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
vector_set_index(shifted_vline, index - 1,
vector_lookup(vline, index));
- ret = cmd_execute_command_real(shifted_vline, FILTER_RELAXED,
- vty, cmd, 0);
+ ret = cmd_execute_command_real(shifted_vline, vty, cmd, 0);
vector_free(shifted_vline);
vty->node = onode;
@@ -1051,7 +1049,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
}
saved_ret = ret =
- cmd_execute_command_real(vline, FILTER_RELAXED, vty, cmd, 0);
+ cmd_execute_command_real(vline, vty, cmd, 0);
if (vtysh)
return saved_ret;
@@ -1069,8 +1067,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
if (vty->xpath_index > 0 && !cnode->no_xpath)
vty->xpath_index--;
- ret = cmd_execute_command_real(vline, FILTER_RELAXED,
- vty, cmd, 0);
+ ret = cmd_execute_command_real(vline, vty, cmd, 0);
if (ret == CMD_SUCCESS || ret == CMD_WARNING
|| ret == CMD_ERR_AMBIGUOUS || ret == CMD_ERR_INCOMPLETE
|| ret == CMD_NOT_MY_INSTANCE
@@ -1102,7 +1099,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
int cmd_execute_command_strict(vector vline, struct vty *vty,
const struct cmd_element **cmd)
{
- return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd, 0);
+ return cmd_execute_command_real(vline, vty, cmd, 0);
}
/*
@@ -1274,8 +1271,7 @@ int command_config_read_one_line(struct vty *vty,
&& ret != CMD_ERR_AMBIGUOUS && ret != CMD_ERR_INCOMPLETE
&& ret != CMD_NOT_MY_INSTANCE && ret != CMD_WARNING_CONFIG_FAILED
&& ret != CMD_NO_LEVEL_UP)
- ret = cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd,
- ++up_level);
+ ret = cmd_execute_command_real(vline, vty, cmd, ++up_level);
if (ret == CMD_NO_LEVEL_UP)
ret = CMD_ERR_NO_MATCH;
diff --git a/lib/command_match.h b/lib/command_match.h
index db2a8535e0..3e7a549e1d 100644
--- a/lib/command_match.h
+++ b/lib/command_match.h
@@ -17,11 +17,6 @@
extern "C" {
#endif
-/* These definitions exist in command.c in the current engine but should be
- * relocated here in the new engine
- */
-enum cmd_filter_type { FILTER_RELAXED, FILTER_STRICT };
-
/* matcher result value */
enum matcher_rv {
MATCHER_NO_MATCH,
diff --git a/lib/zclient.c b/lib/zclient.c
index c36bcc6e2e..294a78feb0 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -3876,6 +3876,7 @@ static int zclient_capability_decode(ZAPI_CALLBACK_ARGS)
cap.mpls_enabled = !!mpls_enabled;
STREAM_GETL(s, cap.ecmp);
STREAM_GETC(s, cap.role);
+ STREAM_GETC(s, cap.v6_with_v4_nexthop);
if (zclient->zebra_capabilities)
(*zclient->zebra_capabilities)(&cap);
diff --git a/lib/zclient.h b/lib/zclient.h
index 316dd4cd68..42c5a5fdac 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -274,6 +274,7 @@ struct zclient_capabilities {
uint32_t ecmp;
bool mpls_enabled;
enum mlag_role role;
+ bool v6_with_v4_nexthop;
};
/* Graceful Restart Capabilities message */
diff --git a/ospfd/ospf_ti_lfa.c b/ospfd/ospf_ti_lfa.c
index 07fc503947..f9bc2b4dd6 100644
--- a/ospfd/ospf_ti_lfa.c
+++ b/ospfd/ospf_ti_lfa.c
@@ -64,6 +64,7 @@ ospf_ti_lfa_find_p_node(struct vertex *pc_node, struct p_space *p_space,
struct vertex_parent *pc_vertex_parent;
curr_node = listnode_lookup(q_space->pc_path, pc_node);
+ assert(curr_node);
pc_node_parent = listgetdata(curr_node->next);
q_space->p_node_info->type = OSPF_TI_LFA_UNDEFINED_NODE;
@@ -105,6 +106,7 @@ static void ospf_ti_lfa_find_q_node(struct vertex *pc_node,
struct vertex_parent *pc_vertex_parent;
curr_node = listnode_lookup(q_space->pc_path, pc_node);
+ assert(curr_node);
next_node = curr_node->next;
pc_node_parent = listgetdata(next_node);
pc_vertex_parent =
@@ -219,7 +221,7 @@ static struct list *ospf_ti_lfa_cut_out_pc_path(struct list *pc_vertex_list,
current_listnode = listnode_lookup(pc_path, current_vertex);
/* Note that the post-convergence paths are reversed. */
- for (;;) {
+ while (current_listnode) {
current_vertex = listgetdata(current_listnode);
listnode_add(inner_pc_path, current_vertex);
@@ -268,6 +270,7 @@ static void ospf_ti_lfa_generate_inner_label_stack(
end_label = MPLS_INVALID_LABEL;
if (p_node_info->node->id.s_addr == p_space->root->id.s_addr) {
pc_p_node = listnode_lookup(q_space->pc_path, p_space->pc_spf);
+ assert(pc_p_node);
start_vertex = listgetdata(pc_p_node->prev);
start_label = ospf_sr_get_adj_sid_by_id(&p_node_info->node->id,
&start_vertex->id);
@@ -275,6 +278,7 @@ static void ospf_ti_lfa_generate_inner_label_stack(
if (q_node_info->node->id.s_addr == q_space->root->id.s_addr) {
pc_q_node = listnode_lookup(q_space->pc_path,
listnode_head(q_space->pc_path));
+ assert(pc_q_node);
end_vertex = listgetdata(pc_q_node->next);
end_label = ospf_sr_get_adj_sid_by_id(&end_vertex->id,
&q_node_info->node->id);
diff --git a/tests/topotests/babel_topo1/r3/babeld.conf b/tests/topotests/babel_topo1/r3/babeld.conf
index bfda3622dd..e10e5aaacc 100644
--- a/tests/topotests/babel_topo1/r3/babeld.conf
+++ b/tests/topotests/babel_topo1/r3/babeld.conf
@@ -14,4 +14,3 @@ router babel
network r3-eth1
redistribute ipv4 connected
redistribute ipv4 static
- redistirbute ipv6 connected
diff --git a/tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf
index ce36494604..72238ccd40 100644
--- a/tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt1/ospfd.conf
@@ -27,6 +27,5 @@ interface eth-rt3
!
router ospf
ospf router-id 1.1.1.1
- passive interface lo
router-info area 0.0.0.0
!
diff --git a/tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf
index a8ca564e4e..c5f4262a8f 100644
--- a/tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt2/ospfd.conf
@@ -25,6 +25,5 @@ interface eth-rt5
!
router ospf
ospf router-id 2.2.2.2
- passive interface lo
router-info area 0.0.0.0
!
diff --git a/tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf
index 0404994c09..e487bdd7c0 100644
--- a/tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt3/ospfd.conf
@@ -25,6 +25,5 @@ interface eth-rt4
!
router ospf
ospf router-id 3.3.3.3
- passive interface lo
router-info area 0.0.0.0
!
diff --git a/tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf
index 6b8ab3704f..560904e75d 100644
--- a/tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt4/ospfd.conf
@@ -24,6 +24,5 @@ interface eth-rt5
!
router ospf
ospf router-id 4.4.4.4
- passive interface lo
router-info area 0.0.0.0
!
diff --git a/tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf b/tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf
index 043432ec3d..77f5445286 100644
--- a/tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt5/ospfd.conf
@@ -24,6 +24,5 @@ interface eth-rt4
!
router ospf
ospf router-id 5.5.5.5
- passive interface lo
router-info area 0.0.0.0
!
diff --git a/tests/topotests/bgp_addpath_best_selected/r2/bgpd.conf b/tests/topotests/bgp_addpath_best_selected/r2/bgpd.conf
index 0c13824323..cdef611286 100644
--- a/tests/topotests/bgp_addpath_best_selected/r2/bgpd.conf
+++ b/tests/topotests/bgp_addpath_best_selected/r2/bgpd.conf
@@ -2,7 +2,6 @@ router bgp 65002
timers bgp 3 10
no bgp ebgp-requires-policy
neighbor 192.168.1.1 remote-as external
- neighbor 192.168.1.1 remote-as external
neighbor 192.168.7.7 remote-as external
neighbor 192.168.7.7 timers connect 5
neighbor 192.168.2.3 remote-as external
diff --git a/tests/topotests/bgp_addpath_best_selected/test_bgp_addpath_best_selected.py b/tests/topotests/bgp_addpath_best_selected/test_bgp_addpath_best_selected.py
index dfd538f1c6..2a610c901e 100644
--- a/tests/topotests/bgp_addpath_best_selected/test_bgp_addpath_best_selected.py
+++ b/tests/topotests/bgp_addpath_best_selected/test_bgp_addpath_best_selected.py
@@ -75,6 +75,42 @@ def test_bgp_addpath_best_selected():
r2 = tgen.gears["r2"]
+ def _bgp_converge():
+ output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast 172.16.16.254/32 json"))
+ expected = {
+ "paths": [
+ {
+ "aspath": {
+ "string": "65006",
+ },
+ "weight": 6,
+ },
+ {
+ "aspath": {
+ "string": "65005",
+ },
+ "weight": 5,
+ },
+ {
+ "aspath": {
+ "string": "65004",
+ },
+ "weight": 4,
+ },
+ {
+ "aspath": {
+ "string": "65003",
+ },
+ "weight": 3,
+ },
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't converge initially"
+
def check_bgp_advertised_routes_to_r1():
output = json.loads(
r2.vtysh_cmd(
@@ -104,7 +140,7 @@ def test_bgp_addpath_best_selected():
return topotest.json_cmp(output, expected)
test_func = functools.partial(check_bgp_advertised_routes_to_r1)
- success, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert (
result is None
), "Received more/less Add-Path best paths, but should be only 1+1 (real best path)"
@@ -143,7 +179,7 @@ def test_bgp_addpath_best_selected():
return topotest.json_cmp(output, expected)
test_func = functools.partial(check_bgp_advertised_routes_to_r7)
- success, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert (
result is None
), "Received more/less Add-Path best paths, but should be only 2+1 (real best path)"
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py
new file mode 100644
index 0000000000..9f37440566
--- /dev/null
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2023 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+"""
+Test if role capability is exchanged dynamically.
+"""
+
+import os
+import re
+import sys
+import json
+import pytest
+import functools
+
+pytestmark = pytest.mark.bgpd
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def setup_module(mod):
+ topodef = {"s1": ("r1", "r2")}
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_dynamic_capability_role():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge():
+ output = json.loads(r1.vtysh_cmd("show bgp neighbor json"))
+ expected = {
+ "192.168.1.2": {
+ "bgpState": "Established",
+ "localRole": "undefined",
+ "remoteRole": "undefined",
+ "neighborCapabilities": {
+ "dynamic": "advertisedAndReceived",
+ },
+ "connectionsEstablished": 1,
+ "connectionsDropped": 0,
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_converge,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't converge"
+
+ step("Set local-role and check if it's exchanged dynamically")
+
+ r1.vtysh_cmd(
+ """
+ configure terminal
+ router bgp
+ neighbor 192.168.1.2 local-role customer
+ """
+ )
+
+ r2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp
+ neighbor 192.168.1.1 local-role provider
+ """
+ )
+
+ def _bgp_check_if_session_not_reset():
+ output = json.loads(r1.vtysh_cmd("show bgp neighbor json"))
+ expected = {
+ "192.168.1.2": {
+ "bgpState": "Established",
+ "localRole": "customer",
+ "remoteRole": "provider",
+ "neighborCapabilities": {
+ "dynamic": "advertisedAndReceived",
+ "role": "advertisedAndReceived",
+ },
+ "connectionsEstablished": 1,
+ "connectionsDropped": 0,
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_check_if_session_not_reset,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Session was reset after setting role capability"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py
index a375993af4..eb81ffeb69 100644
--- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py
@@ -52,7 +52,7 @@ def teardown_module(mod):
tgen.stop_topology()
-def test_bgp_dynamic_capability():
+def test_bgp_dynamic_capability_software_version():
tgen = get_topogen()
if tgen.routers_have_failure():
diff --git a/tests/topotests/bgp_set_aspath_replace/test_bgp_set_aspath_replace.py b/tests/topotests/bgp_set_aspath_replace/test_bgp_set_aspath_replace.py
index 0433c15e0a..c0e19fa356 100644
--- a/tests/topotests/bgp_set_aspath_replace/test_bgp_set_aspath_replace.py
+++ b/tests/topotests/bgp_set_aspath_replace/test_bgp_set_aspath_replace.py
@@ -120,6 +120,82 @@ def test_bgp_set_aspath_replace_test2():
), "Failed overriding incoming AS-PATH with route-map replace with configured ASN"
+def test_bgp_set_aspath_replace_access_list():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ rname = "r1"
+ r1 = tgen.gears[rname]
+
+ r1.vtysh_cmd(
+ """
+conf
+ bgp as-path access-list FIRST permit ^65
+ route-map r2 permit 20
+ set as-path replace as-path-access-list FIRST 65002
+ """
+ )
+
+ expected = {
+ "routes": {
+ "172.16.255.31/32": [{"path": "65002 65500"}],
+ "172.16.255.32/32": [{"path": "65002 65002"}],
+ }
+ }
+
+ def _bgp_regexp_1(router):
+ output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast json"))
+
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_regexp_1, tgen.gears["r1"])
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+
+ assert result is None, "Failed overriding incoming AS-PATH with regex 1 route-map"
+ r1.vtysh_cmd(
+ """
+conf
+ bgp as-path access-list SECOND permit 2
+ route-map r2 permit 10
+ set as-path replace as-path-access-list SECOND 65001
+ """
+ )
+
+ expected = {
+ "routes": {
+ "172.16.255.31/32": [{"path": "65001 65003"}],
+ "172.16.255.32/32": [{"path": "65002 65002"}],
+ }
+ }
+
+ test_func = functools.partial(_bgp_regexp_1, tgen.gears["r1"])
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+
+ assert result is None, "Failed overriding incoming AS-PATH with regex 2 route-map"
+
+ r1.vtysh_cmd(
+ """
+conf
+ bgp as-path access-list TER permit 3
+ route-map r2 permit 10
+ set as-path replace as-path-access-list TER
+ """
+ )
+ expected = {
+ "routes": {
+ "172.16.255.31/32": [{"path": "65002 65001"}],
+ "172.16.255.32/32": [{"path": "65002 65002"}],
+ }
+ }
+
+ test_func = functools.partial(_bgp_regexp_1, tgen.gears["r1"])
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+
+ assert result is None, "Failed overriding incoming AS-PATH with regex 3 route-map"
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_srv6l3vpn_over_ipv6/test_bgp_srv6l3vpn_over_ipv6.py b/tests/topotests/bgp_srv6l3vpn_over_ipv6/test_bgp_srv6l3vpn_over_ipv6.py
index 9e529059e7..14b9ba8498 100755
--- a/tests/topotests/bgp_srv6l3vpn_over_ipv6/test_bgp_srv6l3vpn_over_ipv6.py
+++ b/tests/topotests/bgp_srv6l3vpn_over_ipv6/test_bgp_srv6l3vpn_over_ipv6.py
@@ -24,6 +24,7 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from lib.common_config import required_linux_kernel_version
+from lib.checkping import check_ping
pytestmark = [pytest.mark.bgpd]
@@ -101,31 +102,15 @@ def teardown_module(mod):
tgen.stop_topology()
-def check_ping4(name, dest_addr, expected):
- def _check(name, dest_addr, match):
- tgen = get_topogen()
- output = tgen.gears[name].run("ping {} -c 1 -w 1".format(dest_addr))
- logger.info(output)
- if match not in output:
- return "ping fail"
-
- match = ", {} packet loss".format("0%" if expected else "100%")
- logger.info("[+] check {} {} {}".format(name, dest_addr, match))
- tgen = get_topogen()
- func = functools.partial(_check, name, dest_addr, match)
- success, result = topotest.run_and_expect(func, None, count=10, wait=1)
- assert result is None, "Failed"
-
-
def test_ping():
tgen = get_topogen()
- check_ping4("c11", "192.168.2.1", True)
- check_ping4("c11", "192.168.3.1", True)
- check_ping4("c12", "192.168.2.1", True)
- check_ping4("c12", "192.168.3.1", True)
- check_ping4("c21", "192.168.3.1", True)
- check_ping4("c22", "192.168.3.1", True)
+ check_ping("c11", "192.168.2.1", True, 10, 1)
+ check_ping("c11", "192.168.3.1", True, 10, 1)
+ check_ping("c12", "192.168.2.1", True, 10, 1)
+ check_ping("c12", "192.168.3.1", True, 10, 1)
+ check_ping("c21", "192.168.3.1", True, 10, 1)
+ check_ping("c22", "192.168.3.1", True, 10, 1)
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/test_bgp_srv6l3vpn_sid.py b/tests/topotests/bgp_srv6l3vpn_sid/test_bgp_srv6l3vpn_sid.py
index cddcf6a9a1..189d2baf17 100755
--- a/tests/topotests/bgp_srv6l3vpn_sid/test_bgp_srv6l3vpn_sid.py
+++ b/tests/topotests/bgp_srv6l3vpn_sid/test_bgp_srv6l3vpn_sid.py
@@ -35,6 +35,7 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from lib.common_config import required_linux_kernel_version
+from lib.checkping import check_ping
def build_topo(tgen):
@@ -167,22 +168,6 @@ def open_json_file(filename):
assert False, "Could not read file {}".format(filename)
-def check_ping(name, dest_addr, expect_connected):
- def _check(name, dest_addr, match):
- tgen = get_topogen()
- output = tgen.gears[name].run("ping {} -c 1 -w 1".format(dest_addr))
- logger.info(output)
- if match not in output:
- return True
-
- match = ", {} packet loss".format("0%" if expect_connected else "100%")
- logger.info("[+] check {} {} {}".format(name, dest_addr, match))
- tgen = get_topogen()
- func = functools.partial(_check, name, dest_addr, match)
- success, result = topotest.run_and_expect(func, None, count=10, wait=0.5)
- assert result is None, "Failed"
-
-
def check_rib(name, cmd, expected_file):
def _check(name, cmd, expected_file):
logger.info("polling")
@@ -215,21 +200,21 @@ def test_rib():
def test_ping():
- check_ping("ce1", "2001:2::2", True)
- check_ping("ce1", "2001:3::2", True)
- check_ping("ce1", "2001:4::2", False)
- check_ping("ce1", "2001:5::2", False)
- check_ping("ce1", "2001:6::2", False)
- check_ping("ce4", "2001:1::2", False)
- check_ping("ce4", "2001:2::2", False)
- check_ping("ce4", "2001:3::2", False)
- check_ping("ce4", "2001:5::2", True)
- check_ping("ce4", "2001:6::2", True)
+ check_ping("ce1", "2001:2::2", True, 10, 0.5)
+ check_ping("ce1", "2001:3::2", True, 10, 0.5)
+ check_ping("ce1", "2001:4::2", False, 10, 0.5)
+ check_ping("ce1", "2001:5::2", False, 10, 0.5)
+ check_ping("ce1", "2001:6::2", False, 10, 0.5)
+ check_ping("ce4", "2001:1::2", False, 10, 0.5)
+ check_ping("ce4", "2001:2::2", False, 10, 0.5)
+ check_ping("ce4", "2001:3::2", False, 10, 0.5)
+ check_ping("ce4", "2001:5::2", True, 10, 0.5)
+ check_ping("ce4", "2001:6::2", True, 10, 0.5)
def test_sid_per_afv6_auto():
check_rib("r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_auto_sid_rib.json")
- check_ping("ce1", "2001:2::2", True)
+ check_ping("ce1", "2001:2::2", True, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
configure terminal
@@ -241,7 +226,7 @@ def test_sid_per_afv6_auto():
check_rib(
"r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_auto_no_sid_rib.json"
)
- check_ping("ce1", "2001:2::2", False)
+ check_ping("ce1", "2001:2::2", False, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
@@ -252,7 +237,7 @@ def test_sid_per_afv6_auto():
"""
)
check_rib("r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_auto_sid_rib.json")
- check_ping("ce1", "2001:2::2", True)
+ check_ping("ce1", "2001:2::2", True, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
@@ -265,14 +250,14 @@ def test_sid_per_afv6_auto():
check_rib(
"r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_auto_no_sid_rib.json"
)
- check_ping("ce1", "2001:2::2", False)
+ check_ping("ce1", "2001:2::2", False, 10, 0.5)
def test_sid_per_afv6_manual():
check_rib(
"r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_manual_no_sid_rib.json"
)
- check_ping("ce1", "2001:2::2", False)
+ check_ping("ce1", "2001:2::2", False, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
@@ -286,7 +271,7 @@ def test_sid_per_afv6_manual():
check_rib(
"r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_manual_sid_rib.json"
)
- check_ping("ce1", "2001:2::2", True)
+ check_ping("ce1", "2001:2::2", True, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
@@ -299,12 +284,12 @@ def test_sid_per_afv6_manual():
check_rib(
"r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_afv6_manual_no_sid_rib.json"
)
- check_ping("ce1", "2001:2::2", False)
+ check_ping("ce1", "2001:2::2", False, 10, 0.5)
def test_sid_per_afv4_auto():
check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_auto_sid_rib.json")
- check_ping("ce1", "192.168.2.2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
configure terminal
@@ -317,7 +302,7 @@ def test_sid_per_afv4_auto():
check_rib(
"r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_auto_no_sid_rib.json"
)
- check_ping("ce1", "192.168.2.2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
@@ -329,7 +314,7 @@ def test_sid_per_afv4_auto():
)
check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_auto_sid_rib.json")
- check_ping("ce1", "192.168.2.2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
@@ -342,14 +327,14 @@ def test_sid_per_afv4_auto():
check_rib(
"r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_auto_no_sid_rib.json"
)
- check_ping("ce1", "192.168.2.2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
def test_sid_per_afv4_manual():
check_rib(
"r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_manual_no_sid_rib.json"
)
- check_ping("ce1", "192.168.2.2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
configure terminal
@@ -360,7 +345,7 @@ def test_sid_per_afv4_manual():
)
check_rib("r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_manual_sid_rib.json")
- check_ping("ce1", "192.168.2.2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
@@ -370,7 +355,7 @@ def test_sid_per_afv4_manual():
no sid vpn export 8
"""
)
- check_ping("ce1", "192.168.2.2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
check_rib(
"r1", "show ip route vrf vrf10 json", "r1/vrf10_afv4_manual_no_sid_rib.json"
)
@@ -380,7 +365,7 @@ def test_sid_per_vrf_auto():
check_rib(
"r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_pervrf_auto_no_sid_rib.json"
)
- check_ping("ce1", "2001:2::2", False)
+ check_ping("ce1", "2001:2::2", False, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
configure terminal
@@ -392,11 +377,11 @@ def test_sid_per_vrf_auto():
check_rib(
"r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_pervrf6_auto_sid_rib.json"
)
- check_ping("ce1", "2001:2::2", True)
+ check_ping("ce1", "2001:2::2", True, 10, 0.5)
check_rib(
"r1", "show ip route vrf vrf10 json", "r1/vrf10_pervrf4_auto_sid_rib.json"
)
- check_ping("ce1", "192.168.2.2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
@@ -409,14 +394,14 @@ def test_sid_per_vrf_auto():
check_rib(
"r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_pervrf_auto_no_sid_rib.json"
)
- check_ping("ce1", "2001:2::2", False)
+ check_ping("ce1", "2001:2::2", False, 10, 0.5)
def test_sid_per_vrf_manual():
check_rib(
"r1", "show ip route vrf vrf10 json", "r1/vrf10_pervrf_manual_no_sid_rib.json"
)
- check_ping("ce1", "192.168.2.2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
configure terminal
@@ -428,11 +413,11 @@ def test_sid_per_vrf_manual():
check_rib(
"r1", "show ipv6 route vrf vrf10 json", "r1/vrf10_pervrf6_manual_sid_rib.json"
)
- check_ping("ce1", "2001:2::2", True)
+ check_ping("ce1", "2001:2::2", True, 10, 0.5)
check_rib(
"r1", "show ip route vrf vrf10 json", "r1/vrf10_pervrf4_manual_sid_rib.json"
)
- check_ping("ce1", "192.168.2.2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
get_topogen().gears["r2"].vtysh_cmd(
"""
@@ -445,7 +430,7 @@ def test_sid_per_vrf_manual():
check_rib(
"r1", "show ip route vrf vrf10 json", "r1/vrf10_pervrf_manual_no_sid_rib.json"
)
- check_ping("ce1", "192.168.2.2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/test_bgp_srv6l3vpn_to_bgp_vrf.py b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/test_bgp_srv6l3vpn_to_bgp_vrf.py
index fdc1f4eec3..4afaeaf78a 100755
--- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/test_bgp_srv6l3vpn_to_bgp_vrf.py
+++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/test_bgp_srv6l3vpn_to_bgp_vrf.py
@@ -23,6 +23,7 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from lib.common_config import required_linux_kernel_version
+from lib.checkping import check_ping
pytestmark = [pytest.mark.bgpd]
@@ -134,22 +135,6 @@ def open_json_file(filename):
assert False, "Could not read file {}".format(filename)
-def check_ping(name, dest_addr, expect_connected):
- def _check(name, dest_addr, match):
- tgen = get_topogen()
- output = tgen.gears[name].run("ping6 {} -c 1 -w 1".format(dest_addr))
- logger.info(output)
- if match not in output:
- return "ping fail"
-
- match = ", {} packet loss".format("0%" if expect_connected else "100%")
- logger.info("[+] check {} {} {}".format(name, dest_addr, match))
- tgen = get_topogen()
- func = functools.partial(_check, name, dest_addr, match)
- success, result = topotest.run_and_expect(func, None, count=10, wait=1)
- assert result is None, "Failed"
-
-
def check_rib(name, cmd, expected_file):
def _check(name, cmd, expected_file):
logger.info("polling")
@@ -182,20 +167,20 @@ def test_rib():
def test_ping():
- check_ping("ce1", "2001:2::2", True)
- check_ping("ce1", "2001:3::2", True)
- check_ping("ce1", "2001:4::2", False)
- check_ping("ce1", "2001:5::2", False)
- check_ping("ce1", "2001:6::2", False)
- check_ping("ce4", "2001:1::2", False)
- check_ping("ce4", "2001:2::2", False)
- check_ping("ce4", "2001:3::2", False)
- check_ping("ce4", "2001:5::2", True)
- check_ping("ce4", "2001:6::2", True)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
+ check_ping("ce1", "2001:3::2", True, 10, 1)
+ check_ping("ce1", "2001:4::2", False, 10, 1)
+ check_ping("ce1", "2001:5::2", False, 10, 1)
+ check_ping("ce1", "2001:6::2", False, 10, 1)
+ check_ping("ce4", "2001:1::2", False, 10, 1)
+ check_ping("ce4", "2001:2::2", False, 10, 1)
+ check_ping("ce4", "2001:3::2", False, 10, 1)
+ check_ping("ce4", "2001:5::2", True, 10, 1)
+ check_ping("ce4", "2001:6::2", True, 10, 1)
def test_locator_delete():
- check_ping("ce1", "2001:2::2", True)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -207,11 +192,11 @@ def test_locator_delete():
)
check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_deleted.json")
check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_deleted.json")
- check_ping("ce1", "2001:2::2", False)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
def test_locator_recreate():
- check_ping("ce1", "2001:2::2", False)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -224,11 +209,11 @@ def test_locator_recreate():
)
check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_recreated.json")
check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_recreated.json")
- check_ping("ce1", "2001:2::2", True)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
def test_bgp_locator_unset():
- check_ping("ce1", "2001:2::2", True)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -239,11 +224,11 @@ def test_bgp_locator_unset():
)
check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_deleted.json")
check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_deleted.json")
- check_ping("ce1", "2001:2::2", False)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
def test_bgp_locator_reset():
- check_ping("ce1", "2001:2::2", False)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -254,11 +239,11 @@ def test_bgp_locator_reset():
)
check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_recreated.json")
check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_recreated.json")
- check_ping("ce1", "2001:2::2", True)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
def test_bgp_srv6_unset():
- check_ping("ce1", "2001:2::2", True)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -268,11 +253,11 @@ def test_bgp_srv6_unset():
)
check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_deleted.json")
check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_deleted.json")
- check_ping("ce1", "2001:2::2", False)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
def test_bgp_srv6_reset():
- check_ping("ce1", "2001:2::2", False)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -283,7 +268,7 @@ def test_bgp_srv6_reset():
)
check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_recreated.json")
check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_recreated.json")
- check_ping("ce1", "2001:2::2", True)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/test_bgp_srv6l3vpn_to_bgp_vrf2.py b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/test_bgp_srv6l3vpn_to_bgp_vrf2.py
index a1202f5d93..914c29f0c1 100755
--- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/test_bgp_srv6l3vpn_to_bgp_vrf2.py
+++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf2/test_bgp_srv6l3vpn_to_bgp_vrf2.py
@@ -24,6 +24,7 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from lib.common_config import required_linux_kernel_version
+from lib.checkping import check_ping
pytestmark = [pytest.mark.bgpd]
@@ -96,21 +97,6 @@ def open_json_file(filename):
assert False, "Could not read file {}".format(filename)
-def check_ping(name, dest_addr, expect_connected):
- def _check(name, dest_addr, match):
- tgen = get_topogen()
- output = tgen.gears[name].run("ping {} -c 1 -w 1".format(dest_addr))
- logger.info(output)
- assert match in output, "ping fail"
-
- match = ", {} packet loss".format("0%" if expect_connected else "100%")
- logger.info("[+] check {} {} {}".format(name, dest_addr, match))
- tgen = get_topogen()
- func = functools.partial(_check, name, dest_addr, match)
- success, result = topotest.run_and_expect(func, None, count=10, wait=0.5)
- assert result is None, "Failed"
-
-
def check_rib(name, cmd, expected_file):
def _check(name, dest_addr, match):
logger.info("polling")
@@ -143,16 +129,16 @@ def test_rib():
def test_ping():
- check_ping("ce1", "192.168.2.2", True)
- check_ping("ce1", "192.168.3.2", True)
- check_ping("ce1", "192.168.4.2", False)
- check_ping("ce1", "192.168.5.2", False)
- check_ping("ce1", "192.168.6.2", False)
- check_ping("ce4", "192.168.1.2", False)
- check_ping("ce4", "192.168.2.2", False)
- check_ping("ce4", "192.168.3.2", False)
- check_ping("ce4", "192.168.5.2", True)
- check_ping("ce4", "192.168.6.2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
+ check_ping("ce1", "192.168.3.2", True, 10, 0.5)
+ check_ping("ce1", "192.168.4.2", False, 10, 0.5)
+ check_ping("ce1", "192.168.5.2", False, 10, 0.5)
+ check_ping("ce1", "192.168.6.2", False, 10, 0.5)
+ check_ping("ce4", "192.168.1.2", False, 10, 0.5)
+ check_ping("ce4", "192.168.2.2", False, 10, 0.5)
+ check_ping("ce4", "192.168.3.2", False, 10, 0.5)
+ check_ping("ce4", "192.168.5.2", True, 10, 0.5)
+ check_ping("ce4", "192.168.6.2", True, 10, 0.5)
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/test_bgp_srv6l3vpn_to_bgp_vrf3.py b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/test_bgp_srv6l3vpn_to_bgp_vrf3.py
index 7c2c7cfdaa..8a7b558be3 100644
--- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/test_bgp_srv6l3vpn_to_bgp_vrf3.py
+++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf3/test_bgp_srv6l3vpn_to_bgp_vrf3.py
@@ -21,6 +21,7 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from lib.common_config import required_linux_kernel_version
+from lib.checkping import check_ping, check_ping
pytestmark = [pytest.mark.bgpd]
@@ -93,38 +94,6 @@ def open_json_file(filename):
assert False, "Could not read file {}".format(filename)
-def check_ping4(name, dest_addr, expect_connected):
- def _check(name, dest_addr, match):
- tgen = get_topogen()
- output = tgen.gears[name].run("ping {} -c 1 -w 1".format(dest_addr))
- logger.info(output)
- if match not in output:
- return "ping fail"
-
- match = ", {} packet loss".format("0%" if expect_connected else "100%")
- logger.info("[+] check {} {} {}".format(name, dest_addr, match))
- tgen = get_topogen()
- func = functools.partial(_check, name, dest_addr, match)
- success, result = topotest.run_and_expect(func, None, count=10, wait=0.5)
- assert result is None, "Failed"
-
-
-def check_ping6(name, dest_addr, expect_connected):
- def _check(name, dest_addr, match):
- tgen = get_topogen()
- output = tgen.gears[name].run("ping6 {} -c 1 -w 1".format(dest_addr))
- logger.info(output)
- if match not in output:
- return "ping fail"
-
- match = "{} packet loss".format("0%" if expect_connected else "100%")
- logger.info("[+] check {} {} {}".format(name, dest_addr, match))
- tgen = get_topogen()
- func = functools.partial(_check, name, dest_addr, match)
- success, result = topotest.run_and_expect(func, None, count=10, wait=1)
- assert result is None, "Failed"
-
-
def check_rib(name, cmd, expected_file):
def _check(name, dest_addr, match):
logger.info("polling")
@@ -170,32 +139,32 @@ def test_rib():
def test_ping():
- check_ping4("ce1", "192.168.2.2", True)
- check_ping4("ce1", "192.168.3.2", True)
- check_ping4("ce1", "192.168.4.2", False)
- check_ping4("ce1", "192.168.5.2", False)
- check_ping4("ce1", "192.168.6.2", False)
- check_ping4("ce4", "192.168.1.2", False)
- check_ping4("ce4", "192.168.2.2", False)
- check_ping4("ce4", "192.168.3.2", False)
- check_ping4("ce4", "192.168.5.2", True)
- check_ping4("ce4", "192.168.6.2", True)
-
- check_ping6("ce1", "2001:2::2", True)
- check_ping6("ce1", "2001:3::2", True)
- check_ping6("ce1", "2001:4::2", False)
- check_ping6("ce1", "2001:5::2", False)
- check_ping6("ce1", "2001:6::2", False)
- check_ping6("ce4", "2001:1::2", False)
- check_ping6("ce4", "2001:2::2", False)
- check_ping6("ce4", "2001:3::2", False)
- check_ping6("ce4", "2001:5::2", True)
- check_ping6("ce4", "2001:6::2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
+ check_ping("ce1", "192.168.3.2", True, 10, 0.5)
+ check_ping("ce1", "192.168.4.2", False, 10, 0.5)
+ check_ping("ce1", "192.168.5.2", False, 10, 0.5)
+ check_ping("ce1", "192.168.6.2", False, 10, 0.5)
+ check_ping("ce4", "192.168.1.2", False, 10, 0.5)
+ check_ping("ce4", "192.168.2.2", False, 10, 0.5)
+ check_ping("ce4", "192.168.3.2", False, 10, 0.5)
+ check_ping("ce4", "192.168.5.2", True, 10, 0.5)
+ check_ping("ce4", "192.168.6.2", True, 10, 0.5)
+
+ check_ping("ce1", "2001:2::2", True, 10, 1)
+ check_ping("ce1", "2001:3::2", True, 10, 1)
+ check_ping("ce1", "2001:4::2", False, 10, 1)
+ check_ping("ce1", "2001:5::2", False, 10, 1)
+ check_ping("ce1", "2001:6::2", False, 10, 1)
+ check_ping("ce4", "2001:1::2", False, 10, 1)
+ check_ping("ce4", "2001:2::2", False, 10, 1)
+ check_ping("ce4", "2001:3::2", False, 10, 1)
+ check_ping("ce4", "2001:5::2", True, 10, 1)
+ check_ping("ce4", "2001:6::2", True, 10, 1)
def test_bgp_sid_vpn_export_disable():
- check_ping4("ce1", "192.168.2.2", True)
- check_ping6("ce1", "2001:2::2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -216,13 +185,13 @@ def test_bgp_sid_vpn_export_disable():
check_rib(
"r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_sid_vpn_export_disabled.json"
)
- check_ping4("ce1", "192.168.2.2", False)
- check_ping6("ce1", "2001:2::2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
def test_bgp_sid_vpn_export_reenable():
- check_ping4("ce1", "192.168.2.2", False)
- check_ping6("ce1", "2001:2::2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -243,13 +212,13 @@ def test_bgp_sid_vpn_export_reenable():
check_rib(
"r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_sid_vpn_export_reenabled.json"
)
- check_ping4("ce1", "192.168.2.2", True)
- check_ping6("ce1", "2001:2::2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
def test_locator_delete():
- check_ping4("ce1", "192.168.2.2", True)
- check_ping6("ce1", "2001:2::2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -263,13 +232,13 @@ def test_locator_delete():
check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_locator_deleted.json")
check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_deleted.json")
check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_deleted.json")
- check_ping4("ce1", "192.168.2.2", False)
- check_ping6("ce1", "2001:2::2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
def test_locator_recreate():
- check_ping4("ce1", "192.168.2.2", False)
- check_ping6("ce1", "2001:2::2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -284,13 +253,13 @@ def test_locator_recreate():
check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_locator_recreated.json")
check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_recreated.json")
check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_recreated.json")
- check_ping4("ce1", "192.168.2.2", True)
- check_ping6("ce1", "2001:2::2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
def test_bgp_locator_unset():
- check_ping4("ce1", "192.168.2.2", True)
- check_ping6("ce1", "2001:2::2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -303,13 +272,13 @@ def test_bgp_locator_unset():
check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_locator_deleted.json")
check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_deleted.json")
check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_deleted.json")
- check_ping4("ce1", "192.168.2.2", False)
- check_ping6("ce1", "2001:2::2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
def test_bgp_locator_reset():
- check_ping4("ce1", "192.168.2.2", False)
- check_ping6("ce1", "2001:2::2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -322,13 +291,13 @@ def test_bgp_locator_reset():
check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_locator_recreated.json")
check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_recreated.json")
check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_recreated.json")
- check_ping4("ce1", "192.168.2.2", True)
- check_ping6("ce1", "2001:2::2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
def test_bgp_srv6_unset():
- check_ping4("ce1", "192.168.2.2", True)
- check_ping6("ce1", "2001:2::2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -340,13 +309,13 @@ def test_bgp_srv6_unset():
check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_locator_deleted.json")
check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_deleted.json")
check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_deleted.json")
- check_ping4("ce1", "192.168.2.2", False)
- check_ping6("ce1", "2001:2::2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
def test_bgp_srv6_reset():
- check_ping4("ce1", "192.168.2.2", False)
- check_ping6("ce1", "2001:2::2", False)
+ check_ping("ce1", "192.168.2.2", False, 10, 0.5)
+ check_ping("ce1", "2001:2::2", False, 10, 1)
get_topogen().gears["r1"].vtysh_cmd(
"""
configure terminal
@@ -359,8 +328,8 @@ def test_bgp_srv6_reset():
check_rib("r2", "show bgp ipv4 vpn json", "r2/vpnv4_rib_locator_recreated.json")
check_rib("r1", "show bgp ipv6 vpn json", "r1/vpnv6_rib_locator_recreated.json")
check_rib("r2", "show bgp ipv6 vpn json", "r2/vpnv6_rib_locator_recreated.json")
- check_ping4("ce1", "192.168.2.2", True)
- check_ping6("ce1", "2001:2::2", True)
+ check_ping("ce1", "192.168.2.2", True, 10, 0.5)
+ check_ping("ce1", "2001:2::2", True, 10, 1)
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_update_delay/r2/zebra.conf b/tests/topotests/bgp_update_delay/r2/zebra.conf
index 420f00d974..1fcedaaf72 100644
--- a/tests/topotests/bgp_update_delay/r2/zebra.conf
+++ b/tests/topotests/bgp_update_delay/r2/zebra.conf
@@ -12,9 +12,5 @@ interface r2-eth3
ip address 192.168.252.1/30
vrf vrf1
!
-auto vrf1
-iface vrf1
- vrf-table auto
-!
ip forwarding
!
diff --git a/tests/topotests/bgp_vpnv4_asbr/test_bgp_vpnv4_asbr.py b/tests/topotests/bgp_vpnv4_asbr/test_bgp_vpnv4_asbr.py
index c0e57930a3..a908e74cc6 100644
--- a/tests/topotests/bgp_vpnv4_asbr/test_bgp_vpnv4_asbr.py
+++ b/tests/topotests/bgp_vpnv4_asbr/test_bgp_vpnv4_asbr.py
@@ -50,6 +50,8 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
+from lib.checkping import check_ping
+
# Required to instantiate the topology builder class.
@@ -257,29 +259,6 @@ def mpls_table_check_entry(router, out_label, out_nexthop):
)
-def check_ping(name, dest_addr, expect_connected):
- """
- Assert that ping to dest_addr is expected
- * 'name': the router to set the ping from
- * 'dest_addr': The destination ip address to ping
- * 'expect_connected': True if ping is expected to pass
- """
-
- def _check(name, dest_addr, match):
- tgen = get_topogen()
- output = tgen.gears[name].run("ping {} -c 1 -w 1".format(dest_addr))
- logger.info(output)
- if match not in output:
- return "ping fail"
-
- match = ", {} packet loss".format("0%" if expect_connected else "100%")
- logger.info("[+] check {} {} {}".format(name, dest_addr, match))
- tgen = get_topogen()
- func = functools.partial(_check, name, dest_addr, match)
- success, result = topotest.run_and_expect(func, None, count=20, wait=0.5)
- assert result is None, "Failed"
-
-
def check_show_bgp_vpn_prefix_found(
router, ipversion, prefix, rd, label=None, nexthop=None
):
@@ -493,8 +472,8 @@ def test_mpls_setup_ok():
check_show_bgp_vpn_ok(router, vpnv4_checks)
logger.info("h1, check that ping from h1 to (h2,h3) is ok")
- check_ping("h1", "172.31.1.10", True)
- check_ping("h1", "172.31.2.10", True)
+ check_ping("h1", "172.31.1.10", True, 20, 0.5)
+ check_ping("h1", "172.31.2.10", True, 20, 0.5)
def test_r3_prefixes_removed():
@@ -751,8 +730,8 @@ def test_reconfigure_nexthop_change_nexthop_self():
check_show_bgp_vpn_ok(router, vpnv4_checks)
logger.info("h1, check that ping from h1 to (h2,h3) is ok")
- check_ping("h1", "172.31.1.10", True)
- check_ping("h1", "172.31.2.10", True)
+ check_ping("h1", "172.31.1.10", True, 20, 0.5)
+ check_ping("h1", "172.31.2.10", True, 20, 0.5)
# diagnostic
logger.info("Dumping mplsvpn nexthop table")
router.vtysh_cmd("show bgp mplsvpn-nh-label-bind detail", isjson=False)
diff --git a/tests/topotests/bgp_vpnv4_noretain/r1/isisd.conf b/tests/topotests/bgp_vpnv4_noretain/r1/isisd.conf
deleted file mode 100644
index 233a6473b3..0000000000
--- a/tests/topotests/bgp_vpnv4_noretain/r1/isisd.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-interface r1-eth0
- ip router isis 1
- isis circuit-type level-1
-!
-interface lo
- ip router isis 1
- isis passive
-!
-router isis 1
- is-type level-1
- net 49.0002.0000.1994.00
- segment-routing on
- segment-routing prefix 192.0.2.1/32 index 11
-!
diff --git a/tests/topotests/bgp_vpnv4_noretain/r2/isisd.conf b/tests/topotests/bgp_vpnv4_noretain/r2/isisd.conf
deleted file mode 100644
index 547d10f2bc..0000000000
--- a/tests/topotests/bgp_vpnv4_noretain/r2/isisd.conf
+++ /dev/null
@@ -1,14 +0,0 @@
-interface r2-eth0
- ip router isis 1
- isis circuit-type level-1
-!
-interface lo
- ip router isis 1
- isis passive
-!
-router isis 1
- is-type level-1
- net 49.0002.0000.1995.00
- segment-routing on
- segment-routing prefix 192.0.2.2/32 index 22
-!
diff --git a/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py b/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py
index f665040f7f..f2865fec9e 100644
--- a/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py
+++ b/tests/topotests/bgp_vpnv4_noretain/test_bgp_vpnv4_noretain.py
@@ -120,9 +120,6 @@ def setup_module(mod):
router.load_config(
TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
)
- router.load_config(
- TopoRouter.RD_ISIS, os.path.join(CWD, "{}/bgpd.conf".format(rname))
- )
# Initialize all routers.
tgen.start_router()
diff --git a/tests/topotests/config_timing/r1/zebra.conf b/tests/topotests/config_timing/r1/zebra.conf
index 46fd965034..b4dc338b8d 100644
--- a/tests/topotests/config_timing/r1/zebra.conf
+++ b/tests/topotests/config_timing/r1/zebra.conf
@@ -4,10 +4,8 @@ ip prefix-list ANY permit 0.0.0.0/0 le 32
ipv6 prefix-list ANY seq 10 permit any
route-map RM-NONE4 deny 10
-exit-route-map
route-map RM-NONE6 deny 10
-exit-route-map
interface r1-eth0
ip address 100.0.0.1/24
diff --git a/tests/topotests/cspf_topo1/r1/sharpd.conf b/tests/topotests/cspf_topo1/r1/sharpd.conf
index 272eac944e..465034f150 100644
--- a/tests/topotests/cspf_topo1/r1/sharpd.conf
+++ b/tests/topotests/cspf_topo1/r1/sharpd.conf
@@ -1,3 +1,2 @@
!
-import-te
!
diff --git a/tests/topotests/isis_snmp/r1/ldpd.conf b/tests/topotests/isis_snmp/r1/ldpd.conf
index 5b1cbfebc9..64f51fce27 100644
--- a/tests/topotests/isis_snmp/r1/ldpd.conf
+++ b/tests/topotests/isis_snmp/r1/ldpd.conf
@@ -5,7 +5,6 @@ log file ldpd.log
! debug mpls ldp event
! debug mpls ldp errors
! debug mpls ldp sync
-agentx
!
mpls ldp
router-id 1.1.1.1
diff --git a/tests/topotests/lib/checkping.py b/tests/topotests/lib/checkping.py
new file mode 100644
index 0000000000..aaa6164dd4
--- /dev/null
+++ b/tests/topotests/lib/checkping.py
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Copyright 2023 Quentin Young
+
+import functools
+from lib.topogen import get_topogen
+from lib.topolog import logger
+from lib import topotest
+
+
+def check_ping(name, dest_addr, expect_connected, count, wait):
+ """
+ Assert that ping to dest_addr is expected
+ * 'name': the router to set the ping from
+ * 'dest_addr': The destination ip address to ping
+ * 'expect_connected': True if ping is expected to pass
+ * 'count': how many echos to send
+ * 'wait': how long ping should wait to receive all replies
+ """
+
+ def _check(name, dest_addr, match):
+ tgen = get_topogen()
+ output = tgen.gears[name].run("ping {} -c 1 -w 1".format(dest_addr))
+ logger.info(output)
+ if match not in output:
+ return "ping fail"
+
+ match = ", {} packet loss".format("0%" if expect_connected else "100%")
+ logger.info("[+] check {} {} {}".format(name, dest_addr, match))
+ tgen = get_topogen()
+ func = functools.partial(_check, name, dest_addr, match)
+ success, result = topotest.run_and_expect(func, None, count=count, wait=wait)
+ assert result is None, "Failed"
diff --git a/tests/topotests/ospf6_gr_topo1/rt1/ospf6d.conf b/tests/topotests/ospf6_gr_topo1/rt1/ospf6d.conf
index 8a9b4eb124..aa9438b78e 100644
--- a/tests/topotests/ospf6_gr_topo1/rt1/ospf6d.conf
+++ b/tests/topotests/ospf6_gr_topo1/rt1/ospf6d.conf
@@ -1,4 +1,3 @@
-:assword 1
hostname rt1
log file ospf6d.log
log commands
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index 593de7ffbc..6254a93766 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -548,9 +548,7 @@ static void configvec_dump(vector vec, bool nested)
* are not under the VRF node.
*/
if (config->index == INTERFACE_NODE
- && (listcount(config->line) == 1)
- && (line = listnode_head(config->line))
- && strmatch(line, "exit")) {
+ && list_isempty(config->line)) {
config_del(config);
continue;
}
diff --git a/zebra/main.c b/zebra/main.c
index bd4623be55..aeb9739c13 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -71,22 +71,25 @@ uint32_t rcvbufsize = 128 * 1024;
#define OPTION_V6_RR_SEMANTICS 2000
#define OPTION_ASIC_OFFLOAD 2001
+#define OPTION_V6_WITH_V4_NEXTHOP 2002
/* Command line options. */
const struct option longopts[] = {
- {"batch", no_argument, NULL, 'b'},
- {"allow_delete", no_argument, NULL, 'a'},
- {"socket", required_argument, NULL, 'z'},
- {"ecmp", required_argument, NULL, 'e'},
- {"retain", no_argument, NULL, 'r'},
- {"graceful_restart", required_argument, NULL, 'K'},
- {"asic-offload", optional_argument, NULL, OPTION_ASIC_OFFLOAD},
+ { "batch", no_argument, NULL, 'b' },
+ { "allow_delete", no_argument, NULL, 'a' },
+ { "socket", required_argument, NULL, 'z' },
+ { "ecmp", required_argument, NULL, 'e' },
+ { "retain", no_argument, NULL, 'r' },
+ { "graceful_restart", required_argument, NULL, 'K' },
+ { "asic-offload", optional_argument, NULL, OPTION_ASIC_OFFLOAD },
+ { "v6-with-v4-nexthops", no_argument, NULL, OPTION_V6_WITH_V4_NEXTHOP },
#ifdef HAVE_NETLINK
- {"vrfwnetns", no_argument, NULL, 'n'},
- {"nl-bufsize", required_argument, NULL, 's'},
- {"v6-rr-semantics", no_argument, NULL, OPTION_V6_RR_SEMANTICS},
+ { "vrfwnetns", no_argument, NULL, 'n' },
+ { "nl-bufsize", required_argument, NULL, 's' },
+ { "v6-rr-semantics", no_argument, NULL, OPTION_V6_RR_SEMANTICS },
#endif /* HAVE_NETLINK */
- {0}};
+ { 0 }
+};
zebra_capabilities_t _caps_p[] = {ZCAP_NET_ADMIN, ZCAP_SYS_ADMIN,
ZCAP_NET_RAW,
@@ -287,6 +290,7 @@ int main(int argc, char **argv)
struct sockaddr_storage dummy;
socklen_t dummylen;
bool asic_offload = false;
+ bool v6_with_v4_nexthop = false;
bool notify_on_ack = true;
graceful_restart = 0;
@@ -294,26 +298,26 @@ int main(int argc, char **argv)
frr_preinit(&zebra_di, argc, argv);
- frr_opt_add(
- "baz:e:rK:s:"
+ frr_opt_add("baz:e:rK:s:"
#ifdef HAVE_NETLINK
- "n"
+ "n"
#endif
- ,
- longopts,
- " -b, --batch Runs in batch mode\n"
- " -a, --allow_delete Allow other processes to delete zebra routes\n"
- " -z, --socket Set path of zebra socket\n"
- " -e, --ecmp Specify ECMP to use.\n"
- " -r, --retain When program terminates, retain added route by zebra.\n"
- " -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n"
- " -A, --asic-offload FRR is interacting with an asic underneath the linux kernel\n"
+ ,
+ longopts,
+ " -b, --batch Runs in batch mode\n"
+ " -a, --allow_delete Allow other processes to delete zebra routes\n"
+ " -z, --socket Set path of zebra socket\n"
+ " -e, --ecmp Specify ECMP to use.\n"
+ " -r, --retain When program terminates, retain added route by zebra.\n"
+ " -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n"
+ " -A, --asic-offload FRR is interacting with an asic underneath the linux kernel\n"
+ " --v6-with-v4-nexthops Underlying dataplane supports v6 routes with v4 nexthops"
#ifdef HAVE_NETLINK
- " -s, --nl-bufsize Set netlink receive buffer size\n"
- " -n, --vrfwnetns Use NetNS as VRF backend\n"
- " --v6-rr-semantics Use v6 RR semantics\n"
+ " -s, --nl-bufsize Set netlink receive buffer size\n"
+ " -n, --vrfwnetns Use NetNS as VRF backend\n"
+ " --v6-rr-semantics Use v6 RR semantics\n"
#else
- " -s, Set kernel socket receive buffer size\n"
+ " -s, Set kernel socket receive buffer size\n"
#endif /* HAVE_NETLINK */
);
@@ -383,6 +387,9 @@ int main(int argc, char **argv)
notify_on_ack = true;
asic_offload = true;
break;
+ case OPTION_V6_WITH_V4_NEXTHOP:
+ v6_with_v4_nexthop = true;
+ break;
#endif /* HAVE_NETLINK */
default:
frr_help_exit(1);
@@ -392,7 +399,7 @@ int main(int argc, char **argv)
zrouter.master = frr_init();
/* Zebra related initialize. */
- zebra_router_init(asic_offload, notify_on_ack);
+ zebra_router_init(asic_offload, notify_on_ack, v6_with_v4_nexthop);
zserv_init();
rib_init();
zebra_if_init();
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 2fc696c4e1..e9c243217a 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -2319,7 +2319,7 @@ static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf)
stream_putc(s, mpls_enabled);
stream_putl(s, zrouter.multipath_num);
stream_putc(s, zebra_mlag_get_role());
-
+ stream_putc(s, zrouter.v6_with_v4_nexthop);
stream_putw_at(s, 0, stream_get_endp(s));
zserv_send_message(client, s);
}
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index c5dc0e1829..e527d93610 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -280,34 +280,8 @@ struct dplane_neigh_table {
* Policy based routing rule info for the dataplane
*/
struct dplane_ctx_rule {
- uint32_t seq;
- uint32_t priority;
- uint32_t unique;
+ struct pbr_rule prule;
- /* The route table pointed by this rule */
- uint32_t table;
-
- /* Filter criteria */
- uint32_t filter_bm;
- uint32_t fwmark;
- uint8_t dsfield;
- struct prefix src_ip;
- struct prefix dst_ip;
- uint8_t ip_proto;
- uint16_t src_port;
- uint16_t dst_port;
-
- uint8_t action_pcp;
- uint16_t action_vlan_id;
- uint16_t action_vlan_flags;
-
- uint32_t action_queue_id;
-
- uint8_t filter_pcp;
- uint16_t filter_vlan_id;
- uint16_t filter_vlan_flags;
-
- char ifname[INTERFACE_NAMSIZ + 1];
struct ethaddr smac;
struct ethaddr dmac;
int out_ifindex;
@@ -2774,6 +2748,25 @@ dplane_ctx_gre_get_info(const struct zebra_dplane_ctx *ctx)
return &ctx->u.gre.info;
}
+/***********************************************************************
+ * PBR RULE ACCESSORS - start
+ **********************************************************************/
+
+/*
+ * This accessor fills one or two lib/pbr structs from the PBR context.
+ * New dataplane modules should use this interface where possible instead
+ * of adding more accessors that return fields from 'struct pbr_rule'.
+ */
+void dplane_ctx_rule_get(const struct zebra_dplane_ctx *ctx,
+ struct pbr_rule *pNew, struct pbr_rule *pOld)
+{
+ DPLANE_CTX_VALID(ctx);
+ if (pNew)
+ *pNew = ctx->u.rule.new.prule;
+ if (pOld)
+ *pOld = ctx->u.rule.old.prule;
+}
+
/* Accessors for PBR rule information */
int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx)
{
@@ -2786,7 +2779,7 @@ const char *dplane_ctx_rule_get_ifname(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.ifname;
+ return ctx->u.rule.new.prule.ifname;
}
int dplane_ctx_rule_get_unique(const struct zebra_dplane_ctx *ctx)
@@ -2807,112 +2800,112 @@ uint32_t dplane_ctx_rule_get_priority(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.priority;
+ return ctx->u.rule.new.prule.priority;
}
uint32_t dplane_ctx_rule_get_old_priority(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.priority;
+ return ctx->u.rule.old.prule.priority;
}
uint32_t dplane_ctx_rule_get_table(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.table;
+ return ctx->u.rule.new.prule.action.table;
}
uint32_t dplane_ctx_rule_get_old_table(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.table;
+ return ctx->u.rule.old.prule.action.table;
}
uint32_t dplane_ctx_rule_get_filter_bm(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.filter_bm;
+ return ctx->u.rule.new.prule.filter.filter_bm;
}
uint32_t dplane_ctx_rule_get_old_filter_bm(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.filter_bm;
+ return ctx->u.rule.old.prule.filter.filter_bm;
}
uint32_t dplane_ctx_rule_get_fwmark(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.fwmark;
+ return ctx->u.rule.new.prule.filter.fwmark;
}
uint32_t dplane_ctx_rule_get_old_fwmark(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.fwmark;
+ return ctx->u.rule.old.prule.filter.fwmark;
}
uint8_t dplane_ctx_rule_get_ipproto(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.ip_proto;
+ return ctx->u.rule.new.prule.filter.ip_proto;
}
uint8_t dplane_ctx_rule_get_old_ipproto(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.ip_proto;
+ return ctx->u.rule.old.prule.filter.ip_proto;
}
uint16_t dplane_ctx_rule_get_src_port(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.src_port;
+ return ctx->u.rule.new.prule.filter.src_port;
}
uint16_t dplane_ctx_rule_get_old_src_port(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.src_port;
+ return ctx->u.rule.old.prule.filter.src_port;
}
uint16_t dplane_ctx_rule_get_dst_port(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.dst_port;
+ return ctx->u.rule.new.prule.filter.dst_port;
}
uint16_t dplane_ctx_rule_get_old_dst_port(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.dst_port;
+ return ctx->u.rule.old.prule.filter.dst_port;
}
uint8_t dplane_ctx_rule_get_dsfield(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.new.dsfield;
+ return ctx->u.rule.new.prule.filter.dsfield;
}
uint8_t dplane_ctx_rule_get_old_dsfield(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return ctx->u.rule.old.dsfield;
+ return ctx->u.rule.old.prule.filter.dsfield;
}
const struct prefix *
@@ -2920,7 +2913,7 @@ dplane_ctx_rule_get_src_ip(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return &(ctx->u.rule.new.src_ip);
+ return &(ctx->u.rule.new.prule.filter.src_ip);
}
const struct prefix *
@@ -2928,7 +2921,7 @@ dplane_ctx_rule_get_old_src_ip(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return &(ctx->u.rule.old.src_ip);
+ return &(ctx->u.rule.old.prule.filter.src_ip);
}
const struct prefix *
@@ -2936,7 +2929,7 @@ dplane_ctx_rule_get_dst_ip(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return &(ctx->u.rule.new.dst_ip);
+ return &(ctx->u.rule.new.prule.filter.dst_ip);
}
const struct prefix *
@@ -2944,9 +2937,58 @@ dplane_ctx_rule_get_old_dst_ip(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return &(ctx->u.rule.old.dst_ip);
+ return &(ctx->u.rule.old.prule.filter.dst_ip);
+}
+
+const struct ethaddr *
+dplane_ctx_rule_get_smac(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return &(ctx->u.rule.new.smac);
+}
+
+const struct ethaddr *
+dplane_ctx_rule_get_dmac(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return &(ctx->u.rule.new.dmac);
+}
+
+int dplane_ctx_rule_get_out_ifindex(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.rule.new.out_ifindex;
+}
+
+intptr_t dplane_ctx_rule_get_old_dp_flow_ptr(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.rule.old.dp_flow_ptr;
+}
+
+intptr_t dplane_ctx_rule_get_dp_flow_ptr(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.rule.new.dp_flow_ptr;
+}
+
+void dplane_ctx_rule_set_dp_flow_ptr(struct zebra_dplane_ctx *ctx,
+ intptr_t dp_flow_ptr)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.rule.new.dp_flow_ptr = dp_flow_ptr;
}
+/***********************************************************************
+ * PBR RULE ACCESSORS - end
+ **********************************************************************/
+
uint32_t dplane_ctx_get_br_port_flags(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -3015,55 +3057,6 @@ void dplane_ctx_get_pbr_ipset_entry(const struct zebra_dplane_ctx *ctx,
memcpy(entry, &ctx->u.ipset_entry.entry, sizeof(struct zebra_pbr_ipset_entry));
}
-const struct ethaddr *
-dplane_ctx_rule_get_smac(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return &(ctx->u.rule.new.smac);
-}
-
-const struct ethaddr *
-dplane_ctx_rule_get_dmac(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return &(ctx->u.rule.new.dmac);
-}
-
-int dplane_ctx_rule_get_out_ifindex(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.rule.new.out_ifindex;
-}
-
-intptr_t dplane_ctx_rule_get_old_dp_flow_ptr(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.rule.old.dp_flow_ptr;
-}
-
-intptr_t dplane_ctx_rule_get_dp_flow_ptr(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.rule.new.dp_flow_ptr;
-}
-
-void dplane_ctx_rule_set_dp_flow_ptr(struct zebra_dplane_ctx *ctx,
- intptr_t dp_flow_ptr)
-{
- DPLANE_CTX_VALID(ctx);
-
- ctx->u.rule.new.dp_flow_ptr = dp_flow_ptr;
-}
-
-/*
- * End of dplane context accessors
- */
-
/* Optional extra info about interfaces in nexthops - a plugin must enable
* this extra info.
*/
@@ -3898,27 +3891,8 @@ static void dplane_ctx_rule_init_single(struct dplane_ctx_rule *dplane_rule,
{
struct zebra_neigh_ent *n;
- dplane_rule->priority = rule->rule.priority;
- dplane_rule->table = rule->rule.action.table;
-
- dplane_rule->filter_bm = rule->rule.filter.filter_bm;
- dplane_rule->fwmark = rule->rule.filter.fwmark;
- dplane_rule->dsfield = rule->rule.filter.dsfield;
- dplane_rule->ip_proto = rule->rule.filter.ip_proto;
- dplane_rule->src_port = rule->rule.filter.src_port;
- dplane_rule->dst_port = rule->rule.filter.dst_port;
- dplane_rule->filter_pcp = rule->rule.filter.pcp;
- dplane_rule->filter_vlan_id = rule->rule.filter.vlan_id;
- dplane_rule->filter_vlan_flags = rule->rule.filter.vlan_flags;
- prefix_copy(&(dplane_rule->dst_ip), &rule->rule.filter.dst_ip);
- prefix_copy(&(dplane_rule->src_ip), &rule->rule.filter.src_ip);
-
- dplane_rule->action_pcp = rule->rule.action.pcp;
- dplane_rule->action_vlan_flags = rule->rule.action.vlan_flags;
- dplane_rule->action_vlan_id = rule->rule.action.vlan_id;
- dplane_rule->action_queue_id = rule->rule.action.queue_id;
-
- strlcpy(dplane_rule->ifname, rule->ifname, INTERFACE_NAMSIZ);
+ dplane_rule->prule = rule->rule;
+
dplane_rule->dp_flow_ptr = rule->action.dp_flow_ptr;
n = rule->action.neigh;
if (n && (n->flags & ZEBRA_NEIGH_ENT_ACTIVE)) {
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 4be3f28874..79248a4ae4 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -11,6 +11,7 @@
#include "lib/prefix.h"
#include "lib/nexthop.h"
#include "lib/nexthop_group.h"
+#include "lib/pbr.h"
#include "lib/vlan.h"
#include "zebra/zebra_ns.h"
#include "zebra/rib.h"
@@ -693,6 +694,8 @@ uint16_t dplane_ctx_neigh_get_state(const struct zebra_dplane_ctx *ctx);
uint32_t dplane_ctx_neigh_get_update_flags(const struct zebra_dplane_ctx *ctx);
/* Accessors for policy based routing rule information */
+void dplane_ctx_rule_get(const struct zebra_dplane_ctx *ctx,
+ struct pbr_rule *pNew, struct pbr_rule *pOld);
int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx);
int dplane_ctx_rule_get_unique(const struct zebra_dplane_ctx *ctx);
int dplane_ctx_rule_get_seq(const struct zebra_dplane_ctx *ctx);
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index 1b3e31ee42..4caaf8a9e2 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -255,7 +255,8 @@ bool zebra_router_notify_on_ack(void)
return !zrouter.asic_offloaded || zrouter.notify_on_ack;
}
-void zebra_router_init(bool asic_offload, bool notify_on_ack)
+void zebra_router_init(bool asic_offload, bool notify_on_ack,
+ bool v6_with_v4_nexthop)
{
zrouter.sequence_num = 0;
@@ -310,7 +311,7 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
zrouter.asic_offloaded = asic_offload;
zrouter.notify_on_ack = notify_on_ack;
-
+ zrouter.v6_with_v4_nexthop = v6_with_v4_nexthop;
/*
* If you start using asic_notification_nexthop_control
* come talk to the FRR community about what you are doing
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index a7f0f135f9..bd86cfb495 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -207,6 +207,7 @@ struct zebra_router {
*/
bool asic_offloaded;
bool notify_on_ack;
+ bool v6_with_v4_nexthop;
/*
* If the asic is notifying us about successful nexthop
@@ -237,7 +238,8 @@ struct zebra_router {
extern struct zebra_router zrouter;
extern uint32_t rcvbufsize;
-extern void zebra_router_init(bool asic_offload, bool notify_on_ack);
+extern void zebra_router_init(bool asic_offload, bool notify_on_ack,
+ bool v6_with_v4_nexthop);
extern void zebra_router_cleanup(void);
extern void zebra_router_terminate(void);
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 291c2eb7e0..1a123ba5c2 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -4033,6 +4033,9 @@ DEFUN (show_zebra,
ttable_add_row(table, "VRF|Not Available");
#endif
+ ttable_add_row(table, "v6 with v4 nexthop|%s",
+ zrouter.v6_with_v4_nexthop ? "Used" : "Unavaliable");
+
ttable_add_row(table, "ASIC offload|%s",
zrouter.asic_offloaded ? "Used" : "Unavailable");