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 <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2017-07-27 18:57:37 -03:00
parent c6cef20ba9
commit 599186ad97
3 changed files with 156 additions and 17 deletions

View 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
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;

View 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;

View 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);