#include "bgpd/bgp_memory.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_rd.h"
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_evpn_private.h"
}
static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
- struct bgp_table *table)
+ struct bgp_table *table,
+ struct ethaddr *macaddr)
{
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;
continue;
for (rn = bgp_table_top(sub); rn; rn = bgp_route_next(rn)) {
+ bool rn_affected;
+ struct prefix_evpn *pevpn = (struct prefix_evpn *)&rn->p;
struct prefix_rd prd;
uint32_t num_labels = 0;
mpls_label_t *label_pnt = NULL;
struct bgp_route_evpn evpn;
- count++;
+ if (pevpn->family == AF_EVPN &&
+ pevpn->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
+ memcmp(&rn->p.u.prefix_evpn.macip_addr.mac,
+ macaddr, ETH_ALEN) == 0)
+ rn_affected = true;
+ else
+ rn_affected = false;
+
for (pi = rn->info; pi; pi = pi->next) {
if (pi->peer == peer)
break;
if (!pi)
continue;
+ /*
+ * If the mac address is not the same then
+ * we don't care and since we are looking
+ */
+ if ((memcmp(&pi->attr->rmac, macaddr, ETH_ALEN) != 0) &&
+ !rn_affected)
+ continue;
+
if (pi->extra)
num_labels = pi->extra->num_labels;
if (num_labels)
prd.prefixlen = 64;
memcpy(&prd.val, &prn->p.u.val, 8);
+ if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
+ if (bgp_debug_update(peer, &rn->p, NULL, 1)) {
+ char pfx_buf[BGP_PRD_PATH_STRLEN];
+
+ bgp_debug_rdpfxpath2str(
+ AFI_L2VPN, SAFI_EVPN, &prd,
+ &rn->p, label_pnt, num_labels,
+ pi->addpath_rx_id ? 1 : 0,
+ pi->addpath_rx_id, pfx_buf,
+ sizeof(pfx_buf));
+ zlog_debug(
+ "%s skip update of %s marked as removed",
+ peer->host, pfx_buf);
+ }
+ continue;
+ }
+
memcpy(&evpn, &pi->attr->evpn_overlay, sizeof(evpn));
int32_t ret = bgp_update(peer, &rn->p,
pi->addpath_rx_id,
}
}
-static void bgp_mac_rescan_evpn_table(struct bgp *bgp)
+static void bgp_mac_rescan_evpn_table(struct bgp *bgp, struct ethaddr *macaddr)
{
struct listnode *node;
struct peer *peer;
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);
+ bgp_process_mac_rescan_table(bgp, peer, table, macaddr);
}
}
}
-static void bgp_mac_rescan_all_evpn_tables(void)
+static void bgp_mac_rescan_all_evpn_tables(struct ethaddr *macaddr)
{
struct listnode *node;
struct bgp *bgp;
struct bgp_table *table = bgp->rib[AFI_L2VPN][SAFI_EVPN];
if (table)
- bgp_mac_rescan_evpn_table(bgp);
+ bgp_mac_rescan_evpn_table(bgp, macaddr);
}
}
-static void bgp_mac_remove_ifp_internal(struct bgp_self_mac *bsm, char *ifname)
+static void bgp_mac_remove_ifp_internal(struct bgp_self_mac *bsm, char *ifname,
+ struct ethaddr *macaddr)
{
struct listnode *node = NULL;
char *name;
}
if (bsm->ifp_list->count == 0) {
+ struct ethaddr mac = *macaddr;
+
hash_release(bm->self_mac_hash, bsm);
list_delete(&bsm->ifp_list);
XFREE(MTYPE_BSM, bsm);
- bgp_mac_rescan_all_evpn_tables();
+ bgp_mac_rescan_all_evpn_tables(&mac);
}
}
listnode_add(bsm->ifp_list, ifname);
if (old_bsm)
- bgp_mac_remove_ifp_internal(old_bsm, ifname);
+ bgp_mac_remove_ifp_internal(old_bsm, ifname,
+ &old_bsm->macaddr);
} else {
/*
* If old mac address is the same as the new,
* then there is nothing to do here
*/
- if (old_bsm == bsm)
+ if (old_bsm == bsm) {
+ XFREE(MTYPE_BSM_STRING, ifname);
return;
+ }
if (old_bsm)
- bgp_mac_remove_ifp_internal(old_bsm, ifp->name);
+ bgp_mac_remove_ifp_internal(old_bsm, ifp->name,
+ &old_bsm->macaddr);
listnode_add(bsm->ifp_list, ifname);
}
- bgp_mac_rescan_all_evpn_tables();
+ bgp_mac_rescan_all_evpn_tables(&bsm->macaddr);
}
void bgp_mac_del_mac_entry(struct interface *ifp)
* 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);
+ bgp_mac_remove_ifp_internal(bsm, ifp->name, &bsm->macaddr);
}
/* This API checks MAC address against any of local