summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_mpath.c11
-rw-r--r--bgpd/bgp_nb_config.c8
-rw-r--r--bgpd/bgp_route.c37
-rw-r--r--bgpd/bgp_route.h2
-rw-r--r--bgpd/bgp_routemap.c39
-rw-r--r--bgpd/bgp_vty.c22
-rw-r--r--bgpd/bgpd.c4
-rw-r--r--doc/developer/tracing.rst72
-rw-r--r--doc/developer/workflow.rst2
-rw-r--r--isisd/isis_lsp.c12
-rw-r--r--isisd/isis_lsp.h4
-rw-r--r--isisd/isis_misc.c77
-rw-r--r--isisd/isis_vty_fabricd.c2
-rw-r--r--lib/agentx.c13
-rw-r--r--lib/northbound.c60
-rw-r--r--lib/northbound.h13
-rw-r--r--lib/prefix.c4
-rw-r--r--lib/prefix.h2
-rw-r--r--lib/routing_nb.h7
-rw-r--r--lib/routing_nb_config.c61
-rw-r--r--lib/smux.h4
-rw-r--r--lib/vrf.c7
-rw-r--r--lib/vrf.h3
-rw-r--r--lib/vty.c6
-rw-r--r--ospf6d/ospf6_abr.c6
-rw-r--r--ospf6d/ospf6_asbr.c9
-rw-r--r--ospf6d/ospf6_intra.c8
-rw-r--r--ospfd/ospf_dump.c70
-rw-r--r--ospfd/ospf_main.c20
-rw-r--r--ospfd/ospf_vty.c220
-rw-r--r--ospfd/ospfd.c26
-rw-r--r--ospfd/ospfd.h3
-rw-r--r--pimd/pim_main.c2
-rw-r--r--staticd/static_main.c2
-rw-r--r--tests/topotests/bgp-aggregator-zero/__init__.py0
-rw-r--r--tests/topotests/bgp-aggregator-zero/exabgp.env53
-rw-r--r--tests/topotests/bgp-aggregator-zero/peer1/exabgp.cfg18
-rw-r--r--tests/topotests/bgp-aggregator-zero/r1/bgpd.conf6
-rw-r--r--tests/topotests/bgp-aggregator-zero/r1/zebra.conf6
-rw-r--r--tests/topotests/bgp-aggregator-zero/test_bgp_aggregator_zero.py139
-rw-r--r--vtysh/vtysh.c2
-rw-r--r--zebra/if_netlink.c2
-rw-r--r--zebra/interface.c5
-rw-r--r--zebra/irdp_interface.c18
-rw-r--r--zebra/rt_netlink.c4
-rw-r--r--zebra/zebra_evpn.c25
-rw-r--r--zebra/zebra_evpn_mac.c76
-rw-r--r--zebra/zebra_evpn_mac.h13
-rw-r--r--zebra/zebra_evpn_mh.c168
-rw-r--r--zebra/zebra_evpn_mh.h19
-rw-r--r--zebra/zebra_evpn_neigh.c2
-rw-r--r--zebra/zebra_vxlan.c19
52 files changed, 1069 insertions, 344 deletions
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index ff5cfe05fb..37639f4bce 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -616,7 +616,8 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest,
all_paths_lb = false;
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- cur_mpath, path_buf);
+ cur_mpath, path_buf,
+ sizeof(path_buf));
zlog_debug(
"%pRN: %s is still multipath, cur count %d",
bgp_dest_to_rnode(dest),
@@ -626,7 +627,8 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest,
mpath_changed = 1;
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- cur_mpath, path_buf);
+ cur_mpath, path_buf,
+ sizeof(path_buf));
zlog_debug(
"%pRN: remove mpath %s nexthop %s, cur count %d",
bgp_dest_to_rnode(dest),
@@ -660,7 +662,7 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest,
mpath_changed = 1;
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- cur_mpath, path_buf);
+ cur_mpath, path_buf, sizeof(path_buf));
zlog_debug(
"%pRN: remove mpath %s nexthop %s, cur count %d",
bgp_dest_to_rnode(dest), path_buf,
@@ -710,7 +712,8 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest,
all_paths_lb = false;
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- new_mpath, path_buf);
+ new_mpath, path_buf,
+ sizeof(path_buf));
zlog_debug(
"%pRN: add mpath %s nexthop %s, cur count %d",
bgp_dest_to_rnode(dest),
diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c
index a3f58db88f..721ce5b5c6 100644
--- a/bgpd/bgp_nb_config.c
+++ b/bgpd/bgp_nb_config.c
@@ -69,7 +69,7 @@ int bgp_router_create(struct nb_cb_create_args *args)
{
const struct lyd_node *vrf_dnode;
struct bgp *bgp;
- struct vrf *vrf;
+ const char *vrf_name;
const char *name = NULL;
as_t as;
enum bgp_instance_type inst_type;
@@ -87,12 +87,12 @@ int bgp_router_create(struct nb_cb_create_args *args)
case NB_EV_APPLY:
vrf_dnode = yang_dnode_get_parent(args->dnode,
"control-plane-protocol");
- vrf = nb_running_get_entry(vrf_dnode, NULL, true);
+ vrf_name = yang_dnode_get_string(vrf_dnode, "./vrf");
- if (strmatch(vrf->name, VRF_DEFAULT_NAME)) {
+ if (strmatch(vrf_name, VRF_DEFAULT_NAME)) {
name = NULL;
} else {
- name = vrf->name;
+ name = vrf_name;
inst_type = BGP_INSTANCE_TYPE_VRF;
}
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 0f135985ed..18a0b3fb7d 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -525,13 +525,14 @@ static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
}
}
-void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
+void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
+ size_t buf_len)
{
if (pi->addpath_rx_id)
- sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
- pi->addpath_rx_id);
+ snprintf(buf, buf_len, "path %s (addpath rxid %d)",
+ pi->peer->host, pi->addpath_rx_id);
else
- sprintf(buf, "path %s", pi->peer->host);
+ snprintf(buf, buf_len, "path %s", pi->peer->host);
}
/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
@@ -582,7 +583,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
if (debug)
- bgp_path_info_path_with_addpath_rx_str(new, new_buf);
+ bgp_path_info_path_with_addpath_rx_str(new, new_buf,
+ sizeof(new_buf));
if (exist == NULL) {
*reason = bgp_path_selection_first;
@@ -593,7 +595,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
if (debug) {
- bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
+ bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
+ sizeof(exist_buf));
zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
pfx_buf, new_buf, new->flags, exist_buf,
exist->flags);
@@ -621,10 +624,10 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
prefix2str(
bgp_dest_get_prefix(new->net), pfx_buf,
sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
- bgp_path_info_path_with_addpath_rx_str(new,
- new_buf);
bgp_path_info_path_with_addpath_rx_str(
- exist, exist_buf);
+ new, new_buf, sizeof(new_buf));
+ bgp_path_info_path_with_addpath_rx_str(
+ exist, exist_buf, sizeof(exist_buf));
}
if (newattr->sticky && !existattr->sticky) {
@@ -2348,7 +2351,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- new_select, path_buf);
+ new_select, path_buf, sizeof(path_buf));
zlog_debug(
"%pBD: %s is the bestpath from AS %u",
dest, path_buf,
@@ -2422,8 +2425,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
*/
if (debug) {
if (new_select)
- bgp_path_info_path_with_addpath_rx_str(new_select,
- path_buf);
+ bgp_path_info_path_with_addpath_rx_str(
+ new_select, path_buf, sizeof(path_buf));
else
snprintf(path_buf, sizeof(path_buf), "NONE");
zlog_debug(
@@ -2438,7 +2441,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
if (debug)
bgp_path_info_path_with_addpath_rx_str(
- pi, path_buf);
+ pi, path_buf, sizeof(path_buf));
if (pi == new_select) {
if (debug)
@@ -6389,7 +6392,8 @@ DEFPY_YANG (bgp_network, bgp_network_cmd,
int ret;
ret = netmask_str2prefix_str(address_str, netmask_str,
- addr_prefix_str);
+ addr_prefix_str,
+ sizeof(addr_prefix_str));
if (!ret) {
vty_out(vty, "%% Inconsistent address and mask\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -7780,7 +7784,8 @@ DEFPY_YANG(
char prefix_buf[PREFIX2STR_BUFFER];
if (addr_str) {
- if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
+ if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
+ sizeof(prefix_buf))
== 0) {
vty_out(vty, "%% Inconsistent address and mask\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -14398,7 +14403,7 @@ DEFUN (clear_ip_bgp_dampening_address_mask,
char prefix_str[BUFSIZ];
ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
- prefix_str);
+ prefix_str, sizeof(prefix_str));
if (!ret) {
vty_out(vty, "%% Inconsistent address and mask\n");
return CMD_WARNING;
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 1060d2e60d..766e5ade92 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -598,7 +598,7 @@ extern void bgp_path_info_set_flag(struct bgp_dest *dest,
extern void bgp_path_info_unset_flag(struct bgp_dest *dest,
struct bgp_path_info *path, uint32_t flag);
extern void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi,
- char *buf);
+ char *buf, size_t buf_len);
extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 3dc2cfbd5c..b7f3289ffc 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -4315,13 +4315,15 @@ DEFUN (match_community,
int idx_comm_list = 2;
int ret;
char *argstr;
+ size_t argstr_len;
if (argc == 4) {
- argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
- strlen(argv[idx_comm_list]->arg)
- + strlen("exact-match") + 2);
+ argstr_len = strlen(argv[idx_comm_list]->arg)
+ + strlen("exact-match") + 2;
+ argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
- sprintf(argstr, "%s exact-match", argv[idx_comm_list]->arg);
+ snprintf(argstr, argstr_len, "%s exact-match",
+ argv[idx_comm_list]->arg);
} else
argstr = argv[idx_comm_list]->arg;
@@ -4362,13 +4364,15 @@ DEFUN (match_lcommunity,
int idx_lcomm_list = 2;
int ret;
char *argstr;
+ size_t argstr_len;
if (argc == 4) {
- argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
- strlen(argv[idx_lcomm_list]->arg)
- + strlen("exact-match") + 2);
+ argstr_len = strlen(argv[idx_lcomm_list]->arg)
+ + strlen("exact-match") + 2;
+ argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
- sprintf(argstr, "%s exact-match", argv[idx_lcomm_list]->arg);
+ snprintf(argstr, argstr_len, "%s exact-match",
+ argv[idx_lcomm_list]->arg);
} else
argstr = argv[idx_lcomm_list]->arg;
@@ -5252,6 +5256,7 @@ DEFUN (set_aggregator_as,
int ret;
struct in_addr address;
char *argstr;
+ size_t argstr_len;
ret = inet_aton(argv[idx_ipv4]->arg, &address);
if (ret == 0) {
@@ -5259,11 +5264,12 @@ DEFUN (set_aggregator_as,
return CMD_WARNING_CONFIG_FAILED;
}
- argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
- strlen(argv[idx_number]->arg)
- + strlen(argv[idx_ipv4]->arg) + 2);
+ argstr_len =
+ strlen(argv[idx_number]->arg) + strlen(argv[idx_ipv4]->arg) + 2;
+ argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
- sprintf(argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
+ snprintf(argstr, argstr_len, "%s %s", argv[idx_number]->arg,
+ argv[idx_ipv4]->arg);
ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
"aggregator as", argstr);
@@ -5289,6 +5295,7 @@ DEFUN (no_set_aggregator_as,
int ret;
struct in_addr address;
char *argstr;
+ size_t argstr_len;
if (argc <= idx_asn)
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
@@ -5300,11 +5307,11 @@ DEFUN (no_set_aggregator_as,
return CMD_WARNING_CONFIG_FAILED;
}
- argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
- strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg)
- + 2);
+ argstr_len = strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg) + 2;
+ argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
- sprintf(argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
+ snprintf(argstr, argstr_len, "%s %s", argv[idx_asn]->arg,
+ argv[idx_ip]->arg);
ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
"aggregator as", argstr);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index ab9e8af96d..9e8065691e 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -1483,8 +1483,26 @@ DEFUN_YANG(no_router_bgp,
struct bgp *tmp_bgp;
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, tmp_bgp)) {
- if (tmp_bgp->inst_type
- == BGP_INSTANCE_TYPE_VRF) {
+ if (tmp_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+ continue;
+ if (CHECK_FLAG(tmp_bgp->af_flags[AFI_IP][SAFI_UNICAST],
+ BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6][SAFI_UNICAST],
+ BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT) ||
+ (bgp == bgp_get_evpn() &&
+ (CHECK_FLAG(tmp_bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))) ||
+ (tmp_bgp->vnihash && hashcount(tmp_bgp->vnihash))) {
vty_out(vty,
"%% Cannot delete default BGP instance. Dependent VRF instances exist\n");
return CMD_WARNING_CONFIG_FAILED;
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index b11fd5288a..07ca247ee6 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -5246,8 +5246,8 @@ int peer_timers_set(struct peer *peer, uint32_t keepalive, uint32_t holdtime)
/* Set flag and configuration on peer-group member. */
SET_FLAG(member->flags, PEER_FLAG_TIMER);
- PEER_ATTR_INHERIT(peer, peer->group, holdtime);
- PEER_ATTR_INHERIT(peer, peer->group, keepalive);
+ PEER_ATTR_INHERIT(member, peer->group, holdtime);
+ PEER_ATTR_INHERIT(member, peer->group, keepalive);
}
return 0;
diff --git a/doc/developer/tracing.rst b/doc/developer/tracing.rst
index c194ae1270..71f7b4ac49 100644
--- a/doc/developer/tracing.rst
+++ b/doc/developer/tracing.rst
@@ -173,6 +173,78 @@ Example::
When using LTTng, you can also get zlogs as trace events by enabling
the ``lttng_ust_tracelog:*`` event class.
+To see available SystemTap USDT probes, run::
+
+ stap -L 'process("/usr/lib/frr/bgpd").mark("*")'
+
+Example::
+
+ root@host ~> stap -L 'process("/usr/lib/frr/bgpd").mark("*")'
+ process("/usr/lib/frr/bgpd").mark("capability_process") $arg1:long $arg2:long
+ process("/usr/lib/frr/bgpd").mark("input_filter") $arg1:long $arg2:long $arg3:long $arg4:long $arg5:long
+ process("/usr/lib/frr/bgpd").mark("keepalive_process") $arg1:long $arg2:long
+ process("/usr/lib/frr/bgpd").mark("notification_process") $arg1:long $arg2:long
+ process("/usr/lib/frr/bgpd").mark("open_process") $arg1:long $arg2:long
+ process("/usr/lib/frr/bgpd").mark("output_filter") $arg1:long $arg2:long $arg3:long $arg4:long $arg5:long
+ process("/usr/lib/frr/bgpd").mark("packet_read") $arg1:long $arg2:long
+ process("/usr/lib/frr/bgpd").mark("process_update") $arg1:long $arg2:long $arg3:long $arg4:long $arg5:long $arg6:long
+ process("/usr/lib/frr/bgpd").mark("refresh_process") $arg1:long $arg2:long
+ process("/usr/lib/frr/bgpd").mark("update_process") $arg1:long $arg2:long
+
+When using SystemTap, you can also easily attach to an existing function::
+
+ stap -L 'process("/usr/lib/frr/bgpd").function("bgp_update_receive")'
+
+Example::
+
+ root@host ~> stap -L 'process("/usr/lib/frr/bgpd").function("bgp_update_receive")'
+ process("/usr/lib/frr/bgpd").function("bgp_update_receive@bgpd/bgp_packet.c:1531") $peer:struct peer* $size:bgp_size_t $attr:struct attr $restart:_Bool $nlris:struct bgp_nlri[] $__func__:char const[] const
+
+Complete ``bgp.stp`` example using SystemTap to show BGP peer, prefix and aspath
+using ``process_update`` USDT::
+
+ global pkt_size;
+ probe begin
+ {
+ ansi_clear_screen();
+ println("Starting...");
+ }
+ probe process("/usr/lib/frr/bgpd").function("bgp_update_receive")
+ {
+ pkt_size <<< $size;
+ }
+ probe process("/usr/lib/frr/bgpd").mark("process_update")
+ {
+ aspath = @cast($arg6, "attr")->aspath;
+ printf("> %s via %s (%s)\n",
+ user_string($arg2),
+ user_string(@cast($arg1, "peer")->host),
+ user_string(@cast(aspath, "aspath")->str));
+ }
+ probe end
+ {
+ if (@count(pkt_size))
+ print(@hist_linear(pkt_size, 0, 20, 2));
+ }
+
+Output::
+
+ Starting...
+ > 192.168.0.0/24 via 192.168.0.1 (65534)
+ > 192.168.100.1/32 via 192.168.0.1 (65534)
+ > 172.16.16.1/32 via 192.168.0.1 (65534 65030)
+ ^Cvalue |-------------------------------------------------- count
+ 0 | 0
+ 2 | 0
+ 4 |@ 1
+ 6 | 0
+ 8 | 0
+ ~
+ 18 | 0
+ 20 | 0
+ >20 |@@@@@ 5
+
+
Concepts
--------
diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst
index 41f56e3a03..abdbea5a9c 100644
--- a/doc/developer/workflow.rst
+++ b/doc/developer/workflow.rst
@@ -563,7 +563,7 @@ In general, code submitted into FRR will be rejected if it uses unsafe
programming practices. While there is no enforced overall ruleset, the
following requirements have achieved consensus:
-- ``strcpy``, ``strcat`` and ``sprintf`` are inacceptable without exception.
+- ``strcpy``, ``strcat`` and ``sprintf`` are unacceptable without exception.
Use ``strlcpy``, ``strlcat`` and ``snprintf`` instead. (Rationale: even if
you know the operation cannot overflow the buffer, a future code change may
inadvertedly introduce an overflow.)
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 6d2303817b..a17d9a6ae2 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -691,8 +691,8 @@ static void lsp_set_time(struct isis_lsp *lsp)
stream_putw_at(lsp->pdu, 10, lsp->hdr.rem_lifetime);
}
-void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag,
- struct isis *isis)
+void lspid_print(uint8_t *lsp_id, char *dest, size_t dest_len, char dynhost,
+ char frag, struct isis *isis)
{
struct isis_dynhn *dyn = NULL;
char id[SYSID_STRLEN];
@@ -710,10 +710,10 @@ void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag,
memcpy(id, sysid_print(lsp_id), 15);
if (frag)
- sprintf(dest, "%s.%02x-%02x", id, LSP_PSEUDO_ID(lsp_id),
- LSP_FRAGMENT(lsp_id));
+ snprintf(dest, dest_len, "%s.%02x-%02x", id,
+ LSP_PSEUDO_ID(lsp_id), LSP_FRAGMENT(lsp_id));
else
- sprintf(dest, "%s.%02x", id, LSP_PSEUDO_ID(lsp_id));
+ snprintf(dest, dest_len, "%s.%02x", id, LSP_PSEUDO_ID(lsp_id));
}
/* Convert the lsp attribute bits to attribute string */
@@ -747,7 +747,7 @@ void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost,
char age_out[8];
char b[200];
- lspid_print(lsp->hdr.lsp_id, LSPid, dynhost, 1, isis);
+ lspid_print(lsp->hdr.lsp_id, LSPid, sizeof(LSPid), dynhost, 1, isis);
vty_out(vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' ');
vty_out(vty, "%5hu ", lsp->hdr.pdu_len);
vty_out(vty, "0x%08x ", lsp->hdr.seqno);
diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h
index 0783036e49..896d957607 100644
--- a/isisd/isis_lsp.h
+++ b/isisd/isis_lsp.h
@@ -116,8 +116,8 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
struct isis_tlvs *tlvs, struct stream *stream,
struct isis_area *area, int level, bool confusion);
void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno);
-void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag,
- struct isis *isis);
+void lspid_print(uint8_t *lsp_id, char *dest, size_t dest_len, char dynhost,
+ char frag, struct isis *isis);
void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost,
struct isis *isis);
void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost,
diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c
index 6e9cbaf98e..d3d081d376 100644
--- a/isisd/isis_misc.c
+++ b/isisd/isis_misc.c
@@ -59,27 +59,30 @@ char nlpidstring[30];
const char *isonet_print(const uint8_t *from, int len)
{
int i = 0;
- char *pos = isonet;
+ char tbuf[4];
+ isonet[0] = '\0';
if (!from)
return "unknown";
while (i < len) {
if (i & 1) {
- sprintf(pos, "%02x", *(from + i));
- pos += 2;
+ snprintf(tbuf, sizeof(tbuf), "%02x", *(from + i));
+ strlcat(isonet, tbuf, sizeof(isonet));
} else {
if (i == (len - 1)) { /* No dot at the end of address */
- sprintf(pos, "%02x", *(from + i));
- pos += 2;
+ snprintf(tbuf, sizeof(tbuf), "%02x",
+ *(from + i));
+ strlcat(isonet, tbuf, sizeof(isonet));
} else {
- sprintf(pos, "%02x.", *(from + i));
- pos += 3;
+ snprintf(tbuf, sizeof(tbuf), "%02x.",
+ *(from + i));
+ strlcat(isonet, tbuf, sizeof(isonet));
}
}
i++;
}
- *(pos) = '\0';
+
return isonet;
}
@@ -202,17 +205,18 @@ const char *nlpid2str(uint8_t nlpid)
char *nlpid2string(struct nlpids *nlpids)
{
- char *pos = nlpidstring;
int i;
+ char tbuf[256];
+ nlpidstring[0] = '\0';
for (i = 0; i < nlpids->count; i++) {
- pos += sprintf(pos, "%s", nlpid2str(nlpids->nlpids[i]));
+ snprintf(tbuf, sizeof(tbuf), "%s",
+ nlpid2str(nlpids->nlpids[i]));
+ strlcat(nlpidstring, tbuf, sizeof(nlpidstring));
if (nlpids->count - i > 1)
- pos += sprintf(pos, ", ");
+ strlcat(nlpidstring, ", ", sizeof(nlpidstring));
}
- *(pos) = '\0';
-
return nlpidstring;
}
@@ -359,34 +363,47 @@ const char *isis_format_id(const uint8_t *id, size_t len)
const char *time2string(uint32_t time)
{
- char *pos = datestring;
uint32_t rest;
+ char tbuf[32];
+ datestring[0] = '\0';
if (time == 0)
return "-";
- if (time / SECS_PER_YEAR)
- pos += sprintf(pos, "%uY", time / SECS_PER_YEAR);
+ if (time / SECS_PER_YEAR) {
+ snprintf(tbuf, sizeof(tbuf), "%uY", time / SECS_PER_YEAR);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = time % SECS_PER_YEAR;
- if (rest / SECS_PER_MONTH)
- pos += sprintf(pos, "%uM", rest / SECS_PER_MONTH);
+ if (rest / SECS_PER_MONTH) {
+ snprintf(tbuf, sizeof(tbuf), "%uM", rest / SECS_PER_MONTH);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_MONTH;
- if (rest / SECS_PER_WEEK)
- pos += sprintf(pos, "%uw", rest / SECS_PER_WEEK);
+ if (rest / SECS_PER_WEEK) {
+ snprintf(tbuf, sizeof(tbuf), "%uw", rest / SECS_PER_WEEK);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_WEEK;
- if (rest / SECS_PER_DAY)
- pos += sprintf(pos, "%ud", rest / SECS_PER_DAY);
+ if (rest / SECS_PER_DAY) {
+ snprintf(tbuf, sizeof(tbuf), "%ud", rest / SECS_PER_DAY);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_DAY;
- if (rest / SECS_PER_HOUR)
- pos += sprintf(pos, "%uh", rest / SECS_PER_HOUR);
+ if (rest / SECS_PER_HOUR) {
+ snprintf(tbuf, sizeof(tbuf), "%uh", rest / SECS_PER_HOUR);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_HOUR;
- if (rest / SECS_PER_MINUTE)
- pos += sprintf(pos, "%um", rest / SECS_PER_MINUTE);
+ if (rest / SECS_PER_MINUTE) {
+ snprintf(tbuf, sizeof(tbuf), "%um", rest / SECS_PER_MINUTE);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_MINUTE;
- if (rest)
- pos += sprintf(pos, "%us", rest);
-
- *(pos) = 0;
+ if (rest) {
+ snprintf(tbuf, sizeof(tbuf), "%us", rest);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
return datestring;
}
diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c
index d0a411a8db..6055984195 100644
--- a/isisd/isis_vty_fabricd.c
+++ b/isisd/isis_vty_fabricd.c
@@ -118,7 +118,7 @@ static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp,
char lspid[255];
char buf[MONOTIME_STRLEN];
- lspid_print(lsp->hdr.lsp_id, lspid, true, true, isis);
+ lspid_print(lsp->hdr.lsp_id, lspid, sizeof(lspid), true, true, isis);
vty_out(vty, "Flooding information for %s\n", lspid);
if (!lsp->flooding_neighbors[TX_LSP_NORMAL]) {
diff --git a/lib/agentx.c b/lib/agentx.c
index 5351f8bda2..c8d7d75a81 100644
--- a/lib/agentx.c
+++ b/lib/agentx.c
@@ -36,6 +36,8 @@
XREF_SETUP()
+DEFINE_HOOK(agentx_enabled, (), ())
+
static int agentx_enabled = 0;
static struct thread_master *agentx_tm;
@@ -226,6 +228,7 @@ DEFUN (agentx_enable,
events = list_new();
agentx_events_update();
agentx_enabled = 1;
+ hook_call(agentx_enabled);
}
return CMD_SUCCESS;
@@ -259,6 +262,16 @@ void smux_init(struct thread_master *tm)
install_element(CONFIG_NODE, &no_agentx_cmd);
}
+void smux_agentx_enable(void)
+{
+ if (!agentx_enabled) {
+ init_snmp(FRR_SMUX_NAME);
+ events = list_new();
+ agentx_events_update();
+ agentx_enabled = 1;
+ }
+}
+
void smux_register_mib(const char *descr, struct variable *var, size_t width,
int num, oid name[], size_t namelen)
{
diff --git a/lib/northbound.c b/lib/northbound.c
index ecfa2c9d11..224951b22b 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -185,6 +185,25 @@ struct nb_node *nb_node_find(const char *xpath)
return snode->priv;
}
+void nb_node_set_dependency_cbs(const char *dependency_xpath,
+ const char *dependant_xpath,
+ struct nb_dependency_callbacks *cbs)
+{
+ struct nb_node *dependency = nb_node_find(dependency_xpath);
+ struct nb_node *dependant = nb_node_find(dependant_xpath);
+
+ if (!dependency || !dependant)
+ return;
+
+ dependency->dep_cbs.get_dependant_xpath = cbs->get_dependant_xpath;
+ dependant->dep_cbs.get_dependency_xpath = cbs->get_dependency_xpath;
+}
+
+bool nb_node_has_dependency(struct nb_node *node)
+{
+ return node->dep_cbs.get_dependency_xpath != NULL;
+}
+
static int nb_node_validate_cb(const struct nb_node *nb_node,
enum nb_operation operation,
int callback_implemented, bool optional)
@@ -532,8 +551,9 @@ int nb_candidate_edit(struct nb_config *candidate,
const struct yang_data *previous,
const struct yang_data *data)
{
- struct lyd_node *dnode;
+ struct lyd_node *dnode, *dep_dnode;
char xpath_edit[XPATH_MAXLEN];
+ char dep_xpath[XPATH_MAXLEN];
/* Use special notation for leaf-lists (RFC 6020, section 9.13.5). */
if (nb_node->snode->nodetype == LYS_LEAFLIST)
@@ -549,9 +569,33 @@ int nb_candidate_edit(struct nb_config *candidate,
dnode = lyd_new_path(candidate->dnode, ly_native_ctx,
xpath_edit, (void *)data->value, 0,
LYD_PATH_OPT_UPDATE);
- if (!dnode && ly_errno) {
- flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed",
- __func__);
+ if (dnode) {
+ /*
+ * create dependency
+ *
+ * dnode returned by the lyd_new_path may be from a
+ * different schema, so we need to update the nb_node
+ */
+ nb_node = dnode->schema->priv;
+ if (nb_node->dep_cbs.get_dependency_xpath) {
+ nb_node->dep_cbs.get_dependency_xpath(
+ dnode, dep_xpath);
+
+ ly_errno = 0;
+ dep_dnode = lyd_new_path(candidate->dnode,
+ ly_native_ctx,
+ dep_xpath, NULL, 0,
+ LYD_PATH_OPT_UPDATE);
+ if (!dep_dnode && ly_errno) {
+ flog_warn(EC_LIB_LIBYANG,
+ "%s: lyd_new_path(%s) failed",
+ __func__, dep_xpath);
+ return NB_ERR;
+ }
+ }
+ } else if (ly_errno) {
+ flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path(%s) failed",
+ __func__, xpath_edit);
return NB_ERR;
}
break;
@@ -563,6 +607,14 @@ int nb_candidate_edit(struct nb_config *candidate,
* whether to ignore it or not.
*/
return NB_ERR_NOT_FOUND;
+ /* destroy dependant */
+ if (nb_node->dep_cbs.get_dependant_xpath) {
+ nb_node->dep_cbs.get_dependant_xpath(dnode, dep_xpath);
+
+ dep_dnode = yang_dnode_get(candidate->dnode, dep_xpath);
+ if (dep_dnode)
+ lyd_free(dep_dnode);
+ }
lyd_free(dnode);
break;
case NB_OP_MOVE:
diff --git a/lib/northbound.h b/lib/northbound.h
index 8dd6b4c337..3e1342f985 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -509,6 +509,11 @@ struct nb_callbacks {
void (*cli_show_end)(struct vty *vty, struct lyd_node *dnode);
};
+struct nb_dependency_callbacks {
+ void (*get_dependant_xpath)(const struct lyd_node *dnode, char *xpath);
+ void (*get_dependency_xpath)(const struct lyd_node *dnode, char *xpath);
+};
+
/*
* Northbound-specific data that is allocated for each schema node of the native
* YANG modules.
@@ -523,6 +528,8 @@ struct nb_node {
/* Priority - lower priorities are processed first. */
uint32_t priority;
+ struct nb_dependency_callbacks dep_cbs;
+
/* Callbacks implemented for this node. */
struct nb_callbacks cbs;
@@ -722,6 +729,12 @@ void nb_nodes_delete(void);
*/
extern struct nb_node *nb_node_find(const char *xpath);
+extern void nb_node_set_dependency_cbs(const char *dependency_xpath,
+ const char *dependant_xpath,
+ struct nb_dependency_callbacks *cbs);
+
+bool nb_node_has_dependency(struct nb_node *node);
+
/*
* Create a new northbound configuration.
*
diff --git a/lib/prefix.c b/lib/prefix.c
index 663a87afde..c98e0c1c72 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -1160,7 +1160,7 @@ in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen)
ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
int netmask_str2prefix_str(const char *net_str, const char *mask_str,
- char *prefix_str)
+ char *prefix_str, size_t prefix_str_len)
{
struct in_addr network;
struct in_addr mask;
@@ -1193,7 +1193,7 @@ int netmask_str2prefix_str(const char *net_str, const char *mask_str,
return 0;
}
- sprintf(prefix_str, "%s/%d", net_str, prefixlen);
+ snprintf(prefix_str, prefix_str_len, "%s/%d", net_str, prefixlen);
return 1;
}
diff --git a/lib/prefix.h b/lib/prefix.h
index b7fdc26369..b2f3b0592f 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -491,7 +491,7 @@ extern void masklen2ip(const int, struct in_addr *);
* special treatment for /31 according to RFC3021 section 3.3 */
extern in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen);
-extern int netmask_str2prefix_str(const char *, const char *, char *);
+extern int netmask_str2prefix_str(const char *, const char *, char *, size_t);
extern struct prefix_ipv6 *prefix_ipv6_new(void);
extern void prefix_ipv6_free(struct prefix_ipv6 **p);
diff --git a/lib/routing_nb.h b/lib/routing_nb.h
index d1b59ea29e..ffba631a10 100644
--- a/lib/routing_nb.h
+++ b/lib/routing_nb.h
@@ -15,10 +15,17 @@ int routing_control_plane_protocols_control_plane_protocol_destroy(
#define FRR_ROUTING_KEY_XPATH \
"/frr-routing:routing/control-plane-protocols/" \
"control-plane-protocol[type='%s'][name='%s'][vrf='%s']"
+
+#define FRR_ROUTING_KEY_XPATH_VRF \
+ "/frr-routing:routing/control-plane-protocols/" \
+ "control-plane-protocol[vrf='%s']"
+
/*
* callbacks for routing to handle configuration events
* based on the control plane protocol
*/
DECLARE_HOOK(routing_conf_event, (struct nb_cb_create_args *args), (args))
+void routing_control_plane_protocols_register_vrf_dependency(void);
+
#endif /* _FRR_ROUTING_NB_H_ */
diff --git a/lib/routing_nb_config.c b/lib/routing_nb_config.c
index b789e8494e..17698d2b87 100644
--- a/lib/routing_nb_config.c
+++ b/lib/routing_nb_config.c
@@ -45,15 +45,21 @@ int routing_control_plane_protocols_control_plane_protocol_create(
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- vrfname = yang_dnode_get_string(args->dnode, "./vrf");
- vrf = vrf_lookup_by_name(vrfname);
- vrf = vrf ? vrf : vrf_get(VRF_UNKNOWN, vrfname);
- if (!vrf) {
- flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
- "vrf creation %s failed", vrfname);
- return NB_ERR;
+ /*
+ * If the daemon relies on the VRF pointer stored in this
+ * dnode, then it should register the dependency between this
+ * module and the VRF module using
+ * routing_control_plane_protocols_register_vrf_dependency.
+ * If such dependency is not registered, then nothing is
+ * stored in the dnode. If the dependency is registered,
+ * find the vrf and store the pointer.
+ */
+ if (nb_node_has_dependency(args->dnode->schema->priv)) {
+ vrfname = yang_dnode_get_string(args->dnode, "./vrf");
+ vrf = vrf_lookup_by_name(vrfname);
+ assert(vrf);
+ nb_running_set_entry(args->dnode, vrf);
}
- nb_running_set_entry(args->dnode, vrf);
break;
};
@@ -63,12 +69,45 @@ int routing_control_plane_protocols_control_plane_protocol_create(
int routing_control_plane_protocols_control_plane_protocol_destroy(
struct nb_cb_destroy_args *args)
{
- struct vrf *vrf __attribute__((unused));
-
if (args->event != NB_EV_APPLY)
return NB_OK;
- vrf = nb_running_unset_entry(args->dnode);
+ /*
+ * If dependency on VRF module is registered, then VRF
+ * pointer was stored and must be cleared.
+ */
+ if (nb_node_has_dependency(args->dnode->schema->priv))
+ nb_running_unset_entry(args->dnode);
return NB_OK;
}
+
+static void vrf_to_control_plane_protocol(const struct lyd_node *dnode,
+ char *xpath)
+{
+ const char *vrf;
+
+ vrf = yang_dnode_get_string(dnode, "./name");
+
+ snprintf(xpath, XPATH_MAXLEN, FRR_ROUTING_KEY_XPATH_VRF, vrf);
+}
+
+static void control_plane_protocol_to_vrf(const struct lyd_node *dnode,
+ char *xpath)
+{
+ const char *vrf;
+
+ vrf = yang_dnode_get_string(dnode, "./vrf");
+
+ snprintf(xpath, XPATH_MAXLEN, FRR_VRF_KEY_XPATH, vrf);
+}
+
+void routing_control_plane_protocols_register_vrf_dependency(void)
+{
+ struct nb_dependency_callbacks cbs;
+
+ cbs.get_dependant_xpath = vrf_to_control_plane_protocol;
+ cbs.get_dependency_xpath = control_plane_protocol_to_vrf;
+
+ nb_node_set_dependency_cbs(FRR_VRF_XPATH, FRR_ROUTING_XPATH, &cbs);
+}
diff --git a/lib/smux.h b/lib/smux.h
index 11c1becd60..a263478a2e 100644
--- a/lib/smux.h
+++ b/lib/smux.h
@@ -25,6 +25,7 @@
#include <net-snmp/agent/snmp_vars.h>
#include "thread.h"
+#include "hook.h"
#ifdef __cplusplus
extern "C" {
@@ -103,6 +104,7 @@ struct index_oid {
#define SNMP_IP6ADDRESS(V) (*var_len = sizeof(struct in6_addr), (uint8_t *)&V)
extern void smux_init(struct thread_master *tm);
+extern void smux_agentx_enable(void);
extern void smux_register_mib(const char *, struct variable *, size_t, int,
oid[], size_t);
extern int smux_header_generic(struct variable *, oid[], size_t *, int,
@@ -151,6 +153,8 @@ extern void oid_copy_int(oid oid[], int *val);
extern void oid2string(oid oid[], int len, char *string);
extern void oid_copy_str(oid oid[], const char *string, int len);
+DECLARE_HOOK(agentx_enabled, (), ())
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/vrf.c b/lib/vrf.c
index 136938783f..0a91f4bc86 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -686,8 +686,8 @@ int vrf_handler_create(struct vty *vty, const char *vrfname,
}
if (vty) {
- snprintf(xpath_list, sizeof(xpath_list),
- "/frr-vrf:lib/vrf[name='%s']", vrfname);
+ snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH,
+ vrfname);
nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL);
ret = nb_cli_apply_changes(vty, xpath_list);
@@ -821,8 +821,7 @@ DEFUN_YANG (no_vrf,
return CMD_WARNING_CONFIG_FAILED;
}
- snprintf(xpath_list, sizeof(xpath_list), "/frr-vrf:lib/vrf[name='%s']",
- vrfname);
+ snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, vrfname);
nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, xpath_list);
diff --git a/lib/vrf.h b/lib/vrf.h
index 32e6fb4289..333d68ce96 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -52,6 +52,9 @@ enum { IFLA_VRF_UNSPEC, IFLA_VRF_TABLE, __IFLA_VRF_MAX };
#define VRF_ALL_CMD_HELP_STR "Specify the VRF\nAll VRFs\n"
#define VRF_FULL_CMD_HELP_STR "Specify the VRF\nThe VRF name\nAll VRFs\n"
+#define FRR_VRF_XPATH "/frr-vrf:lib/vrf"
+#define FRR_VRF_KEY_XPATH "/frr-vrf:lib/vrf[name='%s']"
+
/*
* Pass some OS specific data up through
* to the daemons
diff --git a/lib/vty.c b/lib/vty.c
index 65f8d78a96..df518422f0 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -2427,9 +2427,9 @@ bool vty_read_config(struct nb_config *config, const char *config_file,
__func__, errno);
goto tmp_free_and_out;
}
- tmp = XMALLOC(MTYPE_TMP,
- strlen(cwd) + strlen(config_file) + 2);
- sprintf(tmp, "%s/%s", cwd, config_file);
+ size_t tmp_len = strlen(cwd) + strlen(config_file) + 2;
+ tmp = XMALLOC(MTYPE_TMP, tmp_len);
+ snprintf(tmp, tmp_len, "%s/%s", cwd, config_file);
fullpath = tmp;
} else
fullpath = config_file;
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index abcdb40547..f6a246500b 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -1292,6 +1292,7 @@ static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
{
struct ospf6_inter_prefix_lsa *prefix_lsa;
struct in6_addr in6;
+ char tbuf[16];
if (lsa != NULL) {
prefix_lsa =
@@ -1301,8 +1302,9 @@ static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
ospf6_prefix_in6_addr(&in6, prefix_lsa, &prefix_lsa->prefix);
if (buf) {
inet_ntop(AF_INET6, &in6, buf, buflen);
- sprintf(&buf[strlen(buf)], "/%d",
- prefix_lsa->prefix.prefix_length);
+ snprintf(tbuf, sizeof(tbuf), "/%d",
+ prefix_lsa->prefix.prefix_length);
+ strlcat(buf, tbuf, buflen);
}
}
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 3449f48267..d0c93dd577 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -1865,6 +1865,7 @@ static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa *lsa,
struct ospf6_as_external_lsa *external;
struct in6_addr in6;
int prefix_length = 0;
+ char tbuf[16];
if (lsa) {
external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
@@ -1885,9 +1886,11 @@ static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa *lsa,
}
if (buf) {
inet_ntop(AF_INET6, &in6, buf, buflen);
- if (prefix_length)
- sprintf(&buf[strlen(buf)], "/%d",
- prefix_length);
+ if (prefix_length) {
+ snprintf(tbuf, sizeof(tbuf), "/%d",
+ prefix_length);
+ strlcat(buf, tbuf, buflen);
+ }
}
}
return (buf);
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index 5394ba9786..2cffc3a397 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -84,7 +84,7 @@ static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa *lsa, char *buf,
sizeof(buf1));
inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
buf2, sizeof(buf2));
- sprintf(buf, "%s/%s", buf2, buf1);
+ snprintf(buf, buflen, "%s/%s", buf2, buf1);
return buf;
}
@@ -866,6 +866,7 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
struct in6_addr in6;
int prefixnum, cnt = 0;
struct ospf6_prefix *prefix;
+ char tbuf[16];
if (lsa) {
intra_prefix_lsa =
@@ -898,8 +899,9 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
OSPF6_PREFIX_SPACE(
prefix->prefix_length));
inet_ntop(AF_INET6, &in6, buf, buflen);
- sprintf(&buf[strlen(buf)], "/%d",
- prefix->prefix_length);
+ snprintf(tbuf, sizeof(tbuf), "/%d",
+ prefix->prefix_length);
+ strlcat(buf, tbuf, buflen);
return (buf);
}
}
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index b98852eeee..19829d4546 100644
--- a/ospfd/ospf_dump.c
+++ b/ospfd/ospf_dump.c
@@ -616,7 +616,7 @@ DEFUN (debug_ospf_packet,
if (inst) // user passed instance ID
{
- if (!ospf_lookup_instance(strtoul(argv[2]->arg, NULL, 10)))
+ if (inst != ospf_instance)
return CMD_NOT_MY_INSTANCE;
}
@@ -692,7 +692,7 @@ DEFUN (no_debug_ospf_packet,
if (inst) // user passed instance ID
{
- if (!ospf_lookup_instance(strtoul(argv[3]->arg, NULL, 10)))
+ if (inst != ospf_instance)
return CMD_NOT_MY_INSTANCE;
}
@@ -763,7 +763,7 @@ DEFUN (debug_ospf_ism,
if (inst) // user passed instance ID
{
- if (!ospf_lookup_instance(strtoul(argv[2]->arg, NULL, 10)))
+ if (inst != ospf_instance)
return CMD_NOT_MY_INSTANCE;
}
@@ -814,7 +814,7 @@ DEFUN (no_debug_ospf_ism,
if (inst) // user passed instance ID
{
- if (!ospf_lookup_instance(strtoul(argv[3]->arg, NULL, 10)))
+ if (inst != ospf_instance)
return CMD_NOT_MY_INSTANCE;
}
@@ -909,8 +909,8 @@ DEFUN (debug_ospf_instance_nsm,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
return debug_ospf_nsm_common(vty, 4, argc, argv);
}
@@ -981,7 +981,7 @@ DEFUN (no_debug_ospf_instance_nsm,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
return no_debug_ospf_nsm_common(vty, 5, argc, argv);
@@ -1062,7 +1062,7 @@ DEFUN (debug_ospf_instance_lsa,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
return debug_ospf_lsa_common(vty, 4, argc, argv);
@@ -1145,7 +1145,7 @@ DEFUN (no_debug_ospf_instance_lsa,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
return no_debug_ospf_lsa_common(vty, 5, argc, argv);
@@ -1207,7 +1207,7 @@ DEFUN (debug_ospf_instance_zebra,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
return debug_ospf_zebra_common(vty, 4, argc, argv);
@@ -1271,8 +1271,8 @@ DEFUN (no_debug_ospf_instance_zebra,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
return no_debug_ospf_zebra_common(vty, 5, argc, argv);
}
@@ -1317,8 +1317,8 @@ DEFUN (debug_ospf_instance_event,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
if (vty->node == CONFIG_NODE)
CONF_DEBUG_ON(event, EVENT);
@@ -1339,8 +1339,8 @@ DEFUN (no_debug_ospf_instance_event,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
if (vty->node == CONFIG_NODE)
CONF_DEBUG_OFF(event, EVENT);
@@ -1387,8 +1387,8 @@ DEFUN (debug_ospf_instance_nssa,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
if (vty->node == CONFIG_NODE)
CONF_DEBUG_ON(nssa, NSSA);
@@ -1409,8 +1409,8 @@ DEFUN (no_debug_ospf_instance_nssa,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
if (vty->node == CONFIG_NODE)
CONF_DEBUG_OFF(nssa, NSSA);
@@ -1625,12 +1625,12 @@ DEFUN (no_debug_ospf,
return CMD_SUCCESS;
}
-static int show_debugging_ospf_common(struct vty *vty, struct ospf *ospf)
+static int show_debugging_ospf_common(struct vty *vty)
{
int i;
- if (ospf->instance)
- vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance);
+ if (ospf_instance)
+ vty_out(vty, "\nOSPF Instance: %d\n\n", ospf_instance);
vty_out(vty, "OSPF debugging status:\n");
@@ -1742,13 +1742,7 @@ DEFUN_NOSH (show_debugging_ospf,
DEBUG_STR
OSPF_STR)
{
- struct ospf *ospf = NULL;
-
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (ospf == NULL)
- return CMD_SUCCESS;
-
- return show_debugging_ospf_common(vty, ospf);
+ return show_debugging_ospf_common(vty);
}
DEFUN_NOSH (show_debugging_ospf_instance,
@@ -1760,14 +1754,13 @@ DEFUN_NOSH (show_debugging_ospf_instance,
"Instance ID\n")
{
int idx_number = 3;
- struct ospf *ospf;
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL)
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
- return show_debugging_ospf_common(vty, ospf);
+ return show_debugging_ospf_common(vty);
}
static int config_write_debug(struct vty *vty);
@@ -1790,16 +1783,11 @@ static int config_write_debug(struct vty *vty)
"", " send", " recv", "",
" detail", " send detail", " recv detail", " detail"};
- struct ospf *ospf;
char str[16];
memset(str, 0, 16);
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (ospf == NULL)
- return CMD_SUCCESS;
-
- if (ospf->instance)
- snprintf(str, sizeof(str), " %u", ospf->instance);
+ if (ospf_instance)
+ snprintf(str, sizeof(str), " %u", ospf_instance);
/* debug ospf ism (status|events|timers). */
if (IS_CONF_DEBUG_OSPF(ism, ISM) == OSPF_DEBUG_ISM)
diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c
index 6be5486b55..6a90dbff11 100644
--- a/ospfd/ospf_main.c
+++ b/ospfd/ospf_main.c
@@ -146,9 +146,6 @@ FRR_DAEMON_INFO(ospfd, OSPF, .vty_port = OSPF_VTY_PORT,
/* OSPFd main routine. */
int main(int argc, char **argv)
{
- unsigned short instance = 0;
- bool created = false;
-
#ifdef SUPPORT_OSPF_API
/* OSPF apiserver is disabled by default. */
ospf_apiserver_enable = 0;
@@ -169,8 +166,8 @@ int main(int argc, char **argv)
switch (opt) {
case 'n':
- ospfd_di.instance = instance = atoi(optarg);
- if (instance < 1)
+ ospfd_di.instance = ospf_instance = atoi(optarg);
+ if (ospf_instance < 1)
exit(0);
break;
case 0:
@@ -208,7 +205,7 @@ int main(int argc, char **argv)
/* OSPFd inits. */
ospf_if_init();
- ospf_zebra_init(master, instance);
+ ospf_zebra_init(master, ospf_instance);
/* OSPF vty inits. */
ospf_vty_init();
@@ -227,17 +224,6 @@ int main(int argc, char **argv)
/* OSPF errors init */
ospf_error_init();
- /*
- * Need to initialize the default ospf structure, so the interface mode
- * commands can be duly processed if they are received before 'router
- * ospf', when ospfd is restarted
- */
- if (instance && !ospf_get_instance(instance, &created)) {
- flog_err(EC_OSPF_INIT_FAIL, "OSPF instance init failed: %s",
- strerror(errno));
- exit(1);
- }
-
frr_config_fork();
frr_run(master);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 4132452069..2ff59ccf49 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -140,44 +140,37 @@ int ospf_oi_count(struct interface *ifp)
all_vrf = strmatch(vrf_name, "all"); \
}
-static struct ospf *ospf_cmd_lookup_ospf(struct vty *vty,
- struct cmd_token *argv[],
- const int argc, uint32_t enable,
- unsigned short *instance)
+static int ospf_router_cmd_parse(struct vty *vty, struct cmd_token *argv[],
+ const int argc, unsigned short *instance,
+ const char **vrf_name)
{
- struct ospf *ospf = NULL;
int idx_vrf = 0, idx_inst = 0;
- const char *vrf_name = NULL;
- bool created = false;
*instance = 0;
- if (argv_find(argv, argc, "(1-65535)", &idx_inst))
+ if (argv_find(argv, argc, "(1-65535)", &idx_inst)) {
+ if (ospf_instance == 0) {
+ vty_out(vty,
+ "%% OSPF is not running in instance mode\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
*instance = strtoul(argv[idx_inst]->arg, NULL, 10);
+ }
+ *vrf_name = NULL;
if (argv_find(argv, argc, "vrf", &idx_vrf)) {
- vrf_name = argv[idx_vrf + 1]->arg;
- if (vrf_name == NULL || strmatch(vrf_name, VRF_DEFAULT_NAME))
- vrf_name = NULL;
- if (enable) {
- /* Allocate VRF aware instance */
- ospf = ospf_get(*instance, vrf_name, &created);
- } else {
- ospf = ospf_lookup_by_inst_name(*instance, vrf_name);
- }
- } else {
- if (enable) {
- ospf = ospf_get(*instance, NULL, &created);
- } else {
- ospf = ospf_lookup_instance(*instance);
+ if (ospf_instance != 0) {
+ vty_out(vty,
+ "%% VRF is not supported in instance mode\n");
+ return CMD_WARNING_CONFIG_FAILED;
}
- }
- if (created) {
- if (DFLT_OSPF_LOG_ADJACENCY_CHANGES)
- SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES);
+ *vrf_name = argv[idx_vrf + 1]->arg;
+ if (*vrf_name && strmatch(*vrf_name, VRF_DEFAULT_NAME))
+ *vrf_name = NULL;
}
- return ospf;
+ return CMD_SUCCESS;
}
static void ospf_show_vrf_name(struct ospf *ospf, struct vty *vty,
@@ -213,28 +206,35 @@ DEFUN_NOSH (router_ospf,
"Instance ID\n"
VRF_CMD_HELP_STR)
{
- struct ospf *ospf = NULL;
- int ret = CMD_SUCCESS;
- unsigned short instance = 0;
+ unsigned short instance;
+ const char *vrf_name;
+ bool created = false;
+ struct ospf *ospf;
+ int ret;
- ospf = ospf_cmd_lookup_ospf(vty, argv, argc, 1, &instance);
- if (!ospf)
- return CMD_WARNING_CONFIG_FAILED;
+ ret = ospf_router_cmd_parse(vty, argv, argc, &instance, &vrf_name);
+ if (ret != CMD_SUCCESS)
+ return ret;
- /* The following logic to set the vty qobj index is in place to be able
- to ignore the commands which dont belong to this instance. */
- if (ospf->instance != instance) {
+ if (instance != ospf_instance) {
VTY_PUSH_CONTEXT_NULL(OSPF_NODE);
- ret = CMD_NOT_MY_INSTANCE;
- } else {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "Config command 'router ospf %d' received, vrf %s id %u oi_running %u",
- instance, ospf->name ? ospf->name : "NIL",
- ospf->vrf_id, ospf->oi_running);
- VTY_PUSH_CONTEXT(OSPF_NODE, ospf);
+ return CMD_NOT_MY_INSTANCE;
}
+ ospf = ospf_get(instance, vrf_name, &created);
+
+ if (created)
+ if (DFLT_OSPF_LOG_ADJACENCY_CHANGES)
+ SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES);
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "Config command 'router ospf %d' received, vrf %s id %u oi_running %u",
+ ospf->instance, ospf->name ? ospf->name : "NIL",
+ ospf->vrf_id, ospf->oi_running);
+
+ VTY_PUSH_CONTEXT(OSPF_NODE, ospf);
+
return ret;
}
@@ -247,19 +247,25 @@ DEFUN (no_router_ospf,
"Instance ID\n"
VRF_CMD_HELP_STR)
{
+ unsigned short instance;
+ const char *vrf_name;
struct ospf *ospf;
- unsigned short instance = 0;
+ int ret;
- ospf = ospf_cmd_lookup_ospf(vty, argv, argc, 0, &instance);
- if (ospf == NULL) {
- if (instance)
- return CMD_NOT_MY_INSTANCE;
- else
- return CMD_WARNING;
- }
- ospf_finish(ospf);
+ ret = ospf_router_cmd_parse(vty, argv, argc, &instance, &vrf_name);
+ if (ret != CMD_SUCCESS)
+ return ret;
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
+ ospf = ospf_lookup(instance, vrf_name);
+ if (ospf)
+ ospf_finish(ospf);
+ else
+ ret = CMD_WARNING_CONFIG_FAILED;
+
+ return ret;
}
@@ -3381,11 +3387,11 @@ DEFUN (show_ip_ospf_instance,
json_object *json = NULL;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (uj)
@@ -4131,11 +4137,11 @@ DEFUN (show_ip_ospf_instance_interface,
json_object *json = NULL;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (uj)
@@ -4526,11 +4532,11 @@ DEFUN (show_ip_ospf_instance_neighbor,
int ret = CMD_SUCCESS;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (uj)
@@ -4741,11 +4747,11 @@ DEFUN (show_ip_ospf_instance_neighbor_all,
int ret = CMD_SUCCESS;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (uj)
json = json_object_new_object();
@@ -4881,11 +4887,11 @@ DEFUN (show_ip_ospf_instance_neighbor_int,
show_ip_ospf_neighbour_header(vty);
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (!uj)
@@ -5359,11 +5365,11 @@ DEFPY (show_ip_ospf_instance_neighbor_id,
{
struct ospf *ospf;
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_neighbor_id_common(vty, ospf, &router_id, !!json,
@@ -5532,11 +5538,11 @@ DEFUN (show_ip_ospf_instance_neighbor_detail,
int ret = CMD_SUCCESS;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (uj)
@@ -5727,11 +5733,11 @@ DEFUN (show_ip_ospf_instance_neighbor_detail_all,
int ret = CMD_SUCCESS;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (uj)
@@ -5859,11 +5865,11 @@ DEFUN (show_ip_ospf_instance_neighbor_int_detail,
bool uj = use_json(argc, argv);
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_neighbor_int_detail_common(vty, ospf, idx_ifname,
@@ -7136,10 +7142,11 @@ DEFUN (show_ip_ospf_instance_database,
if (argv_find(argv, argc, "(1-65535)", &idx)) {
instance = strtoul(argv[idx]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
return (show_ip_ospf_database_common(
@@ -7212,15 +7219,12 @@ DEFUN (show_ip_ospf_instance_database_max,
json = json_object_new_object();
instance = strtoul(argv[idx_number]->arg, NULL, 10);
-
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running) {
- vty_out(vty, "%% OSPF instance not found\n");
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
- }
show_ip_ospf_database_common(vty, ospf, 1, argc, argv, 0, json, uj);
@@ -7355,13 +7359,12 @@ DEFUN (show_ip_ospf_instance_database_type_adv_router,
if (argv_find(argv, argc, "(1-65535)", &idx)) {
instance = strtoul(argv[idx]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running) {
- vty_out(vty, "%% OSPF instance not found\n");
+
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
- }
return (show_ip_ospf_database_type_adv_router_common(
vty, ospf, idx ? 1 : 0, argc, argv, use_vrf, json, uj));
@@ -8819,7 +8822,7 @@ DEFUN (ip_ospf_area,
else
ospf = ospf_lookup_instance(instance);
- if (instance && ospf == NULL) {
+ if (instance && instance != ospf_instance) {
/*
* At this point we know we have received
* an instance and there is no ospf instance
@@ -8944,7 +8947,7 @@ DEFUN (no_ip_ospf_area,
else
ospf = ospf_lookup_instance(instance);
- if (instance && ospf == NULL)
+ if (instance && instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
argv_find(argv, argc, "area", &idx);
@@ -10918,11 +10921,11 @@ DEFUN (show_ip_ospf_instance_border_routers,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_border_routers_common(vty, ospf, 0);
@@ -11086,11 +11089,11 @@ DEFUN (show_ip_ospf_instance_route,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_route_common(vty, ospf, NULL, 0);
@@ -11189,8 +11192,7 @@ DEFPY (clear_ip_ospf_neighbor,
*/
if (instance != 0) {
/* This means clear only the particular ospf process */
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
}
@@ -11220,8 +11222,7 @@ DEFPY (clear_ip_ospf_process,
/* Check if instance is not passed as an argument */
if (instance != 0) {
/* This means clear only the particular ospf process */
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
}
@@ -11545,7 +11546,6 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
struct ospf_if_params *params;
const char *auth_str;
int write = 0;
- struct ospf *ospf = vrf->info;
FOR_ALL_INTERFACES (vrf, ifp) {
@@ -11698,9 +11698,9 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
/* Area print. */
if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) {
- if (ospf && ospf->instance)
+ if (ospf_instance)
vty_out(vty, " ip ospf %d",
- ospf->instance);
+ ospf_instance);
else
vty_out(vty, " ip ospf");
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 04397d50a5..9590a9c73b 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -70,6 +70,8 @@ static struct ospf_master ospf_master;
/* OSPF process wide configuration pointer to export. */
struct ospf_master *om;
+unsigned short ospf_instance;
+
extern struct zclient *zclient;
@@ -511,36 +513,28 @@ static void ospf_init(struct ospf *ospf)
ospf_router_id_update(ospf);
}
-struct ospf *ospf_get(unsigned short instance, const char *name, bool *created)
+struct ospf *ospf_lookup(unsigned short instance, const char *name)
{
struct ospf *ospf;
- /* vrf name provided call inst and name based api
- * in case of no name pass default ospf instance */
- if (name)
+ if (ospf_instance) {
+ ospf = ospf_lookup_instance(instance);
+ } else {
ospf = ospf_lookup_by_inst_name(instance, name);
- else
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
-
- *created = (ospf == NULL);
- if (ospf == NULL) {
- ospf = ospf_new(instance, name);
- ospf_add(ospf);
-
- ospf_init(ospf);
}
return ospf;
}
-struct ospf *ospf_get_instance(unsigned short instance, bool *created)
+struct ospf *ospf_get(unsigned short instance, const char *name, bool *created)
{
struct ospf *ospf;
- ospf = ospf_lookup_instance(instance);
+ ospf = ospf_lookup(instance, name);
+
*created = (ospf == NULL);
if (ospf == NULL) {
- ospf = ospf_new(instance, NULL /* VRF_DEFAULT*/);
+ ospf = ospf_new(instance, name);
ospf_add(ospf);
ospf_init(ospf);
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 954a469b68..5148bf555c 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -633,6 +633,7 @@ struct ospf_nbr_nbma {
/* Extern variables. */
extern struct ospf_master *om;
+extern unsigned short ospf_instance;
extern const int ospf_redistributed_proto_max;
extern struct zclient *zclient;
extern struct thread_master *master;
@@ -642,10 +643,10 @@ extern struct zebra_privs_t ospfd_privs;
/* Prototypes. */
extern const char *ospf_redist_string(unsigned int route_type);
extern struct ospf *ospf_lookup_instance(unsigned short);
+extern struct ospf *ospf_lookup(unsigned short instance, const char *name);
extern struct ospf *ospf_get(unsigned short instance, const char *name,
bool *created);
extern struct ospf *ospf_new_alloc(unsigned short instance, const char *name);
-extern struct ospf *ospf_get_instance(unsigned short, bool *created);
extern struct ospf *ospf_lookup_by_inst_name(unsigned short instance,
const char *name);
extern struct ospf *ospf_lookup_by_vrf_id(vrf_id_t vrf_id);
diff --git a/pimd/pim_main.c b/pimd/pim_main.c
index 9c11cc47d5..5a09e7a8ee 100644
--- a/pimd/pim_main.c
+++ b/pimd/pim_main.c
@@ -145,6 +145,8 @@ int main(int argc, char **argv, char **envp)
hook_register(routing_conf_event,
routing_control_plane_protocols_name_validate);
+ routing_control_plane_protocols_register_vrf_dependency();
+
frr_config_fork();
#ifdef PIM_DEBUG_BYDEFAULT
diff --git a/staticd/static_main.c b/staticd/static_main.c
index ac8f8ff029..560814771d 100644
--- a/staticd/static_main.c
+++ b/staticd/static_main.c
@@ -164,6 +164,8 @@ int main(int argc, char **argv, char **envp)
hook_register(routing_conf_event,
routing_control_plane_protocols_name_validate);
+ routing_control_plane_protocols_register_vrf_dependency();
+
snprintf(backup_config_file, sizeof(backup_config_file),
"%s/zebra.conf", frr_sysconfdir);
staticd_di.backup_config_file = backup_config_file;
diff --git a/tests/topotests/bgp-aggregator-zero/__init__.py b/tests/topotests/bgp-aggregator-zero/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/__init__.py
diff --git a/tests/topotests/bgp-aggregator-zero/exabgp.env b/tests/topotests/bgp-aggregator-zero/exabgp.env
new file mode 100644
index 0000000000..28e642360a
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/exabgp.env
@@ -0,0 +1,53 @@
+[exabgp.api]
+encoder = text
+highres = false
+respawn = false
+socket = ''
+
+[exabgp.bgp]
+openwait = 60
+
+[exabgp.cache]
+attributes = true
+nexthops = true
+
+[exabgp.daemon]
+daemonize = true
+pid = '/var/run/exabgp/exabgp.pid'
+user = 'exabgp'
+##daemonize = false
+
+[exabgp.log]
+all = false
+configuration = true
+daemon = true
+destination = '/var/log/exabgp.log'
+enable = true
+level = INFO
+message = false
+network = true
+packets = false
+parser = false
+processes = true
+reactor = true
+rib = false
+routes = false
+short = false
+timers = false
+
+[exabgp.pdb]
+enable = false
+
+[exabgp.profile]
+enable = false
+file = ''
+
+[exabgp.reactor]
+speed = 1.0
+
+[exabgp.tcp]
+acl = false
+bind = ''
+delay = 0
+once = false
+port = 179
diff --git a/tests/topotests/bgp-aggregator-zero/peer1/exabgp.cfg b/tests/topotests/bgp-aggregator-zero/peer1/exabgp.cfg
new file mode 100644
index 0000000000..b3f25272d2
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/peer1/exabgp.cfg
@@ -0,0 +1,18 @@
+neighbor 10.0.0.1 {
+ router-id 10.0.0.2;
+ local-address 10.0.0.2;
+ local-as 65001;
+ peer-as 65534;
+
+ static {
+ route 192.168.100.101/32 {
+ aggregator (0:10.0.0.2);
+ next-hop 10.0.0.2;
+ }
+
+ route 192.168.100.102/32 {
+ aggregator (65001:10.0.0.2);
+ next-hop 10.0.0.2;
+ }
+ }
+}
diff --git a/tests/topotests/bgp-aggregator-zero/r1/bgpd.conf b/tests/topotests/bgp-aggregator-zero/r1/bgpd.conf
new file mode 100644
index 0000000000..002a5c78c0
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/r1/bgpd.conf
@@ -0,0 +1,6 @@
+!
+router bgp 65534
+ no bgp ebgp-requires-policy
+ neighbor 10.0.0.2 remote-as external
+ neighbor 10.0.0.2 timers 3 10
+!
diff --git a/tests/topotests/bgp-aggregator-zero/r1/zebra.conf b/tests/topotests/bgp-aggregator-zero/r1/zebra.conf
new file mode 100644
index 0000000000..22a26ac610
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/r1/zebra.conf
@@ -0,0 +1,6 @@
+!
+interface r1-eth0
+ ip address 10.0.0.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp-aggregator-zero/test_bgp_aggregator_zero.py b/tests/topotests/bgp-aggregator-zero/test_bgp_aggregator_zero.py
new file mode 100644
index 0000000000..0db47da3f2
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/test_bgp_aggregator_zero.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2021 by
+# Donatas Abraitis <donatas.abraitis@gmail.com>
+#
+# 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 if BGP UPDATE with AGGREGATOR AS attribute with value zero (0)
+is continued to be processed, but AGGREGATOR attribute is discarded.
+"""
+
+import os
+import sys
+import json
+import time
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from mininet.topo import Topo
+
+
+class BgpAggregatorAsnZero(Topo):
+ def build(self, *_args, **_opts):
+ tgen = get_topogen(self)
+
+ r1 = tgen.add_router("r1")
+ peer1 = tgen.add_exabgp_peer(
+ "peer1", ip="10.0.0.2", defaultRoute="via 10.0.0.1"
+ )
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(r1)
+ switch.add_link(peer1)
+
+
+def setup_module(mod):
+ tgen = Topogen(BgpAggregatorAsnZero, mod.__name__)
+ tgen.start_topology()
+
+ router = tgen.gears["r1"]
+ router.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf"))
+ router.load_config(TopoRouter.RD_BGP, os.path.join(CWD, "r1/bgpd.conf"))
+ router.start()
+
+ peer = tgen.gears["peer1"]
+ peer.start(os.path.join(CWD, "peer1"), os.path.join(CWD, "exabgp.env"))
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_aggregator_zero():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _bgp_converge():
+ output = json.loads(
+ tgen.gears["r1"].vtysh_cmd("show ip bgp neighbor 10.0.0.2 json")
+ )
+ expected = {
+ "10.0.0.2": {
+ "bgpState": "Established",
+ "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+
+ assert result is None, 'Failed bgp convergence in "{}"'.format(tgen.gears["r1"])
+
+ def _bgp_has_correct_aggregator_route_with_asn_0():
+ output = json.loads(
+ tgen.gears["r1"].vtysh_cmd("show ip bgp 192.168.100.101/32 json")
+ )
+
+ if "aggregatorAs" in output["paths"][0].keys():
+ return False
+ else:
+ return True
+
+ assert (
+ _bgp_has_correct_aggregator_route_with_asn_0() is True
+ ), 'Aggregator AS attribute with ASN 0 found in "{}"'.format(tgen.gears["r1"])
+
+ def _bgp_has_correct_aggregator_route_with_good_asn():
+ output = json.loads(
+ tgen.gears["r1"].vtysh_cmd("show ip bgp 192.168.100.102/32 json")
+ )
+ expected = {"paths": [{"aggregatorAs": 65001, "aggregatorId": "10.0.0.2"}]}
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_has_correct_aggregator_route_with_good_asn)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+
+ assert result is None, 'Aggregator AS attribute not found in "{}"'.format(
+ tgen.gears["r1"]
+ )
+
+
+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/vtysh/vtysh.c b/vtysh/vtysh.c
index e026a28628..b41364c04d 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -2693,7 +2693,7 @@ static int show_per_daemon(struct vty *vty, struct cmd_token **argv, int argc,
char *line = do_prepend(vty, argv, argc);
for (i = 0; i < array_size(vtysh_client); i++)
- if (vtysh_client[i].fd >= 0) {
+ if (vtysh_client[i].fd >= 0 || vtysh_client[i].next) {
vty_out(vty, headline, vtysh_client[i].name);
ret = vtysh_client_execute(&vtysh_client[i], line);
vty_out(vty, "\n");
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 00471b9645..3828f8800f 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -561,6 +561,8 @@ static void netlink_interface_update_l2info(struct interface *ifp,
netlink_extract_vlan_info(link_data, &vlan_info);
zebra_l2_vlanif_update(ifp, &vlan_info);
+ zebra_evpn_acc_bd_svi_set(ifp->info, NULL,
+ !!if_is_operative(ifp));
} else if (IS_ZEBRA_IF_VXLAN(ifp)) {
struct zebra_l2info_vxlan vxlan_info;
diff --git a/zebra/interface.c b/zebra/interface.c
index fc34a6fb9e..f74030e4d8 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -1183,6 +1183,11 @@ void zebra_if_update_all_links(void)
zif->link?zif->link->name:"unk",
zif->link_ifindex);
}
+
+ /* Update VLAN<=>SVI map */
+ if (IS_ZEBRA_IF_VLAN(ifp))
+ zebra_evpn_acc_bd_svi_set(zif, NULL,
+ !!if_is_operative(ifp));
}
}
diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c
index 2ab5fd3a4c..5352c6214d 100644
--- a/zebra/irdp_interface.c
+++ b/zebra/irdp_interface.c
@@ -93,10 +93,10 @@ static int irdp_if_delete(struct interface *ifp)
return 0;
}
-static const char *inet_2a(uint32_t a, char *b)
+static const char *inet_2a(uint32_t a, char *b, size_t b_len)
{
- sprintf(b, "%u.%u.%u.%u", (a)&0xFF, (a >> 8) & 0xFF, (a >> 16) & 0xFF,
- (a >> 24) & 0xFF);
+ snprintf(b, b_len, "%u.%u.%u.%u", (a)&0xFF, (a >> 8) & 0xFF,
+ (a >> 16) & 0xFF, (a >> 24) & 0xFF);
return b;
}
@@ -140,7 +140,8 @@ static int if_group(struct interface *ifp, int sock, uint32_t group,
flog_err_sys(EC_LIB_SOCKET, "IRDP: %s can't setsockopt %s: %s",
add_leave == IP_ADD_MEMBERSHIP ? "join group"
: "leave group",
- inet_2a(group, b1), safe_strerror(errno));
+ inet_2a(group, b1, sizeof(b1)),
+ safe_strerror(errno));
return ret;
}
@@ -162,7 +163,8 @@ static int if_add_group(struct interface *ifp)
if (irdp->flags & IF_DEBUG_MISC)
zlog_debug("IRDP: Adding group %s for %s",
- inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), ifp->name);
+ inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1, sizeof(b1)),
+ ifp->name);
return 0;
}
@@ -183,7 +185,8 @@ static int if_drop_group(struct interface *ifp)
if (irdp->flags & IF_DEBUG_MISC)
zlog_debug("IRDP: Leaving group %s for %s",
- inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), ifp->name);
+ inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1, sizeof(b1)),
+ ifp->name);
return 0;
}
@@ -383,7 +386,8 @@ int irdp_config_write(struct vty *vty, struct interface *ifp)
for (ALL_LIST_ELEMENTS_RO(irdp->AdvPrefList, node, adv))
vty_out(vty, " ip irdp address %s preference %d\n",
- inet_2a(adv->ip.s_addr, b1), adv->pref);
+ inet_2a(adv->ip.s_addr, b1, sizeof(b1)),
+ adv->pref);
vty_out(vty, " ip irdp holdtime %d\n", irdp->Lifetime);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 602805be3c..46a751ce69 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1132,8 +1132,8 @@ static int build_label_stack(struct mpls_label_stack *nh_label,
if (IS_ZEBRA_DEBUG_KERNEL) {
if (!num_labels)
- sprintf(label_buf, "label %u",
- nh_label->label[i]);
+ snprintf(label_buf, label_buf_size, "label %u",
+ nh_label->label[i]);
else {
snprintf(label_buf1, sizeof(label_buf1), "/%u",
nh_label->label[i]);
diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c
index b232c664bc..d7076ccce6 100644
--- a/zebra/zebra_evpn.c
+++ b/zebra/zebra_evpn.c
@@ -151,6 +151,9 @@ void zebra_evpn_print(zebra_evpn_t *zevpn, void **ctxt)
buf, sizeof(buf)));
json_object_string_add(json, "advertiseGatewayMacip",
zevpn->advertise_gw_macip ? "Yes" : "No");
+ json_object_string_add(json, "advertiseSviMacip",
+ zevpn->advertise_svi_macip ? "Yes"
+ : "No");
json_object_int_add(json, "numMacs", num_macs);
json_object_int_add(json, "numArpNd", num_neigh);
}
@@ -194,6 +197,8 @@ void zebra_evpn_print(zebra_evpn_t *zevpn, void **ctxt)
num_neigh);
vty_out(vty, " Advertise-gw-macip: %s\n",
zevpn->advertise_gw_macip ? "Yes" : "No");
+ vty_out(vty, " Advertise-svi-macip: %s\n",
+ zevpn->advertise_svi_macip ? "Yes" : "No");
}
}
@@ -429,7 +434,7 @@ int zebra_evpn_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
vxl = &zif->l2info.vxl;
if (zebra_evpn_mac_gw_macip_add(ifp, zevpn, ip, &mac, macaddr,
- vxl->access_vlan)
+ vxl->access_vlan, true)
!= 0)
return -1;
@@ -569,7 +574,9 @@ void zebra_evpn_gw_macip_add_for_evpn_hash(struct hash_bucket *bucket,
return;
/* Add primary SVI MAC-IP */
- zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
+ if (advertise_svi_macip_enabled(zevpn)
+ || advertise_gw_macip_enabled(zevpn))
+ zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
if (advertise_gw_macip_enabled(zevpn)) {
/* Add VRR MAC-IP - if any*/
@@ -925,14 +932,20 @@ void zebra_evpn_read_mac_neigh(zebra_evpn_t *zevpn, struct interface *ifp)
macfdb_read_for_bridge(zns, ifp, zif->brslave_info.br_if);
vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
if (vlan_if) {
+ /* Add SVI MAC */
+ zebra_evpn_acc_bd_svi_mac_add(vlan_if);
/* Add SVI MAC-IP */
- zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
+ if (advertise_svi_macip_enabled(zevpn)
+ || advertise_gw_macip_enabled(zevpn))
+ zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
/* Add VRR MAC-IP - if any*/
- vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
- if (vrr_if)
- zebra_evpn_add_macip_for_intf(vrr_if, zevpn);
+ if (advertise_gw_macip_enabled(zevpn)) {
+ vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
+ if (vrr_if)
+ zebra_evpn_add_macip_for_intf(vrr_if, zevpn);
+ }
neigh_read_for_vlan(zns, vlan_if);
}
diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c
index 5227a480fc..90227aa597 100644
--- a/zebra/zebra_evpn_mac.c
+++ b/zebra/zebra_evpn_mac.c
@@ -221,8 +221,8 @@ void zebra_evpn_deref_ip2mac(zebra_evpn_t *zevpn, zebra_mac_t *mac)
UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
}
- /* If no neighbors, delete the MAC. */
- if (list_isempty(mac->neigh_list))
+ /* If no references, delete the MAC. */
+ if (!zebra_evpn_mac_in_use(mac))
zebra_evpn_mac_del(zevpn, mac);
}
@@ -583,6 +583,9 @@ void zebra_evpn_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
json_object_boolean_true_add(json_mac, "stickyMac");
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI))
+ json_object_boolean_true_add(json_mac, "sviMac");
+
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
json_object_boolean_true_add(json_mac,
"defaultGateway");
@@ -685,6 +688,9 @@ void zebra_evpn_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
vty_out(vty, " Sticky Mac ");
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI))
+ vty_out(vty, " SVI-Mac ");
+
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
vty_out(vty, " Default-gateway Mac ");
@@ -2376,7 +2382,8 @@ int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, zebra_mac_t *mac)
int zebra_evpn_mac_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
struct ipaddr *ip, zebra_mac_t **macp,
- struct ethaddr *macaddr, vlanid_t vlan_id)
+ struct ethaddr *macaddr, vlanid_t vlan_id,
+ bool def_gw)
{
char buf[ETHER_ADDR_STRLEN];
zebra_mac_t *mac;
@@ -2402,7 +2409,8 @@ int zebra_evpn_mac_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
/* Set "local" forwarding info. */
SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
- SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
+ if (def_gw)
+ SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
mac->fwd_info.local.ifindex = ifp->ifindex;
mac->fwd_info.local.ns_id = local_ns_id;
@@ -2412,3 +2420,63 @@ int zebra_evpn_mac_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
return 0;
}
+
+void zebra_evpn_mac_svi_del(struct interface *ifp, zebra_evpn_t *zevpn)
+{
+ zebra_mac_t *mac;
+ struct ethaddr macaddr;
+ bool old_bgp_ready;
+
+ if (!zebra_evpn_mh_do_adv_svi_mac())
+ return;
+
+ memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
+ mac = zebra_evpn_mac_lookup(zevpn, &macaddr);
+ if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI)) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("SVI %s mac free", ifp->name);
+
+ old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_SVI);
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
+ false);
+ zebra_evpn_deref_ip2mac(mac->zevpn, mac);
+ }
+}
+
+void zebra_evpn_mac_svi_add(struct interface *ifp, zebra_evpn_t *zevpn)
+{
+ zebra_mac_t *mac = NULL;
+ struct ethaddr macaddr;
+ struct zebra_if *zif = ifp->info;
+ bool old_bgp_ready;
+ bool new_bgp_ready;
+
+ if (!zebra_evpn_mh_do_adv_svi_mac()
+ || !zebra_evpn_send_to_client_ok(zevpn))
+ return;
+
+ memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
+
+ /* dup check */
+ mac = zebra_evpn_mac_lookup(zevpn, &macaddr);
+ if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI))
+ return;
+
+ /* add/update mac */
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("SVI %s mac add", zif->ifp->name);
+
+ old_bgp_ready = (mac && zebra_evpn_mac_is_ready_for_bgp(mac->flags))
+ ? true
+ : false;
+
+ mac = NULL;
+ zebra_evpn_mac_gw_macip_add(ifp, zevpn, NULL, &mac, &macaddr, 0, false);
+ if (mac)
+ SET_FLAG(mac->flags, ZEBRA_MAC_SVI);
+
+ new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
+ new_bgp_ready);
+}
diff --git a/zebra/zebra_evpn_mac.h b/zebra/zebra_evpn_mac.h
index 242097907f..c021765843 100644
--- a/zebra/zebra_evpn_mac.h
+++ b/zebra/zebra_evpn_mac.h
@@ -80,6 +80,8 @@ struct zebra_mac_t_ {
* to advertise it as locally attached but with a "proxy" flag
*/
#define ZEBRA_MAC_LOCAL_INACTIVE 0x800
+/* The MAC entry was created because of advertise_svi_mac */
+#define ZEBRA_MAC_SVI 0x1000
#define ZEBRA_MAC_ALL_LOCAL_FLAGS (ZEBRA_MAC_LOCAL | ZEBRA_MAC_LOCAL_INACTIVE)
#define ZEBRA_MAC_ALL_PEER_FLAGS \
@@ -201,6 +203,12 @@ static inline void zebra_evpn_mac_clear_sync_info(zebra_mac_t *mac)
zebra_evpn_mac_stop_hold_timer(mac);
}
+static inline bool zebra_evpn_mac_in_use(zebra_mac_t *mac)
+{
+ return !list_isempty(mac->neigh_list)
+ || CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI);
+}
+
struct hash *zebra_mac_db_create(const char *desc);
uint32_t num_valid_macs(zebra_evpn_t *zevi);
uint32_t num_dup_detected_macs(zebra_evpn_t *zevi);
@@ -256,7 +264,10 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, zebra_mac_t *mac);
int zebra_evpn_mac_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
struct ipaddr *ip, zebra_mac_t **macp,
- struct ethaddr *macaddr, vlanid_t vlan_id);
+ struct ethaddr *macaddr, vlanid_t vlan_id,
+ bool def_gw);
+void zebra_evpn_mac_svi_add(struct interface *ifp, zebra_evpn_t *zevpn);
+void zebra_evpn_mac_svi_del(struct interface *ifp, zebra_evpn_t *zevpn);
#ifdef __cplusplus
}
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c
index 7e712bf1ee..0bb1ebb564 100644
--- a/zebra/zebra_evpn_mh.c
+++ b/zebra/zebra_evpn_mh.c
@@ -130,12 +130,6 @@ static struct zebra_evpn_es_evi *zebra_evpn_es_evi_new(struct zebra_evpn_es *es,
return es_evi;
}
-/* returns TRUE if the EVPN is ready to be sent to BGP */
-static inline bool zebra_evpn_send_to_client_ok(zebra_evpn_t *zevpn)
-{
- return !!(zevpn->flags & ZEVPN_READY_FOR_BGP);
-}
-
/* Evaluate if the es_evi is ready to be sent BGP -
* 1. If it is ready an add is sent to BGP
* 2. If it is not ready a del is sent (if the ES had been previously added
@@ -466,6 +460,9 @@ void zebra_evpn_update_all_es(zebra_evpn_t *zevpn)
{
struct zebra_evpn_es_evi *es_evi;
struct listnode *node;
+ struct interface *vlan_if;
+ struct interface *vxlan_if;
+ struct zebra_if *vxlan_zif;
/* the EVPN is now elgible as a base for EVPN-MH */
if (zebra_evpn_send_to_client_ok(zevpn))
@@ -475,6 +472,20 @@ void zebra_evpn_update_all_es(zebra_evpn_t *zevpn)
for (ALL_LIST_ELEMENTS_RO(zevpn->local_es_evi_list, node, es_evi))
zebra_evpn_es_evi_re_eval_send_to_client(es_evi);
+
+ /* reinstall SVI MAC */
+ vxlan_if = zevpn->vxlan_if;
+ if (vxlan_if) {
+ vxlan_zif = vxlan_if->info;
+ if (if_is_operative(vxlan_if)
+ && vxlan_zif->brslave_info.br_if) {
+ vlan_if = zvni_map_to_svi(
+ vxlan_zif->l2info.vxl.access_vlan,
+ vxlan_zif->brslave_info.br_if);
+ if (vlan_if)
+ zebra_evpn_acc_bd_svi_mac_add(vlan_if);
+ }
+ }
}
/*****************************************************************************/
@@ -524,9 +535,11 @@ static struct zebra_evpn_access_bd *zebra_evpn_acc_vl_find(vlanid_t vid)
/* A new broadcast domain can be created when a VLAN member or VLAN<=>VxLAN_IF
* mapping is added.
*/
-static struct zebra_evpn_access_bd *zebra_evpn_acc_vl_new(vlanid_t vid)
+static struct zebra_evpn_access_bd *
+zebra_evpn_acc_vl_new(vlanid_t vid, struct interface *br_if)
{
struct zebra_evpn_access_bd *acc_bd;
+ struct interface *vlan_if;
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
zlog_debug("access vlan %d add", vid);
@@ -544,6 +557,16 @@ static struct zebra_evpn_access_bd *zebra_evpn_acc_vl_new(vlanid_t vid)
return NULL;
}
+ /* check if an svi exists for the vlan */
+ if (br_if) {
+ vlan_if = zvni_map_to_svi(vid, br_if);
+ if (vlan_if) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("vlan %d SVI %s set", vid,
+ vlan_if->name);
+ acc_bd->vlan_zif = vlan_if->info;
+ }
+ }
return acc_bd;
}
@@ -556,6 +579,9 @@ static void zebra_evpn_acc_vl_free(struct zebra_evpn_access_bd *acc_bd)
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
zlog_debug("access vlan %d del", acc_bd->vid);
+ if (acc_bd->vlan_zif && acc_bd->zevpn && acc_bd->zevpn->mac_table)
+ zebra_evpn_mac_svi_del(acc_bd->vlan_zif->ifp, acc_bd->zevpn);
+
/* cleanup resources maintained against the ES */
list_delete(&acc_bd->mbr_zifs);
@@ -584,6 +610,59 @@ static void zebra_evpn_acc_bd_free_on_deref(struct zebra_evpn_access_bd *acc_bd)
zebra_evpn_acc_vl_free(acc_bd);
}
+/* called when a SVI is goes up/down */
+void zebra_evpn_acc_bd_svi_set(struct zebra_if *vlan_zif,
+ struct zebra_if *br_zif, bool is_up)
+{
+ struct zebra_evpn_access_bd *acc_bd;
+ struct zebra_l2info_bridge *br;
+ uint16_t vid;
+ struct zebra_if *tmp_br_zif = br_zif;
+
+ if (!tmp_br_zif) {
+ if (!vlan_zif->link || !vlan_zif->link->info)
+ return;
+
+ tmp_br_zif = vlan_zif->link->info;
+ }
+
+ br = &tmp_br_zif->l2info.br;
+ /* ignore vlan unaware bridges */
+ if (!br->vlan_aware)
+ return;
+
+ vid = vlan_zif->l2info.vl.vid;
+ acc_bd = zebra_evpn_acc_vl_find(vid);
+ if (!acc_bd)
+ return;
+
+ if (is_up) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("vlan %d SVI %s set", vid,
+ vlan_zif->ifp->name);
+
+ acc_bd->vlan_zif = vlan_zif;
+ if (acc_bd->zevpn)
+ zebra_evpn_mac_svi_add(acc_bd->vlan_zif->ifp,
+ acc_bd->zevpn);
+ } else if (acc_bd->vlan_zif) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("vlan %d SVI clear", vid);
+ acc_bd->vlan_zif = NULL;
+ if (acc_bd->zevpn && acc_bd->zevpn->mac_table)
+ zebra_evpn_mac_svi_del(vlan_zif->ifp, acc_bd->zevpn);
+ }
+}
+
+/* On some events macs are force-flushed. This api can be used to reinstate
+ * the svi-mac after such cleanup-events.
+ */
+void zebra_evpn_acc_bd_svi_mac_add(struct interface *vlan_if)
+{
+ zebra_evpn_acc_bd_svi_set(vlan_if->info, NULL,
+ if_is_operative(vlan_if));
+}
+
/* called when a EVPN-L2VNI is set or cleared against a BD */
static void zebra_evpn_acc_bd_evpn_set(struct zebra_evpn_access_bd *acc_bd,
zebra_evpn_t *zevpn, zebra_evpn_t *old_zevpn)
@@ -604,6 +683,15 @@ static void zebra_evpn_acc_bd_evpn_set(struct zebra_evpn_access_bd *acc_bd,
else if (old_zevpn)
zebra_evpn_local_es_evi_del(zif->es_info.es, old_zevpn);
}
+
+ if (acc_bd->vlan_zif) {
+ if (zevpn)
+ zebra_evpn_mac_svi_add(acc_bd->vlan_zif->ifp,
+ acc_bd->zevpn);
+ else if (old_zevpn && old_zevpn->mac_table)
+ zebra_evpn_mac_svi_del(acc_bd->vlan_zif->ifp,
+ old_zevpn);
+ }
}
/* handle VLAN->VxLAN_IF association */
@@ -618,7 +706,8 @@ void zebra_evpn_vl_vxl_ref(uint16_t vid, struct zebra_if *vxlan_zif)
acc_bd = zebra_evpn_acc_vl_find(vid);
if (!acc_bd)
- acc_bd = zebra_evpn_acc_vl_new(vid);
+ acc_bd = zebra_evpn_acc_vl_new(vid,
+ vxlan_zif->brslave_info.br_if);
old_vxlan_zif = acc_bd->vxlan_zif;
acc_bd->vxlan_zif = vxlan_zif;
@@ -712,7 +801,7 @@ void zebra_evpn_vl_mbr_ref(uint16_t vid, struct zebra_if *zif)
acc_bd = zebra_evpn_acc_vl_find(vid);
if (!acc_bd)
- acc_bd = zebra_evpn_acc_vl_new(vid);
+ acc_bd = zebra_evpn_acc_vl_new(vid, zif->brslave_info.br_if);
if (listnode_lookup(acc_bd->mbr_zifs, zif))
return;
@@ -756,6 +845,22 @@ void zebra_evpn_vl_mbr_deref(uint16_t vid, struct zebra_if *zif)
zebra_evpn_acc_bd_free_on_deref(acc_bd);
}
+static void zebra_evpn_acc_vl_adv_svi_mac_cb(struct hash_bucket *bucket,
+ void *ctxt)
+{
+ struct zebra_evpn_access_bd *acc_bd = bucket->data;
+
+ if (acc_bd->vlan_zif && acc_bd->zevpn)
+ zebra_evpn_mac_svi_add(acc_bd->vlan_zif->ifp, acc_bd->zevpn);
+}
+
+/* called when advertise SVI MAC is enabled on the switch */
+static void zebra_evpn_acc_vl_adv_svi_mac_all(void)
+{
+ hash_iterate(zmh_info->evpn_vlan_table,
+ zebra_evpn_acc_vl_adv_svi_mac_cb, NULL);
+}
+
static void zebra_evpn_acc_vl_json_fill(struct zebra_evpn_access_bd *acc_bd,
json_object *json, bool detail)
{
@@ -800,6 +905,8 @@ static void zebra_evpn_acc_vl_show_entry_detail(struct vty *vty,
vty_out(vty, " VxLAN Interface: %s\n",
acc_bd->vxlan_zif ?
acc_bd->vxlan_zif->ifp->name : "-");
+ vty_out(vty, " SVI: %s\n",
+ acc_bd->vlan_zif ? acc_bd->vlan_zif->ifp->name : "-");
vty_out(vty, " L2-VNI: %d\n",
acc_bd->zevpn ? acc_bd->zevpn->vni : 0);
vty_out(vty, " Member Count: %d\n",
@@ -817,12 +924,11 @@ static void zebra_evpn_acc_vl_show_entry(struct vty *vty,
if (json) {
zebra_evpn_acc_vl_json_fill(acc_bd, json, false);
} else {
- vty_out(vty, "%-5u %21s %-8d %u\n",
- acc_bd->vid,
- acc_bd->vxlan_zif ?
- acc_bd->vxlan_zif->ifp->name : "-",
- acc_bd->zevpn ? acc_bd->zevpn->vni : 0,
- listcount(acc_bd->mbr_zifs));
+ vty_out(vty, "%-5u %-15s %-8d %-15s %u\n", acc_bd->vid,
+ acc_bd->vlan_zif ? acc_bd->vlan_zif->ifp->name : "-",
+ acc_bd->zevpn ? acc_bd->zevpn->vni : 0,
+ acc_bd->vxlan_zif ? acc_bd->vxlan_zif->ifp->name : "-",
+ listcount(acc_bd->mbr_zifs));
}
}
@@ -856,8 +962,8 @@ void zebra_evpn_acc_vl_show(struct vty *vty, bool uj)
wctx.detail = false;
if (!uj)
- vty_out(vty, "%-5s %21s %-8s %s\n",
- "VLAN", "VxLAN-IF", "L2-VNI", "# Members");
+ vty_out(vty, "%-5s %-15s %-8s %-15s %s\n", "VLAN", "SVI",
+ "L2-VNI", "VXLAN-IF", "# Members");
hash_iterate(zmh_info->evpn_vlan_table, zebra_evpn_acc_vl_show_hash,
&wctx);
@@ -1960,6 +2066,20 @@ static void zebra_evpn_mh_advertise_reach_neigh_only(void)
*/
}
+/* On config of first local-ES turn on advertisement of local SVI-MAC */
+static void zebra_evpn_mh_advertise_svi_mac(void)
+{
+ if (zmh_info->flags & ZEBRA_EVPN_MH_ADV_SVI_MAC)
+ return;
+
+ zmh_info->flags |= ZEBRA_EVPN_MH_ADV_SVI_MAC;
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("evpn-mh: advertise SVI MAC");
+
+ /* walk through all SVIs and see if we need to advertise the MAC */
+ zebra_evpn_acc_vl_adv_svi_mac_all();
+}
+
static int zebra_evpn_es_df_delay_exp_cb(struct thread *t)
{
struct zebra_evpn_es *es;
@@ -1974,6 +2094,17 @@ static int zebra_evpn_es_df_delay_exp_cb(struct thread *t)
return 0;
}
+/* currently there is no global config to turn on MH instead we use
+ * the addition of the first local Ethernet Segment as the trigger to
+ * init MH specific processing
+ */
+static void zebra_evpn_mh_on_first_local_es(void)
+{
+ zebra_evpn_mh_dup_addr_detect_off();
+ zebra_evpn_mh_advertise_reach_neigh_only();
+ zebra_evpn_mh_advertise_svi_mac();
+}
+
static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
struct zebra_if *zif)
{
@@ -1984,8 +2115,7 @@ static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
zlog_debug("local es %s add; nhg %u if %s", es->esi_str,
es->nhg_id, zif->ifp->name);
- zebra_evpn_mh_dup_addr_detect_off();
- zebra_evpn_mh_advertise_reach_neigh_only();
+ zebra_evpn_mh_on_first_local_es();
es->flags |= ZEBRA_EVPNES_LOCAL;
listnode_init(&es->local_es_listnode, es);
diff --git a/zebra/zebra_evpn_mh.h b/zebra/zebra_evpn_mh.h
index 81ae740d49..94de84ff14 100644
--- a/zebra/zebra_evpn_mh.h
+++ b/zebra/zebra_evpn_mh.h
@@ -180,6 +180,8 @@ struct zebra_evpn_access_bd {
struct list *mbr_zifs;
/* presence of zevpn activates the EVI on all the ESs in mbr_zifs */
zebra_evpn_t *zevpn;
+ /* SVI associated with the VLAN */
+ struct zebra_if *vlan_zif;
};
/* multihoming information stored in zrouter */
@@ -200,6 +202,10 @@ struct zebra_evpn_mh_info {
* this flag when the first local ES is detected.
*/
#define ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY (1 << 2)
+/* If EVPN MH is enabled we advertise the SVI MAC address to avoid
+ * flooding of ARP replies rxed from the multi-homed host
+ */
+#define ZEBRA_EVPN_MH_ADV_SVI_MAC (1 << 3)
/* RB tree of Ethernet segments (used for EVPN-MH) */
struct zebra_es_rb_head es_rb_tree;
@@ -256,6 +262,12 @@ struct zebra_evpn_mh_info {
enum protodown_reasons protodown_rc;
};
+/* returns TRUE if the EVPN is ready to be sent to BGP */
+static inline bool zebra_evpn_send_to_client_ok(zebra_evpn_t *zevpn)
+{
+ return !!(zevpn->flags & ZEVPN_READY_FOR_BGP);
+}
+
static inline bool zebra_evpn_mac_is_es_local(zebra_mac_t *mac)
{
return mac->es && (mac->es->flags & ZEBRA_EVPNES_LOCAL);
@@ -285,6 +297,10 @@ static inline bool zebra_evpn_mh_do_adv_reachable_neigh_only(void)
return !!(zmh_info->flags & ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY);
}
+static inline bool zebra_evpn_mh_do_adv_svi_mac(void)
+{
+ return zmh_info && (zmh_info->flags & ZEBRA_EVPN_MH_ADV_SVI_MAC);
+}
/*****************************************************************************/
extern esi_t *zero_esi;
@@ -357,5 +373,8 @@ extern bool zebra_evpn_is_es_bond_member(struct interface *ifp);
extern void zebra_evpn_mh_print(struct vty *vty);
extern void zebra_evpn_mh_json(json_object *json);
extern void zebra_evpn_l2_nh_show(struct vty *vty, bool uj);
+extern void zebra_evpn_acc_bd_svi_set(struct zebra_if *vlan_zif,
+ struct zebra_if *br_zif, bool is_up);
+extern void zebra_evpn_acc_bd_svi_mac_add(struct interface *vlan_if);
#endif /* _ZEBRA_EVPN_MH_H */
diff --git a/zebra/zebra_evpn_neigh.c b/zebra/zebra_evpn_neigh.c
index 1f45b72e3a..834ad5381d 100644
--- a/zebra/zebra_evpn_neigh.c
+++ b/zebra/zebra_evpn_neigh.c
@@ -2464,7 +2464,7 @@ int zebra_evpn_neigh_del_ip(zebra_evpn_t *zevpn, struct ipaddr *ip)
/* see if the AUTO mac needs to be deleted */
if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
- && !listcount(zmac->neigh_list))
+ && !zebra_evpn_mac_in_use(zmac))
zebra_evpn_mac_del(zevpn, zmac);
return 0;
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 424c00d5eb..a4365e551f 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -3503,6 +3503,8 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
zvrf->advertise_gw_macip ? "Yes" : "No");
vty_out(vty, "Advertise svi mac-ip: %s\n",
zvrf->advertise_svi_macip ? "Yes" : "No");
+ vty_out(vty, "Advertise svi mac: %s\n",
+ zebra_evpn_mh_do_adv_svi_mac() ? "Yes" : "No");
vty_out(vty, "Duplicate address detection: %s\n",
zebra_evpn_do_dup_addr_detect(zvrf) ? "Enable"
: "Disable");
@@ -4493,6 +4495,16 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
return -1;
}
+ /* VRR IP is advertised only if gw-macip-adv-enabled */
+ if (IS_ZEBRA_IF_MACVLAN(ifp)) {
+ if (!advertise_gw_macip_enabled(zevpn))
+ return 0;
+ } else {
+ /* SVI IP is advertised if gw or svi macip-adv-enabled */
+ if (!advertise_svi_macip_enabled(zevpn)
+ && !advertise_gw_macip_enabled(zevpn))
+ return 0;
+ }
memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
@@ -4539,10 +4551,14 @@ int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
} else {
zebra_evpn_t *zevpn = NULL;
+ /* Unlink the SVI from the access VLAN */
+ zebra_evpn_acc_bd_svi_set(ifp->info, link_if->info, false);
+
/* since we dont have svi corresponding to zevpn, we associate it
* to default vrf. Note: the corresponding neigh entries on the
* SVI would have already been deleted */
zevpn = zebra_evpn_from_svi(ifp, link_if);
+
if (zevpn) {
zevpn->vrf_id = VRF_DEFAULT;
@@ -4606,6 +4622,9 @@ int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
n_wctx.zevpn = zevpn;
hash_iterate(zevpn->neigh_table, zebra_evpn_install_neigh_hash,
&n_wctx);
+
+ /* Link the SVI from the access VLAN */
+ zebra_evpn_acc_bd_svi_set(ifp->info, link_if->info, true);
}
return 0;