]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_nexthop.c
bgpd: Refactor some code for nexthop handling
[mirror_frr.git] / bgpd / bgp_nexthop.c
index 8095e6233e47eeb2a175040631805fd9c49f4777..856e6c464d357284109f08d3fda282fc4e1d1bce 100644 (file)
@@ -41,6 +41,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 #include "bgpd/bgp_nht.h"
 #include "bgpd/bgp_debug.h"
 #include "bgpd/bgp_damp.h"
+#include "bgpd/bgp_fsm.h"
 #include "zebra/rib.h"
 #include "zebra/zserv.h"       /* For ZEBRA_SERV_PATH. */
 
@@ -48,11 +49,12 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
 /* Route table for next-hop lookup cache. */
 struct bgp_table *bgp_nexthop_cache_table[AFI_MAX];
-static struct bgp_table *cache1_table[AFI_MAX];
 
 /* Route table for connected route. */
 static struct bgp_table *bgp_connected_table[AFI_MAX];
 
+/* Route table for import-check */
+struct bgp_table *bgp_import_check_table[AFI_MAX];
 
 char *
 bnc_str (struct bgp_nexthop_cache *bnc, char *buf, int size)
@@ -75,7 +77,7 @@ bnc_nexthop_free (struct bgp_nexthop_cache *bnc)
 }
 
 struct bgp_nexthop_cache *
-bnc_new ()
+bnc_new (void)
 {
   struct bgp_nexthop_cache *bnc;
 
@@ -91,45 +93,6 @@ bnc_free (struct bgp_nexthop_cache *bnc)
   XFREE (MTYPE_BGP_NEXTHOP_CACHE, bnc);
 }
 
-/* If nexthop exists on connected network return 1. */
-int
-bgp_nexthop_onlink (afi_t afi, struct attr *attr)
-{
-  struct bgp_node *rn;
-  
-  /* Lookup the address is onlink or not. */
-  if (afi == AFI_IP)
-    {
-      rn = bgp_node_match_ipv4 (bgp_connected_table[AFI_IP], &attr->nexthop);
-      if (rn)
-       {
-         bgp_unlock_node (rn);
-         return 1;
-       }
-    }
-#ifdef HAVE_IPV6
-  else if (afi == AFI_IP6)
-    {
-      if (attr->extra->mp_nexthop_len == 32)
-       return 1;
-      else if (attr->extra->mp_nexthop_len == 16)
-       {
-         if (IN6_IS_ADDR_LINKLOCAL (&attr->extra->mp_nexthop_global))
-           return 1;
-
-         rn = bgp_node_match_ipv6 (bgp_connected_table[AFI_IP6],
-                                     &attr->extra->mp_nexthop_global);
-         if (rn)
-           {
-             bgp_unlock_node (rn);
-             return 1;
-           }
-       }
-    }
-#endif /* HAVE_IPV6 */
-  return 0;
-}
-
 /* Reset and free all BGP nexthop cache. */
 static void
 bgp_nexthop_cache_reset (struct bgp_table *table)
@@ -158,7 +121,7 @@ static struct hash *bgp_address_hash;
 static void *
 bgp_address_hash_alloc (void *p)
 {
-  struct in_addr *val = p;
+  const struct in_addr *val = (const struct in_addr *)p;
   struct bgp_addr *addr;
 
   addr = XMALLOC (MTYPE_BGP_ADDR, sizeof (struct bgp_addr));
@@ -240,23 +203,17 @@ bgp_connected_add (struct connected *ifc)
 {
   struct prefix p;
   struct prefix *addr;
-  struct interface *ifp;
   struct bgp_node *rn;
   struct bgp_connected_ref *bc;
-
-  ifp = ifc->ifp;
-
-  if (! ifp)
-    return;
-
-  if (if_is_loopback (ifp))
-    return;
+  struct listnode *node, *nnode, *mnode;
+  struct bgp *bgp;
+  struct peer *peer;
 
   addr = ifc->address;
 
+  p = *(CONNECTED_PREFIX(ifc));
   if (addr->family == AF_INET)
     {
-      PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
       apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
 
       if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
@@ -276,11 +233,24 @@ bgp_connected_add (struct connected *ifc)
          bc->refcnt = 1;
          rn->info = bc;
        }
+
+      for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
+       {
+         for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+           {
+             if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0) &&
+                 !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
+               {
+                 if (peer_active(peer))
+                   BGP_EVENT_ADD (peer, BGP_Stop);
+                 BGP_EVENT_ADD (peer, BGP_Start);
+               }
+           }
+       }
     }
 #ifdef HAVE_IPV6
   else if (addr->family == AF_INET6)
     {
-      PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
       apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
 
       if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
@@ -310,20 +280,14 @@ bgp_connected_delete (struct connected *ifc)
 {
   struct prefix p;
   struct prefix *addr;
-  struct interface *ifp;
   struct bgp_node *rn;
   struct bgp_connected_ref *bc;
 
-  ifp = ifc->ifp;
-
-  if (if_is_loopback (ifp))
-    return;
-
   addr = ifc->address;
 
+  p = *(CONNECTED_PREFIX(ifc));
   if (addr->family == AF_INET)
     {
-      PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
       apply_mask_ipv4 ((struct prefix_ipv4 *) &p);
 
       if (prefix_ipv4_any ((struct prefix_ipv4 *) &p))
@@ -348,7 +312,6 @@ bgp_connected_delete (struct connected *ifc)
 #ifdef HAVE_IPV6
   else if (addr->family == AF_INET6)
     {
-      PREFIX_COPY_IPV6(&p, CONNECTED_PREFIX(ifc));
       apply_mask_ipv6 ((struct prefix_ipv6 *) &p);
 
       if (IN6_IS_ADDR_UNSPECIFIED (&p.u.prefix6))
@@ -388,7 +351,6 @@ bgp_nexthop_self (struct attr *attr)
   return 0;
 }
 
-
 int
 bgp_multiaccess_check_v4 (struct in_addr nexthop, struct peer *peer)
 {
@@ -429,110 +391,77 @@ show_ip_bgp_nexthop_table (struct vty *vty, int detail)
 {
   struct bgp_node *rn;
   struct bgp_nexthop_cache *bnc;
-  char buf[INET6_ADDRSTRLEN];
+  char buf[PREFIX2STR_BUFFER];
   struct nexthop *nexthop;
   time_t tbuf;
-  u_char i;
+  afi_t afi;
 
   vty_out (vty, "Current BGP nexthop cache:%s", VTY_NEWLINE);
-  for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP]); rn; rn = bgp_route_next (rn))
-    if ((bnc = rn->info) != NULL)
-      {
-       if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
+  for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
+    {
+      for (rn = bgp_table_top (bgp_nexthop_cache_table[afi]); rn; rn = bgp_route_next (rn))
        {
-         vty_out (vty, " %s valid [IGP metric %d], #paths %d%s",
-                  inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN),
-                  bnc->metric, bnc->path_count, VTY_NEWLINE);
-         if (detail)
-           for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
-             switch (nexthop->type)
+         if ((bnc = rn->info) != NULL)
+           {
+             if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
                {
-               case NEXTHOP_TYPE_IPV4:
-                 vty_out (vty, "  gate %s%s",
-                          inet_ntop (AF_INET, &nexthop->gate.ipv4, buf,
-                                     INET6_ADDRSTRLEN), VTY_NEWLINE);
-                 break;
-               case NEXTHOP_TYPE_IFINDEX:
-                 vty_out (vty, "  if %s%s",
-                          ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
-                 break;
-               case NEXTHOP_TYPE_IPV4_IFINDEX:
-                 vty_out (vty, "  gate %s, if %s%s",
-                          inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
-                                    INET6_ADDRSTRLEN),
-                          ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
-                 break;
-               default:
-                 vty_out (vty, "  invalid nexthop type %u%s",
-                          nexthop->type, VTY_NEWLINE);
+                 vty_out (vty, " %s valid [IGP metric %d], #paths %d%s",
+                          inet_ntop (rn->p.family, &rn->p.u.prefix, buf, sizeof (buf)),
+                          bnc->metric, bnc->path_count, VTY_NEWLINE);
+                 if (detail)
+                   for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
+                     switch (nexthop->type)
+                       {
+                       case NEXTHOP_TYPE_IPV6:
+                         vty_out (vty, "  gate %s%s",
+                                  inet_ntop (AF_INET6, &nexthop->gate.ipv6,
+                                             buf, sizeof (buf)), VTY_NEWLINE);
+                         break;
+                       case NEXTHOP_TYPE_IPV6_IFINDEX:
+                         vty_out(vty, "  gate %s, if %s%s",
+                                 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
+                                           sizeof (buf)),
+                                 ifindex2ifname(nexthop->ifindex),
+                                 VTY_NEWLINE);
+                         break;
+                       case NEXTHOP_TYPE_IPV4:
+                         vty_out (vty, "  gate %s%s",
+                                  inet_ntop (AF_INET, &nexthop->gate.ipv4, buf,
+                                             sizeof (buf)), VTY_NEWLINE);
+                         break;
+                       case NEXTHOP_TYPE_IFINDEX:
+                         vty_out (vty, "  if %s%s",
+                                  ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
+                         break;
+                       case NEXTHOP_TYPE_IPV4_IFINDEX:
+                         vty_out (vty, "  gate %s, if %s%s",
+                                  inet_ntop(AF_INET, &nexthop->gate.ipv4, buf,
+                                            sizeof (buf)),
+                                  ifindex2ifname(nexthop->ifindex), VTY_NEWLINE);
+                         break;
+                       default:
+                         vty_out (vty, "  invalid nexthop type %u%s",
+                                  nexthop->type, VTY_NEWLINE);
+                       }
+               }
+             else
+               {
+                 vty_out (vty, " %s invalid%s",
+                          inet_ntop (rn->p.family, &rn->p.u.prefix,
+                                     buf, sizeof (buf)), VTY_NEWLINE);
+                 if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED))
+                   vty_out (vty, "  Must be Connected%s", VTY_NEWLINE);
                }
-       }
-       else
-         vty_out (vty, " %s invalid%s",
-                  inet_ntop (AF_INET, &rn->p.u.prefix4, buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
-#ifdef HAVE_CLOCK_MONOTONIC
-       tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
-       vty_out (vty, "  Last update: %s", ctime(&tbuf));
-#else
-       vty_out (vty, "  Last update: %s", ctime(&bnc->uptime));
-#endif /* HAVE_CLOCK_MONOTONIC */
-
-       vty_out(vty, "%s", VTY_NEWLINE);
-      }
-
-#ifdef HAVE_IPV6
-  {
-    for (rn = bgp_table_top (bgp_nexthop_cache_table[AFI_IP6]);
-         rn;
-         rn = bgp_route_next (rn))
-      if ((bnc = rn->info) != NULL)
-       {
-         if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID))
-         {
-           vty_out (vty, " %s valid [IGP metric %d]%s",
-                    inet_ntop (AF_INET6, &rn->p.u.prefix6, buf,
-                               INET6_ADDRSTRLEN),
-                    bnc->metric, VTY_NEWLINE);
-           if (detail)
-             for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next)
-               switch (nexthop->type)
-                 {
-                 case NEXTHOP_TYPE_IPV6:
-                   vty_out (vty, "  gate %s%s",
-                            inet_ntop (AF_INET6, &nexthop->gate.ipv6,
-                                       buf, INET6_ADDRSTRLEN), VTY_NEWLINE);
-                   break;
-                 case NEXTHOP_TYPE_IPV6_IFINDEX:
-                   vty_out(vty, "  gate %s, if %s%s",
-                           inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
-                                     INET6_ADDRSTRLEN),
-                           ifindex2ifname(nexthop->ifindex),
-                           VTY_NEWLINE);
-                   break;
-                 case NEXTHOP_TYPE_IFINDEX:
-                   vty_out (vty, "  ifidx %u%s", nexthop->ifindex,
-                            VTY_NEWLINE);
-                   break;
-                 default:
-                   vty_out (vty, "  invalid nexthop type %u%s",
-                            nexthop->type, VTY_NEWLINE);
-                 }
-         }
-         else
-           vty_out (vty, " %s invalid%s",
-                    inet_ntop (AF_INET6, &rn->p.u.prefix6, buf, INET6_ADDRSTRLEN),
-                    VTY_NEWLINE);
 #ifdef HAVE_CLOCK_MONOTONIC
-         tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
-         vty_out (vty, "  Last update: %s", ctime(&tbuf));
+             tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
+             vty_out (vty, "  Last update: %s", ctime(&tbuf));
 #else
-         vty_out (vty, "  Last update: %s", ctime(&bnc->uptime));
+             vty_out (vty, "  Last update: %s", ctime(&bnc->uptime));
 #endif /* HAVE_CLOCK_MONOTONIC */
-
-         vty_out(vty, "%s", VTY_NEWLINE);
+             vty_out(vty, "%s", VTY_NEWLINE);
+           }
        }
-  }
-#endif /* HAVE_IPV6 */
+    }
   return CMD_SUCCESS;
 }
 
@@ -561,21 +490,20 @@ DEFUN (show_ip_bgp_nexthop_detail,
 void
 bgp_scan_init (void)
 {
-  cache1_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
-  bgp_nexthop_cache_table[AFI_IP] = cache1_table[AFI_IP];
-
+  bgp_nexthop_cache_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
   bgp_connected_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
+  bgp_import_check_table[AFI_IP] = bgp_table_init (AFI_IP, SAFI_UNICAST);
 
 #ifdef HAVE_IPV6
-  cache1_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
-  bgp_nexthop_cache_table[AFI_IP6] = cache1_table[AFI_IP6];
+  bgp_nexthop_cache_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
   bgp_connected_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
+  bgp_import_check_table[AFI_IP6] = bgp_table_init (AFI_IP6, SAFI_UNICAST);
 #endif /* HAVE_IPV6 */
 
 }
 
 void
-bgp_scan_vty_init()
+bgp_scan_vty_init (void)
 {
   install_element (ENABLE_NODE, &show_ip_bgp_nexthop_cmd);
   install_element (VIEW_NODE, &show_ip_bgp_nexthop_cmd);
@@ -589,20 +517,26 @@ bgp_scan_finish (void)
   /* Only the current one needs to be reset. */
   bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP]);
 
-  bgp_table_unlock (cache1_table[AFI_IP]);
-  cache1_table[AFI_IP] = NULL;
+  bgp_table_unlock (bgp_nexthop_cache_table[AFI_IP]);
+  bgp_nexthop_cache_table[AFI_IP] = NULL;
 
   bgp_table_unlock (bgp_connected_table[AFI_IP]);
   bgp_connected_table[AFI_IP] = NULL;
 
+  bgp_table_unlock (bgp_import_check_table[AFI_IP]);
+  bgp_import_check_table[AFI_IP] = NULL;
+
 #ifdef HAVE_IPV6
   /* Only the current one needs to be reset. */
   bgp_nexthop_cache_reset (bgp_nexthop_cache_table[AFI_IP6]);
 
-  bgp_table_unlock (cache1_table[AFI_IP6]);
-  cache1_table[AFI_IP6] = NULL;
+  bgp_table_unlock (bgp_nexthop_cache_table[AFI_IP6]);
+  bgp_nexthop_cache_table[AFI_IP6] = NULL;
 
   bgp_table_unlock (bgp_connected_table[AFI_IP6]);
   bgp_connected_table[AFI_IP6] = NULL;
+
+  bgp_table_unlock (bgp_import_check_table[AFI_IP6]);
+  bgp_import_check_table[AFI_IP6] = NULL;
 #endif /* HAVE_IPV6 */
 }