Merge branch 'master' of https://github.com/frrouting/frr into pmsi-parse-display

This commit is contained in:
vivek 2018-03-13 17:50:08 +00:00
commit 783e95b8e8
49 changed files with 1817 additions and 1373 deletions

3
.gitignore vendored
View File

@ -82,3 +82,6 @@ GPATH
*.lo *.lo
compile_commands.json compile_commands.json
.dirstamp .dirstamp
# clippy generated source
*_clippy.c

36
alpine/APKBUILD.in Normal file
View File

@ -0,0 +1,36 @@
# Maintainer: Arthur Jones <arthur.jones@riverbed.com>
pkgname=frr
pkgver=@VERSION@
pkgrel=0
pkgdesc="Free Range Routing is a fork of quagga"
url="https://frrouting.org/"
arch="all"
license="GPL-2.0"
depends="iproute2 json-c c-ares ipsec-tools iproute2"
makedepends="ncurses-dev net-snmp-dev gawk texinfo perl
acct autoconf automake bash
binutils binutils-libs bison bsd-compat-headers build-base
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
libgomp libisoburn libisofs libltdl libressl libssh2
libstdc++ libtool libuuid 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"
subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg"
source="$pkgname-$pkgver.tar.gz"
builddir="$srcdir"/$pkgname-$pkgver
build() {
cd "$builddir"
./configure --prefix=/usr || return 1
make || return 1
}
package() {
cd "$builddir"
make DESTDIR="$pkgdir" install || return 1
}

1
bgpd/.gitignore vendored
View File

@ -16,4 +16,3 @@ TAGS
.arch-ids .arch-ids
*~ *~
*.loT *.loT
*clippy.c

View File

@ -474,6 +474,17 @@ static void derive_rd_rt_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
bgp_evpn_derive_auto_rt_export(bgp, vpn); bgp_evpn_derive_auto_rt_export(bgp, vpn);
} }
/*
* Convert nexthop (remote VTEP IP) into an IPv6 address.
*/
static void evpn_convert_nexthop_to_ipv6(struct attr *attr)
{
if (BGP_ATTR_NEXTHOP_AFI_IP6(attr))
return;
ipv4_to_ipv4_mapped_ipv6(&attr->mp_nexthop_global, attr->nexthop);
attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
}
/* /*
* Add (update) or delete MACIP from zebra. * Add (update) or delete MACIP from zebra.
*/ */
@ -622,17 +633,17 @@ static void build_evpn_type5_route_extcomm(struct bgp *bgp_vrf,
} }
/* /*
* Build extended communities for EVPN route. RT and ENCAP are * Build extended communities for EVPN route.
* applicable to all routes. * This function is applicable for type-2 and type-3 routes. The layer-2 RT
* TODO: currently kernel doesnt support ipv6 routes with ipv4 nexthops. * and ENCAP extended communities are applicable for all routes.
* This means that we can't do symmetric routing for ipv6 hosts routes * The default gateway extended community and MAC mobility (sticky) extended
* in the same way as ipv4 host routes. * community are added as needed based on passed settings - only for type-2
* We wont attach l3-vni related RTs for ipv6 routes. * routes. Likewise, the layer-3 RT and Router MAC extended communities are
* For now, We will only adevrtise ipv4 host routes * added, if present, based on passed settings - only for non-link-local
* with L3-VNI related ext-comm. * type-2 routes.
*/ */
static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr, static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
afi_t afi) int add_l3_ecomm)
{ {
struct ecommunity ecom_encap; struct ecommunity ecom_encap;
struct ecommunity ecom_sticky; struct ecommunity ecom_sticky;
@ -662,11 +673,10 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom))
attr->ecommunity = ecommunity_merge(attr->ecommunity, ecom); attr->ecommunity = ecommunity_merge(attr->ecommunity, ecom);
/* /* Add the export RTs for L3VNI if told to - caller determines
* only attach l3-vni export rts for ipv4 address family and if we are * when this should be done.
* advertising both the labels in type-2 routes
*/ */
if (afi == AFI_IP && CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS)) { if (add_l3_ecomm) {
vrf_export_rtl = bgpevpn_get_vrf_export_rtl(vpn); vrf_export_rtl = bgpevpn_get_vrf_export_rtl(vpn);
if (vrf_export_rtl && !list_isempty(vrf_export_rtl)) { if (vrf_export_rtl && !list_isempty(vrf_export_rtl)) {
for (ALL_LIST_ELEMENTS(vrf_export_rtl, node, nnode, for (ALL_LIST_ELEMENTS(vrf_export_rtl, node, nnode,
@ -676,6 +686,7 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
} }
} }
/* Add MAC mobility (sticky) if needed. */
if (attr->sticky) { if (attr->sticky) {
seqnum = 0; seqnum = 0;
memset(&ecom_sticky, 0, sizeof(ecom_sticky)); memset(&ecom_sticky, 0, sizeof(ecom_sticky));
@ -686,12 +697,8 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
ecommunity_merge(attr->ecommunity, &ecom_sticky); ecommunity_merge(attr->ecommunity, &ecom_sticky);
} }
/* /* Add RMAC, if told to. */
* only attach l3-vni rmac for ipv4 address family and if we are if (add_l3_ecomm) {
* advertising both the labels in type-2 routes
*/
if (afi == AFI_IP && !is_zero_mac(&attr->rmac)
&& CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS)) {
memset(&ecom_rmac, 0, sizeof(ecom_rmac)); memset(&ecom_rmac, 0, sizeof(ecom_rmac));
encode_rmac_extcomm(&eval_rmac, &attr->rmac); encode_rmac_extcomm(&eval_rmac, &attr->rmac);
ecom_rmac.size = 1; ecom_rmac.size = 1;
@ -700,6 +707,7 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr,
ecommunity_merge(attr->ecommunity, &ecom_rmac); ecommunity_merge(attr->ecommunity, &ecom_rmac);
} }
/* Add default gateway, if needed. */
if (attr->default_gw) { if (attr->default_gw) {
memset(&ecom_default_gw, 0, sizeof(ecom_default_gw)); memset(&ecom_default_gw, 0, sizeof(ecom_default_gw));
encode_default_gw_extcomm(&eval_default_gw); encode_default_gw_extcomm(&eval_default_gw);
@ -1260,6 +1268,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
struct bgp_node *rn; struct bgp_node *rn;
struct attr attr; struct attr attr;
struct attr *attr_new; struct attr *attr_new;
int add_l3_ecomm = 0;
struct bgp_info *ri; struct bgp_info *ri;
afi_t afi = AFI_L2VPN; afi_t afi = AFI_L2VPN;
safi_t safi = SAFI_EVPN; safi_t safi = SAFI_EVPN;
@ -1279,14 +1288,23 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE)
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL); attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
/* router mac is only needed for type-2 and type-5 routes */ /* router mac is only needed for type-2 routes here. */
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
bgpevpn_get_rmac(vpn, &attr.rmac); bgpevpn_get_rmac(vpn, &attr.rmac);
vni2label(vpn->vni, &(attr.label)); vni2label(vpn->vni, &(attr.label));
/* Set up RT and ENCAP extended community. */ /* Include L3 VNI related RTs and RMAC for type-2 routes, if they're
build_evpn_route_extcomm( * IPv4 or IPv6 global addresses and we're advertising L3VNI with
vpn, &attr, IS_EVPN_PREFIX_IPADDR_V4(p) ? AFI_IP : AFI_IP6); * these routes.
*/
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
(IS_EVPN_PREFIX_IPADDR_V4(p) ||
!IN6_IS_ADDR_LINKLOCAL(&p->prefix.ip.ipaddr_v6)) &&
CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS))
add_l3_ecomm = 1;
/* Set up extended community. */
build_evpn_route_extcomm(vpn, &attr, add_l3_ecomm);
/* First, create (or fetch) route node within the VNI. */ /* First, create (or fetch) route node within the VNI. */
/* NOTE: There is no RD here. */ /* NOTE: There is no RD here. */
@ -1466,22 +1484,20 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
struct attr attr; struct attr attr;
struct attr attr_sticky; struct attr attr_sticky;
struct attr attr_def_gw; struct attr attr_def_gw;
struct attr attr_ip6; struct attr attr_ip6_ll;
struct attr attr_sticky_ip6;
struct attr attr_def_gw_ip6;
struct attr *attr_new; struct attr *attr_new;
int add_l3_ecomm = 0;
afi = AFI_L2VPN; afi = AFI_L2VPN;
safi = SAFI_EVPN; safi = SAFI_EVPN;
memset(&attr, 0, sizeof(struct attr)); memset(&attr, 0, sizeof(struct attr));
memset(&attr_sticky, 0, sizeof(struct attr)); memset(&attr_sticky, 0, sizeof(struct attr));
memset(&attr_def_gw, 0, sizeof(struct attr)); memset(&attr_def_gw, 0, sizeof(struct attr));
memset(&attr_ip6, 0, sizeof(struct attr)); memset(&attr_ip6_ll, 0, sizeof(struct attr));
memset(&attr_sticky_ip6, 0, sizeof(struct attr));
memset(&attr_def_gw_ip6, 0, sizeof(struct attr));
/* Build path-attribute - all type-2 routes for this VNI will share the /* Build path-attribute - multiple type-2 routes for this VNI will share
* same path attribute. * the same path attribute, but we need separate structures for sticky
* MACs, default gateway and IPv6 link-local addresses (no L3 RT/RMAC).
*/ */
bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
bgp_attr_default_set(&attr_sticky, BGP_ORIGIN_IGP); bgp_attr_default_set(&attr_sticky, BGP_ORIGIN_IGP);
@ -1500,31 +1516,21 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
attr_def_gw.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; attr_def_gw.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr_def_gw.default_gw = 1; attr_def_gw.default_gw = 1;
bgpevpn_get_rmac(vpn, &attr_def_gw.rmac); bgpevpn_get_rmac(vpn, &attr_def_gw.rmac);
bgp_attr_default_set(&attr_ip6, BGP_ORIGIN_IGP); bgp_attr_default_set(&attr_ip6_ll, BGP_ORIGIN_IGP);
bgp_attr_default_set(&attr_sticky_ip6, BGP_ORIGIN_IGP); attr_ip6_ll.nexthop = vpn->originator_ip;
bgp_attr_default_set(&attr_def_gw_ip6, BGP_ORIGIN_IGP); attr_ip6_ll.mp_nexthop_global_in = vpn->originator_ip;
attr_ip6.nexthop = vpn->originator_ip; attr_ip6_ll.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr_ip6.mp_nexthop_global_in = vpn->originator_ip;
attr_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
bgpevpn_get_rmac(vpn, &attr_ip6.rmac);
attr_sticky_ip6.nexthop = vpn->originator_ip;
attr_sticky_ip6.mp_nexthop_global_in = vpn->originator_ip;
attr_sticky_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr_sticky_ip6.sticky = 1;
bgpevpn_get_rmac(vpn, &attr_sticky_ip6.rmac);
attr_def_gw_ip6.nexthop = vpn->originator_ip;
attr_def_gw_ip6.mp_nexthop_global_in = vpn->originator_ip;
attr_def_gw_ip6.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr_def_gw_ip6.default_gw = 1;
bgpevpn_get_rmac(vpn, &attr_def_gw_ip6.rmac);
/* Set up RT, ENCAP and sticky MAC extended community. */ /* Add L3 VNI RTs and RMAC for non IPv6 link-local attributes if
build_evpn_route_extcomm(vpn, &attr, AFI_IP); * using L3 VNI for type-2 routes also.
build_evpn_route_extcomm(vpn, &attr_sticky, AFI_IP); */
build_evpn_route_extcomm(vpn, &attr_def_gw, AFI_IP); if (CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS))
build_evpn_route_extcomm(vpn, &attr_ip6, AFI_IP6); add_l3_ecomm = 1;
build_evpn_route_extcomm(vpn, &attr_sticky_ip6, AFI_IP6);
build_evpn_route_extcomm(vpn, &attr_def_gw_ip6, AFI_IP); build_evpn_route_extcomm(vpn, &attr, add_l3_ecomm);
build_evpn_route_extcomm(vpn, &attr_sticky, add_l3_ecomm);
build_evpn_route_extcomm(vpn, &attr_def_gw, add_l3_ecomm);
build_evpn_route_extcomm(vpn, &attr_ip6_ll, 0);
/* Walk this VNI's route table and update local type-2 routes. For any /* Walk this VNI's route table and update local type-2 routes. For any
* routes updated, update corresponding entry in the global table too. * routes updated, update corresponding entry in the global table too.
@ -1538,7 +1544,11 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
continue; continue;
if (IS_EVPN_PREFIX_IPADDR_V4(evp)) { if (IS_EVPN_PREFIX_IPADDR_V6(evp) &&
IN6_IS_ADDR_LINKLOCAL(&evp->prefix.ip.ipaddr_v6))
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_ip6_ll, 0, 1, &ri, 0);
else {
if (evpn_route_is_sticky(bgp, rn)) if (evpn_route_is_sticky(bgp, rn))
update_evpn_route_entry(bgp, vpn, afi, safi, rn, update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_sticky, 0, 1, &ri, &attr_sticky, 0, 1, &ri,
@ -1550,19 +1560,6 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
else else
update_evpn_route_entry(bgp, vpn, afi, safi, rn, update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr, 0, 1, &ri, 0); &attr, 0, 1, &ri, 0);
} else {
if (evpn_route_is_sticky(bgp, rn))
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_sticky_ip6, 0, 1,
&ri, 0);
else if (evpn_route_is_def_gw(bgp, rn))
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_def_gw_ip6, 0, 1,
&ri, 0);
else
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_ip6, 0, 1, &ri,
0);
} }
/* If a local route exists for this prefix, we need to update /* If a local route exists for this prefix, we need to update
@ -1593,11 +1590,9 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
/* Unintern temporary. */ /* Unintern temporary. */
aspath_unintern(&attr.aspath); aspath_unintern(&attr.aspath);
aspath_unintern(&attr_ip6.aspath);
aspath_unintern(&attr_sticky.aspath); aspath_unintern(&attr_sticky.aspath);
aspath_unintern(&attr_sticky_ip6.aspath);
aspath_unintern(&attr_def_gw.aspath); aspath_unintern(&attr_def_gw.aspath);
aspath_unintern(&attr_def_gw_ip6.aspath); aspath_unintern(&attr_ip6_ll.aspath);
return 0; return 0;
} }
@ -1791,6 +1786,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
{ {
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_info *ri; struct bgp_info *ri;
struct attr attr;
struct attr *attr_new; struct attr *attr_new;
int ret = 0; int ret = 0;
struct prefix p; struct prefix p;
@ -1827,6 +1823,15 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
} else } else
return 0; return 0;
/* EVPN routes currently only support a IPv4 next hop which corresponds
* to the remote VTEP. When importing into a VRF, if it is IPv6 host
* route, we have to convert the next hop to an IPv4-mapped address
* for the rest of the code to flow through.
*/
bgp_attr_dup(&attr, parent_ri->attr);
if (afi == AFI_IP6)
evpn_convert_nexthop_to_ipv6(&attr);
/* Check if route entry is already present. */ /* Check if route entry is already present. */
for (ri = rn->info; ri; ri = ri->next) for (ri = rn->info; ri; ri = ri->next)
if (ri->extra if (ri->extra
@ -1835,7 +1840,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
if (!ri) { if (!ri) {
/* Add (or update) attribute to hash. */ /* Add (or update) attribute to hash. */
attr_new = bgp_attr_intern(parent_ri->attr); attr_new = bgp_attr_intern(&attr);
/* Create new route with its attribute. */ /* Create new route with its attribute. */
ri = info_make(parent_ri->type, parent_ri->sub_type, 0, ri = info_make(parent_ri->type, parent_ri->sub_type, 0,
@ -1850,21 +1855,25 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
} }
bgp_info_add(rn, ri); bgp_info_add(rn, ri);
} else { } else {
if (attrhash_cmp(ri->attr, parent_ri->attr) if (attrhash_cmp(ri->attr, &attr)
&& !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
bgp_unlock_node(rn); bgp_unlock_node(rn);
return 0; return 0;
} }
/* The attribute has changed. */ /* The attribute has changed. */
/* Add (or update) attribute to hash. */ /* Add (or update) attribute to hash. */
attr_new = bgp_attr_intern(parent_ri->attr); attr_new = bgp_attr_intern(&attr);
/* Restore route, if needed. */ /* Restore route, if needed. */
if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
bgp_info_restore(rn, ri); bgp_info_restore(rn, ri);
/* Mark if nexthop has changed. */ /* Mark if nexthop has changed. */
if (!IPV4_ADDR_SAME(&ri->attr->nexthop, &attr_new->nexthop)) if ((afi == AFI_IP &&
!IPV4_ADDR_SAME(&ri->attr->nexthop, &attr_new->nexthop)) ||
(afi == AFI_IP6 &&
!IPV6_ADDR_SAME(&ri->attr->mp_nexthop_global,
&attr_new->mp_nexthop_global)))
SET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED); SET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED);
/* Unintern existing, set to new. */ /* Unintern existing, set to new. */
@ -2577,10 +2586,12 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi,
static void delete_withdraw_vrf_routes(struct bgp *bgp_vrf) static void delete_withdraw_vrf_routes(struct bgp *bgp_vrf)
{ {
/* delete all ipv4 routes and withdraw from peers */ /* delete all ipv4 routes and withdraw from peers */
bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST); if (advertise_type5_routes(bgp_vrf, AFI_IP))
bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST);
/* delete all ipv6 routes and withdraw from peers */ /* delete all ipv6 routes and withdraw from peers */
bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST); if (advertise_type5_routes(bgp_vrf, AFI_IP6))
bgp_evpn_withdraw_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST);
} }
/* update and advertise all ipv4 and ipv6 routes in thr vrf table as type-5 /* update and advertise all ipv4 and ipv6 routes in thr vrf table as type-5
@ -2588,10 +2599,12 @@ static void delete_withdraw_vrf_routes(struct bgp *bgp_vrf)
static void update_advertise_vrf_routes(struct bgp *bgp_vrf) static void update_advertise_vrf_routes(struct bgp *bgp_vrf)
{ {
/* update all ipv4 routes */ /* update all ipv4 routes */
bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST); if (advertise_type5_routes(bgp_vrf, AFI_IP))
bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP, SAFI_UNICAST);
/* update all ipv6 routes */ /* update all ipv6 routes */
bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST); if (advertise_type5_routes(bgp_vrf, AFI_IP6))
bgp_evpn_advertise_type5_routes(bgp_vrf, AFI_IP6, SAFI_UNICAST);
} }
/* /*
@ -3227,10 +3240,6 @@ void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, struct prefix *p,
struct prefix_evpn evp; struct prefix_evpn evp;
char buf[PREFIX_STRLEN]; char buf[PREFIX_STRLEN];
/* NOTE: Check needed as this is called per-route also. */
if (!advertise_type5_routes(bgp_vrf, afi))
return;
build_type5_prefix_from_ip_prefix(&evp, p); build_type5_prefix_from_ip_prefix(&evp, p);
ret = delete_evpn_type5_route(bgp_vrf, &evp); ret = delete_evpn_type5_route(bgp_vrf, &evp);
if (ret) { if (ret) {
@ -3248,10 +3257,6 @@ void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, afi_t afi, safi_t safi)
struct bgp_node *rn = NULL; struct bgp_node *rn = NULL;
struct bgp_info *ri; struct bgp_info *ri;
/* Bail out early if we don't have to advertise type-5 routes. */
if (!advertise_type5_routes(bgp_vrf, afi))
return;
table = bgp_vrf->rib[afi][safi]; table = bgp_vrf->rib[afi][safi];
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
/* Only care about "selected" routes - non-imported. */ /* Only care about "selected" routes - non-imported. */
@ -3281,10 +3286,6 @@ void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct prefix *p,
struct prefix_evpn evp; struct prefix_evpn evp;
char buf[PREFIX_STRLEN]; char buf[PREFIX_STRLEN];
/* NOTE: Check needed as this is called per-route also. */
if (!advertise_type5_routes(bgp_vrf, afi))
return;
build_type5_prefix_from_ip_prefix(&evp, p); build_type5_prefix_from_ip_prefix(&evp, p);
ret = update_evpn_type5_route(bgp_vrf, &evp, src_attr); ret = update_evpn_type5_route(bgp_vrf, &evp, src_attr);
if (ret) if (ret)
@ -3303,10 +3304,6 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi,
struct bgp_node *rn = NULL; struct bgp_node *rn = NULL;
struct bgp_info *ri; struct bgp_info *ri;
/* Bail out early if we don't have to advertise type-5 routes. */
if (!advertise_type5_routes(bgp_vrf, afi))
return;
table = bgp_vrf->rib[afi][safi]; table = bgp_vrf->rib[afi][safi];
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
/* Need to identify the "selected" route entry to use its /* Need to identify the "selected" route entry to use its

View File

@ -55,6 +55,25 @@ static inline vni_t label2vni(mpls_label_t *label)
return vni; return vni;
} }
static inline int advertise_type5_routes(struct bgp *bgp_vrf,
afi_t afi)
{
if (!bgp_vrf->l3vni)
return 0;
if (afi == AFI_IP &&
CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
return 1;
if (afi == AFI_IP6 &&
CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
return 1;
return 0;
}
extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf,
struct prefix *p, struct prefix *p,
struct attr *src_attr, afi_t afi, struct attr *src_attr, afi_t afi,

View File

@ -285,6 +285,14 @@ static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp,
} }
} }
static inline int is_evpn_prefix_default(struct prefix *evp)
{
if (evp->family != AF_EVPN)
return 0;
return ((evp->u.prefix_evpn.ip_prefix_length == 0) ? 1 : 0);
}
static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp, static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp,
struct prefix *ip) struct prefix *ip)
{ {
@ -352,19 +360,17 @@ static inline void build_evpn_type3_prefix(struct prefix_evpn *p,
p->prefix.ip.ipaddr_v4 = originator_ip; p->prefix.ip.ipaddr_v4 = originator_ip;
} }
static inline int advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi) static inline int evpn_default_originate_set(struct bgp *bgp, afi_t afi,
safi_t safi)
{ {
if (!bgp_vrf->l3vni) if (afi == AFI_IP &&
return 0; CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
if (afi == AFI_IP
&& CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN))
return 1; return 1;
else if (afi == AFI_IP6 &&
if (afi == AFI_IP6 CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
&& CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
return 1; return 1;
return 0; return 0;
} }

View File

@ -2419,7 +2419,50 @@ static void evpn_unset_advertise_default_gw(struct bgp *bgp,
/* /*
* evpn - enable advertisement of default g/w * evpn - enable advertisement of default g/w
*/ */
static void evpn_set_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn) static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
afi_t afi, int add)
{
struct prefix ip_prefix;
safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
/* form the default prefix 0.0.0.0/0 */
memset(&ip_prefix, 0, sizeof(struct prefix));
ip_prefix.family = afi2family(afi);
ip_prefix.prefixlen = 0;
if (add) {
/* bail if we are already advertising default route */
if (evpn_default_originate_set(bgp_vrf, afi, safi))
return;
if (afi == AFI_IP)
SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
else if (afi == AFI_IP6)
SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
bgp_evpn_advertise_type5_route(bgp_vrf, &ip_prefix,
NULL, afi, safi);
} else {
/* bail out if we havent advertised the default route */
if (!evpn_default_originate_set(bgp_vrf, afi, safi))
return;
if (afi == AFI_IP)
UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
else if (afi == AFI_IP6)
UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
bgp_evpn_withdraw_type5_route(bgp_vrf, &ip_prefix,
afi, safi);
}
}
/*
* evpn - enable advertisement of default g/w
*/
static void evpn_set_advertise_subnet(struct bgp *bgp,
struct bgpevpn *vpn)
{ {
if (vpn->advertise_subnet) if (vpn->advertise_subnet)
return; return;
@ -2612,6 +2655,43 @@ DEFUN (no_bgp_evpn_advertise_all_vni,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFUN (bgp_evpn_default_originate,
bgp_evpn_default_originate_cmd,
"default-originate <ipv4 | ipv6>",
"originate a default route\n"
"ipv4 address family\n"
"ipv6 address family\n")
{
afi_t afi = 0;
int idx_afi = 0;
struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
if (!bgp_vrf)
return CMD_WARNING;
argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
evpn_process_default_originate_cmd(bgp_vrf, afi, 1);
return CMD_SUCCESS;
}
DEFUN (no_bgp_evpn_default_originate,
no_bgp_evpn_default_originate_cmd,
"no default-originate <ipv4 | ipv6>",
NO_STR
"withdraw a default route\n"
"ipv4 address family\n"
"ipv6 address family\n")
{
afi_t afi = 0;
int idx_afi = 0;
struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
if (!bgp_vrf)
return CMD_WARNING;
argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
evpn_process_default_originate_cmd(bgp_vrf, afi, 0);
return CMD_SUCCESS;
}
DEFUN (bgp_evpn_advertise_vni_subnet, DEFUN (bgp_evpn_advertise_vni_subnet,
bgp_evpn_advertise_vni_subnet_cmd, bgp_evpn_advertise_vni_subnet_cmd,
"advertise-subnet", "advertise-subnet",
@ -2631,14 +2711,6 @@ DEFUN (bgp_evpn_advertise_vni_subnet,
if (!bgp_vrf) if (!bgp_vrf)
return CMD_WARNING; return CMD_WARNING;
if (!(advertise_type5_routes(bgp_vrf, AFI_IP)
|| advertise_type5_routes(bgp_vrf, AFI_IP6))) {
vty_out(vty,
"%%Please enable ip prefix advertisement under l2vpn evpn in %s",
vrf_id_to_name(bgp_vrf->vrf_id));
return CMD_WARNING;
}
evpn_set_advertise_subnet(bgp, vpn); evpn_set_advertise_subnet(bgp, vpn);
return CMD_SUCCESS; return CMD_SUCCESS;
} }
@ -2711,19 +2783,23 @@ DEFUN (bgp_evpn_advertise_type5,
/* if we are already advertising ipv4 prefix as type-5 /* if we are already advertising ipv4 prefix as type-5
* nothing to do * nothing to do
*/ */
if (!rmap_changed && CHECK_FLAG(bgp_vrf->vrf_flags, if (!rmap_changed &&
BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
return CMD_WARNING; return CMD_WARNING;
SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN); SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
} else { } else {
/* if we are already advertising ipv6 prefix as type-5 /* if we are already advertising ipv6 prefix as type-5
* nothing to do * nothing to do
*/ */
if (!rmap_changed && CHECK_FLAG(bgp_vrf->vrf_flags, if (!rmap_changed &&
BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
return CMD_WARNING; return CMD_WARNING;
SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN); SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
} }
if (rmap_changed) { if (rmap_changed) {
@ -2766,7 +2842,7 @@ DEFUN (no_bgp_evpn_advertise_type5,
argv_find_and_parse_afi(argv, argc, &idx_afi, &afi); argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
argv_find_and_parse_safi(argv, argc, &idx_safi, &safi); argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
if (!(afi == AFI_IP) || (afi == AFI_IP6)) { if (!(afi == AFI_IP || afi == AFI_IP6)) {
vty_out(vty, vty_out(vty,
"%%only ipv4 or ipv6 address families are supported"); "%%only ipv4 or ipv6 address families are supported");
return CMD_WARNING; return CMD_WARNING;
@ -2780,25 +2856,25 @@ DEFUN (no_bgp_evpn_advertise_type5,
if (afi == AFI_IP) { if (afi == AFI_IP) {
/* if we are already advertising ipv4 prefix as type-5 /* if we are not advertising ipv4 prefix as type-5
* nothing to do * nothing to do
*/ */
if (CHECK_FLAG(bgp_vrf->vrf_flags, if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) { BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi); bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
UNSET_FLAG(bgp_vrf->vrf_flags, UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_VRF_ADVERTISE_IPV4_IN_EVPN); BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
} }
} else { } else {
/* if we are already advertising ipv6 prefix as type-5 /* if we are not advertising ipv6 prefix as type-5
* nothing to do * nothing to do
*/ */
if (CHECK_FLAG(bgp_vrf->vrf_flags, if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) { BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi); bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
UNSET_FLAG(bgp_vrf->vrf_flags, UNSET_FLAG(bgp_vrf->vrf_flags,
BGP_VRF_ADVERTISE_IPV6_IN_EVPN); BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
} }
} }
@ -4305,12 +4381,22 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
if (bgp->advertise_gw_macip) if (bgp->advertise_gw_macip)
vty_out(vty, " advertise-default-gw\n"); vty_out(vty, " advertise-default-gw\n");
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
vty_out(vty, " advertise ipv4 unicast\n"); vty_out(vty, " advertise ipv4 unicast\n");
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
vty_out(vty, " advertise ipv6 unicast\n"); vty_out(vty, " advertise ipv6 unicast\n");
if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
vty_out(vty, " default-originate ipv4\n");
if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
vty_out(vty, " default-originate ipv6\n");
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD)) if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
vty_out(vty, " rd %s\n", vty_out(vty, " rd %s\n",
prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1))); prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
@ -4373,6 +4459,8 @@ void bgp_ethernetvpn_init(void)
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd); install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd); install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd); install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
/* "show bgp l2vpn evpn" commands. */ /* "show bgp l2vpn evpn" commands. */
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd); install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);

View File

@ -2227,12 +2227,13 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
/* advertise/withdraw type-5 routes */ /* advertise/withdraw type-5 routes */
if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
if (new_select if (advertise_type5_routes(bgp, afi) && new_select &&
&& (!new_select->extra || !new_select->extra->parent)) (!new_select->extra || !new_select->extra->parent))
bgp_evpn_advertise_type5_route( bgp_evpn_advertise_type5_route(bgp, &rn->p,
bgp, &rn->p, new_select->attr, afi, safi); new_select->attr,
else if (old_select afi, safi);
&& (!old_select->extra || !old_select->extra->parent)) else if (advertise_type5_routes(bgp, afi) && old_select &&
(!old_select->extra || !old_select->extra->parent))
bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi); bgp_evpn_withdraw_type5_route(bgp, &rn->p, afi, safi);
} }

View File

@ -594,6 +594,24 @@ struct route_map_rule_cmd route_match_ip_route_source_prefix_list_cmd = {
route_match_ip_route_source_prefix_list_compile, route_match_ip_route_source_prefix_list_compile,
route_match_ip_route_source_prefix_list_free}; route_match_ip_route_source_prefix_list_free};
/* `match evpn default-route' */
/* Match function should return 1 if match is success else 0 */
static route_map_result_t route_match_evpn_default_route(void *rule,
struct prefix *p,
route_map_object_t
type, void *object)
{
if (type == RMAP_BGP && is_evpn_prefix_default(p))
return RMAP_MATCH;
return RMAP_NOMATCH;
}
/* Route map commands for default-route matching. */
struct route_map_rule_cmd route_match_evpn_default_route_cmd = {
"evpn default-route", route_match_evpn_default_route, NULL, NULL};
/* `match mac address MAC_ACCESS_LIST' */ /* `match mac address MAC_ACCESS_LIST' */
/* Match function should return 1 if match is success else return /* Match function should return 1 if match is success else return
@ -3249,6 +3267,29 @@ DEFUN (no_match_evpn_vni,
RMAP_EVENT_MATCH_DELETED); RMAP_EVENT_MATCH_DELETED);
} }
DEFUN (match_evpn_default_route,
match_evpn_default_route_cmd,
"match evpn default-route",
MATCH_STR
EVPN_HELP_STR
"default EVPN type-5 route\n")
{
return bgp_route_match_add(vty, "evpn default-route", NULL,
RMAP_EVENT_MATCH_ADDED);
}
DEFUN (no_match_evpn_default_route,
no_match_evpn_default_route_cmd,
"no match evpn default-route",
NO_STR
MATCH_STR
EVPN_HELP_STR
"default EVPN type-5 route\n")
{
return bgp_route_match_delete(vty, "evpn default-route", NULL,
RMAP_EVENT_MATCH_DELETED);
}
DEFUN (match_peer, DEFUN (match_peer,
match_peer_cmd, match_peer_cmd,
"match peer <A.B.C.D|X:X::X:X|WORD>", "match peer <A.B.C.D|X:X::X:X|WORD>",
@ -4628,6 +4669,7 @@ void bgp_route_map_init(void)
route_map_install_match(&route_match_mac_address_cmd); route_map_install_match(&route_match_mac_address_cmd);
route_map_install_match(&route_match_evpn_vni_cmd); route_map_install_match(&route_match_evpn_vni_cmd);
route_map_install_match(&route_match_evpn_route_type_cmd); route_map_install_match(&route_match_evpn_route_type_cmd);
route_map_install_match(&route_match_evpn_default_route_cmd);
route_map_install_set(&route_set_ip_nexthop_cmd); route_map_install_set(&route_set_ip_nexthop_cmd);
route_map_install_set(&route_set_local_pref_cmd); route_map_install_set(&route_set_local_pref_cmd);
@ -4664,6 +4706,8 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &no_match_evpn_vni_cmd); install_element(RMAP_NODE, &no_match_evpn_vni_cmd);
install_element(RMAP_NODE, &match_evpn_route_type_cmd); install_element(RMAP_NODE, &match_evpn_route_type_cmd);
install_element(RMAP_NODE, &no_match_evpn_route_type_cmd); install_element(RMAP_NODE, &no_match_evpn_route_type_cmd);
install_element(RMAP_NODE, &match_evpn_default_route_cmd);
install_element(RMAP_NODE, &no_match_evpn_default_route_cmd);
install_element(RMAP_NODE, &match_aspath_cmd); install_element(RMAP_NODE, &match_aspath_cmd);
install_element(RMAP_NODE, &no_match_aspath_cmd); install_element(RMAP_NODE, &no_match_aspath_cmd);

View File

@ -312,6 +312,13 @@ struct bgp {
u_int16_t af_flags[AFI_MAX][SAFI_MAX]; u_int16_t af_flags[AFI_MAX][SAFI_MAX];
#define BGP_CONFIG_DAMPENING (1 << 0) #define BGP_CONFIG_DAMPENING (1 << 0)
/* l2vpn evpn flags - 1 << 0 is used for DAMPENNG */
#define BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST (1 << 1)
#define BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST (1 << 2)
#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4 (1 << 3)
#define BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6 (1 << 4)
/* Route table for next-hop lookup cache. */ /* Route table for next-hop lookup cache. */
struct bgp_table *nexthop_cache_table[AFI_MAX]; struct bgp_table *nexthop_cache_table[AFI_MAX];
@ -423,12 +430,11 @@ struct bgp {
/* vrf flags */ /* vrf flags */
uint32_t vrf_flags; uint32_t vrf_flags;
#define BGP_VRF_AUTO (1 << 0) #define BGP_VRF_AUTO (1 << 0)
#define BGP_VRF_ADVERTISE_IPV4_IN_EVPN (1 << 1) #define BGP_VRF_IMPORT_RT_CFGD (1 << 1)
#define BGP_VRF_ADVERTISE_IPV6_IN_EVPN (1 << 2) #define BGP_VRF_EXPORT_RT_CFGD (1 << 2)
#define BGP_VRF_IMPORT_RT_CFGD (1 << 3) #define BGP_VRF_RD_CFGD (1 << 3)
#define BGP_VRF_EXPORT_RT_CFGD (1 << 4) #define BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY (1 << 4)
#define BGP_VRF_RD_CFGD (1 << 5)
#define BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY (1 << 6)
/* unique ID for auto derivation of RD for this vrf */ /* unique ID for auto derivation of RD for this vrf */
uint16_t vrf_rd_id; uint16_t vrf_rd_id;

View File

@ -396,6 +396,8 @@ AC_ARG_ENABLE(rpki,
AS_HELP_STRING([--enable-rpki], [enable RPKI prefix validation support])) AS_HELP_STRING([--enable-rpki], [enable RPKI prefix validation support]))
AC_ARG_ENABLE([clippy-only], AC_ARG_ENABLE([clippy-only],
AS_HELP_STRING([--enable-clippy-only], [Only build clippy])) AS_HELP_STRING([--enable-clippy-only], [Only build clippy]))
AC_ARG_ENABLE([numeric_version],
AS_HELP_STRING([--enable-numeric-version], [Only numeric digits allowed in version (for Alpine)]))
AS_IF([test "${enable_clippy_only}" != "yes"], [ AS_IF([test "${enable_clippy_only}" != "yes"], [
AC_CHECK_HEADERS(json-c/json.h) AC_CHECK_HEADERS(json-c/json.h)
@ -647,6 +649,14 @@ AC_DEFINE_UNQUOTED(MULTIPATH_NUM, $MPATH_NUM, Maximum number of paths for a rout
AC_DEFINE_UNQUOTED(VTYSH_PAGER, "$VTYSH_PAGER", [What pager to use]) AC_DEFINE_UNQUOTED(VTYSH_PAGER, "$VTYSH_PAGER", [What pager to use])
dnl ------------------------------------
dnl Alpine only accepts numeric versions
dnl ------------------------------------
if test "x${enable_numeric_version}" != "x" ; then
VERSION="`echo ${VERSION} | tr -c -d '[[.0-9]]'`"
PACKAGE_VERSION="`echo ${PACKAGE_VERSION} | tr -c -d '[[.0-9]]'`"
fi
dnl ----------------------------------- dnl -----------------------------------
dnl Add extra version string to package dnl Add extra version string to package
dnl name, string and version fields. dnl name, string and version fields.
@ -1872,6 +1882,7 @@ AC_CONFIG_FILES([Makefile
redhat/frr.spec redhat/frr.spec
debianpkg/Makefile debianpkg/Makefile
debianpkg/changelog debianpkg/changelog
alpine/APKBUILD
snapcraft/snapcraft.yaml snapcraft/snapcraft.yaml
lib/version.h lib/version.h
tests/lib/cli/test_cli.refout tests/lib/cli/test_cli.refout

View File

@ -109,6 +109,10 @@ of grammar sandbox.
Turn on some compile options to allow you to run fuzzing tools Turn on some compile options to allow you to run fuzzing tools
against the system. This tools is intended as a developer against the system. This tools is intended as a developer
only tool and should not be used for normal operations only tool and should not be used for normal operations
@item --enable-numeric-version
Alpine Linux does not allow non-numeric characters in the version
string. With this option, we provide a way to strip out these
characters for apk dev package builds.
@end table @end table
You may specify any combination of the above options to the configure You may specify any combination of the above options to the configure

1
ldpd/.gitignore vendored
View File

@ -15,4 +15,3 @@ TAGS
.arch-ids .arch-ids
*~ *~
*.loT *.loT
ldp_vty_cmds_clippy.c

1
lib/.gitignore vendored
View File

@ -24,4 +24,3 @@ refix
grammar_sandbox grammar_sandbox
clippy clippy
defun_lex.c defun_lex.c
plist_clippy.c

View File

@ -104,76 +104,77 @@ struct debug_callbacks {
* *
* MT-Safe * MT-Safe
*/ */
#define DEBUG_MODE_CHECK(name, type) \ #define DEBUG_MODE_CHECK(name, mode) \
CHECK_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_MODE_ALL) CHECK_FLAG_ATOMIC(&(name)->flags, (mode)&DEBUG_MODE_ALL)
/* /*
* Check if an option bit is set for a debug. * Check if an option bit is set for a debug.
* *
* MT-Safe * MT-Safe
*/ */
#define DEBUG_OPT_CHECK(name, type) \ #define DEBUG_OPT_CHECK(name, opt) \
CHECK_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_OPT_ALL) CHECK_FLAG_ATOMIC(&(name)->flags, (opt)&DEBUG_OPT_ALL)
/* /*
* Check if bits are set for a debug. * Check if bits are set for a debug.
* *
* MT-Safe * MT-Safe
*/ */
#define DEBUG_FLAGS_CHECK(name, type) CHECK_FLAG_ATOMIC(&(name)->flags, (type)) #define DEBUG_FLAGS_CHECK(name, fl) CHECK_FLAG_ATOMIC(&(name)->flags, (fl))
/*
* Check if any mode is on for a debug.
*
* MT-Safe
*/
#define DEBUG(name) DEBUG_MODE_CHECK((name), DEBUG_MODE_ALL)
/* /*
* Set modes on a debug. * Set modes on a debug.
* *
* MT-Safe * MT-Safe
*/ */
#define DEBUG_MODE_SET(name, type) \ #define DEBUG_MODE_SET(name, mode, onoff) \
SET_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_MODE_ALL) do { \
if (onoff) \
SET_FLAG_ATOMIC(&(name)->flags, \
(mode)&DEBUG_MODE_ALL); \
else \
UNSET_FLAG_ATOMIC(&(name)->flags, \
(mode)&DEBUG_MODE_ALL); \
} while (0)
/* /* Convenience macros for specific set operations. */
* Unset modes on a debug. #define DEBUG_MODE_ON(name, mode) DEBUG_MODE_SET(name, mode, true)
* #define DEBUG_MODE_OFF(name, mode) DEBUG_MODE_SET(name, mode, false)
* MT-Safe
*/
#define DEBUG_MODE_UNSET(name, type) \
UNSET_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_MODE_ALL)
/* /*
* Set options on a debug. * Set options on a debug.
* *
* MT-Safe * MT-Safe
*/ */
#define DEBUG_OPT_SET(name, type) \ #define DEBUG_OPT_SET(name, opt, onoff) \
SET_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_OPT_ALL) do { \
if (onoff) \
SET_FLAG_ATOMIC(&(name)->flags, (opt)&DEBUG_OPT_ALL); \
else \
UNSET_FLAG_ATOMIC(&(name)->flags, \
(opt)&DEBUG_OPT_ALL); \
} while (0)
/* /* Convenience macros for specific set operations. */
* Unset options on a debug. #define DEBUG_OPT_ON(name, opt) DEBUG_OPT_SET(name, opt, true)
* #define DEBUG_OPT_OFF(name, opt) DEBUG_OPT_SET(name, opt, true)
* MT-Safe
*/
#define DEBUG_OPT_UNSET(name, type) \
UNSET_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_OPT_ALL)
/* /*
* Set bits on a debug. * Set bits on a debug.
* *
* MT-Safe * MT-Safe
*/ */
#define DEBUG_FLAGS_SET(name, type) SET_FLAG_ATOMIC(&(name)->flags, (type)) #define DEBUG_FLAGS_SET(name, fl, onoff) \
do { \
if (onoff) \
SET_FLAG_ATOMIC(&(name)->flags, (fl)); \
else \
UNSET_FLAG_ATOMIC(&(name)->flags, (fl)); \
} while (0)
/* /* Convenience macros for specific set operations. */
* Unset bits on a debug. #define DEBUG_FLAGS_ON(name, fl) DEBUG_FLAGS_SET(&(name)->flags, (type), true)
* #define DEBUG_FLAGS_OFF(name, fl) DEBUG_FLAGS_SET(&(name)->flags, (type), false)
* MT-Safe
*/
#define DEBUG_FLAGS_UNSET(name, type) UNSET_FLAG_ATOMIC(&(name)->flags, (type))
/* /*
* Unset all modes and options on a debug. * Unset all modes and options on a debug.
@ -201,6 +202,23 @@ struct debug_callbacks {
#define DEBUG_NODE2MODE(vtynode) \ #define DEBUG_NODE2MODE(vtynode) \
(((vtynode) == CONFIG_NODE) ? DEBUG_MODE_ALL : DEBUG_MODE_TERM) (((vtynode) == CONFIG_NODE) ? DEBUG_MODE_ALL : DEBUG_MODE_TERM)
/*
* Debug at the given level to the default logging destination.
*
* MT-Safe
*/
#define DEBUG(level, name, fmt, ...) \
do { \
if (DEBUG_MODE_CHECK(name, DEBUG_MODE_ALL)) \
zlog_##level(fmt, ##__VA_ARGS__); \
} while (0)
/* Convenience macros for the various levels. */
#define DEBUGE(name, fmt, ...) DEBUG(err, name, fmt, ##__VA_ARGS__)
#define DEBUGW(name, fmt, ...) DEBUG(warn, name, fmt, ##__VA_ARGS__)
#define DEBUGI(name, fmt, ...) DEBUG(info, name, fmt, ##__VA_ARGS__)
#define DEBUGN(name, fmt, ...) DEBUG(notice, name, fmt, ##__VA_ARGS__)
#define DEBUGD(name, fmt, ...) DEBUG(debug, name, fmt, ##__VA_ARGS__)
/* /*
* Optional initializer for debugging. Highly recommended. * Optional initializer for debugging. Highly recommended.

View File

@ -85,4 +85,21 @@ static inline char *ipaddr2str(struct ipaddr *ip, char *buf, int size)
} }
return buf; return buf;
} }
/*
* Convert IPv4 address to IPv4-mapped IPv6 address which is of the
* form ::FFFF:<IPv4 address> (RFC 4291). This IPv6 address can then
* be used to represent the IPv4 address, wherever only an IPv6 address
* is required.
*/
static inline void ipv4_to_ipv4_mapped_ipv6(struct in6_addr *in6,
struct in_addr in)
{
u_int32_t addr_type = htonl(0xFFFF);
memset(in6, 0, sizeof(struct in6_addr));
memcpy((char *)in6 + 8, &addr_type, sizeof(addr_type));
memcpy((char *)in6 + 12, &in, sizeof(struct in_addr));
}
#endif /* __IPADDR_H__ */ #endif /* __IPADDR_H__ */

View File

@ -1092,41 +1092,52 @@ void zlog_hexdump(const void *mem, unsigned int len)
unsigned long i = 0; unsigned long i = 0;
unsigned int j = 0; unsigned int j = 0;
unsigned int columns = 8; unsigned int columns = 8;
char buf[(len * 4) + ((len / 4) * 20) + 30]; /*
* 19 bytes for 0xADDRESS:
* 24 bytes for data; 2 chars plus a space per data byte
* 1 byte for space
* 8 bytes for ASCII representation
* 1 byte for a newline
* =====================
* 53 bytes per 8 bytes of data
* 1 byte for null term
*/
size_t bs = ((len / 8) + 1) * 53 + 1;
char buf[bs];
char *s = buf; char *s = buf;
memset(buf, 0, sizeof(buf));
for (i = 0; i < len + ((len % columns) ? (columns - len % columns) : 0); for (i = 0; i < len + ((len % columns) ? (columns - len % columns) : 0);
i++) { i++) {
/* print offset */ /* print offset */
if (i % columns == 0) if (i % columns == 0)
s += sprintf(s, "0x%016lx: ", (unsigned long)mem + i); s += snprintf(s, bs - (s - buf),
"0x%016lx: ", (unsigned long)mem + i);
/* print hex data */ /* print hex data */
if (i < len) if (i < len)
s += sprintf(s, "%02x ", 0xFF & ((const char *)mem)[i]); s += snprintf(s, bs - (s - buf), "%02x ",
0xFF & ((const char *)mem)[i]);
/* end of block, just aligning for ASCII dump */ /* end of block, just aligning for ASCII dump */
else else
s += sprintf(s, " "); s += snprintf(s, bs - (s - buf), " ");
/* print ASCII dump */ /* print ASCII dump */
if (i % columns == (columns - 1)) { if (i % columns == (columns - 1)) {
for (j = i - (columns - 1); j <= i; j++) { for (j = i - (columns - 1); j <= i; j++) {
if (j >= len) /* end of block, not really /* end of block not really printing */
printing */ if (j >= len)
s += sprintf(s, " "); s += snprintf(s, bs - (s - buf), " ");
else if (isprint((int)((const char *)mem)[j]))
else if (isprint((int)((const char *)mem) s += snprintf(
[j])) /* printable char s, bs - (s - buf), "%c",
*/
s += sprintf(
s, "%c",
0xFF & ((const char *)mem)[j]); 0xFF & ((const char *)mem)[j]);
else /* other char */ else /* other char */
s += sprintf(s, "."); s += snprintf(s, bs - (s - buf), ".");
} }
s += sprintf(s, "\n"); s += snprintf(s, bs - (s - buf), "\n");
} }
} }
zlog_debug("\n%s", buf); zlog_debug("\n%s", buf);

View File

@ -322,6 +322,18 @@ stream_failure:
return 0; return 0;
} }
bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr)
{
STREAM_GETW(zmsg, hdr->length);
STREAM_GETC(zmsg, hdr->marker);
STREAM_GETC(zmsg, hdr->version);
STREAM_GETL(zmsg, hdr->vrf_id);
STREAM_GETW(zmsg, hdr->command);
return true;
stream_failure:
return false;
}
/* Send simple Zebra message. */ /* Send simple Zebra message. */
static int zebra_message_send(struct zclient *zclient, int command, static int zebra_message_send(struct zclient *zclient, int command,
vrf_id_t vrf_id) vrf_id_t vrf_id)

View File

@ -237,14 +237,13 @@ struct zclient {
*/ */
#define ZAPI_MESSAGE_TABLEID 0x80 #define ZAPI_MESSAGE_TABLEID 0x80
#define ZSERV_VERSION 5
/* Zserv protocol message header */ /* Zserv protocol message header */
struct zserv_header { struct zmsghdr {
uint16_t length; uint16_t length;
uint8_t marker; /* corresponds to command field in old zserv /* Always set to 255 in new zserv */
* always set to 255 in new zserv. uint8_t marker;
*/
uint8_t version; uint8_t version;
#define ZSERV_VERSION 5
vrf_id_t vrf_id; vrf_id_t vrf_id;
uint16_t command; uint16_t command;
}; };
@ -380,9 +379,11 @@ struct zclient_options {
/* Prototypes of zebra client service functions. */ /* Prototypes of zebra client service functions. */
extern struct zclient *zclient_new(struct thread_master *); extern struct zclient *zclient_new(struct thread_master *);
/* clang-format off */
#if CONFDATE > 20181101 #if CONFDATE > 20181101
CPP_NOTICE("zclient_new_notify can take over or zclient_new now"); CPP_NOTICE("zclient_new_notify can take over or zclient_new now");
#endif #endif
/* clang-format on */
extern struct zclient_options zclient_options_default; extern struct zclient_options zclient_options_default;
@ -449,9 +450,58 @@ extern int zclient_send_message(struct zclient *);
/* create header for command, length to be filled in by user later */ /* create header for command, length to be filled in by user later */
extern void zclient_create_header(struct stream *, uint16_t, vrf_id_t); extern void zclient_create_header(struct stream *, uint16_t, vrf_id_t);
/*
* Read sizeof(struct zmsghdr) bytes from the provided socket and parse the
* received data into the specified fields. If this is successful, read the
* rest of the packet into the provided stream.
*
* s
* The stream to read into
*
* sock
* The socket to read from
*
* size
* Parsed message size will be placed in the pointed-at integer
*
* marker
* Parsed marker will be placed in the pointed-at byte
*
* version
* Parsed version will be placed in the pointed-at byte
*
* vrf_id
* Parsed VRF ID will be placed in the pointed-at vrf_id_t
*
* cmd
* Parsed command number will be placed in the pointed-at integer
*
* Returns:
* -1 if:
* - insufficient data for header was read
* - a version mismatch was detected
* - a marker mismatch was detected
* - header size field specified more data than could be read
*/
extern int zclient_read_header(struct stream *s, int sock, u_int16_t *size, extern int zclient_read_header(struct stream *s, int sock, u_int16_t *size,
u_char *marker, u_char *version, u_char *marker, u_char *version,
vrf_id_t *vrf_id, u_int16_t *cmd); vrf_id_t *vrf_id, u_int16_t *cmd);
/*
* Parse header from ZAPI message stream into struct zmsghdr.
* This function assumes the stream getp points at the first byte of the header.
* If the function is successful then the stream getp will point to the byte
* immediately after the last byte of the header.
*
* zmsg
* The stream containing the header
*
* hdr
* The header struct to parse into.
*
* Returns:
* true if parsing succeeded, false otherwise
*/
extern bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr);
extern void zclient_interface_set_master(struct zclient *client, extern void zclient_interface_set_master(struct zclient *client,
struct interface *master, struct interface *master,
@ -468,10 +518,11 @@ extern struct interface *zebra_interface_vrf_update_read(struct stream *s,
extern void zebra_interface_if_set_value(struct stream *, struct interface *); extern void zebra_interface_if_set_value(struct stream *, struct interface *);
extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid); extern void zebra_router_id_update_read(struct stream *s, struct prefix *rid);
/* clang-format off */
#if CONFDATE > 20180823 #if CONFDATE > 20180823
CPP_NOTICE( CPP_NOTICE("zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now");
"zapi_ipv4_route, zapi_ipv6_route, zapi_ipv4_route_ipv6_nexthop as well as the zapi_ipv4 and zapi_ipv6 data structures should be removed now");
#endif #endif
/* clang-format on */
extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *, extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *,
struct zapi_ipv4 *) __attribute__((deprecated)); struct zapi_ipv4 *) __attribute__((deprecated));

1
ospfd/.gitignore vendored
View File

@ -15,4 +15,3 @@ TAGS
*~ *~
*.loT *.loT
*.a *.a
*clippy.c

View File

@ -604,11 +604,18 @@ static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
json_object_object_add(json, ifp->name, json_object_object_add(json, ifp->name,
json_row); json_row);
if (igmp->mtrace_only) {
json_object_boolean_true_add(
json_row, "mtraceOnly");
}
} else { } else {
vty_out(vty, vty_out(vty,
"%-9s %5s %15s %d %7s %11s %8s\n", "%-9s %5s %15s %d %7s %11s %8s\n",
ifp->name, ifp->name,
if_is_up(ifp) ? "up" : "down", if_is_up(ifp)
? (igmp->mtrace_only ? "mtrc"
: "up")
: "down",
inet_ntoa(igmp->ifaddr), inet_ntoa(igmp->ifaddr),
pim_ifp->igmp_version, pim_ifp->igmp_version,
igmp->t_igmp_query_timer ? "local" igmp->t_igmp_query_timer ? "local"
@ -758,10 +765,17 @@ static void igmp_show_interfaces_single(struct pim_instance *pim,
json_object_object_add(json, ifp->name, json_object_object_add(json, ifp->name,
json_row); json_row);
if (igmp->mtrace_only) {
json_object_boolean_true_add(
json_row, "mtraceOnly");
}
} else { } else {
vty_out(vty, "Interface : %s\n", ifp->name); vty_out(vty, "Interface : %s\n", ifp->name);
vty_out(vty, "State : %s\n", vty_out(vty, "State : %s\n",
if_is_up(ifp) ? "up" : "down"); if_is_up(ifp)
? (igmp->mtrace_only ? "mtrace"
: "up")
: "down");
vty_out(vty, "Address : %s\n", vty_out(vty, "Address : %s\n",
inet_ntoa(pim_ifp->primary_address)); inet_ntoa(pim_ifp->primary_address));
vty_out(vty, "Uptime : %s\n", uptime); vty_out(vty, "Uptime : %s\n", uptime);

View File

@ -574,7 +574,11 @@ void pim_if_addr_add(struct connected *ifc)
/* if addr new, add IGMP socket */ /* if addr new, add IGMP socket */
if (ifc->address->family == AF_INET) if (ifc->address->family == AF_INET)
pim_igmp_sock_add(pim_ifp->igmp_socket_list, pim_igmp_sock_add(pim_ifp->igmp_socket_list,
ifaddr, ifp); ifaddr, ifp, false);
} else if (igmp->mtrace_only) {
igmp_sock_delete(igmp);
pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
ifp, false);
} }
/* Replay Static IGMP groups */ /* Replay Static IGMP groups */
@ -611,6 +615,20 @@ void pim_if_addr_add(struct connected *ifc)
} }
} }
} /* igmp */ } /* igmp */
else {
struct igmp_sock *igmp;
/* lookup IGMP socket */
igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
ifaddr);
if (ifc->address->family == AF_INET) {
if (igmp)
igmp_sock_delete(igmp);
/* if addr new, add IGMP socket */
pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
ifp, true);
}
} /* igmp mtrace only */
if (PIM_IF_TEST_PIM(pim_ifp->options)) { if (PIM_IF_TEST_PIM(pim_ifp->options)) {

View File

@ -281,6 +281,9 @@ static int igmp_recv_query(struct igmp_sock *igmp, int query_version,
uint16_t recv_checksum; uint16_t recv_checksum;
uint16_t checksum; uint16_t checksum;
if (igmp->mtrace_only)
return 0;
memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr)); memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
ifp = igmp->interface; ifp = igmp->interface;
@ -387,6 +390,9 @@ static int igmp_v1_recv_report(struct igmp_sock *igmp, struct in_addr from,
on_trace(__PRETTY_FUNCTION__, igmp->interface, from); on_trace(__PRETTY_FUNCTION__, igmp->interface, from);
if (igmp->mtrace_only)
return 0;
if (igmp_msg_len != IGMP_V12_MSG_SIZE) { if (igmp_msg_len != IGMP_V12_MSG_SIZE) {
zlog_warn( zlog_warn(
"Recv IGMP report v1 from %s on %s: size=%d other than correct=%d", "Recv IGMP report v1 from %s on %s: size=%d other than correct=%d",
@ -510,7 +516,6 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)
return igmp_mtrace_recv_response(igmp, ip_hdr, ip_hdr->ip_src, return igmp_mtrace_recv_response(igmp, ip_hdr, ip_hdr->ip_src,
from_str, igmp_msg, from_str, igmp_msg,
igmp_msg_len); igmp_msg_len);
break;
case PIM_IGMP_MTRACE_QUERY_REQUEST: case PIM_IGMP_MTRACE_QUERY_REQUEST:
return igmp_mtrace_recv_qry_req(igmp, ip_hdr, ip_hdr->ip_src, return igmp_mtrace_recv_qry_req(igmp, ip_hdr, ip_hdr->ip_src,
from_str, igmp_msg, from_str, igmp_msg,
@ -819,7 +824,7 @@ static int igmp_group_hash_equal(const void *arg1, const void *arg2)
} }
static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr, static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr,
struct interface *ifp) struct interface *ifp, int mtrace_only)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct igmp_sock *igmp; struct igmp_sock *igmp;
@ -862,6 +867,13 @@ static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr,
pim_ifp->igmp_default_robustness_variable; pim_ifp->igmp_default_robustness_variable;
igmp->sock_creation = pim_time_monotonic_sec(); igmp->sock_creation = pim_time_monotonic_sec();
if (mtrace_only) {
igmp->mtrace_only = mtrace_only;
return igmp;
}
igmp->mtrace_only = false;
/* /*
igmp_startup_mode_on() will reset QQI: igmp_startup_mode_on() will reset QQI:
@ -919,7 +931,8 @@ static void igmp_read_on(struct igmp_sock *igmp)
struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list,
struct in_addr ifaddr, struct in_addr ifaddr,
struct interface *ifp) struct interface *ifp,
bool mtrace_only)
{ {
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
struct igmp_sock *igmp; struct igmp_sock *igmp;
@ -934,7 +947,7 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list,
return 0; return 0;
} }
igmp = igmp_sock_new(fd, ifaddr, ifp); igmp = igmp_sock_new(fd, ifaddr, ifp, mtrace_only);
if (!igmp) { if (!igmp) {
zlog_err("%s %s: igmp_sock_new() failure", __FILE__, zlog_err("%s %s: igmp_sock_new() failure", __FILE__,
__PRETTY_FUNCTION__); __PRETTY_FUNCTION__);

View File

@ -90,6 +90,8 @@ struct igmp_sock {
int querier_robustness_variable; /* QRV */ int querier_robustness_variable; /* QRV */
int startup_query_count; int startup_query_count;
bool mtrace_only;
struct list *igmp_group_list; /* list of struct igmp_group */ struct list *igmp_group_list; /* list of struct igmp_group */
struct hash *igmp_group_hash; struct hash *igmp_group_hash;
}; };
@ -99,7 +101,8 @@ struct igmp_sock *pim_igmp_sock_lookup_ifaddr(struct list *igmp_sock_list,
struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, int fd); struct igmp_sock *igmp_sock_lookup_by_fd(struct list *igmp_sock_list, int fd);
struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list, struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list,
struct in_addr ifaddr, struct in_addr ifaddr,
struct interface *ifp); struct interface *ifp,
bool mtrace_only);
void igmp_sock_delete(struct igmp_sock *igmp); void igmp_sock_delete(struct igmp_sock *igmp);
void igmp_sock_free(struct igmp_sock *igmp); void igmp_sock_free(struct igmp_sock *igmp);
void igmp_sock_delete_all(struct interface *ifp); void igmp_sock_delete_all(struct interface *ifp);

View File

@ -111,6 +111,9 @@ int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from,
on_trace(__PRETTY_FUNCTION__, igmp->interface, from); on_trace(__PRETTY_FUNCTION__, igmp->interface, from);
if (igmp->mtrace_only)
return 0;
if (igmp_msg_len != IGMP_V12_MSG_SIZE) { if (igmp_msg_len != IGMP_V12_MSG_SIZE) {
zlog_warn( zlog_warn(
"Recv IGMPv2 REPORT from %s on %s: size=%d other than correct=%d", "Recv IGMPv2 REPORT from %s on %s: size=%d other than correct=%d",
@ -154,6 +157,9 @@ int igmp_v2_recv_leave(struct igmp_sock *igmp, struct in_addr from,
on_trace(__PRETTY_FUNCTION__, igmp->interface, from); on_trace(__PRETTY_FUNCTION__, igmp->interface, from);
if (igmp->mtrace_only)
return 0;
if (igmp_msg_len != IGMP_V12_MSG_SIZE) { if (igmp_msg_len != IGMP_V12_MSG_SIZE) {
zlog_warn( zlog_warn(
"Recv IGMPv2 LEAVE from %s on %s: size=%d other than correct=%d", "Recv IGMPv2 LEAVE from %s on %s: size=%d other than correct=%d",

View File

@ -1874,6 +1874,9 @@ int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from,
int local_ncb = 0; int local_ncb = 0;
struct pim_interface *pim_ifp; struct pim_interface *pim_ifp;
if (igmp->mtrace_only)
return 0;
pim_ifp = igmp->interface->info; pim_ifp = igmp->interface->info;
if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) { if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) {

1
sharpd/.gitignore vendored
View File

@ -13,6 +13,5 @@ TAGS
.arch-ids .arch-ids
*~ *~
*.loT *.loT
*clippy.c
sharpd sharpd
sharpd.conf sharpd.conf

View File

@ -73,6 +73,7 @@ check_PROGRAMS = \
lib/test_timer_correctness \ lib/test_timer_correctness \
lib/test_timer_performance \ lib/test_timer_performance \
lib/test_ttable \ lib/test_ttable \
lib/test_zlog \
lib/cli/test_cli \ lib/cli/test_cli \
lib/cli/test_commands \ lib/cli/test_commands \
$(TESTS_BGPD) \ $(TESTS_BGPD) \
@ -115,9 +116,9 @@ lib_test_heavy_SOURCES = lib/test_heavy.c helpers/c/main.c
lib_test_memory_SOURCES = lib/test_memory.c lib_test_memory_SOURCES = lib/test_memory.c
lib_test_nexthop_iter_SOURCES = lib/test_nexthop_iter.c helpers/c/prng.c lib_test_nexthop_iter_SOURCES = lib/test_nexthop_iter.c helpers/c/prng.c
lib_test_privs_SOURCES = lib/test_privs.c lib_test_privs_SOURCES = lib/test_privs.c
lib_test_ringbuf_SOURCES = lib/test_ringbuf.c
lib_test_srcdest_table_SOURCES = lib/test_srcdest_table.c \ lib_test_srcdest_table_SOURCES = lib/test_srcdest_table.c \
helpers/c/prng.c helpers/c/prng.c
lib_test_ringbuf_SOURCES = lib/test_ringbuf.c
lib_test_segv_SOURCES = lib/test_segv.c lib_test_segv_SOURCES = lib/test_segv.c
lib_test_sig_SOURCES = lib/test_sig.c lib_test_sig_SOURCES = lib/test_sig.c
lib_test_stream_SOURCES = lib/test_stream.c lib_test_stream_SOURCES = lib/test_stream.c
@ -127,6 +128,7 @@ lib_test_timer_correctness_SOURCES = lib/test_timer_correctness.c \
lib_test_timer_performance_SOURCES = lib/test_timer_performance.c \ lib_test_timer_performance_SOURCES = lib/test_timer_performance.c \
helpers/c/prng.c helpers/c/prng.c
lib_test_ttable_SOURCES = lib/test_ttable.c lib_test_ttable_SOURCES = lib/test_ttable.c
lib_test_zlog_SOURCES = lib/test_zlog.c
lib_test_zmq_SOURCES = lib/test_zmq.c lib_test_zmq_SOURCES = lib/test_zmq.c
lib_test_zmq_CFLAGS = $(AM_CFLAGS) $(ZEROMQ_CFLAGS) lib_test_zmq_CFLAGS = $(AM_CFLAGS) $(ZEROMQ_CFLAGS)
lib_cli_test_cli_SOURCES = lib/cli/test_cli.c lib/cli/common_cli.c lib_cli_test_cli_SOURCES = lib/cli/test_cli.c lib/cli/common_cli.c
@ -167,6 +169,7 @@ lib_test_table_LDADD = $(ALL_TESTS_LDADD) -lm
lib_test_timer_correctness_LDADD = $(ALL_TESTS_LDADD) lib_test_timer_correctness_LDADD = $(ALL_TESTS_LDADD)
lib_test_timer_performance_LDADD = $(ALL_TESTS_LDADD) lib_test_timer_performance_LDADD = $(ALL_TESTS_LDADD)
lib_test_ttable_LDADD = $(ALL_TESTS_LDADD) lib_test_ttable_LDADD = $(ALL_TESTS_LDADD)
lib_test_zlog_LDADD = $(ALL_TESTS_LDADD)
lib_test_zmq_LDADD = ../lib/libfrrzmq.la $(ALL_TESTS_LDADD) $(ZEROMQ_LIBS) lib_test_zmq_LDADD = ../lib/libfrrzmq.la $(ALL_TESTS_LDADD) $(ZEROMQ_LIBS)
lib_cli_test_cli_LDADD = $(ALL_TESTS_LDADD) lib_cli_test_cli_LDADD = $(ALL_TESTS_LDADD)
lib_cli_test_commands_LDADD = $(ALL_TESTS_LDADD) lib_cli_test_commands_LDADD = $(ALL_TESTS_LDADD)
@ -207,6 +210,7 @@ EXTRA_DIST = \
lib/test_timer_correctness.py \ lib/test_timer_correctness.py \
lib/test_ttable.py \ lib/test_ttable.py \
lib/test_ttable.refout \ lib/test_ttable.refout \
lib/test_zlog.py \
ospf6d/test_lsdb.py \ ospf6d/test_lsdb.py \
ospf6d/test_lsdb.in \ ospf6d/test_lsdb.in \
ospf6d/test_lsdb.refout \ ospf6d/test_lsdb.refout \

61
tests/lib/test_zlog.c Normal file
View File

@ -0,0 +1,61 @@
/*
* Zlog tests.
* Copyright (C) 2018 Cumulus Networks, Inc.
* Quentin Young
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include <memory.h>
#include "log.h"
/* maximum amount of data to hexdump */
#define MAXDATA 16384
/*
* Test hexdump functionality.
*
* At the moment, not crashing is considered success.
*/
static bool test_zlog_hexdump(void)
{
unsigned int nl = 1;
do {
long d[nl];
for (unsigned int i = 0; i < nl; i++)
d[i] = random();
zlog_hexdump(d, nl * sizeof(long));
} while (++nl * sizeof(long) <= MAXDATA);
return true;
}
bool (*tests[])(void) = {
test_zlog_hexdump,
};
int main(int argc, char **argv)
{
openzlog("testzlog", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID,
LOG_ERR);
zlog_set_file("test_zlog.log", LOG_DEBUG);
for (unsigned int i = 0; i < array_size(tests); i++)
if (!tests[i]())
return 1;
return 0;
}

4
tests/lib/test_zlog.py Normal file
View File

@ -0,0 +1,4 @@
import frrtest
class TestZlog(frrtest.TestMultiOut):
program = './test_zlog'

1
zebra/.gitignore vendored
View File

@ -13,4 +13,3 @@ TAGS
.arch-ids .arch-ids
*~ *~
*.loT *.loT
zebra_vty_clippy.c

View File

@ -30,6 +30,7 @@
*/ */
#define _LINUX_IN6_H #define _LINUX_IN6_H
#include <netinet/if_ether.h>
#include <linux/if_bridge.h> #include <linux/if_bridge.h>
#include <linux/if_link.h> #include <linux/if_link.h>
#include <net/if_arp.h> #include <net/if_arp.h>
@ -362,7 +363,7 @@ static int get_iflink_speed(struct interface *interface)
/* initialize ethtool interface */ /* initialize ethtool interface */
memset(&ecmd, 0, sizeof(ecmd)); memset(&ecmd, 0, sizeof(ecmd));
ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */ ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */
ifdata.ifr_data = (__caddr_t)&ecmd; ifdata.ifr_data = (caddr_t)&ecmd;
/* use ioctl to get IP address of an interface */ /* use ioctl to get IP address of an interface */
if (zserv_privs.change(ZPRIVS_RAISE)) if (zserv_privs.change(ZPRIVS_RAISE))

View File

@ -50,6 +50,8 @@ DEFINE_MTYPE_STATIC(LBL_MGR, LM_CHUNK, "Label Manager Chunk");
* it will be a proxy to relay messages to external label manager * it will be a proxy to relay messages to external label manager
* This zclient thus is to connect to it * This zclient thus is to connect to it
*/ */
static struct stream *ibuf;
static struct stream *obuf;
static struct zclient *zclient; static struct zclient *zclient;
bool lm_is_external; bool lm_is_external;
@ -69,7 +71,7 @@ static int relay_response_back(struct zserv *zserv)
u_int16_t resp_cmd; u_int16_t resp_cmd;
src = zclient->ibuf; src = zclient->ibuf;
dst = zserv->obuf; dst = obuf;
stream_reset(src); stream_reset(src);
@ -87,7 +89,7 @@ static int relay_response_back(struct zserv *zserv)
/* send response back */ /* send response back */
stream_copy(dst, src); stream_copy(dst, src);
ret = writen(zserv->sock, dst->data, stream_get_endp(dst)); ret = writen(zserv->sock, src->data, stream_get_endp(src));
if (ret <= 0) { if (ret <= 0) {
zlog_err("%s: Error sending Label Manager response back: %s", zlog_err("%s: Error sending Label Manager response back: %s",
__func__, strerror(errno)); __func__, strerror(errno));
@ -116,10 +118,10 @@ static int lm_zclient_read(struct thread *t)
static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id) static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id)
{ {
int ret;
struct stream *s; struct stream *s;
s = zserv->obuf; s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
zclient_create_header(s, cmd, vrf_id); zclient_create_header(s, cmd, vrf_id);
@ -129,7 +131,10 @@ static int reply_error(int cmd, struct zserv *zserv, vrf_id_t vrf_id)
/* Write packet size. */ /* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s)); stream_putw_at(s, 0, stream_get_endp(s));
return writen(zserv->sock, s->data, stream_get_endp(s)); ret = writen(zserv->sock, s->data, stream_get_endp(s));
stream_free(s);
return ret;
} }
/** /**
* Receive a request to get or release a label chunk and forward it to external * Receive a request to get or release a label chunk and forward it to external
@ -161,7 +166,7 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv,
ret = relay_response_back(zserv); ret = relay_response_back(zserv);
/* Send request to external label manager */ /* Send request to external label manager */
src = zserv->ibuf; src = ibuf;
dst = zclient->obuf; dst = zclient->obuf;
stream_copy(dst, src); stream_copy(dst, src);
@ -247,6 +252,9 @@ void label_manager_init(char *lm_zserv_path)
lm_is_external = true; lm_is_external = true;
lm_zclient_init(lm_zserv_path); lm_zclient_init(lm_zserv_path);
} }
ibuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
obuf = stream_new(ZEBRA_MAX_PACKET_SIZ);
} }
/** /**
@ -379,4 +387,6 @@ int release_daemon_chunks(u_char proto, u_short instance)
void label_manager_close() void label_manager_close()
{ {
list_delete_and_null(&lbl_mgr.lc_list); list_delete_and_null(&lbl_mgr.lc_list);
stream_free(ibuf);
stream_free(obuf);
} }

View File

@ -243,16 +243,15 @@ void redistribute_delete(struct prefix *p, struct prefix *src_p,
} }
} }
void zebra_redistribute_add(int command, struct zserv *client, int length, void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
struct zebra_vrf *zvrf)
{ {
afi_t afi = 0; afi_t afi = 0;
int type = 0; int type = 0;
u_short instance; u_short instance;
STREAM_GETC(client->ibuf, afi); STREAM_GETC(msg, afi);
STREAM_GETC(client->ibuf, type); STREAM_GETC(msg, type);
STREAM_GETW(client->ibuf, instance); STREAM_GETW(msg, instance);
if (afi == 0 || afi > AFI_MAX) { if (afi == 0 || afi > AFI_MAX) {
zlog_warn("%s: Specified afi %d does not exist", zlog_warn("%s: Specified afi %d does not exist",
@ -287,16 +286,15 @@ stream_failure:
return; return;
} }
void zebra_redistribute_delete(int command, struct zserv *client, int length, void zebra_redistribute_delete(ZAPI_HANDLER_ARGS)
struct zebra_vrf *zvrf)
{ {
afi_t afi = 0; afi_t afi = 0;
int type = 0; int type = 0;
u_short instance; u_short instance;
STREAM_GETC(client->ibuf, afi); STREAM_GETC(msg, afi);
STREAM_GETC(client->ibuf, type); STREAM_GETC(msg, type);
STREAM_GETW(client->ibuf, instance); STREAM_GETW(msg, instance);
if (afi == 0 || afi > AFI_MAX) { if (afi == 0 || afi > AFI_MAX) {
zlog_warn("%s: Specified afi %d does not exist", zlog_warn("%s: Specified afi %d does not exist",
@ -325,15 +323,13 @@ stream_failure:
return; return;
} }
void zebra_redistribute_default_add(int command, struct zserv *client, void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS)
int length, struct zebra_vrf *zvrf)
{ {
vrf_bitmap_set(client->redist_default, zvrf_id(zvrf)); vrf_bitmap_set(client->redist_default, zvrf_id(zvrf));
zebra_redistribute_default(client, zvrf_id(zvrf)); zebra_redistribute_default(client, zvrf_id(zvrf));
} }
void zebra_redistribute_default_delete(int command, struct zserv *client, void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS)
int length, struct zebra_vrf *zvrf)
{ {
vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf)); vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf));
} }

View File

@ -27,15 +27,12 @@
#include "vty.h" #include "vty.h"
#include "vrf.h" #include "vrf.h"
extern void zebra_redistribute_add(int, struct zserv *, int, /* ZAPI command handlers */
struct zebra_vrf *zvrf); extern void zebra_redistribute_add(ZAPI_HANDLER_ARGS);
extern void zebra_redistribute_delete(int, struct zserv *, int, extern void zebra_redistribute_delete(ZAPI_HANDLER_ARGS);
struct zebra_vrf *zvrf); extern void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS);
extern void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS);
extern void zebra_redistribute_default_add(int, struct zserv *, int, /* ----------------- */
struct zebra_vrf *zvrf);
extern void zebra_redistribute_default_delete(int, struct zserv *, int,
struct zebra_vrf *zvrf);
extern void redistribute_update(struct prefix *, struct prefix *, extern void redistribute_update(struct prefix *, struct prefix *,
struct route_entry *, struct route_entry *); struct route_entry *, struct route_entry *);

View File

@ -801,8 +801,7 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
* if the operator has explicitly enabled RA. The enable request can also * if the operator has explicitly enabled RA. The enable request can also
* specify a RA interval (in seconds). * specify a RA interval (in seconds).
*/ */
void zebra_interface_radv_set(struct zserv *client, u_short length, static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
struct zebra_vrf *zvrf, int enable)
{ {
struct stream *s; struct stream *s;
ifindex_t ifindex; ifindex_t ifindex;
@ -810,7 +809,7 @@ void zebra_interface_radv_set(struct zserv *client, u_short length,
struct zebra_if *zif; struct zebra_if *zif;
int ra_interval; int ra_interval;
s = client->ibuf; s = msg;
/* Get interface index and RA interval. */ /* Get interface index and RA interval. */
STREAM_GETL(s, ifindex); STREAM_GETL(s, ifindex);
@ -859,6 +858,15 @@ stream_failure:
return; return;
} }
void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
{
zebra_interface_radv_set(client, hdr, msg, zvrf, 0);
}
void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
{
zebra_interface_radv_set(client, hdr, msg, zvrf, 1);
}
DEFUN (ipv6_nd_suppress_ra, DEFUN (ipv6_nd_suppress_ra,
ipv6_nd_suppress_ra_cmd, ipv6_nd_suppress_ra_cmd,
"ipv6 nd suppress-ra", "ipv6 nd suppress-ra",

View File

@ -103,7 +103,8 @@ typedef enum {
extern void rtadv_init(struct zebra_ns *); extern void rtadv_init(struct zebra_ns *);
extern void rtadv_terminate(struct zebra_ns *); extern void rtadv_terminate(struct zebra_ns *);
extern void rtadv_cmd_init(void); extern void rtadv_cmd_init(void);
extern void zebra_interface_radv_set(struct zserv *client, u_short length, extern void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS);
struct zebra_vrf *zvrf, int enable); extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS);
#endif /* _ZEBRA_RTADV_H */ #endif /* _ZEBRA_RTADV_H */

View File

@ -455,8 +455,7 @@ static int fec_send(zebra_fec_t *fec, struct zserv *client)
rn = fec->rn; rn = fec->rn;
/* Get output stream. */ /* Get output stream. */
s = client->obuf; s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
zclient_create_header(s, ZEBRA_FEC_UPDATE, VRF_DEFAULT); zclient_create_header(s, ZEBRA_FEC_UPDATE, VRF_DEFAULT);
@ -464,7 +463,7 @@ static int fec_send(zebra_fec_t *fec, struct zserv *client)
stream_put_prefix(s, &rn->p); stream_put_prefix(s, &rn->p);
stream_putl(s, fec->label); stream_putl(s, fec->label);
stream_putw_at(s, 0, stream_get_endp(s)); stream_putw_at(s, 0, stream_get_endp(s));
return zebra_server_send_message(client); return zebra_server_send_message(client, s);
} }
/* /*

View File

@ -32,17 +32,16 @@
#include "zebra/rt.h" #include "zebra/rt.h"
#include "zebra/debug.h" #include "zebra/debug.h"
int zebra_ipmr_route_stats(struct zserv *client, u_short length, void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS)
struct zebra_vrf *zvrf)
{ {
struct mcast_route_data mroute; struct mcast_route_data mroute;
struct stream *s; struct stream *s;
int suc = -1; int suc = -1;
memset(&mroute, 0, sizeof(mroute)); memset(&mroute, 0, sizeof(mroute));
STREAM_GET(&mroute.sg.src, client->ibuf, 4); STREAM_GET(&mroute.sg.src, msg, 4);
STREAM_GET(&mroute.sg.grp, client->ibuf, 4); STREAM_GET(&mroute.sg.grp, msg, 4);
STREAM_GETL(client->ibuf, mroute.ifindex); STREAM_GETL(msg, mroute.ifindex);
if (IS_ZEBRA_DEBUG_KERNEL) { if (IS_ZEBRA_DEBUG_KERNEL) {
char sbuf[40]; char sbuf[40];
@ -57,7 +56,7 @@ int zebra_ipmr_route_stats(struct zserv *client, u_short length,
suc = kernel_get_ipmr_sg_stats(zvrf, &mroute); suc = kernel_get_ipmr_sg_stats(zvrf, &mroute);
stream_failure: stream_failure:
s = client->obuf; s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s); stream_reset(s);
@ -68,6 +67,5 @@ stream_failure:
stream_putl(s, suc); stream_putl(s, suc);
stream_putw_at(s, 0, stream_get_endp(s)); stream_putw_at(s, 0, stream_get_endp(s));
zebra_server_send_message(client); zebra_server_send_message(client, s);
return 0;
} }

View File

@ -22,13 +22,14 @@
#ifndef __ZEBRA_MROUTE_H__ #ifndef __ZEBRA_MROUTE_H__
#define __ZEBRA_MROUTE_H__ #define __ZEBRA_MROUTE_H__
#include "zebra/zserv.h"
struct mcast_route_data { struct mcast_route_data {
struct prefix_sg sg; struct prefix_sg sg;
unsigned int ifindex; unsigned int ifindex;
unsigned long long lastused; unsigned long long lastused;
}; };
int zebra_ipmr_route_stats(struct zserv *client, u_short length, void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS);
struct zebra_vrf *zvf);
#endif #endif

View File

@ -661,8 +661,7 @@ int zebra_ptm_sock_read(struct thread *thread)
} }
/* BFD peer/dst register/update */ /* BFD peer/dst register/update */
int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS)
int command, struct zebra_vrf *zvrf)
{ {
struct stream *s; struct stream *s;
struct prefix src_p; struct prefix src_p;
@ -680,20 +679,20 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length,
int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF;
unsigned int pid; unsigned int pid;
if (command == ZEBRA_BFD_DEST_UPDATE) if (hdr->command == ZEBRA_BFD_DEST_UPDATE)
client->bfd_peer_upd8_cnt++; client->bfd_peer_upd8_cnt++;
else else
client->bfd_peer_add_cnt++; client->bfd_peer_add_cnt++;
if (IS_ZEBRA_DEBUG_EVENT) if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("bfd_dst_register msg from client %s: length=%d", zlog_debug("bfd_dst_register msg from client %s: length=%d",
zebra_route_string(client->proto), length); zebra_route_string(client->proto), hdr->length);
if (ptm_cb.ptm_sock == -1) { if (ptm_cb.ptm_sock == -1) {
ptm_cb.t_timer = NULL; ptm_cb.t_timer = NULL;
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
ptm_cb.reconnect_time, &ptm_cb.t_timer); ptm_cb.reconnect_time, &ptm_cb.t_timer);
return -1; return;
} }
ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
@ -703,7 +702,7 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length,
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
tmp_buf); tmp_buf);
s = client->ibuf; s = msg;
STREAM_GETL(s, pid); STREAM_GETL(s, pid);
sprintf(tmp_buf, "%d", pid); sprintf(tmp_buf, "%d", pid);
@ -816,16 +815,14 @@ int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length,
ptm_cb.out_data); ptm_cb.out_data);
zebra_ptm_send_message(ptm_cb.out_data, data_len); zebra_ptm_send_message(ptm_cb.out_data, data_len);
return 0; return;
stream_failure: stream_failure:
ptm_lib_cleanup_msg(ptm_hdl, out_ctxt); ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
return 0;
} }
/* BFD peer/dst deregister */ /* BFD peer/dst deregister */
int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS)
struct zebra_vrf *zvrf)
{ {
struct stream *s; struct stream *s;
struct prefix src_p; struct prefix src_p;
@ -843,13 +840,13 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length,
if (IS_ZEBRA_DEBUG_EVENT) if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("bfd_dst_deregister msg from client %s: length=%d", zlog_debug("bfd_dst_deregister msg from client %s: length=%d",
zebra_route_string(client->proto), length); zebra_route_string(client->proto), hdr->length);
if (ptm_cb.ptm_sock == -1) { if (ptm_cb.ptm_sock == -1) {
ptm_cb.t_timer = NULL; ptm_cb.t_timer = NULL;
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
ptm_cb.reconnect_time, &ptm_cb.t_timer); ptm_cb.reconnect_time, &ptm_cb.t_timer);
return -1; return;
} }
ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
@ -861,7 +858,7 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length,
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD,
tmp_buf); tmp_buf);
s = client->ibuf; s = msg;
STREAM_GETL(s, pid); STREAM_GETL(s, pid);
sprintf(tmp_buf, "%d", pid); sprintf(tmp_buf, "%d", pid);
@ -948,15 +945,14 @@ int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length,
zebra_ptm_send_message(ptm_cb.out_data, data_len); zebra_ptm_send_message(ptm_cb.out_data, data_len);
return 0; return;
stream_failure: stream_failure:
ptm_lib_cleanup_msg(ptm_hdl, out_ctxt); ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
return 0;
} }
/* BFD client register */ /* BFD client register */
int zebra_ptm_bfd_client_register(struct zserv *client, u_short length) void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS)
{ {
struct stream *s; struct stream *s;
unsigned int pid; unsigned int pid;
@ -968,16 +964,16 @@ int zebra_ptm_bfd_client_register(struct zserv *client, u_short length)
if (IS_ZEBRA_DEBUG_EVENT) if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("bfd_client_register msg from client %s: length=%d", zlog_debug("bfd_client_register msg from client %s: length=%d",
zebra_route_string(client->proto), length); zebra_route_string(client->proto), hdr->length);
s = client->ibuf; s = msg;
STREAM_GETL(s, pid); STREAM_GETL(s, pid);
if (ptm_cb.ptm_sock == -1) { if (ptm_cb.ptm_sock == -1) {
ptm_cb.t_timer = NULL; ptm_cb.t_timer = NULL;
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL, thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
ptm_cb.reconnect_time, &ptm_cb.t_timer); ptm_cb.reconnect_time, &ptm_cb.t_timer);
return -1; return;
} }
ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt);
@ -1003,7 +999,7 @@ int zebra_ptm_bfd_client_register(struct zserv *client, u_short length)
SET_FLAG(ptm_cb.client_flags[client->proto], SET_FLAG(ptm_cb.client_flags[client->proto],
ZEBRA_PTM_BFD_CLIENT_FLAG_REG); ZEBRA_PTM_BFD_CLIENT_FLAG_REG);
return 0; return;
stream_failure: stream_failure:
/* /*
@ -1013,7 +1009,7 @@ stream_failure:
* if (out_ctxt) * if (out_ctxt)
* ptm_lib_cleanup_msg(ptm_hdl, out_ctxt); * ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
*/ */
return 0; return;
} }
/* BFD client deregister */ /* BFD client deregister */

View File

@ -28,6 +28,8 @@ extern const char ZEBRA_PTM_SOCK_NAME[];
#define ZEBRA_PTM_BFD_CLIENT_FLAG_REG (1 << 1) /* client registered with BFD */ #define ZEBRA_PTM_BFD_CLIENT_FLAG_REG (1 << 1) /* client registered with BFD */
#include "zebra/zserv.h"
/* Zebra ptm context block */ /* Zebra ptm context block */
struct zebra_ptm_cb { struct zebra_ptm_cb {
int ptm_sock; /* ptm file descriptor. */ int ptm_sock; /* ptm file descriptor. */
@ -62,12 +64,12 @@ int zebra_ptm_connect(struct thread *t);
void zebra_ptm_write(struct vty *vty); void zebra_ptm_write(struct vty *vty);
int zebra_ptm_get_enable_state(void); int zebra_ptm_get_enable_state(void);
int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length, /* ZAPI message handlers */
int command, struct zebra_vrf *zvrf); void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS);
int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length, void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS);
struct zebra_vrf *zvrf); void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS);
void zebra_ptm_show_status(struct vty *vty, struct interface *ifp); void zebra_ptm_show_status(struct vty *vty, struct interface *ifp);
int zebra_ptm_bfd_client_register(struct zserv *client, u_short length);
void zebra_ptm_if_init(struct zebra_if *zebra_ifp); void zebra_ptm_if_init(struct zebra_if *zebra_ifp);
void zebra_ptm_if_set_ptm_state(struct interface *ifp, void zebra_ptm_if_set_ptm_state(struct interface *ifp,
struct zebra_if *zebra_ifp); struct zebra_if *zebra_ifp);

View File

@ -38,8 +38,7 @@ static int zsend_interface_bfd_update(int cmd, struct zserv *client,
if (!client->ifinfo) if (!client->ifinfo)
return 0; return 0;
s = client->obuf; s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
zclient_create_header(s, cmd, vrf_id); zclient_create_header(s, cmd, vrf_id);
if (ifp) if (ifp)
@ -66,7 +65,7 @@ static int zsend_interface_bfd_update(int cmd, struct zserv *client,
stream_putw_at(s, 0, stream_get_endp(s)); stream_putw_at(s, 0, stream_get_endp(s));
client->if_bfd_cnt++; client->if_bfd_cnt++;
return zebra_server_send_message(client); return zebra_server_send_message(client, s);
} }
void zebra_interface_bfd_update(struct interface *ifp, struct prefix *dp, void zebra_interface_bfd_update(struct interface *ifp, struct prefix *dp,
@ -93,8 +92,7 @@ static int zsend_bfd_peer_replay(int cmd, struct zserv *client)
{ {
struct stream *s; struct stream *s;
s = client->obuf; s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
zclient_create_header(s, cmd, VRF_DEFAULT); zclient_create_header(s, cmd, VRF_DEFAULT);
@ -102,7 +100,7 @@ static int zsend_bfd_peer_replay(int cmd, struct zserv *client)
stream_putw_at(s, 0, stream_get_endp(s)); stream_putw_at(s, 0, stream_get_endp(s));
client->bfd_peer_replay_cnt++; client->bfd_peer_replay_cnt++;
return zebra_server_send_message(client); return zebra_server_send_message(client, s);
} }
void zebra_bfd_peer_replay_req(void) void zebra_bfd_peer_replay_req(void)

View File

@ -305,6 +305,8 @@ struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX; nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
nexthop->gate.ipv6 = *ipv6; nexthop->gate.ipv6 = *ipv6;
nexthop->ifindex = ifindex; nexthop->ifindex = ifindex;
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
route_entry_nexthop_add(re, nexthop); route_entry_nexthop_add(re, nexthop);
@ -421,6 +423,10 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
re->nexthop_mtu = 0; re->nexthop_mtu = 0;
} }
/* Next hops (remote VTEPs) for EVPN routes are fully resolved. */
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN_RVTEP))
return 1;
/* Skip nexthops that have been filtered out due to route-map */ /* Skip nexthops that have been filtered out due to route-map */
/* The nexthops are specific to this route and so the same */ /* The nexthops are specific to this route and so the same */
/* nexthop for a different route may not have this flag set */ /* nexthop for a different route may not have this flag set */
@ -859,9 +865,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX: case NEXTHOP_TYPE_IPV4_IFINDEX:
family = AFI_IP; family = AFI_IP;
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN_RVTEP)) if (nexthop_active(AFI_IP, re, nexthop, set, rn))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
else if (nexthop_active(AFI_IP, re, nexthop, set, rn))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
else else
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
@ -2554,10 +2558,17 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
struct ipaddr vtep_ip; struct ipaddr vtep_ip;
memset(&vtep_ip, 0, sizeof(struct ipaddr)); memset(&vtep_ip, 0, sizeof(struct ipaddr));
vtep_ip.ipa_type = IPADDR_V4; if (afi == AFI_IP) {
memcpy(&(vtep_ip.ipaddr_v4), vtep_ip.ipa_type = IPADDR_V4;
&(tmp_nh->gate.ipv4), memcpy(&(vtep_ip.ipaddr_v4),
sizeof(struct in_addr)); &(tmp_nh->gate.ipv4),
sizeof(struct in_addr));
} else {
vtep_ip.ipa_type = IPADDR_V6;
memcpy(&(vtep_ip.ipaddr_v6),
&(tmp_nh->gate.ipv6),
sizeof(struct in6_addr));
}
zebra_vxlan_evpn_vrf_route_del(re->vrf_id, rmac, zebra_vxlan_evpn_vrf_route_del(re->vrf_id, rmac,
&vtep_ip, p); &vtep_ip, p);
} }

View File

@ -995,8 +995,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
re = rnh->state; re = rnh->state;
/* Get output stream. */ /* Get output stream. */
s = client->obuf; s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
zclient_create_header(s, cmd, vrf_id); zclient_create_header(s, cmd, vrf_id);
@ -1063,7 +1062,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
client->nh_last_upd_time = monotime(NULL); client->nh_last_upd_time = monotime(NULL);
client->last_write_cmd = cmd; client->last_write_cmd = cmd;
return zebra_server_send_message(client); return zebra_server_send_message(client, s);
} }
static void print_nh(struct nexthop *nexthop, struct vty *vty) static void print_nh(struct nexthop *nexthop, struct vty *vty)

View File

@ -1157,8 +1157,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
if (!client) if (!client)
return 0; return 0;
s = client->obuf; s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
zclient_create_header(s, cmd, VRF_DEFAULT); zclient_create_header(s, cmd, VRF_DEFAULT);
stream_putl(s, vni); stream_putl(s, vni);
@ -1195,7 +1194,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
else else
client->macipdel_cnt++; client->macipdel_cnt++;
return zebra_server_send_message(client); return zebra_server_send_message(client, s);
} }
/* /*
@ -2565,8 +2564,7 @@ static int zvni_send_add_to_client(zebra_vni_t *zvni)
if (!client) if (!client)
return 0; return 0;
s = client->obuf; s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
zclient_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT); zclient_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT);
stream_putl(s, zvni->vni); stream_putl(s, zvni->vni);
@ -2583,7 +2581,7 @@ static int zvni_send_add_to_client(zebra_vni_t *zvni)
zebra_route_string(client->proto)); zebra_route_string(client->proto));
client->vniadd_cnt++; client->vniadd_cnt++;
return zebra_server_send_message(client); return zebra_server_send_message(client, s);
} }
/* /*
@ -2599,7 +2597,7 @@ static int zvni_send_del_to_client(vni_t vni)
if (!client) if (!client)
return 0; return 0;
s = client->obuf; s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s); stream_reset(s);
zclient_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT); zclient_create_header(s, ZEBRA_VNI_DEL, VRF_DEFAULT);
@ -2613,7 +2611,7 @@ static int zvni_send_del_to_client(vni_t vni)
zebra_route_string(client->proto)); zebra_route_string(client->proto));
client->vnidel_cnt++; client->vnidel_cnt++;
return zebra_server_send_message(client); return zebra_server_send_message(client, s);
} }
/* /*
@ -3550,8 +3548,7 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
memset(&rmac, 0, sizeof(struct ethaddr)); memset(&rmac, 0, sizeof(struct ethaddr));
zl3vni_get_rmac(zl3vni, &rmac); zl3vni_get_rmac(zl3vni, &rmac);
s = client->obuf; s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni)); zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni));
stream_putl(s, zl3vni->vni); stream_putl(s, zl3vni->vni);
@ -3574,7 +3571,7 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
zebra_route_string(client->proto)); zebra_route_string(client->proto));
client->l3vniadd_cnt++; client->l3vniadd_cnt++;
return zebra_server_send_message(client); return zebra_server_send_message(client, s);
} }
/* /*
@ -3590,8 +3587,7 @@ static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni)
if (!client) if (!client)
return 0; return 0;
s = client->obuf; s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni)); zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni));
stream_putl(s, zl3vni->vni); stream_putl(s, zl3vni->vni);
@ -3605,7 +3601,7 @@ static int zl3vni_send_del_to_client(zebra_l3vni_t *zl3vni)
zebra_route_string(client->proto)); zebra_route_string(client->proto));
client->l3vnidel_cnt++; client->l3vnidel_cnt++;
return zebra_server_send_message(client); return zebra_server_send_message(client, s);
} }
static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni) static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni)
@ -3723,8 +3719,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
if (!client) if (!client)
return 0; return 0;
s = client->obuf; s = stream_new(ZEBRA_MAX_PACKET_SIZ);
stream_reset(s);
zclient_create_header(s, cmd, vrf_id); zclient_create_header(s, cmd, vrf_id);
stream_put(s, p, sizeof(struct prefix)); stream_put(s, p, sizeof(struct prefix));
@ -3743,7 +3738,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
else else
client->prefixdel_cnt++; client->prefixdel_cnt++;
return zebra_server_send_message(client); return zebra_server_send_message(client, s);
} }
/* re-add remote rmac if needed */ /* re-add remote rmac if needed */
@ -4863,8 +4858,7 @@ int zebra_vxlan_local_neigh_add_update(struct interface *ifp,
/* /*
* Handle message from client to delete a remote MACIP for a VNI. * Handle message from client to delete a remote MACIP for a VNI.
*/ */
int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length, void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
struct zebra_vrf *zvrf)
{ {
struct stream *s; struct stream *s;
vni_t vni; vni_t vni;
@ -4884,9 +4878,9 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length,
memset(&ip, 0, sizeof(struct ipaddr)); memset(&ip, 0, sizeof(struct ipaddr));
memset(&vtep_ip, 0, sizeof(struct in_addr)); memset(&vtep_ip, 0, sizeof(struct in_addr));
s = client->ibuf; s = msg;
while (l < length) { while (l < hdr->length) {
/* Obtain each remote MACIP and process. */ /* Obtain each remote MACIP and process. */
/* Message contains VNI, followed by MAC followed by IP (if any) /* Message contains VNI, followed by MAC followed by IP (if any)
* followed by remote VTEP IP. * followed by remote VTEP IP.
@ -5008,7 +5002,7 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length,
} }
stream_failure: stream_failure:
return 0; return;
} }
/* /*
@ -5016,8 +5010,7 @@ stream_failure:
* could be just the add of a MAC address or the add of a neighbor * could be just the add of a MAC address or the add of a neighbor
* (IP+MAC). * (IP+MAC).
*/ */
int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length, void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
struct zebra_vrf *zvrf)
{ {
struct stream *s; struct stream *s;
vni_t vni; vni_t vni;
@ -5045,12 +5038,12 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
zlog_warn( zlog_warn(
"%s: EVPN Not turned on yet we have received a remote_macip add zapi callback", "%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
__PRETTY_FUNCTION__); __PRETTY_FUNCTION__);
return -1; return;
} }
s = client->ibuf; s = msg;
while (l < length) { while (l < hdr->length) {
/* Obtain each remote MACIP and process. */ /* Obtain each remote MACIP and process. */
/* Message contains VNI, followed by MAC followed by IP (if any) /* Message contains VNI, followed by MAC followed by IP (if any)
* followed by remote VTEP IP. * followed by remote VTEP IP.
@ -5159,7 +5152,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
prefix_mac2str(&macaddr, buf, prefix_mac2str(&macaddr, buf,
sizeof(buf)), sizeof(buf)),
vni, inet_ntoa(vtep_ip)); vni, inet_ntoa(vtep_ip));
return -1; return;
} }
/* Is this MAC created for a MACIP? */ /* Is this MAC created for a MACIP? */
@ -5212,7 +5205,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
prefix_mac2str(&macaddr, buf, prefix_mac2str(&macaddr, buf,
sizeof(buf)), sizeof(buf)),
vni, inet_ntoa(vtep_ip)); vni, inet_ntoa(vtep_ip));
return -1; return;
} }
} else if (memcmp(&n->emac, &macaddr, sizeof(macaddr)) } else if (memcmp(&n->emac, &macaddr, sizeof(macaddr))
@ -5240,7 +5233,7 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
} }
stream_failure: stream_failure:
return 0; return;
} }
/* /*
@ -5543,8 +5536,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
/* /*
* Handle message from client to delete a remote VTEP for a VNI. * Handle message from client to delete a remote VTEP for a VNI.
*/ */
int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length, void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)
struct zebra_vrf *zvrf)
{ {
struct stream *s; struct stream *s;
u_short l = 0; u_short l = 0;
@ -5559,18 +5551,18 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length,
zlog_warn( zlog_warn(
"%s: EVPN is not enabled yet we have received a vtep del command", "%s: EVPN is not enabled yet we have received a vtep del command",
__PRETTY_FUNCTION__); __PRETTY_FUNCTION__);
return -1; return;
} }
if (zvrf_id(zvrf) != VRF_DEFAULT) { if (zvrf_id(zvrf) != VRF_DEFAULT) {
zlog_err("Recv MACIP DEL for non-default VRF %u", zlog_err("Recv MACIP DEL for non-default VRF %u",
zvrf_id(zvrf)); zvrf_id(zvrf));
return -1; return;
} }
s = client->ibuf; s = msg;
while (l < length) { while (l < hdr->length) {
/* Obtain each remote VTEP and process. */ /* Obtain each remote VTEP and process. */
STREAM_GETL(s, vni); STREAM_GETL(s, vni);
l += 4; l += 4;
@ -5623,14 +5615,13 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length,
} }
stream_failure: stream_failure:
return 0; return;
} }
/* /*
* Handle message from client to add a remote VTEP for a VNI. * Handle message from client to add a remote VTEP for a VNI.
*/ */
int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length, void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)
struct zebra_vrf *zvrf)
{ {
struct stream *s; struct stream *s;
u_short l = 0; u_short l = 0;
@ -5644,18 +5635,18 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length,
zlog_warn( zlog_warn(
"%s: EVPN not enabled yet we received a vtep_add zapi call", "%s: EVPN not enabled yet we received a vtep_add zapi call",
__PRETTY_FUNCTION__); __PRETTY_FUNCTION__);
return -1; return;
} }
if (zvrf_id(zvrf) != VRF_DEFAULT) { if (zvrf_id(zvrf) != VRF_DEFAULT) {
zlog_err("Recv MACIP ADD for non-default VRF %u", zlog_err("Recv MACIP ADD for non-default VRF %u",
zvrf_id(zvrf)); zvrf_id(zvrf));
return -1; return;
} }
s = client->ibuf; s = msg;
while (l < length) { while (l < hdr->length) {
/* Obtain each remote VTEP and process. */ /* Obtain each remote VTEP and process. */
STREAM_GETL(s, vni); STREAM_GETL(s, vni);
l += 4; l += 4;
@ -5705,7 +5696,7 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length,
} }
stream_failure: stream_failure:
return 0; return;
} }
/* /*
@ -6512,8 +6503,7 @@ int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf)
* Handle message from client to enable/disable advertisement of g/w macip * Handle message from client to enable/disable advertisement of g/w macip
* routes * routes
*/ */
int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length, void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)
struct zebra_vrf *zvrf)
{ {
struct stream *s; struct stream *s;
int advertise; int advertise;
@ -6527,19 +6517,19 @@ int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length,
if (zvrf_id(zvrf) != VRF_DEFAULT) { if (zvrf_id(zvrf) != VRF_DEFAULT) {
zlog_err("EVPN GW-MACIP Adv for non-default VRF %u", zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
zvrf_id(zvrf)); zvrf_id(zvrf));
return -1; return;
} }
s = client->ibuf; s = msg;
advertise = stream_getc(s); advertise = stream_getc(s);
vni = stream_get3(s); vni = stream_get3(s);
zvni = zvni_lookup(vni); zvni = zvni_lookup(vni);
if (!zvni) if (!zvni)
return 0; return;
if (zvni->advertise_subnet == advertise) if (zvni->advertise_subnet == advertise)
return 0; return;
if (IS_ZEBRA_DEBUG_VXLAN) if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s", zlog_debug("EVPN subnet Adv %s on VNI %d , currently %s",
@ -6551,35 +6541,32 @@ int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length,
ifp = zvni->vxlan_if; ifp = zvni->vxlan_if;
if (!ifp) if (!ifp)
return 0; return;
zif = ifp->info; zif = ifp->info;
/* If down or not mapped to a bridge, we're done. */ /* If down or not mapped to a bridge, we're done. */
if (!if_is_operative(ifp) || !zif->brslave_info.br_if) if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
return 0; return;
zl2_info = zif->l2info.vxl; zl2_info = zif->l2info.vxl;
vlan_if = vlan_if =
zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if); zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
if (!vlan_if) if (!vlan_if)
return 0; return;
if (zvni->advertise_subnet) if (zvni->advertise_subnet)
zvni_advertise_subnet(zvni, vlan_if, 1); zvni_advertise_subnet(zvni, vlan_if, 1);
else else
zvni_advertise_subnet(zvni, vlan_if, 0); zvni_advertise_subnet(zvni, vlan_if, 0);
return 0;
} }
/* /*
* Handle message from client to enable/disable advertisement of g/w macip * Handle message from client to enable/disable advertisement of g/w macip
* routes * routes
*/ */
int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length, void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)
struct zebra_vrf *zvrf)
{ {
struct stream *s; struct stream *s;
int advertise; int advertise;
@ -6590,10 +6577,10 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
if (zvrf_id(zvrf) != VRF_DEFAULT) { if (zvrf_id(zvrf) != VRF_DEFAULT) {
zlog_err("EVPN GW-MACIP Adv for non-default VRF %u", zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
zvrf_id(zvrf)); zvrf_id(zvrf));
return -1; return;
} }
s = client->ibuf; s = msg;
STREAM_GETC(s, advertise); STREAM_GETC(s, advertise);
STREAM_GET(&vni, s, 3); STREAM_GET(&vni, s, 3);
@ -6606,7 +6593,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
: "disabled"); : "disabled");
if (zvrf->advertise_gw_macip == advertise) if (zvrf->advertise_gw_macip == advertise)
return 0; return;
zvrf->advertise_gw_macip = advertise; zvrf->advertise_gw_macip = advertise;
@ -6625,7 +6612,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
zvni = zvni_lookup(vni); zvni = zvni_lookup(vni);
if (!zvni) if (!zvni)
return 0; return;
if (IS_ZEBRA_DEBUG_VXLAN) if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug( zlog_debug(
@ -6635,26 +6622,26 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
: "disabled"); : "disabled");
if (zvni->advertise_gw_macip == advertise) if (zvni->advertise_gw_macip == advertise)
return 0; return;
zvni->advertise_gw_macip = advertise; zvni->advertise_gw_macip = advertise;
ifp = zvni->vxlan_if; ifp = zvni->vxlan_if;
if (!ifp) if (!ifp)
return 0; return;
zif = ifp->info; zif = ifp->info;
/* If down or not mapped to a bridge, we're done. */ /* If down or not mapped to a bridge, we're done. */
if (!if_is_operative(ifp) || !zif->brslave_info.br_if) if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
return 0; return;
zl2_info = zif->l2info.vxl; zl2_info = zif->l2info.vxl;
vlan_if = zvni_map_to_svi(zl2_info.access_vlan, vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
zif->brslave_info.br_if); zif->brslave_info.br_if);
if (!vlan_if) if (!vlan_if)
return 0; return;
if (advertise_gw_macip_enabled(zvni)) { if (advertise_gw_macip_enabled(zvni)) {
/* Add primary SVI MAC-IP */ /* Add primary SVI MAC-IP */
@ -6676,7 +6663,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
} }
stream_failure: stream_failure:
return 0; return;
} }
@ -6686,8 +6673,7 @@ stream_failure:
* when disabled, the entries should be deleted and remote VTEPs and MACs * when disabled, the entries should be deleted and remote VTEPs and MACs
* uninstalled from the kernel. * uninstalled from the kernel.
*/ */
int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length, void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
struct zebra_vrf *zvrf)
{ {
struct stream *s = NULL; struct stream *s = NULL;
int advertise = 0; int advertise = 0;
@ -6695,10 +6681,10 @@ int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length,
if (zvrf_id(zvrf) != VRF_DEFAULT) { if (zvrf_id(zvrf) != VRF_DEFAULT) {
zlog_err("EVPN VNI Adv for non-default VRF %u", zvrf_id(zvrf)); zlog_err("EVPN VNI Adv for non-default VRF %u", zvrf_id(zvrf));
return -1; return;
} }
s = client->ibuf; s = msg;
STREAM_GETC(s, advertise); STREAM_GETC(s, advertise);
if (IS_ZEBRA_DEBUG_VXLAN) if (IS_ZEBRA_DEBUG_VXLAN)
@ -6707,7 +6693,7 @@ int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length,
is_evpn_enabled() ? "enabled" : "disabled"); is_evpn_enabled() ? "enabled" : "disabled");
if (zvrf->advertise_all_vni == advertise) if (zvrf->advertise_all_vni == advertise)
return 0; return;
zvrf->advertise_all_vni = advertise; zvrf->advertise_all_vni = advertise;
if (is_evpn_enabled()) { if (is_evpn_enabled()) {
@ -6732,13 +6718,13 @@ int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length,
/* cleanup all l3vnis */ /* cleanup all l3vnis */
zns = zebra_ns_lookup(NS_DEFAULT); zns = zebra_ns_lookup(NS_DEFAULT);
if (!zns) if (!zns)
return -1; return;
hash_iterate(zns->l3vni_table, zl3vni_cleanup_all, NULL); hash_iterate(zns->l3vni_table, zl3vni_cleanup_all, NULL);
} }
stream_failure: stream_failure:
return 0; return;
} }
/* /*

View File

@ -33,6 +33,7 @@
#include "lib/json.h" #include "lib/json.h"
#include "zebra/zebra_vrf.h" #include "zebra/zebra_vrf.h"
#include "zebra/zserv.h"
/* Is EVPN enabled? */ /* Is EVPN enabled? */
#define EVPN_ENABLED(zvrf) (zvrf)->advertise_all_vni #define EVPN_ENABLED(zvrf) (zvrf)->advertise_all_vni
@ -51,6 +52,15 @@ static inline int is_evpn_enabled()
#define VNI_STR_LEN 32 #define VNI_STR_LEN 32
/* ZAPI message handlers */
extern void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS);
extern void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS);
extern void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS);
extern void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS);
extern void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS);
extern void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS);
extern void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS);
extern int is_l3vni_for_prefix_routes_only(vni_t vni); extern int is_l3vni_for_prefix_routes_only(vni_t vni);
extern ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id); extern ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id);
extern int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf); extern int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf);
@ -117,10 +127,6 @@ extern int zebra_vxlan_local_neigh_add_update(
extern int zebra_vxlan_local_neigh_del(struct interface *ifp, extern int zebra_vxlan_local_neigh_del(struct interface *ifp,
struct interface *link_if, struct interface *link_if,
struct ipaddr *ip); struct ipaddr *ip);
extern int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
struct zebra_vrf *zvrf);
extern int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length,
struct zebra_vrf *zvrf);
extern int zebra_vxlan_local_mac_add_update(struct interface *ifp, extern int zebra_vxlan_local_mac_add_update(struct interface *ifp,
struct interface *br_if, struct interface *br_if,
struct ethaddr *mac, vlanid_t vid, struct ethaddr *mac, vlanid_t vid,
@ -140,16 +146,6 @@ extern int zebra_vxlan_if_down(struct interface *ifp);
extern int zebra_vxlan_if_add(struct interface *ifp); extern int zebra_vxlan_if_add(struct interface *ifp);
extern int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags); extern int zebra_vxlan_if_update(struct interface *ifp, u_int16_t chgflags);
extern int zebra_vxlan_if_del(struct interface *ifp); extern int zebra_vxlan_if_del(struct interface *ifp);
extern int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length,
struct zebra_vrf *zvrf);
extern int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length,
struct zebra_vrf *zvrf);
extern int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length,
struct zebra_vrf *zvrf);
extern int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
struct zebra_vrf *zvrf);
extern int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length,
struct zebra_vrf *zvrf);
extern int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni, extern int zebra_vxlan_process_vrf_vni_cmd(struct zebra_vrf *zvrf, vni_t vni,
char *err, int err_str_sz, char *err, int err_str_sz,
int filter, int add); int filter, int add);

File diff suppressed because it is too large Load Diff

View File

@ -47,8 +47,12 @@ struct zserv {
int sock; int sock;
/* Input/output buffer to the client. */ /* Input/output buffer to the client. */
struct stream *ibuf; struct stream_fifo *ibuf_fifo;
struct stream *obuf; struct stream_fifo *obuf_fifo;
/* Private I/O buffers */
struct stream *ibuf_work;
struct stream *obuf_work;
/* Buffer of data waiting to be written to client. */ /* Buffer of data waiting to be written to client. */
struct buffer *wb; struct buffer *wb;
@ -129,6 +133,10 @@ struct zserv {
int last_write_cmd; int last_write_cmd;
}; };
#define ZAPI_HANDLER_ARGS \
struct zserv *client, struct zmsghdr *hdr, struct stream *msg, \
struct zebra_vrf *zvrf
/* Zebra instance */ /* Zebra instance */
struct zebra_t { struct zebra_t {
/* Thread master */ /* Thread master */
@ -185,7 +193,7 @@ extern void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
extern void zserv_nexthop_num_warn(const char *, const struct prefix *, extern void zserv_nexthop_num_warn(const char *, const struct prefix *,
const unsigned int); const unsigned int);
extern int zebra_server_send_message(struct zserv *client); extern int zebra_server_send_message(struct zserv *client, struct stream *msg);
extern struct zserv *zebra_find_client(u_char proto, u_short instance); extern struct zserv *zebra_find_client(u_char proto, u_short instance);