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 <mjs@voltanet.io>
This commit is contained in:
Mark Stapp 2021-01-21 10:12:05 -05:00
parent 5a9c0931aa
commit ee94437e28
4 changed files with 57 additions and 19 deletions

View File

@ -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)

View File

@ -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

View File

@ -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);

View File

@ -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);