From dc8f1360641596bf7e88f983fbeaafed332d88cf Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Sat, 20 Jan 2024 00:33:09 +0000 Subject: [PATCH 1/5] lib: cleanup yang lint warnings Signed-off-by: Christian Hopps --- yang/frr-filter.yang | 124 +++++++++++++++++++++---------------------- yang/frr-ripd.yang | 5 +- 2 files changed, 63 insertions(+), 66 deletions(-) diff --git a/yang/frr-filter.yang b/yang/frr-filter.yang index a1946d8342..867e59826c 100644 --- a/yang/frr-filter.yang +++ b/yang/frr-filter.yang @@ -45,114 +45,112 @@ module frr-filter { revision 2019-07-04 { description "Initial revision"; + reference "FRRouting"; } /* * Types. */ typedef access-list-name { - description "Access list name formatting"; type string { length 1..128; } + description "Access list name formatting"; } typedef access-list-sequence { - description "Access list sequence number"; type uint32 { range "1..4294967295"; } + description "Access list sequence number"; } typedef access-list-action { - description "Access list return action on match"; type enumeration { enum deny { - description "Deny an entry"; value 0; + description "Deny an entry"; } enum permit { - description "Accept an entry"; value 1; + description "Accept an entry"; } } + description "Access list return action on match"; } /* * Configuration data. */ container lib { + description "Filter library"; list access-list { + key "type name"; description "Access list instance"; - key "type name"; - leaf type { - description "Access list content type"; type enumeration { enum ipv4 { - description "Internet Protocol address version 4"; value 0; + description "Internet Protocol address version 4"; } enum ipv6 { - description "Internet Protocol address version 6"; value 1; + description "Internet Protocol address version 6"; } enum mac { - description "Media Access Control address"; value 2; + description "Media Access Control address"; } } + description "Access list content type"; } leaf name { - description "Access list name"; type access-list-name; + description "Access list name"; } leaf remark { - description "Access list remark"; type string; + description "Access list remark"; } list entry { - description "Access list entry"; - key "sequence"; - + description "Access list entry"; leaf sequence { - description "Access list sequence value"; type access-list-sequence; + description "Access list sequence value"; } - leaf action { - description "Access list action on match"; type access-list-action; mandatory true; + description "Access list action on match"; } choice value { - description "Access list value to match"; mandatory true; + description "Access list value to match"; case ipv4-prefix { when "../type = 'ipv4'"; choice style { - description "Access list entry style selection: zebra or cisco."; mandatory true; + description "Access list entry style selection: zebra or cisco."; case zebra { leaf ipv4-prefix { - description "Configure IPv4 prefix to match"; type inet:ipv4-prefix; mandatory true; + description "Configure IPv4 prefix to match"; } leaf ipv4-exact-match { - description "Exact match of prefix"; type boolean; default false; + description "Exact match of prefix"; } } case cisco { @@ -160,19 +158,20 @@ module frr-filter { description "Source value to match"; leaf host { - description "Host to match"; type inet:ipv4-address; + description "Host to match"; } container network { + description "Network to match"; leaf address { + type inet:ipv4-address; mandatory true; description "Network address part."; - type inet:ipv4-address; } leaf mask { + type inet:ipv4-address; mandatory true; description "Network mask/wildcard part."; - type inet:ipv4-address; } } leaf source-any { @@ -180,8 +179,8 @@ module frr-filter { * Was `any`, however it conflicts with `any` leaf * outside this choice. */ - description "Match any"; type empty; + description "Match any"; } } @@ -189,24 +188,25 @@ module frr-filter { description "Destination value to match"; leaf destination-host { - description "Host to match"; type inet:ipv4-address; + description "Host to match"; } container destination-network { + description "Destination network to match"; leaf address { + type inet:ipv4-address; mandatory true; description "Network address part."; - type inet:ipv4-address; } leaf mask { + type inet:ipv4-address; mandatory true; description "Network mask/wildcard part."; - type inet:ipv4-address; } } leaf destination-any { - description "Match any"; type empty; + description "Match any"; } } } @@ -216,29 +216,29 @@ module frr-filter { when "../type = 'ipv6'"; leaf ipv6-prefix { - description "Configure IPv6 prefix to match"; type inet:ipv6-prefix; mandatory true; + description "Configure IPv6 prefix to match"; } leaf ipv6-exact-match { - description "Exact match of prefix"; type boolean; default false; + description "Exact match of prefix"; } } case mac { when "../type = 'mac'"; leaf mac { - description "Configure MAC address to match"; type yang:mac-address; + description "Configure MAC address to match"; } } case any { leaf any { - description "Match anything"; type empty; + description "Match anything"; } } } @@ -246,108 +246,104 @@ module frr-filter { } list prefix-list { - description "Prefix list instance"; - key "type name"; - + description "Prefix list instance"; leaf type { - description "Prefix list type"; type enumeration { enum ipv4 { - description "Internet Protocol address version 4"; value 0; + description "Internet Protocol address version 4"; } enum ipv6 { - description "Internet Protocol address version 6"; value 1; + description "Internet Protocol address version 6"; } } + description "Prefix list type"; } leaf name { - description "Prefix list name"; type access-list-name; + description "Prefix list name"; } leaf remark { - description "Prefix list user description"; type string; + description "Prefix list user description"; } list entry { - description "Prefix list entry"; - key "sequence"; - + description "Prefix list entry"; leaf sequence { - description "Prefix list sequence value"; type access-list-sequence; + description "Prefix list sequence value"; } leaf action { - description "Prefix list action on match"; type access-list-action; mandatory true; + description "Prefix list action on match"; } choice value { - description "Prefix list value to match"; mandatory true; + description "Prefix list value to match"; case ipv4-prefix { leaf ipv4-prefix { - description "Configure IPv4 prefix to match"; type inet:ipv4-prefix; mandatory true; + description "Configure IPv4 prefix to match"; } leaf ipv4-prefix-length-greater-or-equal { + type uint8 { + range "0..32"; + } description "Specifies if matching prefixes with length greater than or equal to value"; - type uint8 { - range "0..32"; - } } leaf ipv4-prefix-length-lesser-or-equal { - description - "Specifies if matching prefixes with length lesser than - or equal to value"; type uint8 { range "0..32"; } + description + "Specifies if matching prefixes with length lesser than + or equal to value"; } } case ipv6-prefix { leaf ipv6-prefix { - description "Configure IPv6 prefix to match"; type inet:ipv6-prefix; mandatory true; + description "Configure IPv6 prefix to match"; } leaf ipv6-prefix-length-greater-or-equal { + type uint8 { + range "0..128"; + } description "Specifies if matching prefixes with length greater than or equal to value"; - type uint8 { - range "0..128"; - } } leaf ipv6-prefix-length-lesser-or-equal { - description - "Specifies if matching prefixes with length lesser than - or equal to value"; type uint8 { range "0..128"; } + description + "Specifies if matching prefixes with length lesser than + or equal to value"; } } case any { leaf any { - description "Match anything"; type empty; + description "Match anything"; } } } diff --git a/yang/frr-ripd.yang b/yang/frr-ripd.yang index 5f85a4cabc..756e70b292 100644 --- a/yang/frr-ripd.yang +++ b/yang/frr-ripd.yang @@ -380,9 +380,9 @@ module frr-ripd { } leaf default-bfd-profile { + type frr-bfdd:profile-ref; description "Use this BFD profile for all peers by default."; - type frr-bfdd:profile-ref; } /* @@ -691,12 +691,13 @@ module frr-ripd { container bfd-monitoring { presence "Present if BFD is configured for RIP peers in this interface."; + description "Configure BFD use in RIPD"; leaf enable { type boolean; + default false; description "Enable/disable BFD monitoring."; - default false; } leaf profile { From eba64f79cc9090a1a706291442dc02597e359cac Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Sun, 21 Jan 2024 13:12:39 +0000 Subject: [PATCH 2/5] lib: add northbound support to distribute-list code. Signed-off-by: Christian Hopps --- lib/distribute.c | 123 ++++++++++++++++++++++++++++++++++++++++++- lib/distribute.h | 31 +++++++++++ yang/frr-filter.yang | 74 +++++++++++++++++++++++--- 3 files changed, 221 insertions(+), 7 deletions(-) diff --git a/lib/distribute.c b/lib/distribute.c index 65487676d6..719bac4faa 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -274,7 +274,8 @@ int distribute_list_no_parser(struct vty *vty, bool prefix, bool v4, ret = distfn(ctx, ifname, type, list); if (!ret) { - vty_out(vty, "distribute list doesn't exist\n"); + if (vty) + vty_out(vty, "distribute list doesn't exist\n"); return CMD_WARNING_CONFIG_FAILED; } @@ -443,6 +444,126 @@ int config_write_distribute(struct vty *vty, return write; } +/* ---------- */ +/* Northbound */ +/* ---------- */ + +int group_distribute_list_create_helper( + struct nb_cb_create_args *args, struct distribute_ctx *ctx) +{ + /* The code currently doesn't require this as it uses a global */ + /* nb_running_set_entry(args->dnode, ctx); */ + return NB_OK; +} + +/* + * XPath: /frr-ripd:ripd/instance/distribute-lists/distribute-list/{in,out}/{access,prefix}-list + */ + +int group_distribute_list_destroy(struct nb_cb_destroy_args *args) +{ + nb_running_unset_entry(args->dnode); + return NB_OK; +} + +static int distribute_list_leaf_update(const struct lyd_node *dnode, + int ip_version, bool no) +{ + struct lyd_node *dir_node = lyd_parent(dnode); + struct lyd_node_inner *list_node = dir_node->parent; + struct lyd_node *intf_key = list_node->child; + bool ipv4 = ip_version == 4 ? true : false; + bool prefix; + + /* The code currently doesn't require this as it uses a global */ + /* ctx = nb_running_get_entry_non_rec(&list_node->node, NULL, false); */ + + prefix = dnode->schema->name[0] == 'p' ? true : false; + if (no) + distribute_list_no_parser(NULL, prefix, ipv4, + dir_node->schema->name, + lyd_get_value(dnode), + lyd_get_value(intf_key)); + else + distribute_list_parser(prefix, ipv4, + dir_node->schema->name, + lyd_get_value(dnode), + lyd_get_value(intf_key)); + return NB_OK; +} + +static int distribute_list_leaf_modify(struct nb_cb_modify_args *args, + int ip_version) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + return distribute_list_leaf_update(args->dnode, ip_version, false); +} + +static int distribute_list_leaf_destroy(struct nb_cb_destroy_args *args, + int ip_version) +{ + if (args->event != NB_EV_APPLY) + return NB_OK; + return distribute_list_leaf_update(args->dnode, ip_version, true); +} + +int group_distribute_list_ipv4_modify(struct nb_cb_modify_args *args) +{ + return distribute_list_leaf_modify(args, 4); +} +int group_distribute_list_ipv4_destroy(struct nb_cb_destroy_args *args) +{ + return distribute_list_leaf_destroy(args, 4); +} +int group_distribute_list_ipv6_modify(struct nb_cb_modify_args *args) +{ + return distribute_list_leaf_modify(args, 6); +} +int group_distribute_list_ipv6_destroy(struct nb_cb_destroy_args *args) +{ + return distribute_list_leaf_destroy(args, 6); +} + +static int distribute_list_leaf_cli_show(struct vty *vty, + const struct lyd_node *dnode, + int ip_version) +{ + struct lyd_node *dir_node = lyd_parent(dnode); + struct lyd_node_inner *list_node = dir_node->parent; + struct lyd_node *intf_key = list_node->child; + bool ipv6 = ip_version == 6 ? true : false; + bool prefix; + + prefix = dnode->schema->name[0] == 'p' ? true : false; + vty_out(vty, + " %sdistribute-list %s%s %s %s\n", + ipv6 ? "ipv6 " : "", + prefix ? "prefix " : "", + lyd_get_value(dnode), + dir_node->schema->name, + lyd_get_value(intf_key)); + + return NB_OK; +} + +void group_distribute_list_ipv4_cli_show(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + distribute_list_leaf_cli_show(vty, dnode, 4); +} +void group_distribute_list_ipv6_cli_show(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults) +{ + distribute_list_leaf_cli_show(vty, dnode, 6); +} + +/* ------------- */ +/* Setup/Cleanup */ +/* ------------- */ + void distribute_list_delete(struct distribute_ctx **ctx) { hash_clean_and_free(&(*ctx)->disthash, diff --git a/lib/distribute.h b/lib/distribute.h index 75783712a1..6fe890c045 100644 --- a/lib/distribute.h +++ b/lib/distribute.h @@ -9,6 +9,7 @@ #include #include "if.h" #include "filter.h" +#include "northbound.h" #ifdef __cplusplus extern "C" { @@ -74,6 +75,36 @@ extern int distribute_list_parser(bool prefix, bool v4, const char *dir, extern int distribute_list_no_parser(struct vty *vty, bool prefix, bool v4, const char *dir, const char *list, const char *ifname); + +/* + * Northbound + */ + +/* + * Define your own create callback and then call thes helper with your + * distribute list context when a list entry is created. Additionally, plug the + * destroy callback into the frr_module_yang_info struct, or call it if you have + * your own callback destroy function. + */ +extern int group_distribute_list_create_helper(struct nb_cb_create_args *args, + struct distribute_ctx *ctx); +extern int group_distribute_list_destroy(struct nb_cb_destroy_args *args); + +/* + * Plug 3 of these handlers in for your distribute-list for all the northbound + * distribute_list leaf callbacks. If you need multi-protocol then use the + * grouping twice under 2 different containers. + */ +extern int group_distribute_list_ipv4_modify(struct nb_cb_modify_args *args); +extern int group_distribute_list_ipv4_destroy(struct nb_cb_destroy_args *args); +extern void group_distribute_list_ipv4_cli_show(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults); +extern int group_distribute_list_ipv6_modify(struct nb_cb_modify_args *args); +extern int group_distribute_list_ipv6_destroy(struct nb_cb_destroy_args *args); +extern void group_distribute_list_ipv6_cli_show(struct vty *vty, + const struct lyd_node *dnode, + bool show_defaults); #ifdef __cplusplus } #endif diff --git a/yang/frr-filter.yang b/yang/frr-filter.yang index 867e59826c..9b65fcc025 100644 --- a/yang/frr-filter.yang +++ b/yang/frr-filter.yang @@ -10,6 +10,9 @@ module frr-filter { import ietf-yang-types { prefix yang; } + import frr-interface { + prefix frr-interface; + } organization "FRRouting"; contact @@ -79,6 +82,65 @@ module frr-filter { description "Access list return action on match"; } + typedef access-list-ref { + type leafref { + path "/frr-filter:lib/frr-filter:access-list/frr-filter:name"; + require-instance false; + } + description "IPv4 or IPv6 access list reference"; + } + + typedef prefix-list-ref { + type leafref { + path "/frr-filter:lib/frr-filter:prefix-list/frr-filter:name"; + require-instance false; + } + description "IPv4 or IPv6 prefix list reference"; + } + + /* + * Grouping. + */ + grouping distribute-list-group { + description "Distribute list grouping"; + list distribute-list { + key "interface"; + description "Distribute list configuration"; + + leaf interface { + type union { + type frr-interface:interface-ref; + type empty; + } + description + "Interface to attach list to or empty for global."; + } + + container in { + description "Inbound filter list"; + leaf access-list { + type access-list-ref; + description "inbound access list"; + } + leaf prefix-list { + type prefix-list-ref; + description "inbound prefix list"; + } + } + container out { + description "Outbound filter list"; + leaf access-list { + type access-list-ref; + description "outbound access list"; + } + leaf prefix-list { + type prefix-list-ref; + description "outbound prefix list"; + } + } + } + } + /* * Configuration data. */ @@ -91,12 +153,12 @@ module frr-filter { leaf type { type enumeration { enum ipv4 { - value 0; - description "Internet Protocol address version 4"; - } - enum ipv6 { - value 1; - description "Internet Protocol address version 6"; + value 0; + description "Internet Protocol address version 4"; + } + enum ipv6 { + value 1; + description "Internet Protocol address version 6"; } enum mac { value 2; From a993b8e9bb71407e4adb478e8a57f35fdf85febd Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Mon, 22 Jan 2024 01:15:38 +0000 Subject: [PATCH 3/5] lib: enable multiple instance support with distribute lists Signed-off-by: Christian Hopps --- babeld/babeld.c | 9 +++++---- eigrpd/eigrp_routemap.c | 6 +++--- lib/distribute.c | 30 +++++++++++++++++------------- lib/distribute.h | 8 +++++--- ripd/rip_cli.c | 4 ++-- ripngd/ripng_cli.c | 5 +++-- 6 files changed, 35 insertions(+), 27 deletions(-) diff --git a/babeld/babeld.c b/babeld/babeld.c index 41fac62511..797d12478a 100644 --- a/babeld/babeld.c +++ b/babeld/babeld.c @@ -710,7 +710,7 @@ DEFUN (babel_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_parser(prefix, true, argv[2 + prefix]->text, + return distribute_list_parser(NULL, prefix, true, argv[2 + prefix]->text, argv[1 + prefix]->arg, ifname); } @@ -731,7 +731,7 @@ DEFUN (babel_no_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_no_parser(vty, prefix, true, + return distribute_list_no_parser(NULL, vty, prefix, true, argv[3 + prefix]->text, argv[2 + prefix]->arg, ifname); } @@ -753,7 +753,8 @@ DEFUN (babel_ipv6_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_parser(prefix, false, argv[3 + prefix]->text, + return distribute_list_parser(NULL, prefix, false, + argv[3 + prefix]->text, argv[2 + prefix]->arg, ifname); } @@ -775,7 +776,7 @@ DEFUN (babel_no_ipv6_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_no_parser(vty, prefix, false, + return distribute_list_no_parser(NULL, vty, prefix, false, argv[4 + prefix]->text, argv[3 + prefix]->arg, ifname); } diff --git a/eigrpd/eigrp_routemap.c b/eigrpd/eigrp_routemap.c index 84f27d0167..5a1634592f 100644 --- a/eigrpd/eigrp_routemap.c +++ b/eigrpd/eigrp_routemap.c @@ -1123,7 +1123,7 @@ DEFUN (eigrp_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_parser(prefix, true, argv[2 + prefix]->text, + return distribute_list_parser(NULL, prefix, true, argv[2 + prefix]->text, argv[1 + prefix]->arg, ifname); } @@ -1144,14 +1144,14 @@ DEFUN (eigrp_no_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_no_parser(vty, prefix, true, + return distribute_list_no_parser(NULL, vty, prefix, true, argv[3 + prefix]->text, argv[2 + prefix]->arg, ifname); } /* Route-map init */ -void eigrp_route_map_init() +void eigrp_route_map_init(void) { route_map_init(); route_map_init_vty(); diff --git a/lib/distribute.c b/lib/distribute.c index 719bac4faa..8d1fca9a9e 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -244,11 +244,13 @@ static enum distribute_type distribute_direction(const char *dir, bool v4) __builtin_unreachable(); } -int distribute_list_parser(bool prefix, bool v4, const char *dir, - const char *list, const char *ifname) +int distribute_list_parser(struct distribute_ctx *ctx, bool prefix, bool v4, + const char *dir, const char *list, const char *ifname) { enum distribute_type type = distribute_direction(dir, v4); - struct distribute_ctx *ctx = listnode_head(dist_ctx_list); + + if (!ctx) + ctx = listnode_head(dist_ctx_list); void (*distfn)(struct distribute_ctx *, const char *, enum distribute_type, const char *) = @@ -259,14 +261,17 @@ int distribute_list_parser(bool prefix, bool v4, const char *dir, return CMD_SUCCESS; } -int distribute_list_no_parser(struct vty *vty, bool prefix, bool v4, - const char *dir, const char *list, - const char *ifname) + +int distribute_list_no_parser(struct distribute_ctx *ctx, struct vty *vty, + bool prefix, bool v4, const char *dir, + const char *list, const char *ifname) { enum distribute_type type = distribute_direction(dir, v4); - struct distribute_ctx *ctx = listnode_head(dist_ctx_list); int ret; + if (!ctx) + ctx = listnode_head(dist_ctx_list); + int (*distfn)(struct distribute_ctx *, const char *, enum distribute_type, const char *) = prefix ? &distribute_list_prefix_unset : &distribute_list_unset; @@ -451,8 +456,7 @@ int config_write_distribute(struct vty *vty, int group_distribute_list_create_helper( struct nb_cb_create_args *args, struct distribute_ctx *ctx) { - /* The code currently doesn't require this as it uses a global */ - /* nb_running_set_entry(args->dnode, ctx); */ + nb_running_set_entry(args->dnode, ctx); return NB_OK; } @@ -469,23 +473,23 @@ int group_distribute_list_destroy(struct nb_cb_destroy_args *args) static int distribute_list_leaf_update(const struct lyd_node *dnode, int ip_version, bool no) { + struct distribute_ctx *ctx; struct lyd_node *dir_node = lyd_parent(dnode); struct lyd_node_inner *list_node = dir_node->parent; struct lyd_node *intf_key = list_node->child; bool ipv4 = ip_version == 4 ? true : false; bool prefix; - /* The code currently doesn't require this as it uses a global */ - /* ctx = nb_running_get_entry_non_rec(&list_node->node, NULL, false); */ + ctx = nb_running_get_entry_non_rec(&list_node->node, NULL, false); prefix = dnode->schema->name[0] == 'p' ? true : false; if (no) - distribute_list_no_parser(NULL, prefix, ipv4, + distribute_list_no_parser(ctx, NULL, prefix, ipv4, dir_node->schema->name, lyd_get_value(dnode), lyd_get_value(intf_key)); else - distribute_list_parser(prefix, ipv4, + distribute_list_parser(ctx, prefix, ipv4, dir_node->schema->name, lyd_get_value(dnode), lyd_get_value(intf_key)); diff --git a/lib/distribute.h b/lib/distribute.h index 6fe890c045..a0bc348982 100644 --- a/lib/distribute.h +++ b/lib/distribute.h @@ -70,9 +70,11 @@ extern enum filter_type distribute_apply_in(struct interface *, extern enum filter_type distribute_apply_out(struct interface *, struct prefix *); -extern int distribute_list_parser(bool prefix, bool v4, const char *dir, - const char *list, const char *ifname); -extern int distribute_list_no_parser(struct vty *vty, bool prefix, bool v4, +extern int distribute_list_parser(struct distribute_ctx *ctx, bool prefix, + bool v4, const char *dir, const char *list, + const char *ifname); +extern int distribute_list_no_parser(struct distribute_ctx *ctx, + struct vty *vty, bool prefix, bool v4, const char *dir, const char *list, const char *ifname); diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c index d545e692cb..a4d306a4d2 100644 --- a/ripd/rip_cli.c +++ b/ripd/rip_cli.c @@ -1144,7 +1144,7 @@ DEFUN (rip_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_parser(prefix, true, argv[2 + prefix]->text, + return distribute_list_parser(NULL, prefix, true, argv[2 + prefix]->text, argv[1 + prefix]->arg, ifname); } @@ -1165,7 +1165,7 @@ DEFUN (rip_no_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_no_parser(vty, prefix, true, + return distribute_list_no_parser(NULL, vty, prefix, true, argv[3 + prefix]->text, argv[2 + prefix]->arg, ifname); } diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c index 88b9354d95..c5ffefe96b 100644 --- a/ripngd/ripng_cli.c +++ b/ripngd/ripng_cli.c @@ -533,7 +533,8 @@ DEFUN (ripng_ipv6_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_parser(prefix, false, argv[3 + prefix]->text, + return distribute_list_parser(NULL, prefix, false, + argv[3 + prefix]->text, argv[2 + prefix]->arg, ifname); } @@ -555,7 +556,7 @@ DEFUN (ripng_no_ipv6_distribute_list, if (argv[argc - 1]->type == VARIABLE_TKN) ifname = argv[argc - 1]->arg; - return distribute_list_no_parser(vty, prefix, false, + return distribute_list_no_parser(NULL, vty, prefix, false, argv[4 + prefix]->text, argv[3 + prefix]->arg, ifname); } From 8f7a9355f216adbfb4c2727432e394b5bc8d5703 Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Sun, 21 Jan 2024 14:01:58 +0000 Subject: [PATCH 4/5] ripd: use new distribute-list northbound code. Signed-off-by: Christian Hopps --- ripd/rip_cli.c | 83 +++++++++++++++++++++++++------------------- ripd/rip_nb.c | 44 +++++++++++++++++++++-- ripd/rip_nb.h | 4 +++ ripd/rip_nb_config.c | 17 +++++++++ ripd/ripd.c | 3 -- yang/frr-ripd.yang | 6 ++++ 6 files changed, 117 insertions(+), 40 deletions(-) diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c index a4d306a4d2..d4366d0186 100644 --- a/ripd/rip_cli.c +++ b/ripd/rip_cli.c @@ -1128,46 +1128,59 @@ DEFPY_YANG (clear_ip_rip, return ret; } -DEFUN (rip_distribute_list, - rip_distribute_list_cmd, - "distribute-list [prefix] ACCESSLIST4_NAME [WORD]", - "Filter networks in routing updates\n" - "Specify a prefix\n" - "Access-list name\n" - "Filter incoming routing updates\n" - "Filter outgoing routing updates\n" - "Interface name\n") +DEFPY_YANG( + rip_distribute_list, rip_distribute_list_cmd, + "distribute-list [prefix]$prefix ACCESSLIST4_NAME$name $dir [WORD$ifname]", + "Filter networks in routing updates\n" + "Specify a prefix list\n" + "access-list or prefix-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") { - const char *ifname = NULL; - int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0; + char xpath[XPATH_MAXLEN]; - if (argv[argc - 1]->type == VARIABLE_TKN) - ifname = argv[argc - 1]->arg; - - return distribute_list_parser(NULL, prefix, true, argv[2 + prefix]->text, - argv[1 + prefix]->arg, ifname); + snprintf(xpath, sizeof(xpath), + "./distribute-list[interface='%s']/%s/%s-list", + ifname ? ifname : "", dir, prefix ? "prefix" : "access"); + /* nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); */ + nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, name); + return nb_cli_apply_changes(vty, NULL); } -DEFUN (rip_no_distribute_list, - rip_no_distribute_list_cmd, - "no distribute-list [prefix] ACCESSLIST4_NAME [WORD]", - NO_STR - "Filter networks in routing updates\n" - "Specify a prefix\n" - "Access-list name\n" - "Filter incoming routing updates\n" - "Filter outgoing routing updates\n" - "Interface name\n") +DEFPY_YANG(no_rip_distribute_list, + no_rip_distribute_list_cmd, + "no distribute-list [prefix]$prefix [ACCESSLIST4_NAME$name] $dir [WORD$ifname]", + NO_STR + "Filter networks in routing updates\n" + "Specify a prefix list\n" + "access-list or prefix-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") { - const char *ifname = NULL; - int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; + const struct lyd_node *value_node; + char xpath[XPATH_MAXLEN]; - if (argv[argc - 1]->type == VARIABLE_TKN) - ifname = argv[argc - 1]->arg; - - return distribute_list_no_parser(NULL, vty, prefix, true, - argv[3 + prefix]->text, - argv[2 + prefix]->arg, ifname); + snprintf(xpath, sizeof(xpath), + "./distribute-list[interface='%s']/%s/%s-list", + ifname ? ifname : "", dir, prefix ? "prefix" : "access"); + /* + * See if the user has specified specific list so check it exists. + * + * NOTE: Other FRR CLI commands do not do this sort of verification and + * there may be an official decision not to. + */ + if (name) { + value_node = yang_dnode_getf(vty->candidate_config->dnode, "%s/%s", + VTY_CURR_XPATH, xpath); + if (!value_node || strcmp(name, lyd_get_value(value_node))) { + vty_out(vty, "distribute list doesn't exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); } void rip_cli_init(void) @@ -1176,7 +1189,7 @@ void rip_cli_init(void) install_element(CONFIG_NODE, &no_router_rip_cmd); install_element(RIP_NODE, &rip_distribute_list_cmd); - install_element(RIP_NODE, &rip_no_distribute_list_cmd); + install_element(RIP_NODE, &no_rip_distribute_list_cmd); install_element(RIP_NODE, &rip_allow_ecmp_cmd); install_element(RIP_NODE, &no_rip_allow_ecmp_cmd); diff --git a/ripd/rip_nb.c b/ripd/rip_nb.c index d11f1e1d34..7167be124a 100644 --- a/ripd/rip_nb.c +++ b/ripd/rip_nb.c @@ -6,11 +6,12 @@ #include -#include "northbound.h" +#include "distribute.h" +#include "if_rmap.h" #include "libfrr.h" +#include "northbound.h" #include "ripd/rip_nb.h" -#include "lib/if_rmap.h" /* clang-format off */ const struct frr_yang_module_info frr_ripd_info = { @@ -143,6 +144,45 @@ const struct frr_yang_module_info frr_ripd_info = { .destroy = ripd_instance_non_passive_interface_destroy, }, }, + { + .xpath = "/frr-ripd:ripd/instance/distribute-list", + .cbs = { + .create = ripd_instance_distribute_list_create, + .destroy = group_distribute_list_destroy, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/distribute-list/in/access-list", + .cbs = { + .modify = group_distribute_list_ipv4_modify, + .destroy = group_distribute_list_ipv4_destroy, + .cli_show = group_distribute_list_ipv4_cli_show, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/distribute-list/out/access-list", + .cbs = { + .modify = group_distribute_list_ipv4_modify, + .destroy = group_distribute_list_ipv4_destroy, + .cli_show = group_distribute_list_ipv4_cli_show, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/distribute-list/in/prefix-list", + .cbs = { + .modify = group_distribute_list_ipv4_modify, + .destroy = group_distribute_list_ipv4_destroy, + .cli_show = group_distribute_list_ipv4_cli_show, + } + }, + { + .xpath = "/frr-ripd:ripd/instance/distribute-list/out/prefix-list", + .cbs = { + .modify = group_distribute_list_ipv4_modify, + .destroy = group_distribute_list_ipv4_destroy, + .cli_show = group_distribute_list_ipv4_cli_show, + } + }, { .xpath = "/frr-ripd:ripd/instance/redistribute", .cbs = { diff --git a/ripd/rip_nb.h b/ripd/rip_nb.h index 9929e0952b..811fee55ec 100644 --- a/ripd/rip_nb.h +++ b/ripd/rip_nb.h @@ -7,6 +7,8 @@ #ifndef _FRR_RIP_NB_H_ #define _FRR_RIP_NB_H_ +#include "northbound.h" + extern const struct frr_yang_module_info frr_ripd_info; /* Mandatory callbacks. */ @@ -45,6 +47,8 @@ int ripd_instance_passive_interface_destroy(struct nb_cb_destroy_args *args); int ripd_instance_non_passive_interface_create(struct nb_cb_create_args *args); int ripd_instance_non_passive_interface_destroy( struct nb_cb_destroy_args *args); +int ripd_instance_distribute_list_create(struct nb_cb_create_args *args); +int ripd_instance_distribute_list_destroy(struct nb_cb_destroy_args *args); int ripd_instance_redistribute_create(struct nb_cb_create_args *args); int ripd_instance_redistribute_destroy(struct nb_cb_destroy_args *args); int ripd_instance_redistribute_route_map_modify(struct nb_cb_modify_args *args); diff --git a/ripd/rip_nb_config.c b/ripd/rip_nb_config.c index 8b9cc922ad..fb7533789b 100644 --- a/ripd/rip_nb_config.c +++ b/ripd/rip_nb_config.c @@ -548,6 +548,23 @@ int ripd_instance_non_passive_interface_destroy(struct nb_cb_destroy_args *args) return rip_passive_nondefault_unset(rip, ifname); } + +/* + * XPath: /frr-ripd:ripd/instance/distribute-list + */ +int ripd_instance_distribute_list_create(struct nb_cb_create_args *args) +{ + struct rip *rip; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + rip = nb_running_get_entry(args->dnode, NULL, true); + group_distribute_list_create_helper(args, rip->distribute_ctx); + + return NB_OK; +} + /* * XPath: /frr-ripd:ripd/instance/redistribute */ diff --git a/ripd/ripd.c b/ripd/ripd.c index d5df16c3a9..a744e081d1 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -3271,9 +3271,6 @@ static int config_write_rip(struct vty *vty) nb_cli_show_dnode_cmds(vty, dnode, false); - /* Distribute configuration. */ - config_write_distribute(vty, rip->distribute_ctx); - vty_out(vty, "exit\n"); write = 1; diff --git a/yang/frr-ripd.yang b/yang/frr-ripd.yang index 756e70b292..d65ee48963 100644 --- a/yang/frr-ripd.yang +++ b/yang/frr-ripd.yang @@ -16,6 +16,9 @@ module frr-ripd { import frr-bfdd { prefix frr-bfdd; } + import frr-filter { + prefix frr-filter; + } import frr-interface { prefix frr-interface; } @@ -258,6 +261,9 @@ module frr-ripd { "A list of interfaces where the sending of RIP packets is enabled."; } + + uses frr-filter:distribute-list-group; + list redistribute { key "protocol"; description From cc9f4029cb49e7bee1cda416ae8dc790769cc333 Mon Sep 17 00:00:00 2001 From: Christian Hopps Date: Sun, 21 Jan 2024 21:19:28 +0000 Subject: [PATCH 5/5] ripngd: use new distribute-list northbound code. Signed-off-by: Christian Hopps --- ripngd/ripng_cli.c | 86 ++++++++++++++++++++++------------------ ripngd/ripng_nb.c | 44 +++++++++++++++++++- ripngd/ripng_nb.h | 4 ++ ripngd/ripng_nb_config.c | 16 ++++++++ ripngd/ripngd.c | 2 - yang/frr-ripngd.yang | 11 ++++- 6 files changed, 120 insertions(+), 43 deletions(-) diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c index c5ffefe96b..3212229ac6 100644 --- a/ripngd/ripng_cli.c +++ b/ripngd/ripng_cli.c @@ -516,49 +516,59 @@ DEFPY_YANG (clear_ipv6_rip, return ret; } -DEFUN (ripng_ipv6_distribute_list, - ripng_ipv6_distribute_list_cmd, - "ipv6 distribute-list [prefix] ACCESSLIST6_NAME [WORD]", - "IPv6\n" - "Filter networks in routing updates\n" - "Specify a prefix\n" - "Access-list name\n" - "Filter incoming routing updates\n" - "Filter outgoing routing updates\n" - "Interface name\n") +DEFPY_YANG( + ripng_ipv6_distribute_list, ripng_ipv6_distribute_list_cmd, + "ipv6 distribute-list [prefix]$prefix ACCESSLIST4_NAME$name $dir [WORD$ifname]", + "Filter networks in routing updates\n" + "Specify a prefix list\n" + "access-list or prefix-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") { - const char *ifname = NULL; - int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0; + char xpath[XPATH_MAXLEN]; - if (argv[argc - 1]->type == VARIABLE_TKN) - ifname = argv[argc - 1]->arg; - - return distribute_list_parser(NULL, prefix, false, - argv[3 + prefix]->text, - argv[2 + prefix]->arg, ifname); + snprintf(xpath, sizeof(xpath), + "./distribute-list[interface='%s']/%s/%s-list", + ifname ? ifname : "", dir, prefix ? "prefix" : "access"); + /* nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); */ + nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, name); + return nb_cli_apply_changes(vty, NULL); } -DEFUN (ripng_no_ipv6_distribute_list, - ripng_no_ipv6_distribute_list_cmd, - "no ipv6 distribute-list [prefix] ACCESSLIST6_NAME [WORD]", - NO_STR - "IPv6\n" - "Filter networks in routing updates\n" - "Specify a prefix\n" - "Access-list name\n" - "Filter incoming routing updates\n" - "Filter outgoing routing updates\n" - "Interface name\n") +DEFPY_YANG(no_ripng_ipv6_distribute_list, + no_ripng_ipv6_distribute_list_cmd, + "no ipv6 distribute-list [prefix]$prefix [ACCESSLIST4_NAME$name] $dir [WORD$ifname]", + NO_STR + "Filter networks in routing updates\n" + "Specify a prefix list\n" + "access-list or prefix-list name\n" + "Filter incoming routing updates\n" + "Filter outgoing routing updates\n" + "Interface name\n") { - const char *ifname = NULL; - int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0; + const struct lyd_node *value_node; + char xpath[XPATH_MAXLEN]; - if (argv[argc - 1]->type == VARIABLE_TKN) - ifname = argv[argc - 1]->arg; - - return distribute_list_no_parser(NULL, vty, prefix, false, - argv[4 + prefix]->text, - argv[3 + prefix]->arg, ifname); + snprintf(xpath, sizeof(xpath), + "./distribute-list[interface='%s']/%s/%s-list", + ifname ? ifname : "", dir, prefix ? "prefix" : "access"); + /* + * See if the user has specified specific list so check it exists. + * + * NOTE: Other FRR CLI commands do not do this sort of verification and + * there may be an official decision not to. + */ + if (name) { + value_node = yang_dnode_getf(vty->candidate_config->dnode, "%s/%s", + VTY_CURR_XPATH, xpath); + if (!value_node || strcmp(name, lyd_get_value(value_node))) { + vty_out(vty, "distribute list doesn't exist\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); } void ripng_cli_init(void) @@ -567,7 +577,7 @@ void ripng_cli_init(void) install_element(CONFIG_NODE, &no_router_ripng_cmd); install_element(RIPNG_NODE, &ripng_ipv6_distribute_list_cmd); - install_element(RIPNG_NODE, &ripng_no_ipv6_distribute_list_cmd); + install_element(RIPNG_NODE, &no_ripng_ipv6_distribute_list_cmd); install_element(RIPNG_NODE, &ripng_allow_ecmp_cmd); install_element(RIPNG_NODE, &no_ripng_allow_ecmp_cmd); diff --git a/ripngd/ripng_nb.c b/ripngd/ripng_nb.c index 1c6d7191a3..583a4d08d0 100644 --- a/ripngd/ripng_nb.c +++ b/ripngd/ripng_nb.c @@ -6,11 +6,12 @@ #include -#include "northbound.h" +#include "distribute.h" +#include "if_rmap.h" #include "libfrr.h" +#include "northbound.h" #include "ripngd/ripng_nb.h" -#include "lib/if_rmap.h" /* clang-format off */ const struct frr_yang_module_info frr_ripngd_info = { @@ -92,6 +93,45 @@ const struct frr_yang_module_info frr_ripngd_info = { .destroy = ripngd_instance_passive_interface_destroy, }, }, + { + .xpath = "/frr-ripngd:ripngd/instance/distribute-list", + .cbs = { + .create = ripngd_instance_distribute_list_create, + .destroy = group_distribute_list_destroy, + } + }, + { + .xpath = "/frr-ripngd:ripngd/instance/distribute-list/in/access-list", + .cbs = { + .modify = group_distribute_list_ipv6_modify, + .destroy = group_distribute_list_ipv6_destroy, + .cli_show = group_distribute_list_ipv6_cli_show, + } + }, + { + .xpath = "/frr-ripngd:ripngd/instance/distribute-list/out/access-list", + .cbs = { + .modify = group_distribute_list_ipv6_modify, + .destroy = group_distribute_list_ipv6_destroy, + .cli_show = group_distribute_list_ipv6_cli_show, + } + }, + { + .xpath = "/frr-ripngd:ripngd/instance/distribute-list/in/prefix-list", + .cbs = { + .modify = group_distribute_list_ipv6_modify, + .destroy = group_distribute_list_ipv6_destroy, + .cli_show = group_distribute_list_ipv6_cli_show, + } + }, + { + .xpath = "/frr-ripngd:ripngd/instance/distribute-list/out/prefix-list", + .cbs = { + .modify = group_distribute_list_ipv6_modify, + .destroy = group_distribute_list_ipv6_destroy, + .cli_show = group_distribute_list_ipv6_cli_show, + } + }, { .xpath = "/frr-ripngd:ripngd/instance/redistribute", .cbs = { diff --git a/ripngd/ripng_nb.h b/ripngd/ripng_nb.h index 1c0e63c241..12d3cd5129 100644 --- a/ripngd/ripng_nb.h +++ b/ripngd/ripng_nb.h @@ -7,6 +7,8 @@ #ifndef _FRR_RIPNG_NB_H_ #define _FRR_RIPNG_NB_H_ +#include "northbound.h" + extern const struct frr_yang_module_info frr_ripngd_info; /* Mandatory callbacks. */ @@ -30,6 +32,8 @@ int ripngd_instance_offset_list_access_list_modify( int ripngd_instance_offset_list_metric_modify(struct nb_cb_modify_args *args); int ripngd_instance_passive_interface_create(struct nb_cb_create_args *args); int ripngd_instance_passive_interface_destroy(struct nb_cb_destroy_args *args); +int ripngd_instance_distribute_list_create(struct nb_cb_create_args *args); +int ripngd_instance_distribute_list_destroy(struct nb_cb_destroy_args *args); int ripngd_instance_redistribute_create(struct nb_cb_create_args *args); int ripngd_instance_redistribute_destroy(struct nb_cb_destroy_args *args); int ripngd_instance_redistribute_route_map_modify( diff --git a/ripngd/ripng_nb_config.c b/ripngd/ripng_nb_config.c index 6ce1c1e356..d05d91cfc7 100644 --- a/ripngd/ripng_nb_config.c +++ b/ripngd/ripng_nb_config.c @@ -368,6 +368,22 @@ int ripngd_instance_passive_interface_destroy(struct nb_cb_destroy_args *args) return ripng_passive_interface_unset(ripng, ifname); } +/* + * XPath: /frr-ripng:ripng/instance/distribute-list + */ +int ripngd_instance_distribute_list_create(struct nb_cb_create_args *args) +{ + struct ripng *ripng; + + if (args->event != NB_EV_APPLY) + return NB_OK; + + ripng = nb_running_get_entry(args->dnode, NULL, true); + group_distribute_list_create_helper(args, ripng->distribute_ctx); + + return NB_OK; +} + /* * XPath: /frr-ripngd:ripngd/instance/redistribute */ diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index bb6ec02343..4c3405d7dd 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -2286,8 +2286,6 @@ static int ripng_config_write(struct vty *vty) nb_cli_show_dnode_cmds(vty, dnode, false); - config_write_distribute(vty, ripng->distribute_ctx); - vty_out(vty, "exit\n"); write = 1; diff --git a/yang/frr-ripngd.yang b/yang/frr-ripngd.yang index 4aeaf36400..383b45fa4a 100644 --- a/yang/frr-ripngd.yang +++ b/yang/frr-ripngd.yang @@ -13,6 +13,9 @@ module frr-ripngd { import frr-if-rmap { prefix frr-if-rmap; } + import frr-filter { + prefix frr-filter; + } import frr-interface { prefix frr-interface; } @@ -63,6 +66,7 @@ module frr-ripngd { description "Changed interface references to use frr-interface:interface-ref typedef"; + reference "FRRouting"; } revision 2018-11-27 { description @@ -72,6 +76,7 @@ module frr-ripngd { } container ripngd { + description "ripng routing instance data"; /* * Routing instance configuration. */ @@ -169,15 +174,18 @@ module frr-ripngd { "A list of interfaces where the sending of RIPng packets is disabled."; } + + uses frr-filter:distribute-list-group; + list redistribute { key "protocol"; description "Redistributes routes learned from other routing protocols."; leaf protocol { type frr-route-types:frr-route-types-v6; + must '. != "ripng"'; description "Routing protocol."; - must '. != "ripng"'; } leaf route-map { type frr-route-map:route-map-ref; @@ -330,6 +338,7 @@ module frr-ripngd { * Per-interface configuration data */ augment "/frr-interface:lib/frr-interface:interface" { + description "RIPng interface augmentation."; container ripng { description "RIPng interface parameters.";