]> git.puffer.fish Git - mirror/frr.git/commitdiff
Quagga: Implement VRF change semantics for an interface
authorvivek <vivek@cumulusnetworks.com>
Thu, 25 Feb 2016 19:30:53 +0000 (19:30 +0000)
committervivek <vivek@cumulusnetworks.com>
Thu, 25 Feb 2016 19:30:53 +0000 (19:30 +0000)
Implement VRF change semantics for an interface to be invoked
when an interface is moved from one VRF (e.g., the Default) to
another. This includes the message definition as well as updating,
deleting or adding the interface from clients, depending on their
interest in the VRFs (old and new). Also handle replay of the
addresses on the interface upon VRF change, if required.

Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com>
Reviewed-by: Don Slice <dslice@cumulusnetworks.com>
Ticket: CM-9527
Reviewed By: CCR-4174
Testing Done: Manual tests of various scenarios

lib/log.c
lib/zclient.c
lib/zclient.h
lib/zebra.h
zebra/interface.c
zebra/interface.h
zebra/redistribute.c
zebra/redistribute.h
zebra/redistribute_null.c
zebra/zserv.c
zebra/zserv.h

index ad610050f8ce71b191f31eca9b8042e1a44aae79..fefc0db5260f33872b7675537f2a6b65b7b204c5 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -874,7 +874,8 @@ static const struct zebra_desc_table command_types[] = {
   DESC_ENTRY    (ZEBRA_REDISTRIBUTE_IPV4_ADD),
   DESC_ENTRY    (ZEBRA_REDISTRIBUTE_IPV4_DEL),
   DESC_ENTRY    (ZEBRA_REDISTRIBUTE_IPV6_ADD),
-  DESC_ENTRY    (ZEBRA_REDISTRIBUTE_IPV6_DEL)
+  DESC_ENTRY    (ZEBRA_REDISTRIBUTE_IPV6_DEL),
+  DESC_ENTRY    (ZEBRA_INTERFACE_VRF_UPDATE)
 };
 #undef DESC_ENTRY
 
index 82f0c26e592eac6524fe7be757bfaabb134b5c79..655eda8176b3eadcaf406c1a8d046aef41e3ffdb 100644 (file)
@@ -1211,6 +1211,33 @@ zebra_interface_nbr_address_read (int type, struct stream *s, vrf_id_t vrf_id)
   return ifc;
 }
 
+struct interface *
+zebra_interface_vrf_update_read (struct stream *s, vrf_id_t vrf_id,
+                                 vrf_id_t *new_vrf_id)
+{
+  unsigned int ifindex;
+  struct interface *ifp;
+  vrf_id_t new_id = VRF_DEFAULT;
+
+  /* Get interface index. */
+  ifindex = stream_getl (s);
+
+  /* Lookup interface. */
+  ifp = if_lookup_by_index_vrf (ifindex, vrf_id);
+  if (ifp == NULL)
+    {
+      zlog_warn ("INTERFACE_VRF_UPDATE: Cannot find IF %u in VRF %d",
+                 ifindex, vrf_id);
+      return NULL;
+    }
+
+  /* Fetch new VRF Id. */
+  new_id = stream_getw (s);
+
+  *new_vrf_id = new_id;
+  return ifp;
+}
+
 /* Zebra client message read function. */
 static int
 zclient_read (struct thread *thread)
@@ -1357,6 +1384,10 @@ zclient_read (struct thread *thread)
       if (zclient->interface_down)
        (*zclient->interface_down) (command, zclient, length, vrf_id);
       break;
+    case ZEBRA_INTERFACE_VRF_UPDATE:
+      if (zclient->interface_vrf_update)
+       (*zclient->interface_vrf_update) (command, zclient, length, vrf_id);
+      break;
     case ZEBRA_IPV4_ROUTE_ADD:
       if (zclient->ipv4_route_add)
        (*zclient->ipv4_route_add) (command, zclient, length, vrf_id);
index e58870828b81d5a56803d887a01a2cbe74c6424b..49f73b3e9bd12a3b4b64ece5a46fd151d75470c4 100644 (file)
@@ -98,6 +98,7 @@ struct zclient
   int (*interface_bfd_dest_update) (int, struct zclient *, uint16_t, vrf_id_t);
   int (*interface_nbr_address_add) (int, struct zclient *, uint16_t, vrf_id_t);
   int (*interface_nbr_address_delete) (int, struct zclient *, uint16_t, vrf_id_t);
+  int (*interface_vrf_update) (int, struct zclient *, uint16_t, vrf_id_t);
   int (*ipv4_route_add) (int, struct zclient *, uint16_t, vrf_id_t);
   int (*ipv4_route_delete) (int, struct zclient *, uint16_t, vrf_id_t);
   int (*ipv6_route_add) (int, struct zclient *, uint16_t, vrf_id_t);
@@ -200,6 +201,8 @@ extern struct interface *zebra_interface_add_read (struct stream *, vrf_id_t);
 extern struct interface *zebra_interface_state_read (struct stream *s, vrf_id_t);
 extern struct connected *zebra_interface_address_read (int, struct stream *, vrf_id_t);
 extern struct nbr_connected *zebra_interface_nbr_address_read (int, struct stream *, vrf_id_t);
+extern struct interface * zebra_interface_vrf_update_read (struct stream *s, vrf_id_t vrf_id,
+                            vrf_id_t *new_vrf_id);
 extern void zebra_interface_if_set_value (struct stream *, struct interface *);
 extern void zebra_router_id_update_read (struct stream *s, struct prefix *rid);
 extern int zapi_ipv4_route (u_char, struct zclient *, struct prefix_ipv4 *, 
index 3d38a4c5cb272e7c4967c56ebf029bdca2bc5cc5..2945f15194853bfd6974c621f45ec9b4f7f8e6a8 100644 (file)
@@ -445,7 +445,8 @@ struct in_pktinfo
 #define ZEBRA_VRF_UNREGISTER              42
 #define ZEBRA_VRF_ADD                     43
 #define ZEBRA_VRF_DELETE                  44
-#define ZEBRA_MESSAGE_MAX                 45
+#define ZEBRA_INTERFACE_VRF_UPDATE        45
+#define ZEBRA_MESSAGE_MAX                 46
 
 /* Marker value used in new Zserv, in the byte location corresponding
  * the command value in the old zserv header. To allow old and new
index 7b19379910f87b7ef296e507d57c60a06723cfe8..5a47f60fa08acf4716f1137c3d98d79072213c45 100644 (file)
@@ -54,6 +54,8 @@
 const char *rtadv_pref_strs[] = { "medium", "high", "INVALID", "low", 0 };
 #endif /* HAVE_RTADV */
 
+static void if_down_del_nbr_connected (struct interface *ifp);
+
 struct zebra_ns *dzns;
 
 /* Called when new interface is added. */
@@ -482,32 +484,64 @@ if_add_update (struct interface *ifp)
     }
 }
 
-/* Handle an interface delete event */
-void 
-if_delete_update (struct interface *ifp)
+/* Install connected routes corresponding to an interface. */
+static void
+if_install_connected (struct interface *ifp)
 {
+  struct listnode *node;
+  struct listnode *next;
   struct connected *ifc;
   struct prefix *p;
-  struct route_node *rn;
-  struct zebra_if *zebra_if;
 
-  zebra_if = ifp->info;
+  if (ifp->connected)
+    {
+      for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
+       {
+         p = ifc->address;
 
-  if (if_is_up(ifp))
+         if (p->family == AF_INET)
+           connected_up_ipv4 (ifp, ifc);
+         else if (p->family == AF_INET6)
+           connected_up_ipv6 (ifp, ifc);
+       }
+    }
+}
+
+/* Uninstall connected routes corresponding to an interface. */
+static void
+if_uninstall_connected (struct interface *ifp)
+{
+  struct listnode *node;
+  struct listnode *next;
+  struct connected *ifc;
+  struct prefix *p;
+
+  if (ifp->connected)
     {
-      zlog_err ("interface %s vrf %u index %d is still up while being deleted.",
-                ifp->name, ifp->vrf_id, ifp->ifindex);
-      return;
+      for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
+       {
+         p = ifc->address;
+
+         if (p->family == AF_INET)
+           connected_down_ipv4 (ifp, ifc);
+         else if (p->family == AF_INET6)
+           connected_down_ipv6 (ifp, ifc);
+       }
     }
+}
 
-  /* Mark interface as inactive */
-  UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
-  
-  if (IS_ZEBRA_DEBUG_KERNEL)
-    zlog_debug ("interface %s vrf %u index %d is now inactive.",
-                ifp->name, ifp->vrf_id, ifp->ifindex);
+/* Uninstall and delete connected routes corresponding to an interface. */
+/* TODO - Check why IPv4 handling here is different from install or if_down */
+static void
+if_delete_connected (struct interface *ifp)
+{
+  struct connected *ifc;
+  struct prefix *p;
+  struct route_node *rn;
+  struct zebra_if *zebra_if;
+
+  zebra_if = ifp->info;
 
-  /* Delete connected routes from the kernel. */
   if (ifp->connected)
     {
       struct listnode *node;
@@ -571,7 +605,6 @@ if_delete_update (struct interface *ifp)
              rn->info = NULL;
              route_unlock_node (rn);
            }
-#ifdef HAVE_IPV6
          else if (p->family == AF_INET6)
            {
              connected_down_ipv6 (ifp, ifc);
@@ -589,13 +622,36 @@ if_delete_update (struct interface *ifp)
                  connected_free (ifc);
                }
            }
-#endif /* HAVE_IPV6 */
          else
            {
              last = node;
            }
        }
     }
+}
+
+/* Handle an interface delete event */
+void
+if_delete_update (struct interface *ifp)
+{
+  if (if_is_up(ifp))
+    {
+      zlog_err ("interface %s vrf %u index %d is still up while being deleted.",
+                ifp->name, ifp->vrf_id, ifp->ifindex);
+      return;
+    }
+
+  /* Mark interface as inactive */
+  UNSET_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE);
+
+  if (IS_ZEBRA_DEBUG_KERNEL)
+    zlog_debug ("interface %s vrf %u index %d is now inactive.",
+                ifp->name, ifp->vrf_id, ifp->ifindex);
+
+  /* Delete connected routes from the kernel. */
+  if_delete_connected (ifp);
+
+  /* Send out notification on interface delete. */
   zebra_interface_delete_update (ifp);
 
   if_unlink_per_ns(ifp);
@@ -608,6 +664,55 @@ if_delete_update (struct interface *ifp)
   ifp->ifindex = IFINDEX_INTERNAL;
 }
 
+/* VRF change for an interface */
+void
+if_handle_vrf_change (struct interface *ifp, vrf_id_t vrf_id)
+{
+  vrf_id_t old_vrf_id;
+
+  old_vrf_id = ifp->vrf_id;
+
+  /* Uninstall connected routes. */
+  if_uninstall_connected (ifp);
+
+  /* Delete any IPv4 neighbors created to implement RFC 5549 */
+  if_nbr_ipv6ll_to_ipv4ll_neigh_del_all (ifp);
+
+  /* Delete all neighbor addresses learnt through IPv6 RA */
+  if_down_del_nbr_connected (ifp);
+
+  /* Suppress RAs on this interface, if enabled. */
+  ipv6_nd_suppress_ra_set (ifp, RA_SUPPRESS);
+
+  /* Send out notification on interface VRF change. */
+  /* This is to issue an UPDATE or a DELETE, as appropriate. */
+  zebra_interface_vrf_update_del (ifp, vrf_id);
+
+  /* update VRF */
+  if_update_vrf (ifp, ifp->name, strlen (ifp->name), vrf_id);
+
+  /* Send out notification on interface VRF change. */
+  /* This is to issue an ADD, if needed. */
+  zebra_interface_vrf_update_add (ifp, old_vrf_id);
+
+  /* Install connected routes (in new VRF). */
+  if_install_connected (ifp);
+
+  /* Enable RAs on this interface, if IPv6 addresses are present. */
+  if (ipv6_address_configured(ifp))
+    ipv6_nd_suppress_ra_set (ifp, RA_ENABLE);
+
+  /* Due to connected route change, schedule RIB processing for both old
+   * and new VRF.
+   */
+  if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+    zlog_debug ("%u: IF %s VRF change, scheduling RIB processing",
+                ifp->vrf_id, ifp->name);
+  rib_update (old_vrf_id, RIB_UPDATE_IF_CHANGE);
+  rib_update (ifp->vrf_id, RIB_UPDATE_IF_CHANGE);
+}
+
+
 /* Handle VRF addition */
 void
 vrf_add_update (struct vrf *vrfp)
@@ -728,11 +833,6 @@ if_down_del_nbr_connected (struct interface *ifp)
 void
 if_up (struct interface *ifp)
 {
-  struct listnode *node;
-  struct listnode *next;
-  struct connected *ifc;
-  struct prefix *p;
-
   /* Notify the protocol daemons. */
   if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) {
     zlog_warn("%s: interface %s hasn't passed ptm check\n", __func__,
@@ -744,20 +844,7 @@ if_up (struct interface *ifp)
   if_nbr_ipv6ll_to_ipv4ll_neigh_add_all (ifp);
 
   /* Install connected routes to the kernel. */
-  if (ifp->connected)
-    {
-      for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
-       {
-         p = ifc->address;
-
-         if (p->family == AF_INET)
-           connected_up_ipv4 (ifp, ifc);
-#ifdef HAVE_IPV6
-         else if (p->family == AF_INET6)
-           connected_up_ipv6 (ifp, ifc);
-#endif /* HAVE_IPV6 */
-       }
-    }
+  if_install_connected (ifp);
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
     zlog_debug ("%u: IF %s up, scheduling RIB processing",
@@ -770,29 +857,11 @@ if_up (struct interface *ifp)
 void
 if_down (struct interface *ifp)
 {
-  struct listnode *node;
-  struct listnode *next;
-  struct connected *ifc;
-  struct prefix *p;
-
   /* Notify to the protocol daemons. */
   zebra_interface_down_update (ifp);
 
-  /* Delete connected routes from the kernel. */
-  if (ifp->connected)
-    {
-      for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc))
-       {
-         p = ifc->address;
-
-         if (p->family == AF_INET)
-           connected_down_ipv4 (ifp, ifc);
-#ifdef HAVE_IPV6
-         else if (p->family == AF_INET6)
-           connected_down_ipv6 (ifp, ifc);
-#endif /* HAVE_IPV6 */
-       }
-    }
+  /* Uninstall connected routes from the kernel. */
+  if_uninstall_connected (ifp);
 
   if (IS_ZEBRA_DEBUG_RIB_DETAILED)
     zlog_debug ("%u: IF %s down, scheduling RIB processing",
index 3d8a82d454fbabf23c4377e75d2f005854239a33..ed5150776321c289bf36da320c57ab34f215ad7e 100644 (file)
@@ -225,6 +225,7 @@ extern void if_flags_update (struct interface *, uint64_t);
 extern int if_subnet_add (struct interface *, struct connected *);
 extern int if_subnet_delete (struct interface *, struct connected *);
 extern int ipv6_address_configured (struct interface *ifp);
+extern void if_handle_vrf_change (struct interface *ifp, vrf_id_t vrf_id);
 
 extern void vrf_delete_update (struct vrf *vrfp);
 extern void vrf_add_update (struct vrf *vrfp);
index 552524dbc8b62afc75fa843288f657a37030d8f2..993028519976fffe82eeb609e39e198ece978ff1 100644 (file)
@@ -558,6 +558,74 @@ zebra_interface_address_delete_update (struct interface *ifp,
       }
 }
 
+/* Interface VRF change. May need to delete from clients not interested in
+ * the new VRF. Note that this function is invoked *prior* to the VRF change.
+ */
+void
+zebra_interface_vrf_update_del (struct interface *ifp, vrf_id_t new_vrf_id)
+{
+  struct listnode *node, *nnode;
+  struct zserv *client;
+
+  if (IS_ZEBRA_DEBUG_EVENT)
+    zlog_debug ("MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/DEL %s VRF Id %u -> %u",
+                ifp->name, ifp->vrf_id, new_vrf_id);
+
+  for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
+    {
+      /* Skip clients not interested in both VRFs. */
+      if (!vrf_bitmap_check (client->ifinfo, ifp->vrf_id) &&
+          !vrf_bitmap_check (client->ifinfo, new_vrf_id))
+        continue;
+
+      if (!vrf_bitmap_check (client->ifinfo, new_vrf_id))
+        {
+          /* Need to delete if the client is not interested in the new VRF. */
+          zsend_interface_update (ZEBRA_INTERFACE_DOWN, client, ifp);
+          client->ifdel_cnt++;
+          zsend_interface_delete (client, ifp);
+        }
+      else if (vrf_bitmap_check (client->ifinfo, ifp->vrf_id))
+        {
+          /* Client is interested in both VRFs, inform about the change. */
+          zsend_interface_vrf_update (client, ifp, new_vrf_id);
+        }
+    }
+}
+
+/* Interface VRF change. This function is invoked *post* VRF change and sends an
+ * add to clients who are interested in the new VRF but not in the old VRF.
+ */
+void
+zebra_interface_vrf_update_add (struct interface *ifp, vrf_id_t old_vrf_id)
+{
+  struct listnode *node, *nnode;
+  struct zserv *client;
+
+  if (IS_ZEBRA_DEBUG_EVENT)
+    zlog_debug ("MESSAGE: ZEBRA_INTERFACE_VRF_UPDATE/ADD %s VRF Id %u -> %u",
+                ifp->name, old_vrf_id, ifp->vrf_id);
+
+  for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
+    {
+      /* Skip clients interested in both VRFs - they would've got an Update. */
+      if (vrf_bitmap_check (client->ifinfo, ifp->vrf_id) &&
+          vrf_bitmap_check (client->ifinfo, old_vrf_id))
+        continue;
+
+      /* Skip clients not interested in the new VRF - they would've
+       * got a Delete.
+       */
+      if (!vrf_bitmap_check (client->ifinfo, ifp->vrf_id))
+        continue;
+
+      /* Need to add if the client is interested in the new VRF. */
+      client->ifadd_cnt++;
+      zsend_interface_add (client, ifp);
+      zsend_interface_addresses (client, ifp);
+    }
+}
+
 int
 zebra_add_import_table_entry (struct route_node *rn, struct rib *rib)
 {
index d56e3d0b97af609db982e8e98f11bfa86e06e141..bc30934030f42f20b510cbe70b287161a0276139 100644 (file)
@@ -52,6 +52,8 @@ extern void zebra_interface_address_add_update (struct interface *,
                                                struct connected *);
 extern void zebra_interface_address_delete_update (struct interface *,
                                                   struct connected *c);
+extern void zebra_interface_vrf_update_del (struct interface *, vrf_id_t new_vrf_id);
+extern void zebra_interface_vrf_update_add (struct interface *, vrf_id_t old_vrf_id);
 extern int zebra_import_table (afi_t afi, u_int32_t table_id,
                               u_int32_t metric, int add);
 
index 44295be98bc29497911458b76926b2ee7d393b43..598eafc355f1e81179e16ba0adb64ae8aa65a50d 100644 (file)
@@ -63,6 +63,12 @@ void zebra_interface_address_delete_update (struct interface *a,
 { return; }
 #endif
 
+void zebra_interface_vrf_update_del (struct interface *a, vrf_id_t new_vrf_id)
+{ return; }
+
+void zebra_interface_vrf_update_add (struct interface *a, vrf_id_t old_vrf_id)
+{ return; }
+
 int zebra_import_table (afi_t afi, u_int32_t table_id, u_int32_t metric,
                        int add)
 { return 0; }
index 3f9eceae15a769a3ef97dc0c998ee4cda28c689c..6603437f091dc353239ac96ba9f925280ff30739 100644 (file)
@@ -357,7 +357,7 @@ zsend_interface_nbr_address (int cmd, struct zserv *client,
   struct prefix *p;
 
   /* Check this client need interface information. */
-  if (! client->ifinfo)
+  if (! vrf_bitmap_check (client->ifinfo, ifp->vrf_id))
     return 0;
 
   s = client->obuf;
@@ -433,6 +433,61 @@ zebra_interface_nbr_address_delete_update (struct interface *ifp,
       zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_DELETE, client, ifp, ifc);
 }
 
+/* Send addresses on interface to client */
+int
+zsend_interface_addresses (struct zserv *client, struct interface *ifp)
+{
+  struct listnode *cnode, *cnnode;
+  struct connected *c;
+  struct nbr_connected *nc;
+
+  /* Send interface addresses. */
+  for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, c))
+    {
+      if (!CHECK_FLAG (c->conf, ZEBRA_IFC_REAL))
+        continue;
+
+      if (zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client,
+                                   ifp, c) < 0)
+        return -1;
+    }
+
+  /* Send interface neighbors. */
+  for (ALL_LIST_ELEMENTS (ifp->nbr_connected, cnode, cnnode, nc))
+    {
+      if (zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_ADD,
+                                       client, ifp, nc) < 0)
+        return -1;
+    }
+
+  return 0;
+}
+
+/* Notify client about interface moving from one VRF to another.
+ * Whether client is interested in old and new VRF is checked by caller.
+ */
+int
+zsend_interface_vrf_update (struct zserv *client, struct interface *ifp,
+                            vrf_id_t vrf_id)
+{
+  struct stream *s;
+
+  s = client->obuf;
+  stream_reset (s);
+
+  zserv_create_header (s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id);
+
+  /* Fill in the ifIndex of the interface and its new VRF (id) */
+  stream_putl (s, ifp->ifindex);
+  stream_putw (s, vrf_id);
+
+  /* Write packet size. */
+  stream_putw_at (s, 0, stream_get_endp (s));
+
+  client->if_vrfchg_cnt++;
+  return zebra_server_send_message(client);
+}
+
 /* Add new nbr connected IPv6 address if none exists already, or replace the
    existing one if an ifc entry is found on the interface. */
 void
@@ -1030,10 +1085,7 @@ static int
 zread_interface_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
 {
   struct listnode *ifnode, *ifnnode;
-  struct listnode *cnode, *cnnode;
   struct interface *ifp;
-  struct connected *c;
-  struct nbr_connected *nc;
 
   /* Interface information is needed. */
   vrf_bitmap_set (client->ifinfo, vrf_id);
@@ -1047,20 +1099,8 @@ zread_interface_add (struct zserv *client, u_short length, vrf_id_t vrf_id)
       if (zsend_interface_add (client, ifp) < 0)
         return -1;
 
-      for (ALL_LIST_ELEMENTS (ifp->connected, cnode, cnnode, c))
-       {
-         if (CHECK_FLAG (c->conf, ZEBRA_IFC_REAL) &&
-             (zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_ADD, client, 
-                                       ifp, c) < 0))
-           return -1;
-       }
-      for (ALL_LIST_ELEMENTS (ifp->nbr_connected, cnode, cnnode, nc))
-       {
-         if (zsend_interface_nbr_address (ZEBRA_INTERFACE_NBR_ADDRESS_ADD, client,
-                                       ifp, nc) < 0)
-           return -1;
-       }
-
+      if (zsend_interface_addresses (client, ifp) < 0)
+        return -1;
     }
   return 0;
 }
index 3016428caf9f1e7013979167af3ca5b94e6bf4a9..f3e7a3b88389d15f69d3aacc97e4712d83d5bc35 100644 (file)
@@ -102,6 +102,7 @@ struct zserv
   u_int32_t bfd_peer_replay_cnt;
   u_int32_t vrfadd_cnt;
   u_int32_t vrfdel_cnt;
+  u_int32_t if_vrfchg_cnt;
 
   time_t connect_time;
   time_t last_read_time;
@@ -148,6 +149,7 @@ extern int zsend_vrf_delete (struct zserv *, struct vrf *);
 
 extern int zsend_interface_add (struct zserv *, struct interface *);
 extern int zsend_interface_delete (struct zserv *, struct interface *);
+extern int zsend_interface_addresses (struct zserv *, struct interface *);
 extern int zsend_interface_address (int, struct zserv *, struct interface *,
                                     struct connected *);
 extern void nbr_connected_replacement_add_ipv6 (struct interface *,
@@ -158,6 +160,8 @@ extern int zsend_redistribute_route (int, struct zserv *, struct prefix *,
                                     struct rib *);
 extern int zsend_router_id_update (struct zserv *, struct prefix *,
                                    vrf_id_t);
+extern int zsend_interface_vrf_update (struct zserv *, struct interface *,
+                                       vrf_id_t);
 
 extern pid_t pid;