]> git.proxmox.com Git - mirror_frr.git/commitdiff
ripngd: retrofit the 'offset-list' command to the new northbound model
authorRenato Westphal <renato@opensourcerouting.org>
Thu, 29 Nov 2018 04:27:16 +0000 (02:27 -0200)
committerRenato Westphal <renato@opensourcerouting.org>
Mon, 3 Dec 2018 15:47:58 +0000 (13:47 -0200)
Remove the ripng_offset_list_set() and ripng_offset_list_unset()
functions since they set/unset multiple configuration options at the
same time. The northbound callbacks need to set/unset configuration
options individually.

The frr-ripngd YANG module models the "offset-list" command using a
list keyed by the 'interface' and 'direction' leafs. One important
detail is that the IFNAME parameter is optional, and when it's not
present it means we want to match all interfaces. This is modeled
using an interface name of '*' since list keys are mandatory leafs
by definition in YANG.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
ripngd/ripng_cli.c
ripngd/ripng_cli.h
ripngd/ripng_northbound.c
ripngd/ripng_offset.c
ripngd/ripngd.c
ripngd/ripngd.h

index 53ff3fd061dfc91670c8f4454426f683ace77fca..1eb31a0ce6847cc9a7203abecc193c6f40ec52f4 100644 (file)
@@ -203,6 +203,49 @@ void cli_show_ripng_network_interface(struct vty *vty, struct lyd_node *dnode,
        vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL));
 }
 
+/*
+ * XPath: /frr-ripngd:ripngd/instance/offset-list
+ */
+DEFPY (ripng_offset_list,
+       ripng_offset_list_cmd,
+       "[no] offset-list WORD$acl <in|out>$direction (0-16)$metric [IFNAME]",
+       NO_STR
+       "Modify RIPng metric\n"
+       "Access-list name\n"
+       "For incoming updates\n"
+       "For outgoing updates\n"
+       "Metric value\n"
+       "Interface to match\n")
+{
+       if (!no) {
+               nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
+               nb_cli_enqueue_change(vty, "./access-list", NB_OP_MODIFY, acl);
+               nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY,
+                                     metric_str);
+       } else
+               nb_cli_enqueue_change(vty, ".", NB_OP_DELETE, NULL);
+
+       return nb_cli_apply_changes(
+               vty, "./offset-list[interface='%s'][direction='%s']",
+               ifname ? ifname : "*", direction);
+}
+
+void cli_show_ripng_offset_list(struct vty *vty, struct lyd_node *dnode,
+                               bool show_defaults)
+{
+       const char *interface;
+
+       interface = yang_dnode_get_string(dnode, "./interface");
+
+       vty_out(vty, " offset-list %s %s %s",
+               yang_dnode_get_string(dnode, "./access-list"),
+               yang_dnode_get_string(dnode, "./direction"),
+               yang_dnode_get_string(dnode, "./metric"));
+       if (!strmatch(interface, "*"))
+               vty_out(vty, " %s", interface);
+       vty_out(vty, "\n");
+}
+
 void ripng_cli_init(void)
 {
        install_element(CONFIG_NODE, &router_ripng_cmd);
@@ -214,4 +257,5 @@ void ripng_cli_init(void)
        install_element(RIPNG_NODE, &no_ripng_default_metric_cmd);
        install_element(RIPNG_NODE, &ripng_network_prefix_cmd);
        install_element(RIPNG_NODE, &ripng_network_if_cmd);
+       install_element(RIPNG_NODE, &ripng_offset_list_cmd);
 }
index 144f0afa2ba5c472ba5aa0ac05aace535d1c6cd5..d65241436ff444dc2a4b2d00afe425ab5b55fdc4 100644 (file)
@@ -37,5 +37,7 @@ extern void cli_show_ripng_network_prefix(struct vty *vty,
 extern void cli_show_ripng_network_interface(struct vty *vty,
                                             struct lyd_node *dnode,
                                             bool show_defaults);
+extern void cli_show_ripng_offset_list(struct vty *vty, struct lyd_node *dnode,
+                                      bool show_defaults);
 
 #endif /* _FRR_RIPNG_CLI_H_ */
index ff03e8a91a30c397fdbc2bacc04959449b581191..614259a7b416e0a8099a0e48778a18ef6a9013d5 100644 (file)
@@ -202,14 +202,40 @@ static int ripngd_instance_offset_list_create(enum nb_event event,
                                              const struct lyd_node *dnode,
                                              union nb_resource *resource)
 {
-       /* TODO: implement me. */
+       const char *ifname;
+       struct ripng_offset_list *offset;
+
+       if (event != NB_EV_APPLY)
+               return NB_OK;
+
+       ifname = yang_dnode_get_string(dnode, "./interface");
+
+       offset = ripng_offset_list_new(ifname);
+       yang_dnode_set_entry(dnode, offset);
+
        return NB_OK;
 }
 
 static int ripngd_instance_offset_list_delete(enum nb_event event,
                                              const struct lyd_node *dnode)
 {
-       /* TODO: implement me. */
+       int direct;
+       struct ripng_offset_list *offset;
+
+       if (event != NB_EV_APPLY)
+               return NB_OK;
+
+       direct = yang_dnode_get_enum(dnode, "./direction");
+
+       offset = yang_dnode_get_entry(dnode, true);
+       if (offset->direct[direct].alist_name) {
+               free(offset->direct[direct].alist_name);
+               offset->direct[direct].alist_name = NULL;
+       }
+       if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL
+           && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL)
+               ripng_offset_list_del(offset);
+
        return NB_OK;
 }
 
@@ -221,7 +247,21 @@ ripngd_instance_offset_list_access_list_modify(enum nb_event event,
                                               const struct lyd_node *dnode,
                                               union nb_resource *resource)
 {
-       /* TODO: implement me. */
+       int direct;
+       struct ripng_offset_list *offset;
+       const char *alist_name;
+
+       if (event != NB_EV_APPLY)
+               return NB_OK;
+
+       direct = yang_dnode_get_enum(dnode, "../direction");
+       alist_name = yang_dnode_get_string(dnode, NULL);
+
+       offset = yang_dnode_get_entry(dnode, true);
+       if (offset->direct[direct].alist_name)
+               free(offset->direct[direct].alist_name);
+       offset->direct[direct].alist_name = strdup(alist_name);
+
        return NB_OK;
 }
 
@@ -233,7 +273,19 @@ ripngd_instance_offset_list_metric_modify(enum nb_event event,
                                          const struct lyd_node *dnode,
                                          union nb_resource *resource)
 {
-       /* TODO: implement me. */
+       int direct;
+       uint8_t metric;
+       struct ripng_offset_list *offset;
+
+       if (event != NB_EV_APPLY)
+               return NB_OK;
+
+       direct = yang_dnode_get_enum(dnode, "../direction");
+       metric = yang_dnode_get_uint8(dnode, NULL);
+
+       offset = yang_dnode_get_entry(dnode, true);
+       offset->direct[direct].metric = metric;
+
        return NB_OK;
 }
 
@@ -592,6 +644,7 @@ const struct frr_yang_module_info frr_ripngd_info = {
                        .xpath = "/frr-ripngd:ripngd/instance/offset-list",
                        .cbs.create = ripngd_instance_offset_list_create,
                        .cbs.delete = ripngd_instance_offset_list_delete,
+                       .cbs.cli_show = cli_show_ripng_offset_list,
                },
                {
                        .xpath = "/frr-ripngd:ripngd/instance/offset-list/access-list",
index 32b81b54802bf911d8c2c4c3d15f6cd48c2c045c..278df758924164116f9a21c7f48f0a4af5416cca 100644 (file)
 
 #include "ripngd/ripngd.h"
 
-#define RIPNG_OFFSET_LIST_IN  0
-#define RIPNG_OFFSET_LIST_OUT 1
-#define RIPNG_OFFSET_LIST_MAX 2
-
-struct ripng_offset_list {
-       char *ifname;
-
-       struct {
-               char *alist_name;
-               /* struct access_list *alist; */
-               int metric;
-       } direct[RIPNG_OFFSET_LIST_MAX];
-};
-
 static struct list *ripng_offset_list_master;
 
-static int strcmp_safe(const char *s1, const char *s2)
-{
-       if (s1 == NULL && s2 == NULL)
-               return 0;
-       if (s1 == NULL)
-               return -1;
-       if (s2 == NULL)
-               return 1;
-       return strcmp(s1, s2);
-}
+#define OFFSET_LIST_IN_NAME(O)  ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name)
+#define OFFSET_LIST_IN_METRIC(O)  ((O)->direct[RIPNG_OFFSET_LIST_IN].metric)
+
+#define OFFSET_LIST_OUT_NAME(O)  ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
+#define OFFSET_LIST_OUT_METRIC(O)  ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric)
 
-static struct ripng_offset_list *ripng_offset_list_new(void)
+struct ripng_offset_list *ripng_offset_list_new(const char *ifname)
 {
        struct ripng_offset_list *new;
 
        new = XCALLOC(MTYPE_RIPNG_OFFSET_LIST,
                      sizeof(struct ripng_offset_list));
+       new->ifname = strdup(ifname);
+       listnode_add_sort(ripng_offset_list_master, new);
+
        return new;
 }
 
-static void ripng_offset_list_free(struct ripng_offset_list *offset)
+void ripng_offset_list_del(struct ripng_offset_list *offset)
 {
+       listnode_delete(ripng_offset_list_master, offset);
+       if (OFFSET_LIST_IN_NAME(offset))
+               free(OFFSET_LIST_IN_NAME(offset));
+       if (OFFSET_LIST_OUT_NAME(offset))
+               free(OFFSET_LIST_OUT_NAME(offset));
+       free(offset->ifname);
        XFREE(MTYPE_RIPNG_OFFSET_LIST, offset);
 }
 
-static struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname)
+struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname)
 {
        struct ripng_offset_list *offset;
        struct listnode *node, *nnode;
 
        for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) {
-               if (strcmp_safe(offset->ifname, ifname) == 0)
+               if (strcmp(offset->ifname, ifname) == 0)
                        return offset;
        }
        return NULL;
 }
 
-static struct ripng_offset_list *ripng_offset_list_get(const char *ifname)
-{
-       struct ripng_offset_list *offset;
-
-       offset = ripng_offset_list_lookup(ifname);
-       if (offset)
-               return offset;
-
-       offset = ripng_offset_list_new();
-       if (ifname)
-               offset->ifname = strdup(ifname);
-       listnode_add_sort(ripng_offset_list_master, offset);
-
-       return offset;
-}
-
-static int ripng_offset_list_set(struct vty *vty, const char *alist,
-                                const char *direct_str, const char *metric_str,
-                                const char *ifname)
-{
-       int direct;
-       int metric;
-       struct ripng_offset_list *offset;
-
-       /* Check direction. */
-       if (strncmp(direct_str, "i", 1) == 0)
-               direct = RIPNG_OFFSET_LIST_IN;
-       else if (strncmp(direct_str, "o", 1) == 0)
-               direct = RIPNG_OFFSET_LIST_OUT;
-       else {
-               vty_out(vty, "Invalid direction: %s\n", direct_str);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       /* Check metric. */
-       metric = atoi(metric_str);
-       if (metric < 0 || metric > 16) {
-               vty_out(vty, "Invalid metric: %s\n", metric_str);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       /* Get offset-list structure with interface name. */
-       offset = ripng_offset_list_get(ifname);
-
-       if (offset->direct[direct].alist_name)
-               free(offset->direct[direct].alist_name);
-       offset->direct[direct].alist_name = strdup(alist);
-       offset->direct[direct].metric = metric;
-
-       return CMD_SUCCESS;
-}
-
-static int ripng_offset_list_unset(struct vty *vty, const char *alist,
-                                  const char *direct_str,
-                                  const char *metric_str, const char *ifname)
-{
-       int direct;
-       int metric;
-       struct ripng_offset_list *offset;
-
-       /* Check direction. */
-       if (strncmp(direct_str, "i", 1) == 0)
-               direct = RIPNG_OFFSET_LIST_IN;
-       else if (strncmp(direct_str, "o", 1) == 0)
-               direct = RIPNG_OFFSET_LIST_OUT;
-       else {
-               vty_out(vty, "Invalid direction: %s\n", direct_str);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       /* Check metric. */
-       metric = atoi(metric_str);
-       if (metric < 0 || metric > 16) {
-               vty_out(vty, "Invalid metric: %s\n", metric_str);
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       /* Get offset-list structure with interface name. */
-       offset = ripng_offset_list_lookup(ifname);
-
-       if (offset) {
-               if (offset->direct[direct].alist_name)
-                       free(offset->direct[direct].alist_name);
-               offset->direct[direct].alist_name = NULL;
-
-               if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL
-                   && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name
-                              == NULL) {
-                       listnode_delete(ripng_offset_list_master, offset);
-                       if (offset->ifname)
-                               free(offset->ifname);
-                       ripng_offset_list_free(offset);
-               }
-       } else {
-               vty_out(vty, "Can't find offset-list\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       return CMD_SUCCESS;
-}
-
-#define OFFSET_LIST_IN_NAME(O)  ((O)->direct[RIPNG_OFFSET_LIST_IN].alist_name)
-#define OFFSET_LIST_IN_METRIC(O)  ((O)->direct[RIPNG_OFFSET_LIST_IN].metric)
-
-#define OFFSET_LIST_OUT_NAME(O)  ((O)->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
-#define OFFSET_LIST_OUT_METRIC(O)  ((O)->direct[RIPNG_OFFSET_LIST_OUT].metric)
-
 /* If metric is modifed return 1. */
 int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
                               uint8_t *metric)
@@ -214,7 +98,7 @@ int ripng_offset_list_apply_in(struct prefix_ipv6 *p, struct interface *ifp,
                return 0;
        }
        /* Look up offset-list without interface name. */
-       offset = ripng_offset_list_lookup(NULL);
+       offset = ripng_offset_list_lookup("*");
        if (offset && OFFSET_LIST_IN_NAME(offset)) {
                alist = access_list_lookup(AFI_IP6,
                                           OFFSET_LIST_IN_NAME(offset));
@@ -253,7 +137,7 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
        }
 
        /* Look up offset-list without interface name. */
-       offset = ripng_offset_list_lookup(NULL);
+       offset = ripng_offset_list_lookup("*");
        if (offset && OFFSET_LIST_OUT_NAME(offset)) {
                alist = access_list_lookup(AFI_IP6,
                                           OFFSET_LIST_OUT_NAME(offset));
@@ -269,95 +153,10 @@ int ripng_offset_list_apply_out(struct prefix_ipv6 *p, struct interface *ifp,
        return 0;
 }
 
-DEFUN (ripng_offset_list,
-       ripng_offset_list_cmd,
-       "offset-list WORD <in|out> (0-16)",
-       "Modify RIPng metric\n"
-       "Access-list name\n"
-       "For incoming updates\n"
-       "For outgoing updates\n"
-       "Metric value\n")
-{
-       int idx_word = 1;
-       int idx_in_out = 2;
-       int idx_number = 3;
-       return ripng_offset_list_set(vty, argv[idx_word]->arg,
-                                    argv[idx_in_out]->arg,
-                                    argv[idx_number]->arg, NULL);
-}
-
-DEFUN (ripng_offset_list_ifname,
-       ripng_offset_list_ifname_cmd,
-       "offset-list WORD <in|out> (0-16) IFNAME",
-       "Modify RIPng metric\n"
-       "Access-list name\n"
-       "For incoming updates\n"
-       "For outgoing updates\n"
-       "Metric value\n"
-       "Interface to match\n")
-{
-       int idx_word = 1;
-       int idx_in_out = 2;
-       int idx_number = 3;
-       int idx_ifname = 4;
-       return ripng_offset_list_set(
-               vty, argv[idx_word]->arg, argv[idx_in_out]->arg,
-               argv[idx_number]->arg, argv[idx_ifname]->arg);
-}
-
-DEFUN (no_ripng_offset_list,
-       no_ripng_offset_list_cmd,
-       "no offset-list WORD <in|out> (0-16)",
-       NO_STR
-       "Modify RIPng metric\n"
-       "Access-list name\n"
-       "For incoming updates\n"
-       "For outgoing updates\n"
-       "Metric value\n")
-{
-       int idx_word = 2;
-       int idx_in_out = 3;
-       int idx_number = 4;
-       return ripng_offset_list_unset(vty, argv[idx_word]->arg,
-                                      argv[idx_in_out]->arg,
-                                      argv[idx_number]->arg, NULL);
-}
-
-DEFUN (no_ripng_offset_list_ifname,
-       no_ripng_offset_list_ifname_cmd,
-       "no offset-list WORD <in|out> (0-16) IFNAME",
-       NO_STR
-       "Modify RIPng metric\n"
-       "Access-list name\n"
-       "For incoming updates\n"
-       "For outgoing updates\n"
-       "Metric value\n"
-       "Interface to match\n")
-{
-       int idx_word = 2;
-       int idx_in_out = 3;
-       int idx_number = 4;
-       int idx_ifname = 5;
-       return ripng_offset_list_unset(
-               vty, argv[idx_word]->arg, argv[idx_in_out]->arg,
-               argv[idx_number]->arg, argv[idx_ifname]->arg);
-}
-
 static int offset_list_cmp(struct ripng_offset_list *o1,
                           struct ripng_offset_list *o2)
 {
-       return strcmp_safe(o1->ifname, o2->ifname);
-}
-
-static void offset_list_del(struct ripng_offset_list *offset)
-{
-       if (OFFSET_LIST_IN_NAME(offset))
-               free(OFFSET_LIST_IN_NAME(offset));
-       if (OFFSET_LIST_OUT_NAME(offset))
-               free(OFFSET_LIST_OUT_NAME(offset));
-       if (offset->ifname)
-               free(offset->ifname);
-       ripng_offset_list_free(offset);
+       return strcmp(o1->ifname, o2->ifname);
 }
 
 void ripng_offset_init(void)
@@ -365,12 +164,7 @@ void ripng_offset_init(void)
        ripng_offset_list_master = list_new();
        ripng_offset_list_master->cmp =
                (int (*)(void *, void *))offset_list_cmp;
-       ripng_offset_list_master->del = (void (*)(void *))offset_list_del;
-
-       install_element(RIPNG_NODE, &ripng_offset_list_cmd);
-       install_element(RIPNG_NODE, &ripng_offset_list_ifname_cmd);
-       install_element(RIPNG_NODE, &no_ripng_offset_list_cmd);
-       install_element(RIPNG_NODE, &no_ripng_offset_list_ifname_cmd);
+       ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del;
 }
 
 void ripng_offset_clean(void)
@@ -380,45 +174,5 @@ void ripng_offset_clean(void)
        ripng_offset_list_master = list_new();
        ripng_offset_list_master->cmp =
                (int (*)(void *, void *))offset_list_cmp;
-       ripng_offset_list_master->del = (void (*)(void *))offset_list_del;
-}
-
-int config_write_ripng_offset_list(struct vty *vty)
-{
-       struct listnode *node, *nnode;
-       struct ripng_offset_list *offset;
-
-       for (ALL_LIST_ELEMENTS(ripng_offset_list_master, node, nnode, offset)) {
-               if (!offset->ifname) {
-                       if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name)
-                               vty_out(vty, " offset-list %s in %d\n",
-                                       offset->direct[RIPNG_OFFSET_LIST_IN]
-                                               .alist_name,
-                                       offset->direct[RIPNG_OFFSET_LIST_IN]
-                                               .metric);
-                       if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
-                               vty_out(vty, " offset-list %s out %d\n",
-                                       offset->direct[RIPNG_OFFSET_LIST_OUT]
-                                               .alist_name,
-                                       offset->direct[RIPNG_OFFSET_LIST_OUT]
-                                               .metric);
-               } else {
-                       if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name)
-                               vty_out(vty, " offset-list %s in %d %s\n",
-                                       offset->direct[RIPNG_OFFSET_LIST_IN]
-                                               .alist_name,
-                                       offset->direct[RIPNG_OFFSET_LIST_IN]
-                                               .metric,
-                                       offset->ifname);
-                       if (offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name)
-                               vty_out(vty, " offset-list %s out %d %s\n",
-                                       offset->direct[RIPNG_OFFSET_LIST_OUT]
-                                               .alist_name,
-                                       offset->direct[RIPNG_OFFSET_LIST_OUT]
-                                               .metric,
-                                       offset->ifname);
-               }
-       }
-
-       return 0;
+       ripng_offset_list_master->del = (void (*)(void *))ripng_offset_list_del;
 }
index ef32ed19e296d7b840dce6809fdc50c8b1b84108..f6aa49f6634a8c06fd54b5c835ef56b5c577e58f 100644 (file)
@@ -2524,9 +2524,6 @@ static int ripng_config_write(struct vty *vty)
 
                ripng_redistribute_write(vty, 1);
 
-               /* RIP offset-list configuration. */
-               config_write_ripng_offset_list(vty);
-
                /* RIPng aggregate routes. */
                for (rp = agg_route_top(ripng->aggregate); rp;
                     rp = agg_route_next(rp))
index 95a0b25253b33634834a89f578cf2713f487e501..fd2ae4ad32d74de870f91646d5f23adb63304951 100644 (file)
@@ -325,6 +325,20 @@ enum ripng_event {
                }                                                              \
        } while (0)
 
+#define RIPNG_OFFSET_LIST_IN  0
+#define RIPNG_OFFSET_LIST_OUT 1
+#define RIPNG_OFFSET_LIST_MAX 2
+
+struct ripng_offset_list {
+       char *ifname;
+
+       struct {
+               char *alist_name;
+               /* struct access_list *alist; */
+               uint8_t metric;
+       } direct[RIPNG_OFFSET_LIST_MAX];
+};
+
 /* Extern variables. */
 extern struct ripng *ripng;
 extern struct zebra_privs_t ripngd_privs;
@@ -350,9 +364,6 @@ extern void ripng_terminate(void);
 extern void zebra_init(struct thread_master *);
 extern void ripng_zebra_stop(void);
 extern void ripng_zclient_reset(void);
-extern void ripng_offset_init(void);
-
-extern int config_write_ripng_offset_list(struct vty *);
 
 extern void ripng_peer_init(void);
 extern void ripng_peer_update(struct sockaddr_in6 *, uint8_t);
@@ -362,10 +373,15 @@ extern void ripng_peer_display(struct vty *);
 extern struct ripng_peer *ripng_peer_lookup(struct in6_addr *);
 extern struct ripng_peer *ripng_peer_lookup_next(struct in6_addr *);
 
+extern struct ripng_offset_list *ripng_offset_list_new(const char *ifname);
+extern void ripng_offset_list_del(struct ripng_offset_list *offset);
+extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname);
+extern struct ripng_offset_list *ripng_offset_list_lookup(const char *ifname);
 extern int ripng_offset_list_apply_in(struct prefix_ipv6 *, struct interface *,
                                      uint8_t *);
 extern int ripng_offset_list_apply_out(struct prefix_ipv6 *, struct interface *,
                                       uint8_t *);
+extern void ripng_offset_init(void);
 extern void ripng_offset_clean(void);
 
 extern struct ripng_info *ripng_info_new(void);