]> git.puffer.fish Git - matthieu/frr.git/commitdiff
Use a hash to store BGP peer structures
authorDaniel Walton <dwalton@cumulusnetworks.com>
Fri, 23 Oct 2015 17:34:50 +0000 (17:34 +0000)
committerDaniel Walton <dwalton@cumulusnetworks.com>
Fri, 23 Oct 2015 17:34:50 +0000 (17:34 +0000)
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Ticket: CM-5370

bgpd/bgp_network.c
bgpd/bgp_snmp.c
bgpd/bgpd.c
bgpd/bgpd.h
lib/sockunion.c
lib/sockunion.h

index 592c8416b63bb343d14188c3861333f0d0863e16..bdb8e4c065c38418f66bb9c6f84d4f4950117d94 100644 (file)
@@ -229,6 +229,8 @@ bgp_accept (struct thread *thread)
   struct peer *peer1;
   char buf[SU_ADDRSTRLEN];
 
+  sockunion_init (&su);
+
   /* Register accept thread. */
   accept_sock = THREAD_FD (thread);
   if (accept_sock < 0)
@@ -444,6 +446,8 @@ bgp_update_source (struct peer *peer)
   union sockunion addr;
   int ret = 0;
 
+  sockunion_init (&addr);
+
   /* Source is specified with interface name.  */
   if (peer->update_if)
     {
index 0d1aa4df84afd5234a28b13744a5798e500ad88d..5de2bc4205e1f56caa768609192644f1abb14a53 100644 (file)
@@ -311,7 +311,7 @@ bgp_peer_lookup_next (struct in_addr *src)
   union sockunion su;
   int ret;
 
-  memset (&su, 0, sizeof (union sockunion));
+  sockunion_init (&su);
 
   bgp = bgp_get_default ();
   if (! bgp)
@@ -621,6 +621,8 @@ bgp4PathAttrLookup (struct variable *v, oid name[], size_t *length,
   unsigned int len;
   struct in_addr paddr;
 
+  sockunion_init (&su);
+
 #define BGP_PATHATTR_ENTRY_OFFSET \
           (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE)
 
index 3711c8fbd11b434300f01c5862c991b3b97d4daa..ef0ba846a09b1f160c8d68967a563a5e60143a2f 100644 (file)
@@ -39,6 +39,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "queue.h"
 #include "zclient.h"
 #include "bfd.h"
+#include "hash.h"
+#include "jhash.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_table.h"
@@ -698,6 +700,22 @@ peer_cmp (struct peer *p1, struct peer *p2)
   return sockunion_cmp (&p1->su, &p2->su);
 }
 
+static unsigned int
+peer_hash_key_make(void *p)
+{
+  struct peer *peer = p;
+  return sockunion_hash(&peer->su);
+}
+
+static int
+peer_hash_cmp (const void *p1, const void *p2)
+{
+  const struct peer *peer1 = p1;
+  const struct peer *peer2 = p2;
+  return (sockunion_same (&peer1->su, &peer2->su) &&
+          CHECK_FLAG (peer1->flags, PEER_FLAG_CONFIG_NODE) == CHECK_FLAG (peer2->flags, PEER_FLAG_CONFIG_NODE));
+}
+
 int
 peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
 {
@@ -1309,6 +1327,10 @@ bgp_peer_conf_if_to_su_update (struct peer *peer)
       peer->su.sa.sa_family = AF_UNSPEC;
       memset(&peer->su.sin6.sin6_addr, 0, sizeof (struct in6_addr));
     }
+
+  /* Since our su changed we need to del/add peer to the peerhash */
+  hash_release(peer->bgp->peerhash, peer);
+  hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
 }
 
 /* Create new BGP peer.  */
@@ -1350,6 +1372,7 @@ peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp,
 
   peer = peer_lock (peer); /* bgp peer list reference */
   listnode_add_sort (bgp->peer, peer);
+  hash_get(bgp->peerhash, peer, hash_alloc_intern);
 
   active = peer_active (peer);
 
@@ -1417,7 +1440,7 @@ peer_conf_interface_get(struct bgp *bgp, const char *conf_if, afi_t afi,
   return peer;
 }
 
-/* Make accept BGP peer.  Called from bgp_accept (). */
+/* Make accept BGP peer. This function is only called from the test code */
 struct peer *
 peer_create_accept (struct bgp *bgp)
 {
@@ -1824,6 +1847,7 @@ peer_delete (struct peer *peer)
     {
       peer_unlock (peer); /* bgp peer list reference */
       list_delete_node (bgp->peer, pn);
+      hash_release(bgp->peerhash, peer);
     }
       
   if (peer_rsclient_active (peer)
@@ -2733,6 +2757,7 @@ bgp_create (as_t *as, const char *name)
   bgp->peer_self->host = XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
   bgp->peer = list_new ();
   bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
+  bgp->peerhash = hash_create (peer_hash_key_make, peer_hash_cmp);
 
   bgp->group = list_new ();
   bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
@@ -2996,6 +3021,8 @@ bgp_free (struct bgp *bgp)
   list_delete (bgp->group);
   list_delete (bgp->peer);
   list_delete (bgp->rsclient);
+  hash_free(bgp->peerhash);
+  bgp->peerhash = NULL;
 
   if (bgp->name)
     XFREE(MTYPE_BGP, bgp->name);
@@ -3074,27 +3101,37 @@ peer_lookup_by_hostname (struct bgp *bgp, const char *hostname)
 struct peer *
 peer_lookup (struct bgp *bgp, union sockunion *su)
 {
-  struct peer *peer;
-  struct listnode *node, *nnode;
+  struct peer *peer = NULL;
+  struct peer tmp_peer;
+
+  memset(&tmp_peer, 0, sizeof(struct peer));
+
+  /*
+   * We do not want to find the doppelganger peer so search for the peer in
+   * the hash that has PEER_FLAG_CONFIG_NODE
+   */
+  SET_FLAG (tmp_peer.flags, PEER_FLAG_CONFIG_NODE);
+
+  tmp_peer.su = *su;
 
   if (bgp != NULL)
     {
-      for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
-        if (sockunion_same (&peer->su, su)
-            && (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)))
-          return peer;
+      peer = hash_lookup(bgp->peerhash, &tmp_peer);
     }
   else if (bm->bgp != NULL)
     {
       struct listnode *bgpnode, *nbgpnode;
   
       for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
-        for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
-          if (sockunion_same (&peer->su, su)
-              && (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE)))
-            return peer;
+        {
+          peer = hash_lookup(bgp->peerhash, &tmp_peer);
+
+          if (peer)
+            break;
+        }
     }
-  return NULL;
+
+  return peer;
 }
 
 struct peer *
index 22c4d203060c7464418a58df9a6e3aabf7a0a3dd..05dfecb4da31e00fa1cc83d346cb81dbff280ec0 100644 (file)
@@ -145,6 +145,7 @@ struct bgp
 
   /* BGP peer. */
   struct list *peer;
+  struct hash *peerhash;
 
   /* BGP peer group.  */
   struct list *group;
index b404cb78f42b3e83555fa4600be912cf4d075b2e..968b126ee2b56c92fbe31e2faf350777b3b65141 100644 (file)
@@ -808,3 +808,9 @@ sockunion_free (union sockunion *su)
 {
   XFREE (MTYPE_SOCKUNION, su);
 }
+
+void
+sockunion_init (union sockunion *su)
+{
+  memset(su, 0, sizeof(union sockunion));
+}
index e66b0b8e83d6674cc10a7b9810c80b7cbb004233..195c2fff923c5804ad7e35acf38b744c551f5fd9 100644 (file)
@@ -112,6 +112,7 @@ extern union sockunion *sockunion_getsockname (int);
 extern union sockunion *sockunion_getpeername (int);
 extern union sockunion *sockunion_dup (union sockunion *);
 extern void sockunion_free (union sockunion *);
+extern void sockunion_init (union sockunion *);
 
 #ifndef HAVE_INET_NTOP
 extern const char * inet_ntop (int family, const void *addrptr,