summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_aspath.c2
-rw-r--r--bgpd/bgp_evpn_vty.c4
-rw-r--r--bgpd/bgp_fsm.c36
-rw-r--r--bgpd/bgp_nexthop.c13
-rw-r--r--bgpd/bgp_open.c2
-rw-r--r--bgpd/bgp_packet.c4
-rw-r--r--bgpd/bgp_packet.h3
-rw-r--r--bgpd/bgp_route.c14
-rw-r--r--bgpd/bgp_routemap.c13
-rw-r--r--bgpd/bgp_rpki.c2
-rw-r--r--bgpd/bgp_vty.c448
-rw-r--r--bgpd/bgp_vty.h3
-rwxr-xr-xconfigure.ac1
-rw-r--r--doc/user/bgp.rst49
-rw-r--r--isisd/isis_bfd.c129
-rw-r--r--lib/ferr.c2
-rw-r--r--lib/frrcu.c5
-rw-r--r--lib/if.c28
-rw-r--r--lib/if.h6
-rw-r--r--lib/libfrr.c2
-rw-r--r--lib/northbound.h9
-rw-r--r--lib/northbound_cli.c14
-rw-r--r--lib/prefix.c8
-rw-r--r--lib/stream.c8
-rw-r--r--lib/stream.h5
-rw-r--r--lib/thread.c2
-rw-r--r--lib/vty.c9
-rw-r--r--lib/zclient.c11
-rw-r--r--lib/zebra.h1
-rw-r--r--ospf6d/ospf6_zebra.c2
-rw-r--r--ospfd/ospf_errors.c2
-rw-r--r--ospfd/ospf_vty.c67
-rw-r--r--pbrd/pbrd.conf.sample16
-rw-r--r--pimd/pim_bsm.c4
-rw-r--r--pimd/pim_nht.c2
-rw-r--r--redhat/frr.spec.in2
-rw-r--r--sharpd/sharpd.conf.sample3
-rw-r--r--staticd/staticd.conf.sample4
-rw-r--r--tests/bgpd/test_peer_attr.c6
-rw-r--r--tests/topotests/all-protocol-startup/r1/ipv4_routes.ref2
-rw-r--r--tests/topotests/all-protocol-startup/r1/zebra.conf3
-rw-r--r--tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py2
-rw-r--r--vtysh/vtysh.c16
-rw-r--r--yang/frr-bfdd.yang12
-rw-r--r--yang/frr-isisd.yang22
-rw-r--r--zebra/connected.c92
-rw-r--r--zebra/connected.h8
-rw-r--r--zebra/if_netlink.c15
-rw-r--r--zebra/interface.c14
-rw-r--r--zebra/redistribute.c14
-rw-r--r--zebra/rt.h10
-rw-r--r--zebra/rt_netlink.c108
-rw-r--r--zebra/rt_socket.c14
-rw-r--r--zebra/zebra_dplane.c303
-rw-r--r--zebra/zebra_dplane.h31
-rw-r--r--zebra/zebra_errors.c2
-rw-r--r--zebra/zebra_mpls_openbsd.c4
-rw-r--r--zebra/zebra_rib.c7
-rw-r--r--zebra/zebra_vxlan.c53
-rw-r--r--zebra/zebra_vxlan.h3
60 files changed, 1061 insertions, 615 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 1385345d64..f5652b07c5 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -1466,7 +1466,7 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
/* Not reached */
}
-/* Iterate over AS_PATH segments and wipe all occurences of the
+/* Iterate over AS_PATH segments and wipe all occurrences of the
* listed AS numbers. Hence some segments may lose some or even
* all data on the way, the operation is implemented as a smarter
* version of aspath_dup(), which allocates memory to hold the new
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index d031d34f1f..e6d81e54c4 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -3757,9 +3757,9 @@ DEFUN(show_bgp_l2vpn_evpn_route,
type = BGP_EVPN_MAC_IP_ROUTE;
else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
type = BGP_EVPN_IMET_ROUTE;
- else if (strncmp(argv[type_idx + 1]->arg, "es", 2) == 0)
+ else if (strncmp(argv[type_idx + 1]->arg, "e", 1) == 0)
type = BGP_EVPN_ES_ROUTE;
- else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
+ else if (strncmp(argv[type_idx + 1]->arg, "p", 1) == 0)
type = BGP_EVPN_IP_PREFIX_ROUTE;
else
return CMD_WARNING;
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 4348e6b240..c9c6fc157e 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -96,6 +96,21 @@ static int bgp_holdtime_timer(struct thread *);
/* BGP FSM functions. */
static int bgp_start(struct peer *);
+/* Register peer with NHT */
+static int bgp_peer_reg_with_nht(struct peer *peer)
+{
+ int connected = 0;
+
+ if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
+ && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
+ && !bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
+ connected = 1;
+
+ return bgp_find_or_add_nexthop(
+ peer->bgp, peer->bgp, family2afi(peer->su.sa.sa_family),
+ NULL, peer, connected);
+}
+
static void peer_xfer_stats(struct peer *peer_dst, struct peer *peer_src)
{
/* Copy stats over. These are only the pre-established state stats */
@@ -293,6 +308,11 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
if (from_peer)
peer_xfer_stats(peer, from_peer);
+ /* Register peer for NHT. This is to allow RAs to be enabled when
+ * needed, even on a passive connection.
+ */
+ bgp_peer_reg_with_nht(peer);
+
bgp_reads_on(peer);
bgp_writes_on(peer);
thread_add_timer_msec(bm->master, bgp_process_packet, peer, 0,
@@ -1382,7 +1402,6 @@ static int bgp_connect_fail(struct peer *peer)
int bgp_start(struct peer *peer)
{
int status;
- int connected = 0;
bgp_peer_conf_if_to_su_update(peer);
@@ -1439,17 +1458,10 @@ int bgp_start(struct peer *peer)
return -1;
}
- /* Register to be notified on peer up */
- if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1
- && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)
- && !bgp_flag_check(peer->bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
- connected = 1;
- else
- connected = 0;
-
- if (!bgp_find_or_add_nexthop(peer->bgp, peer->bgp,
- family2afi(peer->su.sa.sa_family), NULL,
- peer, connected)) {
+ /* Register peer for NHT. If next hop is already resolved, proceed
+ * with connection setup, else wait.
+ */
+ if (!bgp_peer_reg_with_nht(peer)) {
if (bgp_zebra_num_connects()) {
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s [FSM] Waiting for NHT",
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index a8c507832c..812f0ce16e 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -680,17 +680,23 @@ static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail,
continue;
for (rn = bgp_table_top(table[afi]); rn;
rn = bgp_route_next(rn)) {
+ struct peer *peer;
+
bnc = bgp_node_get_bgp_nexthop_info(rn);
if (!bnc)
continue;
+ peer = (struct peer *)bnc->nht_info;
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)) {
vty_out(vty,
- " %s valid [IGP metric %d], #paths %d\n",
+ " %s valid [IGP metric %d], #paths %d",
inet_ntop(rn->p.family,
&rn->p.u.prefix, buf,
sizeof(buf)),
bnc->metric, bnc->path_count);
+ if (peer)
+ vty_out(vty, ", peer %s", peer->host);
+ vty_out(vty, "\n");
if (!detail)
continue;
@@ -698,10 +704,13 @@ static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail,
bgp_show_nexthops_detail(vty, bgp, bnc);
} else {
- vty_out(vty, " %s invalid\n",
+ vty_out(vty, " %s invalid",
inet_ntop(rn->p.family,
&rn->p.u.prefix, buf,
sizeof(buf)));
+ if (peer)
+ vty_out(vty, ", peer %s", peer->host);
+ vty_out(vty, "\n");
if (CHECK_FLAG(bnc->flags,
BGP_NEXTHOP_CONNECTED))
vty_out(vty, " Must be Connected\n");
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 64529f6ef3..7e5e07099d 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -503,7 +503,7 @@ static int bgp_capability_restart(struct peer *peer,
if (bgp_debug_neighbor_events(peer))
zlog_debug(
"%s Address family %s is%spreserved",
- peer->host, afi_safi_print(afi, safi),
+ peer->host, get_afi_safi_str(afi, safi, false),
CHECK_FLAG(
peer->af_cap[afi][safi],
PEER_CAP_RESTART_AF_PRESERVE_RCV)
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 99522a6522..d3a08d23d9 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -140,7 +140,7 @@ static struct stream *bgp_update_packet_eor(struct peer *peer, afi_t afi,
if (bgp_debug_neighbor_events(peer))
zlog_debug("send End-of-RIB for %s to %s",
- afi_safi_print(afi, safi), peer->host);
+ get_afi_safi_str(afi, safi, false), peer->host);
s = stream_new(BGP_MAX_PACKET_SIZE);
@@ -1660,7 +1660,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
bgp_clear_stale_route(peer, afi, safi);
zlog_info("%%NOTIFICATION: rcvd End-of-RIB for %s from %s in vrf %s",
- afi_safi_print(afi, safi), peer->host,
+ get_afi_safi_str(afi, safi, false), peer->host,
vrf ? vrf->name : VRF_DEFAULT_NAME);
}
}
diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h
index e8eacee589..fc6fc66a4c 100644
--- a/bgpd/bgp_packet.h
+++ b/bgpd/bgp_packet.h
@@ -57,9 +57,6 @@ extern void bgp_notify_send_with_data(struct peer *, uint8_t, uint8_t,
extern void bgp_route_refresh_send(struct peer *, afi_t, safi_t, uint8_t,
uint8_t, int);
extern void bgp_capability_send(struct peer *, afi_t, safi_t, int, int);
-extern void bgp_default_update_send(struct peer *, struct attr *, afi_t, safi_t,
- struct peer *);
-extern void bgp_default_withdraw_send(struct peer *, afi_t, safi_t);
extern int bgp_capability_receive(struct peer *, bgp_size_t);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 183debddba..32c9fb16f3 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2750,7 +2750,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
zlog_info(
"%%MAXPFXEXCEED: No. of %s prefix received from %s %ld exceed, "
"limit %ld",
- afi_safi_print(afi, safi), peer->host,
+ get_afi_safi_str(afi, safi, false), peer->host,
peer->pcount[afi][safi], peer->pmax[afi][safi]);
SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT);
@@ -2811,7 +2811,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
zlog_info(
"%%MAXPFX: No. of %s prefix received from %s reaches %ld, max %ld",
- afi_safi_print(afi, safi), peer->host,
+ get_afi_safi_str(afi, safi, false), peer->host,
peer->pcount[afi][safi], peer->pmax[afi][safi]);
SET_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_PREFIX_THRESHOLD);
@@ -10696,7 +10696,7 @@ static int bgp_table_stats(struct vty *vty, struct bgp *bgp, afi_t afi,
return CMD_WARNING;
}
- vty_out(vty, "BGP %s RIB statistics\n", afi_safi_print(afi, safi));
+ vty_out(vty, "BGP %s RIB statistics\n", get_afi_safi_str(afi, safi, false));
/* labeled-unicast routes live in the unicast table */
if (safi == SAFI_LABELED_UNICAST)
@@ -10895,7 +10895,7 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
if (use_json) {
json_object_string_add(json, "prefixCountsFor", peer->host);
json_object_string_add(json, "multiProtocol",
- afi_safi_print(afi, safi));
+ get_afi_safi_str(afi, safi, true));
json_object_int_add(json, "pfxCounter",
peer->pcount[afi][safi]);
@@ -10921,10 +10921,10 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
&& bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
vty_out(vty, "Prefix counts for %s/%s, %s\n",
peer->hostname, peer->host,
- afi_safi_print(afi, safi));
+ get_afi_safi_str(afi, safi, false));
} else {
vty_out(vty, "Prefix counts for %s, %s\n", peer->host,
- afi_safi_print(afi, safi));
+ get_afi_safi_str(afi, safi, false));
}
vty_out(vty, "PfxCt: %ld\n", peer->pcount[afi][safi]);
@@ -11552,7 +11552,7 @@ DEFUN (show_ip_bgp_neighbor_received_prefix_filter,
if (count) {
if (!uj)
vty_out(vty, "Address Family: %s\n",
- afi_safi_print(afi, safi));
+ get_afi_safi_str(afi, safi, false));
prefix_bgp_show_prefix_list(vty, afi, name, uj);
} else {
if (uj)
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 7f1a9b71c1..aaae9e380e 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -4158,6 +4158,18 @@ DEFUN (no_set_aspath_prepend,
return ret;
}
+DEFUN (no_set_aspath_prepend_lastas,
+ no_set_aspath_prepend_lastas_cmd,
+ "no set as-path prepend last-as [(1-10)]",
+ NO_STR
+ SET_STR
+ "Transform BGP AS_PATH attribute\n"
+ "Prepend to the as-path\n"
+ "Use the peers AS-number\n"
+ "Number of times to insert\n")
+{
+ return no_set_aspath_prepend(self, vty, argc, argv);
+}
DEFUN (set_aspath_exclude,
set_aspath_exclude_cmd,
@@ -5123,6 +5135,7 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &set_aspath_prepend_lastas_cmd);
install_element(RMAP_NODE, &set_aspath_exclude_cmd);
install_element(RMAP_NODE, &no_set_aspath_prepend_cmd);
+ install_element(RMAP_NODE, &no_set_aspath_prepend_lastas_cmd);
install_element(RMAP_NODE, &no_set_aspath_exclude_cmd);
install_element(RMAP_NODE, &no_set_aspath_exclude_all_cmd);
install_element(RMAP_NODE, &set_origin_cmd);
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 5414e2ef15..22840d54c6 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -1180,7 +1180,7 @@ DEFPY (show_rpki_prefix,
{
if (!is_synchronized()) {
- vty_out(vty, "No Conection to RPKI cache server.\n");
+ vty_out(vty, "No Connection to RPKI cache server.\n");
return CMD_WARNING;
}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 58a202d510..f6aca6fbf5 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -22,6 +22,7 @@
#include "command.h"
#include "lib/json.h"
+#include "lib_errors.h"
#include "lib/zclient.h"
#include "prefix.h"
#include "plist.h"
@@ -130,6 +131,80 @@ static enum node_type bgp_node_type(afi_t afi, safi_t safi)
return BGP_IPV4_NODE;
}
+static const char *get_afi_safi_vty_str(afi_t afi, safi_t safi)
+{
+ if (afi == AFI_IP && safi == SAFI_UNICAST)
+ return "IPv4 Unicast";
+ else if (afi == AFI_IP && safi == SAFI_MULTICAST)
+ return "IPv4 Multicast";
+ else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST)
+ return "IPv4 Labeled Unicast";
+ else if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
+ return "IPv4 VPN";
+ else if (afi == AFI_IP && safi == SAFI_ENCAP)
+ return "IPv4 Encap";
+ else if (afi == AFI_IP && safi == SAFI_FLOWSPEC)
+ return "IPv4 Flowspec";
+ else if (afi == AFI_IP6 && safi == SAFI_UNICAST)
+ return "IPv6 Unicast";
+ else if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
+ return "IPv6 Multicast";
+ else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST)
+ return "IPv6 Labeled Unicast";
+ else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN)
+ return "IPv6 VPN";
+ else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
+ return "IPv6 Encap";
+ else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC)
+ return "IPv6 Flowspec";
+ else if (afi == AFI_L2VPN && safi == SAFI_EVPN)
+ return "L2VPN EVPN";
+ else {
+ flog_err(EC_LIB_DEVELOPMENT, "New afi/safi that needs to be taken care of?");
+ return "Unknown";
+ }
+}
+
+/*
+ * Please note that we have intentionally camelCased
+ * the return strings here. So if you want
+ * to use this function, please ensure you
+ * are doing this within json output
+ */
+static const char *get_afi_safi_json_str(afi_t afi, safi_t safi)
+{
+ if (afi == AFI_IP && safi == SAFI_UNICAST)
+ return "ipv4Unicast";
+ else if (afi == AFI_IP && safi == SAFI_MULTICAST)
+ return "ipv4Multicast";
+ else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST)
+ return "ipv4LabeledUnicast";
+ else if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
+ return "ipv4Vpn";
+ else if (afi == AFI_IP && safi == SAFI_ENCAP)
+ return "ipv4Encap";
+ else if (afi == AFI_IP && safi == SAFI_FLOWSPEC)
+ return "ipv4Flowspec";
+ else if (afi == AFI_IP6 && safi == SAFI_UNICAST)
+ return "ipv6Unicast";
+ else if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
+ return "ipv6Multicast";
+ else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST)
+ return "ipv6LabeledUnicast";
+ else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN)
+ return "ipv6Vpn";
+ else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
+ return "ipv6Encap";
+ else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC)
+ return "ipv6Flowspec";
+ else if (afi == AFI_L2VPN && safi == SAFI_EVPN)
+ return "l2VpnEvpn";
+ else {
+ flog_err(EC_LIB_DEVELOPMENT, "New afi/safi that needs to be taken care of?");
+ return "Unknown";
+ }
+}
+
/* Utility function to get address family from current node. */
afi_t bgp_node_afi(struct vty *vty)
{
@@ -584,7 +659,7 @@ static void bgp_clear_vty_error(struct vty *vty, struct peer *peer, afi_t afi,
case BGP_ERR_AF_UNCONFIGURED:
vty_out(vty,
"%%BGP: Enable %s address family for the neighbor %s\n",
- afi_safi_print(afi, safi), peer->host);
+ get_afi_safi_str(afi, safi, false), peer->host);
break;
case BGP_ERR_SOFT_RECONFIG_UNCONFIGURED:
vty_out(vty,
@@ -596,12 +671,61 @@ static void bgp_clear_vty_error(struct vty *vty, struct peer *peer, afi_t afi,
}
}
+static int bgp_peer_clear(struct peer *peer, afi_t afi, safi_t safi,
+ struct listnode *nnode, enum bgp_clear_type stype)
+{
+ int ret = 0;
+
+ /* if afi/.safi not specified, spin thru all of them */
+ if ((afi == AFI_UNSPEC) && (safi == SAFI_UNSPEC)) {
+ afi_t tmp_afi;
+ safi_t tmp_safi;
+
+ FOREACH_AFI_SAFI (tmp_afi, tmp_safi) {
+ if (!peer->afc[tmp_afi][tmp_safi])
+ continue;
+
+ if (stype == BGP_CLEAR_SOFT_NONE)
+ ret = peer_clear(peer, &nnode);
+ else
+ ret = peer_clear_soft(peer, tmp_afi, tmp_safi,
+ stype);
+ }
+ /* if afi specified and safi not, spin thru safis on this afi */
+ } else if (safi == SAFI_UNSPEC) {
+ safi_t tmp_safi;
+
+ for (tmp_safi = SAFI_UNICAST;
+ tmp_safi < SAFI_MAX; tmp_safi++) {
+ if (!peer->afc[afi][tmp_safi])
+ continue;
+
+ if (stype == BGP_CLEAR_SOFT_NONE)
+ ret = peer_clear(peer, &nnode);
+ else
+ ret = peer_clear_soft(peer, afi,
+ tmp_safi, stype);
+ }
+ /* both afi/safi specified, let the caller know if not defined */
+ } else {
+ if (!peer->afc[afi][safi])
+ return 1;
+
+ if (stype == BGP_CLEAR_SOFT_NONE)
+ ret = peer_clear(peer, &nnode);
+ else
+ ret = peer_clear_soft(peer, afi, safi, stype);
+ }
+
+ return ret;
+}
+
/* `clear ip bgp' functions. */
static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
enum clear_sort sort, enum bgp_clear_type stype,
const char *arg)
{
- int ret;
+ int ret = 0;
bool found = false;
struct peer *peer;
struct listnode *node, *nnode;
@@ -614,13 +738,8 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
*/
if (sort == clear_all) {
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- if (!peer->afc[afi][safi])
- continue;
-
- if (stype == BGP_CLEAR_SOFT_NONE)
- ret = peer_clear(peer, &nnode);
- else
- ret = peer_clear_soft(peer, afi, safi, stype);
+ ret = bgp_peer_clear(peer, afi, safi, nnode,
+ stype);
if (ret < 0)
bgp_clear_vty_error(vty, peer, afi, safi, ret);
@@ -660,12 +779,11 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
}
}
- if (!peer->afc[afi][safi])
+ ret = bgp_peer_clear(peer, afi, safi, NULL, stype);
+
+ /* if afi/safi not defined for this peer, let caller know */
+ if (ret == 1)
ret = BGP_ERR_AF_UNCONFIGURED;
- else if (stype == BGP_CLEAR_SOFT_NONE)
- ret = peer_clear(peer, NULL);
- else
- ret = peer_clear_soft(peer, afi, safi, stype);
if (ret < 0)
bgp_clear_vty_error(vty, peer, afi, safi, ret);
@@ -684,13 +802,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
}
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- if (!peer->afc[afi][safi])
- continue;
-
- if (stype == BGP_CLEAR_SOFT_NONE)
- ret = peer_clear(peer, NULL);
- else
- ret = peer_clear_soft(peer, afi, safi, stype);
+ ret = bgp_peer_clear(peer, afi, safi, nnode, stype);
if (ret < 0)
bgp_clear_vty_error(vty, peer, afi, safi, ret);
@@ -701,7 +813,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
if (!found)
vty_out(vty,
"%%BGP: No %s peer belonging to peer-group %s is configured\n",
- afi_safi_print(afi, safi), arg);
+ get_afi_safi_str(afi, safi, false), arg);
return CMD_SUCCESS;
}
@@ -712,13 +824,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
if (peer->sort == BGP_PEER_IBGP)
continue;
- if (!peer->afc[afi][safi])
- continue;
-
- if (stype == BGP_CLEAR_SOFT_NONE)
- ret = peer_clear(peer, &nnode);
- else
- ret = peer_clear_soft(peer, afi, safi, stype);
+ ret = bgp_peer_clear(peer, afi, safi, nnode, stype);
if (ret < 0)
bgp_clear_vty_error(vty, peer, afi, safi, ret);
@@ -729,7 +835,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
if (!found)
vty_out(vty,
"%%BGP: No external %s peer is configured\n",
- afi_safi_print(afi, safi));
+ get_afi_safi_str(afi, safi, false));
return CMD_SUCCESS;
}
@@ -742,12 +848,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
if (peer->as != as)
continue;
- if (!peer->afc[afi][safi])
- ret = BGP_ERR_AF_UNCONFIGURED;
- else if (stype == BGP_CLEAR_SOFT_NONE)
- ret = peer_clear(peer, &nnode);
- else
- ret = peer_clear_soft(peer, afi, safi, stype);
+ ret = bgp_peer_clear(peer, afi, safi, nnode, stype);
if (ret < 0)
bgp_clear_vty_error(vty, peer, afi, safi, ret);
@@ -758,7 +859,7 @@ static int bgp_clear(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi,
if (!found)
vty_out(vty,
"%%BGP: No %s peer is configured with AS %s\n",
- afi_safi_print(afi, safi), arg);
+ get_afi_safi_str(afi, safi, false), arg);
return CMD_SUCCESS;
}
@@ -6069,7 +6170,7 @@ DEFUN (neighbor_allowas_in,
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Accept as-path with my AS present in it\n"
- "Number of occurences of AS number\n"
+ "Number of occurrences of AS number\n"
"Only accept my AS in the as-path if the route was originated in my AS\n")
{
int idx_peer = 1;
@@ -6103,7 +6204,7 @@ ALIAS_HIDDEN(
"neighbor <A.B.C.D|X:X::X:X|WORD> allowas-in [<(1-10)|origin>]",
NEIGHBOR_STR NEIGHBOR_ADDR_STR2
"Accept as-path with my AS present in it\n"
- "Number of occurences of AS number\n"
+ "Number of occurrences of AS number\n"
"Only accept my AS in the as-path if the route was originated in my AS\n")
DEFUN (no_neighbor_allowas_in,
@@ -6113,7 +6214,7 @@ DEFUN (no_neighbor_allowas_in,
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"allow local ASN appears in aspath attribute\n"
- "Number of occurences of AS number\n"
+ "Number of occurrences of AS number\n"
"Only accept my AS in the as-path if the route was originated in my AS\n")
{
int idx_peer = 2;
@@ -6135,7 +6236,7 @@ ALIAS_HIDDEN(
"no neighbor <A.B.C.D|X:X::X:X|WORD> allowas-in [<(1-10)|origin>]",
NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
"allow local ASN appears in aspath attribute\n"
- "Number of occurences of AS number\n"
+ "Number of occurrences of AS number\n"
"Only accept my AS in the as-path if the route was originated in my AS\n")
DEFUN (neighbor_ttl_security,
@@ -7238,8 +7339,8 @@ DEFUN (clear_ip_bgp_all,
{
char *vrf = NULL;
- afi_t afi = AFI_IP6;
- safi_t safi = SAFI_UNICAST;
+ afi_t afi = AFI_UNSPEC;
+ safi_t safi = SAFI_UNSPEC;
enum clear_sort clr_sort = clear_peer;
enum bgp_clear_type clr_type;
char *clr_arg = NULL;
@@ -8187,7 +8288,7 @@ static int bgp_show_summary(struct vty *vty, struct bgp *bgp, int afi, int safi,
vty_out(vty, "\nTotal number of neighbors %d\n", count);
else {
vty_out(vty, "No %s neighbor is configured\n",
- afi_safi_print(afi, safi));
+ get_afi_safi_str(afi, safi, false));
}
if (dn_count) {
@@ -8234,12 +8335,14 @@ static void bgp_show_summary_afi_safi(struct vty *vty, struct bgp *bgp, int afi,
is_first = 0;
vty_out(vty, "\"%s\":",
- afi_safi_json(afi,
- safi));
+ get_afi_safi_str(afi,
+ safi,
+ true));
} else {
vty_out(vty, "\n%s Summary:\n",
- afi_safi_print(afi,
- safi));
+ get_afi_safi_str(afi,
+ safi,
+ false));
}
}
bgp_show_summary(vty, bgp, afi, safi, use_json);
@@ -8384,74 +8487,12 @@ DEFUN (show_ip_bgp_summary,
return bgp_show_summary_vty(vty, vrf, afi, safi, uj);
}
-const char *afi_safi_print(afi_t afi, safi_t safi)
+const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json)
{
- if (afi == AFI_IP && safi == SAFI_UNICAST)
- return "IPv4 Unicast";
- else if (afi == AFI_IP && safi == SAFI_MULTICAST)
- return "IPv4 Multicast";
- else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST)
- return "IPv4 Labeled Unicast";
- else if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
- return "IPv4 VPN";
- else if (afi == AFI_IP && safi == SAFI_ENCAP)
- return "IPv4 Encap";
- else if (afi == AFI_IP && safi == SAFI_FLOWSPEC)
- return "IPv4 Flowspec";
- else if (afi == AFI_IP6 && safi == SAFI_UNICAST)
- return "IPv6 Unicast";
- else if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
- return "IPv6 Multicast";
- else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST)
- return "IPv6 Labeled Unicast";
- else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN)
- return "IPv6 VPN";
- else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
- return "IPv6 Encap";
- else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC)
- return "IPv6 Flowspec";
- else if (afi == AFI_L2VPN && safi == SAFI_EVPN)
- return "L2VPN EVPN";
+ if (for_json)
+ return get_afi_safi_json_str(afi, safi);
else
- return "Unknown";
-}
-
-/*
- * Please note that we have intentionally camelCased
- * the return strings here. So if you want
- * to use this function, please ensure you
- * are doing this within json output
- */
-const char *afi_safi_json(afi_t afi, safi_t safi)
-{
- if (afi == AFI_IP && safi == SAFI_UNICAST)
- return "ipv4Unicast";
- else if (afi == AFI_IP && safi == SAFI_MULTICAST)
- return "ipv4Multicast";
- else if (afi == AFI_IP && safi == SAFI_LABELED_UNICAST)
- return "ipv4LabeledUnicast";
- else if (afi == AFI_IP && safi == SAFI_MPLS_VPN)
- return "ipv4Vpn";
- else if (afi == AFI_IP && safi == SAFI_ENCAP)
- return "ipv4Encap";
- else if (afi == AFI_IP && safi == SAFI_FLOWSPEC)
- return "ipv4Flowspec";
- else if (afi == AFI_IP6 && safi == SAFI_UNICAST)
- return "ipv6Unicast";
- else if (afi == AFI_IP6 && safi == SAFI_MULTICAST)
- return "ipv6Multicast";
- else if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST)
- return "ipv6LabeledUnicast";
- else if (afi == AFI_IP6 && safi == SAFI_MPLS_VPN)
- return "ipv6Vpn";
- else if (afi == AFI_IP6 && safi == SAFI_ENCAP)
- return "ipv6Encap";
- else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC)
- return "ipv6Flowspec";
- else if (afi == AFI_L2VPN && safi == SAFI_EVPN)
- return "l2VpnEvpn";
- else
- return "Unknown";
+ return get_afi_safi_vty_str(afi, safi);
}
/* Show BGP peer's information. */
@@ -8829,14 +8870,14 @@ static void bgp_show_peer_afi(struct vty *vty, struct peer *p, afi_t afi,
"prefixAllowedRestartIntervalMsecs",
p->pmax_restart[afi][safi] * 60000);
}
- json_object_object_add(json_neigh, afi_safi_print(afi, safi),
+ json_object_object_add(json_neigh, get_afi_safi_str(afi, safi, true),
json_addr);
} else {
filter = &p->filter[afi][safi];
vty_out(vty, " For address family: %s\n",
- afi_safi_print(afi, safi));
+ get_afi_safi_str(afi, safi, false));
if (peer_group_active(p))
vty_out(vty, " %s peer-group member\n",
@@ -9543,8 +9584,8 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
json_object *json_sub = NULL;
json_sub =
json_object_new_object();
- print_store = afi_safi_print(
- afi, safi);
+ print_store = get_afi_safi_str(
+ afi, safi, true);
if (CHECK_FLAG(
p->af_cap[afi]
@@ -9722,9 +9763,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
[AFI_IP]
[safi],
PEER_CAP_ENHE_AF_RCV)) {
- print_store = afi_safi_print(
+ print_store = get_afi_safi_str(
AFI_IP,
- safi);
+ safi, true);
json_object_string_add(
json_nxt,
print_store,
@@ -9824,8 +9865,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
json_object_object_add(
json_multi,
- afi_safi_print(afi,
- safi),
+ get_afi_safi_str(afi,
+ safi,
+ true),
json_exten);
}
}
@@ -9931,9 +9973,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
restart_af_count++;
json_object_object_add(
json_restart,
- afi_safi_print(
+ get_afi_safi_str(
afi,
- safi),
+ safi,
+ true),
json_sub);
}
}
@@ -9992,9 +10035,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
PEER_CAP_ADDPATH_AF_TX_RCV)) {
vty_out(vty,
" %s: TX ",
- afi_safi_print(
+ get_afi_safi_str(
afi,
- safi));
+ safi,
+ false));
if (CHECK_FLAG(
p->af_cap
@@ -10003,9 +10047,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
PEER_CAP_ADDPATH_AF_TX_ADV))
vty_out(vty,
"advertised %s",
- afi_safi_print(
+ get_afi_safi_str(
afi,
- safi));
+ safi,
+ false));
if (CHECK_FLAG(
p->af_cap
@@ -10035,9 +10080,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
PEER_CAP_ADDPATH_AF_RX_RCV)) {
vty_out(vty,
" %s: RX ",
- afi_safi_print(
+ get_afi_safi_str(
afi,
- safi));
+ safi,
+ false));
if (CHECK_FLAG(
p->af_cap
@@ -10046,9 +10092,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
PEER_CAP_ADDPATH_AF_RX_ADV))
vty_out(vty,
"advertised %s",
- afi_safi_print(
+ get_afi_safi_str(
afi,
- safi));
+ safi,
+ false));
if (CHECK_FLAG(
p->af_cap
@@ -10119,9 +10166,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
PEER_CAP_ENHE_AF_RCV))
vty_out(vty,
" %s\n",
- afi_safi_print(
+ get_afi_safi_str(
AFI_IP,
- safi));
+ safi,
+ false));
}
}
@@ -10168,8 +10216,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
|| p->afc_recv[afi][safi]) {
vty_out(vty,
" Address Family %s:",
- afi_safi_print(afi,
- safi));
+ get_afi_safi_str(
+ afi,
+ safi,
+ false));
if (p->afc_adv[afi][safi])
vty_out(vty,
" advertised");
@@ -10254,9 +10304,10 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
restart_af_count
? ", "
: "",
- afi_safi_print(
+ get_afi_safi_str(
afi,
- safi),
+ safi,
+ false),
CHECK_FLAG(
p->af_cap
[afi]
@@ -10295,8 +10346,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
PEER_STATUS_EOR_SEND)) {
json_object_boolean_true_add(
json_grace_send,
- afi_safi_print(afi,
- safi));
+ get_afi_safi_str(afi,
+ safi,
+ true));
eor_send_af_count++;
}
}
@@ -10306,8 +10358,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
PEER_STATUS_EOR_RECEIVED)) {
json_object_boolean_true_add(
json_grace_recv,
- afi_safi_print(afi,
- safi));
+ get_afi_safi_str(afi,
+ safi,
+ true));
eor_receive_af_count++;
}
}
@@ -10345,8 +10398,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
vty_out(vty, "%s%s",
eor_send_af_count ? ", "
: "",
- afi_safi_print(afi,
- safi));
+ get_afi_safi_str(afi,
+ safi,
+ false));
eor_send_af_count++;
}
}
@@ -10360,8 +10414,9 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
eor_receive_af_count
? ", "
: "",
- afi_safi_print(afi,
- safi));
+ get_afi_safi_str(afi,
+ safi,
+ false));
eor_receive_af_count++;
}
}
@@ -11293,7 +11348,7 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
/* Provide context for the block */
json_object_string_add(json, "vrf", name ? name : "default");
json_object_string_add(json, "afiSafi",
- afi_safi_print(afi, safi));
+ get_afi_safi_str(afi, safi, true));
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
@@ -11374,11 +11429,11 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
BGP_CONFIG_VRF_TO_VRF_IMPORT))
vty_out(vty,
"This VRF is not importing %s routes from any other VRF\n",
- afi_safi_print(afi, safi));
+ get_afi_safi_str(afi, safi, false));
else {
vty_out(vty,
"This VRF is importing %s routes from the following VRFs:\n",
- afi_safi_print(afi, safi));
+ get_afi_safi_str(afi, safi, false));
for (ALL_LIST_ELEMENTS_RO(
bgp->vpn_policy[afi].import_vrf,
@@ -11402,11 +11457,11 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
BGP_CONFIG_VRF_TO_VRF_EXPORT))
vty_out(vty,
"This VRF is not exporting %s routes to any other VRF\n",
- afi_safi_print(afi, safi));
+ get_afi_safi_str(afi, safi, false));
else {
vty_out(vty,
"This VRF is exporting %s routes to the following VRFs:\n",
- afi_safi_print(afi, safi));
+ get_afi_safi_str(afi, safi, false));
for (ALL_LIST_ELEMENTS_RO(
bgp->vpn_policy[afi].export_vrf,
@@ -11783,7 +11838,7 @@ static int bgp_show_one_peer_group(struct vty *vty, struct peer_group *group)
FOREACH_AFI_SAFI (afi, safi) {
if (conf->afc[afi][safi]) {
af_cfgd = 1;
- vty_out(vty, " %s;", afi_safi_print(afi, safi));
+ vty_out(vty, " %s;", get_afi_safi_str(afi, safi, false));
}
}
if (!af_cfgd)
@@ -14452,12 +14507,13 @@ ALIAS (show_community_list,
DEFUN (show_community_list_arg,
show_bgp_community_list_arg_cmd,
- "show bgp community-list <(1-500)|WORD>",
+ "show bgp community-list <(1-500)|WORD> detail",
SHOW_STR
BGP_STR
"List community-list\n"
"Community-list number\n"
- "Community-list name\n")
+ "Community-list name\n"
+ "Detailed information on community-list\n")
{
int idx_comm_list = 3;
struct community_list *list;
@@ -14466,8 +14522,8 @@ DEFUN (show_community_list_arg,
if (argv_find(argv, argc, "ip", &idx)) {
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
vty_out(vty, "if you are using this please migrate to the below command.\n");
- vty_out(vty, "'show bgp community-list <(1-500)|WORD>'\n");
- zlog_warn("Deprecated option: 'ip show community-list <(1-500)|WORD>' being used");
+ vty_out(vty, "'show bgp community-list <(1-500)|WORD> detail'\n");
+ zlog_warn("Deprecated option: 'show ip community-list <(1-500)|WORD>' being used");
}
list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, 0,
COMMUNITY_LIST_MASTER);
@@ -14606,28 +14662,6 @@ CPP_NOTICE("bgpd: remove deprecated 'ip large-community-list <(1-99)|(100-500)|s
#endif
DEFUN (lcommunity_list_standard,
bgp_lcommunity_list_standard_cmd,
- "bgp large-community-list (1-99) <deny|permit>",
- BGP_STR
- LCOMMUNITY_LIST_STR
- "Large Community list number (standard)\n"
- "Specify large community to reject\n"
- "Specify large community to accept\n")
-{
- return lcommunity_list_set_vty(vty, argc, argv,
- LARGE_COMMUNITY_LIST_STANDARD, 0);
-}
-
-ALIAS (lcommunity_list_standard,
- ip_lcommunity_list_standard_cmd,
- "ip large-community-list (1-99) <deny|permit>",
- IP_STR
- LCOMMUNITY_LIST_STR
- "Large Community list number (standard)\n"
- "Specify large community to reject\n"
- "Specify large community to accept\n")
-
-DEFUN (lcommunity_list_standard1,
- bgp_lcommunity_list_standard1_cmd,
"bgp large-community-list (1-99) <deny|permit> AA:BB:CC...",
BGP_STR
LCOMMUNITY_LIST_STR
@@ -14640,8 +14674,8 @@ DEFUN (lcommunity_list_standard1,
LARGE_COMMUNITY_LIST_STANDARD, 0);
}
-ALIAS (lcommunity_list_standard1,
- ip_lcommunity_list_standard1_cmd,
+ALIAS (lcommunity_list_standard,
+ ip_lcommunity_list_standard_cmd,
"ip large-community-list (1-99) <deny|permit> AA:BB:CC...",
IP_STR
LCOMMUNITY_LIST_STR
@@ -14676,30 +14710,6 @@ ALIAS (lcommunity_list_expanded,
DEFUN (lcommunity_list_name_standard,
bgp_lcommunity_list_name_standard_cmd,
- "bgp large-community-list standard WORD <deny|permit>",
- BGP_STR
- LCOMMUNITY_LIST_STR
- "Specify standard large-community-list\n"
- "Large Community list name\n"
- "Specify large community to reject\n"
- "Specify large community to accept\n")
-{
- return lcommunity_list_set_vty(vty, argc, argv,
- LARGE_COMMUNITY_LIST_STANDARD, 1);
-}
-
-ALIAS (lcommunity_list_name_standard,
- ip_lcommunity_list_name_standard_cmd,
- "ip large-community-list standard WORD <deny|permit>",
- IP_STR
- LCOMMUNITY_LIST_STR
- "Specify standard large-community-list\n"
- "Large Community list name\n"
- "Specify large community to reject\n"
- "Specify large community to accept\n")
-
-DEFUN (lcommunity_list_name_standard1,
- bgp_lcommunity_list_name_standard1_cmd,
"bgp large-community-list standard WORD <deny|permit> AA:BB:CC...",
BGP_STR
LCOMMUNITY_LIST_STR
@@ -14713,8 +14723,8 @@ DEFUN (lcommunity_list_name_standard1,
LARGE_COMMUNITY_LIST_STANDARD, 1);
}
-ALIAS (lcommunity_list_name_standard1,
- ip_lcommunity_list_name_standard1_cmd,
+ALIAS (lcommunity_list_name_standard,
+ ip_lcommunity_list_name_standard_cmd,
"ip large-community-list standard WORD <deny|permit> AA:BB:CC...",
IP_STR
LCOMMUNITY_LIST_STR
@@ -14977,12 +14987,13 @@ ALIAS (show_lcommunity_list,
DEFUN (show_lcommunity_list_arg,
show_bgp_lcommunity_list_arg_cmd,
- "show bgp large-community-list <(1-500)|WORD>",
+ "show bgp large-community-list <(1-500)|WORD> detail",
SHOW_STR
BGP_STR
"List large-community list\n"
- "large-community-list number\n"
- "large-community-list name\n")
+ "Large-community-list number\n"
+ "Large-community-list name\n"
+ "Detailed information on large-community-list\n")
{
struct community_list *list;
int idx = 0;
@@ -14990,14 +15001,14 @@ DEFUN (show_lcommunity_list_arg,
if (argv_find(argv, argc, "ip", &idx)) {
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
vty_out(vty, "if you are using this please migrate to the below command.\n");
- vty_out(vty, "'show bgp large-community-list <(1-500)|WORD>'\n");
- zlog_warn("Deprecated option: 'ip show large-community-list <(1-500)|WORD>' being used");
+ vty_out(vty, "'show bgp large-community-list <(1-500)|WORD> detail'\n");
+ zlog_warn("Deprecated option: 'show ip large-community-list <(1-500)|WORD>' being used");
}
list = community_list_lookup(bgp_clist, argv[3]->arg, 0,
LARGE_COMMUNITY_LIST_MASTER);
if (!list) {
- vty_out(vty, "%% Can't find extcommunity-list\n");
+ vty_out(vty, "%% Can't find large-community-list\n");
return CMD_WARNING;
}
@@ -15378,12 +15389,13 @@ ALIAS (show_extcommunity_list,
DEFUN (show_extcommunity_list_arg,
show_bgp_extcommunity_list_arg_cmd,
- "show bgp extcommunity-list <(1-500)|WORD>",
+ "show bgp extcommunity-list <(1-500)|WORD> detail",
SHOW_STR
BGP_STR
"List extended-community list\n"
"Extcommunity-list number\n"
- "Extcommunity-list name\n")
+ "Extcommunity-list name\n"
+ "Detailed information on extcommunity-list\n")
{
int idx_comm_list = 3;
struct community_list *list;
@@ -15392,8 +15404,8 @@ DEFUN (show_extcommunity_list_arg,
if (argv_find(argv, argc, "ip", &idx)) {
vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n");
vty_out(vty, "if you are using this please migrate to the below command.\n");
- vty_out(vty, "'show bgp extcommunity-list <(1-500)|WORD>'\n");
- zlog_warn("Deprecated option: 'ip show extcommunity-list <(1-500)|WORD>' being used");
+ vty_out(vty, "'show bgp extcommunity-list <(1-500)|WORD> detail'\n");
+ zlog_warn("Deprecated option: 'show ip extcommunity-list <(1-500)|WORD>' being used");
}
list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, 0,
EXTCOMMUNITY_LIST_MASTER);
@@ -15540,10 +15552,8 @@ static void community_list_vty(void)
/* Large Community List */
install_element(CONFIG_NODE, &bgp_lcommunity_list_standard_cmd);
- install_element(CONFIG_NODE, &bgp_lcommunity_list_standard1_cmd);
install_element(CONFIG_NODE, &bgp_lcommunity_list_expanded_cmd);
install_element(CONFIG_NODE, &bgp_lcommunity_list_name_standard_cmd);
- install_element(CONFIG_NODE, &bgp_lcommunity_list_name_standard1_cmd);
install_element(CONFIG_NODE, &bgp_lcommunity_list_name_expanded_cmd);
install_element(CONFIG_NODE, &no_bgp_lcommunity_list_standard_all_cmd);
install_element(CONFIG_NODE,
@@ -15555,10 +15565,8 @@ static void community_list_vty(void)
install_element(VIEW_NODE, &show_bgp_lcommunity_list_cmd);
install_element(VIEW_NODE, &show_bgp_lcommunity_list_arg_cmd);
install_element(CONFIG_NODE, &ip_lcommunity_list_standard_cmd);
- install_element(CONFIG_NODE, &ip_lcommunity_list_standard1_cmd);
install_element(CONFIG_NODE, &ip_lcommunity_list_expanded_cmd);
install_element(CONFIG_NODE, &ip_lcommunity_list_name_standard_cmd);
- install_element(CONFIG_NODE, &ip_lcommunity_list_name_standard1_cmd);
install_element(CONFIG_NODE, &ip_lcommunity_list_name_expanded_cmd);
install_element(CONFIG_NODE, &no_ip_lcommunity_list_standard_all_cmd);
install_element(CONFIG_NODE,
diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h
index d9df2b4cfe..961467e229 100644
--- a/bgpd/bgp_vty.h
+++ b/bgpd/bgp_vty.h
@@ -45,8 +45,7 @@ struct bgp;
"Address Family modifier\n"
extern void bgp_vty_init(void);
-extern const char *afi_safi_print(afi_t afi, safi_t safi);
-extern const char *afi_safi_json(afi_t afi, safi_t safi);
+extern const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
extern void bgp_config_write_update_delay(struct vty *vty, struct bgp *bgp);
extern void bgp_config_write_wpkt_quanta(struct vty *vty, struct bgp *bgp);
extern void bgp_config_write_rpkt_quanta(struct vty *vty, struct bgp *bgp);
diff --git a/configure.ac b/configure.ac
index 134c8692d4..676c984385 100755
--- a/configure.ac
+++ b/configure.ac
@@ -1061,6 +1061,7 @@ case "$host_os" in
AC_CHECK_LIB([nsl], [main])
AC_CHECK_LIB([umem], [main])
SOLARIS="solaris"
+ AC_MSG_WARN([--Solaris support is being considered for deprecation, please let us know if you are still using this--])
;;
linux*)
AC_MSG_RESULT([Linux])
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index f2b1328075..92d4126cec 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -1169,19 +1169,24 @@ AS path access list is user defined AS path.
Using AS Path in Route Map
--------------------------
-.. index:: match as-path WORD
-.. clicmd:: match as-path WORD
+.. index:: [no] match as-path WORD
+.. clicmd:: [no] match as-path WORD
+ For a given as-path, WORD, match it on the BGP as-path given for the prefix
+ and if it matches do normal route-map actions. The no form of the command
+ removes this match from the route-map.
-.. index:: set as-path prepend AS-PATH
-.. clicmd:: set as-path prepend AS-PATH
+.. index:: [no] set as-path prepend AS-PATH
+.. clicmd:: [no] set as-path prepend AS-PATH
- Prepend the given string of AS numbers to the AS_PATH.
+ Prepend the given string of AS numbers to the AS_PATH of the BGP path's NLRI.
+ The no form of this command removes this set operation from the route-map.
-.. index:: set as-path prepend last-as NUM
-.. clicmd:: set as-path prepend last-as NUM
+.. index:: [no] set as-path prepend last-as NUM
+.. clicmd:: [no] set as-path prepend last-as NUM
Prepend the existing last AS number (the leftmost ASN) to the AS_PATH.
+ The no form of this command removes this set operation from the route-map.
.. _bgp-communities-attribute:
@@ -2138,20 +2143,40 @@ Dumping Messages and Routing Tables
Other BGP Commands
------------------
+.. index:: clear bgp \*
+.. clicmd:: clear bgp \*
+
+ Clear all peers.
+
.. index:: clear bgp ipv4|ipv6 \*
.. clicmd:: clear bgp ipv4|ipv6 \*
- Clear all address family peers.
+ Clear all peers with this address-family activated.
+
+.. index:: clear bgp ipv4|ipv6 unicast \*
+.. clicmd:: clear bgp ipv4|ipv6 unicast \*
+
+ Clear all peers with this address-family and sub-address-family activated.
.. index:: clear bgp ipv4|ipv6 PEER
.. clicmd:: clear bgp ipv4|ipv6 PEER
- Clear peers which have addresses of X.X.X.X
+ Clear peers with address of X.X.X.X and this address-family activated.
+
+.. index:: clear bgp ipv4|ipv6 unicast PEER
+.. clicmd:: clear bgp ipv4|ipv6 unicast PEER
+
+ Clear peer with address of X.X.X.X and this address-family and sub-address-family activated.
+
+.. index:: clear bgp ipv4|ipv6 PEER soft|in|out
+.. clicmd:: clear bgp ipv4|ipv6 PEER soft|in|out
+
+ Clear peer using soft reconfiguration in this address-family.
-.. index:: clear bgp ipv4|ipv6 PEER soft in
-.. clicmd:: clear bgp ipv4|ipv6 PEER soft in
+.. index:: clear bgp ipv4|ipv6 unicast PEER soft|in|out
+.. clicmd:: clear bgp ipv4|ipv6 unicast PEER soft|in|out
- Clear peer using soft reconfiguration.
+ Clear peer using soft reconfiguration in this address-family and sub-address-family.
.. _bgp-displaying-bgp-information:
diff --git a/isisd/isis_bfd.c b/isisd/isis_bfd.c
index fa89c80049..8fc7997d79 100644
--- a/isisd/isis_bfd.c
+++ b/isisd/isis_bfd.c
@@ -19,7 +19,9 @@
#include <zebra.h>
#include "zclient.h"
+#include "nexthop.h"
#include "bfd.h"
+#include "lib_errors.h"
#include "isisd/isis_bfd.h"
#include "isisd/isis_zebra.h"
@@ -33,17 +35,19 @@
DEFINE_MTYPE_STATIC(ISISD, BFD_SESSION, "ISIS BFD Session")
struct bfd_session {
- struct in_addr dst_ip;
- struct in_addr src_ip;
+ int family;
+ union g_addr dst_ip;
+ union g_addr src_ip;
int status;
};
-static struct bfd_session *bfd_session_new(struct in_addr *dst_ip,
- struct in_addr *src_ip)
+static struct bfd_session *bfd_session_new(int family, union g_addr *dst_ip,
+ union g_addr *src_ip)
{
struct bfd_session *rv;
rv = XCALLOC(MTYPE_BFD_SESSION, sizeof(*rv));
+ rv->family = family;
rv->dst_ip = *dst_ip;
rv->src_ip = *src_ip;
return rv;
@@ -58,15 +62,60 @@ static void bfd_session_free(struct bfd_session **session)
*session = NULL;
}
+static bool bfd_session_same(const struct bfd_session *session, int family,
+ const union g_addr *src, const union g_addr *dst)
+{
+ if (session->family != family)
+ return false;
+
+ switch (session->family) {
+ case AF_INET:
+ if (!IPV4_ADDR_SAME(&session->dst_ip.ipv4, &dst->ipv4))
+ return false;
+ if (!IPV4_ADDR_SAME(&session->src_ip.ipv4, &src->ipv4))
+ return false;
+ break;
+ case AF_INET6:
+ if (!IPV6_ADDR_SAME(&session->dst_ip.ipv6, &dst->ipv6))
+ return false;
+ if (!IPV6_ADDR_SAME(&session->src_ip.ipv6, &src->ipv6))
+ return false;
+ break;
+ default:
+ flog_err(EC_LIB_DEVELOPMENT, "%s: unknown address-family: %u",
+ __func__, session->family);
+ exit(1);
+ }
+
+ return true;
+}
+
static void bfd_adj_event(struct isis_adjacency *adj, struct prefix *dst,
int new_status)
{
if (!adj->bfd_session)
return;
- if (adj->bfd_session->dst_ip.s_addr != dst->u.prefix4.s_addr)
+ if (adj->bfd_session->family != dst->family)
return;
+ switch (adj->bfd_session->family) {
+ case AF_INET:
+ if (!IPV4_ADDR_SAME(&adj->bfd_session->dst_ip.ipv4,
+ &dst->u.prefix4))
+ return;
+ break;
+ case AF_INET6:
+ if (!IPV6_ADDR_SAME(&adj->bfd_session->dst_ip.ipv6,
+ &dst->u.prefix6))
+ return;
+ break;
+ default:
+ flog_err(EC_LIB_DEVELOPMENT, "%s: unknown address-family: %u",
+ __func__, adj->bfd_session->family);
+ exit(1);
+ }
+
int old_status = adj->bfd_session->status;
adj->bfd_session->status = new_status;
@@ -76,7 +125,7 @@ static void bfd_adj_event(struct isis_adjacency *adj, struct prefix *dst,
if (isis->debugs & DEBUG_BFD) {
char dst_str[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET, &adj->bfd_session->dst_ip,
+ inet_ntop(adj->bfd_session->family, &adj->bfd_session->dst_ip,
dst_str, sizeof(dst_str));
zlog_debug("ISIS-BFD: Peer %s on %s changed from %s to %s",
dst_str, adj->circuit->interface->name,
@@ -100,14 +149,14 @@ static int isis_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
ifp = bfd_get_peer_info(zclient->ibuf, &dst_ip, NULL, &status,
NULL, vrf_id);
- if (!ifp || dst_ip.family != AF_INET)
+ if (!ifp || (dst_ip.family != AF_INET && dst_ip.family != AF_INET6))
return 0;
if (isis->debugs & DEBUG_BFD) {
char dst_buf[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET, &dst_ip.u.prefix4,
- dst_buf, sizeof(dst_buf));
+ inet_ntop(dst_ip.family, &dst_ip.u.prefix, dst_buf,
+ sizeof(dst_buf));
zlog_debug("ISIS-BFD: Received update for %s on %s: Changed state to %s",
dst_buf, ifp->name, bfd_get_status_str(status));
@@ -171,7 +220,7 @@ static void isis_bfd_zebra_connected(struct zclient *zclient)
bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);
}
-static void bfd_debug(struct in_addr *dst, struct in_addr *src,
+static void bfd_debug(int family, union g_addr *dst, union g_addr *src,
const char *interface, int command)
{
if (!(isis->debugs & DEBUG_BFD))
@@ -180,8 +229,8 @@ static void bfd_debug(struct in_addr *dst, struct in_addr *src,
char dst_str[INET6_ADDRSTRLEN];
char src_str[INET6_ADDRSTRLEN];
- inet_ntop(AF_INET, dst, dst_str, sizeof(dst_str));
- inet_ntop(AF_INET, src, src_str, sizeof(src_str));
+ inet_ntop(family, dst, dst_str, sizeof(dst_str));
+ inet_ntop(family, src, src_str, sizeof(src_str));
const char *command_str;
@@ -209,10 +258,11 @@ static void bfd_handle_adj_down(struct isis_adjacency *adj)
if (!adj->bfd_session)
return;
- bfd_debug(&adj->bfd_session->dst_ip, &adj->bfd_session->src_ip,
- adj->circuit->interface->name, ZEBRA_BFD_DEST_DEREGISTER);
+ bfd_debug(adj->bfd_session->family, &adj->bfd_session->dst_ip,
+ &adj->bfd_session->src_ip, adj->circuit->interface->name,
+ ZEBRA_BFD_DEST_DEREGISTER);
- bfd_peer_sendmsg(zclient, NULL, AF_INET,
+ bfd_peer_sendmsg(zclient, NULL, adj->bfd_session->family,
&adj->bfd_session->dst_ip,
&adj->bfd_session->src_ip,
adj->circuit->interface->name,
@@ -228,33 +278,50 @@ static void bfd_handle_adj_down(struct isis_adjacency *adj)
static void bfd_handle_adj_up(struct isis_adjacency *adj, int command)
{
struct isis_circuit *circuit = adj->circuit;
+ int family;
+ union g_addr dst_ip;
+ union g_addr src_ip;
+ struct list *local_ips;
+ struct prefix *local_ip;
- if (!circuit->bfd_info
- || !circuit->ip_router
- || !adj->ipv4_address_count)
+ if (!circuit->bfd_info)
goto out;
- struct list *local_ips = fabricd_ip_addrs(adj->circuit);
-
- if (!local_ips)
+ /*
+ * If IS-IS is enabled for both IPv4 and IPv6 on the circuit, prefer
+ * creating a BFD session over IPv6.
+ */
+ if (circuit->ipv6_router && adj->ipv6_address_count) {
+ family = AF_INET6;
+ dst_ip.ipv6 = adj->ipv6_addresses[0];
+ local_ips = circuit->ipv6_link;
+ if (!local_ips || list_isempty(local_ips))
+ goto out;
+ local_ip = listgetdata(listhead(local_ips));
+ src_ip.ipv6 = local_ip->u.prefix6;
+ } else if (circuit->ip_router && adj->ipv4_address_count) {
+ family = AF_INET;
+ dst_ip.ipv4 = adj->ipv4_addresses[0];
+ local_ips = fabricd_ip_addrs(adj->circuit);
+ if (!local_ips || list_isempty(local_ips))
+ goto out;
+ local_ip = listgetdata(listhead(local_ips));
+ src_ip.ipv4 = local_ip->u.prefix4;
+ } else
goto out;
- struct in_addr *dst_ip = &adj->ipv4_addresses[0];
- struct prefix_ipv4 *local_ip = listgetdata(listhead(local_ips));
- struct in_addr *src_ip = &local_ip->prefix;
-
if (adj->bfd_session) {
- if (adj->bfd_session->dst_ip.s_addr != dst_ip->s_addr
- || adj->bfd_session->src_ip.s_addr != src_ip->s_addr)
+ if (bfd_session_same(adj->bfd_session, family, &src_ip,
+ &dst_ip))
bfd_handle_adj_down(adj);
}
if (!adj->bfd_session)
- adj->bfd_session = bfd_session_new(dst_ip, src_ip);
+ adj->bfd_session = bfd_session_new(family, &dst_ip, &src_ip);
- bfd_debug(&adj->bfd_session->dst_ip, &adj->bfd_session->src_ip,
- circuit->interface->name, command);
- bfd_peer_sendmsg(zclient, circuit->bfd_info, AF_INET,
+ bfd_debug(adj->bfd_session->family, &adj->bfd_session->dst_ip,
+ &adj->bfd_session->src_ip, circuit->interface->name, command);
+ bfd_peer_sendmsg(zclient, circuit->bfd_info, adj->bfd_session->family,
&adj->bfd_session->dst_ip,
&adj->bfd_session->src_ip,
circuit->interface->name,
diff --git a/lib/ferr.c b/lib/ferr.c
index 8afc926c41..fd5fb50172 100644
--- a/lib/ferr.c
+++ b/lib/ferr.c
@@ -170,7 +170,7 @@ void log_ref_display(struct vty *vty, uint32_t code, bool json)
DEFUN_NOSH(show_error_code,
show_error_code_cmd,
- "show error <(1-4294967296)|all> [json]",
+ "show error <(1-4294967295)|all> [json]",
SHOW_STR
"Information on errors\n"
"Error code to get info about\n"
diff --git a/lib/frrcu.c b/lib/frrcu.c
index 7e6475b648..54626f909d 100644
--- a/lib/frrcu.c
+++ b/lib/frrcu.c
@@ -55,7 +55,6 @@
#include "atomlist.h"
DEFINE_MTYPE_STATIC(LIB, RCU_THREAD, "RCU thread")
-DEFINE_MTYPE_STATIC(LIB, RCU_NEXT, "RCU sequence barrier")
DECLARE_ATOMLIST(rcu_heads, struct rcu_head, head)
@@ -226,7 +225,7 @@ static void rcu_bump(void)
{
struct rcu_next *rn;
- rn = XMALLOC(MTYPE_RCU_NEXT, sizeof(*rn));
+ rn = XMALLOC(MTYPE_RCU_THREAD, sizeof(*rn));
/* note: each RCUA_NEXT item corresponds to exactly one seqno bump.
* This means we don't need to communicate which seqno is which
@@ -269,7 +268,7 @@ static void rcu_bump(void)
* "last item is being deleted - start over" case, and then we may end
* up accessing old RCU queue items that are already free'd.
*/
- rcu_free_internal(MTYPE_RCU_NEXT, rn, head_free);
+ rcu_free_internal(MTYPE_RCU_THREAD, rn, head_free);
/* Only allow the RCU sweeper to run after these 2 items are queued.
*
diff --git a/lib/if.c b/lib/if.c
index 9ee2f02e62..5f92327562 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -45,6 +45,8 @@ DEFINE_MTYPE_STATIC(LIB, NBR_CONNECTED, "Neighbor Connected")
DEFINE_MTYPE(LIB, CONNECTED_LABEL, "Connected interface label")
DEFINE_MTYPE_STATIC(LIB, IF_LINK_PARAMS, "Informational Link Parameters")
+static struct interface *if_lookup_by_ifindex(ifindex_t ifindex,
+ vrf_id_t vrf_id);
static int if_cmp_func(const struct interface *, const struct interface *);
static int if_cmp_index_func(const struct interface *ifp1,
const struct interface *ifp2);
@@ -257,8 +259,9 @@ void if_delete(struct interface *ifp)
XFREE(MTYPE_IF, ifp);
}
-/* Interface existance check by index. */
-struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id)
+/* Used only internally to check within VRF only */
+static struct interface *if_lookup_by_ifindex(ifindex_t ifindex,
+ vrf_id_t vrf_id)
{
struct vrf *vrf;
struct interface if_tmp;
@@ -271,6 +274,19 @@ struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id)
return RB_FIND(if_index_head, &vrf->ifaces_by_index, &if_tmp);
}
+/* Interface existance check by index. */
+struct interface *if_lookup_by_index(ifindex_t ifindex, vrf_id_t vrf_id)
+{
+ switch (vrf_get_backend()) {
+ case VRF_BACKEND_UNKNOWN:
+ case VRF_BACKEND_NETNS:
+ return(if_lookup_by_ifindex(ifindex, vrf_id));
+ case VRF_BACKEND_VRF_LITE:
+ return(if_lookup_by_index_all_vrf(ifindex));
+ }
+ return NULL;
+}
+
const char *ifindex2ifname(ifindex_t ifindex, vrf_id_t vrf_id)
{
struct interface *ifp;
@@ -329,7 +345,7 @@ struct interface *if_lookup_by_index_all_vrf(ifindex_t ifindex)
return NULL;
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) {
- ifp = if_lookup_by_index(ifindex, vrf->vrf_id);
+ ifp = if_lookup_by_ifindex(ifindex, vrf->vrf_id);
if (ifp)
return ifp;
}
@@ -337,7 +353,7 @@ struct interface *if_lookup_by_index_all_vrf(ifindex_t ifindex)
return NULL;
}
-/* Lookup interface by IPv4 address. */
+/* Lookup interface by IP address. */
struct interface *if_lookup_exact_address(void *src, int family,
vrf_id_t vrf_id)
{
@@ -369,7 +385,7 @@ struct interface *if_lookup_exact_address(void *src, int family,
return NULL;
}
-/* Lookup interface by IPv4 address. */
+/* Lookup interface by IP address. */
struct connected *if_lookup_address(void *matchaddr, int family,
vrf_id_t vrf_id)
{
@@ -489,7 +505,7 @@ struct interface *if_get_by_ifindex(ifindex_t ifindex, vrf_id_t vrf_id)
switch (vrf_get_backend()) {
case VRF_BACKEND_UNKNOWN:
case VRF_BACKEND_NETNS:
- ifp = if_lookup_by_index(ifindex, vrf_id);
+ ifp = if_lookup_by_ifindex(ifindex, vrf_id);
if (ifp)
return ifp;
return if_create_ifindex(ifindex, vrf_id);
diff --git a/lib/if.h b/lib/if.h
index 871e319f29..e3ec278f9f 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -383,16 +383,12 @@ struct connected {
/* N.B. the ZEBRA_IFA_PEER flag should be set if and only if
a peer address has been configured. If this flag is set,
the destination field must contain the peer address.
- Otherwise, if this flag is not set, the destination address
- will either contain a broadcast address or be NULL.
*/
/* Address of connected network. */
struct prefix *address;
- /* Peer or Broadcast address, depending on whether ZEBRA_IFA_PEER is
- set.
- Note: destination may be NULL if ZEBRA_IFA_PEER is not set. */
+ /* Peer address, if ZEBRA_IFA_PEER is set, otherwise NULL */
struct prefix *destination;
/* Label for Linux 2.2.X and upper. */
diff --git a/lib/libfrr.c b/lib/libfrr.c
index 35c6092140..4301dc20ad 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -410,7 +410,7 @@ static int frr_opt(int opt)
}
if (di->zpathspace)
fprintf(stderr,
- "-N option overriden by -z for zebra named socket path\n");
+ "-N option overridden by -z for zebra named socket path\n");
if (strchr(optarg, '/') || strchr(optarg, '.')) {
fprintf(stderr,
diff --git a/lib/northbound.h b/lib/northbound.h
index 69d7c8e0ee..ce79d907f9 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -347,15 +347,6 @@ struct nb_callbacks {
* dnode
* libyang data node that should be shown in the form of a CLI
* command.
- *
- * show_defaults
- * Specify whether to display default configuration values or not.
- * This parameter can be ignored most of the time since the
- * northbound doesn't call this callback for default leaves or
- * non-presence containers that contain only default child nodes.
- * The exception are commands associated to multiple configuration
- * nodes, in which case it might be desirable to hide one or more
- * parts of the command when this parameter is set to false.
*/
void (*cli_show_end)(struct vty *vty, struct lyd_node *dnode);
};
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index c691bb27aa..884c01a457 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -757,7 +757,7 @@ DEFPY (config_load,
"configuration load\
<\
file [<json$json|xml$xml> [translate WORD$translator_family]] FILENAME$filename\
- |transaction (1-4294967296)$tid\
+ |transaction (1-4294967295)$tid\
>\
[replace$replace]",
"Configuration related settings\n"
@@ -923,12 +923,12 @@ DEFPY (show_config_compare,
<\
candidate$c1_candidate\
|running$c1_running\
- |transaction (1-4294967296)$c1_tid\
+ |transaction (1-4294967295)$c1_tid\
>\
<\
candidate$c2_candidate\
|running$c2_running\
- |transaction (1-4294967296)$c2_tid\
+ |transaction (1-4294967295)$c2_tid\
>\
[<json$json|xml$xml> [translate WORD$translator_family]]",
SHOW_STR
@@ -1029,11 +1029,11 @@ ALIAS (show_config_compare,
"show configuration compare\
<\
running$c1_running\
- |transaction (1-4294967296)$c1_tid\
+ |transaction (1-4294967295)$c1_tid\
>\
<\
running$c2_running\
- |transaction (1-4294967296)$c2_tid\
+ |transaction (1-4294967295)$c2_tid\
>\
[<json$json|xml$xml> [translate WORD$translator_family]]",
SHOW_STR
@@ -1192,7 +1192,7 @@ DEFPY (show_config_transaction,
show_config_transaction_cmd,
"show configuration transaction\
[\
- (1-4294967296)$transaction_id\
+ (1-4294967295)$transaction_id\
[<json$json|xml$xml> [translate WORD$translator_family]]\
[<\
with-defaults$with_defaults\
@@ -1593,7 +1593,7 @@ static int nb_cli_rollback_configuration(struct vty *vty,
DEFPY (rollback_config,
rollback_config_cmd,
- "rollback configuration (1-4294967296)$transaction_id",
+ "rollback configuration (1-4294967295)$transaction_id",
"Rollback to a previous state\n"
"Running configuration\n"
"Transaction ID\n")
diff --git a/lib/prefix.c b/lib/prefix.c
index 1a4a914e05..ad8dea273e 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -853,7 +853,7 @@ void prefix_ipv4_free(struct prefix_ipv4 *p)
prefix_free((struct prefix *)p);
}
-/* When string format is invalid return 0. */
+/* If given string is valid return 1 else return 0 */
int str2prefix_ipv4(const char *str, struct prefix_ipv4 *p)
{
int ret;
@@ -881,8 +881,10 @@ int str2prefix_ipv4(const char *str, struct prefix_ipv4 *p)
cp = XMALLOC(MTYPE_TMP, (pnt - str) + 1);
memcpy(cp, str, pnt - str);
*(cp + (pnt - str)) = '\0';
- ret = inet_aton(cp, &p->prefix);
+ ret = inet_pton(AF_INET, cp, &p->prefix);
XFREE(MTYPE_TMP, cp);
+ if (ret == 0)
+ return 0;
/* Get prefix length. */
plen = (uint8_t)atoi(++pnt);
@@ -1023,7 +1025,7 @@ void prefix_ipv6_free(struct prefix_ipv6 *p)
prefix_free((struct prefix *)p);
}
-/* If given string is valid return pin6 else return NULL */
+/* If given string is valid return 1 else return 0 */
int str2prefix_ipv6(const char *str, struct prefix_ipv6 *p)
{
char *pnt;
diff --git a/lib/stream.c b/lib/stream.c
index c67bc3c993..dfd13ca186 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -186,14 +186,6 @@ size_t stream_resize_inplace(struct stream **sptr, size_t newsize)
return orig->size;
}
-size_t __attribute__((deprecated))stream_resize_orig(struct stream *s,
- size_t newsize)
-{
- assert("stream_resize: Switch code to use stream_resize_inplace" == NULL);
-
- return stream_resize_inplace(&s, newsize);
-}
-
size_t stream_get_getp(struct stream *s)
{
STREAM_VERIFY_SANE(s);
diff --git a/lib/stream.h b/lib/stream.h
index a903ec0ea5..1144e43ef0 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -153,11 +153,6 @@ extern void stream_free(struct stream *);
extern struct stream *stream_copy(struct stream *, struct stream *src);
extern struct stream *stream_dup(struct stream *);
-#if CONFDATE > 20190821
-CPP_NOTICE("lib: time to remove stream_resize_orig")
-#endif
-extern size_t stream_resize_orig(struct stream *s, size_t newsize);
-#define stream_resize stream_resize_orig
extern size_t stream_resize_inplace(struct stream **sptr, size_t newsize);
extern size_t stream_get_getp(struct stream *);
diff --git a/lib/thread.c b/lib/thread.c
index 5756ebc1f9..943b849ebf 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -714,7 +714,7 @@ static int fd_poll(struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize,
{
/* If timer_wait is null here, that means poll() should block
* indefinitely,
- * unless the thread_master has overriden it by setting
+ * unless the thread_master has overridden it by setting
* ->selectpoll_timeout.
* If the value is positive, it specifies the maximum number of
* milliseconds
diff --git a/lib/vty.c b/lib/vty.c
index c1535802cf..deb9391bd5 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -348,6 +348,15 @@ void vty_hello(struct vty *vty)
vty_out(vty, "MOTD file not found\n");
} else if (host.motd)
vty_out(vty, "%s", host.motd);
+
+#if CONFDATE > 20200901
+ CPP_NOTICE("Please remove solaris code from system as it is deprecated");
+#endif
+#ifdef SUNOS_5
+ zlog_warn("If you are using FRR on Solaris, the FRR developers would love to hear from you\n");
+ zlog_warn("Please send email to dev@lists.frrouting.org about this message\n");
+ zlog_warn("We are considering deprecating Solaris and want to find users of Solaris systems\n");
+#endif
}
/* Put out prompt and wait input from user. */
diff --git a/lib/zclient.c b/lib/zclient.c
index 6937700199..2d79d9b3c5 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -325,8 +325,9 @@ int zclient_read_header(struct stream *s, int sock, uint16_t *size,
if (*size && stream_read(s, sock, *size) != *size)
return -1;
-stream_failure:
return 0;
+stream_failure:
+ return -1;
}
bool zapi_parse_header(struct stream *zmsg, struct zmsghdr *hdr)
@@ -1056,8 +1057,9 @@ int zapi_route_decode(struct stream *s, struct zapi_route *api)
if (CHECK_FLAG(api->message, ZAPI_MESSAGE_TABLEID))
STREAM_GETL(s, api->tableid);
-stream_failure:
return 0;
+stream_failure:
+ return -1;
}
static void zapi_encode_prefix(struct stream *s, struct prefix *p,
@@ -2254,7 +2256,7 @@ int tm_table_manager_connect(struct zclient *zclient)
return (int)result;
stream_failure:
- return 0;
+ return -1;
}
/**
@@ -2321,8 +2323,9 @@ int tm_get_table_chunk(struct zclient *zclient, uint32_t chunk_size,
if (zclient_debug)
zlog_debug("Table Chunk assign: %u - %u ", *start, *end);
-stream_failure:
return 0;
+stream_failure:
+ return -1;
}
/**
diff --git a/lib/zebra.h b/lib/zebra.h
index 352887eca8..789a93a3c4 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -360,6 +360,7 @@ typedef enum {
/* Subsequent Address Family Identifier. */
typedef enum {
+ SAFI_UNSPEC = 0,
SAFI_UNICAST = 1,
SAFI_MULTICAST = 2,
SAFI_MPLS_VPN = 3,
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index af16c5aa7c..8454016b2e 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -258,7 +258,7 @@ DEFUN (show_zebra,
return CMD_SUCCESS;
}
- vty_out(vty, "Zebra Infomation\n");
+ vty_out(vty, "Zebra Information\n");
vty_out(vty, " fail: %d\n", zclient->fail);
vty_out(vty, " redistribute default: %d\n",
vrf_bitmap_check(zclient->default_information[AFI_IP6],
diff --git a/ospfd/ospf_errors.c b/ospfd/ospf_errors.c
index dd02160195..a985efc668 100644
--- a/ospfd/ospf_errors.c
+++ b/ospfd/ospf_errors.c
@@ -39,7 +39,7 @@ static struct log_ref ferr_ospf_warn[] = {
},
{
.code = EC_OSPF_PACKET,
- .title = "OSPF has detected packet information missmatch",
+ .title = "OSPF has detected packet information mismatch",
.description = "OSPF has detected that packet information received is incorrect",
.suggestion = "Ensure interface configuration is correct, gather log files from here and the peer and open an Issue",
},
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 2564c6f330..8fa91f500c 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -3442,6 +3442,9 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
else
vty_out(vty, " This interface is UNNUMBERED,");
} else {
+ struct in_addr dest;
+ const char *dstr;
+
/* Show OSPF interface information. */
if (use_json) {
json_object_string_add(
@@ -3455,46 +3458,40 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
inet_ntoa(oi->address->u.prefix4),
oi->address->prefixlen);
- if (oi->connected->destination
- || oi->type == OSPF_IFTYPE_VIRTUALLINK) {
- struct in_addr *dest;
- const char *dstr;
-
- if (CONNECTED_PEER(oi->connected)
- || oi->type == OSPF_IFTYPE_VIRTUALLINK)
- dstr = "Peer";
- else
- dstr = "Broadcast";
+ /* For Vlinks, showing the peer address is
+ * probably more informative than the local
+ * interface that is being used */
+ if (oi->type == OSPF_IFTYPE_VIRTUALLINK) {
+ dstr = "Peer";
+ dest = oi->vl_data->peer_addr;
+ } else if (CONNECTED_PEER(oi->connected)
+ && oi->connected->destination) {
+ dstr = "Peer";
+ dest = oi->connected->destination->u.prefix4;
+ } else {
+ dstr = "Broadcast";
+ dest.s_addr = ipv4_broadcast_addr(
+ oi->connected->address->u.prefix4.s_addr,
+ oi->connected->address->prefixlen);
+ }
- /* For Vlinks, showing the peer address is
- * probably more
- * * * * * informative than the local
- * interface that is being used
- * * * * */
+ if (use_json) {
+ json_object_string_add(
+ json_interface_sub,
+ "ospfIfType", dstr);
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
- dest = &oi->vl_data->peer_addr;
+ json_object_string_add(
+ json_interface_sub,
+ "vlinkPeer",
+ inet_ntoa(dest));
else
- dest = &oi->connected->destination->u
- .prefix4;
-
- if (use_json) {
json_object_string_add(
json_interface_sub,
- "ospfIfType", dstr);
- if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
- json_object_string_add(
- json_interface_sub,
- "vlinkPeer",
- inet_ntoa(*dest));
- else
- json_object_string_add(
- json_interface_sub,
- "localIfUsed",
- inet_ntoa(*dest));
- } else
- vty_out(vty, " %s %s,", dstr,
- inet_ntoa(*dest));
- }
+ "localIfUsed",
+ inet_ntoa(dest));
+ } else
+ vty_out(vty, " %s %s,", dstr,
+ inet_ntoa(dest));
}
if (use_json) {
json_object_string_add(json_interface_sub, "area",
diff --git a/pbrd/pbrd.conf.sample b/pbrd/pbrd.conf.sample
index bb1c2edca8..c9e7dce01f 100644
--- a/pbrd/pbrd.conf.sample
+++ b/pbrd/pbrd.conf.sample
@@ -1,3 +1,19 @@
+! Sample pbrd configuration file
+!
+! A quick example of what a pbr configuration might look like
!
!
log stdout
+!
+! nexthop-group TEST
+! nexthop 4.5.6.7
+! nexthop 5.6.7.8
+! !
+! pbr-map BLUE seq 100
+! match dst-ip 9.9.9.0/24
+! match src-ip 10.10.10.0/24
+! set nexthop-group TEST
+! !
+! int swp1
+! pbr-policy BLUE
+!
diff --git a/pimd/pim_bsm.c b/pimd/pim_bsm.c
index 62f13b5b53..675092dbec 100644
--- a/pimd/pim_bsm.c
+++ b/pimd/pim_bsm.c
@@ -711,11 +711,11 @@ static bool pim_bsm_frag_send(uint8_t *buf, uint32_t len, struct interface *ifp,
/* MTU passed here is PIM MTU (IP MTU less IP Hdr) */
if (pim_mtu < (PIM_MIN_BSM_LEN)) {
zlog_warn(
- "%s: mtu(pim mtu: %d) size less than minimum bootsrap len",
+ "%s: mtu(pim mtu: %d) size less than minimum bootstrap len",
__PRETTY_FUNCTION__, pim_mtu);
if (PIM_DEBUG_BSM)
zlog_debug(
- "%s: mtu (pim mtu:%d) less than minimum bootsrap len",
+ "%s: mtu (pim mtu:%d) less than minimum bootstrap len",
__PRETTY_FUNCTION__, pim_mtu);
return false;
}
diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c
index 39dc8ad2fa..7900e39231 100644
--- a/pimd/pim_nht.c
+++ b/pimd/pim_nht.c
@@ -479,7 +479,7 @@ static int pim_update_upstream_nh_helper(struct hash_bucket *bucket, void *arg)
zlog_debug("%s: NHT upstream %s(%s) old ifp %s new ifp %s",
__PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
old.source_nexthop.interface
- ? old.source_nexthop.interface->name : "Unknwon",
+ ? old.source_nexthop.interface->name : "Unknown",
up->rpf.source_nexthop.interface->name);
}
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index 27042e197c..014cae02ee 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -1,6 +1,6 @@
# configure options
#
-# Some can be overriden on rpmbuild commandline with:
+# Some can be overridden on rpmbuild commandline with:
# rpmbuild --define 'variable value'
# (use any value, ie 1 for flag "with_XXXX" definitions)
#
diff --git a/sharpd/sharpd.conf.sample b/sharpd/sharpd.conf.sample
index bb1c2edca8..d1cc19a51f 100644
--- a/sharpd/sharpd.conf.sample
+++ b/sharpd/sharpd.conf.sample
@@ -1,3 +1,6 @@
+! Default sharpd configuration sample
!
+! There are no `default` configuration commands for sharpd
+! all commands are at the view or enable level.
!
log stdout
diff --git a/staticd/staticd.conf.sample b/staticd/staticd.conf.sample
index bb1c2edca8..3b64eb9c90 100644
--- a/staticd/staticd.conf.sample
+++ b/staticd/staticd.conf.sample
@@ -1,3 +1,5 @@
-!
+! Default staticd configuration sample
!
log stdout
+!
+! ip route 4.5.6.7/32 10.10.10.10
diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c
index 78016dc9ce..8e1b62ac15 100644
--- a/tests/bgpd/test_peer_attr.c
+++ b/tests/bgpd/test_peer_attr.c
@@ -1170,7 +1170,7 @@ static void test_peer_attr(struct test *test, struct test_peer_attr *pa)
/* Test Preparation: Switch and activate address-family. */
if (!is_attr_type_global(pa->type)) {
test_log(test, "prepare: switch address-family to [%s]",
- afi_safi_print(pa->afi, pa->safi));
+ get_afi_safi_str(pa->afi, pa->safi, false));
test_execute(test, "address-family %s %s",
str_from_afi(pa->afi), str_from_safi(pa->safi));
test_execute(test, "neighbor %s activate", g->name);
@@ -1237,7 +1237,7 @@ static void test_peer_attr(struct test *test, struct test_peer_attr *pa)
/* Test Preparation: Switch and activate address-family. */
if (!is_attr_type_global(pa->type)) {
test_log(test, "prepare: switch address-family to [%s]",
- afi_safi_print(pa->afi, pa->safi));
+ get_afi_safi_str(pa->afi, pa->safi, false));
test_execute(test, "address-family %s %s",
str_from_afi(pa->afi), str_from_safi(pa->safi));
test_execute(test, "neighbor %s activate", g->name);
@@ -1285,7 +1285,7 @@ static void test_peer_attr(struct test *test, struct test_peer_attr *pa)
/* Test Preparation: Switch and activate address-family. */
if (!is_attr_type_global(pa->type)) {
test_log(test, "prepare: switch address-family to [%s]",
- afi_safi_print(pa->afi, pa->safi));
+ get_afi_safi_str(pa->afi, pa->safi, false));
test_execute(test, "address-family %s %s",
str_from_afi(pa->afi), str_from_safi(pa->safi));
test_execute(test, "neighbor %s activate", g->name);
diff --git a/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref b/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref
index 1fb70a0e2f..0a20231371 100644
--- a/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref
+++ b/tests/topotests/all-protocol-startup/r1/ipv4_routes.ref
@@ -13,6 +13,8 @@ O 192.168.3.0/26 [110/10] is directly connected, r1-eth3, XX:XX:XX
S>* 4.5.6.10/32 [1/0] via 192.168.0.2, r1-eth0, XX:XX:XX
S>* 4.5.6.11/32 [1/0] via 192.168.0.2, r1-eth0, XX:XX:XX
S>* 4.5.6.12/32 [1/0] is directly connected, r1-eth0, XX:XX:XX
+S>* 4.5.6.13/32 [1/0] unreachable (blackhole), XX:XX:XX
+S>* 4.5.6.14/32 [1/0] unreachable (blackhole), XX:XX:XX
S>* 4.5.6.7/32 [1/0] unreachable (blackhole), XX:XX:XX
S>* 4.5.6.8/32 [1/0] unreachable (blackhole), XX:XX:XX
S>* 4.5.6.9/32 [1/0] unreachable (ICMP unreachable), XX:XX:XX
diff --git a/tests/topotests/all-protocol-startup/r1/zebra.conf b/tests/topotests/all-protocol-startup/r1/zebra.conf
index 30e05f01e3..c621593ef7 100644
--- a/tests/topotests/all-protocol-startup/r1/zebra.conf
+++ b/tests/topotests/all-protocol-startup/r1/zebra.conf
@@ -9,6 +9,9 @@ ip route 4.5.6.8/32 Null0
ipv6 route 4:5::6:8/128 Null0
ip route 4.5.6.9/32 reject
ipv6 route 4:5::6:9/128 reject
+# Test various spellings of NULL0 to make sure we accept them
+ip route 4.5.6.13/32 null0
+ip route 4.5.6.14/32 NULL0
# Create normal gateway routes
ip route 4.5.6.10/32 192.168.0.2
ipv6 route 4:5::6:10/128 fc00:0:0:0::2
diff --git a/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py b/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py
index de6c35ba8f..ed350ebfeb 100644
--- a/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py
+++ b/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py
@@ -88,7 +88,7 @@ def test_bgp_maximum_prefix_invalid():
while True:
output = json.loads(tgen.gears[router].vtysh_cmd("show ip bgp neighbor 192.168.255.1 json"))
if output['192.168.255.1']['bgpState'] == 'Established':
- if output['192.168.255.1']['addressFamilyInfo']['IPv4 Unicast']['acceptedPrefixCounter'] == 2:
+ if output['192.168.255.1']['addressFamilyInfo']['ipv4Unicast']['acceptedPrefixCounter'] == 2:
return True
def _bgp_comm_list_delete(router):
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index fba754f626..b053392bff 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -164,9 +164,10 @@ static int vtysh_reconnect(struct vtysh_client *vclient);
static void vclient_close(struct vtysh_client *vclient)
{
if (vclient->fd >= 0) {
- vty_out(vty,
- "Warning: closing connection to %s because of an I/O error!\n",
- vclient->name);
+ if (vty->of)
+ vty_out(vty,
+ "Warning: closing connection to %s because of an I/O error!\n",
+ vclient->name);
close(vclient->fd);
/* indicate as candidate for reconnect */
vclient->fd = VTYSH_WAS_ACTIVE;
@@ -237,8 +238,11 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
continue;
if (nread <= 0) {
- vty_out(vty, "vtysh: error reading from %s: %s (%d)",
- vclient->name, safe_strerror(errno), errno);
+ if (vty->of)
+ vty_out(vty,
+ "vtysh: error reading from %s: %s (%d)",
+ vclient->name, safe_strerror(errno),
+ errno);
goto out_err;
}
@@ -383,7 +387,7 @@ static int vtysh_client_run_all(struct vtysh_client *head_client,
rc_all = rc;
}
}
- if (wrong_instance && !correct_instance) {
+ if (wrong_instance && !correct_instance && vty->of) {
vty_out(vty,
"%% [%s]: command ignored as it targets an instance that is not running\n",
head_client->name);
diff --git a/yang/frr-bfdd.yang b/yang/frr-bfdd.yang
index 24ca8f68a8..f9ac2e43b0 100644
--- a/yang/frr-bfdd.yang
+++ b/yang/frr-bfdd.yang
@@ -264,22 +264,22 @@ module frr-bfdd {
leaf session-down-count {
type uint32;
- description "Amount of times the session went down";
+ description "Number of times the session went down";
}
leaf session-up-count {
type uint32;
- description "Amount of times the session went up";
+ description "Number of times the session went up";
}
leaf control-packet-input-count {
type uint64;
- description "Amount of control packets received";
+ description "Number of control packets received";
}
leaf control-packet-output-count {
type uint64;
- description "Amount of control packets sent";
+ description "Number of control packets sent";
}
/*
@@ -296,12 +296,12 @@ module frr-bfdd {
*/
leaf echo-packet-input-count {
type uint64;
- description "Amount of echo packets received";
+ description "Number of echo packets received";
}
leaf echo-packet-output-count {
type uint64;
- description "Amount of echo packets sent";
+ description "Number of echo packets sent";
}
}
diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang
index 05a896a1db..9180b0c5f3 100644
--- a/yang/frr-isisd.yang
+++ b/yang/frr-isisd.yang
@@ -1024,7 +1024,7 @@ module frr-isisd {
"This notification is sent when we attempt to propagate
an LSP that is larger than the dataLinkBlockSize for the
circuit. The notification generation must be throttled
- with at least 5 seconds betweeen successive
+ with at least 5 seconds between successive
notifications.";
uses notification-instance-hdr;
@@ -1090,7 +1090,7 @@ module frr-isisd {
"This notification is sent when we receive a PDU
with a different value for the System ID length.
The notification generation must be throttled
- with at least 5 seconds betweeen successive
+ with at least 5 seconds between successive
notifications.";
uses notification-instance-hdr;
@@ -1114,7 +1114,7 @@ module frr-isisd {
"This notification is sent when we receive a PDU
with a different value for the Maximum Area Addresses.
The notification generation must be throttled
- with at least 5 seconds betweeen successive
+ with at least 5 seconds between successive
notifications.";
uses notification-instance-hdr;
@@ -1170,7 +1170,7 @@ module frr-isisd {
"This notification is sent when the system receives a
PDU with the wrong authentication type field.
The notification generation must be throttled
- with at least 5 seconds betweeen successive
+ with at least 5 seconds between successive
notifications.";
uses notification-instance-hdr;
@@ -1188,7 +1188,7 @@ module frr-isisd {
"This notification is sent when the system receives
a PDU with the wrong authentication information.
The notification generation must be throttled with
- with at least 5 seconds betweeen successive
+ with at least 5 seconds between successive
notifications.";
uses notification-instance-hdr;
@@ -1206,7 +1206,7 @@ module frr-isisd {
"This notification is sent when the system receives a
PDU with a different protocol version number.
The notification generation must be throttled
- with at least 5 seconds betweeen successive
+ with at least 5 seconds between successive
notifications.";
uses notification-instance-hdr;
@@ -1230,7 +1230,7 @@ module frr-isisd {
"This notification is sent when the system receives a
Hello PDU from an IS that does not share any area
address. The notification generation must be throttled
- with at least 5 seconds betweeen successive
+ with at least 5 seconds between successive
notifications.";
uses notification-instance-hdr;
@@ -1248,7 +1248,7 @@ module frr-isisd {
"This notification is sent when the system receives a
Hello PDU from an IS but does not establish an adjacency
for some reason. The notification generation must be
- throttled with at least 5 seconds betweeen successive
+ throttled with at least 5 seconds between successive
notifications.";
uses notification-instance-hdr;
@@ -1273,7 +1273,7 @@ module frr-isisd {
description
"This notification is sent when the system receives an
LSP with a parse error. The notification generation must
- be throttled with at least 5 seconds betweeen successive
+ be throttled with at least 5 seconds between successive
notifications.";
uses notification-instance-hdr;
@@ -1350,7 +1350,7 @@ module frr-isisd {
description
"This notification is sent when an LSP is received.
The notification generation must be throttled with at
- least 5 seconds betweeen successive notifications.";
+ least 5 seconds between successive notifications.";
uses notification-instance-hdr;
uses notification-interface-hdr;
@@ -1384,7 +1384,7 @@ module frr-isisd {
description
"This notification is sent when an LSP is regenerated.
The notification generation must be throttled with at
- least 5 seconds betweeen successive notifications.";
+ least 5 seconds between successive notifications.";
uses notification-instance-hdr;
leaf lsp-id {
diff --git a/zebra/connected.c b/zebra/connected.c
index 4101a4bf24..ffc991861c 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -120,10 +120,6 @@ struct connected *connected_check_ptp(struct interface *ifp,
struct connected *ifc;
struct listnode *node;
- /* ignore broadcast addresses */
- if (p->prefixlen != IPV4_MAX_PREFIXLEN)
- d = NULL;
-
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
if (!prefix_same(ifc->address, p))
continue;
@@ -143,6 +139,12 @@ static int connected_same(struct connected *ifc1, struct connected *ifc2)
if (ifc1->ifp != ifc2->ifp)
return 0;
+ if (ifc1->flags != ifc2->flags)
+ return 0;
+
+ if (ifc1->conf != ifc2->conf)
+ return 0;
+
if (ifc1->destination)
if (!ifc2->destination)
return 0;
@@ -154,12 +156,6 @@ static int connected_same(struct connected *ifc1, struct connected *ifc2)
if (!prefix_same(ifc1->destination, ifc2->destination))
return 0;
- if (ifc1->flags != ifc2->flags)
- return 0;
-
- if (ifc1->conf != ifc2->conf)
- return 0;
-
return 1;
}
@@ -276,7 +272,7 @@ void connected_up(struct interface *ifp, struct connected *ifc)
/* Add connected IPv4 route to the interface. */
void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
- uint16_t prefixlen, struct in_addr *broad,
+ uint16_t prefixlen, struct in_addr *dest,
const char *label, uint32_t metric)
{
struct prefix_ipv4 *p;
@@ -302,59 +298,39 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
: prefixlen;
ifc->address = (struct prefix *)p;
- /* If there is broadcast or peer address. */
- if (broad) {
- p = prefix_ipv4_new();
- p->family = AF_INET;
- p->prefix = *broad;
- p->prefixlen = prefixlen;
- ifc->destination = (struct prefix *)p;
-
+ /* If there is a peer address. */
+ if (CONNECTED_PEER(ifc)) {
/* validate the destination address */
- if (CONNECTED_PEER(ifc)) {
- if (IPV4_ADDR_SAME(addr, broad))
+ if (dest) {
+ p = prefix_ipv4_new();
+ p->family = AF_INET;
+ p->prefix = *dest;
+ p->prefixlen = prefixlen;
+ ifc->destination = (struct prefix *)p;
+
+ if (IPV4_ADDR_SAME(addr, dest))
flog_warn(
EC_ZEBRA_IFACE_SAME_LOCAL_AS_PEER,
"warning: interface %s has same local and peer "
"address %s, routing protocols may malfunction",
ifp->name, inet_ntoa(*addr));
} else {
- if (broad->s_addr
- != ipv4_broadcast_addr(addr->s_addr, prefixlen)) {
- char buf[2][INET_ADDRSTRLEN];
- struct in_addr bcalc;
- bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,
- prefixlen);
- flog_warn(
- EC_ZEBRA_BCAST_ADDR_MISMATCH,
- "warning: interface %s broadcast addr %s/%d != "
- "calculated %s, routing protocols may malfunction",
- ifp->name,
- inet_ntop(AF_INET, broad, buf[0],
- sizeof(buf[0])),
- prefixlen,
- inet_ntop(AF_INET, &bcalc, buf[1],
- sizeof(buf[1])));
- }
- }
-
- } else {
- if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) {
zlog_debug(
"warning: %s called for interface %s "
"with peer flag set, but no peer address supplied",
__func__, ifp->name);
UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
}
-
- /* no broadcast or destination address was supplied */
- if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
- zlog_debug(
- "warning: PtP interface %s with addr %s/%d needs a "
- "peer address",
- ifp->name, inet_ntoa(*addr), prefixlen);
}
+ /* no destination address was supplied */
+ if (!dest && (prefixlen == IPV4_MAX_PREFIXLEN)
+ && if_is_pointopoint(ifp))
+ zlog_debug(
+ "warning: PtP interface %s with addr %s/%d needs a "
+ "peer address",
+ ifp->name, inet_ntoa(*addr), prefixlen);
+
/* Label of this address. */
if (label)
ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);
@@ -464,7 +440,7 @@ static void connected_delete_helper(struct connected *ifc, struct prefix *p)
/* Delete connected IPv4 route to the interface. */
void connected_delete_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, uint16_t prefixlen,
- struct in_addr *broad)
+ struct in_addr *dest)
{
struct prefix p, d;
struct connected *ifc;
@@ -475,10 +451,10 @@ void connected_delete_ipv4(struct interface *ifp, int flags,
p.prefixlen = CHECK_FLAG(flags, ZEBRA_IFA_PEER) ? IPV4_MAX_PREFIXLEN
: prefixlen;
- if (broad) {
+ if (dest) {
memset(&d, 0, sizeof(struct prefix));
d.family = AF_INET;
- d.u.prefix4 = *broad;
+ d.u.prefix4 = *dest;
d.prefixlen = prefixlen;
ifc = connected_check_ptp(ifp, &p, &d);
} else
@@ -489,7 +465,7 @@ void connected_delete_ipv4(struct interface *ifp, int flags,
/* Add connected IPv6 route to the interface. */
void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
- struct in6_addr *broad, uint16_t prefixlen,
+ struct in6_addr *dest, uint16_t prefixlen,
const char *label, uint32_t metric)
{
struct prefix_ipv6 *p;
@@ -514,10 +490,10 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
p->prefixlen = prefixlen;
ifc->address = (struct prefix *)p;
- if (broad) {
+ if (dest) {
p = prefix_ipv6_new();
p->family = AF_INET6;
- IPV6_ADDR_COPY(&p->prefix, broad);
+ IPV6_ADDR_COPY(&p->prefix, dest);
p->prefixlen = prefixlen;
ifc->destination = (struct prefix *)p;
} else {
@@ -547,7 +523,7 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
}
void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address,
- struct in6_addr *broad, uint16_t prefixlen)
+ struct in6_addr *dest, uint16_t prefixlen)
{
struct prefix p, d;
struct connected *ifc;
@@ -557,10 +533,10 @@ void connected_delete_ipv6(struct interface *ifp, struct in6_addr *address,
memcpy(&p.u.prefix6, address, sizeof(struct in6_addr));
p.prefixlen = prefixlen;
- if (broad) {
+ if (dest) {
memset(&d, 0, sizeof(struct prefix));
d.family = AF_INET6;
- IPV6_ADDR_COPY(&d.u.prefix6, broad);
+ IPV6_ADDR_COPY(&d.u.prefix6, dest);
d.prefixlen = prefixlen;
ifc = connected_check_ptp(ifp, &p, &d);
} else
diff --git a/zebra/connected.h b/zebra/connected.h
index 7672bec006..14f6cb2db0 100644
--- a/zebra/connected.h
+++ b/zebra/connected.h
@@ -40,12 +40,12 @@ extern struct connected *connected_check_ptp(struct interface *ifp,
extern void connected_add_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, uint16_t prefixlen,
- struct in_addr *broad, const char *label,
+ struct in_addr *dest, const char *label,
uint32_t metric);
extern void connected_delete_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, uint16_t prefixlen,
- struct in_addr *broad);
+ struct in_addr *dest);
extern void connected_delete_ipv4_unnumbered(struct connected *ifc);
@@ -53,12 +53,12 @@ extern void connected_up(struct interface *ifp, struct connected *ifc);
extern void connected_down(struct interface *ifp, struct connected *ifc);
extern void connected_add_ipv6(struct interface *ifp, int flags,
- struct in6_addr *address, struct in6_addr *broad,
+ struct in6_addr *address, struct in6_addr *dest,
uint16_t prefixlen, const char *label,
uint32_t metric);
extern void connected_delete_ipv6(struct interface *ifp,
struct in6_addr *address,
- struct in6_addr *broad, uint16_t prefixlen);
+ struct in6_addr *dest, uint16_t prefixlen);
extern int connected_is_unnumbered(struct interface *);
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 2c536c5d1f..e157c2d70a 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -888,11 +888,13 @@ static int netlink_address_ctx(const struct zebra_dplane_ctx *ctx)
p = dplane_ctx_get_intf_dest(ctx);
addattr_l(&req.n, sizeof(req), IFA_ADDRESS,
&p->u.prefix, bytelen);
- } else if (cmd == RTM_NEWADDR &&
- dplane_ctx_intf_has_dest(ctx)) {
- p = dplane_ctx_get_intf_dest(ctx);
+ } else if (cmd == RTM_NEWADDR) {
+ struct in_addr broad = {
+ .s_addr = ipv4_broadcast_addr(p->u.prefix4.s_addr,
+ p->prefixlen)
+ };
addattr_l(&req.n, sizeof(req), IFA_BROADCAST,
- &p->u.prefix, bytelen);
+ &broad, bytelen);
}
}
@@ -1065,7 +1067,7 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
else
connected_delete_ipv4(
ifp, flags, (struct in_addr *)addr,
- ifa->ifa_prefixlen, (struct in_addr *)broad);
+ ifa->ifa_prefixlen, NULL);
}
if (ifa->ifa_family == AF_INET6) {
if (ifa->ifa_prefixlen > IPV6_MAX_BITLEN) {
@@ -1091,8 +1093,7 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
metric);
} else
connected_delete_ipv6(ifp, (struct in6_addr *)addr,
- (struct in6_addr *)broad,
- ifa->ifa_prefixlen);
+ NULL, ifa->ifa_prefixlen);
}
return 0;
diff --git a/zebra/interface.c b/zebra/interface.c
index a2f80aff4e..6486c01430 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -1081,12 +1081,10 @@ static void connected_dump_vty(struct vty *vty, struct connected *connected)
vty_out(vty, "/%d", p->prefixlen);
/* If there is destination address, print it. */
- if (connected->destination) {
- vty_out(vty,
- (CONNECTED_PEER(connected) ? " peer " : " broadcast "));
+ if (CONNECTED_PEER(connected) && connected->destination) {
+ vty_out(vty, " peer ");
prefix_vty_out(vty, connected->destination);
- if (CONNECTED_PEER(connected))
- vty_out(vty, "/%d", connected->destination->prefixlen);
+ vty_out(vty, "/%d", connected->destination->prefixlen);
}
if (CHECK_FLAG(connected->flags, ZEBRA_IFA_SECONDARY))
@@ -2684,12 +2682,6 @@ static int ip_address_install(struct vty *vty, struct interface *ifp,
p = prefix_ipv4_new();
*p = pp;
ifc->destination = (struct prefix *)p;
- } else if (p->prefixlen <= IPV4_MAX_PREFIXLEN - 2) {
- p = prefix_ipv4_new();
- *p = lp;
- p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,
- p->prefixlen);
- ifc->destination = (struct prefix *)p;
}
/* Label. */
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 0280cde238..1ae2ba92b0 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -172,6 +172,13 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p,
__FUNCTION__);
return;
}
+ if (!zebra_check_addr(p)) {
+ if (IS_ZEBRA_DEBUG_RIB)
+ zlog_debug("Redist update filter prefix %s",
+ prefix2str(p, buf, sizeof(buf)));
+ return;
+ }
+
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
send_redistribute = 0;
@@ -246,6 +253,13 @@ void redistribute_delete(const struct prefix *p, const struct prefix *src_p,
return;
}
+ if (!zebra_check_addr(p)) {
+ if (IS_ZEBRA_DEBUG_RIB)
+ zlog_debug("Redist delete filter prefix %s",
+ prefix2str(p, buf, sizeof(buf)));
+ return;
+ }
+
for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
if ((is_default_prefix(p)
&& vrf_bitmap_check(client->redist_default[afi],
diff --git a/zebra/rt.h b/zebra/rt.h
index 04576671fe..727d2d0c55 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -41,7 +41,7 @@ extern "C" {
((RKERNEL_ROUTE(type)) || (type) == ZEBRA_ROUTE_CONNECT)
/*
- * Update or delete a route, LSP, or pseudowire from the kernel,
+ * Update or delete a route, LSP, pseudowire, or vxlan MAC from the kernel,
* using info from a dataplane context.
*/
extern enum zebra_dplane_result kernel_route_update(
@@ -55,6 +55,8 @@ enum zebra_dplane_result kernel_pw_update(struct zebra_dplane_ctx *ctx);
enum zebra_dplane_result kernel_address_update_ctx(
struct zebra_dplane_ctx *ctx);
+enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx);
+
extern int kernel_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
int llalen, ns_id_t ns_id);
extern int kernel_interface_set_master(struct interface *master,
@@ -68,12 +70,6 @@ extern int kernel_add_vtep(vni_t vni, struct interface *ifp,
struct in_addr *vtep_ip);
extern int kernel_del_vtep(vni_t vni, struct interface *ifp,
struct in_addr *vtep_ip);
-extern int kernel_add_mac(struct interface *ifp, vlanid_t vid,
- struct ethaddr *mac, struct in_addr vtep_ip,
- bool sticky);
-extern int kernel_del_mac(struct interface *ifp, vlanid_t vid,
- struct ethaddr *mac, struct in_addr vtep_ip);
-
extern int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
struct ethaddr *mac, uint8_t flags);
extern int kernel_del_neigh(struct interface *ifp, struct ipaddr *ip);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 549deb7045..cc73effaf9 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -2282,33 +2282,70 @@ int netlink_macfdb_read_specific_mac(struct zebra_ns *zns,
return ret;
}
-static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
- struct ethaddr *mac, struct in_addr vtep_ip,
- int cmd, bool sticky)
+
+/*
+ * Netlink-specific handler for MAC updates using dataplane context object.
+ */
+static enum zebra_dplane_result
+netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx)
{
- struct zebra_ns *zns;
struct {
struct nlmsghdr n;
struct ndmsg ndm;
char buf[256];
} req;
+ int ret;
int dst_alen;
struct zebra_if *zif;
struct interface *br_if;
struct zebra_if *br_zif;
- char buf[ETHER_ADDR_STRLEN];
int vid_present = 0;
char vid_buf[20];
- char dst_buf[30];
- struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
+ struct zebra_ns *zns;
+ struct interface *ifp;
+ int cmd;
+ struct in_addr vtep_ip;
+ vlanid_t vid;
+
+ if (dplane_ctx_get_op(ctx) == DPLANE_OP_MAC_INSTALL)
+ cmd = RTM_NEWNEIGH;
+ else
+ cmd = RTM_DELNEIGH;
+
+ /* Locate zebra ns and interface objects from context data */
+ zns = zebra_ns_lookup(dplane_ctx_get_ns(ctx)->ns_id);
+ if (zns == NULL) {
+ /* Nothing to be done */
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("MAC %s on IF %s(%u) - zebra ns unknown",
+ (cmd == RTM_NEWNEIGH) ? "add" : "del",
+ dplane_ctx_get_ifname(ctx),
+ dplane_ctx_get_ifindex(ctx));
+
+ return ZEBRA_DPLANE_REQUEST_FAILURE;
+ }
+
+ ifp = if_lookup_by_index_per_ns(zns, dplane_ctx_get_ifindex(ctx));
+ if (ifp == NULL) {
+ /* Nothing to be done */
+ /* Nothing to be done */
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("MAC %s on IF %s(%u) - interface unknown",
+ (cmd == RTM_NEWNEIGH) ? "add" : "del",
+ dplane_ctx_get_ifname(ctx),
+ dplane_ctx_get_ifindex(ctx));
+ return ZEBRA_DPLANE_REQUEST_FAILURE;
+ }
+
+ vid = dplane_ctx_mac_get_vlan(ctx);
- zns = zvrf->zns;
zif = ifp->info;
if ((br_if = zif->brslave_info.br_if) == NULL) {
- zlog_debug("MAC %s on IF %s(%u) - no mapping to bridge",
- (cmd == RTM_NEWNEIGH) ? "add" : "del", ifp->name,
- ifp->ifindex);
- return -1;
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("MAC %s on IF %s(%u) - no mapping to bridge",
+ (cmd == RTM_NEWNEIGH) ? "add" : "del",
+ ifp->name, ifp->ifindex);
+ return ZEBRA_DPLANE_REQUEST_FAILURE;
}
memset(&req, 0, sizeof(req));
@@ -2322,16 +2359,19 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
req.ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
req.ndm.ndm_state = NUD_REACHABLE;
- if (sticky)
+ if (dplane_ctx_mac_is_sticky(ctx))
req.ndm.ndm_state |= NUD_NOARP;
else
req.ndm.ndm_flags |= NTF_EXT_LEARNED;
- addattr_l(&req.n, sizeof(req), NDA_LLADDR, mac, 6);
+ addattr_l(&req.n, sizeof(req), NDA_LLADDR,
+ dplane_ctx_mac_get_addr(ctx), 6);
req.ndm.ndm_ifindex = ifp->ifindex;
+
dst_alen = 4; // TODO: hardcoded
+ vtep_ip = *(dplane_ctx_mac_get_vtep_ip(ctx));
addattr_l(&req.n, sizeof(req), NDA_DST, &vtep_ip, dst_alen);
- sprintf(dst_buf, " dst %s", inet_ntoa(vtep_ip));
+
br_zif = (struct zebra_if *)br_if->info;
if (IS_ZEBRA_IF_BRIDGE_VLAN_AWARE(br_zif) && vid > 0) {
addattr16(&req.n, sizeof(req), NDA_VLAN, vid);
@@ -2340,16 +2380,29 @@ static int netlink_macfdb_update(struct interface *ifp, vlanid_t vid,
}
addattr32(&req.n, sizeof(req), NDA_MASTER, br_if->ifindex);
- if (IS_ZEBRA_DEBUG_KERNEL)
+ if (IS_ZEBRA_DEBUG_KERNEL) {
+ char ipbuf[PREFIX_STRLEN];
+ char buf[ETHER_ADDR_STRLEN];
+ char dst_buf[PREFIX_STRLEN + 10];
+
+ inet_ntop(AF_INET, &vtep_ip, ipbuf, sizeof(ipbuf));
+ snprintf(dst_buf, sizeof(dst_buf), " dst %s", ipbuf);
+ prefix_mac2str(dplane_ctx_mac_get_addr(ctx), buf, sizeof(buf));
+
zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s%s",
nl_msg_type_to_str(cmd),
nl_family_to_str(req.ndm.ndm_family), ifp->name,
ifp->ifindex, vid_present ? vid_buf : "",
- sticky ? "sticky " : "",
- prefix_mac2str(mac, buf, sizeof(buf)), dst_buf);
+ dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "",
+ buf, dst_buf);
+ }
- return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
- 0);
+ ret = netlink_talk_info(netlink_talk_filter, &req.n,
+ dplane_ctx_get_ns(ctx), 0);
+ if (ret == 0)
+ return ZEBRA_DPLANE_REQUEST_SUCCESS;
+ else
+ return ZEBRA_DPLANE_REQUEST_FAILURE;
}
/*
@@ -2762,17 +2815,12 @@ static int netlink_neigh_update2(struct interface *ifp, struct ipaddr *ip,
0);
}
-int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
- struct in_addr vtep_ip, bool sticky)
-{
- return netlink_macfdb_update(ifp, vid, mac, vtep_ip, RTM_NEWNEIGH,
- sticky);
-}
-
-int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
- struct in_addr vtep_ip)
+/*
+ * Update MAC, using dataplane context object.
+ */
+enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
{
- return netlink_macfdb_update(ifp, vid, mac, vtep_ip, RTM_DELNEIGH, 0);
+ return netlink_macfdb_update_ctx(ctx);
}
int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index 8d8bdd0a6d..7e9a42a617 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -386,16 +386,12 @@ int kernel_del_vtep(vni_t vni, struct interface *ifp, struct in_addr *vtep_ip)
return 0;
}
-int kernel_add_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
- struct in_addr vtep_ip, bool sticky)
-{
- return 0;
-}
-
-int kernel_del_mac(struct interface *ifp, vlanid_t vid, struct ethaddr *mac,
- struct in_addr vtep_ip)
+/*
+ * Update MAC, using dataplane context object. No-op here for now.
+ */
+enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
{
- return 0;
+ return ZEBRA_DPLANE_REQUEST_SUCCESS;
}
int kernel_add_neigh(struct interface *ifp, struct ipaddr *ip,
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index c90e027f02..512a9b4021 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -109,8 +109,6 @@ struct dplane_route_info {
* Pseudowire info for the dataplane
*/
struct dplane_pw_info {
- char ifname[IF_NAMESIZE];
- ifindex_t ifindex;
int type;
int af;
int status;
@@ -130,16 +128,13 @@ struct dplane_pw_info {
*/
struct dplane_intf_info {
- char ifname[INTERFACE_NAMSIZ];
- ifindex_t ifindex;
-
uint32_t metric;
uint32_t flags;
#define DPLANE_INTF_CONNECTED (1 << 0) /* Connected peer, p2p */
#define DPLANE_INTF_SECONDARY (1 << 1)
#define DPLANE_INTF_BROADCAST (1 << 2)
-#define DPLANE_INTF_HAS_DEST (1 << 3)
+#define DPLANE_INTF_HAS_DEST DPLANE_INTF_CONNECTED
#define DPLANE_INTF_HAS_LABEL (1 << 4)
/* Interface address/prefix */
@@ -153,6 +148,17 @@ struct dplane_intf_info {
};
/*
+ * MAC address info for the dataplane.
+ */
+struct dplane_mac_info {
+ vlanid_t vid;
+ struct ethaddr mac;
+ struct in_addr vtep_ip;
+ bool is_sticky;
+
+};
+
+/*
* The context block used to exchange info about route updates across
* the boundary between the zebra main context (and pthread) and the
* dataplane layer (and pthread).
@@ -188,12 +194,16 @@ struct zebra_dplane_ctx {
vrf_id_t zd_vrf_id;
uint32_t zd_table_id;
+ char zd_ifname[INTERFACE_NAMSIZ];
+ ifindex_t zd_ifindex;
+
/* Support info for different kinds of updates */
union {
struct dplane_route_info rinfo;
zebra_lsp_t lsp;
struct dplane_pw_info pw;
struct dplane_intf_info intf;
+ struct dplane_mac_info macinfo;
} u;
/* Namespace info, used especially for netlink kernel communication */
@@ -273,8 +283,8 @@ static struct zebra_dplane_globals {
/* Sentinel for end of shutdown */
volatile bool dg_run;
- /* Route-update context queue inbound to the dataplane */
- TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx) dg_route_ctx_q;
+ /* Update context queue inbound to the dataplane */
+ TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx) dg_update_ctx_q;
/* Ordered list of providers */
TAILQ_HEAD(zdg_prov_q, zebra_dplane_provider) dg_providers_q;
@@ -308,6 +318,9 @@ static struct zebra_dplane_globals {
_Atomic uint32_t dg_intf_addrs_in;
_Atomic uint32_t dg_intf_addr_errors;
+ _Atomic uint32_t dg_macs_in;
+ _Atomic uint32_t dg_mac_errors;
+
_Atomic uint32_t dg_update_yields;
/* Dataplane pthread */
@@ -348,6 +361,10 @@ static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
static enum zebra_dplane_result intf_addr_update_internal(
const struct interface *ifp, const struct connected *ifc,
enum dplane_op_e op);
+static enum zebra_dplane_result mac_update_internal(
+ enum dplane_op_e op, const struct interface *ifp,
+ vlanid_t vid, const struct ethaddr *mac,
+ struct in_addr vtep_ip, bool sticky);
/*
* Public APIs
@@ -466,6 +483,8 @@ static void dplane_ctx_free(struct zebra_dplane_ctx **pctx)
}
break;
+ case DPLANE_OP_MAC_INSTALL:
+ case DPLANE_OP_MAC_DELETE:
case DPLANE_OP_NONE:
break;
}
@@ -626,6 +645,12 @@ const char *dplane_op2str(enum dplane_op_e op)
ret = "ADDR_UNINSTALL";
break;
+ case DPLANE_OP_MAC_INSTALL:
+ ret = "MAC_INSTALL";
+ break;
+ case DPLANE_OP_MAC_DELETE:
+ ret = "MAC_DELETE";
+ break;
}
return ret;
@@ -744,6 +769,19 @@ void dplane_ctx_set_notif_provider(struct zebra_dplane_ctx *ctx,
ctx->zd_notif_provider = id;
}
+const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->zd_ifname;
+}
+
+ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->zd_ifindex;
+}
void dplane_ctx_set_type(struct zebra_dplane_ctx *ctx, int type)
{
@@ -1030,13 +1068,6 @@ uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx)
return ctx->u.lsp.num_ecmp;
}
-const char *dplane_ctx_get_pw_ifname(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.pw.ifname;
-}
-
mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -1104,20 +1135,6 @@ dplane_ctx_get_pw_nhg(const struct zebra_dplane_ctx *ctx)
}
/* Accessors for interface information */
-const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.intf.ifname;
-}
-
-ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx)
-{
- DPLANE_CTX_VALID(ctx);
-
- return ctx->u.intf.ifindex;
-}
-
uint32_t dplane_ctx_get_intf_metric(const struct zebra_dplane_ctx *ctx)
{
DPLANE_CTX_VALID(ctx);
@@ -1187,6 +1204,33 @@ const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx)
return ctx->u.intf.label;
}
+/* Accessors for MAC information */
+vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+ return ctx->u.macinfo.vid;
+}
+
+bool dplane_ctx_mac_is_sticky(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+ return ctx->u.macinfo.is_sticky;
+}
+
+const struct ethaddr *dplane_ctx_mac_get_addr(
+ const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+ return &(ctx->u.macinfo.mac);
+}
+
+const struct in_addr *dplane_ctx_mac_get_vtep_ip(
+ const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+ return &(ctx->u.macinfo.vtep_ip);
+}
+
/*
* End of dplane context accessors
*/
@@ -1422,10 +1466,10 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
memset(&ctx->u.pw, 0, sizeof(ctx->u.pw));
/* This name appears to be c-string, so we use string copy. */
- strlcpy(ctx->u.pw.ifname, pw->ifname, sizeof(ctx->u.pw.ifname));
+ strlcpy(ctx->zd_ifname, pw->ifname, sizeof(ctx->zd_ifname));
ctx->zd_vrf_id = pw->vrf_id;
- ctx->u.pw.ifindex = pw->ifindex;
+ ctx->zd_ifindex = pw->ifindex;
ctx->u.pw.type = pw->type;
ctx->u.pw.af = pw->af;
ctx->u.pw.local_label = pw->local_label;
@@ -1467,10 +1511,10 @@ static int dplane_ctx_pw_init(struct zebra_dplane_ctx *ctx,
}
/*
- * Enqueue a new route update,
+ * Enqueue a new update,
* and ensure an event is active for the dataplane pthread.
*/
-static int dplane_route_enqueue(struct zebra_dplane_ctx *ctx)
+static int dplane_update_enqueue(struct zebra_dplane_ctx *ctx)
{
int ret = EINVAL;
uint32_t high, curr;
@@ -1478,7 +1522,7 @@ static int dplane_route_enqueue(struct zebra_dplane_ctx *ctx)
/* Enqueue for processing by the dataplane pthread */
DPLANE_LOCK();
{
- TAILQ_INSERT_TAIL(&zdplane_info.dg_route_ctx_q, ctx,
+ TAILQ_INSERT_TAIL(&zdplane_info.dg_update_ctx_q, ctx,
zd_q_entries);
}
DPLANE_UNLOCK();
@@ -1558,7 +1602,7 @@ dplane_route_update_internal(struct route_node *rn,
}
/* Enqueue context for processing */
- ret = dplane_route_enqueue(ctx);
+ ret = dplane_update_enqueue(ctx);
}
/* Update counter */
@@ -1724,7 +1768,7 @@ dplane_route_notif_update(struct route_node *rn,
dplane_ctx_set_notif_provider(new_ctx,
dplane_ctx_get_notif_provider(ctx));
- dplane_route_enqueue(new_ctx);
+ dplane_update_enqueue(new_ctx);
ret = ZEBRA_DPLANE_REQUEST_QUEUED;
@@ -1791,7 +1835,7 @@ dplane_lsp_notif_update(zebra_lsp_t *lsp,
ctx,
dplane_ctx_get_notif_provider(notif_ctx));
- ret = dplane_route_enqueue(ctx);
+ ret = dplane_update_enqueue(ctx);
done:
/* Update counter */
@@ -1842,7 +1886,7 @@ static enum zebra_dplane_result lsp_update_internal(zebra_lsp_t *lsp,
if (ret != AOK)
goto done;
- ret = dplane_route_enqueue(ctx);
+ ret = dplane_update_enqueue(ctx);
done:
/* Update counter */
@@ -1876,7 +1920,7 @@ static enum zebra_dplane_result pw_update_internal(struct zebra_pw *pw,
if (ret != AOK)
goto done;
- ret = dplane_route_enqueue(ctx);
+ ret = dplane_update_enqueue(ctx);
done:
/* Update counter */
@@ -1967,8 +2011,8 @@ static enum zebra_dplane_result intf_addr_update_internal(
/* Init the interface-addr-specific area */
memset(&ctx->u.intf, 0, sizeof(ctx->u.intf));
- strlcpy(ctx->u.intf.ifname, ifp->name, sizeof(ctx->u.intf.ifname));
- ctx->u.intf.ifindex = ifp->ifindex;
+ strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
+ ctx->zd_ifindex = ifp->ifindex;
ctx->u.intf.prefix = *(ifc->address);
if (if_is_broadcast(ifp))
@@ -1978,9 +2022,6 @@ static enum zebra_dplane_result intf_addr_update_internal(
ctx->u.intf.dest_prefix = *(ifc->destination);
ctx->u.intf.flags |=
(DPLANE_INTF_CONNECTED | DPLANE_INTF_HAS_DEST);
- } else if (ifc->destination) {
- ctx->u.intf.dest_prefix = *(ifc->destination);
- ctx->u.intf.flags |= DPLANE_INTF_HAS_DEST;
}
if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
@@ -2003,7 +2044,7 @@ static enum zebra_dplane_result intf_addr_update_internal(
}
}
- ret = dplane_route_enqueue(ctx);
+ ret = dplane_update_enqueue(ctx);
/* Increment counter */
atomic_fetch_add_explicit(&zdplane_info.dg_intf_addrs_in, 1,
@@ -2022,6 +2063,104 @@ static enum zebra_dplane_result intf_addr_update_internal(
}
/*
+ * Enqueue vxlan/evpn mac add (or update).
+ */
+enum zebra_dplane_result dplane_mac_add(const struct interface *ifp,
+ vlanid_t vid,
+ const struct ethaddr *mac,
+ struct in_addr vtep_ip,
+ bool sticky)
+{
+ enum zebra_dplane_result result;
+
+ /* Use common helper api */
+ result = mac_update_internal(DPLANE_OP_MAC_INSTALL, ifp, vid,
+ mac, vtep_ip, sticky);
+ return result;
+}
+
+/*
+ * Enqueue vxlan/evpn mac delete.
+ */
+enum zebra_dplane_result dplane_mac_del(const struct interface *ifp,
+ vlanid_t vid,
+ const struct ethaddr *mac,
+ struct in_addr vtep_ip)
+{
+ enum zebra_dplane_result result;
+
+ /* Use common helper api */
+ result = mac_update_internal(DPLANE_OP_MAC_DELETE, ifp, vid, mac,
+ vtep_ip, false);
+ return result;
+}
+
+/*
+ * Common helper api for MAC address/vxlan updates
+ */
+static enum zebra_dplane_result
+mac_update_internal(enum dplane_op_e op,
+ const struct interface *ifp,
+ vlanid_t vid,
+ const struct ethaddr *mac,
+ struct in_addr vtep_ip,
+ bool sticky)
+{
+ enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ int ret;
+ struct zebra_dplane_ctx *ctx = NULL;
+ struct zebra_ns *zns;
+
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+ char buf1[ETHER_ADDR_STRLEN], buf2[PREFIX_STRLEN];
+
+ zlog_debug("init mac ctx %s: mac %s, ifp %s, vtep %s",
+ dplane_op2str(op),
+ prefix_mac2str(mac, buf1, sizeof(buf1)),
+ ifp->name,
+ inet_ntop(AF_INET, &vtep_ip, buf2, sizeof(buf2)));
+ }
+
+ ctx = dplane_ctx_alloc();
+
+ ctx->zd_op = op;
+ ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+ ctx->zd_vrf_id = ifp->vrf_id;
+
+ zns = zebra_ns_lookup(ifp->vrf_id);
+ dplane_ctx_ns_init(ctx, zns, false);
+
+ strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
+ ctx->zd_ifindex = ifp->ifindex;
+
+ /* Init the mac-specific data area */
+ memset(&ctx->u.macinfo, 0, sizeof(ctx->u.macinfo));
+
+ ctx->u.macinfo.vtep_ip = vtep_ip;
+ ctx->u.macinfo.mac = *mac;
+ ctx->u.macinfo.vid = vid;
+ ctx->u.macinfo.is_sticky = sticky;
+
+ /* Enqueue for processing on the dplane pthread */
+ ret = dplane_update_enqueue(ctx);
+
+ /* Increment counter */
+ atomic_fetch_add_explicit(&zdplane_info.dg_macs_in, 1,
+ memory_order_relaxed);
+
+ if (ret == AOK)
+ result = ZEBRA_DPLANE_REQUEST_QUEUED;
+ else {
+ /* Error counter */
+ atomic_fetch_add_explicit(&zdplane_info.dg_mac_errors, 1,
+ memory_order_relaxed);
+ dplane_ctx_free(&ctx);
+ }
+
+ return result;
+}
+
+/*
* Handler for 'show dplane'
*/
int dplane_show_helper(struct vty *vty, bool detailed)
@@ -2054,7 +2193,35 @@ int dplane_show_helper(struct vty *vty, bool detailed)
vty_out(vty, "Route update queue limit: %"PRIu64"\n", limit);
vty_out(vty, "Route update queue depth: %"PRIu64"\n", queued);
vty_out(vty, "Route update queue max: %"PRIu64"\n", queue_max);
- vty_out(vty, "Dplane update yields: %"PRIu64"\n", yields);
+ vty_out(vty, "Dplane update yields: %"PRIu64"\n", yields);
+
+ incoming = atomic_load_explicit(&zdplane_info.dg_lsps_in,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_info.dg_lsp_errors,
+ memory_order_relaxed);
+ vty_out(vty, "LSP updates: %"PRIu64"\n", incoming);
+ vty_out(vty, "LSP update errors: %"PRIu64"\n", errs);
+
+ incoming = atomic_load_explicit(&zdplane_info.dg_pws_in,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_info.dg_pw_errors,
+ memory_order_relaxed);
+ vty_out(vty, "PW updates: %"PRIu64"\n", incoming);
+ vty_out(vty, "PW update errors: %"PRIu64"\n", errs);
+
+ incoming = atomic_load_explicit(&zdplane_info.dg_intf_addrs_in,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_info.dg_intf_addr_errors,
+ memory_order_relaxed);
+ vty_out(vty, "Intf addr updates: %"PRIu64"\n", incoming);
+ vty_out(vty, "Intf addr errors: %"PRIu64"\n", errs);
+
+ incoming = atomic_load_explicit(&zdplane_info.dg_macs_in,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_info.dg_mac_errors,
+ memory_order_relaxed);
+ vty_out(vty, "EVPN MAC updates: %"PRIu64"\n", incoming);
+ vty_out(vty, "EVPN MAC errors: %"PRIu64"\n", errs);
return CMD_SUCCESS;
}
@@ -2374,7 +2541,7 @@ kernel_dplane_pw_update(struct zebra_dplane_ctx *ctx)
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
zlog_debug("Dplane pw %s: op %s af %d loc: %u rem: %u",
- dplane_ctx_get_pw_ifname(ctx),
+ dplane_ctx_get_ifname(ctx),
dplane_op2str(ctx->zd_op),
dplane_ctx_get_pw_af(ctx),
dplane_ctx_get_pw_local_label(ctx),
@@ -2428,7 +2595,6 @@ kernel_dplane_address_update(struct zebra_dplane_ctx *ctx)
{
enum zebra_dplane_result res;
-
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
char dest_str[PREFIX_STRLEN];
@@ -2450,6 +2616,34 @@ kernel_dplane_address_update(struct zebra_dplane_ctx *ctx)
}
/*
+ * Handler for kernel-facing MAC address updates
+ */
+static enum zebra_dplane_result
+kernel_dplane_mac_update(struct zebra_dplane_ctx *ctx)
+{
+ enum zebra_dplane_result res;
+
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+ char buf[ETHER_ADDR_STRLEN];
+
+ prefix_mac2str(dplane_ctx_mac_get_addr(ctx), buf,
+ sizeof(buf));
+
+ zlog_debug("Dplane %s, mac %s, ifindex %u",
+ dplane_op2str(dplane_ctx_get_op(ctx)),
+ buf, dplane_ctx_get_ifindex(ctx));
+ }
+
+ res = kernel_mac_update_ctx(ctx);
+
+ if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+ atomic_fetch_add_explicit(&zdplane_info.dg_mac_errors,
+ 1, memory_order_relaxed);
+
+ return res;
+}
+
+/*
* Kernel provider callback
*/
static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
@@ -2503,6 +2697,11 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
res = kernel_dplane_address_update(ctx);
break;
+ case DPLANE_OP_MAC_INSTALL:
+ case DPLANE_OP_MAC_DELETE:
+ res = kernel_dplane_mac_update(ctx);
+ break;
+
/* Ignore 'notifications' - no-op */
case DPLANE_OP_SYS_ROUTE_ADD:
case DPLANE_OP_SYS_ROUTE_DELETE:
@@ -2682,7 +2881,7 @@ static bool dplane_work_pending(void)
*/
DPLANE_LOCK();
{
- ctx = TAILQ_FIRST(&zdplane_info.dg_route_ctx_q);
+ ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q);
prov = TAILQ_FIRST(&zdplane_info.dg_providers_q);
}
DPLANE_UNLOCK();
@@ -2810,9 +3009,9 @@ static int dplane_thread_loop(struct thread *event)
/* Move new work from incoming list to temp list */
for (counter = 0; counter < limit; counter++) {
- ctx = TAILQ_FIRST(&zdplane_info.dg_route_ctx_q);
+ ctx = TAILQ_FIRST(&zdplane_info.dg_update_ctx_q);
if (ctx) {
- TAILQ_REMOVE(&zdplane_info.dg_route_ctx_q, ctx,
+ TAILQ_REMOVE(&zdplane_info.dg_update_ctx_q, ctx,
zd_q_entries);
ctx->zd_provider = prov->dp_id;
@@ -2997,7 +3196,7 @@ static void zebra_dplane_init_internal(void)
pthread_mutex_init(&zdplane_info.dg_mutex, NULL);
- TAILQ_INIT(&zdplane_info.dg_route_ctx_q);
+ TAILQ_INIT(&zdplane_info.dg_update_ctx_q);
TAILQ_INIT(&zdplane_info.dg_providers_q);
zdplane_info.dg_updates_per_cycle = DPLANE_DEFAULT_NEW_WORK;
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 6238026bcf..912fda45d3 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -25,6 +25,7 @@
#include "lib/nexthop.h"
#include "lib/nexthop_group.h"
#include "lib/queue.h"
+#include "lib/vlan.h"
#include "zebra/zebra_ns.h"
#include "zebra/rib.h"
#include "zebra/zserv.h"
@@ -124,6 +125,10 @@ enum dplane_op_e {
/* Interface address update */
DPLANE_OP_ADDR_INSTALL,
DPLANE_OP_ADDR_UNINSTALL,
+
+ /* MAC address update */
+ DPLANE_OP_MAC_INSTALL,
+ DPLANE_OP_MAC_DELETE,
};
/* Enable system route notifications */
@@ -180,6 +185,8 @@ const char *dplane_op2str(enum dplane_op_e op);
const struct prefix *dplane_ctx_get_dest(const struct zebra_dplane_ctx *ctx);
void dplane_ctx_set_dest(struct zebra_dplane_ctx *ctx,
const struct prefix *dest);
+const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx);
+ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx);
/* Retrieve last/current provider id */
uint32_t dplane_ctx_get_provider(const struct zebra_dplane_ctx *ctx);
@@ -262,7 +269,6 @@ const zebra_nhlfe_t *dplane_ctx_set_best_nhlfe(struct zebra_dplane_ctx *ctx,
uint32_t dplane_ctx_get_lsp_num_ecmp(const struct zebra_dplane_ctx *ctx);
/* Accessors for pseudowire information */
-const char *dplane_ctx_get_pw_ifname(const struct zebra_dplane_ctx *ctx);
mpls_label_t dplane_ctx_get_pw_local_label(const struct zebra_dplane_ctx *ctx);
mpls_label_t dplane_ctx_get_pw_remote_label(const struct zebra_dplane_ctx *ctx);
int dplane_ctx_get_pw_type(const struct zebra_dplane_ctx *ctx);
@@ -277,8 +283,6 @@ const struct nexthop_group *dplane_ctx_get_pw_nhg(
const struct zebra_dplane_ctx *ctx);
/* Accessors for interface information */
-const char *dplane_ctx_get_ifname(const struct zebra_dplane_ctx *ctx);
-ifindex_t dplane_ctx_get_ifindex(const struct zebra_dplane_ctx *ctx);
uint32_t dplane_ctx_get_intf_metric(const struct zebra_dplane_ctx *ctx);
/* Is interface addr p2p? */
bool dplane_ctx_intf_is_connected(const struct zebra_dplane_ctx *ctx);
@@ -292,6 +296,14 @@ const struct prefix *dplane_ctx_get_intf_dest(
bool dplane_ctx_intf_has_label(const struct zebra_dplane_ctx *ctx);
const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx);
+/* Accessors for MAC information */
+vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx);
+bool dplane_ctx_mac_is_sticky(const struct zebra_dplane_ctx *ctx);
+const struct ethaddr *dplane_ctx_mac_get_addr(
+ const struct zebra_dplane_ctx *ctx);
+const struct in_addr *dplane_ctx_mac_get_vtep_ip(
+ const struct zebra_dplane_ctx *ctx);
+
/* Namespace info - esp. for netlink communication */
const struct zebra_dplane_info *dplane_ctx_get_ns(
const struct zebra_dplane_ctx *ctx);
@@ -353,6 +365,19 @@ enum zebra_dplane_result dplane_intf_addr_set(const struct interface *ifp,
enum zebra_dplane_result dplane_intf_addr_unset(const struct interface *ifp,
const struct connected *ifc);
+/*
+ * Enqueue evpn mac operations for the dataplane.
+ */
+enum zebra_dplane_result dplane_mac_add(const struct interface *ifp,
+ vlanid_t vid,
+ const struct ethaddr *mac,
+ struct in_addr vtep_ip,
+ bool sticky);
+
+enum zebra_dplane_result dplane_mac_del(const struct interface *ifp,
+ vlanid_t vid,
+ const struct ethaddr *mac,
+ struct in_addr vtep_ip);
/* Retrieve the limit on the number of pending, unprocessed updates. */
uint32_t dplane_get_in_queue_limit(void);
diff --git a/zebra/zebra_errors.c b/zebra/zebra_errors.c
index 5f0a9ec011..a7e5147af3 100644
--- a/zebra/zebra_errors.c
+++ b/zebra/zebra_errors.c
@@ -659,7 +659,7 @@ static struct log_ref ferr_zebra_err[] = {
{
.code = EC_ZEBRA_RTM_VERSION_MISMATCH,
.title =
- "Zebra received kernel message with uknown version",
+ "Zebra received kernel message with unknown version",
.description =
"Zebra received a message from the kernel with a message version that does not match Zebra's internal version. Depending on version compatibility, this may cause issues sending and receiving messages to the kernel.",
.suggestion =
diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c
index e7fdaf127d..9f3ea70c77 100644
--- a/zebra/zebra_mpls_openbsd.c
+++ b/zebra/zebra_mpls_openbsd.c
@@ -369,7 +369,7 @@ static enum zebra_dplane_result kmpw_install(struct zebra_dplane_ctx *ctx)
/* ioctl */
memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, dplane_ctx_get_pw_ifname(ctx),
+ strlcpy(ifr.ifr_name, dplane_ctx_get_ifname(ctx),
sizeof(ifr.ifr_name));
ifr.ifr_data = (caddr_t)&imr;
if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
@@ -388,7 +388,7 @@ static enum zebra_dplane_result kmpw_uninstall(struct zebra_dplane_ctx *ctx)
memset(&ifr, 0, sizeof(ifr));
memset(&imr, 0, sizeof(imr));
- strlcpy(ifr.ifr_name, dplane_ctx_get_pw_ifname(ctx),
+ strlcpy(ifr.ifr_name, dplane_ctx_get_ifname(ctx),
sizeof(ifr.ifr_name));
ifr.ifr_data = (caddr_t)&imr;
if (ioctl(kr_state.ioctl_fd, SIOCSETMPWCFG, &ifr) == -1) {
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 3608b887ee..335cc8294c 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -3178,7 +3178,7 @@ static int handle_pw_result(struct zebra_dplane_ctx *ctx)
if (dplane_ctx_get_status(ctx) != ZEBRA_DPLANE_REQUEST_SUCCESS) {
vrf = zebra_vrf_lookup_by_id(dplane_ctx_get_vrf(ctx));
- pw = zebra_pw_find(vrf, dplane_ctx_get_pw_ifname(ctx));
+ pw = zebra_pw_find(vrf, dplane_ctx_get_ifname(ctx));
if (pw)
zebra_pw_install_failure(pw);
}
@@ -3270,6 +3270,11 @@ static int rib_process_dplane_results(struct thread *thread)
dplane_ctx_fini(&ctx);
break;
+ case DPLANE_OP_MAC_INSTALL:
+ case DPLANE_OP_MAC_DELETE:
+ zebra_vxlan_handle_result(ctx);
+ break;
+
default:
/* Don't expect this: just return the struct? */
dplane_ctx_fini(&ctx);
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 1450072aa9..bb31247b6a 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -3733,13 +3733,14 @@ static struct interface *zvni_map_to_svi(vlanid_t vid, struct interface *br_if)
}
/*
- * Install remote MAC into the kernel.
+ * Install remote MAC into the forwarding plane.
*/
static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
{
struct zebra_if *zif;
struct zebra_l2info_vxlan *vxl;
bool sticky;
+ enum zebra_dplane_result res;
if (!(mac->flags & ZEBRA_MAC_REMOTE))
return 0;
@@ -3752,12 +3753,16 @@ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac)
sticky = !!CHECK_FLAG(mac->flags,
(ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW));
- return kernel_add_mac(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
- mac->fwd_info.r_vtep_ip, sticky);
+ res = dplane_mac_add(zvni->vxlan_if, vxl->access_vlan, &mac->macaddr,
+ mac->fwd_info.r_vtep_ip, sticky);
+ if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
+ return 0;
+ else
+ return -1;
}
/*
- * Uninstall remote MAC from the kernel.
+ * Uninstall remote MAC from the forwarding plane.
*/
static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
{
@@ -3765,6 +3770,7 @@ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
struct zebra_l2info_vxlan *vxl;
struct in_addr vtep_ip;
struct interface *ifp;
+ enum zebra_dplane_result res;
if (!(mac->flags & ZEBRA_MAC_REMOTE))
return 0;
@@ -3783,7 +3789,11 @@ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac)
ifp = zvni->vxlan_if;
vtep_ip = mac->fwd_info.r_vtep_ip;
- return kernel_del_mac(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip);
+ res = dplane_mac_del(ifp, vxl->access_vlan, &mac->macaddr, vtep_ip);
+ if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
+ return 0;
+ else
+ return -1;
}
/*
@@ -4470,12 +4480,13 @@ static int zl3vni_rmac_del(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
}
/*
- * Install remote RMAC into the kernel.
+ * Install remote RMAC into the forwarding plane.
*/
static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
{
struct zebra_if *zif = NULL;
struct zebra_l2info_vxlan *vxl = NULL;
+ enum zebra_dplane_result res;
if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
|| !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
@@ -4487,18 +4498,23 @@ static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
vxl = &zif->l2info.vxl;
- return kernel_add_mac(zl3vni->vxlan_if, vxl->access_vlan,
- &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
+ res = dplane_mac_add(zl3vni->vxlan_if, vxl->access_vlan,
+ &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0);
+ if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
+ return 0;
+ else
+ return -1;
}
/*
- * Uninstall remote RMAC from the kernel.
+ * Uninstall remote RMAC from the forwarding plane.
*/
static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
{
char buf[ETHER_ADDR_STRLEN];
struct zebra_if *zif = NULL;
struct zebra_l2info_vxlan *vxl = NULL;
+ enum zebra_dplane_result res;
if (!(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE))
|| !(CHECK_FLAG(zrmac->flags, ZEBRA_MAC_REMOTE_RMAC)))
@@ -4518,8 +4534,12 @@ static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
vxl = &zif->l2info.vxl;
- return kernel_del_mac(zl3vni->vxlan_if, vxl->access_vlan,
- &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip);
+ res = dplane_mac_del(zl3vni->vxlan_if, vxl->access_vlan,
+ &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip);
+ if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
+ return 0;
+ else
+ return -1;
}
/* handle rmac add */
@@ -6772,7 +6792,7 @@ int zebra_vxlan_clear_dup_detect_vni_ip(struct vty *vty,
if (!CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
vty_out(vty,
- "%% Requsted host IP %s is not duplicate detected\n",
+ "%% Requested host IP %s is not duplicate detected\n",
buf);
return CMD_WARNING;
}
@@ -9913,6 +9933,15 @@ static int zebra_evpn_cfg_clean_up(struct zserv *client)
return 0;
}
+/*
+ * Handle results for vxlan dataplane operations.
+ */
+extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx)
+{
+ /* TODO -- anything other than freeing the context? */
+ dplane_ctx_fini(&ctx);
+}
+
/* Cleanup BGP EVPN configuration upon client disconnect */
extern void zebra_evpn_init(void)
{
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index c71953d6bb..bb80ae1c9a 100644
--- a/zebra/zebra_vxlan.h
+++ b/zebra/zebra_vxlan.h
@@ -35,6 +35,7 @@
#include "lib/json.h"
#include "zebra/zebra_vrf.h"
#include "zebra/zserv.h"
+#include "zebra/zebra_dplane.h"
#ifdef __cplusplus
extern "C" {
@@ -213,6 +214,8 @@ extern int zebra_vxlan_clear_dup_detect_vni_all(struct vty *vty,
extern int zebra_vxlan_clear_dup_detect_vni(struct vty *vty,
struct zebra_vrf *zvrf,
vni_t vni);
+extern void zebra_vxlan_handle_result(struct zebra_dplane_ctx *ctx);
+
extern void zebra_evpn_init(void);
#ifdef __cplusplus