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_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.c37
-rw-r--r--bgpd/bgpd.h2
-rwxr-xr-xconfigure.ac16
-rw-r--r--doc/user/bfd.rst8
-rw-r--r--docker/alpine/Dockerfile5
-rw-r--r--eigrpd/eigrp_network.c5
-rw-r--r--isisd/isis_northbound.c4
-rw-r--r--isisd/isis_te.c3
-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--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--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py11
-rw-r--r--yang/frr-nexthop.yang200
-rw-r--r--yang/frr-zebra.yang1788
-rw-r--r--zebra/if_netlink.c16
-rw-r--r--zebra/interface.c21
-rw-r--r--zebra/rt.h2
-rw-r--r--zebra/rt_socket.c2
-rw-r--r--zebra/zebra_dplane.c12
-rw-r--r--zebra/zebra_dplane.h1
-rw-r--r--zebra/zebra_rib.c7
-rw-r--r--zebra/zebra_vty.c4
-rw-r--r--zebra/zebra_vxlan.c10
45 files changed, 2559 insertions, 294 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_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..37360a559a 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);
}
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 c45a819362..88f1c4f627 100755
--- a/configure.ac
+++ b/configure.ac
@@ -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/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/isisd/isis_northbound.c b/isisd/isis_northbound.c
index ccd4cfbd1c..1e21efa7ce 100644
--- a/isisd/isis_northbound.c
+++ b/isisd/isis_northbound.c
@@ -1559,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;
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/lib/if.c b/lib/if.c
index 1e34ff4b84..fbab0004f9 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -1196,7 +1196,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)
@@ -1206,8 +1206,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
@@ -1216,7 +1216,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;
@@ -1227,24 +1227,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);
@@ -1267,20 +1267,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 692c84ad08..4d7c75a330 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -355,8 +355,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;
@@ -683,6 +681,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.
@@ -774,8 +775,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);
@@ -880,6 +880,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)
{
@@ -888,23 +901,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) {
@@ -913,6 +919,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)) {
@@ -1809,6 +1819,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;
@@ -1849,6 +1861,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;
@@ -1916,13 +1930,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/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 b0db23f54a..37cb12548c 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -1180,12 +1180,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];
@@ -1203,55 +1197,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/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/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/if_netlink.c b/zebra/if_netlink.c
index 08fa77923d..59ab8c9d33 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 */
diff --git a/zebra/interface.c b/zebra/interface.c
index bb808e1852..a724006e27 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;
@@ -1556,7 +1567,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
@@ -1568,8 +1579,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);
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_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/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_rib.c b/zebra/zebra_rib.c
index 5428b6eaef..98e66cd017 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -1556,7 +1556,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 +1994,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_vty.c b/zebra/zebra_vty.c
index 15f0398ca4..5ce9d3f293 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -2658,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;
}
}