]> git.puffer.fish Git - mirror/frr.git/commitdiff
lib: add northbound support to distribute-list code.
authorChristian Hopps <chopps@labn.net>
Sun, 21 Jan 2024 13:12:39 +0000 (13:12 +0000)
committerChristian Hopps <chopps@labn.net>
Mon, 22 Jan 2024 11:32:29 +0000 (11:32 +0000)
Signed-off-by: Christian Hopps <chopps@labn.net>
lib/distribute.c
lib/distribute.h
yang/frr-filter.yang

index 65487676d6c62e1a1554ed772da62142d3aa5299..719bac4faaf84963d8c318b737ae9ef71a48cd7c 100644 (file)
@@ -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,
index 75783712a19993fee010210b385b57e1c259f7fd..6fe890c045bf7f8ade6cc6ff686b9062f18e18a5 100644 (file)
@@ -9,6 +9,7 @@
 #include <zebra.h>
 #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
index 867e59826c7f21126506718dbe8b4cd52a9eaa95..9b65fcc0255afb3b43477ad841ddf8b0be43e0c4 100644 (file)
@@ -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;