summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/rfapi/rfapi.c27
-rw-r--r--bgpd/rfapi/rfapi_rib.c19
-rw-r--r--bgpd/rfapi/rfapi_vty.c1
-rw-r--r--lib/if_rmap.c292
-rw-r--r--lib/if_rmap.h12
-rw-r--r--lib/link_state.c14
-rw-r--r--lib/subdir.am1
-rw-r--r--ospf6d/ospf6_gr_helper.c10
-rw-r--r--ospfd/ospf_lsa.c22
-rw-r--r--ospfd/ospf_vty.c9
-rw-r--r--ripd/rip_nb.c21
-rw-r--r--ripd/rip_nb.h12
-rw-r--r--ripd/rip_nb_config.c90
-rw-r--r--ripngd/ripng_nb.c21
-rw-r--r--ripngd/ripng_nb.h12
-rw-r--r--ripngd/ripng_nb_config.c89
-rw-r--r--tests/topotests/lib/ospf.py2
-rw-r--r--tests/topotests/ospf_gr_helper/test_ospf_gr_helper1.py4
-rw-r--r--yang/frr-if-rmap.yang80
-rw-r--r--yang/frr-ripd.yang6
-rw-r--r--yang/frr-ripngd.yang6
-rw-r--r--yang/subdir.am1
-rw-r--r--zebra/zebra_dplane.c5
-rw-r--r--zebra/zebra_rib.c3
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--;
}
}