summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--zebra/zebra_fpm.c100
-rw-r--r--zebra/zebra_fpm_private.h28
2 files changed, 128 insertions, 0 deletions
diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
index 35a5d69ee..a98515faf 100644
--- a/zebra/zebra_fpm.c
+++ b/zebra/zebra_fpm.c
@@ -30,15 +30,20 @@
#include "network.h"
#include "command.h"
#include "version.h"
+#include "jhash.h"
#include "zebra/rib.h"
#include "zebra/zserv.h"
#include "zebra/zebra_ns.h"
#include "zebra/zebra_vrf.h"
#include "zebra/zebra_errors.h"
+#include "zebra/zebra_memory.h"
#include "fpm/fpm.h"
#include "zebra_fpm_private.h"
+#include "zebra/zebra_router.h"
+
+DEFINE_MTYPE_STATIC(ZEBRA, FPM_MAC_INFO, "FPM_MAC_INFO");
/*
* Interval at which we attempt to connect to the FPM.
@@ -179,6 +184,25 @@ typedef struct zfpm_glob_t_ {
TAILQ_HEAD(zfpm_dest_q, rib_dest_t_) dest_q;
/*
+ * List of fpm_mac_info structures to be processed
+ */
+ TAILQ_HEAD(zfpm_mac_q, fpm_mac_info_t) mac_q;
+
+ /*
+ * Hash table of fpm_mac_info_t entries
+ *
+ * While adding fpm_mac_info_t for a MAC to the mac_q,
+ * it is possible that another fpm_mac_info_t node for the this MAC
+ * is already present in the queue.
+ * This is possible in the case of consecutive add->delete operations.
+ * To avoid such duplicate insertions in the mac_q,
+ * define a hash table for fpm_mac_info_t which can be looked up
+ * to see if an fpm_mac_info_t node for a MAC is already present
+ * in the mac_q.
+ */
+ struct hash *fpm_mac_info_table;
+
+ /*
* Stream socket to the FPM.
*/
int sock;
@@ -1277,6 +1301,75 @@ static int zfpm_trigger_update(struct route_node *rn, const char *reason)
}
/*
+ * Generate Key for FPM MAC info hash entry
+ * Key is generated using MAC address and VNI id which should be sufficient
+ * to provide uniqueness
+ */
+static unsigned int zfpm_mac_info_hash_keymake(const void *p)
+{
+ struct fpm_mac_info_t *fpm_mac = (struct fpm_mac_info_t *)p;
+ uint32_t mac_key;
+
+ mac_key = jhash(fpm_mac->macaddr.octet, ETH_ALEN, 0xa5a5a55a);
+
+ return jhash_2words(mac_key, fpm_mac->vni, 0);
+}
+
+/*
+ * Compare function for FPM MAC info hash lookup
+ */
+static bool zfpm_mac_info_cmp(const void *p1, const void *p2)
+{
+ const struct fpm_mac_info_t *fpm_mac1 = p1;
+ const struct fpm_mac_info_t *fpm_mac2 = p2;
+
+ if (memcmp(fpm_mac1->macaddr.octet, fpm_mac2->macaddr.octet, ETH_ALEN)
+ != 0)
+ return false;
+ if (fpm_mac1->r_vtep_ip.s_addr != fpm_mac2->r_vtep_ip.s_addr)
+ return false;
+ if (fpm_mac1->vni != fpm_mac2->vni)
+ return false;
+
+ return true;
+}
+
+/*
+ * Lookup FPM MAC info hash entry.
+ */
+static struct fpm_mac_info_t *zfpm_mac_info_lookup(struct fpm_mac_info_t *key)
+{
+ return hash_lookup(zfpm_g->fpm_mac_info_table, key);
+}
+
+/*
+ * Callback to allocate fpm_mac_info_t structure.
+ */
+static void *zfpm_mac_info_alloc(void *p)
+{
+ const struct fpm_mac_info_t *key = p;
+ struct fpm_mac_info_t *fpm_mac;
+
+ fpm_mac = XCALLOC(MTYPE_FPM_MAC_INFO, sizeof(struct fpm_mac_info_t));
+
+ memcpy(&fpm_mac->macaddr, &key->macaddr, ETH_ALEN);
+ memcpy(&fpm_mac->r_vtep_ip, &key->r_vtep_ip, sizeof(struct in_addr));
+ fpm_mac->vni = key->vni;
+
+ return (void *)fpm_mac;
+}
+
+/*
+ * Delink and free fpm_mac_info_t.
+ */
+static void zfpm_mac_info_del(struct fpm_mac_info_t *fpm_mac)
+{
+ hash_release(zfpm_g->fpm_mac_info_table, fpm_mac);
+ TAILQ_REMOVE(&zfpm_g->mac_q, fpm_mac, fpm_mac_q_entries);
+ XFREE(MTYPE_FPM_MAC_INFO, fpm_mac);
+}
+
+/*
* zfpm_stats_timer_cb
*/
static int zfpm_stats_timer_cb(struct thread *t)
@@ -1589,6 +1682,13 @@ static int zfpm_init(struct thread_master *master)
memset(zfpm_g, 0, sizeof(*zfpm_g));
zfpm_g->master = master;
TAILQ_INIT(&zfpm_g->dest_q);
+ TAILQ_INIT(&zfpm_g->mac_q);
+
+ /* Create hash table for fpm_mac_info_t enties */
+ zfpm_g->fpm_mac_info_table = hash_create(zfpm_mac_info_hash_keymake,
+ zfpm_mac_info_cmp,
+ "FPM MAC info hash table");
+
zfpm_g->sock = -1;
zfpm_g->state = ZFPM_STATE_IDLE;
diff --git a/zebra/zebra_fpm_private.h b/zebra/zebra_fpm_private.h
index 943aad986..3ca39c45a 100644
--- a/zebra/zebra_fpm_private.h
+++ b/zebra/zebra_fpm_private.h
@@ -53,6 +53,34 @@ static inline void zfpm_debug(const char *format, ...)
}
#endif
+/* This structure contains the MAC addresses enqueued for FPM processing. */
+struct fpm_mac_info_t {
+ struct ethaddr macaddr;
+ uint32_t zebra_flags; /* Could be used to build FPM messages */
+ vni_t vni;
+ ifindex_t vxlan_if;
+ ifindex_t svi_if; /* L2 or L3 Bridge interface */
+ struct in_addr r_vtep_ip; /* Remote VTEP IP */
+
+ /* Linkage to put MAC on the FPM processing queue. */
+ TAILQ_ENTRY(fpm_mac_info_t) fpm_mac_q_entries;
+
+ uint8_t fpm_flags;
+
+#define ZEBRA_MAC_UPDATE_FPM 0x1 /* This flag indicates if we want to upadte
+ * data plane for this MAC. If a MAC is added
+ * and then deleted immediately, we do not want
+ * to update data plane for such operation.
+ * Unset the ZEBRA_MAC_UPDATE_FPM flag in this
+ * case. FPM thread while processing the queue
+ * node will check this flag and dequeue the
+ * node silently without sending any update to
+ * the data plane.
+ */
+#define ZEBRA_MAC_DELETE_FPM 0x2 /* This flag is set if it is a delete operation
+ * for the MAC.
+ */
+};
/*
* Externs