From 599186ad970b50d689f719dbb8cf527df0089d01 Mon Sep 17 00:00:00 2001 From: Renato Westphal Date: Thu, 27 Jul 2017 18:57:37 -0300 Subject: [PATCH] zebra: allow fully specified static ipv4 routes 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 --- zebra/zebra_static.c | 27 +++++++-- zebra/zebra_static.h | 6 +- zebra/zebra_vty.c | 140 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 156 insertions(+), 17 deletions(-) diff --git a/zebra/zebra_static.c b/zebra/zebra_static.c index ae32395161..6cebae997c 100644 --- a/zebra/zebra_static.c +++ b/zebra/zebra_static.c @@ -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; diff --git a/zebra/zebra_static.h b/zebra/zebra_static.h index dff799a9aa..885774895f 100644 --- a/zebra/zebra_static.h +++ b/zebra/zebra_static.h @@ -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; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index c5cdad890a..96f9221698 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -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 [{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 [{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 [{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); -- 2.39.5