summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c2
-rw-r--r--bgpd/bgp_attr.h8
-rw-r--r--bgpd/bgp_flowspec_util.c25
-rw-r--r--bgpd/bgp_flowspec_util.h4
-rw-r--r--bgpd/bgp_mac.c354
-rw-r--r--bgpd/bgp_mac.h41
-rw-r--r--bgpd/bgp_nht.c11
-rw-r--r--bgpd/bgp_pbr.c2
-rw-r--r--bgpd/bgp_pbr.h3
-rw-r--r--bgpd/bgp_route.c14
-rw-r--r--bgpd/bgp_vty.c22
-rw-r--r--bgpd/bgp_zebra.c9
-rw-r--r--bgpd/bgpd.c3
-rw-r--r--bgpd/bgpd.h3
-rw-r--r--bgpd/subdir.am2
-rw-r--r--zebra/main.c5
-rw-r--r--zebra/zebra_netns_notify.c12
-rw-r--r--zebra/zebra_ns.c6
-rw-r--r--zebra/zebra_ns.h2
19 files changed, 510 insertions, 18 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index b990e99bda..03f31eddfc 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -392,7 +392,7 @@ static bool overlay_index_same(const struct attr *a1, const struct attr *a2)
if (!a1 && !a2)
return true;
return !memcmp(&(a1->evpn_overlay), &(a2->evpn_overlay),
- sizeof(struct overlay_index));
+ sizeof(struct bgp_route_evpn));
}
/* Unknown transit attribute. */
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 47a4182fee..6d5c647b21 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -92,12 +92,6 @@ struct bgp_tea_options {
#endif
-/* Overlay Index Info */
-struct overlay_index {
- struct eth_segment_id eth_s_id;
- union gw_addr gw_ip;
-};
-
enum pta_type {
PMSI_TNLTYPE_NO_INFO = 0,
PMSI_TNLTYPE_RSVP_TE_P2MP,
@@ -204,7 +198,7 @@ struct attr {
struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */
#endif
/* EVPN */
- struct overlay_index evpn_overlay;
+ struct bgp_route_evpn evpn_overlay;
/* EVPN MAC Mobility sequence number, if any. */
uint32_t mm_seqnum;
diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c
index c6386dcdb5..cd5bec6267 100644
--- a/bgpd/bgp_flowspec_util.c
+++ b/bgpd/bgp_flowspec_util.c
@@ -23,6 +23,7 @@
#include "prefix.h"
#include "lib_errors.h"
+#include "bgp_route.h"
#include "bgp_table.h"
#include "bgp_flowspec_util.h"
#include "bgp_flowspec_private.h"
@@ -581,3 +582,27 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
}
return error;
}
+
+/* return 1 if FS entry invalid or no NH IP */
+int bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
+ struct prefix *p)
+{
+ struct bgp_pbr_entry_main api;
+ int i;
+ struct bgp_node *rn = pi->net;
+ struct bgp_pbr_entry_action *api_action;
+
+ memset(&api, 0, sizeof(struct bgp_pbr_entry_main));
+ if (bgp_pbr_build_and_validate_entry(&rn->p, pi, &api) < 0)
+ return 1;
+ for (i = 0; i < api.action_num; i++) {
+ api_action = &api.actions[i];
+ if (api_action->action != ACTION_REDIRECT_IP)
+ continue;
+ p->family = AF_INET;
+ p->prefixlen = IPV4_MAX_BITLEN;
+ p->u.prefix4 = api_action->u.zr.redirect_ip_v4;
+ return 0;
+ }
+ return 1;
+}
diff --git a/bgpd/bgp_flowspec_util.h b/bgpd/bgp_flowspec_util.h
index 9bf05847d3..2ce911da4e 100644
--- a/bgpd/bgp_flowspec_util.h
+++ b/bgpd/bgp_flowspec_util.h
@@ -54,4 +54,8 @@ extern bool bgp_flowspec_contains_prefix(struct prefix *pfs,
struct prefix *input,
int prefix_check);
+extern int bgp_flowspec_get_first_nh(struct bgp *bgp,
+ struct bgp_path_info *pi,
+ struct prefix *nh);
+
#endif /* _FRR_BGP_FLOWSPEC_UTIL_H */
diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c
new file mode 100644
index 0000000000..24f93e4373
--- /dev/null
+++ b/bgpd/bgp_mac.c
@@ -0,0 +1,354 @@
+/*
+ * BGPd - Mac hash code
+ * Copyright (C) 2018 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <zebra.h>
+
+#include <jhash.h>
+#include <hash.h>
+#include <prefix.h>
+#include <memory.h>
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_mac.h"
+#include "bgpd/bgp_memory.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_evpn_private.h"
+
+DEFINE_MTYPE_STATIC(BGPD, BSM, "Mac Hash Entry");
+DEFINE_MTYPE_STATIC(BGPD, BSM_STRING, "Mac Hash Entry Interface String");
+
+struct bgp_self_mac {
+ struct ethaddr macaddr;
+ struct list *ifp_list;
+};
+
+static unsigned int bgp_mac_hash_key_make(void *data)
+{
+ struct bgp_self_mac *bsm = data;
+
+ return jhash(&bsm->macaddr, ETH_ALEN, 0xa5a5dead);
+}
+
+static bool bgp_mac_hash_cmp(const void *d1, const void *d2)
+{
+ const struct bgp_self_mac *bsm1 = d1;
+ const struct bgp_self_mac *bsm2 = d2;
+
+ if (memcmp(&bsm1->macaddr, &bsm2->macaddr, ETH_ALEN) == 0)
+ return true;
+
+ return false;
+}
+
+void bgp_mac_init(void)
+{
+ bm->self_mac_hash = hash_create(bgp_mac_hash_key_make, bgp_mac_hash_cmp,
+ "BGP MAC Hash");
+}
+
+static void bgp_mac_hash_free(void *data)
+{
+ struct bgp_self_mac *bsm = data;
+
+ if (bsm->ifp_list)
+ list_delete(&bsm->ifp_list);
+
+ XFREE(MTYPE_BSM, bsm);
+}
+
+void bgp_mac_finish(void)
+{
+ hash_clean(bm->self_mac_hash, bgp_mac_hash_free);
+ hash_free(bm->self_mac_hash);
+}
+
+static void bgp_mac_hash_interface_string_del(void *val)
+{
+ char *data = val;
+
+ XFREE(MTYPE_BSM_STRING, data);
+}
+
+static void *bgp_mac_hash_alloc(void *p)
+{
+ const struct bgp_self_mac *orig = p;
+ struct bgp_self_mac *bsm;
+
+ bsm = XCALLOC(MTYPE_BSM, sizeof(struct bgp_self_mac));
+ memcpy(&bsm->macaddr, &orig->macaddr, ETH_ALEN);
+
+ bsm->ifp_list = list_new();
+ bsm->ifp_list->del = bgp_mac_hash_interface_string_del;
+
+ return bsm;
+}
+
+struct bgp_mac_find_internal {
+ struct bgp_self_mac *bsm;
+ const char *ifname;
+};
+
+static void bgp_mac_find_ifp_internal(struct hash_backet *backet, void *arg)
+{
+ struct bgp_mac_find_internal *bmfi = arg;
+ struct bgp_self_mac *bsm = backet->data;
+ struct listnode *node;
+ char *name;
+
+ for (ALL_LIST_ELEMENTS_RO(bsm->ifp_list, node, name)) {
+ if (strcmp(name, bmfi->ifname) == 0) {
+ bmfi->bsm = bsm;
+ return;
+ }
+ }
+}
+
+static struct bgp_self_mac *bgp_mac_find_interface_name(const char *ifname)
+{
+ struct bgp_mac_find_internal bmfi;
+
+ bmfi.bsm = NULL;
+ bmfi.ifname = ifname;
+ hash_iterate(bm->self_mac_hash, bgp_mac_find_ifp_internal, &bmfi);
+
+ return bmfi.bsm;
+}
+
+static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
+ struct bgp_table *table)
+{
+ struct bgp_node *prn, *rn;
+ struct bgp_path_info *pi;
+ uint32_t count = 0;
+
+ for (prn = bgp_table_top(table); prn; prn = bgp_route_next(prn)) {
+ struct bgp_table *sub = prn->info;
+
+ if (!sub)
+ continue;
+
+ for (rn = bgp_table_top(sub); rn; rn = bgp_route_next(rn)) {
+ struct prefix_rd prd;
+ uint32_t num_labels = 0;
+ mpls_label_t *label_pnt = NULL;
+ struct bgp_route_evpn evpn;
+
+ count++;
+ for (pi = rn->info; pi; pi = pi->next) {
+ if (pi->peer == peer)
+ break;
+ }
+
+ if (!pi)
+ continue;
+
+ if (pi->extra)
+ num_labels = pi->extra->num_labels;
+ if (num_labels)
+ label_pnt = &pi->extra->label[0];
+
+ prd.family = AF_UNSPEC;
+ prd.prefixlen = 64;
+ memcpy(&prd.val, &prn->p.u.val, 8);
+
+ memcpy(&evpn, &pi->attr->evpn_overlay, sizeof(evpn));
+ int32_t ret = bgp_update(peer, &rn->p,
+ pi->addpath_rx_id,
+ pi->attr, AFI_L2VPN, SAFI_EVPN,
+ ZEBRA_ROUTE_BGP,
+ BGP_ROUTE_NORMAL, &prd,
+ label_pnt, num_labels,
+ 1, &evpn);
+
+ if (ret < 0)
+ bgp_unlock_node(rn);
+ }
+ }
+}
+
+static void bgp_mac_rescan_evpn_table(struct bgp *bgp)
+{
+ struct listnode *node;
+ struct peer *peer;
+ safi_t safi;
+ afi_t afi;
+
+ afi = AFI_L2VPN;
+ safi = SAFI_EVPN;
+ for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
+
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
+ continue;
+
+ if (peer->status != Established)
+ continue;
+
+ if (CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_SOFT_RECONFIG)) {
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("Processing EVPN MAC interface change on peer %s (inbound, soft-reconfig)",
+ peer->host);
+
+ bgp_soft_reconfig_in(peer, afi, safi);
+ } else {
+ struct bgp_table *table = bgp->rib[afi][safi];
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("Processing EVPN MAC interface change on peer %s",
+ peer->host);
+ bgp_process_mac_rescan_table(bgp, peer, table);
+ }
+ }
+}
+
+static void bgp_mac_rescan_all_evpn_tables(void)
+{
+ struct listnode *node;
+ struct bgp *bgp;
+
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
+ struct bgp_table *table = bgp->rib[AFI_L2VPN][SAFI_EVPN];
+
+ if (table)
+ bgp_mac_rescan_evpn_table(bgp);
+ }
+}
+
+static void bgp_mac_remove_ifp_internal(struct bgp_self_mac *bsm, char *ifname)
+{
+ struct listnode *node = NULL;
+ char *name;
+
+ for (ALL_LIST_ELEMENTS_RO(bsm->ifp_list, node, name)) {
+ if (strcmp(name, ifname) == 0)
+ break;
+ }
+
+ if (node) {
+ list_delete_node(bsm->ifp_list, node);
+ XFREE(MTYPE_BSM_STRING, name);
+ }
+
+ if (bsm->ifp_list->count == 0) {
+ hash_release(bm->self_mac_hash, bsm);
+ list_delete(&bsm->ifp_list);
+ XFREE(MTYPE_BSM, bsm);
+
+ bgp_mac_rescan_all_evpn_tables();
+ }
+}
+
+void bgp_mac_add_mac_entry(struct interface *ifp)
+{
+ struct bgp_self_mac lookup;
+ struct bgp_self_mac *bsm;
+ struct bgp_self_mac *old_bsm;
+ char *ifname;
+
+ memcpy(&lookup.macaddr, &ifp->hw_addr, ETH_ALEN);
+ bsm = hash_get(bm->self_mac_hash, &lookup, bgp_mac_hash_alloc);
+
+ /*
+ * Does this happen to be a move
+ */
+ old_bsm = bgp_mac_find_interface_name(ifp->name);
+ ifname = XSTRDUP(MTYPE_BSM_STRING, ifp->name);
+
+ if (bsm->ifp_list->count == 0) {
+
+ listnode_add(bsm->ifp_list, ifname);
+ if (old_bsm)
+ bgp_mac_remove_ifp_internal(old_bsm, ifname);
+ } else {
+ /*
+ * If old mac address is the same as the new,
+ * then there is nothing to do here
+ */
+ if (old_bsm == bsm)
+ return;
+
+ if (old_bsm)
+ bgp_mac_remove_ifp_internal(old_bsm, ifp->name);
+
+ listnode_add(bsm->ifp_list, ifname);
+ }
+
+ bgp_mac_rescan_all_evpn_tables();
+}
+
+void bgp_mac_del_mac_entry(struct interface *ifp)
+{
+ struct bgp_self_mac lookup;
+ struct bgp_self_mac *bsm;
+
+ memcpy(&lookup.macaddr, &ifp->hw_addr, ETH_ALEN);
+ bsm = hash_lookup(bm->self_mac_hash, &lookup);
+ if (!bsm)
+ return;
+
+ /*
+ * Write code to allow old mac address to no-longer
+ * win if we happen to have received it from a peer.
+ */
+ bgp_mac_remove_ifp_internal(bsm, ifp->name);
+}
+
+bool bgp_mac_entry_exists(struct prefix *p)
+{
+ struct prefix_evpn *pevpn = (struct prefix_evpn *)p;
+ struct bgp_self_mac lookup;
+ struct bgp_self_mac *bsm;
+
+ if (pevpn->family != AF_EVPN)
+ return false;
+
+ if (pevpn->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
+ return false;
+
+ memcpy(&lookup.macaddr, &p->u.prefix_evpn.macip_addr.mac, ETH_ALEN);
+ bsm = hash_lookup(bm->self_mac_hash, &lookup);
+ if (!bsm)
+ return false;
+
+ return true;
+}
+
+static void bgp_mac_show_mac_entry(struct hash_backet *backet, void *arg)
+{
+ struct vty *vty = arg;
+ struct bgp_self_mac *bsm = backet->data;
+ struct listnode *node;
+ char *name;
+ char buf_mac[ETHER_ADDR_STRLEN];
+
+ vty_out(vty, "Mac Address: %s ",
+ prefix_mac2str(&bsm->macaddr, buf_mac, sizeof(buf_mac)));
+
+ for (ALL_LIST_ELEMENTS_RO(bsm->ifp_list, node, name))
+ vty_out(vty, "%s ", name);
+
+ vty_out(vty, "\n");
+}
+
+void bgp_mac_dump_table(struct vty *vty)
+{
+ hash_iterate(bm->self_mac_hash, bgp_mac_show_mac_entry, vty);
+}
diff --git a/bgpd/bgp_mac.h b/bgpd/bgp_mac.h
new file mode 100644
index 0000000000..1dd987ef12
--- /dev/null
+++ b/bgpd/bgp_mac.h
@@ -0,0 +1,41 @@
+/*
+ * BGPd - Mac hash header
+ * Copyright (C) 2018 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __BGP_MAC_H__
+#define __BGP_MAC_H__
+
+void bgp_mac_init(void);
+void bgp_mac_finish(void);
+
+/*
+ * Functions to add/delete the mac entry from the appropriate
+ * bgp hash's. Additionally to do some additional processing
+ * to allow the win/loss to be processed.
+ */
+void bgp_mac_add_mac_entry(struct interface *ifp);
+void bgp_mac_del_mac_entry(struct interface *ifp);
+
+void bgp_mac_dump_table(struct vty *vty);
+
+/*
+ * Function to lookup the prefix and see if we have a matching mac
+ */
+bool bgp_mac_entry_exists(struct prefix *p);
+
+#endif
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index b6ef5a55c5..2b4ad22b93 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -42,6 +42,7 @@
#include "bgpd/bgp_nht.h"
#include "bgpd/bgp_fsm.h"
#include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_flowspec_util.h"
extern struct zclient *zclient;
@@ -533,7 +534,15 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
&& (pi->sub_type == BGP_ROUTE_STATIC))
? 1
: 0;
-
+ struct bgp_node *net = pi->net;
+ struct prefix *p_orig = &net->p;
+
+ if (p_orig->family == AF_FLOWSPEC) {
+ if (!pi->peer)
+ return -1;
+ return bgp_flowspec_get_first_nh(pi->peer->bgp,
+ pi, p);
+ }
memset(p, 0, sizeof(struct prefix));
switch (afi) {
case AFI_IP:
diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c
index f0a0e615e6..f002154701 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -626,7 +626,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
}
/* return -1 if build or validation failed */
-static int bgp_pbr_build_and_validate_entry(struct prefix *p,
+int bgp_pbr_build_and_validate_entry(struct prefix *p,
struct bgp_path_info *path,
struct bgp_pbr_entry_main *api)
{
diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h
index 84095f9ab9..45c3c9ea13 100644
--- a/bgpd/bgp_pbr.h
+++ b/bgpd/bgp_pbr.h
@@ -290,4 +290,7 @@ extern void bgp_pbr_reset(struct bgp *bgp, afi_t afi);
extern struct bgp_pbr_interface *bgp_pbr_interface_lookup(const char *name,
struct bgp_pbr_interface_head *head);
+extern int bgp_pbr_build_and_validate_entry(struct prefix *p,
+ struct bgp_path_info *path,
+ struct bgp_pbr_entry_main *api);
#endif /* __BGP_PBR_H__ */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 31cd3d1f05..3561674700 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -66,6 +66,7 @@
#include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_label.h"
#include "bgpd/bgp_addpath.h"
+#include "bgpd/bgp_mac.h"
#if ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
@@ -3057,6 +3058,11 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
goto filtered;
}
+ if (bgp_mac_entry_exists(p)) {
+ reason = "self mac;";
+ goto filtered;
+ }
+
attr_new = bgp_attr_intern(&new_attr);
/* If the update is implicit withdraw. */
@@ -3778,16 +3784,22 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
bgp_node_get_bgp_path_info(rn);
uint32_t num_labels = 0;
mpls_label_t *label_pnt = NULL;
+ struct bgp_route_evpn evpn;
if (pi && pi->extra)
num_labels = pi->extra->num_labels;
if (num_labels)
label_pnt = &pi->extra->label[0];
+ if (pi)
+ memcpy(&evpn, &pi->attr->evpn_overlay,
+ sizeof(evpn));
+ else
+ memset(&evpn, 0, sizeof(evpn));
ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
BGP_ROUTE_NORMAL, prd, label_pnt,
- num_labels, 1, NULL);
+ num_labels, 1, &evpn);
if (ret < 0) {
bgp_unlock_node(rn);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 2a4421aa54..cf1421f5a6 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -37,6 +37,7 @@
#include "frrstr.h"
#include "bgpd/bgpd.h"
+#include "bgpd/bgp_attr_evpn.h"
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_aspath.h"
@@ -62,6 +63,7 @@
#include "bgpd/bgp_io.h"
#include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_addpath.h"
+#include "bgpd/bgp_mac.h"
static struct peer_group *listen_range_exists(struct bgp *bgp,
struct prefix *range, int exact);
@@ -7244,13 +7246,15 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,
/* one clear bgp command to rule them all */
DEFUN (clear_ip_bgp_all,
clear_ip_bgp_all_cmd,
- "clear [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> [<soft [<in|out>]|in [prefix-filter]|out>]",
+ "clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> [<soft [<in|out>]|in [prefix-filter]|out>]",
CLEAR_STR
IP_STR
BGP_STR
BGP_INSTANCE_HELP_STR
BGP_AFI_HELP_STR
+ "Address Family\n"
BGP_SAFI_WITH_LABEL_HELP_STR
+ "Address Family modifier\n"
"Clear all peers\n"
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
@@ -7574,6 +7578,18 @@ DEFUN (show_bgp_vrfs,
return CMD_SUCCESS;
}
+DEFUN (show_bgp_mac_hash,
+ show_bgp_mac_hash_cmd,
+ "show bgp mac hash",
+ SHOW_STR
+ BGP_STR
+ "Mac Address\n"
+ "Mac Address database\n")
+{
+ bgp_mac_dump_table(vty);
+
+ return CMD_SUCCESS;
+}
static void show_tip_entry(struct hash_backet *backet, void *args)
{
@@ -12999,6 +13015,8 @@ void bgp_vty_init(void)
&neighbor_soft_reconfiguration_cmd);
install_element(BGP_FLOWSPECV6_NODE,
&no_neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_soft_reconfiguration_cmd);
/* "neighbor attribute-unchanged" commands. */
install_element(BGP_NODE, &neighbor_attr_unchanged_hidden_cmd);
@@ -13832,6 +13850,8 @@ void bgp_vty_init(void)
/* "show bgp martian next-hop" */
install_element(VIEW_NODE, &show_bgp_martian_nexthop_db_cmd);
+ install_element(VIEW_NODE, &show_bgp_mac_hash_cmd);
+
/* "show [ip] bgp views" commands. */
install_element(VIEW_NODE, &show_bgp_views_cmd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 66d3333739..3c4b219466 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -59,6 +59,7 @@
#include "bgpd/bgp_labelpool.h"
#include "bgpd/bgp_pbr.h"
#include "bgpd/bgp_evpn_private.h"
+#include "bgpd/bgp_mac.h"
/* All information about zebra. */
struct zclient *zclient = NULL;
@@ -221,6 +222,8 @@ static int bgp_interface_add(int command, struct zclient *zclient,
if (!bgp)
return 0;
+ bgp_mac_add_mac_entry(ifp);
+
bgp_update_interface_nbrs(bgp, ifp, ifp);
return 0;
}
@@ -245,6 +248,8 @@ static int bgp_interface_delete(int command, struct zclient *zclient,
if (bgp)
bgp_update_interface_nbrs(bgp, ifp, NULL);
+ bgp_mac_del_mac_entry(ifp);
+
if_set_index(ifp, IFINDEX_INTERNAL);
return 0;
}
@@ -267,6 +272,8 @@ static int bgp_interface_up(int command, struct zclient *zclient,
if (!ifp)
return 0;
+ bgp_mac_add_mac_entry(ifp);
+
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Rx Intf up VRF %u IF %s", vrf_id, ifp->name);
@@ -300,6 +307,8 @@ static int bgp_interface_down(int command, struct zclient *zclient,
if (!ifp)
return 0;
+ bgp_mac_del_mac_entry(ifp);
+
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Rx Intf down VRF %u IF %s", vrf_id, ifp->name);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 7a3afbd18d..5b8ceb0541 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -87,6 +87,7 @@
#include "bgpd/bgp_pbr.h"
#include "bgpd/bgp_addpath.h"
#include "bgpd/bgp_evpn_private.h"
+#include "bgpd/bgp_mac.h"
DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
DEFINE_MTYPE_STATIC(BGPD, BGP_EVPN_INFO, "BGP EVPN instance information");
@@ -7775,6 +7776,7 @@ void bgp_master_init(struct thread_master *master)
bgp_process_queue_init();
+ bgp_mac_init();
/* init the rd id space.
assign 0th index in the bitfield,
so that we start with id 1
@@ -7964,4 +7966,5 @@ void bgp_terminate(void)
if (bm->t_rmap_update)
BGP_TIMER_OFF(bm->t_rmap_update);
+ bgp_mac_finish();
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index f28ca9fa0b..484fc105e8 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -122,6 +122,9 @@ struct bgp_master {
/* Listener address */
char *address;
+ /* The Mac table */
+ struct hash *self_mac_hash;
+
/* BGP start time. */
time_t start_time;
diff --git a/bgpd/subdir.am b/bgpd/subdir.am
index 7d7d3ca189..7dd1d73f69 100644
--- a/bgpd/subdir.am
+++ b/bgpd/subdir.am
@@ -72,6 +72,7 @@ bgpd_libbgp_a_SOURCES = \
bgpd/bgp_label.c \
bgpd/bgp_labelpool.c \
bgpd/bgp_lcommunity.c \
+ bgpd/bgp_mac.c \
bgpd/bgp_memory.c \
bgpd/bgp_mpath.c \
bgpd/bgp_mplsvpn.c \
@@ -145,6 +146,7 @@ noinst_HEADERS += \
bgpd/bgp_label.h \
bgpd/bgp_labelpool.h \
bgpd/bgp_lcommunity.h \
+ bgpd/bgp_mac.h \
bgpd/bgp_memory.h \
bgpd/bgp_mpath.h \
bgpd/bgp_mplsvpn.h \
diff --git a/zebra/main.c b/zebra/main.c
index 90d3dbc180..b54c36c109 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -407,10 +407,7 @@ int main(int argc, char **argv)
/*
* Initialize NS( and implicitly the VRF module), and make kernel
* routing socket. */
- zebra_ns_init();
- if (vrf_default_name_configured)
- vrf_set_default_name(vrf_default_name_configured,
- true);
+ zebra_ns_init((const char *)vrf_default_name_configured);
zebra_vty_init();
access_list_init();
prefix_list_init();
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c
index a4e1022148..a6b17303b9 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -215,6 +215,12 @@ static int zebra_ns_ready_read(struct thread *t)
if (err < 0)
return zebra_ns_continue_read(zns_info, stop_retry);
+ /* check default name is not already set */
+ if (strmatch(VRF_DEFAULT_NAME, basename(netnspath))) {
+ zlog_warn("NS notify : NS %s is already default VRF."
+ "Cancel VRF Creation", basename(netnspath));
+ return zebra_ns_continue_read(zns_info, 1);
+ }
if (zebra_ns_notify_is_default_netns(basename(netnspath))) {
zlog_warn(
"NS notify : NS %s is default VRF."
@@ -311,6 +317,12 @@ void zebra_ns_notify_parse(void)
dent->d_name);
continue;
}
+ /* check default name is not already set */
+ if (strmatch(VRF_DEFAULT_NAME, basename(dent->d_name))) {
+ zlog_warn("NS notify : NS %s is already default VRF."
+ "Cancel VRF Creation", dent->d_name);
+ continue;
+ }
if (zebra_ns_notify_is_default_netns(dent->d_name)) {
zlog_warn(
"NS notify : NS %s is default VRF."
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index 03987fcb5b..0c743d8678 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -183,7 +183,7 @@ int zebra_ns_final_shutdown(struct ns *ns)
return 0;
}
-int zebra_ns_init(void)
+int zebra_ns_init(const char *optional_default_name)
{
ns_id_t ns_id;
ns_id_t ns_id_external;
@@ -207,6 +207,10 @@ int zebra_ns_init(void)
/* Default NS is activated */
zebra_ns_enable(ns_id_external, (void **)&dzns);
+ if (optional_default_name)
+ vrf_set_default_name(optional_default_name,
+ true);
+
if (vrf_is_backend_netns()) {
ns_add_hook(NS_NEW_HOOK, zebra_ns_new);
ns_add_hook(NS_ENABLE_HOOK, zebra_ns_enabled);
diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h
index d3592f8f30..01af64c17b 100644
--- a/zebra/zebra_ns.h
+++ b/zebra/zebra_ns.h
@@ -60,7 +60,7 @@ struct zebra_ns {
struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id);
-int zebra_ns_init(void);
+int zebra_ns_init(const char *optional_default_name);
int zebra_ns_enable(ns_id_t ns_id, void **info);
int zebra_ns_disabled(struct ns *ns);
int zebra_ns_early_shutdown(struct ns *ns);