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