summaryrefslogtreecommitdiff
path: root/zebra/zserv.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zserv.c')
-rw-r--r--zebra/zserv.c206
1 files changed, 177 insertions, 29 deletions
diff --git a/zebra/zserv.c b/zebra/zserv.c
index f11c0dd2fd..c06efbfb4b 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 };
@@ -631,7 +632,7 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client,
{
struct stream *s;
unsigned long nump;
- u_char num;
+ uint8_t num;
struct nexthop *nexthop;
/* Get output stream. */
@@ -828,7 +829,8 @@ static int zsend_assign_label_chunk_response(struct zserv *client,
/* Send response to a label manager connect request to client */
static int zsend_label_manager_connect_response(struct zserv *client,
- vrf_id_t vrf_id, u_short result)
+ vrf_id_t vrf_id,
+ unsigned short result)
{
int ret;
struct stream *s = stream_new(ZEBRA_MAX_PACKET_SIZ);
@@ -862,8 +864,8 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS)
struct rnh *rnh;
struct stream *s;
struct prefix p;
- u_short l = 0;
- u_char flags = 0;
+ unsigned short l = 0;
+ uint8_t flags = 0;
uint16_t type = cmd2type[hdr->command];
if (IS_ZEBRA_DEBUG_NHT)
@@ -939,7 +941,7 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS)
struct rnh *rnh;
struct stream *s;
struct prefix p;
- u_short l = 0;
+ unsigned short l = 0;
uint16_t type = cmd2type[hdr->command];
if (IS_ZEBRA_DEBUG_NHT)
@@ -1000,7 +1002,7 @@ stream_failure:
static void zread_fec_register(ZAPI_HANDLER_ARGS)
{
struct stream *s;
- u_short l = 0;
+ unsigned short l = 0;
struct prefix p;
uint16_t flags;
uint32_t label_index = MPLS_INVALID_LABEL_INDEX;
@@ -1059,7 +1061,7 @@ stream_failure:
static void zread_fec_unregister(ZAPI_HANDLER_ARGS)
{
struct stream *s;
- u_short l = 0;
+ unsigned short l = 0;
struct prefix p;
uint16_t flags;
@@ -1432,10 +1434,10 @@ static void zread_ipv4_add(ZAPI_HANDLER_ARGS)
int i;
struct route_entry *re;
struct prefix p;
- u_char message;
+ uint8_t message;
struct in_addr nhop_addr;
- u_char nexthop_num;
- u_char nexthop_type;
+ uint8_t nexthop_num;
+ uint8_t nexthop_type;
struct stream *s;
ifindex_t ifindex;
safi_t safi;
@@ -1585,7 +1587,7 @@ static void zread_ipv4_delete(ZAPI_HANDLER_ARGS)
struct stream *s;
struct zapi_ipv4 api;
struct prefix p;
- u_int32_t table_id;
+ uint32_t table_id;
s = msg;
@@ -1638,9 +1640,9 @@ static void zread_ipv4_route_ipv6_nexthop_add(ZAPI_HANDLER_ARGS)
struct stream *s;
struct in6_addr nhop_addr;
struct route_entry *re;
- u_char message;
- u_char nexthop_num;
- u_char nexthop_type;
+ uint8_t message;
+ uint8_t nexthop_num;
+ uint8_t nexthop_type;
struct prefix p;
safi_t safi;
static struct in6_addr nexthops[MULTIPATH_NUM];
@@ -1810,9 +1812,9 @@ static void zread_ipv6_add(ZAPI_HANDLER_ARGS)
struct in6_addr nhop_addr;
ifindex_t ifindex;
struct route_entry *re;
- u_char message;
- u_char nexthop_num;
- u_char nexthop_type;
+ uint8_t message;
+ uint8_t nexthop_num;
+ uint8_t nexthop_type;
struct prefix p;
struct prefix_ipv6 src_p, *src_pp;
safi_t safi;
@@ -2060,9 +2062,9 @@ static void zread_router_id_delete(ZAPI_HANDLER_ARGS)
static void zread_hello(ZAPI_HANDLER_ARGS)
{
/* type of protocol (lib/zebra.h) */
- u_char proto;
- u_short instance;
- u_char notify;
+ uint8_t proto;
+ unsigned short instance;
+ uint8_t notify;
STREAM_GETC(msg, proto);
STREAM_GETW(msg, instance);
@@ -2110,7 +2112,7 @@ static void zread_mpls_labels(ZAPI_HANDLER_ARGS)
union g_addr gate;
ifindex_t ifindex;
mpls_label_t in_label, out_label;
- u_int8_t distance;
+ uint8_t distance;
/* Get input stream. */
s = msg;
@@ -2185,13 +2187,67 @@ 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)
{
struct stream *s;
/* type of protocol (lib/zebra.h) */
- u_char proto;
- u_short instance;
+ uint8_t proto;
+ unsigned short instance;
/* Get input stream. */
s = msg;
@@ -2216,7 +2272,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",
@@ -2224,7 +2280,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;
}
@@ -2232,7 +2288,7 @@ static void zread_get_label_chunk(struct zserv *client, struct stream *msg,
vrf_id_t vrf_id)
{
struct stream *s;
- u_char keep;
+ uint8_t keep;
uint32_t size;
struct label_manager_chunk *lmc;
@@ -2304,6 +2360,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;
@@ -2626,6 +2768,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,
@@ -2657,7 +2802,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),
@@ -2926,6 +3074,7 @@ static int zserv_process_messages(struct thread *thread)
if (!hdrvalid)
continue;
+ hdr.length -= ZEBRA_HEADER_SIZE;
/* lookup vrf */
zvrf = zebra_vrf_lookup_by_id(hdr.vrf_id);
if (!zvrf && IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) {
@@ -3046,7 +3195,6 @@ static int zserv_read(struct thread *thread)
#if defined(HANDLE_ZAPI_FUZZING)
zserv_write_incoming(client->ibuf_work, command);
#endif
- hdr.length -= ZEBRA_HEADER_SIZE;
/* Debug packet information. */
if (IS_ZEBRA_DEBUG_EVENT)
@@ -3319,7 +3467,7 @@ static void zebra_show_client_brief(struct vty *vty, struct zserv *client)
client->v6_route_del_cnt);
}
-struct zserv *zebra_find_client(u_char proto, u_short instance)
+struct zserv *zebra_find_client(uint8_t proto, unsigned short instance)
{
struct listnode *node, *nnode;
struct zserv *client;