]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: add the handling of table ids from remote daemons
authorPhilippe Guibert <philippe.guibert@6wind.com>
Mon, 5 Mar 2018 17:07:23 +0000 (18:07 +0100)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Thu, 29 Mar 2018 07:19:58 +0000 (09:19 +0200)
This commit is connecting the table manager with remote daemons by
handling the queries.
As the function is similar in many points with label allocator, a
function has been renamed.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
zebra/label_manager.c
zebra/label_manager.h
zebra/zebra_ns.c
zebra/zebra_vrf.c
zebra/zserv.c

index ad881b819cff180b06cf06a41fe12bcb9c6cbc0d..38869e80ecfdbd0c829ec7c49a2bc646f85015ce 100644 (file)
@@ -363,7 +363,7 @@ int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start,
  * @param instance Instance, to identify the owner
  * @return Number of chunks released
  */
-int release_daemon_chunks(uint8_t proto, unsigned short instance)
+int release_daemon_label_chunks(uint8_t proto, unsigned short instance)
 {
        struct listnode *node;
        struct label_manager_chunk *lmc;
index a26e195b71e180064e0b804fdbebf3505c2dd1f2..4395e6897e7efdbc4d61407971db2523cf6c68c0 100644 (file)
@@ -69,7 +69,7 @@ struct label_manager_chunk *assign_label_chunk(uint8_t proto,
                                               uint8_t keep, uint32_t size);
 int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start,
                        uint32_t end);
-int release_daemon_chunks(uint8_t proto, unsigned short instance);
+int release_daemon_label_chunks(uint8_t proto, unsigned short instance);
 void label_manager_close(void);
 
 #endif /* _LABEL_MANAGER_H */
index 66b1131e3983641908a61915dc14bebd88b4ca6d..7393f767afa3d20b72c67670c5b40e84cca94e32 100644 (file)
@@ -38,6 +38,7 @@
 #include "zebra_netns_id.h"
 #include "zebra_pbr.h"
 #include "rib.h"
+#include "table_manager.h"
 
 extern struct zebra_privs_t zserv_privs;
 
@@ -147,6 +148,9 @@ int zebra_ns_enable(ns_id_t ns_id, void **info)
        interface_list(zns);
        route_read(zns);
 
+       /* Initiate Table Manager per ZNS */
+       table_manager_enable(ns_id);
+
        return 0;
 }
 
@@ -259,6 +263,8 @@ int zebra_ns_disable(ns_id_t ns_id, void **info)
 
        kernel_terminate(zns);
 
+       table_manager_disable(zns->ns_id);
+
        zns->ns_id = NS_DEFAULT;
 
        return 0;
index dfb02f15a9647b98c1dcd10bbc5ecd49c037b774..fe1b100575ba3df5d5d1c8ef33589e653838a518 100644 (file)
@@ -122,8 +122,8 @@ static int zebra_vrf_enable(struct vrf *vrf)
        /* Inform clients that the VRF is now active. This is an
         * add for the clients.
         */
-       zebra_vrf_add_update(zvrf);
 
+       zebra_vrf_add_update(zvrf);
        /* Allocate tables */
        for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
                for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++)
index 538487a9cde7537de83e29f48938a83c3adf1804..76e5ea2f08a3b258682733b7e0b02c49c4b4e7d4 100644 (file)
@@ -61,6 +61,7 @@
 #include "zebra/zebra_vxlan.h"
 #include "zebra/rt.h"
 #include "zebra/zebra_pbr.h"
+#include "zebra/table_manager.h"
 
 /* Event list of zebra. */
 enum event { ZEBRA_READ, ZEBRA_WRITE };
@@ -2186,6 +2187,59 @@ stream_failure:
        return;
 }
 
+static int zsend_table_manager_connect_response(struct zserv *client,
+                                               vrf_id_t vrf_id, uint16_t result)
+{
+       struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
+       zclient_create_header(s, ZEBRA_TABLE_MANAGER_CONNECT, vrf_id);
+
+       /* result */
+       stream_putc(s, result);
+
+       stream_putw_at(s, 0, stream_get_endp(s));
+
+       return zebra_server_send_message(client, s);
+}
+
+/* Send response to a table manager connect request to client */
+static void zread_table_manager_connect(struct zserv *client, struct stream *msg,
+                                       vrf_id_t vrf_id)
+{
+       struct stream *s;
+       uint8_t proto;
+       uint16_t instance;
+
+       s = msg;
+
+       /* Get data. */
+       STREAM_GETC(s, proto);
+       STREAM_GETW(s, instance);
+
+       /* accept only dynamic routing protocols */
+       if ((proto >= ZEBRA_ROUTE_MAX) || (proto <= ZEBRA_ROUTE_STATIC)) {
+               zlog_err("client %d has wrong protocol %s", client->sock,
+                        zebra_route_string(proto));
+               zsend_table_manager_connect_response(client, vrf_id, 1);
+               return;
+       }
+       zlog_notice("client %d with vrf %u instance %u connected as %s",
+                   client->sock, vrf_id, instance, zebra_route_string(proto));
+       client->proto = proto;
+       client->instance = instance;
+
+       /*
+        * Release previous labels of same protocol and instance.
+        * This is done in case it restarted from an unexpected shutdown.
+        */
+       release_daemon_table_chunks(proto, instance);
+
+       zsend_table_manager_connect_response(client, vrf_id, 0);
+
+ stream_failure:
+       return;
+}
+
 static void zread_label_manager_connect(struct zserv *client,
                                        struct stream *msg, vrf_id_t vrf_id)
 {
@@ -2217,7 +2271,7 @@ static void zread_label_manager_connect(struct zserv *client,
          Release previous labels of same protocol and instance.
          This is done in case it restarted from an unexpected shutdown.
        */
-       release_daemon_chunks(proto, instance);
+       release_daemon_label_chunks(proto, instance);
 
        zlog_debug(
                " Label Manager client connected: sock %d, proto %s, vrf %u instance %u",
@@ -2225,7 +2279,7 @@ static void zread_label_manager_connect(struct zserv *client,
        /* send response back */
        zsend_label_manager_connect_response(client, vrf_id, 0);
 
-stream_failure:
+ stream_failure:
        return;
 }
 
@@ -2305,6 +2359,92 @@ static void zread_label_manager_request(ZAPI_HANDLER_ARGS)
        }
 }
 
+/* Send response to a get table chunk request to client */
+static int zsend_assign_table_chunk_response(struct zserv *client,
+                                            vrf_id_t vrf_id,
+                                            struct table_manager_chunk *tmc)
+{
+       struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
+       zclient_create_header(s, ZEBRA_GET_TABLE_CHUNK, vrf_id);
+
+       if (tmc) {
+               /* start and end labels */
+               stream_putl(s, tmc->start);
+               stream_putl(s, tmc->end);
+       }
+
+       /* Write packet size. */
+       stream_putw_at(s, 0, stream_get_endp(s));
+
+       return zebra_server_send_message(client, s);
+}
+
+static void zread_get_table_chunk(struct zserv *client, struct stream *msg,
+                                 vrf_id_t vrf_id)
+{
+       struct stream *s;
+       uint32_t size;
+       struct table_manager_chunk *tmc;
+
+       /* Get input stream.  */
+       s = msg;
+
+       /* Get data. */
+       STREAM_GETL(s, size);
+
+       tmc = assign_table_chunk(client->proto, client->instance, size);
+       if (!tmc)
+               zlog_err("%s: Unable to assign Table Chunk of size %u",
+                        __func__, size);
+       else
+               zlog_debug("Assigned Table Chunk %u - %u", tmc->start,
+                          tmc->end);
+       /* send response back */
+       zsend_assign_table_chunk_response(client, vrf_id, tmc);
+
+stream_failure:
+       return;
+}
+
+static void zread_release_table_chunk(struct zserv *client, struct stream *msg)
+{
+       struct stream *s;
+       uint32_t start, end;
+
+       /* Get input stream.  */
+       s = msg;
+
+       /* Get data. */
+       STREAM_GETL(s, start);
+       STREAM_GETL(s, end);
+
+       release_table_chunk(client->proto, client->instance, start, end);
+
+stream_failure:
+       return;
+}
+
+static void zread_table_manager_request(ZAPI_HANDLER_ARGS)
+{
+       /* to avoid sending other messages like ZERBA_INTERFACE_UP */
+       if (hdr->command == ZEBRA_TABLE_MANAGER_CONNECT)
+               zread_table_manager_connect(client, msg, zvrf_id(zvrf));
+       else {
+               /* Sanity: don't allow 'unidentified' requests */
+               if (!client->proto) {
+                       zlog_err(
+                                "Got table request from an unidentified client");
+                       return;
+               }
+               if (hdr->command == ZEBRA_GET_TABLE_CHUNK)
+                       zread_get_table_chunk(client, msg,
+                                             zvrf_id(zvrf));
+               else if (hdr->command == ZEBRA_RELEASE_TABLE_CHUNK)
+                       zread_release_table_chunk(client, msg);
+       }
+}
+
 static void zread_pseudowire(ZAPI_HANDLER_ARGS)
 {
        struct stream *s;
@@ -2627,6 +2767,9 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
        [ZEBRA_PW_UNSET] = zread_pseudowire,
        [ZEBRA_RULE_ADD] = zread_rule,
        [ZEBRA_RULE_DELETE] = zread_rule,
+       [ZEBRA_TABLE_MANAGER_CONNECT] = zread_table_manager_request,
+       [ZEBRA_GET_TABLE_CHUNK] = zread_table_manager_request,
+       [ZEBRA_RELEASE_TABLE_CHUNK] = zread_table_manager_request,
 };
 
 static inline void zserv_handle_commands(struct zserv *client,
@@ -2658,7 +2801,10 @@ static void zebra_client_free(struct zserv *client)
        zebra_client_close_cleanup_rnh(client);
 
        /* Release Label Manager chunks */
-       release_daemon_chunks(client->proto, client->instance);
+       release_daemon_label_chunks(client->proto, client->instance);
+
+       /* Release Table Manager chunks */
+       release_daemon_table_chunks(client->proto, client->instance);
 
        /* Cleanup any FECs registered by this client. */
        zebra_mpls_cleanup_fecs_for_client(vrf_info_lookup(VRF_DEFAULT),