diff options
| -rw-r--r-- | bgpd/rfapi/rfapi.c | 27 | ||||
| -rw-r--r-- | bgpd/rfapi/rfapi_rib.c | 19 | ||||
| -rw-r--r-- | bgpd/rfapi/rfapi_vty.c | 1 | ||||
| -rw-r--r-- | lib/if_rmap.c | 292 | ||||
| -rw-r--r-- | lib/if_rmap.h | 12 | ||||
| -rw-r--r-- | lib/link_state.c | 14 | ||||
| -rw-r--r-- | lib/subdir.am | 1 | ||||
| -rw-r--r-- | ospf6d/ospf6_gr_helper.c | 10 | ||||
| -rw-r--r-- | ospfd/ospf_lsa.c | 22 | ||||
| -rw-r--r-- | ospfd/ospf_vty.c | 9 | ||||
| -rw-r--r-- | ripd/rip_nb.c | 21 | ||||
| -rw-r--r-- | ripd/rip_nb.h | 12 | ||||
| -rw-r--r-- | ripd/rip_nb_config.c | 90 | ||||
| -rw-r--r-- | ripngd/ripng_nb.c | 21 | ||||
| -rw-r--r-- | ripngd/ripng_nb.h | 12 | ||||
| -rw-r--r-- | ripngd/ripng_nb_config.c | 89 | ||||
| -rw-r--r-- | tests/topotests/lib/ospf.py | 2 | ||||
| -rw-r--r-- | tests/topotests/ospf_gr_helper/test_ospf_gr_helper1.py | 4 | ||||
| -rw-r--r-- | yang/frr-if-rmap.yang | 80 | ||||
| -rw-r--r-- | yang/frr-ripd.yang | 6 | ||||
| -rw-r--r-- | yang/frr-ripngd.yang | 6 | ||||
| -rw-r--r-- | yang/subdir.am | 1 | ||||
| -rw-r--r-- | zebra/zebra_dplane.c | 5 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 3 |
24 files changed, 605 insertions, 154 deletions
diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index 8d6db9d775..67c70431bd 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -51,6 +51,8 @@ #include <execinfo.h> #endif /* HAVE_GLIBC_BACKTRACE */ +#define DEBUG_CLEANUP 0 + struct ethaddr rfapi_ethaddr0 = {{0}}; #define DEBUG_RFAPI_STR "RF API debugging/testing command\n" @@ -3677,11 +3679,36 @@ void rfapi_delete(struct bgp *bgp) { extern void rfp_clear_vnc_nve_all(void); /* can't fix correctly yet */ +#if DEBUG_CLEANUP + zlog_debug("%s: bgp %p", __func__, bgp); +#endif + /* * This clears queries and registered routes, and closes nves */ if (bgp->rfapi) rfp_clear_vnc_nve_all(); + + /* + * close any remaining descriptors + */ + struct rfapi *h = bgp->rfapi; + + if (h && h->descriptors.count) { + struct listnode *node, *nnode; + struct rfapi_descriptor *rfd; +#if DEBUG_CLEANUP + zlog_debug("%s: descriptor count %u", __func__, + h->descriptors.count); +#endif + for (ALL_LIST_ELEMENTS(&h->descriptors, node, nnode, rfd)) { +#if DEBUG_CLEANUP + zlog_debug("%s: closing rfd %p", __func__, rfd); +#endif + (void)rfapi_close(rfd); + } + } + bgp_rfapi_cfg_destroy(bgp, bgp->rfapi_cfg); bgp->rfapi_cfg = NULL; bgp_rfapi_destroy(bgp, bgp->rfapi); diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index be9d30768c..5784f95b27 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -40,6 +40,7 @@ #define DEBUG_PENDING_DELETE_ROUTE 0 #define DEBUG_NHL 0 #define DEBUG_RIB_SL_RD 0 +#define DEBUG_CLEANUP 0 /* forward decl */ #if DEBUG_NHL @@ -327,6 +328,11 @@ static void rfapiRibStartTimer(struct rfapi_descriptor *rfd, tcb = XCALLOC(MTYPE_RFAPI_RECENT_DELETE, sizeof(struct rfapi_rib_tcb)); } +#if DEBUG_CLEANUP + zlog_debug("%s: rfd %p, rn %p, ri %p, tcb %p", __func__, rfd, rn, ri, + tcb); +#endif + tcb->rfd = rfd; tcb->ri = ri; tcb->rn = rn; @@ -506,6 +512,16 @@ void rfapiRibClear(struct rfapi_descriptor *rfd) NULL, (void **)&ri)) { + if (ri->timer) { + struct rfapi_rib_tcb + *tcb; + + tcb = EVENT_ARG( + ri->timer); + EVENT_OFF(ri->timer); + XFREE(MTYPE_RFAPI_RECENT_DELETE, + tcb); + } rfapi_info_free(ri); skiplist_delete_first( (struct skiplist *) @@ -555,6 +571,9 @@ void rfapiRibFree(struct rfapi_descriptor *rfd) { afi_t afi; +#if DEBUG_CLEANUP + zlog_debug("%s: rfd %p", __func__, rfd); +#endif /* * NB rfd is typically detached from master list, so is not included diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 2877c29c20..29698846c3 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -4888,6 +4888,7 @@ static int vnc_clear_vrf(struct vty *vty, struct bgp *bgp, const char *arg_vrf, clear_vnc_prefix(&cda); vty_out(vty, "Cleared %u out of %d prefixes.\n", cda.pfx_count, start_count); + print_cleared_stats(&cda); /* frees lists in cda */ return CMD_SUCCESS; } diff --git a/lib/if_rmap.c b/lib/if_rmap.c index 0d305a7af1..5895924a5e 100644 --- a/lib/if_rmap.c +++ b/lib/if_rmap.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* route-map for interface. * Copyright (C) 1999 Kunihiro Ishiguro + * Copyright (C) 2023 LabN Consulting, L.L.C. */ #include <zebra.h> @@ -10,7 +11,9 @@ #include "memory.h" #include "if.h" #include "if_rmap.h" -#include "ripd/ripd.h" +#include "northbound_cli.h" + +#include "lib/if_rmap_clippy.c" DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX, "Interface route map container"); DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX_NAME, @@ -18,8 +21,6 @@ DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX_NAME, DEFINE_MTYPE_STATIC(LIB, IF_RMAP, "Interface route map"); DEFINE_MTYPE_STATIC(LIB, IF_RMAP_NAME, "I.f. route map name"); -static struct list *if_rmap_ctx_list; - static struct if_rmap *if_rmap_new(void) { struct if_rmap *new; @@ -31,7 +32,9 @@ static struct if_rmap *if_rmap_new(void) static void if_rmap_free(struct if_rmap *if_rmap) { - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->ifname); + char *no_const_ifname = (char *)if_rmap->ifname; + + XFREE(MTYPE_IF_RMAP_NAME, no_const_ifname); XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); @@ -41,22 +44,16 @@ static void if_rmap_free(struct if_rmap *if_rmap) struct if_rmap *if_rmap_lookup(struct if_rmap_ctx *ctx, const char *ifname) { - struct if_rmap key; + struct if_rmap key = {.ifname = ifname}; struct if_rmap *if_rmap; - /* temporary copy */ - key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL; - if_rmap = hash_lookup(ctx->ifrmaphash, &key); - XFREE(MTYPE_IF_RMAP_NAME, key.ifname); - return if_rmap; } void if_rmap_hook_add(struct if_rmap_ctx *ctx, - void (*func)(struct if_rmap_ctx *ctx, - struct if_rmap *)) + void (*func)(struct if_rmap_ctx *ctx, struct if_rmap *)) { ctx->if_rmap_add_hook = func; } @@ -81,16 +78,11 @@ static void *if_rmap_hash_alloc(void *arg) static struct if_rmap *if_rmap_get(struct if_rmap_ctx *ctx, const char *ifname) { - struct if_rmap key; + struct if_rmap key = {.ifname = ifname}; struct if_rmap *ret; - /* temporary copy */ - key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL; - ret = hash_get(ctx->ifrmaphash, &key, if_rmap_hash_alloc); - XFREE(MTYPE_IF_RMAP_NAME, key.ifname); - return ret; } @@ -109,147 +101,171 @@ static bool if_rmap_hash_cmp(const void *arg1, const void *arg2) return strcmp(if_rmap1->ifname, if_rmap2->ifname) == 0; } -static struct if_rmap *if_rmap_set(struct if_rmap_ctx *ctx, - const char *ifname, enum if_rmap_type type, - const char *routemap_name) +static void if_rmap_set(struct if_rmap_ctx *ctx, const char *ifname, + enum if_rmap_type type, const char *routemap_name) { - struct if_rmap *if_rmap; - - if_rmap = if_rmap_get(ctx, ifname); + struct if_rmap *if_rmap = if_rmap_get(ctx, ifname); - if (type == IF_RMAP_IN) { - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); - if_rmap->routemap[IF_RMAP_IN] = - XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); - } - if (type == IF_RMAP_OUT) { - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); - if_rmap->routemap[IF_RMAP_OUT] = - XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); - } + assert(type == IF_RMAP_IN || type == IF_RMAP_OUT); + XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[type]); + if_rmap->routemap[type] = XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); if (ctx->if_rmap_add_hook) (ctx->if_rmap_add_hook)(ctx, if_rmap); - - return if_rmap; } -static int if_rmap_unset(struct if_rmap_ctx *ctx, - const char *ifname, enum if_rmap_type type, - const char *routemap_name) +static void if_rmap_unset(struct if_rmap_ctx *ctx, const char *ifname, + enum if_rmap_type type) { - struct if_rmap *if_rmap; + struct if_rmap *if_rmap = if_rmap_lookup(ctx, ifname); - if_rmap = if_rmap_lookup(ctx, ifname); if (!if_rmap) - return 0; - - if (type == IF_RMAP_IN) { - if (!if_rmap->routemap[IF_RMAP_IN]) - return 0; - if (strcmp(if_rmap->routemap[IF_RMAP_IN], routemap_name) != 0) - return 0; - - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); - } + return; - if (type == IF_RMAP_OUT) { - if (!if_rmap->routemap[IF_RMAP_OUT]) - return 0; - if (strcmp(if_rmap->routemap[IF_RMAP_OUT], routemap_name) != 0) - return 0; + assert(type == IF_RMAP_IN || type == IF_RMAP_OUT); + if (!if_rmap->routemap[type]) + return; - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); - } + XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[type]); if (ctx->if_rmap_delete_hook) ctx->if_rmap_delete_hook(ctx, if_rmap); - if (if_rmap->routemap[IF_RMAP_IN] == NULL - && if_rmap->routemap[IF_RMAP_OUT] == NULL) { + if (if_rmap->routemap[IF_RMAP_IN] == NULL && + if_rmap->routemap[IF_RMAP_OUT] == NULL) { hash_release(ctx->ifrmaphash, if_rmap); if_rmap_free(if_rmap); } - - return 1; } -DEFUN (if_rmap, - if_rmap_cmd, - "route-map RMAP_NAME <in|out> IFNAME", - "Route map set\n" - "Route map name\n" - "Route map set for input filtering\n" - "Route map set for output filtering\n" - "Route map interface name\n") +static int if_route_map_handler(struct vty *vty, bool no, const char *dir, + const char *other_dir, const char *ifname, + const char *route_map) { - int idx_rmap_name = 1; - int idx_in_out = 2; - int idx_ifname = 3; - enum if_rmap_type type; - struct if_rmap_ctx *ctx; + enum nb_operation op = no ? NB_OP_DESTROY : NB_OP_MODIFY; const struct lyd_node *dnode; - struct rip *rip; - - dnode = yang_dnode_get(running_config->dnode, VTY_CURR_XPATH); - rip = nb_running_get_entry(dnode, NULL, true); - ctx = rip->if_rmap_ctx; - - if (strncmp(argv[idx_in_out]->text, "in", 1) == 0) - type = IF_RMAP_IN; - else if (strncmp(argv[idx_in_out]->text, "out", 1) == 0) - type = IF_RMAP_OUT; - else { - vty_out(vty, "route-map direction must be [in|out]\n"); - return CMD_WARNING_CONFIG_FAILED; + char xpath[XPATH_MAXLEN]; + + if (!no) { + snprintf( + xpath, sizeof(xpath), + "./if-route-maps/if-route-map[interface='%s']/%s-route-map", + ifname, dir); + } else { + /* + * If we are deleting the last policy for this interface, + * (i.e., no `in` or `out` policy). delete the interface list + * node instead. + */ + dnode = yang_dnode_get(vty->candidate_config->dnode, + VTY_CURR_XPATH); + if (yang_dnode_existsf( + dnode, + "./if-route-maps/if-route-map[interface='%s']/%s-route-map", + ifname, other_dir)) { + snprintf( + xpath, sizeof(xpath), + "./if-route-maps/if-route-map[interface='%s']/%s-route-map", + ifname, dir); + } else { + /* both dir will be empty so delete the list node */ + snprintf(xpath, sizeof(xpath), + "./if-route-maps/if-route-map[interface='%s']", + ifname); + } } + nb_cli_enqueue_change(vty, xpath, op, route_map); - if_rmap_set(ctx, argv[idx_ifname]->arg, - type, argv[idx_rmap_name]->arg); + return nb_cli_apply_changes(vty, NULL); +} - return CMD_SUCCESS; +DEFPY_YANG(if_ipv4_route_map, if_ipv4_route_map_cmd, + "route-map ROUTE-MAP <in$in|out> IFNAME", + "Route map set\n" + "Route map name\n" + "Route map set for input filtering\n" + "Route map set for output filtering\n" INTERFACE_STR) +{ + const char *dir = in ? "in" : "out"; + const char *other_dir = in ? "out" : "in"; + + return if_route_map_handler(vty, false, dir, other_dir, ifname, + route_map); } -DEFUN (no_if_rmap, - no_if_rmap_cmd, - "no route-map ROUTEMAP_NAME <in|out> IFNAME", - NO_STR - "Route map unset\n" - "Route map name\n" - "Route map for input filtering\n" - "Route map for output filtering\n" - "Route map interface name\n") +DEFPY_YANG(no_if_ipv4_route_map, no_if_ipv4_route_map_cmd, + "no route-map [ROUTE-MAP] <in$in|out> IFNAME", + NO_STR + "Route map set\n" + "Route map name\n" + "Route map set for input filtering\n" + "Route map set for output filtering\n" INTERFACE_STR) { - int idx_routemap_name = 2; - int idx_in_out = 3; - int idx_ifname = 4; - int ret; - enum if_rmap_type type; - struct if_rmap_ctx *ctx = - (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list); - - if (strncmp(argv[idx_in_out]->arg, "i", 1) == 0) - type = IF_RMAP_IN; - else if (strncmp(argv[idx_in_out]->arg, "o", 1) == 0) - type = IF_RMAP_OUT; - else { - vty_out(vty, "route-map direction must be [in|out]\n"); - return CMD_WARNING_CONFIG_FAILED; - } + const char *dir = in ? "in" : "out"; + const char *other_dir = in ? "out" : "in"; - ret = if_rmap_unset(ctx, argv[idx_ifname]->arg, type, - argv[idx_routemap_name]->arg); - if (!ret) { - vty_out(vty, "route-map doesn't exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; + return if_route_map_handler(vty, true, dir, other_dir, ifname, + route_map); +} + +/* + * CLI infra requires new handlers for ripngd + */ +DEFPY_YANG(if_ipv6_route_map, if_ipv6_route_map_cmd, + "route-map ROUTE-MAP <in$in|out> IFNAME", + "Route map set\n" + "Route map name\n" + "Route map set for input filtering\n" + "Route map set for output filtering\n" INTERFACE_STR) +{ + const char *dir = in ? "in" : "out"; + const char *other_dir = in ? "out" : "in"; + + return if_route_map_handler(vty, false, dir, other_dir, ifname, + route_map); +} + +DEFPY_YANG(no_if_ipv6_route_map, no_if_ipv6_route_map_cmd, + "no route-map [ROUTE-MAP] <in$in|out> IFNAME", + NO_STR + "Route map set\n" + "Route map name\n" + "Route map set for input filtering\n" + "Route map set for output filtering\n" INTERFACE_STR) +{ + const char *dir = in ? "in" : "out"; + const char *other_dir = in ? "out" : "in"; + + return if_route_map_handler(vty, true, dir, other_dir, ifname, + route_map); +} + + +void if_rmap_yang_modify_cb(struct if_rmap_ctx *ctx, + const struct lyd_node *dnode, + enum if_rmap_type type, bool del) +{ + + const char *mapname = yang_dnode_get_string(dnode, NULL); + const char *ifname = yang_dnode_get_string(dnode, "../interface"); + + if (del) + if_rmap_unset(ctx, ifname, type); + else + if_rmap_set(ctx, ifname, type, mapname); +} + +void if_rmap_yang_destroy_cb(struct if_rmap_ctx *ctx, + const struct lyd_node *dnode) +{ + const char *ifname = yang_dnode_get_string(dnode, "interface"); + if_rmap_unset(ctx, ifname, IF_RMAP_IN); + if_rmap_unset(ctx, ifname, IF_RMAP_OUT); } /* Configuration write function. */ -int config_write_if_rmap(struct vty *vty, - struct if_rmap_ctx *ctx) +int config_write_if_rmap(struct vty *vty, struct if_rmap_ctx *ctx) { unsigned int i; struct hash_bucket *mp; @@ -281,10 +297,8 @@ int config_write_if_rmap(struct vty *vty, void if_rmap_ctx_delete(struct if_rmap_ctx *ctx) { - listnode_delete(if_rmap_ctx_list, ctx); hash_clean_and_free(&ctx->ifrmaphash, (void (*)(void *))if_rmap_free); - if (ctx->name) - XFREE(MTYPE_IF_RMAP_CTX_NAME, ctx->name); + XFREE(MTYPE_IF_RMAP_CTX_NAME, ctx->name); XFREE(MTYPE_IF_RMAP_CTX, ctx); } @@ -296,27 +310,23 @@ struct if_rmap_ctx *if_rmap_ctx_create(const char *name) ctx = XCALLOC(MTYPE_IF_RMAP_CTX, sizeof(struct if_rmap_ctx)); ctx->name = XSTRDUP(MTYPE_IF_RMAP_CTX_NAME, name); - ctx->ifrmaphash = hash_create_size(4, if_rmap_hash_make, if_rmap_hash_cmp, - "Interface Route-Map Hash"); - if (!if_rmap_ctx_list) - if_rmap_ctx_list = list_new(); - listnode_add(if_rmap_ctx_list, ctx); + ctx->ifrmaphash = + hash_create_size(4, if_rmap_hash_make, if_rmap_hash_cmp, + "Interface Route-Map Hash"); return ctx; } void if_rmap_init(int node) { - if (node == RIPNG_NODE) { - } else if (node == RIP_NODE) { - install_element(RIP_NODE, &if_rmap_cmd); - install_element(RIP_NODE, &no_if_rmap_cmd); + if (node == RIP_NODE) { + install_element(RIP_NODE, &if_ipv4_route_map_cmd); + install_element(RIP_NODE, &no_if_ipv4_route_map_cmd); + } else if (node == RIPNG_NODE) { + install_element(RIPNG_NODE, &if_ipv6_route_map_cmd); + install_element(RIPNG_NODE, &no_if_ipv6_route_map_cmd); } - if_rmap_ctx_list = list_new(); } void if_rmap_terminate(void) { - if (!if_rmap_ctx_list) - return; - list_delete(&if_rmap_ctx_list); } diff --git a/lib/if_rmap.h b/lib/if_rmap.h index 3bdbc2a3b2..6f5fb578f0 100644 --- a/lib/if_rmap.h +++ b/lib/if_rmap.h @@ -6,15 +6,20 @@ #ifndef _ZEBRA_IF_RMAP_H #define _ZEBRA_IF_RMAP_H +#include "typesafe.h" + #ifdef __cplusplus extern "C" { #endif +struct lyd_node; +struct vty; + enum if_rmap_type { IF_RMAP_IN, IF_RMAP_OUT, IF_RMAP_MAX }; struct if_rmap { /* Name of the interface. */ - char *ifname; + const char *ifname; char *routemap[IF_RMAP_MAX]; }; @@ -45,6 +50,11 @@ void if_rmap_hook_delete(struct if_rmap_ctx *ctx, struct if_rmap *)); extern struct if_rmap *if_rmap_lookup(struct if_rmap_ctx *ctx, const char *ifname); +extern void if_rmap_yang_modify_cb(struct if_rmap_ctx *ctx, + const struct lyd_node *dnode, + enum if_rmap_type type, bool del); +extern void if_rmap_yang_destroy_cb(struct if_rmap_ctx *ctx, + const struct lyd_node *dnode); extern int config_write_if_rmap(struct vty *, struct if_rmap_ctx *ctx); #ifdef __cplusplus diff --git a/lib/link_state.c b/lib/link_state.c index 076030a839..7f20cdcf5e 100644 --- a/lib/link_state.c +++ b/lib/link_state.c @@ -1907,6 +1907,20 @@ void ls_delete_msg(struct ls_message *msg) if (msg == NULL) return; + if (msg->event == LS_MSG_EVENT_DELETE) { + switch (msg->type) { + case LS_MSG_TYPE_NODE: + ls_node_del(msg->data.node); + break; + case LS_MSG_TYPE_ATTRIBUTES: + ls_attributes_del(msg->data.attr); + break; + case LS_MSG_TYPE_PREFIX: + ls_prefix_del(msg->data.prefix); + break; + } + } + XFREE(MTYPE_LS_DB, msg); } diff --git a/lib/subdir.am b/lib/subdir.am index 83eecbee57..dcc58b31ae 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -174,6 +174,7 @@ clippy_scan += \ lib/affinitymap_cli.c \ lib/if.c \ lib/filter_cli.c \ + lib/if_rmap.c \ lib/log_vty.c \ lib/nexthop_group.c \ lib/northbound_cli.c \ diff --git a/ospf6d/ospf6_gr_helper.c b/ospf6d/ospf6_gr_helper.c index d313510cfa..216d78c1cc 100644 --- a/ospf6d/ospf6_gr_helper.c +++ b/ospf6d/ospf6_gr_helper.c @@ -937,12 +937,22 @@ static void show_ospf6_gr_helper_details(struct vty *vty, struct ospf6 *ospf6, (ospf6->ospf6_helper_cfg.strict_lsa_check) ? "Enabled" : "Disabled"); + +#if CONFDATE > 20240401 + CPP_NOTICE("Remove deprecated json key: restartSupoort") +#endif json_object_string_add( json, "restartSupoort", (ospf6->ospf6_helper_cfg.only_planned_restart) ? "Planned Restart only" : "Planned and Unplanned Restarts"); + json_object_string_add( + json, "restartSupport", + (ospf6->ospf6_helper_cfg.only_planned_restart) + ? "Planned Restart only" + : "Planned and Unplanned Restarts"); + json_object_int_add( json, "supportedGracePeriod", ospf6->ospf6_helper_cfg.supported_grace_time); diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c index 87b683b15d..9e2dd7a457 100644 --- a/ospfd/ospf_lsa.c +++ b/ospfd/ospf_lsa.c @@ -2013,7 +2013,7 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf, struct ospf_lsa *type7, struct ospf_lsa *type5) { - struct ospf_lsa *new; + struct ospf_lsa *new, *translated_lsa; struct as_external_lsa *extnew; if (ospf->gr_info.restart_in_progress) { @@ -2027,7 +2027,8 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf, * the OSPF_LSA_LOCAL_XLT flag, must originate by hand */ - if ((new = ospf_lsa_translated_nssa_new(ospf, type7)) == NULL) { + if ((translated_lsa = ospf_lsa_translated_nssa_new(ospf, type7)) == + NULL) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( "%s: Could not translate Type-7, Id %pI4, to Type-5", @@ -2035,16 +2036,17 @@ struct ospf_lsa *ospf_translated_nssa_originate(struct ospf *ospf, return NULL; } - extnew = (struct as_external_lsa *)new->data; + extnew = (struct as_external_lsa *)translated_lsa->data; /* Update LSA sequence number from translated Type-5 LSA */ if (type5) - new->data->ls_seqnum = lsa_seqnum_increment(type5); + translated_lsa->data->ls_seqnum = lsa_seqnum_increment(type5); - if ((new = ospf_lsa_install(ospf, NULL, new)) == NULL) { + if ((new = ospf_lsa_install(ospf, NULL, translated_lsa)) == NULL) { flog_warn(EC_OSPF_LSA_INSTALL_FAILURE, "%s: Could not install LSA id %pI4", __func__, &type7->data->id); + ospf_lsa_free(translated_lsa); return NULL; } @@ -2067,7 +2069,7 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, struct ospf_lsa *type7, struct ospf_lsa *type5) { - struct ospf_lsa *new = NULL; + struct ospf_lsa *new = NULL, *translated_lsa = NULL; struct as_external_lsa *extold = NULL; uint32_t ls_seqnum = 0; @@ -2143,7 +2145,8 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, ospf_ls_retransmit_delete_nbr_as(ospf, type5); /* create new translated LSA */ - if ((new = ospf_lsa_translated_nssa_new(ospf, type7)) == NULL) { + if ((translated_lsa = ospf_lsa_translated_nssa_new(ospf, type7)) == + NULL) { if (IS_DEBUG_OSPF_NSSA) zlog_debug( "%s: Could not translate Type-7 for %pI4 to Type-5", @@ -2153,13 +2156,14 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf, if (type7->area->suppress_fa == 1) { if (extold->e[0].fwd_addr.s_addr == 0) - new->data->ls_seqnum = htonl(ls_seqnum + 1); + translated_lsa->data->ls_seqnum = htonl(ls_seqnum + 1); } - if (!(new = ospf_lsa_install(ospf, NULL, new))) { + if (!(new = ospf_lsa_install(ospf, NULL, translated_lsa))) { flog_warn(EC_OSPF_LSA_INSTALL_FAILURE, "%s: Could not install translated LSA, Id %pI4", __func__, &type7->data->id); + ospf_lsa_free(translated_lsa); return NULL; } diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 3c0e0fcb63..edec27fc09 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -10096,12 +10096,21 @@ static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf, json_object_string_add(json_vrf, "strictLsaCheck", (ospf->strict_lsa_check) ? "Enabled" : "Disabled"); +#if CONFDATE > 20240401 + CPP_NOTICE("Remove deprecated json key: restartSupoort") +#endif json_object_string_add( json_vrf, "restartSupoort", (ospf->only_planned_restart) ? "Planned Restart only" : "Planned and Unplanned Restarts"); + json_object_string_add( + json_vrf, "restartSupport", + (ospf->only_planned_restart) + ? "Planned Restart only" + : "Planned and Unplanned Restarts"); + json_object_int_add(json_vrf, "supportedGracePeriod", ospf->supported_grace_time); diff --git a/ripd/rip_nb.c b/ripd/rip_nb.c index c332b2a5b7..1a7b34adde 100644 --- a/ripd/rip_nb.c +++ b/ripd/rip_nb.c @@ -166,6 +166,27 @@ const struct frr_yang_module_info frr_ripd_info = { }, }, { + .xpath = "/frr-ripd:ripd/instance/if-route-maps/if-route-map", + .cbs = { + .create = ripd_instance_if_route_maps_if_route_map_create, + .destroy = ripd_instance_if_route_maps_if_route_map_destroy, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/if-route-maps/if-route-map/in-route-map", + .cbs = { + .modify = ripd_instance_if_route_maps_if_route_map_in_route_map_modify, + .destroy = ripd_instance_if_route_maps_if_route_map_in_route_map_destroy, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/if-route-maps/if-route-map/out-route-map", + .cbs = { + .modify = ripd_instance_if_route_maps_if_route_map_out_route_map_modify, + .destroy = ripd_instance_if_route_maps_if_route_map_out_route_map_destroy, + } + }, + { .xpath = "/frr-ripd:ripd/instance/static-route", .cbs = { .cli_show = cli_show_rip_route, diff --git a/ripd/rip_nb.h b/ripd/rip_nb.h index a30e579e1c..ebc60fefb4 100644 --- a/ripd/rip_nb.h +++ b/ripd/rip_nb.h @@ -52,6 +52,18 @@ int ripd_instance_redistribute_route_map_destroy( struct nb_cb_destroy_args *args); int ripd_instance_redistribute_metric_modify(struct nb_cb_modify_args *args); int ripd_instance_redistribute_metric_destroy(struct nb_cb_destroy_args *args); +int ripd_instance_if_route_maps_if_route_map_create( + struct nb_cb_create_args *args); +int ripd_instance_if_route_maps_if_route_map_destroy( + struct nb_cb_destroy_args *args); +int ripd_instance_if_route_maps_if_route_map_in_route_map_modify( + struct nb_cb_modify_args *args); +int ripd_instance_if_route_maps_if_route_map_in_route_map_destroy( + struct nb_cb_destroy_args *args); +int ripd_instance_if_route_maps_if_route_map_out_route_map_modify( + struct nb_cb_modify_args *args); +int ripd_instance_if_route_maps_if_route_map_out_route_map_destroy( + struct nb_cb_destroy_args *args); int ripd_instance_static_route_create(struct nb_cb_create_args *args); int ripd_instance_static_route_destroy(struct nb_cb_destroy_args *args); int ripd_instance_timers_flush_interval_modify(struct nb_cb_modify_args *args); diff --git a/ripd/rip_nb_config.c b/ripd/rip_nb_config.c index 2277ddc204..343bb9bb57 100644 --- a/ripd/rip_nb_config.c +++ b/ripd/rip_nb_config.c @@ -3,6 +3,7 @@ * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro <kunihiro@zebra.org> * Copyright (C) 2018 NetDEF, Inc. * Renato Westphal + * Copyright (C) 2023 LabN Consulting, L.L.C. */ #include <zebra.h> @@ -13,6 +14,7 @@ #include "prefix.h" #include "table.h" #include "command.h" +#include "if_rmap.h" #include "routemap.h" #include "northbound.h" #include "libfrr.h" @@ -681,6 +683,94 @@ int ripd_instance_redistribute_metric_destroy(struct nb_cb_destroy_args *args) } /* + * XPath: /frr-ripd:ripd/instance/if-route-maps/if-route-map + */ +int ripd_instance_if_route_maps_if_route_map_create( + struct nb_cb_create_args *args) +{ + /* if_rmap is created when first routemap is added */ + return NB_OK; +} + +int ripd_instance_if_route_maps_if_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + struct rip *rip; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + /* + * YANG will prune edit deletes up to the most general deleted node so + * we need to handle deleting any existing state underneath and not + * count on those more specific callbacks being called individually. + */ + + rip = nb_running_get_entry(args->dnode, NULL, true); + if_rmap_yang_destroy_cb(rip->if_rmap_ctx, args->dnode); + + return NB_OK; +} + +static void if_route_map_modify(const struct lyd_node *dnode, + enum if_rmap_type type, bool delete) +{ + struct rip *rip = nb_running_get_entry(dnode, NULL, true); + + if_rmap_yang_modify_cb(rip->if_rmap_ctx, dnode, type, delete); +} + +/* + * XPath: /frr-ripd:ripd/instance/if-route-maps/if-route-map/in-route-map + */ +int ripd_instance_if_route_maps_if_route_map_in_route_map_modify( + struct nb_cb_modify_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_IN, false); + + return NB_OK; +} + +int ripd_instance_if_route_maps_if_route_map_in_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_IN, true); + + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/if-route-maps/if-route-map/out-route-map + */ +int ripd_instance_if_route_maps_if_route_map_out_route_map_modify( + struct nb_cb_modify_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_OUT, false); + + return NB_OK; +} + +int ripd_instance_if_route_maps_if_route_map_out_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_OUT, true); + + return NB_OK; +} + +/* * XPath: /frr-ripd:ripd/instance/static-route */ int ripd_instance_static_route_create(struct nb_cb_create_args *args) diff --git a/ripngd/ripng_nb.c b/ripngd/ripng_nb.c index 63144d866b..2f412e5197 100644 --- a/ripngd/ripng_nb.c +++ b/ripngd/ripng_nb.c @@ -115,6 +115,27 @@ const struct frr_yang_module_info frr_ripngd_info = { }, }, { + .xpath = "/frr-ripngd:ripngd/instance/if-route-maps/if-route-map", + .cbs = { + .create = ripngd_instance_if_route_maps_if_route_map_create, + .destroy = ripngd_instance_if_route_maps_if_route_map_destroy, + } + }, + { + .xpath = "/frr-ripngd:ripngd/instance/if-route-maps/if-route-map/in-route-map", + .cbs = { + .modify = ripngd_instance_if_route_maps_if_route_map_in_route_map_modify, + .destroy = ripngd_instance_if_route_maps_if_route_map_in_route_map_destroy, + } + }, + { + .xpath = "/frr-ripngd:ripngd/instance/if-route-maps/if-route-map/out-route-map", + .cbs = { + .modify = ripngd_instance_if_route_maps_if_route_map_out_route_map_modify, + .destroy = ripngd_instance_if_route_maps_if_route_map_out_route_map_destroy, + } + }, + { .xpath = "/frr-ripngd:ripngd/instance/static-route", .cbs = { .cli_show = cli_show_ripng_route, diff --git a/ripngd/ripng_nb.h b/ripngd/ripng_nb.h index 675cef7c92..1c0e63c241 100644 --- a/ripngd/ripng_nb.h +++ b/ripngd/ripng_nb.h @@ -39,6 +39,18 @@ int ripngd_instance_redistribute_route_map_destroy( int ripngd_instance_redistribute_metric_modify(struct nb_cb_modify_args *args); int ripngd_instance_redistribute_metric_destroy( struct nb_cb_destroy_args *args); +int ripngd_instance_if_route_maps_if_route_map_create( + struct nb_cb_create_args *args); +int ripngd_instance_if_route_maps_if_route_map_destroy( + struct nb_cb_destroy_args *args); +int ripngd_instance_if_route_maps_if_route_map_in_route_map_modify( + struct nb_cb_modify_args *args); +int ripngd_instance_if_route_maps_if_route_map_in_route_map_destroy( + struct nb_cb_destroy_args *args); +int ripngd_instance_if_route_maps_if_route_map_out_route_map_modify( + struct nb_cb_modify_args *args); +int ripngd_instance_if_route_maps_if_route_map_out_route_map_destroy( + struct nb_cb_destroy_args *args); int ripngd_instance_static_route_create(struct nb_cb_create_args *args); int ripngd_instance_static_route_destroy(struct nb_cb_destroy_args *args); int ripngd_instance_aggregate_address_create(struct nb_cb_create_args *args); diff --git a/ripngd/ripng_nb_config.c b/ripngd/ripng_nb_config.c index 006bf79ce8..30f707e061 100644 --- a/ripngd/ripng_nb_config.c +++ b/ripngd/ripng_nb_config.c @@ -3,6 +3,7 @@ * Copyright (C) 1998 Kunihiro Ishiguro * Copyright (C) 2018 NetDEF, Inc. * Renato Westphal + * Copyright (C) 2023 LabN Consulting, L.L.C. */ #include <zebra.h> @@ -13,6 +14,7 @@ #include "prefix.h" #include "table.h" #include "command.h" +#include "if_rmap.h" #include "routemap.h" #include "agg_table.h" #include "northbound.h" @@ -503,6 +505,93 @@ int ripngd_instance_redistribute_metric_destroy(struct nb_cb_destroy_args *args) } /* + * XPath: /frr-ripngd:ripngd/instance/if-route-maps/if-route-map + */ +int ripngd_instance_if_route_maps_if_route_map_create( + struct nb_cb_create_args *args) +{ + /* if_rmap is created when first routemap is added */ + return NB_OK; +} + +int ripngd_instance_if_route_maps_if_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + struct ripng *ripng; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + /* + * YANG will prune edit deletes up to the most general deleted node so + * we need to handle deleting any existing state underneath and not + * count on those more specific callbacks being called individually. + */ + + ripng = nb_running_get_entry(args->dnode, NULL, true); + if_rmap_yang_destroy_cb(ripng->if_rmap_ctx, args->dnode); + + return NB_OK; +} + +static void if_route_map_modify(const struct lyd_node *dnode, + enum if_rmap_type type, bool delete) +{ + struct ripng *ripng = nb_running_get_entry(dnode, NULL, true); + + if_rmap_yang_modify_cb(ripng->if_rmap_ctx, dnode, type, delete); +} +/* + * XPath: /frr-ripng:ripng/instance/if-route-maps/if-route-map/in-route-map + */ +int ripngd_instance_if_route_maps_if_route_map_in_route_map_modify( + struct nb_cb_modify_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_IN, false); + + return NB_OK; +} + +int ripngd_instance_if_route_maps_if_route_map_in_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_IN, true); + + return NB_OK; +} + +/* + * XPath: /frr-ripngd:ripngd/instance/if-route-maps/if-route-map/out-route-map + */ +int ripngd_instance_if_route_maps_if_route_map_out_route_map_modify( + struct nb_cb_modify_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_OUT, false); + + return NB_OK; +} + +int ripngd_instance_if_route_maps_if_route_map_out_route_map_destroy( + struct nb_cb_destroy_args *args) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + + if_route_map_modify(args->dnode, IF_RMAP_OUT, true); + + return NB_OK; +} + +/* * XPath: /frr-ripngd:ripngd/instance/static-route */ int ripngd_instance_static_route_create(struct nb_cb_create_args *args) diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py index 23b1f2e533..4a018a08db 100644 --- a/tests/topotests/lib/ospf.py +++ b/tests/topotests/lib/ospf.py @@ -2477,7 +2477,7 @@ def verify_ospf_gr_helper(tgen, topo, dut, input_dict=None): input_dict = { "helperSupport":"Disabled", "strictLsaCheck":"Enabled", - "restartSupoort":"Planned and Unplanned Restarts", + "restartSupport":"Planned and Unplanned Restarts", "supportedGracePeriod":1800 } result = verify_ospf_gr_helper(tgen, topo, dut, input_dict) diff --git a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper1.py b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper1.py index 9dce5a976d..79374281cb 100644 --- a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper1.py +++ b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper1.py @@ -188,7 +188,7 @@ def test_ospf_gr_helper_tc1_p0(request): input_dict = { "helperSupport": "Disabled", "strictLsaCheck": "Enabled", - "restartSupoort": "Planned and Unplanned Restarts", + "restartSupport": "Planned and Unplanned Restarts", "supportedGracePeriod": 1800, } dut = "r0" @@ -220,7 +220,7 @@ def test_ospf_gr_helper_tc1_p0(request): input_dict = { "helperSupport": "Enabled", "strictLsaCheck": "Enabled", - "restartSupoort": "Planned and Unplanned Restarts", + "restartSupport": "Planned and Unplanned Restarts", "supportedGracePeriod": 1800, } dut = "r0" diff --git a/yang/frr-if-rmap.yang b/yang/frr-if-rmap.yang new file mode 100644 index 0000000000..0fa2c5eddf --- /dev/null +++ b/yang/frr-if-rmap.yang @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: BSD-2-Clause +module frr-if-rmap { + yang-version 1.1; + namespace "http://frrouting.org/yang/frr-if-rmap"; + prefix frr-if-map; + + import frr-interface { + prefix frr-interface; + } + + import frr-route-map { + prefix frr-route-map; + } + + organization + "FRRouting"; + contact + "FRR Users List: <mailto:frog@lists.frrouting.org> + FRR Development List: <mailto:dev@lists.frrouting.org>"; + description + "This module defines route map settings + + Copyright 2023 LabN Consulting L.L.C + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; + + revision 2023-04-09 { + description + "Initial revision"; + reference "FRRouting"; + } + + grouping if-route-maps-group { + description "Grouping for interface route maps"; + + container if-route-maps { + description "Collection of interface route-maps"; + + list if-route-map { + must "in-route-map or out-route-map"; + key "interface"; + description "Collection of route-maps for an interface"; + + leaf "interface" { + type frr-interface:interface-ref; + description "The interface the route maps are associated with"; + } + leaf "in-route-map" { + type frr-route-map:route-map-name; + description "Name of the ingress route map"; + } + leaf "out-route-map" { + type frr-route-map:route-map-name; + description "Name of the egress route map"; + } + } + } + } +} diff --git a/yang/frr-ripd.yang b/yang/frr-ripd.yang index 24fe588854..d2088e589e 100644 --- a/yang/frr-ripd.yang +++ b/yang/frr-ripd.yang @@ -10,6 +10,9 @@ module frr-ripd { import ietf-yang-types { prefix yang; } + import frr-if-rmap { + prefix frr-if-rmap; + } import frr-interface { prefix frr-interface; } @@ -282,6 +285,9 @@ module frr-ripd { is 0."; } } + + uses frr-if-rmap:if-route-maps-group; + leaf-list static-route { type inet:ipv4-prefix; description diff --git a/yang/frr-ripngd.yang b/yang/frr-ripngd.yang index d7de4c398a..7b2b135fb5 100644 --- a/yang/frr-ripngd.yang +++ b/yang/frr-ripngd.yang @@ -10,6 +10,9 @@ module frr-ripngd { import ietf-yang-types { prefix yang; } + import frr-if-rmap { + prefix frr-if-rmap; + } import frr-interface { prefix frr-interface; } @@ -196,6 +199,9 @@ module frr-ripngd { is 0."; } } + + uses frr-if-rmap:if-route-maps-group; + leaf-list static-route { type inet:ipv6-prefix; description diff --git a/yang/subdir.am b/yang/subdir.am index 82a6a01474..eb17c38dbc 100644 --- a/yang/subdir.am +++ b/yang/subdir.am @@ -24,6 +24,7 @@ dist_yangmodels_DATA += yang/frr-filter.yang dist_yangmodels_DATA += yang/frr-module-translator.yang dist_yangmodels_DATA += yang/frr-nexthop.yang dist_yangmodels_DATA += yang/frr-test-module.yang +dist_yangmodels_DATA += yang/frr-if-rmap.yang dist_yangmodels_DATA += yang/frr-interface.yang dist_yangmodels_DATA += yang/frr-route-map.yang dist_yangmodels_DATA += yang/frr-zebra-route-map.yang diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index f9253ebf76..e821572c5d 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -3745,6 +3745,11 @@ dplane_route_update_internal(struct route_node *rn, NEXTHOP_FLAG_FIB); } + if ((op == DPLANE_OP_ROUTE_UPDATE) && old_re && re && + (old_re != re) && + !CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) + SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED); + dplane_ctx_free(&ctx); return ZEBRA_DPLANE_REQUEST_SUCCESS; } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 32cfa4d04c..adcaf64044 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -3766,6 +3766,9 @@ static void rib_meta_queue_gr_run_free(struct meta_queue *mq, struct list *l, continue; XFREE(MTYPE_WQ_WRAPPER, gr_run); + node->data = NULL; + list_delete_node(l, node); + mq->size--; } } |
