mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 18:42:23 +00:00
Merge branch 'master' of https://github.com/frrouting/frr into pmsi-parse-display
This commit is contained in:
commit
783e95b8e8
3
.gitignore
vendored
3
.gitignore
vendored
@ -82,3 +82,6 @@ GPATH
|
||||
*.lo
|
||||
compile_commands.json
|
||||
.dirstamp
|
||||
|
||||
# clippy generated source
|
||||
*_clippy.c
|
||||
|
36
alpine/APKBUILD.in
Normal file
36
alpine/APKBUILD.in
Normal 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
1
bgpd/.gitignore
vendored
@ -16,4 +16,3 @@ TAGS
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
*clippy.c
|
||||
|
191
bgpd/bgp_evpn.c
191
bgpd/bgp_evpn.c
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
@ -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
|
||||
* applicable to all routes.
|
||||
* TODO: currently kernel doesnt support ipv6 routes with ipv4 nexthops.
|
||||
* This means that we can't do symmetric routing for ipv6 hosts routes
|
||||
* in the same way as ipv4 host routes.
|
||||
* We wont attach l3-vni related RTs for ipv6 routes.
|
||||
* For now, We will only adevrtise ipv4 host routes
|
||||
* with L3-VNI related ext-comm.
|
||||
* Build extended communities for EVPN route.
|
||||
* This function is applicable for type-2 and type-3 routes. The layer-2 RT
|
||||
* and ENCAP extended communities are applicable for all routes.
|
||||
* The default gateway extended community and MAC mobility (sticky) extended
|
||||
* community are added as needed based on passed settings - only for type-2
|
||||
* routes. Likewise, the layer-3 RT and Router MAC extended communities are
|
||||
* added, if present, based on passed settings - only for non-link-local
|
||||
* type-2 routes.
|
||||
*/
|
||||
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_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))
|
||||
attr->ecommunity = ecommunity_merge(attr->ecommunity, ecom);
|
||||
|
||||
/*
|
||||
* only attach l3-vni export rts for ipv4 address family and if we are
|
||||
* advertising both the labels in type-2 routes
|
||||
/* Add the export RTs for L3VNI if told to - caller determines
|
||||
* when this should be done.
|
||||
*/
|
||||
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);
|
||||
if (vrf_export_rtl && !list_isempty(vrf_export_rtl)) {
|
||||
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) {
|
||||
seqnum = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* only attach l3-vni rmac for ipv4 address family and if we are
|
||||
* 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)) {
|
||||
/* Add RMAC, if told to. */
|
||||
if (add_l3_ecomm) {
|
||||
memset(&ecom_rmac, 0, sizeof(ecom_rmac));
|
||||
encode_rmac_extcomm(&eval_rmac, &attr->rmac);
|
||||
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);
|
||||
}
|
||||
|
||||
/* Add default gateway, if needed. */
|
||||
if (attr->default_gw) {
|
||||
memset(&ecom_default_gw, 0, sizeof(ecom_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 attr attr;
|
||||
struct attr *attr_new;
|
||||
int add_l3_ecomm = 0;
|
||||
struct bgp_info *ri;
|
||||
afi_t afi = AFI_L2VPN;
|
||||
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)
|
||||
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)
|
||||
bgpevpn_get_rmac(vpn, &attr.rmac);
|
||||
vni2label(vpn->vni, &(attr.label));
|
||||
|
||||
/* Set up RT and ENCAP extended community. */
|
||||
build_evpn_route_extcomm(
|
||||
vpn, &attr, IS_EVPN_PREFIX_IPADDR_V4(p) ? AFI_IP : AFI_IP6);
|
||||
/* Include L3 VNI related RTs and RMAC for type-2 routes, if they're
|
||||
* IPv4 or IPv6 global addresses and we're advertising L3VNI with
|
||||
* 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. */
|
||||
/* 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_sticky;
|
||||
struct attr attr_def_gw;
|
||||
struct attr attr_ip6;
|
||||
struct attr attr_sticky_ip6;
|
||||
struct attr attr_def_gw_ip6;
|
||||
struct attr attr_ip6_ll;
|
||||
struct attr *attr_new;
|
||||
int add_l3_ecomm = 0;
|
||||
|
||||
afi = AFI_L2VPN;
|
||||
safi = SAFI_EVPN;
|
||||
memset(&attr, 0, sizeof(struct attr));
|
||||
memset(&attr_sticky, 0, sizeof(struct attr));
|
||||
memset(&attr_def_gw, 0, sizeof(struct attr));
|
||||
memset(&attr_ip6, 0, sizeof(struct attr));
|
||||
memset(&attr_sticky_ip6, 0, sizeof(struct attr));
|
||||
memset(&attr_def_gw_ip6, 0, sizeof(struct attr));
|
||||
memset(&attr_ip6_ll, 0, sizeof(struct attr));
|
||||
|
||||
/* Build path-attribute - all type-2 routes for this VNI will share the
|
||||
* same path attribute.
|
||||
/* Build path-attribute - multiple type-2 routes for this VNI will share
|
||||
* 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_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.default_gw = 1;
|
||||
bgpevpn_get_rmac(vpn, &attr_def_gw.rmac);
|
||||
bgp_attr_default_set(&attr_ip6, BGP_ORIGIN_IGP);
|
||||
bgp_attr_default_set(&attr_sticky_ip6, BGP_ORIGIN_IGP);
|
||||
bgp_attr_default_set(&attr_def_gw_ip6, BGP_ORIGIN_IGP);
|
||||
attr_ip6.nexthop = vpn->originator_ip;
|
||||
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);
|
||||
bgp_attr_default_set(&attr_ip6_ll, BGP_ORIGIN_IGP);
|
||||
attr_ip6_ll.nexthop = vpn->originator_ip;
|
||||
attr_ip6_ll.mp_nexthop_global_in = vpn->originator_ip;
|
||||
attr_ip6_ll.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
|
||||
|
||||
/* Set up RT, ENCAP and sticky MAC extended community. */
|
||||
build_evpn_route_extcomm(vpn, &attr, AFI_IP);
|
||||
build_evpn_route_extcomm(vpn, &attr_sticky, AFI_IP);
|
||||
build_evpn_route_extcomm(vpn, &attr_def_gw, AFI_IP);
|
||||
build_evpn_route_extcomm(vpn, &attr_ip6, AFI_IP6);
|
||||
build_evpn_route_extcomm(vpn, &attr_sticky_ip6, AFI_IP6);
|
||||
build_evpn_route_extcomm(vpn, &attr_def_gw_ip6, AFI_IP);
|
||||
/* Add L3 VNI RTs and RMAC for non IPv6 link-local attributes if
|
||||
* using L3 VNI for type-2 routes also.
|
||||
*/
|
||||
if (CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS))
|
||||
add_l3_ecomm = 1;
|
||||
|
||||
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
|
||||
* 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)
|
||||
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))
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&attr_sticky, 0, 1, &ri,
|
||||
@ -1550,19 +1560,6 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
else
|
||||
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
|
||||
&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
|
||||
@ -1593,11 +1590,9 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
|
||||
|
||||
/* Unintern temporary. */
|
||||
aspath_unintern(&attr.aspath);
|
||||
aspath_unintern(&attr_ip6.aspath);
|
||||
aspath_unintern(&attr_sticky.aspath);
|
||||
aspath_unintern(&attr_sticky_ip6.aspath);
|
||||
aspath_unintern(&attr_def_gw.aspath);
|
||||
aspath_unintern(&attr_def_gw_ip6.aspath);
|
||||
aspath_unintern(&attr_ip6_ll.aspath);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1791,6 +1786,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
|
||||
{
|
||||
struct bgp_node *rn;
|
||||
struct bgp_info *ri;
|
||||
struct attr attr;
|
||||
struct attr *attr_new;
|
||||
int ret = 0;
|
||||
struct prefix p;
|
||||
@ -1827,6 +1823,15 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
|
||||
} else
|
||||
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. */
|
||||
for (ri = rn->info; ri; ri = ri->next)
|
||||
if (ri->extra
|
||||
@ -1835,7 +1840,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
|
||||
|
||||
if (!ri) {
|
||||
/* 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. */
|
||||
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);
|
||||
} else {
|
||||
if (attrhash_cmp(ri->attr, parent_ri->attr)
|
||||
if (attrhash_cmp(ri->attr, &attr)
|
||||
&& !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) {
|
||||
bgp_unlock_node(rn);
|
||||
return 0;
|
||||
}
|
||||
/* The attribute has changed. */
|
||||
/* Add (or update) attribute to hash. */
|
||||
attr_new = bgp_attr_intern(parent_ri->attr);
|
||||
attr_new = bgp_attr_intern(&attr);
|
||||
|
||||
/* Restore route, if needed. */
|
||||
if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
|
||||
bgp_info_restore(rn, ri);
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* 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 */
|
||||
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
|
||||
@ -2588,10 +2599,12 @@ static void delete_withdraw_vrf_routes(struct bgp *bgp_vrf)
|
||||
static void update_advertise_vrf_routes(struct bgp *bgp_vrf)
|
||||
{
|
||||
/* 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 */
|
||||
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;
|
||||
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);
|
||||
ret = delete_evpn_type5_route(bgp_vrf, &evp);
|
||||
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_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];
|
||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
|
||||
/* Only care about "selected" routes - non-imported. */
|
||||
@ -3280,11 +3285,7 @@ void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct prefix *p,
|
||||
int ret = 0;
|
||||
struct prefix_evpn evp;
|
||||
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);
|
||||
ret = update_evpn_type5_route(bgp_vrf, &evp, src_attr);
|
||||
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_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];
|
||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
|
||||
/* Need to identify the "selected" route entry to use its
|
||||
|
@ -55,6 +55,25 @@ static inline vni_t label2vni(mpls_label_t *label)
|
||||
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,
|
||||
struct prefix *p,
|
||||
struct attr *src_attr, afi_t afi,
|
||||
|
@ -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,
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
return 0;
|
||||
|
||||
if (afi == AFI_IP
|
||||
&& CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN))
|
||||
if (afi == AFI_IP &&
|
||||
CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
|
||||
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
|
||||
return 1;
|
||||
|
||||
if (afi == AFI_IP6
|
||||
&& CHECK_FLAG(bgp_vrf->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN))
|
||||
else if (afi == AFI_IP6 &&
|
||||
CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
|
||||
BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2419,7 +2419,50 @@ static void evpn_unset_advertise_default_gw(struct bgp *bgp,
|
||||
/*
|
||||
* 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)
|
||||
return;
|
||||
@ -2612,6 +2655,43 @@ DEFUN (no_bgp_evpn_advertise_all_vni,
|
||||
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,
|
||||
bgp_evpn_advertise_vni_subnet_cmd,
|
||||
"advertise-subnet",
|
||||
@ -2631,14 +2711,6 @@ DEFUN (bgp_evpn_advertise_vni_subnet,
|
||||
if (!bgp_vrf)
|
||||
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);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
@ -2711,19 +2783,23 @@ DEFUN (bgp_evpn_advertise_type5,
|
||||
/* if we are already advertising ipv4 prefix as type-5
|
||||
* nothing to do
|
||||
*/
|
||||
if (!rmap_changed && CHECK_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_ADVERTISE_IPV4_IN_EVPN))
|
||||
if (!rmap_changed &&
|
||||
CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
|
||||
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
|
||||
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 {
|
||||
|
||||
/* if we are already advertising ipv6 prefix as type-5
|
||||
* nothing to do
|
||||
*/
|
||||
if (!rmap_changed && CHECK_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_ADVERTISE_IPV6_IN_EVPN))
|
||||
if (!rmap_changed &&
|
||||
CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
|
||||
BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
|
||||
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) {
|
||||
@ -2766,7 +2842,7 @@ DEFUN (no_bgp_evpn_advertise_type5,
|
||||
argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
|
||||
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,
|
||||
"%%only ipv4 or ipv6 address families are supported");
|
||||
return CMD_WARNING;
|
||||
@ -2780,25 +2856,25 @@ DEFUN (no_bgp_evpn_advertise_type5,
|
||||
|
||||
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
|
||||
*/
|
||||
if (CHECK_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) {
|
||||
if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
|
||||
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
|
||||
bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
|
||||
UNSET_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_ADVERTISE_IPV4_IN_EVPN);
|
||||
UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
|
||||
BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
|
||||
}
|
||||
} else {
|
||||
|
||||
/* if we are already advertising ipv6 prefix as type-5
|
||||
/* if we are not advertising ipv6 prefix as type-5
|
||||
* nothing to do
|
||||
*/
|
||||
if (CHECK_FLAG(bgp_vrf->vrf_flags,
|
||||
BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) {
|
||||
if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
|
||||
BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
|
||||
bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
|
||||
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)
|
||||
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");
|
||||
|
||||
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");
|
||||
|
||||
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))
|
||||
vty_out(vty, " rd %s\n",
|
||||
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, &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. */
|
||||
install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
|
||||
|
@ -2227,12 +2227,13 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
|
||||
|
||||
/* advertise/withdraw type-5 routes */
|
||||
if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) {
|
||||
if (new_select
|
||||
&& (!new_select->extra || !new_select->extra->parent))
|
||||
bgp_evpn_advertise_type5_route(
|
||||
bgp, &rn->p, new_select->attr, afi, safi);
|
||||
else if (old_select
|
||||
&& (!old_select->extra || !old_select->extra->parent))
|
||||
if (advertise_type5_routes(bgp, afi) && new_select &&
|
||||
(!new_select->extra || !new_select->extra->parent))
|
||||
bgp_evpn_advertise_type5_route(bgp, &rn->p,
|
||||
new_select->attr,
|
||||
afi, safi);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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_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 function should return 1 if match is success else return
|
||||
@ -3249,6 +3267,29 @@ DEFUN (no_match_evpn_vni,
|
||||
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,
|
||||
match_peer_cmd,
|
||||
"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_evpn_vni_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_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, &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, &no_match_aspath_cmd);
|
||||
|
18
bgpd/bgpd.h
18
bgpd/bgpd.h
@ -312,6 +312,13 @@ struct bgp {
|
||||
u_int16_t af_flags[AFI_MAX][SAFI_MAX];
|
||||
#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. */
|
||||
struct bgp_table *nexthop_cache_table[AFI_MAX];
|
||||
|
||||
@ -423,12 +430,11 @@ struct bgp {
|
||||
/* vrf flags */
|
||||
uint32_t vrf_flags;
|
||||
#define BGP_VRF_AUTO (1 << 0)
|
||||
#define BGP_VRF_ADVERTISE_IPV4_IN_EVPN (1 << 1)
|
||||
#define BGP_VRF_ADVERTISE_IPV6_IN_EVPN (1 << 2)
|
||||
#define BGP_VRF_IMPORT_RT_CFGD (1 << 3)
|
||||
#define BGP_VRF_EXPORT_RT_CFGD (1 << 4)
|
||||
#define BGP_VRF_RD_CFGD (1 << 5)
|
||||
#define BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY (1 << 6)
|
||||
#define BGP_VRF_IMPORT_RT_CFGD (1 << 1)
|
||||
#define BGP_VRF_EXPORT_RT_CFGD (1 << 2)
|
||||
#define BGP_VRF_RD_CFGD (1 << 3)
|
||||
#define BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY (1 << 4)
|
||||
|
||||
|
||||
/* unique ID for auto derivation of RD for this vrf */
|
||||
uint16_t vrf_rd_id;
|
||||
|
11
configure.ac
11
configure.ac
@ -396,6 +396,8 @@ AC_ARG_ENABLE(rpki,
|
||||
AS_HELP_STRING([--enable-rpki], [enable RPKI prefix validation support]))
|
||||
AC_ARG_ENABLE([clippy-only],
|
||||
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"], [
|
||||
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])
|
||||
|
||||
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 Add extra version string to package
|
||||
dnl name, string and version fields.
|
||||
@ -1872,6 +1882,7 @@ AC_CONFIG_FILES([Makefile
|
||||
redhat/frr.spec
|
||||
debianpkg/Makefile
|
||||
debianpkg/changelog
|
||||
alpine/APKBUILD
|
||||
snapcraft/snapcraft.yaml
|
||||
lib/version.h
|
||||
tests/lib/cli/test_cli.refout
|
||||
|
@ -109,6 +109,10 @@ of grammar sandbox.
|
||||
Turn on some compile options to allow you to run fuzzing tools
|
||||
against the system. This tools is intended as a developer
|
||||
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
|
||||
|
||||
You may specify any combination of the above options to the configure
|
||||
|
1
ldpd/.gitignore
vendored
1
ldpd/.gitignore
vendored
@ -15,4 +15,3 @@ TAGS
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
ldp_vty_cmds_clippy.c
|
||||
|
1
lib/.gitignore
vendored
1
lib/.gitignore
vendored
@ -24,4 +24,3 @@ refix
|
||||
grammar_sandbox
|
||||
clippy
|
||||
defun_lex.c
|
||||
plist_clippy.c
|
||||
|
92
lib/debug.h
92
lib/debug.h
@ -104,76 +104,77 @@ struct debug_callbacks {
|
||||
*
|
||||
* MT-Safe
|
||||
*/
|
||||
#define DEBUG_MODE_CHECK(name, type) \
|
||||
CHECK_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_MODE_ALL)
|
||||
#define DEBUG_MODE_CHECK(name, mode) \
|
||||
CHECK_FLAG_ATOMIC(&(name)->flags, (mode)&DEBUG_MODE_ALL)
|
||||
|
||||
/*
|
||||
* Check if an option bit is set for a debug.
|
||||
*
|
||||
* MT-Safe
|
||||
*/
|
||||
#define DEBUG_OPT_CHECK(name, type) \
|
||||
CHECK_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_OPT_ALL)
|
||||
#define DEBUG_OPT_CHECK(name, opt) \
|
||||
CHECK_FLAG_ATOMIC(&(name)->flags, (opt)&DEBUG_OPT_ALL)
|
||||
|
||||
/*
|
||||
* Check if bits are set for a debug.
|
||||
*
|
||||
* MT-Safe
|
||||
*/
|
||||
#define DEBUG_FLAGS_CHECK(name, type) CHECK_FLAG_ATOMIC(&(name)->flags, (type))
|
||||
|
||||
/*
|
||||
* Check if any mode is on for a debug.
|
||||
*
|
||||
* MT-Safe
|
||||
*/
|
||||
#define DEBUG(name) DEBUG_MODE_CHECK((name), DEBUG_MODE_ALL)
|
||||
#define DEBUG_FLAGS_CHECK(name, fl) CHECK_FLAG_ATOMIC(&(name)->flags, (fl))
|
||||
|
||||
/*
|
||||
* Set modes on a debug.
|
||||
*
|
||||
* MT-Safe
|
||||
*/
|
||||
#define DEBUG_MODE_SET(name, type) \
|
||||
SET_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_MODE_ALL)
|
||||
#define DEBUG_MODE_SET(name, mode, onoff) \
|
||||
do { \
|
||||
if (onoff) \
|
||||
SET_FLAG_ATOMIC(&(name)->flags, \
|
||||
(mode)&DEBUG_MODE_ALL); \
|
||||
else \
|
||||
UNSET_FLAG_ATOMIC(&(name)->flags, \
|
||||
(mode)&DEBUG_MODE_ALL); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Unset modes on a debug.
|
||||
*
|
||||
* MT-Safe
|
||||
*/
|
||||
#define DEBUG_MODE_UNSET(name, type) \
|
||||
UNSET_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_MODE_ALL)
|
||||
/* Convenience macros for specific set operations. */
|
||||
#define DEBUG_MODE_ON(name, mode) DEBUG_MODE_SET(name, mode, true)
|
||||
#define DEBUG_MODE_OFF(name, mode) DEBUG_MODE_SET(name, mode, false)
|
||||
|
||||
/*
|
||||
* Set options on a debug.
|
||||
*
|
||||
* MT-Safe
|
||||
*/
|
||||
#define DEBUG_OPT_SET(name, type) \
|
||||
SET_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_OPT_ALL)
|
||||
#define DEBUG_OPT_SET(name, opt, onoff) \
|
||||
do { \
|
||||
if (onoff) \
|
||||
SET_FLAG_ATOMIC(&(name)->flags, (opt)&DEBUG_OPT_ALL); \
|
||||
else \
|
||||
UNSET_FLAG_ATOMIC(&(name)->flags, \
|
||||
(opt)&DEBUG_OPT_ALL); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Unset options on a debug.
|
||||
*
|
||||
* MT-Safe
|
||||
*/
|
||||
#define DEBUG_OPT_UNSET(name, type) \
|
||||
UNSET_FLAG_ATOMIC(&(name)->flags, (type)&DEBUG_OPT_ALL)
|
||||
/* Convenience macros for specific set operations. */
|
||||
#define DEBUG_OPT_ON(name, opt) DEBUG_OPT_SET(name, opt, true)
|
||||
#define DEBUG_OPT_OFF(name, opt) DEBUG_OPT_SET(name, opt, true)
|
||||
|
||||
/*
|
||||
* Set bits on a debug.
|
||||
*
|
||||
* 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)
|
||||
|
||||
/*
|
||||
* Unset bits on a debug.
|
||||
*
|
||||
* MT-Safe
|
||||
*/
|
||||
#define DEBUG_FLAGS_UNSET(name, type) UNSET_FLAG_ATOMIC(&(name)->flags, (type))
|
||||
/* Convenience macros for specific set operations. */
|
||||
#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)
|
||||
|
||||
/*
|
||||
* Unset all modes and options on a debug.
|
||||
@ -201,6 +202,23 @@ struct debug_callbacks {
|
||||
#define DEBUG_NODE2MODE(vtynode) \
|
||||
(((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.
|
||||
|
17
lib/ipaddr.h
17
lib/ipaddr.h
@ -85,4 +85,21 @@ static inline char *ipaddr2str(struct ipaddr *ip, char *buf, int size)
|
||||
}
|
||||
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__ */
|
||||
|
43
lib/log.c
43
lib/log.c
@ -1092,41 +1092,52 @@ void zlog_hexdump(const void *mem, unsigned int len)
|
||||
unsigned long i = 0;
|
||||
unsigned int j = 0;
|
||||
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;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
for (i = 0; i < len + ((len % columns) ? (columns - len % columns) : 0);
|
||||
i++) {
|
||||
/* print offset */
|
||||
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 */
|
||||
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 */
|
||||
else
|
||||
s += sprintf(s, " ");
|
||||
s += snprintf(s, bs - (s - buf), " ");
|
||||
|
||||
/* print ASCII dump */
|
||||
if (i % columns == (columns - 1)) {
|
||||
for (j = i - (columns - 1); j <= i; j++) {
|
||||
if (j >= len) /* end of block, not really
|
||||
printing */
|
||||
s += sprintf(s, " ");
|
||||
|
||||
else if (isprint((int)((const char *)mem)
|
||||
[j])) /* printable char
|
||||
*/
|
||||
s += sprintf(
|
||||
s, "%c",
|
||||
/* end of block not really printing */
|
||||
if (j >= len)
|
||||
s += snprintf(s, bs - (s - buf), " ");
|
||||
else if (isprint((int)((const char *)mem)[j]))
|
||||
s += snprintf(
|
||||
s, bs - (s - buf), "%c",
|
||||
0xFF & ((const char *)mem)[j]);
|
||||
|
||||
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);
|
||||
|
@ -322,6 +322,18 @@ stream_failure:
|
||||
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. */
|
||||
static int zebra_message_send(struct zclient *zclient, int command,
|
||||
vrf_id_t vrf_id)
|
||||
|
@ -237,14 +237,13 @@ struct zclient {
|
||||
*/
|
||||
#define ZAPI_MESSAGE_TABLEID 0x80
|
||||
|
||||
#define ZSERV_VERSION 5
|
||||
/* Zserv protocol message header */
|
||||
struct zserv_header {
|
||||
struct zmsghdr {
|
||||
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;
|
||||
#define ZSERV_VERSION 5
|
||||
vrf_id_t vrf_id;
|
||||
uint16_t command;
|
||||
};
|
||||
@ -380,9 +379,11 @@ struct zclient_options {
|
||||
/* Prototypes of zebra client service functions. */
|
||||
extern struct zclient *zclient_new(struct thread_master *);
|
||||
|
||||
/* clang-format off */
|
||||
#if CONFDATE > 20181101
|
||||
CPP_NOTICE("zclient_new_notify can take over or zclient_new now");
|
||||
#endif
|
||||
/* clang-format on */
|
||||
|
||||
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 */
|
||||
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,
|
||||
u_char *marker, u_char *version,
|
||||
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,
|
||||
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_router_id_update_read(struct stream *s, struct prefix *rid);
|
||||
|
||||
/* clang-format off */
|
||||
#if CONFDATE > 20180823
|
||||
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");
|
||||
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");
|
||||
#endif
|
||||
/* clang-format on */
|
||||
|
||||
extern int zapi_ipv4_route(u_char, struct zclient *, struct prefix_ipv4 *,
|
||||
struct zapi_ipv4 *) __attribute__((deprecated));
|
||||
|
1
ospfd/.gitignore
vendored
1
ospfd/.gitignore
vendored
@ -15,4 +15,3 @@ TAGS
|
||||
*~
|
||||
*.loT
|
||||
*.a
|
||||
*clippy.c
|
||||
|
@ -604,11 +604,18 @@ static void igmp_show_interfaces(struct pim_instance *pim, struct vty *vty,
|
||||
json_object_object_add(json, ifp->name,
|
||||
json_row);
|
||||
|
||||
if (igmp->mtrace_only) {
|
||||
json_object_boolean_true_add(
|
||||
json_row, "mtraceOnly");
|
||||
}
|
||||
} else {
|
||||
vty_out(vty,
|
||||
"%-9s %5s %15s %d %7s %11s %8s\n",
|
||||
ifp->name,
|
||||
if_is_up(ifp) ? "up" : "down",
|
||||
if_is_up(ifp)
|
||||
? (igmp->mtrace_only ? "mtrc"
|
||||
: "up")
|
||||
: "down",
|
||||
inet_ntoa(igmp->ifaddr),
|
||||
pim_ifp->igmp_version,
|
||||
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_row);
|
||||
|
||||
if (igmp->mtrace_only) {
|
||||
json_object_boolean_true_add(
|
||||
json_row, "mtraceOnly");
|
||||
}
|
||||
} else {
|
||||
vty_out(vty, "Interface : %s\n", ifp->name);
|
||||
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",
|
||||
inet_ntoa(pim_ifp->primary_address));
|
||||
vty_out(vty, "Uptime : %s\n", uptime);
|
||||
|
@ -574,7 +574,11 @@ void pim_if_addr_add(struct connected *ifc)
|
||||
/* if addr new, add IGMP socket */
|
||||
if (ifc->address->family == AF_INET)
|
||||
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 */
|
||||
@ -611,6 +615,20 @@ void pim_if_addr_add(struct connected *ifc)
|
||||
}
|
||||
}
|
||||
} /* 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)) {
|
||||
|
||||
|
@ -281,6 +281,9 @@ static int igmp_recv_query(struct igmp_sock *igmp, int query_version,
|
||||
uint16_t recv_checksum;
|
||||
uint16_t checksum;
|
||||
|
||||
if (igmp->mtrace_only)
|
||||
return 0;
|
||||
|
||||
memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
|
||||
|
||||
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);
|
||||
|
||||
if (igmp->mtrace_only)
|
||||
return 0;
|
||||
|
||||
if (igmp_msg_len != IGMP_V12_MSG_SIZE) {
|
||||
zlog_warn(
|
||||
"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,
|
||||
from_str, igmp_msg,
|
||||
igmp_msg_len);
|
||||
break;
|
||||
case PIM_IGMP_MTRACE_QUERY_REQUEST:
|
||||
return igmp_mtrace_recv_qry_req(igmp, ip_hdr, ip_hdr->ip_src,
|
||||
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,
|
||||
struct interface *ifp)
|
||||
struct interface *ifp, int mtrace_only)
|
||||
{
|
||||
struct pim_interface *pim_ifp;
|
||||
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;
|
||||
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:
|
||||
|
||||
@ -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 in_addr ifaddr,
|
||||
struct interface *ifp)
|
||||
struct interface *ifp,
|
||||
bool mtrace_only)
|
||||
{
|
||||
struct pim_interface *pim_ifp;
|
||||
struct igmp_sock *igmp;
|
||||
@ -934,7 +947,7 @@ struct igmp_sock *pim_igmp_sock_add(struct list *igmp_sock_list,
|
||||
return 0;
|
||||
}
|
||||
|
||||
igmp = igmp_sock_new(fd, ifaddr, ifp);
|
||||
igmp = igmp_sock_new(fd, ifaddr, ifp, mtrace_only);
|
||||
if (!igmp) {
|
||||
zlog_err("%s %s: igmp_sock_new() failure", __FILE__,
|
||||
__PRETTY_FUNCTION__);
|
||||
|
@ -90,6 +90,8 @@ struct igmp_sock {
|
||||
int querier_robustness_variable; /* QRV */
|
||||
int startup_query_count;
|
||||
|
||||
bool mtrace_only;
|
||||
|
||||
struct list *igmp_group_list; /* list of struct igmp_group */
|
||||
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 *pim_igmp_sock_add(struct list *igmp_sock_list,
|
||||
struct in_addr ifaddr,
|
||||
struct interface *ifp);
|
||||
struct interface *ifp,
|
||||
bool mtrace_only);
|
||||
void igmp_sock_delete(struct igmp_sock *igmp);
|
||||
void igmp_sock_free(struct igmp_sock *igmp);
|
||||
void igmp_sock_delete_all(struct interface *ifp);
|
||||
|
@ -111,6 +111,9 @@ int igmp_v2_recv_report(struct igmp_sock *igmp, struct in_addr from,
|
||||
|
||||
on_trace(__PRETTY_FUNCTION__, igmp->interface, from);
|
||||
|
||||
if (igmp->mtrace_only)
|
||||
return 0;
|
||||
|
||||
if (igmp_msg_len != IGMP_V12_MSG_SIZE) {
|
||||
zlog_warn(
|
||||
"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);
|
||||
|
||||
if (igmp->mtrace_only)
|
||||
return 0;
|
||||
|
||||
if (igmp_msg_len != IGMP_V12_MSG_SIZE) {
|
||||
zlog_warn(
|
||||
"Recv IGMPv2 LEAVE from %s on %s: size=%d other than correct=%d",
|
||||
|
@ -1874,6 +1874,9 @@ int igmp_v3_recv_report(struct igmp_sock *igmp, struct in_addr from,
|
||||
int local_ncb = 0;
|
||||
struct pim_interface *pim_ifp;
|
||||
|
||||
if (igmp->mtrace_only)
|
||||
return 0;
|
||||
|
||||
pim_ifp = igmp->interface->info;
|
||||
|
||||
if (igmp_msg_len < IGMP_V3_MSG_MIN_SIZE) {
|
||||
|
1
sharpd/.gitignore
vendored
1
sharpd/.gitignore
vendored
@ -13,6 +13,5 @@ TAGS
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
*clippy.c
|
||||
sharpd
|
||||
sharpd.conf
|
||||
|
@ -73,6 +73,7 @@ check_PROGRAMS = \
|
||||
lib/test_timer_correctness \
|
||||
lib/test_timer_performance \
|
||||
lib/test_ttable \
|
||||
lib/test_zlog \
|
||||
lib/cli/test_cli \
|
||||
lib/cli/test_commands \
|
||||
$(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_nexthop_iter_SOURCES = lib/test_nexthop_iter.c helpers/c/prng.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 \
|
||||
helpers/c/prng.c
|
||||
lib_test_ringbuf_SOURCES = lib/test_ringbuf.c
|
||||
lib_test_segv_SOURCES = lib/test_segv.c
|
||||
lib_test_sig_SOURCES = lib/test_sig.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 \
|
||||
helpers/c/prng.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_CFLAGS = $(AM_CFLAGS) $(ZEROMQ_CFLAGS)
|
||||
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_performance_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_cli_test_cli_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_ttable.py \
|
||||
lib/test_ttable.refout \
|
||||
lib/test_zlog.py \
|
||||
ospf6d/test_lsdb.py \
|
||||
ospf6d/test_lsdb.in \
|
||||
ospf6d/test_lsdb.refout \
|
||||
|
61
tests/lib/test_zlog.c
Normal file
61
tests/lib/test_zlog.c
Normal 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
4
tests/lib/test_zlog.py
Normal file
@ -0,0 +1,4 @@
|
||||
import frrtest
|
||||
|
||||
class TestZlog(frrtest.TestMultiOut):
|
||||
program = './test_zlog'
|
1
zebra/.gitignore
vendored
1
zebra/.gitignore
vendored
@ -13,4 +13,3 @@ TAGS
|
||||
.arch-ids
|
||||
*~
|
||||
*.loT
|
||||
zebra_vty_clippy.c
|
||||
|
@ -30,6 +30,7 @@
|
||||
*/
|
||||
#define _LINUX_IN6_H
|
||||
|
||||
#include <netinet/if_ether.h>
|
||||
#include <linux/if_bridge.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <net/if_arp.h>
|
||||
@ -362,7 +363,7 @@ static int get_iflink_speed(struct interface *interface)
|
||||
/* initialize ethtool interface */
|
||||
memset(&ecmd, 0, sizeof(ecmd));
|
||||
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 */
|
||||
if (zserv_privs.change(ZPRIVS_RAISE))
|
||||
|
@ -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
|
||||
* This zclient thus is to connect to it
|
||||
*/
|
||||
static struct stream *ibuf;
|
||||
static struct stream *obuf;
|
||||
static struct zclient *zclient;
|
||||
bool lm_is_external;
|
||||
|
||||
@ -69,7 +71,7 @@ static int relay_response_back(struct zserv *zserv)
|
||||
u_int16_t resp_cmd;
|
||||
|
||||
src = zclient->ibuf;
|
||||
dst = zserv->obuf;
|
||||
dst = obuf;
|
||||
|
||||
stream_reset(src);
|
||||
|
||||
@ -87,7 +89,7 @@ static int relay_response_back(struct zserv *zserv)
|
||||
|
||||
/* send response back */
|
||||
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) {
|
||||
zlog_err("%s: Error sending Label Manager response back: %s",
|
||||
__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)
|
||||
{
|
||||
int ret;
|
||||
struct stream *s;
|
||||
|
||||
s = zserv->obuf;
|
||||
stream_reset(s);
|
||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
|
||||
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. */
|
||||
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
|
||||
@ -161,7 +166,7 @@ int zread_relay_label_manager_request(int cmd, struct zserv *zserv,
|
||||
ret = relay_response_back(zserv);
|
||||
|
||||
/* Send request to external label manager */
|
||||
src = zserv->ibuf;
|
||||
src = ibuf;
|
||||
dst = zclient->obuf;
|
||||
|
||||
stream_copy(dst, src);
|
||||
@ -247,6 +252,9 @@ void label_manager_init(char *lm_zserv_path)
|
||||
lm_is_external = true;
|
||||
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()
|
||||
{
|
||||
list_delete_and_null(&lbl_mgr.lc_list);
|
||||
stream_free(ibuf);
|
||||
stream_free(obuf);
|
||||
}
|
||||
|
@ -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,
|
||||
struct zebra_vrf *zvrf)
|
||||
void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
afi_t afi = 0;
|
||||
int type = 0;
|
||||
u_short instance;
|
||||
|
||||
STREAM_GETC(client->ibuf, afi);
|
||||
STREAM_GETC(client->ibuf, type);
|
||||
STREAM_GETW(client->ibuf, instance);
|
||||
STREAM_GETC(msg, afi);
|
||||
STREAM_GETC(msg, type);
|
||||
STREAM_GETW(msg, instance);
|
||||
|
||||
if (afi == 0 || afi > AFI_MAX) {
|
||||
zlog_warn("%s: Specified afi %d does not exist",
|
||||
@ -287,16 +286,15 @@ stream_failure:
|
||||
return;
|
||||
}
|
||||
|
||||
void zebra_redistribute_delete(int command, struct zserv *client, int length,
|
||||
struct zebra_vrf *zvrf)
|
||||
void zebra_redistribute_delete(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
afi_t afi = 0;
|
||||
int type = 0;
|
||||
u_short instance;
|
||||
|
||||
STREAM_GETC(client->ibuf, afi);
|
||||
STREAM_GETC(client->ibuf, type);
|
||||
STREAM_GETW(client->ibuf, instance);
|
||||
STREAM_GETC(msg, afi);
|
||||
STREAM_GETC(msg, type);
|
||||
STREAM_GETW(msg, instance);
|
||||
|
||||
if (afi == 0 || afi > AFI_MAX) {
|
||||
zlog_warn("%s: Specified afi %d does not exist",
|
||||
@ -325,15 +323,13 @@ stream_failure:
|
||||
return;
|
||||
}
|
||||
|
||||
void zebra_redistribute_default_add(int command, struct zserv *client,
|
||||
int length, struct zebra_vrf *zvrf)
|
||||
void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
vrf_bitmap_set(client->redist_default, zvrf_id(zvrf));
|
||||
zebra_redistribute_default(client, zvrf_id(zvrf));
|
||||
}
|
||||
|
||||
void zebra_redistribute_default_delete(int command, struct zserv *client,
|
||||
int length, struct zebra_vrf *zvrf)
|
||||
void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
vrf_bitmap_unset(client->redist_default, zvrf_id(zvrf));
|
||||
}
|
||||
|
@ -27,15 +27,12 @@
|
||||
#include "vty.h"
|
||||
#include "vrf.h"
|
||||
|
||||
extern void zebra_redistribute_add(int, struct zserv *, int,
|
||||
struct zebra_vrf *zvrf);
|
||||
extern void zebra_redistribute_delete(int, struct zserv *, int,
|
||||
struct zebra_vrf *zvrf);
|
||||
|
||||
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);
|
||||
/* ZAPI command handlers */
|
||||
extern void zebra_redistribute_add(ZAPI_HANDLER_ARGS);
|
||||
extern void zebra_redistribute_delete(ZAPI_HANDLER_ARGS);
|
||||
extern void zebra_redistribute_default_add(ZAPI_HANDLER_ARGS);
|
||||
extern void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS);
|
||||
/* ----------------- */
|
||||
|
||||
extern void redistribute_update(struct prefix *, struct prefix *,
|
||||
struct route_entry *, struct route_entry *);
|
||||
|
@ -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
|
||||
* specify a RA interval (in seconds).
|
||||
*/
|
||||
void zebra_interface_radv_set(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvrf, int enable)
|
||||
static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
|
||||
{
|
||||
struct stream *s;
|
||||
ifindex_t ifindex;
|
||||
@ -810,7 +809,7 @@ void zebra_interface_radv_set(struct zserv *client, u_short length,
|
||||
struct zebra_if *zif;
|
||||
int ra_interval;
|
||||
|
||||
s = client->ibuf;
|
||||
s = msg;
|
||||
|
||||
/* Get interface index and RA interval. */
|
||||
STREAM_GETL(s, ifindex);
|
||||
@ -859,6 +858,15 @@ stream_failure:
|
||||
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,
|
||||
ipv6_nd_suppress_ra_cmd,
|
||||
"ipv6 nd suppress-ra",
|
||||
|
@ -103,7 +103,8 @@ typedef enum {
|
||||
extern void rtadv_init(struct zebra_ns *);
|
||||
extern void rtadv_terminate(struct zebra_ns *);
|
||||
extern void rtadv_cmd_init(void);
|
||||
extern void zebra_interface_radv_set(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvrf, int enable);
|
||||
extern void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS);
|
||||
extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS);
|
||||
|
||||
|
||||
#endif /* _ZEBRA_RTADV_H */
|
||||
|
@ -455,8 +455,7 @@ static int fec_send(zebra_fec_t *fec, struct zserv *client)
|
||||
rn = fec->rn;
|
||||
|
||||
/* Get output stream. */
|
||||
s = client->obuf;
|
||||
stream_reset(s);
|
||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
|
||||
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_putl(s, fec->label);
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
return zebra_server_send_message(client);
|
||||
return zebra_server_send_message(client, s);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -32,17 +32,16 @@
|
||||
#include "zebra/rt.h"
|
||||
#include "zebra/debug.h"
|
||||
|
||||
int zebra_ipmr_route_stats(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvrf)
|
||||
void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct mcast_route_data mroute;
|
||||
struct stream *s;
|
||||
int suc = -1;
|
||||
|
||||
memset(&mroute, 0, sizeof(mroute));
|
||||
STREAM_GET(&mroute.sg.src, client->ibuf, 4);
|
||||
STREAM_GET(&mroute.sg.grp, client->ibuf, 4);
|
||||
STREAM_GETL(client->ibuf, mroute.ifindex);
|
||||
STREAM_GET(&mroute.sg.src, msg, 4);
|
||||
STREAM_GET(&mroute.sg.grp, msg, 4);
|
||||
STREAM_GETL(msg, mroute.ifindex);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_KERNEL) {
|
||||
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);
|
||||
|
||||
stream_failure:
|
||||
s = client->obuf;
|
||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
|
||||
stream_reset(s);
|
||||
|
||||
@ -68,6 +67,5 @@ stream_failure:
|
||||
stream_putl(s, suc);
|
||||
|
||||
stream_putw_at(s, 0, stream_get_endp(s));
|
||||
zebra_server_send_message(client);
|
||||
return 0;
|
||||
zebra_server_send_message(client, s);
|
||||
}
|
||||
|
@ -22,13 +22,14 @@
|
||||
#ifndef __ZEBRA_MROUTE_H__
|
||||
#define __ZEBRA_MROUTE_H__
|
||||
|
||||
#include "zebra/zserv.h"
|
||||
|
||||
struct mcast_route_data {
|
||||
struct prefix_sg sg;
|
||||
unsigned int ifindex;
|
||||
unsigned long long lastused;
|
||||
};
|
||||
|
||||
int zebra_ipmr_route_stats(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvf);
|
||||
void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS);
|
||||
|
||||
#endif
|
||||
|
@ -661,8 +661,7 @@ int zebra_ptm_sock_read(struct thread *thread)
|
||||
}
|
||||
|
||||
/* BFD peer/dst register/update */
|
||||
int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length,
|
||||
int command, struct zebra_vrf *zvrf)
|
||||
void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
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;
|
||||
unsigned int pid;
|
||||
|
||||
if (command == ZEBRA_BFD_DEST_UPDATE)
|
||||
if (hdr->command == ZEBRA_BFD_DEST_UPDATE)
|
||||
client->bfd_peer_upd8_cnt++;
|
||||
else
|
||||
client->bfd_peer_add_cnt++;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
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) {
|
||||
ptm_cb.t_timer = NULL;
|
||||
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
|
||||
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);
|
||||
@ -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,
|
||||
tmp_buf);
|
||||
|
||||
s = client->ibuf;
|
||||
s = msg;
|
||||
|
||||
STREAM_GETL(s, 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);
|
||||
zebra_ptm_send_message(ptm_cb.out_data, data_len);
|
||||
|
||||
return 0;
|
||||
return;
|
||||
|
||||
stream_failure:
|
||||
ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* BFD peer/dst deregister */
|
||||
int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvrf)
|
||||
void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
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)
|
||||
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) {
|
||||
ptm_cb.t_timer = NULL;
|
||||
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
|
||||
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);
|
||||
@ -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,
|
||||
tmp_buf);
|
||||
|
||||
s = client->ibuf;
|
||||
s = msg;
|
||||
|
||||
STREAM_GETL(s, 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);
|
||||
|
||||
return 0;
|
||||
return;
|
||||
|
||||
stream_failure:
|
||||
ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
unsigned int pid;
|
||||
@ -968,16 +964,16 @@ int zebra_ptm_bfd_client_register(struct zserv *client, u_short length)
|
||||
|
||||
if (IS_ZEBRA_DEBUG_EVENT)
|
||||
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);
|
||||
|
||||
if (ptm_cb.ptm_sock == -1) {
|
||||
ptm_cb.t_timer = NULL;
|
||||
thread_add_timer(zebrad.master, zebra_ptm_connect, NULL,
|
||||
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);
|
||||
@ -1003,7 +999,7 @@ int zebra_ptm_bfd_client_register(struct zserv *client, u_short length)
|
||||
SET_FLAG(ptm_cb.client_flags[client->proto],
|
||||
ZEBRA_PTM_BFD_CLIENT_FLAG_REG);
|
||||
|
||||
return 0;
|
||||
return;
|
||||
|
||||
stream_failure:
|
||||
/*
|
||||
@ -1013,7 +1009,7 @@ stream_failure:
|
||||
* if (out_ctxt)
|
||||
* ptm_lib_cleanup_msg(ptm_hdl, out_ctxt);
|
||||
*/
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* BFD client deregister */
|
||||
|
@ -28,6 +28,8 @@ extern const char ZEBRA_PTM_SOCK_NAME[];
|
||||
|
||||
#define ZEBRA_PTM_BFD_CLIENT_FLAG_REG (1 << 1) /* client registered with BFD */
|
||||
|
||||
#include "zebra/zserv.h"
|
||||
|
||||
/* Zebra ptm context block */
|
||||
struct zebra_ptm_cb {
|
||||
int ptm_sock; /* ptm file descriptor. */
|
||||
@ -62,12 +64,12 @@ int zebra_ptm_connect(struct thread *t);
|
||||
void zebra_ptm_write(struct vty *vty);
|
||||
int zebra_ptm_get_enable_state(void);
|
||||
|
||||
int zebra_ptm_bfd_dst_register(struct zserv *client, u_short length,
|
||||
int command, struct zebra_vrf *zvrf);
|
||||
int zebra_ptm_bfd_dst_deregister(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvrf);
|
||||
/* ZAPI message handlers */
|
||||
void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS);
|
||||
void zebra_ptm_bfd_dst_deregister(ZAPI_HANDLER_ARGS);
|
||||
void zebra_ptm_bfd_client_register(ZAPI_HANDLER_ARGS);
|
||||
|
||||
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_set_ptm_state(struct interface *ifp,
|
||||
struct zebra_if *zebra_ifp);
|
||||
|
@ -38,8 +38,7 @@ static int zsend_interface_bfd_update(int cmd, struct zserv *client,
|
||||
if (!client->ifinfo)
|
||||
return 0;
|
||||
|
||||
s = client->obuf;
|
||||
stream_reset(s);
|
||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
|
||||
zclient_create_header(s, cmd, vrf_id);
|
||||
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));
|
||||
|
||||
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,
|
||||
@ -93,8 +92,7 @@ static int zsend_bfd_peer_replay(int cmd, struct zserv *client)
|
||||
{
|
||||
struct stream *s;
|
||||
|
||||
s = client->obuf;
|
||||
stream_reset(s);
|
||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
|
||||
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));
|
||||
|
||||
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)
|
||||
|
@ -305,6 +305,8 @@ struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
|
||||
nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||
nexthop->gate.ipv6 = *ipv6;
|
||||
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);
|
||||
|
||||
@ -421,6 +423,10 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
|
||||
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 */
|
||||
/* The nexthops are specific to this route and so the same */
|
||||
/* 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_IFINDEX:
|
||||
family = AFI_IP;
|
||||
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN_RVTEP))
|
||||
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
else if (nexthop_active(AFI_IP, re, nexthop, set, rn))
|
||||
if (nexthop_active(AFI_IP, re, nexthop, set, rn))
|
||||
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
|
||||
else
|
||||
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;
|
||||
|
||||
memset(&vtep_ip, 0, sizeof(struct ipaddr));
|
||||
vtep_ip.ipa_type = IPADDR_V4;
|
||||
memcpy(&(vtep_ip.ipaddr_v4),
|
||||
&(tmp_nh->gate.ipv4),
|
||||
sizeof(struct in_addr));
|
||||
if (afi == AFI_IP) {
|
||||
vtep_ip.ipa_type = IPADDR_V4;
|
||||
memcpy(&(vtep_ip.ipaddr_v4),
|
||||
&(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,
|
||||
&vtep_ip, p);
|
||||
}
|
||||
|
@ -995,8 +995,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
|
||||
re = rnh->state;
|
||||
|
||||
/* Get output stream. */
|
||||
s = client->obuf;
|
||||
stream_reset(s);
|
||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
|
||||
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->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)
|
||||
|
@ -1157,8 +1157,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
|
||||
if (!client)
|
||||
return 0;
|
||||
|
||||
s = client->obuf;
|
||||
stream_reset(s);
|
||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
|
||||
zclient_create_header(s, cmd, VRF_DEFAULT);
|
||||
stream_putl(s, vni);
|
||||
@ -1195,7 +1194,7 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
|
||||
else
|
||||
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)
|
||||
return 0;
|
||||
|
||||
s = client->obuf;
|
||||
stream_reset(s);
|
||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
|
||||
zclient_create_header(s, ZEBRA_VNI_ADD, VRF_DEFAULT);
|
||||
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));
|
||||
|
||||
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)
|
||||
return 0;
|
||||
|
||||
s = client->obuf;
|
||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
stream_reset(s);
|
||||
|
||||
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));
|
||||
|
||||
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));
|
||||
zl3vni_get_rmac(zl3vni, &rmac);
|
||||
|
||||
s = client->obuf;
|
||||
stream_reset(s);
|
||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
|
||||
zclient_create_header(s, ZEBRA_L3VNI_ADD, zl3vni_vrf_id(zl3vni));
|
||||
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));
|
||||
|
||||
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)
|
||||
return 0;
|
||||
|
||||
s = client->obuf;
|
||||
stream_reset(s);
|
||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
|
||||
zclient_create_header(s, ZEBRA_L3VNI_DEL, zl3vni_vrf_id(zl3vni));
|
||||
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));
|
||||
|
||||
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)
|
||||
@ -3723,8 +3719,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
|
||||
if (!client)
|
||||
return 0;
|
||||
|
||||
s = client->obuf;
|
||||
stream_reset(s);
|
||||
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
|
||||
|
||||
zclient_create_header(s, cmd, vrf_id);
|
||||
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
|
||||
client->prefixdel_cnt++;
|
||||
|
||||
return zebra_server_send_message(client);
|
||||
return zebra_server_send_message(client, s);
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvrf)
|
||||
void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
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(&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. */
|
||||
/* Message contains VNI, followed by MAC followed by IP (if any)
|
||||
* followed by remote VTEP IP.
|
||||
@ -5008,7 +5002,7 @@ int zebra_vxlan_remote_macip_del(struct zserv *client, u_short length,
|
||||
}
|
||||
|
||||
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
|
||||
* (IP+MAC).
|
||||
*/
|
||||
int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvrf)
|
||||
void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
vni_t vni;
|
||||
@ -5045,12 +5038,12 @@ int zebra_vxlan_remote_macip_add(struct zserv *client, u_short length,
|
||||
zlog_warn(
|
||||
"%s: EVPN Not turned on yet we have received a remote_macip add zapi callback",
|
||||
__PRETTY_FUNCTION__);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
s = client->ibuf;
|
||||
s = msg;
|
||||
|
||||
while (l < length) {
|
||||
while (l < hdr->length) {
|
||||
/* Obtain each remote MACIP and process. */
|
||||
/* Message contains VNI, followed by MAC followed by IP (if any)
|
||||
* 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,
|
||||
sizeof(buf)),
|
||||
vni, inet_ntoa(vtep_ip));
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
sizeof(buf)),
|
||||
vni, inet_ntoa(vtep_ip));
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
} 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:
|
||||
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.
|
||||
*/
|
||||
int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvrf)
|
||||
void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
u_short l = 0;
|
||||
@ -5559,18 +5551,18 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length,
|
||||
zlog_warn(
|
||||
"%s: EVPN is not enabled yet we have received a vtep del command",
|
||||
__PRETTY_FUNCTION__);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (zvrf_id(zvrf) != VRF_DEFAULT) {
|
||||
zlog_err("Recv MACIP DEL for non-default VRF %u",
|
||||
zvrf_id(zvrf));
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
s = client->ibuf;
|
||||
s = msg;
|
||||
|
||||
while (l < length) {
|
||||
while (l < hdr->length) {
|
||||
/* Obtain each remote VTEP and process. */
|
||||
STREAM_GETL(s, vni);
|
||||
l += 4;
|
||||
@ -5623,14 +5615,13 @@ int zebra_vxlan_remote_vtep_del(struct zserv *client, u_short length,
|
||||
}
|
||||
|
||||
stream_failure:
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle message from client to add a remote VTEP for a VNI.
|
||||
*/
|
||||
int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvrf)
|
||||
void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
u_short l = 0;
|
||||
@ -5644,18 +5635,18 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length,
|
||||
zlog_warn(
|
||||
"%s: EVPN not enabled yet we received a vtep_add zapi call",
|
||||
__PRETTY_FUNCTION__);
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (zvrf_id(zvrf) != VRF_DEFAULT) {
|
||||
zlog_err("Recv MACIP ADD for non-default VRF %u",
|
||||
zvrf_id(zvrf));
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
s = client->ibuf;
|
||||
s = msg;
|
||||
|
||||
while (l < length) {
|
||||
while (l < hdr->length) {
|
||||
/* Obtain each remote VTEP and process. */
|
||||
STREAM_GETL(s, vni);
|
||||
l += 4;
|
||||
@ -5705,7 +5696,7 @@ int zebra_vxlan_remote_vtep_add(struct zserv *client, u_short length,
|
||||
}
|
||||
|
||||
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
|
||||
* routes
|
||||
*/
|
||||
int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvrf)
|
||||
void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
int advertise;
|
||||
@ -6527,19 +6517,19 @@ int zebra_vxlan_advertise_subnet(struct zserv *client, u_short length,
|
||||
if (zvrf_id(zvrf) != VRF_DEFAULT) {
|
||||
zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
|
||||
zvrf_id(zvrf));
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
s = client->ibuf;
|
||||
s = msg;
|
||||
advertise = stream_getc(s);
|
||||
vni = stream_get3(s);
|
||||
|
||||
zvni = zvni_lookup(vni);
|
||||
if (!zvni)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if (zvni->advertise_subnet == advertise)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
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;
|
||||
if (!ifp)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
zif = ifp->info;
|
||||
|
||||
/* If down or not mapped to a bridge, we're done. */
|
||||
if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
zl2_info = zif->l2info.vxl;
|
||||
|
||||
vlan_if =
|
||||
zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if);
|
||||
if (!vlan_if)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if (zvni->advertise_subnet)
|
||||
zvni_advertise_subnet(zvni, vlan_if, 1);
|
||||
else
|
||||
zvni_advertise_subnet(zvni, vlan_if, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle message from client to enable/disable advertisement of g/w macip
|
||||
* routes
|
||||
*/
|
||||
int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvrf)
|
||||
void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct stream *s;
|
||||
int advertise;
|
||||
@ -6590,10 +6577,10 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
|
||||
if (zvrf_id(zvrf) != VRF_DEFAULT) {
|
||||
zlog_err("EVPN GW-MACIP Adv for non-default VRF %u",
|
||||
zvrf_id(zvrf));
|
||||
return -1;
|
||||
return;
|
||||
}
|
||||
|
||||
s = client->ibuf;
|
||||
s = msg;
|
||||
STREAM_GETC(s, advertise);
|
||||
STREAM_GET(&vni, s, 3);
|
||||
|
||||
@ -6606,7 +6593,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
|
||||
: "disabled");
|
||||
|
||||
if (zvrf->advertise_gw_macip == advertise)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
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);
|
||||
if (!zvni)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
@ -6635,26 +6622,26 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
|
||||
: "disabled");
|
||||
|
||||
if (zvni->advertise_gw_macip == advertise)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
zvni->advertise_gw_macip = advertise;
|
||||
|
||||
ifp = zvni->vxlan_if;
|
||||
if (!ifp)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
zif = ifp->info;
|
||||
|
||||
/* If down or not mapped to a bridge, we're done. */
|
||||
if (!if_is_operative(ifp) || !zif->brslave_info.br_if)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
zl2_info = zif->l2info.vxl;
|
||||
|
||||
vlan_if = zvni_map_to_svi(zl2_info.access_vlan,
|
||||
zif->brslave_info.br_if);
|
||||
if (!vlan_if)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
if (advertise_gw_macip_enabled(zvni)) {
|
||||
/* Add primary SVI MAC-IP */
|
||||
@ -6676,7 +6663,7 @@ int zebra_vxlan_advertise_gw_macip(struct zserv *client, u_short length,
|
||||
}
|
||||
|
||||
stream_failure:
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -6686,8 +6673,7 @@ stream_failure:
|
||||
* when disabled, the entries should be deleted and remote VTEPs and MACs
|
||||
* uninstalled from the kernel.
|
||||
*/
|
||||
int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length,
|
||||
struct zebra_vrf *zvrf)
|
||||
void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS)
|
||||
{
|
||||
struct stream *s = NULL;
|
||||
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) {
|
||||
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);
|
||||
|
||||
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");
|
||||
|
||||
if (zvrf->advertise_all_vni == advertise)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
zvrf->advertise_all_vni = advertise;
|
||||
if (is_evpn_enabled()) {
|
||||
@ -6732,13 +6718,13 @@ int zebra_vxlan_advertise_all_vni(struct zserv *client, u_short length,
|
||||
/* cleanup all l3vnis */
|
||||
zns = zebra_ns_lookup(NS_DEFAULT);
|
||||
if (!zns)
|
||||
return -1;
|
||||
return;
|
||||
|
||||
hash_iterate(zns->l3vni_table, zl3vni_cleanup_all, NULL);
|
||||
}
|
||||
|
||||
stream_failure:
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include "lib/json.h"
|
||||
#include "zebra/zebra_vrf.h"
|
||||
#include "zebra/zserv.h"
|
||||
|
||||
/* Is EVPN enabled? */
|
||||
#define EVPN_ENABLED(zvrf) (zvrf)->advertise_all_vni
|
||||
@ -51,6 +52,15 @@ static inline int is_evpn_enabled()
|
||||
|
||||
#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 ifindex_t get_l3vni_svi_ifindex(vrf_id_t vrf_id);
|
||||
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,
|
||||
struct interface *link_if,
|
||||
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,
|
||||
struct interface *br_if,
|
||||
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_update(struct interface *ifp, u_int16_t chgflags);
|
||||
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,
|
||||
char *err, int err_str_sz,
|
||||
int filter, int add);
|
||||
|
1937
zebra/zserv.c
1937
zebra/zserv.c
File diff suppressed because it is too large
Load Diff
@ -47,8 +47,12 @@ struct zserv {
|
||||
int sock;
|
||||
|
||||
/* Input/output buffer to the client. */
|
||||
struct stream *ibuf;
|
||||
struct stream *obuf;
|
||||
struct stream_fifo *ibuf_fifo;
|
||||
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. */
|
||||
struct buffer *wb;
|
||||
@ -129,6 +133,10 @@ struct zserv {
|
||||
int last_write_cmd;
|
||||
};
|
||||
|
||||
#define ZAPI_HANDLER_ARGS \
|
||||
struct zserv *client, struct zmsghdr *hdr, struct stream *msg, \
|
||||
struct zebra_vrf *zvrf
|
||||
|
||||
/* Zebra instance */
|
||||
struct zebra_t {
|
||||
/* 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 *,
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user