]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: Make ifchannel lookup a hash lookup
authorDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 13 Feb 2017 01:16:08 +0000 (20:16 -0500)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 24 Feb 2017 15:03:41 +0000 (10:03 -0500)
When we are at scale, it is possible that
we have a very large number of ifchannels
per interface.  So make lookup for
that situation to be a hash lookup.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
pimd/pim_iface.c
pimd/pim_iface.h
pimd/pim_ifchannel.c
pimd/pim_ifchannel.h

index c1289a3ba7e0e453603ffe8175db3481f024e5bf..8f7d40bb36d6a69c711a2ebe084bae617c7f490c 100644 (file)
@@ -27,6 +27,7 @@
 #include "vrf.h"
 #include "linklist.h"
 #include "plist.h"
+#include "hash.h"
 
 #include "pimd.h"
 #include "pim_iface.h"
@@ -86,6 +87,9 @@ static void *if_list_clean(struct pim_interface *pim_ifp)
     list_delete(pim_ifp->pim_ifchannel_list);
   }
 
+  if (pim_ifp->pim_ifchannel_hash)
+    hash_free (pim_ifp->pim_ifchannel_hash);
+
   XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
 
   return 0;
@@ -131,6 +135,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
   pim_ifp->igmp_socket_list = NULL;
   pim_ifp->pim_neighbor_list = NULL;
   pim_ifp->pim_ifchannel_list = NULL;
+  pim_ifp->pim_ifchannel_hash = NULL;
   pim_ifp->pim_generation_id = 0;
 
   /* list of struct igmp_sock */
@@ -161,6 +166,9 @@ struct pim_interface *pim_if_new(struct interface *ifp, int igmp, int pim)
   pim_ifp->pim_ifchannel_list->del = (void (*)(void *)) pim_ifchannel_free;
   pim_ifp->pim_ifchannel_list->cmp = (int (*)(void *, void *)) pim_ifchannel_compare;
 
+  pim_ifp->pim_ifchannel_hash = hash_create (pim_ifchannel_hash_key,
+                                             pim_ifchannel_equal);
+
   ifp->info = pim_ifp;
 
   pim_sock_reset(ifp);
@@ -197,6 +205,8 @@ void pim_if_delete(struct interface *ifp)
   list_delete(pim_ifp->pim_neighbor_list);
   list_delete(pim_ifp->pim_ifchannel_list);
 
+  hash_free (pim_ifp->pim_ifchannel_hash);
+
   XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
 
   ifp->info = NULL;
index 244de598db7dad12f4270db6d2353c71cc56f555..7c0d57a5d132f659df73dcea4e90e44a22a61a11 100644 (file)
@@ -98,6 +98,7 @@ struct pim_interface {
   uint16_t       pim_override_interval_msec; /* config */
   struct list   *pim_neighbor_list; /* list of struct pim_neighbor */
   struct list   *pim_ifchannel_list; /* list of struct pim_ifchannel */
+  struct hash   *pim_ifchannel_hash;
 
   /* neighbors without lan_delay */
   int            pim_number_of_nonlandelay_neighbors;
index 6bff65c1adae634fbc3f89b1641d9c160888f654..021e43a4addd9500118ec6ec8a78e1563349a382 100644 (file)
@@ -25,6 +25,8 @@
 #include "memory.h"
 #include "if.h"
 #include "vrf.h"
+#include "hash.h"
+#include "jhash.h"
 
 #include "pimd.h"
 #include "pim_str.h"
@@ -193,6 +195,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
     called by list_delete_all_node()
   */
   listnode_delete(pim_ifp->pim_ifchannel_list, ch);
+  hash_release(pim_ifp->pim_ifchannel_hash, ch);
   listnode_delete(pim_ifchannel_list, ch);
 
   pim_ifchannel_free(ch);
@@ -373,10 +376,8 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,
                                         struct prefix_sg *sg)
 {
   struct pim_interface *pim_ifp;
-  struct listnode      *ch_node;
   struct pim_ifchannel *ch;
-
-  zassert(ifp);
+  struct pim_ifchannel lookup;
 
   pim_ifp = ifp->info;
 
@@ -385,19 +386,13 @@ struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,
              __PRETTY_FUNCTION__,
              pim_str_sg_dump (sg),
              ifp->name);
-    return 0;
+    return NULL;
   }
 
-  for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_ifchannel_list, ch_node, ch)) {
-    if (
-       (sg->src.s_addr == ch->sg.src.s_addr) &&
-       (sg->grp.s_addr == ch->sg.grp.s_addr)
-       ) {
-      return ch;
-    }
-  }
+  lookup.sg = *sg;
+  ch = hash_lookup (pim_ifp->pim_ifchannel_hash, &lookup);
 
-  return 0;
+  return ch;
 }
 
 static void ifmembership_set(struct pim_ifchannel *ch,
@@ -553,6 +548,7 @@ pim_ifchannel_add(struct interface *ifp,
 
   /* Attach to list */
   listnode_add_sort(pim_ifp->pim_ifchannel_list, ch);
+  ch = hash_get (pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern);
   listnode_add_sort(pim_ifchannel_list, ch);
 
   return ch;
@@ -1228,3 +1224,24 @@ pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom)
        }
     }
 }
+
+unsigned int
+pim_ifchannel_hash_key (void *arg)
+{
+  struct pim_ifchannel *ch = (struct pim_ifchannel *)arg;
+
+  return jhash_2words (ch->sg.src.s_addr, ch->sg.grp.s_addr, 0);
+}
+
+int
+pim_ifchannel_equal (const void *arg1, const void *arg2)
+{
+  const struct pim_ifchannel *ch1 = (const struct pim_ifchannel *)arg1;
+  const struct pim_ifchannel *ch2 = (const struct pim_ifchannel *)arg2;
+
+  if ((ch1->sg.grp.s_addr == ch2->sg.grp.s_addr) &&
+      (ch1->sg.src.s_addr == ch2->sg.src.s_addr))
+    return 1;
+
+  return 0;
+}
index 5cac0318c6ed28ddb00e9e7c789724a4a56debd6..c7084034a0a93c84e15ee8f5cd04c4dff5ebbd89 100644 (file)
@@ -154,4 +154,7 @@ void pim_ifchannel_scan_forward_start (struct interface *new_ifp);
 void pim_ifchannel_set_star_g_join_state (struct pim_ifchannel *ch, int eom);
 
 int pim_ifchannel_compare (struct pim_ifchannel *ch1, struct pim_ifchannel *ch2);
+
+unsigned int pim_ifchannel_hash_key (void *arg);
+int pim_ifchannel_equal (const void *arg1, const void *arg2);
 #endif /* PIM_IFCHANNEL_H */