summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_aspath.c2
-rw-r--r--bgpd/bgp_bfd.c13
-rw-r--r--bgpd/bgp_clist.c2
-rw-r--r--bgpd/bgp_errors.c6
-rw-r--r--bgpd/bgp_errors.h1
-rw-r--r--bgpd/bgp_evpn_vty.c67
-rw-r--r--bgpd/bgp_fsm.c7
-rw-r--r--bgpd/bgp_network.c2
-rw-r--r--bgpd/bgp_nexthop.c107
-rw-r--r--bgpd/bgp_packet.c55
-rw-r--r--bgpd/bgp_pbr.c9
-rw-r--r--bgpd/bgp_route.c195
-rw-r--r--bgpd/bgp_route.h3
-rw-r--r--bgpd/bgp_vty.c96
-rw-r--r--bgpd/bgpd.c74
-rw-r--r--bgpd/bgpd.h4
-rw-r--r--bgpd/rfapi/rfapi_rib.c1
-rw-r--r--doc/developer/cli.rst12
-rw-r--r--doc/developer/library.rst1
-rw-r--r--doc/developer/lists.rst2
-rw-r--r--doc/developer/locking.rst2
-rw-r--r--doc/developer/logging.rst2
-rw-r--r--doc/developer/lua.rst65
-rw-r--r--doc/developer/modules.rst2
-rw-r--r--doc/developer/static-linking.rst4
-rw-r--r--doc/developer/subdir.am1
-rw-r--r--doc/user/bgp.rst10
-rw-r--r--doc/user/overview.rst2
-rw-r--r--doc/user/pim.rst12
-rw-r--r--doc/user/routemap.rst21
-rw-r--r--doc/user/vrrp.rst2
-rw-r--r--isisd/isis_circuit.c1
-rw-r--r--ldpd/address.c2
-rw-r--r--ldpd/ldp_zebra.c11
-rw-r--r--ldpd/ldpd.c61
-rw-r--r--ldpd/socket.c4
-rw-r--r--lib/filter.c2
-rw-r--r--lib/if.c91
-rw-r--r--lib/ipaddr.h5
-rw-r--r--lib/log.c5
-rw-r--r--lib/nexthop_group.c3
-rw-r--r--lib/nexthop_group.h2
-rw-r--r--lib/plist.c9
-rw-r--r--lib/routemap.c1063
-rw-r--r--lib/routemap.h14
-rw-r--r--lib/routemap_cli.c1
-rw-r--r--lib/routemap_northbound.c4
-rw-r--r--lib/skiplist.c4
-rw-r--r--lib/sockopt.c3
-rw-r--r--lib/vrf.h2
-rw-r--r--lib/zclient.c37
-rw-r--r--lib/zclient.h11
-rw-r--r--nhrpd/nhrp_peer.c7
-rw-r--r--ospfd/ospf_abr.c3
-rw-r--r--ospfd/ospf_dump.c4
-rw-r--r--ospfd/ospf_opaque.c4
-rw-r--r--ospfd/ospf_sr.c8
-rw-r--r--ospfd/ospf_zebra.c3
-rw-r--r--pbrd/pbr_vty.c17
-rw-r--r--pimd/pim_cmd.c388
-rw-r--r--pimd/pim_iface.c8
-rw-r--r--pimd/pim_ifchannel.c12
-rw-r--r--pimd/pim_ifchannel.h2
-rw-r--r--pimd/pim_instance.h48
-rw-r--r--pimd/pim_mlag.c655
-rw-r--r--pimd/pim_mlag.h6
-rw-r--r--pimd/pim_mroute.c2
-rw-r--r--pimd/pim_nht.c7
-rw-r--r--pimd/pim_rpf.c45
-rw-r--r--pimd/pim_upstream.c66
-rw-r--r--pimd/pim_upstream.h43
-rw-r--r--pimd/pim_vty.c2
-rw-r--r--pimd/pim_vxlan.c303
-rw-r--r--pimd/pim_vxlan.h21
-rw-r--r--pimd/pim_vxlan_instance.h1
-rw-r--r--pimd/pim_zebra.c8
-rw-r--r--pimd/pimd.c1
-rw-r--r--pimd/pimd.h10
-rw-r--r--ripd/rip_interface.c43
-rw-r--r--ripngd/ripng_interface.c44
-rwxr-xr-xtests/topotests/bgp-route-map/test_route_map_topo1.py26
-rwxr-xr-xtests/topotests/bgp-route-map/test_route_map_topo2.py1259
-rw-r--r--tests/topotests/bgp_aggregate-address_origin/__init__.py0
-rw-r--r--tests/topotests/bgp_aggregate-address_origin/r1/bgpd.conf7
-rw-r--r--tests/topotests/bgp_aggregate-address_origin/r1/zebra.conf9
-rw-r--r--tests/topotests/bgp_aggregate-address_origin/r2/bgpd.conf4
-rw-r--r--tests/topotests/bgp_aggregate-address_origin/r2/zebra.conf6
-rw-r--r--tests/topotests/bgp_aggregate-address_origin/test_bgp_aggregate-address_origin.py128
-rwxr-xr-xtests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py12
-rw-r--r--tests/topotests/evpn-pim-1/host1/bgpd.conf1
-rw-r--r--tests/topotests/evpn-pim-1/host1/pimd.conf4
-rw-r--r--tests/topotests/evpn-pim-1/host1/zebra.conf5
-rw-r--r--tests/topotests/evpn-pim-1/host2/bgpd.conf1
-rw-r--r--tests/topotests/evpn-pim-1/host2/pimd.conf4
-rw-r--r--tests/topotests/evpn-pim-1/host2/zebra.conf5
-rw-r--r--tests/topotests/evpn-pim-1/leaf1/bgpd.conf9
-rw-r--r--tests/topotests/evpn-pim-1/leaf1/pimd.conf15
-rw-r--r--tests/topotests/evpn-pim-1/leaf1/zebra.conf6
-rw-r--r--tests/topotests/evpn-pim-1/leaf2/bgpd.conf9
-rw-r--r--tests/topotests/evpn-pim-1/leaf2/pimd.conf13
-rw-r--r--tests/topotests/evpn-pim-1/leaf2/zebra.conf6
-rw-r--r--tests/topotests/evpn-pim-1/spine/bgp.summ.json44
-rw-r--r--tests/topotests/evpn-pim-1/spine/bgpd.conf10
-rw-r--r--tests/topotests/evpn-pim-1/spine/join-info.json34
-rw-r--r--tests/topotests/evpn-pim-1/spine/pimd.conf13
-rw-r--r--tests/topotests/evpn-pim-1/spine/zebra.conf8
-rwxr-xr-xtests/topotests/evpn-pim-1/test_evpn_pim_topo1.py215
-rw-r--r--tests/topotests/lib/bgp.py4
-rw-r--r--tests/topotests/rip-topo1/r1/rip_status.ref4
-rw-r--r--tests/topotests/rip-topo1/r1/ripd.conf1
-rw-r--r--tests/topotests/rip-topo1/r2/rip_status.ref4
-rw-r--r--tests/topotests/rip-topo1/r2/ripd.conf1
-rw-r--r--tests/topotests/rip-topo1/r3/rip_status.ref4
-rw-r--r--tests/topotests/rip-topo1/r3/ripd.conf1
-rwxr-xr-xtests/topotests/rip-topo1/test_rip_topo1.py5
-rw-r--r--tests/topotests/ripng-topo1/r1/ripng_status.ref4
-rw-r--r--tests/topotests/ripng-topo1/r1/ripngd.conf1
-rw-r--r--tests/topotests/ripng-topo1/r2/ripng_status.ref4
-rw-r--r--tests/topotests/ripng-topo1/r2/ripngd.conf1
-rw-r--r--tests/topotests/ripng-topo1/r3/ripng_status.ref4
-rw-r--r--tests/topotests/ripng-topo1/r3/ripngd.conf1
-rwxr-xr-xtests/topotests/ripng-topo1/test_ripng_topo1.py5
-rw-r--r--zebra/debug.c5
-rw-r--r--zebra/interface.c38
-rw-r--r--zebra/ipforward_proc.c4
-rw-r--r--zebra/irdp_packet.c28
-rw-r--r--zebra/redistribute.c17
-rw-r--r--zebra/rib.h2
-rw-r--r--zebra/rtadv.c21
-rw-r--r--zebra/zapi_msg.c45
-rw-r--r--zebra/zebra_dplane.c12
-rw-r--r--zebra/zebra_fpm_dt.c2
-rw-r--r--zebra/zebra_fpm_netlink.c2
-rw-r--r--zebra/zebra_fpm_protobuf.c2
-rw-r--r--zebra/zebra_gr.c29
-rw-r--r--zebra/zebra_mpls.c14
-rw-r--r--zebra/zebra_nhg.c43
-rw-r--r--zebra/zebra_nhg.h5
-rw-r--r--zebra/zebra_ptm.c6
-rw-r--r--zebra/zebra_pw.c2
-rw-r--r--zebra/zebra_rib.c57
-rw-r--r--zebra/zebra_rnh.c27
-rw-r--r--zebra/zebra_snmp.c12
-rw-r--r--zebra/zebra_vty.c207
144 files changed, 4810 insertions, 1545 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index a781e70d2f..5766236a00 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -793,7 +793,7 @@ static int assegments_parse(struct stream *s, size_t length,
if (head)
prev->next = seg;
else /* it's the first segment */
- head = prev = seg;
+ head = seg;
for (i = 0; i < segh.length; i++)
seg->as[i] =
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index 80ef43f0d3..1f650aaeb7 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -329,19 +329,22 @@ static int bgp_bfd_dest_update(ZAPI_CALLBACK_ARGS)
&remote_cbit, vrf_id);
if (BGP_DEBUG(zebra, ZEBRA)) {
+ struct vrf *vrf;
char buf[2][PREFIX2STR_BUFFER];
+
+ vrf = vrf_lookup_by_id(vrf_id);
prefix2str(&dp, buf[0], sizeof(buf[0]));
if (ifp) {
zlog_debug(
- "Zebra: vrf %u interface %s bfd destination %s %s %s",
- vrf_id, ifp->name, buf[0],
- bfd_get_status_str(status),
+ "Zebra: vrf %s(%u) interface %s bfd destination %s %s %s",
+ VRF_LOGNAME(vrf), vrf_id, ifp->name,
+ buf[0], bfd_get_status_str(status),
remote_cbit ? "(cbit on)" : "");
} else {
prefix2str(&sp, buf[1], sizeof(buf[1]));
zlog_debug(
- "Zebra: vrf %u source %s bfd destination %s %s %s",
- vrf_id, buf[1], buf[0],
+ "Zebra: vrf %s(%u) source %s bfd destination %s %s %s",
+ VRF_LOGNAME(vrf), vrf_id, buf[1], buf[0],
bfd_get_status_str(status),
remote_cbit ? "(cbit on)" : "");
}
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index 7ca48a5bea..18369002b8 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -44,7 +44,7 @@ static int64_t bgp_clist_new_seq_get(struct community_list *list)
int64_t newseq;
struct community_entry *entry;
- maxseq = newseq = 0;
+ maxseq = 0;
for (entry = list->head; entry; entry = entry->next) {
if (maxseq < entry->seq)
diff --git a/bgpd/bgp_errors.c b/bgpd/bgp_errors.c
index d9aba87e35..8a33ce6789 100644
--- a/bgpd/bgp_errors.c
+++ b/bgpd/bgp_errors.c
@@ -457,6 +457,12 @@ static struct log_ref ferr_bgp_err[] = {
.suggestion = "Gather data and open a Issue so that this developmental escape can be fixed, the peer should have been reset",
},
{
+ .code = EC_BGP_ROUTER_ID_SAME,
+ .title = "BGP has detected a duplicate router id during collision resolution",
+ .description = "As part of normal collision detection for opening a connection to a peer, BGP has detected that the remote peer's router-id is the same as ours",
+ .suggestion = "Change one of the two router-id's",
+ },
+ {
.code = END_FERR,
}
};
diff --git a/bgpd/bgp_errors.h b/bgpd/bgp_errors.h
index 35c5cc3998..49c58ae6b0 100644
--- a/bgpd/bgp_errors.h
+++ b/bgpd/bgp_errors.h
@@ -98,6 +98,7 @@ enum bgp_log_refs {
EC_BGP_CAPABILITY_UNKNOWN,
EC_BGP_INVALID_NEXTHOP_LENGTH,
EC_BGP_DOPPELGANGER_CONFIG,
+ EC_BGP_ROUTER_ID_SAME,
};
extern void bgp_error_init(void);
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index c5f7927c4d..7ed37319b1 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -373,14 +373,14 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
json_export_rtl = json_object_new_array();
json_object_int_add(json, "vni", bgp_vrf->l3vni);
json_object_string_add(json, "type", "L3");
- json_object_string_add(json, "kernelFlag", "Yes");
+ json_object_string_add(json, "inKernel", "True");
json_object_string_add(
json, "rd",
prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
json_object_string_add(json, "originatorIp",
inet_ntoa(bgp_vrf->originator_ip));
json_object_string_add(json, "advertiseGatewayMacip", "n/a");
- json_object_string_add(json, "advertiseSviMacip", "n/a");
+ json_object_string_add(json, "advertiseSviMacIp", "n/a");
json_object_to_json_string_ext(json,
JSON_C_TO_STRING_NOSLASHESCAPE);
json_object_string_add(json, "advertisePip",
@@ -519,8 +519,8 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
json_export_rtl = json_object_new_array();
json_object_int_add(json, "vni", vpn->vni);
json_object_string_add(json, "type", "L2");
- json_object_string_add(json, "kernelFlag",
- is_vni_live(vpn) ? "Yes" : "No");
+ json_object_string_add(json, "inKernel",
+ is_vni_live(vpn) ? "True" : "False");
json_object_string_add(
json, "rd",
prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
@@ -544,13 +544,13 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
"Disabled");
if (!vpn->advertise_svi_macip && bgp_evpn &&
bgp_evpn->evpn_info->advertise_svi_macip)
- json_object_string_add(json, "advertiseSviMacip",
+ json_object_string_add(json, "advertiseSviMacIp",
"Active");
else if (vpn->advertise_svi_macip)
- json_object_string_add(json, "advertiseSviMacip",
+ json_object_string_add(json, "advertiseSviMacIp",
"Enabled");
else
- json_object_string_add(json, "advertiseSviMacip",
+ json_object_string_add(json, "advertiseSviMacIp",
"Disabled");
} else {
vty_out(vty, "VNI: %d", vpn->vni);
@@ -887,6 +887,22 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
json_object_string_add(
json_vni, "rd",
prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
+ json_object_string_add(json_vni, "advertiseGatewayMacip",
+ "n/a");
+ json_object_string_add(json_vni, "advertiseSviMacIp", "n/a");
+ json_object_to_json_string_ext(json_vni,
+ JSON_C_TO_STRING_NOSLASHESCAPE);
+ json_object_string_add(
+ json_vni, "advertisePip",
+ bgp->evpn_info->advertise_pip ? "Enabled" : "Disabled");
+ json_object_string_add(json_vni, "sysIP",
+ inet_ntoa(bgp->evpn_info->pip_ip));
+ json_object_string_add(json_vni, "sysMAC",
+ prefix_mac2str(&bgp->evpn_info->pip_rmac,
+ buf2, sizeof(buf2)));
+ json_object_string_add(
+ json_vni, "rmac",
+ prefix_mac2str(&bgp->rmac, buf2, sizeof(buf2)));
} else {
vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, bgp->l3vni, "L3",
prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
@@ -1011,10 +1027,13 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])
char *ecom_str;
struct listnode *node, *nnode;
struct ecommunity *ecom;
+ struct bgp *bgp_evpn;
vty = args[0];
json = args[1];
+ bgp_evpn = bgp_get_evpn();
+
if (json) {
json_vni = json_object_new_object();
json_import_rtl = json_object_new_array();
@@ -1030,13 +1049,37 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])
json_object_string_add(json_vni, "type", "L2");
json_object_string_add(json_vni, "inKernel",
is_vni_live(vpn) ? "True" : "False");
- json_object_string_add(json_vni, "originatorIp",
- inet_ntoa(vpn->originator_ip));
- json_object_string_add(json_vni, "originatorIp",
- inet_ntoa(vpn->originator_ip));
json_object_string_add(
json_vni, "rd",
prefix_rd2str(&vpn->prd, buf2, sizeof(buf2)));
+ json_object_string_add(json_vni, "originatorIp",
+ inet_ntoa(vpn->originator_ip));
+ json_object_string_add(json_vni, "mcastGroup",
+ inet_ntoa(vpn->mcast_grp));
+ /* per vni knob is enabled -- Enabled
+ * Global knob is enabled -- Active
+ * default -- Disabled
+ */
+ if (!vpn->advertise_gw_macip && bgp_evpn
+ && bgp_evpn->advertise_gw_macip)
+ json_object_string_add(
+ json_vni, "advertiseGatewayMacip", "Active");
+ else if (vpn->advertise_gw_macip)
+ json_object_string_add(
+ json_vni, "advertiseGatewayMacip", "Enabled");
+ else
+ json_object_string_add(
+ json_vni, "advertiseGatewayMacip", "Disabled");
+ if (!vpn->advertise_svi_macip && bgp_evpn
+ && bgp_evpn->evpn_info->advertise_svi_macip)
+ json_object_string_add(json_vni, "advertiseSviMacIp",
+ "Active");
+ else if (vpn->advertise_svi_macip)
+ json_object_string_add(json_vni, "advertiseSviMacIp",
+ "Enabled");
+ else
+ json_object_string_add(json_vni, "advertiseSviMacIp",
+ "Disabled");
} else {
vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, vpn->vni, "L2",
prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
@@ -3901,7 +3944,7 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
bgp_evpn->advertise_gw_macip
? "Enabled"
: "Disabled");
- json_object_string_add(json, "advertiseSviMacip",
+ json_object_string_add(json, "advertiseSviMacIp",
bgp_evpn->evpn_info->advertise_svi_macip
? "Enabled" : "Disabled");
json_object_string_add(json, "advertiseAllVnis",
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index e0a9e3e4f0..b483d39bba 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -578,7 +578,8 @@ const char *const peer_down_str[] = {"",
"Waiting for VRF to be initialized",
"No AFI/SAFI activated for peer",
"AS Set config change",
- "Waiting for peer OPEN"};
+ "Waiting for peer OPEN",
+ "Reached received prefix count"};
static int bgp_graceful_restart_timer_expire(struct thread *thread)
{
@@ -1512,6 +1513,10 @@ int bgp_start(struct peer *peer)
"%s [FSM] Trying to start suppressed peer"
" - this is never supposed to happen!",
peer->host);
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
+ peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
+ else if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
+ peer->last_reset = PEER_DOWN_PFX_COUNT;
return -1;
}
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 8b585704d8..8759a88444 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -203,7 +203,7 @@ int bgp_set_socket_ttl(struct peer *peer, int bgp_sock)
int ret = 0;
/* In case of peer is EBGP, we should set TTL for this connection. */
- if (!peer->gtsm_hops && (peer_sort(peer) == BGP_PEER_EBGP)) {
+ if (!peer->gtsm_hops && (peer_sort_lookup(peer) == BGP_PEER_EBGP)) {
ret = sockopt_ttl(peer->su.sa.sa_family, bgp_sock, peer->ttl);
if (ret) {
flog_err(
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 7116c80941..ab0c3a3f11 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -180,7 +180,7 @@ void bgp_tip_del(struct bgp *bgp, struct in_addr *tip)
/* BGP own address structure */
struct bgp_addr {
- struct prefix *p;
+ struct prefix p;
struct list *ifp_name_list;
};
@@ -192,17 +192,10 @@ static void show_address_entry(struct hash_bucket *bucket, void *args)
struct listnode *node;
char str[INET6_ADDRSTRLEN] = {0};
- if (addr->p->family == AF_INET) {
- vty_out(vty, "addr: %s, count: %d : ", inet_ntop(AF_INET,
- &(addr->p->u.prefix4),
- str, INET_ADDRSTRLEN),
- addr->ifp_name_list->count);
- } else if (addr->p->family == AF_INET6) {
- vty_out(vty, "addr: %s, count: %d : ", inet_ntop(AF_INET6,
- &(addr->p->u.prefix6),
- str, INET6_ADDRSTRLEN),
- addr->ifp_name_list->count);
- }
+ vty_out(vty, "addr: %s, count: %d : ",
+ inet_ntop(addr->p.family, &(addr->p.u.prefix),
+ str, INET6_ADDRSTRLEN),
+ addr->ifp_name_list->count);
for (ALL_LIST_ELEMENTS_RO(addr->ifp_name_list, node, name)) {
vty_out(vty, " %s,", name);
@@ -231,8 +224,7 @@ static void *bgp_address_hash_alloc(void *p)
struct bgp_addr *addr = NULL;
addr = XMALLOC(MTYPE_BGP_ADDR, sizeof(struct bgp_addr));
- addr->p = prefix_new();
- prefix_copy(addr->p, copy_addr->p);
+ prefix_copy(&addr->p, &copy_addr->p);
addr->ifp_name_list = list_new();
addr->ifp_name_list->del = bgp_address_hash_string_del;
@@ -244,7 +236,6 @@ static void bgp_address_hash_free(void *data)
{
struct bgp_addr *addr = data;
- prefix_free(&addr->p);
list_delete(&addr->ifp_name_list);
XFREE(MTYPE_BGP_ADDR, addr);
}
@@ -253,7 +244,7 @@ static unsigned int bgp_address_hash_key_make(const void *p)
{
const struct bgp_addr *addr = p;
- return prefix_hash_key((const void *)(addr->p));
+ return prefix_hash_key(&addr->p);
}
static bool bgp_address_hash_cmp(const void *p1, const void *p2)
@@ -261,7 +252,7 @@ static bool bgp_address_hash_cmp(const void *p1, const void *p2)
const struct bgp_addr *addr1 = p1;
const struct bgp_addr *addr2 = p2;
- return prefix_same(addr1->p, addr2->p);
+ return prefix_same(&addr1->p, &addr2->p);
}
void bgp_address_init(struct bgp *bgp)
@@ -288,12 +279,12 @@ static void bgp_address_add(struct bgp *bgp, struct connected *ifc,
struct listnode *node;
char *name;
- tmp.p = p;
+ tmp.p = *p;
- if (tmp.p->family == AF_INET)
- tmp.p->prefixlen = IPV4_MAX_BITLEN;
- else if (tmp.p->family == AF_INET6)
- tmp.p->prefixlen = IPV6_MAX_BITLEN;
+ if (tmp.p.family == AF_INET)
+ tmp.p.prefixlen = IPV4_MAX_BITLEN;
+ else if (tmp.p.family == AF_INET6)
+ tmp.p.prefixlen = IPV6_MAX_BITLEN;
addr = hash_get(bgp->address_hash, &tmp, bgp_address_hash_alloc);
@@ -315,12 +306,12 @@ static void bgp_address_del(struct bgp *bgp, struct connected *ifc,
struct listnode *node;
char *name;
- tmp.p = p;
+ tmp.p = *p;
- if (tmp.p->family == AF_INET)
- tmp.p->prefixlen = IPV4_MAX_BITLEN;
- else if (tmp.p->family == AF_INET6)
- tmp.p->prefixlen = IPV6_MAX_BITLEN;
+ if (tmp.p.family == AF_INET)
+ tmp.p.prefixlen = IPV4_MAX_BITLEN;
+ else if (tmp.p.family == AF_INET6)
+ tmp.p.prefixlen = IPV6_MAX_BITLEN;
addr = hash_lookup(bgp->address_hash, &tmp);
/* may have been deleted earlier by bgp_interface_down() */
@@ -482,75 +473,67 @@ static void bgp_connected_cleanup(struct route_table *table,
int bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type, uint8_t sub_type,
struct attr *attr, struct bgp_node *rn)
{
- struct prefix p = {0};
- afi_t new_afi = afi;
- struct bgp_addr tmp_addr = {0}, *addr = NULL;
+ uint8_t new_afi = afi == AFI_IP ? AF_INET : AF_INET6;
+ struct bgp_addr tmp_addr = {{0}}, *addr = NULL;
struct tip_addr tmp_tip, *tip = NULL;
- bool is_bgp_static_route = ((type == ZEBRA_ROUTE_BGP)
- && (sub_type == BGP_ROUTE_STATIC))
+ bool is_bgp_static_route =
+ ((type == ZEBRA_ROUTE_BGP) && (sub_type == BGP_ROUTE_STATIC))
? true
: false;
if (!is_bgp_static_route)
- new_afi = BGP_ATTR_NEXTHOP_AFI_IP6(attr) ? AFI_IP6 : AFI_IP;
+ new_afi = BGP_ATTR_NEXTHOP_AFI_IP6(attr) ? AF_INET6 : AF_INET;
+ tmp_addr.p.family = new_afi;
switch (new_afi) {
- case AFI_IP:
- p.family = AF_INET;
+ case AF_INET:
if (is_bgp_static_route) {
- p.u.prefix4 = rn->p.u.prefix4;
- p.prefixlen = rn->p.prefixlen;
+ tmp_addr.p.u.prefix4 = rn->p.u.prefix4;
+ tmp_addr.p.prefixlen = rn->p.prefixlen;
} else {
/* Here we need to find out which nexthop to be used*/
- if (attr->flag &
- ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
-
- p.u.prefix4 = attr->nexthop;
- p.prefixlen = IPV4_MAX_BITLEN;
-
- } else if ((attr->mp_nexthop_len) &&
- ((attr->mp_nexthop_len ==
- BGP_ATTR_NHLEN_IPV4) ||
- (attr->mp_nexthop_len ==
- BGP_ATTR_NHLEN_VPNV4))) {
- p.u.prefix4 =
+ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
+ tmp_addr.p.u.prefix4 = attr->nexthop;
+ tmp_addr.p.prefixlen = IPV4_MAX_BITLEN;
+ } else if ((attr->mp_nexthop_len)
+ && ((attr->mp_nexthop_len
+ == BGP_ATTR_NHLEN_IPV4)
+ || (attr->mp_nexthop_len
+ == BGP_ATTR_NHLEN_VPNV4))) {
+ tmp_addr.p.u.prefix4 =
attr->mp_nexthop_global_in;
- p.prefixlen = IPV4_MAX_BITLEN;
+ tmp_addr.p.prefixlen = IPV4_MAX_BITLEN;
} else
return 0;
}
break;
- case AFI_IP6:
- p.family = AF_INET6;
-
+ case AF_INET6:
if (is_bgp_static_route) {
- p.u.prefix6 = rn->p.u.prefix6;
- p.prefixlen = rn->p.prefixlen;
+ tmp_addr.p.u.prefix6 = rn->p.u.prefix6;
+ tmp_addr.p.prefixlen = rn->p.prefixlen;
} else {
- p.u.prefix6 = attr->mp_nexthop_global;
- p.prefixlen = IPV6_MAX_BITLEN;
+ tmp_addr.p.u.prefix6 = attr->mp_nexthop_global;
+ tmp_addr.p.prefixlen = IPV6_MAX_BITLEN;
}
break;
default:
break;
}
- tmp_addr.p = &p;
addr = hash_lookup(bgp->address_hash, &tmp_addr);
if (addr)
return 1;
- if (new_afi == AFI_IP) {
+ if (new_afi == AF_INET) {
memset(&tmp_tip, 0, sizeof(struct tip_addr));
tmp_tip.addr = attr->nexthop;
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
tmp_tip.addr = attr->nexthop;
} else if ((attr->mp_nexthop_len) &&
- ((attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4)
- || (attr->mp_nexthop_len ==
- BGP_ATTR_NHLEN_VPNV4))) {
+ ((attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4)
+ || (attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV4))) {
tmp_tip.addr = attr->mp_nexthop_global_in;
}
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index c72f7226e2..3132c8b866 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1007,6 +1007,11 @@ static int bgp_collision_detect(struct peer *new, struct in_addr remote_id)
return -1;
}
else {
+ if (ntohl(peer->local_id.s_addr) ==
+ ntohl(remote_id.s_addr))
+ flog_err(EC_BGP_ROUTER_ID_SAME, "Peer's router-id %s is the same as ours",
+ inet_ntoa(remote_id));
+
/* 3. Otherwise, the local system closes newly
created
BGP connection (the one associated with the
@@ -1298,8 +1303,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
/* Open option part parse. */
if (optlen != 0) {
- if ((ret = bgp_open_option_parse(peer, optlen, &mp_capability))
- < 0)
+ if (bgp_open_option_parse(peer, optlen, &mp_capability) < 0)
return BGP_Stop;
} else {
if (bgp_debug_neighbor_events(peer))
@@ -1341,7 +1345,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
return BGP_Stop;
/* Get sockname. */
- if ((ret = bgp_getsockname(peer)) < 0) {
+ if (bgp_getsockname(peer) < 0) {
flog_err_sys(EC_LIB_SOCKET,
"%s: bgp_getsockname() failed for peer: %s",
__FUNCTION__, peer->host);
@@ -1967,38 +1971,29 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
} else
p_pnt = p_end;
- if ((ok = (p_pnt < p_end)))
- orfp.ge =
- *p_pnt++; /* value
- checked in
- prefix_bgp_orf_set()
- */
- if ((ok = (p_pnt < p_end)))
- orfp.le =
- *p_pnt++; /* value
- checked in
- prefix_bgp_orf_set()
- */
+ /* val checked in prefix_bgp_orf_set */
+ if (p_pnt < p_end)
+ orfp.ge = *p_pnt++;
+
+ /* val checked in prefix_bgp_orf_set */
+ if (p_pnt < p_end)
+ orfp.le = *p_pnt++;
+
if ((ok = (p_pnt < p_end)))
orfp.p.prefixlen = *p_pnt++;
- orfp.p.family = afi2family(
- afi); /* afi checked already */
-
- psize = PSIZE(
- orfp.p.prefixlen); /* 0 if not
- ok */
- if (psize
- > prefix_blen(
- &orfp.p)) /* valid for
- family ? */
- {
+
+ /* afi checked already */
+ orfp.p.family = afi2family(afi);
+
+ /* 0 if not ok */
+ psize = PSIZE(orfp.p.prefixlen);
+ /* valid for family ? */
+ if (psize > prefix_blen(&orfp.p)) {
ok = 0;
psize = prefix_blen(&orfp.p);
}
- if (psize
- > (p_end - p_pnt)) /* valid for
- packet ? */
- {
+ /* valid for packet ? */
+ if (psize > (p_end - p_pnt)) {
ok = 0;
psize = p_end - p_pnt;
}
diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c
index eea20d7210..172ec8b42e 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -1403,11 +1403,16 @@ void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api)
ptr += sprintf(ptr,
"@redirect ip nh %s", local_buff);
break;
- case ACTION_REDIRECT:
+ case ACTION_REDIRECT: {
+ struct vrf *vrf;
+
+ vrf = vrf_lookup_by_id(api->actions[i].u.redirect_vrf);
INCREMENT_DISPLAY(ptr, nb_items);
- ptr += sprintf(ptr, "@redirect vrf %u",
+ ptr += sprintf(ptr, "@redirect vrf %s(%u)",
+ VRF_LOGNAME(vrf),
api->actions[i].u.redirect_vrf);
break;
+ }
case ACTION_MARKING:
INCREMENT_DISPLAY(ptr, nb_items);
ptr += sprintf(ptr, "@set dscp %u",
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 755024f4b6..1cd0bbe578 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -914,8 +914,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
pair (newm, existm) with the cluster list length. Prefer the
path with smaller cluster list length. */
if (newm == existm) {
- if (peer_sort(new->peer) == BGP_PEER_IBGP
- && peer_sort(exist->peer) == BGP_PEER_IBGP
+ if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
+ && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
&& (mpath_cfg == NULL
|| CHECK_FLAG(
mpath_cfg->ibgp_flags,
@@ -6270,6 +6270,9 @@ void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
else if (aggregate->egp_origin_count > 0)
origin = BGP_ORIGIN_EGP;
+ if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
+ origin = aggregate->origin;
+
if (aggregate->as_set) {
if (aggregate->aspath)
/* Retrieve aggregate route's as-path.
@@ -6434,6 +6437,9 @@ static void bgp_add_route_to_aggregate(struct bgp *bgp, struct prefix *aggr_p,
else if (aggregate->egp_origin_count > 0)
origin = BGP_ORIGIN_EGP;
+ if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
+ origin = aggregate->origin;
+
if (aggregate->as_set) {
/* Compute aggregate route's as-path.
*/
@@ -6565,6 +6571,9 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
else if (aggregate->egp_origin_count > 0)
origin = BGP_ORIGIN_EGP;
+ if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
+ origin = aggregate->origin;
+
if (aggregate->as_set) {
/* Retrieve aggregate route's as-path.
*/
@@ -6660,6 +6669,19 @@ void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
#define AGGREGATE_AS_SET 1
#define AGGREGATE_AS_UNSET 0
+static const char *bgp_origin2str(uint8_t origin)
+{
+ switch (origin) {
+ case BGP_ORIGIN_IGP:
+ return "igp";
+ case BGP_ORIGIN_EGP:
+ return "egp";
+ case BGP_ORIGIN_INCOMPLETE:
+ return "incomplete";
+ }
+ return "n/a";
+}
+
static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
afi_t afi, safi_t safi)
{
@@ -6753,8 +6775,9 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
}
static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
- safi_t safi, const char *rmap, uint8_t summary_only,
- uint8_t as_set)
+ safi_t safi, const char *rmap,
+ uint8_t summary_only, uint8_t as_set,
+ uint8_t origin)
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
int ret;
@@ -6818,6 +6841,12 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
aggregate->as_set = as_set_new;
aggregate->safi = safi;
+ /* Override ORIGIN attribute if defined.
+ * E.g.: Cisco and Juniper set ORIGIN for aggregated address
+ * to IGP which is not what rfc4271 says.
+ * This enables the same behavior, optionally.
+ */
+ aggregate->origin = origin;
if (rmap) {
XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
@@ -6837,7 +6866,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
DEFUN (aggregate_address,
aggregate_address_cmd,
- "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
+ "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
"Configure BGP aggregate entries\n"
"Aggregate prefix\n"
"Generate AS set path information\n"
@@ -6845,12 +6874,17 @@ DEFUN (aggregate_address,
"Filter more specific routes from updates\n"
"Generate AS set path information\n"
"Apply route map to aggregate network\n"
- "Name of route map\n")
+ "Name of route map\n"
+ "BGP origin code\n"
+ "Remote EGP\n"
+ "Local IGP\n"
+ "Unknown heritage\n")
{
int idx = 0;
argv_find(argv, argc, "A.B.C.D/M", &idx);
char *prefix = argv[idx]->arg;
char *rmap = NULL;
+ uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
: AGGREGATE_AS_UNSET;
idx = 0;
@@ -6863,13 +6897,23 @@ DEFUN (aggregate_address,
if (idx)
rmap = argv[idx]->arg;
- return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
- rmap, summary_only, as_set);
+ idx = 0;
+ if (argv_find(argv, argc, "origin", &idx)) {
+ if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
+ origin = BGP_ORIGIN_IGP;
+ if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
+ origin = BGP_ORIGIN_EGP;
+ if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
+ origin = BGP_ORIGIN_INCOMPLETE;
+ }
+
+ return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty), rmap,
+ summary_only, as_set, origin);
}
DEFUN (aggregate_address_mask,
aggregate_address_mask_cmd,
- "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
+ "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
"Configure BGP aggregate entries\n"
"Aggregate address\n"
"Aggregate mask\n"
@@ -6878,7 +6922,11 @@ DEFUN (aggregate_address_mask,
"Filter more specific routes from updates\n"
"Generate AS set path information\n"
"Apply route map to aggregate network\n"
- "Name of route map\n")
+ "Name of route map\n"
+ "BGP origin code\n"
+ "Remote EGP\n"
+ "Local IGP\n"
+ "Unknown heritage\n")
{
int idx = 0;
argv_find(argv, argc, "A.B.C.D", &idx);
@@ -6886,6 +6934,7 @@ DEFUN (aggregate_address_mask,
char *mask = argv[idx + 1]->arg;
bool rmap_found;
char *rmap = NULL;
+ uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
: AGGREGATE_AS_UNSET;
idx = 0;
@@ -6905,13 +6954,23 @@ DEFUN (aggregate_address_mask,
return CMD_WARNING_CONFIG_FAILED;
}
+ idx = 0;
+ if (argv_find(argv, argc, "origin", &idx)) {
+ if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
+ origin = BGP_ORIGIN_IGP;
+ if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
+ origin = BGP_ORIGIN_EGP;
+ if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
+ origin = BGP_ORIGIN_INCOMPLETE;
+ }
+
return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
- rmap, summary_only, as_set);
+ rmap, summary_only, as_set, origin);
}
DEFUN (no_aggregate_address,
no_aggregate_address_cmd,
- "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
+ "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
NO_STR
"Configure BGP aggregate entries\n"
"Aggregate prefix\n"
@@ -6920,7 +6979,11 @@ DEFUN (no_aggregate_address,
"Filter more specific routes from updates\n"
"Generate AS set path information\n"
"Apply route map to aggregate network\n"
- "Name of route map\n")
+ "Name of route map\n"
+ "BGP origin code\n"
+ "Remote EGP\n"
+ "Local IGP\n"
+ "Unknown heritage\n")
{
int idx = 0;
argv_find(argv, argc, "A.B.C.D/M", &idx);
@@ -6930,7 +6993,7 @@ DEFUN (no_aggregate_address,
DEFUN (no_aggregate_address_mask,
no_aggregate_address_mask_cmd,
- "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
+ "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
NO_STR
"Configure BGP aggregate entries\n"
"Aggregate address\n"
@@ -6940,7 +7003,11 @@ DEFUN (no_aggregate_address_mask,
"Filter more specific routes from updates\n"
"Generate AS set path information\n"
"Apply route map to aggregate network\n"
- "Name of route map\n")
+ "Name of route map\n"
+ "BGP origin code\n"
+ "Remote EGP\n"
+ "Local IGP\n"
+ "Unknown heritage\n")
{
int idx = 0;
argv_find(argv, argc, "A.B.C.D", &idx);
@@ -6960,7 +7027,7 @@ DEFUN (no_aggregate_address_mask,
DEFUN (ipv6_aggregate_address,
ipv6_aggregate_address_cmd,
- "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
+ "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
"Configure BGP aggregate entries\n"
"Aggregate prefix\n"
"Generate AS set path information\n"
@@ -6968,13 +7035,18 @@ DEFUN (ipv6_aggregate_address,
"Filter more specific routes from updates\n"
"Generate AS set path information\n"
"Apply route map to aggregate network\n"
- "Name of route map\n")
+ "Name of route map\n"
+ "BGP origin code\n"
+ "Remote EGP\n"
+ "Local IGP\n"
+ "Unknown heritage\n")
{
int idx = 0;
argv_find(argv, argc, "X:X::X:X/M", &idx);
char *prefix = argv[idx]->arg;
char *rmap = NULL;
bool rmap_found;
+ uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
: AGGREGATE_AS_UNSET;
@@ -6987,13 +7059,23 @@ DEFUN (ipv6_aggregate_address,
if (rmap_found)
rmap = argv[idx]->arg;
+ idx = 0;
+ if (argv_find(argv, argc, "origin", &idx)) {
+ if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
+ origin = BGP_ORIGIN_IGP;
+ if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
+ origin = BGP_ORIGIN_EGP;
+ if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
+ origin = BGP_ORIGIN_INCOMPLETE;
+ }
+
return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
- sum_only, as_set);
+ sum_only, as_set, origin);
}
DEFUN (no_ipv6_aggregate_address,
no_ipv6_aggregate_address_cmd,
- "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
+ "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
NO_STR
"Configure BGP aggregate entries\n"
"Aggregate prefix\n"
@@ -7002,7 +7084,11 @@ DEFUN (no_ipv6_aggregate_address,
"Filter more specific routes from updates\n"
"Generate AS set path information\n"
"Apply route map to aggregate network\n"
- "Name of route map\n")
+ "Name of route map\n"
+ "BGP origin code\n"
+ "Remote EGP\n"
+ "Local IGP\n"
+ "Unknown heritage\n")
{
int idx = 0;
argv_find(argv, argc, "X:X::X:X/M", &idx);
@@ -8867,8 +8953,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
} else {
if (nexthop_vrfid == VRF_UNKNOWN)
vty_out(vty, " vrf ?");
- else
- vty_out(vty, " vrf %u", nexthop_vrfid);
+ else {
+ struct vrf *vrf;
+
+ vrf = vrf_lookup_by_id(nexthop_vrfid);
+ vty_out(vty, " vrf %s(%u)",
+ VRF_LOGNAME(vrf), nexthop_vrfid);
+ }
}
}
@@ -10336,32 +10427,20 @@ DEFUN (show_ip_bgp_large_community_list,
"Exact match of the large-communities\n"
JSON_STR)
{
- char *vrf = NULL;
afi_t afi = AFI_IP6;
safi_t safi = SAFI_UNICAST;
int idx = 0;
bool exact_match = 0;
-
- if (argv_find(argv, argc, "ip", &idx))
- afi = AFI_IP;
- if (argv_find(argv, argc, "view", &idx)
- || argv_find(argv, argc, "vrf", &idx))
- vrf = argv[++idx]->arg;
- if (argv_find(argv, argc, "ipv4", &idx)
- || argv_find(argv, argc, "ipv6", &idx)) {
- afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
- if (argv_find(argv, argc, "unicast", &idx)
- || argv_find(argv, argc, "multicast", &idx))
- safi = bgp_vty_safi_from_str(argv[idx]->text);
- }
-
+ struct bgp *bgp = NULL;
bool uj = use_json(argc, argv);
- struct bgp *bgp = bgp_lookup_by_name(vrf);
- if (bgp == NULL) {
- vty_out(vty, "Can't find BGP instance %s\n", vrf);
- return CMD_WARNING;
- }
+ if (uj)
+ argc--;
+
+ bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+ &bgp, uj);
+ if (!idx)
+ return CMD_WARNING;
argv_find(argv, argc, "large-community-list", &idx);
@@ -10387,32 +10466,20 @@ DEFUN (show_ip_bgp_large_community,
"Exact match of the large-communities\n"
JSON_STR)
{
- char *vrf = NULL;
afi_t afi = AFI_IP6;
safi_t safi = SAFI_UNICAST;
int idx = 0;
bool exact_match = 0;
-
- if (argv_find(argv, argc, "ip", &idx))
- afi = AFI_IP;
- if (argv_find(argv, argc, "view", &idx)
- || argv_find(argv, argc, "vrf", &idx))
- vrf = argv[++idx]->arg;
- if (argv_find(argv, argc, "ipv4", &idx)
- || argv_find(argv, argc, "ipv6", &idx)) {
- afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
- if (argv_find(argv, argc, "unicast", &idx)
- || argv_find(argv, argc, "multicast", &idx))
- safi = bgp_vty_safi_from_str(argv[idx]->text);
- }
-
+ struct bgp *bgp = NULL;
bool uj = use_json(argc, argv);
- struct bgp *bgp = bgp_lookup_by_name(vrf);
- if (bgp == NULL) {
- vty_out(vty, "Can't find BGP instance %s\n", vrf);
- return CMD_WARNING;
- }
+ if (uj)
+ argc--;
+
+ bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+ &bgp, uj);
+ if (!idx)
+ return CMD_WARNING;
if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
if (argv_find(argv, argc, "exact-match", &idx))
@@ -12916,6 +12983,10 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
if (bgp_aggregate->rmap.name)
vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
+ if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
+ vty_out(vty, " origin %s",
+ bgp_origin2str(bgp_aggregate->origin));
+
vty_out(vty, "\n");
}
}
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 8f31cd38dc..0ad656d133 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -338,6 +338,9 @@ struct bgp_aggregate {
/* Count of routes of origin type egp under this aggregate. */
unsigned long egp_origin_count;
+ /* Optional modify flag to override ORIGIN */
+ uint8_t origin;
+
/* Hash containing the communities of all the
* routes under this aggregate.
*/
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index f18f9ccf4b..62767a603c 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -9443,7 +9443,7 @@ static void bgp_show_neighnor_graceful_restart_rbit(struct vty *vty,
bool rbit_status = 0;
if (!use_json)
- vty_out(vty, "\n R bit : ");
+ vty_out(vty, "\n R bit: ");
if (CHECK_FLAG(p->cap, PEER_CAP_RESTART_ADV)
&& (CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV))
@@ -9476,7 +9476,7 @@ static void bgp_show_neighbor_graceful_restart_remote_mode(struct vty *vty,
const char *mode = "NotApplicable";
if (!use_json)
- vty_out(vty, "\n Remote GR Mode : ");
+ vty_out(vty, "\n Remote GR Mode: ");
if (CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV)
&& (peer->status == Established)) {
@@ -9512,7 +9512,7 @@ static void bgp_show_neighbor_graceful_restart_local_mode(struct vty *vty,
const char *mode = "Invalid";
if (!use_json)
- vty_out(vty, " Local GR Mode : ");
+ vty_out(vty, " Local GR Mode: ");
if (bgp_peer_gr_mode_get(p) == PEER_HELPER)
mode = "Helper";
@@ -9570,10 +9570,10 @@ static void bgp_show_neighbor_graceful_restart_capability_per_afi_safi(
eor_flag = false;
if (!use_json) {
- vty_out(vty, " %s :\n",
+ vty_out(vty, " %s:\n",
get_afi_safi_str(afi, safi, false));
- vty_out(vty, " F bit : ");
+ vty_out(vty, " F bit: ");
}
if (peer->nsf[afi][safi]
@@ -9594,27 +9594,7 @@ static void bgp_show_neighbor_graceful_restart_capability_per_afi_safi(
}
if (!use_json)
- vty_out(vty, " End-of-RIB Received : ");
-
- if (CHECK_FLAG(peer->af_sflags[afi][safi],
- PEER_STATUS_EOR_RECEIVED)) {
- if (use_json)
- json_object_boolean_true_add(
- json_endofrib_status,
- "endOfRibRecv");
- else
- vty_out(vty, "Yes\n");
- } else {
- if (use_json)
- json_object_boolean_false_add(
- json_endofrib_status,
- "endOfRibRecv");
- else
- vty_out(vty, "No\n");
- }
-
- if (!use_json)
- vty_out(vty, " End-of-RIB Send : ");
+ vty_out(vty, " End-of-RIB sent: ");
if (CHECK_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_EOR_SEND)) {
@@ -9627,7 +9607,7 @@ static void bgp_show_neighbor_graceful_restart_capability_per_afi_safi(
} else {
vty_out(vty, "Yes\n");
vty_out(vty,
- " EoRSentAfterUpdate : ");
+ " End-of-RIB sent after update: ");
PRINT_EOR(eor_flag);
}
@@ -9642,11 +9622,31 @@ static void bgp_show_neighbor_graceful_restart_capability_per_afi_safi(
} else {
vty_out(vty, "No\n");
vty_out(vty,
- " EoRSentAfterUpdate : ");
+ " End-of-RIB sent after update: ");
vty_out(vty, "No\n");
}
}
+ if (!use_json)
+ vty_out(vty, " End-of-RIB received: ");
+
+ if (CHECK_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_EOR_RECEIVED)) {
+ if (use_json)
+ json_object_boolean_true_add(
+ json_endofrib_status,
+ "endOfRibRecv");
+ else
+ vty_out(vty, "Yes\n");
+ } else {
+ if (use_json)
+ json_object_boolean_false_add(
+ json_endofrib_status,
+ "endOfRibRecv");
+ else
+ vty_out(vty, "No\n");
+ }
+
if (use_json) {
json_object_int_add(json_timer,
"stalePathTimer",
@@ -9686,46 +9686,36 @@ static void bgp_show_neighbor_graceful_restart_capability_per_afi_safi(
.t_select_deferral));
}
} else {
- vty_out(vty, " Timers:\n");
-
- vty_out(vty, "%*s", 6, "");
+ vty_out(vty, " Timers:\n");
vty_out(vty,
- "Configured Stale Path Time(sec)%*s: %u\n",
- 8, "", peer->bgp->stalepath_time);
+ " Configured Stale Path Time(sec): %u\n",
+ peer->bgp->stalepath_time);
- if (peer->t_gr_stale != NULL) {
- vty_out(vty, "%*s", 6, "");
+ if (peer->t_gr_stale != NULL)
vty_out(vty,
- "Stale Path Remaining(sec)%*s: %ld\n",
- 14, "",
+ " Stale Path Remaining(sec): %ld\n",
thread_timer_remain_second(
peer->t_gr_stale));
- }
/* Display Configured Selection
* Deferral only when when
* Gr mode is enabled.
*/
if (CHECK_FLAG(peer->flags,
- PEER_FLAG_GRACEFUL_RESTART)) {
- vty_out(vty, "%*s", 6, "");
+ PEER_FLAG_GRACEFUL_RESTART))
vty_out(vty,
- "Configured Selection Deferral Time(sec): %u\n",
+ " Configured Selection Deferral Time(sec): %u\n",
peer->bgp->select_defer_time);
- }
if (peer->bgp->gr_info[afi][safi]
.t_select_deferral
- != NULL) {
-
- vty_out(vty, "%*s", 6, "");
+ != NULL)
vty_out(vty,
- "Selection Deferral Time Remaining(sec) : %ld\n",
+ " Selection Deferral Time Remaining(sec): %ld\n",
thread_timer_remain_second(
peer->bgp
->gr_info[afi]
[safi]
.t_select_deferral));
- }
}
if (use_json) {
json_object_object_add(json_afi_safi,
@@ -9765,19 +9755,17 @@ static void bgp_show_neighbor_graceful_restart_time(struct vty *vty,
json_object_object_add(json, "timers", json_timer);
} else {
- vty_out(vty, " Timers :\n");
- vty_out(vty, " Configured Restart Time(sec) : %u\n",
+ vty_out(vty, " Timers:\n");
+ vty_out(vty, " Configured Restart Time(sec): %u\n",
p->bgp->restart_time);
- vty_out(vty, " Received Restart Time(sec) : %u\n",
+ vty_out(vty, " Received Restart Time(sec): %u\n",
p->v_gr_restart);
if (p->t_gr_restart != NULL)
- vty_out(vty,
- " Restart Time Remaining(sec) : %ld\n",
+ vty_out(vty, " Restart Time Remaining(sec): %ld\n",
thread_timer_remain_second(p->t_gr_restart));
if (p->t_gr_restart != NULL) {
- vty_out(vty,
- " Restart Time Remaining(sec) : %ld\n",
+ vty_out(vty, " Restart Time Remaining(sec): %ld\n",
thread_timer_remain_second(p->t_gr_restart));
}
}
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 34581b66fc..96b307ee21 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -284,8 +284,11 @@ void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id)
*/
if (bgp->established_peers == 0) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("RID change : vrf %u, RTR ID %s",
- bgp->vrf_id, inet_ntoa(*addr));
+ zlog_debug(
+ "RID change : vrf %s(%u), RTR ID %s",
+ bgp->name_pretty,
+ bgp->vrf_id,
+ inet_ntoa(*addr));
bgp_router_id_set(bgp, addr, false);
}
}
@@ -304,8 +307,11 @@ void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id)
*/
if (bgp->established_peers == 0) {
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("RID change : vrf %u, RTR ID %s",
- bgp->vrf_id, inet_ntoa(*addr));
+ zlog_debug(
+ "RID change : vrf %s(%u), RTR ID %s",
+ bgp->name_pretty,
+ bgp->vrf_id,
+ inet_ntoa(*addr));
bgp_router_id_set(bgp, addr, false);
}
}
@@ -427,10 +433,12 @@ int bgp_confederation_id_set(struct bgp *bgp, as_t as)
AS change. Just Reset EBGP sessions, not CONFED sessions. If we
were not doing confederation before, reset all EBGP sessions. */
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ bgp_peer_sort_t ptype = peer_sort(peer);
+
/* We're looking for peers who's AS is not local or part of our
confederation. */
if (already_confed) {
- if (peer_sort(peer) == BGP_PEER_EBGP) {
+ if (ptype == BGP_PEER_EBGP) {
peer->local_as = as;
if (BGP_IS_VALID_STATE_FOR_NOTIF(
peer->status)) {
@@ -446,9 +454,9 @@ int bgp_confederation_id_set(struct bgp *bgp, as_t as)
/* Not doign confederation before, so reset every
non-local
session */
- if (peer_sort(peer) != BGP_PEER_IBGP) {
+ if (ptype != BGP_PEER_IBGP) {
/* Reset the local_as to be our EBGP one */
- if (peer_sort(peer) == BGP_PEER_EBGP)
+ if (ptype == BGP_PEER_EBGP)
peer->local_as = as;
if (BGP_IS_VALID_STATE_FOR_NOTIF(
peer->status)) {
@@ -961,6 +969,11 @@ bgp_peer_sort_t peer_sort(struct peer *peer)
return peer->sort;
}
+bgp_peer_sort_t peer_sort_lookup(struct peer *peer)
+{
+ return peer->sort;
+}
+
static void peer_free(struct peer *peer)
{
afi_t afi;
@@ -1652,7 +1665,7 @@ int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)
/* Change peer's AS number. */
void peer_as_change(struct peer *peer, as_t as, int as_specified)
{
- bgp_peer_sort_t type;
+ bgp_peer_sort_t origtype, newtype;
/* Stop peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
@@ -1663,7 +1676,7 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified)
} else
bgp_session_reset(peer);
}
- type = peer_sort(peer);
+ origtype = peer_sort_lookup(peer);
peer->as = as;
peer->as_type = as_specified;
@@ -1674,21 +1687,22 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified)
else
peer->local_as = peer->bgp->as;
+ newtype = peer_sort(peer);
/* Advertisement-interval reset */
if (!CHECK_FLAG(peer->flags, PEER_FLAG_ROUTEADV)) {
- peer->v_routeadv = (peer_sort(peer) == BGP_PEER_IBGP)
+ peer->v_routeadv = (newtype == BGP_PEER_IBGP)
? BGP_DEFAULT_IBGP_ROUTEADV
: BGP_DEFAULT_EBGP_ROUTEADV;
}
/* TTL reset */
- if (peer_sort(peer) == BGP_PEER_IBGP)
+ if (newtype == BGP_PEER_IBGP)
peer->ttl = MAXTTL;
- else if (type == BGP_PEER_IBGP)
+ else if (origtype == BGP_PEER_IBGP)
peer->ttl = BGP_DEFAULT_TTL;
/* reflector-client reset */
- if (peer_sort(peer) != BGP_PEER_IBGP) {
+ if (newtype != BGP_PEER_IBGP) {
UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_UNICAST],
PEER_FLAG_REFLECTOR_CLIENT);
UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_MULTICAST],
@@ -1718,7 +1732,7 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified)
}
/* local-as reset */
- if (peer_sort(peer) != BGP_PEER_EBGP) {
+ if (newtype != BGP_PEER_EBGP) {
peer->change_local_as = 0;
peer_flag_unset(peer, PEER_FLAG_LOCAL_AS);
peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
@@ -2714,6 +2728,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
int first_member = 0;
afi_t afi;
safi_t safi;
+ bgp_peer_sort_t ptype, gtype;
/* Lookup the peer. */
if (!peer)
@@ -2742,15 +2757,16 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
peer->sort = group->conf->sort;
}
- if (!group->conf->as && peer_sort(peer)) {
- if (peer_sort(group->conf) != BGP_PEER_INTERNAL
- && peer_sort(group->conf) != peer_sort(peer)) {
+ ptype = peer_sort(peer);
+ if (!group->conf->as && ptype != BGP_PEER_UNSPECIFIED) {
+ gtype = peer_sort(group->conf);
+ if ((gtype != BGP_PEER_INTERNAL) && (gtype != ptype)) {
if (as)
*as = peer->as;
return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
}
- if (peer_sort(group->conf) == BGP_PEER_INTERNAL)
+ if (gtype == BGP_PEER_INTERNAL)
first_member = 1;
}
@@ -2782,22 +2798,22 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
}
if (first_member) {
+ gtype = peer_sort(group->conf);
/* Advertisement-interval reset */
if (!CHECK_FLAG(group->conf->flags,
PEER_FLAG_ROUTEADV)) {
group->conf->v_routeadv =
- (peer_sort(group->conf)
- == BGP_PEER_IBGP)
+ (gtype == BGP_PEER_IBGP)
? BGP_DEFAULT_IBGP_ROUTEADV
: BGP_DEFAULT_EBGP_ROUTEADV;
}
/* ebgp-multihop reset */
- if (peer_sort(group->conf) == BGP_PEER_IBGP)
+ if (gtype == BGP_PEER_IBGP)
group->conf->ttl = MAXTTL;
/* local-as reset */
- if (peer_sort(group->conf) != BGP_PEER_EBGP) {
+ if (gtype != BGP_PEER_EBGP) {
group->conf->change_local_as = 0;
peer_flag_unset(group->conf,
PEER_FLAG_LOCAL_AS);
@@ -4119,6 +4135,7 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
struct peer *member;
struct listnode *node, *nnode;
struct peer_flag_action action;
+ bgp_peer_sort_t ptype;
memset(&action, 0, sizeof(struct peer_flag_action));
size = sizeof peer_af_flag_action_list
@@ -4132,18 +4149,17 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
if (!found)
return BGP_ERR_INVALID_FLAG;
+ ptype = peer_sort(peer);
/* Special check for reflector client. */
- if (flag & PEER_FLAG_REFLECTOR_CLIENT
- && peer_sort(peer) != BGP_PEER_IBGP)
+ if (flag & PEER_FLAG_REFLECTOR_CLIENT && ptype != BGP_PEER_IBGP)
return BGP_ERR_NOT_INTERNAL_PEER;
/* Special check for remove-private-AS. */
- if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
- && peer_sort(peer) == BGP_PEER_IBGP)
+ if (flag & PEER_FLAG_REMOVE_PRIVATE_AS && ptype == BGP_PEER_IBGP)
return BGP_ERR_REMOVE_PRIVATE_AS;
/* as-override is not allowed for IBGP peers */
- if (flag & PEER_FLAG_AS_OVERRIDE && peer_sort(peer) == BGP_PEER_IBGP)
+ if (flag & PEER_FLAG_AS_OVERRIDE && ptype == BGP_PEER_IBGP)
return BGP_ERR_AS_OVERRIDE;
/* Handle flag updates where desired state matches current state. */
@@ -5310,9 +5326,9 @@ int peer_local_as_set(struct peer *peer, as_t as, int no_prepend,
struct bgp *bgp = peer->bgp;
struct peer *member;
struct listnode *node, *nnode;
+ bgp_peer_sort_t ptype = peer_sort(peer);
- if (peer_sort(peer) != BGP_PEER_EBGP
- && peer_sort(peer) != BGP_PEER_INTERNAL)
+ if (ptype != BGP_PEER_EBGP && ptype != BGP_PEER_INTERNAL)
return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
if (bgp->as == as)
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index d47ae71582..03d33130fe 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1351,6 +1351,7 @@ struct peer {
#define PEER_DOWN_NOAFI_ACTIVATED 30 /* No AFI/SAFI activated for peer */
#define PEER_DOWN_AS_SETS_REJECT 31 /* Reject routes with AS_SET */
#define PEER_DOWN_WAITING_OPEN 32 /* Waiting for open to succeed */
+#define PEER_DOWN_PFX_COUNT 33 /* Reached received prefix count */
/*
* Remember to update peer_down_str in bgp_fsm.c when you add
* a new value to the last_reset reason
@@ -1489,6 +1490,7 @@ struct bgp_nlri {
#define BGP_ORIGIN_IGP 0
#define BGP_ORIGIN_EGP 1
#define BGP_ORIGIN_INCOMPLETE 2
+#define BGP_ORIGIN_UNSPECIFIED 255
/* BGP notify message codes. */
#define BGP_NOTIFY_HEADER_ERR 1
@@ -1731,6 +1733,8 @@ extern struct peer *peer_unlock_with_caller(const char *, struct peer *);
#define peer_lock(B) peer_lock_with_caller(__FUNCTION__, (B))
extern bgp_peer_sort_t peer_sort(struct peer *peer);
+extern bgp_peer_sort_t peer_sort_lookup(struct peer *peer);
+
extern int peer_active(struct peer *);
extern int peer_active_nego(struct peer *);
extern void bgp_recalculate_all_bestpaths(struct bgp *bgp);
diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c
index 39d4b3ee29..b7ec35c661 100644
--- a/bgpd/rfapi/rfapi_rib.c
+++ b/bgpd/rfapi/rfapi_rib.c
@@ -2184,6 +2184,7 @@ void rfapiRibPendingDeleteRoute(struct bgp *bgp, struct rfapi_import_table *it,
rfapiRibUpdatePendingNode(
bgp, m->rfd, it, it_node,
m->rfd->response_lifetime);
+ agg_unlock_node(rn);
}
}
diff --git a/doc/developer/cli.rst b/doc/developer/cli.rst
index cf35b03f0c..12fcb7a325 100644
--- a/doc/developer/cli.rst
+++ b/doc/developer/cli.rst
@@ -371,11 +371,11 @@ Type rules
+----------------------------+--------------------------------+--------------------------+
| ``A.B.C.D + X:X::X:X`` | ``const union sockunion *`` | ``NULL`` |
+----------------------------+--------------------------------+--------------------------+
-| ``A.B.C.D/M`` | ``const struct prefix_ipv4 *`` | ``NULL`` |
+| ``A.B.C.D/M`` | ``const struct prefix_ipv4 *`` | ``all-zeroes struct`` |
+----------------------------+--------------------------------+--------------------------+
-| ``X:X::X:X/M`` | ``const struct prefix_ipv6 *`` | ``NULL`` |
+| ``X:X::X:X/M`` | ``const struct prefix_ipv6 *`` | ``all-zeroes struct`` |
+----------------------------+--------------------------------+--------------------------+
-| ``A.B.C.D/M + X:X::X:X/M`` | ``const struct prefix *`` | ``NULL`` |
+| ``A.B.C.D/M + X:X::X:X/M`` | ``const struct prefix *`` | ``all-zeroes struct`` |
+----------------------------+--------------------------------+--------------------------+
| ``(0-9)`` | ``long`` | ``0`` |
+----------------------------+--------------------------------+--------------------------+
@@ -395,8 +395,10 @@ Note the following details:
``word`` tokens (e.g. constant words). This is useful if some parts of a
command are optional. The type will be ``const char *``.
- ``[no]`` will be passed as ``const char *no``.
-- Pointers will be ``NULL`` when the argument is optional and the user did not
- use it.
+- Most pointers will be ``NULL`` when the argument is optional and the
+ user did not supply it. As noted in the table above, some prefix
+ struct type arguments are passed as pointers to all-zeroes structs,
+ not as ``NULL`` pointers.
- If a parameter is not a pointer, but is optional and the user didn't use it,
the default value will be passed. Check the ``_str`` argument if you need to
determine whether the parameter was omitted.
diff --git a/doc/developer/library.rst b/doc/developer/library.rst
index a904a4e778..3d5c6a2a15 100644
--- a/doc/developer/library.rst
+++ b/doc/developer/library.rst
@@ -15,5 +15,6 @@ Library Facilities (libfrr)
hooks
cli
modules
+ lua
diff --git a/doc/developer/lists.rst b/doc/developer/lists.rst
index 5f020060ce..853c65ddf3 100644
--- a/doc/developer/lists.rst
+++ b/doc/developer/lists.rst
@@ -1,3 +1,5 @@
+.. _lists:
+
List implementations
====================
diff --git a/doc/developer/locking.rst b/doc/developer/locking.rst
index aee05aae06..d698789f9f 100644
--- a/doc/developer/locking.rst
+++ b/doc/developer/locking.rst
@@ -1,3 +1,5 @@
+.. _locking:
+
Locking
=======
diff --git a/doc/developer/logging.rst b/doc/developer/logging.rst
index e393fe6fba..db577c9216 100644
--- a/doc/developer/logging.rst
+++ b/doc/developer/logging.rst
@@ -1,3 +1,5 @@
+.. _logging:
+
Developer's Guide to Logging
============================
diff --git a/doc/developer/lua.rst b/doc/developer/lua.rst
new file mode 100644
index 0000000000..23eb35fc58
--- /dev/null
+++ b/doc/developer/lua.rst
@@ -0,0 +1,65 @@
+.. _lua:
+
+Lua
+===
+
+Lua is currently experimental within FRR and has very limited
+support. If you would like to compile FRR with Lua you must
+follow these steps:
+
+1. Installation of Relevant Libraries
+
+ .. code-block:: shell
+
+ apt-get install lua5.3 liblua5-3 liblua5.3-dev
+
+ These are the Debian libraries that are needed. There should
+ be equivalent RPM's that can be found
+
+2. Compilation
+
+ Configure needs these options
+
+ .. code-block:: shell
+
+ ./configure --enable-dev-build --enable-lua <all other interesting options>
+
+ Typically you just include the two new enable lines to build with it.
+
+3. Using Lua
+
+ * Copy tools/lua.scr into /etc/frr
+
+ * Create a route-map match command
+
+ .. code-block:: console
+
+ !
+ router bgp 55
+ neighbor 10.50.11.116 remote-as external
+ address-family ipv4 unicast
+ neighbor 10.50.11.116 route-map TEST in
+ exit-address-family
+ !
+ route-map TEST permit 10
+ match command mooey
+ !
+
+ * In the lua.scr file make sure that you have a function named 'mooey'
+
+ .. code-block:: console
+
+ function mooey ()
+ zlog_debug(string.format("afi: %d: %s %d ifdx: %d aspath: %s localpref: %d",
+ prefix.family, prefix.route, nexthop.metric,
+ nexthop.ifindex, nexthop.aspath, nexthop.localpref))
+
+ nexthop.metric = 33
+ nexthop.localpref = 13
+ return 3
+ end
+
+4. General Comments
+
+ Please be aware that this is extremely experimental and needs a ton of work
+ to get this up into a state that is usable.
diff --git a/doc/developer/modules.rst b/doc/developer/modules.rst
index 763d8b1b8d..02330ddfe4 100644
--- a/doc/developer/modules.rst
+++ b/doc/developer/modules.rst
@@ -1,3 +1,5 @@
+.. _modules:
+
Modules
=======
diff --git a/doc/developer/static-linking.rst b/doc/developer/static-linking.rst
index bc33207b38..1e45c48dc3 100644
--- a/doc/developer/static-linking.rst
+++ b/doc/developer/static-linking.rst
@@ -10,7 +10,7 @@ likely to be present on a given platform - libfrr and libyang. The resultant
binaries should still be fairly portable. For example, here is the DSO
dependency list for `bgpd` after using these steps:
-.. code-block::
+.. code-block:: shell
$ ldd bgpd
linux-vdso.so.1 (0x00007ffe3a989000)
@@ -56,7 +56,7 @@ usable for our purposes. So download ``libpcre`` from
`SourceForge <https://sourceforge.net/projects/pcre/>`_, and build it
like this:
-.. code-block::
+.. code-block:: shell
./configure --with-pic
make
diff --git a/doc/developer/subdir.am b/doc/developer/subdir.am
index 791f7679a6..538a290c34 100644
--- a/doc/developer/subdir.am
+++ b/doc/developer/subdir.am
@@ -34,6 +34,7 @@ dev_RSTFILES = \
doc/developer/lists.rst \
doc/developer/locking.rst \
doc/developer/logging.rst \
+ doc/developer/lua.rst \
doc/developer/memtypes.rst \
doc/developer/modules.rst \
doc/developer/next-hop-tracking.rst \
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index fa84f6dc76..de690adb34 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -924,6 +924,11 @@ Route Aggregation-IPv4 Address Family
Apply a route-map for an aggregated prefix.
+.. index:: aggregate-address A.B.C.D/M origin <egp|igp|incomplete>
+.. clicmd:: aggregate-address A.B.C.D/M origin <egp|igp|incomplete>
+
+ Override ORIGIN for an aggregated prefix.
+
.. index:: aggregate-address A.B.C.D/M as-set
.. clicmd:: aggregate-address A.B.C.D/M as-set
@@ -971,6 +976,11 @@ Route Aggregation-IPv6 Address Family
Apply a route-map for an aggregated prefix.
+.. index:: aggregate-address X:X::X:X/M origin <egp|igp|incomplete>
+.. clicmd:: aggregate-address X:X::X:X/M origin <egp|igp|incomplete>
+
+ Override ORIGIN for an aggregated prefix.
+
.. index:: aggregate-address X:X::X:X/M as-set
.. clicmd:: aggregate-address X:X::X:X/M as-set
diff --git a/doc/user/overview.rst b/doc/user/overview.rst
index 262c0117df..2c8eadd4a7 100644
--- a/doc/user/overview.rst
+++ b/doc/user/overview.rst
@@ -292,6 +292,8 @@ BGP
:t:`BGP/MPLS IP Virtual Private Networks (VPNs). Y. Rekhter. Feb 2006.`
- :rfc:`4659`
:t:`BGP-MPLS IP Virtual Private Network (VPN) Extension for IPv6 VPN. J. De Clercq, D. Ooms, M. Carugi, F. Le Faucheur. September 2006.`
+- :rfc:`4893`
+ :t:`BGP Support for Four-octet AS Number Space. Q. Vohra, E. Chen May 2007.`
- :rfc:`5004`
:t:`Avoid BGP Best Path Transitions from One External to Another. E. Chen & S. Sangli. September 2007 (Partial support).`
- :rfc:`5082`
diff --git a/doc/user/pim.rst b/doc/user/pim.rst
index 6bda692607..9876216736 100644
--- a/doc/user/pim.rst
+++ b/doc/user/pim.rst
@@ -461,6 +461,18 @@ cause great confusion.
Display upstream information for S,G's and the RPF data associated with them.
+.. index:: show ip pim [vrf NAME] mlag upstream [A.B.C.D [A.B.C.D]] [json]
+.. clicmd:: show ip pim mlag upstream
+
+ Display upstream entries that are synced across MLAG switches.
+ Allow the user to specify sub Source and Groups address filters.
+
+.. index:: show ip pim mlag summary
+.. clicmd:: show ip pim mlag summary
+
+ Display PIM MLAG (multi-chassis link aggregation) session status and
+ control message statistics.
+
.. index:: show ip pim bsr
.. clicmd:: show ip pim bsr
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index 435639c291..8526b0f984 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -346,6 +346,27 @@ Route Map Exit Action Command
Proceed processing the route-map at the first entry whose order is >= N
+.. _route-map-optimization-command:
+
+Route Map Optimization Command
+==============================
+
+.. index:: route-map optimization
+.. clicmd:: route-map optimization
+
+ Enable route-map processing optimization. The optimization is
+ enabled by default.
+ Instead of sequentially passing through all the route-map indexes
+ until a match is found, the search for the best-match index will be
+ based on a look-up in a prefix-tree. A per-route-map prefix-tree
+ will be constructed for this purpose. The prefix-tree will compose
+ of all the prefixes in all the prefix-lists that are included in the
+ match rule of all the sequences of a route-map.
+
+.. index:: no route-map optimization
+.. clicmd:: no route-map optimization
+
+ Disable the route-map processing optimization.
Route Map Examples
==================
diff --git a/doc/user/vrrp.rst b/doc/user/vrrp.rst
index 435580131b..33582ee446 100644
--- a/doc/user/vrrp.rst
+++ b/doc/user/vrrp.rst
@@ -140,7 +140,7 @@ macvlan device. If you are using ``iproute2``, the equivalent configuration is:
ip link set dev vrrp4-2-1 up
ip link add vrrp6-2-1 link eth0 addrgenmode random type macvlan mode bridge
- ip link set dev vrrp4-2-1 address 00:00:5e:00:02:05
+ ip link set dev vrrp6-2-1 address 00:00:5e:00:02:05
ip addr add 2001:db8::370:7334/64 dev vrrp6-2-1
ip link set dev vrrp6-2-1 up
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index 8343f7d85f..e4152a8712 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -1386,7 +1386,6 @@ int isis_if_delete_hook(struct interface *ifp)
if (ifp && ifp->info) {
circuit = ifp->info;
isis_csm_state_change(IF_DOWN_FROM_Z, circuit, circuit->area);
- isis_csm_state_change(ISIS_DISABLE, circuit, circuit->area);
}
return 0;
diff --git a/ldpd/address.c b/ldpd/address.c
index 9c1564a31f..74a3f5a309 100644
--- a/ldpd/address.c
+++ b/ldpd/address.c
@@ -67,7 +67,7 @@ send_address(struct nbr *nbr, int af, struct if_addr_head *addr_list,
fatalx("send_address: unknown af");
}
- while ((if_addr = LIST_FIRST(addr_list)) != NULL) {
+ while (LIST_FIRST(addr_list) != NULL) {
/*
* Send as many addresses as possible - respect the session's
* negotiated maximum pdu length.
diff --git a/ldpd/ldp_zebra.c b/ldpd/ldp_zebra.c
index 946b51e4ee..b3ccb77602 100644
--- a/ldpd/ldp_zebra.c
+++ b/ldpd/ldp_zebra.c
@@ -106,7 +106,7 @@ static int
ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr)
{
struct zapi_labels zl = {};
- struct zapi_nexthop_label *znh;
+ struct zapi_nexthop *znh;
if (kr->local_label < MPLS_LABEL_RESERVED_MAX ||
kr->remote_label == NO_LABEL)
@@ -143,16 +143,14 @@ ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr)
znh = &zl.nexthops[0];
switch (kr->af) {
case AF_INET:
- znh->family = AF_INET;
- znh->address.ipv4 = kr->nexthop.v4;
+ znh->gate.ipv4 = kr->nexthop.v4;
if (kr->ifindex)
znh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
else
znh->type = NEXTHOP_TYPE_IPV4;
break;
case AF_INET6:
- znh->family = AF_INET6;
- znh->address.ipv6 = kr->nexthop.v6;
+ znh->gate.ipv6 = kr->nexthop.v6;
if (kr->ifindex)
znh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
else
@@ -162,7 +160,8 @@ ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr)
break;
}
znh->ifindex = kr->ifindex;
- znh->label = kr->remote_label;
+ znh->label_num = 1;
+ znh->labels[0] = kr->remote_label;
return zebra_send_mpls_labels(zclient, cmd, &zl);
}
diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c
index dcbcf8ce50..13de48fd70 100644
--- a/ldpd/ldpd.c
+++ b/ldpd/ldpd.c
@@ -858,7 +858,6 @@ ldp_acl_request(struct imsgev *iev, char *acl_name, int af,
union ldpd_addr *addr, uint8_t prefixlen)
{
struct imsg imsg;
- ssize_t n;
struct acl_check acl_check;
if (acl_name[0] == '\0')
@@ -876,9 +875,9 @@ ldp_acl_request(struct imsgev *iev, char *acl_name, int af,
imsg_flush(&iev->ibuf);
/* receive (blocking) and parse result */
- if ((n = imsg_read(&iev->ibuf)) == -1)
+ if (imsg_read(&iev->ibuf) == -1)
fatal("imsg_read error");
- if ((n = imsg_get(&iev->ibuf, &imsg)) == -1)
+ if (imsg_get(&iev->ibuf, &imsg) == -1)
fatal("imsg_get");
if (imsg.hdr.type != IMSG_ACL_CHECK ||
imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(int))
@@ -1408,7 +1407,7 @@ merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf)
RB_FOREACH_SAFE(iface, iface_head, &conf->iface_tree, itmp) {
/* find deleted interfaces */
- if ((xi = if_lookup_name(xconf, iface->name)) == NULL) {
+ if (if_lookup_name(xconf, iface->name) == NULL) {
switch (ldpd_process) {
case PROC_LDP_ENGINE:
ldpe_if_exit(iface);
@@ -1469,7 +1468,7 @@ merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf)
continue;
/* find deleted tnbrs */
- if ((xt = tnbr_find(xconf, tnbr->af, &tnbr->addr)) == NULL) {
+ if (tnbr_find(xconf, tnbr->af, &tnbr->addr) == NULL) {
switch (ldpd_process) {
case PROC_LDP_ENGINE:
tnbr->flags &= ~F_TNBR_CONFIGURED;
@@ -1515,33 +1514,35 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf)
RB_FOREACH_SAFE(nbrp, nbrp_head, &conf->nbrp_tree, ntmp) {
/* find deleted nbrps */
- if ((xn = nbr_params_find(xconf, nbrp->lsr_id)) == NULL) {
- switch (ldpd_process) {
- case PROC_LDP_ENGINE:
- nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr);
- if (nbr) {
- session_shutdown(nbr, S_SHUTDOWN, 0, 0);
+ if (nbr_params_find(xconf, nbrp->lsr_id) != NULL)
+ continue;
+
+ switch (ldpd_process) {
+ case PROC_LDP_ENGINE:
+ nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr);
+ if (nbr) {
+ session_shutdown(nbr, S_SHUTDOWN, 0, 0);
#ifdef __OpenBSD__
- pfkey_remove(nbr);
+ pfkey_remove(nbr);
#else
- sock_set_md5sig(
- (ldp_af_global_get(&global,
- nbr->af))->ldp_session_socket,
- nbr->af, &nbr->raddr, NULL);
+ sock_set_md5sig(
+ (ldp_af_global_get(&global, nbr->af))
+ ->ldp_session_socket,
+ nbr->af, &nbr->raddr, NULL);
#endif
- nbr->auth.method = AUTH_NONE;
- if (nbr_session_active_role(nbr))
- nbr_establish_connection(nbr);
- }
- break;
- case PROC_LDE_ENGINE:
- case PROC_MAIN:
- break;
+ nbr->auth.method = AUTH_NONE;
+ if (nbr_session_active_role(nbr))
+ nbr_establish_connection(nbr);
}
- RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
- free(nbrp);
+ break;
+ case PROC_LDE_ENGINE:
+ case PROC_MAIN:
+ break;
}
+ RB_REMOVE(nbrp_head, &conf->nbrp_tree, nbrp);
+ free(nbrp);
}
+
RB_FOREACH_SAFE(xn, nbrp_head, &xconf->nbrp_tree, ntmp) {
/* find new nbrps */
if ((nbrp = nbr_params_find(conf, xn->lsr_id)) == NULL) {
@@ -1624,7 +1625,7 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf)
RB_FOREACH_SAFE(l2vpn, l2vpn_head, &conf->l2vpn_tree, ltmp) {
/* find deleted l2vpns */
- if ((xl = l2vpn_find(xconf, l2vpn->name)) == NULL) {
+ if (l2vpn_find(xconf, l2vpn->name) == NULL) {
switch (ldpd_process) {
case PROC_LDE_ENGINE:
l2vpn_exit(l2vpn);
@@ -1680,7 +1681,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
/* merge intefaces */
RB_FOREACH_SAFE(lif, l2vpn_if_head, &l2vpn->if_tree, ftmp) {
/* find deleted interfaces */
- if ((xf = l2vpn_if_find(xl, lif->ifname)) == NULL) {
+ if (l2vpn_if_find(xl, lif->ifname) == NULL) {
RB_REMOVE(l2vpn_if_head, &l2vpn->if_tree, lif);
free(lif);
}
@@ -1706,7 +1707,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
/* merge active pseudowires */
RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_tree, ptmp) {
/* find deleted active pseudowires */
- if ((xp = l2vpn_pw_find_active(xl, pw->ifname)) == NULL) {
+ if (l2vpn_pw_find_active(xl, pw->ifname) == NULL) {
switch (ldpd_process) {
case PROC_LDE_ENGINE:
l2vpn_pw_exit(pw);
@@ -1807,7 +1808,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
/* merge inactive pseudowires */
RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree, ptmp) {
/* find deleted inactive pseudowires */
- if ((xp = l2vpn_pw_find_inactive(xl, pw->ifname)) == NULL) {
+ if (l2vpn_pw_find_inactive(xl, pw->ifname) == NULL) {
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
free(pw);
}
diff --git a/ldpd/socket.c b/ldpd/socket.c
index 8706d03c6f..997434620a 100644
--- a/ldpd/socket.c
+++ b/ldpd/socket.c
@@ -209,7 +209,7 @@ sock_set_nonblock(int fd)
flags |= O_NONBLOCK;
- if ((flags = fcntl(fd, F_SETFL, flags)) == -1)
+ if (fcntl(fd, F_SETFL, flags) == -1)
fatal("fcntl F_SETFL");
}
@@ -223,7 +223,7 @@ sock_set_cloexec(int fd)
flags |= FD_CLOEXEC;
- if ((flags = fcntl(fd, F_SETFD, flags)) == -1)
+ if (fcntl(fd, F_SETFD, flags) == -1)
fatal("fcntl F_SETFD");
}
diff --git a/lib/filter.c b/lib/filter.c
index 80f8cf0bd0..3226fb2f5e 100644
--- a/lib/filter.c
+++ b/lib/filter.c
@@ -412,7 +412,7 @@ static int64_t filter_new_seq_get(struct access_list *access)
int64_t newseq;
struct filter *filter;
- maxseq = newseq = 0;
+ maxseq = 0;
for (filter = access->head; filter; filter = filter->next) {
if (maxseq < filter->seq)
diff --git a/lib/if.c b/lib/if.c
index 0e9471923f..5edb58a2de 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -745,12 +745,16 @@ static void if_dump(const struct interface *ifp)
struct listnode *node;
struct connected *c __attribute__((unused));
- for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c))
+ for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, c)) {
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+
zlog_info(
- "Interface %s vrf %u index %d metric %d mtu %d "
+ "Interface %s vrf %s(%u) index %d metric %d mtu %d "
"mtu6 %d %s",
- ifp->name, ifp->vrf_id, ifp->ifindex, ifp->metric,
- ifp->mtu, ifp->mtu6, if_flag_dump(ifp->flags));
+ ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
+ ifp->metric, ifp->mtu, ifp->mtu6,
+ if_flag_dump(ifp->flags));
+ }
}
/* Interface printing for all interface. */
@@ -811,27 +815,25 @@ DEFUN (show_address,
"address\n"
VRF_CMD_HELP_STR)
{
- int idx_vrf = 3;
- struct listnode *node;
- struct interface *ifp;
- struct connected *ifc;
- struct prefix *p;
- vrf_id_t vrf_id = VRF_DEFAULT;
+ int idx_vrf = 3;
+ struct listnode *node;
+ struct interface *ifp;
+ struct connected *ifc;
+ struct prefix *p;
+ vrf_id_t vrf_id = VRF_DEFAULT;
- if (argc > 2)
- VRF_GET_ID (vrf_id, argv[idx_vrf]->arg);
+ if (argc > 2)
+ VRF_GET_ID (vrf_id, argv[idx_vrf]->arg);
- FOR_ALL_INTERFACES (vrf, ifp)
- {
- for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
- {
- p = ifc->address;
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) {
+ p = ifc->address;
- if (p->family == AF_INET)
- vty_out (vty, "%s/%d\n", inet_ntoa (p->u.prefix4), p->prefixlen);
+ if (p->family == AF_INET)
+ vty_out (vty, "%s/%d\n", inet_ntoa (p->u.prefix4), p->prefixlen);
+ }
}
- }
- return CMD_SUCCESS;
+ return CMD_SUCCESS;
}
DEFUN (show_address_vrf_all,
@@ -841,31 +843,30 @@ DEFUN (show_address_vrf_all,
"address\n"
VRF_ALL_CMD_HELP_STR)
{
- struct vrf *vrf;
- struct listnode *node;
- struct interface *ifp;
- struct connected *ifc;
- struct prefix *p;
+ struct vrf *vrf;
+ struct listnode *node;
+ struct interface *ifp;
+ struct connected *ifc;
+ struct prefix *p;
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
- {
- if (RB_EMPTY (if_name_head, &vrf->ifaces_by_name))
- continue;
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
+ {
+ if (RB_EMPTY (if_name_head, &vrf->ifaces_by_name))
+ continue;
- vty_out (vty, "\nVRF %u\n\n", vrf->vrf_id);
+ vty_out (vty, "\nVRF %s(%u)\n\n",
+ VRF_LOGNAME(vrf), vrf->vrf_id);
- FOR_ALL_INTERFACES (vrf, ifp)
- {
- for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc))
- {
- p = ifc->address;
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) {
+ p = ifc->address;
- if (p->family == AF_INET)
- vty_out (vty, "%s/%d\n", inet_ntoa (p->u.prefix4), p->prefixlen);
- }
- }
- }
- return CMD_SUCCESS;
+ if (p->family == AF_INET)
+ vty_out (vty, "%s/%d\n", inet_ntoa (p->u.prefix4), p->prefixlen);
+ }
+ }
+ }
+ return CMD_SUCCESS;
}
#endif
@@ -927,14 +928,16 @@ connected_log(struct connected *connected, char *str)
{
struct prefix *p;
struct interface *ifp;
+ struct vrf *vrf;
char logbuf[BUFSIZ];
char buf[BUFSIZ];
ifp = connected->ifp;
p = connected->address;
- snprintf(logbuf, BUFSIZ, "%s interface %s vrf %u %s %s/%d ", str,
- ifp->name, ifp->vrf_id, prefix_family_str(p),
+ vrf = vrf_lookup_by_id(ifp->vrf_id);
+ snprintf(logbuf, BUFSIZ, "%s interface %s vrf %s(%u) %s %s/%d ", str,
+ ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, prefix_family_str(p),
inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen);
p = connected->destination;
diff --git a/lib/ipaddr.h b/lib/ipaddr.h
index 6bd614044c..c6372f1abb 100644
--- a/lib/ipaddr.h
+++ b/lib/ipaddr.h
@@ -119,10 +119,13 @@ static inline void ipv4_mapped_ipv6_to_ipv4(struct in6_addr *in6,
memcpy(in, (char *)in6 + 12, sizeof(struct in_addr));
}
+/*
+ * Check if a struct ipaddr has nonzero value
+ */
static inline bool ipaddr_isset(struct ipaddr *ip)
{
static struct ipaddr a = {};
- return (0 == memcmp(&a, ip, sizeof(struct ipaddr)));
+ return (0 != memcmp(&a, ip, sizeof(struct ipaddr)));
}
#ifdef __cplusplus
diff --git a/lib/log.c b/lib/log.c
index 7bf16a8212..5240eeaf72 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -1092,6 +1092,11 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_VXLAN_SG_ADD),
DESC_ENTRY(ZEBRA_VXLAN_SG_DEL),
DESC_ENTRY(ZEBRA_VXLAN_SG_REPLAY),
+ DESC_ENTRY(ZEBRA_MLAG_PROCESS_UP),
+ DESC_ENTRY(ZEBRA_MLAG_PROCESS_DOWN),
+ DESC_ENTRY(ZEBRA_MLAG_CLIENT_REGISTER),
+ DESC_ENTRY(ZEBRA_MLAG_CLIENT_UNREGISTER),
+ DESC_ENTRY(ZEBRA_MLAG_FORWARD_MSG),
DESC_ENTRY(ZEBRA_ERROR),
DESC_ENTRY(ZEBRA_CLIENT_CAPABILITIES)};
#undef DESC_ENTRY
diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c
index 3005a51c71..d660428bcd 100644
--- a/lib/nexthop_group.c
+++ b/lib/nexthop_group.c
@@ -216,7 +216,8 @@ struct nexthop_group *nexthop_group_new(void)
return XCALLOC(MTYPE_NEXTHOP_GROUP, sizeof(struct nexthop_group));
}
-void nexthop_group_copy(struct nexthop_group *to, struct nexthop_group *from)
+void nexthop_group_copy(struct nexthop_group *to,
+ const struct nexthop_group *from)
{
/* Copy everything, including recursive info */
copy_nexthops(&to->nexthop, from->nexthop, NULL);
diff --git a/lib/nexthop_group.h b/lib/nexthop_group.h
index 73b020283a..f99a53f694 100644
--- a/lib/nexthop_group.h
+++ b/lib/nexthop_group.h
@@ -43,7 +43,7 @@ struct nexthop_group *nexthop_group_new(void);
void nexthop_group_delete(struct nexthop_group **nhg);
void nexthop_group_copy(struct nexthop_group *to,
- struct nexthop_group *from);
+ const struct nexthop_group *from);
/*
* Copy a list of nexthops in 'nh' to an nhg, enforcing canonical sort order
diff --git a/lib/plist.c b/lib/plist.c
index 662221beec..e465963f21 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -303,6 +303,8 @@ static void prefix_list_delete(struct prefix_list *plist)
/* If prefix-list contain prefix_list_entry free all of it. */
for (pentry = plist->head; pentry; pentry = next) {
+ route_map_notify_pentry_dependencies(plist->name, pentry,
+ RMAP_EVENT_PLIST_DELETED);
next = pentry->next;
prefix_list_trie_del(plist, pentry);
prefix_list_entry_free(pentry);
@@ -385,7 +387,7 @@ static int64_t prefix_new_seq_get(struct prefix_list *plist)
int64_t newseq;
struct prefix_list_entry *pentry;
- maxseq = newseq = 0;
+ maxseq = 0;
for (pentry = plist->head; pentry; pentry = pentry->next) {
if (maxseq < pentry->seq)
@@ -518,6 +520,8 @@ static void prefix_list_entry_delete(struct prefix_list *plist,
else
plist->tail = pentry->prev;
+ route_map_notify_pentry_dependencies(plist->name, pentry,
+ RMAP_EVENT_PLIST_DELETED);
prefix_list_entry_free(pentry);
plist->count--;
@@ -631,6 +635,9 @@ static void prefix_list_entry_add(struct prefix_list *plist,
/* Increment count. */
plist->count++;
+ route_map_notify_pentry_dependencies(plist->name, pentry,
+ RMAP_EVENT_PLIST_ADDED);
+
/* Run hook function. */
if (plist->master->add_hook)
(*plist->master->add_hook)(plist);
diff --git a/lib/routemap.c b/lib/routemap.c
index 0d5621d90e..54b5383173 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -31,6 +31,7 @@
#include "hash.h"
#include "libfrr.h"
#include "lib_errors.h"
+#include "table.h"
DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP, "Route map")
DEFINE_MTYPE(LIB, ROUTE_MAP_NAME, "Route map name")
@@ -44,12 +45,52 @@ DEFINE_MTYPE_STATIC(LIB, ROUTE_MAP_DEP_DATA, "Route map dependency data")
DEFINE_QOBJ_TYPE(route_map_index)
DEFINE_QOBJ_TYPE(route_map)
+#define IPv4_PREFIX_LIST "ip address prefix-list"
+#define IPv6_PREFIX_LIST "ipv6 address prefix-list"
+#define IPv4_MATCH_RULE "ip "
+#define IPv6_MATCH_RULE "ipv6 "
+
+#define IS_RULE_IPv4_PREFIX_LIST(S) \
+ (strncmp(S, IPv4_PREFIX_LIST, strlen(IPv4_PREFIX_LIST)) == 0)
+#define IS_RULE_IPv6_PREFIX_LIST(S) \
+ (strncmp(S, IPv6_PREFIX_LIST, strlen(IPv6_PREFIX_LIST)) == 0)
+
+#define IS_IPv4_RULE(S) \
+ (strncmp(S, IPv4_MATCH_RULE, strlen(IPv4_MATCH_RULE)) == 0)
+#define IS_IPv6_RULE(S) \
+ (strncmp(S, IPv6_MATCH_RULE, strlen(IPv6_MATCH_RULE)) == 0)
+struct route_map_pentry_dep {
+ struct prefix_list_entry *pentry;
+ const char *plist_name;
+ route_map_event_t event;
+};
+
/* Vector for route match rules. */
static vector route_match_vec;
/* Vector for route set rules. */
static vector route_set_vec;
+static void route_map_pfx_tbl_update(route_map_event_t event,
+ struct route_map_index *index, afi_t afi,
+ const char *plist_name);
+static void route_map_pfx_table_add_default(afi_t afi,
+ struct route_map_index *index);
+static void route_map_pfx_table_del_default(afi_t afi,
+ struct route_map_index *index);
+static void route_map_add_plist_entries(afi_t afi,
+ struct route_map_index *index,
+ const char *plist_name,
+ struct prefix_list_entry *entry);
+static void route_map_del_plist_entries(afi_t afi,
+ struct route_map_index *index,
+ const char *plist_name,
+ struct prefix_list_entry *entry);
+static bool route_map_is_ip_rule_present(struct route_map_index *index);
+static bool route_map_is_ipv6_rule_present(struct route_map_index *index);
+
+static struct hash *route_map_get_dep_hash(route_map_event_t event);
+
struct route_map_match_set_hooks rmap_match_set_hook;
/* match interface */
@@ -566,6 +607,12 @@ static struct route_map *route_map_add(const char *name)
route_map_notify_dependencies(name, RMAP_EVENT_CALL_ADDED);
}
+ if (!map->ipv4_prefix_table)
+ map->ipv4_prefix_table = route_table_init();
+
+ if (!map->ipv6_prefix_table)
+ map->ipv6_prefix_table = route_table_init();
+
if (rmap_debug)
zlog_debug("Add route-map %s", name);
return map;
@@ -786,8 +833,9 @@ static void vty_show_route_map_entry(struct vty *vty, struct route_map *map)
struct route_map_index *index;
struct route_map_rule *rule;
- vty_out(vty, "route-map: %s Invoked: %" PRIu64 "\n",
- map->name, map->applied - map->applied_clear);
+ vty_out(vty, "route-map: %s Invoked: %" PRIu64 " Optimization: %s\n",
+ map->name, map->applied - map->applied_clear,
+ map->optimization_disabled ? "disabled" : "enabled");
for (index = map->head; index; index = index->next) {
vty_out(vty, " %s, sequence %d Invoked %" PRIu64 "\n",
@@ -914,6 +962,7 @@ static struct route_map_index *route_map_index_new(void)
/* Free route map index. */
void route_map_index_delete(struct route_map_index *index, int notify)
{
+ struct routemap_hook_context *rhc;
struct route_map_rule *rule;
QOBJ_UNREG(index);
@@ -923,12 +972,21 @@ void route_map_index_delete(struct route_map_index *index, int notify)
index->map->name, index->pref);
/* Free route map northbound hook contexts. */
- while (!TAILQ_EMPTY(&index->rhclist))
- routemap_hook_context_free(TAILQ_FIRST(&index->rhclist));
+ while ((rhc = TAILQ_FIRST(&index->rhclist)) != NULL)
+ routemap_hook_context_free(rhc);
/* Free route match. */
- while ((rule = index->match_list.head) != NULL)
+ while ((rule = index->match_list.head) != NULL) {
+ if (IS_RULE_IPv4_PREFIX_LIST(rule->cmd->str))
+ route_map_pfx_tbl_update(RMAP_EVENT_PLIST_DELETED,
+ index, AFI_IP, rule->rule_str);
+ else if (IS_RULE_IPv6_PREFIX_LIST(rule->cmd->str))
+ route_map_pfx_tbl_update(RMAP_EVENT_PLIST_DELETED,
+ index, AFI_IP6,
+ rule->rule_str);
+
route_map_rule_delete(&index->match_list, rule);
+ }
/* Free route set. */
while ((rule = index->set_list.head) != NULL)
@@ -948,6 +1006,8 @@ void route_map_index_delete(struct route_map_index *index, int notify)
/* Free 'char *nextrm' if not NULL */
XFREE(MTYPE_ROUTE_MAP_NAME, index->nextrm);
+ route_map_pfx_tbl_update(RMAP_EVENT_INDEX_DELETED, index, 0, NULL);
+
/* Execute event hook. */
if (route_map_master.event_hook && notify) {
(*route_map_master.event_hook)(index->map->name);
@@ -1007,6 +1067,8 @@ route_map_index_add(struct route_map *map, enum route_map_type type, int pref)
point->prev = index;
}
+ route_map_pfx_tbl_update(RMAP_EVENT_INDEX_ADDED, index, 0, NULL);
+
/* Execute event hook. */
if (route_map_master.event_hook) {
(*route_map_master.event_hook)(map->name);
@@ -1254,6 +1316,19 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
return RMAP_COMPILE_SUCCESS;
}
+ /* If IPv4 or IPv6 prefix-list match criteria
+ * has been delete to the route-map index, update
+ * the route-map's prefix table.
+ */
+ if (IS_RULE_IPv4_PREFIX_LIST(match_name))
+ route_map_pfx_tbl_update(
+ RMAP_EVENT_PLIST_DELETED, index, AFI_IP,
+ rule->rule_str);
+ else if (IS_RULE_IPv6_PREFIX_LIST(match_name))
+ route_map_pfx_tbl_update(
+ RMAP_EVENT_PLIST_DELETED, index,
+ AFI_IP6, rule->rule_str);
+
/* Remove the dependency of the route-map on the rule
* that is being replaced.
*/
@@ -1282,6 +1357,38 @@ enum rmap_compile_rets route_map_add_match(struct route_map_index *index,
/* Add new route match rule to linked list. */
route_map_rule_add(&index->match_list, rule);
+ /* If IPv4 or IPv6 prefix-list match criteria
+ * has been added to the route-map index, update
+ * the route-map's prefix table.
+ */
+ if (IS_RULE_IPv4_PREFIX_LIST(match_name)) {
+ route_map_pfx_tbl_update(RMAP_EVENT_PLIST_ADDED, index, AFI_IP,
+ match_arg);
+ } else if (IS_RULE_IPv6_PREFIX_LIST(match_name)) {
+ route_map_pfx_tbl_update(RMAP_EVENT_PLIST_ADDED, index, AFI_IP6,
+ match_arg);
+ } else {
+ /* If IPv4 match criteria has been added to the route-map
+ * index, check for IPv6 prefix-list match rule presence and
+ * remove this index from the trie node created for each of the
+ * prefix-entry within the prefix-list. If no IPv6 prefix-list
+ * match rule is present, remove this index from the IPv6
+ * default route's trie node.
+ */
+ if (IS_IPv4_RULE(match_name))
+ route_map_del_plist_entries(AFI_IP6, index, NULL, NULL);
+
+ /* If IPv6 match criteria has been added to the route-map
+ * index, check for IPv4 prefix-list match rule presence and
+ * remove this index from the trie node created for each of the
+ * prefix-entry within the prefix-list. If no IPv4 prefix-list
+ * match rule is present, remove this index from the IPv4
+ * default route's trie node.
+ */
+ else if (IS_IPv6_RULE(match_name))
+ route_map_del_plist_entries(AFI_IP, index, NULL, NULL);
+ }
+
/* Execute event hook. */
if (route_map_master.event_hook) {
(*route_map_master.event_hook)(index->map->name);
@@ -1329,6 +1436,45 @@ enum rmap_compile_rets route_map_delete_match(struct route_map_index *index,
index->map->name);
route_map_rule_delete(&index->match_list, rule);
+
+ /* If IPv4 or IPv6 prefix-list match criteria
+ * has been delete to the route-map index, update
+ * the route-map's prefix table.
+ */
+ if (IS_RULE_IPv4_PREFIX_LIST(match_name)) {
+ route_map_pfx_tbl_update(
+ RMAP_EVENT_PLIST_DELETED, index, AFI_IP,
+ match_arg);
+ } else if (IS_RULE_IPv6_PREFIX_LIST(match_name)) {
+ route_map_pfx_tbl_update(
+ RMAP_EVENT_PLIST_DELETED, index,
+ AFI_IP6, match_arg);
+ } else {
+ /* If no more IPv4 match rules are present in
+ * this index, check for IPv6 prefix-list match
+ * rule presence and add this index to trie node
+ * created for each of the prefix-entry within
+ * the prefix-list. If no IPv6 prefix-list match
+ * rule is present, add this index to the IPv6
+ * default route's trie node.
+ */
+ if (!route_map_is_ip_rule_present(index))
+ route_map_add_plist_entries(
+ AFI_IP6, index, NULL, NULL);
+
+ /* If no more IPv6 match rules are present in
+ * this index, check for IPv4 prefix-list match
+ * rule presence and add this index to trie node
+ * created for each of the prefix-entry within
+ * the prefix-list. If no IPv6 prefix-list match
+ * rule is present, add this index to the IPv4
+ * default route's trie node.
+ */
+ if (!route_map_is_ipv6_rule_present(index))
+ route_map_add_plist_entries(
+ AFI_IP, index, NULL, NULL);
+ }
+
return RMAP_COMPILE_SUCCESS;
}
/* Can't find matched rule. */
@@ -1494,6 +1640,705 @@ route_map_apply_match(struct route_map_rule_list *match_list,
return ret;
}
+static struct list *route_map_get_index_list(struct route_node **rn,
+ const struct prefix *prefix,
+ struct route_table *table)
+{
+ struct route_node *tmp_rn = NULL;
+
+ if (!(*rn)) {
+ *rn = route_node_match(table, prefix);
+
+ if (!(*rn))
+ return NULL;
+
+ if ((*rn)->info)
+ return (struct list *)((*rn)->info);
+
+ /* If rn->info is NULL, get the parent.
+ * Store the rn in tmp_rn and unlock it later.
+ */
+ tmp_rn = *rn;
+ }
+
+ do {
+ *rn = (*rn)->parent;
+ if (tmp_rn)
+ route_unlock_node(tmp_rn);
+
+ if (!(*rn))
+ break;
+
+ if ((*rn)->info) {
+ route_lock_node(*rn);
+ return (struct list *)((*rn)->info);
+ }
+ } while (!(*rn)->info);
+
+ return NULL;
+}
+
+/*
+ * This function returns the route-map index that best matches the prefix.
+ */
+static struct route_map_index *
+route_map_get_index(struct route_map *map, const struct prefix *prefix,
+ route_map_object_t type, void *object, uint8_t *match_ret)
+{
+ int ret = 0;
+ struct list *candidate_rmap_list = NULL;
+ struct route_node *rn = NULL;
+ struct listnode *ln = NULL, *nn = NULL;
+ struct route_map_index *index = NULL, *best_index = NULL;
+ struct route_map_index *head_index = NULL;
+ struct route_table *table = NULL;
+ unsigned char family = prefix->family;
+
+ if (family == AF_INET)
+ table = map->ipv4_prefix_table;
+ else
+ table = map->ipv6_prefix_table;
+
+ if (!table)
+ return NULL;
+
+ do {
+ candidate_rmap_list =
+ route_map_get_index_list(&rn, prefix, table);
+ if (!rn)
+ break;
+
+ /* If the index at the head of the list is of seq higher
+ * than that in best_index, ignore the list and get the
+ * parent node's list.
+ */
+ head_index = (struct route_map_index *)(listgetdata(
+ listhead(candidate_rmap_list)));
+ if (best_index && head_index
+ && (best_index->pref < head_index->pref)) {
+ route_unlock_node(rn);
+ continue;
+ }
+
+ for (ALL_LIST_ELEMENTS(candidate_rmap_list, ln, nn, index)) {
+ /* If the index is of seq higher than that in
+ * best_index, ignore the list and get the parent
+ * node's list.
+ */
+ if (best_index && (best_index->pref < index->pref))
+ break;
+
+ ret = route_map_apply_match(&index->match_list, prefix,
+ type, object);
+
+ if (ret == RMAP_MATCH) {
+ *match_ret = ret;
+ best_index = index;
+ break;
+ } else if (ret == RMAP_NOOP) {
+ /*
+ * If match_ret is denymatch, even if we see
+ * more noops, we retain this return value and
+ * return this eventually if there are no
+ * matches.
+ */
+ if (*match_ret != RMAP_NOMATCH)
+ *match_ret = ret;
+ } else {
+ /*
+ * ret is RMAP_NOMATCH.
+ */
+ *match_ret = ret;
+ }
+ }
+
+ route_unlock_node(rn);
+
+ } while (rn);
+
+ return best_index;
+}
+
+static int route_map_candidate_list_cmp(struct route_map_index *idx1,
+ struct route_map_index *idx2)
+{
+ if (!idx1)
+ return -1;
+ if (!idx2)
+ return 1;
+
+ return (idx1->pref - idx2->pref);
+}
+
+/*
+ * This function adds the route-map index into the default route's
+ * route-node in the route-map's IPv4/IPv6 prefix-table.
+ */
+static void route_map_pfx_table_add_default(afi_t afi,
+ struct route_map_index *index)
+{
+ struct route_node *rn = NULL;
+ struct list *rmap_candidate_list = NULL;
+ struct prefix p;
+ bool updated_rn = false;
+ struct route_table *table = NULL;
+
+ memset(&p, 0, sizeof(p));
+ p.family = afi2family(afi);
+ p.prefixlen = 0;
+
+ if (p.family == AF_INET) {
+ table = index->map->ipv4_prefix_table;
+ if (!table)
+ index->map->ipv4_prefix_table = route_table_init();
+
+ table = index->map->ipv4_prefix_table;
+ } else {
+ table = index->map->ipv6_prefix_table;
+ if (!table)
+ index->map->ipv6_prefix_table = route_table_init();
+
+ table = index->map->ipv6_prefix_table;
+ }
+
+ /* Add default route to table */
+ rn = route_node_get(table, &p);
+
+ if (!rn)
+ return;
+
+ if (!rn->info) {
+ rmap_candidate_list = list_new();
+ rmap_candidate_list->cmp =
+ (int (*)(void *, void *))route_map_candidate_list_cmp;
+ rn->info = rmap_candidate_list;
+ } else {
+ rmap_candidate_list = (struct list *)rn->info;
+ updated_rn = true;
+ }
+
+ listnode_add_sort_nodup(rmap_candidate_list, index);
+ if (updated_rn)
+ route_unlock_node(rn);
+}
+
+/*
+ * This function removes the route-map index from the default route's
+ * route-node in the route-map's IPv4/IPv6 prefix-table.
+ */
+static void route_map_pfx_table_del_default(afi_t afi,
+ struct route_map_index *index)
+{
+ struct route_node *rn = NULL;
+ struct list *rmap_candidate_list = NULL;
+ struct prefix p;
+ struct route_table *table = NULL;
+
+ memset(&p, 0, sizeof(p));
+ p.family = afi2family(afi);
+ p.prefixlen = 0;
+
+ if (p.family == AF_INET)
+ table = index->map->ipv4_prefix_table;
+ else
+ table = index->map->ipv6_prefix_table;
+
+ /* Remove RMAP index from default route in table */
+ rn = route_node_lookup(table, &p);
+ if (!rn || !rn->info)
+ return;
+
+ rmap_candidate_list = (struct list *)rn->info;
+
+ listnode_delete(rmap_candidate_list, index);
+
+ if (listcount(rmap_candidate_list) == 0) {
+ list_delete(&rmap_candidate_list);
+ rn->info = NULL;
+ route_unlock_node(rn);
+ }
+ route_unlock_node(rn);
+}
+
+/*
+ * This function adds the route-map index to the route-node for
+ * the prefix-entry in the route-map's IPv4/IPv6 prefix-table.
+ */
+static void route_map_pfx_table_add(struct route_table *table,
+ struct route_map_index *index,
+ struct prefix_list_entry *pentry)
+{
+ struct route_node *rn = NULL;
+ struct list *rmap_candidate_list = NULL;
+ bool updated_rn = false;
+
+ rn = route_node_get(table, &pentry->prefix);
+ if (!rn)
+ return;
+
+ if (!rn->info) {
+ rmap_candidate_list = list_new();
+ rmap_candidate_list->cmp =
+ (int (*)(void *, void *))route_map_candidate_list_cmp;
+ rn->info = rmap_candidate_list;
+ } else {
+ rmap_candidate_list = (struct list *)rn->info;
+ updated_rn = true;
+ }
+
+ listnode_add_sort_nodup(rmap_candidate_list, index);
+ if (updated_rn)
+ route_unlock_node(rn);
+}
+
+/*
+ * This function removes the route-map index from the route-node for
+ * the prefix-entry in the route-map's IPv4/IPv6 prefix-table.
+ */
+static void route_map_pfx_table_del(struct route_table *table,
+ struct route_map_index *index,
+ struct prefix_list_entry *pentry)
+{
+ struct route_node *rn = NULL;
+ struct list *rmap_candidate_list = NULL;
+
+ rn = route_node_lookup(table, &pentry->prefix);
+ if (!rn || !rn->info)
+ return;
+
+ rmap_candidate_list = (struct list *)rn->info;
+
+ listnode_delete(rmap_candidate_list, index);
+
+ if (listcount(rmap_candidate_list) == 0) {
+ list_delete(&rmap_candidate_list);
+ rn->info = NULL;
+ route_unlock_node(rn);
+ }
+ route_unlock_node(rn);
+}
+
+/* This function checks for the presence of an IPv4 match rule
+ * in the given route-map index.
+ */
+static bool route_map_is_ip_rule_present(struct route_map_index *index)
+{
+ struct route_map_rule_list *match_list = NULL;
+ struct route_map_rule *rule = NULL;
+
+ match_list = &index->match_list;
+ for (rule = match_list->head; rule; rule = rule->next)
+ if (IS_IPv4_RULE(rule->cmd->str))
+ return true;
+
+ return false;
+}
+
+/* This function checks for the presence of an IPv6 match rule
+ * in the given route-map index.
+ */
+static bool route_map_is_ipv6_rule_present(struct route_map_index *index)
+{
+ struct route_map_rule_list *match_list = NULL;
+ struct route_map_rule *rule = NULL;
+
+ match_list = &index->match_list;
+ for (rule = match_list->head; rule; rule = rule->next)
+ if (IS_IPv6_RULE(rule->cmd->str))
+ return true;
+
+ return false;
+}
+
+/* This function does the following:
+ * 1) If plist_name is not present, search for a IPv4 or IPv6 prefix-list
+ * match clause (based on the afi passed to this foo) and get the
+ * prefix-list name.
+ * 2) Look up the prefix-list using the name.
+ * 3) If the prefix-list is not found then, add the index to the IPv4/IPv6
+ * default-route's node in the trie (based on the afi passed to this foo).
+ * 4) If the prefix-list is found then, remove the index from the IPv4/IPv6
+ * default-route's node in the trie (based on the afi passed to this foo).
+ * 5) If a prefix-entry is passed then, create a route-node for this entry and
+ * add this index to the route-node.
+ * 6) If prefix-entry is not passed then, for every prefix-entry in the
+ * prefix-list, create a route-node for this entry and
+ * add this index to the route-node.
+ */
+static void route_map_add_plist_entries(afi_t afi,
+ struct route_map_index *index,
+ const char *plist_name,
+ struct prefix_list_entry *entry)
+{
+ struct route_map_rule_list *match_list = NULL;
+ struct route_map_rule *match = NULL;
+ struct prefix_list *plist = NULL;
+ struct prefix_list_entry *pentry = NULL;
+ bool plist_rule_is_present = false;
+
+ if (!plist_name) {
+ match_list = &index->match_list;
+
+ for (match = match_list->head; match; match = match->next) {
+ if (afi == AFI_IP) {
+ if (IS_RULE_IPv4_PREFIX_LIST(match->cmd->str)) {
+ plist_rule_is_present = true;
+ break;
+ }
+ } else {
+ if (IS_RULE_IPv6_PREFIX_LIST(match->cmd->str)) {
+ plist_rule_is_present = true;
+ break;
+ }
+ }
+ }
+
+ if (plist_rule_is_present)
+ plist = prefix_list_lookup(afi, match->rule_str);
+ } else {
+ plist = prefix_list_lookup(afi, plist_name);
+ }
+
+ if (!plist) {
+ route_map_pfx_table_add_default(afi, index);
+ return;
+ }
+
+ route_map_pfx_table_del_default(afi, index);
+
+ if (entry) {
+ if (afi == AFI_IP) {
+ route_map_pfx_table_add(index->map->ipv4_prefix_table,
+ index, entry);
+ } else {
+ route_map_pfx_table_add(index->map->ipv6_prefix_table,
+ index, entry);
+ }
+ } else {
+ for (pentry = plist->head; pentry; pentry = pentry->next) {
+ if (afi == AFI_IP) {
+ route_map_pfx_table_add(
+ index->map->ipv4_prefix_table, index,
+ pentry);
+ } else {
+ route_map_pfx_table_add(
+ index->map->ipv6_prefix_table, index,
+ pentry);
+ }
+ }
+ }
+}
+
+/* This function does the following:
+ * 1) If plist_name is not present, search for a IPv4 or IPv6 prefix-list
+ * match clause (based on the afi passed to this foo) and get the
+ * prefix-list name.
+ * 2) Look up the prefix-list using the name.
+ * 3) If the prefix-list is not found then, delete the index from the IPv4/IPv6
+ * default-route's node in the trie (based on the afi passed to this foo).
+ * 4) If a prefix-entry is passed then, remove this index from the route-node
+ * for the prefix in this prefix-entry.
+ * 5) If prefix-entry is not passed then, for every prefix-entry in the
+ * prefix-list, remove this index from the route-node
+ * for the prefix in this prefix-entry.
+ */
+static void route_map_del_plist_entries(afi_t afi,
+ struct route_map_index *index,
+ const char *plist_name,
+ struct prefix_list_entry *entry)
+{
+ struct route_map_rule_list *match_list = NULL;
+ struct route_map_rule *match = NULL;
+ struct prefix_list *plist = NULL;
+ struct prefix_list_entry *pentry = NULL;
+ bool plist_rule_is_present = false;
+
+ if (!plist_name) {
+ match_list = &index->match_list;
+
+ for (match = match_list->head; match; match = match->next) {
+ if (afi == AFI_IP) {
+ if (IS_RULE_IPv4_PREFIX_LIST(match->cmd->str)) {
+ plist_rule_is_present = true;
+ break;
+ }
+ } else {
+ if (IS_RULE_IPv6_PREFIX_LIST(match->cmd->str)) {
+ plist_rule_is_present = true;
+ break;
+ }
+ }
+ }
+
+ if (plist_rule_is_present)
+ plist = prefix_list_lookup(afi, match->rule_str);
+ } else {
+ plist = prefix_list_lookup(afi, plist_name);
+ }
+
+ if (!plist) {
+ route_map_pfx_table_del_default(afi, index);
+ return;
+ }
+
+ if (entry) {
+ if (afi == AFI_IP) {
+ route_map_pfx_table_del(index->map->ipv4_prefix_table,
+ index, entry);
+ } else {
+ route_map_pfx_table_del(index->map->ipv6_prefix_table,
+ index, entry);
+ }
+ } else {
+ for (pentry = plist->head; pentry; pentry = pentry->next) {
+ if (afi == AFI_IP) {
+ route_map_pfx_table_del(
+ index->map->ipv4_prefix_table, index,
+ pentry);
+ } else {
+ route_map_pfx_table_del(
+ index->map->ipv6_prefix_table, index,
+ pentry);
+ }
+ }
+ }
+}
+
+/*
+ * This function handles the cases where a prefix-list is added/removed
+ * as a match command from a particular route-map index.
+ * It updates the prefix-table of the route-map accordingly.
+ */
+static void route_map_trie_update(afi_t afi, route_map_event_t event,
+ struct route_map_index *index,
+ const char *plist_name)
+{
+ if (event == RMAP_EVENT_PLIST_ADDED) {
+ if (afi == AFI_IP) {
+ if (!route_map_is_ipv6_rule_present(index)) {
+ route_map_pfx_table_del_default(AFI_IP6, index);
+ route_map_add_plist_entries(afi, index,
+ plist_name, NULL);
+ } else {
+ route_map_del_plist_entries(AFI_IP6, index,
+ NULL, NULL);
+ }
+ } else {
+ if (!route_map_is_ip_rule_present(index)) {
+ route_map_pfx_table_del_default(AFI_IP, index);
+ route_map_add_plist_entries(afi, index,
+ plist_name, NULL);
+ } else {
+ route_map_del_plist_entries(AFI_IP, index, NULL,
+ NULL);
+ }
+ }
+ } else if (event == RMAP_EVENT_PLIST_DELETED) {
+ if (afi == AFI_IP) {
+ route_map_del_plist_entries(afi, index, plist_name,
+ NULL);
+
+ if (!route_map_is_ipv6_rule_present(index))
+ route_map_pfx_table_add_default(afi, index);
+
+ if (!route_map_is_ip_rule_present(index))
+ route_map_add_plist_entries(AFI_IP6, index,
+ NULL, NULL);
+ } else {
+ route_map_del_plist_entries(afi, index, plist_name,
+ NULL);
+
+ if (!route_map_is_ip_rule_present(index))
+ route_map_pfx_table_add_default(afi, index);
+
+ if (!route_map_is_ipv6_rule_present(index))
+ route_map_add_plist_entries(AFI_IP, index, NULL,
+ NULL);
+ }
+ }
+}
+
+/*
+ * This function handles the cases where a route-map index and
+ * prefix-list is added/removed.
+ * It updates the prefix-table of the route-map accordingly.
+ */
+static void route_map_pfx_tbl_update(route_map_event_t event,
+ struct route_map_index *index, afi_t afi,
+ const char *plist_name)
+{
+ struct route_map *rmap = NULL;
+
+ if (!index)
+ return;
+
+ if (event == RMAP_EVENT_INDEX_ADDED) {
+ route_map_pfx_table_add_default(AFI_IP, index);
+ route_map_pfx_table_add_default(AFI_IP6, index);
+ return;
+ }
+
+ if (event == RMAP_EVENT_INDEX_DELETED) {
+ route_map_pfx_table_del_default(AFI_IP, index);
+ route_map_pfx_table_del_default(AFI_IP6, index);
+
+ if ((index->map->head == NULL) && (index->map->tail == NULL)) {
+ rmap = index->map;
+
+ if (rmap->ipv4_prefix_table) {
+ route_table_finish(rmap->ipv4_prefix_table);
+ rmap->ipv4_prefix_table = NULL;
+ }
+
+ if (rmap->ipv6_prefix_table) {
+ route_table_finish(rmap->ipv6_prefix_table);
+ rmap->ipv6_prefix_table = NULL;
+ }
+ }
+ return;
+ }
+
+ /* Handle prefix-list match rule addition/deletion.
+ */
+ route_map_trie_update(afi, event, index, plist_name);
+}
+
+/*
+ * This function handles the cases where a new prefix-entry is added to
+ * a prefix-list or, an existing prefix-entry is removed from the prefix-list.
+ * It updates the prefix-table of the route-map accordingly.
+ */
+static void route_map_pentry_update(route_map_event_t event,
+ const char *plist_name,
+ struct route_map_index *index,
+ struct prefix_list_entry *pentry)
+{
+ struct prefix_list *plist = NULL;
+ afi_t afi;
+ unsigned char family = pentry->prefix.family;
+
+ if (family == AF_INET) {
+ afi = AFI_IP;
+ plist = prefix_list_lookup(AFI_IP, plist_name);
+ } else {
+ afi = AFI_IP6;
+ plist = prefix_list_lookup(AFI_IP6, plist_name);
+ }
+
+ if (event == RMAP_EVENT_PLIST_ADDED) {
+ if (plist->count == 1) {
+ if (afi == AFI_IP) {
+ if (!route_map_is_ipv6_rule_present(index))
+ route_map_add_plist_entries(
+ afi, index, plist_name, pentry);
+ } else {
+ if (!route_map_is_ip_rule_present(index))
+ route_map_add_plist_entries(
+ afi, index, plist_name, pentry);
+ }
+ } else {
+ route_map_add_plist_entries(afi, index, plist_name,
+ pentry);
+ }
+ } else if (event == RMAP_EVENT_PLIST_DELETED) {
+ route_map_del_plist_entries(afi, index, plist_name, pentry);
+
+ if (plist->count == 1) {
+ if (afi == AFI_IP) {
+ if (!route_map_is_ipv6_rule_present(index))
+ route_map_pfx_table_add_default(afi,
+ index);
+ } else {
+ if (!route_map_is_ip_rule_present(index))
+ route_map_pfx_table_add_default(afi,
+ index);
+ }
+ }
+ }
+}
+
+static void route_map_pentry_process_dependency(struct hash_backet *backet,
+ void *data)
+{
+ char *rmap_name = NULL;
+ struct route_map *rmap = NULL;
+ struct route_map_index *index = NULL;
+ struct route_map_rule_list *match_list = NULL;
+ struct route_map_rule *match = NULL;
+ struct route_map_dep_data *dep_data = NULL;
+ struct route_map_pentry_dep *pentry_dep =
+ (struct route_map_pentry_dep *)data;
+ unsigned char family = pentry_dep->pentry->prefix.family;
+
+ dep_data = (struct route_map_dep_data *)backet->data;
+ if (!dep_data)
+ return;
+
+ rmap_name = dep_data->rname;
+ rmap = route_map_lookup_by_name(rmap_name);
+ if (!rmap || !rmap->head)
+ return;
+
+ for (index = rmap->head; index; index = index->next) {
+ match_list = &index->match_list;
+
+ if (!match_list)
+ continue;
+
+ for (match = match_list->head; match; match = match->next) {
+ if (strcmp(match->rule_str, pentry_dep->plist_name)
+ == 0) {
+ if (IS_RULE_IPv4_PREFIX_LIST(match->cmd->str)
+ && family == AF_INET) {
+ route_map_pentry_update(
+ pentry_dep->event,
+ pentry_dep->plist_name, index,
+ pentry_dep->pentry);
+ } else if (IS_RULE_IPv6_PREFIX_LIST(
+ match->cmd->str)
+ && family == AF_INET6) {
+ route_map_pentry_update(
+ pentry_dep->event,
+ pentry_dep->plist_name, index,
+ pentry_dep->pentry);
+ }
+ }
+ }
+ }
+}
+
+void route_map_notify_pentry_dependencies(const char *affected_name,
+ struct prefix_list_entry *pentry,
+ route_map_event_t event)
+{
+ struct route_map_dep *dep = NULL;
+ struct hash *upd8_hash = NULL;
+ struct route_map_pentry_dep pentry_dep;
+
+ if (!affected_name || !pentry)
+ return;
+
+ upd8_hash = route_map_get_dep_hash(event);
+ if (!upd8_hash)
+ return;
+
+ dep = (struct route_map_dep *)hash_get(upd8_hash, (void *)affected_name,
+ NULL);
+ if (dep) {
+ if (!dep->this_hash)
+ dep->this_hash = upd8_hash;
+
+ memset(&pentry_dep, 0, sizeof(struct route_map_pentry_dep));
+ pentry_dep.pentry = pentry;
+ pentry_dep.plist_name = affected_name;
+ pentry_dep.event = event;
+
+ hash_iterate(dep->dep_rmap_hash,
+ route_map_pentry_process_dependency,
+ (void *)&pentry_dep);
+ }
+}
+
/* Apply route map's each index to the object.
The matrix for a route-map looks like this:
@@ -1547,9 +2392,10 @@ route_map_result_t route_map_apply(struct route_map *map,
static int recursion = 0;
enum route_map_cmd_result_t match_ret = RMAP_NOMATCH;
route_map_result_t ret = RMAP_PERMITMATCH;
- struct route_map_index *index;
- struct route_map_rule *set;
+ struct route_map_index *index = NULL;
+ struct route_map_rule *set = NULL;
char buf[PREFIX_STRLEN];
+ bool skip_match_clause = false;
if (recursion > RMAP_RECURSION_LIMIT) {
flog_warn(
@@ -1566,18 +2412,55 @@ route_map_result_t route_map_apply(struct route_map *map,
}
map->applied++;
- for (index = map->head; index; index = index->next) {
- /* Apply this index. */
- index->applied++;
- match_ret = route_map_apply_match(&index->match_list, prefix,
- type, object);
-
- if (rmap_debug) {
- zlog_debug("Route-map: %s, sequence: %d, prefix: %s, result: %s",
- map->name, index->pref,
- prefix2str(prefix, buf, sizeof(buf)),
- route_map_cmd_result_str(match_ret));
+
+ if ((!map->optimization_disabled)
+ && (map->ipv4_prefix_table || map->ipv6_prefix_table)) {
+ index = route_map_get_index(map, prefix, type, object,
+ (uint8_t *)&match_ret);
+ if (index) {
+ if (rmap_debug)
+ zlog_debug(
+ "Best match route-map: %s, sequence: %d for pfx: %s, result: %s",
+ map->name, index->pref,
+ prefix2str(prefix, buf, sizeof(buf)),
+ route_map_cmd_result_str(match_ret));
+ } else {
+ if (rmap_debug)
+ zlog_debug(
+ "No best match sequence for pfx: %s in route-map: %s, result: %s",
+ prefix2str(prefix, buf, sizeof(buf)),
+ map->name,
+ route_map_cmd_result_str(match_ret));
+ /*
+ * No index matches this prefix. Return deny unless,
+ * match_ret = RMAP_NOOP.
+ */
+ if (match_ret == RMAP_NOOP)
+ ret = RMAP_PERMITMATCH;
+ else
+ ret = RMAP_DENYMATCH;
+ goto route_map_apply_end;
}
+ skip_match_clause = true;
+ } else {
+ index = map->head;
+ }
+
+ for (; index; index = index->next) {
+ if (skip_match_clause == false) {
+ /* Apply this index. */
+ match_ret = route_map_apply_match(&index->match_list,
+ prefix, type, object);
+ if (rmap_debug) {
+ zlog_debug(
+ "Route-map: %s, sequence: %d, prefix: %s, result: %s",
+ map->name, index->pref,
+ prefix2str(prefix, buf, sizeof(buf)),
+ route_map_cmd_result_str(match_ret));
+ }
+ } else
+ skip_match_clause = false;
+
/* Now we apply the matrix from above */
if (match_ret == RMAP_NOOP)
@@ -2025,8 +2908,30 @@ void route_map_notify_dependencies(const char *affected_name,
XFREE(MTYPE_ROUTE_MAP_NAME, name);
}
-
/* VTY related functions. */
+DEFUN(no_routemap_optimization, no_routemap_optimization_cmd,
+ "no route-map optimization",
+ NO_STR
+ "route-map\n"
+ "optimization\n")
+{
+ VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+ index->map->optimization_disabled = true;
+ return CMD_SUCCESS;
+}
+
+DEFUN(routemap_optimization, routemap_optimization_cmd,
+ "route-map optimization",
+ "route-map\n"
+ "optimization\n")
+{
+ VTY_DECLVAR_CONTEXT(route_map_index, index);
+
+ index->map->optimization_disabled = false;
+ return CMD_SUCCESS;
+}
+
static void clear_route_map_helper(struct route_map *map)
{
struct route_map_index *index;
@@ -2201,6 +3106,121 @@ void route_map_counter_decrement(struct route_map *map)
}
}
+DEFUN_HIDDEN(show_route_map_pfx_tbl, show_route_map_pfx_tbl_cmd,
+ "show route-map WORD prefix-table",
+ SHOW_STR
+ "route-map\n"
+ "route-map name\n"
+ "internal prefix-table\n")
+{
+ const char *rmap_name = argv[2]->arg;
+ struct route_map *rmap = NULL;
+ struct route_table *rm_pfx_tbl4 = NULL;
+ struct route_table *rm_pfx_tbl6 = NULL;
+ struct route_node *rn = NULL, *prn = NULL;
+ struct list *rmap_index_list = NULL;
+ struct listnode *ln = NULL, *nln = NULL;
+ struct route_map_index *index = NULL;
+ struct prefix *p = NULL, *pp = NULL;
+ char buf[SU_ADDRSTRLEN], pbuf[SU_ADDRSTRLEN];
+ uint8_t len = 54;
+
+ vty_out(vty, "%s:\n", frr_protonameinst);
+ rmap = route_map_lookup_by_name(rmap_name);
+ if (rmap) {
+ rm_pfx_tbl4 = rmap->ipv4_prefix_table;
+ if (rm_pfx_tbl4) {
+ vty_out(vty, "\n%s%43s%s\n", "IPv4 Prefix", "",
+ "Route-map Index List");
+ vty_out(vty, "%s%39s%s\n", "_______________", "",
+ "____________________");
+ for (rn = route_top(rm_pfx_tbl4); rn;
+ rn = route_next(rn)) {
+ p = &rn->p;
+
+ vty_out(vty, " %s/%d (%d)\n",
+ inet_ntop(p->family, &p->u.prefix, buf,
+ SU_ADDRSTRLEN),
+ p->prefixlen, rn->lock);
+
+ vty_out(vty, "(P) ");
+ prn = rn->parent;
+ if (prn) {
+ pp = &prn->p;
+ vty_out(vty, "%s/%d\n",
+ inet_ntop(pp->family,
+ &pp->u.prefix, pbuf,
+ SU_ADDRSTRLEN),
+ pp->prefixlen);
+ }
+
+ vty_out(vty, "\n");
+ rmap_index_list = (struct list *)rn->info;
+ if (!rmap_index_list
+ || !listcount(rmap_index_list))
+ vty_out(vty, "%*s%s\n", len, "", "-");
+ else
+ for (ALL_LIST_ELEMENTS(rmap_index_list,
+ ln, nln,
+ index)) {
+ vty_out(vty, "%*s%s seq %d\n",
+ len, "",
+ index->map->name,
+ index->pref);
+ }
+ vty_out(vty, "\n");
+ }
+ }
+
+ rm_pfx_tbl6 = rmap->ipv6_prefix_table;
+ if (rm_pfx_tbl6) {
+ vty_out(vty, "\n%s%43s%s\n", "IPv6 Prefix", "",
+ "Route-map Index List");
+ vty_out(vty, "%s%39s%s\n", "_______________", "",
+ "____________________");
+ for (rn = route_top(rm_pfx_tbl6); rn;
+ rn = route_next(rn)) {
+ p = &rn->p;
+
+ vty_out(vty, " %s/%d (%d)\n",
+ inet_ntop(p->family, &p->u.prefix, buf,
+ SU_ADDRSTRLEN),
+ p->prefixlen, rn->lock);
+
+ vty_out(vty, "(P) ");
+ prn = rn->parent;
+ if (prn) {
+ pp = &prn->p;
+ vty_out(vty, "%s/%d\n",
+ inet_ntop(pp->family,
+ &pp->u.prefix, pbuf,
+ SU_ADDRSTRLEN),
+ pp->prefixlen);
+ }
+
+ vty_out(vty, "\n");
+ rmap_index_list = (struct list *)rn->info;
+ if (!rmap_index_list
+ || !listcount(rmap_index_list))
+ vty_out(vty, "%*s%s\n", len, "", "-");
+ else
+ for (ALL_LIST_ELEMENTS(rmap_index_list,
+ ln, nln,
+ index)) {
+ vty_out(vty, "%*s%s seq %d\n",
+ len, "",
+ index->map->name,
+ index->pref);
+ }
+ vty_out(vty, "\n");
+ }
+ }
+ }
+
+ vty_out(vty, "\n");
+ return CMD_SUCCESS;
+}
+
/* Initialization of route map vector. */
void route_map_init(void)
{
@@ -2237,4 +3257,9 @@ void route_map_init(void)
install_element(ENABLE_NODE, &debug_rmap_cmd);
install_element(ENABLE_NODE, &no_debug_rmap_cmd);
+
+ install_element(RMAP_NODE, &routemap_optimization_cmd);
+ install_element(RMAP_NODE, &no_routemap_optimization_cmd);
+
+ install_element(ENABLE_NODE, &show_route_map_pfx_tbl_cmd);
}
diff --git a/lib/routemap.h b/lib/routemap.h
index 05c958967c..e8cab64b47 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -25,6 +25,8 @@
#include "memory.h"
#include "qobj.h"
#include "vty.h"
+#include "lib/plist.h"
+#include "lib/plist_int.h"
#ifdef __cplusplus
extern "C" {
@@ -220,6 +222,7 @@ struct route_map {
/* Maintain update info */
bool to_be_processed; /* True if modification isn't acted on yet */
bool deleted; /* If 1, then this node will be deleted */
+ bool optimization_disabled;
/* How many times have we applied this route-map */
uint64_t applied;
@@ -228,6 +231,12 @@ struct route_map {
/* Counter to track active usage of this route-map */
uint16_t use_count;
+ /* Tables to maintain IPv4 and IPv6 prefixes from
+ * the prefix-list match clause.
+ */
+ struct route_table *ipv4_prefix_table;
+ struct route_table *ipv6_prefix_table;
+
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(route_map)
@@ -310,7 +319,10 @@ extern void route_map_upd8_dependency(route_map_event_t type, const char *arg,
const char *rmap_name);
extern void route_map_notify_dependencies(const char *affected_name,
route_map_event_t event);
-
+extern void
+route_map_notify_pentry_dependencies(const char *affected_name,
+ struct prefix_list_entry *pentry,
+ route_map_event_t event);
extern int generic_match_add(struct vty *vty, struct route_map_index *index,
const char *command, const char *arg,
route_map_event_t type);
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index 7023710564..5b03b5266f 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -1064,7 +1064,6 @@ void route_map_cli_init(void)
install_element(CONFIG_NODE, &no_route_map_all_cmd);
/* Install the on-match stuff */
- install_element(RMAP_NODE, &route_map_cmd);
install_element(RMAP_NODE, &rmap_onmatch_next_cmd);
install_element(RMAP_NODE, &no_rmap_onmatch_next_cmd);
install_element(RMAP_NODE, &rmap_onmatch_goto_cmd);
diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c
index 68b112b09a..2d04a3d65c 100644
--- a/lib/routemap_northbound.c
+++ b/lib/routemap_northbound.c
@@ -243,9 +243,7 @@ static int lib_route_map_entry_description_destroy(enum nb_event event,
break;
case NB_EV_APPLY:
rmi = nb_running_get_entry(dnode, NULL, true);
- if (rmi->description != NULL)
- XFREE(MTYPE_TMP, rmi->description);
- rmi->description = NULL;
+ XFREE(MTYPE_TMP, rmi->description);
break;
}
diff --git a/lib/skiplist.c b/lib/skiplist.c
index 6efa2c362d..67cc1ab378 100644
--- a/lib/skiplist.c
+++ b/lib/skiplist.c
@@ -378,7 +378,7 @@ int skiplist_next_value(register struct skiplist *l, /* in */
void **valuePointer, /* in/out */
void **cursor) /* in/out */
{
- register int k, m;
+ register int k;
register struct skiplistnode *p, *q;
CHECKLAST(l);
@@ -389,7 +389,7 @@ int skiplist_next_value(register struct skiplist *l, /* in */
if (!cursor || !*cursor) {
p = l->header;
- k = m = l->level;
+ k = l->level;
/*
* Find matching key
diff --git a/lib/sockopt.c b/lib/sockopt.c
index d6c88c0aff..52b1f0356e 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -90,12 +90,11 @@ int getsockopt_so_recvbuf(const int sock)
static void *getsockopt_cmsg_data(struct msghdr *msgh, int level, int type)
{
struct cmsghdr *cmsg;
- void *ptr = NULL;
for (cmsg = CMSG_FIRSTHDR(msgh); cmsg != NULL;
cmsg = CMSG_NXTHDR(msgh, cmsg))
if (cmsg->cmsg_level == level && cmsg->cmsg_type == type)
- return (ptr = CMSG_DATA(cmsg));
+ return CMSG_DATA(cmsg);
return NULL;
}
diff --git a/lib/vrf.h b/lib/vrf.h
index 1d87576f78..f231d2433f 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -114,6 +114,8 @@ extern struct vrf *vrf_get(vrf_id_t, const char *);
extern const char *vrf_id_to_name(vrf_id_t vrf_id);
extern vrf_id_t vrf_name_to_id(const char *);
+#define VRF_LOGNAME(V) V ? V->name : "Unknown"
+
#define VRF_GET_ID(V, NAME, USE_JSON) \
do { \
struct vrf *_vrf; \
diff --git a/lib/zclient.c b/lib/zclient.c
index 4f2ad959dc..b0d2ea43a2 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -2602,7 +2602,7 @@ int zebra_send_mpls_labels(struct zclient *zclient, int cmd,
int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
{
- struct zapi_nexthop_label *znh;
+ struct zapi_nexthop *znh;
stream_reset(s);
@@ -2631,20 +2631,8 @@ int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
for (int i = 0; i < zl->nexthop_num; i++) {
znh = &zl->nexthops[i];
- stream_putc(s, znh->type);
- stream_putw(s, znh->family);
- switch (znh->family) {
- case AF_INET:
- stream_put_in_addr(s, &znh->address.ipv4);
- break;
- case AF_INET6:
- stream_write(s, (uint8_t *)&znh->address.ipv6, 16);
- break;
- default:
- break;
- }
- stream_putl(s, znh->ifindex);
- stream_putl(s, znh->label);
+ if (zapi_nexthop_encode(s, znh, 0) < 0)
+ return -1;
}
/* Put length at the first point of the stream. */
@@ -2655,7 +2643,7 @@ int zapi_labels_encode(struct stream *s, int cmd, struct zapi_labels *zl)
int zapi_labels_decode(struct stream *s, struct zapi_labels *zl)
{
- struct zapi_nexthop_label *znh;
+ struct zapi_nexthop *znh;
memset(zl, 0, sizeof(*zl));
@@ -2719,21 +2707,8 @@ int zapi_labels_decode(struct stream *s, struct zapi_labels *zl)
for (int i = 0; i < zl->nexthop_num; i++) {
znh = &zl->nexthops[i];
- STREAM_GETC(s, znh->type);
- STREAM_GETW(s, znh->family);
- switch (znh->family) {
- case AF_INET:
- STREAM_GET(&znh->address.ipv4.s_addr, s,
- IPV4_MAX_BYTELEN);
- break;
- case AF_INET6:
- STREAM_GET(&znh->address.ipv6, s, 16);
- break;
- default:
- break;
- }
- STREAM_GETL(s, znh->ifindex);
- STREAM_GETL(s, znh->label);
+ if (zapi_nexthop_decode(s, znh, 0) < 0)
+ return -1;
}
return 0;
diff --git a/lib/zclient.h b/lib/zclient.h
index 9a230d3f34..e6f4c747e3 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -458,14 +458,6 @@ struct zapi_route {
uint32_t tableid;
};
-struct zapi_nexthop_label {
- enum nexthop_types_t type;
- int family;
- union g_addr address;
- ifindex_t ifindex;
- mpls_label_t label;
-};
-
struct zapi_labels {
uint8_t message;
#define ZAPI_LABELS_FTN 0x01
@@ -476,8 +468,9 @@ struct zapi_labels {
uint8_t type;
unsigned short instance;
} route;
+
uint16_t nexthop_num;
- struct zapi_nexthop_label nexthops[MULTIPATH_NUM];
+ struct zapi_nexthop nexthops[MULTIPATH_NUM];
};
struct zapi_pw {
diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c
index c5e985cdac..2d6c263582 100644
--- a/nhrpd/nhrp_peer.c
+++ b/nhrpd/nhrp_peer.c
@@ -755,10 +755,9 @@ static void nhrp_peer_forward(struct nhrp_peer *p,
if ((type == NHRP_EXTENSION_REVERSE_TRANSIT_NHS)
== (packet_types[hdr->type].type == PACKET_REPLY)) {
/* Check NHS list for forwarding loop */
- while ((cie = nhrp_cie_pull(&extpl, pp->hdr,
- &cie_nbma,
- &cie_protocol))
- != NULL) {
+ while (nhrp_cie_pull(&extpl, pp->hdr,
+ &cie_nbma,
+ &cie_protocol) != NULL) {
if (sockunion_same(&p->vc->remote.nbma,
&cie_nbma))
goto err;
diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c
index b4690cfa42..a8dfcbb36b 100644
--- a/ospfd/ospf_abr.c
+++ b/ospfd/ospf_abr.c
@@ -670,8 +670,7 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
* originate translated LSA
*/
- if ((new = ospf_translated_nssa_originate(area->ospf, lsa))
- == NULL) {
+ if (ospf_translated_nssa_originate(area->ospf, lsa) == NULL) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
"ospf_abr_translate_nssa(): Could not translate "
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index dffcb930e4..a16fb81ce3 100644
--- a/ospfd/ospf_dump.c
+++ b/ospfd/ospf_dump.c
@@ -158,12 +158,12 @@ const char *ospf_timeval_dump(struct timeval *t, char *buf, size_t size)
#define HOUR_IN_SECONDS (60*MINUTE_IN_SECONDS)
#define DAY_IN_SECONDS (24*HOUR_IN_SECONDS)
#define WEEK_IN_SECONDS (7*DAY_IN_SECONDS)
- unsigned long w, d, h, m, s, ms, us;
+ unsigned long w, d, h, m, ms, us;
if (!t)
return "inactive";
- w = d = h = m = s = ms = us = 0;
+ w = d = h = m = ms = 0;
memset(buf, 0, size);
us = t->tv_usec;
diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c
index a989b8468c..b042a06372 100644
--- a/ospfd/ospf_opaque.c
+++ b/ospfd/ospf_opaque.c
@@ -1557,8 +1557,8 @@ struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *lsa, int rt_recalc)
ospf_lsa_unlock(&oipi->lsa);
oipi->lsa = ospf_lsa_lock(lsa);
}
- /* Register the new lsa entry and get its control info. */
- else if ((oipi = register_opaque_lsa(lsa)) == NULL) {
+ /* Register the new lsa entry */
+ else if (register_opaque_lsa(lsa) == NULL) {
flog_warn(EC_OSPF_LSA,
"ospf_opaque_lsa_install: register_opaque_lsa() ?");
goto out;
diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c
index ff2039bec8..b5a54a0bc4 100644
--- a/ospfd/ospf_sr.c
+++ b/ospfd/ospf_sr.c
@@ -609,7 +609,7 @@ static int compute_prefix_nhlfe(struct sr_prefix *srp)
static int ospf_zebra_send_mpls_labels(int cmd, struct sr_nhlfe nhlfe)
{
struct zapi_labels zl = {};
- struct zapi_nexthop_label *znh;
+ struct zapi_nexthop *znh;
if (IS_DEBUG_OSPF_SR)
zlog_debug(" |- %s LSP %u/%u for %s/%u via %u",
@@ -631,10 +631,10 @@ static int ospf_zebra_send_mpls_labels(int cmd, struct sr_nhlfe nhlfe)
zl.nexthop_num = 1;
znh = &zl.nexthops[0];
znh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
- znh->family = AF_INET;
- znh->address.ipv4 = nhlfe.nexthop;
+ znh->gate.ipv4 = nhlfe.nexthop;
znh->ifindex = nhlfe.ifindex;
- znh->label = nhlfe.label_out;
+ znh->label_num = 1;
+ znh->labels[0] = nhlfe.label_out;
return zebra_send_mpls_labels(zclient, cmd, &zl);
}
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 64013435f6..d415256652 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -1002,7 +1002,6 @@ static int ospf_distribute_list_update_timer(struct thread *thread)
void ospf_distribute_list_update(struct ospf *ospf, int type,
unsigned short instance)
{
- struct route_table *rt;
struct ospf_external *ext;
void **args = XCALLOC(MTYPE_OSPF_DIST_ARGS, sizeof(void *) * 2);
@@ -1011,7 +1010,7 @@ void ospf_distribute_list_update(struct ospf *ospf, int type,
/* External info does not exist. */
ext = ospf_external_lookup(ospf, type, instance);
- if (!ext || !(rt = EXTERNAL_INFO(ext))) {
+ if (!ext || !EXTERNAL_INFO(ext)) {
XFREE(MTYPE_OSPF_DIST_ARGS, args);
return;
}
diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c
index c1922d8728..e395b7831d 100644
--- a/pbrd/pbr_vty.c
+++ b/pbrd/pbr_vty.c
@@ -88,8 +88,7 @@ DEFUN_NOSH(no_pbr_map, no_pbr_map_cmd, "no pbr-map PBRMAP [seq (1-700)]",
DEFPY(pbr_set_table_range,
pbr_set_table_range_cmd,
- "[no] pbr table range (10000-4294966272)$lb (10000-4294966272)$ub",
- NO_STR
+ "pbr table range (10000-4294966272)$lb (10000-4294966272)$ub",
PBR_STR
"Set table ID range\n"
"Set table ID range\n"
@@ -113,6 +112,19 @@ DEFPY(pbr_set_table_range,
return ret;
}
+DEFPY(no_pbr_set_table_range, no_pbr_set_table_range_cmd,
+ "no pbr table range [(10000-4294966272)$lb (10000-4294966272)$ub]",
+ NO_STR
+ PBR_STR
+ "Set table ID range\n"
+ "Set table ID range\n"
+ "Lower bound for table ID range\n"
+ "Upper bound for table ID range\n")
+{
+ pbr_nht_set_tableid_range(PBR_NHT_DEFAULT_LOW_TABLEID,
+ PBR_NHT_DEFAULT_HIGH_TABLEID);
+ return CMD_SUCCESS;
+}
DEFPY(pbr_map_match_src, pbr_map_match_src_cmd,
"[no] match src-ip <A.B.C.D/M|X:X::X:X/M>$prefix",
@@ -854,6 +866,7 @@ void pbr_vty_init(void)
install_element(CONFIG_NODE, &pbr_map_cmd);
install_element(CONFIG_NODE, &no_pbr_map_cmd);
install_element(CONFIG_NODE, &pbr_set_table_range_cmd);
+ install_element(CONFIG_NODE, &no_pbr_set_table_range_cmd);
install_element(INTERFACE_NODE, &pbr_policy_cmd);
install_element(PBRMAP_NODE, &pbr_map_match_src_cmd);
install_element(PBRMAP_NODE, &pbr_map_match_dst_cmd);
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 6508fb4453..0caf8e4f78 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -166,7 +166,7 @@ static void pim_if_membership_refresh(struct interface *ifp)
sg.src = src->source_addr;
sg.grp = grp->group_addr;
pim_ifchannel_local_membership_add(ifp,
- &sg);
+ &sg, false /*is_vxlan*/);
}
} /* scan group sources */
@@ -4625,6 +4625,379 @@ DEFUN (show_ip_pim_local_membership,
return CMD_SUCCESS;
}
+DEFUN (show_ip_pim_mlag_summary,
+ show_ip_pim_mlag_summary_cmd,
+ "show ip pim mlag summary [json]",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ "MLAG\n"
+ "status and stats\n"
+ JSON_STR)
+{
+ bool uj = use_json(argc, argv);
+ char role_buf[MLAG_ROLE_STRSIZE];
+ char addr_buf[INET_ADDRSTRLEN];
+
+ if (uj) {
+ json_object *json = NULL;
+ json_object *json_stat = NULL;
+
+ json = json_object_new_object();
+ if (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
+ json_object_boolean_true_add(json, "mlagConnUp");
+ if (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
+ json_object_boolean_true_add(json, "mlagPeerConnUp");
+ if (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
+ json_object_boolean_true_add(json, "mlagPeerZebraUp");
+ json_object_string_add(json, "mlagRole",
+ mlag_role2str(router->mlag_role,
+ role_buf, sizeof(role_buf)));
+ inet_ntop(AF_INET, &router->local_vtep_ip,
+ addr_buf, INET_ADDRSTRLEN);
+ json_object_string_add(json, "localVtepIp", addr_buf);
+ inet_ntop(AF_INET, &router->anycast_vtep_ip,
+ addr_buf, INET_ADDRSTRLEN);
+ json_object_string_add(json, "anycastVtepIp", addr_buf);
+ json_object_string_add(json, "peerlinkRif",
+ router->peerlink_rif);
+
+ json_stat = json_object_new_object();
+ json_object_int_add(json_stat, "mlagConnFlaps",
+ router->mlag_stats.mlagd_session_downs);
+ json_object_int_add(json_stat, "mlagPeerConnFlaps",
+ router->mlag_stats.peer_session_downs);
+ json_object_int_add(json_stat, "mlagPeerZebraFlaps",
+ router->mlag_stats.peer_zebra_downs);
+ json_object_int_add(json_stat, "mrouteAddRx",
+ router->mlag_stats.msg.mroute_add_rx);
+ json_object_int_add(json_stat, "mrouteAddTx",
+ router->mlag_stats.msg.mroute_add_tx);
+ json_object_int_add(json_stat, "mrouteDelRx",
+ router->mlag_stats.msg.mroute_del_rx);
+ json_object_int_add(json_stat, "mrouteDelTx",
+ router->mlag_stats.msg.mroute_del_tx);
+ json_object_int_add(json_stat, "mlagStatusUpdates",
+ router->mlag_stats.msg.mlag_status_updates);
+ json_object_int_add(json_stat, "peerZebraStatusUpdates",
+ router->mlag_stats.msg.peer_zebra_status_updates);
+ json_object_int_add(json_stat, "pimStatusUpdates",
+ router->mlag_stats.msg.pim_status_updates);
+ json_object_int_add(json_stat, "vxlanUpdates",
+ router->mlag_stats.msg.vxlan_updates);
+ json_object_object_add(json, "connStats", json_stat);
+
+ vty_out(vty, "%s\n", json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ return CMD_SUCCESS;
+ }
+
+ vty_out(vty, "MLAG daemon connection: %s\n",
+ (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
+ ? "up" : "down");
+ vty_out(vty, "MLAG peer state: %s\n",
+ (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
+ ? "up" : "down");
+ vty_out(vty, "Zebra peer state: %s\n",
+ (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
+ ? "up" : "down");
+ vty_out(vty, "MLAG role: %s\n",
+ mlag_role2str(router->mlag_role, role_buf, sizeof(role_buf)));
+ inet_ntop(AF_INET, &router->local_vtep_ip,
+ addr_buf, INET_ADDRSTRLEN);
+ vty_out(vty, "Local VTEP IP: %s\n", addr_buf);
+ inet_ntop(AF_INET, &router->anycast_vtep_ip,
+ addr_buf, INET_ADDRSTRLEN);
+ vty_out(vty, "Anycast VTEP IP: %s\n", addr_buf);
+ vty_out(vty, "Peerlink: %s\n", router->peerlink_rif);
+ vty_out(vty, "Session flaps: mlagd: %d mlag-peer: %d zebra-peer: %d\n",
+ router->mlag_stats.mlagd_session_downs,
+ router->mlag_stats.peer_session_downs,
+ router->mlag_stats.peer_zebra_downs);
+ vty_out(vty, "Message Statistics:\n");
+ vty_out(vty, " mroute adds: rx: %d, tx: %d\n",
+ router->mlag_stats.msg.mroute_add_rx,
+ router->mlag_stats.msg.mroute_add_tx);
+ vty_out(vty, " mroute dels: rx: %d, tx: %d\n",
+ router->mlag_stats.msg.mroute_del_rx,
+ router->mlag_stats.msg.mroute_del_tx);
+ vty_out(vty, " peer zebra status updates: %d\n",
+ router->mlag_stats.msg.peer_zebra_status_updates);
+ vty_out(vty, " PIM status updates: %d\n",
+ router->mlag_stats.msg.pim_status_updates);
+ vty_out(vty, " VxLAN updates: %d\n",
+ router->mlag_stats.msg.vxlan_updates);
+
+ return CMD_SUCCESS;
+}
+
+static void pim_show_mlag_up_entry_detail(struct vrf *vrf,
+ struct vty *vty, struct pim_upstream *up,
+ char *src_str, char *grp_str, json_object *json)
+{
+ if (json) {
+ json_object *json_row = NULL;
+ json_object *own_list = NULL;
+ json_object *json_group = NULL;
+
+
+ json_object_object_get_ex(json, grp_str, &json_group);
+ if (!json_group) {
+ json_group = json_object_new_object();
+ json_object_object_add(json, grp_str,
+ json_group);
+ }
+
+ json_row = json_object_new_object();
+ json_object_string_add(json_row, "source", src_str);
+ json_object_string_add(json_row, "group", grp_str);
+
+ own_list = json_object_new_array();
+ if (pim_up_mlag_is_local(up))
+ json_object_array_add(own_list,
+ json_object_new_string("local"));
+ if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_PEER))
+ json_object_array_add(own_list,
+ json_object_new_string("peer"));
+ if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE))
+ json_object_array_add(
+ own_list, json_object_new_string("Interface"));
+ json_object_object_add(json_row, "owners", own_list);
+
+ json_object_int_add(json_row, "localCost",
+ pim_up_mlag_local_cost(up));
+ json_object_int_add(json_row, "peerCost",
+ pim_up_mlag_peer_cost(up));
+ if (PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags))
+ json_object_boolean_false_add(json_row, "df");
+ else
+ json_object_boolean_true_add(json_row, "df");
+ json_object_object_add(json_group, src_str, json_row);
+ } else {
+ char own_str[6];
+
+ own_str[0] = '\0';
+ if (pim_up_mlag_is_local(up))
+ strlcat(own_str, "L", sizeof(own_str));
+ if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_PEER))
+ strlcat(own_str, "P", sizeof(own_str));
+ if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE))
+ strlcat(own_str, "I", sizeof(own_str));
+ /* XXX - fixup, print paragraph output */
+ vty_out(vty,
+ "%-15s %-15s %-6s %-11u %-10d %2s\n",
+ src_str, grp_str, own_str,
+ pim_up_mlag_local_cost(up),
+ pim_up_mlag_peer_cost(up),
+ PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags)
+ ? "n" : "y");
+ }
+}
+
+static void pim_show_mlag_up_detail(struct vrf *vrf,
+ struct vty *vty, const char *src_or_group,
+ const char *group, bool uj)
+{
+ char src_str[INET_ADDRSTRLEN];
+ char grp_str[INET_ADDRSTRLEN];
+ struct pim_upstream *up;
+ struct pim_instance *pim = vrf->info;
+ json_object *json = NULL;
+
+ if (uj)
+ json = json_object_new_object();
+ else
+ vty_out(vty,
+ "Source Group Owner Local-cost Peer-cost DF\n");
+
+ frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+ if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_PEER)
+ && !(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE)
+ && !pim_up_mlag_is_local(up))
+ continue;
+
+ pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
+ pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
+ /* XXX: strcmps are clearly inefficient. we should do uint comps
+ * here instead.
+ */
+ if (group) {
+ if (strcmp(src_str, src_or_group) ||
+ strcmp(grp_str, group))
+ continue;
+ } else {
+ if (strcmp(src_str, src_or_group) &&
+ strcmp(grp_str, src_or_group))
+ continue;
+ }
+ pim_show_mlag_up_entry_detail(vrf, vty, up,
+ src_str, grp_str, json);
+ }
+
+ if (uj) {
+ vty_out(vty, "%s\n", json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
+}
+
+static void pim_show_mlag_up_vrf(struct vrf *vrf, struct vty *vty, bool uj)
+{
+ json_object *json = NULL;
+ json_object *json_row;
+ struct pim_upstream *up;
+ char src_str[INET_ADDRSTRLEN];
+ char grp_str[INET_ADDRSTRLEN];
+ struct pim_instance *pim = vrf->info;
+ json_object *json_group = NULL;
+
+ if (uj) {
+ json = json_object_new_object();
+ } else {
+ vty_out(vty,
+ "Source Group Owner Local-cost Peer-cost DF\n");
+ }
+
+ frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+ if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_PEER)
+ && !(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE)
+ && !pim_up_mlag_is_local(up))
+ continue;
+ pim_inet4_dump("<src?>", up->sg.src, src_str, sizeof(src_str));
+ pim_inet4_dump("<grp?>", up->sg.grp, grp_str, sizeof(grp_str));
+ if (uj) {
+ json_object *own_list = NULL;
+
+ json_object_object_get_ex(json, grp_str, &json_group);
+ if (!json_group) {
+ json_group = json_object_new_object();
+ json_object_object_add(json, grp_str,
+ json_group);
+ }
+
+ json_row = json_object_new_object();
+ json_object_string_add(json_row, "vrf", vrf->name);
+ json_object_string_add(json_row, "source", src_str);
+ json_object_string_add(json_row, "group", grp_str);
+
+ own_list = json_object_new_array();
+ if (pim_up_mlag_is_local(up)) {
+
+ json_object_array_add(own_list,
+ json_object_new_string("local"));
+ }
+ if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_PEER)) {
+ json_object_array_add(own_list,
+ json_object_new_string("peer"));
+ }
+ json_object_object_add(json_row, "owners", own_list);
+
+ json_object_int_add(json_row, "localCost",
+ pim_up_mlag_local_cost(up));
+ json_object_int_add(json_row, "peerCost",
+ pim_up_mlag_peer_cost(up));
+ if (PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags))
+ json_object_boolean_false_add(json_row, "df");
+ else
+ json_object_boolean_true_add(json_row, "df");
+ json_object_object_add(json_group, src_str, json_row);
+ } else {
+ char own_str[6];
+
+ own_str[0] = '\0';
+ if (pim_up_mlag_is_local(up))
+ strlcat(own_str, "L", sizeof(own_str));
+ if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_PEER))
+ strlcat(own_str, "P", sizeof(own_str));
+ if (up->flags & (PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE))
+ strlcat(own_str, "I", sizeof(own_str));
+ vty_out(vty,
+ "%-15s %-15s %-6s %-11u %-10u %2s\n",
+ src_str, grp_str, own_str,
+ pim_up_mlag_local_cost(up),
+ pim_up_mlag_peer_cost(up),
+ PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags)
+ ? "n" : "y");
+ }
+ }
+ if (uj) {
+ vty_out(vty, "%s\n", json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
+}
+
+static void pim_show_mlag_help_string(struct vty *vty, bool uj)
+{
+ if (!uj) {
+ vty_out(vty, "Owner codes:\n");
+ vty_out(vty,
+ "L: EVPN-MLAG Entry, I:PIM-MLAG Entry, "
+ "P: Peer Entry\n");
+ }
+}
+
+
+DEFUN(show_ip_pim_mlag_up, show_ip_pim_mlag_up_cmd,
+ "show ip pim [vrf NAME] mlag upstream [A.B.C.D [A.B.C.D]] [json]",
+ SHOW_STR
+ IP_STR
+ PIM_STR
+ VRF_CMD_HELP_STR
+ "MLAG\n"
+ "upstream\n"
+ "Unicast or Multicast address\n"
+ "Multicast address\n" JSON_STR)
+{
+ const char *src_or_group = NULL;
+ const char *group = NULL;
+ int idx = 2;
+ struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
+ bool uj = use_json(argc, argv);
+
+ if (!vrf || !vrf->info) {
+ vty_out(vty, "%s: VRF or Info missing\n", __func__);
+ return CMD_WARNING;
+ }
+
+ if (uj)
+ argc--;
+
+ if (argv_find(argv, argc, "A.B.C.D", &idx)) {
+ src_or_group = argv[idx]->arg;
+ if (idx + 1 < argc)
+ group = argv[idx + 1]->arg;
+ }
+
+ pim_show_mlag_help_string(vty, uj);
+
+ if (src_or_group)
+ pim_show_mlag_up_detail(vrf, vty, src_or_group, group, uj);
+ else
+ pim_show_mlag_up_vrf(vrf, vty, uj);
+
+ return CMD_SUCCESS;
+}
+
+
+DEFUN(show_ip_pim_mlag_up_vrf_all, show_ip_pim_mlag_up_vrf_all_cmd,
+ "show ip pim vrf all mlag upstream [json]",
+ SHOW_STR IP_STR PIM_STR VRF_CMD_HELP_STR
+ "MLAG\n"
+ "upstream\n" JSON_STR)
+{
+ struct vrf *vrf;
+ bool uj = use_json(argc, argv);
+
+ pim_show_mlag_help_string(vty, uj);
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ pim_show_mlag_up_vrf(vrf, vty, uj);
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN (show_ip_pim_neighbor,
show_ip_pim_neighbor_cmd,
"show ip pim [vrf NAME] neighbor [detail|WORD] [json]",
@@ -5294,7 +5667,7 @@ static void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim,
pim = vrf->info;
vty_out(vty, "Router MLAG Role: %s\n",
- mlag_role2str(router->role, mlag_role, sizeof(mlag_role)));
+ mlag_role2str(router->mlag_role, mlag_role, sizeof(mlag_role)));
vty_out(vty, "Mroute socket descriptor:");
vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name);
@@ -10259,7 +10632,7 @@ DEFUN_HIDDEN (no_ip_pim_mlag,
addr.s_addr = 0;
pim_vxlan_mlag_update(true/*mlag_enable*/,
- false/*peer_state*/, PIM_VXLAN_MLAG_ROLE_SECONDARY,
+ false/*peer_state*/, MLAG_ROLE_NONE,
NULL/*peerlink*/, &addr);
return CMD_SUCCESS;
@@ -10299,9 +10672,9 @@ DEFUN_HIDDEN (ip_pim_mlag,
idx += 2;
if (!strcmp(argv[idx]->arg, "primary")) {
- role = PIM_VXLAN_MLAG_ROLE_PRIMARY;
+ role = MLAG_ROLE_PRIMARY;
} else if (!strcmp(argv[idx]->arg, "secondary")) {
- role = PIM_VXLAN_MLAG_ROLE_SECONDARY;
+ role = MLAG_ROLE_SECONDARY;
} else {
vty_out(vty, "unknown MLAG role %s\n", argv[idx]->arg);
return CMD_WARNING;
@@ -10471,6 +10844,9 @@ void pim_cmd_init(void)
install_element(VIEW_NODE, &show_ip_pim_join_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_pim_jp_agg_cmd);
install_element(VIEW_NODE, &show_ip_pim_local_membership_cmd);
+ install_element(VIEW_NODE, &show_ip_pim_mlag_summary_cmd);
+ install_element(VIEW_NODE, &show_ip_pim_mlag_up_cmd);
+ install_element(VIEW_NODE, &show_ip_pim_mlag_up_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_pim_neighbor_cmd);
install_element(VIEW_NODE, &show_ip_pim_neighbor_vrf_all_cmd);
install_element(VIEW_NODE, &show_ip_pim_rpf_cmd);
@@ -10595,6 +10971,8 @@ void pim_cmd_init(void)
install_element(CONFIG_NODE, &no_debug_ssmpingd_cmd);
install_element(CONFIG_NODE, &debug_pim_zebra_cmd);
install_element(CONFIG_NODE, &no_debug_pim_zebra_cmd);
+ install_element(CONFIG_NODE, &debug_pim_mlag_cmd);
+ install_element(CONFIG_NODE, &no_debug_pim_mlag_cmd);
install_element(CONFIG_NODE, &debug_pim_vxlan_cmd);
install_element(CONFIG_NODE, &no_debug_pim_vxlan_cmd);
install_element(CONFIG_NODE, &debug_msdp_cmd);
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index c615540149..8cc720c535 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -498,6 +498,7 @@ void pim_if_addr_add(struct connected *ifc)
struct pim_interface *pim_ifp;
struct interface *ifp;
struct in_addr ifaddr;
+ bool vxlan_term;
zassert(ifc);
@@ -635,7 +636,8 @@ void pim_if_addr_add(struct connected *ifc)
address assigned, then try to create a vif_index.
*/
if (pim_ifp->mroute_vif_index < 0) {
- pim_if_add_vif(ifp, false, false /*vxlan_term*/);
+ vxlan_term = pim_vxlan_is_term_dev_cfg(pim_ifp->pim, ifp);
+ pim_if_add_vif(ifp, false, vxlan_term);
}
pim_ifchannel_scan_forward_start(ifp);
}
@@ -730,6 +732,7 @@ void pim_if_addr_add_all(struct interface *ifp)
int v4_addrs = 0;
int v6_addrs = 0;
struct pim_interface *pim_ifp = ifp->info;
+ bool vxlan_term;
/* PIM/IGMP enabled ? */
@@ -768,7 +771,8 @@ void pim_if_addr_add_all(struct interface *ifp)
* address assigned, then try to create a vif_index.
*/
if (pim_ifp->mroute_vif_index < 0) {
- pim_if_add_vif(ifp, false, false /*vxlan_term*/);
+ vxlan_term = pim_vxlan_is_term_dev_cfg(pim_ifp->pim, ifp);
+ pim_if_add_vif(ifp, false, vxlan_term);
}
pim_ifchannel_scan_forward_start(ifp);
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 22d6e6298e..2ea1f4e9a4 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -854,8 +854,9 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
/*
* If we are going to be a LHR, we need to note it
*/
- if (ch->upstream->parent && (ch->upstream->parent->flags
- & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
+ if (ch->upstream->parent &&
+ (PIM_UPSTREAM_FLAG_TEST_CAN_BE_LHR(
+ ch->upstream->parent->flags))
&& !(ch->upstream->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_LHR)) {
pim_upstream_ref(ch->upstream,
@@ -1042,11 +1043,12 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
}
int pim_ifchannel_local_membership_add(struct interface *ifp,
- struct prefix_sg *sg)
+ struct prefix_sg *sg, bool is_vxlan)
{
struct pim_ifchannel *ch, *starch;
struct pim_interface *pim_ifp;
struct pim_instance *pim;
+ int up_flags;
/* PIM enabled on interface? */
pim_ifp = ifp->info;
@@ -1080,7 +1082,9 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
}
}
- ch = pim_ifchannel_add(ifp, sg, 0, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP);
+ up_flags = is_vxlan ? PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM :
+ PIM_UPSTREAM_FLAG_MASK_SRC_IGMP;
+ ch = pim_ifchannel_add(ifp, sg, 0, up_flags);
ifmembership_set(ch, PIM_IFMEMBERSHIP_INCLUDE);
diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h
index b36c3236b0..3d5cbd8ecf 100644
--- a/pimd/pim_ifchannel.h
+++ b/pimd/pim_ifchannel.h
@@ -130,7 +130,7 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
struct prefix_sg *sg, uint8_t source_flags,
uint16_t holdtime);
int pim_ifchannel_local_membership_add(struct interface *ifp,
- struct prefix_sg *sg);
+ struct prefix_sg *sg, bool is_vxlan);
void pim_ifchannel_local_membership_del(struct interface *ifp,
struct prefix_sg *sg);
diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h
index da0c75decb..7b1fd2e172 100644
--- a/pimd/pim_instance.h
+++ b/pimd/pim_instance.h
@@ -48,6 +48,46 @@ enum pim_spt_switchover {
PIM_SPT_INFINITY,
};
+/* stats for updates rxed from the MLAG component during the life of a
+ * session
+ */
+struct pim_mlag_msg_stats {
+ uint32_t mroute_add_rx;
+ uint32_t mroute_add_tx;
+ uint32_t mroute_del_rx;
+ uint32_t mroute_del_tx;
+ uint32_t mlag_status_updates;
+ uint32_t pim_status_updates;
+ uint32_t vxlan_updates;
+ uint32_t peer_zebra_status_updates;
+};
+
+struct pim_mlag_stats {
+ /* message stats are reset when the connection to mlagd flaps */
+ struct pim_mlag_msg_stats msg;
+ uint32_t mlagd_session_downs;
+ uint32_t peer_session_downs;
+ uint32_t peer_zebra_downs;
+};
+
+enum pim_mlag_flags {
+ PIM_MLAGF_NONE = 0,
+ /* connection to the local MLAG daemon is up */
+ PIM_MLAGF_LOCAL_CONN_UP = (1 << 0),
+ /* connection to the MLAG daemon on the peer switch is up. note
+ * that there is no direct connection between FRR and the peer MLAG
+ * daemon. this is just a peer-session status provided by the local
+ * MLAG daemon.
+ */
+ PIM_MLAGF_PEER_CONN_UP = (1 << 1),
+ /* status update rxed from the local daemon */
+ PIM_MLAGF_STATUS_RXED = (1 << 2),
+ /* initial dump of data done post peerlink flap */
+ PIM_MLAGF_PEER_REPLAY_DONE = (1 << 3),
+ /* zebra is up on the peer */
+ PIM_MLAGF_PEER_ZEBRA_UP = (1 << 4)
+};
+
struct pim_router {
struct thread_master *master;
@@ -65,7 +105,7 @@ struct pim_router {
*/
vrf_id_t vrf_id;
- enum mlag_role role;
+ enum mlag_role mlag_role;
uint32_t pim_mlag_intf_cnt;
/* if true we have registered with MLAG */
bool mlag_process_register;
@@ -77,6 +117,12 @@ struct pim_router {
struct stream_fifo *mlag_fifo;
struct stream *mlag_stream;
struct thread *zpthread_mlag_write;
+ struct in_addr anycast_vtep_ip;
+ struct in_addr local_vtep_ip;
+ struct pim_mlag_stats mlag_stats;
+ enum pim_mlag_flags mlag_flags;
+ char peerlink_rif[INTERFACE_NAMSIZ];
+ struct interface *peerlink_rif_p;
};
/* Per VRF PIM DB */
diff --git a/pimd/pim_mlag.c b/pimd/pim_mlag.c
index f60c18204b..1c2f7c563d 100644
--- a/pimd/pim_mlag.c
+++ b/pimd/pim_mlag.c
@@ -25,14 +25,462 @@
#include "pimd.h"
#include "pim_mlag.h"
+#include "pim_upstream.h"
+#include "pim_vxlan.h"
extern struct zclient *zclient;
+#define PIM_MLAG_METADATA_LEN 4
+
+/******************************* pim upstream sync **************************/
+/* Update DF role for the upstream entry and return true on role change */
+bool pim_mlag_up_df_role_update(struct pim_instance *pim,
+ struct pim_upstream *up, bool is_df, const char *reason)
+{
+ struct channel_oil *c_oil = up->channel_oil;
+ bool old_is_df = !PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags);
+ struct pim_interface *vxlan_ifp;
+
+ if (is_df == old_is_df) {
+ if (PIM_DEBUG_MLAG)
+ zlog_debug(
+ "%s: Ignoring Role update for %s, since no change",
+ __func__, up->sg_str);
+ return false;
+ }
+
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("local MLAG mroute %s role changed to %s based on %s",
+ up->sg_str, is_df ? "df" : "non-df", reason);
+
+ if (is_df)
+ PIM_UPSTREAM_FLAG_UNSET_MLAG_NON_DF(up->flags);
+ else
+ PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(up->flags);
+
+
+ /* If the DF role has changed check if ipmr-lo needs to be
+ * muted/un-muted. Active-Active devices and vxlan termination
+ * devices (ipmr-lo) are suppressed on the non-DF.
+ * This may leave the mroute with the empty OIL in which case the
+ * the forwarding entry's sole purpose is to just blackhole the flow
+ * headed to the switch.
+ */
+ if (c_oil) {
+ vxlan_ifp = pim_vxlan_get_term_ifp(pim);
+ if (vxlan_ifp)
+ pim_channel_update_oif_mute(c_oil, vxlan_ifp);
+ }
+
+ /* If DF role changed on a (*,G) termination mroute update the
+ * associated DF role on the inherited (S,G) entries
+ */
+ if ((up->sg.src.s_addr == INADDR_ANY) &&
+ PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(up->flags))
+ pim_vxlan_inherit_mlag_flags(pim, up, true /* inherit */);
+
+ return true;
+}
+
+/* Run per-upstream entry DF election and return true on role change */
+static bool pim_mlag_up_df_role_elect(struct pim_instance *pim,
+ struct pim_upstream *up)
+{
+ bool is_df;
+ uint32_t peer_cost;
+ uint32_t local_cost;
+ bool rv;
+
+ if (!pim_up_mlag_is_local(up))
+ return false;
+
+ /* We are yet to rx a status update from the local MLAG daemon so
+ * we will assume DF status.
+ */
+ if (!(router->mlag_flags & PIM_MLAGF_STATUS_RXED))
+ return pim_mlag_up_df_role_update(pim, up,
+ true /*is_df*/, "mlagd-down");
+
+ /* If not connected to peer assume DF role on the MLAG primary
+ * switch (and non-DF on the secondary switch.
+ */
+ if (!(router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)) {
+ is_df = (router->mlag_role == MLAG_ROLE_PRIMARY) ? true : false;
+ return pim_mlag_up_df_role_update(pim, up,
+ is_df, "peer-down");
+ }
+
+ /* If MLAG peer session is up but zebra is down on the peer
+ * assume DF role.
+ */
+ if (!(router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP))
+ return pim_mlag_up_df_role_update(pim, up,
+ true /*is_df*/, "zebra-down");
+
+ /* If we are connected to peer switch but don't have a mroute
+ * from it we have to assume non-DF role to avoid duplicates.
+ * Note: When the peer connection comes up we wait for initial
+ * replay to complete before moving "strays" i.e. local-mlag-mroutes
+ * without a peer reference to non-df role.
+ */
+ if (!PIM_UPSTREAM_FLAG_TEST_MLAG_PEER(up->flags))
+ return pim_mlag_up_df_role_update(pim, up,
+ false /*is_df*/, "no-peer-mroute");
+
+ /* switch with the lowest RPF cost wins. if both switches have the same
+ * cost MLAG role is used as a tie breaker (MLAG primary wins).
+ */
+ peer_cost = up->mlag.peer_mrib_metric;
+ local_cost = pim_up_mlag_local_cost(up);
+ if (local_cost == peer_cost) {
+ is_df = (router->mlag_role == MLAG_ROLE_PRIMARY) ? true : false;
+ rv = pim_mlag_up_df_role_update(pim, up, is_df, "equal-cost");
+ } else {
+ is_df = (local_cost < peer_cost) ? true : false;
+ rv = pim_mlag_up_df_role_update(pim, up, is_df, "cost");
+ }
+
+ return rv;
+}
+
+/* Handle upstream entry add from the peer MLAG switch -
+ * - if a local entry doesn't exist one is created with reference
+ * _MLAG_PEER
+ * - if a local entry exists and has a MLAG OIF DF election is run.
+ * the non-DF switch stop forwarding traffic to MLAG devices.
+ */
+static void pim_mlag_up_peer_add(struct mlag_mroute_add *msg)
+{
+ struct pim_upstream *up;
+ struct pim_instance *pim;
+ int flags = 0;
+ struct prefix_sg sg;
+ struct vrf *vrf;
+ char sg_str[PIM_SG_LEN];
+
+ memset(&sg, 0, sizeof(struct prefix_sg));
+ sg.src.s_addr = htonl(msg->source_ip);
+ sg.grp.s_addr = htonl(msg->group_ip);
+ if (PIM_DEBUG_MLAG)
+ pim_str_sg_set(&sg, sg_str);
+
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("peer MLAG mroute add %s:%s cost %d",
+ msg->vrf_name, sg_str, msg->cost_to_rp);
+
+ /* XXX - this is not correct. we MUST cache updates to avoid losing
+ * an entry because of race conditions with the peer switch.
+ */
+ vrf = vrf_lookup_by_name(msg->vrf_name);
+ if (!vrf) {
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("peer MLAG mroute add failed %s:%s; no vrf",
+ msg->vrf_name, sg_str);
+ return;
+ }
+ pim = vrf->info;
+
+ up = pim_upstream_find(pim, &sg);
+ if (up) {
+ /* upstream already exists; create peer reference if it
+ * doesn't already exist.
+ */
+ if (!PIM_UPSTREAM_FLAG_TEST_MLAG_PEER(up->flags))
+ pim_upstream_ref(up,
+ PIM_UPSTREAM_FLAG_MASK_MLAG_PEER,
+ __PRETTY_FUNCTION__);
+ } else {
+ PIM_UPSTREAM_FLAG_SET_MLAG_PEER(flags);
+ up = pim_upstream_add(pim, &sg, NULL /*iif*/, flags,
+ __PRETTY_FUNCTION__, NULL /*if_ch*/);
+
+ if (!up) {
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("peer MLAG mroute add failed %s:%s",
+ vrf->name, sg_str);
+ return;
+ }
+ }
+ up->mlag.peer_mrib_metric = msg->cost_to_rp;
+ pim_mlag_up_df_role_elect(pim, up);
+}
+
+/* Handle upstream entry del from the peer MLAG switch -
+ * - peer reference is removed. this can result in the upstream
+ * being deleted altogether.
+ * - if a local entry continues to exisy and has a MLAG OIF DF election
+ * is re-run (at the end of which the local entry will be the DF).
+ */
+static void pim_mlag_up_peer_deref(struct pim_instance *pim,
+ struct pim_upstream *up)
+{
+ if (!PIM_UPSTREAM_FLAG_TEST_MLAG_PEER(up->flags))
+ return;
+
+ PIM_UPSTREAM_FLAG_UNSET_MLAG_PEER(up->flags);
+ up = pim_upstream_del(pim, up, __PRETTY_FUNCTION__);
+ if (up)
+ pim_mlag_up_df_role_elect(pim, up);
+}
+static void pim_mlag_up_peer_del(struct mlag_mroute_del *msg)
+{
+ struct pim_upstream *up;
+ struct pim_instance *pim;
+ struct prefix_sg sg;
+ struct vrf *vrf;
+ char sg_str[PIM_SG_LEN];
+
+ memset(&sg, 0, sizeof(struct prefix_sg));
+ sg.src.s_addr = htonl(msg->source_ip);
+ sg.grp.s_addr = htonl(msg->group_ip);
+ if (PIM_DEBUG_MLAG)
+ pim_str_sg_set(&sg, sg_str);
+
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("peer MLAG mroute del %s:%s", msg->vrf_name,
+ sg_str);
+
+ vrf = vrf_lookup_by_name(msg->vrf_name);
+ if (!vrf) {
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("peer MLAG mroute del skipped %s:%s; no vrf",
+ msg->vrf_name, sg_str);
+ return;
+ }
+ pim = vrf->info;
+
+ up = pim_upstream_find(pim, &sg);
+ if (!up) {
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("peer MLAG mroute del skipped %s:%s; no up",
+ vrf->name, sg_str);
+ return;
+ }
+
+ pim_mlag_up_peer_deref(pim, up);
+}
+
+/* When we lose connection to the local MLAG daemon we can drop all peer
+ * references.
+ */
+static void pim_mlag_up_peer_del_all(void)
+{
+ struct list *temp = list_new();
+ struct pim_upstream *up;
+ struct vrf *vrf;
+ struct pim_instance *pim;
+
+ /*
+ * So why these gyrations?
+ * pim->upstream_head has the list of *,G and S,G
+ * that are in the system. The problem of course
+ * is that it is an ordered list:
+ * (*,G1) -> (S1,G1) -> (S2,G2) -> (S3, G2) -> (*,G2) -> (S1,G2)
+ * And the *,G1 has pointers to S1,G1 and S2,G1
+ * if we delete *,G1 then we have a situation where
+ * S1,G1 and S2,G2 can be deleted as well. Then a
+ * simple ALL_LIST_ELEMENTS will have the next listnode
+ * pointer become invalid and we crash.
+ * So let's grab the list of MLAG_PEER upstreams
+ * add a refcount put on another list and delete safely
+ */
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
+ pim = vrf->info;
+ frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+ if (!PIM_UPSTREAM_FLAG_TEST_MLAG_PEER(up->flags))
+ continue;
+ listnode_add(temp, up);
+ /*
+ * Add a reference since we are adding to this
+ * list for deletion
+ */
+ up->ref_count++;
+ }
+
+ while (temp->count) {
+ up = listnode_head(temp);
+ listnode_delete(temp, up);
+
+ pim_mlag_up_peer_deref(pim, up);
+ /*
+ * This is the deletion of the reference added
+ * above
+ */
+ pim_upstream_del(pim, up, __PRETTY_FUNCTION__);
+ }
+ }
+
+ list_delete(&temp);
+}
+
+static int pim_mlag_signal_zpthread(void)
+{
+ /* XXX - This is a temporary stub; the MLAG thread code is planned for
+ * a separate commit
+ */
+ return (0);
+}
+
+/* Send upstream entry to the local MLAG daemon (which will subsequently
+ * send it to the peer MLAG switch).
+ */
+static void pim_mlag_up_local_add_send(struct pim_instance *pim,
+ struct pim_upstream *up)
+{
+ struct stream *s = NULL;
+ struct vrf *vrf = pim->vrf;
+
+ if (!(router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP))
+ return;
+
+ s = stream_new(sizeof(struct mlag_mroute_add) + PIM_MLAG_METADATA_LEN);
+ if (!s)
+ return;
+
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("local MLAG mroute add %s:%s",
+ vrf->name, up->sg_str);
+
+ ++router->mlag_stats.msg.mroute_add_tx;
+
+ stream_putl(s, MLAG_MROUTE_ADD);
+ stream_put(s, vrf->name, VRF_NAMSIZ);
+ stream_putl(s, ntohl(up->sg.src.s_addr));
+ stream_putl(s, ntohl(up->sg.grp.s_addr));
+
+ stream_putl(s, pim_up_mlag_local_cost(up));
+ /* XXX - who is addding*/
+ stream_putl(s, MLAG_OWNER_VXLAN);
+ /* XXX - am_i_DR field should be removed */
+ stream_putc(s, false);
+ stream_putc(s, !(PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->flags)));
+ stream_putl(s, vrf->vrf_id);
+ /* XXX - this field is a No-op for VXLAN*/
+ stream_put(s, NULL, INTERFACE_NAMSIZ);
+
+ stream_fifo_push_safe(router->mlag_fifo, s);
+ pim_mlag_signal_zpthread();
+}
+
+static void pim_mlag_up_local_del_send(struct pim_instance *pim,
+ struct pim_upstream *up)
+{
+ struct stream *s = NULL;
+ struct vrf *vrf = pim->vrf;
+
+ if (!(router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP))
+ return;
+
+ s = stream_new(sizeof(struct mlag_mroute_del) + PIM_MLAG_METADATA_LEN);
+ if (!s)
+ return;
+
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("local MLAG mroute del %s:%s",
+ vrf->name, up->sg_str);
+
+ ++router->mlag_stats.msg.mroute_del_tx;
+
+ stream_putl(s, MLAG_MROUTE_DEL);
+ stream_put(s, vrf->name, VRF_NAMSIZ);
+ stream_putl(s, ntohl(up->sg.src.s_addr));
+ stream_putl(s, ntohl(up->sg.grp.s_addr));
+ /* XXX - who is adding */
+ stream_putl(s, MLAG_OWNER_VXLAN);
+ stream_putl(s, vrf->vrf_id);
+ /* XXX - this field is a No-op for VXLAN */
+ stream_put(s, NULL, INTERFACE_NAMSIZ);
+
+ /* XXX - is this the the most optimal way to do things */
+ stream_fifo_push_safe(router->mlag_fifo, s);
+ pim_mlag_signal_zpthread();
+}
+
+
+/* Called when a local upstream entry is created or if it's cost changes */
+void pim_mlag_up_local_add(struct pim_instance *pim,
+ struct pim_upstream *up)
+{
+ pim_mlag_up_df_role_elect(pim, up);
+ /* XXX - need to add some dup checks here */
+ pim_mlag_up_local_add_send(pim, up);
+}
+
+/* Called when local MLAG reference is removed from an upstream entry */
+void pim_mlag_up_local_del(struct pim_instance *pim,
+ struct pim_upstream *up)
+{
+ pim_mlag_up_df_role_elect(pim, up);
+ pim_mlag_up_local_del_send(pim, up);
+}
+
+/* When connection to local MLAG daemon is established all the local
+ * MLAG upstream entries are replayed to it.
+ */
+static void pim_mlag_up_local_replay(void)
+{
+ struct pim_upstream *up;
+ struct vrf *vrf;
+ struct pim_instance *pim;
+
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
+ pim = vrf->info;
+ frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+ if (pim_up_mlag_is_local(up))
+ pim_mlag_up_local_add_send(pim, up);
+ }
+ }
+}
+
+/* on local/peer mlag connection and role changes the DF status needs
+ * to be re-evaluated
+ */
+static void pim_mlag_up_local_reeval(bool mlagd_send, const char *reason_code)
+{
+ struct pim_upstream *up;
+ struct vrf *vrf;
+ struct pim_instance *pim;
+
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("%s re-run DF election because of %s",
+ __func__, reason_code);
+ RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
+ pim = vrf->info;
+ frr_each (rb_pim_upstream, &pim->upstream_head, up) {
+ if (!pim_up_mlag_is_local(up))
+ continue;
+ /* if role changes re-send to peer */
+ if (pim_mlag_up_df_role_elect(pim, up) &&
+ mlagd_send)
+ pim_mlag_up_local_add_send(pim, up);
+ }
+ }
+}
+
+/*****************PIM Actions for MLAG state changes**********************/
+
+/* notify the anycast VTEP component about state changes */
+static inline void pim_mlag_vxlan_state_update(void)
+{
+ bool enable = !!(router->mlag_flags & PIM_MLAGF_STATUS_RXED);
+ bool peer_state = !!(router->mlag_flags & PIM_MLAGF_PEER_CONN_UP);
+
+ pim_vxlan_mlag_update(enable, peer_state, router->mlag_role,
+ router->peerlink_rif_p, &router->local_vtep_ip);
+
+}
+
+/**************End of PIM Actions for MLAG State changes******************/
+
/********************API to process PIM MLAG Data ************************/
static void pim_mlag_process_mlagd_state_change(struct mlag_status msg)
{
+ bool role_chg = false;
+ bool state_chg = false;
+ bool notify_vxlan = false;
+ struct interface *peerlink_rif_p;
char buf[MLAG_ROLE_STRSIZE];
if (PIM_DEBUG_MLAG)
@@ -41,6 +489,84 @@ static void pim_mlag_process_mlagd_state_change(struct mlag_status msg)
mlag_role2str(msg.my_role, buf, sizeof(buf)),
(msg.peer_state == MLAG_STATE_RUNNING ? "RUNNING"
: "DOWN"));
+
+ if (!(router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)) {
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("%s: msg ignored mlagd process state down",
+ __func__);
+ return;
+ }
+ ++router->mlag_stats.msg.mlag_status_updates;
+
+ /* evaluate the changes first */
+ if (router->mlag_role != msg.my_role) {
+ role_chg = true;
+ notify_vxlan = true;
+ router->mlag_role = msg.my_role;
+ }
+
+ strcpy(router->peerlink_rif, msg.peerlink_rif);
+ /* XXX - handle the case where we may rx the interface name from the
+ * MLAG daemon before we get the interface from zebra.
+ */
+ peerlink_rif_p = if_lookup_by_name(router->peerlink_rif, VRF_DEFAULT);
+ if (router->peerlink_rif_p != peerlink_rif_p) {
+ router->peerlink_rif_p = peerlink_rif_p;
+ notify_vxlan = true;
+ }
+
+ if (msg.peer_state == MLAG_STATE_RUNNING) {
+ if (!(router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)) {
+ state_chg = true;
+ notify_vxlan = true;
+ router->mlag_flags |= PIM_MLAGF_PEER_CONN_UP;
+ }
+ router->connected_to_mlag = true;
+ } else {
+ if (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP) {
+ ++router->mlag_stats.peer_session_downs;
+ state_chg = true;
+ notify_vxlan = true;
+ router->mlag_flags &= ~PIM_MLAGF_PEER_CONN_UP;
+ }
+ router->connected_to_mlag = false;
+ }
+
+ /* apply the changes */
+ /* when connection to mlagd comes up we hold send mroutes till we have
+ * rxed the status and had a chance to re-valuate DF state
+ */
+ if (!(router->mlag_flags & PIM_MLAGF_STATUS_RXED)) {
+ router->mlag_flags |= PIM_MLAGF_STATUS_RXED;
+ pim_mlag_vxlan_state_update();
+ /* on session up re-eval DF status */
+ pim_mlag_up_local_reeval(false /*mlagd_send*/, "mlagd_up");
+ /* replay all the upstream entries to the local MLAG daemon */
+ pim_mlag_up_local_replay();
+ return;
+ }
+
+ if (notify_vxlan)
+ pim_mlag_vxlan_state_update();
+
+ if (state_chg) {
+ if (!(router->mlag_flags & PIM_MLAGF_PEER_CONN_UP))
+ /* when a connection goes down the primary takes over
+ * DF role for all entries
+ */
+ pim_mlag_up_local_reeval(true /*mlagd_send*/,
+ "peer_down");
+ else
+ /* XXX - when session comes up we need to wait for
+ * PEER_REPLAY_DONE before running re-election on
+ * local-mlag entries that are missing peer reference
+ */
+ pim_mlag_up_local_reeval(true /*mlagd_send*/,
+ "peer_up");
+ } else if (role_chg) {
+ /* MLAG role changed without a state change */
+ pim_mlag_up_local_reeval(true /*mlagd_send*/, "role_chg");
+ }
}
static void pim_mlag_process_peer_frr_state_change(struct mlag_frr_status msg)
@@ -49,37 +575,116 @@ static void pim_mlag_process_peer_frr_state_change(struct mlag_frr_status msg)
zlog_debug(
"%s: msg dump: peer_frr_state: %s", __func__,
(msg.frr_state == MLAG_FRR_STATE_UP ? "UP" : "DOWN"));
+
+ if (!(router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)) {
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("%s: msg ignored mlagd process state down",
+ __func__);
+ return;
+ }
+ ++router->mlag_stats.msg.peer_zebra_status_updates;
+
+ /* evaluate the changes first */
+ if (msg.frr_state == MLAG_FRR_STATE_UP) {
+ if (!(router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)) {
+ router->mlag_flags |= PIM_MLAGF_PEER_ZEBRA_UP;
+ /* XXX - when peer zebra comes up we need to wait for
+ * for some time to let the peer setup MDTs before
+ * before relinquishing DF status
+ */
+ pim_mlag_up_local_reeval(true /*mlagd_send*/,
+ "zebra_up");
+ }
+ } else {
+ if (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP) {
+ ++router->mlag_stats.peer_zebra_downs;
+ router->mlag_flags &= ~PIM_MLAGF_PEER_ZEBRA_UP;
+ /* when a peer zebra goes down we assume DF role */
+ pim_mlag_up_local_reeval(true /*mlagd_send*/,
+ "zebra_down");
+ }
+ }
}
static void pim_mlag_process_vxlan_update(struct mlag_vxlan *msg)
{
+ char addr_buf1[INET_ADDRSTRLEN];
+ char addr_buf2[INET_ADDRSTRLEN];
+ uint32_t local_ip;
+
+ if (!(router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)) {
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("%s: msg ignored mlagd process state down",
+ __func__);
+ return;
+ }
+
+ ++router->mlag_stats.msg.vxlan_updates;
+ router->anycast_vtep_ip.s_addr = htonl(msg->anycast_ip);
+ local_ip = htonl(msg->local_ip);
+ if (router->local_vtep_ip.s_addr != local_ip) {
+ router->local_vtep_ip.s_addr = local_ip;
+ pim_mlag_vxlan_state_update();
+ }
+
+ if (PIM_DEBUG_MLAG) {
+ inet_ntop(AF_INET, &router->local_vtep_ip,
+ addr_buf1, INET_ADDRSTRLEN);
+ inet_ntop(AF_INET, &router->anycast_vtep_ip,
+ addr_buf2, INET_ADDRSTRLEN);
+
+ zlog_debug("%s: msg dump: local-ip:%s, anycast-ip:%s",
+ __func__, addr_buf1, addr_buf2);
+ }
}
static void pim_mlag_process_mroute_add(struct mlag_mroute_add msg)
{
if (PIM_DEBUG_MLAG) {
zlog_debug(
- "%s: msg dump: vrf_name: %s, s.ip: 0x%x, g.ip: 0x%x cost: %u",
- __func__, msg.vrf_name, msg.source_ip, msg.group_ip,
- msg.cost_to_rp);
+ "%s: msg dump: vrf_name: %s, s.ip: 0x%x, g.ip: 0x%x cost: %u",
+ __func__, msg.vrf_name, msg.source_ip,
+ msg.group_ip, msg.cost_to_rp);
zlog_debug(
- "owner_id: %d, DR: %d, Dual active: %d, vrf_id: 0x%x intf_name: %s",
- msg.owner_id, msg.am_i_dr, msg.am_i_dual_active,
- msg.vrf_id, msg.intf_name);
+ "owner_id: %d, DR: %d, Dual active: %d, vrf_id: 0x%x intf_name: %s",
+ msg.owner_id, msg.am_i_dr, msg.am_i_dual_active,
+ msg.vrf_id, msg.intf_name);
+ }
+
+ if (!(router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)) {
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("%s: msg ignored mlagd process state down",
+ __func__);
+ return;
}
+
+ ++router->mlag_stats.msg.mroute_add_rx;
+
+ pim_mlag_up_peer_add(&msg);
}
static void pim_mlag_process_mroute_del(struct mlag_mroute_del msg)
{
if (PIM_DEBUG_MLAG) {
zlog_debug(
- "%s: msg dump: vrf_name: %s, s.ip: 0x%x, g.ip: 0x%x ",
- __func__, msg.vrf_name, msg.source_ip, msg.group_ip);
+ "%s: msg dump: vrf_name: %s, s.ip: 0x%x, g.ip: 0x%x ",
+ __func__, msg.vrf_name, msg.source_ip,
+ msg.group_ip);
zlog_debug("owner_id: %d, vrf_id: 0x%x intf_name: %s",
- msg.owner_id, msg.vrf_id, msg.intf_name);
+ msg.owner_id, msg.vrf_id, msg.intf_name);
}
-}
+ if (!(router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)) {
+ if (PIM_DEBUG_MLAG)
+ zlog_debug("%s: msg ignored mlagd process state down",
+ __func__);
+ return;
+ }
+
+ ++router->mlag_stats.msg.mroute_del_rx;
+
+ pim_mlag_up_peer_del(&msg);
+}
int pim_zebra_mlag_handle_msg(struct stream *s, int len)
{
@@ -179,11 +784,40 @@ int pim_zebra_mlag_process_up(void)
return 0;
}
+static void pim_mlag_param_reset(void)
+{
+ /* reset the cached params and stats */
+ router->mlag_flags &= ~(PIM_MLAGF_STATUS_RXED |
+ PIM_MLAGF_LOCAL_CONN_UP |
+ PIM_MLAGF_PEER_CONN_UP |
+ PIM_MLAGF_PEER_ZEBRA_UP);
+ router->local_vtep_ip.s_addr = INADDR_ANY;
+ router->anycast_vtep_ip.s_addr = INADDR_ANY;
+ router->mlag_role = MLAG_ROLE_NONE;
+ memset(&router->mlag_stats.msg, 0, sizeof(router->mlag_stats.msg));
+ router->peerlink_rif[0] = '\0';
+}
+
int pim_zebra_mlag_process_down(void)
{
if (PIM_DEBUG_MLAG)
zlog_debug("%s: Received Process-Down from Mlag", __func__);
+ /* Local CLAG is down, reset peer data and forward the traffic if
+ * we are DR
+ */
+ if (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
+ ++router->mlag_stats.peer_session_downs;
+ if (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
+ ++router->mlag_stats.peer_zebra_downs;
+ router->connected_to_mlag = false;
+ pim_mlag_param_reset();
+ /* on mlagd session down re-eval DF status */
+ pim_mlag_up_local_reeval(false /*mlagd_send*/, "mlagd_down");
+ /* flush all peer references */
+ pim_mlag_up_peer_del_all();
+ /* notify the vxlan component */
+ pim_mlag_vxlan_state_update();
return 0;
}
@@ -339,6 +973,7 @@ void pim_instance_mlag_terminate(struct pim_instance *pim)
void pim_mlag_init(void)
{
+ pim_mlag_param_reset();
router->pim_mlag_intf_cnt = 0;
router->connected_to_mlag = false;
router->mlag_fifo = stream_fifo_new();
diff --git a/pimd/pim_mlag.h b/pimd/pim_mlag.h
index e86fdae78f..dab29cc9a2 100644
--- a/pimd/pim_mlag.h
+++ b/pimd/pim_mlag.h
@@ -37,4 +37,10 @@ extern void pim_mlag_deregister(void);
extern int pim_zebra_mlag_process_up(void);
extern int pim_zebra_mlag_process_down(void);
extern int pim_zebra_mlag_handle_msg(struct stream *msg, int len);
+extern void pim_mlag_up_local_add(struct pim_instance *pim,
+ struct pim_upstream *upstream);
+extern void pim_mlag_up_local_del(struct pim_instance *pim,
+ struct pim_upstream *upstream);
+extern bool pim_mlag_up_df_role_update(struct pim_instance *pim,
+ struct pim_upstream *up, bool is_df, const char *reason);
#endif
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index 3459abbc19..4afd05ab76 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -262,7 +262,7 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
up = pim_upstream_find(pim_ifp->pim, &star);
- if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) {
+ if (up && PIM_UPSTREAM_FLAG_TEST_CAN_BE_LHR(up->flags)) {
up = pim_upstream_add(pim_ifp->pim, &sg, ifp,
PIM_UPSTREAM_FLAG_MASK_SRC_LHR,
__PRETTY_FUNCTION__, NULL);
diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c
index 5cb9492ec3..9efeeaee27 100644
--- a/pimd/pim_nht.c
+++ b/pimd/pim_nht.c
@@ -561,6 +561,13 @@ static int pim_ecmp_nexthop_search(struct pim_instance *pim,
"%s: current nexthop does not have nbr ",
__PRETTY_FUNCTION__);
} else {
+ /* update metric even if the upstream
+ * neighbor stays unchanged
+ */
+ nexthop->mrib_metric_preference =
+ pnc->distance;
+ nexthop->mrib_route_metric =
+ pnc->metric;
if (PIM_DEBUG_PIM_NHT) {
char src_str[INET_ADDRSTRLEN];
pim_inet4_dump("<addr?>",
diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c
index 24519adb1e..b27374e302 100644
--- a/pimd/pim_rpf.c
+++ b/pimd/pim_rpf.c
@@ -36,6 +36,7 @@
#include "pim_time.h"
#include "pim_nht.h"
#include "pim_oil.h"
+#include "pim_mlag.h"
static struct in_addr pim_rpf_find_rpf_addr(struct pim_upstream *up);
@@ -194,6 +195,32 @@ static int nexthop_mismatch(const struct pim_nexthop *nh1,
|| (nh1->mrib_route_metric != nh2->mrib_route_metric);
}
+static void pim_rpf_cost_change(struct pim_instance *pim,
+ struct pim_upstream *up, uint32_t old_cost)
+{
+ struct pim_rpf *rpf = &up->rpf;
+ uint32_t new_cost;
+
+ new_cost = pim_up_mlag_local_cost(up);
+ if (PIM_DEBUG_MLAG)
+ zlog_debug(
+ "%s: Cost_to_rp of upstream-%s changed to:%u, from:%u",
+ __func__, up->sg_str, new_cost, old_cost);
+
+ if (old_cost == new_cost)
+ return;
+
+ /* Cost changed, it might Impact MLAG DF election, update */
+ if (PIM_DEBUG_MLAG)
+ zlog_debug(
+ "%s: Cost_to_rp of upstream-%s changed to:%u",
+ __func__, up->sg_str,
+ rpf->source_nexthop.mrib_route_metric);
+
+ if (pim_up_mlag_is_local(up))
+ pim_mlag_up_local_add(pim, up);
+}
+
enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
struct pim_upstream *up, struct pim_rpf *old,
const char *caller)
@@ -203,6 +230,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
struct prefix nht_p;
struct prefix src, grp;
bool neigh_needed = true;
+ uint32_t saved_mrib_route_metric;
if (PIM_UPSTREAM_FLAG_TEST_STATIC_IIF(up->flags))
return PIM_RPF_OK;
@@ -215,6 +243,7 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
saved.source_nexthop = rpf->source_nexthop;
saved.rpf_addr = rpf->rpf_addr;
+ saved_mrib_route_metric = pim_up_mlag_local_cost(up);
if (old) {
old->source_nexthop = saved.source_nexthop;
old->rpf_addr = saved.rpf_addr;
@@ -236,8 +265,12 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
neigh_needed = false;
pim_find_or_track_nexthop(pim, &nht_p, up, NULL, false, NULL);
if (!pim_ecmp_nexthop_lookup(pim, &rpf->source_nexthop, &src, &grp,
- neigh_needed))
+ neigh_needed)) {
+ /* Route is Deleted in Zebra, reset the stored NH data */
+ pim_upstream_rpf_clear(pim, up);
+ pim_rpf_cost_change(pim, up, saved_mrib_route_metric);
return PIM_RPF_FAILURE;
+ }
rpf->rpf_addr.family = AF_INET;
rpf->rpf_addr.u.prefix4 = pim_rpf_find_rpf_addr(up);
@@ -290,10 +323,18 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
if (saved.rpf_addr.u.prefix4.s_addr != rpf->rpf_addr.u.prefix4.s_addr
|| saved.source_nexthop
.interface != rpf->source_nexthop.interface) {
-
+ pim_rpf_cost_change(pim, up, saved_mrib_route_metric);
return PIM_RPF_CHANGED;
}
+ if (PIM_DEBUG_MLAG)
+ zlog_debug(
+ "%s(%s): Cost_to_rp of upstream-%s changed to:%u",
+ __func__, caller, up->sg_str,
+ rpf->source_nexthop.mrib_route_metric);
+
+ pim_rpf_cost_change(pim, up, saved_mrib_route_metric);
+
return PIM_RPF_OK;
}
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index c899e403c8..444ab938f2 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -52,6 +52,7 @@
#include "pim_nht.h"
#include "pim_ssm.h"
#include "pim_vxlan.h"
+#include "pim_mlag.h"
static void join_timer_stop(struct pim_upstream *up);
static void
@@ -193,6 +194,9 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
zlog_debug("pim_upstream free vrf:%s %s flags 0x%x",
pim->vrf->name, up->sg_str, up->flags);
+ if (pim_up_mlag_is_local(up))
+ pim_mlag_up_local_del(pim, up);
+
THREAD_OFF(up->t_ka_timer);
THREAD_OFF(up->t_rs_timer);
THREAD_OFF(up->t_msdp_reg_timer);
@@ -883,6 +887,26 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
}
}
+ /* If (S, G) inherit the MLAG_VXLAN from the parent
+ * (*, G) entry.
+ */
+ if ((up->sg.src.s_addr != INADDR_ANY) &&
+ up->parent &&
+ PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(up->parent->flags) &&
+ !PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN_ORIG(up->flags)) {
+ PIM_UPSTREAM_FLAG_SET_MLAG_VXLAN(up->flags);
+ if (PIM_DEBUG_VXLAN)
+ zlog_debug("upstream %s inherited mlag vxlan flag from parent",
+ up->sg_str);
+ }
+
+ /* send the entry to the MLAG peer */
+ /* XXX - duplicate send is possible here if pim_rpf_update
+ * successfully resolved the nexthop
+ */
+ if (pim_up_mlag_is_local(up))
+ pim_mlag_up_local_add(pim, up);
+
if (PIM_DEBUG_PIM_TRACE) {
zlog_debug(
"%s: Created Upstream %s upstream_addr %s ref count %d increment",
@@ -893,6 +917,30 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
return up;
}
+uint32_t pim_up_mlag_local_cost(struct pim_upstream *up)
+{
+ if (!(pim_up_mlag_is_local(up)))
+ return router->infinite_assert_metric.route_metric;
+
+ if ((up->rpf.source_nexthop.interface ==
+ up->pim->vxlan.peerlink_rif) &&
+ (up->rpf.source_nexthop.mrib_route_metric <
+ (router->infinite_assert_metric.route_metric -
+ PIM_UPSTREAM_MLAG_PEERLINK_PLUS_METRIC)))
+ return up->rpf.source_nexthop.mrib_route_metric +
+ PIM_UPSTREAM_MLAG_PEERLINK_PLUS_METRIC;
+
+ return up->rpf.source_nexthop.mrib_route_metric;
+}
+
+uint32_t pim_up_mlag_peer_cost(struct pim_upstream *up)
+{
+ if (!(up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_PEER))
+ return router->infinite_assert_metric.route_metric;
+
+ return up->mlag.peer_mrib_metric;
+}
+
struct pim_upstream *pim_upstream_find(struct pim_instance *pim,
struct prefix_sg *sg)
{
@@ -916,6 +964,15 @@ struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg,
void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name)
{
+ /* if a local MLAG reference is being created we need to send the mroute
+ * to the peer
+ */
+ if (!PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(up->flags) &&
+ PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(flags)) {
+ PIM_UPSTREAM_FLAG_SET_MLAG_VXLAN(up->flags);
+ pim_mlag_up_local_add(up->pim, up);
+ }
+
/* when we go from non-FHR to FHR we need to re-eval traffic
* forwarding path
*/
@@ -1950,8 +2007,9 @@ static void pim_upstream_sg_running(void *arg)
"source reference created on kat restart %s[%s]",
up->sg_str, pim->vrf->name);
- pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM,
- __PRETTY_FUNCTION__);
+ pim_upstream_ref(up,
+ PIM_UPSTREAM_FLAG_MASK_SRC_STREAM,
+ __PRETTY_FUNCTION__);
PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags);
pim_upstream_fhr_kat_start(up);
}
@@ -1974,7 +2032,7 @@ void pim_upstream_add_lhr_star_pimreg(struct pim_instance *pim)
if (up->sg.src.s_addr != INADDR_ANY)
continue;
- if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags))
+ if (!PIM_UPSTREAM_FLAG_TEST_CAN_BE_LHR(up->flags))
continue;
pim_channel_add_oif(up->channel_oil, pim->regiface,
@@ -2021,7 +2079,7 @@ void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim,
if (up->sg.src.s_addr != INADDR_ANY)
continue;
- if (!PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags))
+ if (!PIM_UPSTREAM_FLAG_TEST_CAN_BE_LHR(up->flags))
continue;
if (!nlist) {
diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h
index 1eb2052bb3..c717c467dc 100644
--- a/pimd/pim_upstream.h
+++ b/pimd/pim_upstream.h
@@ -74,6 +74,8 @@
* blackholing the traffic pulled down to the LHR.
*/
#define PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF (1 << 17)
+/* MLAG mroute rxed from the peer MLAG switch */
+#define PIM_UPSTREAM_FLAG_MASK_MLAG_PEER (1 << 18)
/*
* We are creating a non-joined upstream data structure
* for this S,G as that we want to have a channel oil
@@ -86,6 +88,12 @@
* This flag is only relevant for (S,G) entries.
*/
#define PIM_UPSTREAM_FLAG_MASK_USE_RPT (1 << 20)
+/* PIM Syncs upstream entries to peer Nodes via MLAG in 2 cases.
+ * one is to support plain PIM Redundancy and another one is to support
+ * PIM REdundancy.
+ */
+#define PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE (1 << 21)
+
#define PIM_UPSTREAM_FLAG_ALL 0xFFFFFFFF
@@ -108,8 +116,11 @@
#define PIM_UPSTREAM_FLAG_TEST_SRC_VXLAN(flags) ((flags) & (PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_ORIG | PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM))
#define PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN)
#define PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF)
+#define PIM_UPSTREAM_FLAG_TEST_MLAG_PEER(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_MLAG_PEER)
#define PIM_UPSTREAM_FLAG_TEST_SRC_NOCACHE(flags) ((flags) &PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE)
#define PIM_UPSTREAM_FLAG_TEST_USE_RPT(flags) ((flags) & PIM_UPSTREAM_FLAG_MASK_USE_RPT)
+#define PIM_UPSTREAM_FLAG_TEST_CAN_BE_LHR(flags) ((flags) & (PIM_UPSTREAM_FLAG_MASK_SRC_IGMP | PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM))
+#define PIM_UPSTREAM_FLAG_TEST_MLAG_INTERFACE(flags) ((flags)&PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE)
#define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
#define PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
@@ -129,7 +140,9 @@
#define PIM_UPSTREAM_FLAG_SET_SRC_VXLAN_TERM(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM)
#define PIM_UPSTREAM_FLAG_SET_MLAG_VXLAN(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN)
#define PIM_UPSTREAM_FLAG_SET_MLAG_NON_DF(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF)
+#define PIM_UPSTREAM_FLAG_SET_MLAG_PEER(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_MLAG_PEER)
#define PIM_UPSTREAM_FLAG_SET_USE_RPT(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_USE_RPT)
+#define PIM_UPSTREAM_FLAG_SET_MLAG_INTERFACE(flags) ((flags) |= PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE)
#define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED)
#define PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_DR_JOIN_DESIRED_UPDATED)
@@ -149,8 +162,16 @@
#define PIM_UPSTREAM_FLAG_UNSET_SRC_VXLAN_TERM(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM)
#define PIM_UPSTREAM_FLAG_UNSET_MLAG_VXLAN(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN)
#define PIM_UPSTREAM_FLAG_UNSET_MLAG_NON_DF(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_MLAG_NON_DF)
+#define PIM_UPSTREAM_FLAG_UNSET_MLAG_PEER(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_MLAG_PEER)
#define PIM_UPSTREAM_FLAG_UNSET_SRC_NOCACHE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_SRC_NOCACHE)
#define PIM_UPSTREAM_FLAG_UNSET_USE_RPT(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_USE_RPT)
+#define PIM_UPSTREAM_FLAG_UNSET_MLAG_INTERFACE(flags) ((flags) &= ~PIM_UPSTREAM_FLAG_MASK_MLAG_INTERFACE)
+
+/* The RPF cost is incremented by 10 if the RPF interface is the peerlink-rif.
+ * This is used to force the MLAG switch with the lowest cost to the RPF
+ * to become the MLAG DF.
+ */
+#define PIM_UPSTREAM_MLAG_PEERLINK_PLUS_METRIC 10
enum pim_upstream_state {
PIM_UPSTREAM_NOTJOINED,
@@ -169,6 +190,13 @@ enum pim_upstream_sptbit {
PIM_UPSTREAM_SPTBIT_TRUE
};
+struct pim_up_mlag {
+ /* MRIB.metric(S) from the peer switch. This is used for DF election
+ * and switch with the lowest cost wins.
+ */
+ uint32_t peer_mrib_metric;
+};
+
PREDECL_RBTREE_UNIQ(rb_pim_upstream);
/*
Upstream (S,G) channel in Joined state
@@ -218,6 +246,8 @@ struct pim_upstream {
struct pim_rpf rpf;
+ struct pim_up_mlag mlag;
+
struct thread *t_join_timer;
/*
@@ -249,6 +279,14 @@ static inline bool pim_upstream_is_kat_running(struct pim_upstream *up)
return (up->t_ka_timer != NULL);
}
+static inline bool pim_up_mlag_is_local(struct pim_upstream *up)
+{
+ /* XXX: extend this to also return true if the channel-oil has
+ * any AA devices
+ */
+ return (up->flags & PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN);
+}
+
struct pim_upstream *pim_upstream_find(struct pim_instance *pim,
struct prefix_sg *sg);
struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg,
@@ -259,7 +297,8 @@ struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
struct interface *ifp, int flags,
const char *name,
struct pim_ifchannel *ch);
-void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name);
+void pim_upstream_ref(struct pim_upstream *up,
+ int flags, const char *name);
struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
struct pim_upstream *up,
const char *name);
@@ -350,5 +389,7 @@ void pim_upstream_fill_static_iif(struct pim_upstream *up,
struct interface *incoming);
void pim_upstream_update_use_rpt(struct pim_upstream *up,
bool update_mroute);
+uint32_t pim_up_mlag_local_cost(struct pim_upstream *up);
+uint32_t pim_up_mlag_peer_cost(struct pim_upstream *up);
void pim_upstream_reeval_use_rpt(struct pim_instance *pim);
#endif /* PIM_UPSTREAM_H */
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index c48ec373f8..b5a5089ae7 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -242,8 +242,6 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
}
}
- pim_vxlan_config_write(vty, spaces, &writes);
-
return writes;
}
diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c
index fc34f3f600..57b922a531 100644
--- a/pimd/pim_vxlan.c
+++ b/pimd/pim_vxlan.c
@@ -38,6 +38,7 @@
#include "pim_nht.h"
#include "pim_zebra.h"
#include "pim_vxlan.h"
+#include "pim_mlag.h"
/* pim-vxlan global info */
struct pim_vxlan vxlan_info, *pim_vxlan_p = &vxlan_info;
@@ -476,13 +477,14 @@ static void pim_vxlan_orig_mr_del(struct pim_vxlan_sg *vxlan_sg)
static void pim_vxlan_orig_mr_iif_update(struct hash_backet *backet, void *arg)
{
- struct interface *ifp = (struct interface *)arg;
+ struct interface *ifp;
struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
struct interface *old_iif = vxlan_sg->iif;
if (!pim_vxlan_is_orig_mroute(vxlan_sg))
return;
+ ifp = pim_vxlan_orig_mr_iif_get(vxlan_sg->pim);
if (PIM_DEBUG_VXLAN)
zlog_debug("vxlan SG %s iif changed from %s to %s",
vxlan_sg->sg_str,
@@ -529,8 +531,15 @@ static void pim_vxlan_term_mr_oif_add(struct pim_vxlan_sg *vxlan_sg)
vxlan_sg->sg_str, vxlan_sg->term_oif->name);
if (pim_ifchannel_local_membership_add(vxlan_sg->term_oif,
- &vxlan_sg->sg)) {
+ &vxlan_sg->sg, true /*is_vxlan */)) {
vxlan_sg->flags |= PIM_VXLAN_SGF_OIF_INSTALLED;
+ /* update the inherited OIL */
+ /* XXX - I don't see the inherited OIL updated when a local
+ * member is added. And that probably needs to be fixed. Till
+ * that happens we do a force update on the inherited OIL
+ * here.
+ */
+ pim_upstream_inherited_olist(vxlan_sg->pim, vxlan_sg->up);
} else {
zlog_warn("vxlan SG %s term-oif %s add failed",
vxlan_sg->sg_str, vxlan_sg->term_oif->name);
@@ -548,6 +557,43 @@ static void pim_vxlan_term_mr_oif_del(struct pim_vxlan_sg *vxlan_sg)
vxlan_sg->flags &= ~PIM_VXLAN_SGF_OIF_INSTALLED;
pim_ifchannel_local_membership_del(vxlan_sg->term_oif, &vxlan_sg->sg);
+ /* update the inherited OIL */
+ /* XXX - I don't see the inherited OIL updated when a local member
+ * is deleted. And that probably needs to be fixed. Till that happens
+ * we do a force update on the inherited OIL here.
+ */
+ pim_upstream_inherited_olist(vxlan_sg->pim, vxlan_sg->up);
+}
+
+static void pim_vxlan_update_sg_entry_mlag(struct pim_instance *pim,
+ struct pim_upstream *up, bool inherit)
+{
+ bool is_df = true;
+
+ if (inherit && up->parent &&
+ PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(up->parent->flags) &&
+ PIM_UPSTREAM_FLAG_TEST_MLAG_NON_DF(up->parent->flags))
+ is_df = false;
+
+ pim_mlag_up_df_role_update(pim, up, is_df, "inherit_xg_df");
+}
+
+/* We run MLAG DF election only on mroutes that have the termination
+ * device ipmr-lo in the immediate OIL. This is only (*, G) entries at the
+ * moment. For (S, G) entries that (with ipmr-lo in the inherited OIL) we
+ * inherit the DF role from the (*, G) entry.
+ */
+void pim_vxlan_inherit_mlag_flags(struct pim_instance *pim,
+ struct pim_upstream *up, bool inherit)
+{
+ struct listnode *listnode;
+ struct pim_upstream *child;
+
+ for (ALL_LIST_ELEMENTS_RO(up->sources, listnode,
+ child)) {
+ pim_vxlan_update_sg_entry_mlag(pim,
+ child, true /* inherit */);
+ }
}
static void pim_vxlan_term_mr_up_add(struct pim_vxlan_sg *vxlan_sg)
@@ -576,7 +622,11 @@ static void pim_vxlan_term_mr_up_add(struct pim_vxlan_sg *vxlan_sg)
if (!up) {
zlog_warn("vxlan SG %s term mroute-up add failed",
vxlan_sg->sg_str);
+ return;
}
+
+ /* update existing SG entries with the parent's MLAG flag */
+ pim_vxlan_inherit_mlag_flags(vxlan_sg->pim, up, true /*enable*/);
}
static void pim_vxlan_term_mr_up_del(struct pim_vxlan_sg *vxlan_sg)
@@ -591,10 +641,13 @@ static void pim_vxlan_term_mr_up_del(struct pim_vxlan_sg *vxlan_sg)
vxlan_sg->sg_str);
vxlan_sg->up = NULL;
if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM) {
+ /* update SG entries that are inheriting from this XG entry */
+ pim_vxlan_inherit_mlag_flags(vxlan_sg->pim, up,
+ false /*enable*/);
/* clear out all the vxlan related flags */
up->flags &= ~(PIM_UPSTREAM_FLAG_MASK_SRC_VXLAN_TERM |
PIM_UPSTREAM_FLAG_MASK_MLAG_VXLAN);
-
+ pim_mlag_up_local_del(vxlan_sg->pim, up);
pim_upstream_del(vxlan_sg->pim, up,
__PRETTY_FUNCTION__);
}
@@ -660,6 +713,14 @@ static struct pim_vxlan_sg *pim_vxlan_sg_new(struct pim_instance *pim,
vxlan_sg = hash_get(pim->vxlan.sg_hash, vxlan_sg, hash_alloc_intern);
+ /* we register with the MLAG daemon in the first VxLAN SG and never
+ * de-register during that life of the pimd
+ */
+ if (pim->vxlan.sg_hash->count == 1) {
+ vxlan_mlag.flags |= PIM_VXLAN_MLAGF_DO_REG;
+ pim_mlag_register();
+ }
+
return vxlan_sg;
}
@@ -717,12 +778,18 @@ void pim_vxlan_sg_del(struct pim_instance *pim, struct prefix_sg *sg)
}
/******************************* MLAG handling *******************************/
+bool pim_vxlan_do_mlag_reg(void)
+{
+ return (vxlan_mlag.flags & PIM_VXLAN_MLAGF_DO_REG);
+}
+
/* The peerlink sub-interface is added as an OIF to the origination-mroute.
* This is done to send a copy of the multicast-vxlan encapsulated traffic
* to the MLAG peer which may mroute it over the underlay if there are any
* interested receivers.
*/
-static void pim_vxlan_sg_peerlink_update(struct hash_backet *backet, void *arg)
+static void pim_vxlan_sg_peerlink_oif_update(struct hash_backet *backet,
+ void *arg)
{
struct interface *new_oif = (struct interface *)arg;
struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
@@ -761,8 +828,6 @@ void pim_vxlan_mlag_update(bool enable, bool peer_state, uint32_t role,
struct in_addr *reg_addr)
{
struct pim_instance *pim;
- struct interface *old_oif;
- struct interface *new_oif;
char addr_buf[INET_ADDRSTRLEN];
struct pim_interface *pim_ifp = NULL;
@@ -782,8 +847,6 @@ void pim_vxlan_mlag_update(bool enable, bool peer_state, uint32_t role,
*/
pim = pim_get_pim_instance(VRF_DEFAULT);
- old_oif = pim_vxlan_orig_mr_oif_get(pim);
-
if (enable)
vxlan_mlag.flags |= PIM_VXLAN_MLAGF_ENABLED;
else
@@ -804,35 +867,9 @@ void pim_vxlan_mlag_update(bool enable, bool peer_state, uint32_t role,
pim_vxlan_set_peerlink_rif(pim, peerlink_rif);
else
pim_vxlan_set_peerlink_rif(pim, NULL);
-
- new_oif = pim_vxlan_orig_mr_oif_get(pim);
- if (old_oif != new_oif)
- hash_iterate(pim->vxlan.sg_hash, pim_vxlan_sg_peerlink_update,
- new_oif);
}
/****************************** misc callbacks *******************************/
-void pim_vxlan_config_write(struct vty *vty, char *spaces, int *writes)
-{
- char addr_buf[INET_ADDRSTRLEN];
-
- if ((vxlan_mlag.flags & PIM_VXLAN_MLAGF_ENABLED) &&
- vxlan_mlag.peerlink_rif) {
-
- inet_ntop(AF_INET, &vxlan_mlag.reg_addr,
- addr_buf, sizeof(addr_buf));
- vty_out(vty,
- "%sip pim mlag %s role %s state %s addr %s\n",
- spaces,
- vxlan_mlag.peerlink_rif->name,
- (vxlan_mlag.role == PIM_VXLAN_MLAG_ROLE_PRIMARY) ?
- "primary":"secondary",
- vxlan_mlag.peer_state ? "up" : "down",
- addr_buf);
- *writes += 1;
- }
-}
-
static void pim_vxlan_set_default_iif(struct pim_instance *pim,
struct interface *ifp)
{
@@ -864,13 +901,72 @@ static void pim_vxlan_set_default_iif(struct pim_instance *pim,
*/
if (pim->vxlan.sg_hash)
hash_iterate(pim->vxlan.sg_hash,
- pim_vxlan_orig_mr_iif_update, ifp);
+ pim_vxlan_orig_mr_iif_update, NULL);
+}
+
+static void pim_vxlan_up_cost_update(struct pim_instance *pim,
+ struct pim_upstream *up,
+ struct interface *old_peerlink_rif)
+{
+ if (!PIM_UPSTREAM_FLAG_TEST_MLAG_VXLAN(up->flags))
+ return;
+
+ if (up->rpf.source_nexthop.interface &&
+ ((up->rpf.source_nexthop.interface ==
+ pim->vxlan.peerlink_rif) ||
+ (up->rpf.source_nexthop.interface ==
+ old_peerlink_rif))) {
+ if (PIM_DEBUG_VXLAN)
+ zlog_debug("RPF cost adjust for %s on peerlink-rif (old: %s, new: %s) change",
+ up->sg_str,
+ old_peerlink_rif ?
+ old_peerlink_rif->name : "-",
+ pim->vxlan.peerlink_rif ?
+ pim->vxlan.peerlink_rif->name : "-");
+ pim_mlag_up_local_add(pim, up);
+ }
+}
+
+static void pim_vxlan_term_mr_cost_update(struct hash_backet *backet,
+ void *arg)
+{
+ struct interface *old_peerlink_rif = (struct interface *)arg;
+ struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
+ struct pim_upstream *up;
+ struct listnode *listnode;
+ struct pim_upstream *child;
+
+ if (pim_vxlan_is_orig_mroute(vxlan_sg))
+ return;
+
+ /* Lookup all XG and SG entries with RPF-interface peerlink_rif */
+ up = vxlan_sg->up;
+ if (!up)
+ return;
+
+ pim_vxlan_up_cost_update(vxlan_sg->pim, up,
+ old_peerlink_rif);
+
+ for (ALL_LIST_ELEMENTS_RO(up->sources, listnode,
+ child))
+ pim_vxlan_up_cost_update(vxlan_sg->pim, child,
+ old_peerlink_rif);
+}
+
+static void pim_vxlan_sg_peerlink_rif_update(struct hash_backet *backet,
+ void *arg)
+{
+ pim_vxlan_orig_mr_iif_update(backet, NULL);
+ pim_vxlan_term_mr_cost_update(backet, arg);
}
static void pim_vxlan_set_peerlink_rif(struct pim_instance *pim,
struct interface *ifp)
{
struct interface *old_iif;
+ struct interface *new_iif;
+ struct interface *old_oif;
+ struct interface *new_oif;
if (pim->vxlan.peerlink_rif == ifp)
return;
@@ -882,22 +978,77 @@ static void pim_vxlan_set_peerlink_rif(struct pim_instance *pim,
ifp ? ifp->name : "-");
old_iif = pim_vxlan_orig_mr_iif_get(pim);
+ old_oif = pim_vxlan_orig_mr_oif_get(pim);
pim->vxlan.peerlink_rif = ifp;
- ifp = pim_vxlan_orig_mr_iif_get(pim);
- if (old_iif == ifp)
+
+ new_iif = pim_vxlan_orig_mr_iif_get(pim);
+ if (old_iif != new_iif) {
+ if (PIM_DEBUG_VXLAN)
+ zlog_debug("%s: vxlan orig iif changed from %s to %s",
+ __PRETTY_FUNCTION__,
+ old_iif ? old_iif->name : "-",
+ new_iif ? new_iif->name : "-");
+
+ /* add/del upstream entries for the existing vxlan SG when the
+ * interface becomes available
+ */
+ if (pim->vxlan.sg_hash)
+ hash_iterate(pim->vxlan.sg_hash,
+ pim_vxlan_sg_peerlink_rif_update,
+ old_iif);
+ }
+
+ new_oif = pim_vxlan_orig_mr_oif_get(pim);
+ if (old_oif != new_oif) {
+ if (PIM_DEBUG_VXLAN)
+ zlog_debug("%s: vxlan orig oif changed from %s to %s",
+ __PRETTY_FUNCTION__,
+ old_oif ? old_oif->name : "-",
+ new_oif ? new_oif->name : "-");
+ if (pim->vxlan.sg_hash)
+ hash_iterate(pim->vxlan.sg_hash,
+ pim_vxlan_sg_peerlink_oif_update,
+ new_oif);
+ }
+}
+
+static void pim_vxlan_term_mr_oif_update(struct hash_backet *backet, void *arg)
+{
+ struct interface *ifp = (struct interface *)arg;
+ struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
+
+ if (pim_vxlan_is_orig_mroute(vxlan_sg))
+ return;
+
+ if (vxlan_sg->term_oif == ifp)
return;
if (PIM_DEBUG_VXLAN)
- zlog_debug("%s: vxlan orig iif changed from %s to %s",
- __PRETTY_FUNCTION__, old_iif ? old_iif->name : "-",
+ zlog_debug("vxlan SG %s term oif changed from %s to %s",
+ vxlan_sg->sg_str,
+ vxlan_sg->term_oif ? vxlan_sg->term_oif->name : "-",
ifp ? ifp->name : "-");
- /* add/del upstream entries for the existing vxlan SG when the
- * interface becomes available
- */
+ pim_vxlan_term_mr_del(vxlan_sg);
+ vxlan_sg->term_oif = ifp;
+ pim_vxlan_term_mr_add(vxlan_sg);
+}
+
+static void pim_vxlan_term_oif_update(struct pim_instance *pim,
+ struct interface *ifp)
+{
+ if (pim->vxlan.term_if == ifp)
+ return;
+
+ if (PIM_DEBUG_VXLAN)
+ zlog_debug("vxlan term oif changed from %s to %s",
+ pim->vxlan.term_if ? pim->vxlan.term_if->name : "-",
+ ifp ? ifp->name : "-");
+
+ pim->vxlan.term_if = ifp;
if (pim->vxlan.sg_hash)
hash_iterate(pim->vxlan.sg_hash,
- pim_vxlan_orig_mr_iif_update, ifp);
+ pim_vxlan_term_mr_oif_update, ifp);
}
void pim_vxlan_add_vif(struct interface *ifp)
@@ -914,6 +1065,9 @@ void pim_vxlan_add_vif(struct interface *ifp)
if (vxlan_mlag.flags & PIM_VXLAN_MLAGF_ENABLED &&
(ifp == vxlan_mlag.peerlink_rif))
pim_vxlan_set_peerlink_rif(pim, ifp);
+
+ if (pim->vxlan.term_if_cfg == ifp)
+ pim_vxlan_term_oif_update(pim, ifp);
}
void pim_vxlan_del_vif(struct interface *ifp)
@@ -929,76 +1083,56 @@ void pim_vxlan_del_vif(struct interface *ifp)
if (pim->vxlan.peerlink_rif == ifp)
pim_vxlan_set_peerlink_rif(pim, NULL);
-}
-
-static void pim_vxlan_term_mr_oif_update(struct hash_backet *backet, void *arg)
-{
- struct interface *ifp = (struct interface *)arg;
- struct pim_vxlan_sg *vxlan_sg = (struct pim_vxlan_sg *)backet->data;
- if (pim_vxlan_is_orig_mroute(vxlan_sg))
- return;
-
- if (vxlan_sg->term_oif == ifp)
- return;
-
- if (PIM_DEBUG_VXLAN)
- zlog_debug("vxlan SG %s term oif changed from %s to %s",
- vxlan_sg->sg_str,
- vxlan_sg->term_oif ? vxlan_sg->term_oif->name : "-",
- ifp ? ifp->name : "-");
-
- pim_vxlan_term_mr_del(vxlan_sg);
- vxlan_sg->term_oif = ifp;
- pim_vxlan_term_mr_add(vxlan_sg);
+ if (pim->vxlan.term_if == ifp)
+ pim_vxlan_term_oif_update(pim, NULL);
}
+/* enable pim implicitly on the termination device add */
void pim_vxlan_add_term_dev(struct pim_instance *pim,
struct interface *ifp)
{
struct pim_interface *pim_ifp;
- if (pim->vxlan.term_if == ifp)
+ if (pim->vxlan.term_if_cfg == ifp)
return;
if (PIM_DEBUG_VXLAN)
- zlog_debug("vxlan term oif changed from %s to %s",
- pim->vxlan.term_if ? pim->vxlan.term_if->name : "-",
- ifp->name);
+ zlog_debug("vxlan term oif cfg changed from %s to %s",
+ pim->vxlan.term_if_cfg ?
+ pim->vxlan.term_if_cfg->name : "-",
+ ifp->name);
+
+ pim->vxlan.term_if_cfg = ifp;
/* enable pim on the term ifp */
pim_ifp = (struct pim_interface *)ifp->info;
if (pim_ifp) {
PIM_IF_DO_PIM(pim_ifp->options);
+ /* ifp is already oper up; activate it as a term dev */
+ if (pim_ifp->mroute_vif_index >= 0)
+ pim_vxlan_term_oif_update(pim, ifp);
} else {
- pim_ifp = pim_if_new(ifp, false /*igmp*/, true /*pim*/,
- false /*pimreg*/, true /*vxlan_term*/);
- /* ensure that pimreg existss before using the newly created
+ /* ensure that pimreg exists before using the newly created
* vxlan termination device
*/
pim_if_create_pimreg(pim);
+ (void)pim_if_new(ifp, false /*igmp*/, true /*pim*/,
+ false /*pimreg*/, true /*vxlan_term*/);
}
-
- pim->vxlan.term_if = ifp;
-
- if (pim->vxlan.sg_hash)
- hash_iterate(pim_ifp->pim->vxlan.sg_hash,
- pim_vxlan_term_mr_oif_update, ifp);
}
+/* disable pim implicitly, if needed, on the termination device deletion */
void pim_vxlan_del_term_dev(struct pim_instance *pim)
{
- struct interface *ifp = pim->vxlan.term_if;
+ struct interface *ifp = pim->vxlan.term_if_cfg;
struct pim_interface *pim_ifp;
if (PIM_DEBUG_VXLAN)
- zlog_debug("vxlan term oif changed from %s to -", ifp->name);
+ zlog_debug("vxlan term oif cfg changed from %s to -",
+ ifp->name);
- pim->vxlan.term_if = NULL;
-
- if (pim->vxlan.sg_hash)
- hash_iterate(pim->vxlan.sg_hash,
- pim_vxlan_term_mr_oif_update, NULL);
+ pim->vxlan.term_if_cfg = NULL;
pim_ifp = (struct pim_interface *)ifp->info;
if (pim_ifp) {
@@ -1006,7 +1140,6 @@ void pim_vxlan_del_term_dev(struct pim_instance *pim)
if (!PIM_IF_TEST_IGMP(pim_ifp->options))
pim_if_delete(ifp);
}
-
}
void pim_vxlan_init(struct pim_instance *pim)
diff --git a/pimd/pim_vxlan.h b/pimd/pim_vxlan.h
index c6507a474c..198d1c3281 100644
--- a/pimd/pim_vxlan.h
+++ b/pimd/pim_vxlan.h
@@ -66,17 +66,14 @@ struct pim_vxlan_sg {
enum pim_vxlan_mlag_flags {
PIM_VXLAN_MLAGF_NONE = 0,
- PIM_VXLAN_MLAGF_ENABLED = (1 << 0)
-};
-
-enum pim_vxlan_mlag_role {
- PIM_VXLAN_MLAG_ROLE_SECONDARY = 0,
- PIM_VXLAN_MLAG_ROLE_PRIMARY
+ PIM_VXLAN_MLAGF_ENABLED = (1 << 0),
+ PIM_VXLAN_MLAGF_DO_REG = (1 << 1)
};
struct pim_vxlan_mlag {
enum pim_vxlan_mlag_flags flags;
- enum pim_vxlan_mlag_role role;
+ /* XXX - remove this variable from here */
+ int role;
bool peer_state;
/* routed interface setup on top of MLAG peerlink */
struct interface *peerlink_rif;
@@ -122,6 +119,12 @@ static inline bool pim_vxlan_is_local_sip(struct pim_upstream *up)
if_is_loopback_or_vrf(up->rpf.source_nexthop.interface);
}
+static inline bool pim_vxlan_is_term_dev_cfg(struct pim_instance *pim,
+ struct interface *ifp)
+{
+ return pim->vxlan.term_if_cfg == ifp;
+}
+
extern struct pim_vxlan *pim_vxlan_p;
extern struct pim_vxlan_sg *pim_vxlan_sg_find(struct pim_instance *pim,
struct prefix_sg *sg);
@@ -141,6 +144,8 @@ extern bool pim_vxlan_get_register_src(struct pim_instance *pim,
extern void pim_vxlan_mlag_update(bool enable, bool peer_state, uint32_t role,
struct interface *peerlink_rif,
struct in_addr *reg_addr);
-extern void pim_vxlan_config_write(struct vty *vty, char *spaces, int *writes);
+extern bool pim_vxlan_do_mlag_reg(void);
+extern void pim_vxlan_inherit_mlag_flags(struct pim_instance *pim,
+ struct pim_upstream *up, bool inherit);
#endif /* PIM_VXLAN_H */
diff --git a/pimd/pim_vxlan_instance.h b/pimd/pim_vxlan_instance.h
index 3f99483fbe..5b35bcbeaa 100644
--- a/pimd/pim_vxlan_instance.h
+++ b/pimd/pim_vxlan_instance.h
@@ -36,6 +36,7 @@ struct pim_vxlan_instance {
/* device used by the dataplane to terminate multicast encapsulated
* vxlan traffic
*/
+ struct interface *term_if_cfg;
struct interface *term_if;
};
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index 06507b1f4c..baa6216df2 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -452,7 +452,7 @@ static void pim_zebra_connected(struct zclient *zclient)
static void pim_zebra_capabilities(struct zclient_capabilities *cap)
{
- router->role = cap->role;
+ router->mlag_role = cap->role;
}
void pim_zebra_init(void)
@@ -547,7 +547,8 @@ static void igmp_source_forward_reevaluate_one(struct pim_instance *pim,
"local membership add for %s as G is now ASM",
pim_str_sg_dump(&sg));
pim_ifchannel_local_membership_add(
- group->group_igmp_sock->interface, &sg);
+ group->group_igmp_sock->interface, &sg,
+ false /*is_vxlan*/);
}
}
}
@@ -765,7 +766,8 @@ void igmp_source_forward_start(struct pim_instance *pim,
per-interface (S,G) state.
*/
if (!pim_ifchannel_local_membership_add(
- group->group_igmp_sock->interface, &sg)) {
+ group->group_igmp_sock->interface, &sg,
+ false /*is_vxlan*/)) {
if (PIM_DEBUG_MROUTE)
zlog_warn("%s: Failure to add local membership for %s",
__PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
diff --git a/pimd/pimd.c b/pimd/pimd.c
index 889a83a136..0a7ac3b31f 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -50,6 +50,7 @@ const char *const PIM_ALL_IGMP_ROUTERS = MCAST_ALL_IGMP_ROUTERS;
DEFINE_MTYPE_STATIC(PIMD, ROUTER, "PIM Router information");
struct pim_router *router = NULL;
+struct in_addr qpim_all_pim_routers_addr;
void pim_prefix_list_update(struct prefix_list *plist)
{
diff --git a/pimd/pimd.h b/pimd/pimd.h
index 70d2766220..88e692b50d 100644
--- a/pimd/pimd.h
+++ b/pimd/pimd.h
@@ -131,14 +131,14 @@
#define PIM_UPDATE_SOURCE_DUP -10
#define PIM_GROUP_BAD_ADDR_MASK_COMBO -11
-const char *const PIM_ALL_SYSTEMS;
-const char *const PIM_ALL_ROUTERS;
-const char *const PIM_ALL_PIM_ROUTERS;
-const char *const PIM_ALL_IGMP_ROUTERS;
+extern const char *const PIM_ALL_SYSTEMS;
+extern const char *const PIM_ALL_ROUTERS;
+extern const char *const PIM_ALL_PIM_ROUTERS;
+extern const char *const PIM_ALL_IGMP_ROUTERS;
extern struct pim_router *router;
extern struct zebra_privs_t pimd_privs;
-struct in_addr qpim_all_pim_routers_addr;
+extern struct in_addr qpim_all_pim_routers_addr;
extern uint8_t qpim_ecmp_enable;
extern uint8_t qpim_ecmp_rebalance_enable;
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index d07cc894a5..2ed8d5394d 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -351,11 +351,14 @@ static int rip_ifp_down(struct interface *ifp)
rip_interface_sync(ifp);
rip_if_down(ifp);
- if (IS_RIP_DEBUG_ZEBRA)
+ if (IS_RIP_DEBUG_ZEBRA) {
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+
zlog_debug(
- "interface %s vrf %u index %d flags %llx metric %d mtu %d is down",
- ifp->name, ifp->vrf_id, ifp->ifindex,
+ "interface %s vrf %s(%u) index %d flags %llx metric %d mtu %d is down",
+ ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
+ }
return 0;
}
@@ -363,11 +366,14 @@ static int rip_ifp_down(struct interface *ifp)
/* Inteface link up message processing */
static int rip_ifp_up(struct interface *ifp)
{
- if (IS_RIP_DEBUG_ZEBRA)
+ if (IS_RIP_DEBUG_ZEBRA) {
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+
zlog_debug(
- "interface %s vrf %u index %d flags %#llx metric %d mtu %d is up",
- ifp->name, ifp->vrf_id, ifp->ifindex,
+ "interface %s vrf %s(%u) index %d flags %#llx metric %d mtu %d is up",
+ ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
+ }
rip_interface_sync(ifp);
@@ -388,11 +394,13 @@ static int rip_ifp_create(struct interface *ifp)
{
rip_interface_sync(ifp);
- if (IS_RIP_DEBUG_ZEBRA)
+ if (IS_RIP_DEBUG_ZEBRA) {
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
zlog_debug(
- "interface add %s vrf %u index %d flags %#llx metric %d mtu %d",
- ifp->name, ifp->vrf_id, ifp->ifindex,
+ "interface add %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
+ ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
+ }
/* Check if this interface is RIP enabled or not.*/
rip_enable_apply(ifp);
@@ -413,14 +421,16 @@ static int rip_ifp_create(struct interface *ifp)
static int rip_ifp_destroy(struct interface *ifp)
{
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+
rip_interface_sync(ifp);
if (if_is_up(ifp)) {
rip_if_down(ifp);
}
zlog_info(
- "interface delete %s vrf %u index %d flags %#llx metric %d mtu %d",
- ifp->name, ifp->vrf_id, ifp->ifindex,
+ "interface delete %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
+ ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu);
return 0;
@@ -437,9 +447,14 @@ int rip_interface_vrf_update(ZAPI_CALLBACK_ARGS)
if (!ifp)
return 0;
- if (IS_RIP_DEBUG_ZEBRA)
- zlog_debug("interface %s VRF change vrf_id %u new vrf id %u",
- ifp->name, vrf_id, new_vrf_id);
+ if (IS_RIP_DEBUG_ZEBRA) {
+ struct vrf *vrf = vrf_lookup_by_id(vrf_id);
+ struct vrf *nvrf = vrf_lookup_by_id(new_vrf_id);
+
+ zlog_debug("interface %s VRF change vrf %s(%u) new vrf %s(%u)",
+ ifp->name, VRF_LOGNAME(vrf), vrf_id,
+ VRF_LOGNAME(nvrf), new_vrf_id);
+ }
if_update_to_new_vrf(ifp, new_vrf_id);
rip_interface_sync(ifp);
diff --git a/ripngd/ripng_interface.c b/ripngd/ripng_interface.c
index 250c7803f7..6a30c07d99 100644
--- a/ripngd/ripng_interface.c
+++ b/ripngd/ripng_interface.c
@@ -198,11 +198,14 @@ static int ripng_if_down(struct interface *ifp)
/* Inteface link up message processing. */
static int ripng_ifp_up(struct interface *ifp)
{
- if (IS_RIPNG_DEBUG_ZEBRA)
+ if (IS_RIPNG_DEBUG_ZEBRA) {
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+
zlog_debug(
- "interface up %s vrf %u index %d flags %llx metric %d mtu %d",
- ifp->name, ifp->vrf_id, ifp->ifindex,
+ "interface up %s vrf %s(%u) index %d flags %llx metric %d mtu %d",
+ ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
+ }
ripng_interface_sync(ifp);
@@ -224,11 +227,14 @@ static int ripng_ifp_down(struct interface *ifp)
ripng_interface_sync(ifp);
ripng_if_down(ifp);
- if (IS_RIPNG_DEBUG_ZEBRA)
+ if (IS_RIPNG_DEBUG_ZEBRA) {
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+
zlog_debug(
- "interface down %s vrf %u index %d flags %#llx metric %d mtu %d",
- ifp->name, ifp->vrf_id, ifp->ifindex,
+ "interface down %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
+ ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
+ }
return 0;
}
@@ -238,11 +244,14 @@ static int ripng_ifp_create(struct interface *ifp)
{
ripng_interface_sync(ifp);
- if (IS_RIPNG_DEBUG_ZEBRA)
+ if (IS_RIPNG_DEBUG_ZEBRA) {
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+
zlog_debug(
- "RIPng interface add %s vrf %u index %d flags %#llx metric %d mtu %d",
- ifp->name, ifp->vrf_id, ifp->ifindex,
+ "RIPng interface add %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
+ ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
+ }
/* Check is this interface is RIP enabled or not.*/
ripng_enable_apply(ifp);
@@ -258,14 +267,16 @@ static int ripng_ifp_create(struct interface *ifp)
static int ripng_ifp_destroy(struct interface *ifp)
{
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+
ripng_interface_sync(ifp);
if (if_is_up(ifp)) {
ripng_if_down(ifp);
}
zlog_info(
- "interface delete %s vrf %u index %d flags %#llx metric %d mtu %d",
- ifp->name, ifp->vrf_id, ifp->ifindex,
+ "interface delete %s vrf %s(%u) index %d flags %#llx metric %d mtu %d",
+ ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex,
(unsigned long long)ifp->flags, ifp->metric, ifp->mtu6);
return 0;
@@ -282,9 +293,14 @@ int ripng_interface_vrf_update(ZAPI_CALLBACK_ARGS)
if (!ifp)
return 0;
- if (IS_RIPNG_DEBUG_ZEBRA)
- zlog_debug("interface %s VRF change vrf_id %u new vrf id %u",
- ifp->name, vrf_id, new_vrf_id);
+ if (IS_RIPNG_DEBUG_ZEBRA) {
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+ struct vrf *nvrf = vrf_lookup_by_id(new_vrf_id);
+
+ zlog_debug("interface %s VRF change vrf %s(%u) new vrf %s(%u)",
+ ifp->name, VRF_LOGNAME(vrf), vrf_id,
+ VRF_LOGNAME(nvrf), new_vrf_id);
+ }
if_update_to_new_vrf(ifp, new_vrf_id);
ripng_interface_sync(ifp);
diff --git a/tests/topotests/bgp-route-map/test_route_map_topo1.py b/tests/topotests/bgp-route-map/test_route_map_topo1.py
index 86ec6c82d2..22dd3a6380 100755
--- a/tests/topotests/bgp-route-map/test_route_map_topo1.py
+++ b/tests/topotests/bgp-route-map/test_route_map_topo1.py
@@ -71,7 +71,7 @@ from time import sleep
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(os.path.join(CWD, '../'))
+sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
# Import topogen and topotest helpers
@@ -102,7 +102,7 @@ ADDR_TYPES = check_address_types()
# Reading the data from JSON File for topology and configuration creation
jsonFile = "{}/bgp_route_map_topo1.json".format(CWD)
try:
- with open(jsonFile, 'r') as topoJson:
+ with open(jsonFile, "r") as topoJson:
topo = json.load(topoJson)
except IOError:
assert False, "Could not read file {}".format(jsonFile)
@@ -442,11 +442,12 @@ def test_route_map_inbound_outbound_same_neighbor_p0(request):
}
}
- result = verify_rib(tgen, adt, dut, input_dict_2, protocol=protocol)
+ result = verify_rib(tgen, adt, dut, input_dict_2, protocol=protocol,
+ expected=False)
assert result is not True, "Testcase {} : Failed \n"
- "Expected behavior: routes are not present in rib \n"
- "Error: {}".format(
+ "routes are not present in rib \n Error: {}".format(
tc_name, result)
+ logger.info("Expected behaviour: {}".format(result))
# Verifying RIB routes
dut = "r4"
@@ -461,11 +462,12 @@ def test_route_map_inbound_outbound_same_neighbor_p0(request):
]
}
}
- result = verify_rib(tgen, adt, dut, input_dict, protocol=protocol)
+ result = verify_rib(tgen, adt, dut, input_dict, protocol=protocol,
+ expected=False)
assert result is not True, "Testcase {} : Failed \n "
- "Expected behavior: routes are not present in rib \n "
- "Error: {}".format(
+ "routes are not present in rib \n Error: {}".format(
tc_name, result)
+ logger.info("Expected behaviour: {}".format(result))
write_test_footer(tc_name)
@@ -649,10 +651,14 @@ def test_route_map_with_action_values_combination_of_prefix_action_p0(
}
}
- result = verify_rib(tgen, adt, dut, input_dict_2, protocol=protocol)
+ #tgen.mininet_cli()
+ result = verify_rib(tgen, adt, dut, input_dict_2, protocol=protocol,
+ expected=False)
if "deny" in [prefix_action, rmap_action]:
- assert result is not True, "Testcase {} : Failed \n Error: {}".\
+ assert result is not True, "Testcase {} : Failed \n "
+ "Routes are still present \n Error: {}".\
format(tc_name, result)
+ logger.info("Expected behaviour: {}".format(result))
else:
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
diff --git a/tests/topotests/bgp-route-map/test_route_map_topo2.py b/tests/topotests/bgp-route-map/test_route_map_topo2.py
index 7009fc97ce..f2398c33ff 100755
--- a/tests/topotests/bgp-route-map/test_route_map_topo2.py
+++ b/tests/topotests/bgp-route-map/test_route_map_topo2.py
@@ -32,17 +32,17 @@ TC_61:
TC_50_1:
Test modify/remove prefix-lists referenced by a
route-map for match statement.
-TC_50_1:
+TC_50_2:
Remove prefix-list referencec by route-map match cluase
and verifying it reflecting as intended
TC_51:
Add and remove community-list referencec by route-map match cluase
and verifying it reflecting as intended
TC_45:
- Test multiple match statements as part of a route-map's single
+ Test multiple match statements as part of a route-map"s single
sequence number. (Logical OR-ed of multiple match statements)
TC_44:
- Test multiple match statements as part of a route-map's single
+ Test multiple match statements as part of a route-map"s single
sequence number. (Logical AND of multiple match statements)
TC_41:
Test add/remove route-maps to specific neighbor and see if
@@ -57,7 +57,7 @@ TC_48:
Create route map setting local preference and weight to eBGP peeer
and metric to ibgp peer and verifying it should not get advertised
TC_43:
- Test multiple set statements as part of a route-map's
+ Test multiple set statements as part of a route-map"s
single sequence number.
TC_54:
Verify route-maps continue clause functionality.
@@ -112,7 +112,7 @@ from time import sleep
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(os.path.join(CWD, '../'))
+sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
# Import topogen and topotest helpers
@@ -127,7 +127,8 @@ from lib.common_config import (
verify_rib, delete_route_maps, create_bgp_community_lists,
interface_status, create_route_maps, create_prefix_lists,
verify_route_maps, check_address_types, verify_bgp_community,
- shutdown_bringup_interface, verify_prefix_lists, reset_config_on_routers)
+ shutdown_bringup_interface, verify_prefix_lists, reset_config_on_routers,
+ verify_create_community_list)
from lib.topolog import logger
from lib.bgp import (
verify_bgp_convergence, create_router_bgp,
@@ -138,7 +139,7 @@ from lib.topojson import build_topo_from_json, build_config_from_json
jsonFile = "{}/bgp_route_map_topo2.json".format(CWD)
try:
- with open(jsonFile, 'r') as topoJson:
+ with open(jsonFile, "r") as topoJson:
topo = json.load(topoJson)
except IOError:
assert False, "Could not read file {}".format(jsonFile)
@@ -198,14 +199,14 @@ def setup_module(mod):
global bgp_convergence
global ADDR_TYPES
- # Don't run this test if we have any failure.
+ # Don"t run this test if we have any failure.
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
# Api call verify whether BGP is converged
bgp_convergence = verify_bgp_convergence(tgen, topo)
- assert bgp_convergence is True, ('setup_module :Failed \n Error:'
- ' {}'.format(bgp_convergence))
+ assert bgp_convergence is True, ("setup_module :Failed \n Error:"
+ " {}".format(bgp_convergence))
logger.info("Running setup_module() done")
@@ -241,7 +242,7 @@ def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -250,20 +251,20 @@ def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit',
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit",
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit',
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit",
}]
}
}
@@ -271,7 +272,7 @@ def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
for addr_type in ADDR_TYPES:
# Create route map
@@ -280,7 +281,7 @@ def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
"route_maps": {
"rmap_match_pf_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_" + addr_type
@@ -294,7 +295,7 @@ def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
],
"rmap_match_pf_2_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_" + addr_type
@@ -309,12 +310,12 @@ def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -326,7 +327,7 @@ def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -337,7 +338,7 @@ def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
"route_maps": [{
"name":
"rmap_match_pf_2_ipv4",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -354,7 +355,7 @@ def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -365,7 +366,7 @@ def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
"route_maps": [{
"name":
"rmap_match_pf_2_ipv6",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -379,23 +380,23 @@ def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
# dual stack changes
for addr_type in ADDR_TYPES:
result4 = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result4 is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result4)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -405,21 +406,21 @@ def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result4 = verify_bgp_attributes(tgen, addr_type, dut, routes[
addr_type],rmap_name, input_dict_3)
- assert result4 is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result4)
# Verifying RIB routes
- dut = 'r4'
- protocol = 'bgp'
+ dut = "r4"
+ protocol = "bgp"
# dual stack changes
for addr_type in ADDR_TYPES:
result4 = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result4 is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result4)
# Verifying BGP set attributes
- dut = 'r4'
+ dut = "r4"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -429,7 +430,7 @@ def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
rmap_name = "rmap_match_pf_2_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -448,7 +449,7 @@ def test_modify_set_match_clauses_in_rmap_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -458,37 +459,37 @@ def test_modify_set_match_clauses_in_rmap_p0():
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit',
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit",
}],
- 'pf_list_2_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit'
+ "pf_list_2_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit"
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit',
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit",
}],
- 'pf_list_2_ipv6': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit'
+ "pf_list_2_ipv6": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create route map
@@ -498,7 +499,7 @@ def test_modify_set_match_clauses_in_rmap_p0():
"route_maps": {
"rmap_match_pf_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -510,7 +511,7 @@ def test_modify_set_match_clauses_in_rmap_p0():
}],
"rmap_match_pf_2_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -524,12 +525,12 @@ def test_modify_set_match_clauses_in_rmap_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -541,7 +542,7 @@ def test_modify_set_match_clauses_in_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -552,7 +553,7 @@ def test_modify_set_match_clauses_in_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_2_ipv4",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -569,7 +570,7 @@ def test_modify_set_match_clauses_in_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -580,7 +581,7 @@ def test_modify_set_match_clauses_in_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_2_ipv6",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -593,21 +594,21 @@ def test_modify_set_match_clauses_in_rmap_p0():
}
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -617,21 +618,21 @@ def test_modify_set_match_clauses_in_rmap_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result4 = verify_bgp_attributes(tgen, addr_type, dut, routes[
addr_type],rmap_name, input_dict_3)
- assert result4 is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result4)
# Verifying RIB routes
- dut = 'r4'
- protocol = 'bgp'
+ dut = "r4"
+ protocol = "bgp"
# dual stack changes
for addr_type in ADDR_TYPES:
result4 = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result4 is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result4)
# Verifying BGP set attributes
- dut = 'r4'
+ dut = "r4"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -640,7 +641,7 @@ def test_modify_set_match_clauses_in_rmap_p0():
rmap_name = "rmap_match_pf_2_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[
addr_type],rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Modify set/match clause of in-used route map
@@ -650,7 +651,7 @@ def test_modify_set_match_clauses_in_rmap_p0():
"route_maps": {
"rmap_match_pf_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -662,7 +663,7 @@ def test_modify_set_match_clauses_in_rmap_p0():
}],
"rmap_match_pf_2_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -676,20 +677,20 @@ def test_modify_set_match_clauses_in_rmap_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -698,20 +699,20 @@ def test_modify_set_match_clauses_in_rmap_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r4'
- protocol = 'bgp'
+ dut = "r4"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r4'
+ dut = "r4"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -720,7 +721,7 @@ def test_modify_set_match_clauses_in_rmap_p0():
rmap_name = "rmap_match_pf_2_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -739,7 +740,7 @@ def test_delete_route_maps_p1():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -763,22 +764,22 @@ def test_delete_route_maps_p1():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Delete route maps
for addr_type in ADDR_TYPES:
input_dict = {
- 'r3': {
- 'route_maps': ['rmap_match_tag_1_{}'.format(addr_type)]
+ "r3": {
+ "route_maps": ["rmap_match_tag_1_{}".format(addr_type)]
}
}
result = delete_route_maps(tgen, input_dict)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
result = verify_route_maps(tgen, input_dict)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -797,7 +798,7 @@ def test_modify_prefix_list_referenced_by_rmap_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -806,27 +807,27 @@ def test_modify_prefix_list_referenced_by_rmap_p0():
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit',
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit",
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'permit',
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "permit",
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create route map
@@ -836,7 +837,7 @@ def test_modify_prefix_list_referenced_by_rmap_p0():
"route_maps": {
"rmap_match_pf_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -849,7 +850,7 @@ def test_modify_prefix_list_referenced_by_rmap_p0():
}],
"rmap_match_pf_2_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -863,12 +864,12 @@ def test_modify_prefix_list_referenced_by_rmap_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -880,7 +881,7 @@ def test_modify_prefix_list_referenced_by_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -891,7 +892,7 @@ def test_modify_prefix_list_referenced_by_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_2_ipv4",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -908,7 +909,7 @@ def test_modify_prefix_list_referenced_by_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -919,7 +920,7 @@ def test_modify_prefix_list_referenced_by_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_2_ipv6",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -933,21 +934,21 @@ def test_modify_prefix_list_referenced_by_rmap_p0():
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -956,20 +957,20 @@ def test_modify_prefix_list_referenced_by_rmap_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r4'
- protocol = 'bgp'
+ dut = "r4"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r4'
+ dut = "r4"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -979,55 +980,55 @@ def test_modify_prefix_list_referenced_by_rmap_p0():
rmap_name = "rmap_match_pf_2_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Modify ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'deny'
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "deny"
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'deny'
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "deny"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
sleep(5)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
- protocol=protocol)
- assert result is not True, 'Testcase {} : Failed \n'
- 'Expected behaviour: routes are not present \n '
- 'Error: {}'.format(
+ protocol=protocol, expected=False)
+ assert result is not True, "Testcase {} : Failed \n"
+ "routes are not present \n Error: {}".format(
tc_name, result)
+ logger.info("Expected behaviour: {}".format(result))
# Verifying RIB routes
- dut = 'r4'
- protocol = 'bgp'
+ dut = "r4"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
- protocol=protocol)
- assert result is not True, 'Testcase {} : Failed \n'
- 'Expected behaviour: routes are not present \n '
- 'Error: {}'.format(
+ protocol=protocol, expected=False)
+ assert result is not True, "Testcase {} : Failed \n"
+ "Expected behaviour: routes are not present \n "
+ "Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -1038,7 +1039,7 @@ def test_modify_prefix_list_referenced_by_rmap_p0():
def test_remove_prefix_list_referenced_by_rmap_p0():
"""
- TC_50_1:
+ TC_50_2:
Remove prefix-list referencec by route-map match cluase
and verifying it reflecting as intended
"""
@@ -1046,7 +1047,7 @@ def test_remove_prefix_list_referenced_by_rmap_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -1055,27 +1056,27 @@ def test_remove_prefix_list_referenced_by_rmap_p0():
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit'
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit"
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'permit'
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "permit"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create route map
@@ -1085,7 +1086,7 @@ def test_remove_prefix_list_referenced_by_rmap_p0():
"route_maps": {
"rmap_match_pf_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -1097,7 +1098,7 @@ def test_remove_prefix_list_referenced_by_rmap_p0():
}],
"rmap_match_pf_2_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -1111,13 +1112,13 @@ def test_remove_prefix_list_referenced_by_rmap_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
for addr_type in ADDR_TYPES:
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -1129,7 +1130,7 @@ def test_remove_prefix_list_referenced_by_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -1140,7 +1141,7 @@ def test_remove_prefix_list_referenced_by_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_2_ipv4",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -1157,7 +1158,7 @@ def test_remove_prefix_list_referenced_by_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -1168,7 +1169,7 @@ def test_remove_prefix_list_referenced_by_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_2_ipv6",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -1181,21 +1182,21 @@ def test_remove_prefix_list_referenced_by_rmap_p0():
}
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -1204,20 +1205,20 @@ def test_remove_prefix_list_referenced_by_rmap_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r4'
- protocol = 'bgp'
+ dut = "r4"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r4'
+ dut = "r4"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -1226,67 +1227,67 @@ def test_remove_prefix_list_referenced_by_rmap_p0():
rmap_name = "rmap_match_pf_2_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Remove/Delete prefix list
input_dict_3 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit',
- 'delete': True
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit",
+ "delete": True
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'permit',
- 'delete': True
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "permit",
+ "delete": True
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
result = verify_prefix_lists(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Api call to clear bgp, so config changes would be reflected
- dut = 'r3'
+ dut = "r3"
result = clear_bgp_and_verify(tgen, topo, dut)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
- protocol=protocol)
- assert result is not True, 'Testcase {} : Failed \n'
- 'Expected behaviour: routes are not present \n '
- 'Error: {}'.format(
+ protocol=protocol, expected=False)
+ assert result is not True, "Testcase {} : Failed \n"
+ "routes are not present \n Error: {}".format(
tc_name, result)
+ logger.info("Expected behaviour: {}".format(result))
# Verifying RIB routes
- dut = 'r4'
- protocol = 'bgp'
+ dut = "r4"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
- protocol=protocol)
- assert result is not True, 'Testcase {} : Failed \n'
- 'Expected behaviour: routes are not present \n '
- 'Error: {}'.format(
- tc_name, result)
+ protocol=protocol, expected=False)
+ assert result is not True, "Testcase {} : Failed \n"
+ "routes are not present \n Error: {}".\
+ format(tc_name, result)
+ logger.info("Expected behaviour: {}".format(result))
write_test_footer(tc_name)
@@ -1304,7 +1305,7 @@ def test_add_and_remove_community_list_referenced_by_rmap_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -1329,12 +1330,12 @@ def test_add_and_remove_community_list_referenced_by_rmap_p0():
}
}
result = create_route_maps(tgen, input_dict_5)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_6 = {
- 'r1': {
+ "r1": {
"bgp": {
"address_family": {
"ipv4": {
@@ -1345,7 +1346,7 @@ def test_add_and_remove_community_list_referenced_by_rmap_p0():
"r1": {
"route_maps": [{
"name": "rm_r1_out_ipv4",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -1361,7 +1362,7 @@ def test_add_and_remove_community_list_referenced_by_rmap_p0():
"r1": {
"route_maps": [{
"name": "rm_r1_out_ipv6",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -1375,7 +1376,7 @@ def test_add_and_remove_community_list_referenced_by_rmap_p0():
}
result = create_router_bgp(tgen, topo, input_dict_6)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
for addr_type in ADDR_TYPES:
@@ -1394,9 +1395,14 @@ def test_add_and_remove_community_list_referenced_by_rmap_p0():
}
}
result = create_bgp_community_lists(tgen, input_dict_1)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
+ # Verify BGP large community is created
+ result = verify_create_community_list(tgen, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
for addr_type in ADDR_TYPES:
# Create route map
input_dict_2 = {
@@ -1415,12 +1421,12 @@ def test_add_and_remove_community_list_referenced_by_rmap_p0():
}
}
result = create_route_maps(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_3 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -1431,7 +1437,7 @@ def test_add_and_remove_community_list_referenced_by_rmap_p0():
"r3": {
"route_maps": [{
"name": "rm_r3_in_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -1447,7 +1453,7 @@ def test_add_and_remove_community_list_referenced_by_rmap_p0():
"r3": {
"route_maps": [{
"name": "rm_r3_in_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -1461,33 +1467,33 @@ def test_add_and_remove_community_list_referenced_by_rmap_p0():
}
result = create_router_bgp(tgen, topo, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
sleep(5)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verify large-community-list
- dut = 'r3'
+ dut = "r3"
networks = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
}
input_dict_4 = {
- 'largeCommunity': '1:1:1 1:2:3 2:1:1 2:2:2'
+ "largeCommunity": "1:1:1 1:2:3 2:1:1 2:2:2"
}
for addr_type in ADDR_TYPES:
result = verify_bgp_community(tgen, addr_type, dut, networks[
addr_type],input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -1498,14 +1504,14 @@ def test_add_and_remove_community_list_referenced_by_rmap_p0():
def test_multiple_match_statement_in_route_map_logical_ORed_p0():
"""
TC_45:
- Test multiple match statements as part of a route-map's single
+ Test multiple match statements as part of a route-map"s single
sequence number. (Logical OR-ed of multiple match statements)
"""
tgen = get_topogen()
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -1514,20 +1520,20 @@ def test_multiple_match_statement_in_route_map_logical_ORed_p0():
# Api call to advertise networks
input_dict_nw1 = {
- 'r1': {
+ "r1": {
"bgp": {
"address_family": {
"ipv4": {
"unicast": {
"advertise_networks": [
- {"network": '10.0.30.1/32'}
+ {"network": "10.0.30.1/32"}
]
}
},
"ipv6": {
"unicast": {
"advertise_networks": [
- {"network": '1::1/128'}
+ {"network": "1::1/128"}
]
}
}
@@ -1537,25 +1543,25 @@ def test_multiple_match_statement_in_route_map_logical_ORed_p0():
}
result = create_router_bgp(tgen, topo, input_dict_nw1)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Api call to advertise networks
input_dict_nw2 = {
- 'r1': {
+ "r1": {
"bgp": {
"address_family": {
"ipv4": {
"unicast": {
"advertise_networks": [
- {"network": '20.0.30.1/32'}
+ {"network": "20.0.30.1/32"}
]
}
},
"ipv6": {
"unicast": {
"advertise_networks": [
- {"network": '2::1/128'}
+ {"network": "2::1/128"}
]
}
}
@@ -1565,57 +1571,57 @@ def test_multiple_match_statement_in_route_map_logical_ORed_p0():
}
result = create_router_bgp(tgen, topo, input_dict_nw2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit'
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit"
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'permit'
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "permit"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_2_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit'
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_2_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit"
}]
},
- 'ipv6': {
- 'pf_list_2_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'permit'
+ "ipv6": {
+ "pf_list_2_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "permit"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
input_dict_3_addr_type ={}
@@ -1626,7 +1632,7 @@ def test_multiple_match_statement_in_route_map_logical_ORed_p0():
"route_maps": {
"rmap_match_pf_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -1641,7 +1647,7 @@ def test_multiple_match_statement_in_route_map_logical_ORed_p0():
}
input_dict_3_addr_type[addr_type] = input_dict_3
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create route map
@@ -1651,7 +1657,7 @@ def test_multiple_match_statement_in_route_map_logical_ORed_p0():
"route_maps": {
"rmap_match_pf_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -1666,12 +1672,12 @@ def test_multiple_match_statement_in_route_map_logical_ORed_p0():
}
input_dict_3_addr_type[addr_type] = input_dict_3
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_6 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -1683,7 +1689,7 @@ def test_multiple_match_statement_in_route_map_logical_ORed_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -1700,7 +1706,7 @@ def test_multiple_match_statement_in_route_map_logical_ORed_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -1714,21 +1720,21 @@ def test_multiple_match_statement_in_route_map_logical_ORed_p0():
}
result = create_router_bgp(tgen, topo, input_dict_6)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
routes = {
"ipv4": ["10.0.30.1/32"],
"ipv6": ["1::1/128"]
@@ -1737,7 +1743,7 @@ def test_multiple_match_statement_in_route_map_logical_ORed_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3_addr_type[addr_type])
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
@@ -1748,7 +1754,7 @@ def test_multiple_match_statement_in_route_map_logical_ORed_p0():
for addr_type in ADDR_TYPES:
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -1757,17 +1763,17 @@ def test_multiple_match_statement_in_route_map_logical_ORed_p0():
# tgen.mininet_cli()
-def test_multiple_match_statement_in_route_map_logical_ANDed():
+def test_multiple_match_statement_in_route_map_logical_ANDed_p1():
"""
TC_44:
- Test multiple match statements as part of a route-map's single
+ Test multiple match statements as part of a route-map"s single
sequence number. (Logical AND of multiple match statements)
"""
tgen = get_topogen()
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -1790,13 +1796,13 @@ def test_multiple_match_statement_in_route_map_logical_ANDed():
}
}
result = create_route_maps(tgen, input_dict_5)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
for addr_type in ADDR_TYPES:
input_dict_6 = {
- 'r1': {
+ "r1": {
"bgp": {
"address_family": {
addr_type: {
@@ -1808,7 +1814,7 @@ def test_multiple_match_statement_in_route_map_logical_ANDed():
"route_maps": [{
"name":
"rm_r1_out_{}".format(addr_type),
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -1821,25 +1827,25 @@ def test_multiple_match_statement_in_route_map_logical_ANDed():
}
}
result = create_router_bgp(tgen, topo, input_dict_6)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit'
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit"
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'permit'
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "permit"
}]
}
}
@@ -1847,7 +1853,7 @@ def test_multiple_match_statement_in_route_map_logical_ANDed():
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
for addr_type in ADDR_TYPES:
@@ -1866,9 +1872,14 @@ def test_multiple_match_statement_in_route_map_logical_ANDed():
}
}
result = create_bgp_community_lists(tgen, input_dict_1)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
+ # Verify BGP large community is created
+ result = verify_create_community_list(tgen, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
# Create route map
for addr_type in ADDR_TYPES:
input_dict_3 = {
@@ -1876,7 +1887,7 @@ def test_multiple_match_statement_in_route_map_logical_ANDed():
"route_maps": {
"rmap_match_pf_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -1890,7 +1901,7 @@ def test_multiple_match_statement_in_route_map_logical_ANDed():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
for addr_type in ADDR_TYPES:
@@ -1900,7 +1911,7 @@ def test_multiple_match_statement_in_route_map_logical_ANDed():
"route_maps": {
"rmap_match_pf_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type : {
"large_community_list": {"id": "rmap_lcomm_"+
@@ -1915,12 +1926,12 @@ def test_multiple_match_statement_in_route_map_logical_ANDed():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
for addr_type in ADDR_TYPES:
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
addr_type: {
@@ -1932,7 +1943,7 @@ def test_multiple_match_statement_in_route_map_logical_ANDed():
"route_maps": [{
"name":
"rmap_match_pf_1_{}".format(addr_type),
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -1945,20 +1956,20 @@ def test_multiple_match_statement_in_route_map_logical_ANDed():
}
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# sleep(10)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -1967,7 +1978,7 @@ def test_multiple_match_statement_in_route_map_logical_ANDed():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -1986,7 +1997,7 @@ def test_add_remove_rmap_to_specific_neighbor_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -1995,27 +2006,27 @@ def test_add_remove_rmap_to_specific_neighbor_p0():
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'deny'
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "deny"
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'deny'
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "deny"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create route map
@@ -2025,7 +2036,7 @@ def test_add_remove_rmap_to_specific_neighbor_p0():
"route_maps": {
"rmap_match_pf_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -2039,12 +2050,12 @@ def test_add_remove_rmap_to_specific_neighbor_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -2056,7 +2067,7 @@ def test_add_remove_rmap_to_specific_neighbor_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -2073,7 +2084,7 @@ def test_add_remove_rmap_to_specific_neighbor_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -2087,24 +2098,24 @@ def test_add_remove_rmap_to_specific_neighbor_p0():
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
- protocol=protocol)
- assert result is not True, 'Testcase {} : \n'
- 'Expected Behavior: Routes are not present in RIB \n'
- ' Error: {}'.format(
+ protocol=protocol, expected=False)
+ assert result is not True, "Testcase {} : Failed \n Error"
+ "Routes are still present: {}".format(
tc_name, result)
+ logger.info("Expected behaviour: {}".format(result))
# Remove applied rmap from neighbor
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -2116,7 +2127,7 @@ def test_add_remove_rmap_to_specific_neighbor_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in',
+ "direction": "in",
"delete": True
}]
}
@@ -2134,7 +2145,7 @@ def test_add_remove_rmap_to_specific_neighbor_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv6",
- "direction": 'in',
+ "direction": "in",
"delete": True
}]
}
@@ -2149,16 +2160,16 @@ def test_add_remove_rmap_to_specific_neighbor_p0():
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -2177,7 +2188,7 @@ def test_clear_bgp_and_flap_interface_to_verify_rmap_properties_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -2186,27 +2197,27 @@ def test_clear_bgp_and_flap_interface_to_verify_rmap_properties_p0():
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit'
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit"
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'permit'
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "permit"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create route map
@@ -2216,7 +2227,7 @@ def test_clear_bgp_and_flap_interface_to_verify_rmap_properties_p0():
"route_maps": {
"rmap_match_pf_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5',
+ "seq_id": "5",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -2231,12 +2242,12 @@ def test_clear_bgp_and_flap_interface_to_verify_rmap_properties_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -2248,7 +2259,7 @@ def test_clear_bgp_and_flap_interface_to_verify_rmap_properties_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -2265,7 +2276,7 @@ def test_clear_bgp_and_flap_interface_to_verify_rmap_properties_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -2279,20 +2290,20 @@ def test_clear_bgp_and_flap_interface_to_verify_rmap_properties_p0():
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -2301,26 +2312,26 @@ def test_clear_bgp_and_flap_interface_to_verify_rmap_properties_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# clear bgp, so config changes would be reflected
- dut = 'r3'
+ dut = "r3"
result = clear_bgp_and_verify(tgen, topo, dut)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -2329,7 +2340,7 @@ def test_clear_bgp_and_flap_interface_to_verify_rmap_properties_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Flap interface to see if route-map properties are intact
@@ -2348,19 +2359,19 @@ def test_clear_bgp_and_flap_interface_to_verify_rmap_properties_p0():
# Verify BGP convergence once interface is up
result = verify_bgp_convergence(tgen, topo)
assert result is True, (
- 'setup_module :Failed \n Error:' ' {}'.format(result))
+ "setup_module :Failed \n Error:" " {}".format(result))
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -2369,7 +2380,7 @@ def test_clear_bgp_and_flap_interface_to_verify_rmap_properties_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -2388,7 +2399,7 @@ def test_rmap_without_match_and_set_clause_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -2402,22 +2413,22 @@ def test_rmap_without_match_and_set_clause_p0():
"route_maps": {
"rmap_no_match_set_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '5'
+ "seq_id": "5"
}],
"rmap_no_match_set_2_{}".format(addr_type): [{
"action": "deny",
- 'seq_id': '5'
+ "seq_id": "5"
}]
}
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -2429,7 +2440,7 @@ def test_rmap_without_match_and_set_clause_p0():
"route_maps": [{
"name":
"rmap_no_match_set_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -2440,7 +2451,7 @@ def test_rmap_without_match_and_set_clause_p0():
"route_maps": [{
"name":
"rmap_no_match_set_2_ipv4",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -2457,7 +2468,7 @@ def test_rmap_without_match_and_set_clause_p0():
"route_maps": [{
"name":
"rmap_no_match_set_1_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -2468,7 +2479,7 @@ def test_rmap_without_match_and_set_clause_p0():
"route_maps": [{
"name":
"rmap_no_match_set_2_ipv6",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -2482,30 +2493,30 @@ def test_rmap_without_match_and_set_clause_p0():
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r4'
- protocol = 'bgp'
+ dut = "r4"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
- result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
- assert result is not True, 'Testcase {} : Failed \n'
- 'Expected behaviour: routes are not present \n '
- 'Error: {}'.format(
+ result = verify_rib(tgen, addr_type, dut, input_dict,
+ protocol=protocol, expected=False)
+ assert result is not True, "Testcase {} : Failed \n"
+ "routes are not present \n Error: {}".format(
tc_name, result)
+ logger.info("Expected behaviour: {}".format(result))
write_test_footer(tc_name)
-
# Uncomment next line for debugging
# tgen.mininet_cli()
@@ -2520,7 +2531,7 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -2529,27 +2540,27 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit'
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit"
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'permit'
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "permit"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create route map
@@ -2597,12 +2608,12 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
}
input_dict_3_addr_type[addr_type] = input_dict_3
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -2614,7 +2625,7 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -2625,7 +2636,7 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
"route_maps": [{
"name":
"rmap_match_pf_2_ipv4",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -2636,7 +2647,7 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
"route_maps": [{
"name":
"rmap_match_pf_3_ipv4",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -2653,7 +2664,7 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -2664,7 +2675,7 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
"route_maps": [{
"name":
"rmap_match_pf_2_ipv6",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -2675,7 +2686,7 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
"route_maps": [{
"name":
"rmap_match_pf_3_ipv6",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -2689,21 +2700,21 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -2713,20 +2724,20 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[
addr_type],rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r4'
- protocol = 'bgp'
+ dut = "r4"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r4'
+ dut = "r4"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -2736,22 +2747,23 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
rmap_name = "rmap_match_pf_2_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
- rmap_name, input_dict_3_addr_type[addr_type])
- assert result is not True, 'Testcase {} : Failed \n'
- 'Expected behaviour: Attributes are not set \n'
- 'Error: {}'.format(
+ rmap_name, input_dict_3_addr_type[addr_type],
+ expected=False)
+ assert result is not True, "Testcase {} : Failed \n"
+ "Attributes are not set \n Error: {}".format(
tc_name, result)
+ logger.info("Expected behaviour: {}".format(result))
# Verifying RIB routes
- dut = 'r5'
- protocol = 'bgp'
+ dut = "r5"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r5'
+ dut = "r5"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -2761,12 +2773,11 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
for addr_type in ADDR_TYPES:
rmap_name = "rmap_match_pf_3_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
- rmap_name, input_dict_3_addr_type[addr_type])
- assert result is not True, 'Testcase {} : Failed \n'
- 'Expected behaviour: Attributes are not set \n'
- 'Error: {}'.format(
+ rmap_name, input_dict_3_addr_type[addr_type],
+ expected=False)
+ assert result is not True, "Testcase {} : Failed \n"
+ "Attributes are not set \n Error: {}".format(
tc_name, result)
-
logger.info("Expected behaviour: {}".format(result))
write_test_footer(tc_name)
@@ -2778,14 +2789,14 @@ def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
def test_multiple_set_on_single_sequence_in_rmap_p0():
"""
TC_43:
- Test multiple set statements as part of a route-map's
+ Test multiple set statements as part of a route-map"s
single sequence number.
"""
tgen = get_topogen()
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -2794,27 +2805,27 @@ def test_multiple_set_on_single_sequence_in_rmap_p0():
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit'
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit"
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'permit'
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "permit"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create route map
@@ -2839,12 +2850,12 @@ def test_multiple_set_on_single_sequence_in_rmap_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -2856,7 +2867,7 @@ def test_multiple_set_on_single_sequence_in_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -2873,7 +2884,7 @@ def test_multiple_set_on_single_sequence_in_rmap_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -2886,20 +2897,20 @@ def test_multiple_set_on_single_sequence_in_rmap_p0():
}
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -2910,7 +2921,7 @@ def test_multiple_set_on_single_sequence_in_rmap_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -2928,7 +2939,7 @@ def test_route_maps_with_continue_clause_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -2937,27 +2948,27 @@ def test_route_maps_with_continue_clause_p0():
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit'
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit"
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'permit'
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "permit"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create route map
@@ -2967,7 +2978,7 @@ def test_route_maps_with_continue_clause_p0():
"route_maps": {
"rmap_match_pf_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '10',
+ "seq_id": "10",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -2980,7 +2991,7 @@ def test_route_maps_with_continue_clause_p0():
},
{
"action": "permit",
- 'seq_id': '20',
+ "seq_id": "20",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -2992,7 +3003,7 @@ def test_route_maps_with_continue_clause_p0():
},
{
"action": "permit",
- 'seq_id': '30',
+ "seq_id": "30",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -3007,12 +3018,12 @@ def test_route_maps_with_continue_clause_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -3024,7 +3035,7 @@ def test_route_maps_with_continue_clause_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -3041,7 +3052,7 @@ def test_route_maps_with_continue_clause_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -3054,21 +3065,21 @@ def test_route_maps_with_continue_clause_p0():
}
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
rmap_name = "rmap_match_pf_1"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
@@ -3082,7 +3093,7 @@ def test_route_maps_with_continue_clause_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[
addr_type],rmap_name, input_dict_3, seq_id[addr_type])
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -3100,7 +3111,7 @@ def test_route_maps_with_goto_clause_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -3109,27 +3120,27 @@ def test_route_maps_with_goto_clause_p0():
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit'
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit"
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'permit'
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "permit"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create route map
@@ -3139,7 +3150,7 @@ def test_route_maps_with_goto_clause_p0():
"route_maps": {
"rmap_match_pf_1_{}".format(addr_type): [{
"action": "permit",
- 'seq_id': '10',
+ "seq_id": "10",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -3149,7 +3160,7 @@ def test_route_maps_with_goto_clause_p0():
},
{
"action": "permit",
- 'seq_id': '20',
+ "seq_id": "20",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -3161,7 +3172,7 @@ def test_route_maps_with_goto_clause_p0():
},
{
"action": "permit",
- 'seq_id': '30',
+ "seq_id": "30",
"match": {
addr_type: {
"prefix_lists": "pf_list_1_{}".format(addr_type)
@@ -3176,12 +3187,13 @@ def test_route_maps_with_goto_clause_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ # tgen.mininet_cli()
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -3193,7 +3205,7 @@ def test_route_maps_with_goto_clause_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -3210,7 +3222,7 @@ def test_route_maps_with_goto_clause_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -3223,20 +3235,20 @@ def test_route_maps_with_goto_clause_p0():
}
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
rmap_name = "rmap_match_pf_1"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
@@ -3250,7 +3262,7 @@ def test_route_maps_with_goto_clause_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[
addr_type],rmap_name, input_dict_3, seq_id[addr_type])
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -3268,7 +3280,7 @@ def test_route_maps_with_call_clause_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -3277,27 +3289,27 @@ def test_route_maps_with_call_clause_p0():
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit'
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit"
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'permit'
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "permit"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create route map
@@ -3332,12 +3344,12 @@ def test_route_maps_with_call_clause_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -3349,7 +3361,7 @@ def test_route_maps_with_call_clause_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -3366,7 +3378,7 @@ def test_route_maps_with_call_clause_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv6",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -3379,20 +3391,20 @@ def test_route_maps_with_call_clause_p0():
}
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying BGP set attributes
- dut = 'r3'
+ dut = "r3"
routes = {
"ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
"ipv6": ["1::1/128", "1::2/128"]
@@ -3402,7 +3414,7 @@ def test_route_maps_with_call_clause_p0():
rmap_name = "rmap_match_pf_1_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
rmap_name = "rmap_match_pf_2"
@@ -3410,7 +3422,7 @@ def test_route_maps_with_call_clause_p0():
rmap_name = "rmap_match_pf_2_{}".format(addr_type)
result = verify_bgp_attributes(tgen, addr_type, dut, routes[addr_type],
rmap_name, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -3429,7 +3441,7 @@ def test_create_rmap_match_prefix_list_to_deny_in_and_outbound_prefixes_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -3438,27 +3450,27 @@ def test_create_rmap_match_prefix_list_to_deny_in_and_outbound_prefixes_p0():
# Create ip prefix list
input_dict_2 = {
- 'r3': {
- 'prefix_lists': {
- 'ipv4': {
- 'pf_list_1_ipv4': [{
- 'seqid': 10,
- 'network': 'any',
- 'action': 'permit'
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": "permit"
}]
},
- 'ipv6': {
- 'pf_list_1_ipv6': [{
- 'seqid': 100,
- 'network': 'any',
- 'action': 'permit'
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": "permit"
}]
}
}
}
}
result = create_prefix_lists(tgen, input_dict_2)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Create route map
@@ -3492,12 +3504,12 @@ def test_create_rmap_match_prefix_list_to_deny_in_and_outbound_prefixes_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r3': {
+ "r3": {
"bgp": {
"address_family": {
"ipv4": {
@@ -3509,7 +3521,7 @@ def test_create_rmap_match_prefix_list_to_deny_in_and_outbound_prefixes_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -3520,7 +3532,7 @@ def test_create_rmap_match_prefix_list_to_deny_in_and_outbound_prefixes_p0():
"route_maps": [{
"name":
"rmap_match_pf_2_ipv6",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -3537,7 +3549,7 @@ def test_create_rmap_match_prefix_list_to_deny_in_and_outbound_prefixes_p0():
"route_maps": [{
"name":
"rmap_match_pf_1_ipv4",
- "direction": 'in'
+ "direction": "in"
}]
}
}
@@ -3548,7 +3560,7 @@ def test_create_rmap_match_prefix_list_to_deny_in_and_outbound_prefixes_p0():
"route_maps": [{
"name":
"rmap_match_pf_2_ipv6",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -3561,31 +3573,31 @@ def test_create_rmap_match_prefix_list_to_deny_in_and_outbound_prefixes_p0():
}
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
input_dict = topo["routers"]
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
- protocol=protocol)
- assert result is not True, 'Testcase {} : Failed \n'
- 'Expected behaviour: routes are not present \n '
- 'Error: {}'.format(
- tc_name, result)
+ protocol=protocol, expected=False)
+ assert result is not True, "Testcase {} : Failed \n"
+ "routes are not present \n Error: {}".\
+ format(tc_name, result)
+ logger.info("Expected behaviour: {}".format(result))
# Verifying RIB routes
- dut = 'r4'
- protocol = 'bgp'
+ dut = "r4"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
result = verify_rib(tgen, addr_type, dut, input_dict,
- protocol=protocol)
- assert result is not True, 'Testcase {} : Failed \n'
- 'Expected behaviour: routes are not present \n '
- 'Error: {}'.format(
- tc_name, result)
+ protocol=protocol, expected=False)
+ assert result is not True, "Testcase {} : Failed \n"
+ "routes are not present \n Error: {}".\
+ format(tc_name, result)
+ logger.info("Expected behaviour: {}".format(result))
write_test_footer(tc_name)
@@ -3603,7 +3615,7 @@ def test_create_rmap_to_match_tag_permit_inbound_prefixes_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -3675,12 +3687,12 @@ def test_create_rmap_to_match_tag_permit_inbound_prefixes_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r1': {
+ "r1": {
"bgp": {
"address_family": {
"ipv4": {
@@ -3692,7 +3704,7 @@ def test_create_rmap_to_match_tag_permit_inbound_prefixes_p0():
"route_maps": [{
"name":
"rmap_match_tag_1_ipv4",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -3709,7 +3721,7 @@ def test_create_rmap_to_match_tag_permit_inbound_prefixes_p0():
"route_maps": [{
"name":
"rmap_match_tag_1_ipv6",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -3722,12 +3734,12 @@ def test_create_rmap_to_match_tag_permit_inbound_prefixes_p0():
}
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
input_dict = {
@@ -3743,7 +3755,7 @@ def test_create_rmap_to_match_tag_permit_inbound_prefixes_p0():
}
result = verify_rib(tgen, addr_type, dut, input_dict,
protocol=protocol)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
write_test_footer(tc_name)
@@ -3762,7 +3774,7 @@ def test_create_rmap_to_match_tag_deny_outbound_prefixes_p0():
global bgp_convergence
if bgp_convergence is not True:
- pytest.skip('skipped because of BGP Convergence failure')
+ pytest.skip("skipped because of BGP Convergence failure")
# test case name
tc_name = inspect.stack()[0][3]
@@ -3834,12 +3846,12 @@ def test_create_rmap_to_match_tag_deny_outbound_prefixes_p0():
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Configure neighbor for route map
input_dict_4 = {
- 'r1': {
+ "r1": {
"bgp": {
"address_family": {
"ipv4": {
@@ -3851,7 +3863,7 @@ def test_create_rmap_to_match_tag_deny_outbound_prefixes_p0():
"route_maps": [{
"name":
"rmap_match_tag_1_ipv4",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -3868,7 +3880,7 @@ def test_create_rmap_to_match_tag_deny_outbound_prefixes_p0():
"route_maps": [{
"name":
"rmap_match_tag_1_ipv6",
- "direction": 'out'
+ "direction": "out"
}]
}
}
@@ -3881,12 +3893,12 @@ def test_create_rmap_to_match_tag_deny_outbound_prefixes_p0():
}
}
result = create_router_bgp(tgen, topo, input_dict_4)
- assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result)
# Verifying RIB routes
- dut = 'r3'
- protocol = 'bgp'
+ dut = "r3"
+ protocol = "bgp"
for addr_type in ADDR_TYPES:
input_dict = {
@@ -3901,16 +3913,17 @@ def test_create_rmap_to_match_tag_deny_outbound_prefixes_p0():
}
}
result = verify_rib(tgen, addr_type, dut, input_dict,
- protocol=protocol)
- assert result is not True, 'Testcase {} : Failed \n'
- 'Expected behavior: routes are denied \n Error: {}'.format(
+ protocol=protocol, expected=False)
+ assert result is not True, "Testcase {} : Failed \n"
+ "routes are denied \n Error: {}".format(
tc_name, result)
+ logger.info("Expected behaviour: {}".format(result))
write_test_footer(tc_name)
# Uncomment next line for debugging
# tgen.mininet_cli()
-if __name__ == '__main__':
+if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_aggregate-address_origin/__init__.py b/tests/topotests/bgp_aggregate-address_origin/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_aggregate-address_origin/__init__.py
diff --git a/tests/topotests/bgp_aggregate-address_origin/r1/bgpd.conf b/tests/topotests/bgp_aggregate-address_origin/r1/bgpd.conf
new file mode 100644
index 0000000000..528d02af36
--- /dev/null
+++ b/tests/topotests/bgp_aggregate-address_origin/r1/bgpd.conf
@@ -0,0 +1,7 @@
+router bgp 65000
+ neighbor 192.168.255.2 remote-as 65001
+ address-family ipv4 unicast
+ redistribute connected
+ aggregate-address 172.16.255.0/24 origin igp
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_aggregate-address_origin/r1/zebra.conf b/tests/topotests/bgp_aggregate-address_origin/r1/zebra.conf
new file mode 100644
index 0000000000..0a283c06d5
--- /dev/null
+++ b/tests/topotests/bgp_aggregate-address_origin/r1/zebra.conf
@@ -0,0 +1,9 @@
+!
+interface lo
+ ip address 172.16.255.254/32
+!
+interface r1-eth0
+ ip address 192.168.255.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_aggregate-address_origin/r2/bgpd.conf b/tests/topotests/bgp_aggregate-address_origin/r2/bgpd.conf
new file mode 100644
index 0000000000..73d4d0aeea
--- /dev/null
+++ b/tests/topotests/bgp_aggregate-address_origin/r2/bgpd.conf
@@ -0,0 +1,4 @@
+router bgp 65001
+ neighbor 192.168.255.1 remote-as 65000
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_aggregate-address_origin/r2/zebra.conf b/tests/topotests/bgp_aggregate-address_origin/r2/zebra.conf
new file mode 100644
index 0000000000..606c17bec9
--- /dev/null
+++ b/tests/topotests/bgp_aggregate-address_origin/r2/zebra.conf
@@ -0,0 +1,6 @@
+!
+interface r2-eth0
+ ip address 192.168.255.2/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_aggregate-address_origin/test_bgp_aggregate-address_origin.py b/tests/topotests/bgp_aggregate-address_origin/test_bgp_aggregate-address_origin.py
new file mode 100644
index 0000000000..be29d143dd
--- /dev/null
+++ b/tests/topotests/bgp_aggregate-address_origin/test_bgp_aggregate-address_origin.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+
+#
+# bgp_aggregate-address_origin.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2020 by
+# Donatas Abraitis <donatas.abraitis@gmail.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+bgp_aggregate-address_origin.py:
+
+Test if works the following commands:
+router bgp 65031
+ address-family ipv4 unicast
+ aggregate-address 192.168.255.0/24 origin igp
+"""
+
+import os
+import sys
+import json
+import time
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from mininet.topo import Topo
+
+class TemplateTopo(Topo):
+ def build(self, *_args, **_opts):
+ tgen = get_topogen(self)
+
+ for routern in range(1, 3):
+ tgen.add_router('r{}'.format(routern))
+
+ switch = tgen.add_switch('s1')
+ switch.add_link(tgen.gears['r1'])
+ switch.add_link(tgen.gears['r2'])
+
+def setup_module(mod):
+ tgen = Topogen(TemplateTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.iteritems(), 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_aggregate_address_origin():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router = tgen.gears['r2']
+
+ def _bgp_converge(router):
+ output = json.loads(router.vtysh_cmd("show ip bgp neighbor 192.168.255.1 json"))
+ expected = {
+ '192.168.255.1': {
+ 'bgpState': 'Established',
+ 'addressFamilyInfo': {
+ 'ipv4Unicast': {
+ 'acceptedPrefixCounter': 3
+ }
+ }
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_aggregate_address_has_metric(router):
+ output = json.loads(router.vtysh_cmd("show ip bgp 172.16.255.0/24 json"))
+ expected = {
+ 'paths': [
+ {
+ 'origin': 'IGP'
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge, router)
+ success, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+
+ assert result is None, 'Failed to see bgp convergence in "{}"'.format(router)
+
+ test_func = functools.partial(_bgp_aggregate_address_has_metric, router)
+ success, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+
+ assert result is None, 'Failed to see applied ORIGIN (igp) for aggregated prefix in "{}"'.format(router)
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py b/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py
index 7607fe986b..c851567dda 100755
--- a/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py
+++ b/tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py
@@ -151,8 +151,7 @@ def setup_module(module):
net['r%s' % i].startRouter()
# Starting PE Hosts and init ExaBGP on each of them
- print('*** Starting BGP on all 8 Peers in 10s')
- sleep(10)
+ print('*** Starting BGP on all 8 Peers')
for i in range(1, 9):
net['peer%s' % i].cmd('cp %s/exabgp.env /etc/exabgp/exabgp.env' % thisDir)
net['peer%s' % i].cmd('cp %s/peer%s/* /etc/exabgp/' % (thisDir, i))
@@ -191,7 +190,6 @@ def test_router_running():
print("\n\n** Check if FRR/Quagga is running on each Router node")
print("******************************************\n")
- sleep(5)
# Starting Routers
for i in range(1, 2):
@@ -215,7 +213,7 @@ def test_bgp_converge():
# Wait for BGP to converge (All Neighbors in either Full or TwoWay State)
print("\n\n** Verify for BGP to converge")
print("******************************************\n")
- timeout = 60
+ timeout = 125
while timeout > 0:
print("Timeout in %s: " % timeout),
sys.stdout.flush()
@@ -240,9 +238,9 @@ def test_bgp_converge():
bgpStatus = net['r%s' % i].cmd('vtysh -c "show ip bgp view %s summary"' % view)
assert False, "BGP did not converge:\n%s" % bgpStatus
- # Wait for an extra 30s to announce all routes
- print('Waiting 30s for routes to be announced');
- sleep(30)
+ # Wait for an extra 5s to announce all routes
+ print('Waiting 5s for routes to be announced');
+ sleep(5)
print("BGP converged.")
diff --git a/tests/topotests/evpn-pim-1/host1/bgpd.conf b/tests/topotests/evpn-pim-1/host1/bgpd.conf
new file mode 100644
index 0000000000..cdf4cb4feb
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/host1/bgpd.conf
@@ -0,0 +1 @@
+!
diff --git a/tests/topotests/evpn-pim-1/host1/pimd.conf b/tests/topotests/evpn-pim-1/host1/pimd.conf
new file mode 100644
index 0000000000..63a44c1333
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/host1/pimd.conf
@@ -0,0 +1,4 @@
+int lo
+!
+
+
diff --git a/tests/topotests/evpn-pim-1/host1/zebra.conf b/tests/topotests/evpn-pim-1/host1/zebra.conf
new file mode 100644
index 0000000000..45ad031017
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/host1/zebra.conf
@@ -0,0 +1,5 @@
+int host1-eth0
+ ip addr 192.168.3.4/24
+
+int lo
+ ip addr 192.168.100.4/32
diff --git a/tests/topotests/evpn-pim-1/host2/bgpd.conf b/tests/topotests/evpn-pim-1/host2/bgpd.conf
new file mode 100644
index 0000000000..cdf4cb4feb
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/host2/bgpd.conf
@@ -0,0 +1 @@
+!
diff --git a/tests/topotests/evpn-pim-1/host2/pimd.conf b/tests/topotests/evpn-pim-1/host2/pimd.conf
new file mode 100644
index 0000000000..63a44c1333
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/host2/pimd.conf
@@ -0,0 +1,4 @@
+int lo
+!
+
+
diff --git a/tests/topotests/evpn-pim-1/host2/zebra.conf b/tests/topotests/evpn-pim-1/host2/zebra.conf
new file mode 100644
index 0000000000..bfae53017f
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/host2/zebra.conf
@@ -0,0 +1,5 @@
+int host-eth0
+ ip addr 192.168.4.5/24
+
+int lo
+ ip addr 192.168.100.5/32
diff --git a/tests/topotests/evpn-pim-1/leaf1/bgpd.conf b/tests/topotests/evpn-pim-1/leaf1/bgpd.conf
new file mode 100644
index 0000000000..33d34db677
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/leaf1/bgpd.conf
@@ -0,0 +1,9 @@
+
+router bgp 65002
+ neighbor 192.168.1.1 remote-as external
+ redistribute connected
+ address-family l2vpn evpn
+ neighbor 192.168.1.1 activate
+ advertise-all-vni
+ !
+! \ No newline at end of file
diff --git a/tests/topotests/evpn-pim-1/leaf1/pimd.conf b/tests/topotests/evpn-pim-1/leaf1/pimd.conf
new file mode 100644
index 0000000000..293e252086
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/leaf1/pimd.conf
@@ -0,0 +1,15 @@
+debug pim events
+debug pim nht
+debug pim zebra
+ip pim rp 192.168.100.1
+!
+int lo
+ ip pim
+!
+int leaf1-eth0
+ ip pim
+!
+int leaf1-eth1
+ ip pim
+ ip igmp
+
diff --git a/tests/topotests/evpn-pim-1/leaf1/zebra.conf b/tests/topotests/evpn-pim-1/leaf1/zebra.conf
new file mode 100644
index 0000000000..581cc6e7be
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/leaf1/zebra.conf
@@ -0,0 +1,6 @@
+int leaf1-eth0
+ ip addr 192.168.1.2/24
+int leaf1-eth1
+ ip addr 192.168.3.2/24
+int lo
+ ip addr 192.168.100.2/32
diff --git a/tests/topotests/evpn-pim-1/leaf2/bgpd.conf b/tests/topotests/evpn-pim-1/leaf2/bgpd.conf
new file mode 100644
index 0000000000..3dd9f237be
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/leaf2/bgpd.conf
@@ -0,0 +1,9 @@
+
+router bgp 65003
+ neighbor 192.168.2.1 remote-as external
+ redistribute connected
+ address-family l2vpn evpn
+ neighbor 192.168.2.1 activate
+ advertise-all-vni
+ !
+! \ No newline at end of file
diff --git a/tests/topotests/evpn-pim-1/leaf2/pimd.conf b/tests/topotests/evpn-pim-1/leaf2/pimd.conf
new file mode 100644
index 0000000000..08d5a19a2a
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/leaf2/pimd.conf
@@ -0,0 +1,13 @@
+ip pim rp 192.168.100.1
+!
+int lo
+ ip pim
+!
+int leaf2-eth0
+ ip pim
+!
+int leaf2-eth1
+ ip pim
+ ip igmp
+!
+
diff --git a/tests/topotests/evpn-pim-1/leaf2/zebra.conf b/tests/topotests/evpn-pim-1/leaf2/zebra.conf
new file mode 100644
index 0000000000..1bcf8e1ded
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/leaf2/zebra.conf
@@ -0,0 +1,6 @@
+int leaf2-eth0
+ ip addr 192.168.2.3/24
+int leaf2-eth1
+ ip addr 192.168.4.3/24
+int lo
+ ip addr 192.168.100.3/32
diff --git a/tests/topotests/evpn-pim-1/spine/bgp.summ.json b/tests/topotests/evpn-pim-1/spine/bgp.summ.json
new file mode 100644
index 0000000000..faf40c8d43
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/spine/bgp.summ.json
@@ -0,0 +1,44 @@
+{
+ "routerId":"192.168.100.1",
+ "as":65001,
+ "vrfId":0,
+ "vrfName":"default",
+ "tableVersion":7,
+ "peerCount":2,
+ "peers":{
+ "192.168.1.2":{
+ "remoteAs":65002,
+ "version":4,
+ "tableVersion":0,
+ "outq":0,
+ "inq":0,
+ "prefixReceivedCount":3,
+ "pfxRcd":3,
+ "pfxSnt":7,
+ "state":"Established",
+ "connectionsEstablished":1,
+ "connectionsDropped":0,
+ "idType":"ipv4"
+ },
+ "192.168.2.3":{
+ "remoteAs":65003,
+ "version":4,
+ "tableVersion":0,
+ "outq":0,
+ "inq":0,
+ "prefixReceivedCount":3,
+ "pfxRcd":3,
+ "pfxSnt":7,
+ "state":"Established",
+ "connectionsEstablished":1,
+ "connectionsDropped":0,
+ "idType":"ipv4"
+ }
+ },
+ "failedPeers":0,
+ "totalPeers":2,
+ "dynamicPeers":0,
+ "bestPath":{
+ "multiPathRelax":"false"
+ }
+}
diff --git a/tests/topotests/evpn-pim-1/spine/bgpd.conf b/tests/topotests/evpn-pim-1/spine/bgpd.conf
new file mode 100644
index 0000000000..9a845043e9
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/spine/bgpd.conf
@@ -0,0 +1,10 @@
+
+router bgp 65001
+ neighbor 192.168.1.2 remote-as external
+ neighbor 192.168.2.3 remote-as external
+ redistribute connected
+ address-family l2vpn evpn
+ neighbor 192.168.1.2 activate
+ neighbor 192.168.2.3 activate
+ exit-address-family
+!
diff --git a/tests/topotests/evpn-pim-1/spine/join-info.json b/tests/topotests/evpn-pim-1/spine/join-info.json
new file mode 100644
index 0000000000..3d135fb964
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/spine/join-info.json
@@ -0,0 +1,34 @@
+{
+ "spine-eth0":{
+ "name":"spine-eth0",
+ "state":"up",
+ "address":"192.168.1.1",
+ "flagMulticast":true,
+ "flagBroadcast":true,
+ "lanDelayEnabled":true,
+ "239.1.1.1":{
+ "*":{
+ "source":"*",
+ "group":"239.1.1.1",
+ "prune":"--:--",
+ "channelJoinName":"JOIN"
+ }
+ }
+ },
+ "spine-eth1":{
+ "name":"spine-eth1",
+ "state":"up",
+ "address":"192.168.2.1",
+ "flagMulticast":true,
+ "flagBroadcast":true,
+ "lanDelayEnabled":true,
+ "239.1.1.1":{
+ "*":{
+ "source":"*",
+ "group":"239.1.1.1",
+ "prune":"--:--",
+ "channelJoinName":"JOIN"
+ }
+ }
+ }
+}
diff --git a/tests/topotests/evpn-pim-1/spine/pimd.conf b/tests/topotests/evpn-pim-1/spine/pimd.conf
new file mode 100644
index 0000000000..56adda5cc4
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/spine/pimd.conf
@@ -0,0 +1,13 @@
+ip pim rp 192.168.100.1
+!
+int lo
+ ip pim
+!
+int spine-eth0
+ ip pim
+!
+int spine-eth1
+ ip pim
+!
+
+
diff --git a/tests/topotests/evpn-pim-1/spine/zebra.conf b/tests/topotests/evpn-pim-1/spine/zebra.conf
new file mode 100644
index 0000000000..2cb719486e
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/spine/zebra.conf
@@ -0,0 +1,8 @@
+int spine-eth0
+ ip addr 192.168.1.1/24
+!
+int spine-eth1
+ ip addr 192.168.2.1/24
+!
+int lo
+ ip addr 192.168.100.1/32
diff --git a/tests/topotests/evpn-pim-1/test_evpn_pim_topo1.py b/tests/topotests/evpn-pim-1/test_evpn_pim_topo1.py
new file mode 100755
index 0000000000..dafe2e03ac
--- /dev/null
+++ b/tests/topotests/evpn-pim-1/test_evpn_pim_topo1.py
@@ -0,0 +1,215 @@
+#!/usr/bin/env python
+
+#
+# test_evpn-pim_topo1.py
+#
+# Copyright (c) 2017 by
+# Cumulus Networks, Inc.
+# Donald Sharp
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_evpn_pim_topo1.py: Testing evpn-pim
+
+"""
+
+import os
+import re
+import sys
+import pytest
+import json
+from functools import partial
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+#####################################################
+##
+## Network Topology Definition
+##
+#####################################################
+
+class NetworkTopo(Topo):
+ "evpn-pim Topology 1"
+
+ def build(self, **_opts):
+ "Build function"
+
+ tgen = get_topogen(self)
+
+ tgen.add_router('spine')
+ tgen.add_router('leaf1')
+ tgen.add_router('leaf2')
+ tgen.add_router('host1')
+ tgen.add_router('host2')
+
+ # On main router
+ # First switch is for a dummy interface (for local network)
+ # spine-eth0 is connected to leaf1-eth0
+ switch = tgen.add_switch('sw1')
+ switch.add_link(tgen.gears['spine'])
+ switch.add_link(tgen.gears['leaf1'])
+
+ # spine-eth1 is connected to leaf2-eth0
+ switch = tgen.add_switch('sw2')
+ switch.add_link(tgen.gears['spine'])
+ switch.add_link(tgen.gears['leaf2'])
+
+ # leaf1-eth1 is connected to host1-eth0
+ switch = tgen.add_switch('sw3')
+ switch.add_link(tgen.gears['leaf1'])
+ switch.add_link(tgen.gears['host1'])
+
+ # leaf2-eth1 is connected to host2-eth0
+ switch = tgen.add_switch('sw4')
+ switch.add_link(tgen.gears['leaf2'])
+ switch.add_link(tgen.gears['host2'])
+
+
+
+#####################################################
+##
+## Tests starting
+##
+#####################################################
+
+def setup_module(module):
+ "Setup topology"
+ tgen = Topogen(NetworkTopo, module.__name__)
+ tgen.start_topology()
+
+ leaf1 = tgen.gears['leaf1']
+ leaf2 = tgen.gears['leaf2']
+
+ leaf1.run('brctl addbr brleaf1')
+ leaf2.run('brctl addbr brleaf2')
+ leaf1.run('ip link set dev brleaf1 up')
+ leaf2.run('ip link set dev brleaf2 up')
+ leaf1.run('ip link add vxlan0 type vxlan id 42 group 239.1.1.1 dev leaf1-eth1 dstport 4789')
+ leaf2.run('ip link add vxlan0 type vxlan id 42 group 239.1.1.1 dev leaf2-eth1 dstport 4789')
+ leaf1.run('brctl addif brleaf1 vxlan0')
+ leaf2.run('brctl addif brleaf2 vxlan0')
+ leaf1.run('ip link set up dev vxlan0')
+ leaf2.run('ip link set up dev vxlan0')
+ #tgen.mininet_cli()
+ # This is a sample of configuration loading.
+ router_list = tgen.routers()
+ for rname, router in router_list.iteritems():
+ 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))
+ )
+ router.load_config(
+ TopoRouter.RD_PIM,
+ os.path.join(CWD, '{}/pimd.conf'.format(rname))
+ )
+ tgen.start_router()
+ #tgen.mininet_cli()
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ # This function tears down the whole topology.
+ tgen.stop_topology()
+
+
+def test_converge_protocols():
+ "Wait for protocol convergence"
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ spine = tgen.gears['spine']
+ json_file = '{}/{}/bgp.summ.json'.format(CWD, spine.name)
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(topotest.router_json_cmp,
+ spine, 'show bgp ipv4 uni summ json', expected)
+ _, result = topotest.run_and_expect(test_func, None, count=125, wait=1)
+ assertmsg = '"{}" JSON output mismatches'.format(spine.name)
+ assert result is None, assertmsg
+ #tgen.mininet_cli()
+
+def test_multicast_groups_on_rp():
+ "Ensure the multicast groups show up on the spine"
+ # This test implicitly tests the auto mcast groups
+ # of the created vlans and then the auto-joins that
+ # pim will do to the RP( spine )
+
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ spine = tgen.gears['spine']
+ json_file = '{}/{}/join-info.json'.format(CWD, spine.name)
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(topotest.router_json_cmp,
+ spine, 'show ip pim join json', expected)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assertmsg = '"{}" JSON output mismatches'.format(spine.name)
+ assert result is None, assertmsg
+ #tgen.mininet_cli()
+
+def test_shutdown_check_stderr():
+ if os.environ.get('TOPOTESTS_CHECK_STDERR') is None:
+ pytest.skip('Skipping test for Stderr output and memory leaks')
+
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Verifying unexpected STDERR output from daemons")
+
+ router_list = tgen.routers().values()
+ for router in router_list:
+ router.stop()
+
+ log = tgen.net[router.name].getStdErr('pimd')
+ if log:
+ logger.error('PIMd StdErr Log:' + log)
+ log = tgen.net[router.name].getStdErr('bgpd')
+ if log:
+ logger.error('BGPd StdErr Log:' + log)
+ log = tgen.net[router.name].getStdErr('zebra')
+ if log:
+ logger.error('Zebra StdErr Log:' + log)
+
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
+
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index a8354f4c77..f3c17be684 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -1293,16 +1293,13 @@ def verify_bgp_attributes(tgen, addr_type, dut, static_routes, rmap_name,
for static_route in static_routes:
cmd = "show bgp {} {} json".format(addr_type, static_route)
show_bgp_json = run_frr_cmd(rnode, cmd, isjson=True)
- print("show_bgp_json $$$$$", show_bgp_json)
dict_to_test = []
tmp_list = []
for rmap_router in input_dict.keys():
for rmap, values in input_dict[rmap_router][
"route_maps"].items():
- print("rmap == rmap_name $$$$1", rmap, rmap_name)
if rmap == rmap_name:
- print("rmap == rmap_name $$$$", rmap, rmap_name)
dict_to_test = values
for rmap_dict in values:
if seq_id is not None:
@@ -1318,7 +1315,6 @@ def verify_bgp_attributes(tgen, addr_type, dut, static_routes, rmap_name,
if tmp_list:
dict_to_test = tmp_list
- print("dict_to_test $$$$", dict_to_test)
for rmap_dict in dict_to_test:
if "set" in rmap_dict:
for criteria in rmap_dict["set"].keys():
diff --git a/tests/topotests/rip-topo1/r1/rip_status.ref b/tests/topotests/rip-topo1/r1/rip_status.ref
index 30c840e508..d75fbe85bb 100644
--- a/tests/topotests/rip-topo1/r1/rip_status.ref
+++ b/tests/topotests/rip-topo1/r1/rip_status.ref
@@ -1,6 +1,6 @@
Routing Protocol is "rip"
- Sending updates every 30 seconds with +/-50%, next due in XX seconds
- Timeout after 180 seconds, garbage collect after 120 seconds
+ Sending updates every 5 seconds with +/-50%, next due in XX seconds
+ Timeout after 180 seconds, garbage collect after 5 seconds
Outgoing update filter list for all interface is not set
Incoming update filter list for all interface is not set
Default redistribution metric is 1
diff --git a/tests/topotests/rip-topo1/r1/ripd.conf b/tests/topotests/rip-topo1/r1/ripd.conf
index 70e70d3590..935ec312e5 100644
--- a/tests/topotests/rip-topo1/r1/ripd.conf
+++ b/tests/topotests/rip-topo1/r1/ripd.conf
@@ -1,6 +1,7 @@
log file ripd.log
!
router rip
+ timers basic 5 180 5
version 2
network 193.1.1.0/26
!
diff --git a/tests/topotests/rip-topo1/r2/rip_status.ref b/tests/topotests/rip-topo1/r2/rip_status.ref
index b539d321d5..da1abd041a 100644
--- a/tests/topotests/rip-topo1/r2/rip_status.ref
+++ b/tests/topotests/rip-topo1/r2/rip_status.ref
@@ -1,6 +1,6 @@
Routing Protocol is "rip"
- Sending updates every 30 seconds with +/-50%, next due in XX seconds
- Timeout after 180 seconds, garbage collect after 120 seconds
+ Sending updates every 5 seconds with +/-50%, next due in XX seconds
+ Timeout after 180 seconds, garbage collect after 5 seconds
Outgoing update filter list for all interface is not set
Incoming update filter list for all interface is not set
Default redistribution metric is 1
diff --git a/tests/topotests/rip-topo1/r2/ripd.conf b/tests/topotests/rip-topo1/r2/ripd.conf
index 179a1ebd0f..2e94cfa262 100644
--- a/tests/topotests/rip-topo1/r2/ripd.conf
+++ b/tests/topotests/rip-topo1/r2/ripd.conf
@@ -3,6 +3,7 @@ log file ripd.log
!
router rip
version 2
+ timers basic 5 180 5
network 193.1.1.0/26
network 193.1.2.0/24
!
diff --git a/tests/topotests/rip-topo1/r3/rip_status.ref b/tests/topotests/rip-topo1/r3/rip_status.ref
index 0e3a4be944..040d3c32a1 100644
--- a/tests/topotests/rip-topo1/r3/rip_status.ref
+++ b/tests/topotests/rip-topo1/r3/rip_status.ref
@@ -1,6 +1,6 @@
Routing Protocol is "rip"
- Sending updates every 30 seconds with +/-50%, next due in XX seconds
- Timeout after 180 seconds, garbage collect after 120 seconds
+ Sending updates every 5 seconds with +/-50%, next due in XX seconds
+ Timeout after 180 seconds, garbage collect after 5 seconds
Outgoing update filter list for all interface is not set
Incoming update filter list for all interface is not set
Default redistribution metric is 1
diff --git a/tests/topotests/rip-topo1/r3/ripd.conf b/tests/topotests/rip-topo1/r3/ripd.conf
index 363b91b33a..e27e67503f 100644
--- a/tests/topotests/rip-topo1/r3/ripd.conf
+++ b/tests/topotests/rip-topo1/r3/ripd.conf
@@ -3,6 +3,7 @@ log file ripd.log
!
router rip
version 2
+ timers basic 5 180 5
redistribute connected
redistribute static
network 193.1.2.0/24
diff --git a/tests/topotests/rip-topo1/test_rip_topo1.py b/tests/topotests/rip-topo1/test_rip_topo1.py
index 7aaaacacfb..8f3c25e910 100755
--- a/tests/topotests/rip-topo1/test_rip_topo1.py
+++ b/tests/topotests/rip-topo1/test_rip_topo1.py
@@ -144,7 +144,6 @@ def test_router_running():
print("\n\n** Check if FRR/Quagga is running on each Router node")
print("******************************************\n")
- sleep(5)
# Make sure that all daemons are running
for i in range(1, 4):
@@ -168,8 +167,8 @@ def test_converge_protocols():
print("\n\n** Waiting for protocols convergence")
print("******************************************\n")
- # Not really implemented yet - just sleep 60 secs for now
- sleep(60)
+ # Not really implemented yet - just sleep 11 secs for now
+ sleep(11)
# Make sure that all daemons are still running
for i in range(1, 4):
diff --git a/tests/topotests/ripng-topo1/r1/ripng_status.ref b/tests/topotests/ripng-topo1/r1/ripng_status.ref
index 48816c1a9b..e6197f179b 100644
--- a/tests/topotests/ripng-topo1/r1/ripng_status.ref
+++ b/tests/topotests/ripng-topo1/r1/ripng_status.ref
@@ -1,6 +1,6 @@
Routing Protocol is "RIPng"
- Sending updates every 30 seconds with +/-50%, next due in XX seconds
- Timeout after 180 seconds, garbage collect after 120 seconds
+ Sending updates every 5 seconds with +/-50%, next due in XX seconds
+ Timeout after 180 seconds, garbage collect after 5 seconds
Outgoing update filter list for all interface is not set
Incoming update filter list for all interface is not set
Default redistribution metric is 1
diff --git a/tests/topotests/ripng-topo1/r1/ripngd.conf b/tests/topotests/ripng-topo1/r1/ripngd.conf
index 5eb78eafe2..dd54c43557 100644
--- a/tests/topotests/ripng-topo1/r1/ripngd.conf
+++ b/tests/topotests/ripng-topo1/r1/ripngd.conf
@@ -5,6 +5,7 @@ debug ripng packet
debug ripng zebra
!
router ripng
+ timers basic 5 180 5
network fc00:5::/64
!
line vty
diff --git a/tests/topotests/ripng-topo1/r2/ripng_status.ref b/tests/topotests/ripng-topo1/r2/ripng_status.ref
index fddcf63e5b..640df9a4a0 100644
--- a/tests/topotests/ripng-topo1/r2/ripng_status.ref
+++ b/tests/topotests/ripng-topo1/r2/ripng_status.ref
@@ -1,6 +1,6 @@
Routing Protocol is "RIPng"
- Sending updates every 30 seconds with +/-50%, next due in XX seconds
- Timeout after 180 seconds, garbage collect after 120 seconds
+ Sending updates every 5 seconds with +/-50%, next due in XX seconds
+ Timeout after 180 seconds, garbage collect after 5 seconds
Outgoing update filter list for all interface is not set
Incoming update filter list for all interface is not set
Default redistribution metric is 1
diff --git a/tests/topotests/ripng-topo1/r2/ripngd.conf b/tests/topotests/ripng-topo1/r2/ripngd.conf
index a25a3cd490..ef2c42195d 100644
--- a/tests/topotests/ripng-topo1/r2/ripngd.conf
+++ b/tests/topotests/ripng-topo1/r2/ripngd.conf
@@ -5,6 +5,7 @@ debug ripng packet
debug ripng zebra
!
router ripng
+ timers basic 5 180 5
network fc00:5::/64
network fc00:6::/62
!
diff --git a/tests/topotests/ripng-topo1/r3/ripng_status.ref b/tests/topotests/ripng-topo1/r3/ripng_status.ref
index 1a8dabbf5f..f4bfff0c59 100644
--- a/tests/topotests/ripng-topo1/r3/ripng_status.ref
+++ b/tests/topotests/ripng-topo1/r3/ripng_status.ref
@@ -1,6 +1,6 @@
Routing Protocol is "RIPng"
- Sending updates every 30 seconds with +/-50%, next due in XX seconds
- Timeout after 180 seconds, garbage collect after 120 seconds
+ Sending updates every 5 seconds with +/-50%, next due in XX seconds
+ Timeout after 180 seconds, garbage collect after 5 seconds
Outgoing update filter list for all interface is not set
Incoming update filter list for all interface is not set
Default redistribution metric is 1
diff --git a/tests/topotests/ripng-topo1/r3/ripngd.conf b/tests/topotests/ripng-topo1/r3/ripngd.conf
index dfa5700adb..506eaac442 100644
--- a/tests/topotests/ripng-topo1/r3/ripngd.conf
+++ b/tests/topotests/ripng-topo1/r3/ripngd.conf
@@ -5,6 +5,7 @@ debug ripng packet
debug ripng zebra
!
router ripng
+ timers basic 5 180 5
network fc00:6::/62
redistribute connected
redistribute static
diff --git a/tests/topotests/ripng-topo1/test_ripng_topo1.py b/tests/topotests/ripng-topo1/test_ripng_topo1.py
index 145b1a7efe..32b137240c 100755
--- a/tests/topotests/ripng-topo1/test_ripng_topo1.py
+++ b/tests/topotests/ripng-topo1/test_ripng_topo1.py
@@ -145,7 +145,6 @@ def test_router_running():
print("\n\n** Check if FRR/Quagga is running on each Router node")
print("******************************************\n")
- sleep(5)
# Starting Routers
for i in range(1, 4):
@@ -169,8 +168,8 @@ def test_converge_protocols():
print("\n\n** Waiting for protocols convergence")
print("******************************************\n")
- # Not really implemented yet - just sleep 60 secs for now
- sleep(60)
+ # Not really implemented yet - just sleep 11 secs for now
+ sleep(11)
# Make sure that all daemons are running
for i in range(1, 4):
diff --git a/zebra/debug.c b/zebra/debug.c
index 16b1d0057b..68f6b69305 100644
--- a/zebra/debug.c
+++ b/zebra/debug.c
@@ -544,6 +544,10 @@ static int config_write_debug(struct vty *vty)
vty_out(vty, "debug zebra vxlan\n");
write++;
}
+ if (IS_ZEBRA_DEBUG_MLAG) {
+ vty_out(vty, "debug zebra mlag\n");
+ write++;
+ }
if (IS_ZEBRA_DEBUG_PW) {
vty_out(vty, "debug zebra pseudowires\n");
write++;
@@ -633,4 +637,5 @@ void zebra_debug_init(void)
install_element(CONFIG_NODE, &no_debug_zebra_rib_cmd);
install_element(CONFIG_NODE, &no_debug_zebra_fpm_cmd);
install_element(CONFIG_NODE, &no_debug_zebra_dplane_cmd);
+ install_element(CONFIG_NODE, &debug_zebra_mlag_cmd);
}
diff --git a/zebra/interface.c b/zebra/interface.c
index 7e7397a3bb..a434ba0d38 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -617,11 +617,14 @@ void if_add_update(struct interface *ifp)
SET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) {
- if (IS_ZEBRA_DEBUG_KERNEL)
+ if (IS_ZEBRA_DEBUG_KERNEL) {
zlog_debug(
- "interface %s vrf %u index %d is shutdown. "
+ "interface %s vrf %s(%u) index %d is shutdown. "
"Won't wake it up.",
- ifp->name, ifp->vrf_id, ifp->ifindex);
+ ifp->name, VRF_LOGNAME(zvrf->vrf),
+ ifp->vrf_id, ifp->ifindex);
+ }
+
return;
}
@@ -629,13 +632,15 @@ void if_add_update(struct interface *ifp)
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "interface %s vrf %u index %d becomes active.",
- ifp->name, ifp->vrf_id, ifp->ifindex);
+ "interface %s vrf %s(%u) index %d becomes active.",
+ ifp->name, VRF_LOGNAME(zvrf->vrf), ifp->vrf_id,
+ ifp->ifindex);
} else {
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("interface %s vrf %u index %d is added.",
- ifp->name, ifp->vrf_id, ifp->ifindex);
+ zlog_debug("interface %s vrf %s(%u) index %d is added.",
+ ifp->name, VRF_LOGNAME(zvrf->vrf),
+ ifp->vrf_id, ifp->ifindex);
}
}
@@ -774,10 +779,12 @@ void if_delete_update(struct interface *ifp)
struct zebra_if *zif;
if (if_is_up(ifp)) {
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+
flog_err(
EC_LIB_INTERFACE,
- "interface %s vrf %u index %d is still up while being deleted.",
- ifp->name, ifp->vrf_id, ifp->ifindex);
+ "interface %s vrf %s(%u) index %d is still up while being deleted.",
+ ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id, ifp->ifindex);
return;
}
@@ -787,9 +794,13 @@ void if_delete_update(struct interface *ifp)
/* Mark interface as inactive */
UNSET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("interface %s vrf %u index %d is now inactive.",
- ifp->name, ifp->vrf_id, ifp->ifindex);
+ if (IS_ZEBRA_DEBUG_KERNEL) {
+ struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
+
+ zlog_debug("interface %s vrf %s(%u) index %d is now inactive.",
+ ifp->name, VRF_LOGNAME(vrf), ifp->vrf_id,
+ ifp->ifindex);
+ }
/* Delete connected routes from the kernel. */
if_delete_connected(ifp);
@@ -1863,7 +1874,8 @@ DEFUN (show_interface_desc_vrf_all,
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
if (!RB_EMPTY(if_name_head, &vrf->ifaces_by_name)) {
- vty_out(vty, "\n\tVRF %u\n\n", vrf->vrf_id);
+ vty_out(vty, "\n\tVRF %s(%u)\n\n", VRF_LOGNAME(vrf),
+ vrf->vrf_id);
if_show_description(vty, vrf->vrf_id);
}
diff --git a/zebra/ipforward_proc.c b/zebra/ipforward_proc.c
index 226f722937..4bd160ddbc 100644
--- a/zebra/ipforward_proc.c
+++ b/zebra/ipforward_proc.c
@@ -34,9 +34,7 @@ static const char proc_net_snmp[] = "/proc/net/snmp";
static void dropline(FILE *fp)
{
- int c;
-
- while ((c = getc(fp)) != '\n')
+ while (getc(fp) != '\n')
;
}
diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c
index f6fe6bbf1e..13dcab9294 100644
--- a/zebra/irdp_packet.c
+++ b/zebra/irdp_packet.c
@@ -78,6 +78,7 @@ static void parse_irdp_packet(char *p, int len, struct interface *ifp)
int ip_hlen, iplen, datalen;
struct zebra_if *zi;
struct irdp_interface *irdp;
+ uint16_t saved_chksum;
zi = ifp->info;
if (!zi)
@@ -121,8 +122,10 @@ static void parse_irdp_packet(char *p, int len, struct interface *ifp)
icmp = (struct icmphdr *)(p + ip_hlen);
+ saved_chksum = icmp->checksum;
+ icmp->checksum = 0;
/* check icmp checksum */
- if (in_cksum(icmp, datalen) != icmp->checksum) {
+ if (in_cksum(icmp, datalen) != saved_chksum) {
flog_warn(
EC_ZEBRA_IRDP_BAD_CHECKSUM,
"IRDP: RX ICMP packet from %s. Bad checksum, silently ignored",
@@ -315,15 +318,20 @@ void send_packet(struct interface *ifp, struct stream *s, uint32_t dst,
if (setsockopt(irdp_sock, IPPROTO_IP, IP_HDRINCL, (char *)&on,
sizeof(on))
< 0)
- zlog_debug("sendto %s", safe_strerror(errno));
+ flog_err(EC_LIB_SOCKET,
+ "IRDP: Cannot set IP_HDRINCLU %s(%d) on %s",
+ safe_strerror(errno), errno, ifp->name);
if (dst == INADDR_BROADCAST) {
- on = 1;
- if (setsockopt(irdp_sock, SOL_SOCKET, SO_BROADCAST, (char *)&on,
- sizeof(on))
+ uint32_t bon = 1;
+
+ if (setsockopt(irdp_sock, SOL_SOCKET, SO_BROADCAST, &bon,
+ sizeof(bon))
< 0)
- zlog_debug("sendto %s", safe_strerror(errno));
+ flog_err(EC_LIB_SOCKET,
+ "IRDP: Cannot set SO_BROADCAST %s(%d) on %s",
+ safe_strerror(errno), errno, ifp->name);
}
if (dst != INADDR_BROADCAST)
@@ -354,8 +362,8 @@ void send_packet(struct interface *ifp, struct stream *s, uint32_t dst,
sockopt_iphdrincl_swab_htosys(ip);
- if (sendmsg(irdp_sock, msg, 0) < 0) {
- zlog_debug("sendto %s", safe_strerror(errno));
- }
- /* printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */
+ if (sendmsg(irdp_sock, msg, 0) < 0)
+ flog_err(EC_LIB_SOCKET,
+ "IRDP: sendmsg send failure %s(%d) on %s",
+ safe_strerror(errno), errno, ifp->name);
}
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index b891fb121f..3d203dea47 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -339,9 +339,10 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug(
- "%s: client proto %s afi=%d, wants %s, vrf %u, instance=%d",
+ "%s: client proto %s afi=%d, wants %s, vrf %s(%u), instance=%d",
__func__, zebra_route_string(client->proto), afi,
- zebra_route_string(type), zvrf_id(zvrf), instance);
+ zebra_route_string(type), VRF_LOGNAME(zvrf->vrf),
+ zvrf_id(zvrf), instance);
if (afi == 0 || afi >= AFI_MAX) {
flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
@@ -368,8 +369,10 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
if (!vrf_bitmap_check(client->redist[afi][type],
zvrf_id(zvrf))) {
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("%s: setting vrf %u redist bitmap",
- __func__, zvrf_id(zvrf));
+ zlog_debug(
+ "%s: setting vrf %s(%u) redist bitmap",
+ __func__, VRF_LOGNAME(zvrf->vrf),
+ zvrf_id(zvrf));
vrf_bitmap_set(client->redist[afi][type],
zvrf_id(zvrf));
zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi);
@@ -645,7 +648,7 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
if (rmap_name)
ret = zebra_import_table_route_map_check(
afi, re->type, re->instance, &rn->p,
- re->nhe->nhg->nexthop,
+ re->nhe->nhg.nexthop,
zvrf->vrf->vrf_id, re->tag, rmap_name);
if (ret != RMAP_PERMITMATCH) {
@@ -682,7 +685,7 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
newre->instance = re->table;
ng = nexthop_group_new();
- copy_nexthops(&ng->nexthop, re->nhe->nhg->nexthop, NULL);
+ copy_nexthops(&ng->nexthop, re->nhe->nhg.nexthop, NULL);
rib_add_multipath(afi, SAFI_UNICAST, &p, NULL, newre, ng);
@@ -699,7 +702,7 @@ int zebra_del_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
prefix_copy(&p, &rn->p);
rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_TABLE,
- re->table, re->flags, &p, NULL, re->nhe->nhg->nexthop,
+ re->table, re->flags, &p, NULL, re->nhe->nhg.nexthop,
re->nhe_id, zvrf->table_id, re->metric, re->distance,
false);
diff --git a/zebra/rib.h b/zebra/rib.h
index 927675e3d9..931c97638e 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -515,7 +515,7 @@ static inline struct nexthop_group *rib_active_nhg(struct route_entry *re)
if (re->fib_ng.nexthop)
return &(re->fib_ng);
else
- return re->nhe->nhg;
+ return &(re->nhe->nhg);
}
extern void zebra_vty_init(void);
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index e36af00b4e..829dcfcfd2 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -2479,4 +2479,25 @@ void rtadv_cmd_init(void)
{
/* Empty.*/;
}
+
+void rtadv_add_prefix(struct zebra_if *zif, const struct prefix_ipv6 *p)
+{
+ /* Empty.*/;
+}
+
+void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p)
+{
+ /* Empty.*/;
+}
+
+void rtadv_stop_ra(struct interface *ifp)
+{
+ /* Empty.*/;
+}
+
+void rtadv_stop_ra_all(void)
+{
+ /* Empty.*/;
+}
+
#endif /* HAVE_RTADV */
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 4d0e34561a..43bad5522c 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -580,7 +580,7 @@ int zsend_redistribute_route(int cmd, struct zserv *client,
memcpy(&api.src_prefix, src_p, sizeof(api.src_prefix));
}
- for (nexthop = re->nhe->nhg->nexthop;
+ for (nexthop = re->nhe->nhg.nexthop;
nexthop; nexthop = nexthop->next) {
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
continue;
@@ -689,7 +689,7 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
* nexthop we are looking up. Therefore, we will just iterate
* over the top chain of nexthops.
*/
- for (nexthop = re->nhe->nhg->nexthop; nexthop;
+ for (nexthop = re->nhe->nhg.nexthop; nexthop;
nexthop = nexthop->next)
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
num += zserv_encode_nexthop(s, nexthop);
@@ -1823,17 +1823,17 @@ static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS)
return;
for (int i = 0; i < zl.nexthop_num; i++) {
- struct zapi_nexthop_label *znh;
+ struct zapi_nexthop *znh;
znh = &zl.nexthops[i];
- mpls_lsp_install(zvrf, zl.type, zl.local_label, 1, &znh->label,
- znh->type, &znh->address, znh->ifindex);
+ mpls_lsp_install(zvrf, zl.type, zl.local_label, 1, znh->labels,
+ znh->type, &znh->gate, znh->ifindex);
if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
mpls_ftn_update(1, zvrf, zl.type, &zl.route.prefix,
- znh->type, &znh->address, znh->ifindex,
+ znh->type, &znh->gate, znh->ifindex,
zl.route.type, zl.route.instance,
- znh->label);
+ znh->labels[0]);
}
}
@@ -1866,19 +1866,20 @@ static void zread_mpls_labels_delete(ZAPI_HANDLER_ARGS)
if (zl.nexthop_num > 0) {
for (int i = 0; i < zl.nexthop_num; i++) {
- struct zapi_nexthop_label *znh;
+ struct zapi_nexthop *znh;
znh = &zl.nexthops[i];
mpls_lsp_uninstall(zvrf, zl.type, zl.local_label,
- znh->type, &znh->address,
+ znh->type, &znh->gate,
znh->ifindex);
if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN))
mpls_ftn_update(0, zvrf, zl.type,
&zl.route.prefix, znh->type,
- &znh->address, znh->ifindex,
+ &znh->gate, znh->ifindex,
zl.route.type,
- zl.route.instance, znh->label);
+ zl.route.instance,
+ znh->labels[0]);
}
} else {
mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label);
@@ -1924,17 +1925,18 @@ static void zread_mpls_labels_replace(ZAPI_HANDLER_ARGS)
zl.route.type, zl.route.instance);
for (int i = 0; i < zl.nexthop_num; i++) {
- struct zapi_nexthop_label *znh;
+ struct zapi_nexthop *znh;
znh = &zl.nexthops[i];
- mpls_lsp_install(zvrf, zl.type, zl.local_label, 1, &znh->label,
- znh->type, &znh->address, znh->ifindex);
+ mpls_lsp_install(zvrf, zl.type, zl.local_label,
+ 1, znh->labels, znh->type,
+ &znh->gate, znh->ifindex);
if (CHECK_FLAG(zl.message, ZAPI_LABELS_FTN)) {
mpls_ftn_update(1, zvrf, zl.type, &zl.route.prefix,
- znh->type, &znh->address, znh->ifindex,
+ znh->type, &znh->gate, znh->ifindex,
zl.route.type, zl.route.instance,
- znh->label);
+ znh->labels[0]);
}
}
}
@@ -1946,6 +1948,7 @@ static void zread_table_manager_connect(struct zserv *client,
struct stream *s;
uint8_t proto;
uint16_t instance;
+ struct vrf *vrf = vrf_lookup_by_id(vrf_id);
s = msg;
@@ -1961,8 +1964,9 @@ static void zread_table_manager_connect(struct zserv *client,
zsend_table_manager_connect_response(client, vrf_id, 1);
return;
}
- zlog_notice("client %d with vrf %u instance %u connected as %s",
- client->sock, vrf_id, instance, zebra_route_string(proto));
+ zlog_notice("client %d with vrf %s(%u) instance %u connected as %s",
+ client->sock, VRF_LOGNAME(vrf), vrf_id, instance,
+ zebra_route_string(proto));
client->proto = proto;
client->instance = instance;
@@ -2408,15 +2412,14 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS)
|| zpr.rule.filter.src_ip.family == AF_INET6)) {
zlog_warn(
"Unsupported PBR source IP family: %s (%" PRIu8
- ")\n",
+ ")",
family2str(zpr.rule.filter.src_ip.family),
zpr.rule.filter.src_ip.family);
return;
}
if (!(zpr.rule.filter.dst_ip.family == AF_INET
|| zpr.rule.filter.dst_ip.family == AF_INET6)) {
- zlog_warn("Unsupported PBR IP family: %s (%" PRIu8
- ")\n",
+ zlog_warn("Unsupported PBR IP family: %s (%" PRIu8 ")",
family2str(zpr.rule.filter.dst_ip.family),
zpr.rule.filter.dst_ip.family);
return;
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 17b148178f..5d0d0a48c3 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -1513,9 +1513,9 @@ static int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx,
/* Copy nexthops; recursive info is included too */
copy_nexthops(&(ctx->u.rinfo.zd_ng.nexthop),
- re->nhe->nhg->nexthop, NULL);
+ re->nhe->nhg.nexthop, NULL);
- /* Ensure that the dplane's nexthops flags are clear. */
+ /* Ensure that the dplane nexthops' flags are clear. */
for (ALL_NEXTHOPS(ctx->u.rinfo.zd_ng, nexthop))
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
@@ -1596,9 +1596,9 @@ static int dplane_ctx_nexthop_init(struct zebra_dplane_ctx *ctx,
ctx->u.rinfo.nhe.vrf_id = nhe->vrf_id;
ctx->u.rinfo.nhe.type = nhe->type;
- nexthop_group_copy(&(ctx->u.rinfo.nhe.ng), nhe->nhg);
+ nexthop_group_copy(&(ctx->u.rinfo.nhe.ng), &(nhe->nhg));
- /* If its a group, convert it to a grp array of ids */
+ /* If this is a group, convert it to a grp array of ids */
if (!zebra_nhg_depends_is_empty(nhe)
&& !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_RECURSIVE))
ctx->u.rinfo.nhe.nh_grp_count = zebra_nhg_nhe2grp(
@@ -1753,7 +1753,7 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
if (re)
copy_nexthops(&(ctx->u.pw.nhg.nexthop),
- re->nhe->nhg->nexthop, NULL);
+ re->nhe->nhg.nexthop, NULL);
route_unlock_node(rn);
}
@@ -1849,7 +1849,7 @@ dplane_route_update_internal(struct route_node *rn,
* We'll need these to do per-nexthop deletes.
*/
copy_nexthops(&(ctx->u.rinfo.zd_old_ng.nexthop),
- old_re->nhe->nhg->nexthop, NULL);
+ old_re->nhe->nhg.nexthop, NULL);
#endif /* !HAVE_NETLINK */
}
diff --git a/zebra/zebra_fpm_dt.c b/zebra/zebra_fpm_dt.c
index 389781d4f7..81437e72f5 100644
--- a/zebra/zebra_fpm_dt.c
+++ b/zebra/zebra_fpm_dt.c
@@ -90,7 +90,7 @@ static int zfpm_dt_find_route(rib_dest_t **dest_p, struct route_entry **re_p)
if (!re)
continue;
- if (nexthop_group_active_nexthop_num(re->nhe->nhg) == 0)
+ if (nexthop_group_active_nexthop_num(&(re->nhe->nhg)) == 0)
continue;
*dest_p = dest;
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index be29b75aea..929e675351 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -309,7 +309,7 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd,
ri->rtm_type = RTN_UNICAST;
ri->metric = &re->metric;
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) {
+ for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) {
if (ri->num_nhs >= zrouter.multipath_num)
break;
diff --git a/zebra/zebra_fpm_protobuf.c b/zebra/zebra_fpm_protobuf.c
index d50981debf..ade4b636d6 100644
--- a/zebra/zebra_fpm_protobuf.c
+++ b/zebra/zebra_fpm_protobuf.c
@@ -173,7 +173,7 @@ static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator,
* Figure out the set of nexthops to be added to the message.
*/
num_nhs = 0;
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) {
+ for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) {
if (num_nhs >= zrouter.multipath_num)
break;
diff --git a/zebra/zebra_gr.c b/zebra/zebra_gr.c
index e8c7304f44..956fe9c2c8 100644
--- a/zebra/zebra_gr.c
+++ b/zebra/zebra_gr.c
@@ -468,9 +468,7 @@ static int32_t zebra_gr_route_stale_delete_timer_expiry(struct thread *thread)
LOG_GR("%s: Client %s all starle routes processed", __func__,
zebra_route_string(client->proto));
- if (info->current_prefix != NULL)
- XFREE(MTYPE_TMP, info->current_prefix);
- info->current_prefix = NULL;
+ XFREE(MTYPE_TMP, info->current_prefix);
info->current_afi = 0;
zebra_gr_delete_stale_client(info);
}
@@ -516,7 +514,6 @@ static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info,
struct route_entry *next;
struct route_table *table;
int32_t n = 0;
- struct prefix *p;
afi_t afi, curr_afi;
uint8_t proto;
uint16_t instance;
@@ -541,25 +538,21 @@ static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info,
/* Process routes for all AFI */
for (afi = curr_afi; afi < AFI_MAX; afi++) {
table = zvrf->table[afi][SAFI_UNICAST];
- p = info->current_prefix;
if (table) {
/*
* If the current prefix is NULL then get the first
* route entry in the table
*/
- if (p == NULL) {
+ if (info->current_prefix == NULL) {
rn = route_top(table);
if (rn == NULL)
continue;
- p = XCALLOC(MTYPE_TMP, sizeof(struct prefix));
- if (p == NULL)
- return -1;
curr = rn;
- prefix_copy(p, &rn->p);
} else
/* Get the next route entry */
- curr = route_table_get_next(table, p);
+ curr = route_table_get_next(
+ table, info->current_prefix);
for (rn = curr; rn; rn = srcdest_route_next(rn)) {
RNODE_FOREACH_RE_SAFE (rn, re, next) {
@@ -583,9 +576,13 @@ static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info,
*/
if ((n >= ZEBRA_MAX_STALE_ROUTE_COUNT)
&& (info->delete == false)) {
- prefix_copy(p, &rn->p);
info->current_afi = afi;
- info->current_prefix = p;
+ info->current_prefix = XCALLOC(
+ MTYPE_TMP,
+ sizeof(struct prefix));
+ prefix_copy(
+ info->current_prefix,
+ &rn->p);
return n;
}
}
@@ -595,11 +592,7 @@ static int32_t zebra_gr_delete_stale_route(struct client_gr_info *info,
* Reset the current prefix to indicate processing completion
* of the current AFI
*/
- if (info->current_prefix) {
- XFREE(MTYPE_TMP, info->current_prefix);
- info->current_prefix = NULL;
- }
- continue;
+ XFREE(MTYPE_TMP, info->current_prefix);
}
return 0;
}
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index c167e6a8ad..fa6b952244 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -186,7 +186,7 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
* the label advertised by the recursive nexthop (plus we don't have the
* logic yet to push multiple labels).
*/
- for (nexthop = re->nhe->nhg->nexthop;
+ for (nexthop = re->nhe->nhg.nexthop;
nexthop; nexthop = nexthop->next) {
/* Skip inactive and recursive entries. */
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
@@ -638,7 +638,7 @@ static int nhlfe_nexthop_active_ipv4(zebra_nhlfe_t *nhlfe,
|| !CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED))
continue;
- for (match_nh = match->nhe->nhg->nexthop; match_nh;
+ for (match_nh = match->nhe->nhg.nexthop; match_nh;
match_nh = match_nh->next) {
if (match->type == ZEBRA_ROUTE_CONNECT
|| nexthop->ifindex == match_nh->ifindex) {
@@ -689,10 +689,10 @@ static int nhlfe_nexthop_active_ipv6(zebra_nhlfe_t *nhlfe,
break;
}
- if (!match || !match->nhe->nhg->nexthop)
+ if (!match || !match->nhe->nhg.nexthop)
return 0;
- nexthop->ifindex = match->nhe->nhg->nexthop->ifindex;
+ nexthop->ifindex = match->nhe->nhg.nexthop->ifindex;
return 1;
}
@@ -2631,7 +2631,7 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
* We can't just change the values here since we are hashing
* on labels. We need to create a whole new group
*/
- nexthop_group_copy(&new_grp, re->nhe->nhg);
+ nexthop_group_copy(&new_grp, &(re->nhe->nhg));
found = false;
for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next) {
@@ -2712,7 +2712,7 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
if (re == NULL)
return -1;
- nexthop_group_copy(&new_grp, re->nhe->nhg);
+ nexthop_group_copy(&new_grp, &(re->nhe->nhg));
for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next)
nexthop_del_labels(nexthop);
@@ -2949,7 +2949,7 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
RNODE_FOREACH_RE (rn, re) {
struct nexthop_group new_grp = {};
- nexthop_group_copy(&new_grp, re->nhe->nhg);
+ nexthop_group_copy(&new_grp, &(re->nhe->nhg));
for (nexthop = new_grp.nexthop; nexthop;
nexthop = nexthop->next) {
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index bb95e72382..7f81e530fb 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -315,20 +315,20 @@ zebra_nhg_connect_depends(struct nhg_hash_entry *nhe,
}
/* Add the ifp now if its not a group or recursive and has ifindex */
- if (zebra_nhg_depends_is_empty(nhe) && nhe->nhg->nexthop
- && nhe->nhg->nexthop->ifindex) {
+ if (zebra_nhg_depends_is_empty(nhe) && nhe->nhg.nexthop
+ && nhe->nhg.nexthop->ifindex) {
struct interface *ifp = NULL;
- ifp = if_lookup_by_index(nhe->nhg->nexthop->ifindex,
- nhe->nhg->nexthop->vrf_id);
+ ifp = if_lookup_by_index(nhe->nhg.nexthop->ifindex,
+ nhe->nhg.nexthop->vrf_id);
if (ifp)
zebra_nhg_set_if(nhe, ifp);
else
flog_err(
EC_ZEBRA_IF_LOOKUP_FAILED,
"Zebra failed to lookup an interface with ifindex=%d in vrf=%u for NHE id=%u",
- nhe->nhg->nexthop->ifindex,
- nhe->nhg->nexthop->vrf_id, nhe->id);
+ nhe->nhg.nexthop->ifindex,
+ nhe->nhg.nexthop->vrf_id, nhe->id);
}
}
@@ -350,8 +350,7 @@ static struct nhg_hash_entry *zebra_nhg_copy(const struct nhg_hash_entry *copy,
nhe->id = id;
- nhe->nhg = nexthop_group_new();
- nexthop_group_copy(nhe->nhg, copy->nhg);
+ nexthop_group_copy(&(nhe->nhg), &(copy->nhg));
nhe->vrf_id = copy->vrf_id;
nhe->afi = copy->afi;
@@ -371,7 +370,7 @@ static void *zebra_nhg_hash_alloc(void *arg)
nhe = zebra_nhg_copy(copy, copy->id);
/* Mark duplicate nexthops in a group at creation time. */
- nexthop_group_mark_duplicates(nhe->nhg);
+ nexthop_group_mark_duplicates(&(nhe->nhg));
zebra_nhg_connect_depends(nhe, copy->nhg_depends);
zebra_nhg_insert_id(nhe);
@@ -385,7 +384,8 @@ uint32_t zebra_nhg_hash_key(const void *arg)
uint32_t key = 0x5a351234;
- key = jhash_3words(nhe->vrf_id, nhe->afi, nexthop_group_hash(nhe->nhg),
+ key = jhash_3words(nhe->vrf_id, nhe->afi,
+ nexthop_group_hash(&(nhe->nhg)),
key);
return key;
@@ -416,7 +416,7 @@ bool zebra_nhg_hash_equal(const void *arg1, const void *arg2)
return false;
/* Nexthops should be sorted */
- for (nexthop1 = nhe1->nhg->nexthop, nexthop2 = nhe2->nhg->nexthop;
+ for (nexthop1 = nhe1->nhg.nexthop, nexthop2 = nhe2->nhg.nexthop;
nexthop1 || nexthop2;
nexthop1 = nexthop1->next, nexthop2 = nexthop2->next) {
if (nexthop1 && !nexthop2)
@@ -498,7 +498,7 @@ static int zebra_nhg_process_grp(struct nexthop_group *nhg,
* in the kernel.
*/
- copy_nexthops(&nhg->nexthop, depend->nhg->nexthop, NULL);
+ copy_nexthops(&nhg->nexthop, depend->nhg.nexthop, NULL);
}
return 0;
@@ -536,14 +536,14 @@ static bool zebra_nhg_find(struct nhg_hash_entry **nhe, uint32_t id,
lookup.id = id ? id : ++id_counter;
lookup.type = type ? type : ZEBRA_ROUTE_NHG;
- lookup.nhg = nhg;
+ lookup.nhg = *nhg;
lookup.vrf_id = vrf_id;
- if (lookup.nhg->nexthop->next) {
+ if (lookup.nhg.nexthop->next) {
/* Groups can have all vrfs and AF's in them */
lookup.afi = AFI_UNSPEC;
} else {
- switch (lookup.nhg->nexthop->type) {
+ switch (lookup.nhg.nexthop->type) {
case (NEXTHOP_TYPE_IFINDEX):
case (NEXTHOP_TYPE_BLACKHOLE):
/*
@@ -1206,7 +1206,8 @@ zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi)
static void zebra_nhg_free_members(struct nhg_hash_entry *nhe)
{
- nexthop_group_delete(&nhe->nhg);
+ nexthops_free(nhe->nhg.nexthop);
+
/* Decrement to remove connection ref */
nhg_connected_tree_decrement_ref(&nhe->nhg_depends);
nhg_connected_tree_free(&nhe->nhg_depends);
@@ -1533,7 +1534,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
if (match->type == ZEBRA_ROUTE_CONNECT) {
/* Directly point connected route. */
- newhop = match->nhe->nhg->nexthop;
+ newhop = match->nhe->nhg.nexthop;
if (newhop) {
if (nexthop->type == NEXTHOP_TYPE_IPV4
|| nexthop->type == NEXTHOP_TYPE_IPV6)
@@ -1542,7 +1543,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
return 1;
} else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_ALLOW_RECURSION)) {
resolved = 0;
- for (ALL_NEXTHOPS_PTR(match->nhe->nhg, newhop)) {
+ for (ALL_NEXTHOPS(match->nhe->nhg, newhop)) {
if (!CHECK_FLAG(match->status,
ROUTE_ENTRY_INSTALLED))
continue;
@@ -1563,7 +1564,7 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
return resolved;
} else if (re->type == ZEBRA_ROUTE_STATIC) {
resolved = 0;
- for (ALL_NEXTHOPS_PTR(match->nhe->nhg, newhop)) {
+ for (ALL_NEXTHOPS(match->nhe->nhg, newhop)) {
if (!CHECK_FLAG(match->status,
ROUTE_ENTRY_INSTALLED))
continue;
@@ -1754,7 +1755,7 @@ int nexthop_active_update(struct route_node *rn, struct route_entry *re)
UNSET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
/* Copy over the nexthops in current state */
- nexthop_group_copy(&new_grp, re->nhe->nhg);
+ nexthop_group_copy(&new_grp, &(re->nhe->nhg));
for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next) {
@@ -1866,7 +1867,7 @@ uint8_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe,
if (!duplicate) {
grp[i].id = depend->id;
/* We aren't using weights for anything right now */
- grp[i].weight = depend->nhg->nexthop->weight;
+ grp[i].weight = depend->nhg.nexthop->weight;
i++;
}
diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h
index 4d001944b7..dc3a47c020 100644
--- a/zebra/zebra_nhg.h
+++ b/zebra/zebra_nhg.h
@@ -40,16 +40,15 @@ struct nh_grp {
PREDECL_RBTREE_UNIQ(nhg_connected_tree);
/*
- * Hashtables contiaining entries found in `zebra_router`.
+ * Hashtables containing nhg entries is in `zebra_router`.
*/
-
struct nhg_hash_entry {
uint32_t id;
afi_t afi;
vrf_id_t vrf_id;
int type;
- struct nexthop_group *nhg;
+ struct nexthop_group nhg;
/* If this is not a group, it
* will be a single nexthop
diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c
index 681b4d1ab8..b80c9026a7 100644
--- a/zebra/zebra_ptm.c
+++ b/zebra/zebra_ptm.c
@@ -441,15 +441,17 @@ static void if_bfd_session_update(struct interface *ifp, struct prefix *dp,
dp->prefixlen, ifp->name,
bfd_get_status_str(status));
} else {
+ struct vrf *vrf = vrf_lookup_by_id(vrf_id);
+
zlog_debug(
"MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d "
- "with src %s/%d and vrf %u %s event",
+ "with src %s/%d and vrf %s(%u) %s event",
inet_ntop(dp->family, &dp->u.prefix, buf[0],
INET6_ADDRSTRLEN),
dp->prefixlen,
inet_ntop(sp->family, &sp->u.prefix, buf[1],
INET6_ADDRSTRLEN),
- sp->prefixlen, vrf_id,
+ sp->prefixlen, VRF_LOGNAME(vrf), vrf_id,
bfd_get_status_str(status));
}
}
diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c
index 618a232408..610a052c31 100644
--- a/zebra/zebra_pw.c
+++ b/zebra/zebra_pw.c
@@ -259,7 +259,7 @@ static int zebra_pw_check_reachability(struct zebra_pw *pw)
* Need to ensure that there's a label binding for all nexthops.
* Otherwise, ECMP for this route could render the pseudowire unusable.
*/
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) {
+ for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) {
if (!nexthop->nh_label) {
if (IS_ZEBRA_DEBUG_PW)
zlog_debug("%s: unlabeled route for %s",
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 57bd986872..9185c7ad16 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -198,8 +198,8 @@ int zebra_check_addr(const struct prefix *p)
*/
void route_entry_copy_nexthops(struct route_entry *re, struct nexthop *nh)
{
- assert(!re->nhe->nhg->nexthop);
- copy_nexthops(&re->nhe->nhg->nexthop, nh, NULL);
+ assert(!re->nhe->nhg.nexthop);
+ copy_nexthops(&re->nhe->nhg.nexthop, nh, NULL);
}
static void route_entry_attach_ref(struct route_entry *re,
@@ -217,12 +217,14 @@ int route_entry_update_nhe(struct route_entry *re, struct nhg_hash_entry *new)
int ret = 0;
if (new == NULL) {
- re->nhe->nhg = NULL;
+ if (re->nhe)
+ zebra_nhg_decrement_ref(re->nhe);
+ re->nhe = NULL;
goto done;
}
if (re->nhe_id != new->id) {
- old = zebra_nhg_lookup_id(re->nhe_id);
+ old = re->nhe;
route_entry_attach_ref(re, new);
@@ -404,7 +406,7 @@ int zebra_rib_labeled_unicast(struct route_entry *re)
if (re->type != ZEBRA_ROUTE_BGP)
return 0;
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop))
+ for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
if (!nexthop->nh_label || !nexthop->nh_label->num_labels)
return 0;
@@ -428,7 +430,7 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re,
srcdest_rnode_prefixes(rn, &p, &src_p);
if (info->safi != SAFI_UNICAST) {
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop))
+ for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
return;
}
@@ -437,7 +439,7 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re,
/*
* Install the resolved nexthop object first.
*/
- zebra_nhg_install_kernel(zebra_nhg_lookup_id(re->nhe_id));
+ zebra_nhg_install_kernel(re->nhe);
/*
* If this is a replace to a new RE let the originator of the RE
@@ -506,7 +508,7 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
if (info->safi != SAFI_UNICAST) {
UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop))
+ for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
return;
}
@@ -566,7 +568,7 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re)
re->fib_ng.nexthop = NULL;
}
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop))
+ for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
}
@@ -742,7 +744,7 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
/* Update real nexthop. This may actually determine if nexthop is active
* or not. */
- if (!nexthop_group_active_nexthop_num(new->nhe->nhg)) {
+ if (!nexthop_group_active_nexthop_num(&(new->nhe->nhg))) {
UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
return;
}
@@ -811,7 +813,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
/* Update the nexthop; we could determine here that nexthop is
* inactive. */
- if (nexthop_group_active_nexthop_num(new->nhe->nhg))
+ if (nexthop_group_active_nexthop_num(&(new->nhe->nhg)))
nh_active = 1;
/* If nexthop is active, install the selected route, if
@@ -929,7 +931,7 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
/* both are connected. are either loop or vrf? */
struct nexthop *nexthop = NULL;
- for (ALL_NEXTHOPS_PTR(alternate->nhe->nhg, nexthop)) {
+ for (ALL_NEXTHOPS(alternate->nhe->nhg, nexthop)) {
struct interface *ifp = if_lookup_by_index(
nexthop->ifindex, alternate->vrf_id);
@@ -937,7 +939,7 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
return alternate;
}
- for (ALL_NEXTHOPS_PTR(current->nhe->nhg, nexthop)) {
+ for (ALL_NEXTHOPS(current->nhe->nhg, nexthop)) {
struct interface *ifp = if_lookup_by_index(
nexthop->ifindex, current->vrf_id);
@@ -1269,7 +1271,7 @@ static void zebra_rib_fixup_system(struct route_node *rn)
SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nhop)) {
+ for (ALL_NEXTHOPS(re->nhe->nhg, nhop)) {
if (CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE))
continue;
@@ -1386,7 +1388,7 @@ static bool rib_update_re_from_ctx(struct route_entry *re,
|| !CHECK_FLAG(ctx_nexthop->flags, NEXTHOP_FLAG_ACTIVE))
ctx_nexthop = nexthop_next_active_resolved(ctx_nexthop);
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) {
+ for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) {
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
continue;
@@ -2354,8 +2356,8 @@ void rib_unlink(struct route_node *rn, struct route_entry *re)
nhe = zebra_nhg_lookup_id(re->nhe_id);
if (nhe)
zebra_nhg_decrement_ref(nhe);
- } else if (re->nhe->nhg)
- nexthop_group_delete(&re->nhe->nhg);
+ } else if (re->nhe->nhg.nexthop)
+ nexthops_free(re->nhe->nhg.nexthop);
nexthops_free(re->fib_ng.nexthop);
@@ -2408,13 +2410,14 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
char srcaddr[PREFIX_STRLEN];
char nhname[PREFIX_STRLEN];
struct nexthop *nexthop;
+ struct vrf *vrf = vrf_lookup_by_id(re->vrf_id);
- zlog_debug("%s: dumping RE entry %p for %s%s%s vrf %u", func,
+ zlog_debug("%s: dumping RE entry %p for %s%s%s vrf %s(%u)", func,
(const void *)re, prefix2str(pp, straddr, sizeof(straddr)),
is_srcdst ? " from " : "",
is_srcdst ? prefix2str(src_pp, srcaddr, sizeof(srcaddr))
: "",
- re->vrf_id);
+ VRF_LOGNAME(vrf), re->vrf_id);
zlog_debug("%s: uptime == %lu, type == %u, instance == %d, table == %d",
straddr, (unsigned long)re->uptime, re->type, re->instance,
re->table);
@@ -2422,10 +2425,10 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
"%s: metric == %u, mtu == %u, distance == %u, flags == %u, status == %u",
straddr, re->metric, re->mtu, re->distance, re->flags, re->status);
zlog_debug("%s: nexthop_num == %u, nexthop_active_num == %u", straddr,
- nexthop_group_nexthop_num(re->nhe->nhg),
- nexthop_group_active_nexthop_num(re->nhe->nhg));
+ nexthop_group_nexthop_num(&(re->nhe->nhg)),
+ nexthop_group_active_nexthop_num(&(re->nhe->nhg)));
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) {
+ for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) {
struct interface *ifp;
struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
@@ -2783,7 +2786,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
if (re->type == ZEBRA_ROUTE_KERNEL && re->metric != metric)
continue;
if (re->type == ZEBRA_ROUTE_CONNECT &&
- (rtnh = re->nhe->nhg->nexthop)
+ (rtnh = re->nhe->nhg.nexthop)
&& rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
if (rtnh->ifindex != nh->ifindex)
continue;
@@ -2801,7 +2804,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
same = re;
break;
}
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, rtnh)) {
+ for (ALL_NEXTHOPS(re->nhe->nhg, rtnh)) {
/*
* No guarantee all kernel send nh with labels
* on delete.
@@ -2843,7 +2846,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
if (allow_delete) {
UNSET_FLAG(fib->status, ROUTE_ENTRY_INSTALLED);
/* Unset flags. */
- for (rtnh = fib->nhe->nhg->nexthop; rtnh;
+ for (rtnh = fib->nhe->nhg.nexthop; rtnh;
rtnh = rtnh->next)
UNSET_FLAG(rtnh->flags,
NEXTHOP_FLAG_FIB);
@@ -2899,7 +2902,7 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
if (CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE)) {
struct nexthop *tmp_nh;
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, tmp_nh)) {
+ for (ALL_NEXTHOPS(re->nhe->nhg, tmp_nh)) {
struct ipaddr vtep_ip;
memset(&vtep_ip, 0, sizeof(struct ipaddr));
@@ -3223,7 +3226,7 @@ void rib_sweep_table(struct route_table *table)
* this decision needs to be revisited
*/
SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop))
+ for (ALL_NEXTHOPS(re->nhe->nhg, nexthop))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
rib_uninstall_kernel(rn, re);
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 2d9c83becb..74c3ac3712 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -54,7 +54,7 @@ DEFINE_MTYPE_STATIC(ZEBRA, RNH, "Nexthop tracking object")
static void free_state(vrf_id_t vrf_id, struct route_entry *re,
struct route_node *rn);
-static void copy_state(struct rnh *rnh, struct route_entry *re,
+static void copy_state(struct rnh *rnh, const struct route_entry *re,
struct route_node *rn);
static int compare_state(struct route_entry *r1, struct route_entry *r2);
static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
@@ -384,7 +384,7 @@ static void zebra_rnh_clear_nexthop_rnh_filters(struct route_entry *re)
struct nexthop *nexthop;
if (re) {
- for (nexthop = re->nhe->nhg->nexthop; nexthop;
+ for (nexthop = re->nhe->nhg.nexthop; nexthop;
nexthop = nexthop->next) {
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_RNH_FILTERED);
}
@@ -403,7 +403,7 @@ static int zebra_rnh_apply_nht_rmap(afi_t afi, struct zebra_vrf *zvrf,
route_map_result_t ret;
if (prn && re) {
- for (nexthop = re->nhe->nhg->nexthop; nexthop;
+ for (nexthop = re->nhe->nhg.nexthop; nexthop;
nexthop = nexthop->next) {
ret = zebra_nht_route_map_check(
afi, proto, &prn->p, zvrf, re, nexthop);
@@ -688,7 +688,7 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
/* Just being SELECTED isn't quite enough - must
* have an installed nexthop to be useful.
*/
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) {
+ for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) {
if (rnh_nexthop_valid(re, nexthop))
break;
}
@@ -707,7 +707,7 @@ zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
break;
if (re->type == ZEBRA_ROUTE_NHRP) {
- for (nexthop = re->nhe->nhg->nexthop;
+ for (nexthop = re->nhe->nhg.nexthop;
nexthop;
nexthop = nexthop->next)
if (nexthop->type
@@ -945,7 +945,7 @@ static void free_state(vrf_id_t vrf_id, struct route_entry *re,
XFREE(MTYPE_RE, re);
}
-static void copy_state(struct rnh *rnh, struct route_entry *re,
+static void copy_state(struct rnh *rnh, const struct route_entry *re,
struct route_node *rn)
{
struct route_entry *state;
@@ -966,9 +966,8 @@ static void copy_state(struct rnh *rnh, struct route_entry *re,
state->status = re->status;
state->nhe = zebra_nhg_alloc();
- state->nhe->nhg = nexthop_group_new();
- nexthop_group_copy(state->nhe->nhg, re->nhe->nhg);
+ nexthop_group_copy(&(state->nhe->nhg), &(re->nhe->nhg));
rnh->state = state;
}
@@ -986,12 +985,12 @@ static int compare_state(struct route_entry *r1, struct route_entry *r2)
if (r1->metric != r2->metric)
return 1;
- if (nexthop_group_nexthop_num(r1->nhe->nhg)
- != nexthop_group_nexthop_num(r2->nhe->nhg))
+ if (nexthop_group_nexthop_num(&(r1->nhe->nhg))
+ != nexthop_group_nexthop_num(&(r2->nhe->nhg)))
return 1;
- if (nexthop_group_hash(r1->nhe->nhg) !=
- nexthop_group_hash(r2->nhe->nhg))
+ if (nexthop_group_hash(&(r1->nhe->nhg)) !=
+ nexthop_group_hash(&(r2->nhe->nhg)))
return 1;
return 0;
@@ -1043,7 +1042,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
num = 0;
nump = stream_get_endp(s);
stream_putc(s, 0);
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nh))
+ for (ALL_NEXTHOPS(re->nhe->nhg, nh))
if (rnh_nexthop_valid(re, nh)) {
zapi_nexthop_from_nexthop(&znh, nh);
zapi_nexthop_encode(s, &znh, 0 /* flags */);
@@ -1114,7 +1113,7 @@ static void print_rnh(struct route_node *rn, struct vty *vty)
if (rnh->state) {
vty_out(vty, " resolved via %s\n",
zebra_route_string(rnh->state->type));
- for (nexthop = rnh->state->nhe->nhg->nexthop; nexthop;
+ for (nexthop = rnh->state->nhe->nhg.nexthop; nexthop;
nexthop = nexthop->next)
print_nh(nexthop, vty);
} else
diff --git a/zebra/zebra_snmp.c b/zebra/zebra_snmp.c
index 70bb6a14ca..5de45c0294 100644
--- a/zebra/zebra_snmp.c
+++ b/zebra/zebra_snmp.c
@@ -285,8 +285,8 @@ static void check_replace(struct route_node *np2, struct route_entry *re2,
return;
}
- if (in_addr_cmp((uint8_t *)&(*re)->nhe->nhg->nexthop->gate.ipv4,
- (uint8_t *)&re2->nhe->nhg->nexthop->gate.ipv4)
+ if (in_addr_cmp((uint8_t *)&(*re)->nhe->nhg.nexthop->gate.ipv4,
+ (uint8_t *)&re2->nhe->nhg.nexthop->gate.ipv4)
<= 0)
return;
@@ -372,7 +372,7 @@ static void get_fwtable_route_node(struct variable *v, oid objid[],
(uint8_t *)&dest)) {
RNODE_FOREACH_RE (*np, *re) {
if (!in_addr_cmp((uint8_t *)&(*re)->nhe
- ->nhg->nexthop
+ ->nhg.nexthop
->gate.ipv4,
(uint8_t *)&nexthop))
if (proto
@@ -407,7 +407,7 @@ static void get_fwtable_route_node(struct variable *v, oid objid[],
|| ((policy == policy2) && (proto == proto2)
&& (in_addr_cmp(
(uint8_t *)&re2->nhe
- ->nhg->nexthop->gate.ipv4,
+ ->nhg.nexthop->gate.ipv4,
(uint8_t *)&nexthop)
>= 0)))
check_replace(np2, re2, np, re);
@@ -432,7 +432,7 @@ static void get_fwtable_route_node(struct variable *v, oid objid[],
{
struct nexthop *nexthop;
- nexthop = (*re)->nhe->nhg->nexthop;
+ nexthop = (*re)->nhe->nhg.nexthop;
if (nexthop) {
pnt = (uint8_t *)&nexthop->gate.ipv4;
for (i = 0; i < 4; i++)
@@ -462,7 +462,7 @@ static uint8_t *ipFwTable(struct variable *v, oid objid[], size_t *objid_len,
if (!np)
return NULL;
- nexthop = re->nhe->nhg->nexthop;
+ nexthop = re->nhe->nhg.nexthop;
if (!nexthop)
return NULL;
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 86ec2ffef3..8c719f4b6a 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -62,7 +62,7 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
- unsigned short ospf_instance_id);
+ unsigned short ospf_instance_id, uint32_t tableid);
static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
int mcast, bool use_fib, bool show_ng);
static void vty_show_ip_route_summary(struct vty *vty,
@@ -131,7 +131,7 @@ DEFUN (show_ip_rpf,
{
bool uj = use_json(argc, argv);
return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST,
- false, uj, 0, NULL, false, 0, 0);
+ false, uj, 0, NULL, false, 0, 0, 0);
}
DEFUN (show_ip_rpf_addr,
@@ -264,7 +264,7 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
if (show_ng)
vty_out(vty, " Nexthop Group ID: %u\n", re->nhe_id);
- for (ALL_NEXTHOPS_PTR(re->nhe->nhg, nexthop)) {
+ for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) {
char addrstr[32];
vty_out(vty, " %c%s",
@@ -417,7 +417,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (is_fib)
nhg = rib_active_nhg(re);
else
- nhg = re->nhe->nhg;
+ nhg = &(re->nhe->nhg);
if (json) {
json_route = json_object_new_object();
@@ -470,10 +470,10 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_int_add(json_route, "internalFlags",
re->flags);
json_object_int_add(json_route, "internalNextHopNum",
- nexthop_group_nexthop_num(re->nhe->nhg));
+ nexthop_group_nexthop_num(&(re->nhe->nhg)));
json_object_int_add(json_route, "internalNextHopActiveNum",
nexthop_group_active_nexthop_num(
- re->nhe->nhg));
+ &(re->nhe->nhg)));
if (uptime < ONE_DAY_SECOND)
sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
tm->tm_sec);
@@ -915,12 +915,40 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
}
}
+static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf, afi_t afi,
+ bool use_fib, bool use_json,
+ route_tag_t tag,
+ const struct prefix *longer_prefix_p,
+ bool supernets_only, int type,
+ unsigned short ospf_instance_id)
+{
+ struct zebra_router_table *zrt;
+ rib_table_info_t *info;
+
+ RB_FOREACH (zrt, zebra_router_table_head,
+ &zrouter.tables) {
+ info = route_table_get_info(zrt->table);
+
+ if (zvrf != info->zvrf)
+ continue;
+ if (zrt->afi != afi ||
+ zrt->safi != SAFI_UNICAST)
+ continue;
+ if (zrt->table)
+ do_show_ip_route(vty, zvrf_name(zvrf), afi,
+ SAFI_UNICAST, use_fib, use_json,
+ tag, longer_prefix_p,
+ supernets_only, type,
+ ospf_instance_id, zrt->tableid);
+ }
+}
+
static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
safi_t safi, bool use_fib, bool use_json,
route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
- unsigned short ospf_instance_id)
+ unsigned short ospf_instance_id, uint32_t tableid)
{
struct route_table *table;
struct zebra_vrf *zvrf = NULL;
@@ -941,7 +969,10 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
return CMD_SUCCESS;
}
- table = zebra_vrf_table(afi, safi, zvrf_id(zvrf));
+ if (tableid)
+ table = zebra_router_find_table(zvrf, tableid, afi, SAFI_UNICAST);
+ else
+ table = zebra_vrf_table(afi, safi, zvrf_id(zvrf));
if (!table) {
if (use_json)
vty_out(vty, "{}\n");
@@ -950,95 +981,8 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
do_show_route_helper(vty, zvrf, table, afi, use_fib, tag,
longer_prefix_p, supernets_only, type,
- ospf_instance_id, use_json, 0);
-
- return CMD_SUCCESS;
-}
-
-DEFPY (show_route_table,
- show_route_table_cmd,
- "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table [json$json]",
- SHOW_STR
- IP_STR
- IP6_STR
- "IP routing table\n"
- "Table to display\n"
- "The table number to display, if available\n"
- JSON_STR)
-{
- afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
- struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
- struct route_table *t;
-
- t = zebra_router_find_table(zvrf, table, afi, SAFI_UNICAST);
- if (t)
- do_show_route_helper(vty, zvrf, t, afi, false, 0, false, false,
- 0, 0, !!json, table);
-
- return CMD_SUCCESS;
-}
-
-DEFPY (show_route_table_vrf,
- show_route_table_vrf_cmd,
- "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table vrf NAME$vrf_name [json$json]",
- SHOW_STR
- IP_STR
- IP6_STR
- "IP routing table\n"
- "Table to display\n"
- "The table number to display, if available\n"
- VRF_CMD_HELP_STR
- JSON_STR)
-{
- afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
- struct zebra_vrf *zvrf;
- struct route_table *t;
- vrf_id_t vrf_id = VRF_DEFAULT;
-
- if (vrf_name)
- VRF_GET_ID(vrf_id, vrf_name, !!json);
- zvrf = zebra_vrf_lookup_by_id(vrf_id);
+ ospf_instance_id, use_json, tableid);
- t = zebra_router_find_table(zvrf, table, afi, SAFI_UNICAST);
- if (t)
- do_show_route_helper(vty, zvrf, t, afi, false, 0, false, false,
- 0, 0, !!json, table);
-
- return CMD_SUCCESS;
-}
-
-DEFPY (show_route_all_table_vrf,
- show_route_all_table_vrf_cmd,
- "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] tables [json$json]",
- SHOW_STR
- IP_STR
- IP6_STR
- "IP routing table\n"
- "Display all tables\n"
- VRF_FULL_CMD_HELP_STR
- JSON_STR)
-{
- afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
- struct zebra_vrf *zvrf = NULL;
- vrf_id_t vrf_id = VRF_UNKNOWN;
- struct zebra_router_table *zrt;
-
- if (vrf_name) {
- VRF_GET_ID(vrf_id, vrf_name, !!json);
- zvrf = zebra_vrf_lookup_by_id(vrf_id);
- }
-
- RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) {
- rib_table_info_t *info = route_table_get_info(zrt->table);
-
- if (zvrf && zvrf != info->zvrf)
- continue;
- if (zrt->afi != afi || zrt->safi != SAFI_UNICAST)
- continue;
-
- do_show_route_helper(vty, info->zvrf, zrt->table, afi, false, 0,
- false, false, 0, 0, !!json, zrt->tableid);
- }
return CMD_SUCCESS;
}
@@ -1149,7 +1093,7 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe)
vty_out(vty, "\n");
}
- for (ALL_NEXTHOPS_PTR(nhe->nhg, nexthop)) {
+ for (ALL_NEXTHOPS(nhe->nhg, nexthop)) {
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
vty_out(vty, " ");
else
@@ -1512,7 +1456,8 @@ DEFPY (show_route,
show_route_cmd,
"show\
<\
- ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
+ ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
+ [vrf <NAME$vrf_name|all$vrf_all>]\
[{\
tag (1-4294967295)\
|A.B.C.D/M$prefix longer-prefixes\
@@ -1522,7 +1467,8 @@ DEFPY (show_route,
" FRR_IP_REDIST_STR_ZEBRA "$type_str\
|ospf$type_str (1-65535)$ospf_instance_id\
>]\
- |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
+ |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
+ [vrf <NAME$vrf_name|all$vrf_all>]\
[{\
tag (1-4294967295)\
|X:X::X:X/M$prefix longer-prefixes\
@@ -1534,6 +1480,9 @@ DEFPY (show_route,
IP_STR
"IP forwarding table\n"
"IP routing table\n"
+ "Table to display\n"
+ "The table number to display\n"
+ "All tables\n"
VRF_FULL_CMD_HELP_STR
"Show only routes with tag\n"
"Tag value\n"
@@ -1546,6 +1495,9 @@ DEFPY (show_route,
IPV6_STR
"IP forwarding table\n"
"IP routing table\n"
+ "Table to display\n"
+ "The table number to display\n"
+ "All tables\n"
VRF_FULL_CMD_HELP_STR
"Show only routes with tag\n"
"Tag value\n"
@@ -1557,7 +1509,19 @@ DEFPY (show_route,
afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
struct vrf *vrf;
int type = 0;
+ struct zebra_vrf *zvrf;
+ if (!vrf_is_backend_netns()) {
+ if ((vrf_all || vrf_name) && (table || table_all)) {
+ if (!!json)
+ vty_out(vty, "{}\n");
+ else {
+ vty_out(vty, "Linux vrf backend already points to table id\n");
+ vty_out(vty, "Either remove table parameter or vrf parameter\n");
+ }
+ return CMD_SUCCESS;
+ }
+ }
if (type_str) {
type = proto_redistnum(afi, type_str);
if (type < 0) {
@@ -1568,17 +1532,22 @@ DEFPY (show_route,
if (vrf_all) {
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- struct zebra_vrf *zvrf;
- struct route_table *table;
-
if ((zvrf = vrf->info) == NULL
- || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
+ || (zvrf->table[afi][SAFI_UNICAST] == NULL))
continue;
- do_show_ip_route(
- vty, zvrf_name(zvrf), afi, SAFI_UNICAST, !!fib,
- !!json, tag, prefix_str ? prefix : NULL,
- !!supernets_only, type, ospf_instance_id);
+ if (table_all)
+ do_show_ip_route_all(vty, zvrf, afi,
+ !!fib, !!json,
+ tag, prefix_str ? prefix : NULL,
+ !!supernets_only, type,
+ ospf_instance_id);
+ else
+ do_show_ip_route(vty, zvrf_name(zvrf), afi,
+ SAFI_UNICAST, !!fib, !!json, tag,
+ prefix_str ? prefix : NULL,
+ !!supernets_only, type,
+ ospf_instance_id, table);
}
} else {
vrf_id_t vrf_id = VRF_DEFAULT;
@@ -1586,9 +1555,21 @@ DEFPY (show_route,
if (vrf_name)
VRF_GET_ID(vrf_id, vrf_name, !!json);
vrf = vrf_lookup_by_id(vrf_id);
- do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST, !!fib,
- !!json, tag, prefix_str ? prefix : NULL,
- !!supernets_only, type, ospf_instance_id);
+ if (vrf)
+ zvrf = vrf->info;
+ if (!vrf || !zvrf)
+ return CMD_SUCCESS;
+
+ if (table_all)
+ do_show_ip_route_all(vty, zvrf, afi,
+ !!fib, !!json,
+ tag, prefix_str ? prefix : NULL,
+ !!supernets_only, type,
+ ospf_instance_id);
+ else
+ do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST, !!fib,
+ !!json, tag, prefix_str ? prefix : NULL,
+ !!supernets_only, type, ospf_instance_id, table);
}
return CMD_SUCCESS;
@@ -1970,7 +1951,7 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
fib_cnt[ZEBRA_ROUTE_TOTAL]++;
fib_cnt[re->type]++;
}
- for (nexthop = re->nhe->nhg->nexthop; (!cnt && nexthop);
+ for (nexthop = re->nhe->nhg.nexthop; (!cnt && nexthop);
nexthop = nexthop->next) {
cnt++;
rib_cnt[ZEBRA_ROUTE_TOTAL]++;
@@ -3539,10 +3520,6 @@ void zebra_vty_init(void)
install_element(VIEW_NODE, &show_vrf_cmd);
install_element(VIEW_NODE, &show_vrf_vni_cmd);
install_element(VIEW_NODE, &show_route_cmd);
- install_element(VIEW_NODE, &show_route_table_cmd);
- if (vrf_is_backend_netns())
- install_element(VIEW_NODE, &show_route_table_vrf_cmd);
- install_element(VIEW_NODE, &show_route_all_table_vrf_cmd);
install_element(VIEW_NODE, &show_route_detail_cmd);
install_element(VIEW_NODE, &show_route_summary_cmd);
install_element(VIEW_NODE, &show_ip_nht_cmd);