]> git.proxmox.com Git - mirror_frr.git/commitdiff
staticd: improve CLI/northbound translation code
authorRafael Zalamena <rzalamena@opensourcerouting.org>
Fri, 25 Nov 2022 18:59:21 +0000 (15:59 -0300)
committerRafael Zalamena <rzalamena@opensourcerouting.org>
Fri, 25 Nov 2022 19:26:10 +0000 (16:26 -0300)
Simplify all DEFUNs by moving all logic to the northbound translation
function and transforming all function parameters into a single
structure.

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
staticd/static_vty.c

index 94a3493477f1b7fda32d2f508a05389e60bf5a7e..efae3c53da6b0befc29ede1ff930121fdbbb53aa 100644 (file)
 
 #define STATICD_STR "Static route daemon\n"
 
-static int static_route_leak(struct vty *vty, const char *svrf,
-                            const char *nh_svrf, afi_t afi, safi_t safi,
-                            const char *negate, const char *dest_str,
-                            const char *mask_str, const char *src_str,
-                            const char *gate_str, const char *ifname,
-                            const char *flag_str, const char *tag_str,
-                            const char *distance_str, const char *label_str,
-                            const char *table_str, bool onlink,
-                            const char *color_str)
+/** All possible route parameters available in CLI. */
+struct static_route_args {
+       /** "no" command? */
+       bool delete;
+       /** Is VRF obtained from XPath? */
+       bool xpath_vrf;
+
+       bool onlink;
+       afi_t afi;
+       safi_t safi;
+
+       const char *vrf;
+       const char *nexthop_vrf;
+       const char *prefix;
+       const char *prefix_mask;
+       const char *source;
+       const char *gateway;
+       const char *interface_name;
+       const char *flag;
+       const char *tag;
+       const char *distance;
+       const char *label;
+       const char *table;
+       const char *color;
+};
+
+static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
 {
        int ret;
        struct prefix p, src;
@@ -62,8 +80,8 @@ static int static_route_leak(struct vty *vty, const char *svrf,
        char xpath_label[XPATH_MAXLEN];
        char ab_xpath[XPATH_MAXLEN];
        char buf_prefix[PREFIX_STRLEN];
-       char buf_src_prefix[PREFIX_STRLEN];
-       char buf_nh_type[PREFIX_STRLEN];
+       char buf_src_prefix[PREFIX_STRLEN] = {};
+       char buf_nh_type[PREFIX_STRLEN] = {};
        char buf_tag[PREFIX_STRLEN];
        uint8_t label_stack_id = 0;
        const char *buf_gate_str;
@@ -71,37 +89,46 @@ static int static_route_leak(struct vty *vty, const char *svrf,
        route_tag_t tag = 0;
        uint32_t table_id = 0;
        const struct lyd_node *dnode;
+       const struct lyd_node *vrf_dnode;
 
-       memset(buf_src_prefix, 0, PREFIX_STRLEN);
-       memset(buf_nh_type, 0, PREFIX_STRLEN);
+       if (args->xpath_vrf) {
+               vrf_dnode = yang_dnode_get(vty->candidate_config->dnode,
+                                          VTY_CURR_XPATH);
+               if (vrf_dnode == NULL) {
+                       vty_out(vty,
+                               "%% Failed to get vrf dnode in candidate db\n");
+                       return CMD_WARNING_CONFIG_FAILED;
+               }
+
+               args->vrf = yang_dnode_get_string(vrf_dnode, "./name");
+       } else {
+               if (args->vrf == NULL)
+                       args->vrf = VRF_DEFAULT_NAME;
+       }
+       if (args->nexthop_vrf == NULL)
+               args->nexthop_vrf = args->vrf;
 
-       ret = str2prefix(dest_str, &p);
-       if (ret <= 0) {
-               vty_out(vty, "%% Malformed address\n");
-               return CMD_WARNING_CONFIG_FAILED;
+       if (args->interface_name &&
+           !strcasecmp(args->interface_name, "Null0")) {
+               args->flag = "Null0";
+               args->interface_name = NULL;
        }
 
-       switch (afi) {
+       assert(!!str2prefix(args->prefix, &p));
+
+       switch (args->afi) {
        case AFI_IP:
                /* Cisco like mask notation. */
-               if (mask_str) {
-                       ret = inet_aton(mask_str, &mask);
-                       if (ret == 0) {
-                               vty_out(vty, "%% Malformed address\n");
-                               return CMD_WARNING_CONFIG_FAILED;
-                       }
+               if (args->prefix_mask) {
+                       assert(inet_pton(AF_INET, args->prefix_mask, &mask) ==
+                              1);
                        p.prefixlen = ip_masklen(mask);
                }
                break;
        case AFI_IP6:
                /* srcdest routing */
-               if (src_str) {
-                       ret = str2prefix(src_str, &src);
-                       if (ret <= 0 || src.family != AF_INET6) {
-                               vty_out(vty, "%% Malformed source address\n");
-                               return CMD_WARNING_CONFIG_FAILED;
-                       }
-               }
+               if (args->source)
+                       assert(!!str2prefix(args->source, &src));
                break;
        default:
                break;
@@ -109,62 +136,64 @@ static int static_route_leak(struct vty *vty, const char *svrf,
 
        /* Apply mask for given prefix. */
        apply_mask(&p);
-
        prefix2str(&p, buf_prefix, sizeof(buf_prefix));
 
-       if (src_str)
+       if (args->source)
                prefix2str(&src, buf_src_prefix, sizeof(buf_src_prefix));
-       if (gate_str)
-               buf_gate_str = gate_str;
+       if (args->gateway)
+               buf_gate_str = args->gateway;
        else
                buf_gate_str = "";
 
-       if (gate_str == NULL && ifname == NULL)
+       if (args->gateway == NULL && args->interface_name == NULL)
                type = STATIC_BLACKHOLE;
-       else if (gate_str && ifname) {
-               if (afi == AFI_IP)
+       else if (args->gateway && args->interface_name) {
+               if (args->afi == AFI_IP)
                        type = STATIC_IPV4_GATEWAY_IFNAME;
                else
                        type = STATIC_IPV6_GATEWAY_IFNAME;
-       } else if (ifname)
+       } else if (args->interface_name)
                type = STATIC_IFNAME;
        else {
-               if (afi == AFI_IP)
+               if (args->afi == AFI_IP)
                        type = STATIC_IPV4_GATEWAY;
                else
                        type = STATIC_IPV6_GATEWAY;
        }
 
        /* Administrative distance. */
-       if (distance_str)
-               distance = atoi(distance_str);
+       if (args->distance)
+               distance = strtol(args->distance, NULL, 10);
 
        /* tag */
-       if (tag_str)
-               tag = strtoul(tag_str, NULL, 10);
+       if (args->tag)
+               tag = strtoul(args->tag, NULL, 10);
 
        /* TableID */
-       if (table_str)
-               table_id = atol(table_str);
+       if (args->table)
+               table_id = strtol(args->table, NULL, 10);
 
-       static_get_nh_type(type, buf_nh_type, PREFIX_STRLEN);
-       if (!negate) {
-               if (src_str)
+       static_get_nh_type(type, buf_nh_type, sizeof(buf_nh_type));
+       if (!args->delete) {
+               if (args->source)
                        snprintf(ab_xpath, sizeof(ab_xpath),
                                 FRR_DEL_S_ROUTE_SRC_NH_KEY_NO_DISTANCE_XPATH,
-                                "frr-staticd:staticd", "staticd", svrf,
+                                "frr-staticd:staticd", "staticd", args->vrf,
                                 buf_prefix,
-                                yang_afi_safi_value2identity(afi, safi),
-                                buf_src_prefix, table_id, buf_nh_type, nh_svrf,
-                                buf_gate_str, ifname);
+                                yang_afi_safi_value2identity(args->afi,
+                                                             args->safi),
+                                buf_src_prefix, table_id, buf_nh_type,
+                                args->nexthop_vrf, buf_gate_str,
+                                args->interface_name);
                else
                        snprintf(ab_xpath, sizeof(ab_xpath),
                                 FRR_DEL_S_ROUTE_NH_KEY_NO_DISTANCE_XPATH,
-                                "frr-staticd:staticd", "staticd", svrf,
+                                "frr-staticd:staticd", "staticd", args->vrf,
                                 buf_prefix,
-                                yang_afi_safi_value2identity(afi, safi),
-                                table_id, buf_nh_type, nh_svrf, buf_gate_str,
-                                ifname);
+                                yang_afi_safi_value2identity(args->afi,
+                                                             args->safi),
+                                table_id, buf_nh_type, args->nexthop_vrf,
+                                buf_gate_str, args->interface_name);
 
                /*
                 * If there's already the same nexthop but with a different
@@ -181,19 +210,21 @@ static int static_route_leak(struct vty *vty, const char *svrf,
                }
 
                /* route + path procesing */
-               if (src_str)
+               if (args->source)
                        snprintf(xpath_prefix, sizeof(xpath_prefix),
                                 FRR_S_ROUTE_SRC_INFO_KEY_XPATH,
-                                "frr-staticd:staticd", "staticd", svrf,
+                                "frr-staticd:staticd", "staticd", args->vrf,
                                 buf_prefix,
-                                yang_afi_safi_value2identity(afi, safi),
+                                yang_afi_safi_value2identity(args->afi,
+                                                             args->safi),
                                 buf_src_prefix, table_id, distance);
                else
                        snprintf(xpath_prefix, sizeof(xpath_prefix),
                                 FRR_STATIC_ROUTE_INFO_KEY_XPATH,
-                                "frr-staticd:staticd", "staticd", svrf,
+                                "frr-staticd:staticd", "staticd", args->vrf,
                                 buf_prefix,
-                                yang_afi_safi_value2identity(afi, safi),
+                                yang_afi_safi_value2identity(args->afi,
+                                                             args->safi),
                                 table_id, distance);
 
                nb_cli_enqueue_change(vty, xpath_prefix, NB_OP_CREATE, NULL);
@@ -208,8 +239,8 @@ static int static_route_leak(struct vty *vty, const char *svrf,
                /* nexthop processing */
 
                snprintf(ab_xpath, sizeof(ab_xpath),
-                        FRR_STATIC_ROUTE_NH_KEY_XPATH, buf_nh_type, nh_svrf,
-                        buf_gate_str, ifname);
+                        FRR_STATIC_ROUTE_NH_KEY_XPATH, buf_nh_type,
+                        args->nexthop_vrf, buf_gate_str, args->interface_name);
                strlcpy(xpath_nexthop, xpath_prefix, sizeof(xpath_nexthop));
                strlcat(xpath_nexthop, ab_xpath, sizeof(xpath_nexthop));
                nb_cli_enqueue_change(vty, xpath_nexthop, NB_OP_CREATE, NULL);
@@ -220,8 +251,8 @@ static int static_route_leak(struct vty *vty, const char *svrf,
                                sizeof(ab_xpath));
 
                        /* Route flags */
-                       if (flag_str) {
-                               switch (flag_str[0]) {
+                       if (args->flag) {
+                               switch (args->flag[0]) {
                                case 'r':
                                        bh_type = "reject";
                                        break;
@@ -248,7 +279,7 @@ static int static_route_leak(struct vty *vty, const char *svrf,
                        strlcat(ab_xpath, FRR_STATIC_ROUTE_NH_ONLINK_XPATH,
                                sizeof(ab_xpath));
 
-                       if (onlink)
+                       if (args->onlink)
                                nb_cli_enqueue_change(vty, ab_xpath,
                                                      NB_OP_MODIFY, "true");
                        else
@@ -262,11 +293,12 @@ static int static_route_leak(struct vty *vty, const char *svrf,
                        strlcpy(ab_xpath, xpath_nexthop, sizeof(ab_xpath));
                        strlcat(ab_xpath, FRR_STATIC_ROUTE_NH_COLOR_XPATH,
                                sizeof(ab_xpath));
-                       if (color_str)
+                       if (args->color)
                                nb_cli_enqueue_change(vty, ab_xpath,
-                                                     NB_OP_MODIFY, color_str);
+                                                     NB_OP_MODIFY,
+                                                     args->color);
                }
-               if (label_str) {
+               if (args->label) {
                        /* copy of label string (start) */
                        char *ostr;
                        /* pointer to next segment */
@@ -279,7 +311,7 @@ static int static_route_leak(struct vty *vty, const char *svrf,
                        nb_cli_enqueue_change(vty, xpath_mpls, NB_OP_DESTROY,
                                              NULL);
 
-                       ostr = XSTRDUP(MTYPE_TMP, label_str);
+                       ostr = XSTRDUP(MTYPE_TMP, args->label);
                        while ((nump = strsep(&ostr, "/")) != NULL) {
                                snprintf(ab_xpath, sizeof(ab_xpath),
                                         FRR_STATIC_ROUTE_NHLB_KEY_XPATH,
@@ -302,22 +334,25 @@ static int static_route_leak(struct vty *vty, const char *svrf,
                }
                ret = nb_cli_apply_changes(vty, xpath_prefix);
        } else {
-               if (src_str)
+               if (args->source)
                        snprintf(ab_xpath, sizeof(ab_xpath),
                                 FRR_DEL_S_ROUTE_SRC_NH_KEY_NO_DISTANCE_XPATH,
-                                "frr-staticd:staticd", "staticd", svrf,
+                                "frr-staticd:staticd", "staticd", args->vrf,
                                 buf_prefix,
-                                yang_afi_safi_value2identity(afi, safi),
-                                buf_src_prefix, table_id, buf_nh_type, nh_svrf,
-                                buf_gate_str, ifname);
+                                yang_afi_safi_value2identity(args->afi,
+                                                             args->safi),
+                                buf_src_prefix, table_id, buf_nh_type,
+                                args->nexthop_vrf, buf_gate_str,
+                                args->interface_name);
                else
                        snprintf(ab_xpath, sizeof(ab_xpath),
                                 FRR_DEL_S_ROUTE_NH_KEY_NO_DISTANCE_XPATH,
-                                "frr-staticd:staticd", "staticd", svrf,
+                                "frr-staticd:staticd", "staticd", args->vrf,
                                 buf_prefix,
-                                yang_afi_safi_value2identity(afi, safi),
-                                table_id, buf_nh_type, nh_svrf, buf_gate_str,
-                                ifname);
+                                yang_afi_safi_value2identity(args->afi,
+                                                             args->safi),
+                                table_id, buf_nh_type, args->nexthop_vrf,
+                                buf_gate_str, args->interface_name);
 
                dnode = yang_dnode_get(vty->candidate_config->dnode, ab_xpath);
                if (!dnode) {
@@ -336,22 +371,6 @@ static int static_route_leak(struct vty *vty, const char *svrf,
 
        return ret;
 }
-static int static_route(struct vty *vty, afi_t afi, safi_t safi,
-                       const char *negate, const char *dest_str,
-                       const char *mask_str, const char *src_str,
-                       const char *gate_str, const char *ifname,
-                       const char *flag_str, const char *tag_str,
-                       const char *distance_str, const char *vrf_name,
-                       const char *label_str, const char *table_str)
-{
-       if (!vrf_name)
-               vrf_name = VRF_DEFAULT_NAME;
-
-       return static_route_leak(vty, vrf_name, vrf_name, afi, safi, negate,
-                                dest_str, mask_str, src_str, gate_str, ifname,
-                                flag_str, tag_str, distance_str, label_str,
-                                table_str, false, NULL);
-}
 
 /* Static unicast routes for multicast RPF lookup. */
 DEFPY_YANG (ip_mroute_dist,
@@ -365,9 +384,17 @@ DEFPY_YANG (ip_mroute_dist,
        "Nexthop interface name\n"
        "Distance\n")
 {
-       return static_route(vty, AFI_IP, SAFI_MULTICAST, no, prefix_str,
-                           NULL, NULL, gate_str, ifname, NULL, NULL,
-                           distance_str, NULL, NULL, NULL);
+       struct static_route_args args = {
+               .delete = !!no,
+               .afi = AFI_IP,
+               .safi = SAFI_MULTICAST,
+               .prefix = prefix_str,
+               .gateway = gate_str,
+               .interface_name = ifname,
+               .distance = distance_str,
+       };
+
+       return static_route_nb_run(vty, &args);
 }
 
 /* Static route configuration.  */
@@ -398,9 +425,21 @@ DEFPY_YANG(ip_route_blackhole,
       "Table to configure\n"
       "The table number to configure\n")
 {
-       return static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
-                           mask_str, NULL, NULL, NULL, flag, tag_str,
-                           distance_str, vrf, label, table_str);
+       struct static_route_args args = {
+               .delete = !!no,
+               .afi = AFI_IP,
+               .safi = SAFI_UNICAST,
+               .prefix = prefix,
+               .prefix_mask = mask_str,
+               .flag = flag,
+               .tag = tag_str,
+               .distance = distance_str,
+               .label = label,
+               .table = table_str,
+               .vrf = vrf,
+       };
+
+       return static_route_nb_run(vty, &args);
 }
 
 DEFPY_YANG(ip_route_blackhole_vrf,
@@ -428,26 +467,28 @@ DEFPY_YANG(ip_route_blackhole_vrf,
       "Table to configure\n"
       "The table number to configure\n")
 {
-       const struct lyd_node *vrf_dnode;
-       const char *vrfname;
+       struct static_route_args args = {
+               .delete = !!no,
+               .afi = AFI_IP,
+               .safi = SAFI_UNICAST,
+               .prefix = prefix,
+               .prefix_mask = mask_str,
+               .flag = flag,
+               .tag = tag_str,
+               .distance = distance_str,
+               .label = label,
+               .table = table_str,
+               .xpath_vrf = true,
+       };
 
-       vrf_dnode =
-               yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
-       if (!vrf_dnode) {
-               vty_out(vty, "%% Failed to get vrf dnode in candidate db\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       vrfname = yang_dnode_get_string(vrf_dnode, "./name");
        /*
         * Coverity is complaining that prefix could
         * be dereferenced, but we know that prefix will
         * valid.  Add an assert to make it happy
         */
-       assert(prefix);
-       return static_route_leak(vty, vrfname, vrfname, AFI_IP, SAFI_UNICAST,
-                                no, prefix, mask_str, NULL, NULL, NULL, flag,
-                                tag_str, distance_str, label, table_str,
-                                false, NULL);
+       assert(args.prefix);
+
+       return static_route_nb_run(vty, &args);
 }
 
 DEFPY_YANG(ip_route_address_interface,
@@ -486,25 +527,25 @@ DEFPY_YANG(ip_route_address_interface,
       "SR-TE color\n"
       "The SR-TE color to configure\n")
 {
-       const char *nh_vrf;
-       const char *flag = NULL;
-
-       if (ifname && !strncasecmp(ifname, "Null0", 5)) {
-               flag = "Null0";
-               ifname = NULL;
-       }
-       if (!vrf)
-               vrf = VRF_DEFAULT_NAME;
-
-       if (nexthop_vrf)
-               nh_vrf = nexthop_vrf;
-       else
-               nh_vrf = vrf;
-
-       return static_route_leak(vty, vrf, nh_vrf, AFI_IP, SAFI_UNICAST, no,
-                                prefix, mask_str, NULL, gate_str, ifname, flag,
-                                tag_str, distance_str, label, table_str,
-                                !!onlink, color_str);
+       struct static_route_args args = {
+               .delete = !!no,
+               .afi = AFI_IP,
+               .safi = SAFI_UNICAST,
+               .prefix = prefix,
+               .prefix_mask = mask_str,
+               .gateway = gate_str,
+               .interface_name = ifname,
+               .tag = tag_str,
+               .distance = distance_str,
+               .label = label,
+               .table = table_str,
+               .color = color_str,
+               .onlink = !!onlink,
+               .vrf = vrf,
+               .nexthop_vrf = nexthop_vrf,
+       };
+
+       return static_route_nb_run(vty, &args);
 }
 
 DEFPY_YANG(ip_route_address_interface_vrf,
@@ -541,32 +582,25 @@ DEFPY_YANG(ip_route_address_interface_vrf,
       "SR-TE color\n"
       "The SR-TE color to configure\n")
 {
-       const char *nh_vrf;
-       const char *flag = NULL;
-       const struct lyd_node *vrf_dnode;
-       const char *vrfname;
-
-       vrf_dnode =
-               yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
-       if (!vrf_dnode) {
-               vty_out(vty, "%% Failed to get vrf dnode in candidate db\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-
-       if (ifname && !strncasecmp(ifname, "Null0", 5)) {
-               flag = "Null0";
-               ifname = NULL;
-       }
-       if (nexthop_vrf)
-               nh_vrf = nexthop_vrf;
-       else
-               nh_vrf = vrfname;
-
-       return static_route_leak(vty, vrfname, nh_vrf, AFI_IP, SAFI_UNICAST, no,
-                                prefix, mask_str, NULL, gate_str, ifname, flag,
-                                tag_str, distance_str, label, table_str,
-                                !!onlink, color_str);
+       struct static_route_args args = {
+               .delete = !!no,
+               .afi = AFI_IP,
+               .safi = SAFI_UNICAST,
+               .prefix = prefix,
+               .prefix_mask = mask_str,
+               .gateway = gate_str,
+               .interface_name = ifname,
+               .tag = tag_str,
+               .distance = distance_str,
+               .label = label,
+               .table = table_str,
+               .color = color_str,
+               .onlink = !!onlink,
+               .xpath_vrf = true,
+               .nexthop_vrf = nexthop_vrf,
+       };
+
+       return static_route_nb_run(vty, &args);
 }
 
 DEFPY_YANG(ip_route,
@@ -602,26 +636,24 @@ DEFPY_YANG(ip_route,
       "SR-TE color\n"
       "The SR-TE color to configure\n")
 {
-       const char *nh_vrf;
-       const char *flag = NULL;
-
-       if (ifname && !strncasecmp(ifname, "Null0", 5)) {
-               flag = "Null0";
-               ifname = NULL;
-       }
-
-       if (!vrf)
-               vrf = VRF_DEFAULT_NAME;
-
-       if (nexthop_vrf)
-               nh_vrf = nexthop_vrf;
-       else
-               nh_vrf = vrf;
-
-       return static_route_leak(vty, vrf, nh_vrf, AFI_IP, SAFI_UNICAST, no,
-                                prefix, mask_str, NULL, gate_str, ifname, flag,
-                                tag_str, distance_str, label, table_str,
-                                false, color_str);
+       struct static_route_args args = {
+               .delete = !!no,
+               .afi = AFI_IP,
+               .safi = SAFI_UNICAST,
+               .prefix = prefix,
+               .prefix_mask = mask_str,
+               .gateway = gate_str,
+               .interface_name = ifname,
+               .tag = tag_str,
+               .distance = distance_str,
+               .label = label,
+               .table = table_str,
+               .color = color_str,
+               .vrf = vrf,
+               .nexthop_vrf = nexthop_vrf,
+       };
+
+       return static_route_nb_run(vty, &args);
 }
 
 DEFPY_YANG(ip_route_vrf,
@@ -655,33 +687,24 @@ DEFPY_YANG(ip_route_vrf,
       "SR-TE color\n"
       "The SR-TE color to configure\n")
 {
-       const char *nh_vrf;
-       const char *flag = NULL;
-       const struct lyd_node *vrf_dnode;
-       const char *vrfname;
-
-       vrf_dnode =
-               yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
-       if (!vrf_dnode) {
-               vty_out(vty, "%% Failed to get vrf dnode in candidate db\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-
-       vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-
-       if (ifname && !strncasecmp(ifname, "Null0", 5)) {
-               flag = "Null0";
-               ifname = NULL;
-       }
-       if (nexthop_vrf)
-               nh_vrf = nexthop_vrf;
-       else
-               nh_vrf = vrfname;
-
-       return static_route_leak(vty, vrfname, nh_vrf, AFI_IP, SAFI_UNICAST, no,
-                                prefix, mask_str, NULL, gate_str, ifname, flag,
-                                tag_str, distance_str, label, table_str,
-                                false, color_str);
+       struct static_route_args args = {
+               .delete = !!no,
+               .afi = AFI_IP,
+               .safi = SAFI_UNICAST,
+               .prefix = prefix,
+               .prefix_mask = mask_str,
+               .gateway = gate_str,
+               .interface_name = ifname,
+               .tag = tag_str,
+               .distance = distance_str,
+               .label = label,
+               .table = table_str,
+               .color = color_str,
+               .xpath_vrf = true,
+               .nexthop_vrf = nexthop_vrf,
+       };
+
+       return static_route_nb_run(vty, &args);
 }
 
 DEFPY_YANG(ipv6_route_blackhole,
@@ -711,9 +734,21 @@ DEFPY_YANG(ipv6_route_blackhole,
       "Table to configure\n"
       "The table number to configure\n")
 {
-       return static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
-                           NULL, from_str, NULL, NULL, flag, tag_str,
-                           distance_str, vrf, label, table_str);
+       struct static_route_args args = {
+               .delete = !!no,
+               .afi = AFI_IP6,
+               .safi = SAFI_UNICAST,
+               .prefix = prefix_str,
+               .source = from_str,
+               .flag = flag,
+               .tag = tag_str,
+               .distance = distance_str,
+               .label = label,
+               .table = table_str,
+               .vrf = vrf,
+       };
+
+       return static_route_nb_run(vty, &args);
 }
 
 DEFPY_YANG(ipv6_route_blackhole_vrf,
@@ -741,28 +776,28 @@ DEFPY_YANG(ipv6_route_blackhole_vrf,
       "Table to configure\n"
       "The table number to configure\n")
 {
-       const struct lyd_node *vrf_dnode;
-       const char *vrfname;
-
-       vrf_dnode =
-               yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
-       if (!vrf_dnode) {
-               vty_out(vty, "%% Failed to get vrf dnode in candidate db\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       vrfname = yang_dnode_get_string(vrf_dnode, "./name");
+       struct static_route_args args = {
+               .delete = !!no,
+               .afi = AFI_IP6,
+               .safi = SAFI_UNICAST,
+               .prefix = prefix_str,
+               .source = from_str,
+               .flag = flag,
+               .tag = tag_str,
+               .distance = distance_str,
+               .label = label,
+               .table = table_str,
+               .xpath_vrf = true,
+       };
 
        /*
         * Coverity is complaining that prefix could
         * be dereferenced, but we know that prefix will
         * valid.  Add an assert to make it happy
         */
-       assert(prefix);
+       assert(args.prefix);
 
-       return static_route_leak(vty, vrfname, vrfname, AFI_IP6, SAFI_UNICAST,
-                                no, prefix_str, NULL, from_str, NULL, NULL,
-                                flag, tag_str, distance_str, label, table_str,
-                                false, NULL);
+       return static_route_nb_run(vty, &args);
 }
 
 DEFPY_YANG(ipv6_route_address_interface,
@@ -801,26 +836,25 @@ DEFPY_YANG(ipv6_route_address_interface,
       "SR-TE color\n"
       "The SR-TE color to configure\n")
 {
-       const char *nh_vrf;
-       const char *flag = NULL;
-
-       if (ifname && !strncasecmp(ifname, "Null0", 5)) {
-               flag = "Null0";
-               ifname = NULL;
-       }
-
-       if (!vrf)
-               vrf = VRF_DEFAULT_NAME;
-
-       if (nexthop_vrf)
-               nh_vrf = nexthop_vrf;
-       else
-               nh_vrf = vrf;
-
-       return static_route_leak(vty, vrf, nh_vrf, AFI_IP6, SAFI_UNICAST, no,
-                                prefix_str, NULL, from_str, gate_str, ifname,
-                                flag, tag_str, distance_str, label, table_str,
-                                !!onlink, color_str);
+       struct static_route_args args = {
+               .delete = !!no,
+               .afi = AFI_IP6,
+               .safi = SAFI_UNICAST,
+               .prefix = prefix_str,
+               .source = from_str,
+               .gateway = gate_str,
+               .interface_name = ifname,
+               .tag = tag_str,
+               .distance = distance_str,
+               .label = label,
+               .table = table_str,
+               .color = color_str,
+               .onlink = !!onlink,
+               .vrf = vrf,
+               .nexthop_vrf = nexthop_vrf,
+       };
+
+       return static_route_nb_run(vty, &args);
 }
 
 DEFPY_YANG(ipv6_route_address_interface_vrf,
@@ -857,32 +891,25 @@ DEFPY_YANG(ipv6_route_address_interface_vrf,
       "SR-TE color\n"
       "The SR-TE color to configure\n")
 {
-       const char *nh_vrf;
-       const char *flag = NULL;
-       const struct lyd_node *vrf_dnode;
-       const char *vrfname;
-
-       vrf_dnode =
-               yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
-       if (!vrf_dnode) {
-               vty_out(vty, "%% Failed to get vrf dnode in candidate db\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-
-       if (nexthop_vrf)
-               nh_vrf = nexthop_vrf;
-       else
-               nh_vrf = vrfname;
-
-       if (ifname && !strncasecmp(ifname, "Null0", 5)) {
-               flag = "Null0";
-               ifname = NULL;
-       }
-       return static_route_leak(vty, vrfname, nh_vrf, AFI_IP6, SAFI_UNICAST,
-                                no, prefix_str, NULL, from_str, gate_str,
-                                ifname, flag, tag_str, distance_str, label,
-                                table_str, !!onlink, color_str);
+       struct static_route_args args = {
+               .delete = !!no,
+               .afi = AFI_IP6,
+               .safi = SAFI_UNICAST,
+               .prefix = prefix_str,
+               .source = from_str,
+               .gateway = gate_str,
+               .interface_name = ifname,
+               .tag = tag_str,
+               .distance = distance_str,
+               .label = label,
+               .table = table_str,
+               .color = color_str,
+               .onlink = !!onlink,
+               .xpath_vrf = true,
+               .nexthop_vrf = nexthop_vrf,
+       };
+
+       return static_route_nb_run(vty, &args);
 }
 
 DEFPY_YANG(ipv6_route,
@@ -918,25 +945,24 @@ DEFPY_YANG(ipv6_route,
       "SR-TE color\n"
       "The SR-TE color to configure\n")
 {
-       const char *nh_vrf;
-       const char *flag = NULL;
-
-       if (!vrf)
-               vrf = VRF_DEFAULT_NAME;
-
-       if (nexthop_vrf)
-               nh_vrf = nexthop_vrf;
-       else
-               nh_vrf = vrf;
-
-       if (ifname && !strncasecmp(ifname, "Null0", 5)) {
-               flag = "Null0";
-               ifname = NULL;
-       }
-       return static_route_leak(vty, vrf, nh_vrf, AFI_IP6, SAFI_UNICAST, no,
-                                prefix_str, NULL, from_str, gate_str, ifname,
-                                flag, tag_str, distance_str, label, table_str,
-                                false, color_str);
+       struct static_route_args args = {
+               .delete = !!no,
+               .afi = AFI_IP6,
+               .safi = SAFI_UNICAST,
+               .prefix = prefix_str,
+               .source = from_str,
+               .gateway = gate_str,
+               .interface_name = ifname,
+               .tag = tag_str,
+               .distance = distance_str,
+               .label = label,
+               .table = table_str,
+               .color = color_str,
+               .vrf = vrf,
+               .nexthop_vrf = nexthop_vrf,
+       };
+
+       return static_route_nb_run(vty, &args);
 }
 
 DEFPY_YANG(ipv6_route_vrf,
@@ -970,32 +996,24 @@ DEFPY_YANG(ipv6_route_vrf,
       "SR-TE color\n"
       "The SR-TE color to configure\n")
 {
-       const char *nh_vrf;
-       const char *flag = NULL;
-       const struct lyd_node *vrf_dnode;
-       const char *vrfname;
-
-       vrf_dnode =
-               yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
-       if (!vrf_dnode) {
-               vty_out(vty, "%% Failed to get vrf dnode in candidate db\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-
-       if (nexthop_vrf)
-               nh_vrf = nexthop_vrf;
-       else
-               nh_vrf = vrfname;
-
-       if (ifname && !strncasecmp(ifname, "Null0", 5)) {
-               flag = "Null0";
-               ifname = NULL;
-       }
-       return static_route_leak(vty, vrfname, nh_vrf, AFI_IP6, SAFI_UNICAST,
-                                no, prefix_str, NULL, from_str, gate_str,
-                                ifname, flag, tag_str, distance_str, label,
-                                table_str, false, color_str);
+       struct static_route_args args = {
+               .delete = !!no,
+               .afi = AFI_IP6,
+               .safi = SAFI_UNICAST,
+               .prefix = prefix_str,
+               .source = from_str,
+               .gateway = gate_str,
+               .interface_name = ifname,
+               .tag = tag_str,
+               .distance = distance_str,
+               .label = label,
+               .table = table_str,
+               .color = color_str,
+               .xpath_vrf = true,
+               .nexthop_vrf = nexthop_vrf,
+       };
+
+       return static_route_nb_run(vty, &args);
 }
 
 void static_cli_show(struct vty *vty, const struct lyd_node *dnode,