zebra: use async dplane route updates

Enqueue updates to the dplane system; add a couple of stats.

Signed-off-by: Mark Stapp <mjs@voltanet.io>
This commit is contained in:
Mark Stapp 2018-06-27 16:10:30 -04:00
parent 655d681a44
commit 97f5b44182
2 changed files with 63 additions and 22 deletions

View file

@ -1169,8 +1169,11 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re,
{
struct nexthop *nexthop;
rib_table_info_t *info = srcdest_rnode_table_info(rn);
const struct prefix *p, *src_p;
struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
const struct prefix *p, *src_p;
enum zebra_dplane_result ret;
rib_dest_t *dest = rib_dest_from_rnode(rn);
srcdest_rnode_prefixes(rn, &p, &src_p);
@ -1202,24 +1205,40 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re,
if (old && (old != re) && (old->type != re->type))
zsend_route_notify_owner(old, p, ZAPI_ROUTE_BETTER_ADMIN_WON);
/* Update fib selection */
dest->selected_fib = re;
/*
* Make sure we update the FPM any time we send new information to
* the kernel.
*/
hook_call(rib_update, rn, "installing in kernel");
switch (kernel_route_rib(rn, p, src_p, old, re)) {
/* Send add or update */
if (old && (old != re)) {
ret = dplane_route_update(rn, re, old);
} else {
ret = dplane_route_add(rn, re);
}
switch (ret) {
case ZEBRA_DPLANE_REQUEST_QUEUED:
flog_err(
EC_ZEBRA_DP_INVALID_RC,
"No current known DataPlane interfaces can return this, please fix");
if (zvrf)
zvrf->installs_queued++;
break;
case ZEBRA_DPLANE_REQUEST_FAILURE:
flog_err(
EC_ZEBRA_DP_INSTALL_FAIL,
"No current known Rib Install Failure cases, please fix");
{
char str[SRCDEST2STR_BUFFER];
srcdest_rnode2str(rn, str, sizeof(str));
flog_err(EC_ZEBRA_DP_INSTALL_FAIL,
"%u:%s: Failed to enqueue dataplane install",
re->vrf_id, str);
break;
}
case ZEBRA_DPLANE_REQUEST_SUCCESS:
zvrf->installs++;
if (zvrf)
zvrf->installs++;
break;
}
@ -1231,11 +1250,8 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
{
struct nexthop *nexthop;
rib_table_info_t *info = srcdest_rnode_table_info(rn);
const struct prefix *p, *src_p;
struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
srcdest_rnode_prefixes(rn, &p, &src_p);
if (info->safi != SAFI_UNICAST) {
for (ALL_NEXTHOPS(re->ng, nexthop))
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
@ -1244,20 +1260,25 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
/*
* Make sure we update the FPM any time we send new information to
* the kernel.
* the dataplane.
*/
hook_call(rib_update, rn, "uninstalling from kernel");
switch (kernel_route_rib(rn, p, src_p, re, NULL)) {
switch (dplane_route_delete(rn, re)) {
case ZEBRA_DPLANE_REQUEST_QUEUED:
flog_err(
EC_ZEBRA_DP_INVALID_RC,
"No current known DataPlane interfaces can return this, please fix");
if (zvrf)
zvrf->removals_queued++;
break;
case ZEBRA_DPLANE_REQUEST_FAILURE:
flog_err(
EC_ZEBRA_DP_INSTALL_FAIL,
"No current known RIB Install Failure cases, please fix");
{
char str[SRCDEST2STR_BUFFER];
srcdest_rnode2str(rn, str, sizeof(str));
flog_err(EC_ZEBRA_DP_INSTALL_FAIL,
"%u:%s: Failed to enqueue dataplane uninstall",
re->vrf_id, str);
break;
}
case ZEBRA_DPLANE_REQUEST_SUCCESS:
if (zvrf)
zvrf->removals++;
@ -1272,6 +1293,7 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re)
{
rib_table_info_t *info = srcdest_rnode_table_info(rn);
rib_dest_t *dest = rib_dest_from_rnode(rn);
struct nexthop *nexthop;
if (dest && dest->selected_fib == re) {
if (info->safi == SAFI_UNICAST)
@ -1283,6 +1305,11 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re)
if (!RIB_SYSTEM_ROUTE(re))
rib_uninstall_kernel(rn, re);
dest->selected_fib = NULL;
for (ALL_NEXTHOPS(re->ng, nexthop))
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
}
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
@ -1926,16 +1953,18 @@ done:
}
/*
* TODO - WIP
* TODO - WIP version of route-update processing after async dataplane
* update.
*/
static void rib_process_after(dplane_ctx_h ctx)
{
struct route_table *table = NULL;
struct zebra_vrf *zvrf = NULL;
struct route_node *rn = NULL;
struct route_entry *re = NULL, *old_re = NULL, *rib;
bool is_update = false;
struct nexthop *nexthop;
char dest_str[PREFIX_STRLEN];
char dest_str[PREFIX_STRLEN] = "";
dplane_op_e op;
enum zebra_dplane_result status;
const struct prefix *dest_pfx, *src_pfx;
@ -1957,6 +1986,8 @@ static void rib_process_after(dplane_ctx_h ctx)
goto done;
}
zvrf = vrf_info_lookup(dplane_ctx_get_vrf(ctx));
dest_pfx = dplane_ctx_get_dest(ctx);
/* Note well: only capturing the prefix string if debug is enabled here;
@ -1997,6 +2028,10 @@ static void rib_process_after(dplane_ctx_h ctx)
*/
if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_REMOVED);
if (zvrf) {
zvrf->removals++;
}
} else {
zsend_route_notify_owner_ctx(ctx,
ZAPI_ROUTE_FAIL_INSTALL);
@ -2085,6 +2120,10 @@ static void rib_process_after(dplane_ctx_h ctx)
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
}
if (zvrf) {
zvrf->installs++;
}
/* Redistribute */
/* TODO -- still calling the redist api using the route_entries,
* and there's a corner-case here: if there's no client

View file

@ -133,6 +133,8 @@ struct zebra_vrf {
/* Route Installs */
uint64_t installs;
uint64_t removals;
uint64_t installs_queued;
uint64_t removals_queued;
uint64_t neigh_updates;
uint64_t lsp_installs;
uint64_t lsp_removals;