diff options
| author | Christian Hopps <chopps@labn.net> | 2023-04-09 05:02:51 -0400 | 
|---|---|---|
| committer | Christian Hopps <chopps@labn.net> | 2023-04-11 15:27:05 -0400 | 
| commit | efa2ca6ef0ec09625fc01a9106b183f750361767 (patch) | |
| tree | a29244c0838f1ae79aad82d1a9e35fb4db2909e4 /lib/if_rmap.c | |
| parent | 2eb44711146d15af97873e0ca87ea570f2d11de0 (diff) | |
lib: convert if_rmap to YANG northbound
- nice correspondence between new YANG grouping and shared library code.
- fixes bug with RIPNG use, certainly didn't work before.
- removes rip header from shared library code
- still has uses RIP_NODE/RIPNG_NODE as required by CLI foo.
Signed-off-by: Christian Hopps <chopps@labn.net>
Diffstat (limited to 'lib/if_rmap.c')
| -rw-r--r-- | lib/if_rmap.c | 277 | 
1 files changed, 144 insertions, 133 deletions
diff --git a/lib/if_rmap.c b/lib/if_rmap.c index ae9c107187..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,16 +44,11 @@ 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;  } @@ -80,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;  } @@ -108,58 +101,32 @@ 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); @@ -169,80 +136,131 @@ static int if_rmap_unset(struct if_rmap_ctx *ctx,  		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);  } @@ -279,10 +297,8 @@ int config_write_if_rmap(struct vty *vty, struct if_rmap_ctx *ctx)  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);  } @@ -297,25 +313,20 @@ struct if_rmap_ctx *if_rmap_ctx_create(const char *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);  	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);  }  | 
