summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--babeld/babel_interface.c7
-rw-r--r--bfdd/bfd.c543
-rw-r--r--bfdd/bfd.h59
-rw-r--r--bfdd/bfd_packet.c62
-rw-r--r--bfdd/bfdd_vty.c112
-rw-r--r--bfdd/config.c48
-rw-r--r--bfdd/control.c25
-rw-r--r--bfdd/ptm_adapter.c133
-rw-r--r--bgpd/bgp_advertise.c10
-rw-r--r--bgpd/bgp_aspath.c122
-rw-r--r--bgpd/bgp_aspath.h7
-rw-r--r--bgpd/bgp_attr.c20
-rw-r--r--bgpd/bgp_attr_evpn.c10
-rw-r--r--bgpd/bgp_attr_evpn.h2
-rw-r--r--bgpd/bgp_clist.c9
-rw-r--r--bgpd/bgp_community.c118
-rw-r--r--bgpd/bgp_community.h6
-rw-r--r--bgpd/bgp_ecommunity.c118
-rw-r--r--bgpd/bgp_ecommunity.h10
-rw-r--r--bgpd/bgp_encap_tlv.c3
-rw-r--r--bgpd/bgp_evpn.c29
-rw-r--r--bgpd/bgp_evpn.h3
-rw-r--r--bgpd/bgp_evpn_vty.c3
-rw-r--r--bgpd/bgp_filter.c6
-rw-r--r--bgpd/bgp_fsm.c6
-rw-r--r--bgpd/bgp_labelpool.c6
-rw-r--r--bgpd/bgp_lcommunity.c126
-rw-r--r--bgpd/bgp_lcommunity.h10
-rw-r--r--bgpd/bgp_mac.c33
-rw-r--r--bgpd/bgp_mac.h1
-rw-r--r--bgpd/bgp_mpath.c2
-rw-r--r--bgpd/bgp_mplsvpn.c3
-rw-r--r--bgpd/bgp_pbr.c6
-rw-r--r--bgpd/bgp_rd.c3
-rw-r--r--bgpd/bgp_route.c559
-rw-r--r--bgpd/bgp_route.h70
-rw-r--r--bgpd/bgp_routemap.c67
-rw-r--r--bgpd/bgp_snmp.c14
-rw-r--r--bgpd/bgp_updgrp.c36
-rw-r--r--bgpd/bgp_updgrp_packet.c3
-rw-r--r--bgpd/bgp_vty.c182
-rw-r--r--bgpd/bgp_zebra.c67
-rw-r--r--bgpd/bgpd.c61
-rw-r--r--bgpd/bgpd.h9
-rw-r--r--bgpd/rfapi/bgp_rfapi_cfg.c9
-rw-r--r--bgpd/rfapi/rfapi_import.c6
-rw-r--r--bgpd/rfapi/vnc_debug.c2
-rw-r--r--bgpd/rfapi/vnc_zebra.c12
-rwxr-xr-xconfigure.ac2
-rw-r--r--doc/user/installation.rst3
-rw-r--r--eigrpd/eigrp_fsm.c2
-rw-r--r--eigrpd/eigrp_hello.c4
-rw-r--r--eigrpd/eigrp_main.c5
-rw-r--r--eigrpd/eigrp_vty.c4
-rw-r--r--eigrpd/eigrpd.c7
-rw-r--r--isisd/dict.c8
-rw-r--r--isisd/isis_adjacency.c9
-rw-r--r--isisd/isis_circuit.c7
-rw-r--r--isisd/isis_circuit.h2
-rw-r--r--isisd/isis_dlpi.c2
-rw-r--r--isisd/isis_main.c2
-rw-r--r--isisd/isis_northbound.c4
-rw-r--r--isisd/isis_pdu.c16
-rw-r--r--isisd/isis_redist.c3
-rw-r--r--isisd/isis_tlvs.c5
-rw-r--r--isisd/isisd.c5
-rw-r--r--lib/command.c45
-rw-r--r--lib/command_graph.c2
-rw-r--r--lib/distribute.c27
-rw-r--r--lib/event_counter.c2
-rw-r--r--lib/filter.c12
-rw-r--r--lib/frr_pthread.c3
-rw-r--r--lib/frr_zmq.c4
-rw-r--r--lib/frrstr.c4
-rw-r--r--lib/hash.c5
-rw-r--r--lib/if.c12
-rw-r--r--lib/if_rmap.c118
-rw-r--r--lib/if_rmap.h33
-rw-r--r--lib/imsg.c3
-rw-r--r--lib/jhash.c4
-rw-r--r--lib/keychain.c6
-rw-r--r--lib/libfrr.c2
-rw-r--r--lib/log.c6
-rw-r--r--lib/module.c3
-rw-r--r--lib/netns_linux.c3
-rw-r--r--lib/nexthop.h1
-rw-r--r--lib/nexthop_group.c6
-rw-r--r--lib/northbound.c94
-rw-r--r--lib/northbound_confd.c2
-rw-r--r--lib/plist.c6
-rw-r--r--lib/pqueue.c2
-rw-r--r--lib/prefix.c15
-rw-r--r--lib/privs.c19
-rw-r--r--lib/privs.h10
-rw-r--r--lib/routemap.c15
-rw-r--r--lib/thread.c8
-rw-r--r--lib/vty.c21
-rw-r--r--lib/workqueue.c2
-rw-r--r--lib/yang_translator.c2
-rw-r--r--lib/yang_wrappers.c2
-rw-r--r--nhrpd/netlink_arp.c4
-rw-r--r--ospf6d/ospf6_interface.c3
-rw-r--r--ospf6d/ospf6_lsa.c13
-rw-r--r--ospf6d/ospf6_lsdb.c4
-rw-r--r--ospf6d/ospf6_message.c6
-rw-r--r--ospf6d/ospf6_neighbor.c5
-rw-r--r--ospf6d/ospf6_route.c3
-rw-r--r--ospf6d/ospf6_snmp.c22
-rw-r--r--ospf6d/ospf6_spf.c6
-rw-r--r--ospfd/ospf_asbr.c3
-rw-r--r--ospfd/ospf_dump.c3
-rw-r--r--ospfd/ospf_ism.c4
-rw-r--r--ospfd/ospf_snmp.c34
-rw-r--r--ospfd/ospf_vty.c49
-rw-r--r--ospfd/ospf_zebra.c6
-rw-r--r--pbrd/pbr_map.c3
-rw-r--r--pbrd/pbr_nht.c2
-rw-r--r--pimd/pim_cmd.c16
-rw-r--r--pimd/pim_iface.c3
-rw-r--r--pimd/pim_main.c2
-rw-r--r--pimd/pim_msdp.c3
-rw-r--r--pimd/pim_register.c4
-rw-r--r--pimd/pim_rp.c3
-rw-r--r--pimd/pim_ssm.c3
-rw-r--r--ripd/rip_cli.c17
-rw-r--r--ripd/rip_interface.c6
-rw-r--r--ripd/rip_northbound.c6
-rw-r--r--ripd/ripd.c61
-rw-r--r--ripd/ripd.h6
-rw-r--r--ripngd/ripngd.c37
-rw-r--r--ripngd/ripngd.h3
-rw-r--r--sharpd/sharp_globals.h1
-rw-r--r--sharpd/sharp_vty.c69
-rw-r--r--sharpd/sharp_zebra.c33
-rw-r--r--sharpd/sharp_zebra.h19
-rw-r--r--staticd/static_vty.c36
-rw-r--r--tests/bgpd/test_bgp_table.c2
-rw-r--r--tests/bgpd/test_mpath.c7
-rw-r--r--tests/lib/test_privs.c2
-rw-r--r--tests/lib/test_srcdest_table.c2
-rw-r--r--tests/lib/test_table.c2
-rw-r--r--tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref2
-rw-r--r--tests/topotests/bfd-topo2/__init__.py0
-rw-r--r--tests/topotests/bfd-topo2/r1/bfdd.conf5
-rw-r--r--tests/topotests/bfd-topo2/r1/bgpd.conf13
-rw-r--r--tests/topotests/bfd-topo2/r1/ipv4_routes.json68
-rw-r--r--tests/topotests/bfd-topo2/r1/ipv6_routes.json63
-rw-r--r--tests/topotests/bfd-topo2/r1/peers.json29
-rw-r--r--tests/topotests/bfd-topo2/r1/zebra.conf6
-rw-r--r--tests/topotests/bfd-topo2/r2/bgpd.conf16
-rw-r--r--tests/topotests/bfd-topo2/r2/ipv4_routes.json108
-rw-r--r--tests/topotests/bfd-topo2/r2/ipv6_routes.json63
-rw-r--r--tests/topotests/bfd-topo2/r2/ospf6d.conf9
-rw-r--r--tests/topotests/bfd-topo2/r2/ospfd.conf9
-rw-r--r--tests/topotests/bfd-topo2/r2/peers.json42
-rw-r--r--tests/topotests/bfd-topo2/r2/zebra.conf15
-rw-r--r--tests/topotests/bfd-topo2/r3/ipv4_routes.json109
-rw-r--r--tests/topotests/bfd-topo2/r3/ipv6_routes.json2
-rw-r--r--tests/topotests/bfd-topo2/r3/ospfd.conf8
-rw-r--r--tests/topotests/bfd-topo2/r3/peers.json16
-rw-r--r--tests/topotests/bfd-topo2/r3/zebra.conf6
-rw-r--r--tests/topotests/bfd-topo2/r4/bfdd.conf5
-rw-r--r--tests/topotests/bfd-topo2/r4/ipv4_routes.json24
-rw-r--r--tests/topotests/bfd-topo2/r4/ipv6_routes.json63
-rw-r--r--tests/topotests/bfd-topo2/r4/ospf6d.conf8
-rw-r--r--tests/topotests/bfd-topo2/r4/peers.json29
-rw-r--r--tests/topotests/bfd-topo2/r4/zebra.conf6
-rw-r--r--tests/topotests/bfd-topo2/test_bfd_topo2.dot73
-rw-r--r--tests/topotests/bfd-topo2/test_bfd_topo2.jpgbin0 -> 24206 bytes
-rw-r--r--tests/topotests/bfd-topo2/test_bfd_topo2.py191
-rw-r--r--tools/coccinelle/alloc_cast.cocci101
-rw-r--r--tools/coccinelle/array_size.cocci83
-rw-r--r--tools/coccinelle/badty.cocci76
-rw-r--r--tools/coccinelle/badzero.cocci238
-rw-r--r--tools/coccinelle/boolconv.cocci90
-rw-r--r--tools/coccinelle/boolinit.cocci194
-rw-r--r--tools/coccinelle/boolreturn.cocci59
-rw-r--r--tools/coccinelle/cond_no_effect.cocci64
-rw-r--r--tools/coccinelle/deref_null.cocci282
-rw-r--r--tools/coccinelle/double_lock.cocci92
-rw-r--r--tools/coccinelle/doublebitand.cocci54
-rw-r--r--tools/coccinelle/doubleinit.cocci53
-rw-r--r--tools/coccinelle/doubletest.cocci58
-rw-r--r--tools/coccinelle/ifaddr.cocci34
-rw-r--r--tools/coccinelle/ifnullxfree.cocci15
-rw-r--r--tools/coccinelle/itnull.cocci94
-rw-r--r--tools/coccinelle/mini_lock.cocci98
-rw-r--r--tools/coccinelle/noderef.cocci81
-rw-r--r--tools/coccinelle/replace-strncpy.cocci8
-rw-r--r--tools/coccinelle/returnvar.cocci66
-rw-r--r--tools/coccinelle/semicolon.cocci83
-rw-r--r--tools/coccinelle/strncpy_truncation.cocci41
-rw-r--r--tools/coccinelle/unsigned_lesser_than_zero.cocci75
-rw-r--r--tools/coccinelle/vty_check.cocci (renamed from tools/vty_check.cocci)0
-rw-r--r--tools/coccinelle/vty_index.cocci (renamed from tools/vty_index.cocci)0
-rw-r--r--tools/coccinelle/xcalloc-simple.cocci52
-rw-r--r--tools/coccinelle/xfree.cocci122
-rw-r--r--tools/coccinelle/xfreeaddr.cocci33
-rw-r--r--tools/coccinelle/xmalloc_returnval.cocci37
-rw-r--r--tools/coccinelle/zprivs.cocci (renamed from tools/zprivs.cocci)0
-rw-r--r--vtysh/vtysh.c4
-rw-r--r--vtysh/vtysh_config.c3
-rw-r--r--vtysh/vtysh_user.c2
-rw-r--r--zebra/connected.c2
-rw-r--r--zebra/if_netlink.c3
-rw-r--r--zebra/rt_netlink.c133
-rw-r--r--zebra/zapi_msg.c26
-rw-r--r--zebra/zebra_dplane.c77
-rw-r--r--zebra/zebra_dplane.h9
-rw-r--r--zebra/zebra_mpls.c21
-rw-r--r--zebra/zebra_mpls_openbsd.c10
-rw-r--r--zebra/zebra_pbr.c2
-rw-r--r--zebra/zebra_ptm.c2
-rw-r--r--zebra/zebra_rib.c20
-rw-r--r--zebra/zebra_routemap.c6
-rw-r--r--zebra/zebra_router.c21
-rw-r--r--zebra/zebra_router.h2
-rw-r--r--zebra/zebra_vrf.c16
-rw-r--r--zebra/zebra_vty.c5
-rw-r--r--zebra/zebra_vxlan.c82
220 files changed, 5824 insertions, 1753 deletions
diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c
index 79242f5b85..0ff89abc49 100644
--- a/babeld/babel_interface.c
+++ b/babeld/babel_interface.c
@@ -1414,12 +1414,7 @@ static babel_interface_nfo *
babel_interface_allocate (void)
{
babel_interface_nfo *babel_ifp;
- babel_ifp = XMALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo));
- if(babel_ifp == NULL)
- return NULL;
-
- /* Here are set the default values for an interface. */
- memset(babel_ifp, 0, sizeof(babel_interface_nfo));
+ babel_ifp = XCALLOC(MTYPE_BABEL_IF, sizeof(babel_interface_nfo));
/* All flags are unset */
babel_ifp->bucket_time = babel_now.tv_sec;
babel_ifp->bucket = BUCKET_TOKENS_MAX;
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index afd5d814a0..c8adf82a83 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -36,7 +36,9 @@ DEFINE_QOBJ_TYPE(bfd_session);
/*
* Prototypes
*/
-static struct bfd_session *bs_peer_waiting_find(struct bfd_peer_cfg *bpc);
+void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer,
+ struct sockaddr_any *local, bool mhop, const char *ifname,
+ const char *vrfname);
static uint32_t ptm_bfd_gen_ID(void);
static void ptm_bfd_echo_xmt_TO(struct bfd_session *bfd);
@@ -52,66 +54,47 @@ static void bs_down_handler(struct bfd_session *bs, int nstate);
static void bs_init_handler(struct bfd_session *bs, int nstate);
static void bs_up_handler(struct bfd_session *bs, int nstate);
+/* Zeroed array with the size of an IPv6 address. */
+struct in6_addr zero_addr;
/*
* Functions
*/
-static struct bfd_session *bs_peer_waiting_find(struct bfd_peer_cfg *bpc)
+void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer,
+ struct sockaddr_any *local, bool mhop, const char *ifname,
+ const char *vrfname)
{
- struct bfd_session_observer *bso;
- struct bfd_session *bs = NULL;
- bool is_shop, is_ipv4;
-
- TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
- bs = bso->bso_bs;
-
- is_shop = !BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH);
- is_ipv4 = !BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6);
- /* Quick checks first. */
- if (is_shop != (!bpc->bpc_mhop))
- continue;
- if (is_ipv4 != bpc->bpc_ipv4)
- continue;
-
- /*
- * Slow lookup without hash because we don't have all
- * information yet.
- */
- if (is_shop) {
- if (strcmp(bs->ifname, bpc->bpc_localif))
- continue;
- if (memcmp(&bs->shop.peer, &bpc->bpc_peer,
- sizeof(bs->shop.peer)))
- continue;
-
- break;
- }
-
- if (strcmp(bs->vrfname, bpc->bpc_vrfname))
- continue;
- if (memcmp(&bs->mhop.peer, &bpc->bpc_peer,
- sizeof(bs->mhop.peer)))
- continue;
- if (memcmp(&bs->mhop.local, &bpc->bpc_local,
- sizeof(bs->mhop.local)))
- continue;
+ memset(key, 0, sizeof(*key));
+ switch (peer->sa_sin.sin_family) {
+ case AF_INET:
+ key->family = AF_INET;
+ memcpy(&key->peer, &peer->sa_sin.sin_addr,
+ sizeof(peer->sa_sin.sin_addr));
+ memcpy(&key->local, &local->sa_sin.sin_addr,
+ sizeof(local->sa_sin.sin_addr));
+ break;
+ case AF_INET6:
+ key->family = AF_INET6;
+ memcpy(&key->peer, &peer->sa_sin6.sin6_addr,
+ sizeof(peer->sa_sin6.sin6_addr));
+ memcpy(&key->local, &local->sa_sin6.sin6_addr,
+ sizeof(local->sa_sin6.sin6_addr));
break;
}
- if (bso == NULL)
- bs = NULL;
- return bs;
+ key->mhop = mhop;
+ if (ifname && ifname[0])
+ strlcpy(key->ifname, ifname, sizeof(key->ifname));
+ if (vrfname && vrfname[0])
+ strlcpy(key->vrfname, vrfname, sizeof(key->vrfname));
}
struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc)
{
struct bfd_session *bs;
struct peer_label *pl;
- struct interface *ifp;
- struct vrf *vrf;
- struct bfd_mhop_key mhop;
- struct bfd_shop_key shop;
+ struct bfd_key key;
/* Try to find label first. */
if (bpc->bpc_has_label) {
@@ -123,38 +106,10 @@ struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc)
}
/* Otherwise fallback to peer/local hash lookup. */
- if (bpc->bpc_mhop) {
- memset(&mhop, 0, sizeof(mhop));
- mhop.peer = bpc->bpc_peer;
- mhop.local = bpc->bpc_local;
- if (bpc->bpc_has_vrfname) {
- vrf = vrf_lookup_by_name(bpc->bpc_vrfname);
- if (vrf == NULL)
- return NULL;
-
- mhop.vrfid = vrf->vrf_id;
- }
+ gen_bfd_key(&key, &bpc->bpc_peer, &bpc->bpc_local, bpc->bpc_mhop,
+ bpc->bpc_localif, bpc->bpc_vrfname);
- bs = bfd_mhop_lookup(mhop);
- } else {
- memset(&shop, 0, sizeof(shop));
- shop.peer = bpc->bpc_peer;
- if (bpc->bpc_has_localif) {
- ifp = if_lookup_by_name_all_vrf(bpc->bpc_localif);
- if (ifp == NULL)
- return NULL;
-
- shop.ifindex = ifp->ifindex;
- }
-
- bs = bfd_shop_lookup(shop);
- }
-
- if (bs != NULL)
- return bs;
-
- /* Search for entries that are incomplete. */
- return bs_peer_waiting_find(bpc);
+ return bfd_key_lookup(key);
}
/*
@@ -165,7 +120,6 @@ struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc)
*/
int bfd_session_enable(struct bfd_session *bs)
{
- struct sockaddr_in6 *sin6;
struct interface *ifp = NULL;
struct vrf *vrf = NULL;
int psock;
@@ -174,8 +128,8 @@ int bfd_session_enable(struct bfd_session *bs)
* If the interface or VRF doesn't exist, then we must register
* the session but delay its start.
*/
- if (bs->ifname[0] != 0) {
- ifp = if_lookup_by_name_all_vrf(bs->ifname);
+ if (bs->key.ifname[0]) {
+ ifp = if_lookup_by_name_all_vrf(bs->key.ifname);
if (ifp == NULL) {
log_error(
"session-enable: specified interface doesn't exists.");
@@ -184,15 +138,17 @@ int bfd_session_enable(struct bfd_session *bs)
vrf = vrf_lookup_by_id(ifp->vrf_id);
if (vrf == NULL) {
- log_error("session-enable: specified VRF doesn't exists.");
+ log_error(
+ "session-enable: specified VRF doesn't exists.");
return 0;
}
}
- if (bs->vrfname[0] != 0) {
- vrf = vrf_lookup_by_name(bs->vrfname);
+ if (bs->key.vrfname[0]) {
+ vrf = vrf_lookup_by_name(bs->key.vrfname);
if (vrf == NULL) {
- log_error("session-enable: specified VRF doesn't exists.");
+ log_error(
+ "session-enable: specified VRF doesn't exists.");
return 0;
}
}
@@ -202,26 +158,15 @@ int bfd_session_enable(struct bfd_session *bs)
if (bs->vrf == NULL)
bs->vrf = vrf_lookup_by_id(VRF_DEFAULT);
- if (bs->ifname[0] != 0 &&
- BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH) == 0)
+ if (bs->key.ifname[0]
+ && BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH) == 0)
bs->ifp = ifp;
- /* Set the IPv6 scope id for link-local addresses. */
- if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6)) {
- sin6 = &bs->mhop.peer.sa_sin6;
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
- sin6->sin6_scope_id = bs->ifp != NULL
- ? bs->ifp->ifindex
- : IFINDEX_INTERNAL;
-
- sin6 = &bs->mhop.local.sa_sin6;
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
- sin6->sin6_scope_id = bs->ifp != NULL
- ? bs->ifp->ifindex
- : IFINDEX_INTERNAL;
-
- bs->local_ip.sa_sin6 = *sin6;
- bs->local_address.sa_sin6 = *sin6;
+ /* Sanity check: don't leak open sockets. */
+ if (bs->sock != -1) {
+ zlog_debug("session-enable: previous socket open");
+ close(bs->sock);
+ bs->sock = -1;
}
/*
@@ -232,11 +177,11 @@ int bfd_session_enable(struct bfd_session *bs)
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6) == 0) {
psock = bp_peer_socket(bs);
if (psock == -1)
- return -1;
+ return 0;
} else {
psock = bp_peer_socketv6(bs);
if (psock == -1)
- return -1;
+ return 0;
}
/*
@@ -247,25 +192,6 @@ int bfd_session_enable(struct bfd_session *bs)
bfd_recvtimer_update(bs);
ptm_bfd_start_xmt_timer(bs, false);
- /* Registrate session into data structures. */
- bs->discrs.my_discr = ptm_bfd_gen_ID();
- bfd_id_insert(bs);
- if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
- if (vrf != NULL)
- bs->mhop.vrfid = vrf->vrf_id;
- else
- bs->mhop.vrfid = VRF_DEFAULT;
-
- bfd_mhop_insert(bs);
- } else {
- if (ifp != NULL)
- bs->shop.ifindex = ifp->ifindex;
- else
- bs->shop.ifindex = IFINDEX_INTERNAL;
-
- bfd_shop_insert(bs);
- }
-
return 0;
}
@@ -288,13 +214,6 @@ void bfd_session_disable(struct bfd_session *bs)
bfd_echo_recvtimer_delete(bs);
bfd_xmttimer_delete(bs);
bfd_echo_xmttimer_delete(bs);
-
- /* Unregister session from hashes to avoid unwanted activation. */
- bfd_id_delete(bs->discrs.my_discr);
- if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
- bfd_mhop_delete(bs->mhop);
- else
- bfd_shop_delete(bs->shop);
}
static uint32_t ptm_bfd_gen_ID(void)
@@ -438,21 +357,20 @@ static struct bfd_session *bfd_find_disc(struct sockaddr_any *sa,
if (bs == NULL)
return NULL;
- /* Remove unused fields. */
- switch (sa->sa_sin.sin_family) {
+ switch (bs->key.family) {
case AF_INET:
- sa->sa_sin.sin_port = 0;
- if (memcmp(sa, &bs->shop.peer, sizeof(sa->sa_sin)) == 0)
- return bs;
+ if (memcmp(&sa->sa_sin.sin_addr, &bs->key.peer,
+ sizeof(sa->sa_sin.sin_addr)))
+ return NULL;
break;
case AF_INET6:
- sa->sa_sin6.sin6_port = 0;
- if (memcmp(sa, &bs->shop.peer, sizeof(sa->sa_sin6)) == 0)
- return bs;
+ if (memcmp(&sa->sa_sin6.sin6_addr, &bs->key.peer,
+ sizeof(sa->sa_sin6.sin6_addr)))
+ return NULL;
break;
}
- return NULL;
+ return bs;
}
struct bfd_session *ptm_bfd_sess_find(struct bfd_pkt *cp,
@@ -461,32 +379,30 @@ struct bfd_session *ptm_bfd_sess_find(struct bfd_pkt *cp,
ifindex_t ifindex, vrf_id_t vrfid,
bool is_mhop)
{
- struct bfd_session *l_bfd = NULL;
- struct bfd_mhop_key mhop;
- struct bfd_shop_key shop;
+ struct interface *ifp;
+ struct vrf *vrf;
+ struct bfd_key key;
/* Find our session using the ID signaled by the remote end. */
if (cp->discrs.remote_discr)
return bfd_find_disc(peer, ntohl(cp->discrs.remote_discr));
/* Search for session without using discriminator. */
- if (is_mhop) {
- memset(&mhop, 0, sizeof(mhop));
- mhop.peer = *peer;
- mhop.local = *local;
- mhop.vrfid = vrfid;
-
- l_bfd = bfd_mhop_lookup(mhop);
- } else {
- memset(&shop, 0, sizeof(shop));
- shop.peer = *peer;
- shop.ifindex = ifindex;
+ ifp = if_lookup_by_index(ifindex, vrfid);
+ if (vrfid == VRF_DEFAULT) {
+ /*
+ * Don't use the default vrf, otherwise we won't find
+ * sessions that doesn't specify it.
+ */
+ vrf = NULL;
+ } else
+ vrf = vrf_lookup_by_id(vrfid);
- l_bfd = bfd_shop_lookup(shop);
- }
+ gen_bfd_key(&key, peer, local, is_mhop, ifp ? ifp->name : NULL,
+ vrf ? vrf->name : NULL);
/* XXX maybe remoteDiscr should be checked for remoteHeard cases. */
- return l_bfd;
+ return bfd_key_lookup(key);
}
int bfd_xmt_cb(struct thread *t)
@@ -551,8 +467,6 @@ static struct bfd_session *bfd_session_new(void)
struct bfd_session *bs;
bs = XCALLOC(MTYPE_BFDD_CONFIG, sizeof(*bs));
- if (bs == NULL)
- return NULL;
QOBJ_REG(bs, bfd_session);
@@ -703,6 +617,9 @@ static void bfd_session_free(struct bfd_session *bs)
bfd_session_disable(bs);
+ bfd_key_delete(bs->key);
+ bfd_id_delete(bs->discrs.my_discr);
+
/* Remove observer if any. */
TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
if (bso->bso_bs != bs)
@@ -745,29 +662,47 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
* start. See `bfd_session_enable` for more information.
*/
if (bpc->bpc_has_localif)
- strlcpy(bfd->ifname, bpc->bpc_localif, sizeof(bfd->ifname));
+ strlcpy(bfd->key.ifname, bpc->bpc_localif,
+ sizeof(bfd->key.ifname));
if (bpc->bpc_has_vrfname)
- strlcpy(bfd->vrfname, bpc->bpc_vrfname, sizeof(bfd->vrfname));
-
- /* Add observer if we have moving parts. */
- if (bfd->ifname[0] || bfd->vrfname[0])
- bs_observer_add(bfd);
+ strlcpy(bfd->key.vrfname, bpc->bpc_vrfname,
+ sizeof(bfd->key.vrfname));
/* Copy remaining data. */
if (bpc->bpc_ipv4 == false)
BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6);
- if (bpc->bpc_mhop) {
- BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_MH);
- bfd->mhop.peer = bpc->bpc_peer;
- bfd->mhop.local = bpc->bpc_local;
- } else {
- bfd->shop.peer = bpc->bpc_peer;
+ bfd->key.family = (bpc->bpc_ipv4) ? AF_INET : AF_INET6;
+ switch (bfd->key.family) {
+ case AF_INET:
+ memcpy(&bfd->key.peer, &bpc->bpc_peer.sa_sin.sin_addr,
+ sizeof(bpc->bpc_peer.sa_sin.sin_addr));
+ memcpy(&bfd->key.local, &bpc->bpc_local.sa_sin.sin_addr,
+ sizeof(bpc->bpc_local.sa_sin.sin_addr));
+ break;
+
+ case AF_INET6:
+ memcpy(&bfd->key.peer, &bpc->bpc_peer.sa_sin6.sin6_addr,
+ sizeof(bpc->bpc_peer.sa_sin6.sin6_addr));
+ memcpy(&bfd->key.local, &bpc->bpc_local.sa_sin6.sin6_addr,
+ sizeof(bpc->bpc_local.sa_sin6.sin6_addr));
+ break;
+
+ default:
+ assert(1);
+ break;
}
- bfd->local_ip = bpc->bpc_local;
- bfd->local_address = bpc->bpc_local;
+ if (bpc->bpc_mhop)
+ BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_MH);
+
+ bfd->key.mhop = bpc->bpc_mhop;
+
+ /* Registrate session into data structures. */
+ bfd_key_insert(bfd);
+ bfd->discrs.my_discr = ptm_bfd_gen_ID();
+ bfd_id_insert(bfd);
/* Try to enable session and schedule for packet receive/send. */
if (bfd_session_enable(bfd) == -1) {
@@ -776,6 +711,10 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc)
return NULL;
}
+ /* Add observer if we have moving parts. */
+ if (bfd->key.ifname[0] || bfd->key.vrfname[0] || bfd->sock == -1)
+ bs_observer_add(bfd);
+
/* Apply other configurations. */
_bfd_session_update(bfd, bpc);
@@ -1221,35 +1160,26 @@ void integer2timestr(uint64_t time, char *buf, size_t buflen)
snprintf(buf, buflen, "%u second(s)", second);
}
-const char *bs_to_string(struct bfd_session *bs)
+const char *bs_to_string(const struct bfd_session *bs)
{
static char buf[256];
+ char addr_buf[INET6_ADDRSTRLEN];
int pos;
bool is_mhop = BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH);
pos = snprintf(buf, sizeof(buf), "mhop:%s", is_mhop ? "yes" : "no");
- if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
- pos += snprintf(buf + pos, sizeof(buf) - pos,
- " peer:%s local:%s", satostr(&bs->mhop.peer),
- satostr(&bs->mhop.local));
-
- if (bs->mhop.vrfid != VRF_DEFAULT)
- snprintf(buf + pos, sizeof(buf) - pos, " vrf:%u",
- bs->mhop.vrfid);
- } else {
- pos += snprintf(buf + pos, sizeof(buf) - pos, " peer:%s",
- satostr(&bs->shop.peer));
-
- if (bs->local_address.sa_sin.sin_family)
- pos += snprintf(buf + pos, sizeof(buf) - pos,
- " local:%s",
- satostr(&bs->local_address));
-
- if (bs->shop.ifindex)
- snprintf(buf + pos, sizeof(buf) - pos, " ifindex:%u",
- bs->shop.ifindex);
- }
-
+ pos += snprintf(buf + pos, sizeof(buf) - pos, " peer:%s",
+ inet_ntop(bs->key.family, &bs->key.peer, addr_buf,
+ sizeof(addr_buf)));
+ pos += snprintf(buf + pos, sizeof(buf) - pos, " local:%s",
+ inet_ntop(bs->key.family, &bs->key.local, addr_buf,
+ sizeof(addr_buf)));
+ if (bs->key.vrfname[0])
+ pos += snprintf(buf + pos, sizeof(buf) - pos, " vrf:%s",
+ bs->key.vrfname);
+ if (bs->key.ifname[0])
+ pos += snprintf(buf + pos, sizeof(buf) - pos, " ifname:%s",
+ bs->key.ifname);
return buf;
}
@@ -1261,12 +1191,20 @@ int bs_observer_add(struct bfd_session *bs)
bso->bso_bs = bs;
bso->bso_isinterface = !BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH);
if (bso->bso_isinterface)
- strlcpy(bso->bso_entryname, bs->ifname,
+ strlcpy(bso->bso_entryname, bs->key.ifname,
sizeof(bso->bso_entryname));
else
- strlcpy(bso->bso_entryname, bs->vrfname,
+ strlcpy(bso->bso_entryname, bs->key.vrfname,
sizeof(bso->bso_entryname));
+ /* Handle socket binding failures caused by missing local addresses. */
+ if (bs->sock == -1) {
+ bso->bso_isaddress = true;
+ bso->bso_addr.family = bs->key.family;
+ memcpy(&bso->bso_addr.u.prefix, &bs->key.local,
+ sizeof(bs->key.local));
+ }
+
TAILQ_INSERT_TAIL(&bglobal.bg_obslist, bso, bso_entry);
return 0;
@@ -1278,21 +1216,59 @@ void bs_observer_del(struct bfd_session_observer *bso)
XFREE(MTYPE_BFDD_SESSION_OBSERVER, bso);
}
+void bs_to_bpc(struct bfd_session *bs, struct bfd_peer_cfg *bpc)
+{
+ memset(bpc, 0, sizeof(*bpc));
+
+ bpc->bpc_ipv4 = (bs->key.family == AF_INET);
+ bpc->bpc_mhop = bs->key.mhop;
+
+ switch (bs->key.family) {
+ case AF_INET:
+ bpc->bpc_peer.sa_sin.sin_family = AF_INET;
+ memcpy(&bpc->bpc_peer.sa_sin.sin_addr, &bs->key.peer,
+ sizeof(bpc->bpc_peer.sa_sin.sin_addr));
+
+ if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local))) {
+ bpc->bpc_local.sa_sin.sin_family = AF_INET6;
+ memcpy(&bpc->bpc_local.sa_sin.sin_addr, &bs->key.peer,
+ sizeof(bpc->bpc_local.sa_sin.sin_addr));
+ }
+ break;
+
+ case AF_INET6:
+ bpc->bpc_peer.sa_sin.sin_family = AF_INET6;
+ memcpy(&bpc->bpc_peer.sa_sin6.sin6_addr, &bs->key.peer,
+ sizeof(bpc->bpc_peer.sa_sin6.sin6_addr));
+
+ bpc->bpc_local.sa_sin6.sin6_family = AF_INET6;
+ memcpy(&bpc->bpc_local.sa_sin6.sin6_addr, &bs->key.peer,
+ sizeof(bpc->bpc_local.sa_sin6.sin6_addr));
+ break;
+ }
+
+ if (bs->key.ifname[0]) {
+ bpc->bpc_has_localif = true;
+ strlcpy(bpc->bpc_localif, bs->key.ifname,
+ sizeof(bpc->bpc_localif));
+ }
+
+ if (bs->key.vrfname[0]) {
+ bpc->bpc_has_vrfname = true;
+ strlcpy(bpc->bpc_vrfname, bs->key.vrfname,
+ sizeof(bpc->bpc_vrfname));
+ }
+}
+
/*
* BFD hash data structures to find sessions.
*/
static struct hash *bfd_id_hash;
-static struct hash *bfd_shop_hash;
-static struct hash *bfd_mhop_hash;
+static struct hash *bfd_key_hash;
static unsigned int bfd_id_hash_do(void *p);
-static unsigned int bfd_shop_hash_do(void *p);
-static unsigned int bfd_mhop_hash_do(void *p);
-
-static void _shop_key(struct bfd_session *bs, const struct bfd_shop_key *shop);
-static void _shop_key2(struct bfd_session *bs, const struct bfd_shop_key *shop);
-static void _mhop_key(struct bfd_session *bs, const struct bfd_mhop_key *mhop);
+static unsigned int bfd_key_hash_do(void *p);
static void _bfd_free(struct hash_bucket *hb,
void *arg __attribute__((__unused__)));
@@ -1313,73 +1289,20 @@ static bool bfd_id_hash_cmp(const void *n1, const void *n2)
}
/* BFD hash for single hop. */
-static unsigned int bfd_shop_hash_do(void *p)
-{
- struct bfd_session *bs = p;
-
- return jhash(&bs->shop, sizeof(bs->shop), 0);
-}
-
-static bool bfd_shop_hash_cmp(const void *n1, const void *n2)
-{
- const struct bfd_session *bs1 = n1, *bs2 = n2;
-
- return memcmp(&bs1->shop, &bs2->shop, sizeof(bs1->shop)) == 0;
-}
-
-/* BFD hash for multi hop. */
-static unsigned int bfd_mhop_hash_do(void *p)
+static unsigned int bfd_key_hash_do(void *p)
{
struct bfd_session *bs = p;
- return jhash(&bs->mhop, sizeof(bs->mhop), 0);
+ return jhash(&bs->key, sizeof(bs->key), 0);
}
-static bool bfd_mhop_hash_cmp(const void *n1, const void *n2)
+static bool bfd_key_hash_cmp(const void *n1, const void *n2)
{
const struct bfd_session *bs1 = n1, *bs2 = n2;
- return memcmp(&bs1->mhop, &bs2->mhop, sizeof(bs1->mhop)) == 0;
+ return memcmp(&bs1->key, &bs2->key, sizeof(bs1->key)) == 0;
}
-/* Helper functions */
-static void _shop_key(struct bfd_session *bs, const struct bfd_shop_key *shop)
-{
- bs->shop = *shop;
-
- /* Remove unused fields. */
- switch (bs->shop.peer.sa_sin.sin_family) {
- case AF_INET:
- bs->shop.peer.sa_sin.sin_port = 0;
- break;
- case AF_INET6:
- bs->shop.peer.sa_sin6.sin6_port = 0;
- break;
- }
-}
-
-static void _shop_key2(struct bfd_session *bs, const struct bfd_shop_key *shop)
-{
- _shop_key(bs, shop);
- bs->shop.ifindex = IFINDEX_INTERNAL;
-}
-
-static void _mhop_key(struct bfd_session *bs, const struct bfd_mhop_key *mhop)
-{
- bs->mhop = *mhop;
-
- /* Remove unused fields. */
- switch (bs->mhop.peer.sa_sin.sin_family) {
- case AF_INET:
- bs->mhop.peer.sa_sin.sin_port = 0;
- bs->mhop.local.sa_sin.sin_port = 0;
- break;
- case AF_INET6:
- bs->mhop.peer.sa_sin6.sin6_port = 0;
- bs->mhop.local.sa_sin6.sin6_port = 0;
- break;
- }
-}
/*
* Hash public interface / exported functions.
@@ -1395,32 +1318,33 @@ struct bfd_session *bfd_id_lookup(uint32_t id)
return hash_lookup(bfd_id_hash, &bs);
}
-struct bfd_session *bfd_shop_lookup(struct bfd_shop_key shop)
+struct bfd_session *bfd_key_lookup(struct bfd_key key)
{
struct bfd_session bs, *bsp;
- _shop_key(&bs, &shop);
+ bs.key = key;
+ bsp = hash_lookup(bfd_key_hash, &bs);
- bsp = hash_lookup(bfd_shop_hash, &bs);
- if (bsp == NULL && bs.shop.ifindex != 0) {
- /*
- * Since the local interface spec is optional, try
- * searching the key without it as well.
- */
- _shop_key2(&bs, &shop);
- bsp = hash_lookup(bfd_shop_hash, &bs);
+ /* Handle cases where local-address is optional. */
+ if (bsp == NULL && bs.key.family == AF_INET) {
+ memset(&bs.key.local, 0, sizeof(bs.key.local));
+ bsp = hash_lookup(bfd_key_hash, &bs);
}
- return bsp;
-}
-
-struct bfd_session *bfd_mhop_lookup(struct bfd_mhop_key mhop)
-{
- struct bfd_session bs;
+ /* Handle cases where ifname is optional. */
+ bs.key = key;
+ if (bsp == NULL && bs.key.ifname[0]) {
+ memset(bs.key.ifname, 0, sizeof(bs.key.ifname));
+ bsp = hash_lookup(bfd_key_hash, &bs);
- _mhop_key(&bs, &mhop);
+ /* Handle cases where local-address and ifname are optional. */
+ if (bsp == NULL && bs.key.family == AF_INET) {
+ memset(&bs.key.local, 0, sizeof(bs.key.local));
+ bsp = hash_lookup(bfd_key_hash, &bs);
+ }
+ }
- return hash_lookup(bfd_mhop_hash, &bs);
+ return bsp;
}
/*
@@ -1442,31 +1366,18 @@ struct bfd_session *bfd_id_delete(uint32_t id)
return hash_release(bfd_id_hash, &bs);
}
-struct bfd_session *bfd_shop_delete(struct bfd_shop_key shop)
+struct bfd_session *bfd_key_delete(struct bfd_key key)
{
struct bfd_session bs, *bsp;
- _shop_key(&bs, &shop);
- bsp = hash_release(bfd_shop_hash, &bs);
- if (bsp == NULL && shop.ifindex != 0) {
- /*
- * Since the local interface spec is optional, try
- * searching the key without it as well.
- */
- _shop_key2(&bs, &shop);
- bsp = hash_release(bfd_shop_hash, &bs);
+ bs.key = key;
+ bsp = hash_lookup(bfd_key_hash, &bs);
+ if (bsp == NULL && key.ifname[0]) {
+ memset(bs.key.ifname, 0, sizeof(bs.key.ifname));
+ bsp = hash_lookup(bfd_key_hash, &bs);
}
- return bsp;
-}
-
-struct bfd_session *bfd_mhop_delete(struct bfd_mhop_key mhop)
-{
- struct bfd_session bs;
-
- _mhop_key(&bs, &mhop);
-
- return hash_release(bfd_mhop_hash, &bs);
+ return hash_release(bfd_key_hash, bsp);
}
/* Iteration functions. */
@@ -1475,14 +1386,9 @@ void bfd_id_iterate(hash_iter_func hif, void *arg)
hash_iterate(bfd_id_hash, hif, arg);
}
-void bfd_shop_iterate(hash_iter_func hif, void *arg)
-{
- hash_iterate(bfd_shop_hash, hif, arg);
-}
-
-void bfd_mhop_iterate(hash_iter_func hif, void *arg)
+void bfd_key_iterate(hash_iter_func hif, void *arg)
{
- hash_iterate(bfd_mhop_hash, hif, arg);
+ hash_iterate(bfd_key_hash, hif, arg);
}
/*
@@ -1496,24 +1402,17 @@ bool bfd_id_insert(struct bfd_session *bs)
return (hash_get(bfd_id_hash, bs, hash_alloc_intern) == bs);
}
-bool bfd_shop_insert(struct bfd_session *bs)
-{
- return (hash_get(bfd_shop_hash, bs, hash_alloc_intern) == bs);
-}
-
-bool bfd_mhop_insert(struct bfd_session *bs)
+bool bfd_key_insert(struct bfd_session *bs)
{
- return (hash_get(bfd_mhop_hash, bs, hash_alloc_intern) == bs);
+ return (hash_get(bfd_key_hash, bs, hash_alloc_intern) == bs);
}
void bfd_initialize(void)
{
bfd_id_hash = hash_create(bfd_id_hash_do, bfd_id_hash_cmp,
- "BFD discriminator hash");
- bfd_shop_hash = hash_create(bfd_shop_hash_do, bfd_shop_hash_cmp,
- "BFD single hop hash");
- bfd_mhop_hash = hash_create(bfd_mhop_hash_do, bfd_mhop_hash_cmp,
- "BFD multihop hop hash");
+ "BFD session discriminator hash");
+ bfd_key_hash = hash_create(bfd_key_hash_do, bfd_key_hash_cmp,
+ "BFD session hash");
}
static void _bfd_free(struct hash_bucket *hb,
@@ -1534,11 +1433,9 @@ void bfd_shutdown(void)
* assert() here to make sure it really happened.
*/
bfd_id_iterate(_bfd_free, NULL);
- assert(bfd_shop_hash->count == 0);
- assert(bfd_mhop_hash->count == 0);
+ assert(bfd_key_hash->count == 0);
/* Now free the hashes themselves. */
hash_free(bfd_id_hash);
- hash_free(bfd_shop_hash);
- hash_free(bfd_mhop_hash);
+ hash_free(bfd_key_hash);
}
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index 7451ca82a3..a69ff9a1a7 100644
--- a/bfdd/bfd.h
+++ b/bfdd/bfd.h
@@ -173,15 +173,13 @@ enum bfd_session_flags {
#define BFD_CHECK_FLAG(field, flag) (field & flag)
/* BFD session hash keys */
-struct bfd_shop_key {
- struct sockaddr_any peer;
- ifindex_t ifindex;
-};
-
-struct bfd_mhop_key {
- struct sockaddr_any peer;
- struct sockaddr_any local;
- vrf_id_t vrfid;
+struct bfd_key {
+ uint16_t family;
+ uint8_t mhop;
+ struct in6_addr peer;
+ struct in6_addr local;
+ char ifname[MAXNAMELEN];
+ char vrfname[MAXNAMELEN];
};
struct bfd_session_stats {
@@ -227,19 +225,14 @@ struct bfd_session {
uint8_t polling;
/* This and the localDiscr are the keys to state info */
+ struct bfd_key key;
struct peer_label *pl;
- union {
- struct bfd_shop_key shop;
- struct bfd_mhop_key mhop;
- };
- int sock;
struct sockaddr_any local_address;
- struct sockaddr_any local_ip;
struct interface *ifp;
struct vrf *vrf;
- char ifname[MAXNAMELEN];
- char vrfname[MAXNAMELEN];
+
+ int sock;
/* BFD session flags */
enum bfd_session_flags flags;
@@ -281,7 +274,11 @@ struct bfd_state_str_list {
struct bfd_session_observer {
struct bfd_session *bso_bs;
bool bso_isinterface;
- char bso_entryname[MAXNAMELEN];
+ bool bso_isaddress;
+ union {
+ char bso_entryname[MAXNAMELEN];
+ struct prefix bso_addr;
+ };
TAILQ_ENTRY(bfd_session_observer) bso_entry;
};
@@ -531,38 +528,28 @@ const char *satostr(struct sockaddr_any *sa);
const char *diag2str(uint8_t diag);
int strtosa(const char *addr, struct sockaddr_any *sa);
void integer2timestr(uint64_t time, char *buf, size_t buflen);
-const char *bs_to_string(struct bfd_session *bs);
+const char *bs_to_string(const struct bfd_session *bs);
int bs_observer_add(struct bfd_session *bs);
void bs_observer_del(struct bfd_session_observer *bso);
+void bs_to_bpc(struct bfd_session *bs, struct bfd_peer_cfg *bpc);
+
/* BFD hash data structures interface */
void bfd_initialize(void);
void bfd_shutdown(void);
struct bfd_session *bfd_id_lookup(uint32_t id);
-struct bfd_session *bfd_shop_lookup(struct bfd_shop_key shop);
-struct bfd_session *bfd_mhop_lookup(struct bfd_mhop_key mhop);
-struct bfd_vrf *bfd_vrf_lookup(int vrf_id);
-struct bfd_iface *bfd_iface_lookup(const char *ifname);
+struct bfd_session *bfd_key_lookup(struct bfd_key key);
struct bfd_session *bfd_id_delete(uint32_t id);
-struct bfd_session *bfd_shop_delete(struct bfd_shop_key shop);
-struct bfd_session *bfd_mhop_delete(struct bfd_mhop_key mhop);
-struct bfd_vrf *bfd_vrf_delete(int vrf_id);
-struct bfd_iface *bfd_iface_delete(const char *ifname);
+struct bfd_session *bfd_key_delete(struct bfd_key key);
bool bfd_id_insert(struct bfd_session *bs);
-bool bfd_shop_insert(struct bfd_session *bs);
-bool bfd_mhop_insert(struct bfd_session *bs);
-bool bfd_vrf_insert(struct bfd_vrf *vrf);
-bool bfd_iface_insert(struct bfd_iface *iface);
+bool bfd_key_insert(struct bfd_session *bs);
typedef void (*hash_iter_func)(struct hash_bucket *hb, void *arg);
void bfd_id_iterate(hash_iter_func hif, void *arg);
-void bfd_shop_iterate(hash_iter_func hif, void *arg);
-void bfd_mhop_iterate(hash_iter_func hif, void *arg);
-void bfd_vrf_iterate(hash_iter_func hif, void *arg);
-void bfd_iface_iterate(hash_iter_func hif, void *arg);
+void bfd_key_iterate(hash_iter_func hif, void *arg);
/* Export callback functions for `event.c`. */
extern struct thread_master *master;
@@ -572,6 +559,8 @@ int bfd_echo_recvtimer_cb(struct thread *t);
int bfd_xmt_cb(struct thread *t);
int bfd_echo_xmt_cb(struct thread *t);
+extern struct in6_addr zero_addr;
+
/*
* bfdd_vty.c
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index 45c5f5dbdc..69d27ed698 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -79,7 +79,10 @@ int _ptm_bfd_send(struct bfd_session *bs, uint16_t *port, const void *data,
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6)) {
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
- sin6.sin6_addr = bs->shop.peer.sa_sin6.sin6_addr;
+ memcpy(&sin6.sin6_addr, &bs->key.peer, sizeof(sin6.sin6_addr));
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
+ sin6.sin6_scope_id = bs->ifp->ifindex;
+
sin6.sin6_port =
(port) ? *port
: (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
@@ -92,7 +95,7 @@ int _ptm_bfd_send(struct bfd_session *bs, uint16_t *port, const void *data,
} else {
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
- sin.sin_addr = bs->shop.peer.sa_sin.sin_addr;
+ memcpy(&sin.sin_addr, &bs->key.peer, sizeof(sin.sin_addr));
sin.sin_port =
(port) ? *port
: (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
@@ -120,7 +123,7 @@ int _ptm_bfd_send(struct bfd_session *bs, uint16_t *port, const void *data,
void ptm_bfd_echo_snd(struct bfd_session *bfd)
{
- struct sockaddr_any *sa;
+ struct sockaddr *sa;
socklen_t salen;
int sd;
struct bfd_echo_pkt bep;
@@ -135,31 +138,34 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
bep.len = BFD_ECHO_PKT_LEN;
bep.my_discr = htonl(bfd->discrs.my_discr);
- sa = BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_MH) ? &bfd->mhop.peer
- : &bfd->shop.peer;
if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6)) {
sd = bglobal.bg_echov6;
- sin6 = sa->sa_sin6;
+ memset(&sin6, 0, sizeof(sin6));
+ memcpy(&sin6.sin6_addr, &bfd->key.peer, sizeof(sin6.sin6_addr));
+ if (bfd->ifp && IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
+ sin6.sin6_scope_id = bfd->ifp->ifindex;
+
sin6.sin6_port = htons(BFD_DEF_ECHO_PORT);
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
sin6.sin6_len = sizeof(sin6);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
- sa = (struct sockaddr_any *)&sin6;
+ sa = (struct sockaddr *)&sin6;
salen = sizeof(sin6);
} else {
sd = bglobal.bg_echo;
- sin = sa->sa_sin;
+ memset(&sin6, 0, sizeof(sin6));
+ memcpy(&sin.sin_addr, &bfd->key.peer, sizeof(sin.sin_addr));
sin.sin_port = htons(BFD_DEF_ECHO_PORT);
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
sin.sin_len = sizeof(sin);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
- sa = (struct sockaddr_any *)&sin;
+ sa = (struct sockaddr *)&sin;
salen = sizeof(sin);
}
- if (bp_udp_send(sd, BFD_TTL_VAL, (uint8_t *)&bep, sizeof(bep),
- (struct sockaddr *)sa, salen)
+ if (bp_udp_send(sd, BFD_TTL_VAL, (uint8_t *)&bep, sizeof(bep), sa,
+ salen)
== -1)
return;
@@ -544,7 +550,7 @@ int bfd_recv_cb(struct thread *t)
}
/* Validate packet TTL. */
- if ((is_mhop == false) && (ttl != BFD_TTL_VAL)) {
+ if ((!is_mhop) && (ttl != BFD_TTL_VAL)) {
cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
"invalid TTL: %d expected %d", ttl, BFD_TTL_VAL);
return 0;
@@ -602,8 +608,8 @@ int bfd_recv_cb(struct thread *t)
bfd->mh_ttl, BFD_TTL_VAL);
return 0;
}
- } else if (bfd->local_ip.sa_sin.sin_family == AF_UNSPEC) {
- bfd->local_ip = local;
+ } else if (bfd->local_address.sa_sin.sin_family == AF_UNSPEC) {
+ bfd->local_address = local;
}
/*
@@ -917,25 +923,26 @@ int bp_peer_socket(const struct bfd_session *bs)
return -1;
}
- if (bs->shop.ifindex != IFINDEX_INTERNAL) {
- if (bp_bind_dev(sd, bs->ifp->name) != 0) {
+ if (bs->key.ifname[0]) {
+ if (bp_bind_dev(sd, bs->key.ifname) != 0) {
close(sd);
return -1;
}
- } else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH) &&
- bs->mhop.vrfid != VRF_DEFAULT) {
- if (bp_bind_dev(sd, bs->vrf->name) != 0) {
+ } else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)
+ && bs->key.vrfname[0]) {
+ if (bp_bind_dev(sd, bs->key.vrfname) != 0) {
close(sd);
return -1;
}
}
/* Find an available source port in the proper range */
- sin = bs->local_ip.sa_sin;
+ memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
sin.sin_len = sizeof(sin);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+ memcpy(&sin.sin_addr, &bs->key.local, sizeof(sin.sin_addr));
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH) == 0)
sin.sin_addr.s_addr = INADDR_ANY;
@@ -987,20 +994,23 @@ int bp_peer_socketv6(const struct bfd_session *bs)
}
/* Find an available source port in the proper range */
- sin6 = bs->local_ip.sa_sin6;
+ memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
sin6.sin6_len = sizeof(sin6);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+ memcpy(&sin6.sin6_addr, &bs->key.local, sizeof(sin6.sin6_addr));
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr))
+ sin6.sin6_scope_id = bs->ifp->ifindex;
- if (bs->shop.ifindex != IFINDEX_INTERNAL) {
- if (bp_bind_dev(sd, bs->ifp->name) != 0) {
+ if (bs->key.ifname[0]) {
+ if (bp_bind_dev(sd, bs->key.ifname) != 0) {
close(sd);
return -1;
}
- } else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH) &&
- bs->mhop.vrfid != VRF_DEFAULT) {
- if (bp_bind_dev(sd, bs->vrf->name) != 0) {
+ } else if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)
+ && bs->key.vrfname[0]) {
+ if (bp_bind_dev(sd, bs->key.vrfname) != 0) {
close(sd);
return -1;
}
diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c
index 0041f9cc2e..c139492076 100644
--- a/bfdd/bfdd_vty.c
+++ b/bfdd/bfdd_vty.c
@@ -79,7 +79,6 @@ _find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
const char *local_str, const char *ifname,
const char *vrfname);
-
/*
* Commands definition.
*/
@@ -369,22 +368,25 @@ DEFPY(bfd_no_peer, bfd_no_peer_cmd,
*/
static void _display_peer_header(struct vty *vty, struct bfd_session *bs)
{
- if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
- vty_out(vty, "\tpeer %s", satostr(&bs->mhop.peer));
+ char addr_buf[INET6_ADDRSTRLEN];
+
+ vty_out(vty, "\tpeer %s",
+ inet_ntop(bs->key.family, &bs->key.peer, addr_buf,
+ sizeof(addr_buf)));
+
+ if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
vty_out(vty, " multihop");
- vty_out(vty, " local-address %s", satostr(&bs->mhop.local));
- if (bs->vrfname[0])
- vty_out(vty, " vrf %s", bs->vrfname);
- vty_out(vty, "\n");
- } else {
- vty_out(vty, "\tpeer %s", satostr(&bs->shop.peer));
- if (bs->local_address.sa_sin.sin_family != AF_UNSPEC)
- vty_out(vty, " local-address %s",
- satostr(&bs->local_address));
- if (bs->ifname[0])
- vty_out(vty, " interface %s", bs->ifname);
- vty_out(vty, "\n");
- }
+
+ if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
+ vty_out(vty, " local-address %s",
+ inet_ntop(bs->key.family, &bs->key.local, addr_buf,
+ sizeof(addr_buf)));
+
+ if (bs->key.vrfname[0])
+ vty_out(vty, " vrf %s", bs->key.vrfname);
+ if (bs->key.ifname[0])
+ vty_out(vty, " interface %s", bs->key.ifname);
+ vty_out(vty, "\n");
if (bs->pl)
vty_out(vty, "\t\tlabel: %s\n", bs->pl->pl_label);
@@ -453,22 +455,25 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
static struct json_object *_peer_json_header(struct bfd_session *bs)
{
struct json_object *jo = json_object_new_object();
+ char addr_buf[INET6_ADDRSTRLEN];
- if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
+ if (bs->key.mhop)
json_object_boolean_true_add(jo, "multihop");
- json_object_string_add(jo, "peer", satostr(&bs->mhop.peer));
- json_object_string_add(jo, "local", satostr(&bs->mhop.local));
- if (bs->vrfname[0])
- json_object_string_add(jo, "vrf", bs->vrfname);
- } else {
+ else
json_object_boolean_false_add(jo, "multihop");
- json_object_string_add(jo, "peer", satostr(&bs->shop.peer));
- if (bs->local_address.sa_sin.sin_family != AF_UNSPEC)
- json_object_string_add(jo, "local",
- satostr(&bs->local_address));
- if (bs->ifname[0])
- json_object_string_add(jo, "interface", bs->ifname);
- }
+
+ json_object_string_add(jo, "peer",
+ inet_ntop(bs->key.family, &bs->key.peer,
+ addr_buf, sizeof(addr_buf)));
+ if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
+ json_object_string_add(jo, "local",
+ inet_ntop(bs->key.family, &bs->key.local,
+ addr_buf, sizeof(addr_buf)));
+
+ if (bs->key.vrfname[0])
+ json_object_string_add(jo, "vrf", bs->key.vrfname);
+ if (bs->key.ifname[0])
+ json_object_string_add(jo, "interface", bs->key.ifname);
if (bs->pl)
json_object_string_add(jo, "label", bs->pl->pl_label);
@@ -564,7 +569,7 @@ static void _display_all_peers(struct vty *vty, bool use_json)
{
struct json_object *jo;
- if (use_json == false) {
+ if (!use_json) {
vty_out(vty, "BFD Peers:\n");
bfd_id_iterate(_display_peer_iter, vty);
return;
@@ -647,7 +652,7 @@ static void _display_peers_counter(struct vty *vty, bool use_json)
{
struct json_object *jo;
- if (use_json == false) {
+ if (!use_json) {
vty_out(vty, "BFD Peers:\n");
bfd_id_iterate(_display_peer_counter_iter, vty);
return;
@@ -916,25 +921,29 @@ static int bfdd_write_config(struct vty *vty)
static void _bfdd_peer_write_config(struct vty *vty, struct bfd_session *bs)
{
- if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
- vty_out(vty, " peer %s", satostr(&bs->mhop.peer));
+ char addr_buf[INET6_ADDRSTRLEN];
+
+ vty_out(vty, " peer %s",
+ inet_ntop(bs->key.family, &bs->key.peer, addr_buf,
+ sizeof(addr_buf)));
+
+ if (bs->key.mhop)
vty_out(vty, " multihop");
- vty_out(vty, " local-address %s", satostr(&bs->mhop.local));
- if (bs->vrfname[0])
- vty_out(vty, " vrf %s", bs->vrfname);
- vty_out(vty, "\n");
- } else {
- vty_out(vty, " peer %s", satostr(&bs->shop.peer));
- if (bs->local_address.sa_sin.sin_family != AF_UNSPEC)
- vty_out(vty, " local-address %s",
- satostr(&bs->local_address));
- if (bs->ifname[0])
- vty_out(vty, " interface %s", bs->ifname);
- vty_out(vty, "\n");
- }
+
+ if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
+ vty_out(vty, " local-address %s",
+ inet_ntop(bs->key.family, &bs->key.local, addr_buf,
+ sizeof(addr_buf)));
+
+ if (bs->key.vrfname[0])
+ vty_out(vty, " vrf %s", bs->key.vrfname);
+ if (bs->key.ifname[0])
+ vty_out(vty, " interface %s", bs->key.ifname);
+ vty_out(vty, "\n");
if (bs->sock == -1)
- vty_out(vty, " ! vrf or interface doesn't exist\n");
+ vty_out(vty,
+ " ! vrf, interface or local-address doesn't exist\n");
if (bs->detect_mult != BPC_DEF_DETECTMULTIPLIER)
vty_out(vty, " detect-multiplier %d\n", bs->detect_mult);
@@ -980,16 +989,7 @@ static void _bfdd_peer_write_config_iter(struct hash_bucket *hb, void *arg)
static int bfdd_peer_write_config(struct vty *vty)
{
- struct bfd_session_observer *bso;
-
bfd_id_iterate(_bfdd_peer_write_config_iter, vty);
- TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
- /* Only print disabled sessions here. */
- if (bso->bso_bs->sock != -1)
- continue;
-
- _bfdd_peer_write_config(vty, bso->bso_bs);
- }
return 1;
}
diff --git a/bfdd/config.c b/bfdd/config.c
index d1342eff1e..cd57ea9fe3 100644
--- a/bfdd/config.c
+++ b/bfdd/config.c
@@ -309,24 +309,7 @@ static int parse_peer_label_config(struct json_object *jo,
log_debug("\tpeer-label: %s", sval);
/* Translate the label into BFD address keys. */
- bpc->bpc_ipv4 = !BFD_CHECK_FLAG(pl->pl_bs->flags, BFD_SESS_FLAG_IPV6);
- bpc->bpc_mhop = BFD_CHECK_FLAG(pl->pl_bs->flags, BFD_SESS_FLAG_MH);
- if (bpc->bpc_mhop) {
- bpc->bpc_peer = pl->pl_bs->mhop.peer;
- bpc->bpc_local = pl->pl_bs->mhop.local;
- if (pl->pl_bs->mhop.vrfid != VRF_DEFAULT) {
- bpc->bpc_has_vrfname = true;
- strlcpy(bpc->bpc_vrfname, pl->pl_bs->vrf->name,
- sizeof(bpc->bpc_vrfname));
- }
- } else {
- bpc->bpc_peer = pl->pl_bs->shop.peer;
- if (pl->pl_bs->ifname[0]) {
- bpc->bpc_has_localif = true;
- strlcpy(bpc->bpc_localif, pl->pl_bs->ifname,
- sizeof(bpc->bpc_localif));
- }
- }
+ bs_to_bpc(pl->pl_bs, bpc);
return 0;
}
@@ -519,6 +502,8 @@ int config_notify_request(struct bfd_control_socket *bcs, const char *jsonstr,
static int json_object_add_peer(struct json_object *jo, struct bfd_session *bs)
{
+ char addr_buf[INET6_ADDRSTRLEN];
+
/* Add peer 'key' information. */
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6))
json_object_boolean_true_add(jo, "ipv6");
@@ -528,21 +513,26 @@ static int json_object_add_peer(struct json_object *jo, struct bfd_session *bs)
if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
json_object_boolean_true_add(jo, "multihop");
json_object_string_add(jo, "peer-address",
- satostr(&bs->mhop.peer));
+ inet_ntop(bs->key.family, &bs->key.peer,
+ addr_buf, sizeof(addr_buf)));
json_object_string_add(jo, "local-address",
- satostr(&bs->mhop.local));
- if (bs->vrfname[0])
- json_object_string_add(jo, "vrf-name", bs->vrfname);
+ inet_ntop(bs->key.family, &bs->key.local,
+ addr_buf, sizeof(addr_buf)));
+ if (bs->key.vrfname[0])
+ json_object_string_add(jo, "vrf-name", bs->key.vrfname);
} else {
json_object_boolean_false_add(jo, "multihop");
json_object_string_add(jo, "peer-address",
- satostr(&bs->shop.peer));
- if (bs->local_address.sa_sin.sin_family != AF_UNSPEC)
- json_object_string_add(jo, "local-address",
- satostr(&bs->local_address));
- if (bs->ifname[0])
+ inet_ntop(bs->key.family, &bs->key.peer,
+ addr_buf, sizeof(addr_buf)));
+ if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local)))
+ json_object_string_add(
+ jo, "local-address",
+ inet_ntop(bs->key.family, &bs->key.local,
+ addr_buf, sizeof(addr_buf)));
+ if (bs->key.ifname[0])
json_object_string_add(jo, "local-interface",
- bs->ifname);
+ bs->key.ifname);
}
if (bs->pl)
@@ -574,8 +564,6 @@ struct peer_label *pl_new(const char *label, struct bfd_session *bs)
struct peer_label *pl;
pl = XCALLOC(MTYPE_BFDD_LABEL, sizeof(*pl));
- if (pl == NULL)
- return NULL;
if (strlcpy(pl->pl_label, label, sizeof(pl->pl_label))
> sizeof(pl->pl_label))
diff --git a/bfdd/control.c b/bfdd/control.c
index 40f4f4d3be..c308d647d8 100644
--- a/bfdd/control.c
+++ b/bfdd/control.c
@@ -186,8 +186,6 @@ struct bfd_control_socket *control_new(int sd)
struct bfd_control_socket *bcs;
bcs = XCALLOC(MTYPE_BFDD_CONTROL, sizeof(*bcs));
- if (bcs == NULL)
- return NULL;
/* Disable notifications by default. */
bcs->bcs_notify = 0;
@@ -247,10 +245,6 @@ struct bfd_notify_peer *control_notifypeer_new(struct bfd_control_socket *bcs,
return bnp;
bnp = XCALLOC(MTYPE_BFDD_CONTROL, sizeof(*bnp));
- if (bnp == NULL) {
- log_warning("%s: calloc: %s", __func__, strerror(errno));
- return NULL;
- }
TAILQ_INSERT_TAIL(&bcs->bcs_bnplist, bnp, bnp_entry);
bnp->bnp_bs = bs;
@@ -285,10 +279,6 @@ struct bfd_control_queue *control_queue_new(struct bfd_control_socket *bcs)
struct bfd_control_queue *bcq;
bcq = XCALLOC(MTYPE_BFDD_NOTIFICATION, sizeof(*bcq));
- if (bcq == NULL) {
- log_warning("%s: calloc: %s", __func__, strerror(errno));
- return NULL;
- }
control_reset_buf(&bcq->bcq_bcb);
TAILQ_INSERT_TAIL(&bcs->bcs_bcqueue, bcq, bcq_entry);
@@ -743,11 +733,6 @@ static void control_response(struct bfd_control_socket *bcs, uint16_t id,
jsonstrlen = strlen(jsonstr);
bcm = XMALLOC(MTYPE_BFDD_NOTIFICATION,
sizeof(struct bfd_control_msg) + jsonstrlen);
- if (bcm == NULL) {
- log_warning("%s: malloc: %s", __func__, strerror(errno));
- XFREE(MTYPE_BFDD_NOTIFICATION, jsonstr);
- return;
- }
bcm->bcm_length = htonl(jsonstrlen);
bcm->bcm_ver = BMV_VERSION_1;
@@ -778,11 +763,6 @@ static void _control_notify(struct bfd_control_socket *bcs,
jsonstrlen = strlen(jsonstr);
bcm = XMALLOC(MTYPE_BFDD_NOTIFICATION,
sizeof(struct bfd_control_msg) + jsonstrlen);
- if (bcm == NULL) {
- log_warning("%s: malloc: %s", __func__, strerror(errno));
- XFREE(MTYPE_BFDD_NOTIFICATION, jsonstr);
- return;
- }
bcm->bcm_length = htonl(jsonstrlen);
bcm->bcm_ver = BMV_VERSION_1;
@@ -846,11 +826,6 @@ static void _control_notify_config(struct bfd_control_socket *bcs,
jsonstrlen = strlen(jsonstr);
bcm = XMALLOC(MTYPE_BFDD_NOTIFICATION,
sizeof(struct bfd_control_msg) + jsonstrlen);
- if (bcm == NULL) {
- log_warning("%s: malloc: %s", __func__, strerror(errno));
- XFREE(MTYPE_BFDD_NOTIFICATION, jsonstr);
- return;
- }
bcm->bcm_length = htonl(jsonstrlen);
bcm->bcm_ver = BMV_VERSION_1;
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index 3f1512d8e7..b44d13f132 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -55,7 +55,7 @@ static struct zclient *zclient;
/*
* Prototypes
*/
-static int _ptm_msg_address(struct stream *msg, struct sockaddr_any *sa);
+static int _ptm_msg_address(struct stream *msg, int family, const void *addr);
static void _ptm_msg_read_address(struct stream *msg, struct sockaddr_any *sa);
static int _ptm_msg_read(struct stream *msg, int command,
@@ -127,24 +127,24 @@ static void debug_printbpc(const char *func, unsigned int line,
#define DEBUG_PRINTBPC(bpc)
#endif /* BFD_DEBUG */
-static int _ptm_msg_address(struct stream *msg, struct sockaddr_any *sa)
+static int _ptm_msg_address(struct stream *msg, int family, const void *addr)
{
- switch (sa->sa_sin.sin_family) {
+ stream_putc(msg, family);
+
+ switch (family) {
case AF_INET:
- stream_putc(msg, sa->sa_sin.sin_family);
- stream_put_in_addr(msg, &sa->sa_sin.sin_addr);
+ stream_put(msg, addr, sizeof(struct in_addr));
stream_putc(msg, 32);
break;
case AF_INET6:
- stream_putc(msg, sa->sa_sin6.sin6_family);
- stream_put(msg, &sa->sa_sin6.sin6_addr,
- sizeof(sa->sa_sin6.sin6_addr));
+ stream_put(msg, addr, sizeof(struct in6_addr));
stream_putc(msg, 128);
break;
default:
- return -1;
+ assert(0);
+ break;
}
return 0;
@@ -153,7 +153,6 @@ static int _ptm_msg_address(struct stream *msg, struct sockaddr_any *sa)
int ptm_bfd_notify(struct bfd_session *bs)
{
struct stream *msg;
- struct sockaddr_any sac;
bs->stats.znotification++;
@@ -195,10 +194,7 @@ int ptm_bfd_notify(struct bfd_session *bs)
stream_putl(msg, IFINDEX_INTERNAL);
/* BFD destination prefix information. */
- if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH))
- _ptm_msg_address(msg, &bs->mhop.peer);
- else
- _ptm_msg_address(msg, &bs->shop.peer);
+ _ptm_msg_address(msg, bs->key.family, &bs->key.peer);
/* BFD status */
switch (bs->ses_state) {
@@ -218,34 +214,7 @@ int ptm_bfd_notify(struct bfd_session *bs)
}
/* BFD source prefix information. */
- if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) {
- _ptm_msg_address(msg, &bs->mhop.local);
- } else {
- if (bs->local_address.sa_sin.sin_family)
- _ptm_msg_address(msg, &bs->local_address);
- else if (bs->local_address.sa_sin.sin_family)
- _ptm_msg_address(msg, &bs->local_ip);
- else {
- sac = bs->shop.peer;
- switch (sac.sa_sin.sin_family) {
- case AF_INET:
- memset(&sac.sa_sin.sin_addr, 0,
- sizeof(sac.sa_sin.sin_family));
- break;
- case AF_INET6:
- memset(&sac.sa_sin6.sin6_addr, 0,
- sizeof(sac.sa_sin6.sin6_family));
- break;
-
- default:
- assert(false);
- break;
- }
-
- /* No local address found yet, so send zeroes. */
- _ptm_msg_address(msg, &sac);
- }
- }
+ _ptm_msg_address(msg, bs->key.family, &bs->key.local);
/* Write packet size. */
stream_putw_at(msg, 0, stream_get_endp(msg));
@@ -290,7 +259,6 @@ stream_failure:
static int _ptm_msg_read(struct stream *msg, int command,
struct bfd_peer_cfg *bpc, struct ptm_client **pc)
{
- struct interface *ifp;
uint32_t pid;
uint8_t ttl __attribute__((unused));
size_t ifnamelen;
@@ -385,31 +353,6 @@ static int _ptm_msg_read(struct stream *msg, int command,
if (bpc->bpc_has_localif) {
STREAM_GET(bpc->bpc_localif, msg, ifnamelen);
bpc->bpc_localif[ifnamelen] = 0;
-
- /*
- * IPv6 link-local addresses must use scope id,
- * otherwise the session lookup will always fail
- * and we'll have multiple sessions showing up.
- *
- * This problem only happens with single hop
- * since it is not possible to have link-local
- * address for multi hop sessions.
- */
- if (bpc->bpc_ipv4 == false
- && IN6_IS_ADDR_LINKLOCAL(
- &bpc->bpc_peer.sa_sin6.sin6_addr)) {
- ifp = if_lookup_by_name_all_vrf(
- bpc->bpc_localif);
- if (ifp == NULL) {
- log_error(
- "ptm-read: interface %s doesn't exists",
- bpc->bpc_localif);
- return -1;
- }
-
- bpc->bpc_peer.sa_sin6.sin6_scope_id =
- ifp->ifindex;
- }
}
}
@@ -608,7 +551,7 @@ static void bfdd_sessions_enable_interface(struct interface *ifp)
/* Interface name mismatch. */
bs = bso->bso_bs;
- if (strcmp(ifp->name, bs->ifname))
+ if (strcmp(ifp->name, bs->key.ifname))
continue;
/* Skip enabled sessions. */
if (bs->sock != -1)
@@ -630,7 +573,7 @@ static void bfdd_sessions_disable_interface(struct interface *ifp)
/* Interface name mismatch. */
bs = bso->bso_bs;
- if (strcmp(ifp->name, bs->ifname))
+ if (strcmp(ifp->name, bs->key.ifname))
continue;
/* Skip disabled sessions. */
if (bs->sock == -1)
@@ -691,6 +634,48 @@ static int bfdd_interface_vrf_update(int command __attribute__((__unused__)),
return 0;
}
+static void bfdd_sessions_enable_address(struct connected *ifc)
+{
+ struct bfd_session_observer *bso;
+ struct bfd_session *bs;
+ struct prefix prefix;
+
+ TAILQ_FOREACH(bso, &bglobal.bg_obslist, bso_entry) {
+ if (bso->bso_isaddress == false)
+ continue;
+
+ /* Skip enabled sessions. */
+ bs = bso->bso_bs;
+ if (bs->sock != -1)
+ continue;
+
+ /* Check address. */
+ prefix = bso->bso_addr;
+ prefix.prefixlen = ifc->address->prefixlen;
+ if (prefix_cmp(&prefix, ifc->address))
+ continue;
+
+ /* Try to enable it. */
+ bfd_session_enable(bs);
+ }
+}
+
+static int bfdd_interface_address_update(int cmd, struct zclient *zc,
+ zebra_size_t len
+ __attribute__((__unused__)),
+ vrf_id_t vrfid)
+{
+ struct connected *ifc;
+
+ ifc = zebra_interface_address_read(cmd, zc->ibuf, vrfid);
+ if (ifc == NULL)
+ return 0;
+
+ bfdd_sessions_enable_address(ifc);
+
+ return 0;
+}
+
void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
{
zclient = zclient_new(master, &zclient_options_default);
@@ -713,6 +698,10 @@ void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
/* Learn about interface VRF. */
zclient->interface_vrf_update = bfdd_interface_vrf_update;
+
+ /* Learn about new addresses being registered. */
+ zclient->interface_address_add = bfdd_interface_address_update;
+ zclient->interface_address_delete = bfdd_interface_address_update;
}
void bfdd_zclient_stop(void)
@@ -752,8 +741,6 @@ static struct ptm_client *pc_new(uint32_t pid)
/* Allocate the client data and save it. */
pc = XCALLOC(MTYPE_BFDD_CONTROL, sizeof(*pc));
- if (pc == NULL)
- return NULL;
pc->pc_pid = pid;
TAILQ_INSERT_HEAD(&pcqueue, pc, pc_entry);
@@ -799,8 +786,6 @@ static struct ptm_client_notification *pcn_new(struct ptm_client *pc,
/* Save the client notification data. */
pcn = XCALLOC(MTYPE_BFDD_NOTIFICATION, sizeof(*pcn));
- if (pcn == NULL)
- return NULL;
TAILQ_INSERT_HEAD(&pc->pc_pcnqueue, pcn, pcn_entry);
pcn->pcn_pc = pc;
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
index 208a2947ef..05eeeca156 100644
--- a/bgpd/bgp_advertise.c
+++ b/bgpd/bgp_advertise.c
@@ -45,8 +45,8 @@
peer. */
struct bgp_advertise_attr *baa_new(void)
{
- return (struct bgp_advertise_attr *)XCALLOC(
- MTYPE_BGP_ADVERTISE_ATTR, sizeof(struct bgp_advertise_attr));
+ return XCALLOC(MTYPE_BGP_ADVERTISE_ATTR,
+ sizeof(struct bgp_advertise_attr));
}
static void baa_free(struct bgp_advertise_attr *baa)
@@ -84,8 +84,7 @@ bool baa_hash_cmp(const void *p1, const void *p2)
information. */
struct bgp_advertise *bgp_advertise_new(void)
{
- return (struct bgp_advertise *)XCALLOC(MTYPE_BGP_ADVERTISE,
- sizeof(struct bgp_advertise));
+ return XCALLOC(MTYPE_BGP_ADVERTISE, sizeof(struct bgp_advertise));
}
void bgp_advertise_free(struct bgp_advertise *adv)
@@ -255,8 +254,7 @@ void bgp_sync_delete(struct peer *peer)
safi_t safi;
FOREACH_AFI_SAFI (afi, safi) {
- if (peer->sync[afi][safi])
- XFREE(MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]);
+ XFREE(MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]);
peer->sync[afi][safi] = NULL;
}
}
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 51833394d9..92c37fabd2 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -212,6 +212,9 @@ static struct assegment *assegment_append_asns(struct assegment *seg,
{
as_t *newas;
+ if (!seg)
+ return seg;
+
newas = XREALLOC(MTYPE_AS_SEG_DATA, seg->as,
ASSEGMENT_DATA_SIZE(seg->length + num, 1));
@@ -309,8 +312,7 @@ void aspath_free(struct aspath *aspath)
return;
if (aspath->segments)
assegment_free_all(aspath->segments);
- if (aspath->str)
- XFREE(MTYPE_AS_STR, aspath->str);
+ XFREE(MTYPE_AS_STR, aspath->str);
if (aspath->json) {
json_object_free(aspath->json);
@@ -620,8 +622,7 @@ static void aspath_make_str_count(struct aspath *as, bool make_json)
void aspath_str_update(struct aspath *as, bool make_json)
{
- if (as->str)
- XFREE(MTYPE_AS_STR, as->str);
+ XFREE(MTYPE_AS_STR, as->str);
if (as->json) {
json_object_free(as->json);
@@ -1372,7 +1373,8 @@ static struct aspath *aspath_merge(struct aspath *as1, struct aspath *as2)
while (last && last->next)
last = last->next;
- last->next = as2->segments;
+ if (last)
+ last->next = as2->segments;
as2->segments = new;
aspath_str_update(as2, false);
return as2;
@@ -1447,7 +1449,8 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
* bypass the merged seg2, and attach any chain after it
* to chain descending from as2's head
*/
- as2segtail->next = as2seghead->next;
+ if (as2segtail)
+ as2segtail->next = as2seghead->next;
/* as2->segments is now referenceless and useless */
assegment_free(as2seghead);
@@ -2096,3 +2099,110 @@ void aspath_print_all_vty(struct vty *vty)
void *))aspath_show_all_iterator,
vty);
}
+
+static struct aspath *bgp_aggr_aspath_lookup(struct bgp_aggregate *aggregate,
+ struct aspath *aspath)
+{
+ return hash_lookup(aggregate->aspath_hash, aspath);
+}
+
+static void *bgp_aggr_aspath_hash_alloc(void *p)
+{
+ struct aspath *ref = (struct aspath *)p;
+ struct aspath *aspath = NULL;
+
+ aspath = aspath_dup(ref);
+ return aspath;
+}
+
+static void bgp_aggr_aspath_prepare(struct hash_backet *hb, void *arg)
+{
+ struct aspath *asmerge = NULL;
+ struct aspath *hb_aspath = hb->data;
+ struct aspath **aggr_aspath = arg;
+
+ if (*aggr_aspath) {
+ asmerge = aspath_aggregate(*aggr_aspath, hb_aspath);
+ aspath_free(*aggr_aspath);
+ *aggr_aspath = asmerge;
+ } else
+ *aggr_aspath = aspath_dup(hb_aspath);
+}
+
+void bgp_aggr_aspath_remove(void *arg)
+{
+ struct aspath *aspath = arg;
+
+ aspath_free(aspath);
+}
+
+void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate,
+ struct aspath *aspath)
+{
+ struct aspath *aggr_aspath = NULL;
+
+ if ((aggregate == NULL) || (aspath == NULL))
+ return;
+
+ /* Create hash if not already created.
+ */
+ if (aggregate->aspath_hash == NULL)
+ aggregate->aspath_hash = hash_create(
+ aspath_key_make, aspath_cmp,
+ "BGP Aggregator as-path hash");
+
+ aggr_aspath = bgp_aggr_aspath_lookup(aggregate, aspath);
+ if (aggr_aspath == NULL) {
+ /* Insert as-path into hash.
+ */
+ aggr_aspath = hash_get(aggregate->aspath_hash, aspath,
+ bgp_aggr_aspath_hash_alloc);
+
+ /* Compute aggregate's as-path.
+ */
+ hash_iterate(aggregate->aspath_hash,
+ bgp_aggr_aspath_prepare,
+ &aggregate->aspath);
+ }
+
+ /* Increment refernce counter.
+ */
+ aggr_aspath->refcnt++;
+}
+
+void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate,
+ struct aspath *aspath)
+{
+ struct aspath *aggr_aspath = NULL;
+ struct aspath *ret_aspath = NULL;
+
+ if ((aggregate == NULL) || (aspath == NULL))
+ return;
+
+ if (aggregate->aspath_hash == NULL)
+ return;
+
+ /* Look-up the aspath in the hash.
+ */
+ aggr_aspath = bgp_aggr_aspath_lookup(aggregate, aspath);
+ if (aggr_aspath) {
+ aggr_aspath->refcnt--;
+
+ if (aggr_aspath->refcnt == 0) {
+ ret_aspath = hash_release(aggregate->aspath_hash,
+ aggr_aspath);
+ aspath_free(ret_aspath);
+
+ /* Remove aggregate's old as-path.
+ */
+ aspath_free(aggregate->aspath);
+ aggregate->aspath = NULL;
+
+ /* Compute aggregate's as-path.
+ */
+ hash_iterate(aggregate->aspath_hash,
+ bgp_aggr_aspath_prepare,
+ &aggregate->aspath);
+ }
+ }
+}
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index 9c9c687a6b..be5725c1ae 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -22,6 +22,7 @@
#define _QUAGGA_BGP_ASPATH_H
#include "lib/json.h"
+#include "bgpd/bgp_route.h"
/* AS path segment type. */
#define AS_SET 1
@@ -130,4 +131,10 @@ extern unsigned int aspath_has_as4(struct aspath *);
/* For SNMP BGP4PATHATTRASPATHSEGMENT, might be useful for debug */
extern uint8_t *aspath_snmp_pathseg(struct aspath *, size_t *);
+extern void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate,
+ struct aspath *aspath);
+extern void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate,
+ struct aspath *aspath);
+extern void bgp_aggr_aspath_remove(void *arg);
+
#endif /* _QUAGGA_BGP_ASPATH_H */
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index e731af754c..226bf99d2c 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -54,6 +54,7 @@
#include "bgp_encap_types.h"
#include "bgp_evpn.h"
#include "bgp_flowspec_private.h"
+#include "bgp_mac.h"
/* Attribute strings for logging. */
static const struct message attr_str[] = {
@@ -158,8 +159,7 @@ static bool cluster_hash_cmp(const void *p1, const void *p2)
static void cluster_free(struct cluster_list *cluster)
{
- if (cluster->list)
- XFREE(MTYPE_CLUSTER_VAL, cluster->list);
+ XFREE(MTYPE_CLUSTER_VAL, cluster->list);
XFREE(MTYPE_CLUSTER, cluster);
}
@@ -400,8 +400,7 @@ static struct hash *transit_hash;
static void transit_free(struct transit *transit)
{
- if (transit->val)
- XFREE(MTYPE_TRANSIT_VAL, transit->val);
+ XFREE(MTYPE_TRANSIT_VAL, transit->val);
XFREE(MTYPE_TRANSIT, transit);
}
@@ -1944,7 +1943,18 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
bgp_attr_evpn_na_flag(attr, &attr->router_flag);
/* Extract the Rmac, if any */
- bgp_attr_rmac(attr, &attr->rmac);
+ if (bgp_attr_rmac(attr, &attr->rmac)) {
+ if (bgp_debug_update(peer, NULL, NULL, 1) &&
+ bgp_mac_exist(&attr->rmac)) {
+ char buf1[ETHER_ADDR_STRLEN];
+
+ zlog_debug("%s: router mac %s is self mac",
+ __func__,
+ prefix_mac2str(&attr->rmac, buf1,
+ sizeof(buf1)));
+ }
+
+ }
return BGP_ATTR_PARSE_PROCEED;
}
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
index 3e9d05ad97..15fa322159 100644
--- a/bgpd/bgp_attr_evpn.c
+++ b/bgpd/bgp_attr_evpn.c
@@ -84,8 +84,8 @@ char *esi2str(struct eth_segment_id *id)
return NULL;
val = id->val;
- ptr = (char *)XMALLOC(MTYPE_TMP,
- (ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char));
+ ptr = XMALLOC(MTYPE_TMP,
+ (ESI_LEN * 2 + ESI_LEN - 1 + 1) * sizeof(char));
snprintf(ptr, (ESI_LEN * 2 + ESI_LEN - 1 + 1),
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", val[0],
@@ -106,14 +106,14 @@ char *ecom_mac2str(char *ecom_mac)
}
/* Fetch router-mac from extended community */
-void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
+bool bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
{
int i = 0;
struct ecommunity *ecom;
ecom = attr->ecommunity;
if (!ecom || !ecom->size)
- return;
+ return false;
/* If there is a router mac extended community, set RMAC in attr */
for (i = 0; i < ecom->size; i++) {
@@ -130,7 +130,9 @@ void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
continue;
memcpy(rmac, pnt, ETH_ALEN);
+ return true;
}
+ return false;
}
/*
diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h
index b036702151..5b0ce1da28 100644
--- a/bgpd/bgp_attr_evpn.h
+++ b/bgpd/bgp_attr_evpn.h
@@ -60,7 +60,7 @@ extern void bgp_add_routermac_ecom(struct attr *attr,
struct ethaddr *routermac);
extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag,
struct prefix *dst);
-extern void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac);
+extern bool bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac);
extern uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
uint8_t *sticky);
extern uint8_t bgp_attr_default_gw(struct attr *attr);
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index 84a00488c1..7b64f349d2 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -100,16 +100,14 @@ static void community_entry_free(struct community_entry *entry)
case EXTCOMMUNITY_LIST_STANDARD:
/* In case of standard extcommunity-list, configuration string
is made by ecommunity_ecom2str(). */
- if (entry->config)
- XFREE(MTYPE_ECOMMUNITY_STR, entry->config);
+ XFREE(MTYPE_ECOMMUNITY_STR, entry->config);
if (entry->u.ecom)
ecommunity_free(&entry->u.ecom);
break;
case COMMUNITY_LIST_EXPANDED:
case EXTCOMMUNITY_LIST_EXPANDED:
case LARGE_COMMUNITY_LIST_EXPANDED:
- if (entry->config)
- XFREE(MTYPE_COMMUNITY_LIST_CONFIG, entry->config);
+ XFREE(MTYPE_COMMUNITY_LIST_CONFIG, entry->config);
if (entry->reg)
bgp_regex_free(entry->reg);
default:
@@ -127,8 +125,7 @@ static struct community_list *community_list_new(void)
/* Free community-list. */
static void community_list_free(struct community_list *list)
{
- if (list->name)
- XFREE(MTYPE_COMMUNITY_LIST_NAME, list->name);
+ XFREE(MTYPE_COMMUNITY_LIST_NAME, list->name);
XFREE(MTYPE_COMMUNITY_LIST, list);
}
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index 614e24ca4f..67cd2be214 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -34,17 +34,14 @@ static struct hash *comhash;
/* Allocate a new communities value. */
static struct community *community_new(void)
{
- return (struct community *)XCALLOC(MTYPE_COMMUNITY,
- sizeof(struct community));
+ return XCALLOC(MTYPE_COMMUNITY, sizeof(struct community));
}
/* Free communities value. */
void community_free(struct community **com)
{
- if ((*com)->val)
- XFREE(MTYPE_COMMUNITY_VAL, (*com)->val);
- if ((*com)->str)
- XFREE(MTYPE_COMMUNITY_STR, (*com)->str);
+ XFREE(MTYPE_COMMUNITY_VAL, (*com)->val);
+ XFREE(MTYPE_COMMUNITY_STR, (*com)->str);
if ((*com)->json) {
json_object_free((*com)->json);
@@ -910,3 +907,112 @@ void community_finish(void)
hash_free(comhash);
comhash = NULL;
}
+
+static struct community *bgp_aggr_community_lookup(
+ struct bgp_aggregate *aggregate,
+ struct community *community)
+{
+ return hash_lookup(aggregate->community_hash, community);
+}
+
+static void *bgp_aggr_communty_hash_alloc(void *p)
+{
+ struct community *ref = (struct community *)p;
+ struct community *community = NULL;
+
+ community = community_dup(ref);
+ return community;
+}
+
+static void bgp_aggr_community_prepare(struct hash_backet *hb, void *arg)
+{
+ struct community *commerge = NULL;
+ struct community *hb_community = hb->data;
+ struct community **aggr_community = arg;
+
+ if (*aggr_community) {
+ commerge = community_merge(*aggr_community, hb_community);
+ *aggr_community = community_uniq_sort(commerge);
+ community_free(&commerge);
+ } else
+ *aggr_community = community_dup(hb_community);
+}
+
+void bgp_aggr_community_remove(void *arg)
+{
+ struct community *community = arg;
+
+ community_free(&community);
+}
+
+void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate,
+ struct community *community)
+{
+ struct community *aggr_community = NULL;
+
+ if ((aggregate == NULL) || (community == NULL))
+ return;
+
+ /* Create hash if not already created.
+ */
+ if (aggregate->community_hash == NULL)
+ aggregate->community_hash = hash_create(
+ (unsigned int (*)(void *))community_hash_make,
+ (bool (*)(const void *, const void *))community_cmp,
+ "BGP Aggregator community hash");
+
+ aggr_community = bgp_aggr_community_lookup(aggregate, community);
+ if (aggr_community == NULL) {
+ /* Insert community into hash.
+ */
+ aggr_community = hash_get(aggregate->community_hash, community,
+ bgp_aggr_communty_hash_alloc);
+
+ /* Re-compute aggregate's community.
+ */
+ if (aggregate->community)
+ community_free(&aggregate->community);
+
+ hash_iterate(aggregate->community_hash,
+ bgp_aggr_community_prepare,
+ &aggregate->community);
+ }
+
+ /* Increment refernce counter.
+ */
+ aggr_community->refcnt++;
+}
+
+void bgp_remove_community_from_aggregate(struct bgp_aggregate *aggregate,
+ struct community *community)
+{
+ struct community *aggr_community = NULL;
+ struct community *ret_comm = NULL;
+
+ if ((aggregate == NULL) || (community == NULL))
+ return;
+
+ if (aggregate->community_hash == NULL)
+ return;
+
+ /* Look-up the community in the hash.
+ */
+ aggr_community = bgp_aggr_community_lookup(aggregate, community);
+ if (aggr_community) {
+ aggr_community->refcnt--;
+
+ if (aggr_community->refcnt == 0) {
+ ret_comm = hash_release(aggregate->community_hash,
+ aggr_community);
+ community_free(&ret_comm);
+
+ community_free(&aggregate->community);
+
+ /* Compute aggregate's community.
+ */
+ hash_iterate(aggregate->community_hash,
+ bgp_aggr_community_prepare,
+ &aggregate->community);
+ }
+ }
+}
diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h
index e1545249d7..4ff4d214a5 100644
--- a/bgpd/bgp_community.h
+++ b/bgpd/bgp_community.h
@@ -22,6 +22,7 @@
#define _QUAGGA_BGP_COMMUNITY_H
#include "lib/json.h"
+#include "bgpd/bgp_route.h"
/* Communities attribute. */
struct community {
@@ -89,5 +90,10 @@ extern void community_del_val(struct community *, uint32_t *);
extern unsigned long community_count(void);
extern struct hash *community_hash(void);
extern uint32_t community_val_get(struct community *com, int i);
+extern void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate,
+ struct community *community);
+extern void bgp_remove_community_from_aggregate(struct bgp_aggregate *aggregate,
+ struct community *community);
+extern void bgp_aggr_community_remove(void *arg);
#endif /* _QUAGGA_BGP_COMMUNITY_H */
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index ed0900a721..8ef398952d 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -48,8 +48,7 @@ static struct hash *ecomhash;
/* Allocate a new ecommunities. */
struct ecommunity *ecommunity_new(void)
{
- return (struct ecommunity *)XCALLOC(MTYPE_ECOMMUNITY,
- sizeof(struct ecommunity));
+ return XCALLOC(MTYPE_ECOMMUNITY, sizeof(struct ecommunity));
}
void ecommunity_strfree(char **s)
@@ -60,10 +59,8 @@ void ecommunity_strfree(char **s)
/* Allocate ecommunities. */
void ecommunity_free(struct ecommunity **ecom)
{
- if ((*ecom)->val)
- XFREE(MTYPE_ECOMMUNITY_VAL, (*ecom)->val);
- if ((*ecom)->str)
- XFREE(MTYPE_ECOMMUNITY_STR, (*ecom)->str);
+ XFREE(MTYPE_ECOMMUNITY_VAL, (*ecom)->val);
+ XFREE(MTYPE_ECOMMUNITY_STR, (*ecom)->str);
XFREE(MTYPE_ECOMMUNITY, *ecom);
}
@@ -1026,3 +1023,112 @@ int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
return -1;
return 0;
}
+
+static struct ecommunity *bgp_aggr_ecommunity_lookup(
+ struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity)
+{
+ return hash_lookup(aggregate->ecommunity_hash, ecommunity);
+}
+
+static void *bgp_aggr_ecommunty_hash_alloc(void *p)
+{
+ struct ecommunity *ref = (struct ecommunity *)p;
+ struct ecommunity *ecommunity = NULL;
+
+ ecommunity = ecommunity_dup(ref);
+ return ecommunity;
+}
+
+static void bgp_aggr_ecommunity_prepare(struct hash_backet *hb, void *arg)
+{
+ struct ecommunity *ecommerge = NULL;
+ struct ecommunity *hb_ecommunity = hb->data;
+ struct ecommunity **aggr_ecommunity = arg;
+
+ if (*aggr_ecommunity) {
+ ecommerge = ecommunity_merge(*aggr_ecommunity, hb_ecommunity);
+ *aggr_ecommunity = ecommunity_uniq_sort(ecommerge);
+ ecommunity_free(&ecommerge);
+ } else
+ *aggr_ecommunity = ecommunity_dup(hb_ecommunity);
+}
+
+void bgp_aggr_ecommunity_remove(void *arg)
+{
+ struct ecommunity *ecommunity = arg;
+
+ ecommunity_free(&ecommunity);
+}
+
+void bgp_compute_aggregate_ecommunity(struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity)
+{
+ struct ecommunity *aggr_ecommunity = NULL;
+
+ if ((aggregate == NULL) || (ecommunity == NULL))
+ return;
+
+ /* Create hash if not already created.
+ */
+ if (aggregate->ecommunity_hash == NULL)
+ aggregate->ecommunity_hash = hash_create(
+ ecommunity_hash_make, ecommunity_cmp,
+ "BGP Aggregator ecommunity hash");
+
+ aggr_ecommunity = bgp_aggr_ecommunity_lookup(aggregate, ecommunity);
+ if (aggr_ecommunity == NULL) {
+ /* Insert ecommunity into hash.
+ */
+ aggr_ecommunity = hash_get(aggregate->ecommunity_hash,
+ ecommunity,
+ bgp_aggr_ecommunty_hash_alloc);
+
+ /* Re-compute aggregate's ecommunity.
+ */
+ if (aggregate->ecommunity)
+ ecommunity_free(&aggregate->ecommunity);
+
+ hash_iterate(aggregate->ecommunity_hash,
+ bgp_aggr_ecommunity_prepare,
+ &aggregate->ecommunity);
+ }
+
+ /* Increment refernce counter.
+ */
+ aggr_ecommunity->refcnt++;
+}
+
+void bgp_remove_ecommunity_from_aggregate(struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity)
+{
+ struct ecommunity *aggr_ecommunity = NULL;
+ struct ecommunity *ret_ecomm = NULL;
+
+ if ((aggregate == NULL) || (ecommunity == NULL))
+ return;
+
+ if (aggregate->ecommunity_hash == NULL)
+ return;
+
+ /* Look-up the ecommunity in the hash.
+ */
+ aggr_ecommunity = bgp_aggr_ecommunity_lookup(aggregate, ecommunity);
+ if (aggr_ecommunity) {
+ aggr_ecommunity->refcnt--;
+
+ if (aggr_ecommunity->refcnt == 0) {
+ ret_ecomm = hash_release(aggregate->ecommunity_hash,
+ aggr_ecommunity);
+ ecommunity_free(&ret_ecomm);
+
+ ecommunity_free(&aggregate->ecommunity);
+
+ /* Compute aggregate's ecommunity.
+ */
+ hash_iterate(aggregate->ecommunity_hash,
+ bgp_aggr_ecommunity_prepare,
+ &aggregate->ecommunity);
+ }
+ }
+}
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index 519991da5a..62b2137753 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -21,6 +21,8 @@
#ifndef _QUAGGA_BGP_ECOMMUNITY_H
#define _QUAGGA_BGP_ECOMMUNITY_H
+#include "bgpd/bgp_route.h"
+
/* High-order octet of the Extended Communities type field. */
#define ECOMMUNITY_ENCODE_AS 0x00
#define ECOMMUNITY_ENCODE_IP 0x01
@@ -184,4 +186,12 @@ struct bgp_pbr_entry_action;
extern int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval,
struct bgp_pbr_entry_action *api);
+extern void bgp_compute_aggregate_ecommunity(
+ struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity);
+extern void bgp_remove_ecommunity_from_aggregate(
+ struct bgp_aggregate *aggregate,
+ struct ecommunity *ecommunity);
+extern void bgp_aggr_ecommunity_remove(void *arg);
+
#endif /* _QUAGGA_BGP_ECOMMUNITY_H */
diff --git a/bgpd/bgp_encap_tlv.c b/bgpd/bgp_encap_tlv.c
index 30a08098e8..964adec9b6 100644
--- a/bgpd/bgp_encap_tlv.c
+++ b/bgpd/bgp_encap_tlv.c
@@ -401,8 +401,7 @@ void bgp_encap_type_vxlan_to_tlv(
if (bet == NULL || !bet->vnid)
return;
- if (attr->encap_subtlvs)
- XFREE(MTYPE_ENCAP_TLV, attr->encap_subtlvs);
+ XFREE(MTYPE_ENCAP_TLV, attr->encap_subtlvs);
tlv = XCALLOC(MTYPE_ENCAP_TLV,
sizeof(struct bgp_attr_encap_subtlv) + 12);
tlv->type = 1; /* encapsulation type */
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 361df826fa..19cda453f5 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -184,8 +184,6 @@ static struct vrf_irt_node *vrf_import_rt_new(struct ecommunity_val *rt)
irt = XCALLOC(MTYPE_BGP_EVPN_VRF_IMPORT_RT,
sizeof(struct vrf_irt_node));
- if (!irt)
- return NULL;
irt->rt = *rt;
irt->vrfs = list_new();
@@ -296,8 +294,6 @@ static struct irt_node *import_rt_new(struct bgp *bgp,
return NULL;
irt = XCALLOC(MTYPE_BGP_EVPN_IMPORT_RT, sizeof(struct irt_node));
- if (!irt)
- return NULL;
irt->rt = *rt;
irt->vnis = list_new();
@@ -968,8 +964,6 @@ static struct in_addr *es_vtep_new(struct in_addr vtep)
struct in_addr *ip;
ip = XCALLOC(MTYPE_BGP_EVPN_ES_VTEP, sizeof(struct in_addr));
- if (!ip)
- return NULL;
ip->s_addr = vtep.s_addr;
return ip;
@@ -3941,7 +3935,7 @@ static int process_type4_route(struct peer *peer, afi_t afi, safi_t safi,
*/
static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
struct attr *attr, uint8_t *pfx, int psize,
- uint32_t addpath_id, int withdraw)
+ uint32_t addpath_id)
{
struct prefix_rd prd;
struct prefix_evpn p;
@@ -4027,7 +4021,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
*/
/* Process the route. */
- if (!withdraw)
+ if (attr)
ret = bgp_update(peer, (struct prefix *)&p, addpath_id, attr,
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
&prd, &label, 1, 0, &evpn);
@@ -4882,8 +4876,9 @@ int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
break;
case BGP_EVPN_IP_PREFIX_ROUTE:
- if (process_type5_route(peer, afi, safi, attr, pnt,
- psize, addpath_id, withdraw)) {
+ if (process_type5_route(peer, afi, safi,
+ withdraw ? NULL : attr, pnt,
+ psize, addpath_id)) {
flog_err(
EC_BGP_PKT_PROCESS,
"%u:%s - Error in processing EVPN type-5 NLRI size %d",
@@ -5108,8 +5103,6 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
return NULL;
vpn = XCALLOC(MTYPE_BGP_EVPN, sizeof(struct bgpevpn));
- if (!vpn)
- return NULL;
/* Set values - RD and RT set to defaults. */
vpn->vni = vni;
@@ -5189,8 +5182,6 @@ struct evpnes *bgp_evpn_es_new(struct bgp *bgp,
return NULL;
es = XCALLOC(MTYPE_BGP_EVPN_ES, sizeof(struct evpnes));
- if (!es)
- return NULL;
/* set the ESI and originator_ip */
memcpy(&es->esi, esi, sizeof(esi_t));
@@ -5405,7 +5396,8 @@ static void link_l2vni_hash_to_l3vni(struct hash_bucket *bucket,
}
int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac,
- struct in_addr originator_ip, int filter)
+ struct in_addr originator_ip, int filter,
+ ifindex_t svi_ifindex)
{
struct bgp *bgp_vrf = NULL; /* bgp VRF instance */
struct bgp *bgp_def = NULL; /* default bgp instance */
@@ -5453,14 +5445,11 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac,
SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_AUTO);
}
- /* associate with l3vni */
+ /* associate the vrf with l3vni and related parameters */
bgp_vrf->l3vni = l3vni;
-
- /* set the router mac - to be used in mac-ip routes for this vrf */
memcpy(&bgp_vrf->rmac, rmac, sizeof(struct ethaddr));
-
- /* set the originator ip */
bgp_vrf->originator_ip = originator_ip;
+ bgp_vrf->l3vni_svi_ifindex = svi_ifindex;
/* set the right filter - are we using l3vni only for prefix routes? */
if (filter)
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index dfe141c40e..22fb0939c9 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -173,7 +173,8 @@ extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
uint8_t flags, uint32_t seq);
extern int bgp_evpn_local_l3vni_add(vni_t vni, vrf_id_t vrf_id,
struct ethaddr *rmac,
- struct in_addr originator_ip, int filter);
+ struct in_addr originator_ip, int filter,
+ ifindex_t svi_ifindex);
extern int bgp_evpn_local_l3vni_del(vni_t vni, vrf_id_t vrf_id);
extern int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni);
extern int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index 8437c4024e..fb2d9da533 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -3358,7 +3358,8 @@ DEFUN (bgp_evpn_advertise_type5,
}
/* advertise type-5 routes */
- bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
+ if (advertise_type5_routes(bgp_vrf, afi))
+ bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
return CMD_SUCCESS;
}
diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c
index 1ccb8fb245..80cfb97436 100644
--- a/bgpd/bgp_filter.c
+++ b/bgpd/bgp_filter.c
@@ -95,8 +95,7 @@ static void as_filter_free(struct as_filter *asfilter)
{
if (asfilter->reg)
bgp_regex_free(asfilter->reg);
- if (asfilter->reg_str)
- XFREE(MTYPE_AS_FILTER_STR, asfilter->reg_str);
+ XFREE(MTYPE_AS_FILTER_STR, asfilter->reg_str);
XFREE(MTYPE_AS_FILTER, asfilter);
}
@@ -338,8 +337,7 @@ static void as_list_filter_delete(struct as_list *aslist,
/* Run hook function. */
if (as_list_master.delete_hook)
(*as_list_master.delete_hook)(name);
- if (name)
- XFREE(MTYPE_AS_STR, name);
+ XFREE(MTYPE_AS_STR, name);
}
static int as_filter_match(struct as_filter *asfilter, struct aspath *aspath)
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index b70c8bbd63..447d8da613 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -310,7 +310,8 @@ void bgp_timer_set(struct peer *peer)
status start timer is on unless peer is shutdown or peer is
inactive. All other timer must be turned off */
if (BGP_PEER_START_SUPPRESSED(peer) || !peer_active(peer)
- || peer->bgp->vrf_id == VRF_UNKNOWN) {
+ || (peer->bgp->inst_type != BGP_INSTANCE_TYPE_VIEW &&
+ peer->bgp->vrf_id == VRF_UNKNOWN)) {
BGP_TIMER_OFF(peer->t_start);
} else {
BGP_TIMER_ON(peer->t_start, bgp_start_timer,
@@ -1422,7 +1423,8 @@ int bgp_start(struct peer *peer)
return 0;
}
- if (peer->bgp->vrf_id == VRF_UNKNOWN) {
+ if (peer->bgp->inst_type != BGP_INSTANCE_TYPE_VIEW &&
+ peer->bgp->vrf_id == VRF_UNKNOWN) {
if (bgp_debug_neighbor_events(peer))
flog_err(
EC_BGP_FSM,
diff --git a/bgpd/bgp_labelpool.c b/bgpd/bgp_labelpool.c
index 181f864575..69dd0f9dac 100644
--- a/bgpd/bgp_labelpool.c
+++ b/bgpd/bgp_labelpool.c
@@ -180,14 +180,12 @@ static void lp_cbq_item_free(struct work_queue *wq, void *data)
static void lp_lcb_free(void *goner)
{
- if (goner)
- XFREE(MTYPE_BGP_LABEL_CB, goner);
+ XFREE(MTYPE_BGP_LABEL_CB, goner);
}
static void lp_chunk_free(void *goner)
{
- if (goner)
- XFREE(MTYPE_BGP_LABEL_CHUNK, goner);
+ XFREE(MTYPE_BGP_LABEL_CHUNK, goner);
}
void bgp_lp_init(struct thread_master *master, struct labelpool *pool)
diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c
index cfc9af7777..44766c9b6e 100644
--- a/bgpd/bgp_lcommunity.c
+++ b/bgpd/bgp_lcommunity.c
@@ -38,17 +38,14 @@ static struct hash *lcomhash;
/* Allocate a new lcommunities. */
static struct lcommunity *lcommunity_new(void)
{
- return (struct lcommunity *)XCALLOC(MTYPE_LCOMMUNITY,
- sizeof(struct lcommunity));
+ return XCALLOC(MTYPE_LCOMMUNITY, sizeof(struct lcommunity));
}
/* Allocate lcommunities. */
void lcommunity_free(struct lcommunity **lcom)
{
- if ((*lcom)->val)
- XFREE(MTYPE_LCOMMUNITY_VAL, (*lcom)->val);
- if ((*lcom)->str)
- XFREE(MTYPE_LCOMMUNITY_STR, (*lcom)->str);
+ XFREE(MTYPE_LCOMMUNITY_VAL, (*lcom)->val);
+ XFREE(MTYPE_LCOMMUNITY_STR, (*lcom)->str);
XFREE(MTYPE_LCOMMUNITY, *lcom);
}
@@ -180,7 +177,7 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
{
int i;
int len;
- bool first = 1;
+ bool first = true;
char *str_buf;
char *str_pnt;
uint8_t *pnt;
@@ -218,7 +215,7 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
for (i = 0; i < lcom->size; i++) {
if (first)
- first = 0;
+ first = false;
else
*str_pnt++ = ' ';
@@ -319,10 +316,10 @@ bool lcommunity_cmp(const void *arg1, const void *arg2)
const struct lcommunity *lcom2 = arg2;
if (lcom1 == NULL && lcom2 == NULL)
- return 1;
+ return true;
if (lcom1 == NULL || lcom2 == NULL)
- return 0;
+ return false;
return (lcom1->size == lcom2->size
&& memcmp(lcom1->val, lcom2->val, lcom_length(lcom1)) == 0);
@@ -537,3 +534,112 @@ void lcommunity_del_val(struct lcommunity *lcom, uint8_t *ptr)
i++;
}
}
+
+static struct lcommunity *bgp_aggr_lcommunity_lookup(
+ struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity)
+{
+ return hash_lookup(aggregate->lcommunity_hash, lcommunity);
+}
+
+static void *bgp_aggr_lcommunty_hash_alloc(void *p)
+{
+ struct lcommunity *ref = (struct lcommunity *)p;
+ struct lcommunity *lcommunity = NULL;
+
+ lcommunity = lcommunity_dup(ref);
+ return lcommunity;
+}
+
+static void bgp_aggr_lcommunity_prepare(struct hash_backet *hb, void *arg)
+{
+ struct lcommunity *lcommerge = NULL;
+ struct lcommunity *hb_lcommunity = hb->data;
+ struct lcommunity **aggr_lcommunity = arg;
+
+ if (*aggr_lcommunity) {
+ lcommerge = lcommunity_merge(*aggr_lcommunity, hb_lcommunity);
+ *aggr_lcommunity = lcommunity_uniq_sort(lcommerge);
+ lcommunity_free(&lcommerge);
+ } else
+ *aggr_lcommunity = lcommunity_dup(hb_lcommunity);
+}
+
+void bgp_aggr_lcommunity_remove(void *arg)
+{
+ struct lcommunity *lcommunity = arg;
+
+ lcommunity_free(&lcommunity);
+}
+
+void bgp_compute_aggregate_lcommunity(struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity)
+{
+ struct lcommunity *aggr_lcommunity = NULL;
+
+ if ((aggregate == NULL) || (lcommunity == NULL))
+ return;
+
+ /* Create hash if not already created.
+ */
+ if (aggregate->lcommunity_hash == NULL)
+ aggregate->lcommunity_hash = hash_create(
+ lcommunity_hash_make, lcommunity_cmp,
+ "BGP Aggregator lcommunity hash");
+
+ aggr_lcommunity = bgp_aggr_lcommunity_lookup(aggregate, lcommunity);
+ if (aggr_lcommunity == NULL) {
+ /* Insert lcommunity into hash.
+ */
+ aggr_lcommunity = hash_get(aggregate->lcommunity_hash,
+ lcommunity,
+ bgp_aggr_lcommunty_hash_alloc);
+
+ /* Re-compute aggregate's lcommunity.
+ */
+ if (aggregate->lcommunity)
+ lcommunity_free(&aggregate->lcommunity);
+
+ hash_iterate(aggregate->lcommunity_hash,
+ bgp_aggr_lcommunity_prepare,
+ &aggregate->lcommunity);
+ }
+
+ /* Increment refernce counter.
+ */
+ aggr_lcommunity->refcnt++;
+}
+
+void bgp_remove_lcommunity_from_aggregate(struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity)
+{
+ struct lcommunity *aggr_lcommunity = NULL;
+ struct lcommunity *ret_lcomm = NULL;
+
+ if ((aggregate == NULL) || (lcommunity == NULL))
+ return;
+
+ if (aggregate->lcommunity_hash == NULL)
+ return;
+
+ /* Look-up the lcommunity in the hash.
+ */
+ aggr_lcommunity = bgp_aggr_lcommunity_lookup(aggregate, lcommunity);
+ if (aggr_lcommunity) {
+ aggr_lcommunity->refcnt--;
+
+ if (aggr_lcommunity->refcnt == 0) {
+ ret_lcomm = hash_release(aggregate->lcommunity_hash,
+ aggr_lcommunity);
+ lcommunity_free(&ret_lcomm);
+
+ lcommunity_free(&aggregate->lcommunity);
+
+ /* Compute aggregate's lcommunity.
+ */
+ hash_iterate(aggregate->lcommunity_hash,
+ bgp_aggr_lcommunity_prepare,
+ &aggregate->lcommunity);
+ }
+ }
+}
diff --git a/bgpd/bgp_lcommunity.h b/bgpd/bgp_lcommunity.h
index 23c777d9fd..aa4e8c69fe 100644
--- a/bgpd/bgp_lcommunity.h
+++ b/bgpd/bgp_lcommunity.h
@@ -22,6 +22,7 @@
#define _QUAGGA_BGP_LCOMMUNITY_H
#include "lib/json.h"
+#include "bgpd/bgp_route.h"
/* Large Communities value is twelve octets long. */
#define LCOMMUNITY_SIZE 12
@@ -70,4 +71,13 @@ extern int lcommunity_match(const struct lcommunity *,
extern char *lcommunity_str(struct lcommunity *, bool make_json);
extern int lcommunity_include(struct lcommunity *lcom, uint8_t *ptr);
extern void lcommunity_del_val(struct lcommunity *lcom, uint8_t *ptr);
+
+extern void bgp_compute_aggregate_lcommunity(
+ struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity);
+extern void bgp_remove_lcommunity_from_aggregate(
+ struct bgp_aggregate *aggregate,
+ struct lcommunity *lcommunity);
+extern void bgp_aggr_lcommunity_remove(void *arg);
+
#endif /* _QUAGGA_BGP_LCOMMUNITY_H */
diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c
index 4a408df858..49b5854020 100644
--- a/bgpd/bgp_mac.c
+++ b/bgpd/bgp_mac.c
@@ -311,11 +311,35 @@ void bgp_mac_del_mac_entry(struct interface *ifp)
bgp_mac_remove_ifp_internal(bsm, ifp->name);
}
-bool bgp_mac_entry_exists(struct prefix *p)
+/* This API checks MAC address against any of local
+ * assigned (SVIs) MAC address.
+ * An example: router-mac attribute in any of evpn update
+ * requires to compare against local mac.
+ */
+bool bgp_mac_exist(struct ethaddr *mac)
{
- struct prefix_evpn *pevpn = (struct prefix_evpn *)p;
struct bgp_self_mac lookup;
struct bgp_self_mac *bsm;
+ static uint8_t tmp [ETHER_ADDR_STRLEN] = {0};
+
+ if (memcmp(mac, &tmp, ETH_ALEN) == 0)
+ return false;
+
+ memcpy(&lookup.macaddr, mac, ETH_ALEN);
+ bsm = hash_lookup(bm->self_mac_hash, &lookup);
+ if (!bsm)
+ return false;
+
+ return true;
+}
+
+/* This API checks EVPN type-2 prefix and comapares
+ * mac against any of local assigned (SVIs) MAC
+ * address.
+ */
+bool bgp_mac_entry_exists(struct prefix *p)
+{
+ struct prefix_evpn *pevpn = (struct prefix_evpn *)p;
if (pevpn->family != AF_EVPN)
return false;
@@ -323,10 +347,7 @@ bool bgp_mac_entry_exists(struct prefix *p)
if (pevpn->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
return false;
- memcpy(&lookup.macaddr, &p->u.prefix_evpn.macip_addr.mac, ETH_ALEN);
- bsm = hash_lookup(bm->self_mac_hash, &lookup);
- if (!bsm)
- return false;
+ return bgp_mac_exist(&p->u.prefix_evpn.macip_addr.mac);
return true;
}
diff --git a/bgpd/bgp_mac.h b/bgpd/bgp_mac.h
index 1dd987ef12..68449b574a 100644
--- a/bgpd/bgp_mac.h
+++ b/bgpd/bgp_mac.h
@@ -37,5 +37,6 @@ void bgp_mac_dump_table(struct vty *vty);
* Function to lookup the prefix and see if we have a matching mac
*/
bool bgp_mac_entry_exists(struct prefix *p);
+bool bgp_mac_exist(struct ethaddr *mac);
#endif
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index 241146e451..d5b3d6b197 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -671,7 +671,7 @@ void bgp_mp_dmed_deselect(struct bgp_path_info *dmed_best)
bgp_path_info_mpath_count_set(dmed_best, 0);
UNSET_FLAG(dmed_best->flags, BGP_PATH_MULTIPATH_CHG);
- assert(bgp_path_info_mpath_first(dmed_best) == 0);
+ assert(bgp_path_info_mpath_first(dmed_best) == NULL);
}
/*
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 2d3ff8b695..35634c9ec1 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -1094,8 +1094,6 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
*/
uint8_t nhfamily = NEXTHOP_FAMILY(path_vpn->attr->mp_nexthop_len);
- if (nhfamily != AF_UNSPEC)
- static_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
memset(&nexthop_orig, 0, sizeof(nexthop_orig));
nexthop_orig.family = nhfamily;
@@ -1115,6 +1113,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */
static_attr.mp_nexthop_len =
path_vpn->attr->mp_nexthop_len;
}
+ static_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
break;
case AF_INET6:
/* save */
diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c
index 4c51db8e14..c0be36ed3f 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -333,7 +333,7 @@ static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[],
unary_operator, and_valmask,
or_valmask, list[i].value,
type_entry);
- if (ret == false)
+ if (!ret)
return ret;
continue;
}
@@ -441,7 +441,7 @@ static bool bgp_pbr_extract(struct bgp_pbr_match_val list[],
range->min_port = list[i].value;
exact_match = true;
}
- if (exact_match == true && i > 0)
+ if (exact_match && i > 0)
return false;
if (list[i].compare_operator ==
(OPERATOR_COMPARE_GREATER_THAN +
@@ -545,7 +545,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
"too complex. ignoring.");
return 0;
} else if (api->match_icmp_type_num > 1 &&
- enumerate_icmp == false) {
+ !enumerate_icmp) {
if (BGP_DEBUG(pbr, PBR))
zlog_debug("BGP: match icmp code is enumerate"
", and icmp type is not."
diff --git a/bgpd/bgp_rd.c b/bgpd/bgp_rd.c
index 77f5aade5f..571139a49a 100644
--- a/bgpd/bgp_rd.c
+++ b/bgpd/bgp_rd.c
@@ -155,8 +155,7 @@ int str2prefix_rd(const char *str, struct prefix_rd *prd)
out:
if (s)
stream_free(s);
- if (half)
- XFREE(MTYPE_TMP, half);
+ XFREE(MTYPE_TMP, half);
return lret;
}
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 0b6c536f5a..eca632dd44 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -3096,7 +3096,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
goto filtered;
}
- if (bgp_mac_entry_exists(p)) {
+ if (bgp_mac_entry_exists(p) || bgp_mac_exist(&attr->rmac)) {
reason = "self mac;";
goto filtered;
}
@@ -3285,7 +3285,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
extra = bgp_path_info_extra_get(pi);
if (extra->label != label) {
memcpy(&extra->label, label,
- num_labels * sizeof(mpls_label_t));
+ num_labels * sizeof(mpls_label_t));
extra->num_labels = num_labels;
}
if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
@@ -3457,7 +3457,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
if (has_valid_label) {
extra = bgp_path_info_extra_get(new);
if (extra->label != label) {
- memcpy(&extra->label, label, num_labels * sizeof(mpls_label_t));
+ memcpy(&extra->label, label,
+ num_labels * sizeof(mpls_label_t));
extra->num_labels = num_labels;
}
if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
@@ -4469,12 +4470,10 @@ static struct bgp_static *bgp_static_new(void)
static void bgp_static_free(struct bgp_static *bgp_static)
{
- if (bgp_static->rmap.name)
- XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
+ XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
route_map_counter_decrement(bgp_static->rmap.map);
- if (bgp_static->eth_s_id)
- XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
+ XFREE(MTYPE_ATTR, bgp_static->eth_s_id);
XFREE(MTYPE_BGP_STATIC, bgp_static);
}
@@ -5034,9 +5033,8 @@ static int bgp_static_set(struct vty *vty, const char *negate,
bgp_static->backdoor = backdoor;
if (rmap) {
- if (bgp_static->rmap.name)
- XFREE(MTYPE_ROUTE_MAP_NAME,
- bgp_static->rmap.name);
+ XFREE(MTYPE_ROUTE_MAP_NAME,
+ bgp_static->rmap.name);
route_map_counter_decrement(
bgp_static->rmap.map);
bgp_static->rmap.name =
@@ -5046,9 +5044,8 @@ static int bgp_static_set(struct vty *vty, const char *negate,
route_map_counter_increment(
bgp_static->rmap.map);
} else {
- if (bgp_static->rmap.name)
- XFREE(MTYPE_ROUTE_MAP_NAME,
- bgp_static->rmap.name);
+ XFREE(MTYPE_ROUTE_MAP_NAME,
+ bgp_static->rmap.name);
route_map_counter_decrement(
bgp_static->rmap.map);
bgp_static->rmap.name = NULL;
@@ -5066,9 +5063,8 @@ static int bgp_static_set(struct vty *vty, const char *negate,
bgp_static->label_index = label_index;
if (rmap) {
- if (bgp_static->rmap.name)
- XFREE(MTYPE_ROUTE_MAP_NAME,
- bgp_static->rmap.name);
+ XFREE(MTYPE_ROUTE_MAP_NAME,
+ bgp_static->rmap.name);
route_map_counter_decrement(
bgp_static->rmap.map);
bgp_static->rmap.name =
@@ -5352,9 +5348,7 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
bgp_static->prd = prd;
if (rmap_str) {
- if (bgp_static->rmap.name)
- XFREE(MTYPE_ROUTE_MAP_NAME,
- bgp_static->rmap.name);
+ XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name);
route_map_counter_decrement(bgp_static->rmap.map);
bgp_static->rmap.name =
XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str);
@@ -5461,15 +5455,13 @@ static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
rmap = &bgp->table_map[afi][safi];
if (rmap_name) {
- if (rmap->name)
- XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
+ XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
route_map_counter_decrement(rmap->map);
rmap->name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
rmap->map = route_map_lookup_by_name(rmap_name);
route_map_counter_increment(rmap->map);
} else {
- if (rmap->name)
- XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
+ XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
route_map_counter_decrement(rmap->map);
rmap->name = NULL;
rmap->map = NULL;
@@ -5488,8 +5480,7 @@ static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
struct bgp_rmap *rmap;
rmap = &bgp->table_map[afi][safi];
- if (rmap->name)
- XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
+ XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
route_map_counter_decrement(rmap->map);
rmap->name = NULL;
rmap->map = NULL;
@@ -5585,33 +5576,6 @@ DEFPY(ipv6_bgp_network,
label_index ? (uint32_t)label_index : BGP_INVALID_LABEL_INDEX);
}
-/* Aggreagete address:
-
- advertise-map Set condition to advertise attribute
- as-set Generate AS set path information
- attribute-map Set attributes of aggregate
- route-map Set parameters of aggregate
- summary-only Filter more specific routes from updates
- suppress-map Conditionally filter more specific routes from updates
- <cr>
- */
-struct bgp_aggregate {
- /* Summary-only flag. */
- uint8_t summary_only;
-
- /* AS set generation. */
- uint8_t as_set;
-
- /* Route-map for aggregated route. */
- struct route_map *map;
-
- /* Suppress-count. */
- unsigned long count;
-
- /* SAFI configuration. */
- safi_t safi;
-};
-
static struct bgp_aggregate *bgp_aggregate_new(void)
{
return XCALLOC(MTYPE_BGP_AGGREGATE, sizeof(struct bgp_aggregate));
@@ -5737,8 +5701,7 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi,
/* Update an aggregate as routes are added/removed from the BGP table */
static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
- struct bgp_path_info *pinew, afi_t afi,
- safi_t safi, struct bgp_path_info *del,
+ afi_t afi, safi_t safi,
struct bgp_aggregate *aggregate)
{
struct bgp_table *table;
@@ -5746,13 +5709,9 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
struct bgp_node *rn;
uint8_t origin;
struct aspath *aspath = NULL;
- struct aspath *asmerge = NULL;
struct community *community = NULL;
- struct community *commerge = NULL;
struct ecommunity *ecommunity = NULL;
- struct ecommunity *ecommerge = NULL;
struct lcommunity *lcommunity = NULL;
- struct lcommunity *lcommerge = NULL;
struct bgp_path_info *pi;
unsigned long match = 0;
uint8_t atomic_aggregate = 0;
@@ -5781,9 +5740,6 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
if (BGP_PATH_HOLDDOWN(pi))
continue;
- if (del && pi == del)
- continue;
-
if (pi->attr->flag
& ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))
atomic_aggregate = 1;
@@ -5814,8 +5770,18 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
* route MUST have the ORIGIN attribute with the value
* EGP.
*/
- if (origin < pi->attr->origin)
- origin = pi->attr->origin;
+ switch (pi->attr->origin) {
+ case BGP_ORIGIN_INCOMPLETE:
+ aggregate->incomplete_origin_count++;
+ break;
+ case BGP_ORIGIN_EGP:
+ aggregate->egp_origin_count++;
+ break;
+ default:
+ /*Do nothing.
+ */
+ break;
+ }
if (!aggregate->as_set)
continue;
@@ -5824,130 +5790,68 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
* as-set aggregate route generate origin, as path,
* and community aggregation.
*/
- if (aspath) {
- asmerge = aspath_aggregate(aspath,
- pi->attr->aspath);
- aspath_free(aspath);
- aspath = asmerge;
- } else
- aspath = aspath_dup(pi->attr->aspath);
-
- if (pi->attr->community) {
- if (community) {
- commerge = community_merge(
- community, pi->attr->community);
- community =
- community_uniq_sort(commerge);
- community_free(&commerge);
- } else
- community = community_dup(
- pi->attr->community);
- }
-
- if (pi->attr->ecommunity) {
- if (ecommunity) {
- ecommerge = ecommunity_merge(
- ecommunity,
- pi->attr->ecommunity);
- ecommunity =
- ecommunity_uniq_sort(ecommerge);
- ecommunity_free(&ecommerge);
- } else
- ecommunity = ecommunity_dup(
- pi->attr->ecommunity);
- }
-
- if (pi->attr->lcommunity) {
- if (lcommunity) {
- lcommerge = lcommunity_merge(
- lcommunity,
- pi->attr->lcommunity);
- lcommunity =
- lcommunity_uniq_sort(lcommerge);
- lcommunity_free(&lcommerge);
- } else
- lcommunity = lcommunity_dup(
- pi->attr->lcommunity);
- }
+ /* Compute aggregate route's as-path.
+ */
+ bgp_compute_aggregate_aspath(aggregate,
+ pi->attr->aspath);
+
+ /* Compute aggregate route's community.
+ */
+ if (pi->attr->community)
+ bgp_compute_aggregate_community(
+ aggregate,
+ pi->attr->community);
+
+ /* Compute aggregate route's extended community.
+ */
+ if (pi->attr->ecommunity)
+ bgp_compute_aggregate_ecommunity(
+ aggregate,
+ pi->attr->ecommunity);
+
+ /* Compute aggregate route's large community.
+ */
+ if (pi->attr->lcommunity)
+ bgp_compute_aggregate_lcommunity(
+ aggregate,
+ pi->attr->lcommunity);
}
if (match)
bgp_process(bgp, rn, afi, safi);
}
bgp_unlock_node(top);
- if (pinew) {
- aggregate->count++;
- if (aggregate->summary_only)
- (bgp_path_info_extra_get(pinew))->suppress++;
+ if (aggregate->incomplete_origin_count > 0)
+ origin = BGP_ORIGIN_INCOMPLETE;
+ else if (aggregate->egp_origin_count > 0)
+ origin = BGP_ORIGIN_EGP;
- if (origin < pinew->attr->origin)
- origin = pinew->attr->origin;
+ if (aggregate->as_set) {
+ if (aggregate->aspath)
+ /* Retrieve aggregate route's as-path.
+ */
+ aspath = aspath_dup(aggregate->aspath);
- if (aggregate->as_set) {
- if (aspath) {
- asmerge = aspath_aggregate(aspath,
- pinew->attr->aspath);
- aspath_free(aspath);
- aspath = asmerge;
- } else
- aspath = aspath_dup(pinew->attr->aspath);
+ if (aggregate->community)
+ /* Retrieve aggregate route's community.
+ */
+ community = community_dup(aggregate->community);
- if (pinew->attr->community) {
- if (community) {
- commerge = community_merge(
- community,
- pinew->attr->community);
- community =
- community_uniq_sort(commerge);
- community_free(&commerge);
- } else
- community = community_dup(
- pinew->attr->community);
- }
+ if (aggregate->ecommunity)
+ /* Retrieve aggregate route's ecommunity.
+ */
+ ecommunity = ecommunity_dup(aggregate->ecommunity);
- if (pinew->attr->ecommunity) {
- if (ecommunity) {
- ecommerge = ecommunity_merge(
- ecommunity,
- pinew->attr->ecommunity);
- ecommunity =
- ecommunity_uniq_sort(ecommerge);
- ecommunity_free(&ecommerge);
- } else
- ecommunity = ecommunity_dup(
- pinew->attr->ecommunity);
- }
-
- if (pinew->attr->lcommunity) {
- if (lcommunity) {
- lcommerge = lcommunity_merge(
- lcommunity,
- pinew->attr->lcommunity);
- lcommunity =
- lcommunity_uniq_sort(lcommerge);
- lcommunity_free(&lcommerge);
- } else
- lcommunity = lcommunity_dup(
- pinew->attr->lcommunity);
- }
- }
+ if (aggregate->lcommunity)
+ /* Retrieve aggregate route's lcommunity.
+ */
+ lcommunity = lcommunity_dup(aggregate->lcommunity);
}
bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community,
ecommunity, lcommunity, atomic_aggregate,
aggregate);
-
- if (aggregate->count == 0) {
- if (aspath)
- aspath_free(aspath);
- if (community)
- community_free(&community);
- if (ecommunity)
- ecommunity_free(&ecommunity);
- if (lcommunity)
- lcommunity_free(&lcommunity);
- }
}
static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
@@ -5986,6 +5890,41 @@ static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
}
}
aggregate->count--;
+
+ if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
+ aggregate->incomplete_origin_count--;
+ else if (pi->attr->origin == BGP_ORIGIN_EGP)
+ aggregate->egp_origin_count--;
+
+ if (aggregate->as_set) {
+ /* Remove as-path from aggregate.
+ */
+ bgp_remove_aspath_from_aggregate(
+ aggregate,
+ pi->attr->aspath);
+
+ if (pi->attr->community)
+ /* Remove community from aggregate.
+ */
+ bgp_remove_community_from_aggregate(
+ aggregate,
+ pi->attr->community);
+
+ if (pi->attr->ecommunity)
+ /* Remove ecommunity from aggregate.
+ */
+ bgp_remove_ecommunity_from_aggregate(
+ aggregate,
+ pi->attr->ecommunity);
+
+ if (pi->attr->lcommunity)
+ /* Remove lcommunity from aggregate.
+ */
+ bgp_remove_lcommunity_from_aggregate(
+ aggregate,
+ pi->attr->lcommunity);
+ }
+
}
/* If this node was suppressed, process the change. */
@@ -5995,6 +5934,210 @@ static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi,
bgp_unlock_node(top);
}
+static void bgp_add_route_to_aggregate(struct bgp *bgp, struct prefix *aggr_p,
+ struct bgp_path_info *pinew, afi_t afi,
+ safi_t safi,
+ struct bgp_aggregate *aggregate)
+{
+ uint8_t origin;
+ struct aspath *aspath = NULL;
+ uint8_t atomic_aggregate = 0;
+ struct community *community = NULL;
+ struct ecommunity *ecommunity = NULL;
+ struct lcommunity *lcommunity = NULL;
+
+ /* ORIGIN attribute: If at least one route among routes that are
+ * aggregated has ORIGIN with the value INCOMPLETE, then the
+ * aggregated route must have the ORIGIN attribute with the value
+ * INCOMPLETE. Otherwise, if at least one route among routes that
+ * are aggregated has ORIGIN with the value EGP, then the aggregated
+ * route must have the origin attribute with the value EGP. In all
+ * other case the value of the ORIGIN attribute of the aggregated
+ * route is INTERNAL.
+ */
+ origin = BGP_ORIGIN_IGP;
+
+ aggregate->count++;
+
+ if (aggregate->summary_only)
+ (bgp_path_info_extra_get(pinew))->suppress++;
+
+ switch (pinew->attr->origin) {
+ case BGP_ORIGIN_INCOMPLETE:
+ aggregate->incomplete_origin_count++;
+ break;
+ case BGP_ORIGIN_EGP:
+ aggregate->egp_origin_count++;
+ break;
+ default:
+ /* Do nothing.
+ */
+ break;
+ }
+
+ if (aggregate->incomplete_origin_count > 0)
+ origin = BGP_ORIGIN_INCOMPLETE;
+ else if (aggregate->egp_origin_count > 0)
+ origin = BGP_ORIGIN_EGP;
+
+ if (aggregate->as_set) {
+ /* Compute aggregate route's as-path.
+ */
+ bgp_compute_aggregate_aspath(aggregate,
+ pinew->attr->aspath);
+
+ /* Compute aggregate route's community.
+ */
+ if (pinew->attr->community)
+ bgp_compute_aggregate_community(
+ aggregate,
+ pinew->attr->community);
+
+ /* Compute aggregate route's extended community.
+ */
+ if (pinew->attr->ecommunity)
+ bgp_compute_aggregate_ecommunity(
+ aggregate,
+ pinew->attr->ecommunity);
+
+ /* Compute aggregate route's large community.
+ */
+ if (pinew->attr->lcommunity)
+ bgp_compute_aggregate_lcommunity(
+ aggregate,
+ pinew->attr->lcommunity);
+
+ /* Retrieve aggregate route's as-path.
+ */
+ if (aggregate->aspath)
+ aspath = aspath_dup(aggregate->aspath);
+
+ /* Retrieve aggregate route's community.
+ */
+ if (aggregate->community)
+ community = community_dup(aggregate->community);
+
+ /* Retrieve aggregate route's ecommunity.
+ */
+ if (aggregate->ecommunity)
+ ecommunity = ecommunity_dup(aggregate->ecommunity);
+
+ /* Retrieve aggregate route's lcommunity.
+ */
+ if (aggregate->lcommunity)
+ lcommunity = lcommunity_dup(aggregate->lcommunity);
+ }
+
+ bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
+ aspath, community, ecommunity,
+ lcommunity, atomic_aggregate, aggregate);
+}
+
+static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
+ safi_t safi,
+ struct bgp_path_info *pi,
+ struct bgp_aggregate *aggregate,
+ struct prefix *aggr_p)
+{
+ uint8_t origin;
+ struct aspath *aspath = NULL;
+ uint8_t atomic_aggregate = 0;
+ struct community *community = NULL;
+ struct ecommunity *ecommunity = NULL;
+ struct lcommunity *lcommunity = NULL;
+ unsigned long match = 0;
+
+ if (BGP_PATH_HOLDDOWN(pi))
+ return;
+
+ if (pi->sub_type == BGP_ROUTE_AGGREGATE)
+ return;
+
+ if (aggregate->summary_only
+ && pi->extra
+ && pi->extra->suppress > 0) {
+ pi->extra->suppress--;
+
+ if (pi->extra->suppress == 0) {
+ bgp_path_info_set_flag(pi->net, pi,
+ BGP_PATH_ATTR_CHANGED);
+ match++;
+ }
+ }
+
+ if (aggregate->count > 0)
+ aggregate->count--;
+
+ if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
+ aggregate->incomplete_origin_count--;
+ else if (pi->attr->origin == BGP_ORIGIN_EGP)
+ aggregate->egp_origin_count--;
+
+ if (aggregate->as_set) {
+ /* Remove as-path from aggregate.
+ */
+ bgp_remove_aspath_from_aggregate(aggregate,
+ pi->attr->aspath);
+
+ if (pi->attr->community)
+ /* Remove community from aggregate.
+ */
+ bgp_remove_community_from_aggregate(
+ aggregate,
+ pi->attr->community);
+
+ if (pi->attr->ecommunity)
+ /* Remove ecommunity from aggregate.
+ */
+ bgp_remove_ecommunity_from_aggregate(
+ aggregate,
+ pi->attr->ecommunity);
+
+ if (pi->attr->lcommunity)
+ /* Remove lcommunity from aggregate.
+ */
+ bgp_remove_lcommunity_from_aggregate(
+ aggregate,
+ pi->attr->lcommunity);
+ }
+
+ /* If this node was suppressed, process the change. */
+ if (match)
+ bgp_process(bgp, pi->net, afi, safi);
+
+ origin = BGP_ORIGIN_IGP;
+ if (aggregate->incomplete_origin_count > 0)
+ origin = BGP_ORIGIN_INCOMPLETE;
+ else if (aggregate->egp_origin_count > 0)
+ origin = BGP_ORIGIN_EGP;
+
+ if (aggregate->as_set) {
+ /* Retrieve aggregate route's as-path.
+ */
+ if (aggregate->aspath)
+ aspath = aspath_dup(aggregate->aspath);
+
+ /* Retrieve aggregate route's community.
+ */
+ if (aggregate->community)
+ community = community_dup(aggregate->community);
+
+ /* Retrieve aggregate route's ecommunity.
+ */
+ if (aggregate->ecommunity)
+ ecommunity = ecommunity_dup(aggregate->ecommunity);
+
+ /* Retrieve aggregate route's lcommunity.
+ */
+ if (aggregate->lcommunity)
+ lcommunity = lcommunity_dup(aggregate->lcommunity);
+ }
+
+ bgp_aggregate_install(bgp, afi, safi, aggr_p, origin,
+ aspath, community, ecommunity,
+ lcommunity, atomic_aggregate, aggregate);
+}
+
void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
struct bgp_path_info *pi, afi_t afi, safi_t safi)
{
@@ -6021,9 +6164,8 @@ void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p,
for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
aggregate = bgp_node_get_bgp_aggregate_info(rn);
if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
- bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
- bgp_aggregate_route(bgp, &rn->p, pi, afi, safi, NULL,
- aggregate);
+ bgp_add_route_to_aggregate(bgp, &rn->p, pi, afi,
+ safi, aggregate);
}
}
bgp_unlock_node(child);
@@ -6052,9 +6194,8 @@ void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
for (rn = child; rn; rn = bgp_node_parent_nolock(rn)) {
aggregate = bgp_node_get_bgp_aggregate_info(rn);
if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) {
- bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate);
- bgp_aggregate_route(bgp, &rn->p, NULL, afi, safi, del,
- aggregate);
+ bgp_remove_route_from_aggregate(bgp, afi, safi,
+ del, aggregate, &rn->p);
}
}
bgp_unlock_node(child);
@@ -6096,6 +6237,59 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
/* Unlock aggregate address configuration. */
bgp_node_set_bgp_aggregate_info(rn, NULL);
+
+ if (aggregate->community)
+ community_free(&aggregate->community);
+
+ if (aggregate->community_hash) {
+ /* Delete all communities in the hash.
+ */
+ hash_clean(aggregate->community_hash,
+ bgp_aggr_community_remove);
+ /* Free up the community_hash.
+ */
+ hash_free(aggregate->community_hash);
+ }
+
+ if (aggregate->ecommunity)
+ ecommunity_free(&aggregate->ecommunity);
+
+ if (aggregate->ecommunity_hash) {
+ /* Delete all ecommunities in the hash.
+ */
+ hash_clean(aggregate->ecommunity_hash,
+ bgp_aggr_ecommunity_remove);
+ /* Free up the ecommunity_hash.
+ */
+ hash_free(aggregate->ecommunity_hash);
+ }
+
+ if (aggregate->lcommunity)
+ lcommunity_free(&aggregate->lcommunity);
+
+ if (aggregate->lcommunity_hash) {
+ /* Delete all lcommunities in the hash.
+ */
+ hash_clean(aggregate->lcommunity_hash,
+ bgp_aggr_lcommunity_remove);
+ /* Free up the lcommunity_hash.
+ */
+ hash_free(aggregate->lcommunity_hash);
+ }
+
+ if (aggregate->aspath)
+ aspath_free(aggregate->aspath);
+
+ if (aggregate->aspath_hash) {
+ /* Delete all as-paths in the hash.
+ */
+ hash_clean(aggregate->aspath_hash,
+ bgp_aggr_aspath_remove);
+ /* Free up the aspath_hash.
+ */
+ hash_free(aggregate->aspath_hash);
+ }
+
bgp_aggregate_free(aggregate);
bgp_unlock_node(rn);
bgp_unlock_node(rn);
@@ -6149,7 +6343,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
bgp_node_set_bgp_aggregate_info(rn, aggregate);
/* Aggregate address insert into BGP routing table. */
- bgp_aggregate_route(bgp, &p, NULL, afi, safi, NULL, aggregate);
+ bgp_aggregate_route(bgp, &p, afi, safi, aggregate);
return CMD_SUCCESS;
}
@@ -11259,8 +11453,7 @@ static int bgp_distance_unset(struct vty *vty, const char *distance_str,
return CMD_WARNING_CONFIG_FAILED;
}
- if (bdistance->access_list)
- XFREE(MTYPE_AS_LIST, bdistance->access_list);
+ XFREE(MTYPE_AS_LIST, bdistance->access_list);
bgp_distance_free(bdistance);
bgp_node_set_bgp_path_info(rn, NULL);
@@ -11847,10 +12040,8 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
decode_label(&bgp_static->label), esi, buf2,
macrouter);
- if (macrouter)
- XFREE(MTYPE_TMP, macrouter);
- if (esi)
- XFREE(MTYPE_TMP, esi);
+ XFREE(MTYPE_TMP, macrouter);
+ XFREE(MTYPE_TMP, esi);
}
}
}
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 1527571278..fc5bf0c755 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -272,6 +272,71 @@ struct bgp_static {
struct prefix gatewayIp;
};
+/* Aggreagete address:
+ *
+ * advertise-map Set condition to advertise attribute
+ * as-set Generate AS set path information
+ * attribute-map Set attributes of aggregate
+ * route-map Set parameters of aggregate
+ * summary-only Filter more specific routes from updates
+ * suppress-map Conditionally filter more specific routes from updates
+ * <cr>
+ */
+struct bgp_aggregate {
+ /* Summary-only flag. */
+ uint8_t summary_only;
+
+ /* AS set generation. */
+ uint8_t as_set;
+
+ /* Route-map for aggregated route. */
+ struct route_map *map;
+
+ /* Suppress-count. */
+ unsigned long count;
+
+ /* Count of routes of origin type incomplete under this aggregate. */
+ unsigned long incomplete_origin_count;
+
+ /* Count of routes of origin type egp under this aggregate. */
+ unsigned long egp_origin_count;
+
+ /* Hash containing the communities of all the
+ * routes under this aggregate.
+ */
+ struct hash *community_hash;
+
+ /* Hash containing the extended communities of all the
+ * routes under this aggregate.
+ */
+ struct hash *ecommunity_hash;
+
+ /* Hash containing the large communities of all the
+ * routes under this aggregate.
+ */
+ struct hash *lcommunity_hash;
+
+ /* Hash containing the AS-Path of all the
+ * routes under this aggregate.
+ */
+ struct hash *aspath_hash;
+
+ /* Aggregate route's community. */
+ struct community *community;
+
+ /* Aggregate route's extended community. */
+ struct ecommunity *ecommunity;
+
+ /* Aggregate route's large community. */
+ struct lcommunity *lcommunity;
+
+ /* Aggregate route's as-path. */
+ struct aspath *aspath;
+
+ /* SAFI configuration. */
+ safi_t safi;
+};
+
#define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \
((nhlen) < IPV4_MAX_BYTELEN \
? 0 \
@@ -279,7 +344,10 @@ struct bgp_static {
#define BGP_ATTR_NEXTHOP_AFI_IP6(attr) \
(!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) \
- && ((attr)->mp_nexthop_len == 16 || (attr)->mp_nexthop_len == 32))
+ && ((attr)->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL \
+ || (attr)->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL \
+ || (attr)->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL \
+ || (attr)->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL))
#define BGP_PATH_COUNTABLE(BI) \
(!CHECK_FLAG((BI)->flags, BGP_PATH_HISTORY) \
&& !CHECK_FLAG((BI)->flags, BGP_PATH_REMOVED))
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 17109281bc..c276f5ef7b 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -197,8 +197,6 @@ static void *route_value_compile(const char *arg)
}
rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
- if (!rv)
- return NULL;
rv->action = action;
rv->variable = var;
@@ -324,8 +322,7 @@ static void route_match_peer_free(void *rule)
{
struct bgp_match_peer_compiled *pc = rule;
- if (pc->interface)
- XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, pc->interface);
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
}
@@ -837,8 +834,6 @@ static void *route_match_vni_compile(const char *arg)
char *end = NULL;
vni = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(vni_t));
- if (!vni)
- return NULL;
*vni = strtoul(arg, &end, 10);
if (*end != '\0') {
@@ -998,9 +993,6 @@ static void *route_match_local_pref_compile(const char *arg)
local_pref = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
- if (!local_pref)
- return local_pref;
-
*local_pref = tmpval;
return local_pref;
}
@@ -1555,8 +1547,7 @@ static void route_set_ip_nexthop_free(void *rule)
{
struct rmap_ip_nexthop_set *rins = rule;
- if (rins->address)
- XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rins->address);
XFREE(MTYPE_ROUTE_MAP_COMPILED, rins);
}
@@ -2046,22 +2037,12 @@ static route_map_result_t route_set_lcommunity_delete(void *rule,
static void *route_set_lcommunity_delete_compile(const char *arg)
{
struct rmap_community *rcom;
- char *p;
- char *str;
- int len;
rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
- p = strchr(arg, ' ');
- if (p) {
- len = p - arg;
- str = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
- memcpy(str, arg, len);
- } else
- str = NULL;
-
- rcom->name = str;
+ rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
rcom->name_hash = bgp_clist_hash_key(rcom->name);
+
return rcom;
}
@@ -2141,22 +2122,12 @@ static route_map_result_t route_set_community_delete(
static void *route_set_community_delete_compile(const char *arg)
{
struct rmap_community *rcom;
- char *p;
- char *str;
- int len;
rcom = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_community));
- p = strchr(arg, ' ');
- if (p) {
- len = p - arg;
- str = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, len + 1);
- memcpy(str, arg, len);
- } else
- str = NULL;
-
- rcom->name = str;
+ rcom->name = XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
rcom->name_hash = bgp_clist_hash_key(rcom->name);
+
return rcom;
}
@@ -3105,10 +3076,8 @@ static int bgp_route_match_delete(struct vty *vty, const char *command,
break;
}
- if (dep_name)
- XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
- if (rmap_name)
- XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
+ XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
+ XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
return retval;
}
@@ -3399,7 +3368,7 @@ static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
"Processing route_map %s update on advertise type5 route command",
rmap_name);
- if (route_update) {
+ if (route_update && advertise_type5_routes(bgp, afi)) {
bgp_evpn_withdraw_type5_routes(bgp, afi, safi);
bgp_evpn_advertise_type5_routes(bgp, afi, safi);
}
@@ -4351,17 +4320,10 @@ DEFUN (set_community_delete,
"Delete matching communities\n")
{
int idx_comm_list = 2;
- char *str;
-
- str = XCALLOC(MTYPE_TMP,
- strlen(argv[idx_comm_list]->arg) + strlen(" delete") + 1);
- strcpy(str, argv[idx_comm_list]->arg);
- strcpy(str + strlen(argv[idx_comm_list]->arg), " delete");
generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "comm-list",
- str);
+ argv[idx_comm_list]->arg);
- XFREE(MTYPE_TMP, str);
return CMD_SUCCESS;
}
@@ -4450,16 +4412,9 @@ DEFUN (set_lcommunity_delete,
"Large Community-list name\n"
"Delete matching large communities\n")
{
- char *str;
-
- str = XCALLOC(MTYPE_TMP, strlen(argv[2]->arg) + strlen(" delete") + 1);
- strcpy(str, argv[2]->arg);
- strcpy(str + strlen(argv[2]->arg), " delete");
-
generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
- "large-comm-list", str);
+ "large-comm-list", argv[2]->arg);
- XFREE(MTYPE_TMP, str);
return CMD_SUCCESS;
}
diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c
index c1321dd7dc..44cbeabd69 100644
--- a/bgpd/bgp_snmp.c
+++ b/bgpd/bgp_snmp.c
@@ -900,11 +900,10 @@ static int bgpTrapEstablished(struct peer *peer)
oid_copy_addr(index, &addr, IN_ADDR_SIZE);
- smux_trap(bgp_variables, sizeof bgp_variables / sizeof(struct variable),
- bgp_trap_oid, sizeof bgp_trap_oid / sizeof(oid), bgp_oid,
+ smux_trap(bgp_variables, array_size(bgp_variables), bgp_trap_oid,
+ array_size(bgp_trap_oid), bgp_oid,
sizeof bgp_oid / sizeof(oid), index, IN_ADDR_SIZE,
- bgpTrapList, sizeof bgpTrapList / sizeof(struct trap_object),
- BGPESTABLISHED);
+ bgpTrapList, array_size(bgpTrapList), BGPESTABLISHED);
return 0;
}
@@ -920,11 +919,10 @@ static int bgpTrapBackwardTransition(struct peer *peer)
oid_copy_addr(index, &addr, IN_ADDR_SIZE);
- smux_trap(bgp_variables, sizeof bgp_variables / sizeof(struct variable),
- bgp_trap_oid, sizeof bgp_trap_oid / sizeof(oid), bgp_oid,
+ smux_trap(bgp_variables, array_size(bgp_variables), bgp_trap_oid,
+ array_size(bgp_trap_oid), bgp_oid,
sizeof bgp_oid / sizeof(oid), index, IN_ADDR_SIZE,
- bgpTrapList, sizeof bgpTrapList / sizeof(struct trap_object),
- BGPBACKWARDTRANSITION);
+ bgpTrapList, array_size(bgpTrapList), BGPBACKWARDTRANSITION);
return 0;
}
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index b74dc33ea4..49a435120d 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -110,8 +110,7 @@ static void sync_init(struct update_subgroup *subgrp)
static void sync_delete(struct update_subgroup *subgrp)
{
- if (subgrp->sync)
- XFREE(MTYPE_BGP_SYNCHRONISE, subgrp->sync);
+ XFREE(MTYPE_BGP_SYNCHRONISE, subgrp->sync);
subgrp->sync = NULL;
if (subgrp->hash)
hash_free(subgrp->hash);
@@ -144,8 +143,7 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
dst->v_routeadv = src->v_routeadv;
dst->flags = src->flags;
dst->af_flags[afi][safi] = src->af_flags[afi][safi];
- if (dst->host)
- XFREE(MTYPE_BGP_PEER_HOST, dst->host);
+ XFREE(MTYPE_BGP_PEER_HOST, dst->host);
dst->host = XSTRDUP(MTYPE_BGP_PEER_HOST, src->host);
dst->cap = src->cap;
@@ -208,27 +206,19 @@ static void conf_release(struct peer *src, afi_t afi, safi_t safi)
srcfilter = &src->filter[afi][safi];
- if (src->default_rmap[afi][safi].name)
- XFREE(MTYPE_ROUTE_MAP_NAME, src->default_rmap[afi][safi].name);
+ XFREE(MTYPE_ROUTE_MAP_NAME, src->default_rmap[afi][safi].name);
- if (srcfilter->dlist[FILTER_OUT].name)
- XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->dlist[FILTER_OUT].name);
+ XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->dlist[FILTER_OUT].name);
- if (srcfilter->plist[FILTER_OUT].name)
- XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->plist[FILTER_OUT].name);
+ XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->plist[FILTER_OUT].name);
- if (srcfilter->aslist[FILTER_OUT].name)
- XFREE(MTYPE_BGP_FILTER_NAME,
- srcfilter->aslist[FILTER_OUT].name);
+ XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->aslist[FILTER_OUT].name);
- if (srcfilter->map[RMAP_OUT].name)
- XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->map[RMAP_OUT].name);
+ XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->map[RMAP_OUT].name);
- if (srcfilter->usmap.name)
- XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->usmap.name);
+ XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->usmap.name);
- if (src->host)
- XFREE(MTYPE_BGP_PEER_HOST, src->host);
+ XFREE(MTYPE_BGP_PEER_HOST, src->host);
src->host = NULL;
}
@@ -440,7 +430,7 @@ static bool updgrp_hash_cmp(const void *p1, const void *p2)
return false;
if (pe1->addpath_type[afi][safi] != pe2->addpath_type[afi][safi])
- return 0;
+ return false;
if ((pe1->cap & PEER_UPDGRP_CAP_FLAGS)
!= (pe2->cap & PEER_UPDGRP_CAP_FLAGS))
@@ -741,12 +731,10 @@ static void update_group_delete(struct update_group *updgrp)
hash_release(updgrp->bgp->update_groups[updgrp->afid], updgrp);
conf_release(updgrp->conf, updgrp->afi, updgrp->safi);
- if (updgrp->conf->host)
- XFREE(MTYPE_BGP_PEER_HOST, updgrp->conf->host);
+ XFREE(MTYPE_BGP_PEER_HOST, updgrp->conf->host);
updgrp->conf->host = NULL;
- if (updgrp->conf->ifname)
- XFREE(MTYPE_BGP_PEER_IFNAME, updgrp->conf->ifname);
+ XFREE(MTYPE_BGP_PEER_IFNAME, updgrp->conf->ifname);
XFREE(MTYPE_BGP_PEER, updgrp->conf);
XFREE(MTYPE_BGP_UPDGRP, updgrp);
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index cbbf8b2302..66e306cba2 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -69,8 +69,7 @@ struct bpacket *bpacket_alloc(void)
{
struct bpacket *pkt;
- pkt = (struct bpacket *)XCALLOC(MTYPE_BGP_PACKET,
- sizeof(struct bpacket));
+ pkt = XCALLOC(MTYPE_BGP_PACKET, sizeof(struct bpacket));
return pkt;
}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 2aa4e3ecd4..3e100f2f0a 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -2841,18 +2841,23 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str,
as = strtoul(as_str, NULL, 10);
}
- /* If peer is peer group, call proper function. */
+ /* If peer is peer group or interface peer, call proper function. */
ret = str2sockunion(peer_str, &su);
if (ret < 0) {
- /* Check for peer by interface */
+ struct peer *peer;
+
+ /* Check if existing interface peer */
+ peer = peer_lookup_by_conf_if(bgp, peer_str);
+
ret = peer_remote_as(bgp, NULL, peer_str, &as, as_type, afi,
safi);
- if (ret < 0) {
+
+ /* if not interface peer, check peer-group settings */
+ if (ret < 0 && !peer) {
ret = peer_group_remote_as(bgp, peer_str, &as, as_type);
if (ret < 0) {
vty_out(vty,
- "%% Create the peer-group or interface first or specify \"interface\" keyword\n");
- vty_out(vty, "%% if using an unnumbered interface neighbor\n");
+ "%% Create the peer-group or interface first\n");
return CMD_WARNING_CONFIG_FAILED;
}
return CMD_SUCCESS;
@@ -3251,7 +3256,7 @@ DEFUN (no_neighbor_interface_peer_group_remote_as,
/* look up for neighbor by interface name config. */
peer = peer_lookup_by_conf_if(bgp, argv[idx_word]->arg);
if (peer) {
- peer_as_change(peer, 0, AS_SPECIFIED);
+ peer_as_change(peer, 0, AS_UNSPECIFIED);
return CMD_SUCCESS;
}
@@ -7163,7 +7168,7 @@ DEFUN_NOSH (address_family_vpnv6,
vty->node = BGP_VPNV6_NODE;
return CMD_SUCCESS;
}
-#endif
+#endif /* KEEP_OLD_VPN_COMMANDS */
DEFUN_NOSH (address_family_evpn,
address_family_evpn_cmd,
@@ -8031,7 +8036,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
json, "ribMemory",
ents * sizeof(struct bgp_node));
- ents = listcount(bgp->peer);
+ ents = bgp->af_peer_count[afi][safi];
json_object_int_add(json, "peerCount", ents);
json_object_int_add(json, "peerMemory",
ents * sizeof(struct peer));
@@ -8071,7 +8076,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
bgp_node)));
/* Peer related usage */
- ents = listcount(bgp->peer);
+ ents = bgp->af_peer_count[afi][safi];
vty_out(vty, "Peers %ld, using %s of memory\n",
ents,
mtype_memstr(
@@ -8522,7 +8527,7 @@ const char *afi_safi_json(afi_t afi, safi_t safi)
}
/* Show BGP peer's information. */
-enum show_type { show_all, show_peer };
+enum show_type { show_all, show_peer, show_ipv4_all, show_ipv6_all, show_ipv4_peer, show_ipv6_peer };
static void bgp_show_peer_afi_orf_cap(struct vty *vty, struct peer *p,
afi_t afi, safi_t safi,
@@ -10945,6 +10950,14 @@ static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp,
struct peer *peer;
int find = 0;
bool nbr_output = false;
+ afi_t afi = AFI_MAX;
+ safi_t safi = SAFI_MAX;
+
+ if (type == show_ipv4_peer || type == show_ipv4_all) {
+ afi = AFI_IP;
+ } else if (type == show_ipv6_peer || type == show_ipv6_all) {
+ afi = AFI_IP6;
+ }
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
@@ -10973,17 +10986,54 @@ static int bgp_show_neighbor(struct vty *vty, struct bgp *bgp,
}
}
break;
+ case show_ipv4_peer:
+ case show_ipv6_peer:
+ FOREACH_SAFI (safi) {
+ if (peer->afc[afi][safi]) {
+ if (conf_if) {
+ if ((peer->conf_if
+ && !strcmp(peer->conf_if, conf_if))
+ || (peer->hostname
+ && !strcmp(peer->hostname, conf_if))) {
+ find = 1;
+ bgp_show_peer(vty, peer, use_json,
+ json);
+ break;
+ }
+ } else {
+ if (sockunion_same(&peer->su, su)) {
+ find = 1;
+ bgp_show_peer(vty, peer, use_json,
+ json);
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case show_ipv4_all:
+ case show_ipv6_all:
+ FOREACH_SAFI (safi) {
+ if (peer->afc[afi][safi]) {
+ bgp_show_peer(vty, peer, use_json, json);
+ nbr_output = true;
+ break;
+ }
+ }
+ break;
}
}
- if (type == show_peer && !find) {
+ if ((type == show_peer || type == show_ipv4_peer ||
+ type == show_ipv6_peer) && !find) {
if (use_json)
json_object_boolean_true_add(json, "bgpNoSuchNeighbor");
else
vty_out(vty, "%% No such neighbor in this view/vrf\n");
}
- if (type != show_peer && !nbr_output && !use_json)
+ if (type != show_peer && type != show_ipv4_peer &&
+ type != show_ipv6_peer && !nbr_output && !use_json)
vty_out(vty, "%% No BGP neighbors found\n");
if (use_json) {
@@ -11049,7 +11099,8 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty,
: bgp->name);
}
- if (type == show_peer) {
+ if (type == show_peer || type == show_ipv4_peer ||
+ type == show_ipv6_peer) {
ret = str2sockunion(ip_str, &su);
if (ret < 0)
bgp_show_neighbor(vty, bgp, type, NULL, ip_str,
@@ -11058,7 +11109,7 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty,
bgp_show_neighbor(vty, bgp, type, &su, NULL,
use_json, json);
} else {
- bgp_show_neighbor(vty, bgp, show_all, NULL, NULL,
+ bgp_show_neighbor(vty, bgp, type, NULL, NULL,
use_json, json);
}
json_object_free(json);
@@ -11151,6 +11202,7 @@ DEFUN (show_ip_bgp_neighbors,
char *vrf = NULL;
char *sh_arg = NULL;
enum show_type sh_type;
+ afi_t afi = AFI_MAX;
bool uj = use_json(argc, argv);
@@ -11166,13 +11218,29 @@ DEFUN (show_ip_bgp_neighbors,
vrf = argv[idx + 1]->arg;
idx++;
+
+ if (argv_find(argv, argc, "ipv4", &idx)) {
+ sh_type = show_ipv4_all;
+ afi = AFI_IP;
+ } else if (argv_find(argv, argc, "ipv6", &idx)) {
+ sh_type = show_ipv6_all;
+ afi = AFI_IP6;
+ } else {
+ sh_type = show_all;
+ }
+
if (argv_find(argv, argc, "A.B.C.D", &idx)
|| argv_find(argv, argc, "X:X::X:X", &idx)
|| argv_find(argv, argc, "WORD", &idx)) {
sh_type = show_peer;
sh_arg = argv[idx]->arg;
- } else
- sh_type = show_all;
+ }
+
+ if (sh_type == show_peer && afi == AFI_IP) {
+ sh_type = show_ipv4_peer;
+ } else if (sh_type == show_peer && afi == AFI_IP6) {
+ sh_type = show_ipv6_peer;
+ }
return bgp_show_neighbor_vty(vty, vrf, sh_type, sh_arg, uj);
}
@@ -11267,8 +11335,9 @@ DEFUN (show_ip_bgp_attr_info,
return CMD_SUCCESS;
}
-static int bgp_show_route_leak_vty(struct vty *vty, const char *name, afi_t afi,
- safi_t safi, bool use_json)
+static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
+ afi_t afi, safi_t safi,
+ bool use_json, json_object *json)
{
struct bgp *bgp;
struct listnode *node;
@@ -11277,13 +11346,10 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, afi_t afi,
char *ecom_str;
vpn_policy_direction_t dir;
- if (use_json) {
- json_object *json = NULL;
+ if (json) {
json_object *json_import_vrfs = NULL;
json_object *json_export_vrfs = NULL;
- json = json_object_new_object();
-
bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
if (!bgp) {
@@ -11354,11 +11420,12 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, afi_t afi,
XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
}
- vty_out(vty, "%s\n",
- json_object_to_json_string_ext(json,
+ if (use_json) {
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(json,
JSON_C_TO_STRING_PRETTY));
- json_object_free(json);
-
+ json_object_free(json);
+ }
} else {
bgp = name ? bgp_lookup_by_name(name) : bgp_get_default();
@@ -11422,6 +11489,54 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name, afi_t afi,
return CMD_SUCCESS;
}
+static int bgp_show_all_instance_route_leak_vty(struct vty *vty, afi_t afi,
+ safi_t safi, bool use_json)
+{
+ struct listnode *node, *nnode;
+ struct bgp *bgp;
+ char *vrf_name = NULL;
+ json_object *json = NULL;
+ json_object *json_vrf = NULL;
+ json_object *json_vrfs = NULL;
+
+ if (use_json) {
+ json = json_object_new_object();
+ json_vrfs = json_object_new_object();
+ }
+
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+
+ if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT)
+ vrf_name = bgp->name;
+
+ if (use_json) {
+ json_vrf = json_object_new_object();
+ } else {
+ vty_out(vty, "\nInstance %s:\n",
+ (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ ? VRF_DEFAULT_NAME : bgp->name);
+ }
+ bgp_show_route_leak_vty(vty, vrf_name, afi, safi, 0, json_vrf);
+ if (use_json) {
+ if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
+ json_object_object_add(json_vrfs,
+ VRF_DEFAULT_NAME, json_vrf);
+ else
+ json_object_object_add(json_vrfs, vrf_name,
+ json_vrf);
+ }
+ }
+
+ if (use_json) {
+ json_object_object_add(json, "vrfs", json_vrfs);
+ vty_out(vty, "%s\n", json_object_to_json_string_ext(json,
+ JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ }
+
+ return CMD_SUCCESS;
+}
+
/* "show [ip] bgp route-leak" command. */
DEFUN (show_ip_bgp_route_leak,
show_ip_bgp_route_leak_cmd,
@@ -11441,6 +11556,7 @@ DEFUN (show_ip_bgp_route_leak,
bool uj = use_json(argc, argv);
int idx = 0;
+ json_object *json = NULL;
/* show [ip] bgp */
if (argv_find(argv, argc, "ip", &idx)) {
@@ -11470,7 +11586,13 @@ DEFUN (show_ip_bgp_route_leak,
return CMD_WARNING;
}
- return bgp_show_route_leak_vty(vty, vrf, afi, safi, uj);
+ if (vrf && strmatch(vrf, "all"))
+ return bgp_show_all_instance_route_leak_vty(vty, afi, safi, uj);
+
+ if (uj)
+ json = json_object_new_object();
+
+ return bgp_show_route_leak_vty(vty, vrf, afi, safi, uj, json);
}
static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi,
@@ -14456,8 +14578,7 @@ static int lcommunity_list_set_vty(struct vty *vty, int argc,
/* Free temporary community list string allocated by
argv_concat(). */
- if (str)
- XFREE(MTYPE_TMP, str);
+ XFREE(MTYPE_TMP, str);
if (ret < 0) {
community_list_perror(vty, ret);
@@ -14508,8 +14629,7 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc,
/* Free temporary community list string allocated by
argv_concat(). */
- if (str)
- XFREE(MTYPE_TMP, str);
+ XFREE(MTYPE_TMP, str);
if (ret < 0) {
community_list_perror(vty, ret);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 3f18d69a2d..5f0b20e029 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -945,14 +945,17 @@ bgp_path_info_to_ipv6_nexthop(struct bgp_path_info *path, ifindex_t *ifindex)
struct in6_addr *nexthop = NULL;
/* Only global address nexthop exists. */
- if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
+ if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL
+ || path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL) {
nexthop = &path->attr->mp_nexthop_global;
if (IN6_IS_ADDR_LINKLOCAL(nexthop))
*ifindex = path->attr->nh_ifindex;
}
/* If both global and link-local address present. */
- if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+ if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
+ || path->attr->mp_nexthop_len
+ == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
/* Check if route-map is set to prefer global over link-local */
if (path->attr->mp_nexthop_prefer_global) {
nexthop = &path->attr->mp_nexthop_global;
@@ -1111,20 +1114,24 @@ int bgp_zebra_get_table_range(uint32_t chunk_size,
}
static int update_ipv4nh_for_route_install(int nh_othervrf,
+ struct bgp *nh_bgp,
struct in_addr *nexthop,
struct attr *attr,
bool is_evpn,
struct zapi_nexthop *api_nh)
{
api_nh->gate.ipv4 = *nexthop;
+ api_nh->vrf_id = nh_bgp->vrf_id;
/* Need to set fields appropriately for EVPN routes imported into
* a VRF (which are programmed as onlink on l3-vni SVI) as well as
* connected routes leaked into a VRF.
*/
- if (is_evpn)
+ if (is_evpn) {
api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
- else if (nh_othervrf &&
+ api_nh->onlink = true;
+ api_nh->ifindex = nh_bgp->l3vni_svi_ifindex;
+ } else if (nh_othervrf &&
api_nh->gate.ipv4.s_addr == INADDR_ANY) {
api_nh->type = NEXTHOP_TYPE_IFINDEX;
api_nh->ifindex = attr->nh_ifindex;
@@ -1135,7 +1142,8 @@ static int update_ipv4nh_for_route_install(int nh_othervrf,
}
static int
-update_ipv6nh_for_route_install(int nh_othervrf, struct in6_addr *nexthop,
+update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
+ struct in6_addr *nexthop,
ifindex_t ifindex, struct bgp_path_info *pi,
struct bgp_path_info *best_pi, bool is_evpn,
struct zapi_nexthop *api_nh)
@@ -1143,10 +1151,13 @@ update_ipv6nh_for_route_install(int nh_othervrf, struct in6_addr *nexthop,
struct attr *attr;
attr = pi->attr;
+ api_nh->vrf_id = nh_bgp->vrf_id;
- if (is_evpn)
+ if (is_evpn) {
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
- else if (nh_othervrf) {
+ api_nh->onlink = true;
+ api_nh->ifindex = nh_bgp->l3vni_svi_ifindex;
+ } else if (nh_othervrf) {
if (IN6_IS_ADDR_UNSPECIFIED(nexthop)) {
api_nh->type = NEXTHOP_TYPE_IFINDEX;
api_nh->ifindex = attr->nh_ifindex;
@@ -1297,8 +1308,6 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
continue;
api_nh = &api.nexthops[valid_nh_count];
- api_nh->vrf_id = nh_othervrf ? info->extra->bgp_orig->vrf_id
- : bgp->vrf_id;
if (nh_family == AF_INET) {
if (bgp_debug_zebra(&api.prefix)) {
if (mpinfo->extra) {
@@ -1338,6 +1347,8 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
nh_updated = update_ipv4nh_for_route_install(
nh_othervrf,
+ nh_othervrf ?
+ info->extra->bgp_orig : bgp,
&mpinfo_cp->attr->nexthop,
mpinfo_cp->attr, is_evpn, api_nh);
} else {
@@ -1372,7 +1383,9 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
nexthop = bgp_path_info_to_ipv6_nexthop(mpinfo_cp,
&ifindex);
nh_updated = update_ipv6nh_for_route_install(
- nh_othervrf, nexthop, ifindex,
+ nh_othervrf, nh_othervrf ?
+ info->extra->bgp_orig : bgp,
+ nexthop, ifindex,
mpinfo, info, is_evpn, api_nh);
}
@@ -1573,8 +1586,7 @@ struct bgp_redist *bgp_redist_add(struct bgp *bgp, afi_t afi, uint8_t type,
bgp->redist[afi][type] = list_new();
red_list = bgp->redist[afi][type];
- red = (struct bgp_redist *)XCALLOC(MTYPE_BGP_REDIST,
- sizeof(struct bgp_redist));
+ red = XCALLOC(MTYPE_BGP_REDIST, sizeof(struct bgp_redist));
red->instance = instance;
listnode_add(red_list, red);
@@ -1681,8 +1693,7 @@ int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name,
if (red->rmap.name && (strcmp(red->rmap.name, name) == 0))
return 0;
- if (red->rmap.name)
- XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name);
+ XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name);
/* Decrement the count for existing routemap and
* increment the count for new route map.
*/
@@ -1795,8 +1806,7 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
bgp_redistribute_unreg(bgp, afi, type, instance);
/* Unset route-map. */
- if (red->rmap.name)
- XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name);
+ XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name);
route_map_counter_decrement(red->rmap.map);
red->rmap.name = NULL;
red->rmap.map = NULL;
@@ -2486,6 +2496,7 @@ static int bgp_zebra_process_local_l3vni(int cmd, struct zclient *zclient,
struct ethaddr rmac;
struct in_addr originator_ip;
struct stream *s;
+ ifindex_t svi_ifindex;
memset(&rmac, 0, sizeof(struct ethaddr));
memset(&originator_ip, 0, sizeof(struct in_addr));
@@ -2495,20 +2506,24 @@ static int bgp_zebra_process_local_l3vni(int cmd, struct zclient *zclient,
stream_get(&rmac, s, sizeof(struct ethaddr));
originator_ip.s_addr = stream_get_ipv4(s);
stream_get(&filter, s, sizeof(int));
- }
+ svi_ifindex = stream_getl(s);
- if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx L3-VNI %s VRF %s VNI %u RMAC %s filter %s",
- (cmd == ZEBRA_L3VNI_ADD) ? "add" : "del",
- vrf_id_to_name(vrf_id), l3vni,
- prefix_mac2str(&rmac, buf, sizeof(buf)),
- filter ? "prefix-routes-only" : "none");
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Rx L3-VNI ADD VRF %s VNI %u RMAC %s filter %s svi-if %u",
+ vrf_id_to_name(vrf_id), l3vni,
+ prefix_mac2str(&rmac, buf, sizeof(buf)),
+ filter ? "prefix-routes-only" : "none",
+ svi_ifindex);
- if (cmd == ZEBRA_L3VNI_ADD)
bgp_evpn_local_l3vni_add(l3vni, vrf_id, &rmac, originator_ip,
- filter);
- else
+ filter, svi_ifindex);
+ } else {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Rx L3-VNI DEL VRF %s VNI %u",
+ vrf_id_to_name(vrf_id), l3vni);
+
bgp_evpn_local_l3vni_del(l3vni, vrf_id);
+ }
return 0;
}
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index a920cfeeec..54e8f5f369 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -116,7 +116,7 @@ static int bgp_check_main_socket(bool create, struct bgp *bgp)
{
static int bgp_server_main_created;
- if (create == true) {
+ if (create) {
if (bgp_server_main_created)
return 0;
if (bgp_socket(bgp, bm->port, bm->address) < 0)
@@ -707,6 +707,7 @@ struct peer_af *peer_af_create(struct peer *peer, afi_t afi, safi_t safi)
{
struct peer_af *af;
int afid;
+ struct bgp *bgp;
if (!peer)
return NULL;
@@ -715,6 +716,7 @@ struct peer_af *peer_af_create(struct peer *peer, afi_t afi, safi_t safi)
if (afid >= BGP_AF_MAX)
return NULL;
+ bgp = peer->bgp;
assert(peer->peer_af_array[afid] == NULL);
/* Allocate new peer af */
@@ -725,6 +727,7 @@ struct peer_af *peer_af_create(struct peer *peer, afi_t afi, safi_t safi)
af->safi = safi;
af->afid = afid;
af->peer = peer;
+ bgp->af_peer_count[afi][safi]++;
return af;
}
@@ -747,6 +750,7 @@ int peer_af_delete(struct peer *peer, afi_t afi, safi_t safi)
{
struct peer_af *af;
int afid;
+ struct bgp *bgp;
if (!peer)
return -1;
@@ -759,6 +763,7 @@ int peer_af_delete(struct peer *peer, afi_t afi, safi_t safi)
if (!af)
return -1;
+ bgp = peer->bgp;
bgp_stop_announce_route_timer(af);
if (PAF_SUBGRP(af)) {
@@ -768,8 +773,12 @@ int peer_af_delete(struct peer *peer, afi_t afi, safi_t safi)
af->subgroup->id, peer->host);
}
+
update_subgroup_remove_peer(af->subgroup, af);
+ if (bgp->af_peer_count[afi][safi])
+ bgp->af_peer_count[afi][safi]--;
+
peer->peer_af_array[afid] = NULL;
XFREE(MTYPE_BGP_PEER_AF, af);
return 0;
@@ -1099,8 +1108,7 @@ static void peer_free(struct peer *peer)
peer->update_if = NULL;
}
- if (peer->notify.data)
- XFREE(MTYPE_TMP, peer->notify.data);
+ XFREE(MTYPE_TMP, peer->notify.data);
memset(&peer->notify, 0, sizeof(struct bgp_notify));
if (peer->clear_node_queue)
@@ -1322,8 +1330,7 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
peer_dst->update_source =
sockunion_dup(peer_src->update_source);
} else if (peer_src->update_if) {
- if (peer_dst->update_if)
- XFREE(MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
+ XFREE(MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
if (peer_dst->update_source) {
sockunion_free(peer_dst->update_source);
peer_dst->update_source = NULL;
@@ -1333,8 +1340,7 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
}
if (peer_src->ifname) {
- if (peer_dst->ifname)
- XFREE(MTYPE_BGP_PEER_IFNAME, peer_dst->ifname);
+ XFREE(MTYPE_BGP_PEER_IFNAME, peer_dst->ifname);
peer_dst->ifname =
XSTRDUP(MTYPE_BGP_PEER_IFNAME, peer_src->ifname);
@@ -1541,14 +1547,12 @@ struct peer *peer_create(union sockunion *su, const char *conf_if,
peer->su = *su;
else
bgp_peer_conf_if_to_su_update(peer);
- if (peer->host)
- XFREE(MTYPE_BGP_PEER_HOST, peer->host);
+ XFREE(MTYPE_BGP_PEER_HOST, peer->host);
peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, conf_if);
} else if (su) {
peer->su = *su;
sockunion2str(su, buf, SU_ADDRSTRLEN);
- if (peer->host)
- XFREE(MTYPE_BGP_PEER_HOST, peer->host);
+ XFREE(MTYPE_BGP_PEER_HOST, peer->host);
peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, buf);
}
peer->local_as = local_as;
@@ -2384,8 +2388,7 @@ static int peer_group_cmp(struct peer_group *g1, struct peer_group *g2)
/* Peer group cofiguration. */
static struct peer_group *peer_group_new(void)
{
- return (struct peer_group *)XCALLOC(MTYPE_PEER_GROUP,
- sizeof(struct peer_group));
+ return XCALLOC(MTYPE_PEER_GROUP, sizeof(struct peer_group));
}
static void peer_group_free(struct peer_group *group)
@@ -2416,8 +2419,7 @@ struct peer_group *peer_group_get(struct bgp *bgp, const char *name)
group = peer_group_new();
group->bgp = bgp;
- if (group->name)
- XFREE(MTYPE_PEER_GROUP_HOST, group->name);
+ XFREE(MTYPE_PEER_GROUP_HOST, group->name);
group->name = XSTRDUP(MTYPE_PEER_GROUP_HOST, name);
group->peer = list_new();
for (afi = AFI_IP; afi < AFI_MAX; afi++)
@@ -2425,8 +2427,7 @@ struct peer_group *peer_group_get(struct bgp *bgp, const char *name)
group->conf = peer_new(bgp);
if (!bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4))
group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
- if (group->conf->host)
- XFREE(MTYPE_BGP_PEER_HOST, group->conf->host);
+ XFREE(MTYPE_BGP_PEER_HOST, group->conf->host);
group->conf->host = XSTRDUP(MTYPE_BGP_PEER_HOST, name);
group->conf->group = group;
group->conf->as = 0;
@@ -2722,7 +2723,7 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
peer->sort = group->conf->sort;
}
- if (!group->conf->as) {
+ if (!group->conf->as && peer_sort(peer)) {
if (peer_sort(group->conf) != BGP_PEER_INTERNAL
&& peer_sort(group->conf) != peer_sort(peer)) {
if (as)
@@ -2886,8 +2887,7 @@ static struct bgp *bgp_create(as_t *as, const char *name,
bgp->vrf_id = (inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? VRF_DEFAULT
: VRF_UNKNOWN;
bgp->peer_self = peer_new(bgp);
- if (bgp->peer_self->host)
- XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
+ XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
bgp->peer_self->host =
XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
if (bgp->peer_self->hostname != NULL) {
@@ -3404,8 +3404,7 @@ void bgp_free(struct bgp *bgp)
if (bgp->rib[afi][safi])
bgp_table_finish(&bgp->rib[afi][safi]);
rmap = &bgp->table_map[afi][safi];
- if (rmap->name)
- XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
+ XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
}
bgp_scan_finish(bgp);
@@ -3435,10 +3434,8 @@ void bgp_free(struct bgp *bgp)
ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]);
}
- if (bgp->name)
- XFREE(MTYPE_BGP, bgp->name);
- if (bgp->name_pretty)
- XFREE(MTYPE_BGP, bgp->name_pretty);
+ XFREE(MTYPE_BGP, bgp->name);
+ XFREE(MTYPE_BGP, bgp->name_pretty);
XFREE(MTYPE_BGP, bgp);
}
@@ -4368,8 +4365,7 @@ int peer_ebgp_multihop_unset(struct peer *peer)
/* Neighbor description. */
int peer_description_set(struct peer *peer, const char *desc)
{
- if (peer->desc)
- XFREE(MTYPE_PEER_DESC, peer->desc);
+ XFREE(MTYPE_PEER_DESC, peer->desc);
peer->desc = XSTRDUP(MTYPE_PEER_DESC, desc);
@@ -4378,8 +4374,7 @@ int peer_description_set(struct peer *peer, const char *desc)
int peer_description_unset(struct peer *peer)
{
- if (peer->desc)
- XFREE(MTYPE_PEER_DESC, peer->desc);
+ XFREE(MTYPE_PEER_DESC, peer->desc);
peer->desc = NULL;
@@ -5125,15 +5120,13 @@ int peer_advertise_interval_unset(struct peer *peer)
/* neighbor interface */
void peer_interface_set(struct peer *peer, const char *str)
{
- if (peer->ifname)
- XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
+ XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str);
}
void peer_interface_unset(struct peer *peer)
{
- if (peer->ifname)
- XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
+ XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
peer->ifname = NULL;
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index dde1501d30..7a77c8b3ee 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -99,6 +99,9 @@ enum bgp_af_index {
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++)
+
extern struct frr_pthread *bgp_pth_io;
extern struct frr_pthread *bgp_pth_ka;
@@ -374,6 +377,9 @@ struct bgp {
#define BGP_CONFIG_VRF_TO_VRF_IMPORT (1 << 7)
#define BGP_CONFIG_VRF_TO_VRF_EXPORT (1 << 8)
+ /* BGP per AF peer count */
+ uint32_t af_peer_count[AFI_MAX][SAFI_MAX];
+
/* Route table for next-hop lookup cache. */
struct bgp_table *nexthop_cache_table[AFI_MAX];
@@ -517,6 +523,9 @@ struct bgp {
/* originator ip - to be used as NH for type-5 routes */
struct in_addr originator_ip;
+ /* SVI associated with the L3-VNI corresponding to this vrf */
+ ifindex_t l3vni_svi_ifindex;
+
/* vrf flags */
uint32_t vrf_flags;
#define BGP_VRF_AUTO (1 << 0)
diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c
index d621d58e48..2220f0ed9a 100644
--- a/bgpd/rfapi/bgp_rfapi_cfg.c
+++ b/bgpd/rfapi/bgp_rfapi_cfg.c
@@ -3457,8 +3457,7 @@ static void bgp_rfapi_delete_l2_group(struct vty *vty, /* NULL = no output */
ecommunity_free(&rfg->rt_export_list);
if (rfg->labels)
list_delete(&rfg->labels);
- if (rfg->rfp_cfg)
- XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, rfg->rfp_cfg);
+ XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, rfg->rfp_cfg);
listnode_delete(bgp->rfapi_cfg->l2_groups, rfg);
rfapi_l2_group_del(rfg);
@@ -3815,8 +3814,7 @@ struct rfapi_cfg *bgp_rfapi_cfg_new(struct rfapi_rfp_cfg *cfg)
struct rfapi_cfg *h;
afi_t afi;
- h = (struct rfapi_cfg *)XCALLOC(MTYPE_RFAPI_CFG,
- sizeof(struct rfapi_cfg));
+ h = XCALLOC(MTYPE_RFAPI_CFG, sizeof(struct rfapi_cfg));
assert(h);
h->nve_groups_sequential = list_new();
@@ -3878,8 +3876,7 @@ void bgp_rfapi_cfg_destroy(struct bgp *bgp, struct rfapi_cfg *h)
ecommunity_free(&h->default_rt_export_list);
if (h->default_rt_import_list)
ecommunity_free(&h->default_rt_import_list);
- if (h->default_rfp_cfg)
- XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, h->default_rfp_cfg);
+ XFREE(MTYPE_RFAPI_RFP_GROUP_CFG, h->default_rfp_cfg);
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
agg_table_finish(h->nve_groups_vn[afi]);
agg_table_finish(h->nve_groups_un[afi]);
diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c
index 6b37073e0e..93729c1476 100644
--- a/bgpd/rfapi/rfapi_import.c
+++ b/bgpd/rfapi/rfapi_import.c
@@ -2190,7 +2190,7 @@ static void rfapiItBiIndexDump(struct agg_node *rn)
prefix2str(&k->extra->vnc.import.aux_prefix,
buf_aux_pfx, sizeof(buf_aux_pfx));
} else
- strncpy(buf_aux_pfx, "(none)", PREFIX_STRLEN);
+ strlcpy(buf_aux_pfx, "(none)", sizeof(buf_aux_pfx));
vnc_zlog_debug_verbose("bpi %p, peer %p, rd %s, aux_prefix %s",
k, k->peer, buf, buf_aux_pfx);
@@ -2221,7 +2221,7 @@ static struct bgp_path_info *rfapiItBiIndexSearch(
prefix2str(aux_prefix, buf_aux_pfx,
sizeof(buf_aux_pfx));
} else
- strncpy(buf_aux_pfx, "(nil)", sizeof(buf_aux_pfx));
+ strlcpy(buf_aux_pfx, "(nil)", sizeof(buf_aux_pfx));
vnc_zlog_debug_verbose("%s want prd=%s, peer=%p, aux_prefix=%s",
__func__,
@@ -4285,7 +4285,7 @@ struct rfapi *bgp_rfapi_new(struct bgp *bgp)
assert(bgp->rfapi_cfg == NULL);
- h = (struct rfapi *)XCALLOC(MTYPE_RFAPI, sizeof(struct rfapi));
+ h = XCALLOC(MTYPE_RFAPI, sizeof(struct rfapi));
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
h->un[afi] = agg_table_init();
diff --git a/bgpd/rfapi/vnc_debug.c b/bgpd/rfapi/vnc_debug.c
index 2b08ea493c..cb9799870b 100644
--- a/bgpd/rfapi/vnc_debug.c
+++ b/bgpd/rfapi/vnc_debug.c
@@ -190,7 +190,7 @@ static int bgp_vnc_config_write_debug(struct vty *vty)
int write = 0;
size_t i;
- for (i = 0; i < (sizeof(vncdebug) / sizeof(struct vnc_debug)); ++i) {
+ for (i = 0; i < array_size(vncdebug); ++i) {
if (conf_vnc_debug & vncdebug[i].bit) {
vty_out(vty, "debug bgp vnc %s\n", vncdebug[i].name);
write++;
diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c
index 98f719969c..b08e922962 100644
--- a/bgpd/rfapi/vnc_zebra.c
+++ b/bgpd/rfapi/vnc_zebra.c
@@ -608,10 +608,8 @@ static void vnc_zebra_add_del_prefix(struct bgp *bgp,
add);
}
- if (nhp_ary)
- XFREE(MTYPE_TMP, nhp_ary);
- if (nh_ary)
- XFREE(MTYPE_TMP, nh_ary);
+ XFREE(MTYPE_TMP, nhp_ary);
+ XFREE(MTYPE_TMP, nh_ary);
}
void vnc_zebra_add_prefix(struct bgp *bgp,
@@ -789,10 +787,8 @@ static void vnc_zebra_add_del_group_afi(struct bgp *bgp,
}
}
}
- if (nhp_ary)
- XFREE(MTYPE_TMP, nhp_ary);
- if (nh_ary)
- XFREE(MTYPE_TMP, nh_ary);
+ XFREE(MTYPE_TMP, nhp_ary);
+ XFREE(MTYPE_TMP, nh_ary);
}
}
diff --git a/configure.ac b/configure.ac
index fcfc4bd2fb..9ae196fcb1 100755
--- a/configure.ac
+++ b/configure.ac
@@ -765,7 +765,7 @@ AC_DEFINE_UNQUOTED([CONFIGFILE_MASK], [${enable_configfile_mask}], [Mask for con
enable_logfile_mask=${enable_logfile_mask:-0600}
AC_DEFINE_UNQUOTED([LOGFILE_MASK], [${enable_logfile_mask}], [Mask for log files])
-MPATH_NUM=1
+MPATH_NUM=16
case "${enable_multipath}" in
0)
diff --git a/doc/user/installation.rst b/doc/user/installation.rst
index 4e1582ccd8..e191ebd035 100644
--- a/doc/user/installation.rst
+++ b/doc/user/installation.rst
@@ -275,7 +275,8 @@ options from the list below.
For backwards compatability with older configure options when setting X = 0,
we will build FRR with 64 way ECMP. This is needed because there are
hardcoded arrays that FRR builds towards, so we need to know how big to
- make these arrays at build time.
+ make these arrays at build time. Additionally if this parameter is
+ not passed in FRR will default to 16 ECMP.
.. option:: --enable-shell-access
diff --git a/eigrpd/eigrp_fsm.c b/eigrpd/eigrp_fsm.c
index 374114cf55..22f5a5ddb1 100644
--- a/eigrpd/eigrp_fsm.c
+++ b/eigrpd/eigrp_fsm.c
@@ -231,7 +231,7 @@ static const char *fsm_state2str(enum eigrp_fsm_events event)
return "Query from Successor while in active state";
case EIGRP_FSM_EVENT_LR_FCN:
return "Last Reply Event, Feasibility not satisfied";
- };
+ }
return "Unknown";
}
diff --git a/eigrpd/eigrp_hello.c b/eigrpd/eigrp_hello.c
index b4d850be08..dacd5caeb5 100644
--- a/eigrpd/eigrp_hello.c
+++ b/eigrpd/eigrp_hello.c
@@ -577,8 +577,6 @@ static uint16_t eigrp_next_sequence_encode(struct stream *s)
static uint16_t eigrp_hello_parameter_encode(struct eigrp_interface *ei,
struct stream *s, uint8_t flags)
{
- uint16_t length = EIGRP_TLV_PARAMETER_LEN;
-
// add in the parameters TLV
stream_putw(s, EIGRP_TLV_PARAMETER);
stream_putw(s, EIGRP_TLV_PARAMETER_LEN);
@@ -605,7 +603,7 @@ static uint16_t eigrp_hello_parameter_encode(struct eigrp_interface *ei,
// and set hold time value..
stream_putw(s, ei->params.v_wait);
- return length;
+ return EIGRP_TLV_PARAMETER_LEN;
}
/**
diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c
index b19b383e65..3db59a838b 100644
--- a/eigrpd/eigrp_main.c
+++ b/eigrpd/eigrp_main.c
@@ -211,10 +211,7 @@ int main(int argc, char **argv, char **envp)
/*eigrp_route_map_init();
route_map_add_hook (eigrp_rmap_update);
route_map_delete_hook (eigrp_rmap_update);*/
- /*if_rmap_init (EIGRP_NODE);
- if_rmap_hook_add (eigrp_if_rmap_update);
- if_rmap_hook_delete (eigrp_if_rmap_update);*/
-
+ /*if_rmap_init (EIGRP_NODE); */
/* Distribute list install. */
distribute_list_init(EIGRP_NODE);
diff --git a/eigrpd/eigrp_vty.c b/eigrpd/eigrp_vty.c
index a9b103de47..fc5bdbdbc5 100644
--- a/eigrpd/eigrp_vty.c
+++ b/eigrpd/eigrp_vty.c
@@ -1499,8 +1499,6 @@ static int eigrp_config_write(struct vty *vty)
{
struct eigrp *eigrp;
- int write = 0;
-
eigrp = eigrp_lookup();
if (eigrp != NULL) {
/* Writes 'router eigrp' section to config */
@@ -1525,7 +1523,7 @@ static int eigrp_config_write(struct vty *vty)
// config_write_eigrp_distance (vty, eigrp)
}
- return write;
+ return 0;
}
void eigrp_vty_show_init(void)
diff --git a/eigrpd/eigrpd.c b/eigrpd/eigrpd.c
index 69d947e59f..93f8b6f90e 100644
--- a/eigrpd/eigrpd.c
+++ b/eigrpd/eigrpd.c
@@ -206,6 +206,13 @@ static struct eigrp *eigrp_new(const char *AS)
eigrp_distribute_update);
distribute_list_delete_hook(eigrp->distribute_ctx,
eigrp_distribute_update);
+
+ /*
+ eigrp->if_rmap_ctx = if_rmap_ctx_create(
+ VRF_DEFAULT_NAME);
+ if_rmap_hook_add (eigrp_if_rmap_update);
+ if_rmap_hook_delete (eigrp_if_rmap_update);
+ */
QOBJ_REG(eigrp, eigrp);
return eigrp;
}
diff --git a/isisd/dict.c b/isisd/dict.c
index 5d3e61e6d6..d91f05d254 100644
--- a/isisd/dict.c
+++ b/isisd/dict.c
@@ -1095,10 +1095,10 @@ void dict_load_end(dict_load_t *load)
baselevel = level = 1;
complete = tree[0];
- if (complete != 0) {
+ if (complete != NULL) {
tree[0] = 0;
complete->right = dictnil;
- while (tree[level] != 0) {
+ while (tree[level] != NULL) {
tree[level]->right = complete;
complete->parent = tree[level];
complete = tree[level];
@@ -1114,7 +1114,7 @@ void dict_load_end(dict_load_t *load)
complete = curr;
assert(level == baselevel);
- while (tree[level] != 0) {
+ while (tree[level] != NULL) {
tree[level]->right = complete;
complete->parent = tree[level];
complete = tree[level];
@@ -1134,7 +1134,7 @@ void dict_load_end(dict_load_t *load)
complete = dictnil;
for (i = 0; i < DICT_DEPTH_MAX; i++) {
- if (tree[i] != 0) {
+ if (tree[i] != NULL) {
tree[i]->right = complete;
complete->parent = tree[i];
complete = tree[i];
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index e1cdfc30ea..62814329ea 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -140,12 +140,9 @@ void isis_delete_adj(void *arg)
/* remove from SPF trees */
spftree_area_adj_del(adj->circuit->area, adj);
- if (adj->area_addresses)
- XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses);
- if (adj->ipv4_addresses)
- XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv4_addresses);
- if (adj->ipv6_addresses)
- XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses);
+ XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses);
+ XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv4_addresses);
+ XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv6_addresses);
adj_mt_finish(adj);
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index 36d4a0d7c0..8377638b92 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -1305,8 +1305,8 @@ ferr_r isis_circuit_passwd_unset(struct isis_circuit *circuit)
return ferr_ok();
}
-static int isis_circuit_passwd_set(struct isis_circuit *circuit,
- uint8_t passwd_type, const char *passwd)
+ferr_r isis_circuit_passwd_set(struct isis_circuit *circuit,
+ uint8_t passwd_type, const char *passwd)
{
int len;
@@ -1319,7 +1319,8 @@ static int isis_circuit_passwd_set(struct isis_circuit *circuit,
"circuit password too long (max 254 chars)");
circuit->passwd.len = len;
- strncpy((char *)circuit->passwd.passwd, passwd, 255);
+ strlcpy((char *)circuit->passwd.passwd, passwd,
+ sizeof(circuit->passwd.passwd));
circuit->passwd.type = passwd_type;
return ferr_ok();
}
diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h
index 73ead8f7da..e0ea4f78b4 100644
--- a/isisd/isis_circuit.h
+++ b/isisd/isis_circuit.h
@@ -190,6 +190,8 @@ ferr_r isis_circuit_metric_set(struct isis_circuit *circuit, int level,
int metric);
ferr_r isis_circuit_passwd_unset(struct isis_circuit *circuit);
+ferr_r isis_circuit_passwd_set(struct isis_circuit *circuit,
+ uint8_t passwd_type, const char *passwd);
ferr_r isis_circuit_passwd_cleartext_set(struct isis_circuit *circuit,
const char *passwd);
ferr_r isis_circuit_passwd_hmac_md5_set(struct isis_circuit *circuit,
diff --git a/isisd/isis_dlpi.c b/isisd/isis_dlpi.c
index 54a19ad239..148b438661 100644
--- a/isisd/isis_dlpi.c
+++ b/isisd/isis_dlpi.c
@@ -444,7 +444,7 @@ static int open_dlpi_dev(struct isis_circuit *circuit)
struct strioctl sioc;
pfil.Pf_Priority = 0;
- pfil.Pf_FilterLen = sizeof(pf_filter) / sizeof(unsigned short);
+ pfil.Pf_FilterLen = array_size(pf_filter);
memcpy(pfil.Pf_Filter, pf_filter, sizeof(pf_filter));
/* pfmod does not support transparent ioctls */
sioc.ic_cmd = PFIOCSETF;
diff --git a/isisd/isis_main.c b/isisd/isis_main.c
index 9126e40d42..e74a9baadd 100644
--- a/isisd/isis_main.c
+++ b/isisd/isis_main.c
@@ -80,7 +80,7 @@ struct zebra_privs_t isisd_privs = {
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
- .cap_num_p = sizeof(_caps_p) / sizeof(*_caps_p),
+ .cap_num_p = array_size(_caps_p),
.cap_num_i = 0};
/* isisd options */
diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c
index 3364a9f0be..2d1d6f5927 100644
--- a/isisd/isis_northbound.c
+++ b/isisd/isis_northbound.c
@@ -2092,8 +2092,8 @@ lib_interface_isis_password_password_modify(enum nb_event event,
password = yang_dnode_get_string(dnode, NULL);
circuit = yang_dnode_get_entry(dnode, true);
- circuit->passwd.len = strlen(password);
- strncpy((char *)circuit->passwd.passwd, password, 255);
+
+ isis_circuit_passwd_set(circuit, circuit->passwd.type, password);
return NB_OK;
}
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index 330da9b216..107de47f3d 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -2146,11 +2146,11 @@ int send_csnp(struct isis_circuit *circuit, int level)
* stop lsp_id in this current CSNP.
*/
memcpy(start, stop, ISIS_SYS_ID_LEN + 2);
- loop = 0;
+ loop = false;
for (int i = ISIS_SYS_ID_LEN + 1; i >= 0; --i) {
if (start[i] < (uint8_t)0xff) {
start[i] += 1;
- loop = 1;
+ loop = true;
break;
}
}
@@ -2164,7 +2164,6 @@ int send_csnp(struct isis_circuit *circuit, int level)
int send_l1_csnp(struct thread *thread)
{
struct isis_circuit *circuit;
- int retval = ISIS_OK;
circuit = THREAD_ARG(thread);
assert(circuit);
@@ -2181,13 +2180,12 @@ int send_l1_csnp(struct thread *thread)
isis_jitter(circuit->csnp_interval[0], CSNP_JITTER),
&circuit->t_send_csnp[0]);
- return retval;
+ return ISIS_OK;
}
int send_l2_csnp(struct thread *thread)
{
struct isis_circuit *circuit;
- int retval = ISIS_OK;
circuit = THREAD_ARG(thread);
assert(circuit);
@@ -2204,7 +2202,7 @@ int send_l2_csnp(struct thread *thread)
isis_jitter(circuit->csnp_interval[1], CSNP_JITTER),
&circuit->t_send_csnp[1]);
- return retval;
+ return ISIS_OK;
}
/*
@@ -2329,7 +2327,6 @@ int send_l1_psnp(struct thread *thread)
{
struct isis_circuit *circuit;
- int retval = ISIS_OK;
circuit = THREAD_ARG(thread);
assert(circuit);
@@ -2342,7 +2339,7 @@ int send_l1_psnp(struct thread *thread)
isis_jitter(circuit->psnp_interval[0], PSNP_JITTER),
&circuit->t_send_psnp[0]);
- return retval;
+ return ISIS_OK;
}
/*
@@ -2352,7 +2349,6 @@ int send_l1_psnp(struct thread *thread)
int send_l2_psnp(struct thread *thread)
{
struct isis_circuit *circuit;
- int retval = ISIS_OK;
circuit = THREAD_ARG(thread);
assert(circuit);
@@ -2366,7 +2362,7 @@ int send_l2_psnp(struct thread *thread)
isis_jitter(circuit->psnp_interval[1], PSNP_JITTER),
&circuit->t_send_psnp[1]);
- return retval;
+ return ISIS_OK;
}
/*
diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c
index 20f3e62a74..3a864fb356 100644
--- a/isisd/isis_redist.c
+++ b/isisd/isis_redist.c
@@ -504,8 +504,7 @@ void isis_redist_area_finish(struct isis_area *area)
redist = &area->redist_settings[protocol][type]
[level];
redist->redist = 0;
- if (redist->map_name)
- XFREE(MTYPE_ISIS, redist->map_name);
+ XFREE(MTYPE_ISIS, redist->map_name);
}
route_table_finish(area->ext_reach[protocol][level]);
}
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index 5a6c7bc300..fbb1e5714c 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -1913,7 +1913,7 @@ static void format_item_auth(uint16_t mtid, struct isis_item *i,
default:
sbuf_push(buf, indent, " Unknown (%" PRIu8 ")\n", auth->type);
break;
- };
+ }
}
static void free_item_auth(struct isis_item *i)
@@ -3202,8 +3202,7 @@ void isis_tlvs_set_protocols_supported(struct isis_tlvs *tlvs,
struct nlpids *nlpids)
{
tlvs->protocols_supported.count = nlpids->count;
- if (tlvs->protocols_supported.protocols)
- XFREE(MTYPE_ISIS_TLV, tlvs->protocols_supported.protocols);
+ XFREE(MTYPE_ISIS_TLV, tlvs->protocols_supported.protocols);
if (nlpids->count) {
tlvs->protocols_supported.protocols =
XCALLOC(MTYPE_ISIS_TLV, nlpids->count);
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 13cd510dd1..ad02220438 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -1363,7 +1363,7 @@ struct isis_lsp *lsp_for_arg(const char *argv, dict_t *lspdb)
* xxxx.xxxx.xxxx
*/
if (argv)
- strncpy(sysid, argv, 254);
+ strlcpy(sysid, argv, sizeof(sysid));
if (argv && strlen(argv) > 3) {
pos = argv + strlen(argv) - 3;
if (strncmp(pos, "-", 1) == 0) {
@@ -1639,7 +1639,8 @@ static int isis_area_passwd_set(struct isis_area *area, int level,
return -1;
modified.len = len;
- strncpy((char *)modified.passwd, passwd, 255);
+ strlcpy((char *)modified.passwd, passwd,
+ sizeof(modified.passwd));
modified.type = passwd_type;
modified.snp_auth = snp_auth;
}
diff --git a/lib/command.c b/lib/command.c
index b46241ac87..559457c119 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -1277,8 +1277,7 @@ int cmd_execute(struct vty *vty, const char *cmd,
hook_call(cmd_execute_done, vty, cmd_exec);
- if (cmd_out)
- XFREE(MTYPE_TMP, cmd_out);
+ XFREE(MTYPE_TMP, cmd_out);
return ret;
}
@@ -2408,8 +2407,7 @@ static int set_log_file(struct vty *vty, const char *fname, int loglevel)
ret = zlog_set_file(fullpath, loglevel);
- if (p)
- XFREE(MTYPE_TMP, p);
+ XFREE(MTYPE_TMP, p);
if (!ret) {
if (vty)
@@ -2417,8 +2415,7 @@ static int set_log_file(struct vty *vty, const char *fname, int loglevel)
return CMD_WARNING_CONFIG_FAILED;
}
- if (host.logfile)
- XFREE(MTYPE_HOST, host.logfile);
+ XFREE(MTYPE_HOST, host.logfile);
host.logfile = XSTRDUP(MTYPE_HOST, fname);
@@ -2487,8 +2484,7 @@ static void disable_log_file(void)
{
zlog_reset_file();
- if (host.logfile)
- XFREE(MTYPE_HOST, host.logfile);
+ XFREE(MTYPE_HOST, host.logfile);
host.logfile = NULL;
}
@@ -2637,8 +2633,7 @@ int cmd_banner_motd_file(const char *file)
return CMD_ERR_NO_FILE;
in = strstr(rpath, SYSCONFDIR);
if (in == rpath) {
- if (host.motdfile)
- XFREE(MTYPE_HOST, host.motdfile);
+ XFREE(MTYPE_HOST, host.motdfile);
host.motdfile = XSTRDUP(MTYPE_HOST, file);
} else
success = CMD_WARNING_CONFIG_FAILED;
@@ -2723,8 +2718,7 @@ DEFUN(find,
/* Set config filename. Called from vty.c */
void host_config_set(const char *filename)
{
- if (host.config)
- XFREE(MTYPE_HOST, host.config);
+ XFREE(MTYPE_HOST, host.config);
host.config = XSTRDUP(MTYPE_HOST, filename);
}
@@ -2904,24 +2898,15 @@ void cmd_terminate(void)
cmdvec = NULL;
}
- if (host.name)
- XFREE(MTYPE_HOST, host.name);
- if (host.domainname)
- XFREE(MTYPE_HOST, host.domainname);
- if (host.password)
- XFREE(MTYPE_HOST, host.password);
- if (host.password_encrypt)
- XFREE(MTYPE_HOST, host.password_encrypt);
- if (host.enable)
- XFREE(MTYPE_HOST, host.enable);
- if (host.enable_encrypt)
- XFREE(MTYPE_HOST, host.enable_encrypt);
- if (host.logfile)
- XFREE(MTYPE_HOST, host.logfile);
- if (host.motdfile)
- XFREE(MTYPE_HOST, host.motdfile);
- if (host.config)
- XFREE(MTYPE_HOST, host.config);
+ XFREE(MTYPE_HOST, host.name);
+ XFREE(MTYPE_HOST, host.domainname);
+ XFREE(MTYPE_HOST, host.password);
+ XFREE(MTYPE_HOST, host.password_encrypt);
+ XFREE(MTYPE_HOST, host.enable);
+ XFREE(MTYPE_HOST, host.enable_encrypt);
+ XFREE(MTYPE_HOST, host.logfile);
+ XFREE(MTYPE_HOST, host.motdfile);
+ XFREE(MTYPE_HOST, host.config);
list_delete(&varhandlers);
qobj_finish();
diff --git a/lib/command_graph.c b/lib/command_graph.c
index 0e8669c4b5..4757fd951f 100644
--- a/lib/command_graph.c
+++ b/lib/command_graph.c
@@ -471,7 +471,7 @@ void cmd_graph_node_print_cb(struct graph_node *gn, struct buffer *buf)
struct cmd_token *tok = gn->data;
const char *color;
- if (wasend == true) {
+ if (wasend) {
wasend = false;
return;
}
diff --git a/lib/distribute.c b/lib/distribute.c
index 7cc10a230d..fa8ac5242e 100644
--- a/lib/distribute.c
+++ b/lib/distribute.c
@@ -44,16 +44,15 @@ static void distribute_free(struct distribute *dist)
{
int i = 0;
- if (dist->ifname)
- XFREE(MTYPE_DISTRIBUTE_IFNAME, dist->ifname);
+ XFREE(MTYPE_DISTRIBUTE_IFNAME, dist->ifname);
- for (i = 0; i < DISTRIBUTE_MAX; i++)
- if (dist->list[i])
- XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[i]);
+ for (i = 0; i < DISTRIBUTE_MAX; i++) {
+ XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[i]);
+ }
- for (i = 0; i < DISTRIBUTE_MAX; i++)
- if (dist->prefix[i])
- XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[i]);
+ for (i = 0; i < DISTRIBUTE_MAX; i++) {
+ XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[i]);
+ }
XFREE(MTYPE_DISTRIBUTE, dist);
}
@@ -83,8 +82,7 @@ struct distribute *distribute_lookup(struct distribute_ctx *ctx,
dist = hash_lookup(ctx->disthash, &key);
- if (key.ifname)
- XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname);
+ XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname);
return dist;
}
@@ -128,8 +126,7 @@ static struct distribute *distribute_get(struct distribute_ctx *ctx,
ret = hash_get(ctx->disthash, &key,
(void *(*)(void *))distribute_hash_alloc);
- if (key.ifname)
- XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname);
+ XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname);
return ret;
}
@@ -163,8 +160,7 @@ static void distribute_list_set(struct distribute_ctx *ctx,
dist = distribute_get(ctx, ifname);
- if (dist->list[type])
- XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[type]);
+ XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[type]);
dist->list[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, alist_name);
/* Apply this distribute-list to the interface. */
@@ -210,8 +206,7 @@ static void distribute_list_prefix_set(struct distribute_ctx *ctx,
dist = distribute_get(ctx, ifname);
- if (dist->prefix[type])
- XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[type]);
+ XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[type]);
dist->prefix[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, plist_name);
/* Apply this distribute-list to the interface. */
diff --git a/lib/event_counter.c b/lib/event_counter.c
index c520937a38..57dbfb5fd1 100644
--- a/lib/event_counter.c
+++ b/lib/event_counter.c
@@ -62,7 +62,7 @@ const char *event_counter_format(const struct event_counter *counter)
|| strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %T %z",
last_change)
== 0) {
- strncpy(timebuf, "???", sizeof(timebuf));
+ strlcpy(timebuf, "???", sizeof(timebuf));
}
snprintf(rv, sizeof(rv), "%5llu last: %s", counter->count,
diff --git a/lib/filter.c b/lib/filter.c
index 317c1b68b7..276df4b4d7 100644
--- a/lib/filter.c
+++ b/lib/filter.c
@@ -128,8 +128,7 @@ static struct access_master *access_master_get(afi_t afi)
/* Allocate new filter structure. */
static struct filter *filter_new(void)
{
- return (struct filter *)XCALLOC(MTYPE_ACCESS_FILTER,
- sizeof(struct filter));
+ return XCALLOC(MTYPE_ACCESS_FILTER, sizeof(struct filter));
}
static void filter_free(struct filter *filter)
@@ -202,8 +201,7 @@ static int filter_match_zebra(struct filter *mfilter, const struct prefix *p)
/* Allocate new access list structure. */
static struct access_list *access_list_new(void)
{
- return (struct access_list *)XCALLOC(MTYPE_ACCESS_LIST,
- sizeof(struct access_list));
+ return XCALLOC(MTYPE_ACCESS_LIST, sizeof(struct access_list));
}
/* Free allocated access_list. */
@@ -242,11 +240,9 @@ static void access_list_delete(struct access_list *access)
else
list->head = access->next;
- if (access->name)
- XFREE(MTYPE_ACCESS_LIST_STR, access->name);
+ XFREE(MTYPE_ACCESS_LIST_STR, access->name);
- if (access->remark)
- XFREE(MTYPE_TMP, access->remark);
+ XFREE(MTYPE_TMP, access->remark);
access_list_free(access);
}
diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c
index d7f655271b..2a18e5cfc6 100644
--- a/lib/frr_pthread.c
+++ b/lib/frr_pthread.c
@@ -110,8 +110,7 @@ void frr_pthread_destroy(struct frr_pthread *fpt)
pthread_mutex_destroy(&fpt->mtx);
pthread_mutex_destroy(fpt->running_cond_mtx);
pthread_cond_destroy(fpt->running_cond);
- if (fpt->name)
- XFREE(MTYPE_FRR_PTHREAD, fpt->name);
+ XFREE(MTYPE_FRR_PTHREAD, fpt->name);
XFREE(MTYPE_PTHREAD_PRIM, fpt->running_cond_mtx);
XFREE(MTYPE_PTHREAD_PRIM, fpt->running_cond);
XFREE(MTYPE_FRR_PTHREAD, fpt);
diff --git a/lib/frr_zmq.c b/lib/frr_zmq.c
index cfea238d95..7781beae5e 100644
--- a/lib/frr_zmq.c
+++ b/lib/frr_zmq.c
@@ -176,8 +176,6 @@ int funcname_frrzmq_thread_add_read(struct thread_master *master,
cb = *cbp;
else {
cb = XCALLOC(MTYPE_ZEROMQ_CB, sizeof(struct frrzmq_cb));
- if (!cb)
- return -1;
cb->write.cancelled = 1;
*cbp = cb;
@@ -286,8 +284,6 @@ int funcname_frrzmq_thread_add_write(struct thread_master *master,
cb = *cbp;
else {
cb = XCALLOC(MTYPE_ZEROMQ_CB, sizeof(struct frrzmq_cb));
- if (!cb)
- return -1;
cb->read.cancelled = 1;
*cbp = cb;
diff --git a/lib/frrstr.c b/lib/frrstr.c
index 85d968182b..fd337073f8 100644
--- a/lib/frrstr.c
+++ b/lib/frrstr.c
@@ -155,13 +155,13 @@ void frrstr_strvec_free(vector v)
bool begins_with(const char *str, const char *prefix)
{
if (!str || !prefix)
- return 0;
+ return false;
size_t lenstr = strlen(str);
size_t lenprefix = strlen(prefix);
if (lenprefix > lenstr)
- return 0;
+ return false;
return strncmp(str, prefix, lenprefix) == 0;
}
diff --git a/lib/hash.c b/lib/hash.c
index 9f9fc31d37..c02b81814c 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -95,8 +95,6 @@ static void hash_expand(struct hash *hash)
new_index = XCALLOC(MTYPE_HASH_INDEX,
sizeof(struct hash_bucket *) * new_size);
- if (new_index == NULL)
- return;
hash->stats.empty = new_size;
@@ -324,8 +322,7 @@ void hash_free(struct hash *hash)
}
pthread_mutex_unlock(&_hashes_mtx);
- if (hash->name)
- XFREE(MTYPE_HASH, hash->name);
+ XFREE(MTYPE_HASH, hash->name);
XFREE(MTYPE_HASH_INDEX, hash->index);
XFREE(MTYPE_HASH, hash);
diff --git a/lib/if.c b/lib/if.c
index 48841c7ee8..abcc6c5d3c 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -234,8 +234,7 @@ void if_delete(struct interface *ifp)
if_link_params_free(ifp);
- if (ifp->desc)
- XFREE(MTYPE_TMP, ifp->desc);
+ XFREE(MTYPE_TMP, ifp->desc);
XFREE(MTYPE_IF, ifp);
}
@@ -708,8 +707,7 @@ void connected_free(struct connected *connected)
if (connected->destination)
prefix_free(connected->destination);
- if (connected->label)
- XFREE(MTYPE_CONNECTED_LABEL, connected->label);
+ XFREE(MTYPE_CONNECTED_LABEL, connected->label);
XFREE(MTYPE_CONNECTED, connected);
}
@@ -1349,8 +1347,7 @@ static int lib_interface_description_modify(enum nb_event event,
return NB_OK;
ifp = yang_dnode_get_entry(dnode, true);
- if (ifp->desc)
- XFREE(MTYPE_TMP, ifp->desc);
+ XFREE(MTYPE_TMP, ifp->desc);
description = yang_dnode_get_string(dnode, NULL);
ifp->desc = XSTRDUP(MTYPE_TMP, description);
@@ -1366,8 +1363,7 @@ static int lib_interface_description_delete(enum nb_event event,
return NB_OK;
ifp = yang_dnode_get_entry(dnode, true);
- if (ifp->desc)
- XFREE(MTYPE_TMP, ifp->desc);
+ XFREE(MTYPE_TMP, ifp->desc);
return NB_OK;
}
diff --git a/lib/if_rmap.c b/lib/if_rmap.c
index 7ac5368171..955c1417c4 100644
--- a/lib/if_rmap.c
+++ b/lib/if_rmap.c
@@ -26,14 +26,12 @@
#include "if.h"
#include "if_rmap.h"
+DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX, "Interface route map container")
+DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX_NAME, "Interface route map container name")
DEFINE_MTYPE_STATIC(LIB, IF_RMAP, "Interface route map")
DEFINE_MTYPE_STATIC(LIB, IF_RMAP_NAME, "I.f. route map name")
-struct hash *ifrmaphash;
-
-/* Hook functions. */
-static void (*if_rmap_add_hook)(struct if_rmap *) = NULL;
-static void (*if_rmap_delete_hook)(struct if_rmap *) = NULL;
+struct list *if_rmap_ctx_list;
static struct if_rmap *if_rmap_new(void)
{
@@ -46,18 +44,15 @@ static struct if_rmap *if_rmap_new(void)
static void if_rmap_free(struct if_rmap *if_rmap)
{
- if (if_rmap->ifname)
- XFREE(MTYPE_IF_RMAP_NAME, if_rmap->ifname);
+ XFREE(MTYPE_IF_RMAP_NAME, if_rmap->ifname);
- if (if_rmap->routemap[IF_RMAP_IN])
- XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]);
- if (if_rmap->routemap[IF_RMAP_OUT])
- XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]);
+ XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]);
+ XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]);
XFREE(MTYPE_IF_RMAP, if_rmap);
}
-struct if_rmap *if_rmap_lookup(const char *ifname)
+struct if_rmap *if_rmap_lookup(struct if_rmap_ctx *ctx, const char *ifname)
{
struct if_rmap key;
struct if_rmap *if_rmap;
@@ -65,22 +60,25 @@ struct if_rmap *if_rmap_lookup(const char *ifname)
/* temporary copy */
key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL;
- if_rmap = hash_lookup(ifrmaphash, &key);
+ if_rmap = hash_lookup(ctx->ifrmaphash, &key);
- if (key.ifname)
- XFREE(MTYPE_IF_RMAP_NAME, key.ifname);
+ XFREE(MTYPE_IF_RMAP_NAME, key.ifname);
return if_rmap;
}
-void if_rmap_hook_add(void (*func)(struct if_rmap *))
+void if_rmap_hook_add(struct if_rmap_ctx *ctx,
+ void (*func)(struct if_rmap_ctx *ctx,
+ struct if_rmap *))
{
- if_rmap_add_hook = func;
+ ctx->if_rmap_add_hook = func;
}
-void if_rmap_hook_delete(void (*func)(struct if_rmap *))
+void if_rmap_hook_delete(struct if_rmap_ctx *ctx,
+ void (*func)(struct if_rmap_ctx *ctx,
+ struct if_rmap *))
{
- if_rmap_delete_hook = func;
+ ctx->if_rmap_delete_hook = func;
}
static void *if_rmap_hash_alloc(void *arg)
@@ -94,7 +92,7 @@ static void *if_rmap_hash_alloc(void *arg)
return if_rmap;
}
-static struct if_rmap *if_rmap_get(const char *ifname)
+static struct if_rmap *if_rmap_get(struct if_rmap_ctx *ctx, const char *ifname)
{
struct if_rmap key;
struct if_rmap *ret;
@@ -102,10 +100,9 @@ static struct if_rmap *if_rmap_get(const char *ifname)
/* temporary copy */
key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL;
- ret = hash_get(ifrmaphash, &key, if_rmap_hash_alloc);
+ ret = hash_get(ctx->ifrmaphash, &key, if_rmap_hash_alloc);
- if (key.ifname)
- XFREE(MTYPE_IF_RMAP_NAME, key.ifname);
+ XFREE(MTYPE_IF_RMAP_NAME, key.ifname);
return ret;
}
@@ -125,40 +122,38 @@ static bool if_rmap_hash_cmp(const void *arg1, const void *arg2)
return strcmp(if_rmap1->ifname, if_rmap2->ifname) == 0;
}
-static struct if_rmap *if_rmap_set(const char *ifname, enum if_rmap_type type,
+static struct if_rmap *if_rmap_set(struct if_rmap_ctx *ctx,
+ const char *ifname, enum if_rmap_type type,
const char *routemap_name)
{
struct if_rmap *if_rmap;
- if_rmap = if_rmap_get(ifname);
+ if_rmap = if_rmap_get(ctx, ifname);
if (type == IF_RMAP_IN) {
- if (if_rmap->routemap[IF_RMAP_IN])
- XFREE(MTYPE_IF_RMAP_NAME,
- if_rmap->routemap[IF_RMAP_IN]);
+ XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]);
if_rmap->routemap[IF_RMAP_IN] =
XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name);
}
if (type == IF_RMAP_OUT) {
- if (if_rmap->routemap[IF_RMAP_OUT])
- XFREE(MTYPE_IF_RMAP_NAME,
- if_rmap->routemap[IF_RMAP_OUT]);
+ XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]);
if_rmap->routemap[IF_RMAP_OUT] =
XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name);
}
- if (if_rmap_add_hook)
- (*if_rmap_add_hook)(if_rmap);
+ if (ctx->if_rmap_add_hook)
+ (ctx->if_rmap_add_hook)(ctx, if_rmap);
return if_rmap;
}
-static int if_rmap_unset(const char *ifname, enum if_rmap_type type,
+static int if_rmap_unset(struct if_rmap_ctx *ctx,
+ const char *ifname, enum if_rmap_type type,
const char *routemap_name)
{
struct if_rmap *if_rmap;
- if_rmap = if_rmap_lookup(ifname);
+ if_rmap = if_rmap_lookup(ctx, ifname);
if (!if_rmap)
return 0;
@@ -182,12 +177,12 @@ static int if_rmap_unset(const char *ifname, enum if_rmap_type type,
if_rmap->routemap[IF_RMAP_OUT] = NULL;
}
- if (if_rmap_delete_hook)
- (*if_rmap_delete_hook)(if_rmap);
+ if (ctx->if_rmap_delete_hook)
+ ctx->if_rmap_delete_hook(ctx, if_rmap);
if (if_rmap->routemap[IF_RMAP_IN] == NULL
&& if_rmap->routemap[IF_RMAP_OUT] == NULL) {
- hash_release(ifrmaphash, if_rmap);
+ hash_release(ctx->ifrmaphash, if_rmap);
if_rmap_free(if_rmap);
}
@@ -207,6 +202,8 @@ DEFUN (if_rmap,
int idx_in_out = 2;
int idx_ifname = 3;
enum if_rmap_type type;
+ struct if_rmap_ctx *ctx =
+ (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list);
if (strncmp(argv[idx_in_out]->text, "in", 1) == 0)
type = IF_RMAP_IN;
@@ -217,7 +214,8 @@ DEFUN (if_rmap,
return CMD_WARNING_CONFIG_FAILED;
}
- if_rmap_set(argv[idx_ifname]->arg, type, argv[idx_rmap_name]->arg);
+ if_rmap_set(ctx, argv[idx_ifname]->arg,
+ type, argv[idx_rmap_name]->arg);
return CMD_SUCCESS;
}
@@ -237,6 +235,8 @@ DEFUN (no_if_rmap,
int idx_ifname = 4;
int ret;
enum if_rmap_type type;
+ struct if_rmap_ctx *ctx =
+ (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list);
if (strncmp(argv[idx_in_out]->arg, "i", 1) == 0)
type = IF_RMAP_IN;
@@ -247,7 +247,7 @@ DEFUN (no_if_rmap,
return CMD_WARNING_CONFIG_FAILED;
}
- ret = if_rmap_unset(argv[idx_ifname]->arg, type,
+ ret = if_rmap_unset(ctx, argv[idx_ifname]->arg, type,
argv[idx_routemap_name]->arg);
if (!ret) {
vty_out(vty, "route-map doesn't exist\n");
@@ -258,11 +258,13 @@ DEFUN (no_if_rmap,
/* Configuration write function. */
-int config_write_if_rmap(struct vty *vty)
+int config_write_if_rmap(struct vty *vty,
+ struct if_rmap_ctx *ctx)
{
unsigned int i;
struct hash_bucket *mp;
int write = 0;
+ struct hash *ifrmaphash = ctx->ifrmaphash;
for (i = 0; i < ifrmaphash->size; i++)
for (mp = ifrmaphash->index[i]; mp; mp = mp->next) {
@@ -287,18 +289,44 @@ int config_write_if_rmap(struct vty *vty)
return write;
}
-void if_rmap_reset(void)
+void if_rmap_ctx_delete(struct if_rmap_ctx *ctx)
{
- hash_clean(ifrmaphash, (void (*)(void *))if_rmap_free);
+ hash_clean(ctx->ifrmaphash, (void (*)(void *))if_rmap_free);
+ if (ctx->name)
+ XFREE(MTYPE_IF_RMAP_CTX_NAME, ctx);
+ XFREE(MTYPE_IF_RMAP_CTX, ctx);
+}
+
+/* name is optional: either vrf name, or other */
+struct if_rmap_ctx *if_rmap_ctx_create(const char *name)
+{
+ struct if_rmap_ctx *ctx;
+
+ ctx = XCALLOC(MTYPE_IF_RMAP_CTX, sizeof(struct if_rmap_ctx));
+
+ if (ctx->name)
+ ctx->name = XSTRDUP(MTYPE_IF_RMAP_CTX_NAME, name);
+ ctx->ifrmaphash = hash_create_size(4, if_rmap_hash_make, if_rmap_hash_cmp,
+ "Interface Route-Map Hash");
+ if (!if_rmap_ctx_list)
+ if_rmap_ctx_list = list_new();
+ listnode_add(if_rmap_ctx_list, ctx);
+ return ctx;
}
void if_rmap_init(int node)
{
- ifrmaphash = hash_create_size(4, if_rmap_hash_make, if_rmap_hash_cmp,
- "Interface Route-Map Hash");
if (node == RIPNG_NODE) {
} else if (node == RIP_NODE) {
install_element(RIP_NODE, &if_rmap_cmd);
install_element(RIP_NODE, &no_if_rmap_cmd);
}
+ if_rmap_ctx_list = list_new();
+}
+
+void if_rmap_terminate(void)
+{
+ if (!if_rmap_ctx_list)
+ return;
+ list_delete(&if_rmap_ctx_list);
}
diff --git a/lib/if_rmap.h b/lib/if_rmap.h
index 8dded2cb48..dfc7298823 100644
--- a/lib/if_rmap.h
+++ b/lib/if_rmap.h
@@ -34,12 +34,33 @@ struct if_rmap {
char *routemap[IF_RMAP_MAX];
};
-extern void if_rmap_init(int);
-extern void if_rmap_reset(void);
-extern void if_rmap_hook_add(void (*)(struct if_rmap *));
-extern void if_rmap_hook_delete(void (*)(struct if_rmap *));
-extern struct if_rmap *if_rmap_lookup(const char *);
-extern int config_write_if_rmap(struct vty *);
+struct if_rmap_ctx {
+ /* if_rmap */
+ struct hash *ifrmaphash;
+
+ /* Hook functions. */
+ void (*if_rmap_add_hook)(struct if_rmap_ctx *ctx,
+ struct if_rmap *ifrmap);
+ void (*if_rmap_delete_hook)(struct if_rmap_ctx *ctx,
+ struct if_rmap *ifrmap);
+
+ /* naming information */
+ char *name;
+};
+
+extern struct if_rmap_ctx *if_rmap_ctx_create(const char *name);
+extern void if_rmap_ctx_delete(struct if_rmap_ctx *ctx);
+extern void if_rmap_init(int node);
+extern void if_rmap_terminate(void);
+void if_rmap_hook_add(struct if_rmap_ctx *ctx,
+ void (*func)(struct if_rmap_ctx *ctx,
+ struct if_rmap *));
+void if_rmap_hook_delete(struct if_rmap_ctx *ctx,
+ void (*func)(struct if_rmap_ctx *ctx,
+ struct if_rmap *));
+extern struct if_rmap *if_rmap_lookup(struct if_rmap_ctx *ctx,
+ const char *ifname);
+extern int config_write_if_rmap(struct vty *, struct if_rmap_ctx *ctx);
#ifdef __cplusplus
}
diff --git a/lib/imsg.c b/lib/imsg.c
index 935d137727..57e70617d2 100644
--- a/lib/imsg.c
+++ b/lib/imsg.c
@@ -18,6 +18,7 @@
#include <zebra.h>
+#include "memory.h"
#include "queue.h"
#include "imsg.h"
@@ -35,7 +36,7 @@ static int available_fds(unsigned int n)
unsigned int i;
int ret, fds[256];
- if (n > (sizeof(fds) / sizeof(fds[0])))
+ if (n > (unsigned int)array_size(fds))
return (1);
ret = 0;
diff --git a/lib/jhash.c b/lib/jhash.c
index cb6946f37e..0d561ef3a4 100644
--- a/lib/jhash.c
+++ b/lib/jhash.c
@@ -116,7 +116,7 @@ uint32_t jhash(const void *key, uint32_t length, uint32_t initval)
/* fallthru */
case 1:
a += k[0];
- };
+ }
__jhash_mix(a, b, c);
@@ -151,7 +151,7 @@ uint32_t jhash2(const uint32_t *k, uint32_t length, uint32_t initval)
/* fallthru */
case 1:
a += k[0];
- };
+ }
__jhash_mix(a, b, c);
diff --git a/lib/keychain.c b/lib/keychain.c
index 9aa3ef695f..0a96c4cf0e 100644
--- a/lib/keychain.c
+++ b/lib/keychain.c
@@ -116,8 +116,7 @@ static struct keychain *keychain_get(const char *name)
static void keychain_delete(struct keychain *keychain)
{
- if (keychain->name)
- XFREE(MTYPE_KEYCHAIN, keychain->name);
+ XFREE(MTYPE_KEYCHAIN, keychain->name);
list_delete(&keychain->key);
listnode_delete(keychain_list, keychain);
@@ -217,8 +216,7 @@ static void key_delete(struct keychain *keychain, struct key *key)
{
listnode_delete(keychain->key, key);
- if (key->string)
- XFREE(MTYPE_KEY, key->string);
+ XFREE(MTYPE_KEY, key->string);
key_free(key);
}
diff --git a/lib/libfrr.c b/lib/libfrr.c
index 9119b04992..1afe30d618 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -61,7 +61,7 @@ static char dbfile_default[512];
#endif
static char vtypath_default[256];
-bool debug_memstats_at_exit = 0;
+bool debug_memstats_at_exit = false;
static bool nodetach_term, nodetach_daemon;
static char comb_optstr[256];
diff --git a/lib/log.c b/lib/log.c
index c424a5bc98..e98040eb06 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -851,8 +851,7 @@ void closezlog(void)
if (zl->fp != NULL)
fclose(zl->fp);
- if (zl->filename != NULL)
- XFREE(MTYPE_ZLOG, zl->filename);
+ XFREE(MTYPE_ZLOG, zl->filename);
XFREE(MTYPE_ZLOG, zl);
zlog_default = NULL;
@@ -911,8 +910,7 @@ int zlog_reset_file(void)
logfile_fd = -1;
zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED;
- if (zl->filename)
- XFREE(MTYPE_ZLOG, zl->filename);
+ XFREE(MTYPE_ZLOG, zl->filename);
zl->filename = NULL;
pthread_mutex_unlock(&loglock);
diff --git a/lib/module.c b/lib/module.c
index 6754b94579..098c550684 100644
--- a/lib/module.c
+++ b/lib/module.c
@@ -141,8 +141,7 @@ struct frrmod_runtime *frrmod_load(const char *spec, const char *dir, char *err,
return rtinfo;
out_fail:
- if (rtinfo->load_args)
- XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args);
+ XFREE(MTYPE_MODULE_LOADARGS, rtinfo->load_args);
XFREE(MTYPE_MODULE_LOADNAME, rtinfo->load_name);
return NULL;
}
diff --git a/lib/netns_linux.c b/lib/netns_linux.c
index ef2f5dc953..55c66fdc3d 100644
--- a/lib/netns_linux.c
+++ b/lib/netns_linux.c
@@ -344,8 +344,7 @@ void ns_delete(struct ns *ns)
// if_terminate (&ns->iflist);
RB_REMOVE(ns_head, &ns_tree, ns);
- if (ns->name)
- XFREE(MTYPE_NS_NAME, ns->name);
+ XFREE(MTYPE_NS_NAME, ns->name);
XFREE(MTYPE_NS, ns);
}
diff --git a/lib/nexthop.h b/lib/nexthop.h
index c79ec590a8..fd27ca207b 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -83,7 +83,6 @@ struct nexthop {
#define NEXTHOP_FLAG_MATCHED (1 << 4) /* Already matched vs a nexthop */
#define NEXTHOP_FLAG_FILTERED (1 << 5) /* rmap filtered, used by static only */
#define NEXTHOP_FLAG_DUPLICATE (1 << 6) /* nexthop duplicates another active one */
-#define NEXTHOP_FLAG_EVPN_RVTEP (1 << 7) /* EVPN remote vtep nexthop */
#define NEXTHOP_IS_ACTIVE(flags) \
(CHECK_FLAG(flags, NEXTHOP_FLAG_ACTIVE) \
&& !CHECK_FLAG(flags, NEXTHOP_FLAG_DUPLICATE))
diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c
index 23ea96f75c..f940418d83 100644
--- a/lib/nexthop_group.c
+++ b/lib/nexthop_group.c
@@ -205,11 +205,9 @@ static int nhgl_cmp(struct nexthop_hold *nh1, struct nexthop_hold *nh2)
static void nhgl_delete(struct nexthop_hold *nh)
{
- if (nh->intf)
- XFREE(MTYPE_TMP, nh->intf);
+ XFREE(MTYPE_TMP, nh->intf);
- if (nh->nhvrf_name)
- XFREE(MTYPE_TMP, nh->nhvrf_name);
+ XFREE(MTYPE_TMP, nh->nhvrf_name);
XFREE(MTYPE_TMP, nh);
}
diff --git a/lib/northbound.c b/lib/northbound.c
index 15139aa8d0..edf7e0eca6 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -348,39 +348,58 @@ static void nb_config_diff_del_changes(struct nb_config_cbs *changes)
* configurations. Given a new subtree, calculate all new YANG data nodes,
* excluding default leafs and leaf-lists. This is a recursive function.
*/
-static void nb_config_diff_new_subtree(const struct lyd_node *dnode,
- struct nb_config_cbs *changes)
+static void nb_config_diff_created(const struct lyd_node *dnode,
+ struct nb_config_cbs *changes)
{
+ enum nb_operation operation;
struct lyd_node *child;
- LY_TREE_FOR (dnode->child, child) {
- enum nb_operation operation;
+ switch (dnode->schema->nodetype) {
+ case LYS_LEAF:
+ case LYS_LEAFLIST:
+ if (lyd_wd_default((struct lyd_node_leaf_list *)dnode))
+ break;
- switch (child->schema->nodetype) {
- case LYS_LEAF:
- case LYS_LEAFLIST:
- if (lyd_wd_default((struct lyd_node_leaf_list *)child))
- break;
+ if (nb_operation_is_valid(NB_OP_CREATE, dnode->schema))
+ operation = NB_OP_CREATE;
+ else if (nb_operation_is_valid(NB_OP_MODIFY, dnode->schema))
+ operation = NB_OP_MODIFY;
+ else
+ return;
- if (nb_operation_is_valid(NB_OP_CREATE, child->schema))
- operation = NB_OP_CREATE;
- else if (nb_operation_is_valid(NB_OP_MODIFY,
- child->schema))
- operation = NB_OP_MODIFY;
- else
- continue;
+ nb_config_diff_add_change(changes, operation, dnode);
+ break;
+ case LYS_CONTAINER:
+ case LYS_LIST:
+ if (nb_operation_is_valid(NB_OP_CREATE, dnode->schema))
+ nb_config_diff_add_change(changes, NB_OP_CREATE, dnode);
- nb_config_diff_add_change(changes, operation, child);
- break;
- case LYS_CONTAINER:
- case LYS_LIST:
- if (nb_operation_is_valid(NB_OP_CREATE, child->schema))
- nb_config_diff_add_change(changes, NB_OP_CREATE,
- child);
- nb_config_diff_new_subtree(child, changes);
- break;
- default:
- break;
+ /* Process child nodes recursively. */
+ LY_TREE_FOR (dnode->child, child) {
+ nb_config_diff_created(child, changes);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void nb_config_diff_deleted(const struct lyd_node *dnode,
+ struct nb_config_cbs *changes)
+{
+ if (nb_operation_is_valid(NB_OP_DESTROY, dnode->schema))
+ nb_config_diff_add_change(changes, NB_OP_DESTROY, dnode);
+ else if (CHECK_FLAG(dnode->schema->nodetype, LYS_CONTAINER)) {
+ struct lyd_node *child;
+
+ /*
+ * Non-presence containers need special handling since they
+ * don't have "destroy" callbacks. In this case, what we need to
+ * do is to call the "destroy" callbacks of their child nodes
+ * when applicable (i.e. optional nodes).
+ */
+ LY_TREE_FOR (dnode->child, child) {
+ nb_config_diff_deleted(child, changes);
}
}
}
@@ -399,42 +418,27 @@ static void nb_config_diff(const struct nb_config *config1,
for (int i = 0; diff->type[i] != LYD_DIFF_END; i++) {
LYD_DIFFTYPE type;
struct lyd_node *dnode;
- enum nb_operation operation;
type = diff->type[i];
switch (type) {
case LYD_DIFF_CREATED:
dnode = diff->second[i];
-
- if (nb_operation_is_valid(NB_OP_CREATE, dnode->schema))
- operation = NB_OP_CREATE;
- else if (nb_operation_is_valid(NB_OP_MODIFY,
- dnode->schema))
- operation = NB_OP_MODIFY;
- else
- continue;
+ nb_config_diff_created(dnode, changes);
break;
case LYD_DIFF_DELETED:
dnode = diff->first[i];
- operation = NB_OP_DESTROY;
+ nb_config_diff_deleted(dnode, changes);
break;
case LYD_DIFF_CHANGED:
dnode = diff->second[i];
- operation = NB_OP_MODIFY;
+ nb_config_diff_add_change(changes, NB_OP_MODIFY, dnode);
break;
case LYD_DIFF_MOVEDAFTER1:
case LYD_DIFF_MOVEDAFTER2:
default:
continue;
}
-
- nb_config_diff_add_change(changes, operation, dnode);
-
- if (type == LYD_DIFF_CREATED
- && CHECK_FLAG(dnode->schema->nodetype,
- LYS_CONTAINER | LYS_LIST))
- nb_config_diff_new_subtree(dnode, changes);
}
lyd_free_diff(diff);
diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c
index a8e0017819..a499d48c12 100644
--- a/lib/northbound_confd.c
+++ b/lib/northbound_confd.c
@@ -1383,7 +1383,7 @@ error:
static int frr_confd_finish(void)
{
- if (confd_connected == false)
+ if (!confd_connected)
return 0;
frr_confd_finish_cdb();
diff --git a/lib/plist.c b/lib/plist.c
index 41c8e4f8c0..2a97e1e5b2 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -326,8 +326,7 @@ static void prefix_list_delete(struct prefix_list *plist)
else
list->head = plist->next;
- if (plist->desc)
- XFREE(MTYPE_TMP, plist->desc);
+ XFREE(MTYPE_TMP, plist->desc);
/* Make sure master's recent changed prefix-list information is
cleared. */
@@ -338,8 +337,7 @@ static void prefix_list_delete(struct prefix_list *plist)
if (master->delete_hook)
(*master->delete_hook)(plist);
- if (plist->name)
- XFREE(MTYPE_MPREFIX_LIST_STR, plist->name);
+ XFREE(MTYPE_MPREFIX_LIST_STR, plist->name);
XFREE(MTYPE_PREFIX_LIST_TRIE, plist->trie);
diff --git a/lib/pqueue.c b/lib/pqueue.c
index 1565de216e..87b54a681a 100644
--- a/lib/pqueue.c
+++ b/lib/pqueue.c
@@ -133,8 +133,6 @@ static int pqueue_expand(struct pqueue *queue)
newarray =
XCALLOC(MTYPE_PQUEUE_DATA, queue->array_size * DATA_SIZE * 2);
- if (newarray == NULL)
- return 0;
memcpy(newarray, queue->array, queue->array_size * DATA_SIZE);
diff --git a/lib/prefix.c b/lib/prefix.c
index babd4304d1..52bb266f11 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -866,7 +866,7 @@ int str2prefix_ipv4(const char *str, struct prefix_ipv4 *p)
return ret;
} else {
cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1);
- strncpy(cp, str, pnt - str);
+ memcpy(cp, str, pnt - str);
*(cp + (pnt - str)) = '\0';
ret = inet_aton(cp, &p->prefix);
XFREE(MTYPE_TMP, cp);
@@ -913,7 +913,7 @@ int str2prefix_eth(const char *str, struct prefix_eth *p)
}
cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1);
- strncpy(cp, str, pnt - str);
+ memcpy(cp, str, pnt - str);
*(cp + (pnt - str)) = '\0';
str_addr = cp;
@@ -944,8 +944,7 @@ int str2prefix_eth(const char *str, struct prefix_eth *p)
ret = 1;
done:
- if (cp)
- XFREE(MTYPE_TMP, cp);
+ XFREE(MTYPE_TMP, cp);
return ret;
}
@@ -1030,7 +1029,7 @@ int str2prefix_ipv6(const char *str, struct prefix_ipv6 *p)
int plen;
cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1);
- strncpy(cp, str, pnt - str);
+ memcpy(cp, str, pnt - str);
*(cp + (pnt - str)) = '\0';
ret = inet_pton(AF_INET6, cp, &p->prefix);
XFREE(MTYPE_TMP, cp);
@@ -1503,8 +1502,7 @@ char *prefix_mac2str(const struct ethaddr *mac, char *buf, int size)
if (!mac)
return NULL;
if (!buf)
- ptr = (char *)XMALLOC(MTYPE_TMP,
- ETHER_ADDR_STRLEN * sizeof(char));
+ ptr = XMALLOC(MTYPE_TMP, ETHER_ADDR_STRLEN * sizeof(char));
else {
assert(size >= ETHER_ADDR_STRLEN);
ptr = buf;
@@ -1585,8 +1583,7 @@ char *esi_to_str(const esi_t *esi, char *buf, int size)
if (!esi)
return NULL;
if (!buf)
- ptr = (char *)XMALLOC(MTYPE_TMP,
- ESI_STR_LEN * sizeof(char));
+ ptr = XMALLOC(MTYPE_TMP, ESI_STR_LEN * sizeof(char));
else {
assert(size >= ESI_STR_LEN);
ptr = buf;
diff --git a/lib/privs.c b/lib/privs.c
index 2932800070..3ce8e0d57a 100644
--- a/lib/privs.c
+++ b/lib/privs.c
@@ -706,6 +706,14 @@ struct zebra_privs_t *_zprivs_raise(struct zebra_privs_t *privs,
if (!privs)
return NULL;
+ /* If we're already elevated, just return */
+ pthread_mutex_lock(&(privs->mutex));
+ if (++privs->refcount > 1) {
+ pthread_mutex_unlock(&(privs->mutex));
+ return privs;
+ }
+ pthread_mutex_unlock(&(privs->mutex));
+
errno = 0;
if (privs->change(ZPRIVS_RAISE)) {
zlog_err("%s: Failed to raise privileges (%s)",
@@ -723,6 +731,14 @@ void _zprivs_lower(struct zebra_privs_t **privs)
if (!*privs)
return;
+ /* Don't lower privs if there's another caller */
+ pthread_mutex_lock(&(*privs)->mutex);
+ if (--((*privs)->refcount) > 0) {
+ pthread_mutex_unlock(&(*privs)->mutex);
+ return;
+ }
+ pthread_mutex_unlock(&(*privs)->mutex);
+
errno = 0;
if ((*privs)->change(ZPRIVS_LOWER)) {
zlog_err("%s: Failed to lower privileges (%s)",
@@ -743,6 +759,9 @@ void zprivs_preinit(struct zebra_privs_t *zprivs)
exit(1);
}
+ pthread_mutex_init(&(zprivs->mutex), NULL);
+ zprivs->refcount = 0;
+
if (zprivs->vty_group) {
/* in a "NULL" setup, this is allowed to fail too, but still
* try. */
diff --git a/lib/privs.h b/lib/privs.h
index 1fee423a95..01ddba4622 100644
--- a/lib/privs.h
+++ b/lib/privs.h
@@ -23,6 +23,8 @@
#ifndef _ZEBRA_PRIVS_H
#define _ZEBRA_PRIVS_H
+#include <pthread.h>
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -59,6 +61,14 @@ struct zebra_privs_t {
zebra_capabilities_t *caps_i; /* caps to allow inheritance of */
int cap_num_p; /* number of caps in arrays */
int cap_num_i;
+
+ /* Mutex and counter used to avoid race conditions in multi-threaded
+ * processes. The privs elevation is process-wide, so we need to
+ * avoid changing the privilege status across threads.
+ */
+ pthread_mutex_t mutex;
+ uint32_t refcount;
+
const char *user; /* user and group to run as */
const char *group;
const char *vty_group; /* group to chown vty socket to */
diff --git a/lib/routemap.c b/lib/routemap.c
index 7c1ee2353c..4898a8d0fa 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -538,10 +538,8 @@ int generic_match_delete(struct vty *vty, struct route_map_index *index,
break;
}
- if (dep_name)
- XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
- if (rmap_name)
- XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
+ XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
+ XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
return retval;
}
@@ -1075,8 +1073,7 @@ static void route_map_index_delete(struct route_map_index *index, int notify)
index->map->head = index->next;
/* Free 'char *nextrm' if not NULL */
- if (index->nextrm)
- XFREE(MTYPE_ROUTE_MAP_NAME, index->nextrm);
+ XFREE(MTYPE_ROUTE_MAP_NAME, index->nextrm);
/* Execute event hook. */
if (route_map_master.event_hook && notify) {
@@ -1231,8 +1228,7 @@ static void route_map_rule_delete(struct route_map_rule_list *list,
if (rule->cmd->func_free)
(*rule->cmd->func_free)(rule->value);
- if (rule->rule_str)
- XFREE(MTYPE_ROUTE_MAP_RULE_STR, rule->rule_str);
+ XFREE(MTYPE_ROUTE_MAP_RULE_STR, rule->rule_str);
if (rule->next)
rule->next->prev = rule->prev;
@@ -1779,8 +1775,7 @@ static int route_map_dep_update(struct hash *dephash, const char *dep_name,
}
ret_map_name = (char *)hash_release(dep->dep_rmap_hash, rname);
- if (ret_map_name)
- XFREE(MTYPE_ROUTE_MAP_NAME, ret_map_name);
+ XFREE(MTYPE_ROUTE_MAP_NAME, ret_map_name);
if (!dep->dep_rmap_hash->count) {
dep = hash_release(dephash, dname);
diff --git a/lib/thread.c b/lib/thread.c
index 055587434c..19ab409439 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -414,8 +414,6 @@ struct thread_master *thread_master_create(const char *name)
pthread_once(&init_once, &initializer);
rv = XCALLOC(MTYPE_THREAD_MASTER, sizeof(struct thread_master));
- if (rv == NULL)
- return NULL;
/* Initialize master mutex */
pthread_mutex_init(&rv->mtx, NULL);
@@ -484,8 +482,7 @@ void thread_master_set_name(struct thread_master *master, const char *name)
{
pthread_mutex_lock(&master->mtx);
{
- if (master->name)
- XFREE(MTYPE_THREAD_MASTER, master->name);
+ XFREE(MTYPE_THREAD_MASTER, master->name);
master->name = XSTRDUP(MTYPE_THREAD_MASTER, name);
}
pthread_mutex_unlock(&master->mtx);
@@ -649,8 +646,7 @@ void thread_master_free(struct thread_master *m)
hash_free(m->cpu_record);
m->cpu_record = NULL;
- if (m->name)
- XFREE(MTYPE_THREAD_MASTER, m->name);
+ XFREE(MTYPE_THREAD_MASTER, m->name);
XFREE(MTYPE_THREAD_MASTER, m->handler.pfds);
XFREE(MTYPE_THREAD_MASTER, m->handler.copy);
XFREE(MTYPE_THREAD_MASTER, m);
diff --git a/lib/vty.c b/lib/vty.c
index d6fda8cbb4..0bcee6a801 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -974,8 +974,7 @@ static void vty_complete_command(struct vty *vty)
default:
break;
}
- if (matched)
- XFREE(MTYPE_TMP, matched);
+ XFREE(MTYPE_TMP, matched);
}
static void vty_describe_fold(struct vty *vty, int cmd_width,
@@ -1169,8 +1168,7 @@ static void vty_hist_add(struct vty *vty)
}
/* Insert history entry. */
- if (vty->hist[vty->hindex])
- XFREE(MTYPE_VTY_HIST, vty->hist[vty->hindex]);
+ XFREE(MTYPE_VTY_HIST, vty->hist[vty->hindex]);
vty->hist[vty->hindex] = XSTRDUP(MTYPE_VTY_HIST, vty->buf);
/* History index rotation. */
@@ -2232,9 +2230,9 @@ void vty_close(struct vty *vty)
buffer_free(vty->lbuf);
/* Free command history. */
- for (i = 0; i < VTY_MAXHIST; i++)
- if (vty->hist[i])
- XFREE(MTYPE_VTY_HIST, vty->hist[i]);
+ for (i = 0; i < VTY_MAXHIST; i++) {
+ XFREE(MTYPE_VTY_HIST, vty->hist[i]);
+ }
/* Unset vector. */
if (vty->fd != -1)
@@ -2255,8 +2253,7 @@ void vty_close(struct vty *vty)
if (vty->fd == STDIN_FILENO)
was_stdio = true;
- if (vty->buf)
- XFREE(MTYPE_VTY, vty->buf);
+ XFREE(MTYPE_VTY, vty->buf);
if (vty->error) {
vty->error->del = vty_error_delete;
@@ -2546,8 +2543,7 @@ bool vty_read_config(struct nb_config *config, const char *config_file,
host_config_set(fullpath);
tmp_free_and_out:
- if (tmp)
- XFREE(MTYPE_TMP, tmp);
+ XFREE(MTYPE_TMP, tmp);
return read_success;
}
@@ -3163,8 +3159,7 @@ void vty_init(struct thread_master *master_thread)
void vty_terminate(void)
{
- if (vty_cwd)
- XFREE(MTYPE_TMP, vty_cwd);
+ XFREE(MTYPE_TMP, vty_cwd);
if (vtyvec && Vvty_serv_thread) {
vty_reset();
diff --git a/lib/workqueue.c b/lib/workqueue.c
index fa69ec600e..066d81f350 100644
--- a/lib/workqueue.c
+++ b/lib/workqueue.c
@@ -274,7 +274,7 @@ int work_queue_run(struct thread *thread)
wq->cycles.granularity = WORK_QUEUE_MIN_GRANULARITY;
STAILQ_FOREACH_SAFE (item, &wq->items, wq, titem) {
- assert(item && item->data);
+ assert(item->data);
/* dont run items which are past their allowed retries */
if (item->ran > wq->spec.max_retries) {
diff --git a/lib/yang_translator.c b/lib/yang_translator.c
index 6d6f92836f..76a6cc5fd1 100644
--- a/lib/yang_translator.c
+++ b/lib/yang_translator.c
@@ -511,7 +511,7 @@ static void str_replace(char *o_string, const char *s_string,
if (!ch)
return;
- strncpy(buffer, o_string, ch - o_string);
+ memcpy(buffer, o_string, ch - o_string);
buffer[ch - o_string] = 0;
sprintf(buffer + (ch - o_string), "%s%s", r_string,
diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c
index 6273dff3ce..7ecea5f445 100644
--- a/lib/yang_wrappers.c
+++ b/lib/yang_wrappers.c
@@ -62,7 +62,7 @@ bool yang_str2bool(const char *value)
struct yang_data *yang_data_new_bool(const char *xpath, bool value)
{
- return yang_data_new(xpath, (value == true) ? "true" : "false");
+ return yang_data_new(xpath, (value) ? "true" : "false");
}
bool yang_dnode_get_bool(const struct lyd_node *dnode, const char *xpath_fmt,
diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c
index 4c6827cb3d..6666c6e96b 100644
--- a/nhrpd/netlink_arp.c
+++ b/nhrpd/netlink_arp.c
@@ -122,7 +122,7 @@ static int netlink_route_recv(struct thread *t)
zbuf_init(&zb, buf, sizeof(buf), 0);
while (zbuf_recv(&zb, fd) > 0) {
- while ((n = znl_nlmsg_pull(&zb, &payload)) != 0) {
+ while ((n = znl_nlmsg_pull(&zb, &payload)) != NULL) {
debugf(NHRP_DEBUG_KERNEL,
"Netlink: Received msg_type %u, msg_flags %u",
n->nlmsg_type, n->nlmsg_flags);
@@ -217,7 +217,7 @@ static int netlink_log_recv(struct thread *t)
zbuf_init(&zb, buf, sizeof(buf), 0);
while (zbuf_recv(&zb, fd) > 0) {
- while ((n = znl_nlmsg_pull(&zb, &payload)) != 0) {
+ while ((n = znl_nlmsg_pull(&zb, &payload)) != NULL) {
debugf(NHRP_DEBUG_KERNEL,
"Netlink-log: Received msg_type %u, msg_flags %u",
n->nlmsg_type, n->nlmsg_flags);
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 83b9001fea..692c84ad08 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -177,8 +177,7 @@ struct ospf6_interface *ospf6_interface_create(struct interface *ifp)
struct ospf6_interface *oi;
unsigned int iobuflen;
- oi = (struct ospf6_interface *)XCALLOC(MTYPE_OSPF6_IF,
- sizeof(struct ospf6_interface));
+ oi = XCALLOC(MTYPE_OSPF6_IF, sizeof(struct ospf6_interface));
oi->area = (struct ospf6_area *)NULL;
oi->neighbor_list = list_new();
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index 40b3522c3d..9acbd09b1a 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -518,16 +518,14 @@ struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header)
lsa_size = ntohs(header->length); /* XXX vulnerable */
/* allocate memory for this LSA */
- new_header = (struct ospf6_lsa_header *)XMALLOC(MTYPE_OSPF6_LSA_HEADER,
- lsa_size);
+ new_header = XMALLOC(MTYPE_OSPF6_LSA_HEADER, lsa_size);
/* copy LSA from original header */
memcpy(new_header, header, lsa_size);
/* LSA information structure */
/* allocate memory */
- lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
- sizeof(struct ospf6_lsa));
+ lsa = XCALLOC(MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa));
lsa->header = (struct ospf6_lsa_header *)new_header;
@@ -546,16 +544,15 @@ struct ospf6_lsa *ospf6_lsa_create_headeronly(struct ospf6_lsa_header *header)
struct ospf6_lsa_header *new_header = NULL;
/* allocate memory for this LSA */
- new_header = (struct ospf6_lsa_header *)XMALLOC(
- MTYPE_OSPF6_LSA_HEADER, sizeof(struct ospf6_lsa_header));
+ new_header = XMALLOC(MTYPE_OSPF6_LSA_HEADER,
+ sizeof(struct ospf6_lsa_header));
/* copy LSA from original header */
memcpy(new_header, header, sizeof(struct ospf6_lsa_header));
/* LSA information structure */
/* allocate memory */
- lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
- sizeof(struct ospf6_lsa));
+ lsa = XCALLOC(MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa));
lsa->header = (struct ospf6_lsa_header *)new_header;
SET_FLAG(lsa->flag, OSPF6_LSA_HEADERONLY);
diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c
index 5e02c0c917..b551dbdfa6 100644
--- a/ospf6d/ospf6_lsdb.c
+++ b/ospf6d/ospf6_lsdb.c
@@ -39,10 +39,6 @@ struct ospf6_lsdb *ospf6_lsdb_create(void *data)
struct ospf6_lsdb *lsdb;
lsdb = XCALLOC(MTYPE_OSPF6_LSDB, sizeof(struct ospf6_lsdb));
- if (lsdb == NULL) {
- zlog_warn("Can't malloc lsdb");
- return NULL;
- }
memset(lsdb, 0, sizeof(struct ospf6_lsdb));
lsdb->data = data;
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index cd688bbf89..4acb5e3b2e 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -1505,10 +1505,8 @@ int ospf6_iobuf_size(unsigned int size)
recvnew = XMALLOC(MTYPE_OSPF6_MESSAGE, size);
sendnew = XMALLOC(MTYPE_OSPF6_MESSAGE, size);
- if (recvbuf)
- XFREE(MTYPE_OSPF6_MESSAGE, recvbuf);
- if (sendbuf)
- XFREE(MTYPE_OSPF6_MESSAGE, sendbuf);
+ XFREE(MTYPE_OSPF6_MESSAGE, recvbuf);
+ XFREE(MTYPE_OSPF6_MESSAGE, sendbuf);
recvbuf = recvnew;
sendbuf = sendnew;
iobuflen = size;
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index bb451c239e..46dc621ae7 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -86,10 +86,7 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id,
struct ospf6_neighbor *on;
char buf[16];
- on = (struct ospf6_neighbor *)XMALLOC(MTYPE_OSPF6_NEIGHBOR,
- sizeof(struct ospf6_neighbor));
-
- memset(on, 0, sizeof(struct ospf6_neighbor));
+ on = XCALLOC(MTYPE_OSPF6_NEIGHBOR, sizeof(struct ospf6_neighbor));
inet_ntop(AF_INET, &router_id, buf, sizeof(buf));
snprintf(on->name, sizeof(on->name), "%s%%%s", buf,
oi->interface->name);
diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c
index 79e1a44392..b71b353e1f 100644
--- a/ospf6d/ospf6_route.c
+++ b/ospf6d/ospf6_route.c
@@ -174,8 +174,7 @@ struct ospf6_nexthop *ospf6_nexthop_create(void)
void ospf6_nexthop_delete(struct ospf6_nexthop *nh)
{
- if (nh)
- XFREE(MTYPE_OSPF6_NEXTHOP, nh);
+ XFREE(MTYPE_OSPF6_NEXTHOP, nh);
}
void ospf6_clear_nexthops(struct list *nh_list)
diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c
index 376950e84a..fc7c6177d7 100644
--- a/ospf6d/ospf6_snmp.c
+++ b/ospf6d/ospf6_snmp.c
@@ -1358,13 +1358,10 @@ static int ospf6TrapNbrStateChange(struct ospf6_neighbor *on, int next_state,
index[1] = on->ospf6_if->instance_id;
index[2] = ntohl(on->router_id);
- smux_trap(ospfv3_variables,
- sizeof ospfv3_variables / sizeof(struct variable),
- ospfv3_trap_oid, sizeof ospfv3_trap_oid / sizeof(oid),
- ospfv3_oid, sizeof ospfv3_oid / sizeof(oid), index, 3,
- ospf6NbrTrapList,
- sizeof ospf6NbrTrapList / sizeof(struct trap_object),
- NBRSTATECHANGE);
+ smux_trap(ospfv3_variables, array_size(ospfv3_variables),
+ ospfv3_trap_oid, array_size(ospfv3_trap_oid), ospfv3_oid,
+ sizeof ospfv3_oid / sizeof(oid), index, 3, ospf6NbrTrapList,
+ array_size(ospf6NbrTrapList), NBRSTATECHANGE);
return 0;
}
@@ -1383,13 +1380,10 @@ static int ospf6TrapIfStateChange(struct ospf6_interface *oi, int next_state,
index[0] = oi->interface->ifindex;
index[1] = oi->instance_id;
- smux_trap(ospfv3_variables,
- sizeof ospfv3_variables / sizeof(struct variable),
- ospfv3_trap_oid, sizeof ospfv3_trap_oid / sizeof(oid),
- ospfv3_oid, sizeof ospfv3_oid / sizeof(oid), index, 2,
- ospf6IfTrapList,
- sizeof ospf6IfTrapList / sizeof(struct trap_object),
- IFSTATECHANGE);
+ smux_trap(ospfv3_variables, array_size(ospfv3_variables),
+ ospfv3_trap_oid, array_size(ospfv3_trap_oid), ospfv3_oid,
+ sizeof ospfv3_oid / sizeof(oid), index, 2, ospf6IfTrapList,
+ array_size(ospf6IfTrapList), IFSTATECHANGE);
return 0;
}
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index 2d271c1dab..d4f6f6f4ae 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -107,8 +107,7 @@ static struct ospf6_vertex *ospf6_vertex_create(struct ospf6_lsa *lsa)
{
struct ospf6_vertex *v;
- v = (struct ospf6_vertex *)XMALLOC(MTYPE_OSPF6_VERTEX,
- sizeof(struct ospf6_vertex));
+ v = XMALLOC(MTYPE_OSPF6_VERTEX, sizeof(struct ospf6_vertex));
/* type */
if (ntohs(lsa->header->type) == OSPF6_LSTYPE_ROUTER) {
@@ -1016,8 +1015,7 @@ struct ospf6_lsa *ospf6_create_single_router_lsa(struct ospf6_area *area,
new_header = XMALLOC(MTYPE_OSPF6_LSA_HEADER, total_lsa_length);
/* LSA information structure */
- lsa = (struct ospf6_lsa *)XCALLOC(MTYPE_OSPF6_LSA,
- sizeof(struct ospf6_lsa));
+ lsa = XCALLOC(MTYPE_OSPF6_LSA, sizeof(struct ospf6_lsa));
lsa->header = (struct ospf6_lsa_header *)new_header;
diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c
index ba2e04bf76..ea919017d3 100644
--- a/ospfd/ospf_asbr.c
+++ b/ospfd/ospf_asbr.c
@@ -79,8 +79,7 @@ struct external_info *ospf_external_info_new(uint8_t type,
{
struct external_info *new;
- new = (struct external_info *)XCALLOC(MTYPE_OSPF_EXTERNAL_INFO,
- sizeof(struct external_info));
+ new = XCALLOC(MTYPE_OSPF_EXTERNAL_INFO, sizeof(struct external_info));
new->type = type;
new->instance = instance;
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index 48d210d279..f74d9733ee 100644
--- a/ospfd/ospf_dump.c
+++ b/ospfd/ospf_dump.c
@@ -538,8 +538,7 @@ static void ospf_header_dump(struct ospf_header *ospfh)
case OSPF_AUTH_NULL:
break;
case OSPF_AUTH_SIMPLE:
- memset(buf, 0, 9);
- strncpy(buf, (char *)ospfh->u.auth_data, 8);
+ strlcpy(buf, (char *)ospfh->u.auth_data, sizeof(buf));
zlog_debug(" Simple Password %s", buf);
break;
case OSPF_AUTH_CRYPTOGRAPHIC:
diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c
index 9fd9a70c78..419081fe59 100644
--- a/ospfd/ospf_ism.c
+++ b/ospfd/ospf_ism.c
@@ -380,12 +380,10 @@ static int ism_interface_up(struct ospf_interface *oi)
static int ism_loop_ind(struct ospf_interface *oi)
{
- int ret = 0;
-
/* call ism_interface_down. */
/* ret = ism_interface_down (oi); */
- return ret;
+ return 0;
}
/* Interface down event handler. */
diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c
index 755634a2f1..f068efc8db 100644
--- a/ospfd/ospf_snmp.c
+++ b/ospfd/ospf_snmp.c
@@ -2590,13 +2590,10 @@ static void ospfTrapNbrStateChange(struct ospf_neighbor *on)
oid_copy_addr(index, &(on->address.u.prefix4), IN_ADDR_SIZE);
index[IN_ADDR_SIZE] = 0;
- smux_trap(ospf_variables,
- sizeof ospf_variables / sizeof(struct variable),
- ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid,
+ smux_trap(ospf_variables, array_size(ospf_variables), ospf_trap_oid,
+ array_size(ospf_trap_oid), ospf_oid,
sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1,
- ospfNbrTrapList,
- sizeof ospfNbrTrapList / sizeof(struct trap_object),
- NBRSTATECHANGE);
+ ospfNbrTrapList, array_size(ospfNbrTrapList), NBRSTATECHANGE);
}
static void ospfTrapVirtNbrStateChange(struct ospf_neighbor *on)
@@ -2608,12 +2605,10 @@ static void ospfTrapVirtNbrStateChange(struct ospf_neighbor *on)
oid_copy_addr(index, &(on->address.u.prefix4), IN_ADDR_SIZE);
index[IN_ADDR_SIZE] = 0;
- smux_trap(ospf_variables,
- sizeof ospf_variables / sizeof(struct variable),
- ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid,
+ smux_trap(ospf_variables, array_size(ospf_variables), ospf_trap_oid,
+ array_size(ospf_trap_oid), ospf_oid,
sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1,
- ospfVirtNbrTrapList,
- sizeof ospfVirtNbrTrapList / sizeof(struct trap_object),
+ ospfVirtNbrTrapList, array_size(ospfVirtNbrTrapList),
VIRTNBRSTATECHANGE);
}
@@ -2649,13 +2644,10 @@ static void ospfTrapIfStateChange(struct ospf_interface *oi)
oid_copy_addr(index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
index[IN_ADDR_SIZE] = 0;
- smux_trap(ospf_variables,
- sizeof ospf_variables / sizeof(struct variable),
- ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid,
+ smux_trap(ospf_variables, array_size(ospf_variables), ospf_trap_oid,
+ array_size(ospf_trap_oid), ospf_oid,
sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1,
- ospfIfTrapList,
- sizeof ospfIfTrapList / sizeof(struct trap_object),
- IFSTATECHANGE);
+ ospfIfTrapList, array_size(ospfIfTrapList), IFSTATECHANGE);
}
static void ospfTrapVirtIfStateChange(struct ospf_interface *oi)
@@ -2667,12 +2659,10 @@ static void ospfTrapVirtIfStateChange(struct ospf_interface *oi)
oid_copy_addr(index, &(oi->address->u.prefix4), IN_ADDR_SIZE);
index[IN_ADDR_SIZE] = 0;
- smux_trap(ospf_variables,
- sizeof ospf_variables / sizeof(struct variable),
- ospf_trap_oid, sizeof ospf_trap_oid / sizeof(oid), ospf_oid,
+ smux_trap(ospf_variables, array_size(ospf_variables), ospf_trap_oid,
+ array_size(ospf_trap_oid), ospf_oid,
sizeof ospf_oid / sizeof(oid), index, IN_ADDR_SIZE + 1,
- ospfVirtIfTrapList,
- sizeof ospfVirtIfTrapList / sizeof(struct trap_object),
+ ospfVirtIfTrapList, array_size(ospfVirtIfTrapList),
VIRTIFSTATECHANGE);
}
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index c1dc1f0d6f..b5d8739fcb 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -954,8 +954,9 @@ static int ospf_vl_set_security(struct ospf_vl_data *vl_data,
if (vl_config->auth_key) {
memset(IF_DEF_PARAMS(ifp)->auth_simple, 0,
OSPF_AUTH_SIMPLE_SIZE + 1);
- strncpy((char *)IF_DEF_PARAMS(ifp)->auth_simple,
- vl_config->auth_key, OSPF_AUTH_SIMPLE_SIZE);
+ strlcpy((char *)IF_DEF_PARAMS(ifp)->auth_simple,
+ vl_config->auth_key,
+ sizeof(IF_DEF_PARAMS(ifp)->auth_simple));
} else if (vl_config->md5_key) {
if (ospf_crypt_key_lookup(IF_DEF_PARAMS(ifp)->auth_crypt,
vl_config->crypto_key_id)
@@ -967,8 +968,8 @@ static int ospf_vl_set_security(struct ospf_vl_data *vl_data,
ck = ospf_crypt_key_new();
ck->key_id = vl_config->crypto_key_id;
memset(ck->auth_key, 0, OSPF_AUTH_MD5_SIZE + 1);
- strncpy((char *)ck->auth_key, vl_config->md5_key,
- OSPF_AUTH_MD5_SIZE);
+ strlcpy((char *)ck->auth_key, vl_config->md5_key,
+ sizeof(ck->auth_key));
ospf_crypt_key_add(IF_DEF_PARAMS(ifp)->auth_crypt, ck);
} else if (vl_config->crypto_key_id != 0) {
@@ -1147,14 +1148,12 @@ DEFUN (ospf_area_vlink,
if (vl_config.crypto_key_id < 0)
return CMD_WARNING_CONFIG_FAILED;
- memset(md5_key, 0, OSPF_AUTH_MD5_SIZE + 1);
- strncpy(md5_key, argv[idx + 3]->arg, OSPF_AUTH_MD5_SIZE);
+ strlcpy(md5_key, argv[idx + 3]->arg, sizeof(md5_key));
vl_config.md5_key = md5_key;
}
if (argv_find(argv, argc, "authentication-key", &idx)) {
- memset(auth_key, 0, OSPF_AUTH_SIMPLE_SIZE + 1);
- strncpy(auth_key, argv[idx + 1]->arg, OSPF_AUTH_SIMPLE_SIZE);
+ strlcpy(auth_key, argv[idx + 1]->arg, sizeof(auth_key));
vl_config.auth_key = auth_key;
}
@@ -3030,13 +3029,13 @@ static int show_ip_ospf_common(struct vty *vty, struct ospf *ospf,
if (ospf->stub_router_startup_time
!= OSPF_STUB_ROUTER_UNCONFIGURED)
json_object_int_add(
- json_vrf, "postStartEnabledMsecs",
- ospf->stub_router_startup_time / 1000);
+ json_vrf, "postStartEnabledSecs",
+ ospf->stub_router_startup_time);
if (ospf->stub_router_shutdown_time
!= OSPF_STUB_ROUTER_UNCONFIGURED)
json_object_int_add(
- json_vrf, "preShutdownEnabledMsecs",
- ospf->stub_router_shutdown_time / 1000);
+ json_vrf, "preShutdownEnabledSecs",
+ ospf->stub_router_shutdown_time);
} else {
vty_out(vty,
" Stub router advertisement is configured\n");
@@ -3512,8 +3511,8 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
json_object_int_add(json_interface_sub, "cost",
oi->output_cost);
json_object_int_add(
- json_interface_sub, "transmitDelayMsecs",
- 1000 / OSPF_IF_PARAM(oi, transmit_delay));
+ json_interface_sub, "transmitDelaySecs",
+ OSPF_IF_PARAM(oi, transmit_delay));
json_object_string_add(json_interface_sub, "state",
lookup_msg(ospf_ism_state_msg,
oi->state, NULL));
@@ -3617,20 +3616,20 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
if (OSPF_IF_PARAM(oi, fast_hello) == 0)
json_object_int_add(
json_interface_sub, "timerMsecs",
- 1000 / OSPF_IF_PARAM(oi, v_hello));
+ OSPF_IF_PARAM(oi, v_hello) * 1000);
else
json_object_int_add(
json_interface_sub, "timerMsecs",
1000 / OSPF_IF_PARAM(oi, fast_hello));
json_object_int_add(json_interface_sub,
- "timerDeadMsecs",
- 1000 / OSPF_IF_PARAM(oi, v_wait));
+ "timerDeadSecs",
+ OSPF_IF_PARAM(oi, v_wait));
json_object_int_add(json_interface_sub,
- "timerWaitMsecs",
- 1000 / OSPF_IF_PARAM(oi, v_wait));
+ "timerWaitSecs",
+ OSPF_IF_PARAM(oi, v_wait));
json_object_int_add(
- json_interface_sub, "timerRetransmit",
- 1000 / OSPF_IF_PARAM(oi, retransmit_interval));
+ json_interface_sub, "timerRetransmitSecs",
+ OSPF_IF_PARAM(oi, retransmit_interval));
} else {
vty_out(vty, " Timer intervals configured,");
vty_out(vty, " Hello ");
@@ -6895,9 +6894,8 @@ DEFUN (ip_ospf_authentication_key,
ospf_if_update_params(ifp, addr);
}
- memset(params->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE + 1);
- strncpy((char *)params->auth_simple, argv[3]->arg,
- OSPF_AUTH_SIMPLE_SIZE);
+ strlcpy((char *)params->auth_simple, argv[3]->arg,
+ sizeof(params->auth_simple));
SET_IF_PARAM(params, auth_simple);
return CMD_SUCCESS;
@@ -7006,8 +7004,7 @@ DEFUN (ip_ospf_message_digest_key,
ck = ospf_crypt_key_new();
ck->key_id = (uint8_t)key_id;
- memset(ck->auth_key, 0, OSPF_AUTH_MD5_SIZE + 1);
- strncpy((char *)ck->auth_key, cryptkey, OSPF_AUTH_MD5_SIZE);
+ strlcpy((char *)ck->auth_key, cryptkey, sizeof(ck->auth_key));
ospf_crypt_key_add(params->auth_crypt, ck);
SET_IF_PARAM(params, auth_crypt);
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index ea2c492e18..4cbd817ad8 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -560,8 +560,7 @@ struct ospf_external *ospf_external_add(struct ospf *ospf, uint8_t type,
ospf->external[type] = list_new();
ext_list = ospf->external[type];
- ext = (struct ospf_external *)XCALLOC(MTYPE_OSPF_EXTERNAL,
- sizeof(struct ospf_external));
+ ext = XCALLOC(MTYPE_OSPF_EXTERNAL, sizeof(struct ospf_external));
ext->instance = instance;
EXTERNAL_INFO(ext) = route_table_init();
@@ -621,8 +620,7 @@ struct ospf_redist *ospf_redist_add(struct ospf *ospf, uint8_t type,
ospf->redist[type] = list_new();
red_list = ospf->redist[type];
- red = (struct ospf_redist *)XCALLOC(MTYPE_OSPF_REDISTRIBUTE,
- sizeof(struct ospf_redist));
+ red = XCALLOC(MTYPE_OSPF_REDISTRIBUTE, sizeof(struct ospf_redist));
red->instance = instance;
red->dmetric.type = -1;
red->dmetric.value = -1;
diff --git a/pbrd/pbr_map.c b/pbrd/pbr_map.c
index 8f8b6aeed1..5e67990d5e 100644
--- a/pbrd/pbr_map.c
+++ b/pbrd/pbr_map.c
@@ -71,8 +71,7 @@ static int pbr_map_sequence_compare(const struct pbr_map_sequence *pbrms1,
static void pbr_map_sequence_delete(struct pbr_map_sequence *pbrms)
{
- if (pbrms->internal_nhg_name)
- XFREE(MTYPE_TMP, pbrms->internal_nhg_name);
+ XFREE(MTYPE_TMP, pbrms->internal_nhg_name);
XFREE(MTYPE_PBR_MAP_SEQNO, pbrms);
}
diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c
index 2cba657f65..6a025fd724 100644
--- a/pbrd/pbr_nht.c
+++ b/pbrd/pbr_nht.c
@@ -740,7 +740,7 @@ uint32_t pbr_nht_get_next_tableid(bool peek)
bool found = false;
for (i = pbr_nhg_low_table; i <= pbr_nhg_high_table; i++) {
- if (nhg_tableid[i] == false) {
+ if (!nhg_tableid[i]) {
found = true;
break;
}
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index eaec002a73..012c3b4f1d 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -1191,7 +1191,7 @@ static void pim_show_interfaces_single(struct pim_instance *pim,
vty_out(vty, "Designated Router\n");
vty_out(vty, "-----------------\n");
vty_out(vty, "Address : %s\n", dr_str);
- vty_out(vty, "Priority : %d(%d)\n",
+ vty_out(vty, "Priority : %u(%d)\n",
pim_ifp->pim_dr_priority,
pim_ifp->pim_dr_num_nondrpri_neighbors);
vty_out(vty, "Uptime : %s\n", dr_uptime);
@@ -5159,16 +5159,14 @@ static int pim_cmd_spt_switchover(struct pim_instance *pim,
switch (pim->spt.switchover) {
case PIM_SPT_IMMEDIATE:
- if (pim->spt.plist)
- XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
+ XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
pim_upstream_add_lhr_star_pimreg(pim);
break;
case PIM_SPT_INFINITY:
pim_upstream_remove_lhr_star_pimreg(pim, plist);
- if (pim->spt.plist)
- XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
+ XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist);
if (plist)
pim->spt.plist =
@@ -6353,8 +6351,8 @@ DEFUN (interface_ip_pim_drprio,
pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10);
if (old_dr_prio != pim_ifp->pim_dr_priority) {
- if (pim_if_dr_election(ifp))
- pim_hello_restart_now(ifp);
+ pim_if_dr_election(ifp);
+ pim_hello_restart_now(ifp);
}
return CMD_SUCCESS;
@@ -6379,8 +6377,8 @@ DEFUN (interface_no_ip_pim_drprio,
if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) {
pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY;
- if (pim_if_dr_election(ifp))
- pim_hello_restart_now(ifp);
+ pim_if_dr_election(ifp);
+ pim_hello_restart_now(ifp);
}
return CMD_SUCCESS;
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 6933f4d5bd..92d21cf429 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -208,8 +208,7 @@ void pim_if_delete(struct interface *ifp)
list_delete(&pim_ifp->upstream_switch_list);
list_delete(&pim_ifp->sec_addr_list);
- if (pim_ifp->boundary_oil_plist)
- XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
+ XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
diff --git a/pimd/pim_main.c b/pimd/pim_main.c
index dc42899c7b..5a8991c4c0 100644
--- a/pimd/pim_main.c
+++ b/pimd/pim_main.c
@@ -68,7 +68,7 @@ struct zebra_privs_t pimd_privs = {
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
- .cap_num_p = sizeof(_caps_p) / sizeof(_caps_p[0]),
+ .cap_num_p = array_size(_caps_p),
.cap_num_i = 0};
static const struct frr_yang_module_info *pimd_yang_modules[] = {
diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c
index a4f87fa1a6..395c4af35f 100644
--- a/pimd/pim_msdp.c
+++ b/pimd/pim_msdp.c
@@ -1256,8 +1256,7 @@ static void pim_msdp_mg_free(struct pim_instance *pim)
if (PIM_DEBUG_MSDP_EVENTS) {
zlog_debug("MSDP mesh-group %s deleted", mg->mesh_group_name);
}
- if (mg->mesh_group_name)
- XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name);
+ XFREE(MTYPE_PIM_MSDP_MG_NAME, mg->mesh_group_name);
if (mg->mbr_list)
list_delete(&mg->mbr_list);
diff --git a/pimd/pim_register.c b/pimd/pim_register.c
index b9908ae22b..4b402de634 100644
--- a/pimd/pim_register.c
+++ b/pimd/pim_register.c
@@ -189,8 +189,8 @@ void pim_register_send(const uint8_t *buf, int buf_size, struct in_addr src,
if (PIM_DEBUG_PIM_REG) {
char rp_str[INET_ADDRSTRLEN];
- strncpy(rp_str, inet_ntoa(rpg->rpf_addr.u.prefix4),
- INET_ADDRSTRLEN - 1);
+ strlcpy(rp_str, inet_ntoa(rpg->rpf_addr.u.prefix4),
+ sizeof(rp_str));
zlog_debug("%s: Sending %s %sRegister Packet to %s on %s",
__PRETTY_FUNCTION__, up->sg_str,
null_register ? "NULL " : "", rp_str, ifp->name);
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index 08f2ffc4ea..308d5a5e06 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -65,8 +65,7 @@ void pim_rp_list_hash_clean(void *data)
static void pim_rp_info_free(struct rp_info *rp_info)
{
- if (rp_info->plist)
- XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist);
+ XFREE(MTYPE_PIM_FILTER_NAME, rp_info->plist);
XFREE(MTYPE_PIM_RP, rp_info);
}
diff --git a/pimd/pim_ssm.c b/pimd/pim_ssm.c
index dfc7063fd0..6a70a73b45 100644
--- a/pimd/pim_ssm.c
+++ b/pimd/pim_ssm.c
@@ -151,8 +151,7 @@ void pim_ssm_terminate(struct pim_ssm *ssm)
if (!ssm)
return;
- if (ssm->plist_name)
- XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name);
+ XFREE(MTYPE_PIM_FILTER_NAME, ssm->plist_name);
XFREE(MTYPE_PIM_SSM_INFO, ssm);
}
diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c
index 6fbcdc059b..62aaad5d97 100644
--- a/ripd/rip_cli.c
+++ b/ripd/rip_cli.c
@@ -378,10 +378,19 @@ DEFPY (rip_passive_interface,
"Suppress routing updates on an interface\n"
"Interface name\n")
{
- nb_cli_enqueue_change(vty, "./passive-interface",
- no ? NB_OP_DESTROY : NB_OP_CREATE, ifname);
- nb_cli_enqueue_change(vty, "./non-passive-interface",
- no ? NB_OP_CREATE : NB_OP_DESTROY, ifname);
+ bool passive_default =
+ yang_dnode_get_bool(vty->candidate_config->dnode, "%s%s",
+ VTY_CURR_XPATH, "/passive-default");
+
+ if (passive_default) {
+ nb_cli_enqueue_change(vty, "./non-passive-interface",
+ no ? NB_OP_CREATE : NB_OP_DESTROY,
+ ifname);
+ } else {
+ nb_cli_enqueue_change(vty, "./passive-interface",
+ no ? NB_OP_DESTROY : NB_OP_CREATE,
+ ifname);
+ }
return nb_cli_apply_changes(vty, NULL);
}
diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c
index 9575f6b8a8..8bad6b8b14 100644
--- a/ripd/rip_interface.c
+++ b/ripd/rip_interface.c
@@ -510,11 +510,9 @@ static void rip_interface_reset(struct rip_interface *ri)
ri->ri_receive = yang_get_default_enum("%s/version-receive", RIP_IFACE);
ri->v2_broadcast = yang_get_default_bool("%s/v2-broadcast", RIP_IFACE);
- if (ri->auth_str)
- XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
+ XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
- if (ri->key_chain)
- XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
+ XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
ri->list[RIP_FILTER_IN] = NULL;
ri->list[RIP_FILTER_OUT] = NULL;
diff --git a/ripd/rip_northbound.c b/ripd/rip_northbound.c
index 1e5f86eff8..f3b5dc2dc3 100644
--- a/ripd/rip_northbound.c
+++ b/ripd/rip_northbound.c
@@ -937,8 +937,7 @@ lib_interface_rip_authentication_password_modify(enum nb_event event,
ifp = yang_dnode_get_entry(dnode, true);
ri = ifp->info;
- if (ri->auth_str)
- XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
+ XFREE(MTYPE_RIP_INTERFACE_STRING, ri->auth_str);
ri->auth_str = XSTRDUP(MTYPE_RIP_INTERFACE_STRING,
yang_dnode_get_string(dnode, NULL));
@@ -978,8 +977,7 @@ lib_interface_rip_authentication_key_chain_modify(enum nb_event event,
ifp = yang_dnode_get_entry(dnode, true);
ri = ifp->info;
- if (ri->key_chain)
- XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
+ XFREE(MTYPE_RIP_INTERFACE_STRING, ri->key_chain);
ri->key_chain = XSTRDUP(MTYPE_RIP_INTERFACE_STRING,
yang_dnode_get_string(dnode, NULL));
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 38b4aed5bc..d2fc9eb303 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -71,6 +71,9 @@ static int rip_update_jitter(unsigned long);
static void rip_distribute_update(struct distribute_ctx *ctx,
struct distribute *dist);
+static void rip_if_rmap_update(struct if_rmap_ctx *ctx,
+ struct if_rmap *if_rmap);
+
/* RIP output routes type. */
enum { rip_all_route, rip_changed_route };
@@ -851,7 +854,7 @@ static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from,
MD5_CTX ctx;
uint8_t digest[RIP_AUTH_MD5_SIZE];
uint16_t packet_len;
- char auth_str[RIP_AUTH_MD5_SIZE];
+ char auth_str[RIP_AUTH_MD5_SIZE] = {};
if (IS_RIP_DEBUG_EVENT)
zlog_debug("RIPv2 MD5 authentication from %s",
@@ -895,8 +898,6 @@ static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from,
/* retrieve authentication data */
md5data = (struct rip_md5_data *)(((uint8_t *)packet) + packet_len);
- memset(auth_str, 0, RIP_AUTH_MD5_SIZE);
-
if (ri->key_chain) {
keychain = keychain_lookup(ri->key_chain);
if (keychain == NULL)
@@ -906,9 +907,9 @@ static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from,
if (key == NULL || key->string == NULL)
return 0;
- strncpy(auth_str, key->string, RIP_AUTH_MD5_SIZE);
+ strlcpy(auth_str, key->string, sizeof(auth_str));
} else if (ri->auth_str)
- strncpy(auth_str, ri->auth_str, RIP_AUTH_MD5_SIZE);
+ strlcpy(auth_str, ri->auth_str, sizeof(auth_str));
if (auth_str[0] == 0)
return 0;
@@ -941,9 +942,9 @@ static void rip_auth_prepare_str_send(struct rip_interface *ri, struct key *key,
memset(auth_str, 0, len);
if (key && key->string)
- strncpy(auth_str, key->string, len);
+ strlcpy(auth_str, key->string, len);
else if (ri->auth_str)
- strncpy(auth_str, ri->auth_str, len);
+ strlcpy(auth_str, ri->auth_str, len);
return;
}
@@ -1389,13 +1390,12 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to,
if (IS_RIP_DEBUG_PACKET) {
#define ADDRESS_SIZE 20
char dst[ADDRESS_SIZE];
- dst[ADDRESS_SIZE - 1] = '\0';
if (to) {
- strncpy(dst, inet_ntoa(to->sin_addr), ADDRESS_SIZE - 1);
+ strlcpy(dst, inet_ntoa(to->sin_addr), sizeof(dst));
} else {
sin.sin_addr.s_addr = htonl(INADDR_RIP_GROUP);
- strncpy(dst, inet_ntoa(sin.sin_addr), ADDRESS_SIZE - 1);
+ strlcpy(dst, inet_ntoa(sin.sin_addr), sizeof(dst));
}
#undef ADDRESS_SIZE
zlog_debug("rip_send_packet %s > %s (%s)",
@@ -2100,8 +2100,7 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to,
key = key_lookup_for_send(keychain);
}
/* to be passed to auth functions later */
- rip_auth_prepare_str_send(ri, key, auth_str,
- RIP_AUTH_SIMPLE_SIZE);
+ rip_auth_prepare_str_send(ri, key, auth_str, sizeof(auth_str));
if (strlen(auth_str) == 0)
return;
}
@@ -2712,6 +2711,12 @@ int rip_create(int socket)
rip_distribute_update);
distribute_list_delete_hook(rip->distribute_ctx,
rip_distribute_update);
+
+ /* if rmap install. */
+ rip->if_rmap_ctx = if_rmap_ctx_create(VRF_DEFAULT_NAME);
+ if_rmap_hook_add(rip->if_rmap_ctx, rip_if_rmap_update);
+ if_rmap_hook_delete(rip->if_rmap_ctx, rip_if_rmap_update);
+
return 0;
}
@@ -3228,7 +3233,7 @@ static int config_write_rip(struct vty *vty)
rip->distribute_ctx);
/* Interface routemap configuration */
- write += config_write_if_rmap(vty);
+ write += config_write_if_rmap(vty, rip->if_rmap_ctx);
}
return write;
}
@@ -3381,25 +3386,33 @@ void rip_clean(void)
route_table_finish(rip->neighbor);
distribute_list_delete(&rip->distribute_ctx);
+
+ if_rmap_ctx_delete(rip->if_rmap_ctx);
+
XFREE(MTYPE_RIP, rip);
rip = NULL;
}
-
rip_clean_network();
rip_passive_nondefault_clean();
rip_offset_clean();
rip_interfaces_clean();
rip_distance_reset();
rip_redistribute_clean();
+ if_rmap_terminate();
}
-static void rip_if_rmap_update(struct if_rmap *if_rmap)
+static void rip_if_rmap_update(struct if_rmap_ctx *ctx,
+ struct if_rmap *if_rmap)
{
- struct interface *ifp;
+ struct interface *ifp = NULL;
struct rip_interface *ri;
struct route_map *rmap;
+ struct vrf *vrf = NULL;
- ifp = if_lookup_by_name(if_rmap->ifname, VRF_DEFAULT);
+ if (ctx->name)
+ vrf = vrf_lookup_by_name(ctx->name);
+ if (vrf)
+ ifp = if_lookup_by_name(if_rmap->ifname, vrf->vrf_id);
if (ifp == NULL)
return;
@@ -3426,10 +3439,18 @@ static void rip_if_rmap_update(struct if_rmap *if_rmap)
void rip_if_rmap_update_interface(struct interface *ifp)
{
struct if_rmap *if_rmap;
+ struct if_rmap_ctx *ctx;
- if_rmap = if_rmap_lookup(ifp->name);
+ if (!rip)
+ return;
+ if (ifp->vrf_id != VRF_DEFAULT)
+ return;
+ ctx = rip->if_rmap_ctx;
+ if (!ctx)
+ return;
+ if_rmap = if_rmap_lookup(ctx, ifp->name);
if (if_rmap)
- rip_if_rmap_update(if_rmap);
+ rip_if_rmap_update(ctx, if_rmap);
}
static void rip_routemap_update_redistribute(void)
@@ -3497,8 +3518,6 @@ void rip_init(void)
route_map_delete_hook(rip_routemap_update);
if_rmap_init(RIP_NODE);
- if_rmap_hook_add(rip_if_rmap_update);
- if_rmap_hook_delete(rip_if_rmap_update);
/* Distance control. */
rip_distance_table = route_table_init();
diff --git a/ripd/ripd.h b/ripd/ripd.h
index 7b8fe3a906..383df3707b 100644
--- a/ripd/ripd.h
+++ b/ripd/ripd.h
@@ -154,6 +154,9 @@ struct rip {
/* For distribute-list container */
struct distribute_ctx *distribute_ctx;
+
+ /* For if_rmap container */
+ struct if_rmap_ctx *if_rmap_ctx;
};
/* RIP routing table entry which belong to rip_packet. */
@@ -419,8 +422,7 @@ extern void rip_zebra_ipv4_add(struct route_node *);
extern void rip_zebra_ipv4_delete(struct route_node *);
extern void rip_interface_multicast_set(int, struct connected *);
extern void rip_distribute_update_interface(struct interface *);
-extern void rip_if_rmap_update_interface(struct interface *);
-
+extern void rip_if_rmap_update_interface(struct interface *ifp);
extern int rip_show_network_config(struct vty *);
extern void rip_show_redistribute_config(struct vty *);
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index 70655beff1..9faebcf0d0 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -60,6 +60,9 @@ void ripng_output_process(struct interface *, struct sockaddr_in6 *, int);
int ripng_triggered_update(struct thread *);
+static void ripng_if_rmap_update(struct if_rmap_ctx *ctx,
+ struct if_rmap *if_rmap);
+
/* RIPng next hop specification. */
struct ripng_nexthop {
enum ripng_nexthop_type {
@@ -1816,6 +1819,12 @@ int ripng_create(int socket)
ripng_distribute_update);
distribute_list_delete_hook(ripng->distribute_ctx,
ripng_distribute_update);
+
+ /* if rmap install. */
+ ripng->if_rmap_ctx = if_rmap_ctx_create(VRF_DEFAULT_NAME);
+ if_rmap_hook_add(ripng->if_rmap_ctx, ripng_if_rmap_update);
+ if_rmap_hook_delete(ripng->if_rmap_ctx, ripng_if_rmap_update);
+
/* Make socket. */
ripng->sock = socket;
@@ -2303,7 +2312,7 @@ static int ripng_config_write(struct vty *vty)
config_write_distribute(vty,
ripng->distribute_ctx);
- config_write_if_rmap(vty);
+ config_write_if_rmap(vty, ripng->if_rmap_ctx);
write = 1;
}
@@ -2474,15 +2483,21 @@ void ripng_clean(void)
ripng_offset_clean();
ripng_interface_clean();
ripng_redistribute_clean();
+ if_rmap_terminate();
}
-static void ripng_if_rmap_update(struct if_rmap *if_rmap)
+static void ripng_if_rmap_update(struct if_rmap_ctx *ctx,
+ struct if_rmap *if_rmap)
{
- struct interface *ifp;
+ struct interface *ifp = NULL;
struct ripng_interface *ri;
struct route_map *rmap;
+ struct vrf *vrf = NULL;
- ifp = if_lookup_by_name(if_rmap->ifname, VRF_DEFAULT);
+ if (ctx->name)
+ vrf = vrf_lookup_by_name(ctx->name);
+ if (vrf)
+ ifp = if_lookup_by_name(if_rmap->ifname, vrf->vrf_id);
if (ifp == NULL)
return;
@@ -2510,10 +2525,18 @@ static void ripng_if_rmap_update(struct if_rmap *if_rmap)
void ripng_if_rmap_update_interface(struct interface *ifp)
{
struct if_rmap *if_rmap;
+ struct if_rmap_ctx *ctx;
- if_rmap = if_rmap_lookup(ifp->name);
+ if (ifp->vrf_id != VRF_DEFAULT)
+ return;
+ if (!ripng)
+ return;
+ ctx = ripng->if_rmap_ctx;
+ if (!ctx)
+ return;
+ if_rmap = if_rmap_lookup(ctx, ifp->name);
if (if_rmap)
- ripng_if_rmap_update(if_rmap);
+ ripng_if_rmap_update(ctx, if_rmap);
}
static void ripng_routemap_update_redistribute(void)
@@ -2590,6 +2613,4 @@ void ripng_init(void)
route_map_delete_hook(ripng_routemap_update);
if_rmap_init(RIPNG_NODE);
- if_rmap_hook_add(ripng_if_rmap_update);
- if_rmap_hook_delete(ripng_if_rmap_update);
}
diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h
index 1db7a83b11..3f0ef13a05 100644
--- a/ripngd/ripngd.h
+++ b/ripngd/ripngd.h
@@ -132,6 +132,9 @@ struct ripng {
/* For distribute-list container */
struct distribute_ctx *distribute_ctx;
+
+ /* For if_rmap container */
+ struct if_rmap_ctx *if_rmap_ctx;
};
/* Routing table entry. */
diff --git a/sharpd/sharp_globals.h b/sharpd/sharp_globals.h
index 065fb092d4..4e5c933667 100644
--- a/sharpd/sharp_globals.h
+++ b/sharpd/sharp_globals.h
@@ -38,6 +38,7 @@ struct sharp_routes {
int32_t repeat;
uint8_t inst;
+ vrf_id_t vrf_id;
struct timeval t_start;
struct timeval t_end;
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 9018cfb359..fbcbbe3fdc 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -39,17 +39,28 @@
#endif
DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
- "sharp watch <nexthop$n|import$import> X:X::X:X$nhop [connected$connected]",
+ "sharp watch [vrf NAME$name] <nexthop$n|import$import> X:X::X:X$nhop [connected$connected]",
"Sharp routing Protocol\n"
"Watch for changes\n"
+ "The vrf we would like to watch if non-default\n"
+ "The NAME of the vrf\n"
"Watch for nexthop changes\n"
"Watch for import check changes\n"
"The v6 nexthop to signal for watching\n"
"Should the route be connected\n")
{
+ struct vrf *vrf;
struct prefix p;
bool type_import;
+ if (!name)
+ name = VRF_DEFAULT_NAME;
+ vrf = vrf_lookup_by_name(name);
+ if (!vrf) {
+ vty_out(vty, "The vrf NAME specified: %s does not exist\n",
+ name);
+ return CMD_WARNING;
+ }
if (n)
type_import = false;
@@ -63,23 +74,36 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
p.family = AF_INET6;
sharp_nh_tracker_get(&p);
- sharp_zebra_nexthop_watch(&p, type_import, true, !!connected);
+ sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
+ true, !!connected);
return CMD_SUCCESS;
}
DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
- "sharp watch <nexthop$n|import$import> A.B.C.D$nhop [connected$connected]",
+ "sharp watch [vrf NAME$name] <nexthop$n|import$import> A.B.C.D$nhop [connected$connected]",
"Sharp routing Protocol\n"
"Watch for changes\n"
+ "The vrf we would like to watch if non-default\n"
+ "The NAME of the vrf\n"
"Watch for nexthop changes\n"
"Watch for import check changes\n"
"The v4 nexthop to signal for watching\n"
"Should the route be connected\n")
{
+ struct vrf *vrf;
struct prefix p;
bool type_import;
+ if (!name)
+ name = VRF_DEFAULT_NAME;
+ vrf = vrf_lookup_by_name(name);
+ if (!vrf) {
+ vty_out(vty, "The vrf NAME specified: %s does not exist\n",
+ name);
+ return CMD_WARNING;
+ }
+
memset(&p, 0, sizeof(p));
if (n)
@@ -92,7 +116,8 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
p.family = AF_INET;
sharp_nh_tracker_get(&p);
- sharp_zebra_nexthop_watch(&p, type_import, true, !!connected);
+ sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
+ true, !!connected);
return CMD_SUCCESS;
}
@@ -132,10 +157,12 @@ DEFPY (install_routes_data_dump,
DEFPY (install_routes,
install_routes_cmd,
- "sharp install routes <A.B.C.D$start4|X:X::X:X$start6> <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]",
+ "sharp install routes [vrf NAME$name] <A.B.C.D$start4|X:X::X:X$start6> <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]",
"Sharp routing Protocol\n"
"install some routes\n"
"Routes to install\n"
+ "The vrf we would like to install into if non-default\n"
+ "The NAME of the vrf\n"
"v4 Address to start /32 generation at\n"
"v6 Address to start /32 generation at\n"
"Nexthop to use(Can be an IPv4 or IPv6 address)\n"
@@ -149,6 +176,7 @@ DEFPY (install_routes,
"Should we repeat this command\n"
"How many times to repeat this command\n")
{
+ struct vrf *vrf;
struct prefix prefix;
uint32_t rts;
@@ -176,6 +204,16 @@ DEFPY (install_routes,
}
sg.r.orig_prefix = prefix;
+ if (!name)
+ name = VRF_DEFAULT_NAME;
+
+ vrf = vrf_lookup_by_name(name);
+ if (!vrf) {
+ vty_out(vty, "The vrf NAME specified: %s does not exist\n",
+ name);
+ return CMD_WARNING;
+ }
+
if (nexthop_group) {
struct nexthop_group_cmd *nhgc = nhgc_find(nexthop_group);
if (!nhgc) {
@@ -195,12 +233,15 @@ DEFPY (install_routes,
sg.r.nhop.type = NEXTHOP_TYPE_IPV6;
}
+ sg.r.nhop.vrf_id = vrf->vrf_id;
sg.r.nhop_group.nexthop = &sg.r.nhop;
}
sg.r.inst = instance;
+ sg.r.vrf_id = vrf->vrf_id;
rts = routes;
- sharp_install_routes_helper(&prefix, sg.r.inst, &sg.r.nhop_group, rts);
+ sharp_install_routes_helper(&prefix, sg.r.vrf_id,
+ sg.r.inst, &sg.r.nhop_group, rts);
return CMD_SUCCESS;
}
@@ -237,16 +278,19 @@ DEFPY(vrf_label, vrf_label_cmd,
DEFPY (remove_routes,
remove_routes_cmd,
- "sharp remove routes <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]",
+ "sharp remove routes [vrf NAME$name] <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]",
"Sharp Routing Protocol\n"
"Remove some routes\n"
"Routes to remove\n"
+ "The vrf we would like to remove from if non-default\n"
+ "The NAME of the vrf\n"
"v4 Starting spot\n"
"v6 Starting spot\n"
"Routes to uninstall\n"
"instance to use\n"
"Value of instance\n")
{
+ struct vrf *vrf;
struct prefix prefix;
sg.r.total_routes = routes;
@@ -265,9 +309,18 @@ DEFPY (remove_routes,
prefix.u.prefix6 = start6;
}
+ vrf = vrf_lookup_by_name(name ? name : VRF_DEFAULT_NAME);
+ if (!vrf) {
+ vty_out(vty, "The vrf NAME specified: %s does not exist\n",
+ name ? name : VRF_DEFAULT_NAME);
+ return CMD_WARNING;
+ }
+
sg.r.inst = instance;
+ sg.r.vrf_id = vrf->vrf_id;
rts = routes;
- sharp_remove_routes_helper(&prefix, sg.r.inst, rts);
+ sharp_remove_routes_helper(&prefix, sg.r.vrf_id,
+ sg.r.inst, rts);
return CMD_SUCCESS;
}
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index 4682dbc73a..f1e83628c2 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -131,8 +131,8 @@ static int interface_state_down(int command, struct zclient *zclient,
return 0;
}
-void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
- struct nexthop_group *nhg,
+void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
+ uint8_t instance, struct nexthop_group *nhg,
uint32_t routes)
{
uint32_t temp, i;
@@ -148,7 +148,7 @@ void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
monotime(&sg.r.t_start);
for (i = 0; i < routes; i++) {
- route_add(p, (uint8_t)instance, nhg);
+ route_add(p, vrf_id, (uint8_t)instance, nhg);
if (v4)
p->u.prefix4.s_addr = htonl(++temp);
else
@@ -156,8 +156,8 @@ void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
}
}
-void sharp_remove_routes_helper(struct prefix *p, uint8_t instance,
- uint32_t routes)
+void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id,
+ uint8_t instance, uint32_t routes)
{
uint32_t temp, i;
bool v4 = false;
@@ -172,7 +172,7 @@ void sharp_remove_routes_helper(struct prefix *p, uint8_t instance,
monotime(&sg.r.t_start);
for (i = 0; i < routes; i++) {
- route_delete(p, (uint8_t)instance);
+ route_delete(p, vrf_id, (uint8_t)instance);
if (v4)
p->u.prefix4.s_addr = htonl(++temp);
else
@@ -190,12 +190,14 @@ static void handle_repeated(bool installed)
if (installed) {
sg.r.removed_routes = 0;
- sharp_remove_routes_helper(&p, sg.r.inst, sg.r.total_routes);
+ sharp_remove_routes_helper(&p, sg.r.vrf_id,
+ sg.r.inst, sg.r.total_routes);
}
if (installed) {
sg.r.installed_routes = 0;
- sharp_install_routes_helper(&p, sg.r.inst, &sg.r.nhop_group,
+ sharp_install_routes_helper(&p, sg.r.vrf_id, sg.r.inst,
+ &sg.r.nhop_group,
sg.r.total_routes);
}
}
@@ -255,7 +257,8 @@ void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label)
zclient_send_vrf_label(zclient, vrf_id, afi, label, ZEBRA_LSP_SHARP);
}
-void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *nhg)
+void route_add(struct prefix *p, vrf_id_t vrf_id,
+ uint8_t instance, struct nexthop_group *nhg)
{
struct zapi_route api;
struct zapi_nexthop *api_nh;
@@ -263,7 +266,7 @@ void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *nhg)
int i = 0;
memset(&api, 0, sizeof(api));
- api.vrf_id = VRF_DEFAULT;
+ api.vrf_id = vrf_id;
api.type = ZEBRA_ROUTE_SHARP;
api.instance = instance;
api.safi = SAFI_UNICAST;
@@ -274,7 +277,7 @@ void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *nhg)
for (ALL_NEXTHOPS_PTR(nhg, nh)) {
api_nh = &api.nexthops[i];
- api_nh->vrf_id = VRF_DEFAULT;
+ api_nh->vrf_id = nh->vrf_id;
api_nh->type = nh->type;
switch (nh->type) {
case NEXTHOP_TYPE_IPV4:
@@ -305,12 +308,12 @@ void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *nhg)
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
}
-void route_delete(struct prefix *p, uint8_t instance)
+void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance)
{
struct zapi_route api;
memset(&api, 0, sizeof(api));
- api.vrf_id = VRF_DEFAULT;
+ api.vrf_id = vrf_id;
api.type = ZEBRA_ROUTE_SHARP;
api.safi = SAFI_UNICAST;
api.instance = instance;
@@ -320,7 +323,7 @@ void route_delete(struct prefix *p, uint8_t instance)
return;
}
-void sharp_zebra_nexthop_watch(struct prefix *p, bool import,
+void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import,
bool watch, bool connected)
{
int command;
@@ -337,7 +340,7 @@ void sharp_zebra_nexthop_watch(struct prefix *p, bool import,
command = ZEBRA_IMPORT_ROUTE_UNREGISTER;
}
- if (zclient_send_rnh(zclient, command, p, connected, VRF_DEFAULT) < 0)
+ if (zclient_send_rnh(zclient, command, p, connected, vrf_id) < 0)
zlog_warn("%s: Failure to send nexthop to zebra",
__PRETTY_FUNCTION__);
}
diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h
index b219022f02..57ffcc7690 100644
--- a/sharpd/sharp_zebra.h
+++ b/sharpd/sharp_zebra.h
@@ -25,15 +25,16 @@
extern void sharp_zebra_init(void);
extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label);
-extern void route_add(struct prefix *p, uint8_t instance,
+extern void route_add(struct prefix *p, vrf_id_t, uint8_t instance,
struct nexthop_group *nhg);
-extern void route_delete(struct prefix *p, uint8_t instance);
-extern void sharp_zebra_nexthop_watch(struct prefix *p, bool import,
- bool watch, bool connected);
+extern void route_delete(struct prefix *p, vrf_id_t vrf_id, uint8_t instance);
+extern void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id,
+ bool import, bool watch, bool connected);
-extern void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
- struct nexthop_group *nhg,
- uint32_t routes);
-extern void sharp_remove_routes_helper(struct prefix *p, uint8_t instance,
- uint32_t routes);
+extern void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id,
+ uint8_t instance,
+ struct nexthop_group *nhg,
+ uint32_t routes);
+extern void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id,
+ uint8_t instance, uint32_t routes);
#endif
diff --git a/staticd/static_vty.c b/staticd/static_vty.c
index f09c304359..3a9e4e8fa4 100644
--- a/staticd/static_vty.c
+++ b/staticd/static_vty.c
@@ -104,30 +104,18 @@ static int static_list_compare_helper(const char *s1, const char *s2)
static void static_list_delete(struct static_hold_route *shr)
{
- if (shr->vrf_name)
- XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name);
- if (shr->nhvrf_name)
- XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name);
- if (shr->dest_str)
- XFREE(MTYPE_STATIC_ROUTE, shr->dest_str);
- if (shr->mask_str)
- XFREE(MTYPE_STATIC_ROUTE, shr->mask_str);
- if (shr->src_str)
- XFREE(MTYPE_STATIC_ROUTE, shr->src_str);
- if (shr->gate_str)
- XFREE(MTYPE_STATIC_ROUTE, shr->gate_str);
- if (shr->ifname)
- XFREE(MTYPE_STATIC_ROUTE, shr->ifname);
- if (shr->flag_str)
- XFREE(MTYPE_STATIC_ROUTE, shr->flag_str);
- if (shr->tag_str)
- XFREE(MTYPE_STATIC_ROUTE, shr->tag_str);
- if (shr->distance_str)
- XFREE(MTYPE_STATIC_ROUTE, shr->distance_str);
- if (shr->label_str)
- XFREE(MTYPE_STATIC_ROUTE, shr->label_str);
- if (shr->table_str)
- XFREE(MTYPE_STATIC_ROUTE, shr->table_str);
+ XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name);
+ XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name);
+ XFREE(MTYPE_STATIC_ROUTE, shr->dest_str);
+ XFREE(MTYPE_STATIC_ROUTE, shr->mask_str);
+ XFREE(MTYPE_STATIC_ROUTE, shr->src_str);
+ XFREE(MTYPE_STATIC_ROUTE, shr->gate_str);
+ XFREE(MTYPE_STATIC_ROUTE, shr->ifname);
+ XFREE(MTYPE_STATIC_ROUTE, shr->flag_str);
+ XFREE(MTYPE_STATIC_ROUTE, shr->tag_str);
+ XFREE(MTYPE_STATIC_ROUTE, shr->distance_str);
+ XFREE(MTYPE_STATIC_ROUTE, shr->label_str);
+ XFREE(MTYPE_STATIC_ROUTE, shr->table_str);
XFREE(MTYPE_STATIC_ROUTE, shr);
}
diff --git a/tests/bgpd/test_bgp_table.c b/tests/bgpd/test_bgp_table.c
index 73243dcacf..7b38df5f66 100644
--- a/tests/bgpd/test_bgp_table.c
+++ b/tests/bgpd/test_bgp_table.c
@@ -158,7 +158,7 @@ static void test_range_lookup(void)
"1.16.160.0/19", "1.16.32.0/20",
"1.16.32.0/21", "16.0.0.0/16"};
- int num_prefixes = sizeof(prefixes) / sizeof(prefixes[0]);
+ int num_prefixes = array_size(prefixes);
for (int i = 0; i < num_prefixes; i++)
add_node(table, prefixes[i]);
diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c
index 04fbda42eb..0ecd0fdfec 100644
--- a/tests/bgpd/test_mpath.c
+++ b/tests/bgpd/test_mpath.c
@@ -205,7 +205,7 @@ struct peer test_mp_list_peer[] = {
{.local_as = 1, .as = 2}, {.local_as = 1, .as = 2},
{.local_as = 1, .as = 2},
};
-int test_mp_list_peer_count = sizeof(test_mp_list_peer) / sizeof(struct peer);
+int test_mp_list_peer_count = array_size(test_mp_list_peer);
struct attr test_mp_list_attr[4];
struct bgp_path_info test_mp_list_info[] = {
{.peer = &test_mp_list_peer[0], .attr = &test_mp_list_attr[0]},
@@ -214,8 +214,7 @@ struct bgp_path_info test_mp_list_info[] = {
{.peer = &test_mp_list_peer[3], .attr = &test_mp_list_attr[2]},
{.peer = &test_mp_list_peer[4], .attr = &test_mp_list_attr[3]},
};
-int test_mp_list_info_count =
- sizeof(test_mp_list_info) / sizeof(struct bgp_path_info);
+int test_mp_list_info_count = array_size(test_mp_list_info);
static int setup_bgp_mp_list(testcase_t *t)
{
@@ -370,7 +369,7 @@ testcase_t *all_tests[] = {
&test_bgp_path_info_mpath_update,
};
-int all_tests_count = (sizeof(all_tests) / sizeof(testcase_t *));
+int all_tests_count = array_size(all_tests);
/*=========================================================
* Test Driver Functions
diff --git a/tests/lib/test_privs.c b/tests/lib/test_privs.c
index e203da8f6e..fc3d908661 100644
--- a/tests/lib/test_privs.c
+++ b/tests/lib/test_privs.c
@@ -37,7 +37,7 @@ struct zebra_privs_t test_privs = {
.vty_group = VTY_GROUP,
#endif
.caps_p = _caps_p,
- .cap_num_p = sizeof(_caps_p) / sizeof(_caps_p[0]),
+ .cap_num_p = array_size(_caps_p),
.cap_num_i = 0};
struct option longopts[] = {{"help", no_argument, NULL, 'h'},
diff --git a/tests/lib/test_srcdest_table.c b/tests/lib/test_srcdest_table.c
index 5c0e171778..19a40b2184 100644
--- a/tests/lib/test_srcdest_table.c
+++ b/tests/lib/test_srcdest_table.c
@@ -105,7 +105,7 @@ static unsigned int log_key(void *data)
static bool log_cmp(const void *a, const void *b)
{
if (a == NULL || b == NULL)
- return 0;
+ return false;
return !memcmp(a, b, 2 * sizeof(struct prefix));
}
diff --git a/tests/lib/test_table.c b/tests/lib/test_table.c
index 2b65040627..90d6c76bf1 100644
--- a/tests/lib/test_table.c
+++ b/tests/lib/test_table.c
@@ -478,7 +478,7 @@ static void test_iter_pause(void)
const char *prefixes[] = {"1.0.1.0/24", "1.0.1.0/25", "1.0.1.128/25",
"1.0.2.0/24", "2.0.0.0/8"};
- num_prefixes = sizeof(prefixes) / sizeof(prefixes[0]);
+ num_prefixes = array_size(prefixes);
printf("\n\nTesting that route_table_iter_pause() works as expected\n");
table = route_table_init();
diff --git a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref
index 6777cd9fc3..85388c738d 100644
--- a/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref
+++ b/tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_summary.ref
@@ -1,7 +1,7 @@
BGP router identifier 192.168.0.1, local AS number 100 vrf-id 0
BGP table version 1
RIB entries 1, using XXXX bytes of memory
-Peers 4, using XXXX KiB of memory
+Peers 2, using XXXX KiB of memory
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
fc00:0:0:8::1000 4 100 0 0 0 0 0 never Active
diff --git a/tests/topotests/bfd-topo2/__init__.py b/tests/topotests/bfd-topo2/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bfd-topo2/__init__.py
diff --git a/tests/topotests/bfd-topo2/r1/bfdd.conf b/tests/topotests/bfd-topo2/r1/bfdd.conf
new file mode 100644
index 0000000000..5c2571bdbd
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r1/bfdd.conf
@@ -0,0 +1,5 @@
+bfd
+ peer 2001:db8:4::1 multihop local-address 2001:db8:1::1
+ no shutdown
+ !
+!
diff --git a/tests/topotests/bfd-topo2/r1/bgpd.conf b/tests/topotests/bfd-topo2/r1/bgpd.conf
new file mode 100644
index 0000000000..1623b4578b
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r1/bgpd.conf
@@ -0,0 +1,13 @@
+router bgp 101
+ bgp router-id 10.254.254.1
+ neighbor r2g peer-group
+ neighbor r2g remote-as external
+ neighbor r2g bfd
+ neighbor r1-eth0 interface peer-group r2g
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+ address-family ipv6 unicast
+ neighbor r2g activate
+ exit-address-family
+!
diff --git a/tests/topotests/bfd-topo2/r1/ipv4_routes.json b/tests/topotests/bfd-topo2/r1/ipv4_routes.json
new file mode 100644
index 0000000000..8a2ec25baa
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r1/ipv4_routes.json
@@ -0,0 +1,68 @@
+{
+ "10.0.3.0/24": [
+ {
+ "distance": 20,
+ "protocol": "bgp",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.0.3.0/24",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r1-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ }
+ ],
+ "10.254.254.2/32": [
+ {
+ "distance": 20,
+ "protocol": "bgp",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.2/32",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r1-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ }
+ ],
+ "10.254.254.1/32": [
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.1/32",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "lo",
+ "interfaceIndex": 1,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r1/ipv6_routes.json b/tests/topotests/bfd-topo2/r1/ipv6_routes.json
new file mode 100644
index 0000000000..618853bd42
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r1/ipv6_routes.json
@@ -0,0 +1,63 @@
+{
+ "2001:db8:4::/64": [
+ {
+ "distance": 20,
+ "protocol": "bgp",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "2001:db8:4::/64",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r1-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ }
+ ],
+ "2001:db8:1::/64": [
+ {
+ "distance": 20,
+ "protocol": "bgp",
+ "internalFlags": 0,
+ "metric": 0,
+ "internalStatus": 2,
+ "prefix": "2001:db8:1::/64",
+ "nexthops": [
+ {
+ "interfaceName": "r1-eth0",
+ "interfaceIndex": 2,
+ "flags": 1,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ },
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "2001:db8:1::/64",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r1-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r1/peers.json b/tests/topotests/bfd-topo2/r1/peers.json
new file mode 100644
index 0000000000..b14351cd81
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r1/peers.json
@@ -0,0 +1,29 @@
+[
+ {
+ "multihop":true,
+ "peer":"2001:db8:4::1",
+ "local":"2001:db8:1::1",
+ "status":"up",
+ "diagnostic":"ok",
+ "remote-diagnostic":"ok",
+ "receive-interval":300,
+ "transmit-interval":300,
+ "echo-interval":0,
+ "remote-receive-interval":300,
+ "remote-transmit-interval":300,
+ "remote-echo-interval":50
+ },
+ {
+ "multihop":false,
+ "interface":"r1-eth0",
+ "status":"up",
+ "diagnostic":"ok",
+ "remote-diagnostic":"ok",
+ "receive-interval":300,
+ "transmit-interval":300,
+ "echo-interval":0,
+ "remote-receive-interval":300,
+ "remote-transmit-interval":300,
+ "remote-echo-interval":50
+ }
+]
diff --git a/tests/topotests/bfd-topo2/r1/zebra.conf b/tests/topotests/bfd-topo2/r1/zebra.conf
new file mode 100644
index 0000000000..7fe5eb218f
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r1/zebra.conf
@@ -0,0 +1,6 @@
+interface lo
+ ip address 10.254.254.1/32
+!
+interface r1-eth0
+ ipv6 address 2001:db8:1::1/64
+!
diff --git a/tests/topotests/bfd-topo2/r2/bgpd.conf b/tests/topotests/bfd-topo2/r2/bgpd.conf
new file mode 100644
index 0000000000..bf42d21812
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/bgpd.conf
@@ -0,0 +1,16 @@
+router bgp 102
+ bgp router-id 10.254.254.2
+ neighbor r2g peer-group
+ neighbor r2g remote-as external
+ neighbor r2g bfd
+ neighbor r2-eth0 interface peer-group r2g
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+ !
+ address-family ipv6 unicast
+ redistribute connected
+ neighbor r2g activate
+ exit-address-family
+!
diff --git a/tests/topotests/bfd-topo2/r2/ipv4_routes.json b/tests/topotests/bfd-topo2/r2/ipv4_routes.json
new file mode 100644
index 0000000000..b9d8afb430
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/ipv4_routes.json
@@ -0,0 +1,108 @@
+{
+ "10.0.3.0/24": [
+ {
+ "distance": 110,
+ "protocol": "ospf",
+ "internalFlags": 0,
+ "metric": 10,
+ "internalStatus": 2,
+ "prefix": "10.0.3.0/24",
+ "nexthops": [
+ {
+ "active": true,
+ "directlyConnected": true,
+ "flags": 1,
+ "interfaceIndex": 3,
+ "interfaceName": "r2-eth1"
+ }
+ ]
+ },
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.0.3.0/24",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r2-eth1",
+ "interfaceIndex": 3,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ],
+ "10.254.254.3/32": [
+ {
+ "distance": 110,
+ "protocol": "ospf",
+ "internalFlags": 8,
+ "metric": 20,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.3/32",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r2-eth1",
+ "ip": "10.0.3.1",
+ "interfaceIndex": 3,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv4"
+ }
+ ]
+ }
+ ],
+ "10.254.254.2/32": [
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.2/32",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "lo",
+ "interfaceIndex": 1,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ],
+ "10.254.254.1/32": [
+ {
+ "distance": 20,
+ "protocol": "bgp",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.1/32",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r2-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r2/ipv6_routes.json b/tests/topotests/bfd-topo2/r2/ipv6_routes.json
new file mode 100644
index 0000000000..004e7588aa
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/ipv6_routes.json
@@ -0,0 +1,63 @@
+{
+ "2001:db8:4::/64": [
+ {
+ "distance": 110,
+ "protocol": "ospf6",
+ "internalFlags": 0,
+ "metric": 10,
+ "internalStatus": 2,
+ "prefix": "2001:db8:4::/64",
+ "nexthops": [
+ {
+ "active": true,
+ "directlyConnected": true,
+ "flags": 1,
+ "interfaceIndex": 4,
+ "interfaceName": "r2-eth2"
+ }
+ ]
+ },
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "2001:db8:4::/64",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r2-eth2",
+ "interfaceIndex": 4,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1::/64": [
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "2001:db8:1::/64",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r2-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r2/ospf6d.conf b/tests/topotests/bfd-topo2/r2/ospf6d.conf
new file mode 100644
index 0000000000..f1cdb50285
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/ospf6d.conf
@@ -0,0 +1,9 @@
+interface r2-eth2
+ ipv6 ospf6 bfd
+!
+router ospf6
+ ospf6 router-id 10.254.254.2
+ redistribute connected
+ redistribute bgp
+ interface r2-eth2 area 0.0.0.1
+!
diff --git a/tests/topotests/bfd-topo2/r2/ospfd.conf b/tests/topotests/bfd-topo2/r2/ospfd.conf
new file mode 100644
index 0000000000..8e0c45980d
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/ospfd.conf
@@ -0,0 +1,9 @@
+interface r2-eth1
+ ip ospf area 0.0.0.1
+ ip ospf bfd
+!
+router ospf
+ ospf router-id 10.254.254.2
+ redistribute connected
+ redistribute bgp
+!
diff --git a/tests/topotests/bfd-topo2/r2/peers.json b/tests/topotests/bfd-topo2/r2/peers.json
new file mode 100644
index 0000000000..29075fcc80
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/peers.json
@@ -0,0 +1,42 @@
+[
+ {
+ "status": "up",
+ "transmit-interval": 300,
+ "remote-receive-interval": 300,
+ "echo-interval": 0,
+ "diagnostic": "ok",
+ "multihop": false,
+ "interface": "r2-eth0",
+ "remote-transmit-interval": 300,
+ "receive-interval": 300,
+ "remote-echo-interval": 50,
+ "remote-diagnostic": "ok"
+ },
+ {
+ "status": "up",
+ "transmit-interval": 300,
+ "remote-receive-interval": 300,
+ "echo-interval": 0,
+ "diagnostic": "ok",
+ "multihop": false,
+ "interface": "r2-eth2",
+ "remote-transmit-interval": 300,
+ "receive-interval": 300,
+ "remote-echo-interval": 50,
+ "remote-diagnostic": "ok"
+ },
+ {
+ "status": "up",
+ "transmit-interval": 300,
+ "remote-receive-interval": 300,
+ "echo-interval": 0,
+ "diagnostic": "ok",
+ "multihop": false,
+ "interface": "r2-eth1",
+ "remote-transmit-interval": 300,
+ "receive-interval": 300,
+ "remote-echo-interval": 50,
+ "remote-diagnostic": "ok",
+ "peer": "10.0.3.1"
+ }
+]
diff --git a/tests/topotests/bfd-topo2/r2/zebra.conf b/tests/topotests/bfd-topo2/r2/zebra.conf
new file mode 100644
index 0000000000..cccbf6574a
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r2/zebra.conf
@@ -0,0 +1,15 @@
+ip forwarding
+ipv6 forwarding
+!
+interface lo
+ ip address 10.254.254.2/32
+!
+interface r2-eth0
+ ipv6 address 2001:db8:1::2/64
+!
+interface r2-eth1
+ ip address 10.0.3.2/24
+!
+interface r2-eth2
+ ipv6 address 2001:db8:4::2/64
+!
diff --git a/tests/topotests/bfd-topo2/r3/ipv4_routes.json b/tests/topotests/bfd-topo2/r3/ipv4_routes.json
new file mode 100644
index 0000000000..14dfc692fe
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r3/ipv4_routes.json
@@ -0,0 +1,109 @@
+{
+ "10.0.3.0/24": [
+ {
+ "distance": 110,
+ "protocol": "ospf",
+ "internalFlags": 0,
+ "metric": 10,
+ "internalStatus": 0,
+ "prefix": "10.0.3.0/24",
+ "nexthops": [
+ {
+ "active": true,
+ "directlyConnected": true,
+ "flags": 1,
+ "interfaceIndex": 2,
+ "interfaceName": "r3-eth0"
+ }
+ ]
+ },
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.0.3.0/24",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r3-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ],
+ "10.254.254.3/32": [
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.3/32",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "lo",
+ "interfaceIndex": 1,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ],
+ "10.254.254.2/32": [
+ {
+ "distance": 110,
+ "protocol": "ospf",
+ "internalFlags": 8,
+ "metric": 20,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.2/32",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r3-eth0",
+ "ip": "10.0.3.2",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv4"
+ }
+ ]
+ }
+ ],
+ "10.254.254.1/32": [
+ {
+ "distance": 110,
+ "protocol": "ospf",
+ "internalFlags": 8,
+ "metric": 20,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.1/32",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r3-eth0",
+ "ip": "10.0.3.2",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv4"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r3/ipv6_routes.json b/tests/topotests/bfd-topo2/r3/ipv6_routes.json
new file mode 100644
index 0000000000..2c63c08510
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r3/ipv6_routes.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tests/topotests/bfd-topo2/r3/ospfd.conf b/tests/topotests/bfd-topo2/r3/ospfd.conf
new file mode 100644
index 0000000000..cf2a1bdf76
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r3/ospfd.conf
@@ -0,0 +1,8 @@
+interface r3-eth0
+ ip ospf area 0.0.0.1
+ ip ospf bfd
+!
+router ospf
+ ospf router-id 10.254.254.3
+ redistribute connected
+!
diff --git a/tests/topotests/bfd-topo2/r3/peers.json b/tests/topotests/bfd-topo2/r3/peers.json
new file mode 100644
index 0000000000..6698bff201
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r3/peers.json
@@ -0,0 +1,16 @@
+[
+ {
+ "status": "up",
+ "transmit-interval": 300,
+ "remote-receive-interval": 300,
+ "echo-interval": 0,
+ "diagnostic": "ok",
+ "multihop": false,
+ "interface": "r3-eth0",
+ "remote-transmit-interval": 300,
+ "receive-interval": 300,
+ "remote-echo-interval": 50,
+ "remote-diagnostic": "ok",
+ "peer": "10.0.3.2"
+ }
+]
diff --git a/tests/topotests/bfd-topo2/r3/zebra.conf b/tests/topotests/bfd-topo2/r3/zebra.conf
new file mode 100644
index 0000000000..96fd08c729
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r3/zebra.conf
@@ -0,0 +1,6 @@
+interface lo
+ ip address 10.254.254.3/32
+!
+interface r3-eth0
+ ip address 10.0.3.1/24
+!
diff --git a/tests/topotests/bfd-topo2/r4/bfdd.conf b/tests/topotests/bfd-topo2/r4/bfdd.conf
new file mode 100644
index 0000000000..fdb4412446
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r4/bfdd.conf
@@ -0,0 +1,5 @@
+bfd
+ peer 2001:db8:1::1 multihop local-address 2001:db8:4::1
+ no shutdown
+ !
+!
diff --git a/tests/topotests/bfd-topo2/r4/ipv4_routes.json b/tests/topotests/bfd-topo2/r4/ipv4_routes.json
new file mode 100644
index 0000000000..ae1e97b017
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r4/ipv4_routes.json
@@ -0,0 +1,24 @@
+{
+ "10.254.254.4/32": [
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "10.254.254.4/32",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "lo",
+ "interfaceIndex": 1,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r4/ipv6_routes.json b/tests/topotests/bfd-topo2/r4/ipv6_routes.json
new file mode 100644
index 0000000000..33608b45aa
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r4/ipv6_routes.json
@@ -0,0 +1,63 @@
+{
+ "2001:db8:4::/64": [
+ {
+ "distance": 110,
+ "protocol": "ospf6",
+ "internalFlags": 0,
+ "metric": 10,
+ "internalStatus": 2,
+ "prefix": "2001:db8:4::/64",
+ "nexthops": [
+ {
+ "active": true,
+ "directlyConnected": true,
+ "flags": 1,
+ "interfaceIndex": 2,
+ "interfaceName": "r4-eth0"
+ }
+ ]
+ },
+ {
+ "distance": 0,
+ "protocol": "connected",
+ "internalFlags": 8,
+ "metric": 0,
+ "selected": true,
+ "installed": true,
+ "prefix": "2001:db8:4::/64",
+ "internalStatus": 32,
+ "nexthops": [
+ {
+ "directlyConnected": true,
+ "interfaceName": "r4-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1::/64": [
+ {
+ "distance": 110,
+ "protocol": "ospf6",
+ "internalFlags": 8,
+ "metric": 10,
+ "selected": true,
+ "installed": true,
+ "prefix": "2001:db8:1::/64",
+ "internalStatus": 34,
+ "nexthops": [
+ {
+ "interfaceName": "r4-eth0",
+ "interfaceIndex": 2,
+ "fib": true,
+ "flags": 3,
+ "active": true,
+ "afi": "ipv6"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bfd-topo2/r4/ospf6d.conf b/tests/topotests/bfd-topo2/r4/ospf6d.conf
new file mode 100644
index 0000000000..756597d6f8
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r4/ospf6d.conf
@@ -0,0 +1,8 @@
+interface r4-eth0
+ ipv6 ospf6 bfd
+!
+router ospf6
+ ospf6 router-id 10.254.254.4
+ redistribute connected
+ interface r4-eth0 area 0.0.0.1
+!
diff --git a/tests/topotests/bfd-topo2/r4/peers.json b/tests/topotests/bfd-topo2/r4/peers.json
new file mode 100644
index 0000000000..83101eb47f
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r4/peers.json
@@ -0,0 +1,29 @@
+[
+ {
+ "multihop":true,
+ "peer":"2001:db8:1::1",
+ "local":"2001:db8:4::1",
+ "status":"up",
+ "diagnostic":"ok",
+ "remote-diagnostic":"ok",
+ "receive-interval":300,
+ "transmit-interval":300,
+ "echo-interval":0,
+ "remote-receive-interval":300,
+ "remote-transmit-interval":300,
+ "remote-echo-interval":50
+ },
+ {
+ "multihop":false,
+ "interface":"r4-eth0",
+ "status":"up",
+ "diagnostic":"ok",
+ "remote-diagnostic":"ok",
+ "receive-interval":300,
+ "transmit-interval":300,
+ "echo-interval":0,
+ "remote-receive-interval":300,
+ "remote-transmit-interval":300,
+ "remote-echo-interval":50
+ }
+]
diff --git a/tests/topotests/bfd-topo2/r4/zebra.conf b/tests/topotests/bfd-topo2/r4/zebra.conf
new file mode 100644
index 0000000000..e4f8fd8514
--- /dev/null
+++ b/tests/topotests/bfd-topo2/r4/zebra.conf
@@ -0,0 +1,6 @@
+interface lo
+ ip address 10.254.254.4/32
+!
+interface r4-eth0
+ ipv6 address 2001:db8:4::1/64
+!
diff --git a/tests/topotests/bfd-topo2/test_bfd_topo2.dot b/tests/topotests/bfd-topo2/test_bfd_topo2.dot
new file mode 100644
index 0000000000..6b68fb398f
--- /dev/null
+++ b/tests/topotests/bfd-topo2/test_bfd_topo2.dot
@@ -0,0 +1,73 @@
+## Color coding:
+#########################
+## Main FRR: #f08080 red
+## Switches: #d0e0d0 gray
+## RIP: #19e3d9 Cyan
+## RIPng: #fcb314 dark yellow
+## OSPFv2: #32b835 Green
+## OSPFv3: #19e3d9 Cyan
+## ISIS IPv4 #fcb314 dark yellow
+## ISIS IPv6 #9a81ec purple
+## BGP IPv4 #eee3d3 beige
+## BGP IPv6 #fdff00 yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph template {
+ label="bfd-topo2";
+
+ # Routers
+ r1 [
+ shape=doubleoctagon,
+ label="r1",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r2 [
+ shape=doubleoctagon
+ label="r2",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r3 [
+ shape=doubleoctagon
+ label="r3",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r4 [
+ shape=doubleoctagon
+ label="r4",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+ # Switches
+ sw1 [
+ shape=oval,
+ label="sw1\n2001:db8:1::/64",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ sw2 [
+ shape=oval,
+ label="sw2\n10.0.3.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ sw3 [
+ shape=oval,
+ label="sw3\n2001:db8:4::/64",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+
+ # Connections
+ r1 -- sw1 [label="eth0"];
+ r2 -- sw1 [label="eth0"];
+
+ r2 -- sw2 [label="eth1"];
+ r3 -- sw2 [label="eth0"];
+
+ r2 -- sw3 [label="eth2"];
+ r4 -- sw3 [label="eth0"];
+}
diff --git a/tests/topotests/bfd-topo2/test_bfd_topo2.jpg b/tests/topotests/bfd-topo2/test_bfd_topo2.jpg
new file mode 100644
index 0000000000..35fe562a80
--- /dev/null
+++ b/tests/topotests/bfd-topo2/test_bfd_topo2.jpg
Binary files differ
diff --git a/tests/topotests/bfd-topo2/test_bfd_topo2.py b/tests/topotests/bfd-topo2/test_bfd_topo2.py
new file mode 100644
index 0000000000..773db129f0
--- /dev/null
+++ b/tests/topotests/bfd-topo2/test_bfd_topo2.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+
+#
+# test_bfd_topo2.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2019 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+#
+# 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.
+#
+
+"""
+test_bfd_topo2.py: Test the FRR/Quagga BFD daemon with multihop and BGP
+unnumbered.
+"""
+
+import os
+import sys
+import json
+from functools import partial
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, '../'))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+
+class BFDTopo(Topo):
+ "Test topology builder"
+ def build(self, *_args, **_opts):
+ "Build function"
+ tgen = get_topogen(self)
+
+ # Create 4 routers.
+ for routern in range(1, 5):
+ 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'])
+
+ switch = tgen.add_switch('s3')
+ switch.add_link(tgen.gears['r2'])
+ switch.add_link(tgen.gears['r4'])
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(BFDTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+ for rname, router in router_list.iteritems():
+ router.load_config(
+ TopoRouter.RD_ZEBRA,
+ os.path.join(CWD, '{}/zebra.conf'.format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BFD,
+ os.path.join(CWD, '{}/bfdd.conf'.format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP,
+ os.path.join(CWD, '{}/bgpd.conf'.format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_OSPF,
+ os.path.join(CWD, '{}/ospfd.conf'.format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_OSPF6,
+ os.path.join(CWD, '{}/ospf6d.conf'.format(rname))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+ # Verify that we are using the proper version and that the BFD
+ # daemon exists.
+ for router in router_list.values():
+ # Check for Version
+ if router.has_version('<', '5.1'):
+ tgen.set_error('Unsupported FRR version')
+ break
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_protocols_convergence():
+ """
+ Assert that all protocols have converged before checking for the BFD
+ statuses as they depend on it.
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Check IPv4 routing tables.
+ logger.info("Checking IPv4 routes for convergence")
+ for router in tgen.routers().values():
+ json_file = '{}/{}/ipv4_routes.json'.format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info('skipping file {}'.format(json_file))
+ continue
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(topotest.router_json_cmp,
+ router, 'show ip route json', expected)
+ _, result = topotest.run_and_expect(test_func, None, count=160,
+ wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+ # Check IPv6 routing tables.
+ logger.info("Checking IPv6 routes for convergence")
+ for router in tgen.routers().values():
+ json_file = '{}/{}/ipv6_routes.json'.format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info('skipping file {}'.format(json_file))
+ continue
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(topotest.router_json_cmp,
+ router, 'show ipv6 route json', expected)
+ _, result = topotest.run_and_expect(test_func, None, count=160,
+ wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+
+def test_bfd_connection():
+ "Assert that the BFD peers can find themselves."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info('waiting for bfd peers to go up')
+
+ for router in tgen.routers().values():
+ json_file = '{}/{}/peers.json'.format(CWD, router.name)
+ expected = json.loads(open(json_file).read())
+
+ test_func = partial(topotest.router_json_cmp,
+ router, 'show bfd peers json', expected)
+ _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip('Memory leak test/report is disabled')
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == '__main__':
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tools/coccinelle/alloc_cast.cocci b/tools/coccinelle/alloc_cast.cocci
new file mode 100644
index 0000000000..b1497c750f
--- /dev/null
+++ b/tools/coccinelle/alloc_cast.cocci
@@ -0,0 +1,101 @@
+/// Remove casting the values returned by memory allocation functions
+/// like XMALLOC and XCALLOC.
+///
+// This makes an effort to find cases of casting of values returned by #
+// XMALLOC and XCALLOC and removes the casting as it is not required. The
+// result in the patch case may need some reformatting.
+//
+// Confidence: High
+// Copyright: (C) 2014 Himangi Saraogi GPLv2.
+// Copyright: (C) 2017 Himanshu Jha GPLv2.
+// Copyright: (C) 2019 Quentin Young GPLv2.
+// Comments:
+// Options: --no-includes --include-headers
+//
+
+virtual context
+virtual patch
+virtual org
+virtual report
+
+@initialize:python@
+@@
+import re
+pattern = '__'
+m = re.compile(pattern)
+
+@r1 depends on context || patch@
+type T;
+@@
+
+ (T *)
+ \(XMALLOC\|XCALLOC\)(...)
+
+//----------------------------------------------------------
+// For context mode
+//----------------------------------------------------------
+
+@script:python depends on context@
+t << r1.T;
+@@
+
+if m.search(t) != None:
+ cocci.include_match(False)
+
+@depends on context && r1@
+type r1.T;
+@@
+
+* (T *)
+ \(XMALLOC\|XCALLOC\)(...)
+
+//----------------------------------------------------------
+// For patch mode
+//----------------------------------------------------------
+
+@script:python depends on patch@
+t << r1.T;
+@@
+
+if m.search(t) != None:
+ cocci.include_match(False)
+
+@depends on patch && r1@
+type r1.T;
+@@
+
+- (T *)
+ \(XMALLOC\|XCALLOC\)(...)
+
+//----------------------------------------------------------
+// For org and report mode
+//----------------------------------------------------------
+
+@r2 depends on org || report@
+type T;
+position p;
+@@
+
+ (T@p *)
+ \(XMALLOC\|XCALLOC\)(...)
+
+@script:python depends on org@
+p << r2.p;
+t << r2.T;
+@@
+
+if m.search(t) != None:
+ cocci.include_match(False)
+else:
+ coccilib.org.print_safe_todo(p[0], t)
+
+@script:python depends on report@
+p << r2.p;
+t << r2.T;
+@@
+
+if m.search(t) != None:
+ cocci.include_match(False)
+else:
+ msg="WARNING: casting value returned by memory allocation function to (%s *) is useless." % (t)
+ coccilib.report.print_report(p[0], msg)
diff --git a/tools/coccinelle/array_size.cocci b/tools/coccinelle/array_size.cocci
new file mode 100644
index 0000000000..f977b8aef2
--- /dev/null
+++ b/tools/coccinelle/array_size.cocci
@@ -0,0 +1,83 @@
+/// Use array_size instead of dividing sizeof array with sizeof an element
+///
+//# This makes an effort to find cases where array_size can be used such as
+//# where there is a division of sizeof the array by the sizeof its first
+//# element or by any indexed element or the element type. It replaces the
+//# division of the two sizeofs by array_size.
+//
+// Confidence: High
+// Copyright: (C) 2014 Himangi Saraogi. GPLv2.
+// Copyright: (C) 2019 Quentin Young. GPLv2.
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+//----------------------------------------------------------
+// For context mode
+//----------------------------------------------------------
+
+@depends on context@
+type T;
+T[] E;
+@@
+(
+* (sizeof(E)/sizeof(*E))
+|
+* (sizeof(E)/sizeof(E[...]))
+|
+* (sizeof(E)/sizeof(T))
+)
+
+//----------------------------------------------------------
+// For patch mode
+//----------------------------------------------------------
+
+@depends on patch@
+type T;
+T[] E;
+@@
+(
+- (sizeof(E)/sizeof(*E))
++ array_size(E)
+|
+- (sizeof(E)/sizeof(E[...]))
++ array_size(E)
+|
+- (sizeof(E)/sizeof(T))
++ array_size(E)
+)
+
+//----------------------------------------------------------
+// For org and report mode
+//----------------------------------------------------------
+
+@r depends on (org || report)@
+type T;
+T[] E;
+position p;
+@@
+(
+ (sizeof(E)@p /sizeof(*E))
+|
+ (sizeof(E)@p /sizeof(E[...]))
+|
+ (sizeof(E)@p /sizeof(T))
+)
+
+@script:python depends on org@
+p << r.p;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING should use array_size")
+
+@script:python depends on report@
+p << r.p;
+@@
+
+msg="WARNING: Use array_size"
+coccilib.report.print_report(p[0], msg)
+
diff --git a/tools/coccinelle/badty.cocci b/tools/coccinelle/badty.cocci
new file mode 100644
index 0000000000..481cf301cc
--- /dev/null
+++ b/tools/coccinelle/badty.cocci
@@ -0,0 +1,76 @@
+/// Use ARRAY_SIZE instead of dividing sizeof array with sizeof an element
+///
+//# This makes an effort to find cases where the argument to sizeof is wrong
+//# in memory allocation functions by checking the type of the allocated memory
+//# when it is a double pointer and ensuring the sizeof argument takes a pointer
+//# to the the memory being allocated. There are false positives in cases the
+//# sizeof argument is not used in constructing the return value. The result
+//# may need some reformatting.
+//
+// Confidence: Moderate
+// Copyright: (C) 2014 Himangi Saraogi. GPLv2.
+// Comments:
+// Options:
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+//----------------------------------------------------------
+// For context mode
+//----------------------------------------------------------
+
+@depends on context disable sizeof_type_expr@
+type T;
+T **x;
+@@
+
+ x =
+ <+...sizeof(
+* T
+ )...+>
+
+//----------------------------------------------------------
+// For patch mode
+//----------------------------------------------------------
+
+@depends on patch disable sizeof_type_expr@
+type T;
+T **x;
+@@
+
+ x =
+ <+...sizeof(
+- T
++ *x
+ )...+>
+
+//----------------------------------------------------------
+// For org and report mode
+//----------------------------------------------------------
+
+@r depends on (org || report) disable sizeof_type_expr@
+type T;
+T **x;
+position p;
+@@
+
+ x =
+ <+...sizeof(
+ T@p
+ )...+>
+
+@script:python depends on org@
+p << r.p;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING sizeof argument should be pointer type, not structure type")
+
+@script:python depends on report@
+p << r.p;
+@@
+
+msg="WARNING: Use correct pointer type argument for sizeof"
+coccilib.report.print_report(p[0], msg)
+
diff --git a/tools/coccinelle/badzero.cocci b/tools/coccinelle/badzero.cocci
new file mode 100644
index 0000000000..f597c8007b
--- /dev/null
+++ b/tools/coccinelle/badzero.cocci
@@ -0,0 +1,238 @@
+/// Compare pointer-typed values to NULL rather than 0
+///
+//# This makes an effort to choose between !x and x == NULL. !x is used
+//# if it has previously been used with the function used to initialize x.
+//# This relies on type information. More type information can be obtained
+//# using the option -all_includes and the option -I to specify an
+//# include path.
+//
+// Confidence: High
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Requires: 1.0.0
+// Options:
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+@initialize:ocaml@
+@@
+let negtable = Hashtbl.create 101
+
+@depends on patch@
+expression *E;
+identifier f;
+@@
+
+(
+ (E = f(...)) ==
+- 0
++ NULL
+|
+ (E = f(...)) !=
+- 0
++ NULL
+|
+- 0
++ NULL
+ == (E = f(...))
+|
+- 0
++ NULL
+ != (E = f(...))
+)
+
+
+@t1 depends on !patch@
+expression *E;
+identifier f;
+position p;
+@@
+
+(
+ (E = f(...)) ==
+* 0@p
+|
+ (E = f(...)) !=
+* 0@p
+|
+* 0@p
+ == (E = f(...))
+|
+* 0@p
+ != (E = f(...))
+)
+
+@script:python depends on org@
+p << t1.p;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0")
+
+@script:python depends on report@
+p << t1.p;
+@@
+
+coccilib.report.print_report(p[0], "WARNING comparing pointer to 0")
+
+// Tests of returned values
+
+@s@
+identifier f;
+expression E,E1;
+@@
+
+ E = f(...)
+ ... when != E = E1
+ !E
+
+@script:ocaml depends on s@
+f << s.f;
+@@
+
+try let _ = Hashtbl.find negtable f in ()
+with Not_found -> Hashtbl.add negtable f ()
+
+@ r disable is_zero,isnt_zero exists @
+expression *E;
+identifier f;
+@@
+
+E = f(...)
+...
+(E == 0
+|E != 0
+|0 == E
+|0 != E
+)
+
+@script:ocaml@
+f << r.f;
+@@
+
+try let _ = Hashtbl.find negtable f in ()
+with Not_found -> include_match false
+
+// This rule may lead to inconsistent path problems, if E is defined in two
+// places
+@ depends on patch disable is_zero,isnt_zero @
+expression *E;
+expression E1;
+identifier r.f;
+@@
+
+E = f(...)
+<...
+(
+- E == 0
++ !E
+|
+- E != 0
++ E
+|
+- 0 == E
++ !E
+|
+- 0 != E
++ E
+)
+...>
+?E = E1
+
+@t2 depends on !patch disable is_zero,isnt_zero @
+expression *E;
+expression E1;
+identifier r.f;
+position p1;
+position p2;
+@@
+
+E = f(...)
+<...
+(
+* E == 0@p1
+|
+* E != 0@p2
+|
+* 0@p1 == E
+|
+* 0@p1 != E
+)
+...>
+?E = E1
+
+@script:python depends on org@
+p << t2.p1;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0, suggest !E")
+
+@script:python depends on org@
+p << t2.p2;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0")
+
+@script:python depends on report@
+p << t2.p1;
+@@
+
+coccilib.report.print_report(p[0], "WARNING comparing pointer to 0, suggest !E")
+
+@script:python depends on report@
+p << t2.p2;
+@@
+
+coccilib.report.print_report(p[0], "WARNING comparing pointer to 0")
+
+@ depends on patch disable is_zero,isnt_zero @
+expression *E;
+@@
+
+(
+ E ==
+- 0
++ NULL
+|
+ E !=
+- 0
++ NULL
+|
+- 0
++ NULL
+ == E
+|
+- 0
++ NULL
+ != E
+)
+
+@ t3 depends on !patch disable is_zero,isnt_zero @
+expression *E;
+position p;
+@@
+
+(
+* E == 0@p
+|
+* E != 0@p
+|
+* 0@p == E
+|
+* 0@p != E
+)
+
+@script:python depends on org@
+p << t3.p;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING comparing pointer to 0")
+
+@script:python depends on report@
+p << t3.p;
+@@
+
+coccilib.report.print_report(p[0], "WARNING comparing pointer to 0")
diff --git a/tools/coccinelle/boolconv.cocci b/tools/coccinelle/boolconv.cocci
new file mode 100644
index 0000000000..33c464d6bc
--- /dev/null
+++ b/tools/coccinelle/boolconv.cocci
@@ -0,0 +1,90 @@
+/// Remove unneeded conversion to bool
+///
+//# Relational and logical operators evaluate to bool,
+//# explicit conversion is overly verbose and unneeded.
+//
+// Copyright: (C) 2016 Andrew F. Davis <afd@ti.com> GPLv2.
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+//----------------------------------------------------------
+// For patch mode
+//----------------------------------------------------------
+
+@depends on patch@
+expression A, B;
+symbol true, false;
+@@
+
+(
+ A == B
+|
+ A != B
+|
+ A > B
+|
+ A < B
+|
+ A >= B
+|
+ A <= B
+|
+ A && B
+|
+ A || B
+)
+- ? true : false
+
+//----------------------------------------------------------
+// For context mode
+//----------------------------------------------------------
+
+@r depends on !patch@
+expression A, B;
+symbol true, false;
+position p;
+@@
+
+(
+ A == B
+|
+ A != B
+|
+ A > B
+|
+ A < B
+|
+ A >= B
+|
+ A <= B
+|
+ A && B
+|
+ A || B
+)
+* ? true : false@p
+
+//----------------------------------------------------------
+// For org mode
+//----------------------------------------------------------
+
+@script:python depends on r&&org@
+p << r.p;
+@@
+
+msg = "WARNING: conversion to bool not needed here"
+coccilib.org.print_todo(p[0], msg)
+
+//----------------------------------------------------------
+// For report mode
+//----------------------------------------------------------
+
+@script:python depends on r&&report@
+p << r.p;
+@@
+
+msg = "WARNING: conversion to bool not needed here"
+coccilib.report.print_report(p[0], msg)
diff --git a/tools/coccinelle/boolinit.cocci b/tools/coccinelle/boolinit.cocci
new file mode 100644
index 0000000000..aabb581fab
--- /dev/null
+++ b/tools/coccinelle/boolinit.cocci
@@ -0,0 +1,194 @@
+/// Bool initializations should use true and false. Bool tests don't need
+/// comparisons. Based on contributions from Joe Perches, Rusty Russell
+/// and Bruce W Allan.
+///
+// Confidence: High
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Options: --include-headers
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+@boolok@
+symbol true,false;
+@@
+(
+true
+|
+false
+)
+
+@depends on patch@
+bool t;
+@@
+
+(
+- t == true
++ t
+|
+- true == t
++ t
+|
+- t != true
++ !t
+|
+- true != t
++ !t
+|
+- t == false
++ !t
+|
+- false == t
++ !t
+|
+- t != false
++ t
+|
+- false != t
++ t
+)
+
+@depends on patch disable is_zero, isnt_zero@
+bool t;
+@@
+
+(
+- t == 1
++ t
+|
+- t != 1
++ !t
+|
+- t == 0
++ !t
+|
+- t != 0
++ t
+)
+
+@depends on patch && boolok@
+bool b;
+@@
+(
+ b =
+- 0
++ false
+|
+ b =
+- 1
++ true
+)
+
+// ---------------------------------------------------------------------
+
+@r1 depends on !patch@
+bool t;
+position p;
+@@
+
+(
+* t@p == true
+|
+* true == t@p
+|
+* t@p != true
+|
+* true != t@p
+|
+* t@p == false
+|
+* false == t@p
+|
+* t@p != false
+|
+* false != t@p
+)
+
+@r2 depends on !patch disable is_zero, isnt_zero@
+bool t;
+position p;
+@@
+
+(
+* t@p == 1
+|
+* t@p != 1
+|
+* t@p == 0
+|
+* t@p != 0
+)
+
+@r3 depends on !patch && boolok@
+bool b;
+position p1;
+@@
+(
+*b@p1 = 0
+|
+*b@p1 = 1
+)
+
+@r4 depends on !patch@
+bool b;
+position p2;
+identifier i;
+constant c != {0,1};
+@@
+(
+ b = i
+|
+*b@p2 = c
+)
+
+@script:python depends on org@
+p << r1.p;
+@@
+
+cocci.print_main("WARNING: Comparison to bool",p)
+
+@script:python depends on org@
+p << r2.p;
+@@
+
+cocci.print_main("WARNING: Comparison of 0/1 to bool variable",p)
+
+@script:python depends on org@
+p1 << r3.p1;
+@@
+
+cocci.print_main("WARNING: Assignment of 0/1 to bool variable",p1)
+
+@script:python depends on org@
+p2 << r4.p2;
+@@
+
+cocci.print_main("ERROR: Assignment of non-0/1 constant to bool variable",p2)
+
+@script:python depends on report@
+p << r1.p;
+@@
+
+coccilib.report.print_report(p[0],"WARNING: Comparison to bool")
+
+@script:python depends on report@
+p << r2.p;
+@@
+
+coccilib.report.print_report(p[0],"WARNING: Comparison of 0/1 to bool variable")
+
+@script:python depends on report@
+p1 << r3.p1;
+@@
+
+coccilib.report.print_report(p1[0],"WARNING: Assignment of 0/1 to bool variable")
+
+@script:python depends on report@
+p2 << r4.p2;
+@@
+
+coccilib.report.print_report(p2[0],"ERROR: Assignment of non-0/1 constant to bool variable")
diff --git a/tools/coccinelle/boolreturn.cocci b/tools/coccinelle/boolreturn.cocci
new file mode 100644
index 0000000000..29d2bf41e9
--- /dev/null
+++ b/tools/coccinelle/boolreturn.cocci
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/// Return statements in functions returning bool should use
+/// true/false instead of 1/0.
+//
+// Confidence: High
+// Options: --no-includes --include-headers
+
+virtual patch
+virtual report
+virtual context
+
+@r1 depends on patch@
+identifier fn;
+typedef bool;
+symbol false;
+symbol true;
+@@
+
+bool fn ( ... )
+{
+<...
+return
+(
+- 0
++ false
+|
+- 1
++ true
+)
+ ;
+...>
+}
+
+@r2 depends on report || context@
+identifier fn;
+position p;
+@@
+
+bool fn ( ... )
+{
+<...
+return
+(
+* 0@p
+|
+* 1@p
+)
+ ;
+...>
+}
+
+
+@script:python depends on report@
+p << r2.p;
+fn << r2.fn;
+@@
+
+msg = "WARNING: return of 0/1 in function '%s' with return type bool" % fn
+coccilib.report.print_report(p[0], msg)
diff --git a/tools/coccinelle/cond_no_effect.cocci b/tools/coccinelle/cond_no_effect.cocci
new file mode 100644
index 0000000000..8467dbd1c4
--- /dev/null
+++ b/tools/coccinelle/cond_no_effect.cocci
@@ -0,0 +1,64 @@
+///Find conditions where if and else branch are functionally
+// identical.
+//
+// There can be false positives in cases where the positional
+// information is used (as with lockdep) or where the identity
+// is a placeholder for not yet handled cases.
+// Unfortunately there also seems to be a tendency to use
+// the last if else/else as a "default behavior" - which some
+// might consider a legitimate coding pattern. From discussion
+// on kernelnewbies though it seems that this is not really an
+// accepted pattern and if at all it would need to be commented
+//
+// In the Linux kernel it does not seem to actually report
+// false positives except for those that were documented as
+// being intentional.
+// the two known cases are:
+// arch/sh/kernel/traps_64.c:read_opcode()
+// } else if ((pc & 1) == 0) {
+// /* SHcompact */
+// /* TODO : provide handling for this. We don't really support
+// user-mode SHcompact yet, and for a kernel fault, this would
+// have to come from a module built for SHcompact. */
+// return -EFAULT;
+// } else {
+// /* misaligned */
+// return -EFAULT;
+// }
+// fs/kernfs/file.c:kernfs_fop_open()
+// * Both paths of the branch look the same. They're supposed to
+// * look that way and give @of->mutex different static lockdep keys.
+// */
+// if (has_mmap)
+// mutex_init(&of->mutex);
+// else
+// mutex_init(&of->mutex);
+//
+// All other cases look like bugs or at least lack of documentation
+//
+// Confidence: Moderate
+// Copyright: (C) 2016 Nicholas Mc Guire, OSADL. GPLv2.
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+
+@cond@
+statement S1;
+position p;
+@@
+
+* if@p (...) S1 else S1
+
+@script:python depends on org@
+p << cond.p;
+@@
+
+cocci.print_main("WARNING: possible condition with no effect (if == else)",p)
+
+@script:python depends on report@
+p << cond.p;
+@@
+
+coccilib.report.print_report(p[0],"WARNING: possible condition with no effect (if == else)")
diff --git a/tools/coccinelle/deref_null.cocci b/tools/coccinelle/deref_null.cocci
new file mode 100644
index 0000000000..cbc6184e69
--- /dev/null
+++ b/tools/coccinelle/deref_null.cocci
@@ -0,0 +1,282 @@
+///
+/// A variable is dereferenced under a NULL test.
+/// Even though it is known to be NULL.
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments: -I ... -all_includes can give more complete results
+// Options:
+
+virtual context
+virtual org
+virtual report
+
+// The following two rules are separate, because both can match a single
+// expression in different ways
+@pr1 expression@
+expression E;
+identifier f;
+position p1;
+@@
+
+ (E != NULL && ...) ? <+...E->f@p1...+> : ...
+
+@pr2 expression@
+expression E;
+identifier f;
+position p2;
+@@
+
+(
+ (E != NULL) && ... && <+...E->f@p2...+>
+|
+ (E == NULL) || ... || <+...E->f@p2...+>
+|
+ sizeof(<+...E->f@p2...+>)
+)
+
+@ifm@
+expression *E;
+statement S1,S2;
+position p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...) S1 else S2
+
+// For org and report modes
+
+@r depends on !context && (org || report) exists@
+expression subE <= ifm.E;
+expression *ifm.E;
+expression E1,E2;
+identifier f;
+statement S1,S2,S3,S4;
+iterator iter;
+position p!={pr1.p1,pr2.p2};
+position ifm.p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...)
+{
+ ... when != if (...) S1 else S2
+(
+ iter(subE,...) S4 // no use
+|
+ list_remove_head(E2,subE,...)
+|
+ subE = E1
+|
+ for(subE = E1;...;...) S4
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+ E->f@p // bad use
+)
+ ... when any
+ return ...;
+}
+else S3
+
+@script:python depends on !context && !org && report@
+p << r.p;
+p1 << ifm.p1;
+x << ifm.E;
+@@
+
+msg="ERROR: %s is NULL but dereferenced." % (x)
+coccilib.report.print_report(p[0], msg)
+cocci.include_match(False)
+
+@script:python depends on !context && org && !report@
+p << r.p;
+p1 << ifm.p1;
+x << ifm.E;
+@@
+
+msg="ERROR: %s is NULL but dereferenced." % (x)
+msg_safe=msg.replace("[","@(").replace("]",")")
+cocci.print_main(msg_safe,p)
+cocci.include_match(False)
+
+@s depends on !context && (org || report) exists@
+expression subE <= ifm.E;
+expression *ifm.E;
+expression E1,E2;
+identifier f;
+statement S1,S2,S3,S4;
+iterator iter;
+position p!={pr1.p1,pr2.p2};
+position ifm.p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...)
+{
+ ... when != if (...) S1 else S2
+(
+ iter(subE,...) S4 // no use
+|
+ list_remove_head(E2,subE,...)
+|
+ subE = E1
+|
+ for(subE = E1;...;...) S4
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+ E->f@p // bad use
+)
+ ... when any
+}
+else S3
+
+@script:python depends on !context && !org && report@
+p << s.p;
+p1 << ifm.p1;
+x << ifm.E;
+@@
+
+msg="ERROR: %s is NULL but dereferenced." % (x)
+coccilib.report.print_report(p[0], msg)
+
+@script:python depends on !context && org && !report@
+p << s.p;
+p1 << ifm.p1;
+x << ifm.E;
+@@
+
+msg="ERROR: %s is NULL but dereferenced." % (x)
+msg_safe=msg.replace("[","@(").replace("]",")")
+cocci.print_main(msg_safe,p)
+
+// For context mode
+
+@depends on context && !org && !report exists@
+expression subE <= ifm.E;
+expression *ifm.E;
+expression E1,E2;
+identifier f;
+statement S1,S2,S3,S4;
+iterator iter;
+position p!={pr1.p1,pr2.p2};
+position ifm.p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...)
+{
+ ... when != if (...) S1 else S2
+(
+ iter(subE,...) S4 // no use
+|
+ list_remove_head(E2,subE,...)
+|
+ subE = E1
+|
+ for(subE = E1;...;...) S4
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+* E->f@p // bad use
+)
+ ... when any
+ return ...;
+}
+else S3
+
+// The following three rules are duplicates of ifm, pr1 and pr2 respectively.
+// It is need because the previous rule as already made a "change".
+
+@pr11 depends on context && !org && !report expression@
+expression E;
+identifier f;
+position p1;
+@@
+
+ (E != NULL && ...) ? <+...E->f@p1...+> : ...
+
+@pr12 depends on context && !org && !report expression@
+expression E;
+identifier f;
+position p2;
+@@
+
+(
+ (E != NULL) && ... && <+...E->f@p2...+>
+|
+ (E == NULL) || ... || <+...E->f@p2...+>
+|
+ sizeof(<+...E->f@p2...+>)
+)
+
+@ifm1 depends on context && !org && !report@
+expression *E;
+statement S1,S2;
+position p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...) S1 else S2
+
+@depends on context && !org && !report exists@
+expression subE <= ifm1.E;
+expression *ifm1.E;
+expression E1,E2;
+identifier f;
+statement S1,S2,S3,S4;
+iterator iter;
+position p!={pr11.p1,pr12.p2};
+position ifm1.p1;
+@@
+
+if@p1 ((E == NULL && ...) || ...)
+{
+ ... when != if (...) S1 else S2
+(
+ iter(subE,...) S4 // no use
+|
+ list_remove_head(E2,subE,...)
+|
+ subE = E1
+|
+ for(subE = E1;...;...) S4
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+* E->f@p // bad use
+)
+ ... when any
+}
+else S3
diff --git a/tools/coccinelle/double_lock.cocci b/tools/coccinelle/double_lock.cocci
new file mode 100644
index 0000000000..002752f97d
--- /dev/null
+++ b/tools/coccinelle/double_lock.cocci
@@ -0,0 +1,92 @@
+/// Find double locks. False positives may occur when some paths cannot
+/// occur at execution, due to the values of variables, and when there is
+/// an intervening function call that releases the lock.
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+
+@locked@
+position p1;
+expression E1;
+position p;
+@@
+
+(
+mutex_lock@p1
+|
+mutex_trylock@p1
+|
+spin_lock@p1
+|
+spin_trylock@p1
+|
+read_lock@p1
+|
+read_trylock@p1
+|
+write_lock@p1
+|
+write_trylock@p1
+) (E1@p,...);
+
+@balanced@
+position p1 != locked.p1;
+position locked.p;
+identifier lock,unlock;
+expression x <= locked.E1;
+expression E,locked.E1;
+expression E2;
+@@
+
+if (E) {
+ <+... when != E1
+ lock(E1@p,...)
+ ...+>
+}
+... when != E1
+ when != \(x = E2\|&x\)
+ when forall
+if (E) {
+ <+... when != E1
+ unlock@p1(E1,...)
+ ...+>
+}
+
+@r depends on !balanced exists@
+expression x <= locked.E1;
+expression locked.E1;
+expression E2;
+identifier lock;
+position locked.p,p1,p2;
+@@
+
+lock@p1 (E1@p,...);
+... when != E1
+ when != \(x = E2\|&x\)
+lock@p2 (E1,...);
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+lock << r.lock;
+@@
+
+cocci.print_main(lock,p1)
+cocci.print_secs("second lock",p2)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+lock << r.lock;
+@@
+
+msg = "second lock on line %s" % (p2[0].line)
+coccilib.report.print_report(p1[0],msg)
diff --git a/tools/coccinelle/doublebitand.cocci b/tools/coccinelle/doublebitand.cocci
new file mode 100644
index 0000000000..72f1572aae
--- /dev/null
+++ b/tools/coccinelle/doublebitand.cocci
@@ -0,0 +1,54 @@
+/// Find bit operations that include the same argument more than once
+//# One source of false positives is when the argument performs a side
+//# effect. Another source of false positives is when a neutral value
+//# such as 0 for | is used to indicate no information, to maintain the
+//# same structure as other similar expressions
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual context
+virtual org
+virtual report
+
+@r expression@
+expression E;
+position p;
+@@
+
+(
+* E@p
+ & ... & E
+|
+* E@p
+ | ... | E
+|
+* E@p
+ & ... & !E
+|
+* E@p
+ | ... | !E
+|
+* !E@p
+ & ... & E
+|
+* !E@p
+ | ... | E
+)
+
+@script:python depends on org@
+p << r.p;
+@@
+
+cocci.print_main("duplicated argument to & or |",p)
+
+@script:python depends on report@
+p << r.p;
+@@
+
+coccilib.report.print_report(p[0],"duplicated argument to & or |")
diff --git a/tools/coccinelle/doubleinit.cocci b/tools/coccinelle/doubleinit.cocci
new file mode 100644
index 0000000000..c0c3371d25
--- /dev/null
+++ b/tools/coccinelle/doubleinit.cocci
@@ -0,0 +1,53 @@
+/// Find duplicate field initializations. This has a high rate of false
+/// positives due to #ifdefs, which Coccinelle is not aware of in a structure
+/// initialization.
+///
+// Confidence: Low
+// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments: requires at least Coccinelle 0.2.4, lex or parse error otherwise
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+
+@r@
+identifier I, s, fld;
+position p0,p;
+expression E;
+@@
+
+struct I s =@p0 { ..., .fld@p = E, ...};
+
+@s@
+identifier I, s, r.fld;
+position r.p0,p;
+expression E;
+@@
+
+struct I s =@p0 { ..., .fld@p = E, ...};
+
+@script:python depends on org@
+p0 << r.p0;
+fld << r.fld;
+ps << s.p;
+pr << r.p;
+@@
+
+if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)):
+ cocci.print_main(fld,p0)
+ cocci.print_secs("s",ps)
+ cocci.print_secs("r",pr)
+
+@script:python depends on report@
+p0 << r.p0;
+fld << r.fld;
+ps << s.p;
+pr << r.p;
+@@
+
+if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)):
+ msg = "%s: first occurrence line %s, second occurrence line %s" % (fld,ps[0].line,pr[0].line)
+ coccilib.report.print_report(p0[0],msg)
diff --git a/tools/coccinelle/doubletest.cocci b/tools/coccinelle/doubletest.cocci
new file mode 100644
index 0000000000..7af2ce7eb9
--- /dev/null
+++ b/tools/coccinelle/doubletest.cocci
@@ -0,0 +1,58 @@
+/// Find &&/|| operations that include the same argument more than once
+//# A common source of false positives is when the expression, or
+//# another expresssion in the same && or || operation, performs a
+//# side effect.
+///
+// Confidence: Moderate
+// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
+// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual context
+virtual org
+virtual report
+
+@r expression@
+expression E;
+position p;
+@@
+
+(
+ E@p || ... || E
+|
+ E@p && ... && E
+)
+
+@bad@
+expression r.E,e1,e2,fn;
+position r.p;
+assignment operator op;
+@@
+
+(
+E@p
+&
+ <+... \(fn(...)\|e1 op e2\|e1++\|e1--\|++e1\|--e1\) ...+>
+)
+
+@depends on context && !bad@
+expression r.E;
+position r.p;
+@@
+
+*E@p
+
+@script:python depends on org && !bad@
+p << r.p;
+@@
+
+cocci.print_main("duplicated argument to && or ||",p)
+
+@script:python depends on report && !bad@
+p << r.p;
+@@
+
+coccilib.report.print_report(p[0],"duplicated argument to && or ||")
diff --git a/tools/coccinelle/ifaddr.cocci b/tools/coccinelle/ifaddr.cocci
new file mode 100644
index 0000000000..c2663c677a
--- /dev/null
+++ b/tools/coccinelle/ifaddr.cocci
@@ -0,0 +1,34 @@
+/// The address of a variable or field is likely always to be non-zero.
+///
+// Confidence: High
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+virtual context
+
+@r@
+expression x;
+statement S1,S2;
+position p;
+@@
+
+*if@p (&x)
+ S1 else S2
+
+@script:python depends on org@
+p << r.p;
+@@
+
+cocci.print_main("test of a variable/field address",p)
+
+@script:python depends on report@
+p << r.p;
+@@
+
+msg = "ERROR: test of a variable/field address"
+coccilib.report.print_report(p[0],msg)
diff --git a/tools/coccinelle/ifnullxfree.cocci b/tools/coccinelle/ifnullxfree.cocci
new file mode 100644
index 0000000000..85fc23e394
--- /dev/null
+++ b/tools/coccinelle/ifnullxfree.cocci
@@ -0,0 +1,15 @@
+/// NULL check before some freeing functions is not needed.
+///
+// Copyright: (C) 2014 Fabian Frederick. GPLv2.
+// Copyright: (C) 2019 Quentin Young. GPLv2.
+// Comments: -
+// Options: --no-includes --include-headers
+
+virtual patch
+
+@r2 depends on patch@
+expression E;
+expression Y;
+@@
+- if (E != NULL)
+XFREE(Y, E);
diff --git a/tools/coccinelle/itnull.cocci b/tools/coccinelle/itnull.cocci
new file mode 100644
index 0000000000..f58732b56a
--- /dev/null
+++ b/tools/coccinelle/itnull.cocci
@@ -0,0 +1,94 @@
+/// Many iterators have the property that the first argument is always bound
+/// to a real list element, never NULL.
+//# False positives arise for some iterators that do not have this property,
+//# or in cases when the loop cursor is reassigned. The latter should only
+//# happen when the matched code is on the way to a loop exit (break, goto,
+//# or return).
+///
+// Confidence: Moderate
+// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+@depends on patch@
+iterator I;
+expression x,E,E1,E2;
+statement S,S1,S2;
+@@
+
+I(x,...) { <...
+(
+- if (x == NULL && ...) S
+|
+- if (x != NULL || ...)
+ S
+|
+- (x == NULL) ||
+ E
+|
+- (x != NULL) &&
+ E
+|
+- (x == NULL && ...) ? E1 :
+ E2
+|
+- (x != NULL || ...) ?
+ E1
+- : E2
+|
+- if (x == NULL && ...) S1 else
+ S2
+|
+- if (x != NULL || ...)
+ S1
+- else S2
+|
++ BAD(
+ x == NULL
++ )
+|
++ BAD(
+ x != NULL
++ )
+)
+ ...> }
+
+@r depends on !patch exists@
+iterator I;
+expression x,E;
+position p1,p2;
+@@
+
+*I@p1(x,...)
+{ ... when != x = E
+(
+* x@p2 == NULL
+|
+* x@p2 != NULL
+)
+ ... when any
+}
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("iterator-bound variable",p1)
+cocci.print_secs("useless NULL test",p2)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+msg = "ERROR: iterator variable bound on line %s cannot be NULL" % (p1[0].line)
+coccilib.report.print_report(p2[0], msg)
diff --git a/tools/coccinelle/mini_lock.cocci b/tools/coccinelle/mini_lock.cocci
new file mode 100644
index 0000000000..19c6ee5b98
--- /dev/null
+++ b/tools/coccinelle/mini_lock.cocci
@@ -0,0 +1,98 @@
+/// Find missing unlocks. This semantic match considers the specific case
+/// where the unlock is missing from an if branch, and there is a lock
+/// before the if and an unlock after the if. False positives are due to
+/// cases where the if branch represents a case where the function is
+/// supposed to exit with the lock held, or where there is some preceding
+/// function call that releases the lock.
+///
+// Confidence: Moderate
+// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual context
+virtual org
+virtual report
+
+@prelocked@
+position p1,p;
+expression E1;
+@@
+
+(
+mutex_lock@p1
+|
+mutex_trylock@p1
+|
+spin_lock@p1
+|
+spin_trylock@p1
+|
+read_lock@p1
+|
+read_trylock@p1
+|
+write_lock@p1
+|
+write_trylock@p1
+|
+read_lock_irq@p1
+|
+write_lock_irq@p1
+|
+read_lock_irqsave@p1
+|
+write_lock_irqsave@p1
+|
+spin_lock_irq@p1
+|
+spin_lock_irqsave@p1
+) (E1@p,...);
+
+@looped@
+position r;
+@@
+
+for(...;...;...) { <+... return@r ...; ...+> }
+
+@err exists@
+expression E1;
+position prelocked.p;
+position up != prelocked.p1;
+position r!=looped.r;
+identifier lock,unlock;
+@@
+
+*lock(E1@p,...);
+... when != E1
+ when any
+if (...) {
+ ... when != E1
+* return@r ...;
+}
+... when != E1
+ when any
+*unlock@up(E1,...);
+
+@script:python depends on org@
+p << prelocked.p1;
+lock << err.lock;
+unlock << err.unlock;
+p2 << err.r;
+@@
+
+cocci.print_main(lock,p)
+cocci.print_secs(unlock,p2)
+
+@script:python depends on report@
+p << prelocked.p1;
+lock << err.lock;
+unlock << err.unlock;
+p2 << err.r;
+@@
+
+msg = "preceding lock on line %s" % (p[0].line)
+coccilib.report.print_report(p2[0],msg)
diff --git a/tools/coccinelle/noderef.cocci b/tools/coccinelle/noderef.cocci
new file mode 100644
index 0000000000..ca289d5741
--- /dev/null
+++ b/tools/coccinelle/noderef.cocci
@@ -0,0 +1,81 @@
+/// sizeof when applied to a pointer typed expression gives the size of
+/// the pointer
+///
+// Confidence: High
+// Copyright: (C) 2012 Julia Lawall, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+virtual context
+virtual patch
+
+@depends on patch@
+expression *x;
+expression f;
+expression i;
+type T;
+@@
+
+(
+x = <+... sizeof(
+- x
++ *x
+ ) ...+>
+|
+f(...,(T)(x),...,sizeof(
+- x
++ *x
+ ),...)
+|
+f(...,sizeof(
+- x
++ *x
+ ),...,(T)(x),...)
+|
+f(...,(T)(x),...,i*sizeof(
+- x
++ *x
+ ),...)
+|
+f(...,i*sizeof(
+- x
++ *x
+ ),...,(T)(x),...)
+)
+
+@r depends on !patch@
+expression *x;
+expression f;
+expression i;
+position p;
+type T;
+@@
+
+(
+*x = <+... sizeof@p(x) ...+>
+|
+*f(...,(T)(x),...,sizeof@p(x),...)
+|
+*f(...,sizeof@p(x),...,(T)(x),...)
+|
+*f(...,(T)(x),...,i*sizeof@p(x),...)
+|
+*f(...,i*sizeof@p(x),...,(T)(x),...)
+)
+
+@script:python depends on org@
+p << r.p;
+@@
+
+cocci.print_main("application of sizeof to pointer",p)
+
+@script:python depends on report@
+p << r.p;
+@@
+
+msg = "ERROR: application of sizeof to pointer"
+coccilib.report.print_report(p[0],msg)<Paste>
diff --git a/tools/coccinelle/replace-strncpy.cocci b/tools/coccinelle/replace-strncpy.cocci
new file mode 100644
index 0000000000..18ff1314b0
--- /dev/null
+++ b/tools/coccinelle/replace-strncpy.cocci
@@ -0,0 +1,8 @@
+@@
+type T;
+T[] E;
+expression buf, srclen;
+@@
+
+- strncpy(E, src, srclen)
++ strlcpy(E, src, sizeof(E))
diff --git a/tools/coccinelle/returnvar.cocci b/tools/coccinelle/returnvar.cocci
new file mode 100644
index 0000000000..d8286ef530
--- /dev/null
+++ b/tools/coccinelle/returnvar.cocci
@@ -0,0 +1,66 @@
+///
+/// Remove unneeded variable used to store return value.
+///
+// Confidence: Moderate
+// Copyright: (C) 2012 Peter Senna Tschudin, INRIA/LIP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments: Comments on code can be deleted if near code that is removed.
+// "when strict" can be removed to get more hits, but adds false
+// positives
+// Options: --no-includes --include-headers
+
+virtual patch
+virtual report
+virtual context
+virtual org
+
+@depends on patch@
+type T;
+constant C;
+identifier ret;
+@@
+- T ret = C;
+... when != ret
+ when strict
+return
+- ret
++ C
+;
+
+@depends on context@
+type T;
+constant C;
+identifier ret;
+@@
+* T ret = C;
+... when != ret
+ when strict
+* return ret;
+
+@r1 depends on report || org@
+type T;
+constant C;
+identifier ret;
+position p1, p2;
+@@
+T ret@p1 = C;
+... when != ret
+ when strict
+return ret@p2;
+
+@script:python depends on report@
+p1 << r1.p1;
+p2 << r1.p2;
+C << r1.C;
+ret << r1.ret;
+@@
+coccilib.report.print_report(p1[0], "Unneeded variable: \"" + ret + "\". Return \"" + C + "\" on line " + p2[0].line)
+
+@script:python depends on org@
+p1 << r1.p1;
+p2 << r1.p2;
+C << r1.C;
+ret << r1.ret;
+@@
+cocci.print_main("unneeded \"" + ret + "\" variable", p1)
+cocci.print_sec("return " + C + " here", p2)
diff --git a/tools/coccinelle/semicolon.cocci b/tools/coccinelle/semicolon.cocci
new file mode 100644
index 0000000000..6740c659a2
--- /dev/null
+++ b/tools/coccinelle/semicolon.cocci
@@ -0,0 +1,83 @@
+///
+/// Remove unneeded semicolon.
+///
+// Confidence: Moderate
+// Copyright: (C) 2012 Peter Senna Tschudin, INRIA/LIP6. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments: Some false positives on empty default cases in switch statements.
+// Options: --no-includes --include-headers
+
+virtual patch
+virtual report
+virtual context
+virtual org
+
+@r_default@
+position p;
+@@
+switch (...)
+{
+default: ...;@p
+}
+
+@r_case@
+position p;
+@@
+(
+switch (...)
+{
+case ...:;@p
+}
+|
+switch (...)
+{
+case ...:...
+case ...:;@p
+}
+|
+switch (...)
+{
+case ...:...
+case ...:
+case ...:;@p
+}
+)
+
+@r1@
+statement S;
+position p1;
+position p != {r_default.p, r_case.p};
+identifier label;
+@@
+(
+label:;
+|
+S@p1;@p
+)
+
+@script:python@
+p << r1.p;
+p1 << r1.p1;
+@@
+if p[0].line != p1[0].line_end:
+ cocci.include_match(False)
+
+@depends on patch@
+position r1.p;
+@@
+-;@p
+
+@script:python depends on report@
+p << r1.p;
+@@
+coccilib.report.print_report(p[0],"Unneeded semicolon")
+
+@depends on context@
+position r1.p;
+@@
+*;@p
+
+@script:python depends on org@
+p << r1.p;
+@@
+cocci.print_main("Unneeded semicolon",p)
diff --git a/tools/coccinelle/strncpy_truncation.cocci b/tools/coccinelle/strncpy_truncation.cocci
new file mode 100644
index 0000000000..28b5c2a290
--- /dev/null
+++ b/tools/coccinelle/strncpy_truncation.cocci
@@ -0,0 +1,41 @@
+/// Use strlcpy rather than strncpy(dest,..,sz) + dest[sz-1] = '\0'
+///
+// Confidence: High
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual patch
+virtual context
+virtual report
+virtual org
+
+@r@
+expression dest, src, sz;
+position p;
+@@
+
+strncpy@p(dest, src, sz);
+dest[sz - 1] = '\0';
+
+@script:python depends on org@
+p << r.p;
+@@
+
+cocci.print_main("strncpy followed by truncation can be strlcpy",p)
+
+@script:python depends on report@
+p << r.p;
+@@
+
+msg = "SUGGESTION: strncpy followed by truncation can be strlcpy"
+coccilib.report.print_report(p[0],msg)
+
+@ok depends on patch@
+expression r.dest, r.src, r.sz;
+position r.p;
+@@
+
+-strncpy@p(
++strlcpy(
+ dest, src, sz);
+-dest[sz - 1] = '\0';
diff --git a/tools/coccinelle/unsigned_lesser_than_zero.cocci b/tools/coccinelle/unsigned_lesser_than_zero.cocci
new file mode 100644
index 0000000000..8fa5a3c7b7
--- /dev/null
+++ b/tools/coccinelle/unsigned_lesser_than_zero.cocci
@@ -0,0 +1,75 @@
+/// Unsigned expressions cannot be lesser than zero. Presence of
+/// comparisons 'unsigned (<|<=|>|>=) 0' often indicates a bug,
+/// usually wrong type of variable.
+///
+/// To reduce number of false positives following tests have been added:
+/// - parts of range checks are skipped, eg. "if (u < 0 || u > 15) ...",
+/// developers prefer to keep such code,
+/// - comparisons "<= 0" and "> 0" are performed only on results of
+/// signed functions/macros,
+/// - hardcoded list of signed functions/macros with always non-negative
+/// result is used to avoid false positives difficult to detect by other ways
+///
+// Confidence: Average
+// Copyright: (C) 2015 Andrzej Hajda, Samsung Electronics Co., Ltd. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Options: --all-includes
+
+virtual context
+virtual org
+virtual report
+
+@r_cmp@
+position p;
+typedef bool, u8, u16, u32, u64;
+{unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long,
+ size_t, bool, u8, u16, u32, u64} v;
+expression e;
+@@
+
+ \( v = e \| &v \)
+ ...
+ (\( v@p < 0 \| v@p <= 0 \| v@p >= 0 \| v@p > 0 \))
+
+@r@
+position r_cmp.p;
+typedef s8, s16, s32, s64;
+{char, short, int, long, long long, ssize_t, s8, s16, s32, s64} vs;
+expression c, e, v;
+identifier f !~ "^(ata_id_queue_depth|btrfs_copy_from_user|dma_map_sg|dma_map_sg_attrs|fls|fls64|gameport_time|get_write_extents|nla_len|ntoh24|of_flat_dt_match|of_get_child_count|uart_circ_chars_pending|[A-Z0-9_]+)$";
+@@
+
+(
+ v = f(...)@vs;
+ ... when != v = e;
+* (\( v@p <=@e 0 \| v@p >@e 0 \))
+ ... when any
+|
+(
+ (\( v@p < 0 \| v@p <= 0 \)) || ... || (\( v >= c \| v > c \))
+|
+ (\( v >= c \| v > c \)) || ... || (\( v@p < 0 \| v@p <= 0 \))
+|
+ (\( v@p >= 0 \| v@p > 0 \)) && ... && (\( v < c \| v <= c \))
+|
+ ((\( v < c \| v <= c \) && ... && \( v@p >= 0 \| v@p > 0 \)))
+|
+* (\( v@p <@e 0 \| v@p >=@e 0 \))
+)
+)
+
+@script:python depends on org@
+p << r_cmp.p;
+e << r.e;
+@@
+
+msg = "WARNING: Unsigned expression compared with zero: %s" % (e)
+coccilib.org.print_todo(p[0], msg)
+
+@script:python depends on report@
+p << r_cmp.p;
+e << r.e;
+@@
+
+msg = "WARNING: Unsigned expression compared with zero: %s" % (e)
+coccilib.report.print_report(p[0], msg)
diff --git a/tools/vty_check.cocci b/tools/coccinelle/vty_check.cocci
index 7e5fcc405b..7e5fcc405b 100644
--- a/tools/vty_check.cocci
+++ b/tools/coccinelle/vty_check.cocci
diff --git a/tools/vty_index.cocci b/tools/coccinelle/vty_index.cocci
index eabbaa1aa5..eabbaa1aa5 100644
--- a/tools/vty_index.cocci
+++ b/tools/coccinelle/vty_index.cocci
diff --git a/tools/coccinelle/xcalloc-simple.cocci b/tools/coccinelle/xcalloc-simple.cocci
new file mode 100644
index 0000000000..5be4dafb2b
--- /dev/null
+++ b/tools/coccinelle/xcalloc-simple.cocci
@@ -0,0 +1,52 @@
+///
+/// Use zeroing allocator rather than allocator followed by memset with 0
+///
+/// This considers some simple cases that are common and easy to validate
+/// Note in particular that there are no ...s in the rule, so all of the
+/// matched code has to be contiguous
+///
+// Confidence: High
+// Copyright: (C) 2009-2010 Julia Lawall, Nicolas Palix, DIKU. GPLv2.
+// Copyright: (C) 2009-2010 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2017 Himanshu Jha GPLv2.
+// Copyright: (C) 2019 Quentin Young. GPLv2.
+// URL: http://coccinelle.lip6.fr/rules/kzalloc.html
+// Options: --no-includes --include-headers
+//
+// Keywords: XMALLOC, XCALLOC
+// Version min: < 2.6.12 kmalloc
+// Version min: 2.6.14 kzalloc
+//
+
+virtual context
+virtual patch
+
+//----------------------------------------------------------
+// For context mode
+//----------------------------------------------------------
+
+@depends on context@
+type T, T2;
+expression x;
+expression E1;
+expression t;
+@@
+
+* x = (T)XMALLOC(t, E1);
+* memset((T2)x,0,E1);
+
+//----------------------------------------------------------
+// For patch mode
+//----------------------------------------------------------
+
+@depends on patch@
+type T, T2;
+expression x;
+expression E1;
+expression t;
+@@
+
+- x = (T)XMALLOC(t, E1);
++ x = (T)XCALLOC(t, E1);
+- memset((T2)x,0,E1);
+
diff --git a/tools/coccinelle/xfree.cocci b/tools/coccinelle/xfree.cocci
new file mode 100644
index 0000000000..eb38f0d5a8
--- /dev/null
+++ b/tools/coccinelle/xfree.cocci
@@ -0,0 +1,122 @@
+/// Find a use after free.
+//# Values of variables may imply that some
+//# execution paths are not possible, resulting in false positives.
+//# Another source of false positives are macros such as
+//# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument
+///
+// Confidence: Moderate
+// Copyright: (C) 2010-2012 Nicolas Palix. GPLv2.
+// Copyright: (C) 2010-2012 Julia Lawall, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2010-2012 Gilles Muller, INRIA/LiP6. GPLv2.
+// Copyright: (C) 2019 Quentin Young. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+
+@free@
+expression E, t;
+position p1;
+@@
+
+* XFREE@p1(t, E)
+
+@print expression@
+constant char [] c;
+expression free.E,E2;
+type T;
+position p;
+identifier f;
+@@
+
+(
+ f(...,c,...,(T)E@p,...)
+|
+ E@p == E2
+|
+ E@p != E2
+|
+ E2 == E@p
+|
+ E2 != E@p
+|
+ !E@p
+|
+ E@p || ...
+)
+
+@sz@
+expression free.E;
+position p;
+@@
+
+ sizeof(<+...E@p...+>)
+
+@loop exists@
+expression E, t;
+identifier l;
+position ok;
+@@
+
+while (1) { ...
+* XFREE@ok(t, E)
+ ... when != break;
+ when != goto l;
+ when forall
+}
+
+@r exists@
+expression free.E, subE<=free.E, E2;
+expression E1;
+iterator iter;
+statement S;
+position free.p1!=loop.ok,p2!={print.p,sz.p};
+@@
+
+* XFREE@p1(t, E)
+...
+(
+ iter(...,subE,...) S // no use
+|
+ list_remove_head(E1,subE,...)
+|
+ subE = E2
+|
+ subE++
+|
+ ++subE
+|
+ --subE
+|
+ subE--
+|
+ &subE
+|
+ BUG(...)
+|
+ BUG_ON(...)
+|
+ return_VALUE(...)
+|
+ return_ACPI_STATUS(...)
+|
+ E@p2 // bad use
+)
+
+@script:python depends on org@
+p1 << free.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("kfree",p1)
+cocci.print_secs("ref",p2)
+
+@script:python depends on report@
+p1 << free.p1;
+p2 << r.p2;
+@@
+
+msg = "ERROR: reference preceded by free on line %s" % (p1[0].line)
+coccilib.report.print_report(p2[0],msg)
diff --git a/tools/coccinelle/xfreeaddr.cocci b/tools/coccinelle/xfreeaddr.cocci
new file mode 100644
index 0000000000..c99c7ac3f5
--- /dev/null
+++ b/tools/coccinelle/xfreeaddr.cocci
@@ -0,0 +1,33 @@
+/// Free of a structure field
+///
+// Confidence: High
+// Copyright: (C) 2013 Julia Lawall, INRIA/LIP6. GPLv2.
+// Copyright: (C) 2019 Quentin Young. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: --no-includes --include-headers
+
+virtual org
+virtual report
+virtual context
+
+@r depends on context || report || org @
+expression e, t;
+identifier f;
+position p;
+@@
+
+* XFREE@p(t, &e->f)
+
+@script:python depends on org@
+p << r.p;
+@@
+
+cocci.print_main("XFREE",p)
+
+@script:python depends on report@
+p << r.p;
+@@
+
+msg = "ERROR: invalid free of structure field"
+coccilib.report.print_report(p[0],msg)
diff --git a/tools/coccinelle/xmalloc_returnval.cocci b/tools/coccinelle/xmalloc_returnval.cocci
new file mode 100644
index 0000000000..8e0ad1027d
--- /dev/null
+++ b/tools/coccinelle/xmalloc_returnval.cocci
@@ -0,0 +1,37 @@
+/// XMALLOC, XCALLOC etc either return non-null, or abort the program.
+/// Never nullcheck these.
+//
+// Copyright: (C) 2019 Quentin Young. GPLv2.
+
+virtual patch
+
+//----------------------------------------------------------
+// For patch mode
+//----------------------------------------------------------
+
+@depends on patch@
+identifier alloc;
+@@
+
+alloc = XMALLOC(...);
+
+...
+
+- if (alloc == NULL)
+- {
+- ...
+- }
+
+@depends on patch@
+identifier alloc;
+@@
+
+alloc = XCALLOC(...);
+
+...
+
+- if (alloc == NULL)
+- {
+- ...
+- }
+
diff --git a/tools/zprivs.cocci b/tools/coccinelle/zprivs.cocci
index 76d13c3f0d..76d13c3f0d 100644
--- a/tools/zprivs.cocci
+++ b/tools/coccinelle/zprivs.cocci
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 9ff869e503..1f1152d364 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -1305,6 +1305,7 @@ DEFUNSH(VTYSH_BGPD, router_bgp, router_bgp_cmd,
return CMD_SUCCESS;
}
+#ifdef KEEP_OLD_VPN_COMMANDS
DEFUNSH(VTYSH_BGPD, address_family_vpnv4, address_family_vpnv4_cmd,
"address-family vpnv4 [unicast]",
"Enter Address Family command mode\n"
@@ -1324,6 +1325,7 @@ DEFUNSH(VTYSH_BGPD, address_family_vpnv6, address_family_vpnv6_cmd,
vty->node = BGP_VPNV6_NODE;
return CMD_SUCCESS;
}
+#endif /* KEEP_OLD_VPN_COMMANDS */
DEFUNSH(VTYSH_BGPD, address_family_ipv4, address_family_ipv4_cmd,
"address-family ipv4 [unicast]",
@@ -3735,8 +3737,10 @@ void vtysh_init_vty(void)
install_element(CONFIG_NODE, &router_isis_cmd);
install_element(CONFIG_NODE, &router_openfabric_cmd);
install_element(CONFIG_NODE, &router_bgp_cmd);
+#ifdef KEEP_OLD_VPN_COMMANDS
install_element(BGP_NODE, &address_family_vpnv4_cmd);
install_element(BGP_NODE, &address_family_vpnv6_cmd);
+#endif /* KEEP_OLD_VPN_COMMANDS */
#if defined(ENABLE_BGP_VNC)
install_element(BGP_NODE, &vnc_vrf_policy_cmd);
install_element(BGP_NODE, &vnc_defaults_cmd);
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index 91e49c45c1..7ca3ed9c5e 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -74,8 +74,7 @@ static int config_cmp(struct config *c1, struct config *c2)
static void config_del(struct config *config)
{
list_delete(&config->line);
- if (config->name)
- XFREE(MTYPE_VTYSH_CONFIG_LINE, config->name);
+ XFREE(MTYPE_VTYSH_CONFIG_LINE, config->name);
XFREE(MTYPE_VTYSH_CONFIG, config);
}
diff --git a/vtysh/vtysh_user.c b/vtysh/vtysh_user.c
index dcf8ca0470..aaf70ab08b 100644
--- a/vtysh/vtysh_user.c
+++ b/vtysh/vtysh_user.c
@@ -204,7 +204,7 @@ char *vtysh_get_home(void)
struct passwd *passwd;
char *homedir;
- if ((homedir = getenv("HOME")) != 0)
+ if ((homedir = getenv("HOME")) != NULL)
return homedir;
/* Fallback if HOME is undefined */
diff --git a/zebra/connected.c b/zebra/connected.c
index c449855f6d..128f397552 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -594,5 +594,5 @@ int connected_is_unnumbered(struct interface *ifp)
return CHECK_FLAG(connected->flags,
ZEBRA_IFA_UNNUMBERED);
}
- return 0;
+ return 1;
}
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 3583d63d31..b2f470bc8d 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -1194,8 +1194,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
ifp = if_lookup_by_name_per_ns(zns, name);
if (ifp) {
- if (ifp->desc)
- XFREE(MTYPE_TMP, ifp->desc);
+ XFREE(MTYPE_TMP, ifp->desc);
if (desc)
ifp->desc = XSTRDUP(MTYPE_TMP, desc);
}
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 3868412b20..c56e2f316d 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -927,7 +927,7 @@ static void _netlink_route_nl_add_gateway_info(uint8_t route_family,
uint8_t gw_family,
struct nlmsghdr *nlmsg,
size_t req_size, int bytelen,
- struct nexthop *nexthop)
+ const struct nexthop *nexthop)
{
if (route_family == AF_MPLS) {
struct gw_family_t gw_fam;
@@ -954,7 +954,7 @@ static void _netlink_route_rta_add_gateway_info(uint8_t route_family,
struct rtattr *rta,
struct rtnexthop *rtnh,
size_t req_size, int bytelen,
- struct nexthop *nexthop)
+ const struct nexthop *nexthop)
{
if (route_family == AF_MPLS) {
struct gw_family_t gw_fam;
@@ -990,7 +990,7 @@ static void _netlink_route_rta_add_gateway_info(uint8_t route_family,
* @param req_size: The size allocated for the message.
*/
static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
- struct nexthop *nexthop,
+ const struct nexthop *nexthop,
struct nlmsghdr *nlmsg,
struct rtmsg *rtmsg,
size_t req_size, int cmd)
@@ -1009,7 +1009,7 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
label_buf[0] = '\0';
assert(nexthop);
- for (struct nexthop *nh = nexthop; nh; nh = nh->rparent) {
+ for (const struct nexthop *nh = nexthop; nh; nh = nh->rparent) {
char label_buf1[20];
nh_label = nh->nh_label;
@@ -1175,11 +1175,11 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen,
* the prefsrc should be stored.
*/
static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
- struct nexthop *nexthop,
+ const struct nexthop *nexthop,
struct rtattr *rta,
struct rtnexthop *rtnh,
struct rtmsg *rtmsg,
- union g_addr **src)
+ const union g_addr **src)
{
struct mpls_label_stack *nh_label;
mpls_lse_t out_lse[MPLS_MAX_LABELS];
@@ -1200,7 +1200,7 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
label_buf[0] = '\0';
assert(nexthop);
- for (struct nexthop *nh = nexthop; nh; nh = nh->rparent) {
+ for (const struct nexthop *nh = nexthop; nh; nh = nh->rparent) {
char label_buf1[20];
nh_label = nh->nh_label;
@@ -1342,7 +1342,7 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen,
}
static inline void _netlink_mpls_build_singlepath(const char *routedesc,
- zebra_nhlfe_t *nhlfe,
+ const zebra_nhlfe_t *nhlfe,
struct nlmsghdr *nlmsg,
struct rtmsg *rtmsg,
size_t req_size, int cmd)
@@ -1358,9 +1358,9 @@ static inline void _netlink_mpls_build_singlepath(const char *routedesc,
static inline void
-_netlink_mpls_build_multipath(const char *routedesc, zebra_nhlfe_t *nhlfe,
+_netlink_mpls_build_multipath(const char *routedesc, const zebra_nhlfe_t *nhlfe,
struct rtattr *rta, struct rtnexthop *rtnh,
- struct rtmsg *rtmsg, union g_addr **src)
+ struct rtmsg *rtmsg, const union g_addr **src)
{
int bytelen;
uint8_t family;
@@ -1438,7 +1438,6 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
{
int bytelen;
- struct sockaddr_nl snl;
struct nexthop *nexthop = NULL;
unsigned int nexthop_num;
int family;
@@ -1466,10 +1465,9 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
- if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) {
- if ((p->family == AF_INET) || v6_rr_semantics)
- req.n.nlmsg_flags |= NLM_F_REPLACE;
- }
+ if ((cmd == RTM_NEWROUTE) &&
+ ((p->family == AF_INET) || v6_rr_semantics))
+ req.n.nlmsg_flags |= NLM_F_REPLACE;
req.n.nlmsg_type = cmd;
@@ -1657,7 +1655,7 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
char buf[NL_PKT_BUF_SIZE];
struct rtattr *rta = (void *)buf;
struct rtnexthop *rtnh;
- union g_addr *src1 = NULL;
+ const union g_addr *src1 = NULL;
rta->rta_type = RTA_MULTIPATH;
rta->rta_len = RTA_LENGTH(0);
@@ -1748,11 +1746,6 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx)
}
skip:
-
- /* Destination netlink address. */
- memset(&snl, 0, sizeof(snl));
- snl.nl_family = AF_NETLINK;
-
/* Talk to netlink socket. */
return netlink_talk_info(netlink_talk_filter, &req.n,
dplane_ctx_get_ns(ctx), 0);
@@ -1972,23 +1965,38 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
/* The interface should exist. */
ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id),
ndm->ndm_ifindex);
- if (!ifp || !ifp->info)
+ if (!ifp || !ifp->info) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("\t%s without associated interface: %u",
+ __PRETTY_FUNCTION__, ndm->ndm_ifindex);
return 0;
+ }
/* The interface should be something we're interested in. */
- if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
+ if (!IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("\t%s Not interested in %s, not a slave",
+ __PRETTY_FUNCTION__, ifp->name);
return 0;
+ }
/* Drop "permanent" entries. */
- if (ndm->ndm_state & NUD_PERMANENT)
+ if (ndm->ndm_state & NUD_PERMANENT) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("\t%s Entry is PERMANENT, dropping",
+ __PRETTY_FUNCTION__);
return 0;
+ }
zif = (struct zebra_if *)ifp->info;
if ((br_if = zif->brslave_info.br_if) == NULL) {
- zlog_debug("%s family %s IF %s(%u) brIF %u - no bridge master",
- nl_msg_type_to_str(h->nlmsg_type),
- nl_family_to_str(ndm->ndm_family), ifp->name,
- ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "%s family %s IF %s(%u) brIF %u - no bridge master",
+ nl_msg_type_to_str(h->nlmsg_type),
+ nl_family_to_str(ndm->ndm_family), ifp->name,
+ ndm->ndm_ifindex,
+ zif->brslave_info.bridge_ifindex);
return 0;
}
@@ -1997,20 +2005,24 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
netlink_parse_rtattr(tb, NDA_MAX, NDA_RTA(ndm), len);
if (!tb[NDA_LLADDR]) {
- zlog_debug("%s family %s IF %s(%u) brIF %u - no LLADDR",
- nl_msg_type_to_str(h->nlmsg_type),
- nl_family_to_str(ndm->ndm_family), ifp->name,
- ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s family %s IF %s(%u) brIF %u - no LLADDR",
+ nl_msg_type_to_str(h->nlmsg_type),
+ nl_family_to_str(ndm->ndm_family), ifp->name,
+ ndm->ndm_ifindex,
+ zif->brslave_info.bridge_ifindex);
return 0;
}
if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
- zlog_debug(
- "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %lu",
- nl_msg_type_to_str(h->nlmsg_type),
- nl_family_to_str(ndm->ndm_family), ifp->name,
- ndm->ndm_ifindex, zif->brslave_info.bridge_ifindex,
- (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR]));
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "%s family %s IF %s(%u) brIF %u - LLADDR is not MAC, len %lu",
+ nl_msg_type_to_str(h->nlmsg_type),
+ nl_family_to_str(ndm->ndm_family), ifp->name,
+ ndm->ndm_ifindex,
+ zif->brslave_info.bridge_ifindex,
+ (unsigned long)RTA_PAYLOAD(tb[NDA_LLADDR]));
return 0;
}
@@ -2043,8 +2055,12 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
prefix_mac2str(&mac, buf, sizeof(buf)),
dst_present ? dst_buf : "");
- if (filter_vlan && vid != filter_vlan)
+ if (filter_vlan && vid != filter_vlan) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("\tFiltered due to filter vlan: %d",
+ filter_vlan);
return 0;
+ }
/* If add or update, do accordingly if learnt on a "local" interface; if
* the notification is over VxLAN, this has to be related to
@@ -2052,10 +2068,6 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
* so perform an implicit delete of any local entry (if it exists).
*/
if (h->nlmsg_type == RTM_NEWNEIGH) {
- /* Drop "permanent" entries. */
- if (ndm->ndm_state & NUD_PERMANENT)
- return 0;
-
if (IS_ZEBRA_IF_VXLAN(ifp))
return zebra_vxlan_check_del_local_mac(ifp, br_if, &mac,
vid);
@@ -2072,8 +2084,11 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
* Ignore the notification from VxLan driver as it is also generated
* when mac moves from remote to local.
*/
- if (dst_present)
+ if (dst_present) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("\tNo Destination Present");
return 0;
+ }
if (IS_ZEBRA_IF_VXLAN(ifp))
return zebra_vxlan_check_readd_remote_mac(ifp, br_if, &mac,
@@ -2386,6 +2401,9 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
/* if kernel deletes our rfc5549 neighbor entry, re-install it */
if (h->nlmsg_type == RTM_DELNEIGH && (ndm->ndm_state & NUD_PERMANENT)) {
netlink_handle_5549(ndm, zif, ifp, &ip);
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "\tNeighbor Entry Received is a 5549 entry, finished");
return 0;
}
@@ -2411,20 +2429,27 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
return 0;
} else if (IS_ZEBRA_IF_BRIDGE(ifp))
link_if = ifp;
- else
+ else {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "\tNeighbor Entry received is not on a VLAN or a BRIDGE, ignoring");
return 0;
+ }
memset(&mac, 0, sizeof(struct ethaddr));
if (h->nlmsg_type == RTM_NEWNEIGH) {
if (tb[NDA_LLADDR]) {
if (RTA_PAYLOAD(tb[NDA_LLADDR]) != ETH_ALEN) {
- zlog_debug(
- "%s family %s IF %s(%u) - LLADDR is not MAC, len %lu",
- nl_msg_type_to_str(h->nlmsg_type),
- nl_family_to_str(ndm->ndm_family),
- ifp->name, ndm->ndm_ifindex,
- (unsigned long)RTA_PAYLOAD(
- tb[NDA_LLADDR]));
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "%s family %s IF %s(%u) - LLADDR is not MAC, len %lu",
+ nl_msg_type_to_str(
+ h->nlmsg_type),
+ nl_family_to_str(
+ ndm->ndm_family),
+ ifp->name, ndm->ndm_ifindex,
+ (unsigned long)RTA_PAYLOAD(
+ tb[NDA_LLADDR]));
return 0;
}
@@ -2751,7 +2776,7 @@ int kernel_upd_neigh(struct interface *ifp, struct ipaddr *ip,
int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
{
mpls_lse_t lse;
- zebra_nhlfe_t *nhlfe;
+ const zebra_nhlfe_t *nhlfe;
struct nexthop *nexthop = NULL;
unsigned int nexthop_num;
const char *routedesc;
@@ -2854,7 +2879,7 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx)
char buf[NL_PKT_BUF_SIZE];
struct rtattr *rta = (void *)buf;
struct rtnexthop *rtnh;
- union g_addr *src1 = NULL;
+ const union g_addr *src1 = NULL;
rta->rta_type = RTA_MULTIPATH;
rta->rta_len = RTA_LENGTH(0);
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index ef9917d4e6..4e97c272fb 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -1432,12 +1432,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
case NEXTHOP_TYPE_IPV4_IFINDEX:
memset(&vtep_ip, 0, sizeof(struct ipaddr));
- if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) {
- ifindex = get_l3vni_svi_ifindex(vrf_id);
- } else {
- ifindex = api_nh->ifindex;
- }
-
+ ifindex = api_nh->ifindex;
if (IS_ZEBRA_DEBUG_RECV) {
char nhbuf[INET6_ADDRSTRLEN] = {0};
@@ -1452,12 +1447,10 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
re, &api_nh->gate.ipv4, NULL, ifindex,
api_nh->vrf_id);
- /* if this an EVPN route entry,
- * program the nh as neigh
+ /* Special handling for IPv4 routes sourced from EVPN:
+ * the nexthop and associated MAC need to be installed.
*/
if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) {
- SET_FLAG(nexthop->flags,
- NEXTHOP_FLAG_EVPN_RVTEP);
vtep_ip.ipa_type = IPADDR_V4;
memcpy(&(vtep_ip.ipaddr_v4),
&(api_nh->gate.ipv4),
@@ -1473,22 +1466,15 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
memset(&vtep_ip, 0, sizeof(struct ipaddr));
- if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) {
- ifindex = get_l3vni_svi_ifindex(vrf_id);
- } else {
- ifindex = api_nh->ifindex;
- }
-
+ ifindex = api_nh->ifindex;
nexthop = route_entry_nexthop_ipv6_ifindex_add(
re, &api_nh->gate.ipv6, ifindex,
api_nh->vrf_id);
- /* if this an EVPN route entry,
- * program the nh as neigh
+ /* Special handling for IPv6 routes sourced from EVPN:
+ * the nexthop and associated MAC need to be installed.
*/
if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) {
- SET_FLAG(nexthop->flags,
- NEXTHOP_FLAG_EVPN_RVTEP);
vtep_ip.ipa_type = IPADDR_V6;
memcpy(&vtep_ip.ipaddr_v6, &(api_nh->gate.ipv6),
sizeof(struct in6_addr));
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 928169a862..df26a8534c 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -111,10 +111,13 @@ struct dplane_pw_info {
int af;
int status;
uint32_t flags;
- union g_addr nexthop;
+ union g_addr dest;
mpls_label_t local_label;
mpls_label_t remote_label;
+ /* Nexthops */
+ struct nexthop_group nhg;
+
union pw_protocol_fields fields;
};
@@ -386,6 +389,15 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx)
case DPLANE_OP_PW_INSTALL:
case DPLANE_OP_PW_UNINSTALL:
+ /* Free allocated nexthops */
+ if ((*pctx)->u.pw.nhg.nexthop) {
+ /* This deals with recursive nexthops too */
+ nexthops_free((*pctx)->u.pw.nhg.nexthop);
+
+ (*pctx)->u.pw.nhg.nexthop = NULL;
+ }
+ break;
+
case DPLANE_OP_NONE:
break;
}
@@ -520,7 +532,7 @@ const char *dplane_op2str(enum dplane_op_e op)
ret = "PW_UNINSTALL";
break;
- };
+ }
return ret;
}
@@ -539,7 +551,7 @@ const char *dplane_res2str(enum zebra_dplane_result res)
case ZEBRA_DPLANE_REQUEST_SUCCESS:
ret = "SUCCESS";
break;
- };
+ }
return ret;
}
@@ -744,14 +756,15 @@ uint32_t dplane_ctx_get_lsp_flags(const struct zebra_dplane_ctx *ctx)
return ctx->u.lsp.flags;
}
-zebra_nhlfe_t *dplane_ctx_get_nhlfe(struct zebra_dplane_ctx *ctx)
+const zebra_nhlfe_t *dplane_ctx_get_nhlfe(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
return ctx->u.lsp.nhlfe_list;
}
-zebra_nhlfe_t *dplane_ctx_get_best_nhlfe(struct zebra_dplane_ctx *ctx)
+const zebra_nhlfe_t *
+dplane_ctx_get_best_nhlfe(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -814,12 +827,12 @@ int dplane_ctx_get_pw_status(const struct zebra_dplane_ctx *ctx)
return ctx->u.pw.status;
}
-const union g_addr *dplane_ctx_get_pw_nexthop(
+const union g_addr *dplane_ctx_get_pw_dest(
const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
- return &(ctx->u.pw.nexthop);
+ return &(ctx->u.pw.dest);
}
const union pw_protocol_fields *dplane_ctx_get_pw_proto(
@@ -830,6 +843,14 @@ const union pw_protocol_fields *dplane_ctx_get_pw_proto(
return &(ctx->u.pw.fields);
}
+const struct nexthop_group *
+dplane_ctx_get_pw_nhg(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return &(ctx->u.pw.nhg);
+}
+
/*
* End of dplane context accessors
*/
@@ -1039,7 +1060,11 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
enum dplane_op_e op,
struct zebra_pw *pw)
{
- int ret = AOK;
+ struct prefix p;
+ afi_t afi;
+ struct route_table *table;
+ struct route_node *rn;
+ struct route_entry *re;
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
zlog_debug("init dplane ctx %s: pw '%s', loc %u, rem %u",
@@ -1058,6 +1083,7 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
/* This name appears to be c-string, so we use string copy. */
strlcpy(ctx->u.pw.ifname, pw->ifname, sizeof(ctx->u.pw.ifname));
+
ctx->zd_vrf_id = pw->vrf_id;
ctx->u.pw.ifindex = pw->ifindex;
ctx->u.pw.type = pw->type;
@@ -1066,11 +1092,38 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
ctx->u.pw.remote_label = pw->remote_label;
ctx->u.pw.flags = pw->flags;
- ctx->u.pw.nexthop = pw->nexthop;
+ ctx->u.pw.dest = pw->nexthop;
ctx->u.pw.fields = pw->data;
- return ret;
+ /* Capture nexthop info for the pw destination. We need to look
+ * up and use zebra datastructs, but we're running in the zebra
+ * pthread here so that should be ok.
+ */
+ memcpy(&p.u, &pw->nexthop, sizeof(pw->nexthop));
+ p.family = pw->af;
+ p.prefixlen = ((pw->af == AF_INET) ?
+ IPV4_MAX_PREFIXLEN : IPV6_MAX_PREFIXLEN);
+
+ afi = (pw->af == AF_INET) ? AFI_IP : AFI_IP6;
+ table = zebra_vrf_table(afi, SAFI_UNICAST, pw->vrf_id);
+ if (table) {
+ rn = route_node_match(table, &p);
+ if (rn) {
+ RNODE_FOREACH_RE(rn, re) {
+ if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
+ break;
+ }
+
+ if (re)
+ copy_nexthops(&(ctx->u.pw.nhg.nexthop),
+ re->ng.nexthop, NULL);
+
+ route_unlock_node(rn);
+ }
+ }
+
+ return AOK;
}
/*
@@ -1476,10 +1529,6 @@ int dplane_provider_register(const char *name,
/* Allocate and init new provider struct */
p = XCALLOC(MTYPE_DP_PROV, sizeof(struct zebra_dplane_provider));
- if (p == NULL) {
- ret = ENOMEM;
- goto done;
- }
pthread_mutex_init(&(p->dp_mutex), NULL);
TAILQ_INIT(&(p->dp_ctx_in_q));
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 81226961e8..149ff8dc60 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -203,8 +203,9 @@ const struct nexthop_group *dplane_ctx_get_old_ng(
mpls_label_t dplane_ctx_get_in_label(const struct zebra_dplane_ctx *ctx);
uint8_t dplane_ctx_get_addr_family(const struct zebra_dplane_ctx *ctx);
uint32_t dplane_ctx_get_lsp_flags(const struct zebra_dplane_ctx *ctx);
-zebra_nhlfe_t *dplane_ctx_get_nhlfe(struct zebra_dplane_ctx *ctx);
-zebra_nhlfe_t *dplane_ctx_get_best_nhlfe(struct zebra_dplane_ctx *ctx);
+const zebra_nhlfe_t *dplane_ctx_get_nhlfe(const struct zebra_dplane_ctx *ctx);
+const zebra_nhlfe_t *dplane_ctx_get_best_nhlfe(
+ const struct zebra_dplane_ctx *ctx);
uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx);
/* Accessors for pseudowire information */
@@ -215,10 +216,12 @@ int dplane_ctx_get_pw_type(const struct zebra_dplane_ctx *ctx);
int dplane_ctx_get_pw_af(const struct zebra_dplane_ctx *ctx);
uint32_t dplane_ctx_get_pw_flags(const struct zebra_dplane_ctx *ctx);
int dplane_ctx_get_pw_status(const struct zebra_dplane_ctx *ctx);
-const union g_addr *dplane_ctx_get_pw_nexthop(
+const union g_addr *dplane_ctx_get_pw_dest(
const struct zebra_dplane_ctx *ctx);
const union pw_protocol_fields *dplane_ctx_get_pw_proto(
const struct zebra_dplane_ctx *ctx);
+const struct nexthop_group *dplane_ctx_get_pw_nhg(
+ const struct zebra_dplane_ctx *ctx);
/* Namespace info - esp. for netlink communication */
const struct zebra_dplane_info *dplane_ctx_get_ns(
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index a06e15d90d..5c375a6bef 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -249,8 +249,7 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
lsp->ile.in_label, lsp->flags);
lsp = hash_release(lsp_table, &lsp->ile);
- if (lsp)
- XFREE(MTYPE_LSP, lsp);
+ XFREE(MTYPE_LSP, lsp);
}
return 0;
@@ -313,8 +312,7 @@ static int lsp_uninstall(struct zebra_vrf *zvrf, mpls_label_t label)
lsp->ile.in_label, lsp->flags);
lsp = hash_release(lsp_table, &lsp->ile);
- if (lsp)
- XFREE(MTYPE_LSP, lsp);
+ XFREE(MTYPE_LSP, lsp);
}
return 0;
@@ -1048,8 +1046,7 @@ static void lsp_processq_del(struct work_queue *wq, void *data)
lsp->ile.in_label, lsp->flags);
lsp = hash_release(lsp_table, &lsp->ile);
- if (lsp)
- XFREE(MTYPE_LSP, lsp);
+ XFREE(MTYPE_LSP, lsp);
}
}
@@ -1335,8 +1332,7 @@ static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp,
lsp->ile.in_label, lsp->flags);
lsp = hash_release(lsp_table, &lsp->ile);
- if (lsp)
- XFREE(MTYPE_LSP, lsp);
+ XFREE(MTYPE_LSP, lsp);
}
return 0;
@@ -1659,8 +1655,7 @@ static int snhlfe_del(zebra_snhlfe_t *snhlfe)
slsp->snhlfe_list = snhlfe->next;
snhlfe->prev = snhlfe->next = NULL;
- if (snhlfe->ifname)
- XFREE(MTYPE_SNHLFE_IFNAME, snhlfe->ifname);
+ XFREE(MTYPE_SNHLFE_IFNAME, snhlfe->ifname);
XFREE(MTYPE_SNHLFE, snhlfe);
return 0;
@@ -2539,8 +2534,7 @@ int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
lsp->ile.in_label, lsp->flags);
lsp = hash_release(lsp_table, &lsp->ile);
- if (lsp)
- XFREE(MTYPE_LSP, lsp);
+ XFREE(MTYPE_LSP, lsp);
}
}
return 0;
@@ -2784,8 +2778,7 @@ int zebra_mpls_static_lsp_del(struct zebra_vrf *zvrf, mpls_label_t in_label,
* above. */
if (!slsp->snhlfe_list) {
slsp = hash_release(slsp_table, &tmp_ile);
- if (slsp)
- XFREE(MTYPE_SLSP, slsp);
+ XFREE(MTYPE_SLSP, slsp);
}
return 0;
diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c
index 72c8f73522..977a8eaf3c 100644
--- a/zebra/zebra_mpls_openbsd.c
+++ b/zebra/zebra_mpls_openbsd.c
@@ -43,7 +43,7 @@ struct {
} kr_state;
static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label,
- zebra_nhlfe_t *nhlfe)
+ const zebra_nhlfe_t *nhlfe)
{
struct iovec iov[5];
struct rt_msghdr hdr;
@@ -135,7 +135,7 @@ static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label,
#endif
static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label,
- zebra_nhlfe_t *nhlfe)
+ const zebra_nhlfe_t *nhlfe)
{
struct iovec iov[5];
struct rt_msghdr hdr;
@@ -238,7 +238,7 @@ static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label,
static int kernel_lsp_cmd(struct zebra_dplane_ctx *ctx)
{
- zebra_nhlfe_t *nhlfe;
+ const zebra_nhlfe_t *nhlfe;
struct nexthop *nexthop = NULL;
unsigned int nexthop_num = 0;
int action;
@@ -342,7 +342,7 @@ static enum zebra_dplane_result kmpw_install(struct zebra_dplane_ctx *ctx)
/* pseudowire nexthop */
memset(&ss, 0, sizeof(ss));
- gaddr = dplane_ctx_get_pw_nexthop(ctx);
+ gaddr = dplane_ctx_get_pw_dest(ctx);
switch (dplane_ctx_get_pw_af(ctx)) {
case AF_INET:
sa_in->sin_family = AF_INET;
@@ -415,7 +415,7 @@ enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx)
break;
default:
break;
- };
+ }
return result;
}
diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c
index 348bdeb9fc..73db567eac 100644
--- a/zebra/zebra_pbr.c
+++ b/zebra/zebra_pbr.c
@@ -388,7 +388,7 @@ bool zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2)
r2 = (const struct zebra_pbr_iptable *)arg2;
if (r1->vrf_id != r2->vrf_id)
- return 0;
+ return false;
if (r1->type != r2->type)
return false;
if (r1->unique != r2->unique)
diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c
index 1e942d6433..cc5e38e690 100644
--- a/zebra/zebra_ptm.c
+++ b/zebra/zebra_ptm.c
@@ -1215,8 +1215,6 @@ static struct ptm_process *pp_new(pid_t pid, struct zserv *zs)
/* Allocate and register new process. */
pp = XCALLOC(MTYPE_ZEBRA_PTM_BFD_PROCESS, sizeof(*pp));
- if (pp == NULL)
- return NULL;
pp->pp_pid = pid;
pp->pp_zs = zs;
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 5f9210109d..2014aa3bed 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -276,10 +276,8 @@ struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re,
/*Pending: need to think if null ifp here is ok during bootup?
There was a crash because ifp here was coming to be NULL */
if (ifp)
- if (connected_is_unnumbered(ifp)
- || CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)) {
+ if (connected_is_unnumbered(ifp))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
- }
route_entry_nexthop_add(re, nexthop);
@@ -314,8 +312,6 @@ struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re,
nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
nexthop->gate.ipv6 = *ipv6;
nexthop->ifindex = ifindex;
- if (CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE))
- SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK);
route_entry_nexthop_add(re, nexthop);
@@ -433,10 +429,6 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
re->nexthop_mtu = 0;
}
- /* Next hops (remote VTEPs) for EVPN routes are fully resolved. */
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN_RVTEP))
- return 1;
-
/*
* If the kernel has sent us a route, then
* by golly gee whiz it's a good route.
@@ -459,6 +451,9 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
* Check to see if we should trust the passed in information
* for UNNUMBERED interfaces as that we won't find the GW
* address in the routing table.
+ * This check should suffice to handle IPv4 or IPv6 routes
+ * sourced from EVPN routes which are installed with the
+ * next hop as the remote VTEP IP.
*/
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) {
ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id);
@@ -2937,6 +2932,10 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
return;
}
+ /* Special handling for IPv4 or IPv6 routes sourced from
+ * EVPN - the nexthop (and associated MAC) need to be
+ * uninstalled if no more refs.
+ */
if (CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE)) {
struct nexthop *tmp_nh;
@@ -3236,7 +3235,6 @@ void rib_close_table(struct route_table *table)
*/
static int handle_pw_result(struct zebra_dplane_ctx *ctx)
{
- int ret = 0;
struct zebra_pw *pw;
struct zebra_vrf *vrf;
@@ -3255,7 +3253,7 @@ static int handle_pw_result(struct zebra_dplane_ctx *ctx)
done:
- return ret;
+ return 0;
}
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index 7d72583dd8..5d1cbbe781 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -127,10 +127,8 @@ static int zebra_route_match_delete(struct vty *vty, const char *command,
break;
}
- if (dep_name)
- XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
- if (rmap_name)
- XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
+ XFREE(MTYPE_ROUTE_MAP_RULE, dep_name);
+ XFREE(MTYPE_ROUTE_MAP_NAME, rmap_name);
return retval;
}
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index c3b861c242..cabc8be8dd 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -168,10 +168,31 @@ static void zebra_router_free_table(struct zebra_router_table *zrt)
table_info = route_table_get_info(zrt->table);
route_table_finish(zrt->table);
+ RB_REMOVE(zebra_router_table_head, &zrouter.tables, zrt);
+
XFREE(MTYPE_RIB_TABLE_INFO, table_info);
XFREE(MTYPE_ZEBRA_NS, zrt);
}
+void zebra_router_release_table(struct zebra_vrf *zvrf, uint32_t tableid,
+ afi_t afi, safi_t safi)
+{
+ struct zebra_router_table finder;
+ struct zebra_router_table *zrt;
+
+ memset(&finder, 0, sizeof(finder));
+ finder.afi = afi;
+ finder.safi = safi;
+ finder.tableid = tableid;
+ finder.ns_id = zvrf->zns->ns_id;
+ zrt = RB_FIND(zebra_router_table_head, &zrouter.tables, &finder);
+
+ if (!zrt)
+ return;
+
+ zebra_router_free_table(zrt);
+}
+
uint32_t zebra_router_get_next_sequence(void)
{
return 1
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index fb28495917..e5043f38ae 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -117,6 +117,8 @@ extern struct route_table *zebra_router_find_table(struct zebra_vrf *zvrf,
extern struct route_table *zebra_router_get_table(struct zebra_vrf *zvrf,
uint32_t tableid, afi_t afi,
safi_t safi);
+extern void zebra_router_release_table(struct zebra_vrf *zvrf, uint32_t tableid,
+ afi_t afi, safi_t safi);
extern int zebra_router_config_write(struct vty *vty);
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index d18305495b..1300ca24f3 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -208,8 +208,11 @@ static int zebra_vrf_disable(struct vrf *vrf)
* table, see rib_close_table above
* we no-longer need this pointer.
*/
- for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
+ for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
+ zebra_router_release_table(zvrf, zvrf->table_id, afi,
+ safi);
zvrf->table[afi][safi] = NULL;
+ }
route_table_finish(zvrf->rnh_table[afi]);
zvrf->rnh_table[afi] = NULL;
@@ -256,14 +259,12 @@ static int zebra_vrf_delete(struct vrf *vrf)
/* release allocated memory */
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
- void *table_info;
-
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
table = zvrf->table[afi][safi];
if (table) {
- table_info = route_table_get_info(table);
- route_table_finish(table);
- XFREE(MTYPE_RIB_TABLE_INFO, table_info);
+ zebra_router_release_table(zvrf, zvrf->table_id,
+ afi, safi);
+ zvrf->table[afi][safi] = NULL;
}
}
@@ -351,8 +352,7 @@ void zebra_rtable_node_cleanup(struct route_table *table,
rib_unlink(node, re);
}
- if (node->info)
- XFREE(MTYPE_RIB_DEST, node->info);
+ XFREE(MTYPE_RIB_DEST, node->info);
}
static void zebra_rnhtable_node_cleanup(struct route_table *table,
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 537820f7ea..b0884f22cf 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -383,6 +383,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object *json_labels = NULL;
time_t uptime;
struct tm *tm;
+ rib_dest_t *dest = rib_dest_from_rnode(rn);
uptime = time(NULL);
uptime -= re->uptime;
@@ -407,6 +408,10 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
json_object_boolean_true_add(json_route, "selected");
+ if (dest->selected_fib == re)
+ json_object_boolean_true_add(json_route,
+ "destSelected");
+
json_object_int_add(json_route, "distance",
re->distance);
json_object_int_add(json_route, "metric", re->metric);
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 7d4d5db6b0..00fc230851 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -2213,8 +2213,7 @@ static int zvni_neigh_del(zebra_vni_t *zvni, zebra_neigh_t *n)
/* Free the VNI hash entry and allocated memory. */
tmp_n = hash_release(zvni->neigh_table, n);
- if (tmp_n)
- XFREE(MTYPE_NEIGH, tmp_n);
+ XFREE(MTYPE_NEIGH, tmp_n);
return 0;
}
@@ -2987,8 +2986,12 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
}
zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
- if (!zvrf)
+ if (!zvrf) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("\tUnable to find vrf for: %d",
+ zvni->vxlan_if->vrf_id);
return -1;
+ }
/* Check if the neighbor exists. */
n = zvni_neigh_lookup(zvni, ip);
@@ -3018,6 +3021,9 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
cur_is_router = !!CHECK_FLAG(n->flags,
ZEBRA_NEIGH_ROUTER_FLAG);
if (!mac_different && is_router == cur_is_router) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "\tIgnoring entry mac is the same and is_router == cur_is_router");
n->ifindex = ifp->ifindex;
return 0;
}
@@ -3046,6 +3052,11 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
return zvni_neigh_send_add_to_client(
zvni->vni, ip, macaddr,
n->flags, n->loc_seq);
+ else {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "\tNeighbor active and frozen");
+ }
return 0;
}
@@ -3186,6 +3197,10 @@ static int zvni_local_neigh_update(zebra_vni_t *zvni,
if (!neigh_on_hold)
return zvni_neigh_send_add_to_client(zvni->vni, ip, macaddr,
n->flags, n->loc_seq);
+ else {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("\tNeighbor on hold not sending");
+ }
return 0;
}
@@ -3309,8 +3324,7 @@ static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac)
/* Free the VNI hash entry and allocated memory. */
tmp_mac = hash_release(zvni->mac_table, mac);
- if (tmp_mac)
- XFREE(MTYPE_MAC, tmp_mac);
+ XFREE(MTYPE_MAC, tmp_mac);
return 0;
}
@@ -3862,8 +3876,7 @@ static int zvni_del(zebra_vni_t *zvni)
/* Free the VNI hash entry and allocated memory. */
tmp_zvni = hash_release(zvrf->vni_table, zvni);
- if (tmp_zvni)
- XFREE(MTYPE_ZVNI, tmp_zvni);
+ XFREE(MTYPE_ZVNI, tmp_zvni);
return 0;
}
@@ -4299,8 +4312,7 @@ static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
}
tmp_rmac = hash_release(zl3vni->rmac_table, zrmac);
- if (tmp_rmac)
- XFREE(MTYPE_MAC, tmp_rmac);
+ XFREE(MTYPE_MAC, tmp_rmac);
return 0;
}
@@ -4476,8 +4488,7 @@ static int zl3vni_nh_del(zebra_l3vni_t *zl3vni, zebra_neigh_t *n)
}
tmp_n = hash_release(zl3vni->nh_table, n);
- if (tmp_n)
- XFREE(MTYPE_NEIGH, tmp_n);
+ XFREE(MTYPE_NEIGH, tmp_n);
return 0;
}
@@ -4709,8 +4720,7 @@ static int zl3vni_del(zebra_l3vni_t *zl3vni)
/* Free the VNI hash entry and allocated memory. */
tmp_zl3vni = hash_release(zrouter.l3vni_table, zl3vni);
- if (tmp_zl3vni)
- XFREE(MTYPE_ZL3VNI, tmp_zl3vni);
+ XFREE(MTYPE_ZL3VNI, tmp_zl3vni);
return 0;
}
@@ -4875,6 +4885,7 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
stream_put(s, &rmac, sizeof(struct ethaddr));
stream_put_in_addr(s, &zl3vni->local_vtep_ip);
stream_put(s, &zl3vni->filter, sizeof(int));
+ stream_putl(s, zl3vni->svi_if->ifindex);
/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
@@ -7090,9 +7101,10 @@ void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
zes.zvrf = zvrf;
/* Display all L2-VNIs */
- hash_iterate(zvrf->vni_table, (void (*)(struct hash_bucket *,
- void *))zvni_print_hash_detail,
- &zes);
+ hash_iterate(
+ zvrf->vni_table,
+ (void (*)(struct hash_bucket *, void *))zvni_print_hash_detail,
+ &zes);
/* Display all L3-VNIs */
hash_iterate(zrouter.l3vni_table,
@@ -7101,8 +7113,9 @@ void zebra_vxlan_print_vnis_detail(struct vty *vty, struct zebra_vrf *zvrf,
&zes);
if (use_json) {
- vty_out(vty, "%s\n", json_object_to_json_string_ext(
- json, JSON_C_TO_STRING_PRETTY));
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
json_object_free(json);
}
}
@@ -7582,7 +7595,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
if (!zvni) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "Add/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
+ "\tAdd/Update %sMAC %s intf %s(%u) VID %u, could not find VNI",
sticky ? "sticky " : "",
prefix_mac2str(macaddr, buf, sizeof(buf)),
ifp->name, ifp->ifindex, vid);
@@ -7590,15 +7603,20 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
}
if (!zvni->vxlan_if) {
- zlog_debug(
- "VNI %u hash %p doesn't have intf upon local MAC ADD",
- zvni->vni, zvni);
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug(
+ "\tVNI %u hash %p doesn't have intf upon local MAC ADD",
+ zvni->vni, zvni);
return -1;
}
zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
- if (!zvrf)
+ if (!zvrf) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("\tNo Vrf found for vrf_id: %d",
+ zvni->vxlan_if->vrf_id);
return -1;
+ }
/* Check if we need to create or update or it is a NO-OP. */
mac = zvni_mac_lookup(zvni, macaddr);
@@ -7648,7 +7666,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
&& mac->fwd_info.local.vid == vid) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
+ "\tAdd/Update %sMAC %s intf %s(%u) VID %u -> VNI %u, "
"entry exists and has not changed ",
sticky ? "sticky " : "",
prefix_mac2str(macaddr, buf,
@@ -9160,16 +9178,16 @@ static int zebra_vxlan_dad_ip_auto_recovery_exp(struct thread *t)
nbr = THREAD_ARG(t);
/* since this is asynchronous we need sanity checks*/
- nbr = zvni_neigh_lookup(zvni, &nbr->ip);
- if (!nbr)
+ zvrf = vrf_info_lookup(nbr->zvni->vrf_id);
+ if (!zvrf)
return 0;
zvni = zvni_lookup(nbr->zvni->vni);
if (!zvni)
return 0;
- zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
- if (!zvrf)
+ nbr = zvni_neigh_lookup(zvni, &nbr->ip);
+ if (!nbr)
return 0;
if (IS_ZEBRA_DEBUG_VXLAN)
@@ -9210,16 +9228,16 @@ static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t)
mac = THREAD_ARG(t);
/* since this is asynchronous we need sanity checks*/
- mac = zvni_mac_lookup(zvni, &mac->macaddr);
- if (!mac)
+ zvrf = vrf_info_lookup(mac->zvni->vrf_id);
+ if (!zvrf)
return 0;
zvni = zvni_lookup(mac->zvni->vni);
if (!zvni)
return 0;
- zvrf = vrf_info_lookup(zvni->vxlan_if->vrf_id);
- if (!zvrf)
+ mac = zvni_mac_lookup(zvni, &mac->macaddr);
+ if (!mac)
return 0;
if (IS_ZEBRA_DEBUG_VXLAN)