summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--babeld/babel_interface.c1
-rw-r--r--bfdd/ptm_adapter.c5
-rw-r--r--bgpd/bgp_addpath.c12
-rw-r--r--bgpd/bgp_attr.c262
-rw-r--r--bgpd/bgp_attr.h81
-rw-r--r--bgpd/bgp_conditional_adv.c5
-rw-r--r--bgpd/bgp_debug.c9
-rw-r--r--bgpd/bgp_ecommunity.c3
-rw-r--r--bgpd/bgp_ecommunity.h2
-rw-r--r--bgpd/bgp_errors.c12
-rw-r--r--bgpd/bgp_errors.h2
-rw-r--r--bgpd/bgp_evpn.c33
-rw-r--r--bgpd/bgp_evpn_mh.c3
-rw-r--r--bgpd/bgp_flowspec_vty.c14
-rw-r--r--bgpd/bgp_fsm.c10
-rw-r--r--bgpd/bgp_fsm.h12
-rw-r--r--bgpd/bgp_io.c9
-rw-r--r--bgpd/bgp_mac.c9
-rw-r--r--bgpd/bgp_memory.c2
-rw-r--r--bgpd/bgp_mplsvpn.c6
-rw-r--r--bgpd/bgp_nb_config.c25
-rw-r--r--bgpd/bgp_nexthop.c2
-rw-r--r--bgpd/bgp_packet.c21
-rw-r--r--bgpd/bgp_pbr.c4
-rw-r--r--bgpd/bgp_route.c145
-rw-r--r--bgpd/bgp_route.h7
-rw-r--r--bgpd/bgp_routemap.c1254
-rw-r--r--bgpd/bgp_rpki.c14
-rw-r--r--bgpd/bgp_table.h2
-rw-r--r--bgpd/bgp_updgrp_adv.c57
-rw-r--r--bgpd/bgp_vty.c21
-rw-r--r--bgpd/bgp_zebra.c101
-rw-r--r--bgpd/bgpd.c69
-rw-r--r--bgpd/bgpd.h21
-rw-r--r--bgpd/rfapi/rfapi.c50
-rw-r--r--bgpd/rfapi/rfapi_import.c8
-rw-r--r--bgpd/rfapi/rfapi_rib.c3
-rw-r--r--bgpd/rfapi/rfapi_vty.c18
-rw-r--r--bgpd/rfapi/vnc_export_bgp.c13
-rw-r--r--bgpd/rfapi/vnc_import_bgp.c8
-rw-r--r--doc/developer/building-frr-for-openwrt.rst4
-rw-r--r--doc/developer/fuzzing.rst164
-rw-r--r--doc/developer/index.rst1
-rw-r--r--doc/user/basic.rst2
-rw-r--r--doc/user/bgp.rst121
-rw-r--r--doc/user/ospf6d.rst7
-rw-r--r--doc/user/vrrp.rst2
-rw-r--r--doc/user/zebra.rst13
-rw-r--r--eigrpd/eigrp_zebra.c3
-rw-r--r--include/linux/rtnetlink.h1
-rw-r--r--isisd/isis_redist.c16
-rw-r--r--isisd/isis_redist.h1
-rw-r--r--isisd/isis_routemap.c34
-rw-r--r--isisd/isis_spf.c5
-rw-r--r--isisd/isis_spf.h1
-rw-r--r--isisd/isisd.c8
-rw-r--r--lib/command.c3
-rw-r--r--lib/log.c3
-rw-r--r--lib/routemap.c29
-rw-r--r--lib/routemap.h13
-rw-r--r--lib/sigevent.c2
-rw-r--r--lib/skiplist.c6
-rw-r--r--lib/thread.c7
-rw-r--r--lib/thread.h4
-rw-r--r--lib/vrf.h2
-rw-r--r--lib/zclient.c28
-rw-r--r--lib/zclient.h15
-rw-r--r--lib/zebra.h4
-rw-r--r--nhrpd/nhrp_route.c12
-rw-r--r--ospf6d/ospf6_abr.c13
-rw-r--r--ospf6d/ospf6_asbr.c46
-rw-r--r--ospf6d/ospf6_bfd.c5
-rw-r--r--ospf6d/ospf6_bfd.h6
-rw-r--r--ospf6d/ospf6_interface.c2
-rw-r--r--ospf6d/ospf6_neighbor.c442
-rw-r--r--ospf6d/ospf6_neighbor.h2
-rw-r--r--ospfd/ospf_gr_helper.c16
-rw-r--r--ospfd/ospf_opaque.c2
-rw-r--r--ospfd/ospf_opaque.h2
-rw-r--r--ospfd/ospf_routemap.c176
-rw-r--r--ospfd/ospf_te.c12
-rw-r--r--ospfd/ospf_zebra.c6
-rw-r--r--pbrd/pbr_zebra.c3
-rw-r--r--ripd/rip_routemap.c244
-rw-r--r--ripd/ripd.c6
-rw-r--r--ripngd/ripng_routemap.c133
-rw-r--r--ripngd/ripngd.c10
-rw-r--r--sharpd/sharp_zebra.c3
-rw-r--r--staticd/static_memory.h1
-rw-r--r--staticd/static_routes.c51
-rw-r--r--staticd/static_vrf.c49
-rw-r--r--staticd/static_zebra.c3
-rw-r--r--tests/bgpd/test_mpath.c73
-rw-r--r--tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py6
-rw-r--r--tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py6
-rw-r--r--tests/topotests/bgp_suppress_fib/r1/bgpd.conf15
-rw-r--r--tests/topotests/bgp_suppress_fib/r1/zebra.conf9
-rw-r--r--tests/topotests/bgp_suppress_fib/r2/bgpd.conf6
-rw-r--r--tests/topotests/bgp_suppress_fib/r2/zebra.conf13
-rw-r--r--tests/topotests/bgp_suppress_fib/r3/bgpd.conf9
-rw-r--r--tests/topotests/bgp_suppress_fib/r3/v4_route.json29
-rw-r--r--tests/topotests/bgp_suppress_fib/r3/v4_route2.json4
-rw-r--r--tests/topotests/bgp_suppress_fib/r3/zebra.conf6
-rw-r--r--tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py119
-rw-r--r--tests/topotests/lib/common_config.py277
-rw-r--r--tests/topotests/route-scale/r1/installed.routes.json8
-rw-r--r--tests/topotests/route-scale/test_route_scale.py25
-rw-r--r--zebra/connected.c21
-rw-r--r--zebra/main.c15
-rw-r--r--zebra/rt_netlink.c14
-rw-r--r--zebra/zapi_msg.c27
-rw-r--r--zebra/zapi_msg.h3
-rw-r--r--zebra/zebra_nb_config.c28
-rw-r--r--zebra/zebra_rib.c38
-rw-r--r--zebra/zebra_routemap.c283
-rw-r--r--zebra/zebra_router.c10
-rw-r--r--zebra/zebra_router.h5
-rw-r--r--zebra/zebra_vty.c47
118 files changed, 3025 insertions, 2150 deletions
diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c
index ae8b161b01..d37e0b608f 100644
--- a/babeld/babel_interface.c
+++ b/babeld/babel_interface.c
@@ -187,6 +187,7 @@ babel_interface_address_delete (ZAPI_CALLBACK_ARGS)
send_request(ifc->ifp, NULL, 0);
send_update(ifc->ifp, 0, NULL, 0);
+ connected_free(&ifc);
return 0;
}
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index 64dda0033b..90e2df2367 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -816,7 +816,10 @@ static int bfdd_interface_address_update(ZAPI_CALLBACK_ARGS)
: "delete",
ifc->address);
- bfdd_sessions_enable_address(ifc);
+ if (cmd == ZEBRA_INTERFACE_ADDRESS_ADD)
+ bfdd_sessions_enable_address(ifc);
+ else
+ connected_free(&ifc);
return 0;
}
diff --git a/bgpd/bgp_addpath.c b/bgpd/bgp_addpath.c
index d07d41bef8..d822f6e330 100644
--- a/bgpd/bgp_addpath.c
+++ b/bgpd/bgp_addpath.c
@@ -80,14 +80,12 @@ void bgp_addpath_init_bgp_data(struct bgp_addpath_bgp_data *d)
afi_t afi;
int i;
- for (afi = AFI_IP; afi < AFI_MAX; afi++) {
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- for (i = 0; i < BGP_ADDPATH_MAX; i++) {
- d->id_allocators[afi][safi][i] = NULL;
- d->peercount[afi][safi][i] = 0;
- }
- d->total_peercount[afi][safi] = 0;
+ FOREACH_AFI_SAFI (afi, safi) {
+ for (i = 0; i < BGP_ADDPATH_MAX; i++) {
+ d->id_allocators[afi][safi][i] = NULL;
+ d->peercount[afi][safi][i] = 0;
}
+ d->total_peercount[afi][safi] = 0;
}
}
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index b94e24e870..ce22e8404d 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -257,9 +257,12 @@ void bgp_attr_flush_encap(struct attr *attr)
attr->encap_subtlvs = NULL;
}
#ifdef ENABLE_BGP_VNC
- if (attr->vnc_subtlvs) {
- encap_free(attr->vnc_subtlvs);
- attr->vnc_subtlvs = NULL;
+ struct bgp_attr_encap_subtlv *vnc_subtlvs =
+ bgp_attr_get_vnc_subtlvs(attr);
+
+ if (vnc_subtlvs) {
+ encap_free(vnc_subtlvs);
+ bgp_attr_set_vnc_subtlvs(attr, NULL);
}
#endif
}
@@ -403,7 +406,9 @@ static bool overlay_index_same(const struct attr *a1, const struct attr *a2)
return false;
if (!a1 && !a2)
return true;
- return !memcmp(&(a1->evpn_overlay), &(a2->evpn_overlay),
+
+ return !memcmp(bgp_attr_get_evpn_overlay(a1),
+ bgp_attr_get_evpn_overlay(a2),
sizeof(struct bgp_route_evpn));
}
@@ -663,17 +668,19 @@ unsigned int attrhash_key_make(const void *p)
MIX(lcommunity_hash_make(attr->lcommunity));
if (attr->ecommunity)
MIX(ecommunity_hash_make(attr->ecommunity));
- if (attr->ipv6_ecommunity)
- MIX(ecommunity_hash_make(attr->ipv6_ecommunity));
- if (attr->cluster)
- MIX(cluster_hash_key_make(attr->cluster));
- if (attr->transit)
- MIX(transit_hash_key_make(attr->transit));
+ if (bgp_attr_get_ipv6_ecommunity(attr))
+ MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr)));
+ if (bgp_attr_get_cluster(attr))
+ MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr)));
+ if (bgp_attr_get_transit(attr))
+ MIX(transit_hash_key_make(bgp_attr_get_transit(attr)));
if (attr->encap_subtlvs)
MIX(encap_hash_key_make(attr->encap_subtlvs));
#ifdef ENABLE_BGP_VNC
- if (attr->vnc_subtlvs)
- MIX(encap_hash_key_make(attr->vnc_subtlvs));
+ struct bgp_attr_encap_subtlv *vnc_subtlvs =
+ bgp_attr_get_vnc_subtlvs(attr);
+ if (vnc_subtlvs)
+ MIX(encap_hash_key_make(vnc_subtlvs));
#endif
MIX(attr->mp_nexthop_len);
key = jhash(attr->mp_nexthop_global.s6_addr, IPV6_MAX_BYTELEN, key);
@@ -703,15 +710,19 @@ bool attrhash_cmp(const void *p1, const void *p2)
&& attr1->label_index == attr2->label_index
&& attr1->mp_nexthop_len == attr2->mp_nexthop_len
&& attr1->ecommunity == attr2->ecommunity
- && attr1->ipv6_ecommunity == attr2->ipv6_ecommunity
+ && bgp_attr_get_ipv6_ecommunity(attr1)
+ == bgp_attr_get_ipv6_ecommunity(attr2)
&& attr1->lcommunity == attr2->lcommunity
- && attr1->cluster == attr2->cluster
- && attr1->transit == attr2->transit
+ && bgp_attr_get_cluster(attr1)
+ == bgp_attr_get_cluster(attr2)
+ && bgp_attr_get_transit(attr1)
+ == bgp_attr_get_transit(attr2)
&& attr1->rmap_table_id == attr2->rmap_table_id
&& (attr1->encap_tunneltype == attr2->encap_tunneltype)
&& encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs)
#ifdef ENABLE_BGP_VNC
- && encap_same(attr1->vnc_subtlvs, attr2->vnc_subtlvs)
+ && encap_same(bgp_attr_get_vnc_subtlvs(attr1),
+ bgp_attr_get_vnc_subtlvs(attr2))
#endif
&& IPV6_ADDR_SAME(&attr1->mp_nexthop_global,
&attr2->mp_nexthop_global)
@@ -797,9 +808,11 @@ static void *bgp_attr_hash_alloc(void *p)
val->encap_subtlvs = NULL;
}
#ifdef ENABLE_BGP_VNC
- if (val->vnc_subtlvs) {
- val->vnc_subtlvs = NULL;
- }
+ struct bgp_attr_encap_subtlv *vnc_subtlvs =
+ bgp_attr_get_vnc_subtlvs(val);
+
+ if (vnc_subtlvs)
+ bgp_attr_set_vnc_subtlvs(val, NULL);
#endif
if (val->srv6_l3vpn)
val->srv6_l3vpn = NULL;
@@ -814,6 +827,7 @@ static void *bgp_attr_hash_alloc(void *p)
struct attr *bgp_attr_intern(struct attr *attr)
{
struct attr *find;
+ struct ecommunity *ecomm;
/* Intern referenced strucutre. */
if (attr->aspath) {
@@ -836,12 +850,13 @@ struct attr *bgp_attr_intern(struct attr *attr)
attr->ecommunity->refcnt++;
}
- if (attr->ipv6_ecommunity) {
- if (!attr->ipv6_ecommunity->refcnt)
- attr->ipv6_ecommunity =
- ecommunity_intern(attr->ipv6_ecommunity);
+ ecomm = bgp_attr_get_ipv6_ecommunity(attr);
+ if (ecomm) {
+ if (!ecomm->refcnt)
+ bgp_attr_set_ipv6_ecommunity(attr,
+ ecommunity_intern(ecomm));
else
- attr->ipv6_ecommunity->refcnt++;
+ ecomm->refcnt++;
}
if (attr->lcommunity) {
@@ -850,17 +865,23 @@ struct attr *bgp_attr_intern(struct attr *attr)
else
attr->lcommunity->refcnt++;
}
- if (attr->cluster) {
- if (!attr->cluster->refcnt)
- attr->cluster = cluster_intern(attr->cluster);
+
+ struct cluster_list *cluster = bgp_attr_get_cluster(attr);
+
+ if (cluster) {
+ if (!cluster->refcnt)
+ bgp_attr_set_cluster(attr, cluster_intern(cluster));
else
- attr->cluster->refcnt++;
+ cluster->refcnt++;
}
- if (attr->transit) {
- if (!attr->transit->refcnt)
- attr->transit = transit_intern(attr->transit);
+
+ struct transit *transit = bgp_attr_get_transit(attr);
+
+ if (transit) {
+ if (!transit->refcnt)
+ bgp_attr_set_transit(attr, transit_intern(transit));
else
- attr->transit->refcnt++;
+ transit->refcnt++;
}
if (attr->encap_subtlvs) {
if (!attr->encap_subtlvs->refcnt)
@@ -882,12 +903,16 @@ struct attr *bgp_attr_intern(struct attr *attr)
attr->srv6_vpn->refcnt++;
}
#ifdef ENABLE_BGP_VNC
- if (attr->vnc_subtlvs) {
- if (!attr->vnc_subtlvs->refcnt)
- attr->vnc_subtlvs = encap_intern(attr->vnc_subtlvs,
- VNC_SUBTLV_TYPE);
+ struct bgp_attr_encap_subtlv *vnc_subtlvs =
+ bgp_attr_get_vnc_subtlvs(attr);
+
+ if (vnc_subtlvs) {
+ if (!vnc_subtlvs->refcnt)
+ bgp_attr_set_vnc_subtlvs(
+ attr,
+ encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE));
else
- attr->vnc_subtlvs->refcnt++;
+ vnc_subtlvs->refcnt++;
}
#endif
@@ -1003,8 +1028,7 @@ struct attr *bgp_attr_aggregate_intern(
SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
- ret = route_map_apply(aggregate->rmap.map, p, RMAP_BGP,
- &rmap_path);
+ ret = route_map_apply(aggregate->rmap.map, p, &rmap_path);
bgp->peer_self->rmap_type = 0;
@@ -1036,6 +1060,9 @@ struct attr *bgp_attr_aggregate_intern(
/* Unintern just the sub-components of the attr, but not the attr */
void bgp_attr_unintern_sub(struct attr *attr)
{
+ struct ecommunity *ecomm;
+ struct cluster_list *cluster;
+
/* aspath refcount shoud be decrement. */
if (attr->aspath)
aspath_unintern(&attr->aspath);
@@ -1045,31 +1072,43 @@ void bgp_attr_unintern_sub(struct attr *attr)
community_unintern(&attr->community);
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
- if (attr->ecommunity)
- ecommunity_unintern(&attr->ecommunity);
+ ecommunity_unintern(&attr->ecommunity);
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES));
- if (attr->ipv6_ecommunity)
- ecommunity_unintern(&attr->ipv6_ecommunity);
+ ecomm = bgp_attr_get_ipv6_ecommunity(attr);
+ ecommunity_unintern(&ecomm);
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES));
+ bgp_attr_set_ipv6_ecommunity(attr, NULL);
if (attr->lcommunity)
lcommunity_unintern(&attr->lcommunity);
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
- if (attr->cluster)
- cluster_unintern(&attr->cluster);
+ cluster = bgp_attr_get_cluster(attr);
+ if (cluster) {
+ cluster_unintern(&cluster);
+ bgp_attr_set_cluster(attr, cluster);
+ }
UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST));
- if (attr->transit)
- transit_unintern(&attr->transit);
+ struct transit *transit = bgp_attr_get_transit(attr);
+
+ if (transit) {
+ transit_unintern(&transit);
+ bgp_attr_set_transit(attr, transit);
+ }
if (attr->encap_subtlvs)
encap_unintern(&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE);
#ifdef ENABLE_BGP_VNC
- if (attr->vnc_subtlvs)
- encap_unintern(&attr->vnc_subtlvs, VNC_SUBTLV_TYPE);
+ struct bgp_attr_encap_subtlv *vnc_subtlvs =
+ bgp_attr_get_vnc_subtlvs(attr);
+
+ if (vnc_subtlvs) {
+ encap_unintern(&vnc_subtlvs, VNC_SUBTLV_TYPE);
+ bgp_attr_set_vnc_subtlvs(attr, vnc_subtlvs);
+ }
#endif
if (attr->srv6_l3vpn)
@@ -1129,6 +1168,9 @@ void bgp_attr_unintern(struct attr **pattr)
void bgp_attr_flush(struct attr *attr)
{
+ struct ecommunity *ecomm;
+ struct cluster_list *cluster;
+
if (attr->aspath && !attr->aspath->refcnt) {
aspath_free(attr->aspath);
attr->aspath = NULL;
@@ -1137,26 +1179,36 @@ void bgp_attr_flush(struct attr *attr)
community_free(&attr->community);
if (attr->ecommunity && !attr->ecommunity->refcnt)
ecommunity_free(&attr->ecommunity);
- if (attr->ipv6_ecommunity && !attr->ipv6_ecommunity->refcnt)
- ecommunity_free(&attr->ipv6_ecommunity);
+ ecomm = bgp_attr_get_ipv6_ecommunity(attr);
+ if (ecomm && !ecomm->refcnt)
+ ecommunity_free(&ecomm);
+ bgp_attr_set_ipv6_ecommunity(attr, NULL);
if (attr->lcommunity && !attr->lcommunity->refcnt)
lcommunity_free(&attr->lcommunity);
- if (attr->cluster && !attr->cluster->refcnt) {
- cluster_free(attr->cluster);
- attr->cluster = NULL;
+
+ cluster = bgp_attr_get_cluster(attr);
+ if (cluster && !cluster->refcnt) {
+ cluster_free(cluster);
+ bgp_attr_set_cluster(attr, NULL);
}
- if (attr->transit && !attr->transit->refcnt) {
- transit_free(attr->transit);
- attr->transit = NULL;
+
+ struct transit *transit = bgp_attr_get_transit(attr);
+
+ if (transit && !transit->refcnt) {
+ transit_free(transit);
+ bgp_attr_set_transit(attr, NULL);
}
if (attr->encap_subtlvs && !attr->encap_subtlvs->refcnt) {
encap_free(attr->encap_subtlvs);
attr->encap_subtlvs = NULL;
}
#ifdef ENABLE_BGP_VNC
- if (attr->vnc_subtlvs && !attr->vnc_subtlvs->refcnt) {
- encap_free(attr->vnc_subtlvs);
- attr->vnc_subtlvs = NULL;
+ struct bgp_attr_encap_subtlv *vnc_subtlvs =
+ bgp_attr_get_vnc_subtlvs(attr);
+
+ if (vnc_subtlvs && !vnc_subtlvs->refcnt) {
+ encap_free(vnc_subtlvs);
+ bgp_attr_set_vnc_subtlvs(attr, NULL);
}
#endif
}
@@ -1929,8 +1981,9 @@ bgp_attr_cluster_list(struct bgp_attr_parser_args *args)
args->total);
}
- attr->cluster =
- cluster_parse((struct in_addr *)stream_pnt(peer->curr), length);
+ bgp_attr_set_cluster(
+ attr, cluster_parse((struct in_addr *)stream_pnt(peer->curr),
+ length));
/* XXX: Fix cluster_parse to use stream API and then remove this */
stream_forward_getp(peer->curr, length);
@@ -2302,19 +2355,21 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
struct peer *const peer = args->peer;
struct attr *const attr = args->attr;
const bgp_size_t length = args->length;
+ struct ecommunity *ipv6_ecomm = NULL;
if (length == 0) {
- attr->ipv6_ecommunity = NULL;
+ bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
}
- attr->ipv6_ecommunity =
- ecommunity_parse_ipv6(stream_pnt(peer->curr), length);
+ ipv6_ecomm = ecommunity_parse_ipv6(stream_pnt(peer->curr), length);
+ bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
+
/* XXX: fix ecommunity_parse to use stream API */
stream_forward_getp(peer->curr, length);
- if (!attr->ipv6_ecommunity)
+ if (!ipv6_ecomm)
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
@@ -2419,15 +2474,17 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
#ifdef ENABLE_BGP_VNC
} else {
struct bgp_attr_encap_subtlv *stlv_last;
- for (stlv_last = attr->vnc_subtlvs;
+ struct bgp_attr_encap_subtlv *vnc_subtlvs =
+ bgp_attr_get_vnc_subtlvs(attr);
+
+ for (stlv_last = vnc_subtlvs;
stlv_last && stlv_last->next;
stlv_last = stlv_last->next)
;
- if (stlv_last) {
+ if (stlv_last)
stlv_last->next = tlv;
- } else {
- attr->vnc_subtlvs = tlv;
- }
+ else
+ bgp_attr_set_vnc_subtlvs(attr, tlv);
#endif
}
}
@@ -2787,7 +2844,7 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args)
}
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
- attr->pmsi_tnl_type = tnl_type;
+ bgp_attr_set_pmsi_tnl_type(attr, tnl_type);
stream_get(&attr->label, peer->curr, BGP_LABEL_BYTES);
/* Forward read pointer of input stream. */
@@ -2837,10 +2894,9 @@ static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args)
SET_FLAG(*startp, BGP_ATTR_FLAG_PARTIAL);
/* Store transitive attribute to the end of attr->transit. */
- if (!attr->transit)
- attr->transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit));
-
- transit = attr->transit;
+ transit = bgp_attr_get_transit(attr);
+ if (!transit)
+ transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit));
if (transit->val)
transit->val = XREALLOC(MTYPE_TRANSIT_VAL, transit->val,
@@ -2850,6 +2906,7 @@ static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args)
memcpy(transit->val + transit->length, startp, total);
transit->length += total;
+ bgp_attr_set_transit(attr, transit);
return BGP_ATTR_PARSE_PROCEED;
}
@@ -2922,6 +2979,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
struct aspath *as4_path = NULL;
as_t as4_aggregator = 0;
struct in_addr as4_aggregator_addr = {.s_addr = 0};
+ struct transit *transit;
/* Initialize bitmap. */
memset(seen, 0, BGP_ATTR_BITMAP_SIZE);
@@ -3287,35 +3345,44 @@ done:
aspath_unintern(&as4_path);
}
+ transit = bgp_attr_get_transit(attr);
if (ret != BGP_ATTR_PARSE_ERROR) {
/* Finally intern unknown attribute. */
- if (attr->transit)
- attr->transit = transit_intern(attr->transit);
+ if (transit)
+ bgp_attr_set_transit(attr, transit_intern(transit));
if (attr->encap_subtlvs)
attr->encap_subtlvs = encap_intern(attr->encap_subtlvs,
ENCAP_SUBTLV_TYPE);
#ifdef ENABLE_BGP_VNC
- if (attr->vnc_subtlvs)
- attr->vnc_subtlvs = encap_intern(attr->vnc_subtlvs,
- VNC_SUBTLV_TYPE);
+ struct bgp_attr_encap_subtlv *vnc_subtlvs =
+ bgp_attr_get_vnc_subtlvs(attr);
+
+ if (vnc_subtlvs)
+ bgp_attr_set_vnc_subtlvs(
+ attr,
+ encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE));
#endif
} else {
- if (attr->transit) {
- transit_free(attr->transit);
- attr->transit = NULL;
+ if (transit) {
+ transit_free(transit);
+ bgp_attr_set_transit(attr, NULL);
}
bgp_attr_flush_encap(attr);
};
/* Sanity checks */
- if (attr->transit)
- assert(attr->transit->refcnt > 0);
+ transit = bgp_attr_get_transit(attr);
+ if (transit)
+ assert(transit->refcnt > 0);
if (attr->encap_subtlvs)
assert(attr->encap_subtlvs->refcnt > 0);
#ifdef ENABLE_BGP_VNC
- if (attr->vnc_subtlvs)
- assert(attr->vnc_subtlvs->refcnt > 0);
+ struct bgp_attr_encap_subtlv *vnc_subtlvs =
+ bgp_attr_get_vnc_subtlvs(attr);
+
+ if (vnc_subtlvs)
+ assert(vnc_subtlvs->refcnt > 0);
#endif
return ret;
@@ -3567,7 +3634,7 @@ static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer,
#ifdef ENABLE_BGP_VNC_ATTR
case BGP_ATTR_VNC:
attrname = "VNC";
- subtlvs = attr->vnc_subtlvs;
+ subtlvs = bgp_attr_get_vnc_subtlvs(attr);
if (subtlvs == NULL) /* nothing to do */
return;
attrlenfield = 0; /* no outer T + L */
@@ -3893,6 +3960,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
/* Route Reflector. */
if (peer->sort == BGP_PEER_IBGP && from
&& from->sort == BGP_PEER_IBGP) {
+ struct cluster_list *cluster = bgp_attr_get_cluster(attr);
+
/* Originator ID. */
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc(s, BGP_ATTR_ORIGINATOR_ID);
@@ -3907,16 +3976,15 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
stream_putc(s, BGP_ATTR_FLAG_OPTIONAL);
stream_putc(s, BGP_ATTR_CLUSTER_LIST);
- if (attr->cluster) {
- stream_putc(s, attr->cluster->length + 4);
+ if (cluster) {
+ stream_putc(s, cluster->length + 4);
/* If this peer configuration's parent BGP has
* cluster_id. */
if (bgp->config & BGP_CONFIG_CLUSTER_ID)
stream_put_in_addr(s, &bgp->cluster_id);
else
stream_put_in_addr(s, &bgp->router_id);
- stream_put(s, attr->cluster->list,
- attr->cluster->length);
+ stream_put(s, cluster->list, cluster->length);
} else {
stream_putc(s, 4);
/* If this peer configuration's parent BGP has
@@ -4112,7 +4180,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
stream_putc(s, BGP_ATTR_PMSI_TUNNEL);
stream_putc(s, 9); // Length
stream_putc(s, 0); // Flags
- stream_putc(s, attr->pmsi_tnl_type);
+ stream_putc(s, bgp_attr_get_pmsi_tnl_type(attr));
stream_put(s, &(attr->label),
BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI
stream_put_ipv4(s, attr->nexthop.s_addr);
@@ -4120,8 +4188,10 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
/* Unknown transit attribute. */
- if (attr->transit)
- stream_put(s, attr->transit->val, attr->transit->length);
+ struct transit *transit = bgp_attr_get_transit(attr);
+
+ if (transit)
+ stream_put(s, transit->val, transit->length);
/* Return total size of attribute. */
return stream_get_endp(s) - cp;
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index ef0e74344a..1b176f8716 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -185,7 +185,7 @@ struct attr {
struct lcommunity *lcommunity;
/* Route-Reflector Cluster attribute */
- struct cluster_list *cluster;
+ struct cluster_list *cluster1;
/* Unknown transitive attribute. */
struct transit *transit;
@@ -331,7 +331,7 @@ struct transit {
#define BGP_CLUSTER_LIST_LENGTH(attr) \
(((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) \
- ? (attr)->cluster->length \
+ ? bgp_attr_get_cluster((attr))->length \
: 0)
typedef enum {
@@ -457,4 +457,81 @@ static inline uint32_t mac_mobility_seqnum(struct attr *attr)
{
return (attr) ? attr->mm_seqnum : 0;
}
+
+static inline enum pta_type bgp_attr_get_pmsi_tnl_type(struct attr *attr)
+{
+ return attr->pmsi_tnl_type;
+}
+
+static inline void bgp_attr_set_pmsi_tnl_type(struct attr *attr,
+ enum pta_type pmsi_tnl_type)
+{
+ attr->pmsi_tnl_type = pmsi_tnl_type;
+}
+
+static inline struct ecommunity *
+bgp_attr_get_ipv6_ecommunity(const struct attr *attr)
+{
+ return attr->ipv6_ecommunity;
+}
+
+static inline void bgp_attr_set_ipv6_ecommunity(struct attr *attr,
+ struct ecommunity *ipv6_ecomm)
+{
+ attr->ipv6_ecommunity = ipv6_ecomm;
+}
+
+static inline struct transit *bgp_attr_get_transit(const struct attr *attr)
+{
+ return attr->transit;
+}
+
+static inline void bgp_attr_set_transit(struct attr *attr,
+ struct transit *transit)
+{
+ attr->transit = transit;
+}
+
+static inline struct cluster_list *bgp_attr_get_cluster(const struct attr *attr)
+{
+ return attr->cluster1;
+}
+
+static inline void bgp_attr_set_cluster(struct attr *attr,
+ struct cluster_list *cl)
+{
+ attr->cluster1 = cl;
+}
+
+static inline const struct bgp_route_evpn *
+bgp_attr_get_evpn_overlay(const struct attr *attr)
+{
+ return &attr->evpn_overlay;
+}
+
+static inline void bgp_attr_set_evpn_overlay(struct attr *attr,
+ struct bgp_route_evpn *eo)
+{
+ memcpy(&attr->evpn_overlay, eo, sizeof(struct bgp_route_evpn));
+}
+
+static inline struct bgp_attr_encap_subtlv *
+bgp_attr_get_vnc_subtlvs(const struct attr *attr)
+{
+#ifdef ENABLE_BGP_VNC
+ return attr->vnc_subtlvs;
+#else
+ return NULL;
+#endif
+}
+
+static inline void
+bgp_attr_set_vnc_subtlvs(struct attr *attr,
+ struct bgp_attr_encap_subtlv *vnc_subtlvs)
+{
+#ifdef ENABLE_BGP_VNC
+ attr->vnc_subtlvs = vnc_subtlvs;
+#endif
+}
+
#endif /* _QUAGGA_BGP_ATTR_H */
diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c
index 0731adcb84..b5cd1b52b7 100644
--- a/bgpd/bgp_conditional_adv.c
+++ b/bgpd/bgp_conditional_adv.c
@@ -47,10 +47,11 @@ bgp_check_rmap_prefixes_in_bgp_table(struct bgp_table *table,
RESET_FLAG(dummy_attr.rmap_change_flags);
- ret = route_map_apply(rmap, dest_p, RMAP_BGP, &path);
+ ret = route_map_apply(rmap, dest_p, &path);
if (ret != RMAP_PERMITMATCH)
bgp_attr_flush(&dummy_attr);
else {
+ bgp_dest_unlock_node(dest);
if (BGP_DEBUG(update, UPDATE_OUT))
zlog_debug(
"%s: Condition map routes present in BGP table",
@@ -112,7 +113,7 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
RESET_FLAG(dummy_attr.rmap_change_flags);
- if (route_map_apply(rmap, dest_p, RMAP_BGP, &path)
+ if (route_map_apply(rmap, dest_p, &path)
!= RMAP_PERMITMATCH) {
bgp_attr_flush(&dummy_attr);
continue;
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index c2c2d17a24..2c076fb80b 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -429,18 +429,21 @@ bool bgp_dump_attr(struct attr *attr, char *buf, size_t size)
", originator %pI4", &attr->originator_id);
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) {
+ struct cluster_list *cluster;
int i;
snprintf(buf + strlen(buf), size - strlen(buf),
", clusterlist");
- for (i = 0; i < attr->cluster->length / 4; i++)
+
+ cluster = bgp_attr_get_cluster(attr);
+ for (i = 0; i < cluster->length / 4; i++)
snprintfrr(buf + strlen(buf), size - strlen(buf),
- " %pI4", &attr->cluster->list[i]);
+ " %pI4", &cluster->list[i]);
}
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)))
snprintf(buf + strlen(buf), size - strlen(buf),
- ", pmsi tnltype %u", attr->pmsi_tnl_type);
+ ", pmsi tnltype %u", bgp_attr_get_pmsi_tnl_type(attr));
if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH)))
snprintf(buf + strlen(buf), size - strlen(buf), ", path %s",
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index de3757aebb..74cbf3a80a 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -327,6 +327,9 @@ void ecommunity_unintern(struct ecommunity **ecom)
{
struct ecommunity *ret;
+ if (!*ecom)
+ return;
+
if ((*ecom)->refcnt)
(*ecom)->refcnt--;
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index e9c52287f1..6318e7edb1 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -227,7 +227,7 @@ extern struct ecommunity *ecommunity_merge(struct ecommunity *,
extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *);
extern struct ecommunity *ecommunity_intern(struct ecommunity *);
extern bool ecommunity_cmp(const void *arg1, const void *arg2);
-extern void ecommunity_unintern(struct ecommunity **);
+extern void ecommunity_unintern(struct ecommunity **ecommunity);
extern unsigned int ecommunity_hash_make(const void *);
extern struct ecommunity *ecommunity_str2com(const char *, int, int);
extern struct ecommunity *ecommunity_str2com_ipv6(const char *str, int type,
diff --git a/bgpd/bgp_errors.c b/bgpd/bgp_errors.c
index 8a33ce6789..0f9d5fc73a 100644
--- a/bgpd/bgp_errors.c
+++ b/bgpd/bgp_errors.c
@@ -463,6 +463,18 @@ static struct log_ref ferr_bgp_err[] = {
.suggestion = "Change one of the two router-id's",
},
{
+ .code = EC_BGP_INVALID_BGP_INSTANCE,
+ .title = "BGP instance for the specifc vrf is invalid",
+ .description = "Indicates that specified bgp instance is NULL",
+ .suggestion = "Get log files from router and open an issue",
+ },
+ {
+ .code = EC_BGP_INVALID_ROUTE,
+ .title = "BGP route node is invalid",
+ .description = "BGP route for the specified AFI/SAFI is NULL",
+ .suggestion = "Get log files from router and open an issue",
+ },
+ {
.code = END_FERR,
}
};
diff --git a/bgpd/bgp_errors.h b/bgpd/bgp_errors.h
index 49c58ae6b0..20056d382a 100644
--- a/bgpd/bgp_errors.h
+++ b/bgpd/bgp_errors.h
@@ -99,6 +99,8 @@ enum bgp_log_refs {
EC_BGP_INVALID_NEXTHOP_LENGTH,
EC_BGP_DOPPELGANGER_CONFIG,
EC_BGP_ROUTER_ID_SAME,
+ EC_BGP_INVALID_BGP_INSTANCE,
+ EC_BGP_INVALID_ROUTE,
};
extern void bgp_error_init(void);
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 67d0a95cb6..890f7963e6 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -980,7 +980,7 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
} else if (p->prefix.route_type == BGP_EVPN_AD_ROUTE) {
ret = bgp_evpn_remote_es_evi_add(bgp, vpn, p);
} else {
- switch (pi->attr->pmsi_tnl_type) {
+ switch (bgp_attr_get_pmsi_tnl_type(pi->attr)) {
case PMSI_TNLTYPE_INGR_REPL:
flood_control = VXLAN_FLOOD_HEAD_END_REPL;
break;
@@ -1711,7 +1711,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
/* PMSI is only needed for type-3 routes */
if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL);
- attr.pmsi_tnl_type = PMSI_TNLTYPE_INGR_REPL;
+ bgp_attr_set_pmsi_tnl_type(&attr, PMSI_TNLTYPE_INGR_REPL);
}
if (bgp_debug_zebra(NULL)) {
@@ -2930,6 +2930,8 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install)
evp,
vrf_id_to_name(
bgp_vrf->vrf_id));
+ bgp_dest_unlock_node(rd_dest);
+ bgp_dest_unlock_node(dest);
return ret;
}
}
@@ -3009,6 +3011,9 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
? "MACIP"
: "IMET",
vpn->vni);
+
+ bgp_dest_unlock_node(rd_dest);
+ bgp_dest_unlock_node(dest);
return ret;
}
}
@@ -3738,12 +3743,14 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
*/
if (attr &&
(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL))) {
- if (attr->pmsi_tnl_type != PMSI_TNLTYPE_INGR_REPL &&
- attr->pmsi_tnl_type != PMSI_TNLTYPE_PIM_SM) {
- flog_warn(EC_BGP_EVPN_PMSI_PRESENT,
- "%u:%s - Rx EVPN Type-3 NLRI with unsupported PTA %d",
- peer->bgp->vrf_id, peer->host,
- attr->pmsi_tnl_type);
+ enum pta_type pmsi_tnl_type = bgp_attr_get_pmsi_tnl_type(attr);
+
+ if (pmsi_tnl_type != PMSI_TNLTYPE_INGR_REPL
+ && pmsi_tnl_type != PMSI_TNLTYPE_PIM_SM) {
+ flog_warn(
+ EC_BGP_EVPN_PMSI_PRESENT,
+ "%u:%s - Rx EVPN Type-3 NLRI with unsupported PTA %d",
+ peer->bgp->vrf_id, peer->host, pmsi_tnl_type);
}
}
@@ -3942,11 +3949,13 @@ static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p,
else
stream_put(s, &p_evpn_p->prefix_addr.ip.ipaddr_v6, 16);
if (attr) {
+ const struct bgp_route_evpn *evpn_overlay =
+ bgp_attr_get_evpn_overlay(attr);
+
if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
- stream_put_ipv4(s,
- attr->evpn_overlay.gw_ip.ipv4.s_addr);
+ stream_put_ipv4(s, evpn_overlay->gw_ip.ipv4.s_addr);
else
- stream_put(s, &(attr->evpn_overlay.gw_ip.ipv6), 16);
+ stream_put(s, &(evpn_overlay->gw_ip.ipv6), 16);
} else {
if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
stream_put_ipv4(s, 0);
@@ -4201,7 +4210,7 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi,
bgp_vrf->adv_cmd_rmap[afi][safi]
.map,
bgp_dest_get_prefix(dest),
- RMAP_BGP, &tmp_pi);
+ &tmp_pi);
if (ret == RMAP_DENYMATCH) {
bgp_attr_flush(&tmp_attr);
continue;
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index 021e811147..bf9a2f849a 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -763,6 +763,9 @@ static int bgp_evpn_type4_remote_routes_import(struct bgp *bgp,
install ? "install"
: "uninstall",
evp, es->esi_str);
+
+ bgp_dest_unlock_node(rd_dest);
+ bgp_dest_unlock_node(dest);
return ret;
}
}
diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c
index 3b7fb649a9..57f212b05d 100644
--- a/bgpd/bgp_flowspec_vty.c
+++ b/bgpd/bgp_flowspec_vty.c
@@ -268,6 +268,7 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
json_object *json_ecom_path = NULL;
json_object *json_time_path = NULL;
char timebuf[BGP_UPTIME_LEN];
+ struct ecommunity *ipv6_ecomm = NULL;
if (p == NULL || p->family != AF_FLOWSPEC)
return;
@@ -298,16 +299,19 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
json_object_array_add(json_paths, json_nlri_path);
if (!path)
return;
- if (path->attr &&
- (path->attr->ecommunity || path->attr->ipv6_ecommunity)) {
+
+ if (path->attr)
+ ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(path->attr);
+
+ if (path->attr && (path->attr->ecommunity || ipv6_ecomm)) {
/* Print attribute */
attr = path->attr;
if (attr->ecommunity)
s1 = ecommunity_ecom2str(attr->ecommunity,
ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
- if (attr->ipv6_ecommunity)
- s2 = ecommunity_ecom2str(attr->ipv6_ecommunity,
- ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+ if (ipv6_ecomm)
+ s2 = ecommunity_ecom2str(
+ ipv6_ecomm, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
if (!s1 && !s2)
return;
if (display == NLRI_STRING_FORMAT_LARGE)
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 4468408415..dd31a9b7cb 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -792,9 +792,13 @@ void bgp_adjust_routeadv(struct peer *peer)
BGP_TIMER_OFF(peer->t_routeadv);
peer->synctime = bgp_clock();
- thread_add_timer_msec(bm->master, bgp_generate_updgrp_packets,
- peer, 0,
- &peer->t_generate_updgrp_packets);
+ /* If suppress fib pending is enabled, route is advertised to
+ * peers when the status is received from the FIB. The delay
+ * is added to update group packet generate which will allow
+ * more routes to be sent in the update message
+ */
+ BGP_UPDATE_GROUP_TIMER_ON(&peer->t_generate_updgrp_packets,
+ bgp_generate_updgrp_packets);
return;
}
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index b9156df617..cd464d8c58 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -47,6 +47,18 @@
thread_cancel_event(bm->master, (P)); \
} while (0)
+#define BGP_UPDATE_GROUP_TIMER_ON(T, F) \
+ do { \
+ if (BGP_SUPPRESS_FIB_ENABLED(peer->bgp) && \
+ PEER_ROUTE_ADV_DELAY(peer)) \
+ thread_add_timer_msec(bm->master, (F), peer, \
+ (BGP_DEFAULT_UPDATE_ADVERTISEMENT_TIME * 1000),\
+ T); \
+ else \
+ thread_add_timer_msec(bm->master, (F), peer, \
+ 0, T); \
+ } while (0) \
+
#define BGP_MSEC_JITTER 10
/* Status codes for bgp_event_update() */
diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c
index 38455b5e02..53fd3b5fe3 100644
--- a/bgpd/bgp_io.c
+++ b/bgpd/bgp_io.c
@@ -149,12 +149,17 @@ static int bgp_process_writes(struct thread *thread)
fatal = true;
}
+ /* If suppress fib pending is enabled, route is advertised to peers when
+ * the status is received from the FIB. The delay is added
+ * to update group packet generate which will allow more routes to be
+ * sent in the update message
+ */
if (reschedule) {
thread_add_write(fpt->master, bgp_process_writes, peer,
peer->fd, &peer->t_write);
} else if (!fatal) {
- BGP_TIMER_ON(peer->t_generate_updgrp_packets,
- bgp_generate_updgrp_packets, 0);
+ BGP_UPDATE_GROUP_TIMER_ON(&peer->t_generate_updgrp_packets,
+ bgp_generate_updgrp_packets);
}
return 0;
diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c
index 265b4568e5..ec73ebb296 100644
--- a/bgpd/bgp_mac.c
+++ b/bgpd/bgp_mac.c
@@ -34,7 +34,7 @@
#include "bgpd/bgp_evpn_private.h"
DEFINE_MTYPE_STATIC(BGPD, BSM, "Mac Hash Entry");
-DEFINE_MTYPE_STATIC(BGPD, BSM_STRING, "Mac Hash Entry Interface String");
+DEFINE_MTYPE_STATIC(BGPD, BSM_STRING, "Mac Hash Entry Intf String");
struct bgp_self_mac {
struct ethaddr macaddr;
@@ -156,7 +156,7 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
struct prefix_rd prd;
uint32_t num_labels = 0;
mpls_label_t *label_pnt = NULL;
- struct bgp_route_evpn evpn;
+ struct bgp_route_evpn *evpn;
if (pevpn->family == AF_EVPN
&& pevpn->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
@@ -209,14 +209,15 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
continue;
}
- memcpy(&evpn, &pi->attr->evpn_overlay, sizeof(evpn));
+ memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
+ sizeof(evpn));
int32_t ret = bgp_update(peer, p,
pi->addpath_rx_id,
pi->attr, AFI_L2VPN, SAFI_EVPN,
ZEBRA_ROUTE_BGP,
BGP_ROUTE_NORMAL, &prd,
label_pnt, num_labels,
- 1, &evpn);
+ 1, evpn);
if (ret < 0)
bgp_dest_unlock_node(dest);
diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c
index 8bdab16680..d8fc98e048 100644
--- a/bgpd/bgp_memory.c
+++ b/bgpd/bgp_memory.c
@@ -116,7 +116,7 @@ DEFINE_MTYPE(BGPD, LCOMMUNITY_STR, "Large Community display string")
DEFINE_MTYPE(BGPD, LCOMMUNITY_VAL, "Large Community value")
DEFINE_MTYPE(BGPD, BGP_EVPN, "BGP EVPN Information")
-DEFINE_MTYPE(BGPD, BGP_EVPN_MH_INFO, "BGP EVPN Multihoming Information")
+DEFINE_MTYPE(BGPD, BGP_EVPN_MH_INFO, "BGP EVPN MH Information")
DEFINE_MTYPE(BGPD, BGP_EVPN_ES_VTEP, "BGP EVPN ES VTEP")
DEFINE_MTYPE(BGPD, BGP_EVPN_ES_EVI_VTEP, "BGP EVPN ES-EVI VTEP")
DEFINE_MTYPE(BGPD, BGP_EVPN_ES, "BGP EVPN ESI Information")
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 0c527efb8c..662c5da414 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -265,7 +265,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr,
if (STREAM_READABLE(data) != 0) {
flog_err(
EC_BGP_UPDATE_RCV,
- "%s [Error] Update packet error / VPN (%td data remaining after parsing)",
+ "%s [Error] Update packet error / VPN (%zu data remaining after parsing)",
peer->host, STREAM_READABLE(data));
return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH;
}
@@ -744,7 +744,7 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */
info.attr = &static_attr;
ret = route_map_apply(
bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN],
- p, RMAP_BGP, &info);
+ p, &info);
if (RMAP_DENYMATCH == ret) {
bgp_attr_flush(&static_attr); /* free any added parts */
if (debug)
@@ -1190,7 +1190,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
info.extra = path_vpn->extra; /* Used for source-vrf filter */
ret = route_map_apply(bgp_vrf->vpn_policy[afi]
.rmap[BGP_VPN_POLICY_DIR_FROMVPN],
- p, RMAP_BGP, &info);
+ p, &info);
if (RMAP_DENYMATCH == ret) {
bgp_attr_flush(&static_attr); /* free any added parts */
if (debug)
diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c
index eca7093fcd..ee6b13278d 100644
--- a/bgpd/bgp_nb_config.c
+++ b/bgpd/bgp_nb_config.c
@@ -173,7 +173,6 @@ int bgp_router_destroy(struct nb_cb_destroy_args *args)
case NB_EV_APPLY:
bgp = nb_running_unset_entry(args->dnode);
- bgp_vpn_leak_unimport(bgp);
bgp_delete(bgp);
break;
@@ -9080,10 +9079,10 @@ int bgp_global_afi_safis_afi_safi_ipv4_unicast_use_multiple_paths_ebgp_maximum_p
switch (args->event) {
case NB_EV_VALIDATE:
maxpaths = yang_dnode_get_uint16(args->dnode, NULL);
- if (maxpaths > MULTIPATH_NUM) {
+ if (maxpaths > multipath_num) {
snprintf(args->errmsg, args->errmsg_len,
"maxpaths %u is out of range %u", maxpaths,
- MULTIPATH_NUM);
+ multipath_num);
return NB_ERR_VALIDATION;
}
break;
@@ -9151,10 +9150,10 @@ int bgp_global_afi_safis_afi_safi_ipv4_unicast_use_multiple_paths_ibgp_maximum_p
switch (args->event) {
case NB_EV_VALIDATE:
maxpaths = yang_dnode_get_uint16(args->dnode, NULL);
- if (maxpaths > MULTIPATH_NUM) {
+ if (maxpaths > multipath_num) {
snprintf(args->errmsg, args->errmsg_len,
"maxpaths %u is out of range %u", maxpaths,
- MULTIPATH_NUM);
+ multipath_num);
return NB_ERR_VALIDATION;
}
break;
@@ -10998,10 +10997,10 @@ int bgp_global_afi_safis_afi_safi_ipv6_unicast_use_multiple_paths_ebgp_maximum_p
switch (args->event) {
case NB_EV_VALIDATE:
maxpaths = yang_dnode_get_uint16(args->dnode, NULL);
- if (maxpaths > MULTIPATH_NUM) {
+ if (maxpaths > multipath_num) {
snprintf(args->errmsg, args->errmsg_len,
"maxpaths %u is out of range %u", maxpaths,
- MULTIPATH_NUM);
+ multipath_num);
return NB_ERR_VALIDATION;
}
break;
@@ -11760,10 +11759,10 @@ int bgp_global_afi_safis_afi_safi_ipv4_labeled_unicast_use_multiple_paths_ebgp_m
switch (args->event) {
case NB_EV_VALIDATE:
maxpaths = yang_dnode_get_uint16(args->dnode, NULL);
- if (maxpaths > MULTIPATH_NUM) {
+ if (maxpaths > multipath_num) {
snprintf(args->errmsg, args->errmsg_len,
"maxpaths %u is out of range %u", maxpaths,
- MULTIPATH_NUM);
+ multipath_num);
return NB_ERR_VALIDATION;
}
break;
@@ -11998,10 +11997,10 @@ int bgp_global_afi_safis_afi_safi_ipv6_labeled_unicast_use_multiple_paths_ebgp_m
switch (args->event) {
case NB_EV_VALIDATE:
maxpaths = yang_dnode_get_uint16(args->dnode, NULL);
- if (maxpaths > MULTIPATH_NUM) {
+ if (maxpaths > multipath_num) {
snprintf(args->errmsg, args->errmsg_len,
"maxpaths %u is out of range %u", maxpaths,
- MULTIPATH_NUM);
+ multipath_num);
return NB_ERR_VALIDATION;
}
break;
@@ -12028,10 +12027,10 @@ int bgp_global_afi_safis_afi_safi_ipv6_labeled_unicast_use_multiple_paths_ibgp_m
switch (args->event) {
case NB_EV_VALIDATE:
maxpaths = yang_dnode_get_uint16(args->dnode, NULL);
- if (maxpaths > MULTIPATH_NUM) {
+ if (maxpaths > multipath_num) {
snprintf(args->errmsg, args->errmsg_len,
"maxpaths %u is out of range %u", maxpaths,
- MULTIPATH_NUM);
+ multipath_num);
return NB_ERR_VALIDATION;
}
break;
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 29cca99fd7..1a9f59db64 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -45,7 +45,7 @@
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_rd.h"
-DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Address Intf String");
+DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Addr Intf String");
int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache *a,
const struct bgp_nexthop_cache *b)
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index a23acda0a8..3d73e34235 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -279,18 +279,17 @@ static void bgp_update_explicit_eors(struct peer *peer)
if (bgp_debug_neighbor_events(peer))
zlog_debug("Peer %s: Checking explicit EORs", peer->host);
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- if (peer->afc_nego[afi][safi]
- && !CHECK_FLAG(peer->af_sflags[afi][safi],
- PEER_STATUS_EOR_RECEIVED)) {
- if (bgp_debug_neighbor_events(peer))
- zlog_debug(
- " afi %d safi %d didn't receive EOR",
- afi, safi);
- return;
- }
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (peer->afc_nego[afi][safi]
+ && !CHECK_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_EOR_RECEIVED)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ " afi %d safi %d didn't receive EOR",
+ afi, safi);
+ return;
}
+ }
peer->update_delay_over = 1;
peer->bgp->explicit_eors++;
diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c
index f7dd08443f..a3f1eb8401 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -915,10 +915,10 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p,
api->action_num++;
}
}
- if (path && path->attr && path->attr->ipv6_ecommunity) {
+ if (path && path->attr && bgp_attr_get_ipv6_ecommunity(path->attr)) {
struct ecommunity_val_ipv6 *ipv6_ecom_eval;
- ecom = path->attr->ipv6_ecommunity;
+ ecom = bgp_attr_get_ipv6_ecommunity(path->attr);
for (i = 0; i < ecom->size; i++) {
ipv6_ecom_eval = (struct ecommunity_val_ipv6 *)
(ecom->val + (i * ecom->unit_size));
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index f8a29821d8..8d87f2cd04 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -241,6 +241,9 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
if (e->bgp_orig)
bgp_unlock(e->bgp_orig);
+ if (e->aggr_suppressors)
+ list_delete(&e->aggr_suppressors);
+
if ((*extra)->bgp_fs_iprule)
list_delete(&((*extra)->bgp_fs_iprule));
if ((*extra)->bgp_fs_pbr)
@@ -1439,14 +1442,15 @@ static bool bgp_community_filter(struct peer *peer, struct attr *attr)
static bool bgp_cluster_filter(struct peer *peer, struct attr *attr)
{
struct in_addr cluster_id;
+ struct cluster_list *cluster = bgp_attr_get_cluster(attr);
- if (attr->cluster) {
+ if (cluster) {
if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID)
cluster_id = peer->bgp->cluster_id;
else
cluster_id = peer->bgp->router_id;
- if (cluster_loop_check(attr->cluster, cluster_id))
+ if (cluster_loop_check(cluster, cluster_id))
return true;
}
return false;
@@ -1500,7 +1504,7 @@ static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
/* Apply BGP route map to the attribute. */
- ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
+ ret = route_map_apply(rmap, p, &rmap_path);
peer->rmap_type = 0;
@@ -1551,7 +1555,7 @@ static int bgp_output_modifier(struct peer *peer, const struct prefix *p,
SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT);
/* Apply BGP route map to the attribute. */
- ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path);
+ ret = route_map_apply(rmap, p, &rmap_path);
peer->rmap_type = rmap_type;
@@ -2047,10 +2051,10 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
if (bgp_path_suppressed(pi))
ret = route_map_apply(UNSUPPRESS_MAP(filter), p,
- RMAP_BGP, &rmap_path);
+ &rmap_path);
else
ret = route_map_apply(ROUTE_MAP_OUT(filter), p,
- RMAP_BGP, &rmap_path);
+ &rmap_path);
peer->rmap_type = 0;
@@ -2497,10 +2501,13 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
struct attr attr;
afi_t afi;
safi_t safi;
+ struct bgp *bgp;
+ bool advertise;
p = bgp_dest_get_prefix(dest);
afi = SUBGRP_AFI(subgrp);
safi = SUBGRP_SAFI(subgrp);
+ bgp = SUBGRP_INST(subgrp);
onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer
: NULL);
@@ -2515,13 +2522,23 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp,
memset(&attr, 0, sizeof(struct attr));
/* It's initialized in bgp_announce_check() */
- /* Announcement to the subgroup. If the route is filtered withdraw it.
+ /* Announcement to the subgroup. If the route is filtered withdraw it.
+ * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status
+ * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the
+ * route
*/
+ advertise = bgp_check_advertise(bgp, dest);
+
if (selected) {
if (subgroup_announce_check(dest, selected, subgrp, p, &attr,
- false))
- bgp_adj_out_set_subgroup(dest, subgrp, &attr, selected);
- else
+ false)) {
+ /* Route is selected, if the route is already installed
+ * in FIB, then it is advertised
+ */
+ if (advertise)
+ bgp_adj_out_set_subgroup(dest, subgrp, &attr,
+ selected);
+ } else
bgp_adj_out_unset_subgroup(dest, subgrp, 1,
addpath_tx_id);
}
@@ -2620,7 +2637,7 @@ static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
RESET_FLAG(dummy_attr.rmap_change_flags);
ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map,
- p, RMAP_BGP, &rmap_path);
+ p, &rmap_path);
if (ret == RMAP_DENYMATCH) {
bgp_attr_flush(&dummy_attr);
@@ -3370,17 +3387,22 @@ static void overlay_index_update(struct attr *attr,
if (!attr)
return;
if (gw_ip == NULL) {
- memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr));
+ struct bgp_route_evpn eo;
+
+ memset(&eo, 0, sizeof(eo));
+ bgp_attr_set_evpn_overlay(attr, &eo);
} else {
- memcpy(&(attr->evpn_overlay.gw_ip), gw_ip,
- sizeof(union gw_addr));
+ struct bgp_route_evpn eo = {.gw_ip = *gw_ip};
+
+ bgp_attr_set_evpn_overlay(attr, &eo);
}
}
static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
union gw_addr *gw_ip)
{
- union gw_addr *path_gw_ip, *path_gw_ip_remote;
+ const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr);
+ union gw_addr path_gw_ip, *path_gw_ip_remote;
union {
esi_t esi;
union gw_addr ip;
@@ -3389,7 +3411,7 @@ static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
if (afi != AFI_L2VPN)
return true;
- path_gw_ip = &(path->attr->evpn_overlay.gw_ip);
+ path_gw_ip = eo->gw_ip;
if (gw_ip == NULL) {
memset(&temp, 0, sizeof(temp));
@@ -3397,7 +3419,7 @@ static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path,
} else
path_gw_ip_remote = gw_ip;
- return !!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
+ return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr));
}
/* Check if received nexthop is valid or not. */
@@ -3525,6 +3547,22 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
else
has_valid_label = bgp_is_valid_label(label);
+ if (has_valid_label)
+ assert(label != NULL);
+
+ /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
+ * condition :
+ * Suppress fib is enabled
+ * BGP_OPT_NO_FIB is not enabled
+ * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
+ * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
+ */
+ if (BGP_SUPPRESS_FIB_ENABLED(bgp) &&
+ (sub_type == BGP_ROUTE_NORMAL) &&
+ (!bgp_option_check(BGP_OPT_NO_FIB)) &&
+ (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
+ SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
+
/* When peer's soft reconfiguration enabled. Record input packet in
Adj-RIBs-In. */
if (!soft_reconfig
@@ -4480,7 +4518,8 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
if (num_labels)
label_pnt = &pi->extra->label[0];
if (pi)
- memcpy(&evpn, &pi->attr->evpn_overlay,
+ memcpy(&evpn,
+ bgp_attr_get_evpn_overlay(pi->attr),
sizeof(evpn));
else
memset(&evpn, 0, sizeof(evpn));
@@ -5189,8 +5228,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
- ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
- &rmap_path);
+ ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
bgp->peer_self->rmap_type = 0;
@@ -5509,8 +5547,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
- ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP,
- &rmap_path);
+ ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path);
bgp->peer_self->rmap_type = 0;
@@ -6361,7 +6398,7 @@ static bool aggr_suppress_map_test(struct bgp *bgp,
rmap_path.attr = &attr;
SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE);
- rmr = route_map_apply(aggregate->suppress_map, p, RMAP_BGP, &rmap_path);
+ rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path);
bgp->peer_self->rmap_type = 0;
bgp_attr_flush(&attr);
@@ -6789,6 +6826,12 @@ void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (dest_p->prefixlen <= p->prefixlen)
continue;
+ /* If suppress fib is enabled and route not installed
+ * in FIB, skip the route
+ */
+ if (!bgp_check_advertise(bgp, dest))
+ continue;
+
match = 0;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
@@ -7284,6 +7327,12 @@ void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p,
if (BGP_PATH_HOLDDOWN(pi))
return;
+ /* If suppress fib is enabled and route not installed
+ * in FIB, do not update the aggregate route
+ */
+ if (!bgp_check_advertise(bgp, pi->net))
+ return;
+
child = bgp_node_get(table, p);
/* Aggregate address configuration check. */
@@ -7807,8 +7856,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
SET_FLAG(bgp->peer_self->rmap_type,
PEER_RMAP_TYPE_REDISTRIBUTE);
- ret = route_map_apply(red->rmap.map, p, RMAP_BGP,
- &rmap_path);
+ ret = route_map_apply(red->rmap.map, p, &rmap_path);
bgp->peer_self->rmap_type = 0;
@@ -8926,13 +8974,12 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
}
}
- if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
- inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf,
- BUFSIZ);
- } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
- inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf,
- BUFSIZ);
- }
+ const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr);
+
+ if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p))
+ inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ);
+ else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p))
+ inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ);
if (!json_path)
vty_out(vty, "/%s", buf);
@@ -10018,6 +10065,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
}
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) {
+ struct cluster_list *cluster =
+ bgp_attr_get_cluster(attr);
int i;
if (json_paths) {
@@ -10025,13 +10074,11 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
json_cluster_list_list =
json_object_new_array();
- for (i = 0; i < attr->cluster->length / 4;
- i++) {
+ for (i = 0; i < cluster->length / 4; i++) {
json_string = json_object_new_string(
- inet_ntop(
- AF_INET,
- &attr->cluster->list[i],
- buf, sizeof(buf)));
+ inet_ntop(AF_INET,
+ &cluster->list[i],
+ buf, sizeof(buf)));
json_object_array_add(
json_cluster_list_list,
json_string);
@@ -10043,7 +10090,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
* do. Add this someday if someone asks
* for it.
* json_object_string_add(json_cluster_list,
- * "string", attr->cluster->str);
+ * "string", cluster->str);
*/
json_object_object_add(json_cluster_list,
"list",
@@ -10053,10 +10100,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
} else {
vty_out(vty, ", Cluster list: ");
- for (i = 0; i < attr->cluster->length / 4;
- i++) {
+ for (i = 0; i < cluster->length / 4; i++) {
vty_out(vty, "%pI4 ",
- &attr->cluster->list[i]);
+ &cluster->list[i]);
}
}
}
@@ -10183,9 +10229,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
/* Line 10 display PMSI tunnel attribute, if present */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) {
- const char *str =
- lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type,
- PMSI_TNLTYPE_STR_DEFAULT);
+ const char *str = lookup_msg(bgp_pmsi_tnltype_str,
+ bgp_attr_get_pmsi_tnl_type(attr),
+ PMSI_TNLTYPE_STR_DEFAULT);
if (json_paths) {
json_pmsi = json_object_new_object();
@@ -10354,8 +10400,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
path.peer = pi->peer;
path.attr = &dummy_attr;
- ret = route_map_apply(rmap, dest_p, RMAP_BGP,
- &path);
+ ret = route_map_apply(rmap, dest_p, &path);
if (ret == RMAP_DENYMATCH)
continue;
}
@@ -11168,6 +11213,7 @@ static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
char *str;
int first = 0;
uint8_t show_flags = 0;
+ int ret;
if (uj)
SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
@@ -11195,10 +11241,13 @@ static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc,
return CMD_WARNING;
}
- return bgp_show(vty, bgp, afi, safi,
+ ret = bgp_show(vty, bgp, afi, safi,
(exact ? bgp_show_type_lcommunity_exact
: bgp_show_type_lcommunity),
lcom, show_flags);
+
+ lcommunity_free(&lcom);
+ return ret;
}
static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp,
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index e4c6f9a0e2..0b76d7504b 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -524,6 +524,13 @@ static inline void prep_for_rmap_apply(struct bgp_path_info *dst_pi,
}
}
+static inline bool bgp_check_advertise(struct bgp *bgp, struct bgp_dest *dest)
+{
+ return (!(BGP_SUPPRESS_FIB_ENABLED(bgp) &&
+ CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING) &&
+ (!bgp_option_check(BGP_OPT_NO_FIB))));
+}
+
/* called before bgp_process() */
DECLARE_HOOK(bgp_process,
(struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index e4a9c29000..637eaca397 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -244,8 +244,7 @@ struct bgp_match_peer_compiled {
received in bgp_path_info->peer. If it is the same, or if the peer structure
received is a peer_group containing it, returns RMAP_MATCH. */
static enum route_map_cmd_result_t
-route_match_peer(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_peer(void *rule, const struct prefix *prefix, void *object)
{
struct bgp_match_peer_compiled *pc;
union sockunion *su;
@@ -255,56 +254,51 @@ route_match_peer(void *rule, const struct prefix *prefix,
struct peer *peer;
struct listnode *node, *nnode;
- if (type == RMAP_BGP) {
- pc = rule;
- su = &pc->su;
- peer = ((struct bgp_path_info *)object)->peer;
+ pc = rule;
+ su = &pc->su;
+ peer = ((struct bgp_path_info *)object)->peer;
- if (pc->interface) {
- if (!peer->conf_if)
- return RMAP_NOMATCH;
+ if (pc->interface) {
+ if (!peer->conf_if)
+ return RMAP_NOMATCH;
- if (strcmp(peer->conf_if, pc->interface) == 0)
- return RMAP_MATCH;
+ if (strcmp(peer->conf_if, pc->interface) == 0)
+ return RMAP_MATCH;
- return RMAP_NOMATCH;
- }
+ return RMAP_NOMATCH;
+ }
- /* If su='0.0.0.0' (command 'match peer local'), and it's a
- NETWORK,
- REDISTRIBUTE, AGGREGATE-ADDRESS or DEFAULT_GENERATED route
- => return RMAP_MATCH
- */
- if (sockunion_same(su, &su_def)) {
- int ret;
- if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
- || CHECK_FLAG(peer->rmap_type,
- PEER_RMAP_TYPE_REDISTRIBUTE)
- || CHECK_FLAG(peer->rmap_type,
- PEER_RMAP_TYPE_AGGREGATE)
- || CHECK_FLAG(peer->rmap_type,
- PEER_RMAP_TYPE_DEFAULT))
- ret = RMAP_MATCH;
- else
- ret = RMAP_NOMATCH;
- return ret;
- }
+ /* If su='0.0.0.0' (command 'match peer local'), and it's a
+ NETWORK,
+ REDISTRIBUTE, AGGREGATE-ADDRESS or DEFAULT_GENERATED route
+ => return RMAP_MATCH
+ */
+ if (sockunion_same(su, &su_def)) {
+ int ret;
+ if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK)
+ || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE)
+ || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_AGGREGATE)
+ || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_DEFAULT))
+ ret = RMAP_MATCH;
+ else
+ ret = RMAP_NOMATCH;
+ return ret;
+ }
+
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ if (sockunion_same(su, &peer->su))
+ return RMAP_MATCH;
- if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ return RMAP_NOMATCH;
+ } else {
+ group = peer->group;
+ for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
if (sockunion_same(su, &peer->su))
return RMAP_MATCH;
-
- return RMAP_NOMATCH;
- } else {
- group = peer->group;
- for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
- peer)) {
- if (sockunion_same(su, &peer->su))
- return RMAP_MATCH;
- }
- return RMAP_NOMATCH;
}
+ return RMAP_NOMATCH;
}
+
return RMAP_NOMATCH;
}
@@ -345,8 +339,7 @@ static const struct route_map_rule_cmd route_match_peer_cmd = {
#if defined(HAVE_LUA)
static enum route_map_cmd_result_t
-route_match_command(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_command(void *rule, const struct prefix *prefix, void *object)
{
int status = RMAP_NOMATCH;
u_int32_t locpref = 0;
@@ -443,12 +436,11 @@ static const struct route_map_rule_cmd route_match_command_cmd = {
/* Match function should return 1 if match is success else return
zero. */
static enum route_map_cmd_result_t
-route_match_ip_address(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
{
struct access_list *alist;
- if (type == RMAP_BGP && prefix->family == AF_INET) {
+ if (prefix->family == AF_INET) {
alist = access_list_lookup(AFI_IP, (char *)rule);
if (alist == NULL)
return RMAP_NOMATCH;
@@ -485,14 +477,13 @@ static const struct route_map_rule_cmd route_match_ip_address_cmd = {
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_ip_next_hop(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
{
struct access_list *alist;
struct bgp_path_info *path;
struct prefix_ipv4 p;
- if (type == RMAP_BGP && prefix->family == AF_INET) {
+ if (prefix->family == AF_INET) {
path = object;
p.family = AF_INET;
p.prefix = path->attr->nexthop;
@@ -534,15 +525,14 @@ static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_ip_route_source(void *rule, const struct prefix *pfx,
- route_map_object_t type, void *object)
+route_match_ip_route_source(void *rule, const struct prefix *pfx, void *object)
{
struct access_list *alist;
struct bgp_path_info *path;
struct peer *peer;
struct prefix_ipv4 p;
- if (type == RMAP_BGP && pfx->family == AF_INET) {
+ if (pfx->family == AF_INET) {
path = object;
peer = path->peer;
@@ -624,14 +614,10 @@ route_match_prefix_list_flowspec(afi_t afi, struct prefix_list *plist,
static enum route_map_cmd_result_t
route_match_address_prefix_list(void *rule, afi_t afi,
- const struct prefix *prefix,
- route_map_object_t type, void *object)
+ const struct prefix *prefix, void *object)
{
struct prefix_list *plist;
- if (type != RMAP_BGP)
- return RMAP_NOMATCH;
-
plist = prefix_list_lookup(afi, (char *)rule);
if (plist == NULL)
return RMAP_NOMATCH;
@@ -645,10 +631,9 @@ route_match_address_prefix_list(void *rule, afi_t afi,
static enum route_map_cmd_result_t
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
- return route_match_address_prefix_list(rule, AFI_IP, prefix, type,
- object);
+ return route_match_address_prefix_list(rule, AFI_IP, prefix, object);
}
static void *route_match_ip_address_prefix_list_compile(const char *arg)
@@ -673,13 +658,13 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct prefix_list *plist;
struct bgp_path_info *path;
struct prefix_ipv4 p;
- if (type == RMAP_BGP && prefix->family == AF_INET) {
+ if (prefix->family == AF_INET) {
path = object;
p.family = AF_INET;
p.prefix = path->attr->nexthop;
@@ -718,11 +703,11 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct bgp_path_info *path;
- if (type == RMAP_BGP && prefix->family == AF_INET) {
+ if (prefix->family == AF_INET) {
path = (struct bgp_path_info *)object;
if (!path)
return RMAP_NOMATCH;
@@ -759,16 +744,15 @@ static const struct route_map_rule_cmd
/* `match ip route-source prefix-list PREFIX_LIST' */
static enum route_map_cmd_result_t
-route_match_ip_route_source_prefix_list(void *rule,
- const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ip_route_source_prefix_list(void *rule, const struct prefix *prefix,
+ void *object)
{
struct prefix_list *plist;
struct bgp_path_info *path;
struct peer *peer;
struct prefix_ipv4 p;
- if (type == RMAP_BGP && prefix->family == AF_INET) {
+ if (prefix->family == AF_INET) {
path = object;
peer = path->peer;
@@ -812,10 +796,9 @@ static const struct route_map_rule_cmd
/* Match function should return 1 if match is success else 0 */
static enum route_map_cmd_result_t
-route_match_evpn_default_route(void *rule, const struct prefix *p,
- route_map_object_t type, void *object)
+route_match_evpn_default_route(void *rule, const struct prefix *p, void *object)
{
- if (type == RMAP_BGP && is_evpn_prefix_default(p))
+ if (is_evpn_prefix_default(p))
return RMAP_MATCH;
return RMAP_NOMATCH;
@@ -835,30 +818,24 @@ static const struct route_map_rule_cmd
/* Match function should return 1 if match is success else return
zero. */
static enum route_map_cmd_result_t
-route_match_mac_address(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_mac_address(void *rule, const struct prefix *prefix, void *object)
{
struct access_list *alist;
struct prefix p;
- if (type == RMAP_BGP) {
- alist = access_list_lookup(AFI_L2VPN, (char *)rule);
- if (alist == NULL)
- return RMAP_NOMATCH;
-
- if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE)
- return RMAP_NOMATCH;
+ alist = access_list_lookup(AFI_L2VPN, (char *)rule);
+ if (alist == NULL)
+ return RMAP_NOMATCH;
- p.family = AF_ETHERNET;
- p.prefixlen = ETH_ALEN * 8;
- p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac;
+ if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE)
+ return RMAP_NOMATCH;
- return (access_list_apply(alist, &p) == FILTER_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
+ p.family = AF_ETHERNET;
+ p.prefixlen = ETH_ALEN * 8;
+ p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac;
- return RMAP_NOMATCH;
+ return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
/* Route map `mac address' match statement. `arg' should be
@@ -889,43 +866,42 @@ static const struct route_map_rule_cmd route_match_mac_address_cmd = {
* ...RMAP_NOOP to ignore this match check.
*/
static enum route_map_cmd_result_t
-route_match_vni(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_vni(void *rule, const struct prefix *prefix, void *object)
{
vni_t vni = 0;
unsigned int label_cnt = 0;
struct bgp_path_info *path = NULL;
struct prefix_evpn *evp = (struct prefix_evpn *) prefix;
- if (type == RMAP_BGP) {
- vni = *((vni_t *)rule);
- path = (struct bgp_path_info *)object;
+ vni = *((vni_t *)rule);
+ path = (struct bgp_path_info *)object;
- /*
- * This rmap filter is valid for vxlan tunnel type only.
- * For any other tunnel type, return noop to ignore
- * this check.
- */
- if (path->attr->encap_tunneltype != BGP_ENCAP_TYPE_VXLAN)
- return RMAP_NOOP;
+ /*
+ * This rmap filter is valid for vxlan tunnel type only.
+ * For any other tunnel type, return noop to ignore
+ * this check.
+ */
+ if (path->attr->encap_tunneltype != BGP_ENCAP_TYPE_VXLAN)
+ return RMAP_NOOP;
- /*
- * Apply filter to type 1, 2, 5 routes only.
- * Other route types do not have vni label.
- */
- if (evp && (evp->prefix.route_type != BGP_EVPN_AD_ROUTE &&
- evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE &&
- evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE))
- return RMAP_NOOP;
+ /*
+ * Apply filter to type 1, 2, 5 routes only.
+ * Other route types do not have vni label.
+ */
+ if (evp
+ && (evp->prefix.route_type != BGP_EVPN_AD_ROUTE
+ && evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE
+ && evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE))
+ return RMAP_NOOP;
- if (path->extra == NULL)
- return RMAP_NOMATCH;
+ if (path->extra == NULL)
+ return RMAP_NOMATCH;
- for ( ; label_cnt < BGP_MAX_LABELS &&
- label_cnt < path->extra->num_labels; label_cnt++) {
- if (vni == label2vni(&path->extra->label[label_cnt]))
- return RMAP_MATCH;
- }
+ for (;
+ label_cnt < BGP_MAX_LABELS && label_cnt < path->extra->num_labels;
+ label_cnt++) {
+ if (vni == label2vni(&path->extra->label[label_cnt]))
+ return RMAP_MATCH;
}
return RMAP_NOMATCH;
@@ -967,17 +943,14 @@ static const struct route_map_rule_cmd route_match_evpn_vni_cmd = {
/* Match function should return 1 if match is success else return
zero. */
static enum route_map_cmd_result_t
-route_match_evpn_route_type(void *rule, const struct prefix *pfx,
- route_map_object_t type, void *object)
+route_match_evpn_route_type(void *rule, const struct prefix *pfx, void *object)
{
uint8_t route_type = 0;
- if (type == RMAP_BGP) {
- route_type = *((uint8_t *)rule);
+ route_type = *((uint8_t *)rule);
- if (route_type == pfx->u.prefix_evpn.route_type)
- return RMAP_MATCH;
- }
+ if (route_type == pfx->u.prefix_evpn.route_type)
+ return RMAP_MATCH;
return RMAP_NOMATCH;
}
@@ -1017,28 +990,24 @@ static const struct route_map_rule_cmd route_match_evpn_route_type_cmd = {
/* Match function should return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_rd(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_rd(void *rule, const struct prefix *prefix, void *object)
{
struct prefix_rd *prd_rule = NULL;
const struct prefix_rd *prd_route = NULL;
struct bgp_path_info *path = NULL;
- if (type == RMAP_BGP) {
- if (prefix->family != AF_EVPN)
- return RMAP_NOMATCH;
+ if (prefix->family != AF_EVPN)
+ return RMAP_NOMATCH;
- prd_rule = (struct prefix_rd *)rule;
- path = (struct bgp_path_info *)object;
+ prd_rule = (struct prefix_rd *)rule;
+ path = (struct bgp_path_info *)object;
- if (path->net == NULL || path->net->pdest == NULL)
- return RMAP_NOMATCH;
+ if (path->net == NULL || path->net->pdest == NULL)
+ return RMAP_NOMATCH;
- prd_route = (struct prefix_rd *)bgp_dest_get_prefix(
- path->net->pdest);
- if (memcmp(prd_route->val, prd_rule->val, ECOMMUNITY_SIZE) == 0)
- return RMAP_MATCH;
- }
+ prd_route = (struct prefix_rd *)bgp_dest_get_prefix(path->net->pdest);
+ if (memcmp(prd_route->val, prd_rule->val, ECOMMUNITY_SIZE) == 0)
+ return RMAP_MATCH;
return RMAP_NOMATCH;
}
@@ -1077,26 +1046,24 @@ static const struct route_map_rule_cmd route_match_evpn_rd_cmd = {
/* Route map commands for VRF route leak with source vrf matching */
static enum route_map_cmd_result_t
route_match_vrl_source_vrf(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct bgp_path_info *path;
char *vrf_name;
- if (type == RMAP_BGP) {
- vrf_name = rule;
- path = (struct bgp_path_info *)object;
+ vrf_name = rule;
+ path = (struct bgp_path_info *)object;
- if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
- return RMAP_NOMATCH;
+ if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0)
+ return RMAP_NOMATCH;
- if (path->extra == NULL)
- return RMAP_NOMATCH;
+ if (path->extra == NULL)
+ return RMAP_NOMATCH;
- if (strncmp(vrf_name, vrf_id_to_name(
- path->extra->bgp_orig->vrf_id), VRF_NAMSIZ)
- == 0)
- return RMAP_MATCH;
- }
+ if (strncmp(vrf_name, vrf_id_to_name(path->extra->bgp_orig->vrf_id),
+ VRF_NAMSIZ)
+ == 0)
+ return RMAP_MATCH;
return RMAP_NOMATCH;
}
@@ -1127,22 +1094,18 @@ static const struct route_map_rule_cmd route_match_vrl_source_vrf_cmd = {
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_local_pref(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_local_pref(void *rule, const struct prefix *prefix, void *object)
{
uint32_t *local_pref;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- local_pref = rule;
- path = object;
+ local_pref = rule;
+ path = object;
- if (path->attr->local_pref == *local_pref)
- return RMAP_MATCH;
- else
- return RMAP_NOMATCH;
- }
- return RMAP_NOMATCH;
+ if (path->attr->local_pref == *local_pref)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
}
/*
@@ -1188,18 +1151,14 @@ static const struct route_map_rule_cmd route_match_local_pref_cmd = {
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_metric(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_metric(void *rule, const struct prefix *prefix, void *object)
{
struct rmap_value *rv;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- rv = rule;
- path = object;
- return route_value_match(rv, path->attr->med);
- }
- return RMAP_NOMATCH;
+ rv = rule;
+ path = object;
+ return route_value_match(rv, path->attr->med);
}
/* Route map commands for metric matching. */
@@ -1214,27 +1173,22 @@ static const struct route_map_rule_cmd route_match_metric_cmd = {
/* Match function for as-path match. I assume given object is */
static enum route_map_cmd_result_t
-route_match_aspath(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_aspath(void *rule, const struct prefix *prefix, void *object)
{
struct as_list *as_list;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- as_list = as_list_lookup((char *)rule);
- if (as_list == NULL)
- return RMAP_NOMATCH;
+ as_list = as_list_lookup((char *)rule);
+ if (as_list == NULL)
+ return RMAP_NOMATCH;
- path = object;
+ path = object;
- /* Perform match. */
- return ((as_list_apply(as_list, path->attr->aspath)
- == AS_FILTER_DENY)
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ /* Perform match. */
+ return ((as_list_apply(as_list, path->attr->aspath) == AS_FILTER_DENY)
+ ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
/* Compile function for as-path match. */
@@ -1266,32 +1220,28 @@ struct rmap_community {
/* Match function for community match. */
static enum route_map_cmd_result_t
-route_match_community(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_community(void *rule, const struct prefix *prefix, void *object)
{
struct community_list *list;
struct bgp_path_info *path;
struct rmap_community *rcom = rule;
- if (type == RMAP_BGP) {
- path = object;
- rcom = rule;
+ path = object;
+ rcom = rule;
- list = community_list_lookup(bgp_clist, rcom->name,
- rcom->name_hash,
- COMMUNITY_LIST_MASTER);
- if (!list)
- return RMAP_NOMATCH;
+ list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
+ COMMUNITY_LIST_MASTER);
+ if (!list)
+ return RMAP_NOMATCH;
- if (rcom->exact) {
- if (community_list_exact_match(path->attr->community,
- list))
- return RMAP_MATCH;
- } else {
- if (community_list_match(path->attr->community, list))
- return RMAP_MATCH;
- }
+ if (rcom->exact) {
+ if (community_list_exact_match(path->attr->community, list))
+ return RMAP_MATCH;
+ } else {
+ if (community_list_match(path->attr->community, list))
+ return RMAP_MATCH;
}
+
return RMAP_NOMATCH;
}
@@ -1355,34 +1305,27 @@ static const struct route_map_rule_cmd route_match_community_cmd = {
/* Match function for lcommunity match. */
static enum route_map_cmd_result_t
-route_match_lcommunity(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_lcommunity(void *rule, const struct prefix *prefix, void *object)
{
struct community_list *list;
struct bgp_path_info *path;
struct rmap_community *rcom = rule;
- if (type == RMAP_BGP) {
- path = object;
+ path = object;
- list = community_list_lookup(bgp_clist, rcom->name,
- rcom->name_hash,
- LARGE_COMMUNITY_LIST_MASTER);
- if (!list)
- return RMAP_NOMATCH;
+ list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
+ LARGE_COMMUNITY_LIST_MASTER);
+ if (!list)
+ return RMAP_NOMATCH;
- if (rcom->exact) {
- if (lcommunity_list_exact_match(
- path->attr->lcommunity,
- list))
- return RMAP_MATCH;
- } else {
- if (lcommunity_list_match(
- path->attr->lcommunity,
- list))
- return RMAP_MATCH;
- }
+ if (rcom->exact) {
+ if (lcommunity_list_exact_match(path->attr->lcommunity, list))
+ return RMAP_MATCH;
+ } else {
+ if (lcommunity_list_match(path->attr->lcommunity, list))
+ return RMAP_MATCH;
}
+
return RMAP_NOMATCH;
}
@@ -1431,25 +1374,22 @@ static const struct route_map_rule_cmd route_match_lcommunity_cmd = {
/* Match function for extcommunity match. */
static enum route_map_cmd_result_t
-route_match_ecommunity(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ecommunity(void *rule, const struct prefix *prefix, void *object)
{
struct community_list *list;
struct bgp_path_info *path;
struct rmap_community *rcom = rule;
- if (type == RMAP_BGP) {
- path = object;
+ path = object;
- list = community_list_lookup(bgp_clist, rcom->name,
- rcom->name_hash,
- EXTCOMMUNITY_LIST_MASTER);
- if (!list)
- return RMAP_NOMATCH;
+ list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
+ EXTCOMMUNITY_LIST_MASTER);
+ if (!list)
+ return RMAP_NOMATCH;
+
+ if (ecommunity_list_match(path->attr->ecommunity, list))
+ return RMAP_MATCH;
- if (ecommunity_list_match(path->attr->ecommunity, list))
- return RMAP_MATCH;
- }
return RMAP_NOMATCH;
}
@@ -1487,19 +1427,16 @@ static const struct route_map_rule_cmd route_match_ecommunity_cmd = {
/* `match origin' */
static enum route_map_cmd_result_t
-route_match_origin(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_origin(void *rule, const struct prefix *prefix, void *object)
{
uint8_t *origin;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- origin = rule;
- path = object;
+ origin = rule;
+ path = object;
- if (path->attr->origin == *origin)
- return RMAP_MATCH;
- }
+ if (path->attr->origin == *origin)
+ return RMAP_MATCH;
return RMAP_NOMATCH;
}
@@ -1537,8 +1474,7 @@ static const struct route_map_rule_cmd route_match_origin_cmd = {
/* match probability { */
static enum route_map_cmd_result_t
-route_match_probability(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_probability(void *rule, const struct prefix *prefix, void *object)
{
long r = frr_weak_random();
@@ -1594,26 +1530,22 @@ static const struct route_map_rule_cmd route_match_probability_cmd = {
/* Match function should return 1 if match is success else return
zero. */
static enum route_map_cmd_result_t
-route_match_interface(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_interface(void *rule, const struct prefix *prefix, void *object)
{
struct interface *ifp;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- path = object;
+ path = object;
- if (!path)
- return RMAP_NOMATCH;
+ if (!path)
+ return RMAP_NOMATCH;
- ifp = if_lookup_by_name_all_vrf((char *)rule);
+ ifp = if_lookup_by_name_all_vrf((char *)rule);
- if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex)
- return RMAP_NOMATCH;
+ if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex)
+ return RMAP_NOMATCH;
- return RMAP_MATCH;
- }
- return RMAP_NOMATCH;
+ return RMAP_MATCH;
}
/* Route map `interface' match statement. `arg' should be
@@ -1643,20 +1575,15 @@ static const struct route_map_rule_cmd route_match_interface_cmd = {
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_tag(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_tag(void *rule, const struct prefix *prefix, void *object)
{
route_tag_t *tag;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- tag = rule;
- path = object;
-
- return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH);
- }
+ tag = rule;
+ path = object;
- return RMAP_NOMATCH;
+ return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH);
}
@@ -1669,15 +1596,11 @@ static const struct route_map_rule_cmd route_match_tag_cmd = {
};
static enum route_map_cmd_result_t
-route_set_srte_color(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_srte_color(void *rule, const struct prefix *prefix, void *object)
{
uint32_t *srte_color = rule;
struct bgp_path_info *path;
- if (type != RMAP_BGP)
- return RMAP_OKAY;
-
path = object;
path->attr->srte_color = *srte_color;
@@ -1716,16 +1639,12 @@ struct rmap_ip_nexthop_set {
};
static enum route_map_cmd_result_t
-route_set_ip_nexthop(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_ip_nexthop(void *rule, const struct prefix *prefix, void *object)
{
struct rmap_ip_nexthop_set *rins = rule;
struct bgp_path_info *path;
struct peer *peer;
- if (type != RMAP_BGP)
- return RMAP_OKAY;
-
if (prefix->family == AF_INET6)
return RMAP_OKAY;
@@ -1824,26 +1743,22 @@ static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
/* Set local preference. */
static enum route_map_cmd_result_t
-route_set_local_pref(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_local_pref(void *rule, const struct prefix *prefix, void *object)
{
struct rmap_value *rv;
struct bgp_path_info *path;
uint32_t locpref = 0;
- if (type == RMAP_BGP) {
- /* Fetch routemap's rule information. */
- rv = rule;
- path = object;
+ /* Fetch routemap's rule information. */
+ rv = rule;
+ path = object;
- /* Set local preference value. */
- if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
- locpref = path->attr->local_pref;
+ /* Set local preference value. */
+ if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
+ locpref = path->attr->local_pref;
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
- path->attr->local_pref =
- route_value_adjust(rv, locpref, path->peer);
- }
+ path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
+ path->attr->local_pref = route_value_adjust(rv, locpref, path->peer);
return RMAP_OKAY;
}
@@ -1860,20 +1775,17 @@ static const struct route_map_rule_cmd route_set_local_pref_cmd = {
/* Set weight. */
static enum route_map_cmd_result_t
-route_set_weight(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_weight(void *rule, const struct prefix *prefix, void *object)
{
struct rmap_value *rv;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- /* Fetch routemap's rule information. */
- rv = rule;
- path = object;
+ /* Fetch routemap's rule information. */
+ rv = rule;
+ path = object;
- /* Set weight value. */
- path->attr->weight = route_value_adjust(rv, 0, path->peer);
- }
+ /* Set weight value. */
+ path->attr->weight = route_value_adjust(rv, 0, path->peer);
return RMAP_OKAY;
}
@@ -1888,15 +1800,11 @@ static const struct route_map_rule_cmd route_set_weight_cmd = {
/* `set distance DISTANCE */
static enum route_map_cmd_result_t
-route_set_distance(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_distance(void *rule, const struct prefix *prefix, void *object)
{
struct bgp_path_info *path = object;
struct rmap_value *rv = rule;
- if (type != RMAP_BGP)
- return RMAP_OKAY;
-
path->attr->distance = rv->value;
return RMAP_OKAY;
@@ -1914,24 +1822,22 @@ static const struct route_map_rule_cmd route_set_distance_cmd = {
/* Set metric to attribute. */
static enum route_map_cmd_result_t
-route_set_metric(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_metric(void *rule, const struct prefix *prefix, void *object)
{
struct rmap_value *rv;
struct bgp_path_info *path;
uint32_t med = 0;
- if (type == RMAP_BGP) {
- /* Fetch routemap's rule information. */
- rv = rule;
- path = object;
+ /* Fetch routemap's rule information. */
+ rv = rule;
+ path = object;
- if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
- med = path->attr->med;
+ if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
+ med = path->attr->med;
+
+ path->attr->med = route_value_adjust(rv, med, path->peer);
+ path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
- path->attr->med = route_value_adjust(rv, med, path->peer);
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
- }
return RMAP_OKAY;
}
@@ -1945,21 +1851,20 @@ static const struct route_map_rule_cmd route_set_metric_cmd = {
/* `set table (1-4294967295)' */
-static enum route_map_cmd_result_t route_set_table_id(void *rule,
- const struct prefix *prefix,
- route_map_object_t type,
- void *object)
+static enum route_map_cmd_result_t
+route_set_table_id(void *rule, const struct prefix *prefix,
+
+ void *object)
{
struct rmap_value *rv;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- /* Fetch routemap's rule information. */
- rv = rule;
- path = object;
+ /* Fetch routemap's rule information. */
+ rv = rule;
+ path = object;
+
+ path->attr->rmap_table_id = rv->value;
- path->attr->rmap_table_id = rv->value;
- }
return RMAP_OKAY;
}
@@ -1975,34 +1880,31 @@ static const struct route_map_rule_cmd route_set_table_id_cmd = {
/* For AS path prepend mechanism. */
static enum route_map_cmd_result_t
-route_set_aspath_prepend(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_aspath_prepend(void *rule, const struct prefix *prefix, void *object)
{
struct aspath *aspath;
struct aspath *new;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- path = object;
-
- if (path->attr->aspath->refcnt)
- new = aspath_dup(path->attr->aspath);
- else
- new = path->attr->aspath;
+ path = object;
- if ((uintptr_t)rule > 10) {
- aspath = rule;
- aspath_prepend(aspath, new);
- } else {
- as_t as = aspath_leftmost(new);
- if (!as)
- as = path->peer->as;
- new = aspath_add_seq_n(new, as, (uintptr_t)rule);
- }
+ if (path->attr->aspath->refcnt)
+ new = aspath_dup(path->attr->aspath);
+ else
+ new = path->attr->aspath;
- path->attr->aspath = new;
+ if ((uintptr_t)rule > 10) {
+ aspath = rule;
+ aspath_prepend(aspath, new);
+ } else {
+ as_t as = aspath_leftmost(new);
+ if (!as)
+ as = path->peer->as;
+ new = aspath_add_seq_n(new, as, (uintptr_t)rule);
}
+ path->attr->aspath = new;
+
return RMAP_OKAY;
}
@@ -2039,22 +1941,19 @@ static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
* Make a deep copy of existing AS_PATH, but for the first ASn only.
*/
static enum route_map_cmd_result_t
-route_set_aspath_exclude(void *rule, const struct prefix *dummy,
- route_map_object_t type, void *object)
+route_set_aspath_exclude(void *rule, const struct prefix *dummy, void *object)
{
struct aspath *new_path, *exclude_path;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- exclude_path = rule;
- path = object;
- if (path->attr->aspath->refcnt)
- new_path = aspath_dup(path->attr->aspath);
- else
- new_path = path->attr->aspath;
- path->attr->aspath =
- aspath_filter_exclude(new_path, exclude_path);
- }
+ exclude_path = rule;
+ path = object;
+ if (path->attr->aspath->refcnt)
+ new_path = aspath_dup(path->attr->aspath);
+ else
+ new_path = path->attr->aspath;
+ path->attr->aspath = aspath_filter_exclude(new_path, exclude_path);
+
return RMAP_OKAY;
}
@@ -2075,8 +1974,7 @@ struct rmap_com_set {
/* For community set mechanism. */
static enum route_map_cmd_result_t
-route_set_community(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_community(void *rule, const struct prefix *prefix, void *object)
{
struct rmap_com_set *rcs;
struct bgp_path_info *path;
@@ -2085,44 +1983,42 @@ route_set_community(void *rule, const struct prefix *prefix,
struct community *old;
struct community *merge;
- if (type == RMAP_BGP) {
- rcs = rule;
- path = object;
- attr = path->attr;
- old = attr->community;
-
- /* "none" case. */
- if (rcs->none) {
- attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
- attr->community = NULL;
- /* See the longer comment down below. */
- if (old && old->refcnt == 0)
- community_free(&old);
- return RMAP_OKAY;
- }
+ rcs = rule;
+ path = object;
+ attr = path->attr;
+ old = attr->community;
+
+ /* "none" case. */
+ if (rcs->none) {
+ attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES));
+ attr->community = NULL;
+ /* See the longer comment down below. */
+ if (old && old->refcnt == 0)
+ community_free(&old);
+ return RMAP_OKAY;
+ }
- /* "additive" case. */
- if (rcs->additive && old) {
- merge = community_merge(community_dup(old), rcs->com);
+ /* "additive" case. */
+ if (rcs->additive && old) {
+ merge = community_merge(community_dup(old), rcs->com);
- new = community_uniq_sort(merge);
- community_free(&merge);
- } else
- new = community_dup(rcs->com);
+ new = community_uniq_sort(merge);
+ community_free(&merge);
+ } else
+ new = community_dup(rcs->com);
- /* HACK: if the old community is not intern'd,
- * we should free it here, or all reference to it may be
- * lost.
- * Really need to cleanup attribute caching sometime.
- */
- if (old && old->refcnt == 0)
- community_free(&old);
+ /* HACK: if the old community is not intern'd,
+ * we should free it here, or all reference to it may be
+ * lost.
+ * Really need to cleanup attribute caching sometime.
+ */
+ if (old && old->refcnt == 0)
+ community_free(&old);
- /* will be interned by caller if required */
- attr->community = new;
+ /* will be interned by caller if required */
+ attr->community = new;
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
- }
+ attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
return RMAP_OKAY;
}
@@ -2192,8 +2088,7 @@ struct rmap_lcom_set {
/* For lcommunity set mechanism. */
static enum route_map_cmd_result_t
-route_set_lcommunity(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_lcommunity(void *rule, const struct prefix *prefix, void *object)
{
struct rmap_lcom_set *rcs;
struct bgp_path_info *path;
@@ -2202,46 +2097,42 @@ route_set_lcommunity(void *rule, const struct prefix *prefix,
struct lcommunity *old;
struct lcommunity *merge;
- if (type == RMAP_BGP) {
- rcs = rule;
- path = object;
- attr = path->attr;
- old = attr->lcommunity;
-
- /* "none" case. */
- if (rcs->none) {
- attr->flag &=
- ~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
- attr->lcommunity = NULL;
-
- /* See the longer comment down below. */
- if (old && old->refcnt == 0)
- lcommunity_free(&old);
- return RMAP_OKAY;
- }
-
- if (rcs->additive && old) {
- merge = lcommunity_merge(lcommunity_dup(old),
- rcs->lcom);
+ rcs = rule;
+ path = object;
+ attr = path->attr;
+ old = attr->lcommunity;
- new = lcommunity_uniq_sort(merge);
- lcommunity_free(&merge);
- } else
- new = lcommunity_dup(rcs->lcom);
+ /* "none" case. */
+ if (rcs->none) {
+ attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES));
+ attr->lcommunity = NULL;
- /* HACK: if the old large-community is not intern'd,
- * we should free it here, or all reference to it may be
- * lost.
- * Really need to cleanup attribute caching sometime.
- */
+ /* See the longer comment down below. */
if (old && old->refcnt == 0)
lcommunity_free(&old);
+ return RMAP_OKAY;
+ }
- /* will be intern()'d or attr_flush()'d by bgp_update_main() */
- attr->lcommunity = new;
+ if (rcs->additive && old) {
+ merge = lcommunity_merge(lcommunity_dup(old), rcs->lcom);
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
- }
+ new = lcommunity_uniq_sort(merge);
+ lcommunity_free(&merge);
+ } else
+ new = lcommunity_dup(rcs->lcom);
+
+ /* HACK: if the old large-community is not intern'd,
+ * we should free it here, or all reference to it may be
+ * lost.
+ * Really need to cleanup attribute caching sometime.
+ */
+ if (old && old->refcnt == 0)
+ lcommunity_free(&old);
+
+ /* will be intern()'d or attr_flush()'d by bgp_update_main() */
+ attr->lcommunity = new;
+
+ attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
return RMAP_OKAY;
}
@@ -2306,8 +2197,7 @@ static const struct route_map_rule_cmd route_set_lcommunity_cmd = {
/* For large community set mechanism. */
static enum route_map_cmd_result_t
-route_set_lcommunity_delete(void *rule, const struct prefix *pfx,
- route_map_object_t type, void *object)
+route_set_lcommunity_delete(void *rule, const struct prefix *pfx, void *object)
{
struct community_list *list;
struct lcommunity *merge;
@@ -2316,40 +2206,36 @@ route_set_lcommunity_delete(void *rule, const struct prefix *pfx,
struct bgp_path_info *path;
struct rmap_community *rcom = rule;
- if (type == RMAP_BGP) {
- if (!rcom)
- return RMAP_OKAY;
+ if (!rcom)
+ return RMAP_OKAY;
- path = object;
- list = community_list_lookup(bgp_clist, rcom->name,
- rcom->name_hash,
- LARGE_COMMUNITY_LIST_MASTER);
- old = path->attr->lcommunity;
-
- if (list && old) {
- merge = lcommunity_list_match_delete(
- lcommunity_dup(old), list);
- new = lcommunity_uniq_sort(merge);
- lcommunity_free(&merge);
-
- /* HACK: if the old community is not intern'd,
- * we should free it here, or all reference to it may be
- * lost.
- * Really need to cleanup attribute caching sometime.
- */
- if (old->refcnt == 0)
- lcommunity_free(&old);
-
- if (new->size == 0) {
- path->attr->lcommunity = NULL;
- path->attr->flag &= ~ATTR_FLAG_BIT(
- BGP_ATTR_LARGE_COMMUNITIES);
- lcommunity_free(&new);
- } else {
- path->attr->lcommunity = new;
- path->attr->flag |= ATTR_FLAG_BIT(
- BGP_ATTR_LARGE_COMMUNITIES);
- }
+ path = object;
+ list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
+ LARGE_COMMUNITY_LIST_MASTER);
+ old = path->attr->lcommunity;
+
+ if (list && old) {
+ merge = lcommunity_list_match_delete(lcommunity_dup(old), list);
+ new = lcommunity_uniq_sort(merge);
+ lcommunity_free(&merge);
+
+ /* HACK: if the old community is not intern'd,
+ * we should free it here, or all reference to it may be
+ * lost.
+ * Really need to cleanup attribute caching sometime.
+ */
+ if (old->refcnt == 0)
+ lcommunity_free(&old);
+
+ if (new->size == 0) {
+ path->attr->lcommunity = NULL;
+ path->attr->flag &=
+ ~ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
+ lcommunity_free(&new);
+ } else {
+ path->attr->lcommunity = new;
+ path->attr->flag |=
+ ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES);
}
}
@@ -2399,7 +2285,7 @@ static const struct route_map_rule_cmd route_set_lcommunity_delete_cmd = {
/* For community set mechanism. */
static enum route_map_cmd_result_t
route_set_community_delete(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct community_list *list;
struct community *merge;
@@ -2408,40 +2294,35 @@ route_set_community_delete(void *rule, const struct prefix *prefix,
struct bgp_path_info *path;
struct rmap_community *rcom = rule;
- if (type == RMAP_BGP) {
- if (!rcom)
- return RMAP_OKAY;
+ if (!rcom)
+ return RMAP_OKAY;
- path = object;
- list = community_list_lookup(bgp_clist, rcom->name,
- rcom->name_hash,
- COMMUNITY_LIST_MASTER);
- old = path->attr->community;
-
- if (list && old) {
- merge = community_list_match_delete(community_dup(old),
- list);
- new = community_uniq_sort(merge);
- community_free(&merge);
-
- /* HACK: if the old community is not intern'd,
- * we should free it here, or all reference to it may be
- * lost.
- * Really need to cleanup attribute caching sometime.
- */
- if (old->refcnt == 0)
- community_free(&old);
-
- if (new->size == 0) {
- path->attr->community = NULL;
- path->attr->flag &=
- ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
- community_free(&new);
- } else {
- path->attr->community = new;
- path->attr->flag |=
- ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
- }
+ path = object;
+ list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash,
+ COMMUNITY_LIST_MASTER);
+ old = path->attr->community;
+
+ if (list && old) {
+ merge = community_list_match_delete(community_dup(old), list);
+ new = community_uniq_sort(merge);
+ community_free(&merge);
+
+ /* HACK: if the old community is not intern'd,
+ * we should free it here, or all reference to it may be
+ * lost.
+ * Really need to cleanup attribute caching sometime.
+ */
+ if (old->refcnt == 0)
+ community_free(&old);
+
+ if (new->size == 0) {
+ path->attr->community = NULL;
+ path->attr->flag &=
+ ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
+ community_free(&new);
+ } else {
+ path->attr->community = new;
+ path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES);
}
}
@@ -2489,42 +2370,39 @@ static const struct route_map_rule_cmd route_set_community_delete_cmd = {
/* For community set mechanism. Used by _rt and _soo. */
static enum route_map_cmd_result_t
-route_set_ecommunity(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_ecommunity(void *rule, const struct prefix *prefix, void *object)
{
struct ecommunity *ecom;
struct ecommunity *new_ecom;
struct ecommunity *old_ecom;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- ecom = rule;
- path = object;
+ ecom = rule;
+ path = object;
- if (!ecom)
- return RMAP_OKAY;
+ if (!ecom)
+ return RMAP_OKAY;
- /* We assume additive for Extended Community. */
- old_ecom = path->attr->ecommunity;
+ /* We assume additive for Extended Community. */
+ old_ecom = path->attr->ecommunity;
- if (old_ecom) {
- new_ecom = ecommunity_merge(ecommunity_dup(old_ecom),
- ecom);
+ if (old_ecom) {
+ new_ecom = ecommunity_merge(ecommunity_dup(old_ecom), ecom);
- /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
- * bgp_update_receive()
- * ->refcnt = 0 => set by a previous route-map
- * statement */
- if (!old_ecom->refcnt)
- ecommunity_free(&old_ecom);
- } else
- new_ecom = ecommunity_dup(ecom);
+ /* old_ecom->refcnt = 1 => owned elsewhere, e.g.
+ * bgp_update_receive()
+ * ->refcnt = 0 => set by a previous route-map
+ * statement */
+ if (!old_ecom->refcnt)
+ ecommunity_free(&old_ecom);
+ } else
+ new_ecom = ecommunity_dup(ecom);
- /* will be intern()'d or attr_flush()'d by bgp_update_main() */
- path->attr->ecommunity = new_ecom;
+ /* will be intern()'d or attr_flush()'d by bgp_update_main() */
+ path->attr->ecommunity = new_ecom;
+
+ path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
- }
return RMAP_OKAY;
}
@@ -2588,8 +2466,7 @@ struct rmap_ecomm_lb_set {
};
static enum route_map_cmd_result_t
-route_set_ecommunity_lb(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
{
struct rmap_ecomm_lb_set *rels = rule;
struct bgp_path_info *path;
@@ -2602,9 +2479,6 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix,
struct ecommunity *old_ecom;
as_t as;
- if (type != RMAP_BGP)
- return RMAP_OKAY;
-
path = object;
peer = path->peer;
if (!peer || !peer->bgp)
@@ -2721,18 +2595,15 @@ struct route_map_rule_cmd route_set_ecommunity_lb_cmd = {
/* For origin set. */
static enum route_map_cmd_result_t
-route_set_origin(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_origin(void *rule, const struct prefix *prefix, void *object)
{
uint8_t *origin;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- origin = rule;
- path = object;
+ origin = rule;
+ path = object;
- path->attr->origin = *origin;
- }
+ path->attr->origin = *origin;
return RMAP_OKAY;
}
@@ -2772,15 +2643,12 @@ static const struct route_map_rule_cmd route_set_origin_cmd = {
/* For atomic aggregate set. */
static enum route_map_cmd_result_t
-route_set_atomic_aggregate(void *rule, const struct prefix *pfx,
- route_map_object_t type, void *object)
+route_set_atomic_aggregate(void *rule, const struct prefix *pfx, void *object)
{
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- path = object;
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
- }
+ path = object;
+ path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
return RMAP_OKAY;
}
@@ -2812,20 +2680,17 @@ struct aggregator {
};
static enum route_map_cmd_result_t
-route_set_aggregator_as(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_aggregator_as(void *rule, const struct prefix *prefix, void *object)
{
struct bgp_path_info *path;
struct aggregator *aggregator;
- if (type == RMAP_BGP) {
- path = object;
- aggregator = rule;
+ path = object;
+ aggregator = rule;
- path->attr->aggregator_as = aggregator->as;
- path->attr->aggregator_addr = aggregator->address;
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
- }
+ path->attr->aggregator_as = aggregator->as;
+ path->attr->aggregator_addr = aggregator->address;
+ path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
return RMAP_OKAY;
}
@@ -2867,19 +2732,16 @@ static const struct route_map_rule_cmd route_set_aggregator_as_cmd = {
/* Set tag to object. object must be pointer to struct bgp_path_info */
static enum route_map_cmd_result_t
-route_set_tag(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_tag(void *rule, const struct prefix *prefix, void *object)
{
route_tag_t *tag;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- tag = rule;
- path = object;
+ tag = rule;
+ path = object;
- /* Set tag value */
- path->attr->tag = *tag;
- }
+ /* Set tag value */
+ path->attr->tag = *tag;
return RMAP_OKAY;
}
@@ -2894,24 +2756,21 @@ static const struct route_map_rule_cmd route_set_tag_cmd = {
/* Set label-index to object. object must be pointer to struct bgp_path_info */
static enum route_map_cmd_result_t
-route_set_label_index(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_label_index(void *rule, const struct prefix *prefix, void *object)
{
struct rmap_value *rv;
struct bgp_path_info *path;
uint32_t label_index;
- if (type == RMAP_BGP) {
- /* Fetch routemap's rule information. */
- rv = rule;
- path = object;
+ /* Fetch routemap's rule information. */
+ rv = rule;
+ path = object;
- /* Set label-index value. */
- label_index = rv->value;
- if (label_index) {
- path->attr->label_index = label_index;
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
- }
+ /* Set label-index value. */
+ label_index = rv->value;
+ if (label_index) {
+ path->attr->label_index = label_index;
+ path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
}
return RMAP_OKAY;
@@ -2928,12 +2787,11 @@ static const struct route_map_rule_cmd route_set_label_index_cmd = {
/* `match ipv6 address IP_ACCESS_LIST' */
static enum route_map_cmd_result_t
-route_match_ipv6_address(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
{
struct access_list *alist;
- if (type == RMAP_BGP && prefix->family == AF_INET6) {
+ if (prefix->family == AF_INET6) {
alist = access_list_lookup(AFI_IP6, (char *)rule);
if (alist == NULL)
return RMAP_NOMATCH;
@@ -2966,25 +2824,19 @@ static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
/* `match ipv6 next-hop IP_ADDRESS' */
static enum route_map_cmd_result_t
-route_match_ipv6_next_hop(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object)
{
struct in6_addr *addr = rule;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- path = object;
-
- if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr))
- return RMAP_MATCH;
+ path = object;
- if (path->attr->mp_nexthop_len
- == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
- && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule))
- return RMAP_MATCH;
+ if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr))
+ return RMAP_MATCH;
- return RMAP_NOMATCH;
- }
+ if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
+ && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule))
+ return RMAP_MATCH;
return RMAP_NOMATCH;
}
@@ -3020,22 +2872,17 @@ static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
/* `match ip next-hop IP_ADDRESS' */
static enum route_map_cmd_result_t
-route_match_ipv4_next_hop(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ipv4_next_hop(void *rule, const struct prefix *prefix, void *object)
{
struct in_addr *addr = rule;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- path = object;
-
- if (path->attr->nexthop.s_addr == addr->s_addr ||
- (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4 &&
- IPV4_ADDR_SAME(&path->attr->mp_nexthop_global_in, addr)))
- return RMAP_MATCH;
+ path = object;
- return RMAP_NOMATCH;
- }
+ if (path->attr->nexthop.s_addr == addr->s_addr
+ || (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4
+ && IPV4_ADDR_SAME(&path->attr->mp_nexthop_global_in, addr)))
+ return RMAP_MATCH;
return RMAP_NOMATCH;
}
@@ -3072,10 +2919,9 @@ static const struct route_map_rule_cmd route_match_ipv4_next_hop_cmd = {
static enum route_map_cmd_result_t
route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
- return route_match_address_prefix_list(rule, AFI_IP6, prefix, type,
- object);
+ return route_match_address_prefix_list(rule, AFI_IP6, prefix, object);
}
static void *route_match_ipv6_address_prefix_list_compile(const char *arg)
@@ -3100,12 +2946,12 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct bgp_path_info *path;
struct in6_addr *addr = rule;
- if (type == RMAP_BGP && prefix->family == AF_INET6) {
+ if (prefix->family == AF_INET6) {
path = (struct bgp_path_info *)object;
if (!path)
return RMAP_NOMATCH;
@@ -3114,6 +2960,7 @@ route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
&& !path->attr->nh_ifindex)
return RMAP_MATCH;
}
+
return RMAP_NOMATCH;
}
@@ -3150,27 +2997,24 @@ static const struct route_map_rule_cmd
/* Set nexthop to object. ojbect must be pointer to struct attr. */
static enum route_map_cmd_result_t
-route_set_ipv6_nexthop_global(void *rule, const struct prefix *p,
- route_map_object_t type, void *object)
+route_set_ipv6_nexthop_global(void *rule, const struct prefix *p, void *object)
{
struct in6_addr *address;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- /* Fetch routemap's rule information. */
- address = rule;
- path = object;
+ /* Fetch routemap's rule information. */
+ address = rule;
+ path = object;
- /* Set next hop value. */
- path->attr->mp_nexthop_global = *address;
+ /* Set next hop value. */
+ path->attr->mp_nexthop_global = *address;
- /* Set nexthop length. */
- if (path->attr->mp_nexthop_len == 0)
- path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
+ /* Set nexthop length. */
+ if (path->attr->mp_nexthop_len == 0)
+ path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
- SET_FLAG(path->attr->rmap_change_flags,
- BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
- }
+ SET_FLAG(path->attr->rmap_change_flags,
+ BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED);
return RMAP_OKAY;
}
@@ -3212,28 +3056,27 @@ static const struct route_map_rule_cmd
/* Set next-hop preference value. */
static enum route_map_cmd_result_t
route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct bgp_path_info *path;
struct peer *peer;
- if (type == RMAP_BGP) {
- /* Fetch routemap's rule information. */
- path = object;
- peer = path->peer;
+ /* Fetch routemap's rule information. */
+ path = object;
+ peer = path->peer;
- if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
- || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
- /* Set next hop preference to global */
- path->attr->mp_nexthop_prefer_global = true;
- SET_FLAG(path->attr->rmap_change_flags,
- BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
- } else {
- path->attr->mp_nexthop_prefer_global = false;
- SET_FLAG(path->attr->rmap_change_flags,
- BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
- }
+ if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
+ || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
+ /* Set next hop preference to global */
+ path->attr->mp_nexthop_prefer_global = true;
+ SET_FLAG(path->attr->rmap_change_flags,
+ BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
+ } else {
+ path->attr->mp_nexthop_prefer_global = false;
+ SET_FLAG(path->attr->rmap_change_flags,
+ BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
}
+
return RMAP_OKAY;
}
@@ -3266,29 +3109,24 @@ static const struct route_map_rule_cmd
/* Set nexthop to object. ojbect must be pointer to struct attr. */
static enum route_map_cmd_result_t
-route_set_ipv6_nexthop_local(void *rule, const struct prefix *p,
- route_map_object_t type, void *object)
+route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object)
{
struct in6_addr *address;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- /* Fetch routemap's rule information. */
- address = rule;
- path = object;
+ /* Fetch routemap's rule information. */
+ address = rule;
+ path = object;
- /* Set next hop value. */
- path->attr->mp_nexthop_local = *address;
+ /* Set next hop value. */
+ path->attr->mp_nexthop_local = *address;
- /* Set nexthop length. */
- if (path->attr->mp_nexthop_len
- != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
- path->attr->mp_nexthop_len =
- BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
+ /* Set nexthop length. */
+ if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
+ path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
- SET_FLAG(path->attr->rmap_change_flags,
- BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
- }
+ SET_FLAG(path->attr->rmap_change_flags,
+ BATTR_RMAP_IPV6_LL_NHOP_CHANGED);
return RMAP_OKAY;
}
@@ -3331,55 +3169,52 @@ static const struct route_map_rule_cmd
/* Set nexthop to object. ojbect must be pointer to struct attr. */
static enum route_map_cmd_result_t
-route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx,
- route_map_object_t type, void *object)
+route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object)
{
struct in6_addr peer_address;
struct bgp_path_info *path;
struct peer *peer;
- if (type == RMAP_BGP) {
- /* Fetch routemap's rule information. */
- path = object;
- peer = path->peer;
-
- if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
- || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
- && peer->su_remote
- && sockunion_family(peer->su_remote) == AF_INET6) {
- peer_address = peer->su_remote->sin6.sin6_addr;
- /* Set next hop value and length in attribute. */
- if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
- path->attr->mp_nexthop_local = peer_address;
- if (path->attr->mp_nexthop_len
- != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
- path->attr->mp_nexthop_len =
- BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
- } else {
- path->attr->mp_nexthop_global = peer_address;
- if (path->attr->mp_nexthop_len == 0)
- path->attr->mp_nexthop_len =
- BGP_ATTR_NHLEN_IPV6_GLOBAL;
- }
+ /* Fetch routemap's rule information. */
+ path = object;
+ peer = path->peer;
- } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
- /* The next hop value will be set as part of packet
- * rewrite.
- * Set the flags here to indicate that rewrite needs to
- * be done.
- * Also, clear the value - we clear both global and
- * link-local
- * nexthops, whether we send one or both is determined
- * elsewhere.
- */
- SET_FLAG(path->attr->rmap_change_flags,
- BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
- /* clear next hop value. */
- memset(&(path->attr->mp_nexthop_global), 0,
- sizeof(struct in6_addr));
- memset(&(path->attr->mp_nexthop_local), 0,
- sizeof(struct in6_addr));
+ if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
+ || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT))
+ && peer->su_remote
+ && sockunion_family(peer->su_remote) == AF_INET6) {
+ peer_address = peer->su_remote->sin6.sin6_addr;
+ /* Set next hop value and length in attribute. */
+ if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) {
+ path->attr->mp_nexthop_local = peer_address;
+ if (path->attr->mp_nexthop_len
+ != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
+ path->attr->mp_nexthop_len =
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
+ } else {
+ path->attr->mp_nexthop_global = peer_address;
+ if (path->attr->mp_nexthop_len == 0)
+ path->attr->mp_nexthop_len =
+ BGP_ATTR_NHLEN_IPV6_GLOBAL;
}
+
+ } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) {
+ /* The next hop value will be set as part of packet
+ * rewrite.
+ * Set the flags here to indicate that rewrite needs to
+ * be done.
+ * Also, clear the value - we clear both global and
+ * link-local
+ * nexthops, whether we send one or both is determined
+ * elsewhere.
+ */
+ SET_FLAG(path->attr->rmap_change_flags,
+ BATTR_RMAP_NEXTHOP_PEER_ADDRESS);
+ /* clear next hop value. */
+ memset(&(path->attr->mp_nexthop_global), 0,
+ sizeof(struct in6_addr));
+ memset(&(path->attr->mp_nexthop_local), 0,
+ sizeof(struct in6_addr));
}
return RMAP_OKAY;
@@ -3414,21 +3249,18 @@ static const struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = {
/* `set ipv4 vpn next-hop A.B.C.D' */
static enum route_map_cmd_result_t
-route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix, void *object)
{
struct in_addr *address;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- /* Fetch routemap's rule information. */
- address = rule;
- path = object;
+ /* Fetch routemap's rule information. */
+ address = rule;
+ path = object;
- /* Set next hop value. */
- path->attr->mp_nexthop_global_in = *address;
- path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
- }
+ /* Set next hop value. */
+ path->attr->mp_nexthop_global_in = *address;
+ path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
return RMAP_OKAY;
}
@@ -3453,22 +3285,19 @@ static void *route_set_vpnv4_nexthop_compile(const char *arg)
/* `set ipv6 vpn next-hop A.B.C.D' */
static enum route_map_cmd_result_t
-route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix, void *object)
{
struct in6_addr *address;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- /* Fetch routemap's rule information. */
- address = rule;
- path = object;
+ /* Fetch routemap's rule information. */
+ address = rule;
+ path = object;
- /* Set next hop value. */
- memcpy(&path->attr->mp_nexthop_global, address,
- sizeof(struct in6_addr));
- path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
- }
+ /* Set next hop value. */
+ memcpy(&path->attr->mp_nexthop_global, address,
+ sizeof(struct in6_addr));
+ path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL;
return RMAP_OKAY;
}
@@ -3514,19 +3343,16 @@ static const struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = {
/* For origin set. */
static enum route_map_cmd_result_t
-route_set_originator_id(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_originator_id(void *rule, const struct prefix *prefix, void *object)
{
struct in_addr *address;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- address = rule;
- path = object;
+ address = rule;
+ path = object;
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
- path->attr->originator_id = *address;
- }
+ path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID);
+ path->attr->originator_id = *address;
return RMAP_OKAY;
}
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 0f0aff7eaa..24ee99bddb 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -124,7 +124,7 @@ static int is_running(void);
static void route_match_free(void *rule);
static enum route_map_cmd_result_t route_match(void *rule,
const struct prefix *prefix,
- route_map_object_t type,
+
void *object);
static void *route_match_compile(const char *arg);
static void revalidate_bgp_node(struct bgp_dest *dest, afi_t afi, safi_t safi);
@@ -213,20 +213,18 @@ static void ipv6_addr_to_host_byte_order(const uint32_t *src, uint32_t *dest)
static enum route_map_cmd_result_t route_match(void *rule,
const struct prefix *prefix,
- route_map_object_t type,
void *object)
{
int *rpki_status = rule;
struct bgp_path_info *path;
- if (type == RMAP_BGP) {
- path = object;
+ path = object;
- if (rpki_validate_prefix(path->peer, path->attr, prefix)
- == *rpki_status) {
- return RMAP_MATCH;
- }
+ if (rpki_validate_prefix(path->peer, path->attr, prefix)
+ == *rpki_status) {
+ return RMAP_MATCH;
}
+
return RMAP_NOMATCH;
}
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index 4e9abf863d..738d41ee6d 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -102,6 +102,8 @@ struct bgp_node {
#define BGP_NODE_LABEL_CHANGED (1 << 2)
#define BGP_NODE_REGISTERED_FOR_LABEL (1 << 3)
#define BGP_NODE_SELECT_DEFER (1 << 4)
+#define BGP_NODE_FIB_INSTALL_PENDING (1 << 5)
+#define BGP_NODE_FIB_INSTALLED (1 << 6)
struct bgp_addpath_node_data tx_addpath;
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 3cfb73d8a8..da9e1f28ae 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -315,6 +315,7 @@ static void updgrp_show_adj(struct bgp *bgp, afi_t afi, safi_t safi,
static int subgroup_coalesce_timer(struct thread *thread)
{
struct update_subgroup *subgrp;
+ struct bgp *bgp;
subgrp = THREAD_ARG(thread);
if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
@@ -323,6 +324,7 @@ static int subgroup_coalesce_timer(struct thread *thread)
subgrp->v_coalesce);
subgrp->t_coalesce = NULL;
subgrp->v_coalesce = 0;
+ bgp = SUBGRP_INST(subgrp);
subgroup_announce_route(subgrp);
@@ -334,7 +336,8 @@ static int subgroup_coalesce_timer(struct thread *thread)
* to
* announce, this is the method currently employed to trigger the EOR.
*/
- if (!bgp_update_delay_active(SUBGRP_INST(subgrp))) {
+ if (!bgp_update_delay_active(SUBGRP_INST(subgrp)) &&
+ !(BGP_SUPPRESS_FIB_ENABLED(bgp))) {
struct peer_af *paf;
struct peer *peer;
@@ -458,10 +461,14 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
struct peer *peer;
afi_t afi;
safi_t safi;
+ struct peer *adv_peer;
+ struct peer_af *paf;
+ struct bgp *bgp;
peer = SUBGRP_PEER(subgrp);
afi = SUBGRP_AFI(subgrp);
safi = SUBGRP_SAFI(subgrp);
+ bgp = SUBGRP_INST(subgrp);
if (DISABLE_BGP_ANNOUNCE)
return;
@@ -504,9 +511,21 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest,
* mrai timers so the socket writes can happen.
*/
if (!bgp_adv_fifo_count(&subgrp->sync->update)) {
- struct peer_af *paf;
-
SUBGRP_FOREACH_PEER (subgrp, paf) {
+ /* If there are no routes in the withdraw list, set
+ * the flag PEER_STATUS_ADV_DELAY which will allow
+ * more routes to be sent in the update message
+ */
+ if (BGP_SUPPRESS_FIB_ENABLED(bgp)) {
+ adv_peer = PAF_PEER(paf);
+ if (!bgp_adv_fifo_count(
+ &subgrp->sync->withdraw))
+ SET_FLAG(adv_peer->thread_flags,
+ PEER_THREAD_SUBGRP_ADV_DELAY);
+ else
+ UNSET_FLAG(adv_peer->thread_flags,
+ PEER_THREAD_SUBGRP_ADV_DELAY);
+ }
bgp_adjust_routeadv(PAF_PEER(paf));
}
}
@@ -617,10 +636,13 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
afi_t afi;
safi_t safi;
int addpath_capable;
+ struct bgp *bgp;
+ bool advertise;
peer = SUBGRP_PEER(subgrp);
afi = SUBGRP_AFI(subgrp);
safi = SUBGRP_SAFI(subgrp);
+ bgp = SUBGRP_INST(subgrp);
addpath_capable = bgp_addpath_encode_tx(peer, afi, safi);
if (safi == SAFI_LABELED_UNICAST)
@@ -637,6 +659,9 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
const struct prefix *dest_p = bgp_dest_get_prefix(dest);
+ /* Check if the route can be advertised */
+ advertise = bgp_check_advertise(bgp, dest);
+
for (ri = bgp_dest_get_bgp_path_info(dest); ri; ri = ri->next)
if (CHECK_FLAG(ri->flags, BGP_PATH_SELECTED)
@@ -646,10 +671,14 @@ void subgroup_announce_table(struct update_subgroup *subgrp,
ri))) {
if (subgroup_announce_check(dest, ri, subgrp,
dest_p, &attr,
- false))
- bgp_adj_out_set_subgroup(dest, subgrp,
- &attr, ri);
- else {
+ false)) {
+ /* Check if route can be advertised */
+ if (advertise)
+ bgp_adj_out_set_subgroup(dest,
+ subgrp,
+ &attr,
+ ri);
+ } else {
/* If default originate is enabled for
* the peer, do not send explicit
* withdraw. This will prevent deletion
@@ -794,8 +823,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
ret = route_map_apply(
peer->default_rmap[afi][safi].map,
- bgp_dest_get_prefix(dest), RMAP_BGP,
- &tmp_pi);
+ bgp_dest_get_prefix(dest), &tmp_pi);
if (ret == RMAP_DENYMATCH) {
bgp_attr_flush(&tmp_attr);
@@ -813,8 +841,10 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
break;
}
}
- if (ret == RMAP_PERMITMATCH)
+ if (ret == RMAP_PERMITMATCH) {
+ bgp_dest_unlock_node(dest);
break;
+ }
}
bgp->peer_self->rmap_type = 0;
@@ -944,6 +974,13 @@ void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi,
struct updwalk_context ctx;
ctx.pi = pi;
ctx.dest = dest;
+
+ /* If suppress fib is enabled, the route will be advertised when
+ * FIB status is received
+ */
+ if (!bgp_check_advertise(bgp, dest))
+ return;
+
update_group_af_walk(bgp, afi, safi, group_announce_route_walkcb, &ctx);
}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 6977223b83..40e9707866 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -1514,6 +1514,20 @@ void cli_show_router_bgp_router_id(struct vty *vty, struct lyd_node *dnode,
vty_out(vty, " bgp router-id %s\n", yang_dnode_get_string(dnode, NULL));
}
+DEFPY (bgp_suppress_fib_pending,
+ bgp_suppress_fib_pending_cmd,
+ "[no] bgp suppress-fib-pending",
+ NO_STR
+ BGP_STR
+ "Advertise only routes that are programmed in kernel to peers\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ bgp_suppress_fib_pending_set(bgp, !no);
+ return CMD_SUCCESS;
+}
+
+
/* BGP Cluster ID. */
DEFUN_YANG(bgp_cluster_id,
bgp_cluster_id_cmd,
@@ -16833,6 +16847,10 @@ int bgp_config_write(struct vty *vty)
vty_out(vty, " bgp router-id %pI4\n",
&bgp->router_id_static);
+ /* Suppress fib pending */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING))
+ vty_out(vty, " bgp suppress-fib-pending\n");
+
/* BGP log-neighbor-changes. */
if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES)
!= SAVE_BGP_LOG_NEIGHBOR_CHANGES)
@@ -17348,6 +17366,9 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &bgp_router_id_cmd);
install_element(BGP_NODE, &no_bgp_router_id_cmd);
+ /* "bgp suppress-fib-pending" command */
+ install_element(BGP_NODE, &bgp_suppress_fib_pending_cmd);
+
/* "bgp cluster-id" commands. */
install_element(BGP_NODE, &bgp_cluster_id_cmd);
install_element(BGP_NODE, &no_bgp_cluster_id_cmd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 957db4cbc1..73f03f6a9d 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -531,9 +531,9 @@ static int zebra_read_route(ZAPI_CALLBACK_ARGS)
api.instance, &api.prefix, buf, nhtype, ifindex,
api.metric, api.tag);
} else {
- zlog_debug("Rx route DEL VRF %u %s[%d] %s", vrf_id,
+ zlog_debug("Rx route DEL VRF %u %s[%d] %pFX", vrf_id,
zebra_route_string(api.type), api.instance,
- buf);
+ &api.prefix);
}
}
@@ -918,7 +918,7 @@ static bool bgp_table_map_apply(struct route_map *map, const struct prefix *p,
{
route_map_result_t ret;
- ret = route_map_apply(map, p, RMAP_BGP, path);
+ ret = route_map_apply(map, p, path);
bgp_attr_flush(path->attr);
if (ret != RMAP_DENYMATCH)
@@ -2380,6 +2380,99 @@ static int iptable_notify_owner(ZAPI_CALLBACK_ARGS)
return 0;
}
+/* Process route notification messages from RIB */
+static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
+ zebra_size_t length, vrf_id_t vrf_id)
+{
+ struct prefix p;
+ enum zapi_route_notify_owner note;
+ uint32_t table_id;
+ char buf[PREFIX_STRLEN];
+ afi_t afi;
+ safi_t safi;
+ struct bgp_dest *dest;
+ struct bgp *bgp;
+ struct bgp_path_info *pi, *new_select;
+
+ if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, &note,
+ &afi, &safi)) {
+ zlog_err("%s : error in msg decode", __PRETTY_FUNCTION__);
+ return -1;
+ }
+
+ /* Get the bgp instance */
+ bgp = bgp_lookup_by_vrf_id(vrf_id);
+ if (!bgp) {
+ flog_err(EC_BGP_INVALID_BGP_INSTANCE,
+ "%s : bgp instance not found vrf %d",
+ __PRETTY_FUNCTION__, vrf_id);
+ return -1;
+ }
+
+ if (BGP_DEBUG(zebra, ZEBRA))
+ prefix2str(&p, buf, sizeof(buf));
+
+ /* Find the bgp route node */
+ dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi, &p,
+ &bgp->vrf_prd);
+ if (!dest)
+ return -1;
+
+ bgp_dest_unlock_node(dest);
+
+ switch (note) {
+ case ZAPI_ROUTE_INSTALLED:
+ new_select = NULL;
+ /* Clear the flags so that route can be processed */
+ if (CHECK_FLAG(dest->flags,
+ BGP_NODE_FIB_INSTALL_PENDING)) {
+ UNSET_FLAG(dest->flags,
+ BGP_NODE_FIB_INSTALL_PENDING);
+ SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("route %s : INSTALLED", buf);
+ /* Find the best route */
+ for (pi = dest->info; pi; pi = pi->next) {
+ /* Process aggregate route */
+ bgp_aggregate_increment(bgp, &p, pi,
+ afi, safi);
+ if (CHECK_FLAG(pi->flags,
+ BGP_PATH_SELECTED))
+ new_select = pi;
+ }
+ /* Advertise the route */
+ if (new_select)
+ group_announce_route(bgp, afi, safi,
+ dest, new_select);
+ else {
+ flog_err(EC_BGP_INVALID_ROUTE,
+ "selected route %s not found",
+ buf);
+ return -1;
+ }
+ }
+ break;
+ case ZAPI_ROUTE_REMOVED:
+ /* Route deleted from dataplane, reset the installed flag
+ * so that route can be reinstalled when client sends
+ * route add later
+ */
+ UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED);
+ break;
+ case ZAPI_ROUTE_FAIL_INSTALL:
+ /* Error will be logged by zebra module */
+ break;
+ case ZAPI_ROUTE_BETTER_ADMIN_WON:
+ /* No action required */
+ break;
+ case ZAPI_ROUTE_REMOVE_FAIL:
+ zlog_warn("%s: Route %s failure to remove",
+ __func__, buf);
+ break;
+ }
+ return 0;
+}
+
/* this function is used to forge ip rule,
* - either for iptable/ipset using fwmark id
* - or for sample ip rule cmd
@@ -2747,6 +2840,7 @@ static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS)
stream_get(&esi, s, sizeof(esi_t));
} else {
state = stream_getl(s);
+ memset(&esi, 0, sizeof(esi_t));
}
bgp = bgp_lookup_by_vrf_id(vrf_id);
@@ -2910,6 +3004,7 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance)
zclient->ipset_notify_owner = ipset_notify_owner;
zclient->ipset_entry_notify_owner = ipset_entry_notify_owner;
zclient->iptable_notify_owner = iptable_notify_owner;
+ zclient->route_notify_owner = bgp_zebra_route_notify_owner;
zclient->instance = instance;
}
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index df453dd993..b773c16b57 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -109,6 +109,9 @@ struct community_list_handler *bgp_clist;
unsigned int multipath_num = MULTIPATH_NUM;
+/* Number of bgp instances configured for suppress fib config */
+unsigned int bgp_suppress_fib_count;
+
static void bgp_if_finish(struct bgp *bgp);
static void peer_drop_dynamic_neighbor(struct peer *peer);
@@ -390,6 +393,43 @@ void bgp_router_id_static_set(struct bgp *bgp, struct in_addr id)
true /* is config */);
}
+/* Set the suppress fib pending for the bgp configuration */
+void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set)
+{
+ bool send_msg = false;
+
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
+ return;
+
+ if (set) {
+ SET_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING);
+ /* Send msg to zebra for the first instance of bgp enabled
+ * with suppress fib
+ */
+ if (bgp_suppress_fib_count == 0)
+ send_msg = true;
+ bgp_suppress_fib_count++;
+ } else {
+ UNSET_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING);
+ bgp_suppress_fib_count--;
+
+ /* Send msg to zebra if there are no instances enabled
+ * with suppress fib
+ */
+ if (bgp_suppress_fib_count == 0)
+ send_msg = true;
+ }
+ /* Send route notify request to RIB */
+ if (send_msg) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Sending ZEBRA_ROUTE_NOTIFY_REQUEST");
+
+ if (zclient)
+ zebra_route_notify_send(ZEBRA_ROUTE_NOTIFY_REQUEST,
+ zclient, set);
+ }
+}
+
/* BGP's cluster-id control. */
int bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id)
{
@@ -1054,6 +1094,15 @@ static void peer_free(struct peer *peer)
bgp_delete_connected_nexthop(family2afi(peer->su.sa.sa_family),
peer);
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (peer->filter[afi][safi].advmap.aname)
+ XFREE(MTYPE_BGP_FILTER_NAME,
+ peer->filter[afi][safi].advmap.aname);
+ if (peer->filter[afi][safi].advmap.cname)
+ XFREE(MTYPE_BGP_FILTER_NAME,
+ peer->filter[afi][safi].advmap.cname);
+ }
+
XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
XFREE(MTYPE_PEER_DESC, peer->desc);
@@ -1081,12 +1130,8 @@ static void peer_free(struct peer *peer)
bfd_info_free(&(peer->bfd_info));
- for (afi = AFI_IP; afi < AFI_MAX; afi++) {
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- bgp_addpath_set_peer_type(peer, afi, safi,
- BGP_ADDPATH_NONE);
- }
- }
+ FOREACH_AFI_SAFI (afi, safi)
+ bgp_addpath_set_peer_type(peer, afi, safi, BGP_ADDPATH_NONE);
bgp_unlock(peer->bgp);
@@ -3382,6 +3427,14 @@ int bgp_delete(struct bgp *bgp)
assert(bgp);
+ /* make sure we withdraw any exported routes */
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp_get_default(),
+ bgp);
+ vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6, bgp_get_default(),
+ bgp);
+
+ bgp_vpn_leak_unimport(bgp);
+
hook_call(bgp_inst_delete, bgp);
THREAD_OFF(bgp->t_startup);
@@ -4505,6 +4558,10 @@ int peer_ebgp_multihop_set(struct peer *peer, int ttl)
if (peer->sort == BGP_PEER_IBGP || peer->conf_if)
return 0;
+ /* is there anything to do? */
+ if (peer->ttl == ttl)
+ return 0;
+
/* see comment in peer_ttl_security_hops_set() */
if (ttl != MAXTTL) {
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 287aeca143..d22fd008d8 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -104,10 +104,6 @@ enum bgp_af_index {
#define AF_FOREACH(af) for ((af) = BGP_AF_START; (af) < BGP_AF_MAX; (af)++)
-#define FOREACH_AFI_SAFI(afi, safi) \
- for (afi = AFI_IP; afi < AFI_MAX; afi++) \
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
-
#define FOREACH_SAFI(safi) \
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
@@ -455,11 +451,12 @@ struct bgp {
#define BGP_FLAG_DELETE_IN_PROGRESS (1 << 22)
#define BGP_FLAG_SELECT_DEFER_DISABLE (1 << 23)
#define BGP_FLAG_GR_DISABLE_EOR (1 << 24)
-#define BGP_FLAG_EBGP_REQUIRES_POLICY (1 << 25)
-#define BGP_FLAG_SHOW_NEXTHOP_HOSTNAME (1 << 26)
+#define BGP_FLAG_EBGP_REQUIRES_POLICY (1 << 25)
+#define BGP_FLAG_SHOW_NEXTHOP_HOSTNAME (1 << 26)
/* This flag is set if the instance is in administrative shutdown */
-#define BGP_FLAG_SHUTDOWN (1 << 27)
+#define BGP_FLAG_SHUTDOWN (1 << 27)
+#define BGP_FLAG_SUPPRESS_FIB_PENDING (1 << 28)
enum global_mode GLOBAL_GR_FSM[BGP_GLOBAL_GR_MODE]
[BGP_GLOBAL_GR_EVENT_CMD];
@@ -712,6 +709,9 @@ struct afi_safi_info {
#define BGP_SELECT_DEFER_DISABLE(bgp) \
(CHECK_FLAG(bgp->flags, BGP_FLAG_SELECT_DEFER_DISABLE))
+#define BGP_SUPPRESS_FIB_ENABLED(bgp) \
+ (CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING))
+
/* BGP peer-group support. */
struct peer_group {
/* Name of the peer-group. */
@@ -1283,6 +1283,8 @@ struct peer {
#define PEER_THREAD_WRITES_ON (1U << 0)
#define PEER_THREAD_READS_ON (1U << 1)
#define PEER_THREAD_KEEPALIVES_ON (1U << 2)
+#define PEER_THREAD_SUBGRP_ADV_DELAY (1U << 3)
+
/* workqueues */
struct work_queue *clear_node_queue;
@@ -1507,6 +1509,9 @@ DECLARE_QOBJ_TYPE(peer)
|| CHECK_FLAG((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW) \
|| CHECK_FLAG((P)->bgp->flags, BGP_FLAG_SHUTDOWN))
+#define PEER_ROUTE_ADV_DELAY(peer) \
+ (CHECK_FLAG(peer->thread_flags, PEER_THREAD_SUBGRP_ADV_DELAY))
+
#define PEER_PASSWORD_MINLEN (1)
#define PEER_PASSWORD_MAXLEN (80)
@@ -1677,6 +1682,7 @@ struct bgp_nlri {
#define BGP_DEFAULT_STALEPATH_TIME 360
#define BGP_DEFAULT_SELECT_DEFERRAL_TIME 360
#define BGP_DEFAULT_RIB_STALE_TIME 500
+#define BGP_DEFAULT_UPDATE_ADVERTISEMENT_TIME 1
/* BGP uptime string length. */
#define BGP_UPTIME_LEN 25
@@ -1853,6 +1859,7 @@ extern int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf,
extern void bgp_router_id_zebra_bump(vrf_id_t, const struct prefix *);
extern void bgp_router_id_static_set(struct bgp *, struct in_addr);
+extern void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set);
extern int bgp_cluster_id_set(struct bgp *, struct in_addr *);
extern int bgp_cluster_id_unset(struct bgp *);
diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c
index 2d81a6ce65..f7bbd44512 100644
--- a/bgpd/rfapi/rfapi.c
+++ b/bgpd/rfapi/rfapi.c
@@ -744,7 +744,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
encaptlv->length = 4;
lt = htonl(*lifetime);
memcpy(encaptlv->value, &lt, 4);
- attr.vnc_subtlvs = encaptlv;
+ bgp_attr_set_vnc_subtlvs(&attr, encaptlv);
vnc_zlog_debug_verbose(
"%s: set Encap Attr Prefix Lifetime to %d", __func__,
*lifetime);
@@ -754,7 +754,8 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
if (rfp_options) {
if (flags & RFAPI_AHR_RFPOPT_IS_VNCTLV) {
-
+ struct bgp_attr_encap_subtlv *vnc_subtlvs =
+ bgp_attr_get_vnc_subtlvs(&attr);
/*
* this flag means we're passing a pointer to an
* existing encap tlv chain which we should copy.
@@ -763,16 +764,15 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
*/
encaptlv = encap_tlv_dup(
(struct bgp_attr_encap_subtlv *)rfp_options);
- if (attr.vnc_subtlvs) {
- attr.vnc_subtlvs->next = encaptlv;
- } else {
- attr.vnc_subtlvs = encaptlv;
- }
-
+ if (vnc_subtlvs)
+ vnc_subtlvs->next = encaptlv;
+ else
+ bgp_attr_set_vnc_subtlvs(&attr, encaptlv);
} else {
struct bgp_tea_options *hop;
/* XXX max of one tlv present so far from above code */
- struct bgp_attr_encap_subtlv *tail = attr.vnc_subtlvs;
+ struct bgp_attr_encap_subtlv *tail =
+ bgp_attr_get_vnc_subtlvs(&attr);
for (hop = rfp_options; hop; hop = hop->next) {
@@ -798,11 +798,11 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
/*
* add to end of subtlv chain
*/
- if (tail) {
+ if (tail)
tail->next = encaptlv;
- } else {
- attr.vnc_subtlvs = encaptlv;
- }
+ else
+ bgp_attr_set_vnc_subtlvs(&attr,
+ encaptlv);
tail = encaptlv;
}
}
@@ -3688,20 +3688,16 @@ static void rfapi_print_exported(struct bgp *bgp)
if (!table)
continue;
fprintf(stderr, "%s: encap destn=%p\n", __func__, destn);
- for (dest = bgp_table_top(table))
- ;
- dest;
- dest = bgp_route_next(dest))
- {
- bpi = bgp_dest_get_bgp_path_info(dest);
- if (!bpi)
- continue;
- fprintf(stderr, "%s: dest=%p\n", __func__, dest);
- for (; bpi; bpi = bpi->next) {
- rfapiPrintBi((void *)2,
- bpi); /* 2 => stderr */
- }
- }
+ for (dest = bgp_table_top(table); dest;
+ dest = bgp_route_next(dest)) {
+ bpi = bgp_dest_get_bgp_path_info(dest);
+ if (!bpi)
+ continue;
+ fprintf(stderr, "%s: dest=%p\n", __func__, dest);
+ for (; bpi; bpi = bpi->next) {
+ rfapiPrintBi((void *)2, bpi); /* 2 => stderr */
+ }
+ }
}
}
#endif /* defined(DEBUG_RFAPI) */
diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c
index e3581addee..3d87b63542 100644
--- a/bgpd/rfapi/rfapi_import.c
+++ b/bgpd/rfapi/rfapi_import.c
@@ -298,10 +298,9 @@ static wq_item_status rfapi_deferred_close_workfunc(struct work_queue *q,
int rfapiGetL2o(struct attr *attr, struct rfapi_l2address_option *l2o)
{
if (attr) {
-
struct bgp_attr_encap_subtlv *pEncap;
- for (pEncap = attr->vnc_subtlvs; pEncap;
+ for (pEncap = bgp_attr_get_vnc_subtlvs(attr); pEncap;
pEncap = pEncap->next) {
if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) {
@@ -358,7 +357,7 @@ int rfapiGetVncLifetime(struct attr *attr, uint32_t *lifetime)
if (attr) {
- for (pEncap = attr->vnc_subtlvs; pEncap;
+ for (pEncap = bgp_attr_get_vnc_subtlvs(attr); pEncap;
pEncap = pEncap->next) {
if (pEncap->type
@@ -1337,7 +1336,8 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix,
return NULL;
}
- for (pEncap = bpi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) {
+ for (pEncap = bgp_attr_get_vnc_subtlvs(bpi->attr); pEncap;
+ pEncap = pEncap->next) {
switch (pEncap->type) {
case BGP_VNC_SUBTLV_TYPE_LIFETIME:
/* use configured lifetime, not attr lifetime */
diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c
index 630a379ec2..d1f335f549 100644
--- a/bgpd/rfapi/rfapi_rib.c
+++ b/bgpd/rfapi/rfapi_rib.c
@@ -622,7 +622,8 @@ static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri,
ri->lifetime = lifetime;
/* This loop based on rfapiRouteInfo2NextHopEntry() */
- for (pEncap = bpi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) {
+ for (pEncap = bgp_attr_get_vnc_subtlvs(bpi->attr); pEncap;
+ pEncap = pEncap->next) {
struct bgp_tea_options *hop;
switch (pEncap->type) {
diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c
index b9a6c4ddc4..40d5111e8c 100644
--- a/bgpd/rfapi/rfapi_vty.c
+++ b/bgpd/rfapi/rfapi_vty.c
@@ -456,7 +456,8 @@ void rfapiPrintAttrPtrs(void *stream, struct attr *attr)
struct vty *vty;
void *out;
const char *vty_newline;
-
+ struct transit *transit;
+ struct cluster_list *cluster;
char buf[BUFSIZ];
if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0)
@@ -477,10 +478,14 @@ void rfapiPrintAttrPtrs(void *stream, struct attr *attr)
fp(out, " ecommunity=%p, refcnt=%d%s", attr->ecommunity,
(attr->ecommunity ? attr->ecommunity->refcnt : 0), HVTYNL);
- fp(out, " cluster=%p, refcnt=%d%s", attr->cluster,
- (attr->cluster ? attr->cluster->refcnt : 0), HVTYNL);
- fp(out, " transit=%p, refcnt=%d%s", attr->transit,
- (attr->transit ? attr->transit->refcnt : 0), HVTYNL);
+
+ cluster = bgp_attr_get_cluster(attr);
+ fp(out, " cluster=%p, refcnt=%d%s", cluster,
+ (cluster ? cluster->refcnt : 0), HVTYNL);
+
+ transit = bgp_attr_get_transit(attr);
+ fp(out, " transit=%p, refcnt=%d%s", transit,
+ (transit ? transit->refcnt : 0), HVTYNL);
}
/*
@@ -591,7 +596,8 @@ void rfapiPrintBi(void *stream, struct bgp_path_info *bpi)
}
/* RFP option lengths */
- for (pEncap = bpi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) {
+ for (pEncap = bgp_attr_get_vnc_subtlvs(bpi->attr); pEncap;
+ pEncap = pEncap->next) {
if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) {
if (printed_1st_gol) {
diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c
index 11f39b2b82..762cd2596f 100644
--- a/bgpd/rfapi/vnc_export_bgp.c
+++ b/bgpd/rfapi/vnc_export_bgp.c
@@ -290,7 +290,7 @@ void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn,
info.peer = peer;
info.attr = &hattr;
ret = route_map_apply(bgp->rfapi_cfg->routemap_export_bgp,
- prefix, RMAP_BGP, &info);
+ prefix, &info);
if (ret == RMAP_DENYMATCH) {
bgp_attr_flush(&hattr);
return;
@@ -1033,7 +1033,7 @@ void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd)
ret = route_map_apply(
rfgn->rfg
->routemap_export_bgp,
- p, RMAP_BGP, &info);
+ p, &info);
if (ret == RMAP_DENYMATCH) {
bgp_attr_flush(&hattr);
continue;
@@ -1242,8 +1242,7 @@ static void vnc_direct_add_rn_group_rd(struct bgp *bgp,
info.peer = irfd->peer;
info.attr = &hattr;
- ret = route_map_apply(rfg->routemap_export_bgp, p, RMAP_BGP,
- &info);
+ ret = route_map_apply(rfg->routemap_export_bgp, p, &info);
if (ret == RMAP_DENYMATCH) {
bgp_attr_flush(&hattr);
vnc_zlog_debug_verbose(
@@ -1691,8 +1690,7 @@ void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi,
memset(&info, 0, sizeof(info));
info.peer = peer;
info.attr = &hattr;
- ret = route_map_apply(hc->routemap_export_bgp, prefix, RMAP_BGP,
- &info);
+ ret = route_map_apply(hc->routemap_export_bgp, prefix, &info);
if (ret == RMAP_DENYMATCH) {
bgp_attr_flush(&hattr);
return;
@@ -1917,8 +1915,7 @@ void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi)
info.attr = &hattr;
ret = route_map_apply(
hc->routemap_export_bgp,
- dest_p, RMAP_BGP,
- &info);
+ dest_p, &info);
if (ret == RMAP_DENYMATCH) {
bgp_attr_flush(&hattr);
vnc_zlog_debug_verbose(
diff --git a/bgpd/rfapi/vnc_import_bgp.c b/bgpd/rfapi/vnc_import_bgp.c
index 0b6b39b966..b23c1eda76 100644
--- a/bgpd/rfapi/vnc_import_bgp.c
+++ b/bgpd/rfapi/vnc_import_bgp.c
@@ -357,7 +357,7 @@ static int process_unicast_route(struct bgp *bgp, /* in */
memset(&info, 0, sizeof(info));
info.peer = peer;
info.attr = &hattr;
- ret = route_map_apply(rmap, prefix, RMAP_BGP, &info);
+ ret = route_map_apply(rmap, prefix, &info);
if (ret == RMAP_DENYMATCH) {
bgp_attr_flush(&hattr);
vnc_zlog_debug_verbose(
@@ -468,7 +468,7 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
plifetime = &lifetime;
}
- encaptlvs = bpi->attr->vnc_subtlvs;
+ encaptlvs = bgp_attr_get_vnc_subtlvs(bpi->attr);
if (bpi->attr->encap_tunneltype != BGP_ENCAP_TYPE_RESERVED
&& bpi->attr->encap_tunneltype != BGP_ENCAP_TYPE_MPLS) {
opt = &optary[cur_opt++];
@@ -784,7 +784,7 @@ static void vnc_import_bgp_add_route_mode_plain(struct bgp *bgp,
memset(&info, 0, sizeof(info));
info.peer = peer;
info.attr = &hattr;
- ret = route_map_apply(rmap, prefix, RMAP_BGP, &info);
+ ret = route_map_apply(rmap, prefix, &info);
if (ret == RMAP_DENYMATCH) {
bgp_attr_flush(&hattr);
vnc_zlog_debug_verbose(
@@ -977,7 +977,7 @@ static void vnc_import_bgp_add_route_mode_nvegroup(
memset(&path, 0, sizeof(path));
path.peer = peer;
path.attr = &hattr;
- ret = route_map_apply(rmap, prefix, RMAP_BGP, &path);
+ ret = route_map_apply(rmap, prefix, &path);
if (ret == RMAP_DENYMATCH) {
bgp_attr_flush(&hattr);
vnc_zlog_debug_verbose(
diff --git a/doc/developer/building-frr-for-openwrt.rst b/doc/developer/building-frr-for-openwrt.rst
index 9bd1296dad..47cf2cbd43 100644
--- a/doc/developer/building-frr-for-openwrt.rst
+++ b/doc/developer/building-frr-for-openwrt.rst
@@ -51,7 +51,7 @@ to work and it may be needed to run a ``make`` for the entire build
environment. Add ``V=s`` to get more debugging output.
More information about OpenWrt buildsystem can be found `here
-<https://openwrt.org/docs/guide-developer/build-system/use-buildsystem>`_.
+<https://openwrt.org/docs/guide-developer/build-system/use-buildsystem>`__.
Work with sources
-----------------
@@ -59,7 +59,7 @@ Work with sources
To update to a newer version, or change other options, you need to edit the ``feeds/packages/frr/Makefile``.
More information about working with patches in OpenWrt buildsystem can be found `here
-<https://openwrt.org/docs/guide-developer/build-system/use-patches-with-buildsystem>`_.
+<https://openwrt.org/docs/guide-developer/build-system/use-patches-with-buildsystem>`__.
Usage
-----
diff --git a/doc/developer/fuzzing.rst b/doc/developer/fuzzing.rst
new file mode 100644
index 0000000000..8a3318745e
--- /dev/null
+++ b/doc/developer/fuzzing.rst
@@ -0,0 +1,164 @@
+.. _fuzzing:
+
+Fuzzing
+=======
+
+This page describes the fuzzing targets and supported fuzzers available in FRR
+and how to use them. Familiarity with fuzzing techniques and tools is assumed.
+
+Overview
+--------
+
+It is well known that networked applications tend to be difficult to fuzz on
+their network-facing attack surfaces. Approaches involving actual network
+transmission tend to be slow and are subject to intermediate devices and
+networking stacks which tend to drop fuzzed packets, especially if the fuzzing
+surface covers IP itself. Some time was spent on fuzzing FRR this way with some
+mediocre results but attention quickly turned towards skipping the actual
+networking and instead adding fuzzing targets directly in the packet processing
+code for use by more traditional in- and out-of-process fuzzers. Results from
+this approach have been very fruitful.
+
+The patches to add fuzzing targets are kept in a separate git branch. Typically
+it is better to keep them in the main branch so they are kept up to date and do
+not need to be constantly synchronized with the main codebase. Unfortunately,
+changes to FRR to support fuzzing necessarily extend far beyond the
+entrypoints. Checksums must be disarmed, interactions with the kernel must be
+skipped, sockets and files must be avoided, desired under/overflows must be
+marked, etc. There are the usual ``LD_PRELOAD`` libraries to emulate these
+things (preeny et al) but FRR is a very kernel-reliant program and these
+libraries tend to create annoying problems when used with FRR for whatever
+reason. Keeping this code in the main codebase is cluttering, difficult to work
+with / around, and runs the risk of accidentally introducing bugs even if
+``#ifdef``'d out. Consequently it's in a separate branch that is rebased on
+``master`` from time to time.
+
+
+Code
+----
+
+The git branch with fuzzing targets is located here:
+
+https://github.com/FRRouting/frr/tree/fuzz
+
+To build libFuzzer targets, pass ``--enable-libfuzzer`` to ``configure``.
+To build AFL targets, compile with ``afl-clang`` as usual.
+
+Fuzzing with sanitizers is strongly recommended, especially ASAN, which you can
+enable by passing ``--enable-address-sanitizer`` to ``configure``.
+
+Suggested UBSAN flags: ``-fsanitize-recover=unsigned-integer-overflow,implicit-conversion -fsanitize=unsigned-integer-overflow,implicit-conversion,nullability-arg,nullability-assign,nullability-return``
+Recommended cflags: ``-Wno-all -g3 -O3 -funroll-loops``
+
+Design
+------
+
+All fuzzing targets have support for libFuzzer and AFL. This is done by writing
+the target as a libFuzzer entrypoint (``LLVMFuzzerTestOneInput()``) and calling
+it from the AFL entrypoint in ``main()``. New targets should use this rule.
+
+When adding AFL entrypoints, it's a good idea to use AFL persistent mode for
+better performance. Grep ``bgpd/bgp_main.c`` for ``__AFL_INIT()`` for an
+example of how to do this in FRR. Typically it involves moving all internal
+daemon setup into a setup function. Then this setup function is called exactly
+once for the lifetime of the process. In ``LLVMFuzzerTestOneInput()`` this
+means you need to call it at the start of the function protected by a static
+boolean that is set to true, since that function is your entrypoint. You also
+need to call it prior to ``__AFL_INIT()`` in ``main()`` because ``main()`` is
+your entrypoint in the AFL case.
+
+Adding support to daemons
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This section describes how to add entrypoints to daemons that do not have any
+yet.
+
+Because libFuzzer has its own ``main()`` function, when adding fuzzing support
+to a daemon that doesn't have any targets already, ``main()`` needs to be
+``#ifdef``'d out like so:
+
+.. code:: c
+
+ #ifndef FUZZING_LIBFUZZER
+
+ int main(int argc, char **argv)
+ {
+ ...
+ }
+
+ #endif /* FUZZING_LIBFUZZER */
+
+
+The ``FUZZING_LIBFUZZER`` macro is set by ``--enable-libfuzzer``.
+
+Because libFuzzer can only be linked into daemons that have
+``LLVMFuzzerTestOneInput()`` implemented, we can't pass ``-fsanitize=fuzzer``
+to all daemons in ``AM_CFLAGS``. It needs to go into a variable specific to
+each daemon. Since it can be thought of as a kind of sanitizer, for daemons
+that have libFuzzer support there are now individual flags variables for those
+daemons named ``DAEMON_SAN_FLAGS`` (e.g. ``BGPD_SAN_FLAGS``,
+``ZEBRA_SAN_FLAGS``). This variable has the contents of the generic
+``SAN_FLAGS`` plus any fuzzing-related flags. It is used in daemons'
+``subdir.am`` in place of ``SAN_FLAGS``. Daemons that don't support libFuzzer
+still use ``SAN_FLAGS``. If you want to add fuzzing support to a daemon you
+need to do this flag variable conversion; look at ``configure.ac`` for
+examples, it is fairly straightforward. Remember to update ``subdir.am`` to use
+the new variable.
+
+Do note that when fuzzing is enabled, ``SAN_FLAGS`` gains
+``-fsanitize=fuzzer-no-link``; the result is that all daemons are instrumented
+for fuzzing but only the ones with ``LLVMFuzzerTestOneInput()`` actually get
+linked with libFuzzer.
+
+
+Targets
+-------
+
+A given daemon can have lots of different paths that are interesting to fuzz.
+There's not really a great way to handle this, most fuzzers assume the program
+has one entrypoint. The approach taken in FRR for multiple entrypoints is to
+control which path is taken within ``LLVMFuzzerTestOneInput()`` using
+``#ifdef`` and passing whatever controlling macro definition you want. Take a
+look at that function for the daemon you're interested in fuzzing, pick the
+target, add ``#define MY_TARGET 1`` somewhere before the ``#ifdef`` switch,
+recompile.
+
+.. list-table:: Fuzzing Targets
+
+ * - Daemon
+ - Target
+ - Fuzzers
+ * - bgpd
+ - packet parser
+ - libfuzzer, afl
+ * - ospfd
+ - packet parser
+ - libfuzzer, afl
+ * - pimd
+ - packet parser
+ - libfuzzer, afl
+ * - vrrpd
+ - packet parser
+ - libfuzzer, afl
+ * - vrrpd
+ - zapi parser
+ - libfuzzer, afl
+ * - zebra
+ - netlink
+ - libfuzzer, afl
+ * - zebra
+ - zserv / zapi
+ - libfuzzer, afl
+
+
+Fuzzer Notes
+------------
+
+Some interesting seed corpuses for various daemons are available `here
+<https://github.com/qlyoung/frr-fuzz/tree/master/samples>`_.
+
+For libFuzzer, you need to pass ``-rss_limit_mb=0`` if you are fuzzing with
+ASAN enabled, as you should.
+
+For AFL, afl++ is strongly recommended; afl proper isn't really maintained
+anymore.
diff --git a/doc/developer/index.rst b/doc/developer/index.rst
index 1ba0f31c8a..5a7da806ff 100644
--- a/doc/developer/index.rst
+++ b/doc/developer/index.rst
@@ -9,6 +9,7 @@ FRRouting Developer's Guide
packaging
process-architecture
library
+ fuzzing
tracing
testing
bgpd
diff --git a/doc/user/basic.rst b/doc/user/basic.rst
index 0bdcccaf74..7a450bec53 100644
--- a/doc/user/basic.rst
+++ b/doc/user/basic.rst
@@ -26,7 +26,7 @@ forms the initial command set for a routing beast as it is starting.
Config files are generally found in |INSTALL_PREFIX_ETC|.
Config Methods
-^^^^^^^^^^^^^^
+--------------
There are two ways of configuring FRR.
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 3572734ba9..0a562e1edf 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -962,6 +962,56 @@ Networks
traditional did not check for existence. For versions 7.4 and beyond
both traditional and datacenter the network must exist.
+.. _bgp-ipv6-support:
+
+IPv6 Support
+------------
+
+.. index:: [no] neighbor A.B.C.D activate
+.. clicmd:: [no] neighbor A.B.C.D activate
+
+ This configuration modifies whether to enable an address family for a
+ specific neighbor. By default only the IPv4 unicast address family is
+ enabled.
+
+ .. code-block:: frr
+
+ router bgp 1
+ address-family ipv6 unicast
+ neighbor 2001:0DB8::1 activate
+ network 2001:0DB8:5009::/64
+ exit-address-family
+
+ This configuration example says that network 2001:0DB8:5009::/64 will be
+ announced and enables the neighbor 2001:0DB8::1 to receive this announcement.
+
+.. index:: [no] bgp default ipv4-unicast
+.. clicmd:: [no] bgp default ipv4-unicast
+
+ By default, only the IPv4 unicast address family is announced to all
+ neighbors. Using the 'no bgp default ipv4-unicast' configuration overrides
+ this default so that all address families need to be enabled explicitly.
+
+ .. code-block:: frr
+
+ router bgp 1
+ no bgp default ipv4-unicast
+ neighbor 10.10.10.1 remote-as 2
+ neighbor 2001:0DB8::1 remote-as 3
+ address-family ipv4 unicast
+ neighbor 10.10.10.1 activate
+ network 192.168.1.0/24
+ exit-address-family
+ address-family ipv6 unicast
+ neighbor 2001:0DB8::1 activate
+ network 2001:0DB8:5009::/64
+ exit-address-family
+
+ This configuration demonstrates how the 'no bgp default ipv4-unicast' might
+ be used in a setup with two upstreams where each of the upstreams should only
+ receive either IPv4 or IPv6 annocuments.
+
+
.. _bgp-route-aggregation:
Route Aggregation
@@ -1303,10 +1353,10 @@ Configuring Peers
Optionally you can specify a shutdown message `MSG`.
- Also, you can specify optionally _rtt_ in milliseconds to automatically
+ Also, you can specify optionally ``rtt`` in milliseconds to automatically
shutdown the peer if round-trip-time becomes higher than defined.
- Additional _count_ parameter is the number of keepalive messages to count
+ Additional ``count`` parameter is the number of keepalive messages to count
before shutdown the peer if round-trip-time becomes higher than defined.
.. index:: [no] neighbor PEER disable-connected-check
@@ -1420,7 +1470,7 @@ Configuring Peers
granular and offers much smarter matching criterion than number of received
prefixes, making it more suited to implementing policy.
- If _force_ is set, then ALL prefixes are counted for maximum instead of
+ If ``force`` is set, then ALL prefixes are counted for maximum instead of
accepted only. This is useful for cases where an inbound filter is applied,
but you want maximum-prefix to act on ALL (including filtered) prefixes. This
option requires `soft-reconfiguration inbound` to be enabled for the peer.
@@ -3122,16 +3172,16 @@ displays IPv6 routing table.
Total number of prefixes 1
- If _wide_ option is specified, then the prefix table's width is increased
+ If ``wide`` option is specified, then the prefix table's width is increased
to fully display the prefix and the nexthop.
This is especially handy dealing with IPv6 prefixes and
if :clicmd:`[no] bgp default show-nexthop-hostname` is enabled.
- If _all_ option is specified, _ip_ keyword is ignored, show bgp all and
+ If ``all`` option is specified, ``ip`` keyword is ignored, show bgp all and
show ip bgp all commands display routes for all AFIs and SAFIs.
- If _json_ option is specified, output is displayed in JSON format.
+ If ``json`` option is specified, output is displayed in JSON format.
Some other commands provide additional options for filtering the output.
@@ -3225,18 +3275,18 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`.
from neighbor or filtered routes received from neighbor based on the
option specified.
- If _wide_ option is specified, then the prefix table's width is increased
+ If ``wide`` option is specified, then the prefix table's width is increased
to fully display the prefix and the nexthop.
This is especially handy dealing with IPv6 prefixes and
if :clicmd:`[no] bgp default show-nexthop-hostname` is enabled.
- If _all_ option is specified, _ip_ keyword is ignored and,
+ If ``all`` option is specified, ``ip`` keyword is ignored and,
routes displayed for all AFIs and SAFIs.
- if afi is specified, with _all_ option, routes will be displayed for
+ if afi is specified, with ``all`` option, routes will be displayed for
each SAFI in the selcted AFI
- If _json_ option is specified, output is displayed in JSON format.
+ If ``json`` option is specified, output is displayed in JSON format.
.. _bgp-display-routes-by-community:
@@ -3270,18 +3320,18 @@ attribute.
match the specified community list. When `exact-match` is specified, it
displays only routes that have an exact match.
- If _wide_ option is specified, then the prefix table's width is increased
+ If ``wide`` option is specified, then the prefix table's width is increased
to fully display the prefix and the nexthop.
This is especially handy dealing with IPv6 prefixes and
if :clicmd:`[no] bgp default show-nexthop-hostname` is enabled.
- If _all_ option is specified, _ip_ keyword is ignored and,
+ If ``all`` option is specified, ``ip`` keyword is ignored and,
routes displayed for all AFIs and SAFIs.
- if afi is specified, with _all_ option, routes will be displayed for
+ if afi is specified, with ``all`` option, routes will be displayed for
each SAFI in the selcted AFI
- If _json_ option is specified, output is displayed in JSON format.
+ If ``json`` option is specified, output is displayed in JSON format.
.. _bgp-display-routes-by-lcommunity:
@@ -3412,6 +3462,49 @@ starting the daemon and the configuration gets saved, the option will persist
unless removed from the configuration with the negating command prior to the
configuration write operation.
+.. _bgp-suppress-fib:
+
+Suppressing routes not installed in FIB
+=======================================
+
+The FRR implementation of BGP advertises prefixes learnt from a peer to other
+peers even if the routes do not get installed in the FIB. There can be
+scenarios where the hardware tables in some of the routers (along the path from
+the source to destination) is full which will result in all routes not getting
+installed in the FIB. If these routes are advertised to the downstream routers
+then traffic will start flowing and will be dropped at the intermediate router.
+
+The solution is to provide a configurable option to check for the FIB install
+status of the prefixes and advertise to peers if the prefixes are successfully
+installed in the FIB. The advertisement of the prefixes are suppressed if it is
+not installed in FIB.
+
+The following conditions apply will apply when checking for route installation
+status in FIB:
+
+1. The advertisement or suppression of routes based on FIB install status
+ applies only for newly learnt routes from peer (routes which are not in
+ BGP local RIB).
+2. If the route received from peer already exists in BGP local RIB and route
+ attributes have changed (best path changed), the old path is deleted and
+ new path is installed in FIB. The FIB install status will not have any
+ effect. Therefore only when the route is received first time the checks
+ apply.
+3. The feature will not apply for routes learnt through other means like
+ redistribution to bgp from other protocols. This is applicable only to
+ peer learnt routes.
+4. If a route is installed in FIB and then gets deleted from the dataplane,
+ then routes will not be withdrawn from peers. This will be considered as
+ dataplane issue.
+5. The feature will slightly increase the time required to advertise the routes
+ to peers since the route install status needs to be received from the FIB
+6. If routes are received by the peer before the configuration is applied, then
+ the bgp sessions need to be reset for the configuration to take effect.
+7. If the route which is already installed in dataplane is removed for some
+ reason, sending withdraw message to peers is not currently supported.
+
+.. index:: [no] bgp suppress-fib-pending
+.. clicmd:: [no] bgp suppress-fib-pending
.. _routing-policy:
diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst
index 6295ba9293..dd53d8f8b4 100644
--- a/doc/user/ospf6d.rst
+++ b/doc/user/ospf6d.rst
@@ -179,10 +179,11 @@ Showing OSPF6 information
To see OSPF interface configuration like costs.
-.. index:: show ipv6 ospf6 neighbor
-.. clicmd:: show ipv6 ospf6 neighbor
+.. index:: show ipv6 ospf6 neighbor [json]
+.. clicmd:: show ipv6 ospf6 neighbor [json]
- Shows state and chosen (Backup) DR of neighbor.
+ Shows state and chosen (Backup) DR of neighbor. JSON output can be
+ obtained by appending 'json' at the end.
.. index:: show ipv6 ospf6 request-list A.B.C.D
.. clicmd:: show ipv6 ospf6 request-list A.B.C.D
diff --git a/doc/user/vrrp.rst b/doc/user/vrrp.rst
index 8ab050e9a0..cb70da3f3b 100644
--- a/doc/user/vrrp.rst
+++ b/doc/user/vrrp.rst
@@ -503,6 +503,7 @@ The following configuration is then generated for you:
vrrp 5 ip 10.0.2.16
vrrp 5 ipv6 2001:db8::370:7334
+
VRRP is automatically activated. Global defaults, if set, are applied.
You can then edit this configuration with **vtysh** as needed, and commit it by
@@ -516,6 +517,7 @@ My virtual routers are not seeing each others' advertisements
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Check:
+
- Is your kernel at least 5.1?
- Did you set the macvlan devices to ``bridge`` mode?
- If using IPv4 virtual addresses, does the parent of the macvlan devices have
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index 624e3cfe1a..5c7f4ac773 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -72,6 +72,19 @@ Besides the common invocation options (:ref:`common-invocation-options`), the
option and we will use Route Replace Semantics instead of delete
than add.
+.. option:: --asic-offload [notify_on_offload|notify_on_ack]
+
+ The linux kernel has the ability to use asic-offload ( see switchdev
+ development ). When the operator knows that FRR will be working in
+ this way, allow them to specify this with FRR. At this point this
+ code only supports asynchronous notification of the offload state.
+ In other words the initial ACK received for linux kernel installation
+ does not give zebra any data about what the state of the offload
+ is. This option takes the optional paramegers notify_on_offload
+ or notify_on_ack. This signals to zebra to notify upper level
+ protocols about route installation/update on ack received from
+ the linux kernel or from offload notification.
+
.. _interface-commands:
Configuration Addresses behaviour
diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c
index 473cc75a2a..0795fbd6df 100644
--- a/eigrpd/eigrp_zebra.c
+++ b/eigrpd/eigrp_zebra.c
@@ -88,7 +88,8 @@ static int eigrp_zebra_route_notify_owner(ZAPI_CALLBACK_ARGS)
enum zapi_route_notify_owner note;
uint32_t table;
- if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, &note))
+ if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, &note, NULL,
+ NULL))
return -1;
return 0;
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 9b814c92de..74a0d795ab 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -319,6 +319,7 @@ enum rt_scope_t {
#define RTM_F_FIB_MATCH 0x2000 /* return full fib lookup match */
#define RTM_F_OFFLOAD 0x4000 /* route is offloaded */
#define RTM_F_TRAP 0x8000 /* route is trapping packets */
+#define RTM_F_OFFLOAD_FAILED 0x10000 /* route offload failed */
/* Reserved table identifiers */
diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c
index e6c7a734bd..240be27cf3 100644
--- a/isisd/isis_redist.c
+++ b/isisd/isis_redist.c
@@ -167,8 +167,7 @@ static void isis_redist_update_ext_reach(struct isis_area *area, int level,
area_info.metric = redist->metric;
if (redist->map_name) {
- map_ret =
- route_map_apply(redist->map, p, RMAP_ISIS, &area_info);
+ map_ret = route_map_apply(redist->map, p, &area_info);
if (map_ret == RMAP_DENYMATCH)
area_info.distance = 255;
}
@@ -380,6 +379,19 @@ static void isis_redist_update_zebra_subscriptions(struct isis *isis)
}
}
+void isis_redist_free(struct isis *isis)
+{
+ int i;
+
+ for (i = 0; i < REDIST_PROTOCOL_COUNT; i++) {
+ if (!isis->ext_info[i])
+ continue;
+
+ route_table_finish(isis->ext_info[i]);
+ isis->ext_info[i] = NULL;
+ }
+}
+
void isis_redist_set(struct isis_area *area, int level, int family, int type,
uint32_t metric, const char *routemap, int originate_type)
{
diff --git a/isisd/isis_redist.h b/isisd/isis_redist.h
index 0d2dc6a803..afce922240 100644
--- a/isisd/isis_redist.h
+++ b/isisd/isis_redist.h
@@ -62,4 +62,5 @@ void isis_redist_set(struct isis_area *area, int level, int family, int type,
uint32_t metric, const char *routemap, int originate_type);
void isis_redist_unset(struct isis_area *area, int level, int family, int type);
+void isis_redist_free(struct isis *isis);
#endif
diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c
index 902528e1bb..db0f2fd8be 100644
--- a/isisd/isis_routemap.c
+++ b/isisd/isis_routemap.c
@@ -49,14 +49,10 @@
#include "isis_routemap.h"
static enum route_map_cmd_result_t
-route_match_ip_address(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
{
struct access_list *alist;
- if (type != RMAP_ISIS)
- return RMAP_NOMATCH;
-
alist = access_list_lookup(AFI_IP, (char *)rule);
if (access_list_apply(alist, prefix) != FILTER_DENY)
return RMAP_MATCH;
@@ -85,13 +81,10 @@ static const struct route_map_rule_cmd route_match_ip_address_cmd = {
static enum route_map_cmd_result_t
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct prefix_list *plist;
- if (type != RMAP_ISIS)
- return RMAP_NOMATCH;
-
plist = prefix_list_lookup(AFI_IP, (char *)rule);
if (prefix_list_apply(plist, prefix) != PREFIX_DENY)
return RMAP_MATCH;
@@ -120,14 +113,10 @@ static const struct route_map_rule_cmd
/* ------------------------------------------------------------*/
static enum route_map_cmd_result_t
-route_match_ipv6_address(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
{
struct access_list *alist;
- if (type != RMAP_ISIS)
- return RMAP_NOMATCH;
-
alist = access_list_lookup(AFI_IP6, (char *)rule);
if (access_list_apply(alist, prefix) != FILTER_DENY)
return RMAP_MATCH;
@@ -156,13 +145,10 @@ static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
static enum route_map_cmd_result_t
route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct prefix_list *plist;
- if (type != RMAP_ISIS)
- return RMAP_NOMATCH;
-
plist = prefix_list_lookup(AFI_IP6, (char *)rule);
if (prefix_list_apply(plist, prefix) != PREFIX_DENY)
return RMAP_MATCH;
@@ -191,18 +177,16 @@ static const struct route_map_rule_cmd
/* ------------------------------------------------------------*/
static enum route_map_cmd_result_t
-route_set_metric(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_metric(void *rule, const struct prefix *prefix, void *object)
{
uint32_t *metric;
struct isis_ext_info *info;
- if (type == RMAP_ISIS) {
- metric = rule;
- info = object;
+ metric = rule;
+ info = object;
+
+ info->metric = *metric;
- info->metric = *metric;
- }
return RMAP_OKAY;
}
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 5480a1b339..19cacde4fe 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -1727,6 +1727,11 @@ static struct isis_spf_run *isis_run_spf_arg(struct isis_area *area, int level)
return run;
}
+void isis_spf_timer_free(void *run)
+{
+ XFREE(MTYPE_ISIS_SPF_RUN, run);
+}
+
int _isis_spf_schedule(struct isis_area *area, int level,
const char *func, const char *file, int line)
{
diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h
index a9a14fc75e..ad15d3e3c7 100644
--- a/isisd/isis_spf.h
+++ b/isisd/isis_spf.h
@@ -78,4 +78,5 @@ struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area,
uint8_t *sysid,
struct isis_spftree *spftree);
+void isis_spf_timer_free(void *run);
#endif /* _ZEBRA_ISIS_SPF_H */
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 057ede0e38..950cdc281f 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -442,7 +442,11 @@ void isis_area_destroy(struct isis_area *area)
spftree_area_del(area);
+ if (area->spf_timer[0])
+ isis_spf_timer_free(THREAD_ARG(area->spf_timer[0]));
thread_cancel(&area->spf_timer[0]);
+ if (area->spf_timer[1])
+ isis_spf_timer_free(THREAD_ARG(area->spf_timer[1]));
thread_cancel(&area->spf_timer[1]);
spf_backoff_free(area->spf_delay_ietf[0]);
@@ -583,6 +587,7 @@ void isis_finish(struct isis *isis)
isis_vrf_unlink(isis, vrf);
}
+ isis_redist_free(isis);
list_delete(&isis->area_list);
list_delete(&isis->init_circ_list);
XFREE(MTYPE_ISIS, isis);
@@ -2375,6 +2380,9 @@ static void area_resign_level(struct isis_area *area, int level)
}
}
+ if (area->spf_timer[level - 1])
+ isis_spf_timer_free(THREAD_ARG(area->spf_timer[level - 1]));
+
thread_cancel(&area->spf_timer[level - 1]);
sched_debug(
diff --git a/lib/command.c b/lib/command.c
index 7d335e1c36..87110157f6 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -154,7 +154,8 @@ static bool vty_check_node_for_xpath_decrement(enum node_type target_node,
|| node == BGP_IPV4M_NODE || node == BGP_IPV6M_NODE
|| node == BGP_VPNV4_NODE || node == BGP_VPNV6_NODE
|| node == BGP_EVPN_NODE || node == BGP_IPV4L_NODE
- || node == BGP_IPV6L_NODE ))
+ || node == BGP_IPV6L_NODE || node == BGP_FLOWSPECV4_NODE
+ || node == BGP_FLOWSPECV6_NODE))
return false;
return true;
diff --git a/lib/log.c b/lib/log.c
index b629658f75..7b37ba7f27 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -455,7 +455,8 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_NEIGH_DISCOVER),
DESC_ENTRY(ZEBRA_NHG_ADD),
DESC_ENTRY(ZEBRA_NHG_DEL),
- DESC_ENTRY(ZEBRA_NHG_NOTIFY_OWNER)};
+ DESC_ENTRY(ZEBRA_NHG_NOTIFY_OWNER),
+ DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_REQUEST)};
#undef DESC_ENTRY
static const struct zebra_desc_table unknown = {0, "unknown", '?'};
diff --git a/lib/routemap.c b/lib/routemap.c
index 0eb54a4794..004beb3628 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -1530,8 +1530,7 @@ enum rmap_compile_rets route_map_delete_set(struct route_map_index *index,
static enum route_map_cmd_result_t
route_map_apply_match(struct route_map_rule_list *match_list,
- const struct prefix *prefix, route_map_object_t type,
- void *object)
+ const struct prefix *prefix, void *object)
{
enum route_map_cmd_result_t ret = RMAP_NOMATCH;
struct route_map_rule *match;
@@ -1555,7 +1554,7 @@ route_map_apply_match(struct route_map_rule_list *match_list,
* If all result in NOOP, end-result is NOOP.
*/
ret = (*match->cmd->func_apply)(match->value, prefix,
- type, object);
+ object);
/*
* If the consolidated result of func_apply is:
@@ -1647,9 +1646,10 @@ static struct list *route_map_get_index_list(struct route_node **rn,
/*
* This function returns the route-map index that best matches the prefix.
*/
-static struct route_map_index *
-route_map_get_index(struct route_map *map, const struct prefix *prefix,
- route_map_object_t type, void *object, uint8_t *match_ret)
+static struct route_map_index *route_map_get_index(struct route_map *map,
+ const struct prefix *prefix,
+ void *object,
+ uint8_t *match_ret)
{
int ret = 0;
struct list *candidate_rmap_list = NULL;
@@ -1695,7 +1695,7 @@ route_map_get_index(struct route_map *map, const struct prefix *prefix,
break;
ret = route_map_apply_match(&index->match_list, prefix,
- type, object);
+ object);
if (ret == RMAP_MATCH) {
*match_ret = ret;
@@ -2369,8 +2369,7 @@ void route_map_notify_pentry_dependencies(const char *affected_name,
We need to make sure our route-map processing matches the above
*/
route_map_result_t route_map_apply(struct route_map *map,
- const struct prefix *prefix,
- route_map_object_t type, void *object)
+ const struct prefix *prefix, void *object)
{
static int recursion = 0;
enum route_map_cmd_result_t match_ret = RMAP_NOMATCH;
@@ -2397,7 +2396,7 @@ route_map_result_t route_map_apply(struct route_map *map,
if ((!map->optimization_disabled)
&& (map->ipv4_prefix_table || map->ipv6_prefix_table)) {
- index = route_map_get_index(map, prefix, type, object,
+ index = route_map_get_index(map, prefix, object,
(uint8_t *)&match_ret);
if (index) {
if (rmap_debug)
@@ -2431,7 +2430,7 @@ route_map_result_t route_map_apply(struct route_map *map,
index->applied++;
/* Apply this index. */
match_ret = route_map_apply_match(&index->match_list,
- prefix, type, object);
+ prefix, object);
if (rmap_debug) {
zlog_debug(
"Route-map: %s, sequence: %d, prefix: %pFX, result: %s",
@@ -2489,9 +2488,8 @@ route_map_result_t route_map_apply(struct route_map *map,
* set succeeded or not. So, ignore
* return code.
*/
- (void) (*set->cmd->func_apply)(
- set->value, prefix, type,
- object);
+ (void)(*set->cmd->func_apply)(
+ set->value, prefix, object);
/* Call another route-map if available */
if (index->nextrm) {
@@ -2504,8 +2502,7 @@ route_map_result_t route_map_apply(struct route_map *map,
{
recursion++;
ret = route_map_apply(
- nextrm, prefix, type,
- object);
+ nextrm, prefix, object);
recursion--;
}
diff --git a/lib/routemap.h b/lib/routemap.h
index 64da4b87ef..3e208c8cb5 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -68,17 +68,6 @@ enum route_map_cmd_result_t {
RMAP_ERROR
};
-
-typedef enum {
- RMAP_RIP,
- RMAP_RIPNG,
- RMAP_OSPF,
- RMAP_OSPF6,
- RMAP_BGP,
- RMAP_ZEBRA,
- RMAP_ISIS,
-} route_map_object_t;
-
typedef enum { RMAP_EXIT, RMAP_GOTO, RMAP_NEXT } route_map_end_t;
typedef enum {
@@ -117,7 +106,6 @@ struct route_map_rule_cmd {
/* Function for value set or match. */
enum route_map_cmd_result_t (*func_apply)(void *rule,
const struct prefix *prefix,
- route_map_object_t type,
void *object);
/* Compile argument and return result as void *. */
@@ -299,7 +287,6 @@ struct route_map *route_map_lookup_warn_noexist(struct vty *vty, const char *nam
/* Apply route map to the object. */
extern route_map_result_t route_map_apply(struct route_map *map,
const struct prefix *prefix,
- route_map_object_t object_type,
void *object);
extern void route_map_add_hook(void (*func)(const char *));
diff --git a/lib/sigevent.c b/lib/sigevent.c
index de9e1f5410..8d583096f6 100644
--- a/lib/sigevent.c
+++ b/lib/sigevent.c
@@ -250,6 +250,8 @@ core_handler(int signo, siginfo_t *siginfo, void *context)
/* dump memory stats on core */
log_memstats(stderr, "core_handler");
+
+ zlog_tls_buffer_fini();
abort();
}
diff --git a/lib/skiplist.c b/lib/skiplist.c
index 2bef18f525..b79dfa6772 100644
--- a/lib/skiplist.c
+++ b/lib/skiplist.c
@@ -74,7 +74,6 @@ DEFINE_MTYPE_STATIC(LIB, SKIP_LIST_NODE, "Skip Node")
static int randomsLeft;
static int randomBits;
-static struct skiplist *skiplist_last_created; /* debugging hack */
#if 1
#define CHECKLAST(sl) \
@@ -150,8 +149,6 @@ struct skiplist *skiplist_new(int flags,
if (del)
new->del = del;
- skiplist_last_created = new; /* debug */
-
return new;
}
@@ -586,7 +583,8 @@ void skiplist_debug(struct vty *vty, struct skiplist *l)
int i;
if (!l)
- l = skiplist_last_created;
+ return;
+
vty_out(vty, "Skiplist %p has max level %d\n", l, l->level);
for (i = l->level; i >= 0; --i)
vty_out(vty, " @%d: %ld\n", i,
diff --git a/lib/thread.c b/lib/thread.c
index db53e267f8..e71fd74bd9 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -115,10 +115,9 @@ static void vty_out_cpu_thread_history(struct vty *vty,
struct cpu_thread_history *a)
{
vty_out(vty, "%5zu %10zu.%03zu %9zu %8zu %9zu %8zu %9zu",
- (size_t)a->total_active, a->cpu.total / 1000,
- a->cpu.total % 1000, (size_t)a->total_calls,
- (size_t)(a->cpu.total / a->total_calls), a->cpu.max,
- (size_t)(a->real.total / a->total_calls), a->real.max);
+ a->total_active, a->cpu.total / 1000, a->cpu.total % 1000,
+ a->total_calls, (a->cpu.total / a->total_calls), a->cpu.max,
+ (a->real.total / a->total_calls), a->real.max);
vty_out(vty, " %c%c%c%c%c %s\n",
a->types & (1 << THREAD_READ) ? 'R' : ' ',
a->types & (1 << THREAD_WRITE) ? 'W' : ' ',
diff --git a/lib/thread.h b/lib/thread.h
index 682a17b9f3..eb1b107e7b 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -115,8 +115,8 @@ struct thread {
struct cpu_thread_history {
int (*func)(struct thread *);
- atomic_uint_fast32_t total_calls;
- atomic_uint_fast32_t total_active;
+ atomic_size_t total_calls;
+ atomic_size_t total_active;
struct time_stats {
atomic_size_t total, max;
} real;
diff --git a/lib/vrf.h b/lib/vrf.h
index 2d2fbe4fef..c636b9ea7e 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -43,7 +43,7 @@ enum { IFLA_VRF_UNSPEC, IFLA_VRF_TABLE, __IFLA_VRF_MAX };
#endif
#define VRF_NAMSIZ 36
-#define NS_NAMSIZ 16
+#define NS_NAMSIZ 36
/*
* The command strings
diff --git a/lib/zclient.c b/lib/zclient.c
index d0144279e5..bab1acf667 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1494,9 +1494,12 @@ stream_failure:
bool zapi_route_notify_decode(struct stream *s, struct prefix *p,
uint32_t *tableid,
- enum zapi_route_notify_owner *note)
+ enum zapi_route_notify_owner *note,
+ afi_t *afi, safi_t *safi)
{
uint32_t t;
+ afi_t afi_val;
+ safi_t safi_val;
STREAM_GET(note, s, sizeof(*note));
@@ -1504,9 +1507,16 @@ bool zapi_route_notify_decode(struct stream *s, struct prefix *p,
STREAM_GETC(s, p->prefixlen);
STREAM_GET(&p->u.prefix, s, prefix_blen(p));
STREAM_GETL(s, t);
+ STREAM_GETC(s, afi_val);
+ STREAM_GETC(s, safi_val);
*tableid = t;
+ if (afi)
+ *afi = afi_val;
+ if (safi)
+ *safi = safi_val;
+
return true;
stream_failure:
@@ -1815,6 +1825,22 @@ int zebra_redistribute_default_send(int command, struct zclient *zclient,
return zclient_send_message(zclient);
}
+/* Send route notify request to zebra */
+int zebra_route_notify_send(int command, struct zclient *zclient, bool set)
+{
+ struct stream *s;
+
+ s = zclient->obuf;
+ stream_reset(s);
+
+ zclient_create_header(s, command, 0);
+ stream_putc(s, !!set);
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ return zclient_send_message(zclient);
+}
+
/* Get prefix in ZServ format; family should be filled in on prefix */
static int zclient_stream_get_prefix(struct stream *s, struct prefix *p)
{
diff --git a/lib/zclient.h b/lib/zclient.h
index 80dca3fc56..3c80ba7efa 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -218,6 +218,7 @@ typedef enum {
ZEBRA_OPAQUE_REGISTER,
ZEBRA_OPAQUE_UNREGISTER,
ZEBRA_NEIGH_DISCOVER,
+ ZEBRA_ROUTE_NOTIFY_REQUEST,
} zebra_message_types_t;
enum zebra_error_types {
@@ -513,6 +514,13 @@ struct zapi_route {
* offload situation.
*/
#define ZEBRA_FLAG_OFFLOADED 0x100
+/*
+ * This flag tells everyone that the route has
+ * failed offloading.
+ * This flag makes no sense unless you are in an asic
+ * offload situation.
+ */
+#define ZEBRA_FLAG_OFFLOAD_FAILED 0x200
/* The older XXX_MESSAGE flags live here */
uint32_t message;
@@ -778,6 +786,10 @@ extern int zebra_redistribute_send(int command, struct zclient *, afi_t,
extern int zebra_redistribute_default_send(int command, struct zclient *zclient,
afi_t afi, vrf_id_t vrf_id);
+/* Send route notify request to zebra */
+extern int zebra_route_notify_send(int command, struct zclient *zclient,
+ bool set);
+
/* If state has changed, update state and call zebra_redistribute_send. */
extern void zclient_redistribute(int command, struct zclient *, afi_t, int type,
unsigned short instance, vrf_id_t vrf_id);
@@ -910,7 +922,8 @@ bool zapi_nhg_notify_decode(struct stream *s, uint32_t *id,
enum zapi_nhg_notify_owner *note);
bool zapi_route_notify_decode(struct stream *s, struct prefix *p,
uint32_t *tableid,
- enum zapi_route_notify_owner *note);
+ enum zapi_route_notify_owner *note,
+ afi_t *afi, safi_t *safi);
bool zapi_rule_notify_decode(struct stream *s, uint32_t *seqno,
uint32_t *priority, uint32_t *unique, char *ifname,
enum zapi_rule_notify_owner *note);
diff --git a/lib/zebra.h b/lib/zebra.h
index 14d66d6627..ded44ac636 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -359,6 +359,10 @@ typedef enum {
SAFI_MAX = 8
} safi_t;
+#define FOREACH_AFI_SAFI(afi, safi) \
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) \
+ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
+
/* Default Administrative Distance of each protocol. */
#define ZEBRA_KERNEL_DISTANCE_DEFAULT 0
#define ZEBRA_CONNECT_DISTANCE_DEFAULT 0
diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c
index 2bc2d91597..e7d35b90ff 100644
--- a/nhrpd/nhrp_route.c
+++ b/nhrpd/nhrp_route.c
@@ -350,10 +350,22 @@ void nhrp_zebra_init(void)
zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0, &nhrpd_privs);
}
+static void nhrp_table_node_cleanup(struct route_table *table,
+ struct route_node *node)
+{
+ if (!node->info)
+ return;
+
+ XFREE(MTYPE_NHRP_ROUTE, node->info);
+}
+
void nhrp_zebra_terminate(void)
{
zclient_stop(zclient);
zclient_free(zclient);
+
+ zebra_rib[AFI_IP]->cleanup = nhrp_table_node_cleanup;
+ zebra_rib[AFI_IP6]->cleanup = nhrp_table_node_cleanup;
route_table_finish(zebra_rib[AFI_IP]);
route_table_finish(zebra_rib[AFI_IP6]);
}
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index f087289df6..c71b30a2d4 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -196,7 +196,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
if (ADV_ROUTER_IN_PREFIX(&route->prefix)
== area->ospf6->router_id) {
zlog_debug(
- "%s: Skipping ASBR announcement for ABR (%pFX)",
+ "%s: Skipping ASBR announcement for ABR (%pI4)",
__func__,
&ADV_ROUTER_IN_PREFIX(&route->prefix));
return 0;
@@ -208,7 +208,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
|| IS_OSPF6_DEBUG_ORIGINATE(INTER_ROUTER)) {
is_debug++;
zlog_debug(
- "Originating summary in area %s for ASBR %pFX",
+ "Originating summary in area %s for ASBR %pI4",
area->name,
&ADV_ROUTER_IN_PREFIX(&route->prefix));
}
@@ -225,9 +225,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
if (is_debug)
zlog_debug(
"%s: route %pFX with cost %u is not best, ignore.",
- __func__,
- &ADV_ROUTER_IN_PREFIX(
- &route->prefix),
+ __func__, &route->prefix,
route->path.cost);
return 0;
}
@@ -405,8 +403,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
if (is_debug)
zlog_debug(
"prefix %pFX was denied by export list",
- &ADV_ROUTER_IN_PREFIX(
- &route->prefix));
+ &route->prefix);
return 0;
}
}
@@ -418,7 +415,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
if (is_debug)
zlog_debug(
"prefix %pFX was denied by filter-list out",
- &ADV_ROUTER_IN_PREFIX(&route->prefix));
+ &route->prefix);
return 0;
}
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index c053716f26..1d222d5568 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -1095,8 +1095,7 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
tinfo.ifindex = ifindex;
tinfo.tag = tag;
- ret = route_map_apply(ospf6->rmap[type].map, prefix, RMAP_OSPF6,
- &troute);
+ ret = route_map_apply(ospf6->rmap[type].map, prefix, &troute);
if (ret == RMAP_DENYMATCH) {
if (IS_OSPF6_DEBUG_ASBR)
zlog_debug("Denied by route-map \"%s\"",
@@ -1400,14 +1399,11 @@ static void ospf6_redistribute_show_config(struct vty *vty, struct ospf6 *ospf6)
static enum route_map_cmd_result_t
ospf6_routemap_rule_match_address_prefixlist(void *rule,
const struct prefix *prefix,
- route_map_object_t type,
+
void *object)
{
struct prefix_list *plist;
- if (type != RMAP_OSPF6)
- return RMAP_NOMATCH;
-
plist = prefix_list_lookup(AFI_IP6, (char *)rule);
if (plist == NULL)
return RMAP_NOMATCH;
@@ -1440,18 +1436,16 @@ static const struct route_map_rule_cmd
zero. */
static enum route_map_cmd_result_t
ospf6_routemap_rule_match_interface(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct interface *ifp;
struct ospf6_external_info *ei;
- if (type == RMAP_OSPF6) {
- ei = ((struct ospf6_route *)object)->route_option;
- ifp = if_lookup_by_name_all_vrf((char *)rule);
+ ei = ((struct ospf6_route *)object)->route_option;
+ ifp = if_lookup_by_name_all_vrf((char *)rule);
- if (ifp != NULL && ei->ifindex == ifp->ifindex)
- return RMAP_MATCH;
- }
+ if (ifp != NULL && ei->ifindex == ifp->ifindex)
+ return RMAP_MATCH;
return RMAP_NOMATCH;
}
@@ -1480,14 +1474,13 @@ static const struct route_map_rule_cmd
/* Match function for matching route tags */
static enum route_map_cmd_result_t
-ospf6_routemap_rule_match_tag(void *rule, const struct prefix *p,
- route_map_object_t type, void *object)
+ospf6_routemap_rule_match_tag(void *rule, const struct prefix *p, void *object)
{
route_tag_t *tag = rule;
struct ospf6_route *route = object;
struct ospf6_external_info *info = route->route_option;
- if (type == RMAP_OSPF6 && info->tag == *tag)
+ if (info->tag == *tag)
return RMAP_MATCH;
return RMAP_NOMATCH;
@@ -1503,14 +1496,11 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
ospf6_routemap_rule_set_metric_type(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
char *metric_type = rule;
struct ospf6_route *route = object;
- if (type != RMAP_OSPF6)
- return RMAP_OKAY;
-
if (strcmp(metric_type, "type-2") == 0)
route->path.metric_type = 2;
else
@@ -1541,14 +1531,11 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
ospf6_routemap_rule_set_metric(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
char *metric = rule;
struct ospf6_route *route = object;
- if (type != RMAP_OSPF6)
- return RMAP_OKAY;
-
route->path.cost = atoi(metric);
return RMAP_OKAY;
}
@@ -1578,15 +1565,12 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
ospf6_routemap_rule_set_forwarding(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
char *forwarding = rule;
struct ospf6_route *route = object;
struct ospf6_external_info *info = route->route_option;
- if (type != RMAP_OSPF6)
- return RMAP_OKAY;
-
if (inet_pton(AF_INET6, forwarding, &info->forwarding) != 1) {
memset(&info->forwarding, 0, sizeof(struct in6_addr));
return RMAP_ERROR;
@@ -1617,16 +1601,12 @@ static const struct route_map_rule_cmd
};
static enum route_map_cmd_result_t
-ospf6_routemap_rule_set_tag(void *rule, const struct prefix *p,
- route_map_object_t type, void *object)
+ospf6_routemap_rule_set_tag(void *rule, const struct prefix *p, void *object)
{
route_tag_t *tag = rule;
struct ospf6_route *route = object;
struct ospf6_external_info *info = route->route_option;
- if (type != RMAP_OSPF6)
- return RMAP_OKAY;
-
info->tag = *tag;
return RMAP_OKAY;
}
diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c
index 4e50ab5244..523ed7f181 100644
--- a/ospf6d/ospf6_bfd.c
+++ b/ospf6d/ospf6_bfd.c
@@ -55,12 +55,13 @@ void ospf6_bfd_info_free(void **bfd_info)
/*
* ospf6_bfd_show_info - Show BFD info structure
*/
-void ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only)
+void ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only,
+ json_object *json_obj, bool use_json)
{
if (param_only)
bfd_show_param(vty, bfd_info, 1, 0, 0, NULL);
else
- bfd_show_info(vty, bfd_info, 0, 1, 0, NULL);
+ bfd_show_info(vty, bfd_info, 0, 1, use_json, json_obj);
}
/*
diff --git a/ospf6d/ospf6_bfd.h b/ospf6d/ospf6_bfd.h
index 19dff1ff7c..b4e798e911 100644
--- a/ospf6d/ospf6_bfd.h
+++ b/ospf6d/ospf6_bfd.h
@@ -19,7 +19,7 @@
* 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 "lib/json.h"
#ifndef OSPF6_BFD_H
#define OSPF6_BFD_H
@@ -35,8 +35,8 @@ extern void ospf6_bfd_info_nbr_create(struct ospf6_interface *oi,
extern void ospf6_bfd_info_free(void **bfd_info);
-extern void ospf6_bfd_show_info(struct vty *vty, void *bfd_info,
- int param_only);
+extern void ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only,
+ json_object *json_obj, bool use_json);
extern void ospf6_bfd_reg_dereg_nbr(struct ospf6_neighbor *on, int command);
#endif /* OSPF6_BFD_H */
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 75917b9d85..2d1b5e7b5a 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -996,7 +996,7 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp)
(oi->thread_send_lsack ? "on" : "off"));
for (ALL_LSDB(oi->lsack_list, lsa, lsanext))
vty_out(vty, " %s\n", lsa->name);
- ospf6_bfd_show_info(vty, oi->bfd_info, 1);
+ ospf6_bfd_show_info(vty, oi->bfd_info, 1, NULL, false);
return 0;
}
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index 9f13ecffa1..c1905e8c1e 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -44,6 +44,7 @@
#include "ospf6_lsa.h"
#include "ospf6_spf.h"
#include "ospf6_zebra.h"
+#include "lib/json.h"
DEFINE_HOOK(ospf6_neighbor_change,
(struct ospf6_neighbor * on, int state, int next_state),
@@ -595,7 +596,8 @@ int inactivity_timer(struct thread *thread)
/* vty functions */
/* show neighbor structure */
-static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on)
+static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on,
+ json_object *json_array, bool use_json)
{
char router_id[16];
char duration[64];
@@ -603,6 +605,7 @@ static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on)
char nstate[16];
char deadtime[64];
long h, m, s;
+ json_object *json_route;
/* Router-ID (Name) */
inet_ntop(AF_INET, &on->router_id, router_id, sizeof(router_id));
@@ -641,23 +644,43 @@ static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on)
/*
vty_out (vty, "%-15s %3d %11s %6s/%-12s %11s %s[%s]\n",
- "Neighbor ID", "Pri", "DeadTime", "State", "", "Duration",
- "I/F", "State");
+ "Neighbor ID", "Pri", "DeadTime", "State", "IfState",
+ "Duration", "I/F", "State");
*/
-
- vty_out(vty, "%-15s %3d %11s %8s/%-12s %11s %s[%s]\n", router_id,
- on->priority, deadtime, ospf6_neighbor_state_str[on->state],
- nstate, duration, on->ospf6_if->interface->name,
- ospf6_interface_state_str[on->ospf6_if->state]);
+ if (use_json) {
+ json_route = json_object_new_object();
+
+ json_object_string_add(json_route, "neighborId", router_id);
+ json_object_int_add(json_route, "priority", on->priority);
+ json_object_string_add(json_route, "deadTime", deadtime);
+ json_object_string_add(json_route, "state",
+ ospf6_neighbor_state_str[on->state]);
+ json_object_string_add(json_route, "ifState", nstate);
+ json_object_string_add(json_route, "duration", duration);
+ json_object_string_add(json_route, "interfaceName",
+ on->ospf6_if->interface->name);
+ json_object_string_add(
+ json_route, "interfaceState",
+ ospf6_interface_state_str[on->ospf6_if->state]);
+
+ json_object_array_add(json_array, json_route);
+ } else
+ vty_out(vty, "%-15s %3d %11s %8s/%-12s %11s %s[%s]\n",
+ router_id, on->priority, deadtime,
+ ospf6_neighbor_state_str[on->state], nstate, duration,
+ on->ospf6_if->interface->name,
+ ospf6_interface_state_str[on->ospf6_if->state]);
}
static void ospf6_neighbor_show_drchoice(struct vty *vty,
- struct ospf6_neighbor *on)
+ struct ospf6_neighbor *on,
+ json_object *json_array, bool use_json)
{
char router_id[16];
char drouter[16], bdrouter[16];
char duration[64];
struct timeval now, res;
+ json_object *json_route;
/*
vty_out (vty, "%-15s %6s/%-11s %-15s %-15s %s[%s]\n",
@@ -673,19 +696,39 @@ static void ospf6_neighbor_show_drchoice(struct vty *vty,
timersub(&now, &on->last_changed, &res);
timerstring(&res, duration, sizeof(duration));
- vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", router_id,
- ospf6_neighbor_state_str[on->state], duration, drouter,
- bdrouter, on->ospf6_if->interface->name,
- ospf6_interface_state_str[on->ospf6_if->state]);
+ if (use_json) {
+ json_route = json_object_new_object();
+ json_object_string_add(json_route, "routerId", router_id);
+ json_object_string_add(json_route, "state",
+ ospf6_neighbor_state_str[on->state]);
+ json_object_string_add(json_route, "duration", duration);
+ json_object_string_add(json_route, "dRouter", drouter);
+ json_object_string_add(json_route, "bdRouter", bdrouter);
+ json_object_string_add(json_route, "interfaceName",
+ on->ospf6_if->interface->name);
+ json_object_string_add(
+ json_route, "interfaceState",
+ ospf6_interface_state_str[on->ospf6_if->state]);
+
+ json_object_array_add(json_array, json_route);
+ } else
+ vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", router_id,
+ ospf6_neighbor_state_str[on->state], duration, drouter,
+ bdrouter, on->ospf6_if->interface->name,
+ ospf6_interface_state_str[on->ospf6_if->state]);
}
static void ospf6_neighbor_show_detail(struct vty *vty,
- struct ospf6_neighbor *on)
+ struct ospf6_neighbor *on,
+ json_object *json, bool use_json)
{
char drouter[16], bdrouter[16];
char linklocal_addr[64], duration[32];
struct timeval now, res;
struct ospf6_lsa *lsa, *lsanext;
+ json_object *json_neighbor;
+ json_object *json_array;
+ char db_desc_str[20];
inet_ntop(AF_INET6, &on->linklocal_addr, linklocal_addr,
sizeof(linklocal_addr));
@@ -696,149 +739,333 @@ static void ospf6_neighbor_show_detail(struct vty *vty,
timersub(&now, &on->last_changed, &res);
timerstring(&res, duration, sizeof(duration));
- vty_out(vty, " Neighbor %s\n", on->name);
- vty_out(vty, " Area %s via interface %s (ifindex %d)\n",
- on->ospf6_if->area->name, on->ospf6_if->interface->name,
- on->ospf6_if->interface->ifindex);
- vty_out(vty, " His IfIndex: %d Link-local address: %s\n",
- on->ifindex, linklocal_addr);
- vty_out(vty, " State %s for a duration of %s\n",
- ospf6_neighbor_state_str[on->state], duration);
- vty_out(vty, " His choice of DR/BDR %s/%s, Priority %d\n", drouter,
- bdrouter, on->priority);
- vty_out(vty, " DbDesc status: %s%s%s SeqNum: %#lx\n",
- (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT) ? "Initial "
- : ""),
- (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT) ? "More " : ""),
- (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) ? "Master"
- : "Slave"),
- (unsigned long)ntohl(on->dbdesc_seqnum));
-
- vty_out(vty, " Summary-List: %d LSAs\n", on->summary_list->count);
- for (ALL_LSDB(on->summary_list, lsa, lsanext))
- vty_out(vty, " %s\n", lsa->name);
-
- vty_out(vty, " Request-List: %d LSAs\n", on->request_list->count);
- for (ALL_LSDB(on->request_list, lsa, lsanext))
- vty_out(vty, " %s\n", lsa->name);
-
- vty_out(vty, " Retrans-List: %d LSAs\n", on->retrans_list->count);
- for (ALL_LSDB(on->retrans_list, lsa, lsanext))
- vty_out(vty, " %s\n", lsa->name);
-
- timerclear(&res);
- if (on->thread_send_dbdesc)
- timersub(&on->thread_send_dbdesc->u.sands, &now, &res);
- timerstring(&res, duration, sizeof(duration));
- vty_out(vty, " %d Pending LSAs for DbDesc in Time %s [thread %s]\n",
- on->dbdesc_list->count, duration,
- (on->thread_send_dbdesc ? "on" : "off"));
- for (ALL_LSDB(on->dbdesc_list, lsa, lsanext))
- vty_out(vty, " %s\n", lsa->name);
-
- timerclear(&res);
- if (on->thread_send_lsreq)
- timersub(&on->thread_send_lsreq->u.sands, &now, &res);
- timerstring(&res, duration, sizeof(duration));
- vty_out(vty, " %d Pending LSAs for LSReq in Time %s [thread %s]\n",
- on->request_list->count, duration,
- (on->thread_send_lsreq ? "on" : "off"));
- for (ALL_LSDB(on->request_list, lsa, lsanext))
- vty_out(vty, " %s\n", lsa->name);
-
- timerclear(&res);
- if (on->thread_send_lsupdate)
- timersub(&on->thread_send_lsupdate->u.sands, &now, &res);
- timerstring(&res, duration, sizeof(duration));
- vty_out(vty,
- " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n",
- on->lsupdate_list->count, duration,
- (on->thread_send_lsupdate ? "on" : "off"));
- for (ALL_LSDB(on->lsupdate_list, lsa, lsanext))
- vty_out(vty, " %s\n", lsa->name);
-
- timerclear(&res);
- if (on->thread_send_lsack)
- timersub(&on->thread_send_lsack->u.sands, &now, &res);
- timerstring(&res, duration, sizeof(duration));
- vty_out(vty, " %d Pending LSAs for LSAck in Time %s [thread %s]\n",
- on->lsack_list->count, duration,
- (on->thread_send_lsack ? "on" : "off"));
- for (ALL_LSDB(on->lsack_list, lsa, lsanext))
- vty_out(vty, " %s\n", lsa->name);
-
- ospf6_bfd_show_info(vty, on->bfd_info, 0);
+ if (use_json) {
+ json_neighbor = json_object_new_object();
+ json_object_string_add(json_neighbor, "area",
+ on->ospf6_if->area->name);
+ json_object_string_add(json_neighbor, "interface",
+ on->ospf6_if->interface->name);
+ json_object_int_add(json_neighbor, "interfaceIndex",
+ on->ospf6_if->interface->ifindex);
+ json_object_int_add(json_neighbor, "neighborInterfaceIndex",
+ on->ifindex);
+ json_object_string_add(json_neighbor, "linkLocalAddress",
+ linklocal_addr);
+ json_object_string_add(json_neighbor, "neighborState",
+ ospf6_neighbor_state_str[on->state]);
+ json_object_string_add(json_neighbor, "neighborStateDuration",
+ duration);
+ json_object_string_add(json_neighbor, "neighborDRouter",
+ drouter);
+ json_object_string_add(json_neighbor, "neighborBdRouter",
+ bdrouter);
+ snprintf(db_desc_str, sizeof(db_desc_str), "%s%s%s",
+ (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)
+ ? "Initial "
+ : ""),
+ (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT)
+ ? "More"
+ : ""),
+ (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT)
+ ? "Master"
+ : "Slave"));
+ json_object_string_add(json_neighbor, "dbDescStatus",
+ db_desc_str);
+
+ json_object_int_add(json_neighbor, "dbDescSeqNumber",
+ (unsigned long)ntohl(on->dbdesc_seqnum));
+
+ json_array = json_object_new_array();
+ json_object_int_add(json_neighbor, "summaryListCount",
+ on->summary_list->count);
+ for (ALL_LSDB(on->summary_list, lsa, lsanext))
+ json_object_array_add(
+ json_array, json_object_new_string(lsa->name));
+ json_object_object_add(json_neighbor, "summaryListLsa",
+ json_array);
+
+ json_array = json_object_new_array();
+ json_object_int_add(json_neighbor, "requestListCount",
+ on->request_list->count);
+ for (ALL_LSDB(on->request_list, lsa, lsanext))
+ json_object_array_add(
+ json_array, json_object_new_string(lsa->name));
+ json_object_object_add(json_neighbor, "requestListLsa",
+ json_array);
+
+ json_array = json_object_new_array();
+ json_object_int_add(json_neighbor, "reTransListCount",
+ on->retrans_list->count);
+ for (ALL_LSDB(on->retrans_list, lsa, lsanext))
+ json_object_array_add(
+ json_array, json_object_new_string(lsa->name));
+ json_object_object_add(json_neighbor, "reTransListLsa",
+ json_array);
+
+
+ timerclear(&res);
+ if (on->thread_send_dbdesc)
+ timersub(&on->thread_send_dbdesc->u.sands, &now, &res);
+ timerstring(&res, duration, sizeof(duration));
+ json_object_int_add(json_neighbor, "pendingLsaDbDescCount",
+ on->dbdesc_list->count);
+ json_object_string_add(json_neighbor, "pendingLsaDbDescTime",
+ duration);
+ json_object_string_add(json_neighbor, "dbDescSendThread",
+ (on->thread_send_dbdesc ? "on" : "off"));
+ json_array = json_object_new_array();
+ for (ALL_LSDB(on->dbdesc_list, lsa, lsanext))
+ json_object_array_add(
+ json_array, json_object_new_string(lsa->name));
+ json_object_object_add(json_neighbor, "pendingLsaDbDesc",
+ json_array);
+
+ timerclear(&res);
+ if (on->thread_send_lsreq)
+ timersub(&on->thread_send_lsreq->u.sands, &now, &res);
+ timerstring(&res, duration, sizeof(duration));
+ json_object_int_add(json_neighbor, "pendingLsaLsReqCount",
+ on->request_list->count);
+ json_object_string_add(json_neighbor, "pendingLsaLsReqTime",
+ duration);
+ json_object_string_add(json_neighbor, "lsReqSendThread",
+ (on->thread_send_lsreq ? "on" : "off"));
+ json_array = json_object_new_array();
+ for (ALL_LSDB(on->request_list, lsa, lsanext))
+ json_object_array_add(
+ json_array, json_object_new_string(lsa->name));
+ json_object_object_add(json_neighbor, "pendingLsaLsReq",
+ json_array);
+
+
+ timerclear(&res);
+ if (on->thread_send_lsupdate)
+ timersub(&on->thread_send_lsupdate->u.sands, &now,
+ &res);
+ timerstring(&res, duration, sizeof(duration));
+ json_object_int_add(json_neighbor, "pendingLsaLsUpdateCount",
+ on->lsupdate_list->count);
+ json_object_string_add(json_neighbor, "pendingLsaLsUpdateTime",
+ duration);
+ json_object_string_add(
+ json_neighbor, "lsUpdateSendThread",
+ (on->thread_send_lsupdate ? "on" : "off"));
+ json_array = json_object_new_array();
+ for (ALL_LSDB(on->lsupdate_list, lsa, lsanext))
+ json_object_array_add(
+ json_array, json_object_new_string(lsa->name));
+ json_object_object_add(json_neighbor, "pendingLsaLsUpdate",
+ json_array);
+
+ timerclear(&res);
+ if (on->thread_send_lsack)
+ timersub(&on->thread_send_lsack->u.sands, &now, &res);
+ timerstring(&res, duration, sizeof(duration));
+ json_object_int_add(json_neighbor, "pendingLsaLsAckCount",
+ on->lsack_list->count);
+ json_object_string_add(json_neighbor, "pendingLsaLsAckTime",
+ duration);
+ json_object_string_add(json_neighbor, "lsAckSendThread",
+ (on->thread_send_lsack ? "on" : "off"));
+ json_array = json_object_new_array();
+ for (ALL_LSDB(on->lsack_list, lsa, lsanext))
+ json_object_array_add(
+ json_array, json_object_new_string(lsa->name));
+ json_object_object_add(json_neighbor, "pendingLsaLsAck",
+ json_array);
+
+ ospf6_bfd_show_info(vty, on->bfd_info, 0, json_neighbor,
+ use_json);
+
+ json_object_object_add(json, on->name, json_neighbor);
+
+
+ } else {
+ vty_out(vty, " Neighbor %s\n", on->name);
+ vty_out(vty, " Area %s via interface %s (ifindex %d)\n",
+ on->ospf6_if->area->name, on->ospf6_if->interface->name,
+ on->ospf6_if->interface->ifindex);
+ vty_out(vty, " His IfIndex: %d Link-local address: %s\n",
+ on->ifindex, linklocal_addr);
+ vty_out(vty, " State %s for a duration of %s\n",
+ ospf6_neighbor_state_str[on->state], duration);
+ vty_out(vty, " His choice of DR/BDR %s/%s, Priority %d\n",
+ drouter, bdrouter, on->priority);
+ vty_out(vty, " DbDesc status: %s%s%s SeqNum: %#lx\n",
+ (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT)
+ ? "Initial "
+ : ""),
+ (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT)
+ ? "More "
+ : ""),
+ (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT)
+ ? "Master"
+ : "Slave"),
+ (unsigned long)ntohl(on->dbdesc_seqnum));
+
+ vty_out(vty, " Summary-List: %d LSAs\n",
+ on->summary_list->count);
+ for (ALL_LSDB(on->summary_list, lsa, lsanext))
+ vty_out(vty, " %s\n", lsa->name);
+
+ vty_out(vty, " Request-List: %d LSAs\n",
+ on->request_list->count);
+ for (ALL_LSDB(on->request_list, lsa, lsanext))
+ vty_out(vty, " %s\n", lsa->name);
+
+ vty_out(vty, " Retrans-List: %d LSAs\n",
+ on->retrans_list->count);
+ for (ALL_LSDB(on->retrans_list, lsa, lsanext))
+ vty_out(vty, " %s\n", lsa->name);
+
+ timerclear(&res);
+ if (on->thread_send_dbdesc)
+ timersub(&on->thread_send_dbdesc->u.sands, &now, &res);
+ timerstring(&res, duration, sizeof(duration));
+ vty_out(vty,
+ " %d Pending LSAs for DbDesc in Time %s [thread %s]\n",
+ on->dbdesc_list->count, duration,
+ (on->thread_send_dbdesc ? "on" : "off"));
+ for (ALL_LSDB(on->dbdesc_list, lsa, lsanext))
+ vty_out(vty, " %s\n", lsa->name);
+
+ timerclear(&res);
+ if (on->thread_send_lsreq)
+ timersub(&on->thread_send_lsreq->u.sands, &now, &res);
+ timerstring(&res, duration, sizeof(duration));
+ vty_out(vty,
+ " %d Pending LSAs for LSReq in Time %s [thread %s]\n",
+ on->request_list->count, duration,
+ (on->thread_send_lsreq ? "on" : "off"));
+ for (ALL_LSDB(on->request_list, lsa, lsanext))
+ vty_out(vty, " %s\n", lsa->name);
+
+ timerclear(&res);
+ if (on->thread_send_lsupdate)
+ timersub(&on->thread_send_lsupdate->u.sands, &now,
+ &res);
+ timerstring(&res, duration, sizeof(duration));
+ vty_out(vty,
+ " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n",
+ on->lsupdate_list->count, duration,
+ (on->thread_send_lsupdate ? "on" : "off"));
+ for (ALL_LSDB(on->lsupdate_list, lsa, lsanext))
+ vty_out(vty, " %s\n", lsa->name);
+
+ timerclear(&res);
+ if (on->thread_send_lsack)
+ timersub(&on->thread_send_lsack->u.sands, &now, &res);
+ timerstring(&res, duration, sizeof(duration));
+ vty_out(vty,
+ " %d Pending LSAs for LSAck in Time %s [thread %s]\n",
+ on->lsack_list->count, duration,
+ (on->thread_send_lsack ? "on" : "off"));
+ for (ALL_LSDB(on->lsack_list, lsa, lsanext))
+ vty_out(vty, " %s\n", lsa->name);
+
+ ospf6_bfd_show_info(vty, on->bfd_info, 0, NULL, use_json);
+ }
}
DEFUN (show_ipv6_ospf6_neighbor,
show_ipv6_ospf6_neighbor_cmd,
- "show ipv6 ospf6 neighbor [<detail|drchoice>]",
+ "show ipv6 ospf6 neighbor [<detail|drchoice>] [json]",
SHOW_STR
IP6_STR
OSPF6_STR
"Neighbor list\n"
"Display details\n"
- "Display DR choices\n")
+ "Display DR choices\n"
+ JSON_STR)
{
int idx_type = 4;
struct ospf6_neighbor *on;
struct ospf6_interface *oi;
struct ospf6_area *oa;
struct listnode *i, *j, *k;
- void (*showfunc)(struct vty *, struct ospf6_neighbor *);
struct ospf6 *ospf6;
+ json_object *json = NULL;
+ json_object *json_array = NULL;
+ bool uj = use_json(argc, argv);
+ void (*showfunc)(struct vty *, struct ospf6_neighbor *,
+ json_object *json, bool use_json);
ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
OSPF6_CMD_CHECK_RUNNING(ospf6);
showfunc = ospf6_neighbor_show;
- if (argc == 5) {
+ if ((uj && argc == 6) || (!uj && argc == 5)) {
if (!strncmp(argv[idx_type]->arg, "de", 2))
showfunc = ospf6_neighbor_show_detail;
else if (!strncmp(argv[idx_type]->arg, "dr", 2))
showfunc = ospf6_neighbor_show_drchoice;
}
- if (showfunc == ospf6_neighbor_show)
- vty_out(vty, "%-15s %3s %11s %8s/%-12s %11s %s[%s]\n",
- "Neighbor ID", "Pri", "DeadTime", "State", "IfState",
- "Duration", "I/F", "State");
- else if (showfunc == ospf6_neighbor_show_drchoice)
- vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", "RouterID",
- "State", "Duration", "DR", "BDR", "I/F", "State");
+ if (uj) {
+ json = json_object_new_object();
+ json_array = json_object_new_array();
+ } else {
+ if (showfunc == ospf6_neighbor_show)
+ vty_out(vty, "%-15s %3s %11s %8s/%-12s %11s %s[%s]\n",
+ "Neighbor ID", "Pri", "DeadTime", "State",
+ "IfState", "Duration", "I/F", "State");
+ else if (showfunc == ospf6_neighbor_show_drchoice)
+ vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n",
+ "RouterID", "State", "Duration", "DR", "BDR",
+ "I/F", "State");
+ }
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa))
for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi))
- for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on))
- (*showfunc)(vty, on);
-
+ for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) {
+ if (showfunc == ospf6_neighbor_show_detail)
+ (*showfunc)(vty, on, json, uj);
+ else
+ (*showfunc)(vty, on, json_array, uj);
+ }
+
+ if (uj) {
+ if (showfunc != ospf6_neighbor_show_detail)
+ json_object_object_add(json, "neighbors", json_array);
+ else
+ json_object_free(json_array);
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
return CMD_SUCCESS;
}
DEFUN (show_ipv6_ospf6_neighbor_one,
show_ipv6_ospf6_neighbor_one_cmd,
- "show ipv6 ospf6 neighbor A.B.C.D",
+ "show ipv6 ospf6 neighbor A.B.C.D [json]",
SHOW_STR
IP6_STR
OSPF6_STR
"Neighbor list\n"
"Specify Router-ID as IPv4 address notation\n"
- )
+ JSON_STR)
{
int idx_ipv4 = 4;
struct ospf6_neighbor *on;
struct ospf6_interface *oi;
struct ospf6_area *oa;
struct listnode *i, *j, *k;
- void (*showfunc)(struct vty *, struct ospf6_neighbor *);
+ void (*showfunc)(struct vty *, struct ospf6_neighbor *,
+ json_object *json, bool use_json);
uint32_t router_id;
struct ospf6 *ospf6;
+ json_object *json = NULL;
+ bool uj = use_json(argc, argv);
ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
OSPF6_CMD_CHECK_RUNNING(ospf6);
showfunc = ospf6_neighbor_show_detail;
+ if (uj)
+ json = json_object_new_object();
if ((inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id)) != 1) {
vty_out(vty, "Router-ID is not parsable: %s\n",
@@ -849,8 +1076,15 @@ DEFUN (show_ipv6_ospf6_neighbor_one,
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa))
for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi))
for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on))
- (*showfunc)(vty, on);
+ (*showfunc)(vty, on, json, uj);
+
+ if (uj) {
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
return CMD_SUCCESS;
}
diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h
index 1a45a1966a..94300ff2ba 100644
--- a/ospf6d/ospf6_neighbor.h
+++ b/ospf6d/ospf6_neighbor.h
@@ -64,7 +64,7 @@ struct ospf6_neighbor {
/* Options field (Capability) */
char options[3];
- /* IPaddr of I/F on our side link */
+ /* IPaddr of I/F on neighbour's link */
struct in6_addr linklocal_addr;
/* For Database Exchange */
diff --git a/ospfd/ospf_gr_helper.c b/ospfd/ospf_gr_helper.c
index 9c029a49ba..a86e1b8401 100644
--- a/ospfd/ospf_gr_helper.c
+++ b/ospfd/ospf_gr_helper.c
@@ -251,7 +251,7 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
/* Check TLV len against overall LSA */
if (sum + TLV_SIZE(tlvh) > length) {
if (IS_DEBUG_OSPF_GR_HELPER)
- zlog_debug("%s: Malformed packet: Invalid TLV len:%zu",
+ zlog_debug("%s: Malformed packet: Invalid TLV len:%u",
__func__, TLV_SIZE(tlvh));
return OSPF_GR_FAILURE;
}
@@ -260,7 +260,7 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
case GRACE_PERIOD_TYPE:
if (TLV_SIZE(tlvh) <
sizeof(struct grace_tlv_graceperiod)) {
- zlog_debug("%s: Malformed packet: Invalid grace TLV len:%zu",
+ zlog_debug("%s: Malformed packet: Invalid grace TLV len:%u",
__func__, TLV_SIZE(tlvh));
return OSPF_GR_FAILURE;
}
@@ -277,7 +277,7 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
case RESTART_REASON_TYPE:
if (TLV_SIZE(tlvh) <
sizeof(struct grace_tlv_restart_reason)) {
- zlog_debug("%s: Malformed packet: Invalid reason TLV len:%zu",
+ zlog_debug("%s: Malformed packet: Invalid reason TLV len:%u",
__func__, TLV_SIZE(tlvh));
return OSPF_GR_FAILURE;
}
@@ -292,7 +292,7 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa,
case RESTARTER_IP_ADDR_TYPE:
if (TLV_SIZE(tlvh) <
sizeof(struct grace_tlv_restart_addr)) {
- zlog_debug("%s: Malformed packet: Invalid addr TLV len:%zu",
+ zlog_debug("%s: Malformed packet: Invalid addr TLV len:%u",
__func__, TLV_SIZE(tlvh));
return OSPF_GR_FAILURE;
}
@@ -1018,7 +1018,7 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa)
tlvh = TLV_HDR_NEXT(tlvh)) {
/* Check TLV len */
if (sum + TLV_SIZE(tlvh) > length) {
- vty_out(vty, "%% Invalid TLV length: %zu\n",
+ vty_out(vty, "%% Invalid TLV length: %u\n",
TLV_SIZE(tlvh));
return;
}
@@ -1028,7 +1028,7 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa)
if (TLV_SIZE(tlvh) <
sizeof(struct grace_tlv_graceperiod)) {
vty_out(vty,
- "%% Invalid grace TLV length %zu\n",
+ "%% Invalid grace TLV length %u\n",
TLV_SIZE(tlvh));
return;
}
@@ -1043,7 +1043,7 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa)
if (TLV_SIZE(tlvh) <
sizeof(struct grace_tlv_restart_reason)) {
vty_out(vty,
- "%% Invalid reason TLV length %zu\n",
+ "%% Invalid reason TLV length %u\n",
TLV_SIZE(tlvh));
return;
}
@@ -1058,7 +1058,7 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa)
if (TLV_SIZE(tlvh) <
sizeof(struct grace_tlv_restart_addr)) {
vty_out(vty,
- "%% Invalid addr TLV length %zu\n",
+ "%% Invalid addr TLV length %u\n",
TLV_SIZE(tlvh));
return;
}
diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c
index eb0c4a949a..3939b5479f 100644
--- a/ospfd/ospf_opaque.c
+++ b/ospfd/ospf_opaque.c
@@ -126,6 +126,8 @@ void ospf_opaque_term(void)
void ospf_opaque_finish(void)
{
+ ospf_mpls_te_finish();
+
ospf_router_info_finish();
ospf_ext_finish();
diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h
index f02f34c9af..c63b8ebdaf 100644
--- a/ospfd/ospf_opaque.h
+++ b/ospfd/ospf_opaque.h
@@ -94,7 +94,7 @@ struct tlv_header {
#define TLV_BODY_SIZE(tlvh) (ROUNDUP(ntohs((tlvh)->length), sizeof(uint32_t)))
-#define TLV_SIZE(tlvh) (TLV_HDR_SIZE + TLV_BODY_SIZE(tlvh))
+#define TLV_SIZE(tlvh) (uint32_t)(TLV_HDR_SIZE + TLV_BODY_SIZE(tlvh))
#define TLV_HDR_TOP(lsah) \
(struct tlv_header *)((char *)(lsah) + OSPF_LSA_HEADER_SIZE)
diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c
index c89fd3597f..f9e11541fc 100644
--- a/ospfd/ospf_routemap.c
+++ b/ospfd/ospf_routemap.c
@@ -127,27 +127,22 @@ static void ospf_route_map_event(const char *name)
/* `match ip netxthop ' */
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_ip_nexthop(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ip_nexthop(void *rule, const struct prefix *prefix, void *object)
{
struct access_list *alist;
struct external_info *ei = object;
struct prefix_ipv4 p;
- if (type == RMAP_OSPF) {
- p.family = AF_INET;
- p.prefix = ei->nexthop;
- p.prefixlen = IPV4_MAX_BITLEN;
+ p.family = AF_INET;
+ p.prefix = ei->nexthop;
+ p.prefixlen = IPV4_MAX_BITLEN;
- alist = access_list_lookup(AFI_IP, (char *)rule);
- if (alist == NULL)
- return RMAP_NOMATCH;
+ alist = access_list_lookup(AFI_IP, (char *)rule);
+ if (alist == NULL)
+ return RMAP_NOMATCH;
- return (access_list_apply(alist, &p) == FILTER_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
/* Route map `ip next-hop' match statement. `arg' should be
@@ -175,26 +170,22 @@ static const struct route_map_rule_cmd route_match_ip_nexthop_cmd = {
static enum route_map_cmd_result_t
route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct prefix_list *plist;
struct external_info *ei = object;
struct prefix_ipv4 p;
- if (type == RMAP_OSPF) {
- p.family = AF_INET;
- p.prefix = ei->nexthop;
- p.prefixlen = IPV4_MAX_BITLEN;
+ p.family = AF_INET;
+ p.prefix = ei->nexthop;
+ p.prefixlen = IPV4_MAX_BITLEN;
- plist = prefix_list_lookup(AFI_IP, (char *)rule);
- if (plist == NULL)
- return RMAP_NOMATCH;
+ plist = prefix_list_lookup(AFI_IP, (char *)rule);
+ if (plist == NULL)
+ return RMAP_NOMATCH;
- return (prefix_list_apply(plist, &p) == PREFIX_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ return (prefix_list_apply(plist, &p) == PREFIX_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
@@ -219,11 +210,11 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct external_info *ei = object;
- if (type == RMAP_OSPF && prefix->family == AF_INET) {
+ if (prefix->family == AF_INET) {
ei = (struct external_info *)object;
if (!ei)
return RMAP_NOMATCH;
@@ -256,22 +247,17 @@ static const struct route_map_rule_cmd
/* Match function should return 1 if match is success else return
zero. */
static enum route_map_cmd_result_t
-route_match_ip_address(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
{
struct access_list *alist;
/* struct prefix_ipv4 match; */
- if (type == RMAP_OSPF) {
- alist = access_list_lookup(AFI_IP, (char *)rule);
- if (alist == NULL)
- return RMAP_NOMATCH;
+ alist = access_list_lookup(AFI_IP, (char *)rule);
+ if (alist == NULL)
+ return RMAP_NOMATCH;
- return (access_list_apply(alist, prefix) == FILTER_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ return (access_list_apply(alist, prefix) == FILTER_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
/* Route map `ip address' match statement. `arg' should be
@@ -298,20 +284,16 @@ static const struct route_map_rule_cmd route_match_ip_address_cmd = {
/* `match ip address prefix-list PREFIX_LIST' */
static enum route_map_cmd_result_t
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct prefix_list *plist;
- if (type == RMAP_OSPF) {
- plist = prefix_list_lookup(AFI_IP, (char *)rule);
- if (plist == NULL)
- return RMAP_NOMATCH;
+ plist = prefix_list_lookup(AFI_IP, (char *)rule);
+ if (plist == NULL)
+ return RMAP_NOMATCH;
- return (prefix_list_apply(plist, prefix) == PREFIX_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
static void *route_match_ip_address_prefix_list_compile(const char *arg)
@@ -336,22 +318,18 @@ static const struct route_map_rule_cmd
/* Match function should return 1 if match is success else return
zero. */
static enum route_map_cmd_result_t
-route_match_interface(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_interface(void *rule, const struct prefix *prefix, void *object)
{
struct interface *ifp;
struct external_info *ei;
- if (type == RMAP_OSPF) {
- ei = object;
- ifp = if_lookup_by_name_all_vrf((char *)rule);
+ ei = object;
+ ifp = if_lookup_by_name_all_vrf((char *)rule);
- if (ifp == NULL || ifp->ifindex != ei->ifindex)
- return RMAP_NOMATCH;
+ if (ifp == NULL || ifp->ifindex != ei->ifindex)
+ return RMAP_NOMATCH;
- return RMAP_MATCH;
- }
- return RMAP_NOMATCH;
+ return RMAP_MATCH;
}
/* Route map `interface' match statement. `arg' should be
@@ -377,20 +355,15 @@ static const struct route_map_rule_cmd route_match_interface_cmd = {
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_tag(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_tag(void *rule, const struct prefix *prefix, void *object)
{
route_tag_t *tag;
struct external_info *ei;
- if (type == RMAP_OSPF) {
- tag = rule;
- ei = object;
+ tag = rule;
+ ei = object;
- return ((ei->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH);
- }
-
- return RMAP_NOMATCH;
+ return ((ei->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH);
}
/* Route map commands for tag matching. */
@@ -410,33 +383,31 @@ struct ospf_metric {
/* `set metric METRIC' */
/* Set metric to attribute. */
static enum route_map_cmd_result_t
-route_set_metric(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_metric(void *rule, const struct prefix *prefix, void *object)
{
struct ospf_metric *metric;
struct external_info *ei;
- if (type == RMAP_OSPF) {
- /* Fetch routemap's rule information. */
- metric = rule;
- ei = object;
+ /* Fetch routemap's rule information. */
+ metric = rule;
+ ei = object;
- /* Set metric out value. */
- if (!metric->used)
- return RMAP_OKAY;
+ /* Set metric out value. */
+ if (!metric->used)
+ return RMAP_OKAY;
- ei->route_map_set.metric = DEFAULT_DEFAULT_METRIC;
+ ei->route_map_set.metric = DEFAULT_DEFAULT_METRIC;
- if (metric->type == metric_increment)
- ei->route_map_set.metric += metric->metric;
- else if (metric->type == metric_decrement)
- ei->route_map_set.metric -= metric->metric;
- else if (metric->type == metric_absolute)
- ei->route_map_set.metric = metric->metric;
+ if (metric->type == metric_increment)
+ ei->route_map_set.metric += metric->metric;
+ else if (metric->type == metric_decrement)
+ ei->route_map_set.metric -= metric->metric;
+ else if (metric->type == metric_absolute)
+ ei->route_map_set.metric = metric->metric;
+
+ if (ei->route_map_set.metric > OSPF_LS_INFINITY)
+ ei->route_map_set.metric = OSPF_LS_INFINITY;
- if (ei->route_map_set.metric > OSPF_LS_INFINITY)
- ei->route_map_set.metric = OSPF_LS_INFINITY;
- }
return RMAP_OKAY;
}
@@ -492,20 +463,18 @@ static const struct route_map_rule_cmd route_set_metric_cmd = {
/* `set metric-type TYPE' */
/* Set metric-type to attribute. */
static enum route_map_cmd_result_t
-route_set_metric_type(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_metric_type(void *rule, const struct prefix *prefix, void *object)
{
uint32_t *metric_type;
struct external_info *ei;
- if (type == RMAP_OSPF) {
- /* Fetch routemap's rule information. */
- metric_type = rule;
- ei = object;
+ /* Fetch routemap's rule information. */
+ metric_type = rule;
+ ei = object;
+
+ /* Set metric out value. */
+ ei->route_map_set.metric_type = *metric_type;
- /* Set metric out value. */
- ei->route_map_set.metric_type = *metric_type;
- }
return RMAP_OKAY;
}
@@ -543,19 +512,16 @@ static const struct route_map_rule_cmd route_set_metric_type_cmd = {
};
static enum route_map_cmd_result_t
-route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type,
- void *object)
+route_set_tag(void *rule, const struct prefix *prefix, void *object)
{
route_tag_t *tag;
struct external_info *ei;
- if (type == RMAP_OSPF) {
- tag = rule;
- ei = object;
+ tag = rule;
+ ei = object;
- /* Set tag value */
- ei->tag = *tag;
- }
+ /* Set tag value */
+ ei->tag = *tag;
return RMAP_OKAY;
}
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index e3c554c530..17ff9a1a46 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -187,6 +187,7 @@ void ospf_mpls_te_finish(void)
// list_delete_all_node(OspfMplsTE.iflist);
OspfMplsTE.enabled = false;
+ ospf_mpls_te_unregister();
OspfMplsTE.inter_as = Off;
}
@@ -2229,6 +2230,17 @@ DEFUN (no_ospf_mpls_te,
if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED))
ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA);
+ /*
+ * This resets the OspfMplsTE.inter_as to its initial state.
+ * This is to avoid having an inter-as value different from
+ * Off when mpls-te gets restarted (after being removed)
+ */
+ if (OspfMplsTE.inter_as != Off) {
+ /* Deregister the Callbacks for Inter-AS support */
+ ospf_mpls_te_unregister();
+ OspfMplsTE.inter_as = Off;
+ }
+
return CMD_SUCCESS;
}
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index fd965e8f21..d449f9d2fa 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -902,8 +902,7 @@ int ospf_external_info_apply_default_routemap(struct ospf *ospf,
if (red && ROUTEMAP_NAME(red)) {
route_map_result_t ret;
- ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p,
- RMAP_OSPF, ei);
+ ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, ei);
if (ret == RMAP_DENYMATCH) {
ei->route_map_set = save_values;
@@ -1056,8 +1055,7 @@ int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei,
if (red && ROUTEMAP_NAME(red)) {
route_map_result_t ret;
- ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p,
- RMAP_OSPF, ei);
+ ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, ei);
if (ret == RMAP_DENYMATCH) {
ei->route_map_set = save_values;
diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c
index 32660b4dee..82a2d2feb5 100644
--- a/pbrd/pbr_zebra.c
+++ b/pbrd/pbr_zebra.c
@@ -167,7 +167,8 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS)
enum zapi_route_notify_owner note;
uint32_t table_id;
- if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, &note))
+ if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, &note,
+ NULL, NULL))
return -1;
switch (note) {
diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c
index 77c2db8ceb..061cefec30 100644
--- a/ripd/rip_routemap.c
+++ b/ripd/rip_routemap.c
@@ -43,27 +43,23 @@ struct rip_metric_modifier {
/* `match metric METRIC' */
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_metric(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_metric(void *rule, const struct prefix *prefix, void *object)
{
uint32_t *metric;
uint32_t check;
struct rip_info *rinfo;
- if (type == RMAP_RIP) {
- metric = rule;
- rinfo = object;
-
- /* If external metric is available, the route-map should
- work on this one (for redistribute purpose) */
- check = (rinfo->external_metric) ? rinfo->external_metric
- : rinfo->metric;
- if (check == *metric)
- return RMAP_MATCH;
- else
- return RMAP_NOMATCH;
- }
- return RMAP_NOMATCH;
+ metric = rule;
+ rinfo = object;
+
+ /* If external metric is available, the route-map should
+ work on this one (for redistribute purpose) */
+ check = (rinfo->external_metric) ? rinfo->external_metric
+ : rinfo->metric;
+ if (check == *metric)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
}
/* Route map `match metric' match statement. `arg' is METRIC value */
@@ -98,29 +94,25 @@ static const struct route_map_rule_cmd route_match_metric_cmd = {
/* `match interface IFNAME' */
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_interface(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_interface(void *rule, const struct prefix *prefix, void *object)
{
struct rip_info *rinfo;
struct interface *ifp;
char *ifname;
- if (type == RMAP_RIP) {
- ifname = rule;
- ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
+ ifname = rule;
+ ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
- if (!ifp)
- return RMAP_NOMATCH;
+ if (!ifp)
+ return RMAP_NOMATCH;
- rinfo = object;
+ rinfo = object;
- if (rinfo->ifindex_out == ifp->ifindex
- || rinfo->nh.ifindex == ifp->ifindex)
- return RMAP_MATCH;
- else
- return RMAP_NOMATCH;
- }
- return RMAP_NOMATCH;
+ if (rinfo->ifindex_out == ifp->ifindex
+ || rinfo->nh.ifindex == ifp->ifindex)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
}
/* Route map `match interface' match statement. `arg' is IFNAME value */
@@ -148,30 +140,25 @@ static const struct route_map_rule_cmd route_match_interface_cmd = {
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_ip_next_hop(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
{
struct access_list *alist;
struct rip_info *rinfo;
struct prefix_ipv4 p;
- if (type == RMAP_RIP) {
- rinfo = object;
- p.family = AF_INET;
- p.prefix = (rinfo->nh.gate.ipv4.s_addr != INADDR_ANY)
- ? rinfo->nh.gate.ipv4
- : rinfo->from;
- p.prefixlen = IPV4_MAX_BITLEN;
+ rinfo = object;
+ p.family = AF_INET;
+ p.prefix = (rinfo->nh.gate.ipv4.s_addr != INADDR_ANY)
+ ? rinfo->nh.gate.ipv4
+ : rinfo->from;
+ p.prefixlen = IPV4_MAX_BITLEN;
- alist = access_list_lookup(AFI_IP, (char *)rule);
- if (alist == NULL)
- return RMAP_NOMATCH;
+ alist = access_list_lookup(AFI_IP, (char *)rule);
+ if (alist == NULL)
+ return RMAP_NOMATCH;
- return (access_list_apply(alist, &p) == FILTER_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
/* Route map `ip next-hop' match statement. `arg' should be
@@ -199,29 +186,25 @@ static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
static enum route_map_cmd_result_t
route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct prefix_list *plist;
struct rip_info *rinfo;
struct prefix_ipv4 p;
- if (type == RMAP_RIP) {
- rinfo = object;
- p.family = AF_INET;
- p.prefix = (rinfo->nh.gate.ipv4.s_addr != INADDR_ANY)
- ? rinfo->nh.gate.ipv4
- : rinfo->from;
- p.prefixlen = IPV4_MAX_BITLEN;
+ rinfo = object;
+ p.family = AF_INET;
+ p.prefix = (rinfo->nh.gate.ipv4.s_addr != INADDR_ANY)
+ ? rinfo->nh.gate.ipv4
+ : rinfo->from;
+ p.prefixlen = IPV4_MAX_BITLEN;
- plist = prefix_list_lookup(AFI_IP, (char *)rule);
- if (plist == NULL)
- return RMAP_NOMATCH;
+ plist = prefix_list_lookup(AFI_IP, (char *)rule);
+ if (plist == NULL)
+ return RMAP_NOMATCH;
- return (prefix_list_apply(plist, &p) == PREFIX_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ return (prefix_list_apply(plist, &p) == PREFIX_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
@@ -246,11 +229,11 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct rip_info *rinfo;
- if (type == RMAP_RIP && prefix->family == AF_INET) {
+ if (prefix->family == AF_INET) {
rinfo = (struct rip_info *)object;
if (!rinfo)
return RMAP_NOMATCH;
@@ -284,21 +267,16 @@ static const struct route_map_rule_cmd
/* Match function should return 1 if match is success else return
zero. */
static enum route_map_cmd_result_t
-route_match_ip_address(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
{
struct access_list *alist;
- if (type == RMAP_RIP) {
- alist = access_list_lookup(AFI_IP, (char *)rule);
- if (alist == NULL)
- return RMAP_NOMATCH;
+ alist = access_list_lookup(AFI_IP, (char *)rule);
+ if (alist == NULL)
+ return RMAP_NOMATCH;
- return (access_list_apply(alist, prefix) == FILTER_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ return (access_list_apply(alist, prefix) == FILTER_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
/* Route map `ip address' match statement. `arg' should be
@@ -326,20 +304,16 @@ static const struct route_map_rule_cmd route_match_ip_address_cmd = {
static enum route_map_cmd_result_t
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct prefix_list *plist;
- if (type == RMAP_RIP) {
- plist = prefix_list_lookup(AFI_IP, (char *)rule);
- if (plist == NULL)
- return RMAP_NOMATCH;
+ plist = prefix_list_lookup(AFI_IP, (char *)rule);
+ if (plist == NULL)
+ return RMAP_NOMATCH;
- return (prefix_list_apply(plist, prefix) == PREFIX_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
static void *route_match_ip_address_prefix_list_compile(const char *arg)
@@ -363,25 +337,21 @@ static const struct route_map_rule_cmd
/* `match tag TAG' */
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_tag(void *rule, const struct prefix *p, route_map_object_t type,
- void *object)
+route_match_tag(void *rule, const struct prefix *p, void *object)
{
route_tag_t *tag;
struct rip_info *rinfo;
route_tag_t rinfo_tag;
- if (type == RMAP_RIP) {
- tag = rule;
- rinfo = object;
+ tag = rule;
+ rinfo = object;
- /* The information stored by rinfo is host ordered. */
- rinfo_tag = rinfo->tag;
- if (rinfo_tag == *tag)
- return RMAP_MATCH;
- else
- return RMAP_NOMATCH;
- }
- return RMAP_NOMATCH;
+ /* The information stored by rinfo is host ordered. */
+ rinfo_tag = rinfo->tag;
+ if (rinfo_tag == *tag)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
}
/* Route map commands for tag matching. */
@@ -396,33 +366,30 @@ static const struct route_map_rule_cmd route_match_tag_cmd = {
/* Set metric to attribute. */
static enum route_map_cmd_result_t
-route_set_metric(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_metric(void *rule, const struct prefix *prefix, void *object)
{
- if (type == RMAP_RIP) {
- struct rip_metric_modifier *mod;
- struct rip_info *rinfo;
+ struct rip_metric_modifier *mod;
+ struct rip_info *rinfo;
- mod = rule;
- rinfo = object;
+ mod = rule;
+ rinfo = object;
- if (!mod->used)
- return RMAP_OKAY;
+ if (!mod->used)
+ return RMAP_OKAY;
- if (mod->type == metric_increment)
- rinfo->metric_out += mod->metric;
- else if (mod->type == metric_decrement)
- rinfo->metric_out -= mod->metric;
- else if (mod->type == metric_absolute)
- rinfo->metric_out = mod->metric;
+ if (mod->type == metric_increment)
+ rinfo->metric_out += mod->metric;
+ else if (mod->type == metric_decrement)
+ rinfo->metric_out -= mod->metric;
+ else if (mod->type == metric_absolute)
+ rinfo->metric_out = mod->metric;
- if ((signed int)rinfo->metric_out < 1)
- rinfo->metric_out = 1;
- if (rinfo->metric_out > RIP_METRIC_INFINITY)
- rinfo->metric_out = RIP_METRIC_INFINITY;
+ if ((signed int)rinfo->metric_out < 1)
+ rinfo->metric_out = 1;
+ if (rinfo->metric_out > RIP_METRIC_INFINITY)
+ rinfo->metric_out = RIP_METRIC_INFINITY;
- rinfo->metric_set = 1;
- }
+ rinfo->metric_set = 1;
return RMAP_OKAY;
}
@@ -495,22 +462,20 @@ static const struct route_map_rule_cmd route_set_metric_cmd = {
/* `set ip next-hop IP_ADDRESS' */
/* Set nexthop to object. ojbect must be pointer to struct attr. */
-static enum route_map_cmd_result_t route_set_ip_nexthop(void *rule,
- const struct prefix *prefix,
- route_map_object_t type,
- void *object)
+static enum route_map_cmd_result_t
+route_set_ip_nexthop(void *rule, const struct prefix *prefix,
+
+ void *object)
{
struct in_addr *address;
struct rip_info *rinfo;
- if (type == RMAP_RIP) {
- /* Fetch routemap's rule information. */
- address = rule;
- rinfo = object;
+ /* Fetch routemap's rule information. */
+ address = rule;
+ rinfo = object;
- /* Set next hop value. */
- rinfo->nexthop_out = *address;
- }
+ /* Set next hop value. */
+ rinfo->nexthop_out = *address;
return RMAP_OKAY;
}
@@ -552,20 +517,17 @@ static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
/* Set tag to object. ojbect must be pointer to struct attr. */
static enum route_map_cmd_result_t
-route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type,
- void *object)
+route_set_tag(void *rule, const struct prefix *prefix, void *object)
{
route_tag_t *tag;
struct rip_info *rinfo;
- if (type == RMAP_RIP) {
- /* Fetch routemap's rule information. */
- tag = rule;
- rinfo = object;
+ /* Fetch routemap's rule information. */
+ tag = rule;
+ rinfo = object;
- /* Set next hop value. */
- rinfo->tag_out = *tag;
- }
+ /* Set next hop value. */
+ rinfo->tag_out = *tag;
return RMAP_OKAY;
}
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 059a0e2efd..0cec847f05 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -462,7 +462,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
if (ri->routemap[RIP_FILTER_IN]) {
/* The object should be of the type of rip_info */
ret = route_map_apply(ri->routemap[RIP_FILTER_IN],
- (struct prefix *)&p, RMAP_RIP, &newinfo);
+ (struct prefix *)&p, &newinfo);
if (ret == RMAP_DENYMATCH) {
if (IS_RIP_DEBUG_PACKET)
@@ -2251,7 +2251,7 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
if (ri->routemap[RIP_FILTER_OUT]) {
ret = route_map_apply(
ri->routemap[RIP_FILTER_OUT],
- (struct prefix *)p, RMAP_RIP, rinfo);
+ (struct prefix *)p, rinfo);
if (ret == RMAP_DENYMATCH) {
if (IS_RIP_DEBUG_PACKET)
@@ -2267,7 +2267,7 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
&& rinfo->sub_type != RIP_ROUTE_INTERFACE) {
ret = route_map_apply(
rip->redist[rinfo->type].route_map.map,
- (struct prefix *)p, RMAP_RIP, rinfo);
+ (struct prefix *)p, rinfo);
if (ret == RMAP_DENYMATCH) {
if (IS_RIP_DEBUG_PACKET)
diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c
index b5f80d2ab0..9aed8d6963 100644
--- a/ripngd/ripng_routemap.c
+++ b/ripngd/ripng_routemap.c
@@ -39,21 +39,19 @@ struct rip_metric_modifier {
/* `match metric METRIC' */
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_metric(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_metric(void *rule, const struct prefix *prefix, void *object)
{
uint32_t *metric;
struct ripng_info *rinfo;
- if (type == RMAP_RIPNG) {
- metric = rule;
- rinfo = object;
+ metric = rule;
+ rinfo = object;
+
+ if (rinfo->metric == *metric)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
- if (rinfo->metric == *metric)
- return RMAP_MATCH;
- else
- return RMAP_NOMATCH;
- }
return RMAP_NOMATCH;
}
@@ -89,27 +87,25 @@ static const struct route_map_rule_cmd route_match_metric_cmd = {
/* `match interface IFNAME' */
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_interface(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_interface(void *rule, const struct prefix *prefix, void *object)
{
struct ripng_info *rinfo;
struct interface *ifp;
char *ifname;
- if (type == RMAP_RIPNG) {
- ifname = rule;
- ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
+ ifname = rule;
+ ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
- if (!ifp)
- return RMAP_NOMATCH;
+ if (!ifp)
+ return RMAP_NOMATCH;
- rinfo = object;
+ rinfo = object;
+
+ if (rinfo->ifindex == ifp->ifindex)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
- if (rinfo->ifindex == ifp->ifindex)
- return RMAP_MATCH;
- else
- return RMAP_NOMATCH;
- }
return RMAP_NOMATCH;
}
@@ -135,27 +131,24 @@ static const struct route_map_rule_cmd route_match_interface_cmd = {
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t route_match_tag(void *rule,
const struct prefix *prefix,
- route_map_object_t type,
void *object)
{
route_tag_t *tag;
struct ripng_info *rinfo;
route_tag_t rinfo_tag;
- if (type == RMAP_RIPNG) {
- tag = rule;
- rinfo = object;
+ tag = rule;
+ rinfo = object;
- /* The information stored by rinfo is host ordered. */
- rinfo_tag = rinfo->tag;
- if (rinfo_tag == *tag)
- return RMAP_MATCH;
- else
- return RMAP_NOMATCH;
- }
- return RMAP_NOMATCH;
+ /* The information stored by rinfo is host ordered. */
+ rinfo_tag = rinfo->tag;
+ if (rinfo_tag == *tag)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
}
+
static const struct route_map_rule_cmd route_match_tag_cmd = {
"tag",
route_match_tag,
@@ -167,33 +160,31 @@ static const struct route_map_rule_cmd route_match_tag_cmd = {
/* Set metric to attribute. */
static enum route_map_cmd_result_t
-route_set_metric(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_set_metric(void *rule, const struct prefix *prefix, void *object)
{
- if (type == RMAP_RIPNG) {
- struct rip_metric_modifier *mod;
- struct ripng_info *rinfo;
+ struct rip_metric_modifier *mod;
+ struct ripng_info *rinfo;
- mod = rule;
- rinfo = object;
+ mod = rule;
+ rinfo = object;
- if (!mod->used)
- return RMAP_OKAY;
+ if (!mod->used)
+ return RMAP_OKAY;
- if (mod->type == metric_increment)
- rinfo->metric_out += mod->metric;
- else if (mod->type == metric_decrement)
- rinfo->metric_out -= mod->metric;
- else if (mod->type == metric_absolute)
- rinfo->metric_out = mod->metric;
+ if (mod->type == metric_increment)
+ rinfo->metric_out += mod->metric;
+ else if (mod->type == metric_decrement)
+ rinfo->metric_out -= mod->metric;
+ else if (mod->type == metric_absolute)
+ rinfo->metric_out = mod->metric;
- if (rinfo->metric_out < 1)
- rinfo->metric_out = 1;
- if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
- rinfo->metric_out = RIPNG_METRIC_INFINITY;
+ if (rinfo->metric_out < 1)
+ rinfo->metric_out = 1;
+ if (rinfo->metric_out > RIPNG_METRIC_INFINITY)
+ rinfo->metric_out = RIPNG_METRIC_INFINITY;
+
+ rinfo->metric_set = 1;
- rinfo->metric_set = 1;
- }
return RMAP_OKAY;
}
@@ -265,20 +256,17 @@ static const struct route_map_rule_cmd route_set_metric_cmd = {
/* Set nexthop to object. ojbect must be pointer to struct attr. */
static enum route_map_cmd_result_t
-route_set_ipv6_nexthop_local(void *rule, const struct prefix *p,
- route_map_object_t type, void *object)
+route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object)
{
struct in6_addr *address;
struct ripng_info *rinfo;
- if (type == RMAP_RIPNG) {
- /* Fetch routemap's rule information. */
- address = rule;
- rinfo = object;
+ /* Fetch routemap's rule information. */
+ address = rule;
+ rinfo = object;
- /* Set next hop value. */
- rinfo->nexthop_out = *address;
- }
+ /* Set next hop value. */
+ rinfo->nexthop_out = *address;
return RMAP_OKAY;
}
@@ -321,20 +309,17 @@ static const struct route_map_rule_cmd
/* Set tag to object. ojbect must be pointer to struct attr. */
static enum route_map_cmd_result_t
-route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type,
- void *object)
+route_set_tag(void *rule, const struct prefix *prefix, void *object)
{
route_tag_t *tag;
struct ripng_info *rinfo;
- if (type == RMAP_RIPNG) {
- /* Fetch routemap's rule information. */
- tag = rule;
- rinfo = object;
+ /* Fetch routemap's rule information. */
+ tag = rule;
+ rinfo = object;
- /* Set next hop value. */
- rinfo->tag_out = *tag;
- }
+ /* Set next hop value. */
+ rinfo->tag_out = *tag;
return RMAP_OKAY;
}
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index 8d9249e4ae..1ebdae43fb 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -748,8 +748,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from,
/* Modify entry. */
if (ri->routemap[RIPNG_FILTER_IN]) {
ret = route_map_apply(ri->routemap[RIPNG_FILTER_IN],
- (struct prefix *)&p, RMAP_RIPNG,
- &newinfo);
+ (struct prefix *)&p, &newinfo);
if (ret == RMAP_DENYMATCH) {
if (IS_RIPNG_DEBUG_PACKET)
@@ -1661,7 +1660,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to,
if (ri->routemap[RIPNG_FILTER_OUT]) {
ret = route_map_apply(
ri->routemap[RIPNG_FILTER_OUT],
- (struct prefix *)p, RMAP_RIPNG, rinfo);
+ (struct prefix *)p, rinfo);
if (ret == RMAP_DENYMATCH) {
if (IS_RIPNG_DEBUG_PACKET)
@@ -1677,7 +1676,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to,
ret = route_map_apply(ripng->redist[rinfo->type]
.route_map.map,
(struct prefix *)p,
- RMAP_RIPNG, rinfo);
+ rinfo);
if (ret == RMAP_DENYMATCH) {
if (IS_RIPNG_DEBUG_PACKET)
@@ -1773,8 +1772,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to,
ret = route_map_apply(
ri->routemap[RIPNG_FILTER_OUT],
- (struct prefix *)p, RMAP_RIPNG,
- &newinfo);
+ (struct prefix *)p, &newinfo);
if (ret == RMAP_DENYMATCH) {
if (IS_RIPNG_DEBUG_PACKET)
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 231de6403d..7a335fca3b 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -301,7 +301,8 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS)
enum zapi_route_notify_owner note;
uint32_t table;
- if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, &note))
+ if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, &note,
+ NULL, NULL))
return -1;
switch (note) {
diff --git a/staticd/static_memory.h b/staticd/static_memory.h
index e9cc7ba469..077cd0f32b 100644
--- a/staticd/static_memory.h
+++ b/staticd/static_memory.h
@@ -23,6 +23,7 @@
DECLARE_MGROUP(STATIC)
+DECLARE_MTYPE(STATIC_ROUTE);
DECLARE_MTYPE(STATIC_NEXTHOP);
DECLARE_MTYPE(STATIC_PATH);
diff --git a/staticd/static_routes.c b/staticd/static_routes.c
index d105b2123f..05355c48fe 100644
--- a/staticd/static_routes.c
+++ b/staticd/static_routes.c
@@ -35,7 +35,7 @@
#include "static_zebra.h"
#include "static_debug.h"
-DEFINE_MTYPE_STATIC(STATIC, STATIC_ROUTE, "Static Route Info");
+DEFINE_MTYPE(STATIC, STATIC_ROUTE, "Static Route Info");
DEFINE_MTYPE(STATIC, STATIC_PATH, "Static Path");
/* Install static path into rib. */
@@ -546,19 +546,15 @@ void static_fixup_vrf_ids(struct static_vrf *enable_svrf)
svrf = vrf->info;
/* Install any static routes configured for this VRF. */
- for (afi = AFI_IP; afi < AFI_MAX; afi++) {
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- stable = svrf->stable[afi][safi];
- if (!stable)
- continue;
+ FOREACH_AFI_SAFI (afi, safi) {
+ stable = svrf->stable[afi][safi];
+ if (!stable)
+ continue;
- static_fixup_vrf(enable_svrf, stable,
- afi, safi);
+ static_fixup_vrf(enable_svrf, stable, afi, safi);
- if (enable_svrf == svrf)
- static_enable_vrf(svrf, stable,
- afi, safi);
- }
+ if (enable_svrf == svrf)
+ static_enable_vrf(svrf, stable, afi, safi);
}
}
}
@@ -649,20 +645,17 @@ void static_cleanup_vrf_ids(struct static_vrf *disable_svrf)
svrf = vrf->info;
/* Uninstall any static routes configured for this VRF. */
- for (afi = AFI_IP; afi < AFI_MAX; afi++) {
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- struct route_table *stable;
+ FOREACH_AFI_SAFI (afi, safi) {
+ struct route_table *stable;
- stable = svrf->stable[afi][safi];
- if (!stable)
- continue;
+ stable = svrf->stable[afi][safi];
+ if (!stable)
+ continue;
- static_cleanup_vrf(disable_svrf, stable,
- afi, safi);
+ static_cleanup_vrf(disable_svrf, stable, afi, safi);
- if (disable_svrf == svrf)
- static_disable_vrf(stable, afi, safi);
- }
+ if (disable_svrf == svrf)
+ static_disable_vrf(stable, afi, safi);
}
}
}
@@ -725,14 +718,12 @@ void static_install_intf_nh(struct interface *ifp)
continue;
/* Install any static routes configured for this interface. */
- for (afi = AFI_IP; afi < AFI_MAX; afi++) {
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- stable = svrf->stable[afi][safi];
- if (!stable)
- continue;
+ FOREACH_AFI_SAFI (afi, safi) {
+ stable = svrf->stable[afi][safi];
+ if (!stable)
+ continue;
- static_fixup_intf_nh(stable, ifp, afi, safi);
- }
+ static_fixup_intf_nh(stable, ifp, afi, safi);
}
}
}
diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c
index 39b86787ff..83894e9267 100644
--- a/staticd/static_vrf.c
+++ b/staticd/static_vrf.c
@@ -38,6 +38,10 @@ static void zebra_stable_node_cleanup(struct route_table *table,
struct static_nexthop *nh;
struct static_path *pn;
struct static_route_info *si;
+ struct route_table *src_table;
+ struct route_node *src_node;
+ struct static_path *src_pn;
+ struct static_route_info *src_si;
si = node->info;
@@ -51,6 +55,37 @@ static void zebra_stable_node_cleanup(struct route_table *table,
static_path_list_del(&si->path_list, pn);
XFREE(MTYPE_STATIC_PATH, pn);
}
+
+ /* clean up for dst table */
+ src_table = srcdest_srcnode_table(node);
+ if (src_table) {
+ /* This means the route_node is part of the top
+ * hierarchy and refers to a destination prefix.
+ */
+ for (src_node = route_top(src_table); src_node;
+ src_node = route_next(src_node)) {
+ src_si = src_node->info;
+
+ frr_each_safe(static_path_list,
+ &src_si->path_list, src_pn) {
+ frr_each_safe(static_nexthop_list,
+ &src_pn->nexthop_list,
+ nh) {
+ static_nexthop_list_del(
+ &src_pn->nexthop_list,
+ nh);
+ XFREE(MTYPE_STATIC_NEXTHOP, nh);
+ }
+ static_path_list_del(&src_si->path_list,
+ src_pn);
+ XFREE(MTYPE_STATIC_PATH, src_pn);
+ }
+
+ XFREE(MTYPE_STATIC_ROUTE, src_node->info);
+ }
+ }
+
+ XFREE(MTYPE_STATIC_ROUTE, node->info);
}
}
@@ -203,14 +238,12 @@ int static_vrf_has_config(struct static_vrf *svrf)
* NOTE: This is a don't care for the default VRF, but we go through
* the motions to keep things consistent.
*/
- for (afi = AFI_IP; afi < AFI_MAX; afi++) {
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- table = svrf->stable[afi][safi];
- if (!table)
- continue;
- if (route_table_count(table))
- return 1;
- }
+ FOREACH_AFI_SAFI (afi, safi) {
+ table = svrf->stable[afi][safi];
+ if (!table)
+ continue;
+ if (route_table_count(table))
+ return 1;
}
return 0;
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index a9b570de83..0bccbfbead 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -110,7 +110,8 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS)
enum zapi_route_notify_owner note;
uint32_t table_id;
- if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, &note))
+ if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, &note,
+ NULL, NULL))
return -1;
switch (note) {
diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c
index 99fb7b620d..520c460f15 100644
--- a/tests/bgpd/test_mpath.c
+++ b/tests/bgpd/test_mpath.c
@@ -106,15 +106,13 @@ static struct bgp *bgp_create_fake(as_t *as, const char *name)
// bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
bgp_evpn_init(bgp);
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- bgp->route[afi][safi] = bgp_table_init(bgp, afi, safi);
- bgp->aggregate[afi][safi] = bgp_table_init(
- bgp, afi, safi);
- bgp->rib[afi][safi] = bgp_table_init(bgp, afi, safi);
- bgp->maxpaths[afi][safi].maxpaths_ebgp = MULTIPATH_NUM;
- bgp->maxpaths[afi][safi].maxpaths_ibgp = MULTIPATH_NUM;
- }
+ FOREACH_AFI_SAFI (afi, safi) {
+ bgp->route[afi][safi] = bgp_table_init(bgp, afi, safi);
+ bgp->aggregate[afi][safi] = bgp_table_init(bgp, afi, safi);
+ bgp->rib[afi][safi] = bgp_table_init(bgp, afi, safi);
+ bgp->maxpaths[afi][safi].maxpaths_ebgp = MULTIPATH_NUM;
+ bgp->maxpaths[afi][safi].maxpaths_ibgp = MULTIPATH_NUM;
+ }
bgp_scan_init(bgp);
bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
@@ -152,36 +150,33 @@ static int run_bgp_cfg_maximum_paths(testcase_t *t)
int test_result = TEST_PASSED;
bgp = t->tmp_data;
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
- for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- /* test bgp_maximum_paths_set */
- api_result = bgp_maximum_paths_set(
- bgp, afi, safi, BGP_PEER_EBGP, 10, 0);
- EXPECT_TRUE(api_result == 0, test_result);
- api_result = bgp_maximum_paths_set(
- bgp, afi, safi, BGP_PEER_IBGP, 10, 0);
- EXPECT_TRUE(api_result == 0, test_result);
- EXPECT_TRUE(bgp->maxpaths[afi][safi].maxpaths_ebgp
- == 10,
- test_result);
- EXPECT_TRUE(bgp->maxpaths[afi][safi].maxpaths_ibgp
- == 10,
- test_result);
-
- /* test bgp_maximum_paths_unset */
- api_result = bgp_maximum_paths_unset(bgp, afi, safi,
- BGP_PEER_EBGP);
- EXPECT_TRUE(api_result == 0, test_result);
- api_result = bgp_maximum_paths_unset(bgp, afi, safi,
- BGP_PEER_IBGP);
- EXPECT_TRUE(api_result == 0, test_result);
- EXPECT_TRUE((bgp->maxpaths[afi][safi].maxpaths_ebgp
- == MULTIPATH_NUM),
- test_result);
- EXPECT_TRUE((bgp->maxpaths[afi][safi].maxpaths_ibgp
- == MULTIPATH_NUM),
- test_result);
- }
+ FOREACH_AFI_SAFI (afi, safi) {
+ /* test bgp_maximum_paths_set */
+ api_result = bgp_maximum_paths_set(bgp, afi, safi,
+ BGP_PEER_EBGP, 10, 0);
+ EXPECT_TRUE(api_result == 0, test_result);
+ api_result = bgp_maximum_paths_set(bgp, afi, safi,
+ BGP_PEER_IBGP, 10, 0);
+ EXPECT_TRUE(api_result == 0, test_result);
+ EXPECT_TRUE(bgp->maxpaths[afi][safi].maxpaths_ebgp == 10,
+ test_result);
+ EXPECT_TRUE(bgp->maxpaths[afi][safi].maxpaths_ibgp == 10,
+ test_result);
+
+ /* test bgp_maximum_paths_unset */
+ api_result =
+ bgp_maximum_paths_unset(bgp, afi, safi, BGP_PEER_EBGP);
+ EXPECT_TRUE(api_result == 0, test_result);
+ api_result =
+ bgp_maximum_paths_unset(bgp, afi, safi, BGP_PEER_IBGP);
+ EXPECT_TRUE(api_result == 0, test_result);
+ EXPECT_TRUE((bgp->maxpaths[afi][safi].maxpaths_ebgp
+ == MULTIPATH_NUM),
+ test_result);
+ EXPECT_TRUE((bgp->maxpaths[afi][safi].maxpaths_ibgp
+ == MULTIPATH_NUM),
+ test_result);
+ }
return test_result;
}
diff --git a/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py b/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py
index 12069a12dc..54a3c699f3 100644
--- a/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py
+++ b/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py
@@ -292,6 +292,10 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type):
input_dict_1 = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}}
logger.info("Verifying %s routes on r3", addr_type)
+
+ # Only test the count of nexthops; the actual nexthop addresses
+ # can vary and are not deterministic.
+ #
result = verify_rib(
tgen,
addr_type,
@@ -299,7 +303,9 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type):
input_dict_1,
next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)],
protocol=protocol,
+ count_only=True
)
+
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
diff --git a/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py b/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py
index 50aa281d34..73724ac069 100644
--- a/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py
+++ b/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py
@@ -293,6 +293,10 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type):
input_dict_1 = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}}
logger.info("Verifying %s routes on r3", addr_type)
+
+ # Test only the count of nexthops, not the specific nexthop addresses -
+ # they're not deterministic
+ #
result = verify_rib(
tgen,
addr_type,
@@ -300,7 +304,9 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type):
input_dict_1,
next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)],
protocol=protocol,
+ count_only=True
)
+
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
diff --git a/tests/topotests/bgp_suppress_fib/r1/bgpd.conf b/tests/topotests/bgp_suppress_fib/r1/bgpd.conf
new file mode 100644
index 0000000000..69c563d37c
--- /dev/null
+++ b/tests/topotests/bgp_suppress_fib/r1/bgpd.conf
@@ -0,0 +1,15 @@
+! exit1
+router bgp 1
+ no bgp ebgp-requires-policy
+ neighbor 10.0.0.2 remote-as 2
+
+ address-family ipv4 unicast
+ redistribute static
+ neighbor 10.0.0.2 route-map rmap out
+ exit-address-family
+
+ip prefix-list plist seq 5 permit any
+
+route-map rmap permit 1
+ match ip address prefix-list plist
+!
diff --git a/tests/topotests/bgp_suppress_fib/r1/zebra.conf b/tests/topotests/bgp_suppress_fib/r1/zebra.conf
new file mode 100644
index 0000000000..7b442164ff
--- /dev/null
+++ b/tests/topotests/bgp_suppress_fib/r1/zebra.conf
@@ -0,0 +1,9 @@
+! exit1
+interface r1-eth0
+ ip address 10.0.0.1/30
+!
+ip forwarding
+!
+ip route 40.0.0.0/8 blackhole
+ip route 50.0.0.0/8 blackhole
+!
diff --git a/tests/topotests/bgp_suppress_fib/r2/bgpd.conf b/tests/topotests/bgp_suppress_fib/r2/bgpd.conf
new file mode 100644
index 0000000000..8321c915e3
--- /dev/null
+++ b/tests/topotests/bgp_suppress_fib/r2/bgpd.conf
@@ -0,0 +1,6 @@
+!
+router bgp 2
+ no bgp ebgp-requires-policy
+ bgp suppress-fib-pending
+ neighbor 10.0.0.1 remote-as 1
+ neighbor 10.0.0.10 remote-as 3
diff --git a/tests/topotests/bgp_suppress_fib/r2/zebra.conf b/tests/topotests/bgp_suppress_fib/r2/zebra.conf
new file mode 100644
index 0000000000..443fffc703
--- /dev/null
+++ b/tests/topotests/bgp_suppress_fib/r2/zebra.conf
@@ -0,0 +1,13 @@
+!
+interface r2-eth0
+ ip address 10.0.0.2/30
+!
+interface r2-eth1
+ ip address 10.0.0.9/30
+
+access-list access seq 5 permit 40.0.0.0/8
+
+route-map LIMIT permit 10
+ match ip address access
+
+ip protocol bgp route-map LIMIT
diff --git a/tests/topotests/bgp_suppress_fib/r3/bgpd.conf b/tests/topotests/bgp_suppress_fib/r3/bgpd.conf
new file mode 100644
index 0000000000..11715d45d7
--- /dev/null
+++ b/tests/topotests/bgp_suppress_fib/r3/bgpd.conf
@@ -0,0 +1,9 @@
+!
+router bgp 3
+ no bgp ebgp-requires-policy
+ neighbor 10.0.0.9 remote-as 2
+
+route-map rmap permit 1
+ match ip address prefix-list plist
+ !
+!
diff --git a/tests/topotests/bgp_suppress_fib/r3/v4_route.json b/tests/topotests/bgp_suppress_fib/r3/v4_route.json
new file mode 100644
index 0000000000..19294eb492
--- /dev/null
+++ b/tests/topotests/bgp_suppress_fib/r3/v4_route.json
@@ -0,0 +1,29 @@
+{
+ "40.0.0.0\/8":[
+ {
+ "prefix":"40.0.0.0\/8",
+ "protocol":"bgp",
+ "selected":true,
+ "destSelected":true,
+ "distance":20,
+ "metric":0,
+ "installed":true,
+ "table":254,
+ "internalStatus":16,
+ "internalFlags":8,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "ip":"10.0.0.9",
+ "afi":"ipv4",
+ "interfaceIndex":2,
+ "interfaceName":"r3-eth0",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_suppress_fib/r3/v4_route2.json b/tests/topotests/bgp_suppress_fib/r3/v4_route2.json
new file mode 100644
index 0000000000..a35d49e9e8
--- /dev/null
+++ b/tests/topotests/bgp_suppress_fib/r3/v4_route2.json
@@ -0,0 +1,4 @@
+{
+ "0.0.0.0\/0":[
+ ]
+}
diff --git a/tests/topotests/bgp_suppress_fib/r3/zebra.conf b/tests/topotests/bgp_suppress_fib/r3/zebra.conf
new file mode 100644
index 0000000000..793b043a7b
--- /dev/null
+++ b/tests/topotests/bgp_suppress_fib/r3/zebra.conf
@@ -0,0 +1,6 @@
+!
+interface r3-eth0
+ ip address 10.0.0.10/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py
new file mode 100644
index 0000000000..cf8be5f44f
--- /dev/null
+++ b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+
+#
+# test_bgp_suppress_fib.py
+#
+# Copyright (c) 2019 by
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+"""
+
+import os
+import sys
+import json
+import time
+import pytest
+from functools import partial
+from time import sleep
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from mininet.topo import Topo
+
+
+class TemplateTopo(Topo):
+ def build(self, *_args, **_opts):
+ tgen = get_topogen(self)
+
+ for routern in range(1, 4):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+def setup_module(mod):
+ tgen = Topogen(TemplateTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_route():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r3 = tgen.gears["r3"]
+
+ sleep(5)
+
+ json_file = "{}/r3/v4_route.json".format(CWD)
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(
+ topotest.router_json_cmp,
+ r3,
+ "show ip route 40.0.0.0 json",
+ expected,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=2, wait=0.5)
+ assertmsg = '"r3" JSON output mismatches'
+ assert result is None, assertmsg
+
+ json_file = "{}/r3/v4_route2.json".format(CWD)
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(
+ topotest.router_json_cmp,
+ r3,
+ "show ip route 50.0.0.0 json",
+ expected,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=3, wait=0.5)
+ assertmsg = '"r3" JSON output mismatches'
+ assert result is None, assertmsg
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index d83f946c42..e42992e294 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -2559,6 +2559,7 @@ def verify_rib(
tag=None,
metric=None,
fib=None,
+ count_only=False
):
"""
Data will be read from input_dict or input JSON file, API will generate
@@ -2576,6 +2577,8 @@ def verify_rib(
* `next_hop`[optional]: next_hop which needs to be verified,
default: static
* `protocol`[optional]: protocol, default = None
+ * `count_only`[optional]: count of nexthops only, not specific addresses,
+ default = False
Usage
-----
@@ -2739,7 +2742,23 @@ def verify_rib(
for rib_r in rib_routes_json[st_rt][0]["nexthops"]
]
- if found_hops:
+ # Check only the count of nexthops
+ if count_only:
+ if len(next_hop) == len(found_hops):
+ nh_found = True
+ else:
+ errormsg = (
+ "Nexthops are missing for "
+ "route {} in RIB of router {}: "
+ "expected {}, found {}\n".format(
+ st_rt, dut, len(next_hop),
+ len(found_hops)
+ )
+ )
+ return errormsg
+
+ # Check the actual nexthops
+ elif found_hops:
missing_list_of_nexthops = set(
found_hops
).difference(next_hop)
@@ -3019,262 +3038,6 @@ def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None):
for st_rt in ip_list:
st_rt = str(ipaddress.ip_network(frr_unicode(st_rt)))
- # st_rt = str(ipaddr.IPNetwork(unicode(st_rt)))
-
- _addr_type = validate_ip_address(st_rt)
- if _addr_type != addr_type:
- continue
-
- if st_rt in rib_routes_json:
- st_found = True
- found_routes.append(st_rt)
-
- if next_hop:
- if type(next_hop) is not list:
- next_hop = [next_hop]
-
- count = 0
- for nh in next_hop:
- for nh_dict in rib_routes_json[st_rt][0][
- "nexthops"
- ]:
- if nh_dict["ip"] != nh:
- continue
- else:
- count += 1
-
- if count == len(next_hop):
- nh_found = True
- else:
- missing_routes.append(st_rt)
- errormsg = (
- "Nexthop {} is Missing"
- " for route {} in "
- "RIB of router {}\n".format(
- next_hop, st_rt, dut
- )
- )
- return errormsg
-
- else:
- missing_routes.append(st_rt)
-
- if len(missing_routes) > 0:
- errormsg = "[DUT: {}]: Missing route in FIB:" " {}".format(
- dut, missing_routes
- )
- return errormsg
-
- if nh_found:
- logger.info(
- "Found next_hop {} for all routes in RIB"
- " of router {}\n".format(next_hop, dut)
- )
-
- if found_routes:
- logger.info(
- "[DUT: %s]: Verified routes in FIB, found" " routes are: %s\n",
- dut,
- found_routes,
- )
-
- continue
-
- if "bgp" in input_dict[routerInput]:
- if (
- "advertise_networks"
- not in input_dict[routerInput]["bgp"]["address_family"][addr_type][
- "unicast"
- ]
- ):
- continue
-
- found_routes = []
- missing_routes = []
- advertise_network = input_dict[routerInput]["bgp"]["address_family"][
- addr_type
- ]["unicast"]["advertise_networks"]
-
- # Continue if there are no network advertise
- if len(advertise_network) == 0:
- continue
-
- for advertise_network_dict in advertise_network:
- if "vrf" in advertise_network_dict:
- cmd = "{} vrf {} json".format(command, static_route["vrf"])
- else:
- cmd = "{} json".format(command)
-
- rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True)
-
- # Verifying output dictionary rib_routes_json is not empty
- if bool(rib_routes_json) is False:
- errormsg = "No route found in rib of router {}..".format(router)
- return errormsg
-
- start_ip = advertise_network_dict["network"]
- if "no_of_network" in advertise_network_dict:
- no_of_network = advertise_network_dict["no_of_network"]
- else:
- no_of_network = 1
-
- # Generating IPs for verification
- ip_list = generate_ips(start_ip, no_of_network)
- st_found = False
- nh_found = False
-
- for st_rt in ip_list:
- # st_rt = str(ipaddr.IPNetwork(unicode(st_rt)))
- st_rt = str(ipaddress.ip_network(frr_unicode(st_rt)))
-
- _addr_type = validate_ip_address(st_rt)
- if _addr_type != addr_type:
- continue
-
- if st_rt in rib_routes_json:
- st_found = True
- found_routes.append(st_rt)
-
- if next_hop:
- if type(next_hop) is not list:
- next_hop = [next_hop]
-
- count = 0
- for nh in next_hop:
- for nh_dict in rib_routes_json[st_rt][0]["nexthops"]:
- if nh_dict["ip"] != nh:
- continue
- else:
- count += 1
-
- if count == len(next_hop):
- nh_found = True
- else:
- missing_routes.append(st_rt)
- errormsg = (
- "Nexthop {} is Missing"
- " for route {} in "
- "RIB of router {}\n".format(next_hop, st_rt, dut)
- )
- return errormsg
- else:
- missing_routes.append(st_rt)
-
- if len(missing_routes) > 0:
- errormsg = "[DUT: {}]: Missing route in FIB: " "{} \n".format(
- dut, missing_routes
- )
- return errormsg
-
- if nh_found:
- logger.info(
- "Found next_hop {} for all routes in RIB"
- " of router {}\n".format(next_hop, dut)
- )
-
- if found_routes:
- logger.info(
- "[DUT: {}]: Verified routes FIB"
- ", found routes are: {}\n".format(dut, found_routes)
- )
-
- logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
- return True
-
-
-@retry(attempts=5, wait=2, return_is_str=True, initial_wait=2)
-def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None):
- """
- Data will be read from input_dict or input JSON file, API will generate
- same prefixes, which were redistributed by either create_static_routes() or
- advertise_networks_using_network_command() and will verify next_hop and
- each prefix/routes is present in "show ip/ipv6 fib json"
- command o/p.
-
- Parameters
- ----------
- * `tgen` : topogen object
- * `addr_type` : ip type, ipv4/ipv6
- * `dut`: Device Under Test, for which user wants to test the data
- * `input_dict` : input dict, has details of static routes
- * `next_hop`[optional]: next_hop which needs to be verified,
- default: static
-
- Usage
- -----
- input_routes_r1 = {
- "r1": {
- "static_routes": [{
- "network": ["1.1.1.1/32],
- "next_hop": "Null0",
- "vrf": "RED"
- }]
- }
- }
- result = result = verify_fib_routes(tgen, "ipv4, "r1", input_routes_r1)
-
- Returns
- -------
- errormsg(str) or True
- """
-
- logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
-
- router_list = tgen.routers()
- for routerInput in input_dict.keys():
- for router, rnode in router_list.items():
- if router != dut:
- continue
-
- logger.info("Checking router %s FIB routes:", router)
-
- # Verifying RIB routes
- if addr_type == "ipv4":
- command = "show ip fib"
- else:
- command = "show ipv6 fib"
-
- found_routes = []
- missing_routes = []
-
- if "static_routes" in input_dict[routerInput]:
- static_routes = input_dict[routerInput]["static_routes"]
-
- for static_route in static_routes:
- if "vrf" in static_route and static_route["vrf"] is not None:
-
- logger.info(
- "[DUT: {}]: Verifying routes for VRF:"
- " {}".format(router, static_route["vrf"])
- )
-
- cmd = "{} vrf {}".format(command, static_route["vrf"])
-
- else:
- cmd = "{}".format(command)
-
- cmd = "{} json".format(cmd)
-
- rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True)
-
- # Verifying output dictionary rib_routes_json is not empty
- if bool(rib_routes_json) is False:
- errormsg = "[DUT: {}]: No route found in fib".format(router)
- return errormsg
-
- network = static_route["network"]
- if "no_of_ip" in static_route:
- no_of_ip = static_route["no_of_ip"]
- else:
- no_of_ip = 1
-
- # Generating IPs for verification
- ip_list = generate_ips(network, no_of_ip)
- st_found = False
- nh_found = False
-
- for st_rt in ip_list:
- st_rt = str(ipaddress.ip_network(frr_unicode(st_rt)))
_addr_type = validate_ip_address(st_rt)
if _addr_type != addr_type:
diff --git a/tests/topotests/route-scale/r1/installed.routes.json b/tests/topotests/route-scale/r1/installed.routes.json
index 25d209f9eb..24a45dca81 100644
--- a/tests/topotests/route-scale/r1/installed.routes.json
+++ b/tests/topotests/route-scale/r1/installed.routes.json
@@ -6,11 +6,11 @@
"type":"connected"
},
{
- "fib":1000000,
- "rib":1000000,
+ "fib":200000,
+ "rib":200000,
"type":"sharp"
}
],
- "routesTotal":1000032,
- "routesTotalFib":1000032
+ "routesTotal":200032,
+ "routesTotalFib":200032
}
diff --git a/tests/topotests/route-scale/test_route_scale.py b/tests/topotests/route-scale/test_route_scale.py
index 8aedfc198c..bbd6ef8d60 100644
--- a/tests/topotests/route-scale/test_route_scale.py
+++ b/tests/topotests/route-scale/test_route_scale.py
@@ -122,15 +122,20 @@ def run_one_setup(r1, s):
expected_installed = s["expect_in"]
expected_removed = s["expect_rem"]
- count = s["count"]
+ retries = s["retries"]
wait = s["wait"]
- logger.info("Testing 1 million routes X {} ecmp".format(s["ecmp"]))
+ for d in expected_installed["routes"]:
+ if d["type"] == "sharp":
+ count = d["rib"]
+ break
+
+ logger.info("Testing {} routes X {} ecmp".format(count, s["ecmp"]))
r1.vtysh_cmd(
"sharp install route 1.0.0.0 \
- nexthop-group {} 1000000".format(
- s["nhg"]
+ nexthop-group {} {}".format(
+ s["nhg"], count
),
isjson=False,
)
@@ -138,21 +143,21 @@ def run_one_setup(r1, s):
test_func = partial(
topotest.router_json_cmp, r1, "show ip route summary json", expected_installed
)
- success, result = topotest.run_and_expect(test_func, None, count, wait)
+ success, result = topotest.run_and_expect(test_func, None, retries, wait)
assert success, "Route scale test install failed:\n{}".format(result)
output = r1.vtysh_cmd("sharp data route", isjson=False)
- logger.info("1 million routes X {} ecmp installed".format(s["ecmp"]))
+ logger.info("{} routes X {} ecmp installed".format(count, s["ecmp"]))
logger.info(output)
- r1.vtysh_cmd("sharp remove route 1.0.0.0 1000000", isjson=False)
+ r1.vtysh_cmd("sharp remove route 1.0.0.0 {}".format(count), isjson=False)
test_func = partial(
topotest.router_json_cmp, r1, "show ip route summary json", expected_removed
)
- success, result = topotest.run_and_expect(test_func, None, count, wait)
+ success, result = topotest.run_and_expect(test_func, None, retries, wait)
assert success, "Route scale test remove failed:\n{}".format(result)
output = r1.vtysh_cmd("sharp data route", isjson=False)
- logger.info("1 million routes x {} ecmp removed".format(s["ecmp"]))
+ logger.info("{} routes x {} ecmp removed".format(count, s["ecmp"]))
logger.info(output)
@@ -174,7 +179,7 @@ def test_route_install():
# dict keys of params: ecmp number, corresponding nhg name, timeout,
# number of times to wait
- scale_keys = ["ecmp", "nhg", "wait", "count", "expect_in", "expect_rem"]
+ scale_keys = ["ecmp", "nhg", "wait", "retries", "expect_in", "expect_rem"]
# Table of defaults, used for timeout values and 'expected' objects
scale_defaults = dict(
diff --git a/zebra/connected.c b/zebra/connected.c
index 6a1efc3e65..70ea2e3805 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -41,6 +41,7 @@
#include "zebra/zebra_mpls.h"
#include "zebra/debug.h"
#include "zebra/zebra_errors.h"
+#include "zebra/zebra_router.h"
/* communicate the withdrawal of a connected address */
static void connected_withdraw(struct connected *ifc)
@@ -207,6 +208,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
};
struct zebra_vrf *zvrf;
uint32_t metric;
+ uint32_t flags = 0;
zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
if (!zvrf) {
@@ -251,11 +253,22 @@ void connected_up(struct interface *ifp, struct connected *ifc)
metric = (ifc->metric < (uint32_t)METRIC_MAX) ?
ifc->metric : ifp->metric;
- rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT,
- 0, 0, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0);
- rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT,
- 0, 0, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0);
+ /*
+ * Since we are hand creating the connected routes
+ * in our main routing table, *if* we are working
+ * in an offloaded environment then we need to
+ * pretend like the route is offloaded so everything
+ * else will work
+ */
+ if (zrouter.asic_offloaded)
+ flags |= ZEBRA_FLAG_OFFLOADED;
+
+ rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
+ flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0);
+
+ rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
+ flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0);
/* Schedule LSP forwarding entries for processing, if appropriate. */
if (zvrf->vrf->vrf_id == VRF_DEFAULT) {
diff --git a/zebra/main.c b/zebra/main.c
index ced29e1a25..55fd3244cb 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -83,6 +83,8 @@ uint32_t nl_rcvbufsize = 4194304;
#endif /* HAVE_NETLINK */
#define OPTION_V6_RR_SEMANTICS 2000
+#define OPTION_ASIC_OFFLOAD 2001
+
/* Command line options. */
const struct option longopts[] = {
{"batch", no_argument, NULL, 'b'},
@@ -92,6 +94,7 @@ const struct option longopts[] = {
{"retain", no_argument, NULL, 'r'},
{"vrfdefaultname", required_argument, NULL, 'o'},
{"graceful_restart", required_argument, NULL, 'K'},
+ {"asic-offload", optional_argument, NULL, OPTION_ASIC_OFFLOAD},
#ifdef HAVE_NETLINK
{"vrfwnetns", no_argument, NULL, 'n'},
{"nl-bufsize", required_argument, NULL, 's'},
@@ -281,6 +284,8 @@ int main(int argc, char **argv)
char *vrf_default_name_configured = NULL;
struct sockaddr_storage dummy;
socklen_t dummylen;
+ bool asic_offload = false;
+ bool notify_on_ack = true;
graceful_restart = 0;
vrf_configure_backend(VRF_BACKEND_VRF_LITE);
@@ -301,6 +306,7 @@ int main(int argc, char **argv)
" -r, --retain When program terminates, retain added route by zebra.\n"
" -o, --vrfdefaultname Set default VRF name.\n"
" -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n"
+ " -A, --asic-offload FRR is interacting with an asic underneath the linux kernel\n"
#ifdef HAVE_NETLINK
" -n, --vrfwnetns Use NetNS as VRF backend\n"
" -s, --nl-bufsize Set netlink receive buffer size\n"
@@ -366,6 +372,13 @@ int main(int argc, char **argv)
case OPTION_V6_RR_SEMANTICS:
v6_rr_semantics = true;
break;
+ case OPTION_ASIC_OFFLOAD:
+ if (!strcmp(optarg, "notify_on_offload"))
+ notify_on_ack = false;
+ if (!strcmp(optarg, "notify_on_ack"))
+ notify_on_ack = true;
+ asic_offload = true;
+ break;
#endif /* HAVE_NETLINK */
default:
frr_help_exit(1);
@@ -376,7 +389,7 @@ int main(int argc, char **argv)
zrouter.master = frr_init();
/* Zebra related initialize. */
- zebra_router_init();
+ zebra_router_init(asic_offload, notify_on_ack);
zserv_init();
rib_init();
zebra_if_init();
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index ef51989a0c..3402edf467 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -642,7 +642,9 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
selfroute = is_selfroute(rtm->rtm_protocol);
- if (!startup && selfroute && h->nlmsg_type == RTM_NEWROUTE) {
+ if (!startup && selfroute
+ && h->nlmsg_type == RTM_NEWROUTE
+ && !zrouter.asic_offloaded) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("Route type: %d Received that we think we have originated, ignoring",
rtm->rtm_protocol);
@@ -672,6 +674,8 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
flags |= ZEBRA_FLAG_TRAPPED;
if (rtm->rtm_flags & RTM_F_OFFLOAD)
flags |= ZEBRA_FLAG_OFFLOADED;
+ if (rtm->rtm_flags & RTM_F_OFFLOAD_FAILED)
+ flags |= ZEBRA_FLAG_OFFLOAD_FAILED;
/* Route which inserted by Zebra. */
if (selfroute) {
@@ -3179,10 +3183,14 @@ ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, void *data,
update_flags = dplane_ctx_mac_get_update_flags(ctx);
if (update_flags & DPLANE_MAC_REMOTE) {
flags |= NTF_SELF;
- if (dplane_ctx_mac_is_sticky(ctx))
+ if (dplane_ctx_mac_is_sticky(ctx)) {
+ /* NUD_NOARP prevents the entry from expiring */
+ state |= NUD_NOARP;
+ /* sticky the entry from moving */
flags |= NTF_STICKY;
- else
+ } else {
flags |= NTF_EXT_LEARNED;
+ }
/* if it was static-local previously we need to clear the
* notify flags on replace with remote
*/
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 18017c9700..1d68019909 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -742,7 +742,8 @@ static int nhg_notify(uint16_t type, uint16_t instance, uint32_t id,
static int route_notify_internal(const struct prefix *p, int type,
uint16_t instance, vrf_id_t vrf_id,
uint32_t table_id,
- enum zapi_route_notify_owner note)
+ enum zapi_route_notify_owner note,
+ afi_t afi, safi_t safi)
{
struct zserv *client;
struct stream *s;
@@ -778,16 +779,21 @@ static int route_notify_internal(const struct prefix *p, int type,
stream_putl(s, table_id);
+ /* Encode AFI, SAFI in the message */
+ stream_putc(s, afi);
+ stream_putc(s, safi);
+
stream_putw_at(s, 0, stream_get_endp(s));
return zserv_send_message(client, s);
}
int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p,
- enum zapi_route_notify_owner note)
+ enum zapi_route_notify_owner note,
+ afi_t afi, safi_t safi)
{
return (route_notify_internal(p, re->type, re->instance, re->vrf_id,
- re->table, note));
+ re->table, note, afi, safi));
}
/*
@@ -801,7 +807,19 @@ int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx,
dplane_ctx_get_instance(ctx),
dplane_ctx_get_vrf(ctx),
dplane_ctx_get_table(ctx),
- note));
+ note,
+ dplane_ctx_get_afi(ctx),
+ dplane_ctx_get_safi(ctx)));
+}
+
+static void zread_route_notify_request(ZAPI_HANDLER_ARGS)
+{
+ uint8_t notify;
+
+ STREAM_GETC(msg, notify);
+ client->notify_owner = notify;
+stream_failure:
+ return;
}
void zsend_rule_notify_owner(const struct zebra_dplane_ctx *ctx,
@@ -3275,6 +3293,7 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover,
[ZEBRA_NHG_ADD] = zread_nhg_add,
[ZEBRA_NHG_DEL] = zread_nhg_del,
+ [ZEBRA_ROUTE_NOTIFY_REQUEST] = zread_route_notify_request,
};
/*
diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h
index 9f23a313bf..efc52059b6 100644
--- a/zebra/zapi_msg.h
+++ b/zebra/zapi_msg.h
@@ -77,7 +77,8 @@ extern int zsend_interface_link_params(struct zserv *zclient,
extern int zsend_pw_update(struct zserv *client, struct zebra_pw *pw);
extern int zsend_route_notify_owner(struct route_entry *re,
const struct prefix *p,
- enum zapi_route_notify_owner note);
+ enum zapi_route_notify_owner note,
+ afi_t afi, safi_t safi);
extern int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx,
enum zapi_route_notify_owner note);
diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c
index df95770307..ea2e20ed3b 100644
--- a/zebra/zebra_nb_config.c
+++ b/zebra/zebra_nb_config.c
@@ -1550,12 +1550,14 @@ int lib_route_map_entry_set_action_source_v4_modify(
if (pif != NULL)
break;
}
- if (pif == NULL) {
- snprintf(args->errmsg, args->errmsg_len,
- "is not a local address: %s",
- yang_dnode_get_string(args->dnode, NULL));
- return NB_ERR_VALIDATION;
- }
+ /*
+ * On startup the local address *may* not have come up
+ * yet. We need to allow startup configuration of
+ * set src or we are fudged. Log it for future fun
+ */
+ if (pif == NULL)
+ zlog_warn("set src %pI4 is not a local address",
+ &p.u.prefix4);
return NB_OK;
case NB_EV_PREPARE:
case NB_EV_ABORT:
@@ -1618,12 +1620,14 @@ int lib_route_map_entry_set_action_source_v6_modify(
if (pif != NULL)
break;
}
- if (pif == NULL) {
- snprintf(args->errmsg, args->errmsg_len,
- "is not a local adddress: %s",
- yang_dnode_get_string(args->dnode, NULL));
- return NB_ERR_VALIDATION;
- }
+ /*
+ * On startup the local address *may* not have come up
+ * yet. We need to allow startup configuration of
+ * set src or we are fudged. Log it for future fun
+ */
+ if (pif == NULL)
+ zlog_warn("set src %pI6 is not a local address",
+ &p.u.prefix6);
return NB_OK;
case NB_EV_PREPARE:
case NB_EV_ABORT:
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index e76ecc85a6..569b23573c 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -481,7 +481,8 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re,
* know that they've lost
*/
if (old && (old != re) && (old->type != re->type))
- zsend_route_notify_owner(old, p, ZAPI_ROUTE_BETTER_ADMIN_WON);
+ zsend_route_notify_owner(old, p, ZAPI_ROUTE_BETTER_ADMIN_WON,
+ info->afi, info->safi);
/* Update fib selection */
dest->selected_fib = re;
@@ -1748,6 +1749,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
uint32_t seq;
rib_dest_t *dest;
bool fib_changed = false;
+ struct rib_table_info *info;
zvrf = vrf_info_lookup(dplane_ctx_get_vrf(ctx));
vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
@@ -1767,6 +1769,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
dest = rib_dest_from_rnode(rn);
srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx);
+ info = srcdest_rnode_table_info(rn);
op = dplane_ctx_get_op(ctx);
status = dplane_ctx_get_status(ctx);
@@ -1818,8 +1821,12 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
"%s(%u):%pFX Stale dplane result for re %p",
VRF_LOGNAME(vrf),
dplane_ctx_get_vrf(ctx), dest_pfx, re);
- } else
- UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
+ } else {
+ if (!zrouter.asic_offloaded ||
+ (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED) ||
+ CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED)))
+ UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
+ }
}
if (old_re) {
@@ -1896,8 +1903,23 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
zvrf->installs++;
/* Notify route owner */
- zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED);
-
+ if (zebra_router_notify_on_ack())
+ zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED);
+ else {
+ if (re) {
+ if (CHECK_FLAG(re->flags,
+ ZEBRA_FLAG_OFFLOADED))
+ zsend_route_notify_owner_ctx(
+ ctx,
+ ZAPI_ROUTE_INSTALLED);
+ if (CHECK_FLAG(
+ re->flags,
+ ZEBRA_FLAG_OFFLOAD_FAILED))
+ zsend_route_notify_owner_ctx(
+ ctx,
+ ZAPI_ROUTE_FAIL_INSTALL);
+ }
+ }
} else {
if (re) {
SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
@@ -1906,7 +1928,8 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx)
SET_FLAG(old_re->status, ROUTE_ENTRY_FAILED);
if (re)
zsend_route_notify_owner(re, dest_pfx,
- ZAPI_ROUTE_FAIL_INSTALL);
+ ZAPI_ROUTE_FAIL_INSTALL,
+ info->afi, info->safi);
zlog_warn("%s(%u:%u):%pFX: Route install failed",
VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx),
@@ -2063,7 +2086,8 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx)
}
/* Ensure we clear the QUEUED flag */
- UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
+ if (!zrouter.asic_offloaded)
+ UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
/* Is this a notification that ... matters? We mostly care about
* the route that is currently selected for installation; we may also
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index 294f2c17ff..7b0a1e3d9c 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -64,19 +64,17 @@ static void zebra_route_map_set_delay_timer(uint32_t value);
* Match function return 1 if match is success else return 0
*/
static enum route_map_cmd_result_t
-route_match_tag(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_tag(void *rule, const struct prefix *prefix, void *object)
{
route_tag_t *tag;
struct nh_rmap_obj *nh_data;
- if (type == RMAP_ZEBRA) {
- tag = rule;
- nh_data = object;
+ tag = rule;
+ nh_data = object;
+
+ if (nh_data->tag == *tag)
+ return RMAP_MATCH;
- if (nh_data->tag == *tag)
- return RMAP_MATCH;
- }
return RMAP_NOMATCH;
}
@@ -92,25 +90,23 @@ static const struct route_map_rule_cmd route_match_tag_cmd = {
/* `match interface IFNAME' */
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_interface(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_interface(void *rule, const struct prefix *prefix, void *object)
{
struct nh_rmap_obj *nh_data;
char *ifname = rule;
ifindex_t ifindex;
- if (type == RMAP_ZEBRA) {
- if (strcasecmp(ifname, "any") == 0)
- return RMAP_MATCH;
- nh_data = object;
- if (!nh_data || !nh_data->nexthop)
- return RMAP_NOMATCH;
- ifindex = ifname2ifindex(ifname, nh_data->vrf_id);
- if (ifindex == 0)
- return RMAP_NOMATCH;
- if (nh_data->nexthop->ifindex == ifindex)
- return RMAP_MATCH;
- }
+ if (strcasecmp(ifname, "any") == 0)
+ return RMAP_MATCH;
+ nh_data = object;
+ if (!nh_data || !nh_data->nexthop)
+ return RMAP_NOMATCH;
+ ifindex = ifname2ifindex(ifname, nh_data->vrf_id);
+ if (ifindex == 0)
+ return RMAP_NOMATCH;
+ if (nh_data->nexthop->ifindex == ifindex)
+ return RMAP_MATCH;
+
return RMAP_NOMATCH;
}
@@ -938,40 +934,35 @@ DEFPY_YANG (show_ipv6_protocol_nht,
/* Match function return 1 if match is success else return zero. */
static enum route_map_cmd_result_t
-route_match_ip_next_hop(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
{
struct access_list *alist;
struct nh_rmap_obj *nh_data;
struct prefix_ipv4 p;
- if (type == RMAP_ZEBRA) {
- nh_data = object;
- if (!nh_data)
- return RMAP_NOMATCH;
-
- switch (nh_data->nexthop->type) {
- case NEXTHOP_TYPE_IFINDEX:
- /* Interface routes can't match ip next-hop */
- return RMAP_NOMATCH;
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- case NEXTHOP_TYPE_IPV4:
- p.family = AF_INET;
- p.prefix = nh_data->nexthop->gate.ipv4;
- p.prefixlen = IPV4_MAX_BITLEN;
- break;
- default:
- return RMAP_NOMATCH;
- }
- alist = access_list_lookup(AFI_IP, (char *)rule);
- if (alist == NULL)
- return RMAP_NOMATCH;
+ nh_data = object;
+ if (!nh_data)
+ return RMAP_NOMATCH;
- return (access_list_apply(alist, &p) == FILTER_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
+ switch (nh_data->nexthop->type) {
+ case NEXTHOP_TYPE_IFINDEX:
+ /* Interface routes can't match ip next-hop */
+ return RMAP_NOMATCH;
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ case NEXTHOP_TYPE_IPV4:
+ p.family = AF_INET;
+ p.prefix = nh_data->nexthop->gate.ipv4;
+ p.prefixlen = IPV4_MAX_BITLEN;
+ break;
+ default:
+ return RMAP_NOMATCH;
}
- return RMAP_NOMATCH;
+ alist = access_list_lookup(AFI_IP, (char *)rule);
+ if (alist == NULL)
+ return RMAP_NOMATCH;
+
+ return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
/* Route map `ip next-hop' match statement. `arg' should be
@@ -999,39 +990,35 @@ static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
static enum route_map_cmd_result_t
route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct prefix_list *plist;
struct nh_rmap_obj *nh_data;
struct prefix_ipv4 p;
- if (type == RMAP_ZEBRA) {
- nh_data = (struct nh_rmap_obj *)object;
- if (!nh_data)
- return RMAP_NOMATCH;
-
- switch (nh_data->nexthop->type) {
- case NEXTHOP_TYPE_IFINDEX:
- /* Interface routes can't match ip next-hop */
- return RMAP_NOMATCH;
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- case NEXTHOP_TYPE_IPV4:
- p.family = AF_INET;
- p.prefix = nh_data->nexthop->gate.ipv4;
- p.prefixlen = IPV4_MAX_BITLEN;
- break;
- default:
- return RMAP_NOMATCH;
- }
- plist = prefix_list_lookup(AFI_IP, (char *)rule);
- if (plist == NULL)
- return RMAP_NOMATCH;
+ nh_data = (struct nh_rmap_obj *)object;
+ if (!nh_data)
+ return RMAP_NOMATCH;
- return (prefix_list_apply(plist, &p) == PREFIX_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
+ switch (nh_data->nexthop->type) {
+ case NEXTHOP_TYPE_IFINDEX:
+ /* Interface routes can't match ip next-hop */
+ return RMAP_NOMATCH;
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ case NEXTHOP_TYPE_IPV4:
+ p.family = AF_INET;
+ p.prefix = nh_data->nexthop->gate.ipv4;
+ p.prefixlen = IPV4_MAX_BITLEN;
+ break;
+ default:
+ return RMAP_NOMATCH;
}
- return RMAP_NOMATCH;
+ plist = prefix_list_lookup(AFI_IP, (char *)rule);
+ if (plist == NULL)
+ return RMAP_NOMATCH;
+
+ return (prefix_list_apply(plist, &p) == PREFIX_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
@@ -1058,34 +1045,28 @@ static const struct route_map_rule_cmd
zero. */
static enum route_map_cmd_result_t
route_match_address(afi_t afi, void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct access_list *alist;
- if (type == RMAP_ZEBRA) {
- alist = access_list_lookup(afi, (char *)rule);
- if (alist == NULL)
- return RMAP_NOMATCH;
+ alist = access_list_lookup(afi, (char *)rule);
+ if (alist == NULL)
+ return RMAP_NOMATCH;
- return (access_list_apply(alist, prefix) == FILTER_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ return (access_list_apply(alist, prefix) == FILTER_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
static enum route_map_cmd_result_t
-route_match_ip_address(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
{
- return route_match_address(AFI_IP, rule, prefix, type, object);
+ return route_match_address(AFI_IP, rule, prefix, object);
}
static enum route_map_cmd_result_t
-route_match_ipv6_address(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
{
- return route_match_address(AFI_IP6, rule, prefix, type, object);
+ return route_match_address(AFI_IP6, rule, prefix, object);
}
/* Route map `ip address' match statement. `arg' should be
@@ -1121,28 +1102,23 @@ static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
static enum route_map_cmd_result_t
route_match_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object, afi_t afi)
+ void *object, afi_t afi)
{
struct prefix_list *plist;
- if (type == RMAP_ZEBRA) {
- plist = prefix_list_lookup(afi, (char *)rule);
- if (plist == NULL)
- return RMAP_NOMATCH;
+ plist = prefix_list_lookup(afi, (char *)rule);
+ if (plist == NULL)
+ return RMAP_NOMATCH;
- return (prefix_list_apply(plist, prefix) == PREFIX_DENY
- ? RMAP_NOMATCH
- : RMAP_MATCH);
- }
- return RMAP_NOMATCH;
+ return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
+ : RMAP_MATCH);
}
static enum route_map_cmd_result_t
route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
- return (route_match_address_prefix_list(rule, prefix, type, object,
- AFI_IP));
+ return (route_match_address_prefix_list(rule, prefix, object, AFI_IP));
}
static void *route_match_address_prefix_list_compile(const char *arg)
@@ -1165,10 +1141,9 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
- return (route_match_address_prefix_list(rule, prefix, type, object,
- AFI_IP6));
+ return (route_match_address_prefix_list(rule, prefix, object, AFI_IP6));
}
static const struct route_map_rule_cmd
@@ -1183,11 +1158,11 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct nh_rmap_obj *nh_data;
- if (type == RMAP_ZEBRA && prefix->family == AF_INET6) {
+ if (prefix->family == AF_INET6) {
nh_data = (struct nh_rmap_obj *)object;
if (!nh_data)
return RMAP_NOMATCH;
@@ -1195,6 +1170,7 @@ route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
return RMAP_MATCH;
}
+
return RMAP_NOMATCH;
}
@@ -1220,15 +1196,11 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_address_prefix_len(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
uint32_t *prefixlen = (uint32_t *)rule;
- if (type == RMAP_ZEBRA) {
- return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH
- : RMAP_NOMATCH);
- }
- return RMAP_NOMATCH;
+ return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
}
static void *route_match_address_prefix_len_compile(const char *arg)
@@ -1277,34 +1249,30 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
uint32_t *prefixlen = (uint32_t *)rule;
struct nh_rmap_obj *nh_data;
struct prefix_ipv4 p;
- if (type == RMAP_ZEBRA) {
- nh_data = (struct nh_rmap_obj *)object;
- if (!nh_data || !nh_data->nexthop)
- return RMAP_NOMATCH;
+ nh_data = (struct nh_rmap_obj *)object;
+ if (!nh_data || !nh_data->nexthop)
+ return RMAP_NOMATCH;
- switch (nh_data->nexthop->type) {
- case NEXTHOP_TYPE_IFINDEX:
- /* Interface routes can't match ip next-hop */
- return RMAP_NOMATCH;
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- case NEXTHOP_TYPE_IPV4:
- p.family = AF_INET;
- p.prefix = nh_data->nexthop->gate.ipv4;
- p.prefixlen = IPV4_MAX_BITLEN;
- break;
- default:
- return RMAP_NOMATCH;
- }
- return ((p.prefixlen == *prefixlen) ? RMAP_MATCH
- : RMAP_NOMATCH);
+ switch (nh_data->nexthop->type) {
+ case NEXTHOP_TYPE_IFINDEX:
+ /* Interface routes can't match ip next-hop */
+ return RMAP_NOMATCH;
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ case NEXTHOP_TYPE_IPV4:
+ p.family = AF_INET;
+ p.prefix = nh_data->nexthop->gate.ipv4;
+ p.prefixlen = IPV4_MAX_BITLEN;
+ break;
+ default:
+ return RMAP_NOMATCH;
}
- return RMAP_NOMATCH;
+ return ((p.prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
}
static const struct route_map_rule_cmd
@@ -1319,11 +1287,11 @@ static const struct route_map_rule_cmd
static enum route_map_cmd_result_t
route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+ void *object)
{
struct nh_rmap_obj *nh_data;
- if (type == RMAP_ZEBRA && prefix->family == AF_INET) {
+ if (prefix->family == AF_INET) {
nh_data = (struct nh_rmap_obj *)object;
if (!nh_data)
return RMAP_NOMATCH;
@@ -1331,6 +1299,7 @@ route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
return RMAP_MATCH;
}
+
return RMAP_NOMATCH;
}
@@ -1355,21 +1324,17 @@ static const struct route_map_rule_cmd
/* `match source-protocol PROTOCOL' */
static enum route_map_cmd_result_t
-route_match_source_protocol(void *rule, const struct prefix *p,
- route_map_object_t type, void *object)
+route_match_source_protocol(void *rule, const struct prefix *p, void *object)
{
uint32_t *rib_type = (uint32_t *)rule;
struct nh_rmap_obj *nh_data;
- if (type == RMAP_ZEBRA) {
- nh_data = (struct nh_rmap_obj *)object;
- if (!nh_data)
- return RMAP_NOMATCH;
+ nh_data = (struct nh_rmap_obj *)object;
+ if (!nh_data)
+ return RMAP_NOMATCH;
- return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
- : RMAP_NOMATCH);
- }
- return RMAP_NOMATCH;
+ return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
+ : RMAP_NOMATCH);
}
static void *route_match_source_protocol_compile(const char *arg)
@@ -1399,15 +1364,11 @@ static const struct route_map_rule_cmd route_match_source_protocol_cmd = {
/* `source-instance` */
static enum route_map_cmd_result_t
-route_match_source_instance(void *rule, const struct prefix *p,
- route_map_object_t type, void *object)
+route_match_source_instance(void *rule, const struct prefix *p, void *object)
{
uint8_t *instance = (uint8_t *)rule;
struct nh_rmap_obj *nh_data;
- if (type != RMAP_ZEBRA)
- return RMAP_NOMATCH;
-
nh_data = (struct nh_rmap_obj *)object;
if (!nh_data)
return RMAP_NOMATCH;
@@ -1444,15 +1405,13 @@ static const struct route_map_rule_cmd route_match_source_instance_cmd = {
/* Set src. */
static enum route_map_cmd_result_t
-route_set_src(void *rule, const struct prefix *prefix, route_map_object_t type,
- void *object)
+route_set_src(void *rule, const struct prefix *prefix, void *object)
{
struct nh_rmap_obj *nh_data;
- if (type == RMAP_ZEBRA) {
- nh_data = (struct nh_rmap_obj *)object;
- nh_data->nexthop->rmap_src = *(union g_addr *)rule;
- }
+ nh_data = (struct nh_rmap_obj *)object;
+ nh_data->nexthop->rmap_src = *(union g_addr *)rule;
+
return RMAP_OKAY;
}
@@ -1738,7 +1697,7 @@ zebra_route_map_check(int family, int rib_type, uint8_t instance,
if (!rmap && PROTO_RM_NAME(zvrf, family, ZEBRA_ROUTE_MAX))
rmap = PROTO_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX);
if (rmap) {
- ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
+ ret = route_map_apply(rmap, p, &nh_obj);
}
return (ret);
@@ -1782,7 +1741,7 @@ zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
rmap = route_map_lookup_by_name(rmap_name);
if (rmap) {
- ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
+ ret = route_map_apply(rmap, p, &nh_obj);
}
return (ret);
@@ -1810,7 +1769,7 @@ route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto,
if (!rmap && NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX))
rmap = NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX);
if (rmap)
- ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj);
+ ret = route_map_apply(rmap, p, &nh_obj);
return ret;
}
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index fc4390f7f8..249ec38a69 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -257,7 +257,12 @@ void zebra_router_terminate(void)
hash_free(zrouter.iptable_hash);
}
-void zebra_router_init(void)
+bool zebra_router_notify_on_ack(void)
+{
+ return !zrouter.asic_offloaded || zrouter.notify_on_ack;
+}
+
+void zebra_router_init(bool asic_offload, bool notify_on_ack)
{
zrouter.sequence_num = 0;
@@ -291,5 +296,6 @@ void zebra_router_init(void)
hash_create_size(8, zebra_nhg_id_key, zebra_nhg_hash_id_equal,
"Zebra Router Nexthop Groups ID index");
- zrouter.asic_offloaded = false;
+ zrouter.asic_offloaded = asic_offload;
+ zrouter.notify_on_ack = notify_on_ack;
}
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index 8651a01e9f..08c5fcaf8d 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -210,13 +210,14 @@ struct zebra_router {
* Does the underlying system provide an asic offload
*/
bool asic_offloaded;
+ bool notify_on_ack;
};
#define GRACEFUL_RESTART_TIME 60
extern struct zebra_router zrouter;
-extern void zebra_router_init(void);
+extern void zebra_router_init(bool asic_offload, bool notify_on_ack);
extern void zebra_router_cleanup(void);
extern void zebra_router_terminate(void);
@@ -255,6 +256,8 @@ extern void multicast_mode_ipv4_set(enum multicast_mode mode);
extern enum multicast_mode multicast_mode_ipv4_get(void);
+extern bool zebra_router_notify_on_ack(void);
+
/* zebra_northbound.c */
extern const struct frr_yang_module_info frr_zebra_info;
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index ab7d2845e7..ea7baa2565 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -204,12 +204,16 @@ static char re_status_output_char(const struct route_entry *re,
star_p = true;
}
+ if (zrouter.asic_offloaded &&
+ CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
+ return 'q';
+
if (zrouter.asic_offloaded
&& CHECK_FLAG(re->flags, ZEBRA_FLAG_TRAPPED))
return 't';
if (zrouter.asic_offloaded
- && !CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED))
+ && CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED))
return 'o';
if (star_p)
@@ -870,6 +874,9 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED))
json_object_boolean_true_add(json_route, "offloaded");
+ if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED))
+ json_object_boolean_false_add(json_route, "offloaded");
+
if (re->tag)
json_object_int_add(json_route, "tag", re->tag);
@@ -2005,6 +2012,8 @@ static void vty_show_ip_route_summary(struct vty *vty,
#define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
+ uint32_t offload_cnt[ZEBRA_ROUTE_TOTAL + 1];
+ uint32_t trap_cnt[ZEBRA_ROUTE_TOTAL + 1];
uint32_t i;
uint32_t is_ibgp;
json_object *json_route_summary = NULL;
@@ -2012,6 +2021,8 @@ static void vty_show_ip_route_summary(struct vty *vty,
memset(&rib_cnt, 0, sizeof(rib_cnt));
memset(&fib_cnt, 0, sizeof(fib_cnt));
+ memset(&offload_cnt, 0, sizeof(offload_cnt));
+ memset(&trap_cnt, 0, sizeof(trap_cnt));
if (use_json) {
json_route_summary = json_object_new_object();
@@ -2039,6 +2050,20 @@ static void vty_show_ip_route_summary(struct vty *vty,
else
fib_cnt[re->type]++;
}
+
+ if (CHECK_FLAG(re->flags, ZEBRA_FLAG_TRAPPED)) {
+ if (is_ibgp)
+ trap_cnt[ZEBRA_ROUTE_IBGP]++;
+ else
+ trap_cnt[re->type]++;
+ }
+
+ if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED)) {
+ if (is_ibgp)
+ offload_cnt[ZEBRA_ROUTE_IBGP]++;
+ else
+ offload_cnt[re->type]++;
+ }
}
if (!use_json)
@@ -2062,6 +2087,13 @@ static void vty_show_ip_route_summary(struct vty *vty,
json_object_int_add(
json_route_ebgp, "rib",
rib_cnt[ZEBRA_ROUTE_BGP]);
+ json_object_int_add(
+ json_route_ebgp, "fibOffLoaded",
+ offload_cnt[ZEBRA_ROUTE_BGP]);
+ json_object_int_add(
+ json_route_ebgp, "fibTrapped",
+ trap_cnt[ZEBRA_ROUTE_BGP]);
+
json_object_string_add(json_route_ebgp,
"type", "ebgp");
json_object_array_add(json_route_routes,
@@ -2076,6 +2108,12 @@ static void vty_show_ip_route_summary(struct vty *vty,
json_object_int_add(
json_route_ibgp, "rib",
rib_cnt[ZEBRA_ROUTE_IBGP]);
+ json_object_int_add(
+ json_route_ibgp, "fibOffLoaded",
+ offload_cnt[ZEBRA_ROUTE_IBGP]);
+ json_object_int_add(
+ json_route_ibgp, "fibTrapped",
+ trap_cnt[ZEBRA_ROUTE_IBGP]);
json_object_string_add(json_route_ibgp,
"type", "ibgp");
json_object_array_add(json_route_routes,
@@ -2099,6 +2137,13 @@ static void vty_show_ip_route_summary(struct vty *vty,
"fib", fib_cnt[i]);
json_object_int_add(json_route_type,
"rib", rib_cnt[i]);
+
+ json_object_int_add(json_route_type,
+ "fibOffLoaded",
+ offload_cnt[i]);
+ json_object_int_add(json_route_type,
+ "fibTrapped",
+ trap_cnt[i]);
json_object_string_add(
json_route_type, "type",
zebra_route_string(i));