summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--alpine/APKBUILD.in4
-rw-r--r--bfdd/bfdd_vty.c8
-rw-r--r--bgpd/bgp_aspath.c83
-rw-r--r--bgpd/bgp_aspath.h8
-rw-r--r--bgpd/bgp_attr.c10
-rw-r--r--bgpd/bgp_community.c89
-rw-r--r--bgpd/bgp_community.h8
-rw-r--r--bgpd/bgp_ecommunity.c86
-rw-r--r--bgpd/bgp_ecommunity.h9
-rw-r--r--bgpd/bgp_lcommunity.c88
-rw-r--r--bgpd/bgp_lcommunity.h10
-rw-r--r--bgpd/bgp_route.c65
-rw-r--r--bgpd/bgp_updgrp.c6
-rw-r--r--bgpd/bgp_updgrp_adv.c5
-rw-r--r--bgpd/bgp_updgrp_packet.c47
-rw-r--r--bgpd/bgpd.h2
-rwxr-xr-xconfigure.ac18
-rw-r--r--doc/user/bfd.rst8
-rw-r--r--doc/user/bgp.rst17
-rw-r--r--doc/user/zebra.rst29
-rw-r--r--docker/alpine/Dockerfile5
-rw-r--r--eigrpd/eigrp_network.c5
-rw-r--r--include/linux/fib_rules.h20
-rw-r--r--include/linux/if_addr.h3
-rw-r--r--include/linux/if_bridge.h10
-rw-r--r--include/linux/if_link.h92
-rw-r--r--include/linux/lwtunnel.h7
-rw-r--r--include/linux/mpls_iptunnel.h7
-rw-r--r--include/linux/neighbour.h3
-rw-r--r--include/linux/net_namespace.h7
-rw-r--r--include/linux/netlink.h11
-rw-r--r--include/linux/rtnetlink.h49
-rw-r--r--include/linux/socket.h7
-rw-r--r--isisd/isis_adjacency.c1
-rw-r--r--isisd/isis_circuit.h7
-rw-r--r--isisd/isis_main.c2
-rw-r--r--isisd/isis_northbound.c493
-rw-r--r--isisd/isis_pdu.c33
-rw-r--r--isisd/isis_te.c3
-rw-r--r--isisd/isisd.c3
-rw-r--r--isisd/isisd.h3
-rw-r--r--lib/if.c24
-rw-r--r--lib/nexthop_group.c8
-rw-r--r--lib/vrf.c8
-rw-r--r--ospf6d/ospf6_interface.c55
-rw-r--r--ospf6d/ospf6_interface.h1
-rw-r--r--ospf6d/ospf6_lsdb.c15
-rw-r--r--ospf6d/ospf6_message.c44
-rw-r--r--ospf6d/ospf6_neighbor.c33
-rw-r--r--ospf6d/ospf6_snmp.c4
-rw-r--r--ospf6d/ospf6_top.c5
-rw-r--r--ospf6d/ospf6_top.h3
-rw-r--r--pbrd/pbr_nht.c2
-rw-r--r--pbrd/pbr_vty.c8
-rw-r--r--pimd/pim_pim.c1
-rw-r--r--pimd/pim_sock.c6
-rw-r--r--pimd/pim_zebra.c55
-rw-r--r--sharpd/sharp_vty.c42
-rw-r--r--staticd/static_vrf.c4
-rw-r--r--staticd/static_zebra.c14
-rw-r--r--staticd/static_zebra.h3
-rw-r--r--tests/topotests/bgp-route-map/bgp_route_map_topo1.json187
-rwxr-xr-xtests/topotests/bgp-route-map/bgp_route_map_topo2.json316
-rwxr-xr-xtests/topotests/bgp-route-map/test_route_map_topo1.py1361
-rwxr-xr-xtests/topotests/bgp-route-map/test_route_map_topo2.py3916
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py11
-rw-r--r--tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref31
-rw-r--r--tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-no-neigh18
-rw-r--r--tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-old-nolist14
-rw-r--r--tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref30
-rw-r--r--tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-no-neigh18
-rw-r--r--tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-old-nolist14
-rw-r--r--tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref30
-rw-r--r--tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-no-neigh18
-rw-r--r--tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-old-nolist14
-rwxr-xr-xtests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py27
-rw-r--r--tests/topotests/lib/bgp.py144
-rw-r--r--tests/topotests/lib/common_config.py458
-rw-r--r--tests/topotests/lib/topojson.py2
-rw-r--r--vtysh/vtysh.c57
-rw-r--r--yang/frr-isisd.yang682
-rw-r--r--yang/frr-nexthop.yang200
-rw-r--r--yang/frr-zebra.yang1788
-rw-r--r--zebra/connected.c2
-rw-r--r--zebra/if_netlink.c19
-rw-r--r--zebra/interface.c30
-rw-r--r--zebra/redistribute.c4
-rw-r--r--zebra/rt.h2
-rw-r--r--zebra/rt_netlink.c12
-rw-r--r--zebra/rt_socket.c2
-rw-r--r--zebra/rule_netlink.c4
-rw-r--r--zebra/zebra_dplane.c12
-rw-r--r--zebra/zebra_dplane.h1
-rw-r--r--zebra/zebra_fpm.c5
-rw-r--r--zebra/zebra_rib.c19
-rw-r--r--zebra/zebra_rnh.c5
-rw-r--r--zebra/zebra_vrf.c2
-rw-r--r--zebra/zebra_vty.c15
-rw-r--r--zebra/zebra_vxlan.c10
99 files changed, 10259 insertions, 927 deletions
diff --git a/alpine/APKBUILD.in b/alpine/APKBUILD.in
index e0b00f9782..60753c1227 100644
--- a/alpine/APKBUILD.in
+++ b/alpine/APKBUILD.in
@@ -13,13 +13,13 @@ makedepends="ncurses-dev net-snmp-dev gawk texinfo perl
c-ares c-ares-dev ca-certificates cryptsetup-libs curl
device-mapper-libs expat fakeroot flex fortify-headers gdbm
git gmp isl json-c-dev kmod lddtree libacl libatomic libattr
- libblkid libburn libbz2 libc-dev libcap libcurl libedit libffi libgcc
+ libblkid libburn libbz2 libc-dev libcap-dev libcurl libedit libffi libgcc
libgomp libisoburn libisofs libltdl libressl libssh2
libstdc++ libtool libuuid libyang-dev linux-headers lzip lzo m4 make mkinitfs mpc1
mpfr3 mtools musl-dev ncurses-libs ncurses-terminfo ncurses-terminfo-base
patch pax-utils pcre perl pkgconf python2 python2-dev readline
readline-dev sqlite-libs squashfs-tools sudo tar texinfo xorriso xz-libs
- py-sphinx rtrlib rtrlib-dev"
+ py-pip py-sphinx rtrlib rtrlib-dev"
checkdepends="pytest py-setuptools"
install="$pkgname.pre-install $pkgname.pre-deinstall $pkgname.post-deinstall"
subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg"
diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c
index 5663ce54cb..f8ee66e2c8 100644
--- a/bfdd/bfdd_vty.c
+++ b/bfdd/bfdd_vty.c
@@ -516,7 +516,7 @@ DEFPY(bfd_show_peers, bfd_show_peers_cmd, "show bfd [vrf <NAME>] peers [json]",
}
DEFPY(bfd_show_peer, bfd_show_peer_cmd,
- "show bfd [vrf <NAME$vrfname>] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]",
+ "show bfd [vrf <NAME$vrf_name>] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]",
SHOW_STR
"Bidirection Forwarding Detection\n"
VRF_CMD_HELP_STR
@@ -528,7 +528,7 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd,
/* Look up the BFD peer. */
bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
- ifname, vrfname);
+ ifname, vrf_name);
if (bs == NULL)
return CMD_WARNING_CONFIG_FAILED;
@@ -543,7 +543,7 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd,
}
DEFPY(bfd_show_peer_counters, bfd_show_peer_counters_cmd,
- "show bfd [vrf <NAME$vrfname>] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> counters [json]",
+ "show bfd [vrf <NAME$vrf_name>] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> counters [json]",
SHOW_STR
"Bidirection Forwarding Detection\n"
VRF_CMD_HELP_STR
@@ -564,7 +564,7 @@ DEFPY(bfd_show_peer_counters, bfd_show_peer_counters_cmd,
/* Look up the BFD peer. */
bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str,
- ifname, vrfname);
+ ifname, vrf_name);
if (bs == NULL)
return CMD_WARNING_CONFIG_FAILED;
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index f5652b07c5..6caeb7ca1f 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -2114,15 +2114,12 @@ static void *bgp_aggr_aspath_hash_alloc(void *p)
static void bgp_aggr_aspath_prepare(struct hash_backet *hb, void *arg)
{
- struct aspath *asmerge = NULL;
struct aspath *hb_aspath = hb->data;
struct aspath **aggr_aspath = arg;
- if (*aggr_aspath) {
- asmerge = aspath_aggregate(*aggr_aspath, hb_aspath);
- aspath_free(*aggr_aspath);
- *aggr_aspath = asmerge;
- } else
+ if (*aggr_aspath)
+ *aggr_aspath = aspath_aggregate(*aggr_aspath, hb_aspath);
+ else
*aggr_aspath = aspath_dup(hb_aspath);
}
@@ -2136,6 +2133,15 @@ void bgp_aggr_aspath_remove(void *arg)
void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate,
struct aspath *aspath)
{
+ bgp_compute_aggregate_aspath_hash(aggregate, aspath);
+
+ bgp_compute_aggregate_aspath_val(aggregate);
+
+}
+
+void bgp_compute_aggregate_aspath_hash(struct bgp_aggregate *aggregate,
+ struct aspath *aspath)
+{
struct aspath *aggr_aspath = NULL;
if ((aggregate == NULL) || (aspath == NULL))
@@ -2154,17 +2160,29 @@ void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate,
*/
aggr_aspath = hash_get(aggregate->aspath_hash, aspath,
bgp_aggr_aspath_hash_alloc);
+ }
- /* Compute aggregate's as-path.
- */
+ /* Increment reference counter.
+ */
+ aggr_aspath->refcnt++;
+}
+
+void bgp_compute_aggregate_aspath_val(struct bgp_aggregate *aggregate)
+{
+ if (aggregate == NULL)
+ return;
+ /* Re-compute aggregate's as-path.
+ */
+ if (aggregate->aspath) {
+ aspath_free(aggregate->aspath);
+ aggregate->aspath = NULL;
+ }
+ if (aggregate->aspath_hash
+ && aggregate->aspath_hash->count) {
hash_iterate(aggregate->aspath_hash,
bgp_aggr_aspath_prepare,
&aggregate->aspath);
}
-
- /* Increment refernce counter.
- */
- aggr_aspath->refcnt++;
}
void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate,
@@ -2173,10 +2191,9 @@ void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate,
struct aspath *aggr_aspath = NULL;
struct aspath *ret_aspath = NULL;
- if ((aggregate == NULL) || (aspath == NULL))
- return;
-
- if (aggregate->aspath_hash == NULL)
+ if ((!aggregate)
+ || (!aggregate->aspath_hash)
+ || (!aspath))
return;
/* Look-up the aspath in the hash.
@@ -2189,17 +2206,41 @@ void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate,
ret_aspath = hash_release(aggregate->aspath_hash,
aggr_aspath);
aspath_free(ret_aspath);
+ ret_aspath = NULL;
/* Remove aggregate's old as-path.
*/
aspath_free(aggregate->aspath);
aggregate->aspath = NULL;
- /* Compute aggregate's as-path.
- */
- hash_iterate(aggregate->aspath_hash,
- bgp_aggr_aspath_prepare,
- &aggregate->aspath);
+ bgp_compute_aggregate_aspath_val(aggregate);
}
}
}
+
+void bgp_remove_aspath_from_aggregate_hash(struct bgp_aggregate *aggregate,
+ struct aspath *aspath)
+{
+ struct aspath *aggr_aspath = NULL;
+ struct aspath *ret_aspath = NULL;
+
+ if ((!aggregate)
+ || (!aggregate->aspath_hash)
+ || (!aspath))
+ return;
+
+ /* Look-up the aspath in the hash.
+ */
+ aggr_aspath = bgp_aggr_aspath_lookup(aggregate, aspath);
+ if (aggr_aspath) {
+ aggr_aspath->refcnt--;
+
+ if (aggr_aspath->refcnt == 0) {
+ ret_aspath = hash_release(aggregate->aspath_hash,
+ aggr_aspath);
+ aspath_free(ret_aspath);
+ ret_aspath = NULL;
+ }
+ }
+}
+
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index f84b3740c9..10f6ee2821 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -134,8 +134,16 @@ extern uint8_t *aspath_snmp_pathseg(struct aspath *, size_t *);
extern void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate,
struct aspath *aspath);
+
+extern void bgp_compute_aggregate_aspath_hash(struct bgp_aggregate *aggregate,
+ struct aspath *aspath);
+extern void bgp_compute_aggregate_aspath_val(struct bgp_aggregate *aggregate);
extern void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate,
struct aspath *aspath);
+extern void bgp_remove_aspath_from_aggregate_hash(
+ struct bgp_aggregate *aggregate,
+ struct aspath *aspath);
+
extern void bgp_aggr_aspath_remove(void *arg);
#endif /* _QUAGGA_BGP_ASPATH_H */
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 248bbca8cf..a7cd3fee88 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -1305,14 +1305,20 @@ bgp_attr_nexthop_valid(struct peer *peer, struct attr *attr)
if ((IPV4_NET0(nexthop_h) || IPV4_NET127(nexthop_h)
|| IPV4_CLASS_DE(nexthop_h))
&& !BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) {
+ uint8_t data[7]; /* type(2) + length(1) + nhop(4) */
char buf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &attr->nexthop.s_addr, buf,
INET_ADDRSTRLEN);
flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %s",
buf);
- bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR,
- BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP);
+ data[0] = BGP_ATTR_FLAG_TRANS;
+ data[1] = BGP_ATTR_NEXT_HOP;
+ data[2] = BGP_ATTR_NHLEN_IPV4;
+ memcpy(&data[3], &attr->nexthop.s_addr, BGP_ATTR_NHLEN_IPV4);
+ bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR,
+ BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP,
+ data, 7);
return BGP_ATTR_PARSE_ERROR;
}
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index 22d61f702d..432c922ea5 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -910,15 +910,13 @@ static void *bgp_aggr_communty_hash_alloc(void *p)
static void bgp_aggr_community_prepare(struct hash_backet *hb, void *arg)
{
- struct community *commerge = NULL;
struct community *hb_community = hb->data;
struct community **aggr_community = arg;
- if (*aggr_community) {
- commerge = community_merge(*aggr_community, hb_community);
- *aggr_community = community_uniq_sort(commerge);
- community_free(&commerge);
- } else
+ if (*aggr_community)
+ *aggr_community = community_merge(*aggr_community,
+ hb_community);
+ else
*aggr_community = community_dup(hb_community);
}
@@ -932,6 +930,14 @@ void bgp_aggr_community_remove(void *arg)
void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate,
struct community *community)
{
+ bgp_compute_aggregate_community_hash(aggregate, community);
+ bgp_compute_aggregate_community_val(aggregate);
+}
+
+
+void bgp_compute_aggregate_community_hash(struct bgp_aggregate *aggregate,
+ struct community *community)
+{
struct community *aggr_community = NULL;
if ((aggregate == NULL) || (community == NULL))
@@ -951,32 +957,47 @@ void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate,
*/
aggr_community = hash_get(aggregate->community_hash, community,
bgp_aggr_communty_hash_alloc);
+ }
- /* Re-compute aggregate's community.
- */
- if (aggregate->community)
- community_free(&aggregate->community);
+ /* Increment reference counter.
+ */
+ aggr_community->refcnt++;
+}
+void bgp_compute_aggregate_community_val(struct bgp_aggregate *aggregate)
+{
+ struct community *commerge = NULL;
+
+ if (aggregate == NULL)
+ return;
+
+ /* Re-compute aggregate's community.
+ */
+ if (aggregate->community)
+ community_free(&aggregate->community);
+ if (aggregate->community_hash &&
+ aggregate->community_hash->count) {
hash_iterate(aggregate->community_hash,
bgp_aggr_community_prepare,
&aggregate->community);
+ commerge = aggregate->community;
+ aggregate->community = community_uniq_sort(commerge);
+ if (commerge)
+ community_free(&commerge);
}
-
- /* Increment refernce counter.
- */
- aggr_community->refcnt++;
}
+
+
void bgp_remove_community_from_aggregate(struct bgp_aggregate *aggregate,
struct community *community)
{
struct community *aggr_community = NULL;
struct community *ret_comm = NULL;
- if ((aggregate == NULL) || (community == NULL))
- return;
-
- if (aggregate->community_hash == NULL)
+ if ((!aggregate)
+ || (!aggregate->community_hash)
+ || (!community))
return;
/* Look-up the community in the hash.
@@ -990,13 +1011,33 @@ void bgp_remove_community_from_aggregate(struct bgp_aggregate *aggregate,
aggr_community);
community_free(&ret_comm);
- community_free(&aggregate->community);
+ bgp_compute_aggregate_community_val(aggregate);
+ }
+ }
+}
+
+void bgp_remove_comm_from_aggregate_hash(struct bgp_aggregate *aggregate,
+ struct community *community)
+{
+
+ struct community *aggr_community = NULL;
+ struct community *ret_comm = NULL;
- /* Compute aggregate's community.
- */
- hash_iterate(aggregate->community_hash,
- bgp_aggr_community_prepare,
- &aggregate->community);
+ if ((!aggregate)
+ || (!aggregate->community_hash)
+ || (!community))
+ return;
+
+ /* Look-up the community in the hash.
+ */
+ aggr_community = bgp_aggr_community_lookup(aggregate, community);
+ if (aggr_community) {
+ aggr_community->refcnt--;
+
+ if (aggr_community->refcnt == 0) {
+ ret_comm = hash_release(aggregate->community_hash,
+ aggr_community);
+ community_free(&ret_comm);
}
}
}
diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h
index f761a8f5e0..74a3a6b507 100644
--- a/bgpd/bgp_community.h
+++ b/bgpd/bgp_community.h
@@ -92,8 +92,16 @@ extern struct hash *community_hash(void);
extern uint32_t community_val_get(struct community *com, int i);
extern void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate,
struct community *community);
+
+extern void bgp_compute_aggregate_community_val(
+ struct bgp_aggregate *aggregate);
+extern void bgp_compute_aggregate_community_hash(
+ struct bgp_aggregate *aggregate,
+ struct community *community);
extern void bgp_remove_community_from_aggregate(struct bgp_aggregate *aggregate,
struct community *community);
+extern void bgp_remove_comm_from_aggregate_hash(struct bgp_aggregate *aggregate,
+ struct community *community);
extern void bgp_aggr_community_remove(void *arg);
#endif /* _QUAGGA_BGP_COMMUNITY_H */
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 850b85aa6a..11f5a326df 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -1042,15 +1042,13 @@ static void *bgp_aggr_ecommunty_hash_alloc(void *p)
static void bgp_aggr_ecommunity_prepare(struct hash_backet *hb, void *arg)
{
- struct ecommunity *ecommerge = NULL;
struct ecommunity *hb_ecommunity = hb->data;
struct ecommunity **aggr_ecommunity = arg;
- if (*aggr_ecommunity) {
- ecommerge = ecommunity_merge(*aggr_ecommunity, hb_ecommunity);
- *aggr_ecommunity = ecommunity_uniq_sort(ecommerge);
- ecommunity_free(&ecommerge);
- } else
+ if (*aggr_ecommunity)
+ *aggr_ecommunity = ecommunity_merge(*aggr_ecommunity,
+ hb_ecommunity);
+ else
*aggr_ecommunity = ecommunity_dup(hb_ecommunity);
}
@@ -1064,6 +1062,14 @@ void bgp_aggr_ecommunity_remove(void *arg)
void bgp_compute_aggregate_ecommunity(struct bgp_aggregate *aggregate,
struct ecommunity *ecommunity)
{
+ bgp_compute_aggregate_ecommunity_hash(aggregate, ecommunity);
+ bgp_compute_aggregate_ecommunity_val(aggregate);
+}
+
+
+void bgp_compute_aggregate_ecommunity_hash(struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity)
+{
struct ecommunity *aggr_ecommunity = NULL;
if ((aggregate == NULL) || (ecommunity == NULL))
@@ -1083,20 +1089,34 @@ void bgp_compute_aggregate_ecommunity(struct bgp_aggregate *aggregate,
aggr_ecommunity = hash_get(aggregate->ecommunity_hash,
ecommunity,
bgp_aggr_ecommunty_hash_alloc);
+ }
- /* Re-compute aggregate's ecommunity.
- */
- if (aggregate->ecommunity)
- ecommunity_free(&aggregate->ecommunity);
+ /* Increment reference counter.
+ */
+ aggr_ecommunity->refcnt++;
+}
+void bgp_compute_aggregate_ecommunity_val(struct bgp_aggregate *aggregate)
+{
+ struct ecommunity *ecommerge = NULL;
+
+ if (aggregate == NULL)
+ return;
+
+ /* Re-compute aggregate's ecommunity.
+ */
+ if (aggregate->ecommunity)
+ ecommunity_free(&aggregate->ecommunity);
+ if (aggregate->ecommunity_hash
+ && aggregate->ecommunity_hash->count) {
hash_iterate(aggregate->ecommunity_hash,
bgp_aggr_ecommunity_prepare,
&aggregate->ecommunity);
+ ecommerge = aggregate->ecommunity;
+ aggregate->ecommunity = ecommunity_uniq_sort(ecommerge);
+ if (ecommerge)
+ ecommunity_free(&ecommerge);
}
-
- /* Increment refernce counter.
- */
- aggr_ecommunity->refcnt++;
}
void bgp_remove_ecommunity_from_aggregate(struct bgp_aggregate *aggregate,
@@ -1105,10 +1125,9 @@ void bgp_remove_ecommunity_from_aggregate(struct bgp_aggregate *aggregate,
struct ecommunity *aggr_ecommunity = NULL;
struct ecommunity *ret_ecomm = NULL;
- if ((aggregate == NULL) || (ecommunity == NULL))
- return;
-
- if (aggregate->ecommunity_hash == NULL)
+ if ((!aggregate)
+ || (!aggregate->ecommunity_hash)
+ || (!ecommunity))
return;
/* Look-up the ecommunity in the hash.
@@ -1121,14 +1140,33 @@ void bgp_remove_ecommunity_from_aggregate(struct bgp_aggregate *aggregate,
ret_ecomm = hash_release(aggregate->ecommunity_hash,
aggr_ecommunity);
ecommunity_free(&ret_ecomm);
+ bgp_compute_aggregate_ecommunity_val(aggregate);
+ }
+ }
+}
+
+void bgp_remove_ecomm_from_aggregate_hash(struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity)
+{
+
+ struct ecommunity *aggr_ecommunity = NULL;
+ struct ecommunity *ret_ecomm = NULL;
- ecommunity_free(&aggregate->ecommunity);
+ if ((!aggregate)
+ || (!aggregate->ecommunity_hash)
+ || (!ecommunity))
+ return;
- /* Compute aggregate's ecommunity.
- */
- hash_iterate(aggregate->ecommunity_hash,
- bgp_aggr_ecommunity_prepare,
- &aggregate->ecommunity);
+ /* Look-up the ecommunity in the hash.
+ */
+ aggr_ecommunity = bgp_aggr_ecommunity_lookup(aggregate, ecommunity);
+ if (aggr_ecommunity) {
+ aggr_ecommunity->refcnt--;
+
+ if (aggr_ecommunity->refcnt == 0) {
+ ret_ecomm = hash_release(aggregate->ecommunity_hash,
+ aggr_ecommunity);
+ ecommunity_free(&ret_ecomm);
}
}
}
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index 79be4ee422..249e5bf7de 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -190,9 +190,18 @@ extern int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
extern void bgp_compute_aggregate_ecommunity(
struct bgp_aggregate *aggregate,
struct ecommunity *ecommunity);
+
+extern void bgp_compute_aggregate_ecommunity_hash(
+ struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity);
+extern void bgp_compute_aggregate_ecommunity_val(
+ struct bgp_aggregate *aggregate);
extern void bgp_remove_ecommunity_from_aggregate(
struct bgp_aggregate *aggregate,
struct ecommunity *ecommunity);
+extern void bgp_remove_ecomm_from_aggregate_hash(
+ struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity);
extern void bgp_aggr_ecommunity_remove(void *arg);
#endif /* _QUAGGA_BGP_ECOMMUNITY_H */
diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c
index aeb290719a..3243ce96b5 100644
--- a/bgpd/bgp_lcommunity.c
+++ b/bgpd/bgp_lcommunity.c
@@ -555,15 +555,13 @@ static void *bgp_aggr_lcommunty_hash_alloc(void *p)
static void bgp_aggr_lcommunity_prepare(struct hash_backet *hb, void *arg)
{
- struct lcommunity *lcommerge = NULL;
struct lcommunity *hb_lcommunity = hb->data;
struct lcommunity **aggr_lcommunity = arg;
- if (*aggr_lcommunity) {
- lcommerge = lcommunity_merge(*aggr_lcommunity, hb_lcommunity);
- *aggr_lcommunity = lcommunity_uniq_sort(lcommerge);
- lcommunity_free(&lcommerge);
- } else
+ if (*aggr_lcommunity)
+ *aggr_lcommunity = lcommunity_merge(*aggr_lcommunity,
+ hb_lcommunity);
+ else
*aggr_lcommunity = lcommunity_dup(hb_lcommunity);
}
@@ -577,6 +575,15 @@ void bgp_aggr_lcommunity_remove(void *arg)
void bgp_compute_aggregate_lcommunity(struct bgp_aggregate *aggregate,
struct lcommunity *lcommunity)
{
+
+ bgp_compute_aggregate_lcommunity_hash(aggregate, lcommunity);
+ bgp_compute_aggregate_lcommunity_val(aggregate);
+}
+
+void bgp_compute_aggregate_lcommunity_hash(struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity)
+{
+
struct lcommunity *aggr_lcommunity = NULL;
if ((aggregate == NULL) || (lcommunity == NULL))
@@ -596,20 +603,34 @@ void bgp_compute_aggregate_lcommunity(struct bgp_aggregate *aggregate,
aggr_lcommunity = hash_get(aggregate->lcommunity_hash,
lcommunity,
bgp_aggr_lcommunty_hash_alloc);
+ }
- /* Re-compute aggregate's lcommunity.
- */
- if (aggregate->lcommunity)
- lcommunity_free(&aggregate->lcommunity);
+ /* Increment reference counter.
+ */
+ aggr_lcommunity->refcnt++;
+}
+
+void bgp_compute_aggregate_lcommunity_val(struct bgp_aggregate *aggregate)
+{
+ struct lcommunity *lcommerge = NULL;
+
+ if (aggregate == NULL)
+ return;
+ /* Re-compute aggregate's lcommunity.
+ */
+ if (aggregate->lcommunity)
+ lcommunity_free(&aggregate->lcommunity);
+ if (aggregate->lcommunity_hash &&
+ aggregate->lcommunity_hash->count) {
hash_iterate(aggregate->lcommunity_hash,
bgp_aggr_lcommunity_prepare,
&aggregate->lcommunity);
+ lcommerge = aggregate->lcommunity;
+ aggregate->lcommunity = lcommunity_uniq_sort(lcommerge);
+ if (lcommerge)
+ lcommunity_free(&lcommerge);
}
-
- /* Increment refernce counter.
- */
- aggr_lcommunity->refcnt++;
}
void bgp_remove_lcommunity_from_aggregate(struct bgp_aggregate *aggregate,
@@ -618,10 +639,9 @@ void bgp_remove_lcommunity_from_aggregate(struct bgp_aggregate *aggregate,
struct lcommunity *aggr_lcommunity = NULL;
struct lcommunity *ret_lcomm = NULL;
- if ((aggregate == NULL) || (lcommunity == NULL))
- return;
-
- if (aggregate->lcommunity_hash == NULL)
+ if ((!aggregate)
+ || (!aggregate->lcommunity_hash)
+ || (!lcommunity))
return;
/* Look-up the lcommunity in the hash.
@@ -635,13 +655,33 @@ void bgp_remove_lcommunity_from_aggregate(struct bgp_aggregate *aggregate,
aggr_lcommunity);
lcommunity_free(&ret_lcomm);
- lcommunity_free(&aggregate->lcommunity);
+ bgp_compute_aggregate_lcommunity_val(aggregate);
+
+ }
+ }
+}
+
+void bgp_remove_lcomm_from_aggregate_hash(struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity)
+{
+ struct lcommunity *aggr_lcommunity = NULL;
+ struct lcommunity *ret_lcomm = NULL;
- /* Compute aggregate's lcommunity.
- */
- hash_iterate(aggregate->lcommunity_hash,
- bgp_aggr_lcommunity_prepare,
- &aggregate->lcommunity);
+ if ((!aggregate)
+ || (!aggregate->lcommunity_hash)
+ || (!lcommunity))
+ return;
+
+ /* Look-up the lcommunity in the hash.
+ */
+ aggr_lcommunity = bgp_aggr_lcommunity_lookup(aggregate, lcommunity);
+ if (aggr_lcommunity) {
+ aggr_lcommunity->refcnt--;
+
+ if (aggr_lcommunity->refcnt == 0) {
+ ret_lcomm = hash_release(aggregate->lcommunity_hash,
+ aggr_lcommunity);
+ lcommunity_free(&ret_lcomm);
}
}
}
diff --git a/bgpd/bgp_lcommunity.h b/bgpd/bgp_lcommunity.h
index a512395492..7d63f4d26a 100644
--- a/bgpd/bgp_lcommunity.h
+++ b/bgpd/bgp_lcommunity.h
@@ -75,9 +75,19 @@ extern void lcommunity_del_val(struct lcommunity *lcom, uint8_t *ptr);
extern void bgp_compute_aggregate_lcommunity(
struct bgp_aggregate *aggregate,
struct lcommunity *lcommunity);
+
+extern void bgp_compute_aggregate_lcommunity_hash(
+ struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity);
+extern void bgp_compute_aggregate_lcommunity_val(
+ struct bgp_aggregate *aggregate);
+
extern void bgp_remove_lcommunity_from_aggregate(
struct bgp_aggregate *aggregate,
struct lcommunity *lcommunity);
+extern void bgp_remove_lcomm_from_aggregate_hash(
+ struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity);
extern void bgp_aggr_lcommunity_remove(void *arg);
#endif /* _QUAGGA_BGP_LCOMMUNITY_H */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 05974bb2ba..d083586c93 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -5927,33 +5927,41 @@ void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
*/
/* Compute aggregate route's as-path.
*/
- bgp_compute_aggregate_aspath(aggregate,
- pi->attr->aspath);
+ bgp_compute_aggregate_aspath_hash(aggregate,
+ pi->attr->aspath);
/* Compute aggregate route's community.
*/
if (pi->attr->community)
- bgp_compute_aggregate_community(
+ bgp_compute_aggregate_community_hash(
aggregate,
pi->attr->community);
/* Compute aggregate route's extended community.
*/
if (pi->attr->ecommunity)
- bgp_compute_aggregate_ecommunity(
+ bgp_compute_aggregate_ecommunity_hash(
aggregate,
pi->attr->ecommunity);
/* Compute aggregate route's large community.
*/
if (pi->attr->lcommunity)
- bgp_compute_aggregate_lcommunity(
+ bgp_compute_aggregate_lcommunity_hash(
aggregate,
pi->attr->lcommunity);
}
if (match)
bgp_process(bgp, rn, afi, safi);
}
+ if (aggregate->as_set) {
+ bgp_compute_aggregate_aspath_val(aggregate);
+ bgp_compute_aggregate_community_val(aggregate);
+ bgp_compute_aggregate_ecommunity_val(aggregate);
+ bgp_compute_aggregate_lcommunity_val(aggregate);
+ }
+
+
bgp_unlock_node(top);
@@ -6034,28 +6042,28 @@ void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
if (aggregate->as_set) {
/* Remove as-path from aggregate.
*/
- bgp_remove_aspath_from_aggregate(
+ bgp_remove_aspath_from_aggregate_hash(
aggregate,
pi->attr->aspath);
if (pi->attr->community)
/* Remove community from aggregate.
*/
- bgp_remove_community_from_aggregate(
+ bgp_remove_comm_from_aggregate_hash(
aggregate,
pi->attr->community);
if (pi->attr->ecommunity)
/* Remove ecommunity from aggregate.
*/
- bgp_remove_ecommunity_from_aggregate(
+ bgp_remove_ecomm_from_aggregate_hash(
aggregate,
pi->attr->ecommunity);
if (pi->attr->lcommunity)
/* Remove lcommunity from aggregate.
*/
- bgp_remove_lcommunity_from_aggregate(
+ bgp_remove_lcomm_from_aggregate_hash(
aggregate,
pi->attr->lcommunity);
}
@@ -6066,6 +6074,17 @@ void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
if (match)
bgp_process(bgp, rn, afi, safi);
}
+ if (aggregate->as_set) {
+ aspath_free(aggregate->aspath);
+ aggregate->aspath = NULL;
+ if (aggregate->community)
+ community_free(&aggregate->community);
+ if (aggregate->ecommunity)
+ ecommunity_free(&aggregate->ecommunity);
+ if (aggregate->lcommunity)
+ lcommunity_free(&aggregate->lcommunity);
+ }
+
bgp_unlock_node(top);
}
@@ -6543,6 +6562,7 @@ DEFUN (aggregate_address_mask,
argv_find(argv, argc, "A.B.C.D", &idx);
char *prefix = argv[idx]->arg;
char *mask = argv[idx + 1]->arg;
+ bool rmap_found;
char *rmap = NULL;
int as_set =
argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
@@ -6551,8 +6571,8 @@ DEFUN (aggregate_address_mask,
? AGGREGATE_SUMMARY_ONLY
: 0;
- argv_find(argv, argc, "WORD", &idx);
- if (idx)
+ rmap_found = argv_find(argv, argc, "WORD", &idx);
+ if (rmap_found)
rmap = argv[idx]->arg;
char prefix_str[BUFSIZ];
@@ -6569,14 +6589,16 @@ DEFUN (aggregate_address_mask,
DEFUN (no_aggregate_address,
no_aggregate_address_cmd,
- "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>]",
+ "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
NO_STR
"Configure BGP aggregate entries\n"
"Aggregate prefix\n"
"Generate AS set path information\n"
"Filter more specific routes from updates\n"
"Filter more specific routes from updates\n"
- "Generate AS set path information\n")
+ "Generate AS set path information\n"
+ "Apply route map to aggregate network\n"
+ "Name of route map\n")
{
int idx = 0;
argv_find(argv, argc, "A.B.C.D/M", &idx);
@@ -6586,7 +6608,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]>]",
+ "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
NO_STR
"Configure BGP aggregate entries\n"
"Aggregate address\n"
@@ -6594,7 +6616,9 @@ DEFUN (no_aggregate_address_mask,
"Generate AS set path information\n"
"Filter more specific routes from updates\n"
"Filter more specific routes from updates\n"
- "Generate AS set path information\n")
+ "Generate AS set path information\n"
+ "Apply route map to aggregate network\n"
+ "Name of route map\n")
{
int idx = 0;
argv_find(argv, argc, "A.B.C.D", &idx);
@@ -6628,6 +6652,7 @@ DEFUN (ipv6_aggregate_address,
argv_find(argv, argc, "X:X::X:X/M", &idx);
char *prefix = argv[idx]->arg;
char *rmap = NULL;
+ bool rmap_found;
int as_set =
argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET : 0;
@@ -6636,8 +6661,8 @@ DEFUN (ipv6_aggregate_address,
? AGGREGATE_SUMMARY_ONLY
: 0;
- argv_find(argv, argc, "WORD", &idx);
- if (idx)
+ rmap_found = argv_find(argv, argc, "WORD", &idx);
+ if (rmap_found)
rmap = argv[idx]->arg;
return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
@@ -6646,14 +6671,16 @@ DEFUN (ipv6_aggregate_address,
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]>]",
+ "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
NO_STR
"Configure BGP aggregate entries\n"
"Aggregate prefix\n"
"Generate AS set path information\n"
"Filter more specific routes from updates\n"
"Filter more specific routes from updates\n"
- "Generate AS set path information\n")
+ "Generate AS set path information\n"
+ "Apply route map to aggregate network\n"
+ "Name of route map\n")
{
int idx = 0;
argv_find(argv, argc, "X:X::X:X/M", &idx);
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index de7b05bdd9..4b6af935e0 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -570,8 +570,7 @@ static int update_group_show_walkcb(struct update_group *updgrp, void *arg)
vty_out(vty, " Created: %s", timestamp_string(updgrp->uptime));
filter = &updgrp->conf->filter[updgrp->afi][updgrp->safi];
if (filter->map[RMAP_OUT].name)
- vty_out(vty, " Outgoing route map: %s%s\n",
- filter->map[RMAP_OUT].map ? "X" : "",
+ vty_out(vty, " Outgoing route map: %s\n",
filter->map[RMAP_OUT].name);
vty_out(vty, " MRAI value (seconds): %d\n", updgrp->conf->v_routeadv);
if (updgrp->conf->change_local_as)
@@ -613,6 +612,9 @@ static int update_group_show_walkcb(struct update_group *updgrp, void *arg)
subgrp->peer_refreshes_combined);
vty_out(vty, " Merge checks triggered: %u\n",
subgrp->merge_checks_triggered);
+ vty_out(vty, " Coalesce Time: %u%s\n",
+ (UPDGRP_INST(subgrp->update_group))->coalesce_time,
+ subgrp->t_coalesce ? "(Running)" : "");
vty_out(vty, " Version: %" PRIu64 "\n", subgrp->version);
vty_out(vty, " Packet queue length: %d\n",
bpacket_queue_length(SUBGRP_PKTQ(subgrp)));
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 21f1dff60d..5c1483a768 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -324,8 +324,9 @@ static int subgroup_coalesce_timer(struct thread *thread)
subgrp = THREAD_ARG(thread);
if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
zlog_debug("u%" PRIu64 ":s%" PRIu64
- " announcing routes upon coalesce timer expiry",
- (SUBGRP_UPDGRP(subgrp))->id, subgrp->id);
+ " announcing routes upon coalesce timer expiry(%u ms)",
+ (SUBGRP_UPDGRP(subgrp))->id, subgrp->id,
+ subgrp->v_coalesce),
subgrp->t_coalesce = NULL;
subgrp->v_coalesce = 0;
subgroup_announce_route(subgrp);
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index 688abae0e4..9329c8d892 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -391,6 +391,7 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
struct peer *peer;
char buf[BUFSIZ];
char buf2[BUFSIZ];
+ struct bgp_filter *filter;
s = stream_dup(pkt->buffer);
peer = PAF_PEER(paf);
@@ -401,6 +402,8 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
afi_t nhafi;
int route_map_sets_nh;
nhlen = stream_getc_from(s, vec->offset);
+ filter = &peer->filter[paf->afi][paf->safi];
+
if (peer_cap_enhe(peer, paf->afi, paf->safi))
nhafi = AFI_IP6;
else
@@ -439,25 +442,25 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
mod_v4nh = &v4nh;
/*
- * If route-map has set the nexthop, that is always
- * used; if it is
- * specified as peer-address, the peering address is
- * picked up.
- * Otherwise, if NH is unavailable from attribute, the
- * peering addr
- * is picked up; the "NH unavailable" case also covers
- * next-hop-self
- * and some other scenarios -- see
- * subgroup_announce_check(). In
- * all other cases, use the nexthop carried in the
- * attribute unless
- * it is EBGP non-multiaccess and there is no
- * next-hop-unchanged setting.
+ * If route-map has set the nexthop, that is normally
+ * used; if it is specified as peer-address, the peering
+ * address is picked up. Otherwise, if NH is unavailable
+ * from attribute, the peering addr is picked up; the
+ * "NH unavailable" case also covers next-hop-self and
+ * some other scenarios - see subgroup_announce_check().
+ * In all other cases, use the nexthop carried in the
+ * attribute unless it is EBGP non-multiaccess and there
+ * is no next-hop-unchanged setting or the peer is EBGP
+ * and the route-map that changed the next-hop value
+ * was applied inbound rather than outbound. Updates to
+ * an EBGP peer should only modify the next-hop if it
+ * was set in an outbound route-map to that peer.
* Note: It is assumed route-map cannot set the nexthop
- * to an
- * invalid value.
+ * to an invalid value.
*/
- if (route_map_sets_nh) {
+ if (route_map_sets_nh
+ && ((peer->sort != BGP_PEER_EBGP)
+ || ROUTE_MAP_OUT(filter))) {
if (CHECK_FLAG(
vec->flags,
BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)) {
@@ -543,7 +546,15 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
stream_get_from(&v6nhglobal, s, offset_nhglobal,
IPV6_MAX_BYTELEN);
- if (route_map_sets_nh) {
+
+ /*
+ * Updates to an EBGP peer should only modify the
+ * next-hop if it was set in an outbound route-map
+ * to that peer.
+ */
+ if (route_map_sets_nh
+ && ((peer->sort != BGP_PEER_EBGP)
+ || ROUTE_MAP_OUT(filter))) {
if (CHECK_FLAG(
vec->flags,
BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)) {
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 9d45d96987..320f1ec96c 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1202,7 +1202,7 @@ struct peer {
uint8_t last_reset_cause[BGP_MAX_PACKET_SIZE];
/* The kind of route-map Flags.*/
- uint8_t rmap_type;
+ uint16_t rmap_type;
#define PEER_RMAP_TYPE_IN (1 << 0) /* neighbor route-map in */
#define PEER_RMAP_TYPE_OUT (1 << 1) /* neighbor route-map out */
#define PEER_RMAP_TYPE_NETWORK (1 << 2) /* network route-map */
diff --git a/configure.ac b/configure.ac
index 6c1b35b5f2..88f1c4f627 100755
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
##
AC_PREREQ([2.60])
-AC_INIT([frr], [7.2-dev], [https://github.com/frrouting/frr/issues])
+AC_INIT([frr], [7.3-dev], [https://github.com/frrouting/frr/issues])
PACKAGE_URL="https://frrouting.org/"
AC_SUBST([PACKAGE_URL])
PACKAGE_FULLNAME="FRRouting"
@@ -1452,6 +1452,12 @@ if test "x$enable_pcreposix" = "xyes"; then
fi
AC_SUBST([HAVE_LIBPCREPOSIX])
+dnl ##########################################################################
+dnl test "${enable_clippy_only}" != "yes"
+fi
+dnl END OF LARGE if block
+dnl ##########################################################################
+
dnl ------------------
dnl check C-Ares library
dnl ------------------
@@ -1462,12 +1468,6 @@ PKG_CHECK_MODULES([CARES], [libcares], [
])
AM_CONDITIONAL([CARES], [$c_ares_found])
-dnl ##########################################################################
-dnl test "${enable_clippy_only}" != "yes"
-fi
-dnl END OF LARGE if block
-dnl ##########################################################################
-
dnl ----------------------------------------------------------------------------
dnl figure out if domainname is available in the utsname struct (GNU extension).
@@ -1535,9 +1535,11 @@ case "$host_os" in
no)
;;
yes)
+ if test "${enable_clippy_only}" != "yes"; then
if test "$c_ares_found" != "true" ; then
AC_MSG_ERROR([nhrpd requires libcares. Please install c-ares and its -dev headers.])
fi
+ fi
NHRPD="nhrpd"
;;
*)
@@ -2041,9 +2043,11 @@ if test "${enable_capabilities}" != "no"; then
case "$host_os" in
linux*)
+ if test "${enable_clippy_only}" != "yes"; then
if test "$frr_ac_lcaps" != "yes"; then
AC_MSG_ERROR([libcap and/or its headers were not found. Running FRR without libcap support built in causes a huge performance penalty.])
fi
+ fi
;;
esac
else
diff --git a/doc/user/bfd.rst b/doc/user/bfd.rst
index 32ca5707d2..525a31d486 100644
--- a/doc/user/bfd.rst
+++ b/doc/user/bfd.rst
@@ -79,8 +79,8 @@ BFDd Commands
`vrf` selects which domain we want to use.
-.. index:: no peer <A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrfname}]
-.. clicmd:: no peer <A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrfname}]
+.. index:: no peer <A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrf_name}]
+.. clicmd:: no peer <A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrf_name}]
Stops and removes the selected peer.
@@ -89,8 +89,8 @@ BFDd Commands
Show all configured BFD peers information and current status.
-.. index:: show bfd [vrf NAME$vrfname] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]
-.. clicmd:: show bfd [vrf NAME$vrfname] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]
+.. index:: show bfd [vrf NAME$vrf_name] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]
+.. clicmd:: show bfd [vrf NAME$vrf_name] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]
Show status for a specific BFD peer.
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 7b3cdf2c4b..8edd19026d 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -2396,6 +2396,23 @@ Displaying Routes by AS Path
Print a summary of neighbor connections for the specified AFI/SAFI combination.
+Displaying Update Group Information
+-----------------------------------
+
+..index:: show bgp update-groups SUBGROUP-ID [advertise-queue|advertised-routes|packet-queue]
+..clicmd:: show bgp update-groups [advertise-queue|advertised-routes|packet-queue]
+
+ Display Information about each individual update-group being used.
+ If SUBGROUP-ID is specified only display about that particular group. If
+ advertise-queue is specified the list of routes that need to be sent
+ to the peers in the update-group is displayed, advertised-routes means
+ the list of routes we have sent to the peers in the update-group and
+ packet-queue specifies the list of packets in the queue to be sent.
+
+..index:: show bgp update-groups statistics
+..clicmd:: show bgp update-groups statistics
+
+ Display Information about update-group events in FRR.
.. _bgp-route-reflector:
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index b7283d83de..5d2cfbc337 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -663,19 +663,30 @@ kernel.
.. clicmd:: ip protocol PROTOCOL route-map ROUTEMAP
Apply a route-map filter to routes for the specified protocol. PROTOCOL can
- be **any** or one of
+ be:
- - system,
- - kernel,
+ - any,
+ - babel,
+ - bgp,
- connected,
- - static,
- - rip,
- - ripng,
+ - eigrp,
+ - isis,
+ - kernel,
+ - nhrp,
+ - openfabric,
- ospf,
- ospf6,
- - isis,
- - bgp,
- - hsls.
+ - rip,
+ - sharp,
+ - static,
+ - ripng,
+ - table,
+ - vnc.
+
+ If you choose any as the option that will cause all protocols that are sending
+ routes to zebra. You can specify a :dfn:`ip protocol PROTOCOL route-map ROUTEMAP`
+ on a per vrf basis, by entering this command under vrf mode for the vrf you
+ want to apply the route-map against.
.. index:: set src ADDRESS
.. clicmd:: set src ADDRESS
diff --git a/docker/alpine/Dockerfile b/docker/alpine/Dockerfile
index 815983a394..88c8f88f81 100644
--- a/docker/alpine/Dockerfile
+++ b/docker/alpine/Dockerfile
@@ -9,7 +9,8 @@ RUN source /src/alpine/APKBUILD.in \
--no-cache \
--update-cache \
$makedepends \
- gzip
+ gzip \
+ && pip install pytest
COPY . /src
ARG PKGVER
@@ -29,6 +30,8 @@ RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/reposit
abuild \
alpine-conf \
alpine-sdk \
+ py-pip \
+ && pip install pytest \
&& setup-apkcache /var/cache/apk \
&& mkdir -p /pkgs/apk \
&& echo 'builder ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c
index c7ffbf9f0e..3e09ec41bb 100644
--- a/eigrpd/eigrp_network.c
+++ b/eigrpd/eigrp_network.c
@@ -55,12 +55,15 @@ static void eigrp_network_run_interface(struct eigrp *, struct prefix *,
int eigrp_sock_init(struct vrf *vrf)
{
- int eigrp_sock;
+ int eigrp_sock = -1;
int ret;
#ifdef IP_HDRINCL
int hincl = 1;
#endif
+ if (!vrf)
+ return eigrp_sock;
+
frr_with_privs(&eigrpd_privs) {
eigrp_sock = vrf_socket(
AF_INET, SOCK_RAW, IPPROTO_EIGRPIGP, vrf->vrf_id,
diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h
index bc6688012c..232df14e12 100644
--- a/include/linux/fib_rules.h
+++ b/include/linux/fib_rules.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef __LINUX_FIB_RULES_H
#define __LINUX_FIB_RULES_H
@@ -22,13 +23,23 @@ struct fib_rule_hdr {
__u8 tos;
__u8 table;
- __u8 res1; /* reserved */
+ __u8 res1; /* reserved */
__u8 res2; /* reserved */
__u8 action;
__u32 flags;
};
+struct fib_rule_uid_range {
+ __u32 start;
+ __u32 end;
+};
+
+struct fib_rule_port_range {
+ __u16 start;
+ __u16 end;
+};
+
enum {
FRA_UNSPEC,
FRA_DST, /* destination address */
@@ -43,7 +54,7 @@ enum {
FRA_UNUSED5,
FRA_FWMARK, /* mark */
FRA_FLOW, /* flow/class id */
- FRA_UNUSED6,
+ FRA_TUN_ID,
FRA_SUPPRESS_IFGROUP,
FRA_SUPPRESS_PREFIXLEN,
FRA_TABLE, /* Extended table id */
@@ -51,6 +62,11 @@ enum {
FRA_OIFNAME,
FRA_PAD,
FRA_L3MDEV, /* iif or oif is l3mdev goto its table */
+ FRA_UID_RANGE, /* UID range */
+ FRA_PROTOCOL, /* Originator of the rule */
+ FRA_IP_PROTO, /* ip proto */
+ FRA_SPORT_RANGE, /* sport */
+ FRA_DPORT_RANGE, /* dport */
__FRA_MAX
};
diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h
index a924606f36..dfcf3ce009 100644
--- a/include/linux/if_addr.h
+++ b/include/linux/if_addr.h
@@ -34,6 +34,7 @@ enum {
IFA_MULTICAST,
IFA_FLAGS,
IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */
+ IFA_TARGET_NETNSID,
__IFA_MAX,
};
@@ -63,7 +64,9 @@ struct ifa_cacheinfo {
};
/* backwards compatibility for userspace */
+#ifndef __KERNEL__
#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
+#endif
#endif
diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h
index 156f4434ca..fb79481cb2 100644
--- a/include/linux/if_bridge.h
+++ b/include/linux/if_bridge.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* Linux ethernet bridge
*
@@ -10,8 +11,8 @@
* 2 of the License, or (at your option) any later version.
*/
-#ifndef _LINUX_IF_BRIDGE_H
-#define _LINUX_IF_BRIDGE_H
+#ifndef _UAPI_LINUX_IF_BRIDGE_H
+#define _UAPI_LINUX_IF_BRIDGE_H
#include <linux/types.h>
#include <linux/if_ether.h>
@@ -96,7 +97,7 @@ struct __fdb_entry {
__u32 ageing_timer_value;
__u8 port_hi;
__u8 pad0;
- __u16 unused;
+ __u16 vlan;
};
/* Bridge Flags */
@@ -236,6 +237,7 @@ struct br_mdb_entry {
#define MDB_PERMANENT 1
__u8 state;
#define MDB_FLAGS_OFFLOAD (1 << 0)
+#define MDB_FLAGS_FAST_LEAVE (1 << 1)
__u8 flags;
__u16 vid;
struct {
@@ -291,4 +293,4 @@ struct br_mcast_stats {
__u64 mcast_bytes[BR_MCAST_DIR_SIZE];
__u64 mcast_packets[BR_MCAST_DIR_SIZE];
};
-#endif /* _LINUX_IF_BRIDGE_H */
+#endif /* _UAPI_LINUX_IF_BRIDGE_H */
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index 1f97d0560b..22a45914a2 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -1,5 +1,6 @@
-#ifndef _LINUX_IF_LINK_H
-#define _LINUX_IF_LINK_H
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_LINUX_IF_LINK_H
+#define _UAPI_LINUX_IF_LINK_H
#include <linux/types.h>
#include <linux/netlink.h>
@@ -158,6 +159,14 @@ enum {
IFLA_PAD,
IFLA_XDP,
IFLA_EVENT,
+ IFLA_NEW_NETNSID,
+ IFLA_IF_NETNSID,
+ IFLA_TARGET_NETNSID = IFLA_IF_NETNSID, /* new alias */
+ IFLA_CARRIER_UP_COUNT,
+ IFLA_CARRIER_DOWN_COUNT,
+ IFLA_NEW_IFINDEX,
+ IFLA_MIN_MTU,
+ IFLA_MAX_MTU,
__IFLA_MAX
};
@@ -165,8 +174,10 @@ enum {
#define IFLA_MAX (__IFLA_MAX - 1)
/* backwards compatibility for userspace */
+#ifndef __KERNEL__
#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
+#endif
enum {
IFLA_INET_UNSPEC,
@@ -276,6 +287,7 @@ enum {
IFLA_BR_MCAST_STATS_ENABLED,
IFLA_BR_MCAST_IGMP_VERSION,
IFLA_BR_MCAST_MLD_VERSION,
+ IFLA_BR_VLAN_STATS_PER_PORT,
__IFLA_BR_MAX,
};
@@ -323,6 +335,14 @@ enum {
IFLA_BRPORT_MCAST_TO_UCAST,
IFLA_BRPORT_VLAN_TUNNEL,
IFLA_BRPORT_BCAST_FLOOD,
+ IFLA_BRPORT_GROUP_FWD_MASK,
+ IFLA_BRPORT_NEIGH_SUPPRESS,
+ IFLA_BRPORT_ISOLATED,
+ IFLA_BRPORT_BACKUP_PORT,
+ IFLA_BRPORT_PEER_LINK = 60, /* MLAG peer link */
+ IFLA_BRPORT_DUAL_LINK, /* MLAG Dual Connected link */
+ IFLA_BRPORT_GROUP_FWD_MASKHI,
+ IFLA_BRPORT_DUAL_LINK_READY,
__IFLA_BRPORT_MAX
};
#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
@@ -448,6 +468,16 @@ enum {
#define IFLA_MACSEC_MAX (__IFLA_MACSEC_MAX - 1)
+/* XFRM section */
+enum {
+ IFLA_XFRM_UNSPEC,
+ IFLA_XFRM_LINK,
+ IFLA_XFRM_IF_ID,
+ __IFLA_XFRM_MAX
+};
+
+#define IFLA_XFRM_MAX (__IFLA_XFRM_MAX - 1)
+
enum macsec_validation_type {
MACSEC_VALIDATE_DISABLED = 0,
MACSEC_VALIDATE_CHECK = 1,
@@ -460,6 +490,7 @@ enum macsec_validation_type {
enum {
IFLA_IPVLAN_UNSPEC,
IFLA_IPVLAN_MODE,
+ IFLA_IPVLAN_FLAGS,
__IFLA_IPVLAN_MAX
};
@@ -472,6 +503,9 @@ enum ipvlan_mode {
IPVLAN_MODE_MAX
};
+#define IPVLAN_F_PRIVATE 0x01
+#define IPVLAN_F_VEPA 0x02
+
/* VXLAN section */
enum {
IFLA_VXLAN_UNSPEC,
@@ -502,6 +536,7 @@ enum {
IFLA_VXLAN_COLLECT_METADATA,
IFLA_VXLAN_LABEL,
IFLA_VXLAN_GPE,
+ IFLA_VXLAN_TTL_INHERIT,
__IFLA_VXLAN_MAX
};
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
@@ -585,6 +620,8 @@ enum {
IFLA_BOND_AD_USER_PORT_KEY,
IFLA_BOND_AD_ACTOR_SYSTEM,
IFLA_BOND_TLB_DYNAMIC_LB,
+ IFLA_BOND_CL_START = 60,
+ IFLA_BOND_AD_LACP_BYPASS = IFLA_BOND_CL_START,
__IFLA_BOND_MAX,
};
@@ -612,6 +649,9 @@ enum {
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID,
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE,
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE,
+
+ IFLA_BOND_SLAVE_CL_START = 50,
+ IFLA_BOND_SLAVE_AD_RX_BYPASS = IFLA_BOND_SLAVE_CL_START,
__IFLA_BOND_SLAVE_MAX,
};
@@ -721,6 +761,8 @@ enum {
IFLA_VF_STATS_BROADCAST,
IFLA_VF_STATS_MULTICAST,
IFLA_VF_STATS_PAD,
+ IFLA_VF_STATS_RX_DROPPED,
+ IFLA_VF_STATS_TX_DROPPED,
__IFLA_VF_STATS_MAX,
};
@@ -872,6 +914,7 @@ enum {
enum {
LINK_XSTATS_TYPE_UNSPEC,
LINK_XSTATS_TYPE_BRIDGE,
+ LINK_XSTATS_TYPE_BOND,
__LINK_XSTATS_TYPE_MAX
};
#define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1)
@@ -902,6 +945,7 @@ enum {
XDP_ATTACHED_DRV,
XDP_ATTACHED_SKB,
XDP_ATTACHED_HW,
+ XDP_ATTACHED_MULTI,
};
enum {
@@ -910,6 +954,9 @@ enum {
IFLA_XDP_ATTACHED,
IFLA_XDP_FLAGS,
IFLA_XDP_PROG_ID,
+ IFLA_XDP_DRV_PROG_ID,
+ IFLA_XDP_SKB_PROG_ID,
+ IFLA_XDP_HW_PROG_ID,
__IFLA_XDP_MAX,
};
@@ -925,4 +972,43 @@ enum {
IFLA_EVENT_BONDING_OPTIONS, /* change in bonding options */
};
-#endif /* _LINUX_IF_LINK_H */
+/* tun section */
+
+enum {
+ IFLA_TUN_UNSPEC,
+ IFLA_TUN_OWNER,
+ IFLA_TUN_GROUP,
+ IFLA_TUN_TYPE,
+ IFLA_TUN_PI,
+ IFLA_TUN_VNET_HDR,
+ IFLA_TUN_PERSIST,
+ IFLA_TUN_MULTI_QUEUE,
+ IFLA_TUN_NUM_QUEUES,
+ IFLA_TUN_NUM_DISABLED_QUEUES,
+ __IFLA_TUN_MAX,
+};
+
+#define IFLA_TUN_MAX (__IFLA_TUN_MAX - 1)
+
+/* rmnet section */
+
+#define RMNET_FLAGS_INGRESS_DEAGGREGATION (1U << 0)
+#define RMNET_FLAGS_INGRESS_MAP_COMMANDS (1U << 1)
+#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4 (1U << 2)
+#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4 (1U << 3)
+
+enum {
+ IFLA_RMNET_UNSPEC,
+ IFLA_RMNET_MUX_ID,
+ IFLA_RMNET_FLAGS,
+ __IFLA_RMNET_MAX,
+};
+
+#define IFLA_RMNET_MAX (__IFLA_RMNET_MAX - 1)
+
+struct ifla_rmnet_flags {
+ __u32 flags;
+ __u32 mask;
+};
+
+#endif /* _UAPI_LINUX_IF_LINK_H */
diff --git a/include/linux/lwtunnel.h b/include/linux/lwtunnel.h
index 3298426271..de696ca12f 100644
--- a/include/linux/lwtunnel.h
+++ b/include/linux/lwtunnel.h
@@ -1,5 +1,6 @@
-#ifndef _LWTUNNEL_H_
-#define _LWTUNNEL_H_
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_LWTUNNEL_H_
+#define _UAPI_LWTUNNEL_H_
#include <linux/types.h>
@@ -67,4 +68,4 @@ enum {
#define LWT_BPF_MAX_HEADROOM 256
-#endif /* _LWTUNNEL_H_ */
+#endif /* _UAPI_LWTUNNEL_H_ */
diff --git a/include/linux/mpls_iptunnel.h b/include/linux/mpls_iptunnel.h
index 1a0e57b45a..521f2e605f 100644
--- a/include/linux/mpls_iptunnel.h
+++ b/include/linux/mpls_iptunnel.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* mpls tunnel api
*
@@ -10,8 +11,8 @@
* 2 of the License, or (at your option) any later version.
*/
-#ifndef _LINUX_MPLS_IPTUNNEL_H
-#define _LINUX_MPLS_IPTUNNEL_H
+#ifndef _UAPI_LINUX_MPLS_IPTUNNEL_H
+#define _UAPI_LINUX_MPLS_IPTUNNEL_H
/* MPLS tunnel attributes
* [RTA_ENCAP] = {
@@ -27,4 +28,4 @@ enum {
};
#define MPLS_IPTUNNEL_MAX (__MPLS_IPTUNNEL_MAX - 1)
-#endif /* _LINUX_MPLS_IPTUNNEL_H */
+#endif /* _UAPI_LINUX_MPLS_IPTUNNEL_H */
diff --git a/include/linux/neighbour.h b/include/linux/neighbour.h
index 3199d28980..cd144e3099 100644
--- a/include/linux/neighbour.h
+++ b/include/linux/neighbour.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef __LINUX_NEIGHBOUR_H
#define __LINUX_NEIGHBOUR_H
@@ -27,6 +28,7 @@ enum {
NDA_MASTER,
NDA_LINK_NETNSID,
NDA_SRC_VNI,
+ NDA_PROTOCOL, /* Originator of entry */
__NDA_MAX
};
@@ -42,6 +44,7 @@ enum {
#define NTF_PROXY 0x08 /* == ATF_PUBL */
#define NTF_EXT_LEARNED 0x10
#define NTF_OFFLOADED 0x20
+#define NTF_STICKY 0x40
#define NTF_ROUTER 0x80
/*
diff --git a/include/linux/net_namespace.h b/include/linux/net_namespace.h
index 9a92b7e14a..0187c74d88 100644
--- a/include/linux/net_namespace.h
+++ b/include/linux/net_namespace.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/* Copyright (c) 2015 6WIND S.A.
* Author: Nicolas Dichtel <nicolas.dichtel@6wind.com>
*
@@ -5,8 +6,8 @@
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
-#ifndef _LINUX_NET_NAMESPACE_H_
-#define _LINUX_NET_NAMESPACE_H_
+#ifndef _UAPI_LINUX_NET_NAMESPACE_H_
+#define _UAPI_LINUX_NET_NAMESPACE_H_
/* Attributes of RTM_NEWNSID/RTM_GETNSID messages */
enum {
@@ -20,4 +21,4 @@ enum {
#define NETNSA_MAX (__NETNSA_MAX - 1)
-#endif /* _LINUX_NET_NAMESPACE_H_ */
+#endif /* _UAPI_LINUX_NET_NAMESPACE_H_ */
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index 0b2c29bd08..0a4d733177 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef __LINUX_NETLINK_H
-#define __LINUX_NETLINK_H
+#ifndef _UAPI__LINUX_NETLINK_H
+#define _UAPI__LINUX_NETLINK_H
#include <linux/kernel.h>
#include <linux/socket.h> /* for __kernel_sa_family_t */
@@ -147,12 +147,15 @@ enum nlmsgerr_attrs {
#define NETLINK_PKTINFO 3
#define NETLINK_BROADCAST_ERROR 4
#define NETLINK_NO_ENOBUFS 5
+#ifndef __KERNEL__
#define NETLINK_RX_RING 6
#define NETLINK_TX_RING 7
+#endif
#define NETLINK_LISTEN_ALL_NSID 8
#define NETLINK_LIST_MEMBERSHIPS 9
#define NETLINK_CAP_ACK 10
#define NETLINK_EXT_ACK 11
+#define NETLINK_GET_STRICT_CHK 12
struct nl_pktinfo {
__u32 group;
@@ -175,6 +178,7 @@ struct nl_mmap_hdr {
__u32 nm_gid;
};
+#ifndef __KERNEL__
enum nl_mmap_status {
NL_MMAP_STATUS_UNUSED,
NL_MMAP_STATUS_RESERVED,
@@ -186,6 +190,7 @@ enum nl_mmap_status {
#define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO
#define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT)
#define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr))
+#endif
#define NET_MAJOR 36 /* Major 36 is reserved for networking */
@@ -244,4 +249,4 @@ struct nla_bitfield32 {
__u32 selector;
};
-#endif /* __LINUX_NETLINK_H */
+#endif /* _UAPI__LINUX_NETLINK_H */
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 813e9e0767..ce2a623abb 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -1,5 +1,6 @@
-#ifndef __LINUX_RTNETLINK_H
-#define __LINUX_RTNETLINK_H
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI__LINUX_RTNETLINK_H
+#define _UAPI__LINUX_RTNETLINK_H
#include <linux/types.h>
#include <linux/netlink.h>
@@ -149,6 +150,20 @@ enum {
RTM_NEWCACHEREPORT = 96,
#define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT
+ RTM_NEWCHAIN = 100,
+#define RTM_NEWCHAIN RTM_NEWCHAIN
+ RTM_DELCHAIN,
+#define RTM_DELCHAIN RTM_DELCHAIN
+ RTM_GETCHAIN,
+#define RTM_GETCHAIN RTM_GETCHAIN
+
+ RTM_NEWNEXTHOP = 104,
+#define RTM_NEWNEXTHOP RTM_NEWNEXTHOP
+ RTM_DELNEXTHOP,
+#define RTM_DELNEXTHOP RTM_DELNEXTHOP
+ RTM_GETNEXTHOP,
+#define RTM_GETNEXTHOP RTM_GETNEXTHOP
+
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
};
@@ -253,6 +268,11 @@ enum {
#define RTPROT_DHCP 16 /* DHCP client */
#define RTPROT_MROUTED 17 /* Multicast daemon */
#define RTPROT_BABEL 42 /* Babel daemon */
+#define RTPROT_BGP 186 /* BGP Routes */
+#define RTPROT_ISIS 187 /* ISIS Routes */
+#define RTPROT_OSPF 188 /* OSPF Routes */
+#define RTPROT_RIP 189 /* RIP Routes */
+#define RTPROT_EIGRP 192 /* EIGRP Routes */
/* rtm_scope
@@ -326,6 +346,10 @@ enum rtattr_type_t {
RTA_PAD,
RTA_UID,
RTA_TTL_PROPAGATE,
+ RTA_IP_PROTO,
+ RTA_SPORT,
+ RTA_DPORT,
+ RTA_NH_ID,
__RTA_MAX
};
@@ -430,6 +454,8 @@ enum {
#define RTAX_QUICKACK RTAX_QUICKACK
RTAX_CC_ALGO,
#define RTAX_CC_ALGO RTAX_CC_ALGO
+ RTAX_FASTOPEN_NO_COOKIE,
+#define RTAX_FASTOPEN_NO_COOKIE RTAX_FASTOPEN_NO_COOKIE
__RTAX_MAX
};
@@ -538,9 +564,19 @@ struct tcmsg {
int tcm_ifindex;
__u32 tcm_handle;
__u32 tcm_parent;
+/* tcm_block_index is used instead of tcm_parent
+ * in case tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK
+ */
+#define tcm_block_index tcm_parent
__u32 tcm_info;
};
+/* For manipulation of filters in shared block, tcm_ifindex is set to
+ * TCM_IFINDEX_MAGIC_BLOCK, and tcm_parent is aliased to tcm_block_index
+ * which is the block index.
+ */
+#define TCM_IFINDEX_MAGIC_BLOCK (0xFFFFFFFFU)
+
enum {
TCA_UNSPEC,
TCA_KIND,
@@ -554,6 +590,9 @@ enum {
TCA_PAD,
TCA_DUMP_INVISIBLE,
TCA_CHAIN,
+ TCA_HW_OFFLOAD,
+ TCA_INGRESS_BLOCK,
+ TCA_EGRESS_BLOCK,
__TCA_MAX
};
@@ -586,6 +625,7 @@ enum {
#define NDUSEROPT_MAX (__NDUSEROPT_MAX - 1)
+#ifndef __KERNEL__
/* RTnetlink multicast groups - backwards compatibility for userspace */
#define RTMGRP_LINK 1
#define RTMGRP_NOTIFY 2
@@ -606,6 +646,7 @@ enum {
#define RTMGRP_DECnet_ROUTE 0x4000
#define RTMGRP_IPV6_PREFIX 0x20000
+#endif
/* RTnetlink multicast groups */
enum rtnetlink_groups {
@@ -671,6 +712,8 @@ enum rtnetlink_groups {
#define RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV4_MROUTE_R
RTNLGRP_IPV6_MROUTE_R,
#define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R
+ RTNLGRP_NEXTHOP,
+#define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
@@ -715,4 +758,4 @@ enum {
-#endif /* __LINUX_RTNETLINK_H */
+#endif /* _UAPI__LINUX_RTNETLINK_H */
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 8c1e501774..8eb9602170 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -1,5 +1,6 @@
-#ifndef _LINUX_SOCKET_H
-#define _LINUX_SOCKET_H
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _UAPI_LINUX_SOCKET_H
+#define _UAPI_LINUX_SOCKET_H
/*
* Desired design of maximum size and alignment (see RFC2553)
@@ -18,4 +19,4 @@ struct __kernel_sockaddr_storage {
/* _SS_MAXSIZE value minus size of ss_family */
} __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */
-#endif /* _LINUX_SOCKET_H */
+#endif /* _UAPI_LINUX_SOCKET_H */
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index 9b368cc404..d2ec6ff566 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -254,6 +254,7 @@ void isis_adj_state_change(struct isis_adjacency *adj,
reason ? reason : "unspecified");
}
+ circuit->adj_state_changes++;
#ifndef FABRICD
/* send northbound notification */
isis_notif_adj_state_change(adj, new_state, reason);
diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h
index e834e31600..f677d3aded 100644
--- a/isisd/isis_circuit.h
+++ b/isisd/isis_circuit.h
@@ -146,6 +146,13 @@ struct isis_circuit {
uint32_t
desig_changes[2]; /* lanLxDesignatedIntermediateSystemChanges */
uint32_t rej_adjacencies; /* rejectedAdjacencies */
+ /*
+ * Counters as in ietf-isis@2019-09-09.yang
+ */
+ uint32_t id_len_mismatches; /* id-len-mismatch */
+ uint32_t max_area_addr_mismatches; /* max-area-addresses-mismatch */
+ uint32_t auth_type_failures; /*authentication-type-fails */
+ uint32_t auth_failures; /* authentication-fails */
QOBJ_FIELDS
};
diff --git a/isisd/isis_main.c b/isisd/isis_main.c
index 7f49e9d89a..718924daf2 100644
--- a/isisd/isis_main.c
+++ b/isisd/isis_main.c
@@ -243,7 +243,7 @@ int main(int argc, char **argv, char **envp)
mt_init();
/* create the global 'isis' instance */
- isis_new(1);
+ isis_new(1, VRF_DEFAULT);
isis_zebra_init(master);
isis_bfd_init();
diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c
index bd61918697..1e21efa7ce 100644
--- a/isisd/isis_northbound.c
+++ b/isisd/isis_northbound.c
@@ -49,6 +49,23 @@
#include "lib/vrf.h"
/*
+ * Helper functions.
+ */
+static const char *isis_yang_adj_state(enum isis_adj_state state)
+{
+ switch (state) {
+ case ISIS_ADJ_DOWN:
+ return "down";
+ case ISIS_ADJ_UP:
+ return "up";
+ case ISIS_ADJ_INITIALIZING:
+ return "init";
+ default:
+ return "failed";
+ }
+}
+
+/*
* XPath: /frr-isisd:isis/instance
*/
static int isis_instance_create(enum nb_event event,
@@ -1542,9 +1559,9 @@ static int lib_interface_isis_create(enum nb_event event,
/* check if interface mtu is sufficient. If the area has not
* been created yet, assume default MTU for the area
*/
- ifp = nb_running_get_entry(dnode, NULL, true);
+ ifp = nb_running_get_entry(dnode, NULL, false);
/* zebra might not know yet about the MTU - nothing we can do */
- if (ifp->mtu == 0)
+ if (!ifp || ifp->mtu == 0)
break;
actual_mtu =
if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu;
@@ -2304,6 +2321,368 @@ static int lib_interface_isis_multi_topology_ipv6_dstsrc_modify(
}
/*
+ * XPath: /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency
+ */
+static const void *
+lib_interface_isis_adjacencies_adjacency_get_next(const void *parent_list_entry,
+ const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+ struct isis_adjacency *adj, *adj_next = NULL;
+ struct list *list;
+ struct listnode *node, *node_next;
+
+ /* Get first adjacency. */
+ if (list_entry == NULL) {
+ ifp = (struct interface *)parent_list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ switch (circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS;
+ level++) {
+ adj = listnode_head(
+ circuit->u.bc.adjdb[level - 1]);
+ if (adj)
+ break;
+ }
+ break;
+ case CIRCUIT_T_P2P:
+ adj = circuit->u.p2p.neighbor;
+ break;
+ default:
+ adj = NULL;
+ break;
+ }
+
+ return adj;
+ }
+
+ /* Get next adjacency. */
+ adj = (struct isis_adjacency *)list_entry;
+ circuit = adj->circuit;
+ switch (circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ list = circuit->u.bc.adjdb[adj->level - 1];
+ node = listnode_lookup(list, adj);
+ node_next = listnextnode(node);
+ if (node_next)
+ adj_next = listgetdata(node_next);
+ else if (adj->level == ISIS_LEVEL1) {
+ /*
+ * Once we finish the L1 adjacencies, move to the L2
+ * adjacencies list.
+ */
+ list = circuit->u.bc.adjdb[ISIS_LEVEL2 - 1];
+ adj_next = listnode_head(list);
+ }
+ break;
+ case CIRCUIT_T_P2P:
+ /* P2P circuits have at most one adjacency. */
+ default:
+ break;
+ }
+
+ return adj_next;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_neighbor_sys_type_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_enum(xpath, adj->level);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_neighbor_sysid_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_string(xpath, sysid_print(adj->sysid));
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_uint32(xpath, adj->circuit->circuit_id);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_neighbor_snpa_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_string(xpath, snpa_print(adj->snpa));
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/hold-timer
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_hold_timer_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_uint16(xpath, adj->hold_time);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-priority
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_neighbor_priority_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_uint8(xpath, adj->prio[adj->level - 1]);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/state
+ */
+static struct yang_data *
+lib_interface_isis_adjacencies_adjacency_state_get_elem(const char *xpath,
+ const void *list_entry)
+{
+ const struct isis_adjacency *adj = list_entry;
+
+ return yang_data_new_string(xpath, isis_yang_adj_state(adj->adj_state));
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-changes
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_adjacency_changes_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->adj_state_changes);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-number
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_adjacency_number_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+ struct isis_adjacency *adj;
+ struct listnode *node;
+ uint32_t total = 0;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ /*
+ * TODO: keep track of the number of adjacencies instead of calculating
+ * it on demand.
+ */
+ switch (circuit->circ_type) {
+ case CIRCUIT_T_BROADCAST:
+ for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) {
+ for (ALL_LIST_ELEMENTS_RO(
+ circuit->u.bc.adjdb[level - 1], node, adj))
+ total++;
+ }
+ break;
+ case CIRCUIT_T_P2P:
+ adj = circuit->u.p2p.neighbor;
+ if (adj)
+ total = 1;
+ break;
+ default:
+ break;
+ }
+
+ return yang_data_new_uint32(xpath, total);
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-isisd:isis/event-counters/init-fails
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_init_fails_get_elem(const char *xpath,
+ const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->init_failures);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-rejects
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_adjacency_rejects_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->rej_adjacencies);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/id-len-mismatch
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_id_len_mismatch_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->id_len_mismatches);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/max-area-addresses-mismatch
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_max_area_addresses_mismatch_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->max_area_addr_mismatches);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-type-fails
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_authentication_type_fails_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->auth_type_failures);
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-fails
+ */
+static struct yang_data *
+lib_interface_isis_event_counters_authentication_fails_get_elem(
+ const char *xpath, const void *list_entry)
+{
+ struct interface *ifp;
+ struct isis_circuit *circuit;
+
+ ifp = (struct interface *)list_entry;
+ if (!ifp)
+ return NULL;
+
+ circuit = circuit_scan_by_ifp(ifp);
+ if (!circuit)
+ return NULL;
+
+ return yang_data_new_uint32(xpath, circuit->auth_failures);
+}
+
+/*
* NOTIFICATIONS
*/
static void notif_prep_instance_hdr(const char *xpath,
@@ -2545,19 +2924,7 @@ void isis_notif_adj_state_change(const struct isis_adjacency *adj,
listnode_add(arguments, data);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/state", xpath);
- switch (new_state) {
- case ISIS_ADJ_DOWN:
- data = yang_data_new_string(xpath_arg, "down");
- break;
- case ISIS_ADJ_UP:
- data = yang_data_new_string(xpath_arg, "up");
- break;
- case ISIS_ADJ_INITIALIZING:
- data = yang_data_new_string(xpath_arg, "init");
- break;
- default:
- data = yang_data_new_string(xpath_arg, "failed");
- }
+ data = yang_data_new_string(xpath_arg, isis_yang_adj_state(new_state));
listnode_add(arguments, data);
if (new_state == ISIS_ADJ_DOWN) {
snprintf(xpath_arg, sizeof(xpath_arg), "%s/reason", xpath);
@@ -3484,6 +3851,102 @@ const struct frr_yang_module_info frr_isisd_info = {
},
},
{
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency",
+ .cbs = {
+ .get_next = lib_interface_isis_adjacencies_adjacency_get_next,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_sys_type_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_sysid_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_snpa_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/hold-timer",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_hold_timer_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-priority",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_priority_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/state",
+ .cbs = {
+ .get_elem = lib_interface_isis_adjacencies_adjacency_state_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-changes",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_adjacency_changes_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-number",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_adjacency_number_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/init-fails",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_init_fails_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-rejects",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_adjacency_rejects_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/id-len-mismatch",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_id_len_mismatch_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/max-area-addresses-mismatch",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_max_area_addresses_mismatch_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-type-fails",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_authentication_type_fails_get_elem,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-fails",
+ .cbs = {
+ .get_elem = lib_interface_isis_event_counters_authentication_fails_get_elem,
+ }
+ },
+ {
.xpath = NULL,
},
}
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index ecfce392ff..46b013ddd0 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -576,6 +576,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
if (p2p_hello) {
if (circuit->circ_type != CIRCUIT_T_P2P) {
zlog_warn("p2p hello on non p2p circuit");
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "p2p hello on non p2p circuit",
@@ -586,6 +587,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
} else {
if (circuit->circ_type != CIRCUIT_T_BROADCAST) {
zlog_warn("lan hello on non broadcast circuit");
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "lan hello on non broadcast circuit",
@@ -598,6 +600,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
zlog_debug(
"level %d LAN Hello received over circuit with externalDomain = true",
level);
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit,
@@ -614,6 +617,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
circuit->area->area_tag,
circuit->interface->name);
}
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "Interface level mismatch", raw_pdu);
@@ -643,6 +647,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
"ISIS-Adj (%s): Rcvd %s from (%s) with invalid pdu length %" PRIu16,
circuit->area->area_tag, pdu_name,
circuit->interface->name, iih.pdu_len);
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(circuit, "Invalid PDU length",
raw_pdu);
@@ -654,6 +659,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
flog_err(EC_ISIS_PACKET,
"Level %d LAN Hello with Circuit Type %d", level,
iih.circ_type);
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "LAN Hello with wrong IS-level", raw_pdu);
@@ -667,6 +673,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
if (isis_unpack_tlvs(STREAM_READABLE(circuit->rcv_stream),
circuit->rcv_stream, &iih.tlvs, &error_log)) {
zlog_warn("isis_unpack_tlvs() failed: %s", error_log);
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(circuit, "Failed to unpack TLVs",
raw_pdu);
@@ -685,6 +692,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
if (!iih.tlvs->protocols_supported.count) {
zlog_warn("No supported protocols TLV in %s", pdu_name);
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "No supported protocols TLV", raw_pdu);
@@ -702,11 +710,14 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
/* send northbound notification */
stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start,
pdu_end - pdu_start);
- if (auth_code == ISIS_AUTH_FAILURE)
+ if (auth_code == ISIS_AUTH_FAILURE) {
+ circuit->auth_failures++;
isis_notif_authentication_failure(circuit, raw_pdu);
- else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
+ } else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
+ circuit->auth_type_failures++;
isis_notif_authentication_type_failure(circuit,
raw_pdu);
+ }
#endif /* ifndef FABRICD */
goto out;
}
@@ -715,6 +726,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
zlog_warn(
"ISIS-Adj (%s): Received IIH with own sysid - discard",
circuit->area->area_tag);
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "Received IIH with our own sysid", raw_pdu);
@@ -752,6 +764,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
"ISIS-Adj (%s): Neither IPv4 nor IPv6 considered usable. Ignoring IIH",
circuit->area->area_tag);
}
+ circuit->rej_adjacencies++;
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "Neither IPv4 not IPv6 considered usable",
@@ -940,11 +953,14 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
hdr.lsp_id);
#ifndef FABRICD
/* send northbound notification */
- if (auth_code == ISIS_AUTH_FAILURE)
+ if (auth_code == ISIS_AUTH_FAILURE) {
+ circuit->auth_failures++;
isis_notif_authentication_failure(circuit, raw_pdu);
- else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
+ } else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
+ circuit->auth_type_failures++;
isis_notif_authentication_type_failure(circuit,
raw_pdu);
+ }
#endif /* ifndef FABRICD */
goto out;
}
@@ -1373,12 +1389,15 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
/* send northbound notification */
stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start,
pdu_end - pdu_start);
- if (auth_code == ISIS_AUTH_FAILURE)
+ if (auth_code == ISIS_AUTH_FAILURE) {
+ circuit->auth_failures++;
isis_notif_authentication_failure(circuit,
raw_pdu);
- else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
+ } else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
+ circuit->auth_type_failures++;
isis_notif_authentication_type_failure(circuit,
raw_pdu);
+ }
#endif /* ifndef FABRICD */
goto out;
}
@@ -1614,6 +1633,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
"IDFieldLengthMismatch: ID Length field in a received PDU %" PRIu8
", while the parameter for this IS is %u",
id_len, ISIS_SYS_ID_LEN);
+ circuit->id_len_mismatches++;
#ifndef FABRICD
/* send northbound notification */
isis_notif_id_len_mismatch(circuit, id_len, raw_pdu);
@@ -1666,6 +1686,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
"maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %" PRIu8
" while the parameter for this IS is %u",
max_area_addrs, isis->max_area_addrs);
+ circuit->max_area_addr_mismatches++;
#ifndef FABRICD
/* send northbound notification */
isis_notif_max_area_addr_mismatch(circuit, max_area_addrs,
diff --git a/isisd/isis_te.c b/isisd/isis_te.c
index 44fa45d02b..9871d2bcb9 100644
--- a/isisd/isis_te.c
+++ b/isisd/isis_te.c
@@ -81,8 +81,7 @@ void isis_link_params_update(struct isis_circuit *circuit,
return;
/* Sanity Check */
- if ((circuit == NULL) || (ifp == NULL)
- || (circuit->state != C_STATE_UP))
+ if ((ifp == NULL) || (circuit->state != C_STATE_UP))
return;
zlog_debug("TE(%s): Update circuit parameters for interface %s",
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 67f557ab50..029a9e0688 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -75,12 +75,13 @@ int clear_isis_neighbor_common(struct vty *, const char *id);
int isis_config_write(struct vty *);
-void isis_new(unsigned long process_id)
+void isis_new(unsigned long process_id, vrf_id_t vrf_id)
{
isis = XCALLOC(MTYPE_ISIS, sizeof(struct isis));
/*
* Default values
*/
+ isis->vrf_id = vrf_id;
isis->max_area_addrs = 3;
isis->process_id = process_id;
isis->router_id = 0;
diff --git a/isisd/isisd.h b/isisd/isisd.h
index 308f018c19..f825b6ecb4 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -62,6 +62,7 @@ extern struct zebra_privs_t isisd_privs;
struct fabricd;
struct isis {
+ vrf_id_t vrf_id;
unsigned long process_id;
int sysid_set;
uint8_t sysid[ISIS_SYS_ID_LEN]; /* SystemID for this IS */
@@ -189,7 +190,7 @@ struct isis_area {
DECLARE_QOBJ_TYPE(isis_area)
void isis_init(void);
-void isis_new(unsigned long);
+void isis_new(unsigned long process_id, vrf_id_t vrf_id);
struct isis_area *isis_area_create(const char *);
struct isis_area *isis_area_lookup(const char *);
int isis_area_get(struct vty *vty, const char *area_tag);
diff --git a/lib/if.c b/lib/if.c
index 87d0ea968b..f2b45512da 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -1231,7 +1231,7 @@ void if_link_params_free(struct interface *ifp)
*/
DEFPY_NOSH (interface,
interface_cmd,
- "interface IFNAME [vrf NAME$vrfname]",
+ "interface IFNAME [vrf NAME$vrf_name]",
"Select an interface to configure\n"
"Interface's name\n"
VRF_CMD_HELP_STR)
@@ -1241,8 +1241,8 @@ DEFPY_NOSH (interface,
struct interface *ifp;
int ret;
- if (!vrfname)
- vrfname = VRF_DEFAULT_NAME;
+ if (!vrf_name)
+ vrf_name = VRF_DEFAULT_NAME;
/*
* This command requires special handling to maintain backward
@@ -1251,7 +1251,7 @@ DEFPY_NOSH (interface,
* interface is found, then a new one should be created on the default
* VRF.
*/
- VRF_GET_ID(vrf_id, vrfname, false);
+ VRF_GET_ID(vrf_id, vrf_name, false);
ifp = if_lookup_by_name_all_vrf(ifname);
if (ifp && ifp->vrf_id != vrf_id) {
struct vrf *vrf;
@@ -1262,24 +1262,24 @@ DEFPY_NOSH (interface,
*/
if (vrf_id != VRF_DEFAULT) {
vty_out(vty, "%% interface %s not in %s vrf\n", ifname,
- vrfname);
+ vrf_name);
return CMD_WARNING_CONFIG_FAILED;
}
/*
* Special case 2: a VRF name was *not* specified, and the found
* interface is associated to a VRF other than the default one.
- * Update vrf_id and vrfname to account for that.
+ * Update vrf_id and vrf_name to account for that.
*/
vrf = vrf_lookup_by_id(ifp->vrf_id);
assert(vrf);
vrf_id = ifp->vrf_id;
- vrfname = vrf->name;
+ vrf_name = vrf->name;
}
snprintf(xpath_list, sizeof(xpath_list),
"/frr-interface:lib/interface[name='%s'][vrf='%s']", ifname,
- vrfname);
+ vrf_name);
nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
ret = nb_cli_apply_changes(vty, xpath_list);
@@ -1302,20 +1302,20 @@ DEFPY_NOSH (interface,
DEFPY (no_interface,
no_interface_cmd,
- "no interface IFNAME [vrf NAME$vrfname]",
+ "no interface IFNAME [vrf NAME$vrf_name]",
NO_STR
"Delete a pseudo interface's configuration\n"
"Interface's name\n"
VRF_CMD_HELP_STR)
{
- if (!vrfname)
- vrfname = VRF_DEFAULT_NAME;
+ if (!vrf_name)
+ vrf_name = VRF_DEFAULT_NAME;
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(
vty, "/frr-interface:lib/interface[name='%s'][vrf='%s']",
- ifname, vrfname);
+ ifname, vrf_name);
}
static void cli_show_interface(struct vty *vty, struct lyd_node *dnode,
diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c
index abe2096cec..9564321d38 100644
--- a/lib/nexthop_group.c
+++ b/lib/nexthop_group.c
@@ -475,7 +475,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
<A.B.C.D|X:X::X:X>$addr [INTERFACE$intf]\
|INTERFACE$intf\
>\
- [nexthop-vrf NAME$name]",
+ [nexthop-vrf NAME$vrf_name]",
NO_STR
"Specify one of the nexthops in this ECMP group\n"
"v4 Address\n"
@@ -490,7 +490,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
struct nexthop *nh;
bool legal;
- legal = nexthop_group_parse_nexthop(&nhop, addr, intf, name);
+ legal = nexthop_group_parse_nexthop(&nhop, addr, intf, vrf_name);
if (nhop.type == NEXTHOP_TYPE_IPV6
&& IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6)) {
@@ -502,7 +502,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
nh = nexthop_exists(&nhgc->nhg, &nhop);
if (no) {
- nexthop_group_unsave_nhop(nhgc, name, addr, intf);
+ nexthop_group_unsave_nhop(nhgc, vrf_name, addr, intf);
if (nh) {
_nexthop_del(&nhgc->nhg, nh);
@@ -520,7 +520,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd,
_nexthop_add(&nhgc->nhg.nexthop, nh);
}
- nexthop_group_save_nhop(nhgc, name, addr, intf);
+ nexthop_group_save_nhop(nhgc, vrf_name, addr, intf);
if (legal && nhg_hooks.add_nexthop)
nhg_hooks.add_nexthop(nhgc, nh);
diff --git a/lib/vrf.c b/lib/vrf.c
index 4c6df797ad..2411cc3111 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -472,6 +472,14 @@ static const struct cmd_variable_handler vrf_var_handlers[] = {
.varname = "vrf",
.completions = vrf_autocomplete,
},
+ {
+ .varname = "vrf_name",
+ .completions = vrf_autocomplete,
+ },
+ {
+ .varname = "nexthop_vrf",
+ .completions = vrf_autocomplete,
+ },
{.completions = NULL},
};
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index e62efc5a0d..a56ba0a694 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -356,8 +356,6 @@ void ospf6_interface_state_update(struct interface *ifp)
oi = (struct ospf6_interface *)ifp->info;
if (oi == NULL)
return;
- if (oi->area == NULL)
- return;
if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
return;
@@ -684,6 +682,9 @@ int interface_up(struct thread *thread)
oi = (struct ospf6_interface *)THREAD_ARG(thread);
assert(oi && oi->interface);
+ if (!oi->type_cfg)
+ oi->type = ospf6_default_iftype(oi->interface);
+
/*
* Remove old pointer. If this thread wasn't a timer this
* operation won't make a difference, because it is already NULL.
@@ -775,8 +776,7 @@ int interface_up(struct thread *thread)
}
/* decide next interface state */
- if ((if_is_pointopoint(oi->interface))
- || (oi->type == OSPF_IFTYPE_POINTOPOINT)) {
+ if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT, oi);
} else if (oi->priority == 0)
ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER, oi);
@@ -881,6 +881,19 @@ int interface_down(struct thread *thread)
}
+static const char *ospf6_iftype_str(uint8_t iftype)
+{
+ switch (iftype) {
+ case OSPF_IFTYPE_LOOPBACK:
+ return "LOOPBACK";
+ case OSPF_IFTYPE_BROADCAST:
+ return "BROADCAST";
+ case OSPF_IFTYPE_POINTOPOINT:
+ return "POINTOPOINT";
+ }
+ return "UNKNOWN";
+}
+
/* show specified interface structure */
static int ospf6_interface_show(struct vty *vty, struct interface *ifp)
{
@@ -889,23 +902,16 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp)
struct prefix *p;
struct listnode *i;
char strbuf[PREFIX2STR_BUFFER], drouter[32], bdrouter[32];
- const char *type;
+ uint8_t default_iftype;
struct timeval res, now;
char duration[32];
struct ospf6_lsa *lsa;
- /* check physical interface type */
- if (if_is_loopback(ifp))
- type = "LOOPBACK";
- else if (if_is_broadcast(ifp))
- type = "BROADCAST";
- else if (if_is_pointopoint(ifp))
- type = "POINTOPOINT";
- else
- type = "UNKNOWN";
+ default_iftype = ospf6_default_iftype(ifp);
vty_out(vty, "%s is %s, type %s\n", ifp->name,
- (if_is_operative(ifp) ? "up" : "down"), type);
+ (if_is_operative(ifp) ? "up" : "down"),
+ ospf6_iftype_str(default_iftype));
vty_out(vty, " Interface ID: %d\n", ifp->ifindex);
if (ifp->info == NULL) {
@@ -914,6 +920,10 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp)
} else
oi = (struct ospf6_interface *)ifp->info;
+ if (if_is_operative(ifp) && oi->type != default_iftype)
+ vty_out(vty, " Operating as type %s\n",
+ ospf6_iftype_str(oi->type));
+
vty_out(vty, " Internet Address:\n");
for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) {
@@ -1810,6 +1820,8 @@ DEFUN (ipv6_ospf6_network,
}
assert(oi);
+ oi->type_cfg = true;
+
if (strncmp(argv[idx_network]->arg, "b", 1) == 0) {
if (oi->type == OSPF_IFTYPE_BROADCAST)
return CMD_SUCCESS;
@@ -1850,6 +1862,8 @@ DEFUN (no_ipv6_ospf6_network,
return CMD_SUCCESS;
}
+ oi->type_cfg = false;
+
type = ospf6_default_iftype(ifp);
if (oi->type == type) {
return CMD_SUCCESS;
@@ -1917,13 +1931,10 @@ static int config_write_ospf6_interface(struct vty *vty)
if (oi->mtu_ignore)
vty_out(vty, " ipv6 ospf6 mtu-ignore\n");
- if (oi->type != ospf6_default_iftype(ifp)) {
- if (oi->type == OSPF_IFTYPE_POINTOPOINT)
- vty_out(vty,
- " ipv6 ospf6 network point-to-point\n");
- else if (oi->type == OSPF_IFTYPE_BROADCAST)
- vty_out(vty, " ipv6 ospf6 network broadcast\n");
- }
+ if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOPOINT)
+ vty_out(vty, " ipv6 ospf6 network point-to-point\n");
+ else if (oi->type_cfg && oi->type == OSPF_IFTYPE_BROADCAST)
+ vty_out(vty, " ipv6 ospf6 network broadcast\n");
ospf6_bfd_write_config(vty, oi);
diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h
index e0c39a29b4..53a8910f4d 100644
--- a/ospf6d/ospf6_interface.h
+++ b/ospf6d/ospf6_interface.h
@@ -55,6 +55,7 @@ struct ospf6_interface {
/* Network Type */
uint8_t type;
+ bool type_cfg;
/* Router Priority */
uint8_t priority;
diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c
index b551dbdfa6..0a9f1c6f7c 100644
--- a/ospf6d/ospf6_lsdb.c
+++ b/ospf6d/ospf6_lsdb.c
@@ -298,13 +298,17 @@ struct ospf6_lsa *ospf6_lsdb_next(const struct route_node *iterend,
void ospf6_lsdb_remove_all(struct ospf6_lsdb *lsdb)
{
- struct ospf6_lsa *lsa;
+ struct ospf6_lsa *lsa, *lsa_next;
+ const struct route_node *iterend;
if (lsdb == NULL)
return;
- for (ALL_LSDB(lsdb, lsa))
+ for (iterend = ospf6_lsdb_head(lsdb, 0, 0, 0, &lsa); lsa;
+ lsa = lsa_next) {
+ lsa_next = ospf6_lsdb_next(iterend, lsa);
ospf6_lsdb_remove(lsa, lsdb);
+ }
}
void ospf6_lsdb_lsa_unlock(struct ospf6_lsa *lsa)
@@ -319,9 +323,12 @@ void ospf6_lsdb_lsa_unlock(struct ospf6_lsa *lsa)
int ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb)
{
int reschedule = 0;
- struct ospf6_lsa *lsa;
+ struct ospf6_lsa *lsa, *lsa_next;
+ const struct route_node *iterend;
- for (ALL_LSDB(lsdb, lsa)) {
+ for (iterend = ospf6_lsdb_head(lsdb, 0, 0, 0, &lsa); lsa;
+ lsa = lsa_next) {
+ lsa_next = ospf6_lsdb_next(iterend, lsa);
if (!OSPF6_LSA_IS_MAXAGE(lsa))
continue;
if (lsa->retrans_count != 0) {
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index 4acb5e3b2e..da42a24252 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -1866,7 +1866,8 @@ int ospf6_dbdesc_send(struct thread *thread)
int ospf6_dbdesc_send_newone(struct thread *thread)
{
struct ospf6_neighbor *on;
- struct ospf6_lsa *lsa;
+ struct ospf6_lsa *lsa, *lsa_next;
+ const struct route_node *iterend;
unsigned int size = 0;
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
@@ -1876,7 +1877,10 @@ int ospf6_dbdesc_send_newone(struct thread *thread)
structure)
so that ospf6_send_dbdesc () can send those LSAs */
size = sizeof(struct ospf6_lsa_header) + sizeof(struct ospf6_dbdesc);
- for (ALL_LSDB(on->summary_list, lsa)) {
+
+ for (iterend = ospf6_lsdb_head(on->summary_list, 0, 0, 0, &lsa); lsa;
+ lsa = lsa_next) {
+ lsa_next = ospf6_lsdb_next(iterend, lsa);
if (size + sizeof(struct ospf6_lsa_header)
> ospf6_packet_max(on->ospf6_if)) {
ospf6_lsdb_lsa_unlock(lsa);
@@ -2019,7 +2023,8 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread)
struct ospf6_lsupdate *lsupdate;
uint8_t *p;
int lsa_cnt;
- struct ospf6_lsa *lsa;
+ struct ospf6_lsa *lsa, *lsa_next;
+ const struct route_node *iterend;
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
on->thread_send_lsupdate = (struct thread *)NULL;
@@ -2044,7 +2049,9 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread)
/* lsupdate_list lists those LSA which doesn't need to be
retransmitted. remove those from the list */
- for (ALL_LSDB(on->lsupdate_list, lsa)) {
+ for (iterend = ospf6_lsdb_head(on->lsupdate_list, 0, 0, 0, &lsa); lsa;
+ lsa = lsa_next) {
+ lsa_next = ospf6_lsdb_next(iterend, lsa);
/* MTU check */
if ((p - sendbuf + (unsigned int)OSPF6_LSA_SIZE(lsa->header))
> ospf6_packet_max(on->ospf6_if)) {
@@ -2074,7 +2081,7 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread)
p += OSPF6_LSA_SIZE(lsa->header);
lsa_cnt++;
- assert(lsa->lock == 2);
+ assert(lsa->lock == 1);
ospf6_lsdb_remove(lsa, on->lsupdate_list);
}
@@ -2202,7 +2209,8 @@ int ospf6_lsupdate_send_interface(struct thread *thread)
struct ospf6_lsupdate *lsupdate;
uint8_t *p;
int lsa_cnt;
- struct ospf6_lsa *lsa;
+ struct ospf6_lsa *lsa, *lsa_next;
+ const struct route_node *iterend;
oi = (struct ospf6_interface *)THREAD_ARG(thread);
oi->thread_send_lsupdate = (struct thread *)NULL;
@@ -2228,7 +2236,9 @@ int ospf6_lsupdate_send_interface(struct thread *thread)
p = (uint8_t *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
lsa_cnt = 0;
- for (ALL_LSDB(oi->lsupdate_list, lsa)) {
+ for (iterend = ospf6_lsdb_head(oi->lsupdate_list, 0, 0, 0, &lsa); lsa;
+ lsa = lsa_next) {
+ lsa_next = ospf6_lsdb_next(iterend, lsa);
/* MTU check */
if ((p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE(lsa->header)))
> ospf6_packet_max(oi)) {
@@ -2263,7 +2273,7 @@ int ospf6_lsupdate_send_interface(struct thread *thread)
p += OSPF6_LSA_SIZE(lsa->header);
lsa_cnt++;
- assert(lsa->lock == 2);
+ assert(lsa->lock == 1);
ospf6_lsdb_remove(lsa, oi->lsupdate_list);
}
@@ -2289,7 +2299,8 @@ int ospf6_lsack_send_neighbor(struct thread *thread)
struct ospf6_neighbor *on;
struct ospf6_header *oh;
uint8_t *p;
- struct ospf6_lsa *lsa;
+ struct ospf6_lsa *lsa, *lsa_next;
+ const struct route_node *iterend;
int lsa_cnt = 0;
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
@@ -2312,7 +2323,9 @@ int ospf6_lsack_send_neighbor(struct thread *thread)
p = (uint8_t *)((caddr_t)oh + sizeof(struct ospf6_header));
- for (ALL_LSDB(on->lsack_list, lsa)) {
+ for (iterend = ospf6_lsdb_head(on->lsack_list, 0, 0, 0, &lsa); lsa;
+ lsa = lsa_next) {
+ lsa_next = ospf6_lsdb_next(iterend, lsa);
/* MTU check */
if (p - sendbuf + sizeof(struct ospf6_lsa_header)
> ospf6_packet_max(on->ospf6_if)) {
@@ -2340,7 +2353,7 @@ int ospf6_lsack_send_neighbor(struct thread *thread)
memcpy(p, lsa->header, sizeof(struct ospf6_lsa_header));
p += sizeof(struct ospf6_lsa_header);
- assert(lsa->lock == 2);
+ assert(lsa->lock == 1);
ospf6_lsdb_remove(lsa, on->lsack_list);
lsa_cnt++;
}
@@ -2367,7 +2380,8 @@ int ospf6_lsack_send_interface(struct thread *thread)
struct ospf6_interface *oi;
struct ospf6_header *oh;
uint8_t *p;
- struct ospf6_lsa *lsa;
+ struct ospf6_lsa *lsa, *lsa_next;
+ const struct route_node *iterend;
int lsa_cnt = 0;
oi = (struct ospf6_interface *)THREAD_ARG(thread);
@@ -2391,7 +2405,9 @@ int ospf6_lsack_send_interface(struct thread *thread)
p = (uint8_t *)((caddr_t)oh + sizeof(struct ospf6_header));
- for (ALL_LSDB(oi->lsack_list, lsa)) {
+ for (iterend = ospf6_lsdb_head(oi->lsack_list, 0, 0, 0, &lsa); lsa;
+ lsa = lsa_next) {
+ lsa_next = ospf6_lsdb_next(iterend, lsa);
/* MTU check */
if (p - sendbuf + sizeof(struct ospf6_lsa_header)
> ospf6_packet_max(oi)) {
@@ -2409,7 +2425,7 @@ int ospf6_lsack_send_interface(struct thread *thread)
memcpy(p, lsa->header, sizeof(struct ospf6_lsa_header));
p += sizeof(struct ospf6_lsa_header);
- assert(lsa->lock == 2);
+ assert(lsa->lock == 1);
ospf6_lsdb_remove(lsa, oi->lsack_list);
lsa_cnt++;
}
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index 46dc621ae7..4318db5225 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -112,11 +112,15 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id,
void ospf6_neighbor_delete(struct ospf6_neighbor *on)
{
- struct ospf6_lsa *lsa;
+ struct ospf6_lsa *lsa, *lsa_next;
+ const struct route_node *iterend;
ospf6_lsdb_remove_all(on->summary_list);
ospf6_lsdb_remove_all(on->request_list);
- for (ALL_LSDB(on->retrans_list, lsa)) {
+
+ for (iterend = ospf6_lsdb_head(on->retrans_list, 0, 0, 0, &lsa); lsa;
+ lsa = lsa_next) {
+ lsa_next = ospf6_lsdb_next(iterend, lsa);
ospf6_decrement_retrans_count(lsa);
ospf6_lsdb_remove(lsa, on->retrans_list);
}
@@ -287,7 +291,8 @@ int twoway_received(struct thread *thread)
int negotiation_done(struct thread *thread)
{
struct ospf6_neighbor *on;
- struct ospf6_lsa *lsa;
+ struct ospf6_lsa *lsa, *lsa_next;
+ const struct route_node *iterend;
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
assert(on);
@@ -301,7 +306,10 @@ int negotiation_done(struct thread *thread)
/* clear ls-list */
ospf6_lsdb_remove_all(on->summary_list);
ospf6_lsdb_remove_all(on->request_list);
- for (ALL_LSDB(on->retrans_list, lsa)) {
+
+ for (iterend = ospf6_lsdb_head(on->retrans_list, 0, 0, 0, &lsa); lsa;
+ lsa = lsa_next) {
+ lsa_next = ospf6_lsdb_next(iterend, lsa);
ospf6_decrement_retrans_count(lsa);
ospf6_lsdb_remove(lsa, on->retrans_list);
}
@@ -495,7 +503,8 @@ int seqnumber_mismatch(struct thread *thread)
int bad_lsreq(struct thread *thread)
{
struct ospf6_neighbor *on;
- struct ospf6_lsa *lsa;
+ struct ospf6_lsa *lsa, *lsa_next;
+ const struct route_node *iterend;
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
assert(on);
@@ -514,7 +523,10 @@ int bad_lsreq(struct thread *thread)
ospf6_lsdb_remove_all(on->summary_list);
ospf6_lsdb_remove_all(on->request_list);
- for (ALL_LSDB(on->retrans_list, lsa)) {
+
+ for (iterend = ospf6_lsdb_head(on->retrans_list, 0, 0, 0, &lsa); lsa;
+ lsa = lsa_next) {
+ lsa_next = ospf6_lsdb_next(iterend, lsa);
ospf6_decrement_retrans_count(lsa);
ospf6_lsdb_remove(lsa, on->retrans_list);
}
@@ -532,7 +544,8 @@ int bad_lsreq(struct thread *thread)
int oneway_received(struct thread *thread)
{
struct ospf6_neighbor *on;
- struct ospf6_lsa *lsa;
+ struct ospf6_lsa *lsa, *lsa_next;
+ const struct route_node *iterend;
on = (struct ospf6_neighbor *)THREAD_ARG(thread);
assert(on);
@@ -549,7 +562,9 @@ int oneway_received(struct thread *thread)
ospf6_lsdb_remove_all(on->summary_list);
ospf6_lsdb_remove_all(on->request_list);
- for (ALL_LSDB(on->retrans_list, lsa)) {
+ for (iterend = ospf6_lsdb_head(on->retrans_list, 0, 0, 0, &lsa); lsa;
+ lsa = lsa_next) {
+ lsa_next = ospf6_lsdb_next(iterend, lsa);
ospf6_decrement_retrans_count(lsa);
ospf6_lsdb_remove(lsa, on->retrans_list);
}
@@ -618,7 +633,7 @@ static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on)
snprintf(deadtime, sizeof(deadtime), "%02ld:%02ld:%02ld", h, m, s);
/* Neighbor State */
- if (if_is_pointopoint(on->ospf6_if->interface))
+ if (on->ospf6_if->type == OSPF_IFTYPE_POINTOPOINT)
snprintf(nstate, sizeof(nstate), "PointToPoint");
else {
if (on->router_id == on->drouter)
diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c
index fc7c6177d7..1ba89f3bd6 100644
--- a/ospf6d/ospf6_snmp.c
+++ b/ospf6d/ospf6_snmp.c
@@ -1130,9 +1130,9 @@ static uint8_t *ospfv3IfEntry(struct variable *v, oid *name, size_t *length,
return SNMP_INTEGER(ntohl(oi->area->area_id));
break;
case OSPFv3IFTYPE:
- if (if_is_broadcast(oi->interface))
+ if (oi->type == OSPF_IFTYPE_BROADCAST)
return SNMP_INTEGER(1);
- else if (if_is_pointopoint(oi->interface))
+ else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
return SNMP_INTEGER(3);
else
break; /* Unknown, don't put anything */
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index 40c6123810..95dafff84e 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -136,7 +136,7 @@ static void ospf6_top_brouter_hook_remove(struct ospf6_route *route)
ospf6_abr_originate_summary(route);
}
-static struct ospf6 *ospf6_create(void)
+static struct ospf6 *ospf6_create(vrf_id_t vrf_id)
{
struct ospf6 *o;
@@ -144,6 +144,7 @@ static struct ospf6 *ospf6_create(void)
/* initialize */
monotime(&o->starttime);
+ o->vrf_id = vrf_id;
o->area_list = list_new();
o->area_list->cmp = ospf6_area_cmp;
o->lsdb = ospf6_lsdb_create(o);
@@ -325,7 +326,7 @@ DEFUN_NOSH (router_ospf6,
OSPF6_STR)
{
if (ospf6 == NULL) {
- ospf6 = ospf6_create();
+ ospf6 = ospf6_create(VRF_DEFAULT);
if (ospf6->router_id == 0)
ospf6_router_id_update();
}
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index 381027dcff..ba41fca65b 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -31,6 +31,9 @@ struct ospf6_master {
/* OSPFv3 top level data structure */
struct ospf6 {
+ /* The relevant vrf_id */
+ vrf_id_t vrf_id;
+
/* my router id */
uint32_t router_id;
diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c
index 359f869c42..ae04402f49 100644
--- a/pbrd/pbr_nht.c
+++ b/pbrd/pbr_nht.c
@@ -711,7 +711,7 @@ pbr_nht_individual_nexthop_gw_update(struct pbr_nexthop_cache *pnhc,
}
if (pnhc->nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
- || pnhc->nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
+ || pnhc->nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
/* GATEWAY_IFINDEX type shouldn't resolve to group */
if (pnhi->nhr->nexthop_num > 1) {
diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c
index 5e7addc9d2..a6e764bbb0 100644
--- a/pbrd/pbr_vty.c
+++ b/pbrd/pbr_vty.c
@@ -254,7 +254,7 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
<A.B.C.D|X:X::X:X>$addr [INTERFACE$intf]\
|INTERFACE$intf\
>\
- [nexthop-vrf NAME$name]",
+ [nexthop-vrf NAME$vrf_name]",
NO_STR
"Set for the PBR-MAP\n"
"Specify one of the nexthops in this map\n"
@@ -276,13 +276,13 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
return CMD_WARNING_CONFIG_FAILED;
}
- if (name)
- vrf = vrf_lookup_by_name(name);
+ if (vrf_name)
+ vrf = vrf_lookup_by_name(vrf_name);
else
vrf = vrf_lookup_by_id(VRF_DEFAULT);
if (!vrf) {
- vty_out(vty, "Specified: %s is non-existent\n", name);
+ vty_out(vty, "Specified: %s is non-existent\n", vrf_name);
return CMD_WARNING_CONFIG_FAILED;
}
diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c
index 12b28ed9af..cd2d306f3d 100644
--- a/pimd/pim_pim.c
+++ b/pimd/pim_pim.c
@@ -574,6 +574,7 @@ int pim_msg_send(int fd, struct in_addr src, struct in_addr dst,
ip->ip_id = htons(++ip_id);
ip->ip_hl = 5;
ip->ip_v = 4;
+ ip->ip_tos = IPTOS_PREC_INTERNETCONTROL;
ip->ip_p = PIM_IP_PROTO_PIM;
ip->ip_src = src;
ip->ip_dst = dst;
diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c
index 82255cd3b0..7f03e18389 100644
--- a/pimd/pim_sock.c
+++ b/pimd/pim_sock.c
@@ -255,6 +255,12 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp,
}
}
+ /* Set Tx socket DSCP byte */
+ if (setsockopt_ipv4_tos(fd, IPTOS_PREC_INTERNETCONTROL)) {
+ zlog_warn("can't set sockopt IP_TOS to PIM/IGMP socket %d: %s",
+ fd, safe_strerror(errno));
+ }
+
return fd;
}
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index db0aedad6a..dadcbbe65d 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -964,12 +964,6 @@ void pim_forward_start(struct pim_ifchannel *ch)
{
struct pim_upstream *up = ch->upstream;
uint32_t mask = PIM_OIF_FLAG_PROTO_PIM;
- int input_iface_vif_index = 0;
- struct pim_instance *pim;
- struct pim_interface *pim_ifp;
-
- pim_ifp = ch->interface->info;
- pim = pim_ifp->pim;
if (PIM_DEBUG_PIM_TRACE) {
char source_str[INET_ADDRSTRLEN];
@@ -987,55 +981,6 @@ void pim_forward_start(struct pim_ifchannel *ch)
inet_ntoa(up->upstream_addr));
}
- /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
- as part of mroute_del called by pim_forward_stop.
- */
- if ((up->upstream_addr.s_addr != INADDR_ANY) && (!up->channel_oil)) {
- struct prefix src, grp;
-
- grp.family = AF_INET;
- grp.prefixlen = IPV4_MAX_BITLEN;
- grp.u.prefix4 = up->sg.grp;
- src.family = AF_INET;
- src.prefixlen = IPV4_MAX_BITLEN;
- src.u.prefix4 = up->sg.src;
-
- if (pim_ecmp_nexthop_lookup(pim, &up->rpf.source_nexthop, &src,
- &grp, 0))
- input_iface_vif_index = pim_if_find_vifindex_by_ifindex(
- pim, up->rpf.source_nexthop.interface->ifindex);
-
- if (input_iface_vif_index < 1) {
- if (PIM_DEBUG_PIM_TRACE) {
- char source_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<source?>", up->sg.src,
- source_str, sizeof(source_str));
- zlog_debug(
- "%s %s: could not find input interface for source %s",
- __FILE__, __PRETTY_FUNCTION__,
- source_str);
- }
- pim_channel_oil_change_iif(pim, up->channel_oil,
- MAXVIFS,
- __PRETTY_FUNCTION__);
- }
-
- else
- pim_channel_oil_change_iif(pim, up->channel_oil,
- input_iface_vif_index,
- __PRETTY_FUNCTION__);
-
- if (PIM_DEBUG_TRACE) {
- struct interface *in_intf = pim_if_find_by_vif_index(
- pim, input_iface_vif_index);
- zlog_debug(
- "%s: Update channel_oil IIF %s VIFI %d entry %s ",
- __PRETTY_FUNCTION__,
- in_intf ? in_intf->name : "Unknown",
- input_iface_vif_index, up->sg_str);
- }
- }
-
if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
mask = PIM_OIF_FLAG_PROTO_IGMP;
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 60cfb2e486..486ccf6bfe 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -39,7 +39,7 @@
#endif
DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
- "sharp watch [vrf NAME$name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop> [connected$connected]",
+ "sharp watch [vrf NAME$vrf_name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop> [connected$connected]",
"Sharp routing Protocol\n"
"Watch for changes\n"
"The vrf we would like to watch if non-default\n"
@@ -54,12 +54,12 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
struct prefix p;
bool type_import;
- if (!name)
- name = VRF_DEFAULT_NAME;
- vrf = vrf_lookup_by_name(name);
+ if (!vrf_name)
+ vrf_name = VRF_DEFAULT_NAME;
+ vrf = vrf_lookup_by_name(vrf_name);
if (!vrf) {
vty_out(vty, "The vrf NAME specified: %s does not exist\n",
- name);
+ vrf_name);
return CMD_WARNING;
}
@@ -83,7 +83,7 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
}
DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
- "sharp watch [vrf NAME$name] <nexthop$n A.B.C.D$nhop|import$import A.B.C.D/M$inhop> [connected$connected]",
+ "sharp watch [vrf NAME$vrf_name] <nexthop$n A.B.C.D$nhop|import$import A.B.C.D/M$inhop> [connected$connected]",
"Sharp routing Protocol\n"
"Watch for changes\n"
"The vrf we would like to watch if non-default\n"
@@ -98,12 +98,12 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
struct prefix p;
bool type_import;
- if (!name)
- name = VRF_DEFAULT_NAME;
- vrf = vrf_lookup_by_name(name);
+ if (!vrf_name)
+ vrf_name = VRF_DEFAULT_NAME;
+ vrf = vrf_lookup_by_name(vrf_name);
if (!vrf) {
vty_out(vty, "The vrf NAME specified: %s does not exist\n",
- name);
+ vrf_name);
return CMD_WARNING;
}
@@ -162,7 +162,7 @@ DEFPY (install_routes_data_dump,
DEFPY (install_routes,
install_routes_cmd,
- "sharp install routes [vrf NAME$name] <A.B.C.D$start4|X:X::X:X$start6> <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NHGNAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]",
+ "sharp install routes [vrf NAME$vrf_name] <A.B.C.D$start4|X:X::X:X$start6> <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NHGNAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]",
"Sharp routing Protocol\n"
"install some routes\n"
"Routes to install\n"
@@ -209,13 +209,13 @@ DEFPY (install_routes,
}
sg.r.orig_prefix = prefix;
- if (!name)
- name = VRF_DEFAULT_NAME;
+ if (!vrf_name)
+ vrf_name = VRF_DEFAULT_NAME;
- vrf = vrf_lookup_by_name(name);
+ vrf = vrf_lookup_by_name(vrf_name);
if (!vrf) {
vty_out(vty, "The vrf NAME specified: %s does not exist\n",
- name);
+ vrf_name);
return CMD_WARNING;
}
@@ -252,7 +252,7 @@ DEFPY (install_routes,
}
DEFPY(vrf_label, vrf_label_cmd,
- "sharp label <ip$ipv4|ipv6$ipv6> vrf NAME$name label (0-100000)$label",
+ "sharp label <ip$ipv4|ipv6$ipv6> vrf NAME$vrf_name label (0-100000)$label",
"Sharp Routing Protocol\n"
"Give a vrf a label\n"
"Pop and forward for IPv4\n"
@@ -264,10 +264,10 @@ DEFPY(vrf_label, vrf_label_cmd,
struct vrf *vrf;
afi_t afi = (ipv4) ? AFI_IP : AFI_IP6;
- if (strcmp(name, "default") == 0)
+ if (strcmp(vrf_name, "default") == 0)
vrf = vrf_lookup_by_id(VRF_DEFAULT);
else
- vrf = vrf_lookup_by_name(name);
+ vrf = vrf_lookup_by_name(vrf_name);
if (!vrf) {
vty_out(vty, "Unable to find vrf you silly head");
@@ -283,7 +283,7 @@ DEFPY(vrf_label, vrf_label_cmd,
DEFPY (remove_routes,
remove_routes_cmd,
- "sharp remove routes [vrf NAME$name] <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]",
+ "sharp remove routes [vrf NAME$vrf_name] <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]",
"Sharp Routing Protocol\n"
"Remove some routes\n"
"Routes to remove\n"
@@ -314,10 +314,10 @@ DEFPY (remove_routes,
prefix.u.prefix6 = start6;
}
- vrf = vrf_lookup_by_name(name ? name : VRF_DEFAULT_NAME);
+ vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
if (!vrf) {
vty_out(vty, "The vrf NAME specified: %s does not exist\n",
- name ? name : VRF_DEFAULT_NAME);
+ vrf_name ? vrf_name : VRF_DEFAULT_NAME);
return CMD_WARNING;
}
diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c
index 9dd25fbdd1..abb64aad3f 100644
--- a/staticd/static_vrf.c
+++ b/staticd/static_vrf.c
@@ -27,6 +27,7 @@
#include "static_memory.h"
#include "static_vrf.h"
#include "static_routes.h"
+#include "static_zebra.h"
#include "static_vty.h"
static void zebra_stable_node_cleanup(struct route_table *table,
@@ -76,6 +77,8 @@ static int static_vrf_new(struct vrf *vrf)
static int static_vrf_enable(struct vrf *vrf)
{
+ static_zebra_vrf_register(vrf);
+
static_fixup_vrf_ids(vrf->info);
/*
@@ -89,6 +92,7 @@ static int static_vrf_enable(struct vrf *vrf)
static int static_vrf_disable(struct vrf *vrf)
{
+ static_zebra_vrf_unregister(vrf);
return 0;
}
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index b364dd6290..976f892efb 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -484,3 +484,17 @@ void static_zebra_init(void)
static_nht_hash_cmp,
"Static Nexthop Tracking hash");
}
+
+void static_zebra_vrf_register(struct vrf *vrf)
+{
+ if (vrf->vrf_id == VRF_DEFAULT)
+ return;
+ zclient_send_reg_requests(zclient, vrf->vrf_id);
+}
+
+void static_zebra_vrf_unregister(struct vrf *vrf)
+{
+ if (vrf->vrf_id == VRF_DEFAULT)
+ return;
+ zclient_send_dereg_requests(zclient, vrf->vrf_id);
+}
diff --git a/staticd/static_zebra.h b/staticd/static_zebra.h
index 15f5410b81..962dc3908f 100644
--- a/staticd/static_zebra.h
+++ b/staticd/static_zebra.h
@@ -28,4 +28,7 @@ extern void static_zebra_route_add(struct route_node *rn,
struct static_route *si_changed,
vrf_id_t vrf_id, safi_t safi, bool install);
extern void static_zebra_init(void);
+extern void static_zebra_vrf_register(struct vrf *vrf);
+extern void static_zebra_vrf_unregister(struct vrf *vrf);
+
#endif
diff --git a/tests/topotests/bgp-route-map/bgp_route_map_topo1.json b/tests/topotests/bgp-route-map/bgp_route_map_topo1.json
new file mode 100644
index 0000000000..e89263961d
--- /dev/null
+++ b/tests/topotests/bgp-route-map/bgp_route_map_topo1.json
@@ -0,0 +1,187 @@
+{
+ "address_types": ["ipv4","ipv6"],
+ "ipv4base":"10.0.0.0",
+ "ipv4mask":30,
+ "ipv6base":"fd00::",
+ "ipv6mask":64,
+ "link_ip_start":{"ipv4":"10.0.0.0", "v4mask":30, "ipv6":"fd00::", "v6mask":64},
+ "lo_prefix":{"ipv4":"1.0.", "v4mask":32, "ipv6":"2001:DB8:F::", "v6mask":128},
+ "routers":{
+ "r1":{
+ "links":{
+ "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
+ "r2":{"ipv4":"auto", "ipv6":"auto"},
+ "r3":{"ipv4":"auto", "ipv6":"auto"}
+ },
+ "bgp":{
+ "local_as":"100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r1": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r1": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r2":{
+ "links":{
+ "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
+ "r1":{"ipv4":"auto", "ipv6":"auto"},
+ "r3":{"ipv4":"auto", "ipv6":"auto"}
+ },
+ "bgp":{
+ "local_as":"100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r2": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r2": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r3":{
+ "links":{
+ "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
+ "r1":{"ipv4":"auto", "ipv6":"auto"},
+ "r2":{"ipv4":"auto", "ipv6":"auto"},
+ "r4":{"ipv4":"auto", "ipv6":"auto"}
+ },
+ "bgp":{
+ "local_as":"100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r4":{
+ "links":{
+ "lo": {"ipv4": "auto", "ipv6": "auto", "type": "loopback"},
+ "r3":{"ipv4":"auto", "ipv6":"auto"}
+ },
+ "bgp":{
+ "local_as":"200",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/topotests/bgp-route-map/bgp_route_map_topo2.json b/tests/topotests/bgp-route-map/bgp_route_map_topo2.json
new file mode 100755
index 0000000000..c22a4c3ea7
--- /dev/null
+++ b/tests/topotests/bgp-route-map/bgp_route_map_topo2.json
@@ -0,0 +1,316 @@
+{
+ "address_types": ["ipv4", "ipv6"],
+ "ipv4base": "10.0.0.0",
+ "ipv4mask": 30,
+ "ipv6base": "fd00::",
+ "ipv6mask": 64,
+ "link_ip_start": {
+ "ipv4": "10.0.0.0",
+ "v4mask": 30,
+ "ipv6": "fd00::",
+ "v6mask": 64
+ },
+ "lo_prefix": {
+ "ipv4": "1.0.",
+ "v4mask": 32,
+ "ipv6": "2001:DB8:F::",
+ "v6mask": 128
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r2": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r1": {}
+ }
+ }
+ },
+ "redistribute": [{
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r1": {}
+ }
+ }
+ },
+ "redistribute": [{
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ }
+ }
+ },
+
+ "static_routes": [{
+ "network": "10.0.20.1/32",
+ "no_of_ip": 2,
+ "next_hop": "10.0.0.2"
+ },
+ {
+ "network": "1::1/128",
+ "no_of_ip": 2,
+ "next_hop": "fd00::2"
+ }]
+ },
+ "r2": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r1": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r2": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r2": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r3": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r1": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r2": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r4": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r5": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r4": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "200",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r5": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "300",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/topotests/bgp-route-map/test_route_map_topo1.py b/tests/topotests/bgp-route-map/test_route_map_topo1.py
new file mode 100755
index 0000000000..86ec6c82d2
--- /dev/null
+++ b/tests/topotests/bgp-route-map/test_route_map_topo1.py
@@ -0,0 +1,1361 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2019 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+#################################
+# TOPOLOGY
+#################################
+"""
+
+ +-------+
+ +------- | R2 |
+ | +-------+
+ | |
+ +-------+ |
+ | R1 | |
+ +-------+ |
+ | |
+ | +-------+ +-------+
+ +---------- | R3 |----------| R4 |
+ +-------+ +-------+
+
+"""
+
+#################################
+# TEST SUMMARY
+#################################
+"""
+Following tests are covered to test route-map functionality:
+TC_34:
+ Verify if route-maps is applied in both inbound and
+ outbound direction to same neighbor/interface.
+TC_36:
+ Test permit/deny statements operation in route-maps with a
+ permutation and combination of permit/deny in prefix-lists
+TC_35:
+ Test multiple sequence numbers in a single route-map for different
+ match/set clauses.
+TC_37:
+ Test add/remove route-maps with multiple set
+ clauses and without any match statement.(Set only)
+TC_38:
+ Test add/remove route-maps with multiple match
+ clauses and without any set statement.(Match only)
+"""
+
+import sys
+import json
+import time
+import pytest
+import inspect
+import os
+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, '../'))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, get_topogen
+from mininet.topo import Topo
+
+# Required to instantiate the topology builder class.
+from lib.topojson import *
+from lib.common_config import (
+ start_topology, write_test_header,
+ write_test_footer, verify_bgp_community,
+ verify_rib, delete_route_maps, create_bgp_community_lists,
+ interface_status, create_route_maps, create_prefix_lists,
+ verify_route_maps, check_address_types,
+ shutdown_bringup_interface, verify_prefix_lists, reset_config_on_routers)
+from lib.topolog import logger
+from lib.bgp import (
+ verify_bgp_convergence, create_router_bgp,
+ clear_bgp_and_verify, verify_bgp_attributes)
+from lib.topojson import build_topo_from_json, build_config_from_json
+
+
+# Global variables
+bgp_convergence = False
+BGP_CONVERGENCE = False
+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:
+ topo = json.load(topoJson)
+except IOError:
+ assert False, "Could not read file {}".format(jsonFile)
+
+# Global variables
+bgp_convergence = False
+NETWORK = {
+ "ipv4": ["11.0.20.1/32", "20.0.20.1/32"],
+ "ipv6": ["1::1/128", "2::1/128"]
+}
+MASK = {"ipv4": "32", "ipv6": "128"}
+NEXT_HOP = {
+ "ipv4": "10.0.0.2",
+ "ipv6": "fd00::2"
+}
+ADDR_TYPES = check_address_types()
+
+
+class CreateTopo(Topo):
+ """
+ Test topology builder
+
+
+ * `Topo`: Topology object
+ """
+
+ def build(self, *_args, **_opts):
+ """Build function"""
+ tgen = get_topogen(self)
+
+ # Building topology from json file
+ build_topo_from_json(tgen, topo)
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+ global ADDR_TYPES
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ tgen = Topogen(CreateTopo, mod.__name__)
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Checking BGP convergence
+ global bgp_convergence
+
+ # 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))
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module():
+ """
+ Teardown the pytest environment
+
+ * `mod`: module name
+ """
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info("Testsuite end time: {}".
+ format(time.asctime(time.localtime(time.time()))))
+ logger.info("=" * 40)
+
+
+def test_route_map_inbound_outbound_same_neighbor_p0(request):
+ """
+ TC_34:
+ Verify if route-maps is applied in both inbound and
+ outbound direction to same neighbor/interface.
+ """
+
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ for adt in ADDR_TYPES:
+
+ # Create Static routes
+ input_dict = {
+ "r1": {
+ "static_routes": [
+ {
+ "network": NETWORK[adt][0],
+ "no_of_ip": 9,
+ "next_hop": NEXT_HOP[adt],
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Api call to redistribute static routes
+ input_dict_1 = {
+ "r1": {
+ "bgp": {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ input_dict_2 = {
+ "r4": {
+ "static_routes": [
+ {
+ "network": NETWORK[adt][1],
+ "no_of_ip": 9,
+ "next_hop": NEXT_HOP[adt],
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Api call to redistribute static routes
+ input_dict_5 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_5)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ input_dict_2 = {
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "action": "permit",
+ "network": NETWORK["ipv4"][0]
+ }],
+ "pf_list_2_ipv4": [{
+ "seqid": 10,
+ "action": "permit",
+ "network": NETWORK["ipv4"][1]
+ }]
+ },
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "action": "permit",
+ "network": NETWORK["ipv6"][0]
+ }],
+ "pf_list_2_ipv6": [{
+ "seqid": 100,
+ "action": "permit",
+ "network": NETWORK["ipv6"][1]
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_6 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_tag_1_{}".format(addr_type): [{
+ "action": "deny",
+ "match": {
+ addr_type: {
+ "prefix_lists":
+ "pf_list_1_{}".format(addr_type)
+ }
+ }
+ }],
+ "rmap_match_tag_2_{}".format(addr_type): [{
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists":
+ "pf_list_2_{}".format(addr_type)
+ }
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_6)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_7 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [
+ {"name":
+ "rmap_match_tag_1_ipv4",
+ "direction": "in"},
+ {"name":
+ "rmap_match_tag_1_ipv4",
+ "direction": "out"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [
+ {"name":
+ "rmap_match_tag_1_ipv6",
+ "direction": "in"},
+ {"name":
+ "rmap_match_tag_1_ipv6",
+ "direction": "out"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_7)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ for adt in ADDR_TYPES:
+ # Verifying RIB routes
+ dut = "r3"
+ protocol = "bgp"
+ input_dict_2 = {
+ "r4": {
+ "static_routes": [
+ {
+ "network": [NETWORK[adt][1]],
+ "no_of_ip": 9,
+ "next_hop": NEXT_HOP[adt]
+ }
+ ]
+ }
+ }
+
+ result = verify_rib(tgen, adt, dut, input_dict_2, protocol=protocol)
+ assert result is not True, "Testcase {} : Failed \n"
+ "Expected behavior: routes are not present in rib \n"
+ "Error: {}".format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ dut = "r4"
+ input_dict = {
+ "r1": {
+ "static_routes": [
+ {
+ "network": [NETWORK[adt][0]],
+ "no_of_ip": 9,
+ "next_hop": NEXT_HOP[adt]
+ }
+ ]
+ }
+ }
+ result = verify_rib(tgen, adt, dut, input_dict, protocol=protocol)
+ assert result is not True, "Testcase {} : Failed \n "
+ "Expected behavior: routes are not present in rib \n "
+ "Error: {}".format(
+ tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+@pytest.mark.parametrize("prefix_action, rmap_action", [("permit", "permit"),
+ ("permit", "deny"), ("deny", "permit"),
+ ("deny", "deny")])
+def test_route_map_with_action_values_combination_of_prefix_action_p0(
+ request, prefix_action, rmap_action):
+ """
+ TC_36:
+ Test permit/deny statements operation in route-maps with a permutation and
+ combination of permit/deny in prefix-lists
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ for adt in ADDR_TYPES:
+ # Create Static routes
+ input_dict = {
+ "r1": {
+ "static_routes": [
+ {
+ "network": NETWORK[adt][0],
+ "no_of_ip": 9,
+ "next_hop": NEXT_HOP[adt]
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Api call to redistribute static routes
+ input_dict_1 = {
+ "r1": {
+ "bgp": {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Permit in perfix list and route-map
+ input_dict_2 = {
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "network": "any",
+ "action": prefix_action
+ }]
+ },
+ "ipv6": {
+ "pf_list_1_ipv6": [{
+ "seqid": 100,
+ "network": "any",
+ "action": prefix_action
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": rmap_action,
+ "match": {
+ addr_type: {
+ "prefix_lists":
+ "pf_list_1_{}".format(addr_type)
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_7 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [
+ {"name":
+ "rmap_match_pf_1_ipv4",
+ "direction": "in"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [
+ {"name":
+ "rmap_match_pf_1_ipv6",
+ "direction": "in"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_7)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ dut = "r3"
+ protocol = "bgp"
+ input_dict_2 = {
+ "r1": {
+ "static_routes": [
+ {
+ "network": [NETWORK[adt][0]],
+ "no_of_ip": 9,
+ "next_hop": NEXT_HOP[adt],
+ }
+ ]
+ }
+ }
+
+ result = verify_rib(tgen, adt, dut, input_dict_2, protocol=protocol)
+ if "deny" in [prefix_action, rmap_action]:
+ assert result is not True, "Testcase {} : Failed \n Error: {}".\
+ format(tc_name, result)
+ else:
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+
+def test_route_map_multiple_seq_different_match_set_clause_p0(request):
+ """
+ TC_35:
+ Test multiple sequence numbers in a single route-map for different
+ match/set clauses.
+ """
+
+ tgen = get_topogen()
+ # test case name
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ for adt in ADDR_TYPES:
+ # Create Static routes
+ input_dict = {
+ "r1": {
+ "static_routes": [{
+ "network": NETWORK[adt][0],
+ "no_of_ip": 1,
+ "next_hop": NEXT_HOP[adt]
+ }]
+ }
+ }
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Api call to redistribute static routes
+ input_dict_1 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ 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"
+ }]
+ },
+ "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(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [
+ {
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists":
+ "pf_list_2_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "aspath": {
+ "as_num": 500
+ }
+ }
+ },
+ {
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists":
+ "pf_list_2_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 150,
+ }
+ },
+ {
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists":
+ "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "med": 50
+ }
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": "out"
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": "out"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ for adt in ADDR_TYPES:
+ # Verifying RIB routes
+ dut = "r3"
+ protocol = "bgp"
+ input_dict = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_list1": [{
+ "set": {
+ "med": 50,
+ }
+ }],
+ }
+ }
+ }
+
+ static_routes = [NETWORK[adt][0]]
+
+ time.sleep(2)
+ result = verify_bgp_attributes(tgen, adt, dut, static_routes,
+ "rmap_match_pf_list1", input_dict)
+ assert result is True, "Test case {} : Failed \n Error: {}". \
+ format(tc_name, result)
+
+ dut = "r4"
+ result = verify_bgp_attributes(tgen, adt, dut, static_routes,
+ "rmap_match_pf_list1", input_dict)
+ assert result is True, "Test case {} : Failed \n Error: {}". \
+ format(tc_name, result)
+
+ logger.info("Testcase " + tc_name + " :Passed \n")
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_route_map_set_only_no_match_p0(request):
+ """
+ TC_37:
+ Test add/remove route-maps with multiple set
+ clauses and without any match statement.(Set only)
+ """
+
+ tgen = get_topogen()
+ # test case name
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ for adt in ADDR_TYPES:
+ # Create Static routes
+ input_dict = {
+ "r1": {
+ "static_routes": [{
+ "network": NETWORK[adt][0],
+ "no_of_ip": 1,
+ "next_hop": NEXT_HOP[adt]
+ }]
+ }
+ }
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Api call to redistribute static routes
+ input_dict_1 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Create route map
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1": [
+ {
+ "action": "permit",
+ "set": {
+ "med": 50,
+ "localpref": 150,
+ "weight": 4000
+ }
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name": "rmap_match_pf_1",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name": "rmap_match_pf_1",
+ "direction": "out"
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name": "rmap_match_pf_1",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name": "rmap_match_pf_1",
+ "direction": "out"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ time.sleep(2)
+ for adt in ADDR_TYPES:
+ input_dict_4 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1": [
+ {
+ "action": "permit",
+ "set": {
+ "med": 50,
+ }
+ }
+ ]
+ }
+ }
+ }
+ # Verifying RIB routes
+ static_routes = [NETWORK[adt][0]]
+ result = verify_bgp_attributes(tgen, adt, "r3", static_routes,
+ "rmap_match_pf_1", input_dict_3)
+ assert result is True, "Test case {} : Failed \n Error: {}". \
+ format(tc_name, result)
+
+ result = verify_bgp_attributes(tgen, adt, "r4", static_routes,
+ "rmap_match_pf_1", input_dict_4)
+ assert result is True, "Test case {} : Failed \n Error: {}". \
+ format(tc_name, result)
+
+ logger.info("Testcase " + tc_name + " :Passed \n")
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_route_map_match_only_no_set_p0(request):
+ """
+ TC_38:
+ Test add/remove route-maps with multiple match
+ clauses and without any set statement.(Match only)
+ """
+
+ tgen = get_topogen()
+ # test case name
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Creating configuration from JSON
+ reset_config_on_routers(tgen)
+
+ for adt in ADDR_TYPES:
+ # Create Static routes
+ input_dict = {
+ "r1": {
+ "static_routes": [{
+ "network": NETWORK[adt][0],
+ "no_of_ip": 1,
+ "next_hop": NEXT_HOP[adt]
+ }]
+ }
+ }
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Api call to redistribute static routes
+ input_dict_1 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Create ip prefix list
+ input_dict_2 = {
+ "r1": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_list_1_ipv4": [{
+ "seqid": 10,
+ "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(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r1": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ "set": {
+ "med": 50,
+ "localpref": 150,
+ }
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": "out"
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": "out"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Create ip prefix list
+ input_dict_5 = {
+ "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"
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_5)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_6 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_2_{}".format(addr_type): [{
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists":
+ "pf_list_1_{}".format(addr_type)
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_6)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_7 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv4",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv4",
+ "direction": "out"
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv6",
+ "direction": "in"
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv6",
+ "direction": "out"
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_7)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ for adt in ADDR_TYPES:
+ # Verifying RIB routes
+ static_routes = [NETWORK[adt][0]]
+ result = verify_bgp_attributes(tgen, adt, "r3", static_routes,
+ "rmap_match_pf_1", input_dict_3)
+ assert result is True, "Test case {} : Failed \n Error: {}". \
+ format(tc_name, result)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
+
+
diff --git a/tests/topotests/bgp-route-map/test_route_map_topo2.py b/tests/topotests/bgp-route-map/test_route_map_topo2.py
new file mode 100755
index 0000000000..7009fc97ce
--- /dev/null
+++ b/tests/topotests/bgp-route-map/test_route_map_topo2.py
@@ -0,0 +1,3916 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2019 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""Following tests are covered to test route-map functionality.
+TC_57:
+ Create route map to match prefix-list and permit inbound
+ and outbound prefixes and set criteria on match
+TC_52:
+ Test modify set/match clauses in a route-map to see
+ if it takes immediate effect.
+TC_61:
+ Delete the route maps.
+TC_50_1:
+ Test modify/remove prefix-lists referenced by a
+ route-map for match statement.
+TC_50_1:
+ 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
+ sequence number. (Logical OR-ed of multiple match statements)
+TC_44:
+ 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
+ it takes effect as intended
+TC_56:
+ Test clear BGP sessions and interface flaps to see if
+ route-map properties are intact.
+TC_46:
+ Verify if a blank sequence number can be create(without any
+ match/set clause) and check if it allows all the traffic/prefixes
+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
+ single sequence number.
+TC_54:
+ Verify route-maps continue clause functionality.
+TC_55:
+ Verify route-maps goto clause functionality.
+TC_53:
+ Verify route-maps call clause functionality.
+TC_58:
+ Create route map deny inbound and outbound prefixes on
+ match prefix list and set criteria on match
+TC_59:
+ Create route map to permit inbound prefixes with filter
+ match tag and set criteria
+TC_60
+ Create route map to deny outbound prefixes with filter match tag,
+ and set criteria
+"""
+
+#################################
+# TOPOLOGY
+#################################
+"""
+
+ +-------+
+ +--------- | R2 |
+ | +-------+
+ |iBGP |
+ +-------+ |
+ | R1 | |iBGP
+ +-------+ |
+ | |
+ | iBGP +-------+ eBGP +-------+
+ +---------- | R3 |----------| R4 |
+ +-------+ +-------+
+ |
+ |eBGP
+ |
+ +-------+
+ | R5 |
+ +-------+
+
+
+"""
+
+import sys
+import json
+import time
+import pytest
+import inspect
+import os
+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, '../'))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, get_topogen
+from mininet.topo import Topo
+
+# Required to instantiate the topology builder class.
+from lib.common_config import (
+ start_topology, write_test_header,
+ write_test_footer, create_static_routes,
+ 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)
+from lib.topolog import logger
+from lib.bgp import (
+ verify_bgp_convergence, create_router_bgp,
+ clear_bgp_and_verify, verify_bgp_attributes)
+from lib.topojson import build_topo_from_json, build_config_from_json
+
+# Reading the data from JSON File for topology and configuration creation
+jsonFile = "{}/bgp_route_map_topo2.json".format(CWD)
+
+try:
+ with open(jsonFile, 'r') as topoJson:
+ topo = json.load(topoJson)
+except IOError:
+ assert False, "Could not read file {}".format(jsonFile)
+
+# Global variables
+# Global variables
+bgp_convergence = False
+NETWORK = {
+ "ipv4": ["11.0.20.1/32", "11.0.20.2/32"],
+ "ipv6": ["2::1/128", "2::2/128"]
+}
+
+bgp_convergence = False
+BGP_CONVERGENCE = False
+ADDR_TYPES = check_address_types()
+
+
+class BGPRmapTopo(Topo):
+ """BGPRmapTopo.
+
+ BGPRmap topology 1
+ * `Topo`: Topology object
+ """
+
+ def build(self, *_args, **_opts):
+ """Build function."""
+ tgen = get_topogen(self)
+
+ # Building topology and configuration from json file
+ build_topo_from_json(tgen, topo)
+
+
+def setup_module(mod):
+ """setup_module.
+
+ Set up the pytest environment
+ * `mod`: module name
+ """
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("="*40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ tgen = Topogen(BGPRmapTopo, mod.__name__)
+ # ... and here it calls Mininet initialization functions.
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Checking BGP convergence
+ global bgp_convergence
+ global ADDR_TYPES
+
+ # 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))
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """teardown_module.
+
+ Teardown the pytest environment.
+ * `mod`: module name
+ """
+ logger.info("Running teardown_module to delete topology")
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info("Testsuite end time: {}".format(
+ time.asctime(time.localtime(time.time()))))
+ logger.info("="*40)
+
+
+#####################################################
+# Tests starting
+#####################################################
+
+
+def test_rmap_match_prefix_list_permit_in_and_outbound_prefixes_p0():
+ """
+ TC: 57
+ Create route map to match prefix-list and permit inbound
+ and outbound prefixes and set criteria on match
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create ip prefix list
+ input_dict_2 = {
+ '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',
+ }]
+ }
+ }
+ }
+ }
+
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+ for addr_type in ADDR_TYPES:
+ # Create route map
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_" + addr_type
+ }
+ },
+ "set": {
+ "localpref": 150,
+ "weight": 100
+ }
+ },
+ ],
+ "rmap_match_pf_2_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_" + addr_type
+ }
+ },
+ "set": {
+ "med": 50
+ }
+ },
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv4",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv6",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result4)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ # dual stack changes
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result4)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result4)
+
+ # Verifying BGP set attributes
+ dut = 'r4'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ # dual stack changes
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_modify_set_match_clauses_in_rmap_p0():
+ """
+ TC_52:
+ Test modify set/match clauses in a route-map to see
+ if it takes immediate effect.
+ """
+
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create ip prefix list
+
+ input_dict_2 = {
+ 'r3': {
+ 'prefix_lists': {
+ 'ipv4': {
+ 'pf_list_1_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',
+ }],
+ '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(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 150,
+ }
+ }],
+ "rmap_match_pf_2_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "med": 50
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv4",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv6",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ # dual stack changes
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result4)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result4)
+
+ # Verifying BGP set attributes
+ dut = 'r4'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ # Modify set/match clause of in-used route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 1000,
+ }
+ }],
+ "rmap_match_pf_2_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "med": 2000
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r4'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_delete_route_maps_p1():
+ """
+ TC_61:
+ Delete the route maps.
+ """
+
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_tag_1_{}".format(addr_type): [{
+ "action": "deny",
+ "match": {
+ addr_type: {
+ "tag": "4001"
+ }
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ 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)]
+ }
+ }
+ result = delete_route_maps(tgen, input_dict)
+ 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(
+ tc_name, result)
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_modify_prefix_list_referenced_by_rmap_p0():
+ """
+ TC_50_1:
+ Test modify/remove prefix-lists referenced by a
+ route-map for match statement.
+ """
+
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create ip prefix list
+ input_dict_2 = {
+ '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',
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 150,
+ "weight": 100
+ }
+ }],
+ "rmap_match_pf_2_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "med": 50
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv4",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv6",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r4'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ # Modify ip prefix list
+ input_dict_2 = {
+ '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'
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ sleep(5)
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_remove_prefix_list_referenced_by_rmap_p0():
+ """
+ TC_50_1:
+ Remove prefix-list referencec by route-map match cluase
+ and verifying it reflecting as intended
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create ip prefix list
+ input_dict_2 = {
+ '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'
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 150,
+ }
+ }],
+ "rmap_match_pf_2_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "med": 50
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ 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': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv4",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv6",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r4'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ for addr_type in ADDR_TYPES:
+ 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(
+ 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
+ }]
+ },
+ '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(
+ tc_name, result)
+
+ result = verify_prefix_lists(tgen, input_dict_3)
+ 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'
+ result = clear_bgp_and_verify(tgen, topo, dut)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_add_and_remove_community_list_referenced_by_rmap_p0():
+ """
+ TC_51:
+ Add and remove community-list referencec by route-map match cluase
+ and verifying it reflecting as intended
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Creating configuration from JSON
+ # build_config_from_json(tgen, topo)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_5 = {
+ "r1": {
+ "route_maps": {
+ "rm_r1_out_{}".format(addr_type): [{
+ "action": "permit",
+ "set": {
+ "large_community": {"num": "1:1:1 1:2:3 2:1:1 2:2:2"}
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_5)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_6 = {
+ 'r1': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "route_maps": [{
+ "name": "rm_r1_out_ipv4",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "route_maps": [{
+ "name": "rm_r1_out_ipv6",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_6)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ # Create standard large commumity-list
+ input_dict_1 = {
+ "r3": {
+ "bgp_community_lists": [
+ {
+ "community_type": "standard",
+ "action": "permit",
+ "name": "rmap_lcomm_{}".format(addr_type),
+ "value": "1:1:1 1:2:3 2:1:1 2:2:2",
+ "large": True
+ }
+ ]
+ }
+ }
+ result = create_bgp_community_lists(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 = {
+ "r3": {
+ "route_maps": {
+ "rm_r3_in_{}".format(addr_type): [{
+ "action": "permit",
+ "match": {
+ addr_type : {
+ "large-community-list": {"id": "rmap_lcomm_"+
+ addr_type}
+ }
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_3 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name": "rm_r3_in_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name": "rm_r3_in_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_3)
+
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ sleep(5)
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verify large-community-list
+ 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'
+ }
+ 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(
+ tc_name, result)
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+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
+ 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')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Api call to advertise networks
+ input_dict_nw1 = {
+ 'r1': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "advertise_networks": [
+ {"network": '10.0.30.1/32'}
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "advertise_networks": [
+ {"network": '1::1/128'}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_nw1)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Api call to advertise networks
+ input_dict_nw2 = {
+ 'r1': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "advertise_networks": [
+ {"network": '20.0.30.1/32'}
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "advertise_networks": [
+ {"network": '2::1/128'}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_nw2)
+ 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'
+ }]
+ },
+ '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(
+ tc_name, result)
+
+ # Create ip prefix list
+ input_dict_2 = {
+ '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'
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ input_dict_3_addr_type ={}
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 150
+ }
+ }]
+ }
+ }
+ }
+ 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(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 200
+ }
+ }]
+ }
+ }
+ }
+ 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(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_6 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_6)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ routes = {
+ "ipv4": ["10.0.30.1/32"],
+ "ipv6": ["1::1/128"]
+ }
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ routes = {
+ "ipv4": ["20.0.30.1/32"],
+ "ipv6": ["2::1/128"]
+ }
+ 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(
+ tc_name, result)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_multiple_match_statement_in_route_map_logical_ANDed():
+ """
+ TC_44:
+ 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')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_5 = {
+ "r1": {
+ "route_maps": {
+ "rm_r1_out_{}".format(addr_type): [{
+ "action": "permit",
+ "set": {
+ "large_community": {
+ "num": "1:1:1 1:2:3 2:1:1 2:2:2"}
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_5)
+ 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': {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "route_maps": [{
+ "name":
+ "rm_r1_out_{}".format(addr_type),
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_6)
+ 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'
+ }]
+ },
+ '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(
+ tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ # Create standard large commumity-list
+ input_dict_1 = {
+ "r3": {
+ "bgp_community_lists": [
+ {
+ "community_type": "standard",
+ "action": "permit",
+ "name": "rmap_lcomm_{}".format(addr_type),
+ "value": "1:1:1 1:2:3 2:1:1 2:2:2",
+ "large": True
+ }
+ ]
+ }
+ }
+ result = create_bgp_community_lists(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 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 150,
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ for addr_type in ADDR_TYPES:
+ # Create route map
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type : {
+ "large_community_list": {"id": "rmap_lcomm_"+
+ addr_type}
+ }
+ },
+ "set": {
+ "localpref": 150,
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ 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': {
+ "bgp": {
+ "address_family": {
+ addr_type: {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_{}".format(addr_type),
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+ # sleep(10)
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_add_remove_rmap_to_specific_neighbor_p0():
+ """
+ TC_41:
+ Test add/remove route-maps to specific neighbor and see if
+ it takes effect as intended
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create ip prefix list
+ input_dict_2 = {
+ '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'
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 150,
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Remove applied rmap from neighbor
+ input_dict_4 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in',
+ "delete": True
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": 'in',
+ "delete": True
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_clear_bgp_and_flap_interface_to_verify_rmap_properties_p0():
+ """
+ TC_56:
+ Test clear BGP sessions and interface flaps to see if
+ route-map properties are intact.
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create ip prefix list
+ input_dict_2 = {
+ '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'
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 150,
+ "weight": 100
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ # clear bgp, so config changes would be reflected
+ dut = 'r3'
+ result = clear_bgp_and_verify(tgen, topo, dut)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ # Flap interface to see if route-map properties are intact
+ # Shutdown interface
+ dut = "r3"
+ intf = "r3-r1-eth0"
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ sleep(5)
+
+ # Bringup interface
+ dut = "r3"
+ intf = "r3-r1-eth0"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ # Verify BGP convergence once interface is up
+ result = verify_bgp_convergence(tgen, topo)
+ assert result is True, (
+ 'setup_module :Failed \n Error:' ' {}'.format(result))
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_rmap_without_match_and_set_clause_p0():
+ """
+ TC_46:
+ Verify if a blank sequence number can be create(without any
+ match/set clause) and check if it allows all the traffic/prefixes
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_no_match_set_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '5'
+ }],
+ "rmap_no_match_set_2_{}".format(addr_type): [{
+ "action": "deny",
+ 'seq_id': '5'
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_no_match_set_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_no_match_set_2_ipv4",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_no_match_set_1_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_no_match_set_2_ipv6",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_set_localpref_weight_to_ebgp_and_med_to_ibgp_peers_p0():
+ """
+ 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
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create ip prefix list
+ input_dict_2 = {
+ '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'
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Create route map
+ input_dict_3_addr_type ={}
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(
+ addr_type)
+ }
+ },
+ "set": {
+ "med": 50
+ }
+ }],
+ "rmap_match_pf_2_{}".format(addr_type): [{
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(
+ addr_type)
+ }},
+ "set": {
+ "localpref": 150
+ }
+ }],
+ "rmap_match_pf_3_{}".format(addr_type): [{
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(
+ addr_type)
+ }},
+ "set": {
+ "weight": 1000
+ }
+ }]
+ }
+ }
+ }
+ 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(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv4",
+ "direction": 'out'
+ }]
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_3_ipv4",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv6",
+ "direction": 'out'
+ }]
+ }
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_3_ipv6",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ rmap_name = "rmap_match_pf_1"
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r4'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ rmap_name = "rmap_match_pf_2"
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+ # Verifying BGP set attributes
+ dut = 'r5'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+
+ rmap_name = "rmap_match_pf_3"
+ 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(
+ tc_name, result)
+
+ logger.info("Expected behaviour: {}".format(result))
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_multiple_set_on_single_sequence_in_rmap_p0():
+ """
+ TC_43:
+ 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')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create ip prefix list
+ input_dict_2 = {
+ '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'
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 150,
+ "weight": 100,
+ "med": 50
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+
+ rmap_name = "rmap_match_pf_1"
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_route_maps_with_continue_clause_p0():
+ """
+ TC_54:
+ Verify route-maps continue clause functionality.
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create ip prefix list
+ input_dict_2 = {
+ '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'
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '10',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 150
+ },
+ "continue": "30"
+ },
+ {
+ "action": "permit",
+ 'seq_id': '20',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "med": 200
+ }
+ },
+ {
+ "action": "permit",
+ 'seq_id': '30',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "med": 100
+ }
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ rmap_name = "rmap_match_pf_1"
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ seq_id = {
+ "ipv4": ["10", "30"],
+ "ipv6": ["10", "30"]
+ }
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_route_maps_with_goto_clause_p0():
+ """
+ TC_55:
+ Verify route-maps goto clause functionality.
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create ip prefix list
+ input_dict_2 = {
+ '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'
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ 'seq_id': '10',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "goto": "30"
+ },
+ {
+ "action": "permit",
+ 'seq_id': '20',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "med": 100
+ }
+ },
+ {
+ "action": "permit",
+ 'seq_id': '30',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "med": 200
+ }
+ }
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ rmap_name = "rmap_match_pf_1"
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ seq_id = {
+ "ipv4": ["10", "30"],
+ "ipv6": ["10", "30"]
+ }
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_route_maps_with_call_clause_p0():
+ """
+ TC_53:
+ Verify route-maps call clause functionality.
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create ip prefix list
+ input_dict_2 = {
+ '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'
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 150
+ },
+ "call": "rmap_match_pf_2_{}".format(addr_type)
+ }],
+ "rmap_match_pf_2_{}".format(addr_type): [{
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "med": 200
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv6",
+ "direction": 'in'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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(
+ tc_name, result)
+
+ # Verifying BGP set attributes
+ dut = 'r3'
+ routes = {
+ "ipv4": ["10.0.20.1/32", "10.0.20.2/32"],
+ "ipv6": ["1::1/128", "1::2/128"]
+ }
+ rmap_name = "rmap_match_pf_1"
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ rmap_name = "rmap_match_pf_2"
+ for addr_type in ADDR_TYPES:
+ 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(
+ tc_name, result)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_create_rmap_match_prefix_list_to_deny_in_and_outbound_prefixes_p0():
+ """
+ TC_58:
+ Create route map deny inbound and outbound prefixes on
+ match prefix list and set criteria on match
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ # Create ip prefix list
+ input_dict_2 = {
+ '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'
+ }]
+ }
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Create route map
+ for addr_type in ADDR_TYPES:
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_{}".format(addr_type): [{
+ "action": "deny",
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "localpref": 150,
+ }
+ }],
+ "rmap_match_pf_2_{}".format(addr_type): [{
+ "action": "deny",
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_{}".format(addr_type)
+ }
+ },
+ "set": {
+ "med": 50
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r3': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv6",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_1_ipv4",
+ "direction": 'in'
+ }]
+ }
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [{
+ "name":
+ "rmap_match_pf_2_ipv6",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ 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)
+
+ # Verifying RIB routes
+ 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)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_create_rmap_to_match_tag_permit_inbound_prefixes_p0():
+ """
+ TC_59:
+ Create route map to permit inbound prefixes with filter
+ match tag and set criteria
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ for addr_type in ADDR_TYPES:
+ # Create Static routes
+ input_dict = {
+ "r1": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type],
+ "next_hop": "Null0",
+ "tag": 4001
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Api call to redistribute static routes
+ input_dict_1 = {
+ "r1": {
+ "bgp": {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Create route map
+ input_dict_3 = {
+ "r1": {
+ "route_maps": {
+ "rmap_match_tag_1_{}".format(addr_type): [{
+ "action": "permit",
+ "match": {
+ addr_type: {
+ "tag": "4001"
+ }
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r1': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "route_maps": [{
+ "name":
+ "rmap_match_tag_1_ipv4",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "route_maps": [{
+ "name":
+ "rmap_match_tag_1_ipv6",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ dut = 'r3'
+ protocol = 'bgp'
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r1": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type],
+ "next_hop": "Null0",
+ "tag": 4001
+ }
+ ]
+ }
+ }
+ result = verify_rib(tgen, addr_type, dut, input_dict,
+ protocol=protocol)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+
+def test_create_rmap_to_match_tag_deny_outbound_prefixes_p0():
+ """
+ TC_60
+ Create route map to deny outbound prefixes with filter match tag,
+ and set criteria
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip('skipped because of BGP Convergence failure')
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ reset_config_on_routers(tgen)
+
+ for addr_type in ADDR_TYPES:
+ # Create Static routes
+ input_dict = {
+ "r1": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type],
+ "next_hop": "Null0",
+ "tag": 4001
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Api call to redistribute static routes
+ input_dict_1 = {
+ "r1": {
+ "bgp": {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "redistribute": [
+ {"redist_type": "static"},
+ {"redist_type": "connected"}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result)
+
+ # Create route map
+ input_dict_3 = {
+ "r1": {
+ "route_maps": {
+ "rmap_match_tag_1_{}".format(addr_type): [{
+ "action": "deny",
+ "match": {
+ addr_type: {
+ "tag": "4001"
+ }
+ }
+ }]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ 'r1': {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "route_maps": [{
+ "name":
+ "rmap_match_tag_1_ipv4",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r1": {
+ "route_maps": [{
+ "name":
+ "rmap_match_tag_1_ipv6",
+ "direction": 'out'
+ }]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, 'Testcase {} : Failed \n Error: {}'.format(
+ tc_name, result)
+
+ # Verifying RIB routes
+ dut = 'r3'
+ protocol = 'bgp'
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r1": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type],
+ "next_hop": "Null0",
+ "tag": 4001
+ }
+ ]
+ }
+ }
+ 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(
+ tc_name, result)
+
+ write_test_footer(tc_name)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py
index 149a420a32..547a5949a3 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py
@@ -11,16 +11,17 @@ for rtr in l3mdev_rtrs:
rtrs = ['r1', 'r3', 'r4']
for rtr in rtrs:
- luCommand(rtr, 'ip link show type vrf {}-cust1'.format(rtr),'cust1: .*UP,LOWER_UP','pass','VRF cust1 up')
- luCommand(rtr, 'ip add show vrf {}-cust1'.format(rtr),'r..eth4: .*UP,LOWER_UP.* 192.168','pass','VRF cust1 IP config')
+ luCommand(rtr, 'ip link show type vrf {}-cust1'.format(rtr),'cust1: .*UP','pass','VRF cust1 intf up')
+ luCommand(rtr, 'ip add show vrf {}-cust1'.format(rtr),'r..eth4.*UP','pass','VRF cust1 IP intf up')
+ luCommand(rtr, 'ip add show vrf {}-cust1'.format(rtr),'192.168','pass','VRF cust1 IP config')
luCommand(rtr, 'ip route show vrf {}-cust1'.format(rtr),'192.168...0/24 dev r.-eth','pass','VRF cust1 interface route')
-luCommand('r4', 'ip link show type vrf r4-cust2','cust2: .*UP,LOWER_UP','pass','VRF cust2 up')
-luCommand('r4', 'ip add show vrf r4-cust2','r..eth5.*UP,LOWER_UP.* 192.168','pass','VRF cust1 IP config')
+luCommand('r4', 'ip link show type vrf r4-cust2','cust2: .*UP','pass','VRF cust2 up')
+luCommand('r4', 'ip add show vrf r4-cust2','r..eth5.*UP.* 192.168','pass','VRF cust1 IP config')
luCommand(rtr, 'ip route show vrf r4-cust2'.format(rtr),'192.168...0/24 dev r.-eth','pass','VRF cust2 interface route')
rtrs = ['ce1', 'ce2', 'ce3']
for rtr in rtrs:
luCommand(rtr, 'ip route show','192.168...0/24 dev ce.-eth0','pass','CE interface route')
luCommand(rtr,'ping 192.168.1.1 -c 1',' 0. packet loss','wait','CE->PE ping')
-luCommand('ce4', 'ip link show type vrf ce4-cust2','cust2: .*UP,LOWER_UP','pass','VRF cust2 up')
+luCommand('ce4', 'ip link show type vrf ce4-cust2','cust2: .*UP','pass','VRF cust2 up')
luCommand('ce4', 'ip route show vrf ce4-cust2','192.168...0/24 dev ce.-eth0','pass','CE interface route')
luCommand('ce4','ping 192.168.2.1 -c 1 -I ce4-cust2',' 0. packet loss','wait','CE4->PE4 ping')
diff --git a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref b/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref
deleted file mode 100644
index fb193265be..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref
+++ /dev/null
@@ -1,31 +0,0 @@
-{
- "neighbors":[
- {
- "2.2.2.2":[
- {
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.1.2",
- "ifaceName":"r1-eth1:10.0.1.1",
- "retransmitCounter":0,
- "requestCounter":0,
- "dbSummaryCounter":0
- }
- ]
- },
- {
- "3.3.3.3":[
- {
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.2.3",
- "ifaceName":"r1-eth2:10.0.2.1",
- "retransmitCounter":0,
- "requestCounter":0,
- "dbSummaryCounter":0
- }
- ]
- }
- ]
-}
-
diff --git a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-no-neigh b/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-no-neigh
deleted file mode 100644
index 7c4d0ab58c..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-no-neigh
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "2.2.2.2":[
- {
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.1.2",
- "ifaceName":"r1-eth1:10.0.1.1"
- }
- ],
- "3.3.3.3":[
- {
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.2.3",
- "ifaceName":"r1-eth2:10.0.2.1"
- }
- ]
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-old-nolist b/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-old-nolist
deleted file mode 100644
index 2270c3fdde..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-old-nolist
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "2.2.2.2":{
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.1.2",
- "ifaceName":"r1-eth1:10.0.1.1"
- },
- "3.3.3.3":{
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.2.3",
- "ifaceName":"r1-eth2:10.0.2.1"
- }
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref b/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref
deleted file mode 100644
index 1376579757..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "neighbors":[
- {
- "1.1.1.1":[
- {
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.1.1",
- "ifaceName":"r2-eth1:10.0.1.2",
- "retransmitCounter":0,
- "requestCounter":0,
- "dbSummaryCounter":0
- }
- ]
- },
- {
- "3.3.3.3":[
- {
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.3.3",
- "ifaceName":"r2-eth2:10.0.3.2",
- "retransmitCounter":0,
- "requestCounter":0,
- "dbSummaryCounter":0
- }
- ]
- }
- ]
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-no-neigh b/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-no-neigh
deleted file mode 100644
index a982c1cbd3..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-no-neigh
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "1.1.1.1":[
- {
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.1.1",
- "ifaceName":"r2-eth1:10.0.1.2"
- }
- ],
- "3.3.3.3":[
- {
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.3.3",
- "ifaceName":"r2-eth2:10.0.3.2"
- }
- ]
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-old-nolist b/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-old-nolist
deleted file mode 100644
index 18ffbc2f8a..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-old-nolist
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "1.1.1.1":{
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.1.1",
- "ifaceName":"r2-eth1:10.0.1.2"
- },
- "3.3.3.3":{
- "priority":1,
- "state":"Full/DR",
- "address":"10.0.3.3",
- "ifaceName":"r2-eth2:10.0.3.2"
- }
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref b/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref
deleted file mode 100644
index 41de304b2b..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "neighbors":[
- {
- "1.1.1.1":[
- {
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.2.1",
- "ifaceName":"r3-eth1:10.0.2.3",
- "retransmitCounter":0,
- "requestCounter":0,
- "dbSummaryCounter":0
- }
- ]
- },
- {
- "2.2.2.2":[
- {
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.3.2",
- "ifaceName":"r3-eth2:10.0.3.3",
- "retransmitCounter":0,
- "requestCounter":0,
- "dbSummaryCounter":0
- }
- ]
- }
- ]
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-no-neigh b/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-no-neigh
deleted file mode 100644
index d7e0e42405..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-no-neigh
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- "1.1.1.1":[
- {
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.2.1",
- "ifaceName":"r3-eth1:10.0.2.3"
- }
- ],
- "2.2.2.2":[
- {
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.3.2",
- "ifaceName":"r3-eth2:10.0.3.3"
- }
- ]
-}
diff --git a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-old-nolist b/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-old-nolist
deleted file mode 100644
index b0669742ab..0000000000
--- a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-old-nolist
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "1.1.1.1":{
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.2.1",
- "ifaceName":"r3-eth1:10.0.2.3"
- },
- "2.2.2.2":{
- "priority":1,
- "state":"Full/Backup",
- "address":"10.0.3.2",
- "ifaceName":"r3-eth2:10.0.3.3"
- }
-}
diff --git a/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py b/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py
index 0948c2e41b..ce651c50cd 100755
--- a/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py
+++ b/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py
@@ -144,9 +144,6 @@ def setup_module(mod):
)
tgen.start_router()
- for router in router_list.values():
- if router.has_version('<', '3'):
- tgen.set_error('unsupported version')
def teardown_module(mod):
"Teardown the pytest environment"
@@ -180,30 +177,8 @@ def test_ospf_convergence():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- # Old output (before FRR PR1383) didn't show a list of neighbors.
- # Check for dict object and compare to old output if this is the case
- tgen = get_topogen()
- router = tgen.gears['r1']
- output = router.vtysh_cmd("show ip ospf neighbor json", isjson=True)
-
- # We could have either old format (without "neighbors" and direct list
- # of IP's or new format from PR1659 with "neighbors".
- # Trying old formats first and fall back to new format
- #
- # New format: neighbors have dict instead of list of dicts (PR1723).
- if output.has_key('neighbors'):
- if isinstance(output['neighbors'], dict):
- reffile = "show_ip_ospf_neighbor.json"
- else:
- reffile = "show_ip_ospf_neighbor.ref"
- else:
- if isinstance(output["2.2.2.2"], dict):
- reffile = "show_ip_ospf_neighbor.ref-old-nolist"
- else:
- reffile = "show_ip_ospf_neighbor.ref-no-neigh"
-
for rname in ['r1', 'r2', 'r3']:
- router_compare_json_output(rname, "show ip ospf neighbor json", reffile)
+ router_compare_json_output(rname, "show ip ospf neighbor json", "show_ip_ospf_neighbor.json")
def test_rib():
logger.info("Test: verify RIB")
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index c05e14a95e..bfc34c25e4 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -1229,6 +1229,150 @@ def verify_bgp_timers_and_functionality(tgen, topo, input_dict):
return True
+@retry(attempts=3, wait=4, return_is_str=True)
+def verify_bgp_attributes(tgen, addr_type, dut, static_routes, rmap_name,
+ input_dict, seq_id=None):
+ """
+ API will verify BGP attributes set by Route-map for given prefix and
+ DUT. it will run "show bgp ipv4/ipv6 {prefix_address} json" command
+ in DUT to verify BGP attributes set by route-map, Set attributes
+ values will be read from input_dict and verified with command output.
+
+ * `tgen`: topogen object
+ * `addr_type` : ip type, ipv4/ipv6
+ * `dut`: Device Under Test
+ * `static_routes`: Static Routes for which BGP set attributes needs to be
+ verified
+ * `rmap_name`: route map name for which set criteria needs to be verified
+ * `input_dict`: defines for which router, AS numbers needs
+ * `seq_id`: sequence number of rmap, default is None
+
+ Usage
+ -----
+ input_dict = {
+ "r3": {
+ "route_maps": {
+ "rmap_match_pf_1_ipv4": [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_" + addr_type
+ }
+ },
+ "set": {
+ "localpref": 150,
+ "weight": 100
+ }
+ }],
+ "rmap_match_pf_2_ipv6": [{
+ "action": "permit",
+ 'seq_id': '5',
+ "match": {
+ addr_type: {
+ "prefix_lists": "pf_list_1_" + addr_type
+ }
+ },
+ "set": {
+ "med": 50
+ }
+ }]
+ }
+ }
+ }
+ result = verify_bgp_attributes(tgen, 'ipv4', "r1", "10.0.20.1/32",
+ rmap_match_pf_1_ipv4, input_dict)
+
+ Returns
+ -------
+ errormsg(str) or True
+ """
+
+ logger.debug("Entering lib API: verify_bgp_attributes()")
+ for router, rnode in tgen.routers().iteritems():
+ if router != dut:
+ continue
+
+ logger.info('Verifying BGP set attributes for dut {}:'.format(router))
+
+ 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:
+ if type(seq_id) is not list:
+ seq_id = [seq_id]
+
+ if "seq_id" in rmap_dict:
+ rmap_seq_id = \
+ rmap_dict["seq_id"]
+ for _seq_id in seq_id:
+ if _seq_id == rmap_seq_id:
+ tmp_list.append(rmap_dict)
+ 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():
+ if criteria not in show_bgp_json[
+ "paths"][0]:
+ errormsg = ("BGP attribute: {}"
+ " is not found in"
+ " cli: {} output "
+ "in router {}".
+ format(criteria,
+ cmd,
+ router))
+ return errormsg
+
+ if rmap_dict["set"][criteria] == \
+ show_bgp_json["paths"][0][
+ criteria]:
+ logger.info("Verifying BGP "
+ "attribute {} for"
+ " route: {} in "
+ "router: {}, found"
+ " expected value:"
+ " {}".
+ format(criteria,
+ static_route,
+ dut,
+ rmap_dict[
+ "set"][
+ criteria]))
+ else:
+ errormsg = \
+ ("Failed: Verifying BGP "
+ "attribute {} for route:"
+ " {} in router: {}, "
+ " expected value: {} but"
+ " found: {}".
+ format(criteria,
+ static_route,
+ dut,
+ rmap_dict["set"]
+ [criteria],
+ show_bgp_json[
+ 'paths'][
+ 0][criteria]))
+ return errormsg
+
+ logger.debug("Exiting lib API: verify_bgp_attributes()")
+ return True
+
@retry(attempts=3, wait=2, return_is_str=True)
def verify_best_path_as_per_bgp_attribute(tgen, addr_type, router, input_dict,
attribute):
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index f2d33f94ae..ba8a4cb0f4 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -21,6 +21,7 @@
from collections import OrderedDict
from datetime import datetime
from time import sleep
+from copy import deepcopy
from subprocess import call
from subprocess import STDOUT as SUB_STDOUT
from subprocess import PIPE as SUB_PIPE
@@ -208,6 +209,7 @@ def create_common_configuration(tgen, router, data, config_type=None,
"interface_config": "! Interfaces Config\n",
"static_route": "! Static Route Config\n",
"prefix_list": "! Prefix List Config\n",
+ "bgp_community_list": "! Community List Config\n",
"route_maps": "! Route Maps Config\n",
"bgp": "! BGP Config\n"
})
@@ -547,13 +549,11 @@ def generate_ips(network, no_of_ips):
Returns list of IPs.
based on start_ip and no_of_ips
- * `network` : from here the ip will start generating, start_ip will be
- first ip
+ * `network` : from here the ip will start generating,
+ start_ip will be
* `no_of_ips` : these many IPs will be generated
-
- Limitation: It will generate IPs only for ip_mask 32
-
"""
+
ipaddress_list = []
if type(network) is not list:
network = [network]
@@ -893,6 +893,7 @@ def create_static_routes(tgen, input_dict, build=False):
"""
result = False
logger.debug("Entering lib API: create_static_routes()")
+ input_dict = deepcopy(input_dict)
try:
for router in input_dict.keys():
if "static_routes" not in input_dict[router]:
@@ -918,16 +919,21 @@ def create_static_routes(tgen, input_dict, build=False):
next_hop = static_route["next_hop"]
network = static_route["network"]
- ip_list = generate_ips([network], no_of_ip)
+ if type(network) is not list:
+ network = [network]
+
+ ip_list = generate_ips(network, no_of_ip)
for ip in ip_list:
addr_type = validate_ip_address(ip)
+
if addr_type == "ipv4":
cmd = "ip route {} {}".format(ip, next_hop)
else:
cmd = "ipv6 route {} {}".format(ip, next_hop)
if tag:
- cmd = "{} {}".format(cmd, str(tag))
+ cmd = "{} tag {}".format(cmd, str(tag))
+
if admin_distance:
cmd = "{} {}".format(cmd, admin_distance)
@@ -1112,11 +1118,11 @@ def create_route_maps(tgen, input_dict, build=False):
"prefix_list": "pf_list_1"
}
- "large-community-list": "{
+ "large-community-list": {
"id": "community_1",
"exact_match": True
}
- "community": {
+ "community_list": {
"id": "community_2",
"exact_match": True
}
@@ -1152,12 +1158,11 @@ def create_route_maps(tgen, input_dict, build=False):
result = False
logger.debug("Entering lib API: create_route_maps()")
-
+ input_dict = deepcopy(input_dict)
try:
for router in input_dict.keys():
if "route_maps" not in input_dict[router]:
- errormsg = "route_maps not present in input_dict"
- logger.debug(errormsg)
+ logger.debug("route_maps not present in input_dict")
continue
rmap_data = []
for rmap_name, rmap_value in \
@@ -1187,10 +1192,41 @@ def create_route_maps(tgen, input_dict, build=False):
rmap_name, rmap_action, seq_id
))
+ if "continue" in rmap_dict:
+ continue_to = rmap_dict["continue"]
+ if continue_to:
+ rmap_data.append("on-match goto {}".
+ format(continue_to))
+ else:
+ logger.error("In continue, 'route-map entry "
+ "sequence number' is not provided")
+ return False
+
+ if "goto" in rmap_dict:
+ go_to = rmap_dict["goto"]
+ if go_to:
+ rmap_data.append("on-match goto {}".
+ format(go_to))
+ else:
+ logger.error("In goto, 'Goto Clause number' is not"
+ " provided")
+ return False
+
+ if "call" in rmap_dict:
+ call_rmap = rmap_dict["call"]
+ if call_rmap:
+ rmap_data.append("call {}".
+ format(call_rmap))
+ else:
+ logger.error("In call, 'destination Route-Map' is"
+ " not provided")
+ return False
+
# Verifying if SET criteria is defined
if "set" in rmap_dict:
set_data = rmap_dict["set"]
-
+ ipv4_data = set_data.setdefault("ipv4", {})
+ ipv6_data = set_data.setdefault("ipv6", {})
local_preference = set_data.setdefault("localpref",
None)
metric = set_data.setdefault("med", None)
@@ -1199,7 +1235,10 @@ def create_route_maps(tgen, input_dict, build=False):
community = set_data.setdefault("community", {})
large_community = set_data.setdefault(
"large_community", {})
+ large_comm_list = set_data.setdefault(
+ "large_comm_list", {})
set_action = set_data.setdefault("set_action", None)
+ nexthop = set_data.setdefault("nexthop", None)
# Local Preference
if local_preference:
@@ -1243,42 +1282,84 @@ def create_route_maps(tgen, input_dict, build=False):
rmap_data.append(cmd)
else:
- logger.errror("In large_community, AS Num not"
- " provided")
+ logger.error("In large_community, AS Num not"
+ " provided")
+ return False
+ if large_comm_list:
+ id = large_comm_list.setdefault("id", None)
+ del_comm = large_comm_list.setdefault("delete",
+ None)
+ if id:
+ cmd = "set large-comm-list {}".format(id)
+ if del_comm:
+ cmd = "{} delete".format(cmd)
+
+ rmap_data.append(cmd)
+ else:
+ logger.error("In large_comm_list 'id' not"
+ " provided")
return False
# Weight
if weight:
- rmap_data.append("set weight {}".format(
+ rmap_data.append("set weight {} \n".format(
weight))
-
+ if ipv6_data:
+ nexthop = ipv6_data.setdefault("nexthop",None)
+ if nexthop:
+ rmap_data.append("set ipv6 next-hop \
+ {}".format(nexthop))
# Adding MATCH and SET sequence to RMAP if defined
if "match" in rmap_dict:
match_data = rmap_dict["match"]
ipv4_data = match_data.setdefault("ipv4", {})
ipv6_data = match_data.setdefault("ipv6", {})
- community = match_data.setdefault("community-list",
- {})
+ community = match_data.setdefault(
+ "community_list",{})
large_community = match_data.setdefault(
- "large-community-list", {}
+ "large_community", {}
+ )
+ large_community_list = match_data.setdefault(
+ "large_community_list", {}
)
- tag = match_data.setdefault("tag", None)
if ipv4_data:
- prefix_name = ipv4_data.setdefault("prefix_lists",
- None)
+ # fetch prefix list data from rmap
+ prefix_name = \
+ ipv4_data.setdefault("prefix_lists",
+ None)
if prefix_name:
- rmap_data.append("match ip address prefix-list"
- " {}".format(prefix_name))
+ rmap_data.append("match ip address"
+ " prefix-list {}".format(prefix_name))
+
+ # fetch tag data from rmap
+ tag = ipv4_data.setdefault("tag", None)
+ if tag:
+ rmap_data.append("match tag {}".format(tag))
+
+ # fetch large community data from rmap
+ large_community_list = ipv4_data.setdefault(
+ "large_community_list",{})
+ large_community = match_data.setdefault(
+ "large_community", {})
+
if ipv6_data:
prefix_name = ipv6_data.setdefault("prefix_lists",
None)
if prefix_name:
- rmap_data.append("match ipv6 address "
- "prefix-list {}".
- format(prefix_name))
- if tag:
- rmap_data.append("match tag {}".format(tag))
+ rmap_data.append("match ipv6 address"
+ " prefix-list {}".format(prefix_name))
+
+ # fetch tag data from rmap
+ tag = ipv6_data.setdefault("tag", None)
+ if tag:
+ rmap_data.append("match tag {}".format(tag))
+
+ # fetch large community data from rmap
+ large_community_list = ipv6_data.setdefault(
+ "large_community_list",{})
+ large_community = match_data.setdefault(
+ "large_community", {})
if community:
if "id" not in community:
@@ -1293,10 +1374,9 @@ def create_route_maps(tgen, input_dict, build=False):
cmd = "{} exact-match".format(cmd)
rmap_data.append(cmd)
-
if large_community:
if "id" not in large_community:
- logger.error("'num' is mandatory for "
+ logger.error("'id' is mandatory for "
"large-community-list in match "
"criteria")
return False
@@ -1306,7 +1386,19 @@ def create_route_maps(tgen, input_dict, build=False):
"exact_match", False)
if exact_match:
cmd = "{} exact-match".format(cmd)
-
+ rmap_data.append(cmd)
+ if large_community_list:
+ if "id" not in large_community_list:
+ logger.error("'id' is mandatory for "
+ "large-community-list in match "
+ "criteria")
+ return False
+ cmd = "match large-community {}".format(
+ large_community_list["id"])
+ exact_match = large_community_list.setdefault(
+ "exact_match", False)
+ if exact_match:
+ cmd = "{} exact-match".format(cmd)
rmap_data.append(cmd)
result = create_common_configuration(tgen, router,
@@ -1320,10 +1412,178 @@ def create_route_maps(tgen, input_dict, build=False):
logger.error(errormsg)
return errormsg
- logger.debug("Exiting lib API: create_prefix_lists()")
+ logger.debug("Exiting lib API: create_route_maps()")
+ return result
+
+
+def delete_route_maps(tgen, input_dict):
+ """
+ Delete ip route maps from device
+
+ * `tgen` : Topogen object
+ * `input_dict` : for which router,
+ route map has to be deleted
+
+ Usage
+ -----
+ # Delete route-map rmap_1 and rmap_2 from router r1
+ input_dict = {
+ "r1": {
+ "route_maps": ["rmap_1", "rmap__2"]
+ }
+ }
+ result = delete_route_maps("ipv4", input_dict)
+
+ Returns
+ -------
+ errormsg(str) or True
+ """
+ logger.info("Entering lib API: delete_route_maps()")
+
+ for router in input_dict.keys():
+ route_maps = input_dict[router]["route_maps"][:]
+ rmap_data = input_dict[router]
+ rmap_data["route_maps"] = {}
+ for route_map_name in route_maps:
+ rmap_data["route_maps"].update({
+ route_map_name:
+ [{
+ "delete": True
+ }]
+ })
+
+ return create_route_maps(tgen, input_dict)
+
+
+def create_bgp_community_lists(tgen, input_dict, build=False):
+ """
+ Create bgp community-list or large-community-list on the devices as per
+ the arguments passed. Takes list of communities in input.
+
+ Parameters
+ ----------
+ * `tgen` : Topogen object
+ * `input_dict` : Input dict data, required when configuring from testcase
+ * `build` : Only for initial setup phase this is set as True.
+ Usage
+ -----
+ input_dict_1 = {
+ "r3": {
+ "bgp_community_lists": [
+ {
+ "community_type": "standard",
+ "action": "permit",
+ "name": "rmap_lcomm_{}".format(addr_type),
+ "value": "1:1:1 1:2:3 2:1:1 2:2:2",
+ "large": True
+ }
+ ]
+ }
+ }
+ }
+ result = create_bgp_community_lists(tgen, input_dict_1)
+ """
+
+ result = False
+ logger.debug("Entering lib API: create_bgp_community_lists()")
+ input_dict = deepcopy(input_dict)
+ try:
+ for router in input_dict.keys():
+ if "bgp_community_lists" not in input_dict[router]:
+ errormsg = "bgp_community_lists not present in input_dict"
+ logger.debug(errormsg)
+ continue
+
+ config_data = []
+
+ community_list = input_dict[router]["bgp_community_lists"]
+ for community_dict in community_list:
+ del_action = community_dict.setdefault("delete", False)
+ community_type = community_dict.setdefault("community_type",
+ None)
+ action = community_dict.setdefault("action", None)
+ value = community_dict.setdefault("value", '')
+ large = community_dict.setdefault("large", None)
+ name = community_dict.setdefault("name", None)
+ if large:
+ cmd = "bgp large-community-list"
+ else:
+ cmd = "bgp community-list"
+
+ if not large and not (community_type and action and value):
+ errormsg = "community_type, action and value are " \
+ "required in bgp_community_list"
+ logger.error(errormsg)
+ return False
+
+ try:
+ community_type = int(community_type)
+ cmd = "{} {} {} {}".format(cmd, community_type, action,
+ value)
+ except ValueError:
+
+ cmd = "{} {} {} {} {}".format(
+ cmd, community_type, name, action, value)
+
+ if del_action:
+ cmd = "no {}".format(cmd)
+
+ config_data.append(cmd)
+
+ result = create_common_configuration(tgen, router, config_data,
+ "bgp_community_list",
+ build=build)
+
+ except InvalidCLIError:
+ # Traceback
+ errormsg = traceback.format_exc()
+ logger.error(errormsg)
+ return errormsg
+
+ logger.debug("Exiting lib API: create_bgp_community_lists()")
return result
+def shutdown_bringup_interface(tgen, dut, intf_name, ifaceaction=False):
+ """
+ Shutdown or bringup router's interface "
+
+ * `tgen` : Topogen object
+ * `dut` : Device under test
+ * `intf_name` : Interface name to be shut/no shut
+ * `ifaceaction` : Action, to shut/no shut interface,
+ by default is False
+
+ Usage
+ -----
+ dut = "r3"
+ intf = "r3-r1-eth0"
+ # Shut down ineterface
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ # Bring up ineterface
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ Returns
+ -------
+ errormsg(str) or True
+ """
+
+ from topotest import interface_set_status
+ router_list = tgen.routers()
+ if ifaceaction:
+ logger.info("Bringing up interface : {}".format(intf_name))
+ else:
+ logger.info("Shutting down interface : {}".format(intf_name))
+
+ interface_set_status(router_list[dut], intf_name,
+ ifaceaction)
+
+ if ifaceaction:
+ # Disabling v6 link local once interfac comes up back
+ disable_v6_link_local(tgen, dut, intf_name=intf_name)
+
+
#############################################
# Verification APIs
#############################################
@@ -1625,5 +1885,133 @@ def verify_prefix_lists(tgen, input_dict):
logger.info("Prefix list %s is/are not present in the router"
" from router %s", prefix_list, router)
- logger.debug("Exiting lib API: verify_prefix_lissts()")
+ logger.debug("Exiting lib API: verify_prefix_lists()")
+ return True
+
+
+@retry(attempts=2, wait=4, return_is_str=True, initial_wait=2)
+def verify_route_maps(tgen, input_dict):
+ """
+ Running "show route-map" command and verifying given route-map
+ is present in router.
+ Parameters
+ ----------
+ * `tgen` : topogen object
+ * `input_dict`: data to verify prefix lists
+ Usage
+ -----
+ # To verify rmap_1 and rmap_2 are present in router r1
+ input_dict = {
+ "r1": {
+ "route_maps": ["rmap_1", "rmap_2"]
+ }
+ }
+ result = verify_route_maps(tgen, input_dict)
+ Returns
+ -------
+ errormsg(str) or True
+ """
+
+ logger.debug("Entering lib API: verify_route_maps()")
+
+ for router in input_dict.keys():
+ if router not in tgen.routers():
+ continue
+
+ rnode = tgen.routers()[router]
+ # Show ip route-map
+ show_route_maps = rnode.vtysh_cmd("show route-map")
+
+ # Verify route-map is deleted
+ route_maps = input_dict[router]["route_maps"]
+ for route_map in route_maps:
+ if route_map in show_route_maps:
+ errormsg = ("Route map {} is not deleted from router"
+ " {}".format(route_map, router))
+ return errormsg
+
+ logger.info("Route map %s is/are deleted successfully from"
+ " router %s", route_maps, router)
+
+ logger.debug("Exiting lib API: verify_route_maps()")
+ return True
+
+
+@retry(attempts=3, wait=4, return_is_str=True)
+def verify_bgp_community(tgen, addr_type, router, network, input_dict=None):
+ """
+ API to veiryf BGP large community is attached in route for any given
+ DUT by running "show bgp ipv4/6 {route address} json" command.
+
+ Parameters
+ ----------
+ * `tgen`: topogen object
+ * `addr_type` : ip type, ipv4/ipv6
+ * `dut`: Device Under Test
+ * `network`: network for which set criteria needs to be verified
+ * `input_dict`: having details like - for which router, community and
+ values needs to be verified
+ Usage
+ -----
+ networks = ["200.50.2.0/32"]
+ input_dict = {
+ "largeCommunity": "2:1:1 2:2:2 2:3:3 2:4:4 2:5:5"
+ }
+ result = verify_bgp_community(tgen, "ipv4", dut, network, input_dict=None)
+
+ Returns
+ -------
+ errormsg(str) or True
+ """
+
+ logger.info("Entering lib API: verify_bgp_community()")
+ if router not in tgen.routers():
+ return False
+
+ rnode = tgen.routers()[router]
+
+ logger.debug("Verifying BGP community attributes on dut %s: for %s "
+ "network %s", router, addr_type, network)
+
+ for net in network:
+ cmd = "show bgp {} {} json".format(addr_type, net)
+ show_bgp_json = rnode.vtysh_cmd(cmd, isjson=True)
+ logger.info(show_bgp_json)
+ if "paths" not in show_bgp_json:
+ return "Prefix {} not found in BGP table of router: {}". \
+ format(net, router)
+
+ as_paths = show_bgp_json["paths"]
+ found = False
+ for i in range(len(as_paths)):
+ if "largeCommunity" in show_bgp_json["paths"][i] or \
+ "community" in show_bgp_json["paths"][i]:
+ found = True
+ logger.info("Large Community attribute is found for route:"
+ " %s in router: %s", net, router)
+ if input_dict is not None:
+ for criteria, comm_val in input_dict.items():
+ show_val = show_bgp_json["paths"][i][criteria][
+ "string"]
+ if comm_val == show_val:
+ logger.info("Verifying BGP %s for prefix: %s"
+ " in router: %s, found expected"
+ " value: %s", criteria, net, router,
+ comm_val)
+ else:
+ errormsg = "Failed: Verifying BGP attribute" \
+ " {} for route: {} in router: {}" \
+ ", expected value: {} but found" \
+ ": {}".format(
+ criteria, net, router, comm_val,
+ show_val)
+ return errormsg
+
+ if not found:
+ errormsg = (
+ "Large Community attribute is not found for route: "
+ "{} in router: {} ".format(net, router))
+ return errormsg
+
+ logger.debug("Exiting lib API: verify_bgp_community()")
return True
diff --git a/tests/topotests/lib/topojson.py b/tests/topotests/lib/topojson.py
index 7a00fe4c50..fff5a1e82f 100644
--- a/tests/topotests/lib/topojson.py
+++ b/tests/topotests/lib/topojson.py
@@ -35,6 +35,7 @@ from lib.common_config import (
create_static_routes,
create_prefix_lists,
create_route_maps,
+ create_bgp_community_lists
)
from lib.bgp import create_router_bgp
@@ -179,6 +180,7 @@ def build_config_from_json(tgen, topo, save_bkup=True):
("links", create_interfaces_cfg),
("static_routes", create_static_routes),
("prefix_lists", create_prefix_lists),
+ ("bgp_community_list", create_bgp_community_lists),
("route_maps", create_route_maps),
("bgp", create_router_bgp)
])
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index a762e9555c..08126f6885 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -2422,6 +2422,53 @@ DEFUN (vtysh_show_error_code,
return CMD_SUCCESS;
}
+/* Northbound. */
+DEFUN (show_yang_operational_data,
+ show_yang_operational_data_cmd,
+ "show yang operational-data XPATH$xpath\
+ [{\
+ format <json$json|xml$xml>\
+ |translate WORD$translator_family\
+ }]" DAEMONS_LIST,
+ SHOW_STR
+ "YANG information\n"
+ "Show YANG operational data\n"
+ "XPath expression specifying the YANG data path\n"
+ "Set the output format\n"
+ "JavaScript Object Notation\n"
+ "Extensible Markup Language\n"
+ "Translate operational data\n"
+ "YANG module translator\n"
+ DAEMONS_STR)
+{
+ int idx_protocol = argc - 1;
+ char *fcmd = argv_concat(argv, argc - 1, 0);
+ int ret = vtysh_client_execute_name(argv[idx_protocol]->text, fcmd);
+ XFREE(MTYPE_TMP, fcmd);
+ return ret;
+}
+
+DEFUNSH(VTYSH_ALL, debug_nb,
+ debug_nb_cmd,
+ "[no] debug northbound\
+ [<\
+ callbacks$cbs [{configuration$cbs_cfg|state$cbs_state|rpc$cbs_rpc}]\
+ |notifications$notifications\
+ |events$events\
+ >]",
+ NO_STR
+ DEBUG_STR
+ "Northbound debugging\n"
+ "Callbacks\n"
+ "Configuration\n"
+ "State\n"
+ "RPC\n"
+ "Notifications\n"
+ "Events\n")
+{
+ return CMD_SUCCESS;
+}
+
/* Memory */
DEFUN (vtysh_show_memory,
vtysh_show_memory_cmd,
@@ -2548,10 +2595,11 @@ DEFUNSH(VTYSH_ALL, vtysh_log_facility, vtysh_log_facility_cmd,
}
DEFUNSH(VTYSH_ALL, no_vtysh_log_facility, no_vtysh_log_facility_cmd,
- "no log facility [FACILITY]", NO_STR
+ "no log facility [<kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7>]",
+ NO_STR
"Logging control\n"
"Reset syslog facility to default (daemon)\n"
- "Syslog facility\n")
+ LOG_FACILITY_DESC)
{
return CMD_SUCCESS;
}
@@ -4017,6 +4065,11 @@ void vtysh_init_vty(void)
install_element(ENABLE_NODE, &vtysh_debug_memstats_cmd);
install_element(CONFIG_NODE, &vtysh_debug_memstats_cmd);
+ /* northbound */
+ install_element(VIEW_NODE, &show_yang_operational_data_cmd);
+ install_element(ENABLE_NODE, &debug_nb_cmd);
+ install_element(CONFIG_NODE, &debug_nb_cmd);
+
/* misc lib show commands */
install_element(VIEW_NODE, &vtysh_show_memory_cmd);
install_element(VIEW_NODE, &vtysh_show_modules_cmd);
diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang
index 3313dc2f20..faa880eff4 100644
--- a/yang/frr-isisd.yang
+++ b/yang/frr-isisd.yang
@@ -61,6 +61,13 @@ module frr-isisd {
"This type defines IS-IS level of an object.";
}
+ typedef extended-circuit-id {
+ type uint32;
+ description
+ "This type defines the extended circuit ID
+ associated with an interface.";
+ }
+
typedef network-type {
type enumeration {
enum "unknown" {
@@ -95,6 +102,20 @@ module frr-isisd {
pattern, An example LSP ID is 0143.0438.AeF0.02-01";
}
+ typedef snpa {
+ type string {
+ length "0 .. 20";
+ }
+ description
+ "This type defines the Subnetwork Point
+ of Attachment (SNPA) format.
+ The SNPA should be encoded according to the rules
+ specified for the particular type of subnetwork
+ being used. As an example, for an ethernet subnetwork,
+ the SNPA is encoded as a MAC address like
+ '00aa.bbcc.ddee'.";
+ }
+
typedef system-id {
type string {
pattern "[0-9A-Fa-f]{4}\\.[0-9A-Fa-f]{4}\\.[0-9A-Fa-f]{4}";
@@ -275,6 +296,399 @@ module frr-isisd {
}
}
+ grouping interface-config {
+ description "Interface configuration grouping";
+
+ leaf area-tag {
+ type string;
+ mandatory true;
+ description
+ "Area-tag associated to this circuit.";
+ }
+
+ leaf ipv4-routing {
+ type boolean;
+ default "false";
+ description
+ "Routing IS-IS IPv4 traffic over this circuit.";
+ }
+
+ leaf ipv6-routing {
+ type boolean;
+ default "false";
+ description
+ "Routing IS-IS IPv6 traffic over this circuit.";
+ }
+
+ leaf circuit-type {
+ type level;
+ default "level-1-2";
+ description
+ "IS-type of this circuit.";
+ }
+
+ leaf bfd-monitoring {
+ type boolean;
+ default false;
+ description "Monitor IS-IS peers on this circuit.";
+ }
+
+ container csnp-interval {
+ description
+ "Complete Sequence Number PDU (CSNP) generation interval.";
+ leaf level-1 {
+ type uint16 {
+ range "1..600";
+ }
+ units "seconds";
+ default "10";
+ description
+ "CNSP interval for level-1";
+ }
+
+ leaf level-2 {
+ type uint16 {
+ range "1..600";
+ }
+ units "seconds";
+ default "10";
+ description
+ "CNSP interval for level-2";
+ }
+ }
+
+ container psnp-interval {
+ description
+ "Partial Sequence Number PDU (PSNP) generation interval.";
+ leaf level-1 {
+ type uint16 {
+ range "1..120";
+ }
+ units "seconds";
+ default "2";
+ description
+ "PNSP interval for level-1";
+ }
+
+ leaf level-2 {
+ type uint16 {
+ range "1..120";
+ }
+ units "seconds";
+ default "2";
+ description
+ "PCNSP interval for level-2";
+ }
+ }
+
+ container hello {
+ description
+ "Parameters related to IS-IS hello PDUs.";
+ leaf padding {
+ type boolean;
+ default "true";
+ description
+ "Add padding to IS-IS hello PDUs.";
+ }
+
+ container interval {
+ description
+ "Interval between consecutive hello messages.";
+ leaf level-1 {
+ type uint32 {
+ range "1..600";
+ }
+ units "seconds";
+ default "3";
+ description
+ "Holding time for level-1; interval will depend on multiplier.";
+ }
+
+ leaf level-2 {
+ type uint32 {
+ range "1..600";
+ }
+ units "seconds";
+ default "3";
+ description
+ "Holding time for level-2; interval will depend on multiplier.";
+ }
+ }
+
+ container multiplier {
+ description
+ "Multiplier for the hello messages holding time.";
+ leaf level-1 {
+ type uint16 {
+ range "2..100";
+ }
+ default "10";
+ description
+ "Multiplier for the hello holding time.";
+ }
+
+ leaf level-2 {
+ type uint16 {
+ range "2..100";
+ }
+ default "10";
+ description
+ "Multiplier for the hello holding time.";
+ }
+ }
+ }
+
+ container metric {
+ description
+ "Default metric for this IS-IS circuit.";
+ leaf level-1 {
+ type uint32 {
+ range "0..16777215";
+ }
+ must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'";
+ default "10";
+ description
+ "Default level-1 metric for this IS-IS circuit.";
+ }
+
+ leaf level-2 {
+ type uint32 {
+ range "0..16777215";
+ }
+ must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'";
+ default "10";
+ description
+ "Default level-2 metric for this IS-IS circuit.";
+ }
+ }
+
+ container priority {
+ description
+ "Priority for Designated Router election.";
+ leaf level-1 {
+ type uint8 {
+ range "0..127";
+ }
+ default "64";
+ description
+ "Level-1 priority for this IS-IS circuit.";
+ }
+
+ leaf level-2 {
+ type uint8 {
+ range "0..127";
+ }
+ default "64";
+ description
+ "Level-2 priority for this IS-IS circuit.";
+ }
+ }
+
+ leaf network-type {
+ type network-type;
+ default "broadcast";
+ must "(. = \"point-to-point\") or (. = \"broadcast\")";
+ description
+ "Explicitly configured type of IS-IS circuit (broadcast or point-to-point).";
+ }
+
+ leaf passive {
+ type boolean;
+ default "false";
+ description
+ "Interface is in passive mode.";
+ }
+
+ container password {
+ presence "Present if a password is set for this IS interface.";
+ uses isis-password;
+ }
+
+ leaf disable-three-way-handshake {
+ type boolean;
+ default "false";
+ description
+ "Disables three-way handshake when creating new adjacencies.";
+ }
+
+ container multi-topology {
+ description
+ "IS-IS topologies configured on this circuit.";
+ leaf ipv4-unicast {
+ type boolean;
+ default "true";
+ description
+ "IPv4 unicast topology.";
+ }
+
+ leaf ipv4-multicast {
+ type boolean;
+ default "true";
+ description
+ "IPv4 multicast topology.";
+ }
+
+ leaf ipv4-management {
+ type boolean;
+ default "true";
+ description
+ "IPv4 management topology.";
+ }
+
+ leaf ipv6-unicast {
+ type boolean;
+ default "true";
+ description
+ "IPv6 unicast topology.";
+ }
+
+ leaf ipv6-multicast {
+ type boolean;
+ default "true";
+ description
+ "IPv6 multicast topology.";
+ }
+
+ leaf ipv6-management {
+ type boolean;
+ default "true";
+ description
+ "IPv6 management topology.";
+ }
+
+ leaf ipv6-dstsrc {
+ type boolean;
+ default "true";
+ description
+ "IPv6 destination-source topology.";
+ }
+ }
+ }
+
+ grouping adjacency-state {
+ container adjacencies {
+ config false;
+ list adjacency {
+ leaf neighbor-sys-type {
+ type level;
+ description
+ "Level capability of neighboring system";
+ }
+ leaf neighbor-sysid {
+ type system-id;
+ description
+ "The system-id of the neighbor";
+ }
+ leaf neighbor-extended-circuit-id {
+ type extended-circuit-id;
+ description
+ "Circuit ID of the neighbor";
+ }
+ leaf neighbor-snpa {
+ type snpa;
+ description
+ "SNPA of the neighbor";
+ }
+ leaf hold-timer {
+ type uint16;
+ units seconds;
+ description
+ "The holding time in seconds for this
+ adjacency. This value is based on
+ received hello PDUs and the elapsed
+ time since receipt.";
+ }
+ leaf neighbor-priority {
+ type uint8 {
+ range "0 .. 127";
+ }
+ description
+ "Priority of the neighboring IS for becoming
+ the DIS.";
+ }
+ leaf state {
+ type adj-state-type;
+ description
+ "This leaf describes the state of the interface.";
+ }
+
+ description
+ "List of operational adjacencies.";
+ }
+ description
+ "This container lists the adjacencies of
+ the local node.";
+ }
+ description
+ "Adjacency state";
+ }
+
+ grouping event-counters {
+ container event-counters {
+ config false;
+ leaf adjacency-changes {
+ type uint32;
+ description
+ "The number of times an adjacency state change has
+ occurred on this interface.";
+ }
+ leaf adjacency-number {
+ type uint32;
+ description
+ "The number of adjacencies on this interface.";
+ }
+ leaf init-fails {
+ type uint32;
+ description
+ "The number of times initialization of this
+ interface has failed. This counts events such
+ as PPP NCP failures. Failures to form an
+ adjacency are counted by adjacency-rejects.";
+ }
+ leaf adjacency-rejects {
+ type uint32;
+ description
+ "The number of times an adjacency has been
+ rejected on this interface.";
+ }
+ leaf id-len-mismatch {
+ type uint32;
+ description
+ "The number of times an IS-IS PDU with an ID
+ field length different from that for this
+ system has been received on this interface.";
+ }
+ leaf max-area-addresses-mismatch {
+ type uint32;
+ description
+ "The number of times an IS-IS PDU has been
+ received on this interface with the
+ max area address field differing from that of
+ this system.";
+ }
+ leaf authentication-type-fails {
+ type uint32;
+ description
+ "Number of authentication type mismatches.";
+ }
+ leaf authentication-fails {
+ type uint32;
+ description
+ "Number of authentication key failures.";
+ }
+ description "IS-IS interface event counters.";
+ }
+ description
+ "Grouping for IS-IS interface event counters";
+ }
+
+ grouping interface-state {
+ description
+ "IS-IS interface operational state.";
+ uses adjacency-state;
+ uses event-counters;
+ }
+
grouping notification-instance-hdr {
description
"Instance specific IS-IS notification data grouping";
@@ -313,7 +727,7 @@ module frr-isisd {
}
leaf extended-circuit-id {
- type uint32;
+ type extended-circuit-id;
description
"Eextended circuit-id of the interface.";
}
@@ -733,270 +1147,8 @@ module frr-isisd {
presence "Present if an IS-IS circuit is defined for this interface.";
description
"IS-IS interface parameters.";
- leaf area-tag {
- type string;
- mandatory true;
- description
- "Area-tag associated to this circuit.";
- }
-
- leaf ipv4-routing {
- type boolean;
- default "false";
- description
- "Routing IS-IS IPv4 traffic over this circuit.";
- }
-
- leaf ipv6-routing {
- type boolean;
- default "false";
- description
- "Routing IS-IS IPv6 traffic over this circuit.";
- }
-
- leaf circuit-type {
- type level;
- default "level-1-2";
- description
- "IS-type of this circuit.";
- }
-
- leaf bfd-monitoring {
- type boolean;
- default false;
- description "Monitor IS-IS peers on this circuit.";
- }
-
- container csnp-interval {
- description
- "Complete Sequence Number PDU (CSNP) generation interval.";
- leaf level-1 {
- type uint16 {
- range "1..600";
- }
- units "seconds";
- default "10";
- description
- "CNSP interval for level-1";
- }
-
- leaf level-2 {
- type uint16 {
- range "1..600";
- }
- units "seconds";
- default "10";
- description
- "CNSP interval for level-2";
- }
- }
-
- container psnp-interval {
- description
- "Partial Sequence Number PDU (PSNP) generation interval.";
- leaf level-1 {
- type uint16 {
- range "1..120";
- }
- units "seconds";
- default "2";
- description
- "PNSP interval for level-1";
- }
-
- leaf level-2 {
- type uint16 {
- range "1..120";
- }
- units "seconds";
- default "2";
- description
- "PCNSP interval for level-2";
- }
- }
-
- container hello {
- description
- "Parameters related to IS-IS hello PDUs.";
- leaf padding {
- type boolean;
- default "true";
- description
- "Add padding to IS-IS hello PDUs.";
- }
-
- container interval {
- description
- "Interval between consecutive hello messages.";
- leaf level-1 {
- type uint32 {
- range "1..600";
- }
- units "seconds";
- default "3";
- description
- "Holding time for level-1; interval will depend on multiplier.";
- }
-
- leaf level-2 {
- type uint32 {
- range "1..600";
- }
- units "seconds";
- default "3";
- description
- "Holding time for level-2; interval will depend on multiplier.";
- }
- }
-
- container multiplier {
- description
- "Multiplier for the hello messages holding time.";
- leaf level-1 {
- type uint16 {
- range "2..100";
- }
- default "10";
- description
- "Multiplier for the hello holding time.";
- }
-
- leaf level-2 {
- type uint16 {
- range "2..100";
- }
- default "10";
- description
- "Multiplier for the hello holding time.";
- }
- }
- }
-
- container metric {
- description
- "Default metric for this IS-IS circuit.";
- leaf level-1 {
- type uint32 {
- range "0..16777215";
- }
- must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'";
- default "10";
- description
- "Default level-1 metric for this IS-IS circuit.";
- }
-
- leaf level-2 {
- type uint32 {
- range "0..16777215";
- }
- must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'";
- default "10";
- description
- "Default level-2 metric for this IS-IS circuit.";
- }
- }
-
- container priority {
- description
- "Priority for Designated Router election.";
- leaf level-1 {
- type uint8 {
- range "0..127";
- }
- default "64";
- description
- "Level-1 priority for this IS-IS circuit.";
- }
-
- leaf level-2 {
- type uint8 {
- range "0..127";
- }
- default "64";
- description
- "Level-2 priority for this IS-IS circuit.";
- }
- }
-
- leaf network-type {
- type network-type;
- default "broadcast";
- must "(. = \"point-to-point\") or (. = \"broadcast\")";
- description
- "Explicitly configured type of IS-IS circuit (broadcast or point-to-point).";
- }
-
- leaf passive {
- type boolean;
- default "false";
- description
- "Interface is in passive mode.";
- }
-
- container password {
- presence "Present if a password is set for this IS interface.";
- uses isis-password;
- }
-
- leaf disable-three-way-handshake {
- type boolean;
- default "false";
- description
- "Disables three-way handshake when creating new adjacencies.";
- }
-
- container multi-topology {
- description
- "IS-IS topologies configured on this circuit.";
- leaf ipv4-unicast {
- type boolean;
- default "true";
- description
- "IPv4 unicast topology.";
- }
-
- leaf ipv4-multicast {
- type boolean;
- default "true";
- description
- "IPv4 multicast topology.";
- }
-
- leaf ipv4-management {
- type boolean;
- default "true";
- description
- "IPv4 management topology.";
- }
-
- leaf ipv6-unicast {
- type boolean;
- default "true";
- description
- "IPv6 unicast topology.";
- }
-
- leaf ipv6-multicast {
- type boolean;
- default "true";
- description
- "IPv6 multicast topology.";
- }
-
- leaf ipv6-management {
- type boolean;
- default "true";
- description
- "IPv6 management topology.";
- }
-
- leaf ipv6-dstsrc {
- type boolean;
- default "true";
- description
- "IPv6 destination-source topology.";
- }
- }
+ uses interface-config;
+ uses interface-state;
}
}
diff --git a/yang/frr-nexthop.yang b/yang/frr-nexthop.yang
new file mode 100644
index 0000000000..00ba02a3c3
--- /dev/null
+++ b/yang/frr-nexthop.yang
@@ -0,0 +1,200 @@
+module frr-nexthop {
+ yang-version 1.1;
+ namespace "http://frrouting.org/yang/nexthop";
+ prefix frr-nexthop;
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+
+ import ietf-routing-types {
+ prefix rt-types;
+ }
+
+ organization
+ "Free Range Routing";
+ contact
+ "FRR Users List: <mailto:frog@lists.frrouting.org>
+ FRR Development List: <mailto:dev@lists.frrouting.org>";
+ description
+ "This module defines a model for managing FRR nexthop information.";
+
+ revision 2019-08-15 {
+ description
+ "Initial revision.";
+ }
+
+ typedef gateway-address {
+ type inet:ip-address;
+ }
+
+ typedef nexthop-type {
+ type enumeration {
+ enum "ifindex" {
+ value 1;
+ description
+ "Specific interface.";
+ }
+ enum "ip4" {
+ value 2;
+ description
+ "IPv4 address.";
+ }
+ enum "ip4-ifindex" {
+ value 3;
+ description
+ "IPv4 address and interface.";
+ }
+ enum "ip6" {
+ value 4;
+ description
+ "IPv6 address.";
+ }
+ enum "ip6-ifindex" {
+ value 5;
+ description
+ "IPv6 address and interface.";
+ }
+ enum "blackhole" {
+ value 6;
+ description
+ "Unreachable or prohibited.";
+ }
+ }
+ description
+ "Nexthop types.";
+ }
+
+ typedef blackhole-type {
+ type enumeration {
+ enum "unspec" {
+ value 0;
+ description
+ "Generic unreachable.";
+ }
+ enum "null" {
+ value 1;
+ description
+ "Null type.";
+ }
+ enum "reject" {
+ value 2;
+ description
+ "ICMP unreachable.";
+ }
+ enum "prohibited" {
+ value 3;
+ description
+ "ICMP admin-prohibited.";
+ }
+ }
+ default "null";
+ description
+ "Nexthop blackhole types.";
+ }
+
+ /*
+ * Nexthop object
+ */
+ grouping frr-nexthop {
+ leaf nh-type {
+ type nexthop-type;
+ mandatory true;
+ description
+ "The nexthop type.";
+ }
+
+ leaf gateway {
+ type gateway-address;
+ description
+ "The nexthop gateway address.";
+ }
+
+ leaf vrf {
+ type string;
+ description
+ "The nexthop vrf name, if different from the route.";
+ }
+
+ leaf interface {
+ type string;
+ description
+ "The nexthop egress interface.";
+ }
+
+ leaf bh-type {
+ type blackhole-type;
+ description
+ "A blackhole sub-type, if the nexthop is a blackhole type.";
+ }
+
+ leaf flags {
+ type uint32;
+ description
+ "The nexthop's raw flags value.";
+ }
+
+ leaf is-duplicate {
+ type empty;
+ description
+ "Duplicate nexthop; will be ignored.";
+ }
+ leaf is-recursive {
+ type empty;
+ description
+ "Nexthop must be resolved through another gateway.";
+ }
+ leaf is-onlink {
+ type empty;
+ description
+ "Nexthop is directly connected.";
+ }
+ leaf is-active {
+ type empty;
+ description
+ "Nexthop is active.";
+ }
+
+ uses rt-types:mpls-label-stack {
+ description
+ "Nexthop's MPLS label stack.";
+ }
+
+ leaf mtu {
+ type uint32;
+ description
+ "The nexthop's specific MTU.";
+ }
+
+ } // End of nexthop
+
+ /*
+ * Nexthop-group container
+ */
+ grouping frr-nexthop-group {
+ description
+ "A nexthop-group, represented as a list of nexthop objects.";
+
+ leaf name {
+ type string;
+ description
+ "The nexthop-group name.";
+ }
+
+ list entry {
+ key "id";
+ description
+ "A list of nexthop objects.";
+ leaf id {
+ type uint32;
+ description
+ "Identifies a nexthop within a nexthop group; the entries
+ are ordered by id value, and the value has no other meaning.";
+ }
+
+ uses frr-nexthop;
+
+ }
+ } // End of frr-nexthop-group
+
+}
diff --git a/yang/frr-zebra.yang b/yang/frr-zebra.yang
new file mode 100644
index 0000000000..b5ca5c9a40
--- /dev/null
+++ b/yang/frr-zebra.yang
@@ -0,0 +1,1788 @@
+module frr-zebra {
+ yang-version 1.1;
+ namespace "http://frrouting.org/yang/zebra";
+ prefix frr-zebra;
+
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+
+ import frr-route-types {
+ prefix frr-route-types;
+ }
+
+ import ietf-routing-types {
+ prefix rt-types;
+ }
+
+ import frr-nexthop {
+ prefix frr-nh;
+ }
+
+ import frr-interface {
+ prefix frr-interface;
+ }
+
+ organization
+ "Free Range Routing";
+ contact
+ "FRR Users List: <mailto:frog@lists.frrouting.org>
+ FRR Development List: <mailto:dev@lists.frrouting.org>";
+ description
+ "This module defines a model for managing the FRR zebra daemon.";
+
+ revision 2019-06-01 {
+ description
+ "Initial revision.";
+ }
+
+ typedef unix-timestamp {
+ type uint32;
+ units "seconds";
+ description
+ "An absolute time in seconds since the unix epoch.";
+ }
+
+ /*
+ * Multicast RPF mode configurable type
+ */
+ typedef mcast-rpf-lookup-mode {
+ type enumeration {
+ enum "none" {
+ value 0;
+ description
+ "No mode set.";
+ }
+ enum "mrib-only" {
+ value 1;
+ description
+ "Lookup in unicast RIB only.";
+ }
+ enum "urib-only" {
+ value 2;
+ description
+ "Lookup in multicast RIB only.";
+ }
+ enum "mrib-then-urib" {
+ value 3;
+ description
+ "Try multicast RIB first, fall back to unicast RIB.";
+ }
+ enum "lower-distance" {
+ value 4;
+ description
+ "Lookup both unicast and mcast, use entry with lower distance.";
+ }
+ enum "longer-prefix" {
+ value 5;
+ description
+ "Lookup both unicast and mcast, use entry with longer prefix.";
+ }
+ }
+ description
+ "Multicast RPF lookup behavior";
+ }
+
+ /*
+ * Common route data, shared by v4 and v6 routes.
+ */
+ grouping route-common {
+ description
+ "Common information about a route.";
+
+ leaf vrf {
+ type string;
+ description
+ "The route's vrf name.";
+ }
+
+ leaf distance {
+ type uint8;
+ description
+ "Admin distance based on routing protocol.";
+ }
+ leaf metric {
+ type uint32;
+ description
+ "Route metric value.";
+ }
+ leaf tag {
+ type uint32 {
+ range "1..4294967295";
+ }
+ description
+ "Route tag value.";
+ }
+
+ leaf is-selected {
+ type empty;
+ description
+ "Route is the selected or preferred route for the prefix.";
+ }
+ leaf is-installed {
+ type empty;
+ description
+ "Route is installed in the FIB.";
+ }
+ leaf is-failed {
+ type empty;
+ description
+ "Route installation in FIB has failed.";
+ }
+ leaf is-queued {
+ type empty;
+ description
+ "Route has a pending FIB operation that has not completed.";
+ }
+
+ leaf internal-flags {
+ type int32;
+ description
+ "Internal flags for the route.";
+ }
+ leaf internal-status {
+ type int32;
+ description
+ "Internal status for the route.";
+ }
+
+ leaf uptime {
+ type uint32;
+ units "seconds";
+ description
+ "Uptime for the route.";
+ }
+
+ container nexthop-group {
+ description
+ "Nexthop information for the route.";
+
+ uses frr-nh:frr-nexthop-group;
+ }
+
+ } // End of route-common
+
+ /*
+ * IPv4 Route object.
+ */
+ grouping ip4-route {
+ description
+ "An IPv4 route.";
+
+ leaf prefix {
+ type inet:ipv4-prefix;
+ description
+ "IP address (in the form A.B.C.D) and prefix length,
+ separated by the slash (/) character. The range of
+ values for the prefix-length is 0 to 32.";
+ }
+ leaf "protocol" {
+ type frr-route-types:frr-route-types-v4;
+ description
+ "The protocol owning the route.";
+ }
+
+ uses route-common;
+
+ } // End of ip4-route
+
+ /*
+ * IPv6 Route object.
+ */
+ grouping ip6-route {
+ description
+ "An IPv6 route.";
+
+ leaf prefix {
+ type inet:ipv6-prefix;
+ description
+ "The route's IPv6 prefix.";
+ }
+ leaf "protocol" {
+ type frr-route-types:frr-route-types-v6;
+ description
+ "The protocol owning the route.";
+ }
+
+ uses route-common;
+
+ } // End of ip6-route
+
+ /*
+ * VxLAN Network Identifier type
+ */
+ typedef vni-id-type {
+ type uint32 {
+ range "0..16777215";
+ }
+ description
+ "A VxLAN network identifier value.";
+ }
+
+ typedef vni-vtep-flood-type {
+ type enumeration {
+ enum "head-end-repl" {
+ value 0;
+ description
+ "Head-end replication.";
+ }
+ enum "disabled" {
+ value 1;
+ description
+ "Flooding disabled.";
+ }
+ enum pim-sm {
+ value 2;
+ description
+ "Multicast PIM-SM.";
+ }
+ }
+ }
+
+ /*
+ * Information about EVPN VNIs
+ */
+ grouping vni-information {
+ choice type-choice {
+ case l2 {
+ leaf is-layer2 {
+ type empty;
+ description
+ "Information about an L2 VNI.";
+ }
+ leaf vtep-count {
+ type uint32;
+ description
+ "Number of VTEPs.";
+ }
+ }
+ case l3 {
+ leaf is-layer3 {
+ type empty;
+ description
+ "Information about an L3 VNI.";
+ }
+ }
+ }
+ leaf vni-id {
+ type vni-id-type;
+ description
+ "The VNI identifier.";
+ }
+ leaf vxlan-ifname {
+ type frr-interface:interface-ref;
+ description
+ "The VxLAN interface name.";
+ }
+ leaf mac-count {
+ type uint32;
+ description
+ "Number of valid MACs.";
+ }
+ leaf neighbor-count {
+ type uint32;
+ description
+ "Number of neighbors.";
+ }
+ leaf vrf {
+ type string;
+ description
+ "The tenant VRF.";
+ }
+ leaf local-vtep-addr {
+ type inet:ipv4-address;
+ description
+ "The local VTEP IP address.";
+ }
+ }
+
+ /*
+ * Detailed EVPN VNI information for L2.
+ */
+ grouping vni-l2-detail {
+ leaf if-index {
+ type uint32;
+ description
+ "The VxLAN ifindex.";
+ }
+ leaf advertise-gw {
+ type empty;
+ description
+ "The gateway MAC-IP is being advertised.";
+ }
+ leaf mcase-group {
+ type rt-types:ipv4-multicast-group-address;
+ description
+ "The VNI multicast group for BUM traffic.";
+ }
+ list remote-vtep-list {
+ leaf remote-vtep {
+ type inet:ipv4-address;
+ description
+ "The remote VTEP IP address.";
+ }
+ leaf vtep-flood {
+ type vni-vtep-flood-type;
+ }
+ }
+ }
+
+ /*
+ * Detailed EVPN VNI information for L3.
+ */
+ grouping vni-l3-detail {
+ leaf svi-interface {
+ type string;
+ description
+ "The SVI interface.";
+ }
+ leaf is-up {
+ type empty;
+ description
+ "The state is active.";
+ }
+ leaf prefix-only {
+ type empty;
+ description
+ "Prefix routes only";
+ }
+ leaf router-mac {
+ type yang:mac-address;
+ description
+ "The VNI Router MAC address.";
+ }
+ list vni-list {
+ description
+ "A list of the associated L2 VNIs.";
+ leaf vni-id {
+ type vni-id-type;
+ description
+ "An L2 VNI identifier.";
+ }
+ }
+ }
+
+ /*
+ * Debug options
+ */
+ grouping zebra-debugs {
+ leaf debug-events {
+ type boolean;
+ description "Debug ZAPI events.";
+ }
+ leaf debug-zapi-send {
+ type boolean;
+ description "Debug ZAPI messages sent.";
+ }
+ leaf debug-zapi-recv {
+ type boolean;
+ description "Debug ZAPI messages received.";
+ }
+ leaf debug-zapi-detail {
+ type boolean;
+ description "Debug ZAPI details.";
+ }
+ leaf debug-kernel {
+ type boolean;
+ description "Debug kernel events.";
+ }
+ leaf debug-kernel-msg-send {
+ type boolean;
+ description "Debug kernel messages sent.";
+ }
+ leaf debug-kernel-msg-recv {
+ type boolean;
+ description "Debug kernel messages received.";
+ }
+ leaf debug-rib {
+ type boolean;
+ description "Debug RIB processing.";
+ }
+ leaf debug-rib-detail {
+ type boolean;
+ description "Debug RIB processing details.";
+ }
+ leaf debug-fpm {
+ type boolean;
+ description "Debug the FIB Push Interface subsystem.";
+ }
+ leaf debug-nht {
+ type boolean;
+ description "Debug Nexthop-tracking.";
+ }
+ leaf debug-nht-detail {
+ type boolean;
+ description "Debug Nexthop-tracking details.";
+ }
+ leaf debug-mpls {
+ type boolean;
+ description "Debug MPLS.";
+ }
+ leaf debug-vxlan {
+ type boolean;
+ description "Debug VxLAN.";
+ }
+ leaf debug-pw {
+ type boolean;
+ description "Debug pseudowires.";
+ }
+ leaf debug-dplane {
+ type boolean;
+ description "Debug the dataplane subsystem.";
+ }
+ leaf debug-dplane-detail {
+ type boolean;
+ description "Debug dataplane subsystem details.";
+ }
+ leaf debug-mlag {
+ type boolean;
+ description "Debug MLAG.";
+ }
+ }
+
+ /*
+ * Main zebra container
+ */
+ container zebra {
+ description
+ "Data model for the Zebra daemon.";
+
+ leaf mcast-rpf-lookup {
+ type frr-zebra:mcast-rpf-lookup-mode;
+ default "mrib-then-urib";
+ description
+ "Multicast RPF lookup behavior.";
+ }
+
+ leaf ip-forwarding {
+ type boolean;
+ description
+ "IP forwarding status.";
+ }
+
+ leaf ipv6-forwarding {
+ type enumeration {
+ enum "unknown" {
+ value -1;
+ description
+ "Unknown state.";
+ }
+ enum "off" {
+ value 0;
+ description
+ "IPv6 forwarding disabled.";
+ }
+ enum "on" {
+ value 1;
+ description
+ "IPv6 forwarding enabled.";
+ }
+ }
+ description
+ "IPv6 forwarding status.";
+ }
+
+ leaf workqueue-hold-timer {
+ type uint32 {
+ range "0..10000";
+ }
+ units "milliseconds";
+ default "10";
+ description
+ "Work-queue processing hold timer, in milliseconds.";
+ }
+
+ leaf zapi-packets {
+ type uint32 {
+ range "1..10000";
+ }
+ default "1000";
+ description
+ "Number of ZAPI packets to process before relinquishing
+ the main thread.";
+ }
+
+ container import-kernel-table {
+ description
+ "Parameters to use when importing IPv4 routes from a non-main kernel
+ routing table.";
+
+ leaf table-id {
+ type uint32 {
+ range "1..252";
+ }
+ description
+ "The kernel table id.";
+ }
+ leaf distance {
+ type uint32 {
+ range "1..255";
+ }
+ default "15";
+ description
+ "The admin distance to use for imported routes.";
+ }
+ leaf route-map {
+ type string;
+ description
+ "A route-map to filter imported routes.";
+ }
+ }
+
+ leaf allow-external-route-update {
+ type empty;
+ description
+ "Allow FRR-controlled routes to be overwritten by external processes";
+ }
+
+ leaf dplane-queue-limit {
+ type uint32 {
+ range "0..10000";
+ }
+ default "200";
+ description
+ "Limit on the number of updates queued to the dataplane subsystem.";
+ }
+
+ list vrf-vni-mapping {
+ description
+ "EVPN VNI mapping corresponding to a VRF.";
+ key "vrf-id";
+ leaf vrf-id {
+ type uint32;
+ description
+ "The identifier for a VRF.";
+ }
+ leaf vni-id {
+ type vni-id-type;
+ description
+ "The VNI id to map to the VRF.";
+ }
+ leaf prefix-only {
+ type empty;
+ description
+ "Prefix routes only.";
+ }
+ }
+
+ /*
+ * Debug options
+ */
+ container debugs {
+ uses zebra-debugs;
+ } /* End of debugs */
+
+ /*
+ * End of configuration attributes
+ */
+
+ /*
+ * Operational data.
+ */
+ container state {
+ config false;
+ description
+ "Operational data.";
+
+ } // End of operational / state container
+
+ } // End of zebra container
+
+ /*
+ * RPCs
+ */
+ rpc get-route-information {
+ description
+ "Retrieve IPv4 or IPv6 unicast routes.";
+
+ input {
+
+ choice ip-type {
+ case v4 {
+ leaf ipv4 {
+ type empty;
+ mandatory true;
+ description
+ "Retrieve IPv4 routes.";
+ }
+ leaf prefix-v4 {
+ type inet:ipv4-prefix;
+ description
+ "Retrieve routes matching a specific prefix.";
+ }
+ leaf supernets-only {
+ type empty;
+ description
+ "Skip routes that are subnets of classful prefix sizes.";
+ }
+ }
+ case v6 {
+ leaf ipv6 {
+ type empty;
+ mandatory true;
+ description
+ "Retrieve IPv6 routes.";
+ }
+ leaf prefix-v6 {
+ type inet:ipv6-prefix;
+ description
+ "Retrieve routes matching a specific prefix.";
+ }
+ }
+ }
+
+ choice vrf-choice {
+ case single {
+ leaf vrf {
+ type string;
+ description
+ "Retrieve routes in a non-default vrf.";
+ }
+ }
+ case all {
+ leaf all-vrfs {
+ type empty;
+ description
+ "Retrieve routes from all vrfs.";
+ }
+ }
+ }
+
+ leaf fib-routes {
+ type empty;
+ description
+ "Retrieve FIB routes rather than RIB routes.";
+ }
+
+ leaf table-id {
+ type uint32 {
+ range "1..4294967295";
+ }
+ description
+ "Routing table id to retrieve.";
+ }
+
+ leaf protocol {
+ type frr-route-types:frr-route-types-v4;
+ description
+ "Retrieve routes from a specific protocol daemon.";
+ }
+ leaf ospf-instance {
+ type uint32 {
+ range "1..65535";
+ }
+ must '../protocol = "ospf"';
+ description
+ "Retrieve routes from a specific OSPF instance.";
+ }
+
+ choice detail {
+ case det {
+ leaf include-detail {
+ type empty;
+ description
+ "Include detailed information.";
+ }
+ }
+ case summ {
+ leaf summary {
+ type empty;
+ description
+ "Include summary information only.";
+ }
+ }
+ }
+ } // End of input
+
+ output {
+ choice route-list {
+ case v4 {
+ container routes-v4 {
+ description
+ "IPv4 route information.";
+ list route {
+ uses ip4-route;
+ }
+ }
+ }
+ case v6 {
+ container routes-v6 {
+ description
+ "IPv6 route information.";
+ list route {
+ uses ip6-route;
+ }
+ }
+ }
+ }
+ } // End of output
+
+ } // End get-route-information
+
+ rpc get-v6-mroute-info {
+ description
+ "Retrieve IPv6 multicast routes.";
+
+ input {
+ choice vrf-choice {
+ case single {
+ leaf vrf {
+ type string;
+ description
+ "Retrieve routes in a non-default vrf.";
+ }
+ }
+ case all {
+ leaf all-vrfs {
+ type empty;
+ description
+ "Retrieve routes from all vrfs.";
+ }
+ }
+ }
+ }
+
+ output {
+ container routes {
+ description
+ "IPv6 mcast route information.";
+ list route {
+ uses ip6-route;
+ }
+ }
+ }
+
+ }// End get-v6-mroute-info
+
+
+ rpc get-vrf-info {
+ description
+ "Retrieve VRF information; the default VRF is elided.";
+
+ // Note: no input clause.
+
+ output {
+ list vrf-list {
+ leaf name {
+ type string;
+ description
+ "The VRF name";
+ }
+ leaf is-user-config {
+ type empty;
+ description
+ "The VRF was configured by an admin.";
+ }
+ leaf vrf-id {
+ type uint32;
+ description
+ "The VRF id.";
+ }
+ choice vrf-type {
+ case inactive {
+ leaf is-inactive {
+ type empty;
+ description
+ "The VRF is inactive.";
+ }
+ }
+ case netns {
+ leaf netns-name {
+ type string;
+ description
+ "The net namespace name associated with the VRF.";
+ }
+ }
+ case table {
+ leaf table-id {
+ type uint32;
+ description
+ "The table-id associated with the VRF.";
+ }
+ }
+ }
+ }
+ }
+ } // End get-vrf-info
+
+ rpc get-vrf-vni-info {
+ description
+ "Retrieve mappings between EVPN VNI and VRF.";
+
+ // Note: no input clause.
+
+ output {
+ list vrf-vni-list {
+ leaf vrf-name {
+ type string;
+ description
+ "The VRF name.";
+ }
+ leaf vni-id {
+ type vni-id-type;
+ description
+ "The EVPN VNI.";
+ }
+ leaf vxlan-if-name {
+ type frr-interface:interface-ref;
+ description
+ "The VxLAN interface name.";
+ }
+ leaf svi-if-name {
+ type frr-interface:interface-ref;
+ description
+ "The SVI interface name.";
+ }
+ leaf router-mac-addr {
+ type yang:mac-address;
+ description
+ "Router MAC address.";
+ }
+ leaf is-up {
+ type empty;
+ description
+ "The state is active.";
+ }
+ }
+ }
+ } // End get-vrf-vni-info
+
+ rpc get-evpn-info {
+ description
+ "Retrieve global information about EVPN.";
+
+ // Note: No input clause.
+
+ output {
+ leaf l2vni-count {
+ type uint32;
+ description
+ "Number of L2 VNIs.";
+ }
+ leaf l3vni-count {
+ type uint32;
+ description
+ "Number of L3 VNIs.";
+ }
+ leaf advertise-gateway {
+ type empty;
+ description
+ "Advertise the gateway MAC-IP.";
+ }
+ leaf advertise-svi {
+ type empty;
+ description
+ "Advertise SVI MAC-IP.";
+ }
+ leaf dup-detect {
+ type empty;
+ description
+ "Duplicate address detection is enabled.";
+ }
+ leaf dad-max-moves {
+ type uint32;
+ description
+ "Maximum moves allowed before address is considered duplicate.";
+ }
+ leaf dad-timeout {
+ type uint32;
+ units "seconds";
+ description
+ "Duplicate address detection timeout.";
+ }
+ leaf dad-freeze {
+ type empty;
+ description
+ "Duplicate address detection freeze enabled.";
+ }
+
+ choice dad-freeze-choice {
+ case freeze-permanent {
+ leaf dad-freeze-perm {
+ type empty;
+ description
+ "Duplicate address detection freeze is permanent.";
+ }
+ }
+ case freeze-time {
+ leaf dad-freeze-time {
+ type uint32;
+ units "seconds";
+ description
+ "Duplicate address detection freeze timer.";
+ }
+ }
+ }
+ }
+ } // End get-evpn-info
+
+ rpc get-vni-info {
+ // If no vni is specified, retrieve global list.
+ input {
+ choice vni-choice {
+ default "all-vnis";
+ case all-vnis {
+ leaf all-vnis {
+ type empty;
+ description
+ "Retrieve information about all VNIs.";
+ }
+ }
+ case single-vni {
+ leaf vni-id {
+ type vni-id-type;
+ description
+ "Retrieve information about a specific EVPN VNI.";
+ }
+ }
+ }
+ leaf detailed-info {
+ type empty;
+ description
+ "Retrieve detailed information.";
+ }
+ }
+
+ output {
+ list vni-list {
+ description
+ "Information about EVPN VNI objects.";
+
+ uses vni-information;
+
+ choice detail-choice {
+ case l2 {
+ description
+ "Detailed L2 information.";
+ uses vni-l2-detail;
+ }
+ case l3 {
+ description
+ "Detailed L3 information.";
+ uses vni-l3-detail;
+ }
+ }
+ }
+ }
+ } // End get-vni-info
+
+ rpc get-evpn-vni-rmac {
+ description
+ "Retrieve information about VxLAN VNI RMACs.";
+
+ input {
+ choice vni-choice {
+ default "all-vnis";
+ case all-vnis {
+ leaf all-vnis {
+ type empty;
+ description
+ "Retrieve information about all VNIs.";
+ }
+ }
+ case single-vni {
+ leaf vni-id {
+ type vni-id-type;
+ description
+ "Retrieve information about a specific EVPN VNI.";
+ }
+ leaf vni-rmac {
+ type yang:mac-address;
+ description
+ "A single RMAC address.";
+ }
+ }
+ }
+ }
+
+ output {
+ list rmac-info-list {
+ leaf rmac {
+ type yang:mac-address;
+ description
+ "The RMAC address.";
+ }
+ leaf remote-vtep {
+ type inet:ipv4-address;
+ description
+ "The remote VTEP IP address.";
+ }
+ leaf refcount {
+ type uint32;
+ description
+ "The refcount of the RMAC.";
+ }
+ list prefix-list {
+ leaf prefix-item {
+ type inet:ip-prefix;
+ description
+ "IP prefixes associated with the RMAC.";
+ }
+ }
+ }
+ }
+ } // End get-evpn-vni-rmac
+
+ rpc get-evpn-vni-nexthops {
+ description
+ "Retrieve information about EVPN nexthops.";
+
+ input {
+ choice vni-choice {
+ default "all-vnis";
+ case all-vnis {
+ leaf all-vnis {
+ type empty;
+ description
+ "Retrieve information about all VNIs.";
+ }
+ }
+ case single-vni {
+ leaf vni-id {
+ type vni-id-type;
+ description
+ "Retrieve information about a specific EVPN VNI.";
+ }
+ leaf vni-ipaddr {
+ type inet:ip-address;
+ description
+ "A single host IP address (v4 or v6).";
+ }
+ }
+ }
+ }
+
+ output {
+ list nh-info-list {
+ leaf ip-addr {
+ type inet:ip-address;
+ description
+ "The nexthop IP address.";
+ }
+ leaf mac-addr {
+ type yang:mac-address;
+ description
+ "The nexthop MAC address.";
+ }
+ leaf refcount {
+ type uint32;
+ description
+ "The refcount of the RMAC.";
+ }
+ list prefix-list {
+ leaf prefix-item {
+ type inet:ip-prefix;
+ description
+ "IP prefixes associated with the RMAC.";
+ }
+ }
+ }
+ }
+ } // End get-evpn-vni-vteps
+
+ rpc clear-evpn-dup-addr {
+ description
+ "Clear duplicate address detection state for one or all VNIs.";
+ input {
+ choice clear-dup-choice {
+ case all-case {
+ leaf all-vnis {
+ type empty;
+ description
+ "Clear all VNIs.";
+ }
+ }
+ case single-case {
+ leaf vni-id {
+ type vni-id-type;
+ description
+ "Clear state for a single EVPN VNI.";
+ }
+ choice ip-mac-choice {
+ description
+ "Clear state for a specific MAC or IP address.";
+ case ip-case {
+ leaf vni-ipaddr {
+ type inet:ip-address;
+ description
+ "A specific IP address (v4 or v6).";
+ }
+ }
+ case mac-case {
+ leaf mac-addr {
+ type yang:mac-address;
+ description
+ "A specific MAC address.";
+ }
+ }
+ }
+ }
+ }
+ }
+ } // End clear-evpn-dup-addr
+
+ rpc get-evpn-macs {
+ description
+ "Retrieve information about EVPN MAC addresses.";
+ input {
+ choice all-choice {
+ default "all-vni";
+
+ case all-vni {
+ leaf all-vnis {
+ type empty;
+ description
+ "Retrieve information for all VNIs.";
+ }
+ choice all-choices {
+ case detail-case {
+ leaf all-detail {
+ type empty;
+ description
+ "Include detailed results.";
+ }
+ }
+ case vtep-case {
+ leaf all-vtep-addr {
+ type inet:ipv4-address;
+ description
+ "A single VTEP address.";
+ }
+ }
+ case dup-case {
+ leaf all-dup {
+ type empty;
+ description
+ "Show duplicate addresses.";
+ }
+ }
+ }
+ }
+ case single-vni {
+ leaf vni-id {
+ type vni-id-type;
+ description
+ "Retrieve information for a single VNI.";
+ }
+ choice single-choices {
+ case detail-case {
+ leaf single-detail {
+ type empty;
+ description
+ "Include detailed results.";
+ }
+ }
+ case mac-case {
+ leaf single-mac {
+ type yang:mac-address;
+ description
+ "A specific MAC address.";
+ }
+ }
+ case vtep-case {
+ leaf single-vtep {
+ type inet:ipv4-address;
+ description
+ "A single VTEP address.";
+ }
+ }
+ case dup-case {
+ leaf single-dup {
+ type empty;
+ description
+ "Show duplicate addresses.";
+ }
+ }
+ }
+ }
+ }
+ } // End of input section
+
+ output {
+ list mac-list {
+ leaf mac-addr {
+ type yang:mac-address;
+ description
+ "The MAC address.";
+ }
+ leaf vni {
+ type vni-id-type;
+ description
+ "The VNI value.";
+ }
+ leaf local-sequence {
+ type uint32;
+ description
+ "Local sequence number.";
+ }
+ leaf remote-sequence {
+ type uint32;
+ description
+ "Remote sequence number.";
+ }
+ leaf dad-count {
+ type uint32;
+ description
+ "Duplicate detection counter.";
+ }
+ leaf is-duplicate {
+ type empty;
+ description
+ "Duplicate MAC detected.";
+ }
+ leaf dup-detect-time {
+ type unix-timestamp;
+ description
+ "If a duplicate, the detection time.";
+ }
+ container dup-detect-started {
+ leaf dup-detect-start {
+ type unix-timestamp;
+ description
+ "Duplicate detection process start time.";
+ }
+ leaf dup-count {
+ type uint32;
+ description
+ "Duplicate detection count.";
+ }
+ }
+
+ leaf is-auto {
+ type empty;
+ description
+ "This is an Auto MAC.";
+ }
+ leaf is-sticky {
+ type empty;
+ description
+ "This is a sticky MAC.";
+ }
+ leaf is-default-gw {
+ type empty;
+ description
+ "This is a default-gateway MAC.";
+ }
+ leaf is-remote-gw {
+ type empty;
+ description
+ "This is a remote-gateway MAC.";
+ }
+ list neighbor-list {
+ leaf neighbor-addr {
+ type inet:ip-address;
+ description
+ "Neighbor address.";
+ }
+ leaf is-active {
+ type empty;
+ description
+ "Neighbor is active.";
+ }
+ }
+
+ leaf mac-count {
+ type uint32;
+ description
+ "Number of MACs (local and remote).";
+ }
+ choice local-rem-choice {
+ case local-case {
+ leaf intf {
+ type frr-interface:interface-ref;
+ description
+ "The local interface name.";
+ }
+ leaf vlan {
+ type uint32;
+ description
+ "A VLAN id.";
+ }
+ }
+ case remote-case {
+ leaf vtep-addr {
+ type inet:ipv4-address;
+ description
+ "The remote VTEP IP address.";
+ }
+ }
+ }
+ }
+ }
+ } // End get-evpn-macs
+
+ rpc get-evpn-arp-cache {
+ description
+ "Retrieve information about EVPN neighbor cache entries.";
+ input {
+ choice all-choice {
+ default "all-vni";
+
+ case all-vni {
+ leaf all-vnis {
+ type empty;
+ description
+ "Retrieve information for all VNIs.";
+ }
+ choice all-choices {
+ case detail-case {
+ leaf all-detail {
+ type empty;
+ description
+ "Include detailed results.";
+ }
+ }
+ case dup-case {
+ leaf all-dup {
+ type empty;
+ description
+ "Show duplicates.";
+ }
+ }
+ }
+ }
+ case single-vni {
+ leaf vni-id {
+ type vni-id-type;
+ description
+ "Retrieve information for a single VNI.";
+ }
+ choice single-choices {
+ case vtep-case {
+ leaf single-vtep {
+ type inet:ipv4-address;
+ description
+ "A single VTEP address.";
+ }
+ }
+ case neighbor-case {
+ leaf neighbor-addr {
+ type inet:ip-address;
+ description
+ "A single neighbor address.";
+ }
+ }
+ case dup-case {
+ leaf single-dup {
+ type empty;
+ description
+ "Show duplicates.";
+ }
+ }
+ }
+ }
+ }
+ } // End input section
+
+ output {
+ list vni-list {
+ container vni-container {
+ description
+ "Information for one VNI.";
+ leaf vni-id {
+ type vni-id-type;
+ description
+ "The VNI id.";
+ }
+ list neigh-list {
+ description
+ "Information about a VNI's neighbor cache.";
+
+ leaf mac-addr {
+ type yang:mac-address;
+ description
+ "A neighbor MAC address.";
+ }
+ leaf ip-addr {
+ type inet:ip-address;
+ description
+ "A neighbor IP address.";
+ }
+ leaf state-active {
+ type empty;
+ description
+ "Indicates whether the entry is active.";
+ }
+
+ choice local-remote-choice {
+ case local-case {
+ leaf is-local {
+ type empty;
+ description
+ "The entry is local.";
+ }
+ }
+ case remote-case {
+ leaf is-remote {
+ type empty;
+ description
+ "The entry is remote.";
+ }
+ }
+ }
+
+ leaf is-dup {
+ type empty;
+ description
+ "The entry is a detected duplicate.";
+ }
+ leaf is-default-gw {
+ type empty;
+ description
+ "The entry is a default gateway.";
+ }
+ leaf is-router {
+ type empty;
+ description
+ "The entry is a router.";
+ }
+ leaf local-sequence {
+ type uint32;
+ description
+ "The local sequence number.";
+ }
+ leaf remote-sequence {
+ type uint32;
+ description
+ "The remote sequence number.";
+ }
+ leaf remote-vtep {
+ type inet:ipv4-address;
+ description
+ "The remote VTEP address.";
+ }
+ }
+ }
+ }
+ }
+ } // End get-evpn-arp-cache
+
+ rpc get-pbr-ipset {
+ input {
+ leaf name {
+ type string;
+ description
+ "An optional specific IPset name.";
+ }
+ }
+
+ output {
+ list ipset-list {
+ leaf name {
+ type string;
+ description
+ "The IPset name.";
+ }
+ leaf ipset-type {
+ type enumeration {
+ enum "net-net" {
+ value 1;
+ description
+ "";
+ }
+ enum "net-port-net" {
+ value 2;
+ description
+ "";
+ }
+ enum "net-port" {
+ value 3;
+ description
+ "";
+ }
+ enum "net" {
+ value 4;
+ description
+ "";
+ }
+ }
+ }
+ leaf src-prefix {
+ type inet:ip-prefix;
+ description
+ "";
+ }
+ leaf dest-prefix {
+ type inet:ip-prefix;
+ description
+ "";
+ }
+ leaf src-port {
+ type inet:port-number;
+ description
+ "";
+ }
+ leaf dest-port {
+ type inet:port-number;
+ description
+ "";
+ }
+
+ choice proto-choice {
+ description
+ "Filter UDP/TCP only, or a specific protocol number.";
+ case udp-tcp-case {
+ leaf is-udp-tcp {
+ type empty;
+ description
+ "Filter TCP/UDP ports only.";
+ }
+ }
+ case proto-case {
+ leaf proto {
+ type uint32;
+ description
+ "Filter a specific protocol number.";
+ }
+ }
+ }
+ container icmp-info {
+ description
+ "Additional information for ICMP filters.";
+ leaf type-min {
+ type uint8;
+ description
+ "";
+ }
+ leaf type-max {
+ type uint8;
+ description
+ "";
+ }
+ leaf code-min {
+ type uint8;
+ description
+ "";
+ }
+ leaf code-max {
+ type uint8;
+ description
+ "";
+ }
+ }
+ container ipset-stats {
+ leaf is-unique {
+ type empty;
+ description
+ "";
+ }
+ leaf packet-counter {
+ type uint64;
+ description
+ "";
+ }
+ leaf bytes-counter {
+ type uint64;
+ description
+ "";
+ }
+ }
+ }
+ }
+ } // End get-pbr-ipset
+
+ rpc get-pbr-iptable {
+ input {
+ leaf name {
+ type string;
+ description
+ "An optional single IPtable name.";
+ }
+ }
+
+ output {
+ list iptable-list {
+ leaf name {
+ type string;
+ description
+ "The IPtable name.";
+ }
+ leaf unique-val {
+ type uint32;
+ description
+ "";
+ }
+ choice action-choice {
+ description "The table action.";
+ case drop-case {
+ leaf action-drop {
+ type empty;
+ description "";
+ }
+ }
+ case redirect-case {
+ leaf action-redirect {
+ type empty;
+ description "";
+ }
+ }
+ }
+ leaf min-packet {
+ type uint32;
+ description
+ "";
+ }
+ leaf max-packet {
+ type uint32;
+ description
+ "";
+ }
+ leaf lookup-src-port {
+ type empty;
+ description
+ "";
+ }
+ leaf lookup-dst-port {
+ type empty;
+ description
+ "";
+ }
+ leaf tcp-flags {
+ type uint16;
+ description
+ "";
+ }
+ leaf tcp-flags-mask {
+ type uint16;
+ description
+ "";
+ }
+ leaf protocol-val {
+ type uint32;
+ description "An IP protocol number.";
+ }
+ container dscp-info {
+ leaf dscp-value {
+ type uint32;
+ description
+ "A DSCP value to match.";
+ }
+ leaf invert-match {
+ type empty;
+ description
+ "If set, exclude the specified value";
+ }
+ }
+ container fragment-info {
+ leaf fragment-val {
+ type uint32;
+ description "An IP fragment value.";
+ }
+ leaf invert-match {
+ type empty;
+ description
+ "If set, exclude the specified value.";
+ }
+ }
+ container iptable-stats {
+ leaf packet-counter {
+ type uint64;
+ description
+ "";
+ }
+ leaf bytes-counter {
+ type uint64;
+ description
+ "";
+ }
+ }
+ container rule-info {
+ description
+ "Information about a rule, for redirect tables.";
+ leaf table-id {
+ type uint32;
+ description
+ "The rule table id.";
+ }
+ leaf table-fwmark {
+ type uint32;
+ description
+ "The firewall mark for the rule.";
+ }
+ }
+ }
+ }
+ } // End get-pbr-iptable
+
+ /*
+ * Handy 'all-at-once' api to retrieve debugs
+ */
+ rpc get-debugs {
+ output {
+ uses zebra-debugs;
+ }
+ } // End get-debugs
+
+ augment "/frr-interface:lib/frr-interface:interface" {
+ description
+ "Extends interface model with Zebra-related parameters.";
+ container zebra {
+ list ip4-addr-list {
+ description
+ "IPv4 prefixes for an interface.";
+ key "ip4-prefix";
+ leaf ip4-prefix {
+ type inet:ipv4-prefix;
+ description
+ "IPv4 address prefix.";
+ }
+ leaf ip4-peer {
+ type inet:ipv4-prefix;
+ description
+ "Peer prefix, for peer-to-peer interfaces.";
+ }
+ leaf label {
+ type string;
+ description
+ "Optional string label for the address.";
+ }
+ }
+ list ip6-addr-list {
+ description
+ "IPv6 prefixes for an interface.";
+ key "ip6-prefix";
+ leaf ip6-prefix {
+ type inet:ipv6-prefix;
+ description
+ "IPv6 address prefix.";
+ }
+ leaf label {
+ type string;
+ description
+ "Optional string label for the address.";
+ }
+ }
+
+ leaf multicast {
+ type boolean;
+ description
+ "Multicast flag for the interface.";
+ }
+ leaf link-detect {
+ type boolean;
+ description
+ "Link-detection for the interface.";
+ }
+ leaf shutdown {
+ type boolean;
+ description
+ "Interface admin status.";
+ }
+ leaf bandwidth {
+ type uint32 {
+ range "1..100000";
+ }
+ description
+ "Link bandwidth informational parameter, in megabits.";
+ }
+
+ // TODO -- link-params for (experimental/partial TE use in IGP extensions)
+
+ }
+ } // End interface model augmentation
+
+}
diff --git a/zebra/connected.c b/zebra/connected.c
index 6b92945c63..87cf8c8f20 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -385,7 +385,7 @@ void connected_down(struct interface *ifp, struct connected *ifc)
return;
break;
default:
- zlog_info("Unknown AFI: %s", afi2str(afi));
+ zlog_warn("Unknown AFI: %s", afi2str(afi));
break;
}
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index bb6b9973bf..35cb3a6f5f 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -365,7 +365,7 @@ static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb,
}
}
-static int get_iflink_speed(struct interface *interface)
+static int get_iflink_speed(struct interface *interface, int *error)
{
struct ifreq ifdata;
struct ethtool_cmd ecmd;
@@ -373,6 +373,8 @@ static int get_iflink_speed(struct interface *interface)
int rc;
const char *ifname = interface->name;
+ if (error)
+ *error = 0;
/* initialize struct */
memset(&ifdata, 0, sizeof(ifdata));
@@ -393,6 +395,9 @@ static int get_iflink_speed(struct interface *interface)
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("Failure to read interface %s speed: %d %s",
ifname, errno, safe_strerror(errno));
+ /* no vrf socket creation may probably mean vrf issue */
+ if (error)
+ *error = -1;
return 0;
}
/* Get the current link state for the interface */
@@ -404,6 +409,9 @@ static int get_iflink_speed(struct interface *interface)
zlog_debug(
"IOCTL failure to read interface %s speed: %d %s",
ifname, errno, safe_strerror(errno));
+ /* no device means interface unreachable */
+ if (errno == ENODEV && error)
+ *error = -1;
ecmd.speed_hi = 0;
ecmd.speed = 0;
}
@@ -413,9 +421,9 @@ static int get_iflink_speed(struct interface *interface)
return (ecmd.speed_hi << 16) | ecmd.speed;
}
-uint32_t kernel_get_speed(struct interface *ifp)
+uint32_t kernel_get_speed(struct interface *ifp, int *error)
{
- return get_iflink_speed(ifp);
+ return get_iflink_speed(ifp, error);
}
static int netlink_extract_bridge_info(struct rtattr *link_data,
@@ -696,7 +704,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
ifp->flags = ifi->ifi_flags & 0x0000fffff;
ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]);
ifp->metric = 0;
- ifp->speed = get_iflink_speed(ifp);
+ ifp->speed = get_iflink_speed(ifp, NULL);
ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
/* Set zebra interface type */
@@ -1032,7 +1040,8 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
/* addr is primary key, SOL if we don't have one */
if (addr == NULL) {
- zlog_debug("%s: NULL address", __func__);
+ zlog_debug("%s: Local Interface Address is NULL for %s",
+ __func__, ifp->name);
return -1;
}
diff --git a/zebra/interface.c b/zebra/interface.c
index baf94ad285..ef03cf87f6 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -70,10 +70,19 @@ static int if_zebra_speed_update(struct thread *thread)
struct zebra_if *zif = ifp->info;
uint32_t new_speed;
bool changed = false;
+ int error = 0;
zif->speed_update = NULL;
- new_speed = kernel_get_speed(ifp);
+ new_speed = kernel_get_speed(ifp, &error);
+
+ /* error may indicate vrf not available or
+ * interfaces not available.
+ * note that loopback & virtual interfaces can return 0 as speed
+ */
+ if (error < 0)
+ return 1;
+
if (new_speed != ifp->speed) {
zlog_info("%s: %s old speed: %u new speed: %u",
__PRETTY_FUNCTION__, ifp->name, ifp->speed,
@@ -261,8 +270,10 @@ struct interface *if_lookup_by_name_per_ns(struct zebra_ns *ns,
for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) {
ifp = (struct interface *)rn->info;
- if (ifp && strcmp(ifp->name, ifname) == 0)
+ if (ifp && strcmp(ifp->name, ifname) == 0) {
+ route_unlock_node(rn);
return (ifp);
+ }
}
return NULL;
@@ -1563,7 +1574,7 @@ struct cmd_node interface_node = {INTERFACE_NODE, "%s(config-if)# ", 1};
#endif
/* Show all interfaces to vty. */
DEFPY(show_interface, show_interface_cmd,
- "show interface [vrf NAME$name] [brief$brief]",
+ "show interface [vrf NAME$vrf_name] [brief$brief]",
SHOW_STR
"Interface status and configuration\n"
VRF_CMD_HELP_STR
@@ -1575,8 +1586,8 @@ DEFPY(show_interface, show_interface_cmd,
interface_update_stats();
- if (name)
- VRF_GET_ID(vrf_id, name, false);
+ if (vrf_name)
+ VRF_GET_ID(vrf_id, vrf_name, false);
/* All interface print. */
vrf = vrf_lookup_by_id(vrf_id);
@@ -2041,13 +2052,13 @@ DEFUN (link_params_enable,
/* This command could be issue at startup, when activate MPLS TE */
/* on a new interface or after a ON / OFF / ON toggle */
/* In all case, TE parameters are reset to their default factory */
- if (IS_ZEBRA_DEBUG_EVENT)
+ if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
zlog_debug(
"Link-params: enable TE link parameters on interface %s",
ifp->name);
if (!if_link_params_get(ifp)) {
- if (IS_ZEBRA_DEBUG_EVENT)
+ if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
zlog_debug(
"Link-params: failed to init TE link parameters %s",
ifp->name);
@@ -2070,8 +2081,9 @@ DEFUN (no_link_params_enable,
{
VTY_DECLVAR_CONTEXT(interface, ifp);
- zlog_debug("MPLS-TE: disable TE link parameters on interface %s",
- ifp->name);
+ if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS)
+ zlog_debug("MPLS-TE: disable TE link parameters on interface %s",
+ ifp->name);
if_link_params_free(ifp);
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 4f72e2414a..227226b5f9 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -119,7 +119,7 @@ static void zebra_redistribute(struct zserv *client, int type,
srcdest_rnode_prefixes(rn, &dst_p, &src_p);
- if (IS_ZEBRA_DEBUG_EVENT)
+ if (IS_ZEBRA_DEBUG_RIB)
zlog_debug(
"%s: client %s %s(%u) checking: selected=%d, type=%d, distance=%d, metric=%d zebra_check_addr=%d",
__func__,
@@ -201,7 +201,7 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p,
send_redistribute = 1;
if (send_redistribute) {
- if (IS_ZEBRA_DEBUG_EVENT) {
+ if (IS_ZEBRA_DEBUG_RIB) {
zlog_debug(
"%s: client %s %s(%u), type=%d, distance=%d, metric=%d",
__func__,
diff --git a/zebra/rt.h b/zebra/rt.h
index 59b42fed18..f311a6b9d3 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -66,7 +66,7 @@ extern int kernel_interface_set_master(struct interface *master,
extern int mpls_kernel_init(void);
-extern uint32_t kernel_get_speed(struct interface *ifp);
+extern uint32_t kernel_get_speed(struct interface *ifp, int *error);
extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);
/*
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 91a3024038..43e44cad16 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1440,6 +1440,7 @@ static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc)
static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
int llalen, ns_id_t ns_id)
{
+ uint8_t protocol = RTPROT_ZEBRA;
struct {
struct nlmsghdr n;
struct ndmsg ndm;
@@ -1460,6 +1461,8 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
req.ndm.ndm_ifindex = ifindex;
req.ndm.ndm_type = RTN_UNICAST;
+ addattr_l(&req.n, sizeof(req),
+ NDA_PROTOCOL, &protocol, sizeof(protocol));
addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4);
addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
@@ -1930,6 +1933,7 @@ int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx,
int cmd)
{
+ uint8_t protocol = RTPROT_ZEBRA;
struct {
struct nlmsghdr n;
struct ndmsg ndm;
@@ -1950,6 +1954,8 @@ static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx,
req.ndm.ndm_flags |= NTF_SELF; // Handle by "self", not "master"
+ addattr_l(&req.n, sizeof(req),
+ NDA_PROTOCOL, &protocol, sizeof(protocol));
addattr_l(&req.n, sizeof(req), NDA_LLADDR, &dst_mac, 6);
req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
@@ -2297,6 +2303,7 @@ int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
static enum zebra_dplane_result
netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx)
{
+ uint8_t protocol = RTPROT_ZEBRA;
struct {
struct nlmsghdr n;
struct ndmsg ndm;
@@ -2330,6 +2337,8 @@ netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx)
else
req.ndm.ndm_flags |= NTF_EXT_LEARNED;
+ addattr_l(&req.n, sizeof(req),
+ NDA_PROTOCOL, &protocol, sizeof(protocol));
addattr_l(&req.n, sizeof(req), NDA_LLADDR,
dplane_ctx_mac_get_addr(ctx), 6);
req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx);
@@ -2748,6 +2757,7 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
static int netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
int cmd)
{
+ uint8_t protocol = RTPROT_ZEBRA;
struct {
struct nlmsghdr n;
struct ndmsg ndm;
@@ -2782,6 +2792,8 @@ static int netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
req.ndm.ndm_type = RTN_UNICAST;
req.ndm.ndm_flags = flags;
+ addattr_l(&req.n, sizeof(req),
+ NDA_PROTOCOL, &protocol, sizeof(protocol));
ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN;
addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
if (mac)
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index dc0f29bdbc..981ef7a889 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -396,7 +396,7 @@ extern int kernel_interface_set_master(struct interface *master,
return 0;
}
-uint32_t kernel_get_speed(struct interface *ifp)
+uint32_t kernel_get_speed(struct interface *ifp, int *error)
{
return ifp->speed;
}
diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c
index 8cc5b52b34..711c4e0877 100644
--- a/zebra/rule_netlink.c
+++ b/zebra/rule_netlink.c
@@ -54,6 +54,7 @@
*/
static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)
{
+ uint8_t protocol = RTPROT_ZEBRA;
int family;
int bytelen;
struct {
@@ -78,6 +79,9 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)
req.frh.family = family;
req.frh.action = FR_ACT_TO_TBL;
+ addattr_l(&req.n, sizeof(req),
+ FRA_PROTOCOL, &protocol, sizeof(protocol));
+
/* rule's pref # */
addattr32(&req.n, sizeof(req), FRA_PRIORITY, rule->rule.priority);
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 12f8a1ae3d..bf343e06e5 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -2511,6 +2511,18 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed)
}
/*
+ * Helper for 'show run' etc.
+ */
+int dplane_config_write_helper(struct vty *vty)
+{
+ if (zdplane_info.dg_max_queued_updates != DPLANE_DEFAULT_MAX_QUEUED)
+ vty_out(vty, "zebra dplane limit %u\n",
+ zdplane_info.dg_max_queued_updates);
+
+ return 0;
+}
+
+/*
* Provider registration
*/
int dplane_provider_register(const char *name,
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 30dfdafdf5..be945632c1 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -455,6 +455,7 @@ uint32_t dplane_get_in_queue_len(void);
*/
int dplane_show_helper(struct vty *vty, bool detailed);
int dplane_show_provs_helper(struct vty *vty, bool detailed);
+int dplane_config_write_helper(struct vty *vty);
/*
* Dataplane providers: modules that process or consume dataplane events.
diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
index 4144c0afe0..5d88d4eeb4 100644
--- a/zebra/zebra_fpm.c
+++ b/zebra/zebra_fpm.c
@@ -711,7 +711,6 @@ static void zfpm_connection_down(const char *detail)
* Start thread to clean up state after the connection goes down.
*/
assert(!zfpm_g->t_conn_down);
- zfpm_debug("Starting conn_down thread");
zfpm_rnodes_iter_init(&zfpm_g->t_conn_down_state.iter);
zfpm_g->t_conn_down = NULL;
thread_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb, NULL, 0,
@@ -806,8 +805,6 @@ static int zfpm_read_cb(struct thread *thread)
goto done;
}
- zfpm_debug("Read out a full fpm message");
-
/*
* Just throw it away for now.
*/
@@ -1249,7 +1246,7 @@ static int zfpm_connect_cb(struct thread *t)
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
- zfpm_debug("Failed to create socket for connect(): %s",
+ zlog_err("Failed to create socket for connect(): %s",
strerror(errno));
zfpm_g->stats.connect_no_sock++;
return 0;
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 5428b6eaef..f0601012b6 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1046,14 +1046,18 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
struct nexthop *nexthop = NULL;
for (ALL_NEXTHOPS(alternate->ng, nexthop)) {
- if (if_is_loopback_or_vrf(if_lookup_by_index(
- nexthop->ifindex, alternate->vrf_id)))
+ struct interface *ifp = if_lookup_by_index(
+ nexthop->ifindex, alternate->vrf_id);
+
+ if (ifp && if_is_loopback_or_vrf(ifp))
return alternate;
}
for (ALL_NEXTHOPS(current->ng, nexthop)) {
- if (if_is_loopback_or_vrf(if_lookup_by_index(
- nexthop->ifindex, current->vrf_id)))
+ struct interface *ifp = if_lookup_by_index(
+ nexthop->ifindex, current->vrf_id);
+
+ if (ifp && if_is_loopback_or_vrf(ifp))
return current;
}
@@ -1556,7 +1560,9 @@ static bool rib_update_re_from_ctx(struct route_entry *re,
changed_p = true;
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
- break;
+
+ /* Keep checking nexthops */
+ continue;
}
if (CHECK_FLAG(ctx_nexthop->flags, NEXTHOP_FLAG_FIB)) {
@@ -1992,6 +1998,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
* not-installed; or not-installed to installed.
*/
if (start_count > 0 && end_count > 0) {
+ if (debug_p)
+ zlog_debug("%u:%s applied nexthop changes from dplane notification",
+ dplane_ctx_get_vrf(ctx), dest_str);
/* Changed nexthops - update kernel/others */
dplane_route_notif_update(rn, re,
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index bcaf1b5204..5df5d94f4b 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -337,7 +337,7 @@ static void addr2hostprefix(int af, const union g_addr *addr,
break;
default:
memset(prefix, 0, sizeof(*prefix));
- zlog_debug("%s: unknown address family %d", __func__, af);
+ zlog_warn("%s: unknown address family %d", __func__, af);
break;
}
}
@@ -916,7 +916,8 @@ void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
table = get_rnh_table(vrfid, afi, type);
if (!table) {
- zlog_debug("print_rnhs: rnh table not found");
+ if (IS_ZEBRA_DEBUG_NHT)
+ zlog_debug("print_rnhs: rnh table not found");
return;
}
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index 72d0b6866d..4f1868311c 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -92,7 +92,7 @@ static int zebra_vrf_new(struct vrf *vrf)
struct zebra_vrf *zvrf;
if (IS_ZEBRA_DEBUG_EVENT)
- zlog_info("VRF %s created, id %u", vrf->name, vrf->vrf_id);
+ zlog_debug("VRF %s created, id %u", vrf->name, vrf->vrf_id);
zvrf = zebra_vrf_alloc();
vrf->info = zvrf;
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 7984481093..5ce9d3f293 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -394,6 +394,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object *json_labels = NULL;
time_t uptime;
struct tm *tm;
+ struct vrf *vrf = NULL;
rib_dest_t *dest = rib_dest_from_rnode(rn);
struct nexthop_group *nhg;
@@ -422,9 +423,13 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_int_add(json_route, "instance",
re->instance);
- if (re->vrf_id)
+ if (re->vrf_id) {
json_object_int_add(json_route, "vrfId", re->vrf_id);
+ vrf = vrf_lookup_by_id(re->vrf_id);
+ json_object_string_add(json_route, "vrfName",
+ vrf->name);
+ }
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
json_object_boolean_true_add(json_route, "selected");
@@ -565,9 +570,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if ((nexthop->vrf_id != re->vrf_id)
&& (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
- struct vrf *vrf =
- vrf_lookup_by_id(nexthop->vrf_id);
-
+ vrf = vrf_lookup_by_id(nexthop->vrf_id);
json_object_string_add(json_nexthop, "vrf",
vrf->name);
}
@@ -2655,6 +2658,10 @@ static int config_write_protocol(struct vty *vty)
== MCAST_MIX_DISTANCE
? "lower-distance"
: "longer-prefix");
+
+ /* Include dataplane info */
+ dplane_config_write_helper(vty);
+
return 1;
}
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index c7f2976ace..2417b505ad 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -9153,6 +9153,11 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
if (zvni->advertise_svi_macip == advertise)
return;
+ /* Store flag even though SVI is not present.
+ * Once SVI comes up triggers self MAC-IP route add.
+ */
+ zvni->advertise_svi_macip = advertise;
+
ifp = zvni->vxlan_if;
if (!ifp)
return;
@@ -9164,20 +9169,17 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS)
return;
zl2_info = zif->l2info.vxl;
-
vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
zif->brslave_info.br_if);
if (!vlan_if)
return;
if (advertise) {
- zvni->advertise_svi_macip = advertise;
/* Add primary SVI MAC-IP */
zvni_add_macip_for_intf(vlan_if, zvni);
} else {
- /* Del primary MAC-IP */
+ /* Del primary SVI MAC-IP */
zvni_del_macip_for_intf(vlan_if, zvni);
- zvni->advertise_svi_macip = advertise;
}
}