summaryrefslogtreecommitdiff
path: root/zebra/zebra_vty.c
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2018-01-23 08:25:01 +0100
committerGitHub <noreply@github.com>2018-01-23 08:25:01 +0100
commitd6fed381094ba34c04166b08cd16af01f6c263ea (patch)
tree84eef98e9afe3c57dc9dff2e28a117c79511b936 /zebra/zebra_vty.c
parent5c6580957d18884f12dd8cdab9945b6f6bafd0ce (diff)
parent61408536df768ec97b235b463453b64f4e813369 (diff)
Merge pull request #1618 from donaldsharp/zebra_startup_ordering
zebra route-leaking for static routes
Diffstat (limited to 'zebra/zebra_vty.c')
-rw-r--r--zebra/zebra_vty.c609
1 files changed, 491 insertions, 118 deletions
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index df461ab10c..92e1076b2e 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -78,13 +78,16 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
#define CMD_VNI_RANGE "(1-16777215)"
/* General function for static route. */
-static int zebra_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_id_str,
- const char *label_str)
+static int zebra_static_route_leak(struct vty *vty,
+ struct zebra_vrf *zvrf,
+ struct zebra_vrf *nh_zvrf,
+ 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)
{
int ret;
u_char distance;
@@ -95,7 +98,6 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
struct in_addr mask;
enum static_blackhole_type bh_type = 0;
route_tag_t tag = 0;
- struct zebra_vrf *zvrf;
u_char type;
struct static_nh_label snh_label;
@@ -145,14 +147,6 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
if (tag_str)
tag = strtoul(tag_str, NULL, 10);
- /* VRF id */
- zvrf = zebra_vrf_lookup_by_name(vrf_id_str);
-
- if (!zvrf) {
- vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
/* Labels */
memset(&snh_label, 0, sizeof(struct static_nh_label));
if (label_str) {
@@ -239,7 +233,8 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
if (!negate)
static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
- bh_type, tag, distance, zvrf, &snh_label);
+ bh_type, tag, distance, zvrf, nh_zvrf,
+ &snh_label);
else
static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
tag, distance, zvrf, &snh_label);
@@ -247,6 +242,31 @@ static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
return CMD_SUCCESS;
}
+static int zebra_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_id_str,
+ const char *label_str)
+{
+ struct zebra_vrf *zvrf;
+
+ /* VRF id */
+ zvrf = zebra_vrf_lookup_by_name(vrf_id_str);
+
+ if (!zvrf) {
+ vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, zvrf, afi, safi,
+ negate, dest_str, mask_str, src_str,
+ gate_str, ifname, flag_str, tag_str,
+ distance_str, label_str);
+}
+
+
/* Static unicast routes for multicast RPF lookup. */
DEFPY (ip_mroute_dist,
ip_mroute_dist_cmd,
@@ -387,6 +407,37 @@ DEFPY(ip_route_blackhole,
tag_str, distance_str, vrf, label);
}
+DEFPY(ip_route_blackhole_vrf,
+ ip_route_blackhole_vrf_cmd,
+ "[no] ip route\
+ <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
+ <reject|blackhole>$flag \
+ [{ \
+ tag (1-4294967295) \
+ |(1-255)$distance \
+ |label WORD \
+ }]",
+ NO_STR IP_STR
+ "Establish static routes\n"
+ "IP destination prefix (e.g. 10.0.0.0/8)\n"
+ "IP destination prefix\n"
+ "IP destination prefix mask\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n"
+ "Set tag for this route\n"
+ "Tag value\n"
+ "Distance value for this route\n"
+ MPLS_LABEL_HELPSTR)
+{
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+ struct zebra_vrf *zvrf = vrf->info;
+
+ return zebra_static_route_leak(vty, zvrf, zvrf,
+ AFI_IP, SAFI_UNICAST, no, prefix,
+ mask_str, NULL, NULL, NULL, flag,
+ tag_str, distance_str, label);
+}
+
DEFPY(ip_route_address_interface,
ip_route_address_interface_cmd,
"[no] ip route\
@@ -398,6 +449,7 @@ DEFPY(ip_route_address_interface,
|(1-255)$distance \
|vrf NAME \
|label WORD \
+ |nexthop-vrf NAME \
}]",
NO_STR IP_STR
"Establish static routes\n"
@@ -411,16 +463,85 @@ DEFPY(ip_route_address_interface,
"Tag value\n"
"Distance value for this route\n"
VRF_CMD_HELP_STR
- MPLS_LABEL_HELPSTR)
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
{
+ struct zebra_vrf *zvrf;
+ struct zebra_vrf *nh_zvrf;
+
const char *flag = NULL;
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
- return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
- mask_str, NULL, gate_str, ifname, flag,
- tag_str, distance_str, vrf, label);
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ zvrf = zebra_vrf_lookup_by_name(vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP, SAFI_UNICAST, no, prefix,
+ mask_str, NULL, gate_str, ifname, flag,
+ tag_str, distance_str, label);
+}
+
+DEFPY(ip_route_address_interface_vrf,
+ ip_route_address_interface_vrf_cmd,
+ "[no] ip route\
+ <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
+ A.B.C.D$gate \
+ INTERFACE$ifname \
+ [{ \
+ tag (1-4294967295) \
+ |(1-255)$distance \
+ |label WORD \
+ |nexthop-vrf NAME \
+ }]",
+ NO_STR IP_STR
+ "Establish static routes\n"
+ "IP destination prefix (e.g. 10.0.0.0/8)\n"
+ "IP destination prefix\n"
+ "IP destination prefix mask\n"
+ "IP gateway address\n"
+ "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
+ null route.\n"
+ "Set tag for this route\n"
+ "Tag value\n"
+ "Distance value for this route\n"
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
+{
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+ const char *flag = NULL;
+ struct zebra_vrf *zvrf = vrf->info;
+ struct zebra_vrf *nh_zvrf;
+
+ if (ifname && !strncasecmp(ifname, "Null0", 5)) {
+ flag = "Null0";
+ ifname = NULL;
+ }
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP, SAFI_UNICAST, no, prefix,
+ mask_str, NULL, gate_str, ifname, flag,
+ tag_str, distance_str, label);
}
DEFPY(ip_route,
@@ -433,6 +554,7 @@ DEFPY(ip_route,
|(1-255)$distance \
|vrf NAME \
|label WORD \
+ |nexthop-vrf NAME \
}]",
NO_STR IP_STR
"Establish static routes\n"
@@ -445,16 +567,83 @@ DEFPY(ip_route,
"Tag value\n"
"Distance value for this route\n"
VRF_CMD_HELP_STR
- MPLS_LABEL_HELPSTR)
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
{
+ struct zebra_vrf *zvrf;
+ struct zebra_vrf *nh_zvrf;
const char *flag = NULL;
+
if (ifname && !strncasecmp(ifname, "Null0", 5)) {
flag = "Null0";
ifname = NULL;
}
- return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
- mask_str, NULL, gate_str, ifname, flag,
- tag_str, distance_str, vrf, label);
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ zvrf = zebra_vrf_lookup_by_name(vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP, SAFI_UNICAST, no, prefix,
+ mask_str, NULL, gate_str, ifname, flag,
+ tag_str, distance_str, label);
+}
+
+DEFPY(ip_route_vrf,
+ ip_route_vrf_cmd,
+ "[no] ip route\
+ <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
+ <A.B.C.D$gate|INTERFACE$ifname> \
+ [{ \
+ tag (1-4294967295) \
+ |(1-255)$distance \
+ |label WORD \
+ |nexthop-vrf NAME \
+ }]",
+ NO_STR IP_STR
+ "Establish static routes\n"
+ "IP destination prefix (e.g. 10.0.0.0/8)\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"
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
+{
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+ struct zebra_vrf *zvrf = vrf->info;
+ struct zebra_vrf *nh_zvrf;
+
+ const char *flag = NULL;
+ if (ifname && !strncasecmp(ifname, "Null0", 5)) {
+ flag = "Null0";
+ ifname = NULL;
+ }
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP, SAFI_UNICAST, no, prefix,
+ mask_str, NULL, gate_str, ifname, flag,
+ tag_str, distance_str, label);
}
/* New RIB. Detailed information for IPv4 route. */
@@ -539,7 +728,7 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
if (nexthop->ifindex)
vty_out(vty, ", via %s",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
@@ -549,12 +738,12 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
if (nexthop->ifindex)
vty_out(vty, ", via %s",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_IFINDEX:
vty_out(vty, " directly connected, %s",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_BLACKHOLE:
vty_out(vty, " unreachable");
@@ -576,6 +765,14 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
default:
break;
}
+
+ if (re->vrf_id != re->nh_vrf_id) {
+ struct vrf *vrf =
+ vrf_lookup_by_id(re->nh_vrf_id);
+
+ vty_out(vty, "(vrf %s)", vrf->name);
+ }
+
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
vty_out(vty, " (duplicate nexthop removed)");
@@ -715,7 +912,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_string_add(
json_nexthop, "interfaceName",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
}
break;
case NEXTHOP_TYPE_IPV6:
@@ -734,7 +931,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_string_add(
json_nexthop, "interfaceName",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
}
break;
@@ -747,7 +944,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
json_object_string_add(
json_nexthop, "interfaceName",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_BLACKHOLE:
json_object_boolean_true_add(json_nexthop,
@@ -774,6 +971,14 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
break;
}
+ if (re->nh_vrf_id != re->vrf_id) {
+ struct vrf *vrf =
+ vrf_lookup_by_id(re->nh_vrf_id);
+
+ json_object_string_add(json_nexthop,
+ "vrf",
+ vrf->name);
+ }
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
json_object_boolean_true_add(json_nexthop,
"duplicate");
@@ -881,7 +1086,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (nexthop->ifindex)
vty_out(vty, ", %s",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
@@ -891,12 +1096,13 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
if (nexthop->ifindex)
vty_out(vty, ", %s",
ifindex2ifname(nexthop->ifindex,
- re->vrf_id));
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_IFINDEX:
vty_out(vty, " is directly connected, %s",
- ifindex2ifname(nexthop->ifindex, re->vrf_id));
+ ifindex2ifname(nexthop->ifindex,
+ re->nh_vrf_id));
break;
case NEXTHOP_TYPE_BLACKHOLE:
vty_out(vty, " unreachable");
@@ -917,6 +1123,14 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
default:
break;
}
+
+ if (re->nh_vrf_id != re->vrf_id) {
+ struct vrf *vrf =
+ vrf_lookup_by_id(re->nh_vrf_id);
+
+ vty_out(vty, "(vrf %s)", vrf->name);
+ }
+
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
vty_out(vty, " inactive");
@@ -1603,97 +1817,98 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
}
/* Write static route configuration. */
-static int static_config(struct vty *vty, afi_t afi, safi_t safi,
- const char *cmd)
+int static_config(struct vty *vty, struct zebra_vrf *zvrf,
+ afi_t afi, safi_t safi, const char *cmd)
{
+ char spacing[100];
struct route_node *rn;
struct static_route *si;
struct route_table *stable;
- struct vrf *vrf;
- struct zebra_vrf *zvrf;
char buf[SRCDEST2STR_BUFFER];
int write = 0;
- RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- if (!(zvrf = vrf->info))
- continue;
- if ((stable = zvrf->stable[afi][safi]) == NULL)
- continue;
+ if ((stable = zvrf->stable[afi][safi]) == NULL)
+ return write;
- for (rn = route_top(stable); rn; rn = srcdest_route_next(rn))
- for (si = rn->info; si; si = si->next) {
- vty_out(vty, "%s %s", cmd,
- srcdest_rnode2str(rn, buf, sizeof buf));
+ sprintf(spacing, "%s%s",
+ (zvrf->vrf->vrf_id == VRF_DEFAULT) ? "" : " ",
+ cmd);
- switch (si->type) {
- case STATIC_IPV4_GATEWAY:
- vty_out(vty, " %s",
- inet_ntoa(si->addr.ipv4));
- break;
- case STATIC_IPV6_GATEWAY:
- vty_out(vty, " %s",
- inet_ntop(AF_INET6,
- &si->addr.ipv6, buf,
- sizeof buf));
- break;
- case STATIC_IFNAME:
- vty_out(vty, " %s", si->ifname);
- break;
- case STATIC_BLACKHOLE:
- switch (si->bh_type) {
- case STATIC_BLACKHOLE_DROP:
- vty_out(vty, " blackhole");
- break;
- case STATIC_BLACKHOLE_NULL:
- vty_out(vty, " Null0");
- break;
- case STATIC_BLACKHOLE_REJECT:
- vty_out(vty, " reject");
- break;
- }
+ for (rn = route_top(stable); rn; rn = srcdest_route_next(rn))
+ for (si = rn->info; si; si = si->next) {
+ vty_out(vty, "%s %s", spacing,
+ srcdest_rnode2str(rn, buf, sizeof buf));
+
+ switch (si->type) {
+ case STATIC_IPV4_GATEWAY:
+ vty_out(vty, " %s",
+ inet_ntoa(si->addr.ipv4));
+ break;
+ case STATIC_IPV6_GATEWAY:
+ vty_out(vty, " %s",
+ inet_ntop(AF_INET6,
+ &si->addr.ipv6, buf,
+ sizeof buf));
+ break;
+ case STATIC_IFNAME:
+ vty_out(vty, " %s", si->ifname);
+ break;
+ case STATIC_BLACKHOLE:
+ switch (si->bh_type) {
+ case STATIC_BLACKHOLE_DROP:
+ vty_out(vty, " blackhole");
break;
- case STATIC_IPV4_GATEWAY_IFNAME:
- vty_out(vty, " %s %s",
- inet_ntop(AF_INET,
- &si->addr.ipv4, buf,
- sizeof buf),
- si->ifname);
+ case STATIC_BLACKHOLE_NULL:
+ vty_out(vty, " Null0");
break;
- case STATIC_IPV6_GATEWAY_IFNAME:
- vty_out(vty, " %s %s",
- inet_ntop(AF_INET6,
- &si->addr.ipv6, buf,
- sizeof buf),
- si->ifname);
+ case STATIC_BLACKHOLE_REJECT:
+ vty_out(vty, " reject");
break;
}
+ break;
+ case STATIC_IPV4_GATEWAY_IFNAME:
+ vty_out(vty, " %s %s",
+ inet_ntop(AF_INET,
+ &si->addr.ipv4, buf,
+ sizeof buf),
+ si->ifname);
+ break;
+ case STATIC_IPV6_GATEWAY_IFNAME:
+ vty_out(vty, " %s %s",
+ inet_ntop(AF_INET6,
+ &si->addr.ipv6, buf,
+ sizeof buf),
+ si->ifname);
+ break;
+ }
- if (si->tag)
- vty_out(vty, " tag %" ROUTE_TAG_PRI,
- si->tag);
+ if (si->tag)
+ vty_out(vty, " tag %" ROUTE_TAG_PRI,
+ si->tag);
- if (si->distance
- != ZEBRA_STATIC_DISTANCE_DEFAULT)
- vty_out(vty, " %d", si->distance);
+ if (si->distance
+ != ZEBRA_STATIC_DISTANCE_DEFAULT)
+ vty_out(vty, " %d", si->distance);
- if (si->vrf_id != VRF_DEFAULT)
- vty_out(vty, " vrf %s",
- zvrf_name(zvrf));
+ if (si->nh_vrf_id != si->vrf_id) {
+ struct vrf *vrf;
- /* Label information */
- if (si->snh_label.num_labels)
- vty_out(vty, " label %s",
- mpls_label2str(
- si->snh_label
- .num_labels,
- si->snh_label.label,
- buf, sizeof buf, 0));
+ vrf = vrf_lookup_by_id(si->nh_vrf_id);
+ vty_out(vty, " nexthop-vrf %s",
+ (vrf) ? vrf->name : "Unknown");
+ }
- vty_out(vty, "\n");
+ /* Label information */
+ if (si->snh_label.num_labels)
+ vty_out(vty, " label %s",
+ mpls_label2str(si->snh_label.num_labels,
+ si->snh_label.label,
+ buf, sizeof buf, 0));
- write = 1;
- }
- }
+ vty_out(vty, "\n");
+
+ write = 1;
+ }
return write;
}
@@ -1727,6 +1942,38 @@ DEFPY(ipv6_route_blackhole,
tag_str, distance_str, vrf, label);
}
+DEFPY(ipv6_route_blackhole_vrf,
+ ipv6_route_blackhole_vrf_cmd,
+ "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
+ <Null0|reject|blackhole>$flag \
+ [{ \
+ tag (1-4294967295) \
+ |(1-255)$distance \
+ |label WORD \
+ }]",
+ NO_STR
+ IPV6_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 source-dest route\n"
+ "IPv6 source prefix\n"
+ "Null interface\n"
+ "Emit an ICMP unreachable when matched\n"
+ "Silently discard pkts when matched\n"
+ "Set tag for this route\n"
+ "Tag value\n"
+ "Distance value for this prefix\n"
+ MPLS_LABEL_HELPSTR)
+{
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+ struct zebra_vrf *zvrf = vrf->info;
+
+ return zebra_static_route_leak(vty, zvrf, zvrf,
+ AFI_IP6, SAFI_UNICAST, no, prefix_str,
+ NULL, from_str, NULL, NULL, flag,
+ tag_str, distance_str, label);
+}
+
DEFPY(ipv6_route_address_interface,
ipv6_route_address_interface_cmd,
"[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
@@ -1737,6 +1984,7 @@ DEFPY(ipv6_route_address_interface,
|(1-255)$distance \
|vrf NAME \
|label WORD \
+ |nexthop-vrf NAME \
}]",
NO_STR
IPV6_STR
@@ -1750,11 +1998,72 @@ DEFPY(ipv6_route_address_interface,
"Tag value\n"
"Distance value for this prefix\n"
VRF_CMD_HELP_STR
- MPLS_LABEL_HELPSTR)
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
{
- return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
- NULL, from_str, gate_str, ifname, NULL,
- tag_str, distance_str, vrf, label);
+ struct zebra_vrf *zvrf;
+ struct zebra_vrf *nh_zvrf;
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ zvrf = zebra_vrf_lookup_by_name(vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP6, SAFI_UNICAST, no, prefix_str,
+ NULL, from_str, gate_str, ifname, NULL,
+ tag_str, distance_str, label);
+}
+
+DEFPY(ipv6_route_address_interface_vrf,
+ ipv6_route_address_interface_vrf_cmd,
+ "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
+ X:X::X:X$gate \
+ INTERFACE$ifname \
+ [{ \
+ tag (1-4294967295) \
+ |(1-255)$distance \
+ |label WORD \
+ |nexthop-vrf NAME \
+ }]",
+ NO_STR
+ IPV6_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 source-dest route\n"
+ "IPv6 source prefix\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Set tag for this route\n"
+ "Tag value\n"
+ "Distance value for this prefix\n"
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
+{
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+ struct zebra_vrf *zvrf = vrf->info;
+ struct zebra_vrf *nh_zvrf;
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP6, SAFI_UNICAST, no, prefix_str,
+ NULL, from_str, gate_str, ifname, NULL,
+ tag_str, distance_str, label);
}
DEFPY(ipv6_route,
@@ -1766,6 +2075,7 @@ DEFPY(ipv6_route,
|(1-255)$distance \
|vrf NAME \
|label WORD \
+ |nexthop-vrf NAME \
}]",
NO_STR
IPV6_STR
@@ -1779,11 +2089,71 @@ DEFPY(ipv6_route,
"Tag value\n"
"Distance value for this prefix\n"
VRF_CMD_HELP_STR
- MPLS_LABEL_HELPSTR)
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
{
- return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
- NULL, from_str, gate_str, ifname, NULL,
- tag_str, distance_str, vrf, label);
+ struct zebra_vrf *zvrf;
+ struct zebra_vrf *nh_zvrf;
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ zvrf = zebra_vrf_lookup_by_name(vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP6, SAFI_UNICAST, no, prefix_str,
+ NULL, from_str, gate_str, ifname, NULL,
+ tag_str, distance_str, label);
+}
+
+DEFPY(ipv6_route_vrf,
+ ipv6_route_vrf_cmd,
+ "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
+ <X:X::X:X$gate|INTERFACE$ifname> \
+ [{ \
+ tag (1-4294967295) \
+ |(1-255)$distance \
+ |label WORD \
+ |nexthop-vrf NAME \
+ }]",
+ NO_STR
+ IPV6_STR
+ "Establish static routes\n"
+ "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
+ "IPv6 source-dest route\n"
+ "IPv6 source prefix\n"
+ "IPv6 gateway address\n"
+ "IPv6 gateway interface name\n"
+ "Set tag for this route\n"
+ "Tag value\n"
+ "Distance value for this prefix\n"
+ MPLS_LABEL_HELPSTR
+ VRF_CMD_HELP_STR)
+{
+ VTY_DECLVAR_CONTEXT(vrf, vrf);
+ struct zebra_vrf *zvrf = vrf->info;
+ struct zebra_vrf *nh_zvrf;
+
+ nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
+ if (!nh_zvrf) {
+ vty_out(vty, "%% nexthop vrf %s is not defined\n",
+ nexthop_vrf);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ return zebra_static_route_leak(vty, zvrf, nh_zvrf,
+ AFI_IP6, SAFI_UNICAST, no, prefix_str,
+ NULL, from_str, gate_str, ifname, NULL,
+ tag_str, distance_str, label);
}
/*
@@ -2419,11 +2789,8 @@ static int zebra_ip_config(struct vty *vty)
{
int write = 0;
- write += static_config(vty, AFI_IP, SAFI_UNICAST, "ip route");
- write += static_config(vty, AFI_IP, SAFI_MULTICAST, "ip mroute");
- write += static_config(vty, AFI_IP6, SAFI_UNICAST, "ipv6 route");
-
write += zebra_import_table_config(vty);
+
return write;
}
@@ -2859,8 +3226,11 @@ 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_blackhole_cmd);
+ install_element(VRF_NODE, &ip_route_blackhole_vrf_cmd);
install_element(CONFIG_NODE, &ip_route_address_interface_cmd);
+ install_element(VRF_NODE, &ip_route_address_interface_vrf_cmd);
install_element(CONFIG_NODE, &ip_route_cmd);
+ install_element(VRF_NODE, &ip_route_vrf_cmd);
install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);
@@ -2882,8 +3252,11 @@ void zebra_vty_init(void)
install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
install_element(CONFIG_NODE, &ipv6_route_blackhole_cmd);
+ install_element(VRF_NODE, &ipv6_route_blackhole_vrf_cmd);
install_element(CONFIG_NODE, &ipv6_route_address_interface_cmd);
+ install_element(VRF_NODE, &ipv6_route_address_interface_vrf_cmd);
install_element(CONFIG_NODE, &ipv6_route_cmd);
+ install_element(VRF_NODE, &ipv6_route_vrf_cmd);
install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);