From 8288a24fc1b65cca0ff41bfa213bb9528d998d4f Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Mon, 5 Mar 2018 18:07:23 +0100 Subject: [PATCH] zebra: add the handling of table ids from remote daemons 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 --- zebra/label_manager.c | 2 +- zebra/label_manager.h | 2 +- zebra/zebra_ns.c | 6 ++ zebra/zebra_vrf.c | 2 +- zebra/zserv.c | 152 +++++++++++++++++++++++++++++++++++++++++- 5 files changed, 158 insertions(+), 6 deletions(-) diff --git a/zebra/label_manager.c b/zebra/label_manager.c index ad881b819c..38869e80ec 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -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; diff --git a/zebra/label_manager.h b/zebra/label_manager.h index a26e195b71..4395e6897e 100644 --- a/zebra/label_manager.h +++ b/zebra/label_manager.h @@ -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 */ diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 66b1131e39..7393f767af 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -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; diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index dfb02f15a9..fe1b100575 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -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++) diff --git a/zebra/zserv.c b/zebra/zserv.c index 538487a9cd..76e5ea2f08 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -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), -- 2.39.5