]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: allow fully specified static ipv4 routes
authorRenato Westphal <renato@opensourcerouting.org>
Thu, 27 Jul 2017 21:57:37 +0000 (18:57 -0300)
committerRenato Westphal <renato@opensourcerouting.org>
Fri, 28 Jul 2017 02:46:41 +0000 (23:46 -0300)
Fully specified routes are useful when you need to ensure that the
nexthop address is reachable through the specified interface.

Addresses Issue #641.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
zebra/zebra_static.c
zebra/zebra_static.h
zebra/zebra_vty.c

index ae32395161733d9f611f360aaefcdbd81f4fba56..6cebae997c86f256d4dc59d7a5d83b685f289149 100644 (file)
@@ -81,6 +81,10 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
                        nh_p.u.prefix4 = si->addr.ipv4;
                        zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
                        break;
+               case STATIC_IPV4_GATEWAY_IFINDEX:
+                       nexthop = route_entry_nexthop_ipv4_ifindex_add(
+                               re, &si->addr.ipv4, NULL, si->ifindex);
+                       break;
                case STATIC_IFINDEX:
                        nexthop = route_entry_nexthop_ifindex_add(re,
                                                                  si->ifindex);
@@ -152,6 +156,10 @@ void static_install_route(afi_t afi, safi_t safi, struct prefix *p,
                        nh_p.u.prefix4 = si->addr.ipv4;
                        zebra_register_rnh_static_nh(si->vrf_id, &nh_p, rn);
                        break;
+               case STATIC_IPV4_GATEWAY_IFINDEX:
+                       nexthop = route_entry_nexthop_ipv4_ifindex_add(
+                               re, &si->addr.ipv4, NULL, si->ifindex);
+                       break;
                case STATIC_IFINDEX:
                        nexthop = route_entry_nexthop_ifindex_add(re,
                                                                  si->ifindex);
@@ -216,6 +224,11 @@ static int static_nexthop_same(struct nexthop *nexthop, struct static_route *si)
            && si->type == STATIC_IPV4_GATEWAY
            && IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4))
                return 1;
+       else if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX
+                && si->type == STATIC_IPV4_GATEWAY_IFINDEX
+                && IPV4_ADDR_SAME(&nexthop->gate.ipv4, &si->addr.ipv4)
+                && nexthop->ifindex == si->ifindex)
+               return 1;
        else if (nexthop->type == NEXTHOP_TYPE_IFINDEX
                 && si->type == STATIC_IFINDEX
                 && nexthop->ifindex == si->ifindex)
@@ -361,12 +374,17 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
        if (!stable)
                return -1;
 
-       if (!gate && (type == STATIC_IPV4_GATEWAY || type == STATIC_IPV6_GATEWAY
-                     || type == STATIC_IPV6_GATEWAY_IFINDEX))
+       if (!gate
+           && (type == STATIC_IPV4_GATEWAY
+               || type == STATIC_IPV4_GATEWAY_IFINDEX
+               || type == STATIC_IPV6_GATEWAY
+               || type == STATIC_IPV6_GATEWAY_IFINDEX))
                return -1;
 
        if (!ifindex
-           && (type == STATIC_IFINDEX || type == STATIC_IPV6_GATEWAY_IFINDEX))
+           && (type == STATIC_IFINDEX
+               || type == STATIC_IPV4_GATEWAY_IFINDEX
+               || type == STATIC_IPV6_GATEWAY_IFINDEX))
                return -1;
 
        /* Lookup static route prefix. */
@@ -411,11 +429,10 @@ int static_add_route(afi_t afi, safi_t safi, u_char type, struct prefix *p,
 
        switch (type) {
        case STATIC_IPV4_GATEWAY:
+       case STATIC_IPV4_GATEWAY_IFINDEX:
                si->addr.ipv4 = gate->ipv4;
                break;
        case STATIC_IPV6_GATEWAY:
-               si->addr.ipv6 = gate->ipv6;
-               break;
        case STATIC_IPV6_GATEWAY_IFINDEX:
                si->addr.ipv6 = gate->ipv6;
                break;
index dff799a9aa2671d0b6e7aa1d7235ccd03a546cc7..885774895fe9a4a70fcf3182ee2384a9f4b40ab2 100644 (file)
@@ -32,6 +32,7 @@ struct static_nh_label {
 typedef enum {
        STATIC_IFINDEX,
        STATIC_IPV4_GATEWAY,
+       STATIC_IPV4_GATEWAY_IFINDEX,
        STATIC_BLACKHOLE,
        STATIC_IPV6_GATEWAY,
        STATIC_IPV6_GATEWAY_IFINDEX,
@@ -57,11 +58,6 @@ struct static_route {
 
        /*
         * Nexthop value.
-        *
-        * Under IPv4 addr and ifindex are
-        * used independentyly.
-        * STATIC_IPV4_GATEWAY uses addr
-        * STATIC_IFINDEX uses ifindex
         */
        union g_addr addr;
        ifindex_t ifindex;
index c5cdad890a62d00c5d2e74a1429d9590b203c1a6..96f9221698f4e5aa28bc4a4f604d54b0ea3f3a77 100644 (file)
@@ -201,8 +201,7 @@ static int zebra_static_ipv4(struct vty *vty, safi_t safi, int add_cmd,
        if (gate_str == NULL && ifname == NULL)
                type = STATIC_BLACKHOLE;
        else if (gate_str && ifname)
-               /* TODO: not implemented yet */
-               return CMD_WARNING_CONFIG_FAILED;
+               type = STATIC_IPV4_GATEWAY_IFINDEX;
        else if (ifname)
                type = STATIC_IFINDEX;
        else
@@ -457,6 +456,34 @@ DEFUN (ip_route_flags,
                NULL, argv[idx_reject_blackhole]->arg, tag, distance, vrf, NULL);
 }
 
+DEFUN (ip_route_ifname,
+       ip_route_ifname_cmd,
+       "ip route A.B.C.D/M A.B.C.D INTERFACE [{tag (1-4294967295)|(1-255)|vrf NAME|label WORD}]",
+       IP_STR
+       "Establish static routes\n"
+       "IP destination prefix (e.g. 10.0.0.0/8)\n"
+       "IP gateway address\n"
+       "IP gateway interface name\n"
+       "Set tag for this route\n"
+       "Tag value\n"
+       "Distance value for this route\n"
+       VRF_CMD_HELP_STR
+       MPLS_LABEL_HELPSTR)
+{
+       int idx_ipv4_prefixlen = 2;
+       int idx_curr = 5;
+       char *gate = argv[3]->arg;
+       char *ifname = argv[4]->arg;
+       char *tag, *distance, *vrf, *label;
+
+       zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance,
+                                     &vrf, &label);
+
+       return zebra_static_ipv4(vty, SAFI_UNICAST, 1,
+                                argv[idx_ipv4_prefixlen]->arg, NULL, gate,
+                                ifname, NULL, tag, distance, vrf, label);
+}
+
 /* Mask as A.B.C.D format.  */
 DEFUN_HIDDEN (ip_route_mask,
               ip_route_mask_cmd,
@@ -494,6 +521,36 @@ DEFUN_HIDDEN (ip_route_mask,
                                 gate, ifname, NULL, tag, distance, vrf, label);
 }
 
+DEFUN_HIDDEN (ip_route_mask_ifname,
+              ip_route_mask_ifname_cmd,
+              "ip route A.B.C.D A.B.C.D A.B.C.D INTERFACE [{tag (1-4294967295)|(1-255)|vrf NAME|label WORD}]",
+              IP_STR
+              "Establish static routes\n"
+              "IP destination prefix\n"
+              "IP destination prefix mask\n"
+              "IP gateway address\n"
+              "IP gateway interface name\n"
+              "Set tag for this route\n"
+              "Tag value\n"
+              "Distance value for this route\n"
+              VRF_CMD_HELP_STR
+              MPLS_LABEL_HELPSTR)
+{
+       int idx_ipv4 = 2;
+       int idx_ipv4_2 = 3;
+       int idx_curr = 6;
+       char *gate = argv[4]->arg;
+       char *ifname = argv[5]->arg;
+       char *tag, *distance, *vrf, *label;
+
+       zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance,
+                                     &vrf, &label);
+
+       return zebra_static_ipv4(vty, SAFI_UNICAST, 1, argv[idx_ipv4]->arg,
+                                argv[idx_ipv4_2]->arg,
+                                gate, ifname, NULL, tag, distance, vrf, label);
+}
+
 DEFUN_HIDDEN (ip_route_mask_flags,
               ip_route_mask_flags_cmd,
               "ip route A.B.C.D A.B.C.D <reject|blackhole> [{tag (1-4294967295)|(1-255)|vrf NAME}]",
@@ -558,6 +615,35 @@ DEFUN (no_ip_route,
                                 gate, ifname, NULL, tag, distance, vrf, label);
 }
 
+DEFUN (no_ip_route_ifname,
+       no_ip_route_ifname_cmd,
+       "no ip route A.B.C.D/M A.B.C.D INTERFACE [{tag (1-4294967295)|(1-255)|vrf NAME|label WORD}]",
+       NO_STR
+       IP_STR
+       "Establish static routes\n"
+       "IP destination prefix (e.g. 10.0.0.0/8)\n"
+       "IP gateway address\n"
+       "IP gateway interface name\n"
+       "Tag of this route\n"
+       "Tag value\n"
+       "Distance value for this route\n"
+       VRF_CMD_HELP_STR
+       MPLS_LABEL_HELPSTR)
+{
+       int idx_ipv4_prefixlen = 3;
+       int idx_curr = 6;
+       char *gate = argv[4]->arg;
+       char *ifname = argv[5]->arg;
+       char *tag, *distance, *vrf, *label;
+
+       zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance,
+                                     &vrf, &label);
+
+       return zebra_static_ipv4(vty, SAFI_UNICAST, 0,
+                                argv[idx_ipv4_prefixlen]->arg, NULL,
+                                gate, ifname, NULL, tag, distance, vrf, label);
+}
+
 DEFUN (no_ip_route_flags,
        no_ip_route_flags_cmd,
        "no ip route A.B.C.D/M <reject|blackhole> [{tag (1-4294967295)|(1-255)|vrf NAME}]",
@@ -621,6 +707,37 @@ DEFUN_HIDDEN (no_ip_route_mask,
                                 gate, ifname, NULL, tag, distance, vrf, label);
 }
 
+DEFUN_HIDDEN (no_ip_route_mask_ifname,
+              no_ip_route_mask_ifname_cmd,
+              "no ip route A.B.C.D A.B.C.D A.B.C.D INTERFACE [{tag (1-4294967295)|(1-255)|vrf NAME|label WORD}]",
+              NO_STR
+              IP_STR
+              "Establish static routes\n"
+              "IP destination prefix\n"
+              "IP destination prefix mask\n"
+              "IP gateway address\n"
+              "IP gateway interface name\n"
+              "Tag of this route\n"
+              "Tag value\n"
+              "Distance value for this route\n"
+              VRF_CMD_HELP_STR
+              MPLS_LABEL_HELPSTR)
+{
+       int idx_ipv4 = 3;
+       int idx_ipv4_2 = 4;
+       int idx_curr = 7;
+       char *gate = argv[5]->arg;
+       char *ifname = argv[6]->arg;
+       char *tag, *distance, *vrf, *label;
+
+       zebra_vty_ip_route_tdv_helper(argc, argv, idx_curr, &tag, &distance,
+                                     &vrf, &label);
+
+       return zebra_static_ipv4(vty, SAFI_UNICAST, 0, argv[idx_ipv4]->arg,
+                                argv[idx_ipv4_2]->arg,
+                                gate, ifname, NULL, tag, distance, vrf, label);
+}
+
 DEFUN_HIDDEN (no_ip_route_mask_flags,
               no_ip_route_mask_flags_cmd,
               "no ip route A.B.C.D A.B.C.D <reject|blackhole> [{tag (1-4294967295)|(1-255)|vrf NAME}]",
@@ -1970,6 +2087,14 @@ static int static_config(struct vty *vty, afi_t afi, safi_t safi,
                                        else
                                                vty_out(vty, " Null0");
                                        break;
+                               case STATIC_IPV4_GATEWAY_IFINDEX:
+                                       vty_out(vty, " %s %s",
+                                               inet_ntop(AF_INET,
+                                                         &si->addr.ipv4, buf,
+                                                         sizeof buf),
+                                               ifindex2ifname(si->ifindex,
+                                                              si->vrf_id));
+                                       break;
                                case STATIC_IPV6_GATEWAY_IFINDEX:
                                        vty_out(vty, " %s %s",
                                                inet_ntop(AF_INET6,
@@ -3288,11 +3413,17 @@ void zebra_vty_init(void)
        install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
        install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
        install_element(CONFIG_NODE, &ip_route_cmd);
+       install_element(CONFIG_NODE, &ip_route_ifname_cmd);
        install_element(CONFIG_NODE, &ip_route_flags_cmd);
        install_element(CONFIG_NODE, &ip_route_mask_cmd);
+       install_element(CONFIG_NODE, &ip_route_mask_ifname_cmd);
        install_element(CONFIG_NODE, &ip_route_mask_flags_cmd);
        install_element(CONFIG_NODE, &no_ip_route_cmd);
+       install_element(CONFIG_NODE, &no_ip_route_flags_cmd);
+       install_element(CONFIG_NODE, &no_ip_route_ifname_cmd);
        install_element(CONFIG_NODE, &no_ip_route_mask_cmd);
+       install_element(CONFIG_NODE, &no_ip_route_mask_flags_cmd);
+       install_element(CONFIG_NODE, &no_ip_route_mask_ifname_cmd);
        install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
        install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
 
@@ -3310,11 +3441,6 @@ void zebra_vty_init(void)
        install_element(VIEW_NODE, &show_ip_rpf_cmd);
        install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
 
-       /* Commands for VRF */
-
-       install_element(CONFIG_NODE, &no_ip_route_flags_cmd);
-       install_element(CONFIG_NODE, &no_ip_route_mask_flags_cmd);
-
        install_element(VIEW_NODE, &show_ip_route_vrf_all_addr_cmd);
        install_element(VIEW_NODE, &show_ip_route_vrf_all_prefix_cmd);
        install_element(VIEW_NODE, &show_ip_route_vrf_all_summary_cmd);