]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vty.c
zebra: Enable JSON for EVPN show cmds
[mirror_frr.git] / zebra / zebra_vty.c
1 /* Zebra VTY functions
2 * Copyright (C) 2002 Kunihiro Ishiguro
3 *
4 * This file is part of GNU Zebra.
5 *
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <zebra.h>
22
23 #include "memory.h"
24 #include "zebra_memory.h"
25 #include "if.h"
26 #include "prefix.h"
27 #include "command.h"
28 #include "table.h"
29 #include "rib.h"
30 #include "nexthop.h"
31 #include "vrf.h"
32 #include "mpls.h"
33 #include "routemap.h"
34 #include "srcdest_table.h"
35 #include "vxlan.h"
36
37 #include "zebra/zserv.h"
38 #include "zebra/zebra_vrf.h"
39 #include "zebra/zebra_mpls.h"
40 #include "zebra/zebra_rnh.h"
41 #include "zebra/redistribute.h"
42 #include "zebra/zebra_routemap.h"
43 #include "zebra/zebra_static.h"
44 #include "lib/json.h"
45 #include "zebra/zebra_vxlan.h"
46 #include "zebra/zebra_vty_clippy.c"
47
48 extern int allow_delete;
49
50 static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
51 safi_t safi, bool use_fib, u_char use_json,
52 route_tag_t tag, struct prefix *longer_prefix_p,
53 bool supernets_only, int type,
54 u_short ospf_instance_id);
55 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
56 int mcast);
57
58 #define ONE_DAY_SECOND 60*60*24
59 #define ONE_WEEK_SECOND 60*60*24*7
60
61 /* VNI range as per RFC 7432 */
62 #define CMD_VNI_RANGE "(1-16777215)"
63
64 /* General function for static route. */
65 static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
66 const char *negate, const char *dest_str,
67 const char *mask_str, const char *src_str,
68 const char *gate_str, const char *ifname,
69 const char *flag_str, const char *tag_str,
70 const char *distance_str, const char *vrf_id_str,
71 const char *label_str)
72 {
73 int ret;
74 u_char distance;
75 struct prefix p, src;
76 struct prefix_ipv6 *src_p = NULL;
77 union g_addr gate;
78 union g_addr *gatep = NULL;
79 struct in_addr mask;
80 u_char flag = 0;
81 route_tag_t tag = 0;
82 struct zebra_vrf *zvrf;
83 unsigned int ifindex = 0;
84 u_char type;
85 struct static_nh_label snh_label;
86
87 ret = str2prefix(dest_str, &p);
88 if (ret <= 0) {
89 vty_out(vty, "%% Malformed address\n");
90 return CMD_WARNING_CONFIG_FAILED;
91 }
92
93 switch (afi) {
94 case AFI_IP:
95 /* Cisco like mask notation. */
96 if (mask_str) {
97 ret = inet_aton(mask_str, &mask);
98 if (ret == 0) {
99 vty_out(vty, "%% Malformed address\n");
100 return CMD_WARNING_CONFIG_FAILED;
101 }
102 p.prefixlen = ip_masklen(mask);
103 }
104 break;
105 case AFI_IP6:
106 /* srcdest routing */
107 if (src_str) {
108 ret = str2prefix(src_str, &src);
109 if (ret <= 0 || src.family != AF_INET6) {
110 vty_out(vty, "%% Malformed source address\n");
111 return CMD_WARNING_CONFIG_FAILED;
112 }
113 src_p = (struct prefix_ipv6 *)&src;
114 }
115 break;
116 default:
117 break;
118 }
119
120 /* Apply mask for given prefix. */
121 apply_mask(&p);
122
123 /* Administrative distance. */
124 if (distance_str)
125 distance = atoi(distance_str);
126 else
127 distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
128
129 /* tag */
130 if (tag_str)
131 tag = strtoul(tag_str, NULL, 10);
132
133 /* VRF id */
134 zvrf = zebra_vrf_lookup_by_name(vrf_id_str);
135
136 if (!zvrf) {
137 vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str);
138 return CMD_WARNING_CONFIG_FAILED;
139 }
140
141 /* Labels */
142 memset(&snh_label, 0, sizeof(struct static_nh_label));
143 if (label_str) {
144 if (!mpls_enabled) {
145 vty_out(vty,
146 "%% MPLS not turned on in kernel, ignoring command\n");
147 return CMD_WARNING_CONFIG_FAILED;
148 }
149 int rc = mpls_str2label(label_str, &snh_label.num_labels,
150 snh_label.label);
151 if (rc < 0) {
152 switch (rc) {
153 case -1:
154 vty_out(vty, "%% Malformed label(s)\n");
155 break;
156 case -2:
157 vty_out(vty,
158 "%% Cannot use reserved label(s) (%d-%d)\n",
159 MPLS_MIN_RESERVED_LABEL,
160 MPLS_MAX_RESERVED_LABEL);
161 break;
162 case -3:
163 vty_out(vty,
164 "%% Too many labels. Enter %d or fewer\n",
165 MPLS_MAX_LABELS);
166 break;
167 }
168 return CMD_WARNING_CONFIG_FAILED;
169 }
170 }
171
172 /* Null0 static route. */
173 if ((ifname != NULL)
174 && (strncasecmp(ifname, "Null0", strlen(ifname)) == 0)) {
175 if (flag_str) {
176 vty_out(vty, "%% can not have flag %s with Null0\n",
177 flag_str);
178 return CMD_WARNING_CONFIG_FAILED;
179 }
180 SET_FLAG(flag, ZEBRA_FLAG_BLACKHOLE);
181 ifname = NULL;
182 }
183
184 /* Route flags */
185 if (flag_str) {
186 switch (flag_str[0]) {
187 case 'r':
188 case 'R': /* XXX */
189 SET_FLAG(flag, ZEBRA_FLAG_REJECT);
190 break;
191 case 'b':
192 case 'B': /* XXX */
193 SET_FLAG(flag, ZEBRA_FLAG_BLACKHOLE);
194 break;
195 default:
196 vty_out(vty, "%% Malformed flag %s \n", flag_str);
197 return CMD_WARNING_CONFIG_FAILED;
198 }
199 }
200
201 if (gate_str) {
202 if (inet_pton(afi2family(afi), gate_str, &gate) != 1) {
203 vty_out(vty, "%% Malformed nexthop address %s\n",
204 gate_str);
205 return CMD_WARNING_CONFIG_FAILED;
206 }
207 gatep = &gate;
208 }
209
210 if (ifname) {
211 struct interface *ifp;
212 ifp = if_lookup_by_name(ifname, zvrf_id(zvrf));
213 if (!ifp) {
214 vty_out(vty, "%% Malformed Interface name %s\n",
215 ifname);
216 ifindex = IFINDEX_DELETED;
217 } else
218 ifindex = ifp->ifindex;
219 }
220
221 if (gate_str == NULL && ifname == NULL)
222 type = STATIC_BLACKHOLE;
223 else if (gate_str && ifname) {
224 if (afi == AFI_IP)
225 type = STATIC_IPV4_GATEWAY_IFINDEX;
226 else
227 type = STATIC_IPV6_GATEWAY_IFINDEX;
228 } else if (ifname)
229 type = STATIC_IFINDEX;
230 else {
231 if (afi == AFI_IP)
232 type = STATIC_IPV4_GATEWAY;
233 else
234 type = STATIC_IPV6_GATEWAY;
235 }
236
237 if (!negate)
238 static_add_route(afi, safi, type, &p, src_p, gatep, ifindex,
239 ifname, flag, tag, distance, zvrf, &snh_label);
240 else
241 static_delete_route(afi, safi, type, &p, src_p, gatep, ifindex,
242 tag, distance, zvrf, &snh_label);
243
244 return CMD_SUCCESS;
245 }
246
247 /* Static unicast routes for multicast RPF lookup. */
248 DEFPY (ip_mroute_dist,
249 ip_mroute_dist_cmd,
250 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
251 NO_STR
252 IP_STR
253 "Configure static unicast route into MRIB for multicast RPF lookup\n"
254 "IP destination prefix (e.g. 10.0.0.0/8)\n"
255 "Nexthop address\n"
256 "Nexthop interface name\n"
257 "Distance\n")
258 {
259 return zebra_static_route(vty, AFI_IP, SAFI_MULTICAST, no, prefix_str,
260 NULL, NULL, gate_str, ifname, NULL, NULL,
261 distance_str, NULL, NULL);
262 }
263
264 DEFUN (ip_multicast_mode,
265 ip_multicast_mode_cmd,
266 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
267 IP_STR
268 "Multicast options\n"
269 "RPF lookup behavior\n"
270 "Lookup in unicast RIB only\n"
271 "Lookup in multicast RIB only\n"
272 "Try multicast RIB first, fall back to unicast RIB\n"
273 "Lookup both, use entry with lower distance\n"
274 "Lookup both, use entry with longer prefix\n")
275 {
276 char *mode = argv[3]->text;
277
278 if (strmatch(mode, "urib-only"))
279 multicast_mode_ipv4_set(MCAST_URIB_ONLY);
280 else if (strmatch(mode, "mrib-only"))
281 multicast_mode_ipv4_set(MCAST_MRIB_ONLY);
282 else if (strmatch(mode, "mrib-then-urib"))
283 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST);
284 else if (strmatch(mode, "lower-distance"))
285 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE);
286 else if (strmatch(mode, "longer-prefix"))
287 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN);
288 else {
289 vty_out(vty, "Invalid mode specified\n");
290 return CMD_WARNING_CONFIG_FAILED;
291 }
292
293 return CMD_SUCCESS;
294 }
295
296 DEFUN (no_ip_multicast_mode,
297 no_ip_multicast_mode_cmd,
298 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
299 NO_STR
300 IP_STR
301 "Multicast options\n"
302 "RPF lookup behavior\n"
303 "Lookup in unicast RIB only\n"
304 "Lookup in multicast RIB only\n"
305 "Try multicast RIB first, fall back to unicast RIB\n"
306 "Lookup both, use entry with lower distance\n"
307 "Lookup both, use entry with longer prefix\n")
308 {
309 multicast_mode_ipv4_set(MCAST_NO_CONFIG);
310 return CMD_SUCCESS;
311 }
312
313
314 DEFUN (show_ip_rpf,
315 show_ip_rpf_cmd,
316 "show ip rpf [json]",
317 SHOW_STR
318 IP_STR
319 "Display RPF information for multicast source\n"
320 JSON_STR)
321 {
322 int uj = use_json(argc, argv);
323 return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST,
324 false, uj, 0, NULL, false, -1, 0);
325 }
326
327 DEFUN (show_ip_rpf_addr,
328 show_ip_rpf_addr_cmd,
329 "show ip rpf A.B.C.D",
330 SHOW_STR
331 IP_STR
332 "Display RPF information for multicast source\n"
333 "IP multicast source address (e.g. 10.0.0.0)\n")
334 {
335 int idx_ipv4 = 3;
336 struct in_addr addr;
337 struct route_node *rn;
338 struct route_entry *re;
339 int ret;
340
341 ret = inet_aton(argv[idx_ipv4]->arg, &addr);
342 if (ret == 0) {
343 vty_out(vty, "%% Malformed address\n");
344 return CMD_WARNING;
345 }
346
347 re = rib_match_ipv4_multicast(VRF_DEFAULT, addr, &rn);
348
349 if (re)
350 vty_show_ip_route_detail(vty, rn, 1);
351 else
352 vty_out(vty, "%% No match for RPF lookup\n");
353
354 return CMD_SUCCESS;
355 }
356
357 /* Static route configuration. */
358 DEFPY (ip_route,
359 ip_route_cmd,
360 "[no] ip route\
361 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask>\
362 <\
363 {A.B.C.D$gate|INTERFACE$ifname}\
364 |null0$ifname\
365 |<reject|blackhole>$flag\
366 >\
367 [{\
368 tag (1-4294967295)\
369 |(1-255)$distance\
370 |vrf NAME\
371 |label WORD\
372 }]",
373 NO_STR
374 IP_STR
375 "Establish static routes\n"
376 "IP destination prefix (e.g. 10.0.0.0/8)\n"
377 "IP destination prefix\n"
378 "IP destination prefix mask\n"
379 "IP gateway address\n"
380 "IP gateway interface name\n"
381 "Null interface\n"
382 "Emit an ICMP unreachable when matched\n"
383 "Silently discard pkts when matched\n"
384 "Set tag for this route\n"
385 "Tag value\n"
386 "Distance value for this route\n"
387 VRF_CMD_HELP_STR
388 MPLS_LABEL_HELPSTR)
389 {
390 return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
391 mask_str, NULL, gate_str, ifname, flag,
392 tag_str, distance_str, vrf, label);
393 return 0;
394 }
395
396 /* New RIB. Detailed information for IPv4 route. */
397 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
398 int mcast)
399 {
400 struct route_entry *re;
401 struct nexthop *nexthop;
402 char buf[SRCDEST2STR_BUFFER];
403 struct zebra_vrf *zvrf;
404
405 RNODE_FOREACH_RE(rn, re)
406 {
407 const char *mcast_info = "";
408 if (mcast) {
409 rib_table_info_t *info = srcdest_rnode_table_info(rn);
410 mcast_info = (info->safi == SAFI_MULTICAST)
411 ? " using Multicast RIB"
412 : " using Unicast RIB";
413 }
414
415 vty_out(vty, "Routing entry for %s%s\n",
416 srcdest_rnode2str(rn, buf, sizeof(buf)), mcast_info);
417 vty_out(vty, " Known via \"%s", zebra_route_string(re->type));
418 if (re->instance)
419 vty_out(vty, "[%d]", re->instance);
420 vty_out(vty, "\"");
421 vty_out(vty, ", distance %u, metric %u", re->distance,
422 re->metric);
423 if (re->tag)
424 vty_out(vty, ", tag %d", re->tag);
425 if (re->mtu)
426 vty_out(vty, ", mtu %u", re->mtu);
427 if (re->vrf_id != VRF_DEFAULT) {
428 zvrf = vrf_info_lookup(re->vrf_id);
429 vty_out(vty, ", vrf %s", zvrf_name(zvrf));
430 }
431 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
432 vty_out(vty, ", best");
433 if (re->refcnt)
434 vty_out(vty, ", refcnt %ld", re->refcnt);
435 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE))
436 vty_out(vty, ", blackhole");
437 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT))
438 vty_out(vty, ", reject");
439 vty_out(vty, "\n");
440
441 if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
442 || re->type == ZEBRA_ROUTE_ISIS
443 || re->type == ZEBRA_ROUTE_NHRP
444 || re->type == ZEBRA_ROUTE_TABLE
445 || re->type == ZEBRA_ROUTE_BGP) {
446 time_t uptime;
447 struct tm *tm;
448
449 uptime = time(NULL);
450 uptime -= re->uptime;
451 tm = gmtime(&uptime);
452
453 vty_out(vty, " Last update ");
454
455 if (uptime < ONE_DAY_SECOND)
456 vty_out(vty, "%02d:%02d:%02d", tm->tm_hour,
457 tm->tm_min, tm->tm_sec);
458 else if (uptime < ONE_WEEK_SECOND)
459 vty_out(vty, "%dd%02dh%02dm", tm->tm_yday,
460 tm->tm_hour, tm->tm_min);
461 else
462 vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7,
463 tm->tm_yday - ((tm->tm_yday / 7) * 7),
464 tm->tm_hour);
465 vty_out(vty, " ago\n");
466 }
467
468 for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
469 char addrstr[32];
470
471 vty_out(vty, " %c%s",
472 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
473 ? '*'
474 : ' ',
475 nexthop->rparent ? " " : "");
476
477 switch (nexthop->type) {
478 case NEXTHOP_TYPE_IPV4:
479 case NEXTHOP_TYPE_IPV4_IFINDEX:
480 vty_out(vty, " %s",
481 inet_ntoa(nexthop->gate.ipv4));
482 if (nexthop->ifindex)
483 vty_out(vty, ", via %s",
484 ifindex2ifname(nexthop->ifindex,
485 re->vrf_id));
486 break;
487 case NEXTHOP_TYPE_IPV6:
488 case NEXTHOP_TYPE_IPV6_IFINDEX:
489 vty_out(vty, " %s",
490 inet_ntop(AF_INET6, &nexthop->gate.ipv6,
491 buf, sizeof buf));
492 if (nexthop->ifindex)
493 vty_out(vty, ", via %s",
494 ifindex2ifname(nexthop->ifindex,
495 re->vrf_id));
496 break;
497 case NEXTHOP_TYPE_IFINDEX:
498 vty_out(vty, " directly connected, %s",
499 ifindex2ifname(nexthop->ifindex,
500 re->vrf_id));
501 break;
502 case NEXTHOP_TYPE_BLACKHOLE:
503 vty_out(vty, " directly connected, Null0");
504 break;
505 default:
506 break;
507 }
508 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
509 vty_out(vty, " inactive");
510
511 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
512 vty_out(vty, " onlink");
513
514 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
515 vty_out(vty, " (recursive)");
516
517 switch (nexthop->type) {
518 case NEXTHOP_TYPE_IPV4:
519 case NEXTHOP_TYPE_IPV4_IFINDEX:
520 if (nexthop->src.ipv4.s_addr) {
521 if (inet_ntop(AF_INET,
522 &nexthop->src.ipv4,
523 addrstr, sizeof addrstr))
524 vty_out(vty, ", src %s",
525 addrstr);
526 }
527 break;
528 case NEXTHOP_TYPE_IPV6:
529 case NEXTHOP_TYPE_IPV6_IFINDEX:
530 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
531 &in6addr_any)) {
532 if (inet_ntop(AF_INET6,
533 &nexthop->src.ipv6,
534 addrstr, sizeof addrstr))
535 vty_out(vty, ", src %s",
536 addrstr);
537 }
538 break;
539 default:
540 break;
541 }
542
543 if (re->nexthop_mtu)
544 vty_out(vty, ", mtu %u", re->nexthop_mtu);
545
546 /* Label information */
547 if (nexthop->nh_label
548 && nexthop->nh_label->num_labels) {
549 vty_out(vty, ", label %s",
550 mpls_label2str(
551 nexthop->nh_label->num_labels,
552 nexthop->nh_label->label, buf,
553 sizeof buf, 1));
554 }
555
556 vty_out(vty, "\n");
557 }
558 vty_out(vty, "\n");
559 }
560 }
561
562 static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
563 struct route_entry *re, json_object *json)
564 {
565 struct nexthop *nexthop;
566 int len = 0;
567 char buf[SRCDEST2STR_BUFFER];
568 json_object *json_nexthops = NULL;
569 json_object *json_nexthop = NULL;
570 json_object *json_route = NULL;
571 json_object *json_labels = NULL;
572
573 if (json) {
574 json_route = json_object_new_object();
575 json_nexthops = json_object_new_array();
576
577 json_object_string_add(json_route, "prefix",
578 srcdest_rnode2str(rn, buf, sizeof buf));
579 json_object_string_add(json_route, "protocol",
580 zebra_route_string(re->type));
581
582 if (re->instance)
583 json_object_int_add(json_route, "instance",
584 re->instance);
585
586 if (re->vrf_id)
587 json_object_int_add(json_route, "vrfId", re->vrf_id);
588
589 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
590 json_object_boolean_true_add(json_route, "selected");
591
592 if (re->type != ZEBRA_ROUTE_CONNECT) {
593 json_object_int_add(json_route, "distance",
594 re->distance);
595 json_object_int_add(json_route, "metric", re->metric);
596 }
597
598 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE))
599 json_object_boolean_true_add(json_route, "blackhole");
600
601 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT))
602 json_object_boolean_true_add(json_route, "reject");
603
604 if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
605 || re->type == ZEBRA_ROUTE_ISIS
606 || re->type == ZEBRA_ROUTE_NHRP
607 || re->type == ZEBRA_ROUTE_TABLE
608 || re->type == ZEBRA_ROUTE_BGP) {
609 time_t uptime;
610 struct tm *tm;
611
612 uptime = time(NULL);
613 uptime -= re->uptime;
614 tm = gmtime(&uptime);
615
616 if (uptime < ONE_DAY_SECOND)
617 sprintf(buf, "%02d:%02d:%02d", tm->tm_hour,
618 tm->tm_min, tm->tm_sec);
619 else if (uptime < ONE_WEEK_SECOND)
620 sprintf(buf, "%dd%02dh%02dm", tm->tm_yday,
621 tm->tm_hour, tm->tm_min);
622 else
623 sprintf(buf, "%02dw%dd%02dh", tm->tm_yday / 7,
624 tm->tm_yday - ((tm->tm_yday / 7) * 7),
625 tm->tm_hour);
626
627 json_object_string_add(json_route, "uptime", buf);
628 }
629
630 for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
631 json_nexthop = json_object_new_object();
632
633 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
634 json_object_boolean_true_add(json_nexthop,
635 "fib");
636
637 switch (nexthop->type) {
638 case NEXTHOP_TYPE_IPV4:
639 case NEXTHOP_TYPE_IPV4_IFINDEX:
640 json_object_string_add(
641 json_nexthop, "ip",
642 inet_ntoa(nexthop->gate.ipv4));
643 json_object_string_add(json_nexthop, "afi",
644 "ipv4");
645
646 if (nexthop->ifindex) {
647 json_object_int_add(json_nexthop,
648 "interfaceIndex",
649 nexthop->ifindex);
650 json_object_string_add(
651 json_nexthop, "interfaceName",
652 ifindex2ifname(nexthop->ifindex,
653 re->vrf_id));
654 }
655 break;
656 case NEXTHOP_TYPE_IPV6:
657 case NEXTHOP_TYPE_IPV6_IFINDEX:
658 json_object_string_add(
659 json_nexthop, "ip",
660 inet_ntop(AF_INET6, &nexthop->gate.ipv6,
661 buf, sizeof buf));
662 json_object_string_add(json_nexthop, "afi",
663 "ipv6");
664
665 if (nexthop->ifindex) {
666 json_object_int_add(json_nexthop,
667 "interfaceIndex",
668 nexthop->ifindex);
669 json_object_string_add(
670 json_nexthop, "interfaceName",
671 ifindex2ifname(nexthop->ifindex,
672 re->vrf_id));
673 }
674 break;
675
676 case NEXTHOP_TYPE_IFINDEX:
677 json_object_boolean_true_add(
678 json_nexthop, "directlyConnected");
679 json_object_int_add(json_nexthop,
680 "interfaceIndex",
681 nexthop->ifindex);
682 json_object_string_add(
683 json_nexthop, "interfaceName",
684 ifindex2ifname(nexthop->ifindex,
685 re->vrf_id));
686 break;
687 case NEXTHOP_TYPE_BLACKHOLE:
688 json_object_boolean_true_add(json_nexthop,
689 "blackhole");
690 break;
691 default:
692 break;
693 }
694
695 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
696 json_object_boolean_true_add(json_nexthop,
697 "active");
698
699 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
700 json_object_boolean_true_add(json_nexthop,
701 "onLink");
702
703 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
704 json_object_boolean_true_add(json_nexthop,
705 "recursive");
706
707 switch (nexthop->type) {
708 case NEXTHOP_TYPE_IPV4:
709 case NEXTHOP_TYPE_IPV4_IFINDEX:
710 if (nexthop->src.ipv4.s_addr) {
711 if (inet_ntop(AF_INET,
712 &nexthop->src.ipv4, buf,
713 sizeof buf))
714 json_object_string_add(
715 json_nexthop, "source",
716 buf);
717 }
718 break;
719 case NEXTHOP_TYPE_IPV6:
720 case NEXTHOP_TYPE_IPV6_IFINDEX:
721 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
722 &in6addr_any)) {
723 if (inet_ntop(AF_INET6,
724 &nexthop->src.ipv6, buf,
725 sizeof buf))
726 json_object_string_add(
727 json_nexthop, "source",
728 buf);
729 }
730 break;
731 default:
732 break;
733 }
734
735 if (nexthop->nh_label
736 && nexthop->nh_label->num_labels) {
737 json_labels = json_object_new_array();
738
739 for (int label_index = 0;
740 label_index
741 < nexthop->nh_label->num_labels;
742 label_index++)
743 json_object_array_add(
744 json_labels,
745 json_object_new_int(
746 nexthop->nh_label->label
747 [label_index]));
748
749 json_object_object_add(json_nexthop, "labels",
750 json_labels);
751 }
752
753 json_object_array_add(json_nexthops, json_nexthop);
754 }
755
756 json_object_object_add(json_route, "nexthops", json_nexthops);
757 json_object_array_add(json, json_route);
758 return;
759 }
760
761 /* Nexthop information. */
762 for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
763 if (nexthop == re->nexthop) {
764 /* Prefix information. */
765 len = vty_out(vty, "%c", zebra_route_char(re->type));
766 if (re->instance)
767 len += vty_out(vty, "[%d]", re->instance);
768 len += vty_out(
769 vty, "%c%c %s",
770 CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)
771 ? '>'
772 : ' ',
773 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
774 ? '*'
775 : ' ',
776 srcdest_rnode2str(rn, buf, sizeof buf));
777
778 /* Distance and metric display. */
779 if (re->type != ZEBRA_ROUTE_CONNECT)
780 len += vty_out(vty, " [%d/%d]", re->distance,
781 re->metric);
782 } else
783 vty_out(vty, " %c%*c",
784 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
785 ? '*'
786 : ' ',
787 len - 3 + (2 * nexthop_level(nexthop)), ' ');
788
789 switch (nexthop->type) {
790 case NEXTHOP_TYPE_IPV4:
791 case NEXTHOP_TYPE_IPV4_IFINDEX:
792 vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4));
793 if (nexthop->ifindex)
794 vty_out(vty, ", %s",
795 ifindex2ifname(nexthop->ifindex,
796 re->vrf_id));
797 break;
798 case NEXTHOP_TYPE_IPV6:
799 case NEXTHOP_TYPE_IPV6_IFINDEX:
800 vty_out(vty, " via %s",
801 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
802 sizeof buf));
803 if (nexthop->ifindex)
804 vty_out(vty, ", %s",
805 ifindex2ifname(nexthop->ifindex,
806 re->vrf_id));
807 break;
808
809 case NEXTHOP_TYPE_IFINDEX:
810 vty_out(vty, " is directly connected, %s",
811 ifindex2ifname(nexthop->ifindex, re->vrf_id));
812 break;
813 case NEXTHOP_TYPE_BLACKHOLE:
814 vty_out(vty, " is directly connected, Null0");
815 break;
816 default:
817 break;
818 }
819 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
820 vty_out(vty, " inactive");
821
822 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
823 vty_out(vty, " onlink");
824
825 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
826 vty_out(vty, " (recursive)");
827
828 switch (nexthop->type) {
829 case NEXTHOP_TYPE_IPV4:
830 case NEXTHOP_TYPE_IPV4_IFINDEX:
831 if (nexthop->src.ipv4.s_addr) {
832 if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
833 sizeof buf))
834 vty_out(vty, ", src %s", buf);
835 }
836 break;
837 case NEXTHOP_TYPE_IPV6:
838 case NEXTHOP_TYPE_IPV6_IFINDEX:
839 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
840 if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
841 sizeof buf))
842 vty_out(vty, ", src %s", buf);
843 }
844 break;
845 default:
846 break;
847 }
848
849 /* Label information */
850 if (nexthop->nh_label && nexthop->nh_label->num_labels) {
851 vty_out(vty, ", label %s",
852 mpls_label2str(nexthop->nh_label->num_labels,
853 nexthop->nh_label->label, buf,
854 sizeof buf, 1));
855 }
856
857 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE))
858 vty_out(vty, ", bh");
859 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT))
860 vty_out(vty, ", rej");
861
862 if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
863 || re->type == ZEBRA_ROUTE_ISIS
864 || re->type == ZEBRA_ROUTE_NHRP
865 || re->type == ZEBRA_ROUTE_TABLE
866 || re->type == ZEBRA_ROUTE_BGP) {
867 time_t uptime;
868 struct tm *tm;
869
870 uptime = time(NULL);
871 uptime -= re->uptime;
872 tm = gmtime(&uptime);
873
874 if (uptime < ONE_DAY_SECOND)
875 vty_out(vty, ", %02d:%02d:%02d", tm->tm_hour,
876 tm->tm_min, tm->tm_sec);
877 else if (uptime < ONE_WEEK_SECOND)
878 vty_out(vty, ", %dd%02dh%02dm", tm->tm_yday,
879 tm->tm_hour, tm->tm_min);
880 else
881 vty_out(vty, ", %02dw%dd%02dh", tm->tm_yday / 7,
882 tm->tm_yday - ((tm->tm_yday / 7) * 7),
883 tm->tm_hour);
884 }
885 vty_out(vty, "\n");
886 }
887 }
888
889 static bool use_fib(struct cmd_token *token)
890 {
891 return strncmp(token->arg, "route", strlen(token->arg));
892 }
893
894 static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
895 safi_t safi, bool use_fib, u_char use_json,
896 route_tag_t tag, struct prefix *longer_prefix_p,
897 bool supernets_only, int type,
898 u_short ospf_instance_id)
899 {
900 struct route_table *table;
901 struct route_node *rn;
902 struct route_entry *re;
903 int first = 1;
904 struct zebra_vrf *zvrf = NULL;
905 char buf[BUFSIZ];
906 json_object *json = NULL;
907 json_object *json_prefix = NULL;
908 u_int32_t addr;
909
910 if (!(zvrf = zebra_vrf_lookup_by_name(vrf_name))) {
911 if (use_json)
912 vty_out(vty, "{}\n");
913 else
914 vty_out(vty, "vrf %s not defined\n", vrf_name);
915 return CMD_SUCCESS;
916 }
917
918 if (zvrf_id(zvrf) == VRF_UNKNOWN) {
919 if (use_json)
920 vty_out(vty, "{}\n");
921 else
922 vty_out(vty, "vrf %s inactive\n", vrf_name);
923 return CMD_SUCCESS;
924 }
925
926 table = zebra_vrf_table(afi, safi, zvrf_id(zvrf));
927 if (!table) {
928 if (use_json)
929 vty_out(vty, "{}\n");
930 return CMD_SUCCESS;
931 }
932
933 if (use_json)
934 json = json_object_new_object();
935
936 /* Show all routes. */
937 for (rn = route_top(table); rn; rn = route_next(rn)) {
938 RNODE_FOREACH_RE(rn, re)
939 {
940 if (use_fib
941 && !CHECK_FLAG(re->status,
942 ROUTE_ENTRY_SELECTED_FIB))
943 continue;
944
945 if (tag && re->tag != tag)
946 continue;
947
948 if (longer_prefix_p
949 && !prefix_match(longer_prefix_p, &rn->p))
950 continue;
951
952 /* This can only be true when the afi is IPv4 */
953 if (supernets_only) {
954 addr = ntohl(rn->p.u.prefix4.s_addr);
955
956 if (IN_CLASSC(addr) && rn->p.prefixlen >= 24)
957 continue;
958
959 if (IN_CLASSB(addr) && rn->p.prefixlen >= 16)
960 continue;
961
962 if (IN_CLASSA(addr) && rn->p.prefixlen >= 8)
963 continue;
964 }
965
966 if (type && re->type != type)
967 continue;
968
969 if (ospf_instance_id
970 && (re->type != ZEBRA_ROUTE_OSPF
971 || re->instance != ospf_instance_id))
972 continue;
973
974 if (use_json) {
975 if (!json_prefix)
976 json_prefix = json_object_new_array();
977 } else {
978 if (first) {
979 if (afi == AFI_IP)
980 vty_out(vty,
981 SHOW_ROUTE_V4_HEADER);
982 else
983 vty_out(vty,
984 SHOW_ROUTE_V6_HEADER);
985
986 if (zvrf_id(zvrf) != VRF_DEFAULT)
987 vty_out(vty, "\nVRF %s:\n",
988 zvrf_name(zvrf));
989
990 first = 0;
991 }
992 }
993
994 vty_show_ip_route(vty, rn, re, json_prefix);
995 }
996
997 if (json_prefix) {
998 prefix2str(&rn->p, buf, sizeof buf);
999 json_object_object_add(json, buf, json_prefix);
1000 json_prefix = NULL;
1001 }
1002 }
1003
1004 if (use_json) {
1005 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1006 json, JSON_C_TO_STRING_PRETTY));
1007 json_object_free(json);
1008 }
1009
1010 return CMD_SUCCESS;
1011 }
1012
1013 DEFUN (show_ip_nht,
1014 show_ip_nht_cmd,
1015 "show ip nht [vrf NAME]",
1016 SHOW_STR
1017 IP_STR
1018 "IP nexthop tracking table\n"
1019 VRF_CMD_HELP_STR)
1020 {
1021 int idx_vrf = 4;
1022 vrf_id_t vrf_id = VRF_DEFAULT;
1023
1024 if (argc == 5)
1025 VRF_GET_ID(vrf_id, argv[idx_vrf]->arg);
1026
1027 zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE);
1028 return CMD_SUCCESS;
1029 }
1030
1031
1032 DEFUN (show_ip_nht_vrf_all,
1033 show_ip_nht_vrf_all_cmd,
1034 "show ip nht vrf all",
1035 SHOW_STR
1036 IP_STR
1037 "IP nexthop tracking table\n"
1038 VRF_ALL_CMD_HELP_STR)
1039 {
1040 struct vrf *vrf;
1041 struct zebra_vrf *zvrf;
1042
1043 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1044 if ((zvrf = vrf->info) != NULL) {
1045 vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
1046 zebra_print_rnh_table(zvrf_id(zvrf), AF_INET, vty,
1047 RNH_NEXTHOP_TYPE);
1048 }
1049
1050 return CMD_SUCCESS;
1051 }
1052
1053 DEFUN (show_ipv6_nht,
1054 show_ipv6_nht_cmd,
1055 "show ipv6 nht [vrf NAME]",
1056 SHOW_STR
1057 IPV6_STR
1058 "IPv6 nexthop tracking table\n"
1059 VRF_CMD_HELP_STR)
1060 {
1061 int idx_vrf = 4;
1062 vrf_id_t vrf_id = VRF_DEFAULT;
1063
1064 if (argc == 5)
1065 VRF_GET_ID(vrf_id, argv[idx_vrf]->arg);
1066
1067 zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE);
1068 return CMD_SUCCESS;
1069 }
1070
1071
1072 DEFUN (show_ipv6_nht_vrf_all,
1073 show_ipv6_nht_vrf_all_cmd,
1074 "show ipv6 nht vrf all",
1075 SHOW_STR
1076 IP_STR
1077 "IPv6 nexthop tracking table\n"
1078 VRF_ALL_CMD_HELP_STR)
1079 {
1080 struct vrf *vrf;
1081 struct zebra_vrf *zvrf;
1082
1083 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1084 if ((zvrf = vrf->info) != NULL) {
1085 vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
1086 zebra_print_rnh_table(zvrf_id(zvrf), AF_INET6, vty,
1087 RNH_NEXTHOP_TYPE);
1088 }
1089
1090 return CMD_SUCCESS;
1091 }
1092
1093 DEFUN (ip_nht_default_route,
1094 ip_nht_default_route_cmd,
1095 "ip nht resolve-via-default",
1096 IP_STR
1097 "Filter Next Hop tracking route resolution\n"
1098 "Resolve via default route\n")
1099 {
1100 if (zebra_rnh_ip_default_route)
1101 return CMD_SUCCESS;
1102
1103 zebra_rnh_ip_default_route = 1;
1104 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1105 return CMD_SUCCESS;
1106 }
1107
1108 DEFUN (no_ip_nht_default_route,
1109 no_ip_nht_default_route_cmd,
1110 "no ip nht resolve-via-default",
1111 NO_STR
1112 IP_STR
1113 "Filter Next Hop tracking route resolution\n"
1114 "Resolve via default route\n")
1115 {
1116 if (!zebra_rnh_ip_default_route)
1117 return CMD_SUCCESS;
1118
1119 zebra_rnh_ip_default_route = 0;
1120 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1121 return CMD_SUCCESS;
1122 }
1123
1124 DEFUN (ipv6_nht_default_route,
1125 ipv6_nht_default_route_cmd,
1126 "ipv6 nht resolve-via-default",
1127 IP6_STR
1128 "Filter Next Hop tracking route resolution\n"
1129 "Resolve via default route\n")
1130 {
1131 if (zebra_rnh_ipv6_default_route)
1132 return CMD_SUCCESS;
1133
1134 zebra_rnh_ipv6_default_route = 1;
1135 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1136 return CMD_SUCCESS;
1137 }
1138
1139 DEFUN (no_ipv6_nht_default_route,
1140 no_ipv6_nht_default_route_cmd,
1141 "no ipv6 nht resolve-via-default",
1142 NO_STR
1143 IP6_STR
1144 "Filter Next Hop tracking route resolution\n"
1145 "Resolve via default route\n")
1146 {
1147 if (!zebra_rnh_ipv6_default_route)
1148 return CMD_SUCCESS;
1149
1150 zebra_rnh_ipv6_default_route = 0;
1151 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1152 return CMD_SUCCESS;
1153 }
1154
1155 DEFUN (show_ip_route,
1156 show_ip_route_cmd,
1157 "show ip <fib|route> [vrf NAME] [tag (1-4294967295)|A.B.C.D/M longer-prefixes|supernets-only|" FRR_IP_REDIST_STR_ZEBRA "|ospf (1-65535)] [json]",
1158 SHOW_STR
1159 IP_STR
1160 "IP forwarding table\n"
1161 "IP routing table\n"
1162 VRF_CMD_HELP_STR
1163 "Show only routes with tag\n"
1164 "Tag value\n"
1165 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1166 "Show route matching the specified Network/Mask pair only\n"
1167 "Show supernet entries only\n"
1168 FRR_IP_REDIST_HELP_STR_ZEBRA
1169 "Open Shortest Path First (OSPFv2)\n"
1170 "Instance ID\n"
1171 JSON_STR)
1172 {
1173 bool uf = use_fib(argv[2]);
1174 struct route_table *table;
1175 int vrf_all = 0;
1176 route_tag_t tag = 0;
1177 vrf_id_t vrf_id = VRF_DEFAULT;
1178 struct vrf *vrf;
1179 struct zebra_vrf *zvrf;
1180 int uj = use_json(argc, argv);
1181 int idx = 0;
1182 struct prefix p;
1183 bool longer_prefixes = false;
1184 bool supernets_only = false;
1185 int type = 0;
1186 u_short ospf_instance_id = 0;
1187
1188 if (argv_find(argv, argc, "vrf", &idx)) {
1189 if (strmatch(argv[idx + 1]->arg, "all"))
1190 vrf_all = 1;
1191 else
1192 VRF_GET_ID(vrf_id, argv[idx + 1]->arg);
1193 }
1194
1195 if (argv_find(argv, argc, "tag", &idx))
1196 tag = strtoul(argv[idx + 1]->arg, NULL, 10);
1197
1198 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)) {
1199 str2prefix(argv[idx]->arg, &p);
1200 longer_prefixes = true;
1201 }
1202
1203 else if (argv_find(argv, argc, "supernets_only", &idx))
1204 supernets_only = true;
1205
1206 else {
1207 if (argv_find(argv, argc, "kernel", &idx))
1208 type = proto_redistnum(AFI_IP, argv[idx]->text);
1209 else if (argv_find(argv, argc, "babel", &idx))
1210 type = proto_redistnum(AFI_IP, argv[idx]->text);
1211 else if (argv_find(argv, argc, "connected", &idx))
1212 type = proto_redistnum(AFI_IP, argv[idx]->text);
1213 else if (argv_find(argv, argc, "static", &idx))
1214 type = proto_redistnum(AFI_IP, argv[idx]->text);
1215 else if (argv_find(argv, argc, "rip", &idx))
1216 type = proto_redistnum(AFI_IP, argv[idx]->text);
1217 else if (argv_find(argv, argc, "ospf", &idx))
1218 type = proto_redistnum(AFI_IP, argv[idx]->text);
1219 else if (argv_find(argv, argc, "isis", &idx))
1220 type = proto_redistnum(AFI_IP, argv[idx]->text);
1221 else if (argv_find(argv, argc, "bgp", &idx))
1222 type = proto_redistnum(AFI_IP, argv[idx]->text);
1223 else if (argv_find(argv, argc, "pim", &idx))
1224 type = proto_redistnum(AFI_IP, argv[idx]->text);
1225 else if (argv_find(argv, argc, "eigrp", &idx))
1226 type = proto_redistnum(AFI_IP, argv[idx]->text);
1227 else if (argv_find(argv, argc, "nhrp", &idx))
1228 type = proto_redistnum(AFI_IP, argv[idx]->text);
1229 else if (argv_find(argv, argc, "table", &idx))
1230 type = proto_redistnum(AFI_IP, argv[idx]->text);
1231 else if (argv_find(argv, argc, "vnc", &idx))
1232 type = proto_redistnum(AFI_IP, argv[idx]->text);
1233
1234 if (argv_find(argv, argc, "(1-65535)", &idx))
1235 ospf_instance_id = strtoul(argv[idx]->arg, NULL, 10);
1236
1237 if (type < 0) {
1238 vty_out(vty, "Unknown route type\n");
1239 return CMD_WARNING;
1240 }
1241 }
1242
1243 if (vrf_all) {
1244 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1245 {
1246 if ((zvrf = vrf->info) == NULL
1247 || (table = zvrf->table[AFI_IP][SAFI_UNICAST])
1248 == NULL)
1249 continue;
1250
1251 do_show_ip_route(
1252 vty, zvrf_name(zvrf), AFI_IP, SAFI_UNICAST, uf,
1253 uj, tag, longer_prefixes ? &p : NULL,
1254 supernets_only, type, ospf_instance_id);
1255 }
1256 } else {
1257 vrf = vrf_lookup_by_id(vrf_id);
1258 do_show_ip_route(vty, vrf->name, AFI_IP, SAFI_UNICAST, uf, uj,
1259 tag, longer_prefixes ? &p : NULL,
1260 supernets_only, type, ospf_instance_id);
1261 }
1262 return CMD_SUCCESS;
1263 }
1264
1265 DEFUN (show_ip_route_addr,
1266 show_ip_route_addr_cmd,
1267 "show ip route [vrf NAME] A.B.C.D",
1268 SHOW_STR
1269 IP_STR
1270 "IP routing table\n"
1271 VRF_CMD_HELP_STR
1272 "Network in the IP routing table to display\n")
1273 {
1274 int ret;
1275 struct prefix_ipv4 p;
1276 struct route_table *table;
1277 struct route_node *rn;
1278 vrf_id_t vrf_id = VRF_DEFAULT;
1279
1280 if (strmatch(argv[3]->text, "vrf")) {
1281 VRF_GET_ID(vrf_id, argv[4]->arg);
1282 ret = str2prefix_ipv4(argv[5]->arg, &p);
1283 } else {
1284 ret = str2prefix_ipv4(argv[3]->arg, &p);
1285 }
1286
1287 if (ret <= 0) {
1288 vty_out(vty, "%% Malformed IPv4 address\n");
1289 return CMD_WARNING;
1290 }
1291
1292 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
1293 if (!table)
1294 return CMD_SUCCESS;
1295
1296 rn = route_node_match(table, (struct prefix *)&p);
1297 if (!rn) {
1298 vty_out(vty, "%% Network not in table\n");
1299 return CMD_WARNING;
1300 }
1301
1302 vty_show_ip_route_detail(vty, rn, 0);
1303
1304 route_unlock_node(rn);
1305
1306 return CMD_SUCCESS;
1307 }
1308
1309 DEFUN (show_ip_route_prefix,
1310 show_ip_route_prefix_cmd,
1311 "show ip route [vrf NAME] A.B.C.D/M",
1312 SHOW_STR
1313 IP_STR
1314 "IP routing table\n"
1315 VRF_CMD_HELP_STR
1316 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
1317 {
1318 int ret;
1319 struct prefix_ipv4 p;
1320 struct route_table *table;
1321 struct route_node *rn;
1322 vrf_id_t vrf_id = VRF_DEFAULT;
1323
1324 if (strmatch(argv[3]->text, "vrf")) {
1325 VRF_GET_ID(vrf_id, argv[4]->arg);
1326 ret = str2prefix_ipv4(argv[5]->arg, &p);
1327 } else {
1328 ret = str2prefix_ipv4(argv[3]->arg, &p);
1329 }
1330
1331 if (ret <= 0) {
1332 vty_out(vty, "%% Malformed IPv4 address\n");
1333 return CMD_WARNING;
1334 }
1335
1336 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
1337 if (!table)
1338 return CMD_SUCCESS;
1339
1340 rn = route_node_match(table, (struct prefix *)&p);
1341 if (!rn || rn->p.prefixlen != p.prefixlen) {
1342 vty_out(vty, "%% Network not in table\n");
1343 return CMD_WARNING;
1344 }
1345
1346 vty_show_ip_route_detail(vty, rn, 0);
1347
1348 route_unlock_node(rn);
1349
1350 return CMD_SUCCESS;
1351 }
1352
1353
1354 static void vty_show_ip_route_summary(struct vty *vty,
1355 struct route_table *table)
1356 {
1357 struct route_node *rn;
1358 struct route_entry *re;
1359 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
1360 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
1361 u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1362 u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1363 u_int32_t i;
1364 u_int32_t is_ibgp;
1365
1366 memset(&rib_cnt, 0, sizeof(rib_cnt));
1367 memset(&fib_cnt, 0, sizeof(fib_cnt));
1368 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
1369 RNODE_FOREACH_RE(rn, re)
1370 {
1371 is_ibgp = (re->type == ZEBRA_ROUTE_BGP
1372 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP));
1373
1374 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
1375 if (is_ibgp)
1376 rib_cnt[ZEBRA_ROUTE_IBGP]++;
1377 else
1378 rib_cnt[re->type]++;
1379
1380 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
1381 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
1382
1383 if (is_ibgp)
1384 fib_cnt[ZEBRA_ROUTE_IBGP]++;
1385 else
1386 fib_cnt[re->type]++;
1387 }
1388 }
1389
1390 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source", "Routes",
1391 "FIB", zvrf_name(((rib_table_info_t *)table->info)->zvrf));
1392
1393 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1394 if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP
1395 && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) {
1396 if (i == ZEBRA_ROUTE_BGP) {
1397 vty_out(vty, "%-20s %-20d %-20d \n", "ebgp",
1398 rib_cnt[ZEBRA_ROUTE_BGP],
1399 fib_cnt[ZEBRA_ROUTE_BGP]);
1400 vty_out(vty, "%-20s %-20d %-20d \n", "ibgp",
1401 rib_cnt[ZEBRA_ROUTE_IBGP],
1402 fib_cnt[ZEBRA_ROUTE_IBGP]);
1403 } else
1404 vty_out(vty, "%-20s %-20d %-20d \n",
1405 zebra_route_string(i), rib_cnt[i],
1406 fib_cnt[i]);
1407 }
1408 }
1409
1410 vty_out(vty, "------\n");
1411 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
1412 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
1413 vty_out(vty, "\n");
1414 }
1415
1416 /*
1417 * Implementation of the ip route summary prefix command.
1418 *
1419 * This command prints the primary prefixes that have been installed by various
1420 * protocols on the box.
1421 *
1422 */
1423 static void vty_show_ip_route_summary_prefix(struct vty *vty,
1424 struct route_table *table)
1425 {
1426 struct route_node *rn;
1427 struct route_entry *re;
1428 struct nexthop *nexthop;
1429 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
1430 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
1431 u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1432 u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1433 u_int32_t i;
1434 int cnt;
1435
1436 memset(&rib_cnt, 0, sizeof(rib_cnt));
1437 memset(&fib_cnt, 0, sizeof(fib_cnt));
1438 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
1439 RNODE_FOREACH_RE(rn, re)
1440 {
1441
1442 /*
1443 * In case of ECMP, count only once.
1444 */
1445 cnt = 0;
1446 for (nexthop = re->nexthop; (!cnt && nexthop);
1447 nexthop = nexthop->next) {
1448 cnt++;
1449 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
1450 rib_cnt[re->type]++;
1451 if (CHECK_FLAG(nexthop->flags,
1452 NEXTHOP_FLAG_FIB)) {
1453 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
1454 fib_cnt[re->type]++;
1455 }
1456 if (re->type == ZEBRA_ROUTE_BGP
1457 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) {
1458 rib_cnt[ZEBRA_ROUTE_IBGP]++;
1459 if (CHECK_FLAG(nexthop->flags,
1460 NEXTHOP_FLAG_FIB))
1461 fib_cnt[ZEBRA_ROUTE_IBGP]++;
1462 }
1463 }
1464 }
1465
1466 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
1467 "Prefix Routes", "FIB",
1468 zvrf_name(((rib_table_info_t *)table->info)->zvrf));
1469
1470 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1471 if (rib_cnt[i] > 0) {
1472 if (i == ZEBRA_ROUTE_BGP) {
1473 vty_out(vty, "%-20s %-20d %-20d \n", "ebgp",
1474 rib_cnt[ZEBRA_ROUTE_BGP]
1475 - rib_cnt[ZEBRA_ROUTE_IBGP],
1476 fib_cnt[ZEBRA_ROUTE_BGP]
1477 - fib_cnt[ZEBRA_ROUTE_IBGP]);
1478 vty_out(vty, "%-20s %-20d %-20d \n", "ibgp",
1479 rib_cnt[ZEBRA_ROUTE_IBGP],
1480 fib_cnt[ZEBRA_ROUTE_IBGP]);
1481 } else
1482 vty_out(vty, "%-20s %-20d %-20d \n",
1483 zebra_route_string(i), rib_cnt[i],
1484 fib_cnt[i]);
1485 }
1486 }
1487
1488 vty_out(vty, "------\n");
1489 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
1490 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
1491 vty_out(vty, "\n");
1492 }
1493
1494 /* Show route summary. */
1495 DEFUN (show_ip_route_summary,
1496 show_ip_route_summary_cmd,
1497 "show ip route [vrf NAME] summary",
1498 SHOW_STR
1499 IP_STR
1500 "IP routing table\n"
1501 VRF_CMD_HELP_STR
1502 "Summary of all routes\n")
1503 {
1504 struct route_table *table;
1505 vrf_id_t vrf_id = VRF_DEFAULT;
1506
1507 if (strmatch(argv[3]->text, "vrf"))
1508 VRF_GET_ID(vrf_id, argv[4]->arg);
1509
1510 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
1511 if (!table)
1512 return CMD_SUCCESS;
1513
1514 vty_show_ip_route_summary(vty, table);
1515
1516 return CMD_SUCCESS;
1517 }
1518
1519 /* Show route summary prefix. */
1520 DEFUN (show_ip_route_summary_prefix,
1521 show_ip_route_summary_prefix_cmd,
1522 "show ip route [vrf NAME] summary prefix",
1523 SHOW_STR
1524 IP_STR
1525 "IP routing table\n"
1526 VRF_CMD_HELP_STR
1527 "Summary of all routes\n"
1528 "Prefix routes\n")
1529 {
1530 struct route_table *table;
1531 vrf_id_t vrf_id = VRF_DEFAULT;
1532
1533 if (strmatch(argv[3]->text, "vrf"))
1534 VRF_GET_ID(vrf_id, argv[4]->arg);
1535
1536 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
1537 if (!table)
1538 return CMD_SUCCESS;
1539
1540 vty_show_ip_route_summary_prefix(vty, table);
1541
1542 return CMD_SUCCESS;
1543 }
1544
1545
1546 DEFUN (show_ip_route_vrf_all_addr,
1547 show_ip_route_vrf_all_addr_cmd,
1548 "show ip route vrf all A.B.C.D",
1549 SHOW_STR
1550 IP_STR
1551 "IP routing table\n"
1552 VRF_ALL_CMD_HELP_STR
1553 "Network in the IP routing table to display\n")
1554 {
1555 int idx_ipv4 = 5;
1556 int ret;
1557 struct prefix_ipv4 p;
1558 struct route_table *table;
1559 struct route_node *rn;
1560 struct vrf *vrf;
1561 struct zebra_vrf *zvrf;
1562
1563 ret = str2prefix_ipv4(argv[idx_ipv4]->arg, &p);
1564 if (ret <= 0) {
1565 vty_out(vty, "%% Malformed IPv4 address\n");
1566 return CMD_WARNING;
1567 }
1568
1569 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1570 {
1571 if ((zvrf = vrf->info) == NULL
1572 || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL)
1573 continue;
1574
1575 rn = route_node_match(table, (struct prefix *)&p);
1576 if (!rn)
1577 continue;
1578
1579 vty_show_ip_route_detail(vty, rn, 0);
1580
1581 route_unlock_node(rn);
1582 }
1583
1584 return CMD_SUCCESS;
1585 }
1586
1587 DEFUN (show_ip_route_vrf_all_prefix,
1588 show_ip_route_vrf_all_prefix_cmd,
1589 "show ip route vrf all A.B.C.D/M",
1590 SHOW_STR
1591 IP_STR
1592 "IP routing table\n"
1593 VRF_ALL_CMD_HELP_STR
1594 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
1595 {
1596 int idx_ipv4_prefixlen = 5;
1597 int ret;
1598 struct prefix_ipv4 p;
1599 struct route_table *table;
1600 struct route_node *rn;
1601 struct vrf *vrf;
1602 struct zebra_vrf *zvrf;
1603
1604 ret = str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
1605 if (ret <= 0) {
1606 vty_out(vty, "%% Malformed IPv4 address\n");
1607 return CMD_WARNING;
1608 }
1609
1610 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1611 {
1612 if ((zvrf = vrf->info) == NULL
1613 || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL)
1614 continue;
1615
1616 rn = route_node_match(table, (struct prefix *)&p);
1617 if (!rn)
1618 continue;
1619 if (rn->p.prefixlen != p.prefixlen) {
1620 route_unlock_node(rn);
1621 continue;
1622 }
1623
1624 vty_show_ip_route_detail(vty, rn, 0);
1625
1626 route_unlock_node(rn);
1627 }
1628
1629 return CMD_SUCCESS;
1630 }
1631
1632 DEFUN (show_ip_route_vrf_all_summary,
1633 show_ip_route_vrf_all_summary_cmd,
1634 "show ip route vrf all summary ",
1635 SHOW_STR
1636 IP_STR
1637 "IP routing table\n"
1638 VRF_ALL_CMD_HELP_STR
1639 "Summary of all routes\n")
1640 {
1641 struct vrf *vrf;
1642 struct zebra_vrf *zvrf;
1643
1644 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1645 if ((zvrf = vrf->info) != NULL)
1646 vty_show_ip_route_summary(vty,
1647 zvrf->table[AFI_IP][SAFI_UNICAST]);
1648
1649 return CMD_SUCCESS;
1650 }
1651
1652 DEFUN (show_ip_route_vrf_all_summary_prefix,
1653 show_ip_route_vrf_all_summary_prefix_cmd,
1654 "show ip route vrf all summary prefix",
1655 SHOW_STR
1656 IP_STR
1657 "IP routing table\n"
1658 VRF_ALL_CMD_HELP_STR
1659 "Summary of all routes\n"
1660 "Prefix routes\n")
1661 {
1662 struct vrf *vrf;
1663 struct zebra_vrf *zvrf;
1664
1665 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1666 if ((zvrf = vrf->info) != NULL)
1667 vty_show_ip_route_summary_prefix(
1668 vty, zvrf->table[AFI_IP][SAFI_UNICAST]);
1669
1670 return CMD_SUCCESS;
1671 }
1672
1673 /* Write static route configuration. */
1674 static int static_config(struct vty *vty, afi_t afi, safi_t safi,
1675 const char *cmd)
1676 {
1677 struct route_node *rn;
1678 struct static_route *si;
1679 struct route_table *stable;
1680 struct vrf *vrf;
1681 struct zebra_vrf *zvrf;
1682 char buf[SRCDEST2STR_BUFFER];
1683 int write = 0;
1684
1685 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1686 {
1687 if (!(zvrf = vrf->info))
1688 continue;
1689 if ((stable = zvrf->stable[afi][safi]) == NULL)
1690 continue;
1691
1692 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn))
1693 for (si = rn->info; si; si = si->next) {
1694 vty_out(vty, "%s %s", cmd,
1695 srcdest_rnode2str(rn, buf, sizeof buf));
1696
1697 switch (si->type) {
1698 case STATIC_IPV4_GATEWAY:
1699 vty_out(vty, " %s",
1700 inet_ntoa(si->addr.ipv4));
1701 break;
1702 case STATIC_IPV6_GATEWAY:
1703 vty_out(vty, " %s",
1704 inet_ntop(AF_INET6,
1705 &si->addr.ipv6, buf,
1706 sizeof buf));
1707 break;
1708 case STATIC_IFINDEX:
1709 vty_out(vty, " %s", si->ifname);
1710 break;
1711 /* blackhole and Null0 mean the same thing */
1712 case STATIC_BLACKHOLE:
1713 if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT))
1714 vty_out(vty, " reject");
1715 else
1716 vty_out(vty, " Null0");
1717 break;
1718 case STATIC_IPV4_GATEWAY_IFINDEX:
1719 vty_out(vty, " %s %s",
1720 inet_ntop(AF_INET,
1721 &si->addr.ipv4, buf,
1722 sizeof buf),
1723 ifindex2ifname(si->ifindex,
1724 si->vrf_id));
1725 break;
1726 case STATIC_IPV6_GATEWAY_IFINDEX:
1727 vty_out(vty, " %s %s",
1728 inet_ntop(AF_INET6,
1729 &si->addr.ipv6, buf,
1730 sizeof buf),
1731 ifindex2ifname(si->ifindex,
1732 si->vrf_id));
1733 break;
1734 }
1735
1736 /* flags are incompatible with STATIC_BLACKHOLE
1737 */
1738 if (si->type != STATIC_BLACKHOLE) {
1739 if (CHECK_FLAG(si->flags,
1740 ZEBRA_FLAG_REJECT))
1741 vty_out(vty, " %s", "reject");
1742
1743 if (CHECK_FLAG(si->flags,
1744 ZEBRA_FLAG_BLACKHOLE))
1745 vty_out(vty, " %s",
1746 "blackhole");
1747 }
1748
1749 if (si->tag)
1750 vty_out(vty, " tag %" ROUTE_TAG_PRI,
1751 si->tag);
1752
1753 if (si->distance
1754 != ZEBRA_STATIC_DISTANCE_DEFAULT)
1755 vty_out(vty, " %d", si->distance);
1756
1757 if (si->vrf_id != VRF_DEFAULT)
1758 vty_out(vty, " vrf %s",
1759 zvrf_name(zvrf));
1760
1761 /* Label information */
1762 if (si->snh_label.num_labels)
1763 vty_out(vty, " label %s",
1764 mpls_label2str(
1765 si->snh_label
1766 .num_labels,
1767 si->snh_label.label,
1768 buf, sizeof buf, 0));
1769
1770 vty_out(vty, "\n");
1771
1772 write = 1;
1773 }
1774 }
1775 return write;
1776 }
1777
1778 DEFPY (ipv6_route,
1779 ipv6_route_cmd,
1780 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M]\
1781 <\
1782 {X:X::X:X$gate|INTERFACE$ifname}\
1783 |null0$ifname\
1784 |<reject|blackhole>$flag\
1785 >\
1786 [{\
1787 tag (1-4294967295)\
1788 |(1-255)$distance\
1789 |vrf NAME\
1790 |label WORD\
1791 }]",
1792 NO_STR
1793 IPV6_STR
1794 "Establish static routes\n"
1795 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1796 "IPv6 source-dest route\n"
1797 "IPv6 source prefix\n"
1798 "IPv6 gateway address\n"
1799 "IPv6 gateway interface name\n"
1800 "Null interface\n"
1801 "Emit an ICMP unreachable when matched\n"
1802 "Silently discard pkts when matched\n"
1803 "Set tag for this route\n"
1804 "Tag value\n"
1805 "Distance value for this prefix\n"
1806 VRF_CMD_HELP_STR
1807 MPLS_LABEL_HELPSTR)
1808 {
1809 return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
1810 NULL, from_str, gate_str, ifname, flag,
1811 tag_str, distance_str, vrf, label);
1812 }
1813
1814 DEFUN (show_ipv6_route,
1815 show_ipv6_route_cmd,
1816 "show ipv6 <fib|route> [vrf NAME] [tag (1-4294967295)|X:X::X:X/M longer-prefixes|" FRR_IP6_REDIST_STR_ZEBRA "] [json]",
1817 SHOW_STR
1818 IP_STR
1819 "IP forwarding table\n"
1820 "IP routing table\n"
1821 VRF_CMD_HELP_STR
1822 "Show only routes with tag\n"
1823 "Tag value\n"
1824 "IPv6 prefix\n"
1825 "Show route matching the specified Network/Mask pair only\n"
1826 FRR_IP6_REDIST_HELP_STR_ZEBRA
1827 JSON_STR)
1828 {
1829 bool uf = use_fib(argv[2]);
1830 struct route_table *table;
1831 int vrf_all = 0;
1832 route_tag_t tag = 0;
1833 vrf_id_t vrf_id = VRF_DEFAULT;
1834 struct vrf *vrf;
1835 struct zebra_vrf *zvrf;
1836 int uj = use_json(argc, argv);
1837 int idx = 0;
1838 struct prefix p;
1839 bool longer_prefixes = false;
1840 bool supernets_only = false;
1841 int type = 0;
1842
1843 if (argv_find(argv, argc, "vrf", &idx)) {
1844 if (strmatch(argv[idx + 1]->arg, "all"))
1845 vrf_all = 1;
1846 else
1847 VRF_GET_ID(vrf_id, argv[idx + 1]->arg);
1848 }
1849
1850 if (argv_find(argv, argc, "tag", &idx))
1851 tag = strtoul(argv[idx + 1]->arg, NULL, 10);
1852
1853 else if (argv_find(argv, argc, "X:X::X:X/M", &idx)) {
1854 str2prefix(argv[idx]->arg, &p);
1855 longer_prefixes = true;
1856 }
1857
1858 else {
1859 if (argv_find(argv, argc, "kernel", &idx))
1860 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1861 else if (argv_find(argv, argc, "babel", &idx))
1862 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1863 else if (argv_find(argv, argc, "connected", &idx))
1864 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1865 else if (argv_find(argv, argc, "static", &idx))
1866 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1867 else if (argv_find(argv, argc, "ripng", &idx))
1868 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1869 else if (argv_find(argv, argc, "ospf6", &idx))
1870 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1871 else if (argv_find(argv, argc, "isis", &idx))
1872 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1873 else if (argv_find(argv, argc, "bgp", &idx))
1874 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1875 else if (argv_find(argv, argc, "nhrp", &idx))
1876 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1877 else if (argv_find(argv, argc, "table", &idx))
1878 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1879 else if (argv_find(argv, argc, "vnc", &idx))
1880 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1881
1882 if (type < 0) {
1883 vty_out(vty, "Unknown route type\n");
1884 return CMD_WARNING;
1885 }
1886 }
1887
1888 if (vrf_all) {
1889 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1890 {
1891 if ((zvrf = vrf->info) == NULL
1892 || (table = zvrf->table[AFI_IP6][SAFI_UNICAST])
1893 == NULL)
1894 continue;
1895
1896 do_show_ip_route(vty, zvrf_name(zvrf), AFI_IP6,
1897 SAFI_UNICAST, uf, uj, tag,
1898 longer_prefixes ? &p : NULL,
1899 supernets_only, type, 0);
1900 }
1901 } else {
1902 vrf = vrf_lookup_by_id(vrf_id);
1903 do_show_ip_route(vty, vrf->name, AFI_IP6, SAFI_UNICAST, uf, uj,
1904 tag, longer_prefixes ? &p : NULL,
1905 supernets_only, type, 0);
1906 }
1907 return CMD_SUCCESS;
1908 }
1909
1910 DEFUN (show_ipv6_route_addr,
1911 show_ipv6_route_addr_cmd,
1912 "show ipv6 route [vrf NAME] X:X::X:X",
1913 SHOW_STR
1914 IP_STR
1915 "IPv6 routing table\n"
1916 VRF_CMD_HELP_STR
1917 "IPv6 Address\n")
1918 {
1919 int ret;
1920 struct prefix_ipv6 p;
1921 struct route_table *table;
1922 struct route_node *rn;
1923 vrf_id_t vrf_id = VRF_DEFAULT;
1924
1925 if (strmatch(argv[3]->text, "vrf")) {
1926 VRF_GET_ID(vrf_id, argv[4]->arg);
1927 ret = str2prefix_ipv6(argv[5]->arg, &p);
1928 } else {
1929 ret = str2prefix_ipv6(argv[3]->arg, &p);
1930 }
1931
1932 if (ret <= 0) {
1933 vty_out(vty, "Malformed IPv6 address\n");
1934 return CMD_WARNING;
1935 }
1936
1937 table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
1938 if (!table)
1939 return CMD_SUCCESS;
1940
1941 rn = route_node_match(table, (struct prefix *)&p);
1942 if (!rn) {
1943 vty_out(vty, "%% Network not in table\n");
1944 return CMD_WARNING;
1945 }
1946
1947 vty_show_ip_route_detail(vty, rn, 0);
1948
1949 route_unlock_node(rn);
1950
1951 return CMD_SUCCESS;
1952 }
1953
1954 DEFUN (show_ipv6_route_prefix,
1955 show_ipv6_route_prefix_cmd,
1956 "show ipv6 route [vrf NAME] X:X::X:X/M",
1957 SHOW_STR
1958 IP_STR
1959 "IPv6 routing table\n"
1960 VRF_CMD_HELP_STR
1961 "IPv6 prefix\n")
1962 {
1963 int ret;
1964 struct prefix_ipv6 p;
1965 struct route_table *table;
1966 struct route_node *rn;
1967 vrf_id_t vrf_id = VRF_DEFAULT;
1968
1969 if (strmatch(argv[3]->text, "vrf")) {
1970 VRF_GET_ID(vrf_id, argv[4]->arg);
1971 ret = str2prefix_ipv6(argv[5]->arg, &p);
1972 } else
1973 ret = str2prefix_ipv6(argv[3]->arg, &p);
1974
1975 if (ret <= 0) {
1976 vty_out(vty, "Malformed IPv6 prefix\n");
1977 return CMD_WARNING;
1978 }
1979
1980 table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
1981 if (!table)
1982 return CMD_SUCCESS;
1983
1984 rn = route_node_match(table, (struct prefix *)&p);
1985 if (!rn || rn->p.prefixlen != p.prefixlen) {
1986 vty_out(vty, "%% Network not in table\n");
1987 return CMD_WARNING;
1988 }
1989
1990 vty_show_ip_route_detail(vty, rn, 0);
1991
1992 route_unlock_node(rn);
1993
1994 return CMD_SUCCESS;
1995 }
1996
1997
1998 /* Show route summary. */
1999 DEFUN (show_ipv6_route_summary,
2000 show_ipv6_route_summary_cmd,
2001 "show ipv6 route [vrf NAME] summary",
2002 SHOW_STR
2003 IP_STR
2004 "IPv6 routing table\n"
2005 VRF_CMD_HELP_STR
2006 "Summary of all IPv6 routes\n")
2007 {
2008 struct route_table *table;
2009 vrf_id_t vrf_id = VRF_DEFAULT;
2010
2011 if (strmatch(argv[3]->text, "vrf"))
2012 VRF_GET_ID(vrf_id, argv[4]->arg);
2013
2014 table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
2015 if (!table)
2016 return CMD_SUCCESS;
2017
2018 vty_show_ip_route_summary(vty, table);
2019
2020 return CMD_SUCCESS;
2021 }
2022
2023
2024 /* Show ipv6 route summary prefix. */
2025 DEFUN (show_ipv6_route_summary_prefix,
2026 show_ipv6_route_summary_prefix_cmd,
2027 "show ipv6 route [vrf NAME] summary prefix",
2028 SHOW_STR
2029 IP_STR
2030 "IPv6 routing table\n"
2031 VRF_CMD_HELP_STR
2032 "Summary of all IPv6 routes\n"
2033 "Prefix routes\n")
2034 {
2035 struct route_table *table;
2036 vrf_id_t vrf_id = VRF_DEFAULT;
2037
2038 if (strmatch(argv[3]->text, "vrf"))
2039 VRF_GET_ID(vrf_id, argv[4]->arg);
2040
2041 table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
2042 if (!table)
2043 return CMD_SUCCESS;
2044
2045 vty_show_ip_route_summary_prefix(vty, table);
2046
2047 return CMD_SUCCESS;
2048 }
2049
2050
2051 /*
2052 * Show IPv6 mroute command.Used to dump
2053 * the Multicast routing table.
2054 */
2055 DEFUN (show_ipv6_mroute,
2056 show_ipv6_mroute_cmd,
2057 "show ipv6 mroute [vrf NAME]",
2058 SHOW_STR
2059 IP_STR
2060 "IPv6 Multicast routing table\n"
2061 VRF_CMD_HELP_STR)
2062 {
2063 struct route_table *table;
2064 struct route_node *rn;
2065 struct route_entry *re;
2066 int first = 1;
2067 vrf_id_t vrf_id = VRF_DEFAULT;
2068
2069 if (argc == 5)
2070 VRF_GET_ID(vrf_id, argv[4]->arg);
2071
2072 table = zebra_vrf_table(AFI_IP6, SAFI_MULTICAST, vrf_id);
2073 if (!table)
2074 return CMD_SUCCESS;
2075
2076 /* Show all IPv6 route. */
2077 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2078 RNODE_FOREACH_RE(rn, re)
2079 {
2080 if (first) {
2081 vty_out(vty, SHOW_ROUTE_V6_HEADER);
2082 first = 0;
2083 }
2084 vty_show_ip_route(vty, rn, re, NULL);
2085 }
2086 return CMD_SUCCESS;
2087 }
2088
2089 DEFUN (show_ipv6_route_vrf_all_addr,
2090 show_ipv6_route_vrf_all_addr_cmd,
2091 "show ipv6 route vrf all X:X::X:X",
2092 SHOW_STR
2093 IP_STR
2094 "IPv6 routing table\n"
2095 VRF_ALL_CMD_HELP_STR
2096 "IPv6 Address\n")
2097 {
2098 int idx_ipv6 = 5;
2099 int ret;
2100 struct prefix_ipv6 p;
2101 struct route_table *table;
2102 struct route_node *rn;
2103 struct vrf *vrf;
2104 struct zebra_vrf *zvrf;
2105
2106 ret = str2prefix_ipv6(argv[idx_ipv6]->arg, &p);
2107 if (ret <= 0) {
2108 vty_out(vty, "Malformed IPv6 address\n");
2109 return CMD_WARNING;
2110 }
2111
2112 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
2113 {
2114 if ((zvrf = vrf->info) == NULL
2115 || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL)
2116 continue;
2117
2118 rn = route_node_match(table, (struct prefix *)&p);
2119 if (!rn)
2120 continue;
2121
2122 vty_show_ip_route_detail(vty, rn, 0);
2123
2124 route_unlock_node(rn);
2125 }
2126
2127 return CMD_SUCCESS;
2128 }
2129
2130 DEFUN (show_ipv6_route_vrf_all_prefix,
2131 show_ipv6_route_vrf_all_prefix_cmd,
2132 "show ipv6 route vrf all X:X::X:X/M",
2133 SHOW_STR
2134 IP_STR
2135 "IPv6 routing table\n"
2136 VRF_ALL_CMD_HELP_STR
2137 "IPv6 prefix\n")
2138 {
2139 int idx_ipv6_prefixlen = 5;
2140 int ret;
2141 struct prefix_ipv6 p;
2142 struct route_table *table;
2143 struct route_node *rn;
2144 struct vrf *vrf;
2145 struct zebra_vrf *zvrf;
2146
2147 ret = str2prefix_ipv6(argv[idx_ipv6_prefixlen]->arg, &p);
2148 if (ret <= 0) {
2149 vty_out(vty, "Malformed IPv6 prefix\n");
2150 return CMD_WARNING;
2151 }
2152
2153 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
2154 {
2155 if ((zvrf = vrf->info) == NULL
2156 || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL)
2157 continue;
2158
2159 rn = route_node_match(table, (struct prefix *)&p);
2160 if (!rn)
2161 continue;
2162 if (rn->p.prefixlen != p.prefixlen) {
2163 route_unlock_node(rn);
2164 continue;
2165 }
2166
2167 vty_show_ip_route_detail(vty, rn, 0);
2168
2169 route_unlock_node(rn);
2170 }
2171
2172 return CMD_SUCCESS;
2173 }
2174
2175 DEFUN (show_ipv6_route_vrf_all_summary,
2176 show_ipv6_route_vrf_all_summary_cmd,
2177 "show ipv6 route vrf all summary",
2178 SHOW_STR
2179 IP_STR
2180 "IPv6 routing table\n"
2181 VRF_ALL_CMD_HELP_STR
2182 "Summary of all IPv6 routes\n")
2183 {
2184 struct vrf *vrf;
2185 struct zebra_vrf *zvrf;
2186
2187 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
2188 if ((zvrf = vrf->info) != NULL)
2189 vty_show_ip_route_summary(vty,
2190 zvrf->table[AFI_IP6][SAFI_UNICAST]);
2191
2192 return CMD_SUCCESS;
2193 }
2194
2195 DEFUN (show_ipv6_mroute_vrf_all,
2196 show_ipv6_mroute_vrf_all_cmd,
2197 "show ipv6 mroute vrf all",
2198 SHOW_STR
2199 IP_STR
2200 "IPv6 Multicast routing table\n"
2201 VRF_ALL_CMD_HELP_STR)
2202 {
2203 struct route_table *table;
2204 struct route_node *rn;
2205 struct route_entry *re;
2206 struct vrf *vrf;
2207 struct zebra_vrf *zvrf;
2208 int first = 1;
2209
2210 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
2211 {
2212 if ((zvrf = vrf->info) == NULL
2213 || (table = zvrf->table[AFI_IP6][SAFI_MULTICAST]) == NULL)
2214 continue;
2215
2216 /* Show all IPv6 route. */
2217 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2218 RNODE_FOREACH_RE(rn, re)
2219 {
2220 if (first) {
2221 vty_out(vty, SHOW_ROUTE_V6_HEADER);
2222 first = 0;
2223 }
2224 vty_show_ip_route(vty, rn, re, NULL);
2225 }
2226 }
2227 return CMD_SUCCESS;
2228 }
2229
2230 DEFUN (show_ipv6_route_vrf_all_summary_prefix,
2231 show_ipv6_route_vrf_all_summary_prefix_cmd,
2232 "show ipv6 route vrf all summary prefix",
2233 SHOW_STR
2234 IP_STR
2235 "IPv6 routing table\n"
2236 VRF_ALL_CMD_HELP_STR
2237 "Summary of all IPv6 routes\n"
2238 "Prefix routes\n")
2239 {
2240 struct vrf *vrf;
2241 struct zebra_vrf *zvrf;
2242
2243 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
2244 if ((zvrf = vrf->info) != NULL)
2245 vty_show_ip_route_summary_prefix(
2246 vty, zvrf->table[AFI_IP6][SAFI_UNICAST]);
2247
2248 return CMD_SUCCESS;
2249 }
2250
2251 DEFUN (allow_external_route_update,
2252 allow_external_route_update_cmd,
2253 "allow-external-route-update",
2254 "Allow FRR routes to be overwritten by external processes\n")
2255 {
2256 allow_delete = 1;
2257
2258 return CMD_SUCCESS;
2259 }
2260
2261 DEFUN (no_allow_external_route_update,
2262 no_allow_external_route_update_cmd,
2263 "no allow-external-route-update",
2264 NO_STR
2265 "Allow FRR routes to be overwritten by external processes\n")
2266 {
2267 allow_delete = 0;
2268
2269 return CMD_SUCCESS;
2270 }
2271
2272 /* show vrf */
2273 DEFUN (show_vrf,
2274 show_vrf_cmd,
2275 "show vrf",
2276 SHOW_STR
2277 "VRF\n")
2278 {
2279 struct vrf *vrf;
2280 struct zebra_vrf *zvrf;
2281
2282 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
2283 {
2284 if (!(zvrf = vrf->info))
2285 continue;
2286 if (!zvrf_id(zvrf))
2287 continue;
2288
2289 vty_out(vty, "vrf %s ", zvrf_name(zvrf));
2290 if (zvrf_id(zvrf) == VRF_UNKNOWN)
2291 vty_out(vty, "inactive");
2292 else
2293 vty_out(vty, "id %u table %u", zvrf_id(zvrf),
2294 zvrf->table_id);
2295 vty_out(vty, "\n");
2296 }
2297
2298 return CMD_SUCCESS;
2299 }
2300
2301 DEFUN (show_evpn_vni,
2302 show_evpn_vni_cmd,
2303 "show evpn vni [json]",
2304 SHOW_STR
2305 "EVPN\n"
2306 "VxLAN information\n"
2307 "JavaScript Object Notation\n")
2308 {
2309 struct zebra_vrf *zvrf;
2310 u_char uj = use_json(argc, argv);
2311
2312 zvrf = vrf_info_lookup(VRF_DEFAULT);
2313 zebra_vxlan_print_vnis(vty, zvrf, uj);
2314 return CMD_SUCCESS;
2315 }
2316
2317 DEFUN (show_evpn_vni_vni,
2318 show_evpn_vni_vni_cmd,
2319 "show evpn vni " CMD_VNI_RANGE "[json]",
2320 SHOW_STR
2321 "EVPN\n"
2322 "VxLAN Network Identifier\n"
2323 "VNI number\n"
2324 "JavaScript Object Notation\n")
2325 {
2326 struct zebra_vrf *zvrf;
2327 vni_t vni;
2328 u_char uj = use_json(argc, argv);
2329
2330 vni = strtoul(argv[3]->arg, NULL, 10);
2331 zvrf = vrf_info_lookup(VRF_DEFAULT);
2332 zebra_vxlan_print_vni(vty, zvrf, vni, uj);
2333 return CMD_SUCCESS;
2334 }
2335
2336 DEFUN (show_evpn_mac_vni,
2337 show_evpn_mac_vni_cmd,
2338 "show evpn mac vni " CMD_VNI_RANGE "[json]",
2339 SHOW_STR
2340 "EVPN\n"
2341 "MAC addresses\n"
2342 "VxLAN Network Identifier\n"
2343 "VNI number\n"
2344 "JavaScript Object Notation\n")
2345 {
2346 struct zebra_vrf *zvrf;
2347 vni_t vni;
2348 u_char uj = use_json(argc, argv);
2349
2350 vni = strtoul(argv[4]->arg, NULL, 10);
2351 zvrf = vrf_info_lookup(VRF_DEFAULT);
2352 zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj);
2353 return CMD_SUCCESS;
2354 }
2355
2356 DEFUN (show_evpn_mac_vni_all,
2357 show_evpn_mac_vni_all_cmd,
2358 "show evpn mac vni all [json]",
2359 SHOW_STR
2360 "EVPN\n"
2361 "MAC addresses\n"
2362 "VxLAN Network Identifier\n"
2363 "All VNIs\n"
2364 "JavaScript Object Notation\n")
2365 {
2366 struct zebra_vrf *zvrf;
2367 u_char uj = use_json(argc, argv);
2368
2369 zvrf = vrf_info_lookup(VRF_DEFAULT);
2370 zebra_vxlan_print_macs_all_vni(vty, zvrf, uj);
2371 return CMD_SUCCESS;
2372 }
2373
2374 DEFUN (show_evpn_mac_vni_all_vtep,
2375 show_evpn_mac_vni_all_vtep_cmd,
2376 "show evpn mac vni all vtep A.B.C.D [json]",
2377 SHOW_STR
2378 "EVPN\n"
2379 "MAC addresses\n"
2380 "VxLAN Network Identifier\n"
2381 "All VNIs\n"
2382 "Remote VTEP\n"
2383 "Remote VTEP IP address\n"
2384 "JavaScript Object Notation\n")
2385 {
2386 struct zebra_vrf *zvrf;
2387 struct in_addr vtep_ip;
2388 u_char uj = use_json(argc, argv);
2389
2390 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2391 if (!uj)
2392 vty_out(vty, "%% Malformed VTEP IP address\n");
2393 return CMD_WARNING;
2394 }
2395 zvrf = vrf_info_lookup(VRF_DEFAULT);
2396 zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip, uj);
2397
2398 return CMD_SUCCESS;
2399 }
2400
2401
2402 DEFUN (show_evpn_mac_vni_mac,
2403 show_evpn_mac_vni_mac_cmd,
2404 "show evpn mac vni " CMD_VNI_RANGE " mac WORD",
2405 SHOW_STR
2406 "EVPN\n"
2407 "MAC addresses\n"
2408 "VxLAN Network Identifier\n"
2409 "VNI number\n"
2410 "MAC\n"
2411 "MAC address (e.g., 00:e0:ec:20:12:62)\n")
2412 {
2413 struct zebra_vrf *zvrf;
2414 vni_t vni;
2415 struct ethaddr mac;
2416
2417 vni = strtoul(argv[4]->arg, NULL, 10);
2418 if (!prefix_str2mac(argv[6]->arg, &mac)) {
2419 vty_out(vty, "%% Malformed MAC address");
2420 return CMD_WARNING;
2421 }
2422 zvrf = vrf_info_lookup(VRF_DEFAULT);
2423 zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac);
2424 return CMD_SUCCESS;
2425 }
2426
2427 DEFUN (show_evpn_mac_vni_vtep,
2428 show_evpn_mac_vni_vtep_cmd,
2429 "show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D" "[json]",
2430 SHOW_STR
2431 "EVPN\n"
2432 "MAC addresses\n"
2433 "VxLAN Network Identifier\n"
2434 "VNI number\n"
2435 "Remote VTEP\n"
2436 "Remote VTEP IP address\n"
2437 "JavaScript Object Notation\n")
2438 {
2439 struct zebra_vrf *zvrf;
2440 vni_t vni;
2441 struct in_addr vtep_ip;
2442 u_char uj = use_json(argc, argv);
2443
2444 vni = strtoul(argv[4]->arg, NULL, 10);
2445 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2446 if (!uj)
2447 vty_out(vty, "%% Malformed VTEP IP address\n");
2448 return CMD_WARNING;
2449 }
2450
2451 zvrf = vrf_info_lookup(VRF_DEFAULT);
2452 zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
2453 return CMD_SUCCESS;
2454 }
2455
2456 DEFUN (show_evpn_neigh_vni,
2457 show_evpn_neigh_vni_cmd,
2458 "show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
2459 SHOW_STR
2460 "EVPN\n"
2461 "ARP and ND cache\n"
2462 "VxLAN Network Identifier\n"
2463 "VNI number\n"
2464 "JavaScript Object Notation\n")
2465 {
2466 struct zebra_vrf *zvrf;
2467 vni_t vni;
2468 u_char uj = use_json(argc, argv);
2469
2470 vni = strtoul(argv[4]->arg, NULL, 10);
2471 zvrf = vrf_info_lookup(VRF_DEFAULT);
2472 zebra_vxlan_print_neigh_vni(vty, zvrf, vni, uj);
2473 return CMD_SUCCESS;
2474 }
2475
2476 DEFUN (show_evpn_neigh_vni_all,
2477 show_evpn_neigh_vni_all_cmd,
2478 "show evpn arp-cache vni all [json]",
2479 SHOW_STR
2480 "EVPN\n"
2481 "ARP and ND cache\n"
2482 "VxLAN Network Identifier\n"
2483 "All VNIs\n"
2484 "JavaScript Object Notation\n")
2485 {
2486 struct zebra_vrf *zvrf;
2487 u_char uj = use_json(argc, argv);
2488
2489 zvrf = vrf_info_lookup(VRF_DEFAULT);
2490 zebra_vxlan_print_neigh_all_vni(vty, zvrf, uj);
2491 return CMD_SUCCESS;
2492 }
2493
2494 DEFUN (show_evpn_neigh_vni_neigh,
2495 show_evpn_neigh_vni_neigh_cmd,
2496 "show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD [json]",
2497 SHOW_STR
2498 "EVPN\n"
2499 "ARP and ND cache\n"
2500 "VxLAN Network Identifier\n"
2501 "VNI number\n"
2502 "Neighbor\n"
2503 "Neighbor address (IPv4 or IPv6 address)\n"
2504 "JavaScript Object Notation\n")
2505 {
2506 struct zebra_vrf *zvrf;
2507 vni_t vni;
2508 struct ipaddr ip;
2509 u_char uj = use_json(argc, argv);
2510
2511 vni = strtoul(argv[4]->arg, NULL, 10);
2512 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
2513 if (!uj)
2514 vty_out(vty, "%% Malformed Neighbor address\n");
2515 return CMD_WARNING;
2516 }
2517 zvrf = vrf_info_lookup(VRF_DEFAULT);
2518 zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip, uj);
2519 return CMD_SUCCESS;
2520 }
2521
2522 DEFUN (show_evpn_neigh_vni_vtep,
2523 show_evpn_neigh_vni_vtep_cmd,
2524 "show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D [json]",
2525 SHOW_STR
2526 "EVPN\n"
2527 "ARP and ND cache\n"
2528 "VxLAN Network Identifier\n"
2529 "VNI number\n"
2530 "Remote VTEP\n"
2531 "Remote VTEP IP address\n"
2532 "JavaScript Object Notation\n")
2533 {
2534 struct zebra_vrf *zvrf;
2535 vni_t vni;
2536 struct in_addr vtep_ip;
2537 u_char uj = use_json(argc, argv);
2538
2539 vni = strtoul(argv[4]->arg, NULL, 10);
2540 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2541 if (!uj)
2542 vty_out(vty, "%% Malformed VTEP IP address\n");
2543 return CMD_WARNING;
2544 }
2545
2546 zvrf = vrf_info_lookup(VRF_DEFAULT);
2547 zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
2548 return CMD_SUCCESS;
2549 }
2550
2551 /* Static ip route configuration write function. */
2552 static int zebra_ip_config(struct vty *vty)
2553 {
2554 int write = 0;
2555
2556 write += static_config(vty, AFI_IP, SAFI_UNICAST, "ip route");
2557 write += static_config(vty, AFI_IP, SAFI_MULTICAST, "ip mroute");
2558 write += static_config(vty, AFI_IP6, SAFI_UNICAST, "ipv6 route");
2559
2560 write += zebra_import_table_config(vty);
2561 return write;
2562 }
2563
2564 DEFUN (ip_zebra_import_table_distance,
2565 ip_zebra_import_table_distance_cmd,
2566 "ip import-table (1-252) [distance (1-255)] [route-map WORD]",
2567 IP_STR
2568 "import routes from non-main kernel table\n"
2569 "kernel routing table id\n"
2570 "Distance for imported routes\n"
2571 "Default distance value\n"
2572 "route-map for filtering\n"
2573 "route-map name\n")
2574 {
2575 u_int32_t table_id = 0;
2576
2577 table_id = strtoul(argv[2]->arg, NULL, 10);
2578 int distance = ZEBRA_TABLE_DISTANCE_DEFAULT;
2579 char *rmap =
2580 strmatch(argv[argc - 2]->text, "route-map")
2581 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg)
2582 : NULL;
2583 int ret;
2584
2585 if (argc == 7 || (argc == 5 && !rmap))
2586 distance = strtoul(argv[4]->arg, NULL, 10);
2587
2588 if (!is_zebra_valid_kernel_table(table_id)) {
2589 vty_out(vty,
2590 "Invalid routing table ID, %d. Must be in range 1-252\n",
2591 table_id);
2592 return CMD_WARNING;
2593 }
2594
2595 if (is_zebra_main_routing_table(table_id)) {
2596 vty_out(vty,
2597 "Invalid routing table ID, %d. Must be non-default table\n",
2598 table_id);
2599 return CMD_WARNING;
2600 }
2601
2602 ret = zebra_import_table(AFI_IP, table_id, distance, rmap, 1);
2603 if (rmap)
2604 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
2605
2606 return ret;
2607 }
2608
2609 DEFUN (no_ip_zebra_import_table,
2610 no_ip_zebra_import_table_cmd,
2611 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
2612 NO_STR
2613 IP_STR
2614 "import routes from non-main kernel table\n"
2615 "kernel routing table id\n"
2616 "Distance for imported routes\n"
2617 "Default distance value\n"
2618 "route-map for filtering\n"
2619 "route-map name\n")
2620 {
2621 u_int32_t table_id = 0;
2622 table_id = strtoul(argv[3]->arg, NULL, 10);
2623
2624 if (!is_zebra_valid_kernel_table(table_id)) {
2625 vty_out(vty,
2626 "Invalid routing table ID. Must be in range 1-252\n");
2627 return CMD_WARNING;
2628 }
2629
2630 if (is_zebra_main_routing_table(table_id)) {
2631 vty_out(vty,
2632 "Invalid routing table ID, %d. Must be non-default table\n",
2633 table_id);
2634 return CMD_WARNING;
2635 }
2636
2637 if (!is_zebra_import_table_enabled(AFI_IP, table_id))
2638 return CMD_SUCCESS;
2639
2640 return (zebra_import_table(AFI_IP, table_id, 0, NULL, 0));
2641 }
2642
2643 static int config_write_protocol(struct vty *vty)
2644 {
2645 if (allow_delete)
2646 vty_out(vty, "allow-external-route-update\n");
2647
2648 if (zebra_rnh_ip_default_route)
2649 vty_out(vty, "ip nht resolve-via-default\n");
2650
2651 if (zebra_rnh_ipv6_default_route)
2652 vty_out(vty, "ipv6 nht resolve-via-default\n");
2653
2654 enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get();
2655
2656 if (ipv4_multicast_mode != MCAST_NO_CONFIG)
2657 vty_out(vty, "ip multicast rpf-lookup-mode %s\n",
2658 ipv4_multicast_mode == MCAST_URIB_ONLY
2659 ? "urib-only"
2660 : ipv4_multicast_mode == MCAST_MRIB_ONLY
2661 ? "mrib-only"
2662 : ipv4_multicast_mode
2663 == MCAST_MIX_MRIB_FIRST
2664 ? "mrib-then-urib"
2665 : ipv4_multicast_mode
2666 == MCAST_MIX_DISTANCE
2667 ? "lower-distance"
2668 : "longer-prefix");
2669
2670 zebra_routemap_config_write_protocol(vty);
2671
2672 return 1;
2673 }
2674
2675 /* IP node for static routes. */
2676 static struct cmd_node ip_node = {IP_NODE, "", 1};
2677 static struct cmd_node protocol_node = {PROTOCOL_NODE, "", 1};
2678
2679 /* Route VTY. */
2680 void zebra_vty_init(void)
2681 {
2682 install_node(&ip_node, zebra_ip_config);
2683 install_node(&protocol_node, config_write_protocol);
2684
2685 install_element(CONFIG_NODE, &allow_external_route_update_cmd);
2686 install_element(CONFIG_NODE, &no_allow_external_route_update_cmd);
2687 install_element(CONFIG_NODE, &ip_mroute_dist_cmd);
2688 install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
2689 install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
2690 install_element(CONFIG_NODE, &ip_route_cmd);
2691 install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
2692 install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
2693
2694 install_element(VIEW_NODE, &show_vrf_cmd);
2695 install_element(VIEW_NODE, &show_ip_route_cmd);
2696 install_element(VIEW_NODE, &show_ip_nht_cmd);
2697 install_element(VIEW_NODE, &show_ip_nht_vrf_all_cmd);
2698 install_element(VIEW_NODE, &show_ipv6_nht_cmd);
2699 install_element(VIEW_NODE, &show_ipv6_nht_vrf_all_cmd);
2700 install_element(VIEW_NODE, &show_ip_route_addr_cmd);
2701 install_element(VIEW_NODE, &show_ip_route_prefix_cmd);
2702 install_element(VIEW_NODE, &show_ip_route_summary_cmd);
2703 install_element(VIEW_NODE, &show_ip_route_summary_prefix_cmd);
2704
2705 install_element(VIEW_NODE, &show_ip_rpf_cmd);
2706 install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
2707
2708 install_element(VIEW_NODE, &show_ip_route_vrf_all_addr_cmd);
2709 install_element(VIEW_NODE, &show_ip_route_vrf_all_prefix_cmd);
2710 install_element(VIEW_NODE, &show_ip_route_vrf_all_summary_cmd);
2711 install_element(VIEW_NODE, &show_ip_route_vrf_all_summary_prefix_cmd);
2712
2713 install_element(CONFIG_NODE, &ipv6_route_cmd);
2714 install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
2715 install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
2716 install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
2717 install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd);
2718 install_element(VIEW_NODE, &show_ipv6_route_cmd);
2719 install_element(VIEW_NODE, &show_ipv6_route_summary_cmd);
2720 install_element(VIEW_NODE, &show_ipv6_route_summary_prefix_cmd);
2721 install_element(VIEW_NODE, &show_ipv6_route_addr_cmd);
2722 install_element(VIEW_NODE, &show_ipv6_route_prefix_cmd);
2723 install_element(VIEW_NODE, &show_ipv6_mroute_cmd);
2724
2725 /* Commands for VRF */
2726 install_element(VIEW_NODE, &show_ipv6_route_vrf_all_summary_cmd);
2727 install_element(VIEW_NODE, &show_ipv6_route_vrf_all_summary_prefix_cmd);
2728 install_element(VIEW_NODE, &show_ipv6_route_vrf_all_addr_cmd);
2729 install_element(VIEW_NODE, &show_ipv6_route_vrf_all_prefix_cmd);
2730
2731 install_element(VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd);
2732
2733 install_element(VIEW_NODE, &show_evpn_vni_cmd);
2734 install_element(VIEW_NODE, &show_evpn_vni_vni_cmd);
2735 install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
2736 install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
2737 install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
2738 install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
2739 install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
2740 install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
2741 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
2742 install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
2743 install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
2744 }