diff options
author | Mark Stapp <mjs@voltanet.io> | 2020-04-15 14:34:03 +0200 |
---|---|---|
committer | Mark Stapp <mjs@voltanet.io> | 2020-04-16 18:07:54 +0200 |
commit | 4cebdb9bb858674980d2a04304c3197afd665f28 (patch) | |
tree | 45537be5fe9a7d4ccd194d38e4502ea8c0ef6f12 | |
parent | lib,zebra: add a session id for zapi sessions (diff) | |
download | frr-4cebdb9bb858674980d2a04304c3197afd665f28.tar.xz frr-4cebdb9bb858674980d2a04304c3197afd665f28.zip |
zebra,ldpd: use zapi client session id in LM apis
Use the zapi client session id in the label manager apis;
use the client struct directly in some code. Assign a session
id to ldpd's sync LM zapi session.
Signed-off-by: Mark Stapp <mjs@voltanet.io>
-rw-r--r-- | ldpd/lde.c | 1 | ||||
-rw-r--r-- | zebra/label_manager.c | 172 | ||||
-rw-r--r-- | zebra/label_manager.h | 53 | ||||
-rw-r--r-- | zebra/zapi_msg.c | 15 | ||||
-rw-r--r-- | zebra/zapi_msg.h | 3 |
5 files changed, 135 insertions, 109 deletions
diff --git a/ldpd/lde.c b/ldpd/lde.c index ae883078d..2223e32f8 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -1756,6 +1756,7 @@ static void zclient_sync_init(unsigned short instance) zclient_sync->sock = -1; zclient_sync->redist_default = ZEBRA_ROUTE_LDP; zclient_sync->instance = instance; + zclient_sync->session_id = 1; /* Distinguish from main session */ zclient_sync->privs = &lde_privs; while (zclient_socket_connect(zclient_sync) < 0) { diff --git a/zebra/label_manager.c b/zebra/label_manager.c index 5f2128a09..93736e672 100644 --- a/zebra/label_manager.c +++ b/zebra/label_manager.c @@ -52,48 +52,45 @@ DEFINE_MTYPE_STATIC(LBL_MGR, LM_CHUNK, "Label Manager Chunk"); * externally */ -DEFINE_HOOK(lm_client_connect, - (uint8_t proto, uint16_t instance, vrf_id_t vrf_id), - (proto, instance, vrf_id)); -DEFINE_HOOK(lm_client_disconnect, (uint8_t proto, uint16_t instance), - (proto, instance)); +DEFINE_HOOK(lm_client_connect, (struct zserv *client, vrf_id_t vrf_id), + (client, vrf_id)); +DEFINE_HOOK(lm_client_disconnect, (struct zserv *client), (client)); DEFINE_HOOK(lm_get_chunk, - (struct label_manager_chunk * *lmc, uint8_t proto, - uint16_t instance, uint8_t keep, uint32_t size, uint32_t base, - vrf_id_t vrf_id), - (lmc, proto, instance, keep, size, base, vrf_id)); + (struct label_manager_chunk * *lmc, struct zserv *client, + uint8_t keep, uint32_t size, uint32_t base, vrf_id_t vrf_id), + (lmc, client, keep, size, base, vrf_id)); DEFINE_HOOK(lm_release_chunk, - (uint8_t proto, uint16_t instance, uint32_t start, uint32_t end), - (proto, instance, start, end)); + (struct zserv *client, uint32_t start, uint32_t end), + (client, start, end)); DEFINE_HOOK(lm_cbs_inited, (), ()); /* define wrappers to be called in zapi_msg.c (as hooks must be called in * source file where they were defined) */ -void lm_client_connect_call(uint8_t proto, uint16_t instance, vrf_id_t vrf_id) +void lm_client_connect_call(struct zserv *client, vrf_id_t vrf_id) { - hook_call(lm_client_connect, proto, instance, vrf_id); + hook_call(lm_client_connect, client, vrf_id); } -void lm_get_chunk_call(struct label_manager_chunk **lmc, uint8_t proto, - uint16_t instance, uint8_t keep, uint32_t size, - uint32_t base, vrf_id_t vrf_id) +void lm_get_chunk_call(struct label_manager_chunk **lmc, struct zserv *client, + uint8_t keep, uint32_t size, uint32_t base, + vrf_id_t vrf_id) { - hook_call(lm_get_chunk, lmc, proto, instance, keep, size, base, vrf_id); + hook_call(lm_get_chunk, lmc, client, keep, size, base, vrf_id); } -void lm_release_chunk_call(uint8_t proto, uint16_t instance, uint32_t start, - uint32_t end) +void lm_release_chunk_call(struct zserv *client, uint32_t start, uint32_t end) { - hook_call(lm_release_chunk, proto, instance, start, end); + hook_call(lm_release_chunk, client, start, end); } /* forward declarations of the static functions to be used for some hooks */ -static int label_manager_connect(uint8_t proto, uint16_t instance, - vrf_id_t vrf_id); -static int label_manager_disconnect(uint8_t proto, uint16_t instance); +static int label_manager_connect(struct zserv *client, vrf_id_t vrf_id); +static int label_manager_disconnect(struct zserv *client); static int label_manager_get_chunk(struct label_manager_chunk **lmc, - uint8_t proto, uint16_t instance, - uint8_t keep, uint32_t size, uint32_t base, + struct zserv *client, uint8_t keep, + uint32_t size, uint32_t base, vrf_id_t vrf_id); +static int label_manager_release_label_chunk(struct zserv *client, + uint32_t start, uint32_t end); void delete_label_chunk(void *val) { @@ -110,7 +107,7 @@ void delete_label_chunk(void *val) * @param instance Instance, to identify the owner * @return Number of chunks released */ -int release_daemon_label_chunks(uint8_t proto, unsigned short instance) +int release_daemon_label_chunks(struct zserv *client) { struct listnode *node; struct label_manager_chunk *lmc; @@ -118,13 +115,16 @@ int release_daemon_label_chunks(uint8_t proto, unsigned short instance) int ret; if (IS_ZEBRA_DEBUG_PACKET) - zlog_debug("%s: Releasing chunks for client proto %s, instance %d", - __func__, zebra_route_string(proto), instance); + zlog_debug("%s: Releasing chunks for client proto %s, instance %d, session %u", + __func__, zebra_route_string(client->proto), + client->instance, client->session_id); for (ALL_LIST_ELEMENTS_RO(lbl_mgr.lc_list, node, lmc)) { - if (lmc->proto == proto && lmc->instance == instance - && lmc->keep == 0) { + if (lmc->proto == client->proto && + lmc->instance == client->instance && + lmc->session_id == client->session_id && lmc->keep == 0) { ret = release_label_chunk(lmc->proto, lmc->instance, + lmc->session_id, lmc->start, lmc->end); if (ret == 0) count++; @@ -139,10 +139,7 @@ int release_daemon_label_chunks(uint8_t proto, unsigned short instance) int lm_client_disconnect_cb(struct zserv *client) { - uint8_t proto = client->proto; - uint16_t instance = client->instance; - - hook_call(lm_client_disconnect, proto, instance); + hook_call(lm_client_disconnect, client); return 0; } @@ -151,14 +148,14 @@ void lm_hooks_register(void) hook_register(lm_client_connect, label_manager_connect); hook_register(lm_client_disconnect, label_manager_disconnect); hook_register(lm_get_chunk, label_manager_get_chunk); - hook_register(lm_release_chunk, release_label_chunk); + hook_register(lm_release_chunk, label_manager_release_label_chunk); } void lm_hooks_unregister(void) { hook_unregister(lm_client_connect, label_manager_connect); hook_unregister(lm_client_disconnect, label_manager_disconnect); hook_unregister(lm_get_chunk, label_manager_get_chunk); - hook_unregister(lm_release_chunk, release_label_chunk); + hook_unregister(lm_release_chunk, label_manager_release_label_chunk); } /** @@ -180,6 +177,7 @@ void label_manager_init(void) /* alloc and fill a label chunk */ struct label_manager_chunk *create_label_chunk(uint8_t proto, unsigned short instance, + uint32_t session_id, uint8_t keep, uint32_t start, uint32_t end) { @@ -191,6 +189,7 @@ struct label_manager_chunk *create_label_chunk(uint8_t proto, lmc->end = end; lmc->proto = proto; lmc->instance = instance; + lmc->session_id = session_id; lmc->keep = keep; return lmc; @@ -199,7 +198,8 @@ struct label_manager_chunk *create_label_chunk(uint8_t proto, /* attempt to get a specific label chunk */ static struct label_manager_chunk * assign_specific_label_chunk(uint8_t proto, unsigned short instance, - uint8_t keep, uint32_t size, uint32_t base) + uint32_t session_id, uint8_t keep, uint32_t size, + uint32_t base) { struct label_manager_chunk *lmc; struct listnode *node, *next = NULL; @@ -248,7 +248,8 @@ assign_specific_label_chunk(uint8_t proto, unsigned short instance, /* insert chunk between existing chunks */ if (insert_node) { - lmc = create_label_chunk(proto, instance, keep, base, end); + lmc = create_label_chunk(proto, instance, session_id, keep, + base, end); listnode_add_before(lbl_mgr.lc_list, insert_node, lmc); return lmc; } @@ -270,7 +271,8 @@ assign_specific_label_chunk(uint8_t proto, unsigned short instance, delete_label_chunk(death); } - lmc = create_label_chunk(proto, instance, keep, base, end); + lmc = create_label_chunk(proto, instance, session_id, keep, + base, end); if (last_node) listnode_add_before(lbl_mgr.lc_list, last_node, lmc); else @@ -280,7 +282,8 @@ assign_specific_label_chunk(uint8_t proto, unsigned short instance, } else { /* create a new chunk past all the existing ones and link at * tail */ - lmc = create_label_chunk(proto, instance, keep, base, end); + lmc = create_label_chunk(proto, instance, session_id, keep, + base, end); listnode_add(lbl_mgr.lc_list, lmc); return lmc; } @@ -301,6 +304,7 @@ assign_specific_label_chunk(uint8_t proto, unsigned short instance, */ struct label_manager_chunk *assign_label_chunk(uint8_t proto, unsigned short instance, + uint32_t session_id, uint8_t keep, uint32_t size, uint32_t base) { @@ -310,8 +314,8 @@ struct label_manager_chunk *assign_label_chunk(uint8_t proto, /* handle chunks request with a specific base label */ if (base != MPLS_LABEL_BASE_ANY) - return assign_specific_label_chunk(proto, instance, keep, size, - base); + return assign_specific_label_chunk(proto, instance, session_id, + keep, size, base); /* appease scan-build, who gets confused by the use of macros */ assert(lbl_mgr.lc_list); @@ -322,6 +326,7 @@ struct label_manager_chunk *assign_label_chunk(uint8_t proto, && lmc->end - lmc->start + 1 == size) { lmc->proto = proto; lmc->instance = instance; + lmc->session_id = session_id; lmc->keep = keep; return lmc; } @@ -329,8 +334,9 @@ struct label_manager_chunk *assign_label_chunk(uint8_t proto, */ if ((lmc->start > prev_end) && (lmc->start - prev_end >= size)) { - lmc = create_label_chunk(proto, instance, keep, - prev_end + 1, prev_end + size); + lmc = create_label_chunk(proto, instance, session_id, + keep, prev_end + 1, + prev_end + size); listnode_add_before(lbl_mgr.lc_list, node, lmc); return lmc; } @@ -355,13 +361,31 @@ struct label_manager_chunk *assign_label_chunk(uint8_t proto, } /* create chunk and link at tail */ - lmc = create_label_chunk(proto, instance, keep, start_free, + lmc = create_label_chunk(proto, instance, session_id, keep, start_free, start_free + size - 1); listnode_add(lbl_mgr.lc_list, lmc); return lmc; } /** + * Release label chunks from a client. + * + * Called on client disconnection or reconnection. It only releases chunks + * with empty keep value. + * + * @param client Client zapi session + * @param start First label of the chunk + * @param end Last label of the chunk + * @return 0 on success + */ +static int label_manager_release_label_chunk(struct zserv *client, + uint32_t start, uint32_t end) +{ + return release_label_chunk(client->proto, client->instance, + client->session_id, start, end); +} + +/** * Core function, release no longer used label chunks * * @param proto Daemon protocol of client, to identify the owner @@ -370,8 +394,8 @@ struct label_manager_chunk *assign_label_chunk(uint8_t proto, * @param end Last label of the chunk * @return 0 on success, -1 otherwise */ -int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start, - uint32_t end) +int release_label_chunk(uint8_t proto, unsigned short instance, + uint32_t session_id, uint32_t start, uint32_t end) { struct listnode *node; struct label_manager_chunk *lmc; @@ -386,13 +410,15 @@ int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start, continue; if (lmc->end != end) continue; - if (lmc->proto != proto || lmc->instance != instance) { + if (lmc->proto != proto || lmc->instance != instance || + lmc->session_id != session_id) { flog_err(EC_ZEBRA_LM_DAEMON_MISMATCH, "%s: Daemon mismatch!!", __func__); continue; } lmc->proto = NO_PROTO; lmc->instance = 0; + lmc->session_id = 0; lmc->keep = 0; ret = 0; break; @@ -405,64 +431,60 @@ int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start, } /* default functions to be called on hooks */ -static int label_manager_connect(uint8_t proto, uint16_t instance, - vrf_id_t vrf_id) +static int label_manager_connect(struct zserv *client, vrf_id_t vrf_id) { /* * Release previous labels of same protocol and instance. * This is done in case it restarted from an unexpected shutdown. */ - release_daemon_label_chunks(proto, instance); - return lm_client_connect_response(proto, instance, vrf_id, 0); + release_daemon_label_chunks(client); + return zsend_label_manager_connect_response(client, vrf_id, 0); } -static int label_manager_disconnect(uint8_t proto, uint16_t instance) +static int label_manager_disconnect(struct zserv *client) { - release_daemon_label_chunks(proto, instance); + release_daemon_label_chunks(client); return 0; } static int label_manager_get_chunk(struct label_manager_chunk **lmc, - uint8_t proto, uint16_t instance, - uint8_t keep, uint32_t size, uint32_t base, + struct zserv *client, uint8_t keep, + uint32_t size, uint32_t base, vrf_id_t vrf_id) { - *lmc = assign_label_chunk(proto, instance, keep, size, base); - return lm_get_chunk_response(*lmc, proto, instance, vrf_id); + *lmc = assign_label_chunk(client->proto, client->instance, + client->session_id, keep, size, base); + return lm_get_chunk_response(*lmc, client, vrf_id); } /* Respond to a connect request */ int lm_client_connect_response(uint8_t proto, uint16_t instance, - vrf_id_t vrf_id, uint8_t result) + uint32_t session_id, vrf_id_t vrf_id, + uint8_t result) { - struct zserv *client = zserv_find_client(proto, instance); + struct zserv *client = zserv_find_client_session(proto, instance, + session_id); if (!client) { - zlog_err("%s: could not find client for daemon %s instance %u", - __func__, zebra_route_string(proto), instance); + zlog_err("%s: could not find client for daemon %s instance %u session %u", + __func__, zebra_route_string(proto), instance, + session_id); return 1; } return zsend_label_manager_connect_response(client, vrf_id, result); } /* Respond to a get_chunk request */ -int lm_get_chunk_response(struct label_manager_chunk *lmc, uint8_t proto, - uint16_t instance, vrf_id_t vrf_id) +int lm_get_chunk_response(struct label_manager_chunk *lmc, struct zserv *client, + vrf_id_t vrf_id) { if (!lmc) flog_err(EC_ZEBRA_LM_CANNOT_ASSIGN_CHUNK, "Unable to assign Label Chunk to %s instance %u", - zebra_route_string(proto), instance); + zebra_route_string(client->proto), client->instance); else if (IS_ZEBRA_DEBUG_PACKET) zlog_debug("Assigned Label Chunk %u - %u to %s instance %u", - lmc->start, lmc->end, zebra_route_string(proto), - instance); + lmc->start, lmc->end, + zebra_route_string(client->proto), client->instance); - struct zserv *client = zserv_find_client(proto, instance); - if (!client) { - zlog_err("%s: could not find client for daemon %s instance %u", - __func__, zebra_route_string(proto), instance); - return 1; - } - return zsend_assign_label_chunk_response(client, vrf_id, proto, - instance, lmc); + return zsend_assign_label_chunk_response(client, vrf_id, lmc); } void label_manager_close(void) diff --git a/zebra/label_manager.h b/zebra/label_manager.h index 4fee34d30..82154982c 100644 --- a/zebra/label_manager.h +++ b/zebra/label_manager.h @@ -40,19 +40,20 @@ extern "C" { /* * Label chunk struct - * Client daemon which the chunk belongs to can be identified by either - * proto (daemon protocol) + instance. + * Client daemon which the chunk belongs to can be identified by a tuple of: + * proto (daemon protocol) + instance + zapi session_id * If the client then passes a non-empty value to keep field when it requests * for chunks, the chunks won't be garbage collected and the client will be - * responsible of its release. + * responsible for releasing them. * Otherwise, if the keep field is not set (value 0) for the chunk, it will be * automatically released when the client disconnects or when it reconnects * (in case it died unexpectedly, we can know it's the same because it will have - * the same proto and instance values) + * the same proto+instance+session values) */ struct label_manager_chunk { uint8_t proto; unsigned short instance; + uint32_t session_id; uint8_t keep; uint32_t start; /* First label of the chunk */ uint32_t end; /* Last label of the chunk */ @@ -63,41 +64,40 @@ struct label_manager_chunk { * so that any external module wanting to replace those can react */ -DECLARE_HOOK(lm_client_connect, - (uint8_t proto, uint16_t instance, vrf_id_t vrf_id), - (proto, instance, vrf_id)); -DECLARE_HOOK(lm_client_disconnect, (uint8_t proto, uint16_t instance), - (proto, instance)); +DECLARE_HOOK(lm_client_connect, (struct zserv *client, vrf_id_t vrf_id), + (client, vrf_id)); +DECLARE_HOOK(lm_client_disconnect, (struct zserv *client), (client)); DECLARE_HOOK(lm_get_chunk, - (struct label_manager_chunk * *lmc, uint8_t proto, - uint16_t instance, uint8_t keep, uint32_t size, uint32_t base, - vrf_id_t vrf_id), - (lmc, proto, instance, keep, size, base, vrf_id)); + (struct label_manager_chunk * *lmc, struct zserv *client, + uint8_t keep, uint32_t size, uint32_t base, vrf_id_t vrf_id), + (lmc, client, keep, size, base, vrf_id)); DECLARE_HOOK(lm_release_chunk, - (uint8_t proto, uint16_t instance, uint32_t start, uint32_t end), - (proto, instance, start, end)); + (struct zserv *client, uint32_t start, uint32_t end), + (client, start, end)); DECLARE_HOOK(lm_cbs_inited, (), ()); /* declare wrappers to be called in zapi_msg.c (as hooks must be called in * source file where they were defined) */ -void lm_client_connect_call(uint8_t proto, uint16_t instance, vrf_id_t vrf_id); -void lm_get_chunk_call(struct label_manager_chunk **lmc, uint8_t proto, - uint16_t instance, uint8_t keep, uint32_t size, - uint32_t base, vrf_id_t vrf_id); -void lm_release_chunk_call(uint8_t proto, uint16_t instance, uint32_t start, +void lm_client_connect_call(struct zserv *client, vrf_id_t vrf_id); +void lm_get_chunk_call(struct label_manager_chunk **lmc, struct zserv *client, + uint8_t keep, uint32_t size, uint32_t base, + vrf_id_t vrf_id); +void lm_release_chunk_call(struct zserv *client, uint32_t start, uint32_t end); /* API for an external LM to return responses for requests */ int lm_client_connect_response(uint8_t proto, uint16_t instance, - vrf_id_t vrf_id, uint8_t result); -int lm_get_chunk_response(struct label_manager_chunk *lmc, uint8_t proto, - uint16_t instance, vrf_id_t vrf_id); + uint32_t session_id, vrf_id_t vrf_id, + uint8_t result); +int lm_get_chunk_response(struct label_manager_chunk *lmc, struct zserv *client, + vrf_id_t vrf_id); /* convenience function to allocate an lmc to be consumed by the above API */ struct label_manager_chunk *create_label_chunk(uint8_t proto, unsigned short instance, + uint32_t session_id, uint8_t keep, uint32_t start, uint32_t end); void delete_label_chunk(void *val); @@ -117,12 +117,13 @@ struct label_manager { void label_manager_init(void); struct label_manager_chunk *assign_label_chunk(uint8_t proto, unsigned short instance, + uint32_t session_id, uint8_t keep, uint32_t size, uint32_t base); -int release_label_chunk(uint8_t proto, unsigned short instance, uint32_t start, - uint32_t end); +int release_label_chunk(uint8_t proto, unsigned short instance, + uint32_t session_id, uint32_t start, uint32_t end); int lm_client_disconnect_cb(struct zserv *client); -int release_daemon_label_chunks(uint8_t proto, unsigned short instance); +int release_daemon_label_chunks(struct zserv *client); void label_manager_close(void); #ifdef __cplusplus diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index d6f23de48..092b5dd3c 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -957,7 +957,6 @@ int zsend_pw_update(struct zserv *client, struct zebra_pw *pw) /* Send response to a get label chunk request to client */ int zsend_assign_label_chunk_response(struct zserv *client, vrf_id_t vrf_id, - uint8_t proto, uint16_t instance, struct label_manager_chunk *lmc) { int ret; @@ -965,9 +964,9 @@ int zsend_assign_label_chunk_response(struct zserv *client, vrf_id_t vrf_id, zclient_create_header(s, ZEBRA_GET_LABEL_CHUNK, vrf_id); /* proto */ - stream_putc(s, proto); + stream_putc(s, client->proto); /* instance */ - stream_putw(s, instance); + stream_putw(s, client->instance); if (lmc) { /* keep */ @@ -2199,7 +2198,7 @@ static void zread_label_manager_connect(struct zserv *client, client->instance = instance; /* call hook for connection using wrapper */ - lm_client_connect_call(proto, instance, vrf_id); + lm_client_connect_call(client, vrf_id); stream_failure: return; @@ -2225,8 +2224,10 @@ static void zread_get_label_chunk(struct zserv *client, struct stream *msg, STREAM_GETL(s, size); STREAM_GETL(s, base); + assert(proto == client->proto && instance == client->instance); + /* call hook to get a chunk using wrapper */ - lm_get_chunk_call(&lmc, proto, instance, keep, size, base, vrf_id); + lm_get_chunk_call(&lmc, client, keep, size, base, vrf_id); stream_failure: return; @@ -2248,8 +2249,10 @@ static void zread_release_label_chunk(struct zserv *client, struct stream *msg) STREAM_GETL(s, start); STREAM_GETL(s, end); + assert(proto == client->proto && instance == client->instance); + /* call hook to release a chunk using wrapper */ - lm_release_chunk_call(proto, instance, start, end); + lm_release_chunk_call(client, start, end); stream_failure: return; diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index 996a255ff..a4f5e74e4 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -94,8 +94,7 @@ extern void zserv_nexthop_num_warn(const char *caller, const struct prefix *p, extern void zsend_capabilities_all_clients(void); extern int zsend_assign_label_chunk_response(struct zserv *client, - vrf_id_t vrf_id, uint8_t proto, - uint16_t instance, + vrf_id_t vrf_id, struct label_manager_chunk *lmc); extern int zsend_label_manager_connect_response(struct zserv *client, vrf_id_t vrf_id, |