From: Paul Jakma <[email protected]>

Add a new message to Zserv to allow zebra to inform Zserv clients of the VRF
IDs that are valid on this Zserv socket.  This is to allow responsibility
for different VRFs to be distributed over different sockets.  Rendezvous is
left as a separate issue.

* lib/zebra.h: Add ZEBRA_VRF_ID_UPDATE message to Zserv. Add
  {ADD,DEL} sub-commands for ZEBRA_VRF_ID_UPDATE
* zserv.c: (zsend_vrf_id_update) Send update of an added or deleted VRF Id to
  all zclients
  (zsend_vrf_init) Send an Add of a list valid VRFs to the given client.
  (zebra_client_create) Call previous helper to send all VRFs to new clients
  immediately.
* zserv.h: Export zsend_vrf_id_update helper.
* main.c: (zebra_vrf_{en,dis}able) Have the vrf enable/disable hooks call
  zsend_vrf_id_update to update all clients.  Not quite sure this a good
  place for these hooks though.

* zclient.c: (zebra_vrf_id_update_read) client side parser for the
  ZEBRA_VRF_ID_UPDATE message, returns a dynamic storage (struct
  zserv_vrf_id_update *), which the caller should free with...
  (zserv_vrf_id_update_free) Free return val of zebra_vrf_id_update_read.
* zclient.h: export (struct zserv_vrf_id_update), zebra_vrf_id_update_read,
   and zserv_vrf_id_update_free.

Patch originates while with OpenSourceRouting.org.
---
 lib/memtypes.c |  1 +
 lib/zclient.c  | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
 lib/zclient.h  | 12 ++++++++++++
 lib/zebra.h    |  7 ++++++-
 zebra/main.c   |  5 ++++-
 zebra/zserv.c  | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 zebra/zserv.h  |  2 ++
 7 files changed, 125 insertions(+), 3 deletions(-)

diff --git a/lib/memtypes.c b/lib/memtypes.c
index ed1615a..e7b0cc6 100644
--- a/lib/memtypes.c
+++ b/lib/memtypes.c
@@ -72,6 +72,7 @@ struct memory_list memory_list_lib[] =
   { MTYPE_VRF,                 "VRF"                           },
   { MTYPE_VRF_NAME,            "VRF name"                      },
   { MTYPE_VRF_BITMAP,          "VRF bit-map"                   },
+  { MTYPE_ZCLIENT_VRF_ID_UPDATE,"Zclient VRF ID Update"        },
   { -1, NULL },
 };
 
diff --git a/lib/zclient.c b/lib/zclient.c
index fb62be7..0214a38 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -665,6 +665,52 @@ zebra_router_id_update_read (struct stream *s, struct 
prefix *rid)
   rid->prefixlen = stream_getc (s);
 }
 
+void
+zserv_vrf_id_update_free (struct zserv_vrf_id_update *vu)
+{
+  XFREE (MTYPE_ZCLIENT_VRF_ID_UPDATE, vu);
+}
+
+struct zserv_vrf_id_update *
+zebra_vrf_id_update_read (struct stream *s)
+{
+  struct zserv_vrf_id_update *vu 
+    = XMALLOC(MTYPE_ZCLIENT_VRF_ID_UPDATE, sizeof (struct 
zserv_vrf_id_update));
+  
+  if (vu == NULL)
+    return NULL;
+  
+  vu->cmd = stream_getw (s);
+  
+  assert (vu->cmd == ZEBRA_VRF_ID_UPDATE_ADD 
+          || vu->cmd == ZEBRA_VRF_ID_UPDATE_DEL);
+  if (vu->cmd != ZEBRA_VRF_ID_UPDATE_ADD 
+      && vu->cmd != ZEBRA_VRF_ID_UPDATE_DEL)
+    {
+      zlog_warn ("%s: unknown ZEBRA_VRF_ID_UPDATE sub-cmd %d", 
+                 __func__, vu->cmd);
+      zserv_vrf_id_update_free (vu);
+      return NULL;
+    }
+  
+  vu->num = stream_getw (s);
+  
+  assert (vu->num >= 1);
+  if (vu->num <= 0)
+    {
+      zlog_warn ("%s: bad ZEBRA_VRF_ID_UPDATE number %d", __func__, vu->num);
+      zserv_vrf_id_update_free (vu);
+      return NULL;
+    }
+  
+  vu = XREALLOC(MTYPE_ZCLIENT_VRF_ID_UPDATE, vu,
+                sizeof (struct zserv_vrf_id_update) 
+                + (sizeof(vrf_id_t) * vu->num));
+  for (int i = 0; i < vu->num; i++)
+    vu->vrf_ids[i] = stream_getw (s);
+  return vu;
+}
+
 /* Interface addition from zebra daemon. */
 /*  
  * The format of the message sent with type ZEBRA_INTERFACE_ADD or
@@ -1027,6 +1073,9 @@ zclient_read (struct thread *thread)
       if (zclient->ipv6_route_delete)
        (*zclient->ipv6_route_delete) (command, zclient, length, vrf_id);
       break;
+    case ZEBRA_VRF_ID_UPDATE:
+      if (zclient->vrf_id_update)
+        (*zclient->vrf_id_update) (command, zclient, length, vrf_id);
     default:
       break;
     }
diff --git a/lib/zclient.h b/lib/zclient.h
index d069eb2..886624d 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -79,6 +79,7 @@ struct zclient
   /* Pointer to the callback functions. */
   void (*zebra_connected) (struct zclient *);
   int (*router_id_update) (int, struct zclient *, uint16_t, vrf_id_t);
+  int (*vrf_id_update) (int, struct zclient *, uint16_t, vrf_id_t);
   int (*interface_add) (int, struct zclient *, uint16_t, vrf_id_t);
   int (*interface_delete) (int, struct zclient *, uint16_t, vrf_id_t);
   int (*interface_up) (int, struct zclient *, uint16_t, vrf_id_t);
@@ -137,6 +138,13 @@ struct zapi_ipv4
   vrf_id_t vrf_id;
 };
 
+struct zserv_vrf_id_update
+{
+  char cmd; /* ZEBRA_VRF_ID_UPDATE_ADD or ZEBRA_VRF_ID_UPDATE_DEL */
+  int num;
+  vrf_id_t vrf_ids[];
+};
+
 /* Prototypes of zebra client service functions. */
 extern struct zclient *zclient_new (struct thread_master *);
 extern void zclient_init (struct zclient *, int);
@@ -181,6 +189,10 @@ extern struct connected *zebra_interface_address_read 
(int, struct stream *,
     vrf_id_t);
 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 struct zserv_vrf_id_update *zebra_vrf_id_update_read (struct stream *s);
+extern void zserv_vrf_id_update_free (struct zserv_vrf_id_update *);
+
 extern int zapi_ipv4_route (u_char, struct zclient *, struct prefix_ipv4 *, 
                             struct zapi_ipv4 *);
 
diff --git a/lib/zebra.h b/lib/zebra.h
index 97ed05c..3361fc3 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -415,7 +415,8 @@ struct in_pktinfo
 #define ZEBRA_HELLO                       23
 #define ZEBRA_IPV4_NEXTHOP_LOOKUP_MRIB    24
 #define ZEBRA_VRF_UNREGISTER              25
-#define ZEBRA_MESSAGE_MAX                 26
+#define ZEBRA_VRF_ID_UPDATE                  27
+#define ZEBRA_MESSAGE_MAX                 28
 
 /* Marker value used in new Zserv, in the byte location corresponding
  * the command value in the old zserv header. To allow old and new
@@ -478,6 +479,10 @@ extern const char *zserv_command_string (unsigned int 
command);
 #define ZEBRA_NEXTHOP_IPV6_IFNAME        8
 #define ZEBRA_NEXTHOP_BLACKHOLE          9
 
+/* ZEBRA_VRF_ID_UPDATE sub-commands */
+#define ZEBRA_VRF_ID_UPDATE_ADD                 1
+#define ZEBRA_VRF_ID_UPDATE_DEL             2
+
 #ifndef INADDR_LOOPBACK
 #define        INADDR_LOOPBACK 0x7f000001      /* Internet address 127.0.0.1.  
*/
 #endif
diff --git a/zebra/main.c b/zebra/main.c
index f3c08f1..74abde6 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -235,6 +235,7 @@ zebra_vrf_enable (vrf_id_t vrf_id, void **info)
   kernel_init (zvrf);
   interface_list (zvrf);
   route_read (zvrf);
+  zsend_vrf_update (zvrf, ZEBRA_VRF_ID_UPDATE_ADD);
 
   return 0;
 }
@@ -248,7 +249,9 @@ zebra_vrf_disable (vrf_id_t vrf_id, void **info)
   struct interface *ifp;
 
   assert (zvrf);
-
+  
+  zsend_vrf_update (zvrf, ZEBRA_VRF_ID_UPDATE_DEL);
+  
   rib_close_table (zvrf->table[AFI_IP][SAFI_UNICAST]);
   rib_close_table (zvrf->table[AFI_IP6][SAFI_UNICAST]);
 
diff --git a/zebra/zserv.c b/zebra/zserv.c
index f14b1b1..009e053 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -775,6 +775,54 @@ zsend_router_id_update (struct zserv *client, struct 
prefix *p,
   return zebra_server_send_message(client);
 }
 
+/* Inform all clients of additions and deletes to valid VRF IDs */
+void
+zsend_vrf_update (struct zebra_vrf *zvrf, int cmd)
+{
+  struct listnode *node, *nnode;
+  struct zserv *client;
+  
+  for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client))
+    {
+      struct stream *s = client->obuf;
+      stream_reset (s);
+      
+      zserv_create_header (s, ZEBRA_VRF_ID_UPDATE, 0);
+      stream_putw (s, cmd);
+      stream_putw (s, 1);
+      stream_putw (s, zvrf->vrf_id);
+      stream_putw_at (s, 0, stream_get_endp (s));
+      
+      zebra_server_send_message (client);
+    }
+}
+
+static int
+zsend_vrf_init (struct zserv *client)
+{
+  vrf_iter_t iter;
+  struct stream *s = client->obuf;
+  int n;
+  
+  stream_reset (s);
+  
+  zserv_create_header (s, ZEBRA_VRF_ID_UPDATE, 0);
+  stream_putw (s, ZEBRA_VRF_ID_UPDATE_ADD);
+  size_t npos = stream_get_endp (s);
+  stream_putw (s, 0);
+  
+  for (n = 0, iter = vrf_first ();
+       iter != VRF_ITER_INVALID;
+       iter = vrf_next (iter), n++)
+    {
+      struct zebra_vrf *zvrf = vrf_iter2info (iter);
+      stream_putw (s, zvrf->vrf_id);
+    }
+  stream_putw_at (s, 0, stream_get_endp (s));
+  stream_putw_at (s, npos, n);
+  return zebra_server_send_message(client);
+}
+
 /* Register zebra server interface information.  Send current all
    interface and address information. */
 static int
@@ -1325,7 +1373,7 @@ zebra_client_create (int sock)
   client->obuf = stream_new (ZEBRA_MAX_PACKET_SIZ);
   client->wb = buffer_new(0);
 
-  /* Set table number. */
+  /* Set table number. XXX? Make sense with VRFs? */
   client->rtm_table = zebrad.rtm_table_default;
 
   /* Initialize flags */
@@ -1338,6 +1386,8 @@ zebra_client_create (int sock)
   /* Add this client to linked list. */
   listnode_add (zebrad.client_list, client);
   
+  zsend_vrf_init (client);
+  
   /* Make new read thread. */
   zebra_event (ZEBRA_READ, sock, client);
 }
diff --git a/zebra/zserv.h b/zebra/zserv.h
index fc01f96..e3cf26c 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -111,6 +111,8 @@ extern int zsend_route_multipath (int, struct zserv *, 
struct prefix *,
 extern int zsend_router_id_update (struct zserv *, struct prefix *,
                                    vrf_id_t);
 
+extern void zsend_vrf_update (struct zebra_vrf *, int);
+
 extern pid_t pid;
 
 #endif /* _ZEBRA_ZEBRA_H */
-- 
2.5.0


_______________________________________________
Quagga-dev mailing list
[email protected]
https://lists.quagga.net/mailman/listinfo/quagga-dev

Reply via email to