]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_zebra.c
lib, bgpd: Remove 'struct fifo' from lib/zebra.h
[mirror_frr.git] / bgpd / bgp_zebra.c
index 0e831523971aa28da5f6bc9517f8dddcadcda706..c2df521e79bba4d652c3b41c338960ff54ae5bfe 100644 (file)
@@ -32,6 +32,8 @@ Boston, MA 02111-1307, USA.  */
 #include "queue.h"
 #include "memory.h"
 #include "lib/json.h"
+#include "lib/bfd.h"
+#include "filter.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_route.h"
@@ -109,8 +111,6 @@ bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length,
     vrf_id_t vrf_id)
 {
   struct prefix router_id;
-  struct listnode *node, *nnode;
-  struct bgp *bgp;
 
   zebra_router_id_update_read(zclient->ibuf,&router_id);
 
@@ -121,32 +121,7 @@ bgp_router_id_update (int command, struct zclient *zclient, zebra_size_t length,
       zlog_debug("Rx Router Id update VRF %u Id %s", vrf_id, buf);
     }
 
-  if (vrf_id == VRF_DEFAULT)
-    {
-      /* Router-id change for default VRF has to also update all views. */
-      for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
-        {
-          if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
-            continue;
-
-          bgp->router_id_zebra = router_id.u.prefix4;
-
-          if (!bgp->router_id_static.s_addr)
-            bgp_router_id_set (bgp, &router_id.u.prefix4);
-        }
-    }
-  else
-    {
-      bgp = bgp_lookup_by_vrf_id (vrf_id);
-      if (bgp)
-        {
-          bgp->router_id_zebra = router_id.u.prefix4;
-
-          if (!bgp->router_id_static.s_addr)
-            bgp_router_id_set (bgp, &router_id.u.prefix4);
-        }
-    }
-
+  bgp_router_id_zebra_bump (vrf_id, &router_id);
   return 0;
 }
 
@@ -167,6 +142,36 @@ bgp_read_import_check_update(int command, struct zclient *zclient,
   return 0;
 }
 
+/* Set or clear interface on which unnumbered neighbor is configured. This
+ * would in turn cause BGP to initiate or turn off IPv6 RAs on this
+ * interface.
+ */
+static void
+bgp_update_interface_nbrs (struct bgp *bgp, struct interface *ifp,
+                           struct interface *upd_ifp)
+{
+  struct listnode *node, *nnode;
+  struct peer *peer;
+
+  for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
+    {
+      if (peer->conf_if &&
+          (strcmp (peer->conf_if, ifp->name) == 0))
+        {
+          if (upd_ifp)
+           {
+             peer->ifp = upd_ifp;
+             bgp_zebra_initiate_radv (bgp, peer);
+           }
+          else
+           {
+             bgp_zebra_terminate_radv (bgp, peer);
+             peer->ifp = upd_ifp;
+           }
+        }
+    }
+}
+
 static void
 bgp_start_interface_nbrs (struct bgp *bgp, struct interface *ifp)
 {
@@ -222,6 +227,7 @@ bgp_nbr_connected_delete (struct bgp *bgp, struct nbr_connected *ifc, int del)
     {
       if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0))
         {
+          peer->last_reset = PEER_DOWN_NBR_ADDR_DEL;
           BGP_EVENT_ADD (peer, BGP_Stop);
         }
     }
@@ -234,76 +240,26 @@ bgp_nbr_connected_delete (struct bgp *bgp, struct nbr_connected *ifc, int del)
     }
 }
 
-/* VRF learnt from Zebra. */
-static int
-bgp_vrf_add (int command, struct zclient *zclient, zebra_size_t length,
-    vrf_id_t vrf_id)
-{
-  struct vrf *vrf;
-  struct bgp *bgp;
-
-  vrf = zebra_vrf_add_read (zclient->ibuf, vrf_id);
-  if (!vrf) // unexpected
-    return -1;
-
-  if (BGP_DEBUG (zebra, ZEBRA))
-    zlog_debug("Rx VRF add %s id %d", vrf->name, vrf_id);
-
-  bgp = bgp_lookup_by_name(vrf->name);
-  if (bgp)
-    {
-      /* We have instance configured, link to VRF and make it "up". */
-      bgp_vrf_link (bgp, vrf);
-      bgp_instance_up (bgp);
-    }
-
-  return 0;
-}
-
-/* VRF deleted by Zebra. */
-static int
-bgp_vrf_delete (int command, struct zclient *zclient, zebra_size_t length,
-    vrf_id_t vrf_id)
-{
-  struct vrf *vrf;
-  struct bgp *bgp;
-
-  /* Default VRF cannot be deleted. */
-  assert (vrf_id != VRF_DEFAULT);
-
-  vrf = zebra_vrf_state_read (zclient->ibuf, vrf_id);
-  if (!vrf) // unexpected
-    return -1;
-
-  if (BGP_DEBUG (zebra, ZEBRA))
-    zlog_debug("Rx VRF del %s id %d", vrf->name, vrf_id);
-
-  bgp = bgp_lookup_by_name(vrf->name);
-  if (bgp)
-    {
-      /* We have instance configured, unlink from VRF and make it "down". */
-      bgp_vrf_unlink (bgp, vrf);
-      bgp_instance_down (bgp);
-    }
-
-  /* Note: This is a callback, the VRF will be deleted by the caller. */
-  return 0;
-}
-
-
-
 /* Inteface addition message from zebra. */
 static int
 bgp_interface_add (int command, struct zclient *zclient, zebra_size_t length,
     vrf_id_t vrf_id)
 {
   struct interface *ifp;
+  struct bgp *bgp;
 
   ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
+  if (!ifp) // unexpected
+    return 0;
 
   if (BGP_DEBUG (zebra, ZEBRA) && ifp)
     zlog_debug("Rx Intf add VRF %u IF %s", vrf_id, ifp->name);
 
+  bgp = bgp_lookup_by_vrf_id (vrf_id);
+  if (!bgp)
+    return 0;
+
+  bgp_update_interface_nbrs (bgp, ifp, ifp);
   return 0;
 }
 
@@ -313,17 +269,23 @@ bgp_interface_delete (int command, struct zclient *zclient,
 {
   struct stream *s;
   struct interface *ifp;
+  struct bgp *bgp;
 
   s = zclient->ibuf;
   ifp = zebra_interface_state_read (s, vrf_id);
-  if (! ifp) /* This may happen if we've just unregistered for a VRF. */
+  if (!ifp) /* This may happen if we've just unregistered for a VRF. */
     return 0;
 
-  ifp->ifindex = IFINDEX_INTERNAL;
+  ifp->ifindex = IFINDEX_DELETED;
 
   if (BGP_DEBUG (zebra, ZEBRA))
     zlog_debug("Rx Intf del VRF %u IF %s", vrf_id, ifp->name);
 
+  bgp = bgp_lookup_by_vrf_id (vrf_id);
+  if (!bgp)
+    return 0;
+
+  bgp_update_interface_nbrs (bgp, ifp, NULL);
   return 0;
 }
 
@@ -398,11 +360,23 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length,
 
     for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
       {
+#if defined(HAVE_CUMULUS)
+        /* Take down directly connected EBGP peers as well as 1-hop BFD
+         * tracked (directly connected) IBGP peers.
+         */
+        if ((peer->ttl != 1) && (peer->gtsm_hops != 1) &&
+            (!peer->bfd_info || bgp_bfd_is_peer_multihop(peer)))
+#else
+        /* Take down directly connected EBGP peers */
         if ((peer->ttl != 1) && (peer->gtsm_hops != 1))
+#endif
           continue;
 
         if (ifp == peer->nexthop.ifp)
-          BGP_EVENT_ADD (peer, BGP_Stop);
+          {
+            BGP_EVENT_ADD (peer, BGP_Stop);
+            peer->last_reset = PEER_DOWN_IF_DOWN;
+          }
       }
   }
 
@@ -892,7 +866,7 @@ if_lookup_by_ipv4_exact (struct in_addr *addr, vrf_id_t vrf_id)
 
 #ifdef HAVE_IPV6
 struct interface *
-if_lookup_by_ipv6 (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id)
+if_lookup_by_ipv6 (struct in6_addr *addr, ifindex_t ifindex, vrf_id_t vrf_id)
 {
   struct listnode *ifnode;
   struct listnode *cnode;
@@ -914,7 +888,7 @@ if_lookup_by_ipv6 (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id)
          if (cp->family == AF_INET6)
            if (prefix_match (cp, (struct prefix *)&p))
              {
-               if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6.s6_addr32[0]))
+               if (IN6_IS_ADDR_LINKLOCAL(&cp->u.prefix6))
                  {
                    if (ifindex == ifp->ifindex)
                      return ifp;
@@ -928,7 +902,7 @@ if_lookup_by_ipv6 (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id)
 }
 
 struct interface *
-if_lookup_by_ipv6_exact (struct in6_addr *addr, unsigned int ifindex, vrf_id_t vrf_id)
+if_lookup_by_ipv6_exact (struct in6_addr *addr, ifindex_t ifindex, vrf_id_t vrf_id)
 {
   struct listnode *ifnode;
   struct listnode *cnode;
@@ -1048,7 +1022,7 @@ bgp_nexthop_set (union sockunion *local, union sockunion *remote,
       if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr))
        {
          if (peer->conf_if || peer->ifname)
-           ifp = if_lookup_by_index_vrf (if_nametoindex (peer->conf_if ? peer->conf_if : peer->ifname), peer->bgp->vrf_id);
+           ifp = if_lookup_by_name_vrf (peer->conf_if ? peer->conf_if : peer->ifname, peer->bgp->vrf_id);
        }
       else if (peer->update_if)
         ifp = if_lookup_by_name_vrf (peer->update_if, peer->bgp->vrf_id);
@@ -1173,12 +1147,18 @@ bgp_info_to_ipv6_nexthop (struct bgp_info *info)
   /* If both global and link-local address present. */
   if (info->attr->extra->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
     {
-      /* Workaround for Cisco's nexthop bug.  */
-      if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
-          && info->peer->su_remote->sa.sa_family == AF_INET6)
-        nexthop = &info->peer->su_remote->sin6.sin6_addr;
+      /* Check if route-map is set to prefer global over link-local */
+      if (info->attr->extra->mp_nexthop_prefer_global)
+        nexthop = &info->attr->extra->mp_nexthop_global;
       else
-        nexthop = &info->attr->extra->mp_nexthop_local;
+        {
+          /* Workaround for Cisco's nexthop bug.  */
+          if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global)
+              && info->peer->su_remote->sa.sa_family == AF_INET6)
+            nexthop = &info->peer->su_remote->sin6.sin6_addr;
+          else
+            nexthop = &info->attr->extra->mp_nexthop_local;
+        }
     }
 
   return nexthop;
@@ -1373,6 +1353,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
       api.ifindex_num = 0;
       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
       api.metric = metric;
+      api.tag = 0;
 
       if (tag)
         {
@@ -1410,7 +1391,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
   if (p->family == AF_INET6 ||
       (p->family == AF_INET && BGP_ATTR_NEXTHOP_AFI_IP6(info->attr)))
     {
-      unsigned int ifindex;
+      ifindex_t ifindex;
       struct in6_addr *nexthop;
       struct zapi_ipv6 api;
       int valid_nh_count = 0;
@@ -1522,7 +1503,7 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
           if (!ifindex)
            {
              if (mpinfo->peer->conf_if || mpinfo->peer->ifname)
-               ifindex = if_nametoindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname);
+               ifindex = ifname2ifindex (mpinfo->peer->conf_if ? mpinfo->peer->conf_if : mpinfo->peer->ifname);
              else if (mpinfo->peer->nexthop.ifp)
                ifindex = mpinfo->peer->nexthop.ifp->ifindex;
            }
@@ -1556,9 +1537,10 @@ bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp,
       api.nexthop = (struct in6_addr **)STREAM_DATA (bgp_nexthop_buf);
       SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
       api.ifindex_num = valid_nh_count;
-      api.ifindex = (unsigned int *)STREAM_DATA (bgp_ifindices_buf);
+      api.ifindex = (ifindex_t *)STREAM_DATA (bgp_ifindices_buf);
       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
       api.metric = metric;
+      api.tag = 0;
 
       if (tag)
         {
@@ -1686,6 +1668,7 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
       api.ifindex_num = 0;
       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
       api.metric = info->attr->med;
+      api.tag = 0;
 
       if ((info->attr->extra) && (info->attr->extra->tag != 0))
         {
@@ -1712,7 +1695,7 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
       struct zapi_ipv6 api;
       
       assert (info->attr->extra);
-      
+
       api.vrf_id = peer->bgp->vrf_id;
       api.flags = flags;
       api.type = ZEBRA_ROUTE_BGP;
@@ -1725,6 +1708,7 @@ bgp_zebra_withdraw (struct prefix *p, struct bgp_info *info, safi_t safi)
       api.ifindex_num = 0;
       SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
       api.metric = info->attr->med;
+      api.tag = 0;
 
       if ((info->attr->extra) && (info->attr->extra->tag != 0))
         {
@@ -1859,9 +1843,9 @@ bgp_redistribute_resend (struct bgp *bgp, afi_t afi, int type, u_short instance)
 
   /* Send distribute add message to zebra. */
   zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient, afi, type,
-                           instance, VRF_DEFAULT);
+                           instance, bgp->vrf_id);
   zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient, afi, type,
-                           instance, VRF_DEFAULT);
+                           instance, bgp->vrf_id);
 
   return 0;
 }
@@ -1897,16 +1881,30 @@ bgp_redistribute_metric_set (struct bgp *bgp, struct bgp_redist *red, afi_t afi,
   red->redist_metric_flag = 1;
   red->redist_metric = metric;
 
-  for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) {
-    for (ri = rn->info; ri; ri = ri->next) {
-      if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE && ri->type == type &&
-         ri->instance == red->instance) {
-         ri->attr->med = red->redist_metric;
-         bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
-         bgp_process(bgp, rn, afi, SAFI_UNICAST);
-      }
+  for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn))
+    {
+      for (ri = rn->info; ri; ri = ri->next)
+        {
+          if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE &&
+              ri->type == type &&
+              ri->instance == red->instance)
+            {
+              struct attr *old_attr;
+              struct attr new_attr;
+              struct attr_extra new_extra;
+
+              new_attr.extra = &new_extra;
+              bgp_attr_dup (&new_attr, ri->attr);
+              new_attr.med = red->redist_metric;
+              old_attr = ri->attr;
+              ri->attr = bgp_attr_intern (&new_attr);
+              bgp_attr_unintern (&old_attr);
+
+              bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED);
+              bgp_process(bgp, rn, afi, SAFI_UNICAST);
+            }
+        }
     }
-  }
 
   return 1;
 }
@@ -1978,6 +1976,24 @@ bgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type, u_short instance)
   return CMD_SUCCESS;
 }
 
+/* Update redistribute vrf bitmap during triggers like
+   restart networking or delete/add VRFs */
+void
+bgp_update_redist_vrf_bitmaps (struct bgp *bgp, vrf_id_t old_vrf_id)
+{
+  int i;
+  afi_t afi;
+
+  for (afi = AFI_IP; afi < AFI_MAX; afi++)
+    for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
+      if (vrf_bitmap_check (zclient->redist[afi][i], old_vrf_id))
+        {
+          vrf_bitmap_unset (zclient->redist[afi][i], old_vrf_id);
+          vrf_bitmap_set (zclient->redist[afi][i], bgp->vrf_id);
+        }
+  return;
+}
+
 void
 bgp_zclient_reset (void)
 {
@@ -1992,7 +2008,7 @@ void
 bgp_zebra_instance_register (struct bgp *bgp)
 {
   /* Don't try to register if we're not connected to Zebra */
-  if (zclient->sock < 0)
+  if (!zclient || zclient->sock < 0)
     return;
 
   if (BGP_DEBUG (zebra, ZEBRA))
@@ -2019,6 +2035,34 @@ bgp_zebra_instance_deregister (struct bgp *bgp)
   zclient_send_dereg_requests (zclient, bgp->vrf_id);
 }
 
+void
+bgp_zebra_initiate_radv (struct bgp *bgp, struct peer *peer)
+{
+  int ra_interval = BGP_UNNUM_DEFAULT_RA_INTERVAL;
+
+  /* Don't try to initiate if we're not connected to Zebra */
+  if (zclient->sock < 0)
+    return;
+
+  if (BGP_DEBUG (zebra, ZEBRA))
+    zlog_debug("%u: Initiating RA for peer %s", bgp->vrf_id, peer->host);
+
+  zclient_send_interface_radv_req (zclient, bgp->vrf_id, peer->ifp, 1, ra_interval);
+}
+
+void
+bgp_zebra_terminate_radv (struct bgp *bgp, struct peer *peer)
+{
+  /* Don't try to terminate if we're not connected to Zebra */
+  if (zclient->sock < 0)
+    return;
+
+  if (BGP_DEBUG (zebra, ZEBRA))
+    zlog_debug("%u: Terminating RA for peer %s", bgp->vrf_id, peer->host);
+
+  zclient_send_interface_radv_req (zclient, bgp->vrf_id, peer->ifp, 0, 0);
+}
+
 /* BGP has established connection with Zebra. */
 static void
 bgp_zebra_connected (struct zclient *zclient)
@@ -2035,6 +2079,9 @@ bgp_zebra_connected (struct zclient *zclient)
 
   bgp_zebra_instance_register (bgp);
 
+  /* Send the client registration */
+  bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
+
   /* TODO - What if we have peers and networks configured, do we have to
    * kick-start them?
    */
@@ -2049,8 +2096,6 @@ bgp_zebra_init (struct thread_master *master)
   zclient_init (zclient, ZEBRA_ROUTE_BGP, 0);
   zclient->zebra_connected = bgp_zebra_connected;
   zclient->router_id_update = bgp_router_id_update;
-  zclient->vrf_add = bgp_vrf_add;
-  zclient->vrf_delete = bgp_vrf_delete;
   zclient->interface_add = bgp_interface_add;
   zclient->interface_delete = bgp_interface_delete;
   zclient->interface_address_add = bgp_interface_address_add;
@@ -2064,15 +2109,23 @@ bgp_zebra_init (struct thread_master *master)
   zclient->redistribute_route_ipv4_del = zebra_read_ipv4;
   zclient->interface_up = bgp_interface_up;
   zclient->interface_down = bgp_interface_down;
-#ifdef HAVE_IPV6
   zclient->ipv6_route_add = zebra_read_ipv6;
   zclient->ipv6_route_delete = zebra_read_ipv6;
   zclient->redistribute_route_ipv6_add = zebra_read_ipv6;
   zclient->redistribute_route_ipv6_del = zebra_read_ipv6;
-#endif /* HAVE_IPV6 */
   zclient->nexthop_update = bgp_read_nexthop_update;
   zclient->import_check_update = bgp_read_import_check_update;
 
   bgp_nexthop_buf = stream_new(BGP_NEXTHOP_BUF_SIZE);
   bgp_ifindices_buf = stream_new(BGP_IFINDICES_BUF_SIZE);
 }
+
+void
+bgp_zebra_destroy(void)
+{
+  if (zclient == NULL)
+    return;
+  zclient_stop(zclient);
+  zclient_free(zclient);
+  zclient = NULL;
+}