]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_mac.c
bgpd: Adding BGP GR Global & Per Neighbour FSM changes
[mirror_frr.git] / bgpd / bgp_mac.c
index 24f93e43732d46c2e5825b26743a471d799ca2c2..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"
 
@@ -40,9 +41,9 @@ struct bgp_self_mac {
        struct list *ifp_list;
 };
 
-static unsigned int bgp_mac_hash_key_make(void *data)
+static unsigned int bgp_mac_hash_key_make(const void *data)
 {
-       struct bgp_self_mac *bsm = data;
+       const struct bgp_self_mac *bsm = data;
 
        return jhash(&bsm->macaddr, ETH_ALEN, 0xa5a5dead);
 }
@@ -106,10 +107,10 @@ struct bgp_mac_find_internal {
        const char *ifname;
 };
 
-static void bgp_mac_find_ifp_internal(struct hash_backet *backet, void *arg)
+static void bgp_mac_find_ifp_internal(struct hash_bucket *bucket, void *arg)
 {
        struct bgp_mac_find_internal *bmfi = arg;
-       struct bgp_self_mac *bsm = backet->data;
+       struct bgp_self_mac *bsm = bucket->data;
        struct listnode *node;
        char *name;
 
@@ -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,14 +350,38 @@ 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);
 }
 
-bool bgp_mac_entry_exists(struct prefix *p)
+/* This API checks MAC address against any of local
+ * assigned (SVIs) MAC address.
+ * An example: router-mac attribute in any of evpn update
+ * requires to compare against local mac.
+ */
+bool bgp_mac_exist(struct ethaddr *mac)
 {
-       struct prefix_evpn *pevpn = (struct prefix_evpn *)p;
        struct bgp_self_mac lookup;
        struct bgp_self_mac *bsm;
+       static uint8_t tmp [ETHER_ADDR_STRLEN] = {0};
+
+       if (memcmp(mac, &tmp, ETH_ALEN) == 0)
+               return false;
+
+       memcpy(&lookup.macaddr, mac, ETH_ALEN);
+       bsm = hash_lookup(bm->self_mac_hash, &lookup);
+       if (!bsm)
+               return false;
+
+       return true;
+}
+
+/* This API checks EVPN type-2 prefix and comapares
+ * mac against any of local assigned (SVIs) MAC
+ * address.
+ */
+bool bgp_mac_entry_exists(struct prefix *p)
+{
+       struct prefix_evpn *pevpn = (struct prefix_evpn *)p;
 
        if (pevpn->family != AF_EVPN)
                return false;
@@ -323,18 +389,15 @@ bool bgp_mac_entry_exists(struct prefix *p)
        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 bgp_mac_exist(&p->u.prefix_evpn.macip_addr.mac);
 
        return true;
 }
 
-static void bgp_mac_show_mac_entry(struct hash_backet *backet, void *arg)
+static void bgp_mac_show_mac_entry(struct hash_bucket *bucket, void *arg)
 {
        struct vty *vty = arg;
-       struct bgp_self_mac *bsm = backet->data;
+       struct bgp_self_mac *bsm = bucket->data;
        struct listnode *node;
        char *name;
        char buf_mac[ETHER_ADDR_STRLEN];