]> git.proxmox.com Git - mirror_frr.git/blobdiff - isisd/isis_zebra.c
quagga: delete interface from default table when moved to vrf
[mirror_frr.git] / isisd / isis_zebra.c
index bcd00184e5b6612f9799b5a87cde50631f92b361..d8bfafbe54619137fea526f54a8c567d6e45ab2e 100644 (file)
 #include "zclient.h"
 #include "stream.h"
 #include "linklist.h"
+#include "vrf.h"
 
+#include "isisd/dict.h"
 #include "isisd/isis_constants.h"
 #include "isisd/isis_common.h"
+#include "isisd/isis_flags.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_tlv.h"
+#include "isisd/isisd.h"
 #include "isisd/isis_circuit.h"
 #include "isisd/isis_csm.h"
+#include "isisd/isis_lsp.h"
 #include "isisd/isis_route.h"
 #include "isisd/isis_zebra.h"
 
 struct zclient *zclient = NULL;
 
-extern struct thread_master *master;
-struct in_addr router_id_zebra;
-
 /* Router-id update message from zebra. */
-int
+static int
 isis_router_id_update_zebra (int command, struct zclient *zclient,
-                            zebra_size_t length)
+                            zebra_size_t length, vrf_id_t vrf_id)
 {
+  struct isis_area *area;
+  struct listnode *node;
   struct prefix router_id;
 
-  zebra_router_id_update_read (zclient->ibuf,&router_id);
-  router_id_zebra = router_id.u.prefix4;
+  zebra_router_id_update_read (zclient->ibuf, &router_id);
+  if (isis->router_id == router_id.u.prefix4.s_addr)
+    return 0;
+
+  isis->router_id = router_id.u.prefix4.s_addr;
+  for (ALL_LIST_ELEMENTS_RO (isis->area_list, node, area))
+    if (listcount (area->area_addrs) > 0)
+      lsp_regenerate_schedule (area, area->is_type, 0);
 
-  /* FIXME: Do we react somehow? */
   return 0;
 }
 
-int
-isis_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length)
+static int
+isis_zebra_if_add (int command, struct zclient *zclient, zebra_size_t length,
+    vrf_id_t vrf_id)
 {
   struct interface *ifp;
 
-  ifp = zebra_interface_add_read (zclient->ibuf);
+  ifp = zebra_interface_add_read (zclient->ibuf, vrf_id);
 
+  if (isis->debugs & DEBUG_ZEBRA)
+    zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
+               ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
 
-  zlog_debug ("Zebra I/F add: %s index %d flags %ld metric %d mtu %d",
-             ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
-
-  if (if_is_up (ifp))
+  if (if_is_operative (ifp))
     isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
 
   return 0;
 }
 
-int
-isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length)
+static int
+isis_zebra_if_del (int command, struct zclient *zclient, zebra_size_t length,
+    vrf_id_t vrf_id)
 {
   struct interface *ifp;
   struct stream *s;
 
   s = zclient->ibuf;
-  ifp = zebra_interface_state_read (s);
+  ifp = zebra_interface_state_read (s, vrf_id);
 
   if (!ifp)
     return 0;
 
-  if (if_is_up (ifp))
+  if (if_is_operative (ifp))
     zlog_warn ("Zebra: got delete of %s, but interface is still up",
               ifp->name);
 
-  zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
-             ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);
-
-  if_delete (ifp);
+  if (isis->debugs & DEBUG_ZEBRA)
+    zlog_debug ("Zebra I/F delete: %s index %d flags %ld metric %d mtu %d",
+               ifp->name, ifp->ifindex, (long)ifp->flags, ifp->metric, ifp->mtu);
 
   isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
 
-  return 0;
-}
-
-struct interface *
-zebra_interface_if_lookup (struct stream *s)
-{
-  struct interface *ifp;
-  u_char ifname_tmp[INTERFACE_NAMSIZ];
+  /* Cannot call if_delete because we should retain the pseudo interface
+     in case there is configuration info attached to it. */
+  if_delete_retain(ifp);
 
-  /* Read interface name. */
-  stream_get (ifname_tmp, s, INTERFACE_NAMSIZ);
+  ifp->ifindex = IFINDEX_DELETED;
 
-  /* Lookup this by interface index. */
-  ifp = if_lookup_by_name ((char *) ifname_tmp);
-
-  /* If such interface does not exist, indicate an error */
-  if (!ifp)
-    return NULL;
-
-  return ifp;
+  return 0;
 }
 
-int
+static int
 isis_zebra_if_state_up (int command, struct zclient *zclient,
-                       zebra_size_t length)
+                       zebra_size_t length, vrf_id_t vrf_id)
 {
   struct interface *ifp;
 
-  ifp = zebra_interface_if_lookup (zclient->ibuf);
+  ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
 
-  if (!ifp)
+  if (ifp == NULL)
     return 0;
 
-  if (if_is_up (ifp))
-    {
-      zebra_interface_if_set_value (zclient->ibuf, ifp);
-      /* HT: This is wrong actually. We can't assume that circuit exist
-       * if we delete circuit during if_state_down event. Needs rethink.
-       * TODO */
-      isis_circuit_update_params (circuit_scan_by_ifp (ifp), ifp);
-      return 0;
-    }
-
-  zebra_interface_if_set_value (zclient->ibuf, ifp);
   isis_csm_state_change (IF_UP_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
 
   return 0;
 }
 
-int
+static int
 isis_zebra_if_state_down (int command, struct zclient *zclient,
-                         zebra_size_t length)
+                         zebra_size_t length, vrf_id_t vrf_id)
 {
   struct interface *ifp;
+  struct isis_circuit *circuit;
 
-  ifp = zebra_interface_if_lookup (zclient->ibuf);
+  ifp = zebra_interface_state_read (zclient->ibuf, vrf_id);
 
   if (ifp == NULL)
     return 0;
 
-  if (if_is_up (ifp))
-    {
-      zebra_interface_if_set_value (zclient->ibuf, ifp);
-      isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp), ifp);
-    }
+  circuit = isis_csm_state_change (IF_DOWN_FROM_Z, circuit_scan_by_ifp (ifp),
+                                   ifp);
+  if (circuit)
+    SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
 
   return 0;
 }
 
-int
+static int
 isis_zebra_if_address_add (int command, struct zclient *zclient,
-                          zebra_size_t length)
+                          zebra_size_t length, vrf_id_t vrf_id)
 {
   struct connected *c;
   struct prefix *p;
-  char buf[BUFSIZ];
+  char buf[PREFIX2STR_BUFFER];
 
   c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_ADD,
-                                   zclient->ibuf);
+                                   zclient->ibuf, vrf_id);
 
   if (c == NULL)
     return 0;
 
   p = c->address;
 
-  prefix2str (p, buf, BUFSIZ);
+  prefix2str (p, buf, sizeof (buf));
 #ifdef EXTREME_DEBUG
   if (p->family == AF_INET)
     zlog_debug ("connected IP address %s", buf);
@@ -193,24 +182,25 @@ isis_zebra_if_address_add (int command, struct zclient *zclient,
     zlog_debug ("connected IPv6 address %s", buf);
 #endif /* HAVE_IPV6 */
 #endif /* EXTREME_DEBUG */
-  isis_circuit_add_addr (circuit_scan_by_ifp (c->ifp), c);
+  if (if_is_operative (c->ifp))
+    isis_circuit_add_addr (circuit_scan_by_ifp (c->ifp), c);
 
   return 0;
 }
 
-int
+static int
 isis_zebra_if_address_del (int command, struct zclient *client,
-                          zebra_size_t length)
+                          zebra_size_t length, vrf_id_t vrf_id)
 {
   struct connected *c;
   struct interface *ifp;
 #ifdef EXTREME_DEBUG
   struct prefix *p;
-  u_char buf[BUFSIZ];
+  char buf[PREFIX2STR_BUFFER];
 #endif /* EXTREME_DEBUG */
 
   c = zebra_interface_address_read (ZEBRA_INTERFACE_ADDRESS_DELETE,
-                                   zclient->ibuf);
+                                   zclient->ibuf, vrf_id);
 
   if (c == NULL)
     return 0;
@@ -219,7 +209,7 @@ isis_zebra_if_address_del (int command, struct zclient *client,
 
 #ifdef EXTREME_DEBUG
   p = c->address;
-  prefix2str (p, buf, BUFSIZ);
+  prefix2str (p, buf, sizeof (buf));
 
   if (p->family == AF_INET)
     zlog_debug ("disconnected IP address %s", buf);
@@ -229,13 +219,14 @@ isis_zebra_if_address_del (int command, struct zclient *client,
 #endif /* HAVE_IPV6 */
 #endif /* EXTREME_DEBUG */
 
-  isis_circuit_del_addr (circuit_scan_by_ifp (ifp), c);
+  if (if_is_operative (ifp))
+    isis_circuit_del_addr (circuit_scan_by_ifp (ifp), c);
   connected_free (c);
 
   return 0;
 }
 
-void
+static void
 isis_zebra_route_add_ipv4 (struct prefix *prefix,
                           struct isis_route_info *route_info)
 {
@@ -245,10 +236,10 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix,
   struct isis_nexthop *nexthop;
   struct listnode *node;
 
-  if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
+  if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
     return;
 
-  if (zclient->redist[ZEBRA_ROUTE_ISIS])
+  if (vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], VRF_DEFAULT))
     {
       message = 0;
       flags = 0;
@@ -261,16 +252,17 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix,
 
       stream = zclient->obuf;
       stream_reset (stream);
-      /* Length place holder. */
-      stream_putw (stream, 0);
-      /* command */
-      stream_putc (stream, ZEBRA_IPV4_ROUTE_ADD);
+      zclient_create_header (stream, ZEBRA_IPV4_ROUTE_ADD, VRF_DEFAULT);
       /* type */
       stream_putc (stream, ZEBRA_ROUTE_ISIS);
+      /* instance */
+      stream_putw (stream, 0);
       /* flags */
       stream_putc (stream, flags);
       /* message */
       stream_putc (stream, message);
+      /* SAFI */
+      stream_putw (stream, SAFI_UNICAST);
       /* prefix information */
       psize = PSIZE (prefix->prefixlen);
       stream_putc (stream, prefix->prefixlen);
@@ -279,9 +271,8 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix,
       stream_putc (stream, listcount (route_info->nexthops));
 
       /* Nexthop, ifindex, distance and metric information */
-      for (node = listhead (route_info->nexthops); node; nextnode (node))
+      for (ALL_LIST_ELEMENTS_RO (route_info->nexthops, node, nexthop))
        {
-         nexthop = getdata (node);
          /* FIXME: can it be ? */
          if (nexthop->ip.s_addr != INADDR_ANY)
            {
@@ -302,33 +293,39 @@ isis_zebra_route_add_ipv4 (struct prefix *prefix,
        stream_putl (stream, route_info->cost);
 
       stream_putw_at (stream, 0, stream_get_endp (stream));
-      writen (zclient->sock, stream->data, stream_get_endp (stream));
+      zclient_send_message(zclient);
+      SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
+      UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
     }
 }
 
-void
+static void
 isis_zebra_route_del_ipv4 (struct prefix *prefix,
                           struct isis_route_info *route_info)
 {
   struct zapi_ipv4 api;
   struct prefix_ipv4 prefix4;
 
-  if (zclient->redist[ZEBRA_ROUTE_ISIS])
+  if (vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], VRF_DEFAULT))
     {
+      api.vrf_id = VRF_DEFAULT;
       api.type = ZEBRA_ROUTE_ISIS;
+      api.instance = 0;
       api.flags = 0;
       api.message = 0;
+      api.safi = SAFI_UNICAST;
       prefix4.family = AF_INET;
       prefix4.prefixlen = prefix->prefixlen;
       prefix4.prefix = prefix->u.prefix4;
       zapi_ipv4_route (ZEBRA_IPV4_ROUTE_DELETE, zclient, &prefix4, &api);
     }
+  UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
 
   return;
 }
 
 #ifdef HAVE_IPV6
-void
+static void
 isis_zebra_route_add_ipv6 (struct prefix *prefix,
                           struct isis_route_info *route_info)
 {
@@ -340,12 +337,15 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix,
   struct listnode *node;
   struct prefix_ipv6 prefix6;
 
-  if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
+  if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
     return;
 
+  api.vrf_id = VRF_DEFAULT;
   api.type = ZEBRA_ROUTE_ISIS;
+  api.instance = 0;
   api.flags = 0;
   api.message = 0;
+  api.safi = SAFI_UNICAST;
   SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
   SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
   SET_FLAG (api.message, ZAPI_MESSAGE_METRIC);
@@ -378,10 +378,8 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix,
 
   /* for each nexthop */
   i = 0;
-  for (node = listhead (route_info->nexthops6); node; nextnode (node))
+  for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
     {
-      nexthop6 = getdata (node);
-
       if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
          !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
        {
@@ -404,7 +402,8 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix,
       prefix6.prefixlen = prefix->prefixlen;
       memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
       zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, &prefix6, &api);
-      SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
+      SET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
+      UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_RESYNC);
     }
 
   XFREE (MTYPE_ISIS_TMP, nexthop_list);
@@ -413,7 +412,7 @@ isis_zebra_route_add_ipv6 (struct prefix *prefix,
   return;
 }
 
-void
+static void
 isis_zebra_route_del_ipv6 (struct prefix *prefix,
                           struct isis_route_info *route_info)
 {
@@ -425,12 +424,15 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix,
   struct listnode *node;
   struct prefix_ipv6 prefix6;
 
-  if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC))
+  if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED))
     return;
 
+  api.vrf_id = VRF_DEFAULT;
   api.type = ZEBRA_ROUTE_ISIS;
+  api.instance = 0;
   api.flags = 0;
   api.message = 0;
+  api.safi = SAFI_UNICAST;
   SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP);
   SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX);
   api.nexthop_num = listcount (route_info->nexthops6);
@@ -457,10 +459,8 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix,
 
   /* for each nexthop */
   i = 0;
-  for (node = listhead (route_info->nexthops6); node; nextnode (node))
+  for (ALL_LIST_ELEMENTS_RO (route_info->nexthops6, node, nexthop6))
     {
-      nexthop6 = getdata (node);
-
       if (!IN6_IS_ADDR_LINKLOCAL (&nexthop6->ip6) &&
          !IN6_IS_ADDR_UNSPECIFIED (&nexthop6->ip6))
        {
@@ -483,7 +483,7 @@ isis_zebra_route_del_ipv6 (struct prefix *prefix,
       prefix6.prefixlen = prefix->prefixlen;
       memcpy (&prefix6.prefix, &prefix->u.prefix6, sizeof (struct in6_addr));
       zapi_ipv6_route (ZEBRA_IPV6_ROUTE_DELETE, zclient, &prefix6, &api);
-      UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNC);
+      UNSET_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ZEBRA_SYNCED);
     }
 
   XFREE (MTYPE_ISIS_TMP, nexthop_list);
@@ -499,7 +499,8 @@ isis_zebra_route_update (struct prefix *prefix,
   if (zclient->sock < 0)
     return;
 
-  if (!zclient->redist[ZEBRA_ROUTE_ISIS])
+  if ((prefix->family == AF_INET && !vrf_bitmap_check (zclient->redist[AFI_IP][ZEBRA_ROUTE_ISIS], VRF_DEFAULT)) ||
+      (prefix->family == AF_INET6 && !vrf_bitmap_check (zclient->redist[AFI_IP6][ZEBRA_ROUTE_ISIS], VRF_DEFAULT)))
     return;
 
   if (CHECK_FLAG (route_info->flag, ISIS_ROUTE_FLAG_ACTIVE))
@@ -523,21 +524,19 @@ isis_zebra_route_update (struct prefix *prefix,
   return;
 }
 
-int
+static int
 isis_zebra_read_ipv4 (int command, struct zclient *zclient,
-                     zebra_size_t length)
+                     zebra_size_t length, vrf_id_t vrf_id)
 {
   struct stream *stream;
   struct zapi_ipv4 api;
   struct prefix_ipv4 p;
-  unsigned long ifindex;
-  struct in_addr nexthop;
 
   stream = zclient->ibuf;
   memset (&p, 0, sizeof (struct prefix_ipv4));
-  ifindex = 0;
 
   api.type = stream_getc (stream);
+  api.instance = stream_getw (stream);
   api.flags = stream_getc (stream);
   api.message = stream_getc (stream);
 
@@ -548,12 +547,12 @@ isis_zebra_read_ipv4 (int command, struct zclient *zclient,
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP))
     {
       api.nexthop_num = stream_getc (stream);
-      nexthop.s_addr = stream_get_ipv4 (stream);
+      (void)stream_get_ipv4 (stream);
     }
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX))
     {
       api.ifindex_num = stream_getc (stream);
-      ifindex = stream_getl (stream);
+      stream_getl (stream);
     }
   if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE))
     api.distance = stream_getc (stream);
@@ -562,23 +561,29 @@ isis_zebra_read_ipv4 (int command, struct zclient *zclient,
   else
     api.metric = 0;
 
-  if (command == ZEBRA_IPV4_ROUTE_ADD)
+  if (command == ZEBRA_REDISTRIBUTE_IPV4_ADD)
     {
-      zlog_debug ("IPv4 Route add from Z");
+      if (isis->debugs & DEBUG_ZEBRA)
+       zlog_debug ("IPv4 Route add from Z");
     }
 
   return 0;
 }
 
-int
+#ifdef HAVE_IPV6
+static int
 isis_zebra_read_ipv6 (int command, struct zclient *zclient,
-                     zebra_size_t length)
+                     zebra_size_t length, vrf_id_t vrf_id)
 {
   return 0;
 }
+#endif
 
 #define ISIS_TYPE_IS_REDISTRIBUTED(T) \
-T == ZEBRA_ROUTE_MAX ? zclient->default_information : zclient->redist[type]
+T == ZEBRA_ROUTE_MAX ? \
+  vrf_bitmap_check (zclient->default_information, VRF_DEFAULT) : \
+  (vrf_bitmap_check (zclient->redist[AFI_IP][type], VRF_DEFAULT) || \
+   vrf_bitmap_check (zclient->redist[AFI_IP6][type], VRF_DEFAULT)
 
 int
 isis_distribute_list_update (int routetype)
@@ -586,18 +591,27 @@ isis_distribute_list_update (int routetype)
   return 0;
 }
 
-int
+#if 0 /* Not yet. */
+static int
 isis_redistribute_default_set (int routetype, int metric_type,
                               int metric_value)
 {
   return 0;
 }
+#endif /* 0 */
+
+static void
+isis_zebra_connected (struct zclient *zclient)
+{
+  zclient_send_reg_requests (zclient, VRF_DEFAULT);
+}
 
 void
-isis_zebra_init ()
+isis_zebra_init (struct thread_master *master)
 {
-  zclient = zclient_new ();
-  zclient_init (zclient, ZEBRA_ROUTE_ISIS);
+  zclient = zclient_new (master);
+  zclient_init (zclient, ZEBRA_ROUTE_ISIS, 0);
+  zclient->zebra_connected = isis_zebra_connected;
   zclient->router_id_update = isis_router_id_update_zebra;
   zclient->interface_add = isis_zebra_if_add;
   zclient->interface_delete = isis_zebra_if_del;
@@ -607,20 +621,14 @@ isis_zebra_init ()
   zclient->interface_address_delete = isis_zebra_if_address_del;
   zclient->ipv4_route_add = isis_zebra_read_ipv4;
   zclient->ipv4_route_delete = isis_zebra_read_ipv4;
+  zclient->redistribute_route_ipv4_add = isis_zebra_read_ipv4;
+  zclient->redistribute_route_ipv4_del = isis_zebra_read_ipv4;
 #ifdef HAVE_IPV6
   zclient->ipv6_route_add = isis_zebra_read_ipv6;
   zclient->ipv6_route_delete = isis_zebra_read_ipv6;
+  zclient->redistribute_route_ipv6_add = isis_zebra_read_ipv6;
+  zclient->redistribute_route_ipv6_del = isis_zebra_read_ipv6;
 #endif /* HAVE_IPV6 */
 
   return;
 }
-
-void
-isis_zebra_finish ()
-{
-  zclient_stop (zclient);
-  zclient_free (zclient);
-  zclient = (struct zclient *) NULL;
-
-  return;
-}