diff options
Diffstat (limited to 'zebra/zserv.c')
| -rw-r--r-- | zebra/zserv.c | 206 |
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; |
