From ee94437e28f8b5e7f9ad8584f36fe8fbc11facb3 Mon Sep 17 00:00:00 2001 From: Mark Stapp Date: Thu, 21 Jan 2021 10:12:05 -0500 Subject: [PATCH] zebra: send async nhg update results Send the results of daemons' nhg updates asynchronously, after the update has actually completed. Capture additional info about the source daemon in order to locate the correct zapi session. Simplify the result types considered by the zebra_nhg module. Signed-off-by: Mark Stapp --- zebra/zapi_msg.c | 36 +++++++++++++++++++++--------------- zebra/zapi_msg.h | 3 +++ zebra/zebra_nhg.c | 30 ++++++++++++++++++++++++++---- zebra/zebra_nhg.h | 7 +++++++ 4 files changed, 57 insertions(+), 19 deletions(-) diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index a62e020e4a..8e68984823 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -709,13 +709,13 @@ static int zsend_ipv4_nexthop_lookup_mrib(struct zserv *client, return zserv_send_message(client, s); } -static int nhg_notify(uint16_t type, uint16_t instance, uint32_t id, - enum zapi_nhg_notify_owner note) +int zsend_nhg_notify(uint16_t type, uint16_t instance, uint32_t session_id, + uint32_t id, enum zapi_nhg_notify_owner note) { struct zserv *client; struct stream *s; - client = zserv_find_client(type, instance); + client = zserv_find_client_session(type, instance, session_id); if (!client) { if (IS_ZEBRA_DEBUG_PACKET) { zlog_debug("Not Notifying Owner: %u(%u) about %u(%d)", @@ -724,6 +724,10 @@ static int nhg_notify(uint16_t type, uint16_t instance, uint32_t id, return 0; } + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug("%s: type %d, id %d, note %d", + __func__, type, id, note); + s = stream_new(ZEBRA_MAX_PACKET_SIZ); stream_reset(s); @@ -1822,16 +1826,17 @@ static void zread_nhg_del(ZAPI_HANDLER_ARGS) /* * Delete the received nhg id */ - nhe = zebra_nhg_proto_del(api_nhg.id, api_nhg.proto); if (nhe) { zebra_nhg_decrement_ref(nhe); - nhg_notify(api_nhg.proto, client->instance, api_nhg.id, - ZAPI_NHG_REMOVED); + zsend_nhg_notify(api_nhg.proto, client->instance, + client->session_id, api_nhg.id, + ZAPI_NHG_REMOVED); } else - nhg_notify(api_nhg.proto, client->instance, api_nhg.id, - ZAPI_NHG_REMOVE_FAIL); + zsend_nhg_notify(api_nhg.proto, client->instance, + client->session_id, api_nhg.id, + ZAPI_NHG_REMOVE_FAIL); } static void zread_nhg_add(ZAPI_HANDLER_ARGS) @@ -1865,7 +1870,8 @@ static void zread_nhg_add(ZAPI_HANDLER_ARGS) /* * Create the nhg */ - nhe = zebra_nhg_proto_add(api_nhg.id, api_nhg.proto, nhg, 0); + nhe = zebra_nhg_proto_add(api_nhg.id, api_nhg.proto, client->instance, + client->session_id, nhg, 0); nexthop_group_delete(&nhg); zebra_nhg_backup_free(&bnhg); @@ -1876,12 +1882,12 @@ static void zread_nhg_add(ZAPI_HANDLER_ARGS) * * Resolution is going to need some more work. */ - if (nhe) - nhg_notify(api_nhg.proto, client->instance, api_nhg.id, - ZAPI_NHG_INSTALLED); - else - nhg_notify(api_nhg.proto, client->instance, api_nhg.id, - ZAPI_NHG_FAIL_INSTALL); + + /* If there's a failure, notify sender immediately */ + if (nhe == NULL) + zsend_nhg_notify(api_nhg.proto, client->instance, + client->session_id, api_nhg.id, + ZAPI_NHG_FAIL_INSTALL); } static void zread_route_add(ZAPI_HANDLER_ARGS) diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index 9822d72022..c03278669a 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -108,6 +108,9 @@ extern int zsend_sr_policy_notify_status(uint32_t color, extern int zsend_client_close_notify(struct zserv *client, struct zserv *closed_client); +int zsend_nhg_notify(uint16_t type, uint16_t instance, uint32_t session_id, + uint32_t id, enum zapi_nhg_notify_owner note); + #ifdef __cplusplus } #endif diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index ff020af4d6..604480b68b 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -43,6 +43,7 @@ #include "zebra_errors.h" #include "zebra_dplane.h" #include "zebra/interface.h" +#include "zebra/zapi_msg.h" DEFINE_MTYPE_STATIC(ZEBRA, NHG, "Nexthop Group Entry"); DEFINE_MTYPE_STATIC(ZEBRA, NHG_CONNECTED, "Nexthop Group Connected"); @@ -2105,10 +2106,10 @@ done_with_match: /* This function verifies reachability of one given nexthop, which can be * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored * in nexthop->flags field. The nexthop->ifindex will be updated - * appropriately as well. An existing route map can turn - * (otherwise active) nexthop into inactive, but not vice versa. + * appropriately as well. An existing route map can turn an + * otherwise active nexthop into inactive, but not vice versa. * - * If it finds a nexthop recursivedly, set the resolved_id + * If it finds a nexthop recursively, set the resolved_id * to match that nexthop's nhg_hash_entry ID; * * The return value is the final value of 'ACTIVE' flag. @@ -2131,6 +2132,7 @@ static unsigned nexthop_active_check(struct route_node *rn, family = AFI_IP6; else family = 0; + switch (nexthop->type) { case NEXTHOP_TYPE_IFINDEX: ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id); @@ -2641,6 +2643,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx) EC_ZEBRA_DP_DELETE_FAIL, "Failed to uninstall Nexthop ID (%u) from the kernel", id); + /* We already free'd the data, nothing to do */ break; case DPLANE_OP_NH_INSTALL: @@ -2661,12 +2664,26 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx) SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID); SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED); zebra_nhg_handle_install(nhe); - } else + + /* If daemon nhg, send it an update */ + if (nhe->id >= ZEBRA_NHG_PROTO_LOWER) + zsend_nhg_notify(nhe->type, nhe->zapi_instance, + nhe->zapi_session, nhe->id, + ZAPI_NHG_INSTALLED); + } else { + /* If daemon nhg, send it an update */ + if (nhe->id >= ZEBRA_NHG_PROTO_LOWER) + zsend_nhg_notify(nhe->type, nhe->zapi_instance, + nhe->zapi_session, nhe->id, + ZAPI_NHG_FAIL_INSTALL); + flog_err( EC_ZEBRA_DP_INSTALL_FAIL, "Failed to install Nexthop ID (%u) into the kernel", nhe->id); + } break; + case DPLANE_OP_ROUTE_INSTALL: case DPLANE_OP_ROUTE_UPDATE: case DPLANE_OP_ROUTE_DELETE: @@ -2775,6 +2792,7 @@ bool zebra_nhg_proto_nexthops_only(void) /* Add NHE from upper level proto */ struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type, + uint16_t instance, uint32_t session, struct nexthop_group *nhg, afi_t afi) { struct nhg_hash_entry lookup; @@ -2858,6 +2876,10 @@ struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type, zebra_nhg_increment_ref(new); + /* Capture zapi client info */ + new->zapi_instance = instance; + new->zapi_session = session; + zebra_nhg_set_valid_if_active(new); zebra_nhg_install_kernel(new); diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h index 9382b8c65d..db20f2beaf 100644 --- a/zebra/zebra_nhg.h +++ b/zebra/zebra_nhg.h @@ -50,8 +50,14 @@ struct nhg_hash_entry { uint32_t id; afi_t afi; vrf_id_t vrf_id; + + /* Source protocol - zebra or another daemon */ int type; + /* zapi instance and session id, for groups from other daemons */ + uint16_t zapi_instance; + uint32_t zapi_session; + struct nexthop_group nhg; /* If supported, a mapping of backup nexthops. */ @@ -292,6 +298,7 @@ zebra_nhg_rib_find_nhe(struct nhg_hash_entry *rt_nhe, afi_t rt_afi); * Returns allocated NHE on success, otherwise NULL. */ struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type, + uint16_t instance, uint32_t session, struct nexthop_group *nhg, afi_t afi); -- 2.39.5