]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_mac.c
Merge pull request #5717 from pguibert6WIND/flowspec_issue_redistribute
[mirror_frr.git] / bgpd / bgp_mac.c
index f19453fecb68db648532a1da44d79f9b19d7a6e0..537bb45455e8c2357485fc88f4c22389a4789436 100644 (file)
@@ -29,6 +29,7 @@
 #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"
 
@@ -133,11 +134,11 @@ static struct bgp_self_mac *bgp_mac_find_interface_name(const char *ifname)
 }
 
 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;
@@ -146,12 +147,21 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
                        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;
@@ -160,6 +170,14 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
                        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)
@@ -169,6 +187,23 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
                        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,
@@ -184,7 +219,7 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
        }
 }
 
-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;
@@ -214,12 +249,12 @@ static void bgp_mac_rescan_evpn_table(struct bgp *bgp)
                        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;
@@ -228,11 +263,12 @@ static void bgp_mac_rescan_all_evpn_tables(void)
                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;
@@ -248,11 +284,13 @@ static void bgp_mac_remove_ifp_internal(struct bgp_self_mac *bsm, char *ifname)
        }
 
        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);
        }
 }
 
@@ -276,22 +314,26 @@ void bgp_mac_add_mac_entry(struct interface *ifp)
 
                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)
@@ -308,7 +350,7 @@ 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