]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vty.c
Merge pull request #2728 from donaldsharp/table_cleanup
[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 "linklist.h"
33 #include "mpls.h"
34 #include "routemap.h"
35 #include "srcdest_table.h"
36 #include "vxlan.h"
37
38 #include "zebra/zserv.h"
39 #include "zebra/zebra_vrf.h"
40 #include "zebra/zebra_mpls.h"
41 #include "zebra/zebra_rnh.h"
42 #include "zebra/redistribute.h"
43 #include "zebra/zebra_routemap.h"
44 #include "zebra/zebra_static.h"
45 #include "lib/json.h"
46 #include "zebra/zebra_vxlan.h"
47 #ifndef VTYSH_EXTRACT_PL
48 #include "zebra/zebra_vty_clippy.c"
49 #endif
50 #include "zebra/zserv.h"
51 #include "zebra/router-id.h"
52 #include "zebra/ipforward.h"
53 #include "zebra/zebra_vxlan_private.h"
54 #include "zebra/zebra_pbr.h"
55
56 extern int allow_delete;
57
58 static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
59 safi_t safi, bool use_fib, uint8_t use_json,
60 route_tag_t tag,
61 const struct prefix *longer_prefix_p,
62 bool supernets_only, int type,
63 unsigned short ospf_instance_id);
64 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
65 int mcast);
66 static void vty_show_ip_route_summary(struct vty *vty,
67 struct route_table *table);
68 static void vty_show_ip_route_summary_prefix(struct vty *vty,
69 struct route_table *table);
70
71 /*
72 * special macro to allow us to get the correct zebra_vrf
73 */
74 #define ZEBRA_DECLVAR_CONTEXT(A, B) \
75 struct vrf *A = VTY_GET_CONTEXT(vrf); \
76 struct zebra_vrf *B = (vrf) ? vrf->info : NULL;
77
78 /* VNI range as per RFC 7432 */
79 #define CMD_VNI_RANGE "(1-16777215)"
80
81 struct static_hold_route {
82 char *vrf_name;
83 char *nhvrf_name;
84 afi_t afi;
85 safi_t safi;
86 char *dest_str;
87 char *mask_str;
88 char *src_str;
89 char *gate_str;
90 char *ifname;
91 char *flag_str;
92 char *tag_str;
93 char *distance_str;
94 char *label_str;
95 char *table_str;
96
97 /* processed & masked destination, used for config display */
98 struct prefix dest;
99 };
100
101 static struct list *static_list;
102
103 static int static_list_compare_helper(const char *s1, const char *s2)
104 {
105 /* Are Both NULL */
106 if (s1 == s2)
107 return 0;
108
109 if (!s1 && s2)
110 return -1;
111
112 if (s1 && !s2)
113 return 1;
114
115 return strcmp(s1, s2);
116 }
117
118 static void static_list_delete(struct static_hold_route *shr)
119 {
120 if (shr->vrf_name)
121 XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name);
122 if (shr->nhvrf_name)
123 XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name);
124 if (shr->dest_str)
125 XFREE(MTYPE_STATIC_ROUTE, shr->dest_str);
126 if (shr->mask_str)
127 XFREE(MTYPE_STATIC_ROUTE, shr->mask_str);
128 if (shr->src_str)
129 XFREE(MTYPE_STATIC_ROUTE, shr->src_str);
130 if (shr->gate_str)
131 XFREE(MTYPE_STATIC_ROUTE, shr->gate_str);
132 if (shr->ifname)
133 XFREE(MTYPE_STATIC_ROUTE, shr->ifname);
134 if (shr->flag_str)
135 XFREE(MTYPE_STATIC_ROUTE, shr->flag_str);
136 if (shr->tag_str)
137 XFREE(MTYPE_STATIC_ROUTE, shr->tag_str);
138 if (shr->distance_str)
139 XFREE(MTYPE_STATIC_ROUTE, shr->distance_str);
140 if (shr->label_str)
141 XFREE(MTYPE_STATIC_ROUTE, shr->label_str);
142
143 XFREE(MTYPE_STATIC_ROUTE, shr);
144 }
145
146 static int static_list_compare(void *arg1, void *arg2)
147 {
148 struct static_hold_route *shr1 = arg1;
149 struct static_hold_route *shr2 = arg2;
150 int ret;
151
152 ret = strcmp(shr1->vrf_name, shr2->vrf_name);
153 if (ret)
154 return ret;
155
156 ret = strcmp(shr1->nhvrf_name, shr2->nhvrf_name);
157 if (ret)
158 return ret;
159
160 ret = shr1->afi - shr2->afi;
161 if (ret)
162 return ret;
163
164 ret = shr1->safi - shr2->safi;
165 if (ret)
166 return ret;
167
168 ret = prefix_cmp(&shr1->dest, &shr2->dest);
169 if (ret)
170 return ret;
171
172 ret = static_list_compare_helper(shr1->src_str, shr2->src_str);
173 if (ret)
174 return ret;
175
176 ret = static_list_compare_helper(shr1->gate_str, shr2->gate_str);
177 if (ret)
178 return ret;
179
180 ret = static_list_compare_helper(shr1->ifname, shr2->ifname);
181 if (ret)
182 return ret;
183
184 ret = static_list_compare_helper(shr1->flag_str, shr2->flag_str);
185 if (ret)
186 return ret;
187
188 ret = static_list_compare_helper(shr1->tag_str, shr2->tag_str);
189 if (ret)
190 return ret;
191
192 ret = static_list_compare_helper(shr1->distance_str,
193 shr2->distance_str);
194 if (ret)
195 return ret;
196
197 ret = static_list_compare_helper(shr1->table_str,
198 shr2->table_str);
199 if (ret)
200 return ret;
201
202 return static_list_compare_helper(shr1->label_str, shr2->label_str);
203 }
204
205
206 /* General function for static route. */
207 static int zebra_static_route_holdem(
208 struct zebra_vrf *zvrf, struct zebra_vrf *nh_zvrf, afi_t afi,
209 safi_t safi, const char *negate, struct prefix *dest,
210 const char *dest_str, const char *mask_str, const char *src_str,
211 const char *gate_str, const char *ifname, const char *flag_str,
212 const char *tag_str, const char *distance_str, const char *label_str,
213 const char *table_str)
214 {
215 struct static_hold_route *shr, *lookup;
216 struct listnode *node;
217
218 zlog_warn("Static Route to %s not installed currently because dependent config not fully available",
219 dest_str);
220
221 shr = XCALLOC(MTYPE_STATIC_ROUTE, sizeof(*shr));
222 shr->vrf_name = XSTRDUP(MTYPE_STATIC_ROUTE, zvrf->vrf->name);
223 shr->nhvrf_name = XSTRDUP(MTYPE_STATIC_ROUTE, nh_zvrf->vrf->name);
224 shr->afi = afi;
225 shr->safi = safi;
226 if (dest)
227 prefix_copy(&shr->dest, dest);
228 if (dest_str)
229 shr->dest_str = XSTRDUP(MTYPE_STATIC_ROUTE, dest_str);
230 if (mask_str)
231 shr->mask_str = XSTRDUP(MTYPE_STATIC_ROUTE, mask_str);
232 if (src_str)
233 shr->src_str = XSTRDUP(MTYPE_STATIC_ROUTE, src_str);
234 if (gate_str)
235 shr->gate_str = XSTRDUP(MTYPE_STATIC_ROUTE, gate_str);
236 if (ifname)
237 shr->ifname = XSTRDUP(MTYPE_STATIC_ROUTE, ifname);
238 if (flag_str)
239 shr->flag_str = XSTRDUP(MTYPE_STATIC_ROUTE, flag_str);
240 if (tag_str)
241 shr->tag_str = XSTRDUP(MTYPE_STATIC_ROUTE, tag_str);
242 if (distance_str)
243 shr->distance_str = XSTRDUP(MTYPE_STATIC_ROUTE, distance_str);
244 if (label_str)
245 shr->label_str = XSTRDUP(MTYPE_STATIC_ROUTE, label_str);
246 if (table_str)
247 shr->table_str = XSTRDUP(MTYPE_STATIC_ROUTE, table_str);
248
249 for (ALL_LIST_ELEMENTS_RO(static_list, node, lookup)) {
250 if (static_list_compare(shr, lookup) == 0)
251 break;
252 }
253
254 if (lookup) {
255 if (negate) {
256 listnode_delete(static_list, lookup);
257 static_list_delete(shr);
258 static_list_delete(lookup);
259
260 return CMD_SUCCESS;
261 }
262
263 /*
264 * If a person enters the same line again
265 * we need to silently accept it
266 */
267 goto shr_cleanup;
268 }
269
270 if (!negate) {
271 listnode_add_sort(static_list, shr);
272 return CMD_SUCCESS;
273 }
274
275 shr_cleanup:
276 XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name);
277 XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name);
278 XFREE(MTYPE_STATIC_ROUTE, shr);
279
280 return CMD_SUCCESS;
281 }
282
283 static int zebra_static_route_leak(
284 struct vty *vty, struct zebra_vrf *zvrf, struct zebra_vrf *nh_zvrf,
285 afi_t afi, safi_t safi, const char *negate, const char *dest_str,
286 const char *mask_str, const char *src_str, const char *gate_str,
287 const char *ifname, const char *flag_str, const char *tag_str,
288 const char *distance_str, const char *label_str, const char *table_str)
289 {
290 int ret;
291 uint8_t distance;
292 struct prefix p, src;
293 struct prefix_ipv6 *src_p = NULL;
294 union g_addr gate;
295 union g_addr *gatep = NULL;
296 struct in_addr mask;
297 enum static_blackhole_type bh_type = 0;
298 route_tag_t tag = 0;
299 uint8_t type;
300 struct static_nh_label snh_label;
301 uint32_t table_id = 0;
302
303 ret = str2prefix(dest_str, &p);
304 if (ret <= 0) {
305 if (vty)
306 vty_out(vty, "%% Malformed address\n");
307 else
308 zlog_warn("%s: Malformed address: %s",
309 __PRETTY_FUNCTION__, dest_str);
310 return CMD_WARNING_CONFIG_FAILED;
311 }
312
313 switch (afi) {
314 case AFI_IP:
315 /* Cisco like mask notation. */
316 if (mask_str) {
317 ret = inet_aton(mask_str, &mask);
318 if (ret == 0) {
319 if (vty)
320 vty_out(vty, "%% Malformed address\n");
321 else
322 zlog_warn("%s: Malformed address: %s",
323 __PRETTY_FUNCTION__,
324 mask_str);
325 return CMD_WARNING_CONFIG_FAILED;
326 }
327 p.prefixlen = ip_masklen(mask);
328 }
329 break;
330 case AFI_IP6:
331 /* srcdest routing */
332 if (src_str) {
333 ret = str2prefix(src_str, &src);
334 if (ret <= 0 || src.family != AF_INET6) {
335 if (vty)
336 vty_out(vty,
337 "%% Malformed source address\n");
338 else
339 zlog_warn(
340 "%s: Malformed Source address: %s",
341 __PRETTY_FUNCTION__, src_str);
342 return CMD_WARNING_CONFIG_FAILED;
343 }
344 src_p = (struct prefix_ipv6 *)&src;
345 }
346 break;
347 default:
348 break;
349 }
350
351 /* Apply mask for given prefix. */
352 apply_mask(&p);
353
354 if (zvrf->vrf->vrf_id == VRF_UNKNOWN
355 || nh_zvrf->vrf->vrf_id == VRF_UNKNOWN) {
356 vrf_set_user_cfged(zvrf->vrf);
357 return zebra_static_route_holdem(
358 zvrf, nh_zvrf, afi, safi, negate, &p, dest_str,
359 mask_str, src_str, gate_str, ifname, flag_str, tag_str,
360 distance_str, label_str, table_str);
361 }
362 if (table_str) {
363 /* table configured. check consistent with vrf config
364 */
365 if (zvrf->table_id != RT_TABLE_MAIN &&
366 zvrf->table_id != zebrad.rtm_table_default) {
367 if (vty)
368 vty_out(vty,
369 "%% Table %s overlaps vrf table %u\n",
370 table_str, zvrf->table_id);
371 else
372 zlog_warn(
373 "%s: Table %s overlaps vrf table %u",
374 __PRETTY_FUNCTION__,
375 table_str, zvrf->table_id);
376 return CMD_WARNING_CONFIG_FAILED;
377 }
378 }
379
380 /* Administrative distance. */
381 if (distance_str)
382 distance = atoi(distance_str);
383 else
384 distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
385
386 /* tag */
387 if (tag_str)
388 tag = strtoul(tag_str, NULL, 10);
389
390 /* Labels */
391 memset(&snh_label, 0, sizeof(struct static_nh_label));
392 if (label_str) {
393 if (!mpls_enabled) {
394 if (vty)
395 vty_out(vty,
396 "%% MPLS not turned on in kernel, ignoring command\n");
397 else
398 zlog_warn(
399 "%s: MPLS not turned on in kernel ignoring static route to %s",
400 __PRETTY_FUNCTION__, dest_str);
401 return CMD_WARNING_CONFIG_FAILED;
402 }
403 int rc = mpls_str2label(label_str, &snh_label.num_labels,
404 snh_label.label);
405 if (rc < 0) {
406 switch (rc) {
407 case -1:
408 if (vty)
409 vty_out(vty, "%% Malformed label(s)\n");
410 else
411 zlog_warn(
412 "%s: Malformed labels specified for route %s",
413 __PRETTY_FUNCTION__, dest_str);
414 break;
415 case -2:
416 if (vty)
417 vty_out(vty,
418 "%% Cannot use reserved label(s) (%d-%d)\n",
419 MPLS_LABEL_RESERVED_MIN,
420 MPLS_LABEL_RESERVED_MAX);
421 else
422 zlog_warn(
423 "%s: Cannot use reserved labels (%d-%d) for %s",
424 __PRETTY_FUNCTION__,
425 MPLS_LABEL_RESERVED_MIN,
426 MPLS_LABEL_RESERVED_MAX,
427 dest_str);
428 break;
429 case -3:
430 if (vty)
431 vty_out(vty,
432 "%% Too many labels. Enter %d or fewer\n",
433 MPLS_MAX_LABELS);
434 else
435 zlog_warn(
436 "%s: Too many labels, Enter %d or fewer for %s",
437 __PRETTY_FUNCTION__,
438 MPLS_MAX_LABELS, dest_str);
439 break;
440 }
441 return CMD_WARNING_CONFIG_FAILED;
442 }
443 }
444 /* TableID */
445 if (table_str)
446 table_id = atol(table_str);
447
448 /* Null0 static route. */
449 if (ifname != NULL) {
450 if (strncasecmp(ifname, "Null0", strlen(ifname)) == 0
451 || strncasecmp(ifname, "reject", strlen(ifname)) == 0
452 || strncasecmp(ifname, "blackhole", strlen(ifname)) == 0) {
453 if (vty)
454 vty_out(vty,
455 "%% Nexthop interface cannot be Null0, reject or blackhole\n");
456 else
457 zlog_warn(
458 "%s: Nexthop interface cannot be Null0, reject or blackhole for %s",
459 __PRETTY_FUNCTION__, dest_str);
460 return CMD_WARNING_CONFIG_FAILED;
461 }
462 }
463
464 /* Route flags */
465 if (flag_str) {
466 switch (flag_str[0]) {
467 case 'r':
468 bh_type = STATIC_BLACKHOLE_REJECT;
469 break;
470 case 'b':
471 bh_type = STATIC_BLACKHOLE_DROP;
472 break;
473 case 'N':
474 bh_type = STATIC_BLACKHOLE_NULL;
475 break;
476 default:
477 if (vty)
478 vty_out(vty, "%% Malformed flag %s \n",
479 flag_str);
480 else
481 zlog_warn("%s: Malformed flag %s for %s",
482 __PRETTY_FUNCTION__, flag_str,
483 dest_str);
484 return CMD_WARNING_CONFIG_FAILED;
485 }
486 }
487
488 if (gate_str) {
489 if (inet_pton(afi2family(afi), gate_str, &gate) != 1) {
490 if (vty)
491 vty_out(vty,
492 "%% Malformed nexthop address %s\n",
493 gate_str);
494 else
495 zlog_warn(
496 "%s: Malformed nexthop address %s for %s",
497 __PRETTY_FUNCTION__, gate_str,
498 dest_str);
499 return CMD_WARNING_CONFIG_FAILED;
500 }
501 gatep = &gate;
502 }
503
504 if (gate_str == NULL && ifname == NULL)
505 type = STATIC_BLACKHOLE;
506 else if (gate_str && ifname) {
507 if (afi == AFI_IP)
508 type = STATIC_IPV4_GATEWAY_IFNAME;
509 else
510 type = STATIC_IPV6_GATEWAY_IFNAME;
511 } else if (ifname)
512 type = STATIC_IFNAME;
513 else {
514 if (afi == AFI_IP)
515 type = STATIC_IPV4_GATEWAY;
516 else
517 type = STATIC_IPV6_GATEWAY;
518 }
519
520 if (!negate) {
521 static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
522 bh_type, tag, distance, zvrf, nh_zvrf,
523 &snh_label, table_id);
524 /* Mark as having FRR configuration */
525 vrf_set_user_cfged(zvrf->vrf);
526 } else {
527 static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
528 tag, distance, zvrf, &snh_label, table_id);
529 /* If no other FRR config for this VRF, mark accordingly. */
530 if (!zebra_vrf_has_config(zvrf))
531 vrf_reset_user_cfged(zvrf->vrf);
532 }
533
534 return CMD_SUCCESS;
535 }
536
537 static struct zebra_vrf *zebra_vty_get_unknown_vrf(struct vty *vty,
538 const char *vrf_name)
539 {
540 struct zebra_vrf *zvrf;
541 struct vrf *vrf;
542
543 zvrf = zebra_vrf_lookup_by_name(vrf_name);
544
545 if (zvrf)
546 return zvrf;
547
548 vrf = vrf_get(VRF_UNKNOWN, vrf_name);
549 if (!vrf) {
550 vty_out(vty, "%% Could not create vrf %s\n", vrf_name);
551 return NULL;
552 }
553 zvrf = vrf->info;
554 if (!zvrf) {
555 vty_out(vty, "%% Could not create vrf-info %s\n",
556 vrf_name);
557 return NULL;
558 }
559 /* Mark as having FRR configuration */
560 vrf_set_user_cfged(vrf);
561
562 return zvrf;
563 }
564
565 static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
566 const char *negate, const char *dest_str,
567 const char *mask_str, const char *src_str,
568 const char *gate_str, const char *ifname,
569 const char *flag_str, const char *tag_str,
570 const char *distance_str, const char *vrf_name,
571 const char *label_str, const char *table_str)
572 {
573 struct zebra_vrf *zvrf;
574
575 /* VRF id */
576 zvrf = zebra_vrf_lookup_by_name(vrf_name);
577
578 /* When trying to delete, the VRF must exist. */
579 if (negate && !zvrf) {
580 vty_out(vty, "%% vrf %s is not defined\n", vrf_name);
581 return CMD_WARNING_CONFIG_FAILED;
582 }
583
584 /* When trying to create, create the VRF if it doesn't exist.
585 * Note: The VRF isn't active until we hear about it from the kernel.
586 */
587 if (!zvrf) {
588 zvrf = zebra_vty_get_unknown_vrf(vty, vrf_name);
589 if (!zvrf)
590 return CMD_WARNING_CONFIG_FAILED;
591 }
592 return zebra_static_route_leak(
593 vty, zvrf, zvrf, afi, safi, negate, dest_str, mask_str, src_str,
594 gate_str, ifname, flag_str, tag_str, distance_str, label_str,
595 table_str);
596 }
597
598 void static_config_install_delayed_routes(struct zebra_vrf *zvrf)
599 {
600 struct listnode *node, *nnode;
601 struct static_hold_route *shr;
602 struct zebra_vrf *ozvrf, *nh_zvrf;
603 int installed;
604
605 for (ALL_LIST_ELEMENTS(static_list, node, nnode, shr)) {
606 ozvrf = zebra_vrf_lookup_by_name(shr->vrf_name);
607 nh_zvrf = zebra_vrf_lookup_by_name(shr->nhvrf_name);
608
609 if (ozvrf != zvrf && nh_zvrf != zvrf)
610 continue;
611
612 if (ozvrf->vrf->vrf_id == VRF_UNKNOWN
613 || nh_zvrf->vrf->vrf_id == VRF_UNKNOWN)
614 continue;
615
616 installed = zebra_static_route_leak(
617 NULL, ozvrf, nh_zvrf, shr->afi, shr->safi, NULL,
618 shr->dest_str, shr->mask_str, shr->src_str,
619 shr->gate_str, shr->ifname, shr->flag_str, shr->tag_str,
620 shr->distance_str, shr->label_str, shr->table_str);
621
622 if (installed != CMD_SUCCESS)
623 zlog_debug(
624 "%s: Attempt to install %s as a route and it was rejected",
625 __PRETTY_FUNCTION__, shr->dest_str);
626 listnode_delete(static_list, shr);
627 static_list_delete(shr);
628 }
629 }
630 /* Static unicast routes for multicast RPF lookup. */
631 DEFPY (ip_mroute_dist,
632 ip_mroute_dist_cmd,
633 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
634 NO_STR
635 IP_STR
636 "Configure static unicast route into MRIB for multicast RPF lookup\n"
637 "IP destination prefix (e.g. 10.0.0.0/8)\n"
638 "Nexthop address\n"
639 "Nexthop interface name\n"
640 "Distance\n")
641 {
642 return zebra_static_route(vty, AFI_IP, SAFI_MULTICAST, no, prefix_str,
643 NULL, NULL, gate_str, ifname, NULL, NULL,
644 distance_str, NULL, NULL, NULL);
645 }
646
647 DEFUN (ip_multicast_mode,
648 ip_multicast_mode_cmd,
649 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
650 IP_STR
651 "Multicast options\n"
652 "RPF lookup behavior\n"
653 "Lookup in unicast RIB only\n"
654 "Lookup in multicast RIB only\n"
655 "Try multicast RIB first, fall back to unicast RIB\n"
656 "Lookup both, use entry with lower distance\n"
657 "Lookup both, use entry with longer prefix\n")
658 {
659 char *mode = argv[3]->text;
660
661 if (strmatch(mode, "urib-only"))
662 multicast_mode_ipv4_set(MCAST_URIB_ONLY);
663 else if (strmatch(mode, "mrib-only"))
664 multicast_mode_ipv4_set(MCAST_MRIB_ONLY);
665 else if (strmatch(mode, "mrib-then-urib"))
666 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST);
667 else if (strmatch(mode, "lower-distance"))
668 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE);
669 else if (strmatch(mode, "longer-prefix"))
670 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN);
671 else {
672 vty_out(vty, "Invalid mode specified\n");
673 return CMD_WARNING_CONFIG_FAILED;
674 }
675
676 return CMD_SUCCESS;
677 }
678
679 DEFUN (no_ip_multicast_mode,
680 no_ip_multicast_mode_cmd,
681 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
682 NO_STR
683 IP_STR
684 "Multicast options\n"
685 "RPF lookup behavior\n"
686 "Lookup in unicast RIB only\n"
687 "Lookup in multicast RIB only\n"
688 "Try multicast RIB first, fall back to unicast RIB\n"
689 "Lookup both, use entry with lower distance\n"
690 "Lookup both, use entry with longer prefix\n")
691 {
692 multicast_mode_ipv4_set(MCAST_NO_CONFIG);
693 return CMD_SUCCESS;
694 }
695
696
697 DEFUN (show_ip_rpf,
698 show_ip_rpf_cmd,
699 "show ip rpf [json]",
700 SHOW_STR
701 IP_STR
702 "Display RPF information for multicast source\n"
703 JSON_STR)
704 {
705 int uj = use_json(argc, argv);
706 return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST,
707 false, uj, 0, NULL, false, 0, 0);
708 }
709
710 DEFUN (show_ip_rpf_addr,
711 show_ip_rpf_addr_cmd,
712 "show ip rpf A.B.C.D",
713 SHOW_STR
714 IP_STR
715 "Display RPF information for multicast source\n"
716 "IP multicast source address (e.g. 10.0.0.0)\n")
717 {
718 int idx_ipv4 = 3;
719 struct in_addr addr;
720 struct route_node *rn;
721 struct route_entry *re;
722 int ret;
723
724 ret = inet_aton(argv[idx_ipv4]->arg, &addr);
725 if (ret == 0) {
726 vty_out(vty, "%% Malformed address\n");
727 return CMD_WARNING;
728 }
729
730 re = rib_match_ipv4_multicast(VRF_DEFAULT, addr, &rn);
731
732 if (re)
733 vty_show_ip_route_detail(vty, rn, 1);
734 else
735 vty_out(vty, "%% No match for RPF lookup\n");
736
737 return CMD_SUCCESS;
738 }
739
740 /* Static route configuration. */
741 DEFPY(ip_route_blackhole,
742 ip_route_blackhole_cmd,
743 "[no] ip route\
744 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
745 <reject|blackhole>$flag \
746 [{ \
747 tag (1-4294967295) \
748 |(1-255)$distance \
749 |vrf NAME \
750 |label WORD \
751 |table (1-4294967295) \
752 }]",
753 NO_STR IP_STR
754 "Establish static routes\n"
755 "IP destination prefix (e.g. 10.0.0.0/8)\n"
756 "IP destination prefix\n"
757 "IP destination prefix mask\n"
758 "Emit an ICMP unreachable when matched\n"
759 "Silently discard pkts when matched\n"
760 "Set tag for this route\n"
761 "Tag value\n"
762 "Distance value for this route\n"
763 VRF_CMD_HELP_STR
764 MPLS_LABEL_HELPSTR
765 "Table to configure\n"
766 "The table number to configure\n")
767 {
768 if (table_str && !vrf_is_backend_netns()) {
769 vty_out(vty,
770 "%% table param only available when running on netns-based vrfs\n");
771 return CMD_WARNING_CONFIG_FAILED;
772 }
773 return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
774 mask_str, NULL, NULL, NULL, flag, tag_str,
775 distance_str, vrf, label, table_str);
776 }
777
778 DEFPY(ip_route_blackhole_vrf,
779 ip_route_blackhole_vrf_cmd,
780 "[no] ip route\
781 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
782 <reject|blackhole>$flag \
783 [{ \
784 tag (1-4294967295) \
785 |(1-255)$distance \
786 |label WORD \
787 |table (1-4294967295) \
788 }]",
789 NO_STR IP_STR
790 "Establish static routes\n"
791 "IP destination prefix (e.g. 10.0.0.0/8)\n"
792 "IP destination prefix\n"
793 "IP destination prefix mask\n"
794 "Emit an ICMP unreachable when matched\n"
795 "Silently discard pkts when matched\n"
796 "Set tag for this route\n"
797 "Tag value\n"
798 "Distance value for this route\n"
799 MPLS_LABEL_HELPSTR
800 "Table to configure\n"
801 "The table number to configure\n")
802 {
803 VTY_DECLVAR_CONTEXT(vrf, vrf);
804 struct zebra_vrf *zvrf = vrf->info;
805
806 if (table_str && !vrf_is_backend_netns()) {
807 vty_out(vty,
808 "%% table param only available when running on netns-based vrfs\n");
809 return CMD_WARNING_CONFIG_FAILED;
810 }
811 /*
812 * Coverity is complaining that prefix could
813 * be dereferenced, but we know that prefix will
814 * valid. Add an assert to make it happy
815 */
816 assert(prefix);
817 return zebra_static_route_leak(vty, zvrf, zvrf, AFI_IP, SAFI_UNICAST,
818 no, prefix, mask_str, NULL, NULL, NULL,
819 flag, tag_str, distance_str, label, table_str);
820 }
821
822 DEFPY(ip_route_address_interface,
823 ip_route_address_interface_cmd,
824 "[no] ip route\
825 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
826 A.B.C.D$gate \
827 INTERFACE$ifname \
828 [{ \
829 tag (1-4294967295) \
830 |(1-255)$distance \
831 |vrf NAME \
832 |label WORD \
833 |table (1-4294967295) \
834 |nexthop-vrf NAME \
835 }]",
836 NO_STR IP_STR
837 "Establish static routes\n"
838 "IP destination prefix (e.g. 10.0.0.0/8)\n"
839 "IP destination prefix\n"
840 "IP destination prefix mask\n"
841 "IP gateway address\n"
842 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
843 null route.\n"
844 "Set tag for this route\n"
845 "Tag value\n"
846 "Distance value for this route\n"
847 VRF_CMD_HELP_STR
848 MPLS_LABEL_HELPSTR
849 "Table to configure\n"
850 "The table number to configure\n"
851 VRF_CMD_HELP_STR)
852 {
853 struct zebra_vrf *zvrf;
854 struct zebra_vrf *nh_zvrf;
855
856 const char *flag = NULL;
857 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
858 flag = "Null0";
859 ifname = NULL;
860 }
861
862 zvrf = zebra_vty_get_unknown_vrf(vty, vrf);
863 if (!zvrf) {
864 vty_out(vty, "%% vrf %s is not defined\n", vrf);
865 return CMD_WARNING_CONFIG_FAILED;
866 }
867
868 if (table_str && !vrf_is_backend_netns()) {
869 vty_out(vty,
870 "%% table param only available when running on netns-based vrfs\n");
871 return CMD_WARNING_CONFIG_FAILED;
872 }
873
874 if (nexthop_vrf)
875 nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
876 else
877 nh_zvrf = zvrf;
878
879 if (!nh_zvrf) {
880 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
881 return CMD_WARNING_CONFIG_FAILED;
882 }
883
884 return zebra_static_route_leak(
885 vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
886 NULL, gate_str, ifname, flag, tag_str, distance_str, label,
887 table_str);
888 }
889
890 DEFPY(ip_route_address_interface_vrf,
891 ip_route_address_interface_vrf_cmd,
892 "[no] ip route\
893 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
894 A.B.C.D$gate \
895 INTERFACE$ifname \
896 [{ \
897 tag (1-4294967295) \
898 |(1-255)$distance \
899 |label WORD \
900 |table (1-4294967295) \
901 |nexthop-vrf NAME \
902 }]",
903 NO_STR IP_STR
904 "Establish static routes\n"
905 "IP destination prefix (e.g. 10.0.0.0/8)\n"
906 "IP destination prefix\n"
907 "IP destination prefix mask\n"
908 "IP gateway address\n"
909 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
910 null route.\n"
911 "Set tag for this route\n"
912 "Tag value\n"
913 "Distance value for this route\n"
914 MPLS_LABEL_HELPSTR
915 "Table to configure\n"
916 "The table number to configure\n"
917 VRF_CMD_HELP_STR)
918 {
919 VTY_DECLVAR_CONTEXT(vrf, vrf);
920 const char *flag = NULL;
921 struct zebra_vrf *zvrf = vrf->info;
922 struct zebra_vrf *nh_zvrf;
923
924 if (table_str && !vrf_is_backend_netns()) {
925 vty_out(vty,
926 "%% table param only available when running on netns-based vrfs\n");
927 return CMD_WARNING_CONFIG_FAILED;
928 }
929
930 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
931 flag = "Null0";
932 ifname = NULL;
933 }
934
935 if (nexthop_vrf)
936 nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
937 else
938 nh_zvrf = zvrf;
939
940 if (!nh_zvrf) {
941 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
942 return CMD_WARNING_CONFIG_FAILED;
943 }
944
945 return zebra_static_route_leak(
946 vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
947 NULL, gate_str, ifname, flag, tag_str, distance_str, label,
948 table_str);
949 }
950
951 DEFPY(ip_route,
952 ip_route_cmd,
953 "[no] ip route\
954 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
955 <A.B.C.D$gate|INTERFACE$ifname> \
956 [{ \
957 tag (1-4294967295) \
958 |(1-255)$distance \
959 |vrf NAME \
960 |label WORD \
961 |table (1-4294967295) \
962 |nexthop-vrf NAME \
963 }]",
964 NO_STR IP_STR
965 "Establish static routes\n"
966 "IP destination prefix (e.g. 10.0.0.0/8)\n"
967 "IP destination prefix\n"
968 "IP destination prefix mask\n"
969 "IP gateway address\n"
970 "IP gateway interface name\n"
971 "Set tag for this route\n"
972 "Tag value\n"
973 "Distance value for this route\n"
974 VRF_CMD_HELP_STR
975 MPLS_LABEL_HELPSTR
976 "Table to configure\n"
977 "The table number to configure\n"
978 VRF_CMD_HELP_STR)
979 {
980 struct zebra_vrf *zvrf;
981 struct zebra_vrf *nh_zvrf;
982 const char *flag = NULL;
983
984 if (table_str && !vrf_is_backend_netns()) {
985 vty_out(vty,
986 "%% table param only available when running on netns-based vrfs\n");
987 return CMD_WARNING_CONFIG_FAILED;
988 }
989
990 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
991 flag = "Null0";
992 ifname = NULL;
993 }
994
995 zvrf = zebra_vty_get_unknown_vrf(vty, vrf);
996 if (!zvrf) {
997 vty_out(vty, "%% vrf %s is not defined\n", vrf);
998 return CMD_WARNING_CONFIG_FAILED;
999 }
1000
1001 if (nexthop_vrf)
1002 nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
1003 else
1004 nh_zvrf = zvrf;
1005
1006 if (!nh_zvrf) {
1007 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
1008 return CMD_WARNING_CONFIG_FAILED;
1009 }
1010
1011
1012 return zebra_static_route_leak(
1013 vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
1014 NULL, gate_str, ifname, flag, tag_str, distance_str, label,
1015 table_str);
1016 }
1017
1018 DEFPY(ip_route_vrf,
1019 ip_route_vrf_cmd,
1020 "[no] ip route\
1021 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
1022 <A.B.C.D$gate|INTERFACE$ifname> \
1023 [{ \
1024 tag (1-4294967295) \
1025 |(1-255)$distance \
1026 |label WORD \
1027 |table (1-4294967295) \
1028 |nexthop-vrf NAME \
1029 }]",
1030 NO_STR IP_STR
1031 "Establish static routes\n"
1032 "IP destination prefix (e.g. 10.0.0.0/8)\n"
1033 "IP destination prefix\n"
1034 "IP destination prefix mask\n"
1035 "IP gateway address\n"
1036 "IP gateway interface name\n"
1037 "Set tag for this route\n"
1038 "Tag value\n"
1039 "Distance value for this route\n"
1040 MPLS_LABEL_HELPSTR
1041 "Table to configure\n"
1042 "The table number to configure\n"
1043 VRF_CMD_HELP_STR)
1044 {
1045 VTY_DECLVAR_CONTEXT(vrf, vrf);
1046 struct zebra_vrf *zvrf = vrf->info;
1047 struct zebra_vrf *nh_zvrf;
1048 const char *flag = NULL;
1049
1050 if (table_str && !vrf_is_backend_netns()) {
1051 vty_out(vty,
1052 "%% table param only available when running on netns-based vrfs\n");
1053 return CMD_WARNING_CONFIG_FAILED;
1054 }
1055
1056 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
1057 flag = "Null0";
1058 ifname = NULL;
1059 }
1060
1061 if (nexthop_vrf)
1062 nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
1063 else
1064 nh_zvrf = zvrf;
1065
1066 if (!nh_zvrf) {
1067 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
1068 return CMD_WARNING_CONFIG_FAILED;
1069 }
1070
1071 return zebra_static_route_leak(
1072 vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
1073 NULL, gate_str, ifname, flag, tag_str, distance_str, label,
1074 table_str);
1075 }
1076
1077 /* New RIB. Detailed information for IPv4 route. */
1078 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
1079 int mcast)
1080 {
1081 struct route_entry *re;
1082 struct nexthop *nexthop;
1083 char buf[SRCDEST2STR_BUFFER];
1084 struct zebra_vrf *zvrf;
1085
1086 RNODE_FOREACH_RE (rn, re) {
1087 const char *mcast_info = "";
1088 if (mcast) {
1089 rib_table_info_t *info = srcdest_rnode_table_info(rn);
1090 mcast_info = (info->safi == SAFI_MULTICAST)
1091 ? " using Multicast RIB"
1092 : " using Unicast RIB";
1093 }
1094
1095 vty_out(vty, "Routing entry for %s%s\n",
1096 srcdest_rnode2str(rn, buf, sizeof(buf)), mcast_info);
1097 vty_out(vty, " Known via \"%s", zebra_route_string(re->type));
1098 if (re->instance)
1099 vty_out(vty, "[%d]", re->instance);
1100 vty_out(vty, "\"");
1101 vty_out(vty, ", distance %u, metric %u", re->distance,
1102 re->metric);
1103 if (re->tag) {
1104 vty_out(vty, ", tag %u", re->tag);
1105 #if defined(SUPPORT_REALMS)
1106 if (re->tag > 0 && re->tag <= 255)
1107 vty_out(vty, "(realm)");
1108 #endif
1109 }
1110 if (re->mtu)
1111 vty_out(vty, ", mtu %u", re->mtu);
1112 if (re->vrf_id != VRF_DEFAULT) {
1113 zvrf = vrf_info_lookup(re->vrf_id);
1114 vty_out(vty, ", vrf %s", zvrf_name(zvrf));
1115 }
1116 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
1117 vty_out(vty, ", best");
1118 vty_out(vty, "\n");
1119
1120 time_t uptime;
1121 struct tm *tm;
1122
1123 uptime = time(NULL);
1124 uptime -= re->uptime;
1125 tm = gmtime(&uptime);
1126
1127 vty_out(vty, " Last update ");
1128
1129 if (uptime < ONE_DAY_SECOND)
1130 vty_out(vty, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
1131 tm->tm_sec);
1132 else if (uptime < ONE_WEEK_SECOND)
1133 vty_out(vty, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
1134 tm->tm_min);
1135 else
1136 vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7,
1137 tm->tm_yday - ((tm->tm_yday / 7) * 7),
1138 tm->tm_hour);
1139 vty_out(vty, " ago\n");
1140
1141 for (ALL_NEXTHOPS(re->ng, nexthop)) {
1142 char addrstr[32];
1143
1144 vty_out(vty, " %c%s",
1145 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
1146 ? CHECK_FLAG(nexthop->flags,
1147 NEXTHOP_FLAG_DUPLICATE)
1148 ? ' '
1149 : '*'
1150 : ' ',
1151 nexthop->rparent ? " " : "");
1152
1153 switch (nexthop->type) {
1154 case NEXTHOP_TYPE_IPV4:
1155 case NEXTHOP_TYPE_IPV4_IFINDEX:
1156 vty_out(vty, " %s",
1157 inet_ntoa(nexthop->gate.ipv4));
1158 if (nexthop->ifindex)
1159 vty_out(vty, ", via %s",
1160 ifindex2ifname(
1161 nexthop->ifindex,
1162 nexthop->vrf_id));
1163 break;
1164 case NEXTHOP_TYPE_IPV6:
1165 case NEXTHOP_TYPE_IPV6_IFINDEX:
1166 vty_out(vty, " %s",
1167 inet_ntop(AF_INET6, &nexthop->gate.ipv6,
1168 buf, sizeof buf));
1169 if (nexthop->ifindex)
1170 vty_out(vty, ", via %s",
1171 ifindex2ifname(
1172 nexthop->ifindex,
1173 nexthop->vrf_id));
1174 break;
1175 case NEXTHOP_TYPE_IFINDEX:
1176 vty_out(vty, " directly connected, %s",
1177 ifindex2ifname(nexthop->ifindex,
1178 nexthop->vrf_id));
1179 break;
1180 case NEXTHOP_TYPE_BLACKHOLE:
1181 vty_out(vty, " unreachable");
1182 switch (nexthop->bh_type) {
1183 case BLACKHOLE_REJECT:
1184 vty_out(vty, " (ICMP unreachable)");
1185 break;
1186 case BLACKHOLE_ADMINPROHIB:
1187 vty_out(vty,
1188 " (ICMP admin-prohibited)");
1189 break;
1190 case BLACKHOLE_NULL:
1191 vty_out(vty, " (blackhole)");
1192 break;
1193 case BLACKHOLE_UNSPEC:
1194 break;
1195 }
1196 break;
1197 default:
1198 break;
1199 }
1200
1201 if ((re->vrf_id != nexthop->vrf_id)
1202 && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
1203 struct vrf *vrf =
1204 vrf_lookup_by_id(nexthop->vrf_id);
1205
1206 if (vrf)
1207 vty_out(vty, "(vrf %s)", vrf->name);
1208 else
1209 vty_out(vty, "(vrf UKNOWN)");
1210 }
1211
1212 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
1213 vty_out(vty, " (duplicate nexthop removed)");
1214
1215 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1216 vty_out(vty, " inactive");
1217
1218 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1219 vty_out(vty, " onlink");
1220
1221 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1222 vty_out(vty, " (recursive)");
1223
1224 switch (nexthop->type) {
1225 case NEXTHOP_TYPE_IPV4:
1226 case NEXTHOP_TYPE_IPV4_IFINDEX:
1227 if (nexthop->src.ipv4.s_addr) {
1228 if (inet_ntop(AF_INET,
1229 &nexthop->src.ipv4,
1230 addrstr, sizeof addrstr))
1231 vty_out(vty, ", src %s",
1232 addrstr);
1233 }
1234 break;
1235 case NEXTHOP_TYPE_IPV6:
1236 case NEXTHOP_TYPE_IPV6_IFINDEX:
1237 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
1238 &in6addr_any)) {
1239 if (inet_ntop(AF_INET6,
1240 &nexthop->src.ipv6,
1241 addrstr, sizeof addrstr))
1242 vty_out(vty, ", src %s",
1243 addrstr);
1244 }
1245 break;
1246 default:
1247 break;
1248 }
1249
1250 if (re->nexthop_mtu)
1251 vty_out(vty, ", mtu %u", re->nexthop_mtu);
1252
1253 /* Label information */
1254 if (nexthop->nh_label
1255 && nexthop->nh_label->num_labels) {
1256 vty_out(vty, ", label %s",
1257 mpls_label2str(
1258 nexthop->nh_label->num_labels,
1259 nexthop->nh_label->label, buf,
1260 sizeof buf, 1));
1261 }
1262
1263 vty_out(vty, "\n");
1264 }
1265 vty_out(vty, "\n");
1266 }
1267 }
1268
1269 static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
1270 struct route_entry *re, json_object *json)
1271 {
1272 struct nexthop *nexthop;
1273 int len = 0;
1274 char buf[SRCDEST2STR_BUFFER];
1275 json_object *json_nexthops = NULL;
1276 json_object *json_nexthop = NULL;
1277 json_object *json_route = NULL;
1278 json_object *json_labels = NULL;
1279 time_t uptime;
1280 struct tm *tm;
1281
1282 uptime = time(NULL);
1283 uptime -= re->uptime;
1284 tm = gmtime(&uptime);
1285
1286 if (json) {
1287 json_route = json_object_new_object();
1288 json_nexthops = json_object_new_array();
1289
1290 json_object_string_add(json_route, "prefix",
1291 srcdest_rnode2str(rn, buf, sizeof buf));
1292 json_object_string_add(json_route, "protocol",
1293 zebra_route_string(re->type));
1294
1295 if (re->instance)
1296 json_object_int_add(json_route, "instance",
1297 re->instance);
1298
1299 if (re->vrf_id)
1300 json_object_int_add(json_route, "vrfId", re->vrf_id);
1301
1302 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
1303 json_object_boolean_true_add(json_route, "selected");
1304
1305 if (re->type != ZEBRA_ROUTE_CONNECT) {
1306 json_object_int_add(json_route, "distance",
1307 re->distance);
1308 json_object_int_add(json_route, "metric", re->metric);
1309 }
1310
1311 json_object_int_add(json_route, "internalStatus",
1312 re->status);
1313 json_object_int_add(json_route, "internalFlags",
1314 re->flags);
1315 if (uptime < ONE_DAY_SECOND)
1316 sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
1317 tm->tm_sec);
1318 else if (uptime < ONE_WEEK_SECOND)
1319 sprintf(buf, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
1320 tm->tm_min);
1321 else
1322 sprintf(buf, "%02dw%dd%02dh", tm->tm_yday / 7,
1323 tm->tm_yday - ((tm->tm_yday / 7) * 7),
1324 tm->tm_hour);
1325
1326 json_object_string_add(json_route, "uptime", buf);
1327
1328 for (ALL_NEXTHOPS(re->ng, nexthop)) {
1329 json_nexthop = json_object_new_object();
1330
1331 json_object_int_add(json_nexthop, "flags",
1332 nexthop->flags);
1333
1334 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
1335 json_object_boolean_true_add(json_nexthop,
1336 "duplicate");
1337
1338 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
1339 json_object_boolean_true_add(json_nexthop,
1340 "fib");
1341
1342 switch (nexthop->type) {
1343 case NEXTHOP_TYPE_IPV4:
1344 case NEXTHOP_TYPE_IPV4_IFINDEX:
1345 json_object_string_add(
1346 json_nexthop, "ip",
1347 inet_ntoa(nexthop->gate.ipv4));
1348 json_object_string_add(json_nexthop, "afi",
1349 "ipv4");
1350
1351 if (nexthop->ifindex) {
1352 json_object_int_add(json_nexthop,
1353 "interfaceIndex",
1354 nexthop->ifindex);
1355 json_object_string_add(
1356 json_nexthop, "interfaceName",
1357 ifindex2ifname(
1358 nexthop->ifindex,
1359 nexthop->vrf_id));
1360 }
1361 break;
1362 case NEXTHOP_TYPE_IPV6:
1363 case NEXTHOP_TYPE_IPV6_IFINDEX:
1364 json_object_string_add(
1365 json_nexthop, "ip",
1366 inet_ntop(AF_INET6, &nexthop->gate.ipv6,
1367 buf, sizeof buf));
1368 json_object_string_add(json_nexthop, "afi",
1369 "ipv6");
1370
1371 if (nexthop->ifindex) {
1372 json_object_int_add(json_nexthop,
1373 "interfaceIndex",
1374 nexthop->ifindex);
1375 json_object_string_add(
1376 json_nexthop, "interfaceName",
1377 ifindex2ifname(
1378 nexthop->ifindex,
1379 nexthop->vrf_id));
1380 }
1381 break;
1382
1383 case NEXTHOP_TYPE_IFINDEX:
1384 json_object_boolean_true_add(
1385 json_nexthop, "directlyConnected");
1386 json_object_int_add(json_nexthop,
1387 "interfaceIndex",
1388 nexthop->ifindex);
1389 json_object_string_add(
1390 json_nexthop, "interfaceName",
1391 ifindex2ifname(nexthop->ifindex,
1392 nexthop->vrf_id));
1393 break;
1394 case NEXTHOP_TYPE_BLACKHOLE:
1395 json_object_boolean_true_add(json_nexthop,
1396 "unreachable");
1397 switch (nexthop->bh_type) {
1398 case BLACKHOLE_REJECT:
1399 json_object_boolean_true_add(
1400 json_nexthop, "reject");
1401 break;
1402 case BLACKHOLE_ADMINPROHIB:
1403 json_object_boolean_true_add(
1404 json_nexthop,
1405 "admin-prohibited");
1406 break;
1407 case BLACKHOLE_NULL:
1408 json_object_boolean_true_add(
1409 json_nexthop, "blackhole");
1410 break;
1411 case BLACKHOLE_UNSPEC:
1412 break;
1413 }
1414 break;
1415 default:
1416 break;
1417 }
1418
1419 if ((nexthop->vrf_id != re->vrf_id)
1420 && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
1421 struct vrf *vrf =
1422 vrf_lookup_by_id(nexthop->vrf_id);
1423
1424 json_object_string_add(json_nexthop, "vrf",
1425 vrf->name);
1426 }
1427 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
1428 json_object_boolean_true_add(json_nexthop,
1429 "duplicate");
1430
1431 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1432 json_object_boolean_true_add(json_nexthop,
1433 "active");
1434
1435 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1436 json_object_boolean_true_add(json_nexthop,
1437 "onLink");
1438
1439 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1440 json_object_boolean_true_add(json_nexthop,
1441 "recursive");
1442
1443 switch (nexthop->type) {
1444 case NEXTHOP_TYPE_IPV4:
1445 case NEXTHOP_TYPE_IPV4_IFINDEX:
1446 if (nexthop->src.ipv4.s_addr) {
1447 if (inet_ntop(AF_INET,
1448 &nexthop->src.ipv4, buf,
1449 sizeof buf))
1450 json_object_string_add(
1451 json_nexthop, "source",
1452 buf);
1453 }
1454 break;
1455 case NEXTHOP_TYPE_IPV6:
1456 case NEXTHOP_TYPE_IPV6_IFINDEX:
1457 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
1458 &in6addr_any)) {
1459 if (inet_ntop(AF_INET6,
1460 &nexthop->src.ipv6, buf,
1461 sizeof buf))
1462 json_object_string_add(
1463 json_nexthop, "source",
1464 buf);
1465 }
1466 break;
1467 default:
1468 break;
1469 }
1470
1471 if (nexthop->nh_label
1472 && nexthop->nh_label->num_labels) {
1473 json_labels = json_object_new_array();
1474
1475 for (int label_index = 0;
1476 label_index
1477 < nexthop->nh_label->num_labels;
1478 label_index++)
1479 json_object_array_add(
1480 json_labels,
1481 json_object_new_int(
1482 nexthop->nh_label->label
1483 [label_index]));
1484
1485 json_object_object_add(json_nexthop, "labels",
1486 json_labels);
1487 }
1488
1489 json_object_array_add(json_nexthops, json_nexthop);
1490 }
1491
1492 json_object_object_add(json_route, "nexthops", json_nexthops);
1493 json_object_array_add(json, json_route);
1494 return;
1495 }
1496
1497 /* Nexthop information. */
1498 for (ALL_NEXTHOPS(re->ng, nexthop)) {
1499 if (nexthop == re->ng.nexthop) {
1500 /* Prefix information. */
1501 len = vty_out(vty, "%c", zebra_route_char(re->type));
1502 if (re->instance)
1503 len += vty_out(vty, "[%d]", re->instance);
1504 len += vty_out(
1505 vty, "%c%c %s",
1506 CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)
1507 ? '>'
1508 : ' ',
1509 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
1510 ? '*'
1511 : ' ',
1512 srcdest_rnode2str(rn, buf, sizeof buf));
1513
1514 /* Distance and metric display. */
1515 if (re->type != ZEBRA_ROUTE_CONNECT)
1516 len += vty_out(vty, " [%u/%u]", re->distance,
1517 re->metric);
1518 } else {
1519 vty_out(vty, " %c%*c",
1520 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
1521 ? CHECK_FLAG(nexthop->flags,
1522 NEXTHOP_FLAG_DUPLICATE)
1523 ? ' '
1524 : '*'
1525 : ' ',
1526 len - 3 + (2 * nexthop_level(nexthop)), ' ');
1527 }
1528
1529 switch (nexthop->type) {
1530 case NEXTHOP_TYPE_IPV4:
1531 case NEXTHOP_TYPE_IPV4_IFINDEX:
1532 vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4));
1533 if (nexthop->ifindex)
1534 vty_out(vty, ", %s",
1535 ifindex2ifname(nexthop->ifindex,
1536 nexthop->vrf_id));
1537 break;
1538 case NEXTHOP_TYPE_IPV6:
1539 case NEXTHOP_TYPE_IPV6_IFINDEX:
1540 vty_out(vty, " via %s",
1541 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
1542 sizeof buf));
1543 if (nexthop->ifindex)
1544 vty_out(vty, ", %s",
1545 ifindex2ifname(nexthop->ifindex,
1546 nexthop->vrf_id));
1547 break;
1548
1549 case NEXTHOP_TYPE_IFINDEX:
1550 vty_out(vty, " is directly connected, %s",
1551 ifindex2ifname(nexthop->ifindex,
1552 nexthop->vrf_id));
1553 break;
1554 case NEXTHOP_TYPE_BLACKHOLE:
1555 vty_out(vty, " unreachable");
1556 switch (nexthop->bh_type) {
1557 case BLACKHOLE_REJECT:
1558 vty_out(vty, " (ICMP unreachable)");
1559 break;
1560 case BLACKHOLE_ADMINPROHIB:
1561 vty_out(vty, " (ICMP admin-prohibited)");
1562 break;
1563 case BLACKHOLE_NULL:
1564 vty_out(vty, " (blackhole)");
1565 break;
1566 case BLACKHOLE_UNSPEC:
1567 break;
1568 }
1569 break;
1570 default:
1571 break;
1572 }
1573
1574 if ((nexthop->vrf_id != re->vrf_id)
1575 && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) {
1576 struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
1577
1578 if (vrf)
1579 vty_out(vty, "(vrf %s)", vrf->name);
1580 else
1581 vty_out(vty, "(vrf UKNOWN)");
1582 }
1583
1584 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1585 vty_out(vty, " inactive");
1586
1587 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1588 vty_out(vty, " onlink");
1589
1590 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1591 vty_out(vty, " (recursive)");
1592
1593 switch (nexthop->type) {
1594 case NEXTHOP_TYPE_IPV4:
1595 case NEXTHOP_TYPE_IPV4_IFINDEX:
1596 if (nexthop->src.ipv4.s_addr) {
1597 if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
1598 sizeof buf))
1599 vty_out(vty, ", src %s", buf);
1600 }
1601 break;
1602 case NEXTHOP_TYPE_IPV6:
1603 case NEXTHOP_TYPE_IPV6_IFINDEX:
1604 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
1605 if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
1606 sizeof buf))
1607 vty_out(vty, ", src %s", buf);
1608 }
1609 break;
1610 default:
1611 break;
1612 }
1613
1614 /* Label information */
1615 if (nexthop->nh_label && nexthop->nh_label->num_labels) {
1616 vty_out(vty, ", label %s",
1617 mpls_label2str(nexthop->nh_label->num_labels,
1618 nexthop->nh_label->label, buf,
1619 sizeof buf, 1));
1620 }
1621
1622 if (uptime < ONE_DAY_SECOND)
1623 vty_out(vty, ", %02d:%02d:%02d", tm->tm_hour,
1624 tm->tm_min, tm->tm_sec);
1625 else if (uptime < ONE_WEEK_SECOND)
1626 vty_out(vty, ", %dd%02dh%02dm", tm->tm_yday,
1627 tm->tm_hour, tm->tm_min);
1628 else
1629 vty_out(vty, ", %02dw%dd%02dh", tm->tm_yday / 7,
1630 tm->tm_yday - ((tm->tm_yday / 7) * 7),
1631 tm->tm_hour);
1632 vty_out(vty, "\n");
1633 }
1634 }
1635
1636 static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
1637 struct route_table *table, afi_t afi,
1638 bool use_fib, route_tag_t tag,
1639 const struct prefix *longer_prefix_p,
1640 bool supernets_only, int type,
1641 unsigned short ospf_instance_id,
1642 uint8_t use_json)
1643 {
1644 struct route_node *rn;
1645 struct route_entry *re;
1646 int first = 1;
1647 rib_dest_t *dest;
1648 json_object *json = NULL;
1649 json_object *json_prefix = NULL;
1650 uint32_t addr;
1651 char buf[BUFSIZ];
1652
1653 if (use_json)
1654 json = json_object_new_object();
1655
1656 /* Show all routes. */
1657 for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
1658 dest = rib_dest_from_rnode(rn);
1659
1660 RNODE_FOREACH_RE (rn, re) {
1661 if (use_fib && re != dest->selected_fib)
1662 continue;
1663
1664 if (tag && re->tag != tag)
1665 continue;
1666
1667 if (longer_prefix_p
1668 && !prefix_match(longer_prefix_p, &rn->p))
1669 continue;
1670
1671 /* This can only be true when the afi is IPv4 */
1672 if (supernets_only) {
1673 addr = ntohl(rn->p.u.prefix4.s_addr);
1674
1675 if (IN_CLASSC(addr) && rn->p.prefixlen >= 24)
1676 continue;
1677
1678 if (IN_CLASSB(addr) && rn->p.prefixlen >= 16)
1679 continue;
1680
1681 if (IN_CLASSA(addr) && rn->p.prefixlen >= 8)
1682 continue;
1683 }
1684
1685 if (type && re->type != type)
1686 continue;
1687
1688 if (ospf_instance_id
1689 && (re->type != ZEBRA_ROUTE_OSPF
1690 || re->instance != ospf_instance_id))
1691 continue;
1692
1693 if (use_json) {
1694 if (!json_prefix)
1695 json_prefix = json_object_new_array();
1696 } else {
1697 if (first) {
1698 if (afi == AFI_IP)
1699 vty_out(vty,
1700 SHOW_ROUTE_V4_HEADER);
1701 else
1702 vty_out(vty,
1703 SHOW_ROUTE_V6_HEADER);
1704
1705 if (zvrf_id(zvrf) != VRF_DEFAULT)
1706 vty_out(vty, "\nVRF %s:\n",
1707 zvrf_name(zvrf));
1708
1709 first = 0;
1710 }
1711 }
1712
1713 vty_show_ip_route(vty, rn, re, json_prefix);
1714 }
1715
1716 if (json_prefix) {
1717 prefix2str(&rn->p, buf, sizeof buf);
1718 json_object_object_add(json, buf, json_prefix);
1719 json_prefix = NULL;
1720 }
1721 }
1722
1723 if (use_json) {
1724 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1725 json, JSON_C_TO_STRING_PRETTY));
1726 json_object_free(json);
1727 }
1728 }
1729
1730 static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
1731 safi_t safi, bool use_fib, uint8_t use_json,
1732 route_tag_t tag,
1733 const struct prefix *longer_prefix_p,
1734 bool supernets_only, int type,
1735 unsigned short ospf_instance_id)
1736 {
1737 struct route_table *table;
1738 struct zebra_vrf *zvrf = NULL;
1739
1740 if (!(zvrf = zebra_vrf_lookup_by_name(vrf_name))) {
1741 if (use_json)
1742 vty_out(vty, "{}\n");
1743 else
1744 vty_out(vty, "vrf %s not defined\n", vrf_name);
1745 return CMD_SUCCESS;
1746 }
1747
1748 if (zvrf_id(zvrf) == VRF_UNKNOWN) {
1749 if (use_json)
1750 vty_out(vty, "{}\n");
1751 else
1752 vty_out(vty, "vrf %s inactive\n", vrf_name);
1753 return CMD_SUCCESS;
1754 }
1755
1756 table = zebra_vrf_table(afi, safi, zvrf_id(zvrf));
1757 if (!table) {
1758 if (use_json)
1759 vty_out(vty, "{}\n");
1760 return CMD_SUCCESS;
1761 }
1762
1763 do_show_route_helper(vty, zvrf, table, afi, use_fib, tag,
1764 longer_prefix_p, supernets_only, type,
1765 ospf_instance_id, use_json);
1766
1767 return CMD_SUCCESS;
1768 }
1769
1770 DEFPY (show_route_table,
1771 show_route_table_cmd,
1772 "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table [json$json]",
1773 SHOW_STR
1774 IP_STR
1775 IP6_STR
1776 "IP routing table\n"
1777 "Table to display\n"
1778 "The table number to display, if available\n"
1779 JSON_STR)
1780 {
1781 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1782 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
1783 struct route_table *t;
1784
1785 t = zebra_ns_find_table(zvrf->zns, table, afi);
1786 if (t)
1787 do_show_route_helper(vty, zvrf, t, afi, false, 0, false, false,
1788 0, 0, !!json);
1789
1790 return CMD_SUCCESS;
1791 }
1792
1793 DEFPY (show_route_table_vrf,
1794 show_route_table_vrf_cmd,
1795 "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table vrf NAME$vrf_name [json$json]",
1796 SHOW_STR
1797 IP_STR
1798 IP6_STR
1799 "IP routing table\n"
1800 "Table to display\n"
1801 "The table number to display, if available\n"
1802 VRF_CMD_HELP_STR
1803 JSON_STR)
1804 {
1805 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1806 struct zebra_vrf *zvrf;
1807 struct route_table *t;
1808 vrf_id_t vrf_id = VRF_DEFAULT;
1809
1810 if (vrf_name)
1811 VRF_GET_ID(vrf_id, vrf_name, !!json);
1812 zvrf = zebra_vrf_lookup_by_id(vrf_id);
1813
1814 t = zebra_ns_find_table(zvrf->zns, table, afi);
1815 if (t)
1816 do_show_route_helper(vty, zvrf, t, afi, false, 0, false, false,
1817 0, 0, !!json);
1818
1819 return CMD_SUCCESS;
1820 }
1821
1822 DEFUN (show_ip_nht,
1823 show_ip_nht_cmd,
1824 "show ip nht [vrf NAME]",
1825 SHOW_STR
1826 IP_STR
1827 "IP nexthop tracking table\n"
1828 VRF_CMD_HELP_STR)
1829 {
1830 int idx_vrf = 4;
1831 vrf_id_t vrf_id = VRF_DEFAULT;
1832
1833 if (argc == 5)
1834 VRF_GET_ID(vrf_id, argv[idx_vrf]->arg, false);
1835
1836 zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE);
1837 return CMD_SUCCESS;
1838 }
1839
1840
1841 DEFUN (show_ip_nht_vrf_all,
1842 show_ip_nht_vrf_all_cmd,
1843 "show ip nht vrf all",
1844 SHOW_STR
1845 IP_STR
1846 "IP nexthop tracking table\n"
1847 VRF_ALL_CMD_HELP_STR)
1848 {
1849 struct vrf *vrf;
1850 struct zebra_vrf *zvrf;
1851
1852 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
1853 if ((zvrf = vrf->info) != NULL) {
1854 vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
1855 zebra_print_rnh_table(zvrf_id(zvrf), AF_INET, vty,
1856 RNH_NEXTHOP_TYPE);
1857 }
1858
1859 return CMD_SUCCESS;
1860 }
1861
1862 DEFUN (show_ipv6_nht,
1863 show_ipv6_nht_cmd,
1864 "show ipv6 nht [vrf NAME]",
1865 SHOW_STR
1866 IPV6_STR
1867 "IPv6 nexthop tracking table\n"
1868 VRF_CMD_HELP_STR)
1869 {
1870 int idx_vrf = 4;
1871 vrf_id_t vrf_id = VRF_DEFAULT;
1872
1873 if (argc == 5)
1874 VRF_GET_ID(vrf_id, argv[idx_vrf]->arg, false);
1875
1876 zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE);
1877 return CMD_SUCCESS;
1878 }
1879
1880
1881 DEFUN (show_ipv6_nht_vrf_all,
1882 show_ipv6_nht_vrf_all_cmd,
1883 "show ipv6 nht vrf all",
1884 SHOW_STR
1885 IP_STR
1886 "IPv6 nexthop tracking table\n"
1887 VRF_ALL_CMD_HELP_STR)
1888 {
1889 struct vrf *vrf;
1890 struct zebra_vrf *zvrf;
1891
1892 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
1893 if ((zvrf = vrf->info) != NULL) {
1894 vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
1895 zebra_print_rnh_table(zvrf_id(zvrf), AF_INET6, vty,
1896 RNH_NEXTHOP_TYPE);
1897 }
1898
1899 return CMD_SUCCESS;
1900 }
1901
1902 DEFUN (ip_nht_default_route,
1903 ip_nht_default_route_cmd,
1904 "ip nht resolve-via-default",
1905 IP_STR
1906 "Filter Next Hop tracking route resolution\n"
1907 "Resolve via default route\n")
1908 {
1909 if (zebra_rnh_ip_default_route)
1910 return CMD_SUCCESS;
1911
1912 zebra_rnh_ip_default_route = 1;
1913 zebra_evaluate_rnh(VRF_DEFAULT, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1914 return CMD_SUCCESS;
1915 }
1916
1917 DEFUN (no_ip_nht_default_route,
1918 no_ip_nht_default_route_cmd,
1919 "no ip nht resolve-via-default",
1920 NO_STR
1921 IP_STR
1922 "Filter Next Hop tracking route resolution\n"
1923 "Resolve via default route\n")
1924 {
1925 if (!zebra_rnh_ip_default_route)
1926 return CMD_SUCCESS;
1927
1928 zebra_rnh_ip_default_route = 0;
1929 zebra_evaluate_rnh(VRF_DEFAULT, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1930 return CMD_SUCCESS;
1931 }
1932
1933 DEFUN (ipv6_nht_default_route,
1934 ipv6_nht_default_route_cmd,
1935 "ipv6 nht resolve-via-default",
1936 IP6_STR
1937 "Filter Next Hop tracking route resolution\n"
1938 "Resolve via default route\n")
1939 {
1940 if (zebra_rnh_ipv6_default_route)
1941 return CMD_SUCCESS;
1942
1943 zebra_rnh_ipv6_default_route = 1;
1944 zebra_evaluate_rnh(VRF_DEFAULT, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1945 return CMD_SUCCESS;
1946 }
1947
1948 DEFUN (no_ipv6_nht_default_route,
1949 no_ipv6_nht_default_route_cmd,
1950 "no ipv6 nht resolve-via-default",
1951 NO_STR
1952 IP6_STR
1953 "Filter Next Hop tracking route resolution\n"
1954 "Resolve via default route\n")
1955 {
1956 if (!zebra_rnh_ipv6_default_route)
1957 return CMD_SUCCESS;
1958
1959 zebra_rnh_ipv6_default_route = 0;
1960 zebra_evaluate_rnh(VRF_DEFAULT, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1961 return CMD_SUCCESS;
1962 }
1963
1964 DEFPY (show_route,
1965 show_route_cmd,
1966 "show\
1967 <\
1968 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1969 [{\
1970 tag (1-4294967295)\
1971 |A.B.C.D/M$prefix longer-prefixes\
1972 |supernets-only$supernets_only\
1973 }]\
1974 [<\
1975 " FRR_IP_REDIST_STR_ZEBRA "$type_str\
1976 |ospf$type_str (1-65535)$ospf_instance_id\
1977 >]\
1978 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1979 [{\
1980 tag (1-4294967295)\
1981 |X:X::X:X/M$prefix longer-prefixes\
1982 }]\
1983 [" FRR_IP6_REDIST_STR_ZEBRA "$type_str]\
1984 >\
1985 [json$json]",
1986 SHOW_STR
1987 IP_STR
1988 "IP forwarding table\n"
1989 "IP routing table\n"
1990 VRF_FULL_CMD_HELP_STR
1991 "Show only routes with tag\n"
1992 "Tag value\n"
1993 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1994 "Show route matching the specified Network/Mask pair only\n"
1995 "Show supernet entries only\n"
1996 FRR_IP_REDIST_HELP_STR_ZEBRA
1997 "Open Shortest Path First (OSPFv2)\n"
1998 "Instance ID\n"
1999 IPV6_STR
2000 "IP forwarding table\n"
2001 "IP routing table\n"
2002 VRF_FULL_CMD_HELP_STR
2003 "Show only routes with tag\n"
2004 "Tag value\n"
2005 "IPv6 prefix\n"
2006 "Show route matching the specified Network/Mask pair only\n"
2007 FRR_IP6_REDIST_HELP_STR_ZEBRA
2008 JSON_STR)
2009 {
2010 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
2011 struct vrf *vrf;
2012 int type = 0;
2013
2014 if (type_str) {
2015 type = proto_redistnum(afi, type_str);
2016 if (type < 0) {
2017 vty_out(vty, "Unknown route type\n");
2018 return CMD_WARNING;
2019 }
2020 }
2021
2022 if (vrf_all) {
2023 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2024 struct zebra_vrf *zvrf;
2025 struct route_table *table;
2026
2027 if ((zvrf = vrf->info) == NULL
2028 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
2029 continue;
2030
2031 do_show_ip_route(
2032 vty, zvrf_name(zvrf), afi, SAFI_UNICAST, !!fib,
2033 !!json, tag, prefix_str ? prefix : NULL,
2034 !!supernets_only, type, ospf_instance_id);
2035 }
2036 } else {
2037 vrf_id_t vrf_id = VRF_DEFAULT;
2038
2039 if (vrf_name)
2040 VRF_GET_ID(vrf_id, vrf_name, !!json);
2041 vrf = vrf_lookup_by_id(vrf_id);
2042 do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST, !!fib,
2043 !!json, tag, prefix_str ? prefix : NULL,
2044 !!supernets_only, type, ospf_instance_id);
2045 }
2046
2047 return CMD_SUCCESS;
2048 }
2049
2050 DEFPY (show_route_detail,
2051 show_route_detail_cmd,
2052 "show\
2053 <\
2054 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
2055 <\
2056 A.B.C.D$address\
2057 |A.B.C.D/M$prefix\
2058 >\
2059 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
2060 <\
2061 X:X::X:X$address\
2062 |X:X::X:X/M$prefix\
2063 >\
2064 >",
2065 SHOW_STR
2066 IP_STR
2067 "IP routing table\n"
2068 VRF_FULL_CMD_HELP_STR
2069 "Network in the IP routing table to display\n"
2070 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
2071 IP6_STR
2072 "IP routing table\n"
2073 VRF_FULL_CMD_HELP_STR
2074 "IPv6 Address\n"
2075 "IPv6 prefix\n")
2076 {
2077 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
2078 struct route_table *table;
2079 struct prefix p;
2080 struct route_node *rn;
2081
2082 if (address_str)
2083 prefix_str = address_str;
2084 if (str2prefix(prefix_str, &p) < 0) {
2085 vty_out(vty, "%% Malformed address\n");
2086 return CMD_WARNING;
2087 }
2088
2089 if (vrf_all) {
2090 struct vrf *vrf;
2091 struct zebra_vrf *zvrf;
2092
2093 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2094 if ((zvrf = vrf->info) == NULL
2095 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
2096 continue;
2097
2098 rn = route_node_match(table, &p);
2099 if (!rn)
2100 continue;
2101 if (!address_str && rn->p.prefixlen != p.prefixlen) {
2102 route_unlock_node(rn);
2103 continue;
2104 }
2105
2106 vty_show_ip_route_detail(vty, rn, 0);
2107
2108 route_unlock_node(rn);
2109 }
2110 } else {
2111 vrf_id_t vrf_id = VRF_DEFAULT;
2112
2113 if (vrf_name)
2114 VRF_GET_ID(vrf_id, vrf_name, false);
2115
2116 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
2117 if (!table)
2118 return CMD_SUCCESS;
2119
2120 rn = route_node_match(table, &p);
2121 if (!rn) {
2122 vty_out(vty, "%% Network not in table\n");
2123 return CMD_WARNING;
2124 }
2125 if (!address_str && rn->p.prefixlen != p.prefixlen) {
2126 vty_out(vty, "%% Network not in table\n");
2127 route_unlock_node(rn);
2128 return CMD_WARNING;
2129 }
2130
2131 vty_show_ip_route_detail(vty, rn, 0);
2132
2133 route_unlock_node(rn);
2134 }
2135
2136 return CMD_SUCCESS;
2137 }
2138
2139 DEFPY (show_route_summary,
2140 show_route_summary_cmd,
2141 "show\
2142 <\
2143 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
2144 summary [prefix$prefix]\
2145 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
2146 summary [prefix$prefix]\
2147 >",
2148 SHOW_STR
2149 IP_STR
2150 "IP routing table\n"
2151 VRF_FULL_CMD_HELP_STR
2152 "Summary of all routes\n"
2153 "Prefix routes\n"
2154 IP6_STR
2155 "IP routing table\n"
2156 VRF_FULL_CMD_HELP_STR
2157 "Summary of all routes\n"
2158 "Prefix routes\n")
2159 {
2160 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
2161 struct route_table *table;
2162
2163 if (vrf_all) {
2164 struct vrf *vrf;
2165 struct zebra_vrf *zvrf;
2166
2167 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2168 if ((zvrf = vrf->info) == NULL
2169 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
2170 continue;
2171
2172 if (prefix)
2173 vty_show_ip_route_summary_prefix(vty, table);
2174 else
2175 vty_show_ip_route_summary(vty, table);
2176 }
2177 } else {
2178 vrf_id_t vrf_id = VRF_DEFAULT;
2179
2180 if (vrf_name)
2181 VRF_GET_ID(vrf_id, vrf_name, false);
2182
2183 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
2184 if (!table)
2185 return CMD_SUCCESS;
2186
2187 if (prefix)
2188 vty_show_ip_route_summary_prefix(vty, table);
2189 else
2190 vty_show_ip_route_summary(vty, table);
2191 }
2192
2193 return CMD_SUCCESS;
2194 }
2195
2196 static void vty_show_ip_route_summary(struct vty *vty,
2197 struct route_table *table)
2198 {
2199 struct route_node *rn;
2200 struct route_entry *re;
2201 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2202 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2203 uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2204 uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2205 uint32_t i;
2206 uint32_t is_ibgp;
2207
2208 memset(&rib_cnt, 0, sizeof(rib_cnt));
2209 memset(&fib_cnt, 0, sizeof(fib_cnt));
2210 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2211 RNODE_FOREACH_RE (rn, re) {
2212 is_ibgp = (re->type == ZEBRA_ROUTE_BGP
2213 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP));
2214
2215 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
2216 if (is_ibgp)
2217 rib_cnt[ZEBRA_ROUTE_IBGP]++;
2218 else
2219 rib_cnt[re->type]++;
2220
2221 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
2222 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
2223
2224 if (is_ibgp)
2225 fib_cnt[ZEBRA_ROUTE_IBGP]++;
2226 else
2227 fib_cnt[re->type]++;
2228 }
2229 }
2230
2231 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source", "Routes",
2232 "FIB", zvrf_name(((rib_table_info_t *)table->info)->zvrf));
2233
2234 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
2235 if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP
2236 && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) {
2237 if (i == ZEBRA_ROUTE_BGP) {
2238 vty_out(vty, "%-20s %-20d %-20d \n", "ebgp",
2239 rib_cnt[ZEBRA_ROUTE_BGP],
2240 fib_cnt[ZEBRA_ROUTE_BGP]);
2241 vty_out(vty, "%-20s %-20d %-20d \n", "ibgp",
2242 rib_cnt[ZEBRA_ROUTE_IBGP],
2243 fib_cnt[ZEBRA_ROUTE_IBGP]);
2244 } else
2245 vty_out(vty, "%-20s %-20d %-20d \n",
2246 zebra_route_string(i), rib_cnt[i],
2247 fib_cnt[i]);
2248 }
2249 }
2250
2251 vty_out(vty, "------\n");
2252 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
2253 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
2254 vty_out(vty, "\n");
2255 }
2256
2257 /*
2258 * Implementation of the ip route summary prefix command.
2259 *
2260 * This command prints the primary prefixes that have been installed by various
2261 * protocols on the box.
2262 *
2263 */
2264 static void vty_show_ip_route_summary_prefix(struct vty *vty,
2265 struct route_table *table)
2266 {
2267 struct route_node *rn;
2268 struct route_entry *re;
2269 struct nexthop *nexthop;
2270 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2271 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2272 uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2273 uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2274 uint32_t i;
2275 int cnt;
2276
2277 memset(&rib_cnt, 0, sizeof(rib_cnt));
2278 memset(&fib_cnt, 0, sizeof(fib_cnt));
2279 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2280 RNODE_FOREACH_RE (rn, re) {
2281
2282 /*
2283 * In case of ECMP, count only once.
2284 */
2285 cnt = 0;
2286 for (nexthop = re->ng.nexthop; (!cnt && nexthop);
2287 nexthop = nexthop->next) {
2288 cnt++;
2289 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
2290 rib_cnt[re->type]++;
2291 if (CHECK_FLAG(nexthop->flags,
2292 NEXTHOP_FLAG_FIB)) {
2293 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
2294 fib_cnt[re->type]++;
2295 }
2296 if (re->type == ZEBRA_ROUTE_BGP
2297 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) {
2298 rib_cnt[ZEBRA_ROUTE_IBGP]++;
2299 if (CHECK_FLAG(nexthop->flags,
2300 NEXTHOP_FLAG_FIB))
2301 fib_cnt[ZEBRA_ROUTE_IBGP]++;
2302 }
2303 }
2304 }
2305
2306 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2307 "Prefix Routes", "FIB",
2308 zvrf_name(((rib_table_info_t *)table->info)->zvrf));
2309
2310 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
2311 if (rib_cnt[i] > 0) {
2312 if (i == ZEBRA_ROUTE_BGP) {
2313 vty_out(vty, "%-20s %-20d %-20d \n", "ebgp",
2314 rib_cnt[ZEBRA_ROUTE_BGP]
2315 - rib_cnt[ZEBRA_ROUTE_IBGP],
2316 fib_cnt[ZEBRA_ROUTE_BGP]
2317 - fib_cnt[ZEBRA_ROUTE_IBGP]);
2318 vty_out(vty, "%-20s %-20d %-20d \n", "ibgp",
2319 rib_cnt[ZEBRA_ROUTE_IBGP],
2320 fib_cnt[ZEBRA_ROUTE_IBGP]);
2321 } else
2322 vty_out(vty, "%-20s %-20d %-20d \n",
2323 zebra_route_string(i), rib_cnt[i],
2324 fib_cnt[i]);
2325 }
2326 }
2327
2328 vty_out(vty, "------\n");
2329 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
2330 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
2331 vty_out(vty, "\n");
2332 }
2333
2334 /* Write static route configuration. */
2335 int static_config(struct vty *vty, struct zebra_vrf *zvrf, afi_t afi,
2336 safi_t safi, const char *cmd)
2337 {
2338 struct static_hold_route *shr;
2339 struct listnode *node;
2340 char spacing[100];
2341 struct route_node *rn;
2342 struct static_route *si;
2343 struct route_table *stable;
2344 char buf[SRCDEST2STR_BUFFER];
2345 int write = 0;
2346
2347 if ((stable = zvrf->stable[afi][safi]) == NULL)
2348 return write;
2349
2350 sprintf(spacing, "%s%s", (zvrf->vrf->vrf_id == VRF_DEFAULT) ? "" : " ",
2351 cmd);
2352
2353 /*
2354 * Static routes for vrfs not fully inited
2355 */
2356 for (ALL_LIST_ELEMENTS_RO(static_list, node, shr)) {
2357 if (shr->afi != afi || shr->safi != safi)
2358 continue;
2359
2360 if (strcmp(zvrf->vrf->name, shr->vrf_name) != 0)
2361 continue;
2362
2363 char dest_str[PREFIX_STRLEN];
2364
2365 prefix2str(&shr->dest, dest_str, sizeof(dest_str));
2366
2367 vty_out(vty, "%s ", spacing);
2368 if (shr->dest_str)
2369 vty_out(vty, "%s ", dest_str);
2370 if (shr->src_str)
2371 vty_out(vty, "from %s ", shr->src_str);
2372 if (shr->gate_str)
2373 vty_out(vty, "%s ", shr->gate_str);
2374 if (shr->ifname)
2375 vty_out(vty, "%s ", shr->ifname);
2376 if (shr->flag_str)
2377 vty_out(vty, "%s ", shr->flag_str);
2378 if (shr->tag_str)
2379 vty_out(vty, "tag %s ", shr->tag_str);
2380 if (shr->distance_str)
2381 vty_out(vty, "%s ", shr->distance_str);
2382 if (shr->label_str)
2383 vty_out(vty, "label %s ", shr->label_str);
2384 if (shr->table_str)
2385 vty_out(vty, "table %s ", shr->table_str);
2386 if (strcmp(shr->vrf_name, shr->nhvrf_name) != 0)
2387 vty_out(vty, "nexthop-vrf %s", shr->nhvrf_name);
2388 vty_out(vty, "\n");
2389 }
2390
2391 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn))
2392 for (si = rn->info; si; si = si->next) {
2393 vty_out(vty, "%s %s", spacing,
2394 srcdest_rnode2str(rn, buf, sizeof buf));
2395
2396 switch (si->type) {
2397 case STATIC_IPV4_GATEWAY:
2398 vty_out(vty, " %s", inet_ntoa(si->addr.ipv4));
2399 break;
2400 case STATIC_IPV6_GATEWAY:
2401 vty_out(vty, " %s",
2402 inet_ntop(AF_INET6, &si->addr.ipv6, buf,
2403 sizeof buf));
2404 break;
2405 case STATIC_IFNAME:
2406 vty_out(vty, " %s", si->ifname);
2407 break;
2408 case STATIC_BLACKHOLE:
2409 switch (si->bh_type) {
2410 case STATIC_BLACKHOLE_DROP:
2411 vty_out(vty, " blackhole");
2412 break;
2413 case STATIC_BLACKHOLE_NULL:
2414 vty_out(vty, " Null0");
2415 break;
2416 case STATIC_BLACKHOLE_REJECT:
2417 vty_out(vty, " reject");
2418 break;
2419 }
2420 break;
2421 case STATIC_IPV4_GATEWAY_IFNAME:
2422 vty_out(vty, " %s %s",
2423 inet_ntop(AF_INET, &si->addr.ipv4, buf,
2424 sizeof buf),
2425 si->ifname);
2426 break;
2427 case STATIC_IPV6_GATEWAY_IFNAME:
2428 vty_out(vty, " %s %s",
2429 inet_ntop(AF_INET6, &si->addr.ipv6, buf,
2430 sizeof buf),
2431 si->ifname);
2432 break;
2433 }
2434
2435 if (si->tag)
2436 vty_out(vty, " tag %" ROUTE_TAG_PRI, si->tag);
2437
2438 if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
2439 vty_out(vty, " %d", si->distance);
2440
2441 /* Label information */
2442 if (si->snh_label.num_labels)
2443 vty_out(vty, " label %s",
2444 mpls_label2str(si->snh_label.num_labels,
2445 si->snh_label.label, buf,
2446 sizeof buf, 0));
2447
2448 if (si->nh_vrf_id != si->vrf_id) {
2449 vty_out(vty, " nexthop-vrf %s", si->nh_vrfname);
2450 }
2451
2452 /* table ID from VRF overrides configured
2453 */
2454 if (si->table_id && zvrf->table_id == RT_TABLE_MAIN)
2455 vty_out(vty, " table %u", si->table_id);
2456
2457 vty_out(vty, "\n");
2458
2459 write = 1;
2460 }
2461 return write;
2462 }
2463
2464 DEFPY(ipv6_route_blackhole,
2465 ipv6_route_blackhole_cmd,
2466 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2467 <Null0|reject|blackhole>$flag \
2468 [{ \
2469 tag (1-4294967295) \
2470 |(1-255)$distance \
2471 |vrf NAME \
2472 |label WORD \
2473 |table (1-4294967295) \
2474 }]",
2475 NO_STR
2476 IPV6_STR
2477 "Establish static routes\n"
2478 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2479 "IPv6 source-dest route\n"
2480 "IPv6 source prefix\n"
2481 "Null interface\n"
2482 "Emit an ICMP unreachable when matched\n"
2483 "Silently discard pkts when matched\n"
2484 "Set tag for this route\n"
2485 "Tag value\n"
2486 "Distance value for this prefix\n"
2487 VRF_CMD_HELP_STR
2488 MPLS_LABEL_HELPSTR
2489 "Table to configure\n"
2490 "The table number to configure\n")
2491 {
2492 if (table_str && !vrf_is_backend_netns()) {
2493 vty_out(vty,
2494 "%% table param only available when running on netns-based vrfs\n");
2495 return CMD_WARNING_CONFIG_FAILED;
2496 }
2497
2498 return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
2499 NULL, from_str, NULL, NULL, flag, tag_str,
2500 distance_str, vrf, label, table_str);
2501 }
2502
2503 DEFPY(ipv6_route_blackhole_vrf,
2504 ipv6_route_blackhole_vrf_cmd,
2505 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2506 <Null0|reject|blackhole>$flag \
2507 [{ \
2508 tag (1-4294967295) \
2509 |(1-255)$distance \
2510 |label WORD \
2511 |table (1-4294967295) \
2512 }]",
2513 NO_STR
2514 IPV6_STR
2515 "Establish static routes\n"
2516 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2517 "IPv6 source-dest route\n"
2518 "IPv6 source prefix\n"
2519 "Null interface\n"
2520 "Emit an ICMP unreachable when matched\n"
2521 "Silently discard pkts when matched\n"
2522 "Set tag for this route\n"
2523 "Tag value\n"
2524 "Distance value for this prefix\n"
2525 MPLS_LABEL_HELPSTR
2526 "Table to configure\n"
2527 "The table number to configure\n")
2528 {
2529 VTY_DECLVAR_CONTEXT(vrf, vrf);
2530 struct zebra_vrf *zvrf = vrf->info;
2531
2532 if (table_str && !vrf_is_backend_netns()) {
2533 vty_out(vty,
2534 "%% table param only available when running on netns-based vrfs\n");
2535 return CMD_WARNING_CONFIG_FAILED;
2536 }
2537 /*
2538 * Coverity is complaining that prefix could
2539 * be dereferenced, but we know that prefix will
2540 * valid. Add an assert to make it happy
2541 */
2542 assert(prefix);
2543 return zebra_static_route_leak(
2544 vty, zvrf, zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
2545 from_str, NULL, NULL, flag, tag_str, distance_str, label,
2546 table_str);
2547 }
2548
2549 DEFPY(ipv6_route_address_interface,
2550 ipv6_route_address_interface_cmd,
2551 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2552 X:X::X:X$gate \
2553 INTERFACE$ifname \
2554 [{ \
2555 tag (1-4294967295) \
2556 |(1-255)$distance \
2557 |vrf NAME \
2558 |label WORD \
2559 |table (1-4294967295) \
2560 |nexthop-vrf NAME \
2561 }]",
2562 NO_STR
2563 IPV6_STR
2564 "Establish static routes\n"
2565 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2566 "IPv6 source-dest route\n"
2567 "IPv6 source prefix\n"
2568 "IPv6 gateway address\n"
2569 "IPv6 gateway interface name\n"
2570 "Set tag for this route\n"
2571 "Tag value\n"
2572 "Distance value for this prefix\n"
2573 VRF_CMD_HELP_STR
2574 MPLS_LABEL_HELPSTR
2575 "Table to configure\n"
2576 "The table number to configure\n"
2577 VRF_CMD_HELP_STR)
2578 {
2579 struct zebra_vrf *zvrf;
2580 struct zebra_vrf *nh_zvrf;
2581
2582 if (table_str && !vrf_is_backend_netns()) {
2583 vty_out(vty,
2584 "%% table param only available when running on netns-based vrfs\n");
2585 return CMD_WARNING_CONFIG_FAILED;
2586 }
2587
2588 zvrf = zebra_vty_get_unknown_vrf(vty, vrf);
2589 if (!zvrf) {
2590 vty_out(vty, "%% vrf %s is not defined\n", vrf);
2591 return CMD_WARNING_CONFIG_FAILED;
2592 }
2593
2594 if (nexthop_vrf)
2595 nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
2596 else
2597 nh_zvrf = zvrf;
2598
2599 if (!nh_zvrf) {
2600 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
2601 return CMD_WARNING_CONFIG_FAILED;
2602 }
2603
2604 return zebra_static_route_leak(
2605 vty, zvrf, nh_zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
2606 from_str, gate_str, ifname, NULL, tag_str, distance_str, label,
2607 table_str);
2608 }
2609
2610 DEFPY(ipv6_route_address_interface_vrf,
2611 ipv6_route_address_interface_vrf_cmd,
2612 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2613 X:X::X:X$gate \
2614 INTERFACE$ifname \
2615 [{ \
2616 tag (1-4294967295) \
2617 |(1-255)$distance \
2618 |label WORD \
2619 |table (1-4294967295) \
2620 |nexthop-vrf NAME \
2621 }]",
2622 NO_STR
2623 IPV6_STR
2624 "Establish static routes\n"
2625 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2626 "IPv6 source-dest route\n"
2627 "IPv6 source prefix\n"
2628 "IPv6 gateway address\n"
2629 "IPv6 gateway interface name\n"
2630 "Set tag for this route\n"
2631 "Tag value\n"
2632 "Distance value for this prefix\n"
2633 MPLS_LABEL_HELPSTR
2634 "Table to configure\n"
2635 "The table number to configure\n"
2636 VRF_CMD_HELP_STR)
2637 {
2638 VTY_DECLVAR_CONTEXT(vrf, vrf);
2639 struct zebra_vrf *zvrf = vrf->info;
2640 struct zebra_vrf *nh_zvrf;
2641
2642 if (table_str && !vrf_is_backend_netns()) {
2643 vty_out(vty,
2644 "%% table param only available when running on netns-based vrfs\n");
2645 return CMD_WARNING_CONFIG_FAILED;
2646 }
2647
2648 if (nexthop_vrf)
2649 nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
2650 else
2651 nh_zvrf = zvrf;
2652
2653 if (!nh_zvrf) {
2654 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
2655 return CMD_WARNING_CONFIG_FAILED;
2656 }
2657
2658 return zebra_static_route_leak(
2659 vty, zvrf, nh_zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
2660 from_str, gate_str, ifname, NULL, tag_str, distance_str, label,
2661 table_str);
2662 }
2663
2664 DEFPY(ipv6_route,
2665 ipv6_route_cmd,
2666 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2667 <X:X::X:X$gate|INTERFACE$ifname> \
2668 [{ \
2669 tag (1-4294967295) \
2670 |(1-255)$distance \
2671 |vrf NAME \
2672 |label WORD \
2673 |table (1-4294967295) \
2674 |nexthop-vrf NAME \
2675 }]",
2676 NO_STR
2677 IPV6_STR
2678 "Establish static routes\n"
2679 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2680 "IPv6 source-dest route\n"
2681 "IPv6 source prefix\n"
2682 "IPv6 gateway address\n"
2683 "IPv6 gateway interface name\n"
2684 "Set tag for this route\n"
2685 "Tag value\n"
2686 "Distance value for this prefix\n"
2687 VRF_CMD_HELP_STR
2688 MPLS_LABEL_HELPSTR
2689 "Table to configure\n"
2690 "The table number to configure\n"
2691 VRF_CMD_HELP_STR)
2692 {
2693 struct zebra_vrf *zvrf;
2694 struct zebra_vrf *nh_zvrf;
2695
2696 if (table_str && !vrf_is_backend_netns()) {
2697 vty_out(vty,
2698 "%% table param only available when running on netns-based vrfs\n");
2699 return CMD_WARNING_CONFIG_FAILED;
2700 }
2701
2702 zvrf = zebra_vty_get_unknown_vrf(vty, vrf);
2703 if (!zvrf) {
2704 vty_out(vty, "%% vrf %s is not defined\n", vrf);
2705 return CMD_WARNING_CONFIG_FAILED;
2706 }
2707
2708 if (nexthop_vrf)
2709 nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
2710 else
2711 nh_zvrf = zvrf;
2712
2713 if (!nh_zvrf) {
2714 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
2715 return CMD_WARNING_CONFIG_FAILED;
2716 }
2717
2718 return zebra_static_route_leak(
2719 vty, zvrf, nh_zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
2720 from_str, gate_str, ifname, NULL, tag_str, distance_str, label,
2721 table_str);
2722 }
2723
2724 DEFPY(ipv6_route_vrf,
2725 ipv6_route_vrf_cmd,
2726 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2727 <X:X::X:X$gate|INTERFACE$ifname> \
2728 [{ \
2729 tag (1-4294967295) \
2730 |(1-255)$distance \
2731 |label WORD \
2732 |table (1-4294967295) \
2733 |nexthop-vrf NAME \
2734 }]",
2735 NO_STR
2736 IPV6_STR
2737 "Establish static routes\n"
2738 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2739 "IPv6 source-dest route\n"
2740 "IPv6 source prefix\n"
2741 "IPv6 gateway address\n"
2742 "IPv6 gateway interface name\n"
2743 "Set tag for this route\n"
2744 "Tag value\n"
2745 "Distance value for this prefix\n"
2746 MPLS_LABEL_HELPSTR
2747 "Table to configure\n"
2748 "The table number to configure\n"
2749 VRF_CMD_HELP_STR)
2750 {
2751 VTY_DECLVAR_CONTEXT(vrf, vrf);
2752 struct zebra_vrf *zvrf = vrf->info;
2753 struct zebra_vrf *nh_zvrf;
2754
2755 if (table_str && !vrf_is_backend_netns()) {
2756 vty_out(vty,
2757 "%% table param only available when running on netns-based vrfs\n");
2758 return CMD_WARNING_CONFIG_FAILED;
2759 }
2760
2761 if (nexthop_vrf)
2762 nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
2763 else
2764 nh_zvrf = zvrf;
2765
2766 if (!nh_zvrf) {
2767 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
2768 return CMD_WARNING_CONFIG_FAILED;
2769 }
2770
2771 return zebra_static_route_leak(
2772 vty, zvrf, nh_zvrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL,
2773 from_str, gate_str, ifname, NULL, tag_str, distance_str, label,
2774 table_str);
2775 }
2776
2777 /*
2778 * Show IPv6 mroute command.Used to dump
2779 * the Multicast routing table.
2780 */
2781 DEFUN (show_ipv6_mroute,
2782 show_ipv6_mroute_cmd,
2783 "show ipv6 mroute [vrf NAME]",
2784 SHOW_STR
2785 IP_STR
2786 "IPv6 Multicast routing table\n"
2787 VRF_CMD_HELP_STR)
2788 {
2789 struct route_table *table;
2790 struct route_node *rn;
2791 struct route_entry *re;
2792 int first = 1;
2793 vrf_id_t vrf_id = VRF_DEFAULT;
2794
2795 if (argc == 5)
2796 VRF_GET_ID(vrf_id, argv[4]->arg, false);
2797
2798 table = zebra_vrf_table(AFI_IP6, SAFI_MULTICAST, vrf_id);
2799 if (!table)
2800 return CMD_SUCCESS;
2801
2802 /* Show all IPv6 route. */
2803 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2804 RNODE_FOREACH_RE (rn, re) {
2805 if (first) {
2806 vty_out(vty, SHOW_ROUTE_V6_HEADER);
2807 first = 0;
2808 }
2809 vty_show_ip_route(vty, rn, re, NULL);
2810 }
2811 return CMD_SUCCESS;
2812 }
2813
2814 DEFUN (show_ipv6_mroute_vrf_all,
2815 show_ipv6_mroute_vrf_all_cmd,
2816 "show ipv6 mroute vrf all",
2817 SHOW_STR
2818 IP_STR
2819 "IPv6 Multicast routing table\n"
2820 VRF_ALL_CMD_HELP_STR)
2821 {
2822 struct route_table *table;
2823 struct route_node *rn;
2824 struct route_entry *re;
2825 struct vrf *vrf;
2826 struct zebra_vrf *zvrf;
2827 int first = 1;
2828
2829 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2830 if ((zvrf = vrf->info) == NULL
2831 || (table = zvrf->table[AFI_IP6][SAFI_MULTICAST]) == NULL)
2832 continue;
2833
2834 /* Show all IPv6 route. */
2835 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2836 RNODE_FOREACH_RE (rn, re) {
2837 if (first) {
2838 vty_out(vty, SHOW_ROUTE_V6_HEADER);
2839 first = 0;
2840 }
2841 vty_show_ip_route(vty, rn, re, NULL);
2842 }
2843 }
2844 return CMD_SUCCESS;
2845 }
2846
2847 DEFUN (allow_external_route_update,
2848 allow_external_route_update_cmd,
2849 "allow-external-route-update",
2850 "Allow FRR routes to be overwritten by external processes\n")
2851 {
2852 allow_delete = 1;
2853
2854 return CMD_SUCCESS;
2855 }
2856
2857 DEFUN (no_allow_external_route_update,
2858 no_allow_external_route_update_cmd,
2859 "no allow-external-route-update",
2860 NO_STR
2861 "Allow FRR routes to be overwritten by external processes\n")
2862 {
2863 allow_delete = 0;
2864
2865 return CMD_SUCCESS;
2866 }
2867
2868 /* show vrf */
2869 DEFUN (show_vrf,
2870 show_vrf_cmd,
2871 "show vrf",
2872 SHOW_STR
2873 "VRF\n")
2874 {
2875 struct vrf *vrf;
2876 struct zebra_vrf *zvrf;
2877
2878 if (vrf_is_backend_netns())
2879 vty_out(vty, "netns-based vrfs\n");
2880
2881 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2882 if (!(zvrf = vrf->info))
2883 continue;
2884 if (zvrf_id(zvrf) == VRF_DEFAULT)
2885 continue;
2886
2887 vty_out(vty, "vrf %s ", zvrf_name(zvrf));
2888 if (zvrf_id(zvrf) == VRF_UNKNOWN || !zvrf_is_active(zvrf))
2889 vty_out(vty, "inactive");
2890 else if (zvrf_ns_name(zvrf))
2891 vty_out(vty, "id %u netns %s", zvrf_id(zvrf),
2892 zvrf_ns_name(zvrf));
2893 else
2894 vty_out(vty, "id %u table %u", zvrf_id(zvrf),
2895 zvrf->table_id);
2896 if (vrf_is_user_cfged(vrf))
2897 vty_out(vty, " (configured)");
2898 vty_out(vty, "\n");
2899 }
2900
2901 return CMD_SUCCESS;
2902 }
2903
2904 DEFUN_HIDDEN (default_vrf_vni_mapping,
2905 default_vrf_vni_mapping_cmd,
2906 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2907 "VNI corresponding to the DEFAULT VRF\n"
2908 "VNI-ID\n"
2909 "Prefix routes only \n")
2910 {
2911 int ret = 0;
2912 char err[ERR_STR_SZ];
2913 struct zebra_vrf *zvrf = NULL;
2914 vni_t vni = strtoul(argv[1]->arg, NULL, 10);
2915 int filter = 0;
2916
2917 zvrf = vrf_info_lookup(VRF_DEFAULT);
2918 if (!zvrf)
2919 return CMD_WARNING;
2920
2921 if (argc == 3)
2922 filter = 1;
2923
2924 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ,
2925 filter, 1);
2926 if (ret != 0) {
2927 vty_out(vty, "%s\n", err);
2928 return CMD_WARNING;
2929 }
2930
2931 return CMD_SUCCESS;
2932 }
2933
2934 DEFUN_HIDDEN (no_default_vrf_vni_mapping,
2935 no_default_vrf_vni_mapping_cmd,
2936 "no vni " CMD_VNI_RANGE,
2937 NO_STR
2938 "VNI corresponding to DEFAULT VRF\n"
2939 "VNI-ID")
2940 {
2941 int ret = 0;
2942 char err[ERR_STR_SZ];
2943 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2944 struct zebra_vrf *zvrf = NULL;
2945
2946 zvrf = vrf_info_lookup(VRF_DEFAULT);
2947 if (!zvrf)
2948 return CMD_WARNING;
2949
2950 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 0, 0);
2951 if (ret != 0) {
2952 vty_out(vty, "%s\n", err);
2953 return CMD_WARNING;
2954 }
2955
2956 return CMD_SUCCESS;
2957 }
2958
2959 DEFUN (vrf_vni_mapping,
2960 vrf_vni_mapping_cmd,
2961 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2962 "VNI corresponding to tenant VRF\n"
2963 "VNI-ID\n"
2964 "prefix-routes-only\n")
2965 {
2966 int ret = 0;
2967 int filter = 0;
2968
2969 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
2970 vni_t vni = strtoul(argv[1]->arg, NULL, 10);
2971 char err[ERR_STR_SZ];
2972
2973 assert(vrf);
2974 assert(zvrf);
2975
2976 if (argc == 3)
2977 filter = 1;
2978
2979 /* Mark as having FRR configuration */
2980 vrf_set_user_cfged(vrf);
2981 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ,
2982 filter, 1);
2983 if (ret != 0) {
2984 vty_out(vty, "%s\n", err);
2985 return CMD_WARNING;
2986 }
2987
2988 return CMD_SUCCESS;
2989 }
2990
2991 DEFUN (no_vrf_vni_mapping,
2992 no_vrf_vni_mapping_cmd,
2993 "no vni " CMD_VNI_RANGE "[prefix-routes-only]",
2994 NO_STR
2995 "VNI corresponding to tenant VRF\n"
2996 "VNI-ID\n"
2997 "prefix-routes-only\n")
2998 {
2999 int ret = 0;
3000 int filter = 0;
3001 char err[ERR_STR_SZ];
3002 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
3003
3004 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
3005
3006 assert(vrf);
3007 assert(zvrf);
3008
3009 if (argc == 4)
3010 filter = 1;
3011
3012 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err,
3013 ERR_STR_SZ, filter, 0);
3014 if (ret != 0) {
3015 vty_out(vty, "%s\n", err);
3016 return CMD_WARNING;
3017 }
3018
3019 /* If no other FRR config for this VRF, mark accordingly. */
3020 if (!zebra_vrf_has_config(zvrf))
3021 vrf_reset_user_cfged(vrf);
3022
3023 return CMD_SUCCESS;
3024 }
3025
3026 /* show vrf */
3027 DEFUN (show_vrf_vni,
3028 show_vrf_vni_cmd,
3029 "show vrf vni [json]",
3030 SHOW_STR
3031 "VRF\n"
3032 "VNI\n"
3033 JSON_STR)
3034 {
3035 struct vrf *vrf;
3036 struct zebra_vrf *zvrf;
3037 json_object *json = NULL;
3038 json_object *json_vrfs = NULL;
3039 uint8_t uj = use_json(argc, argv);
3040
3041 if (uj) {
3042 json = json_object_new_object();
3043 json_vrfs = json_object_new_array();
3044 }
3045
3046 if (!uj)
3047 vty_out(vty, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
3048 "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
3049
3050 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3051 zvrf = vrf->info;
3052 if (!zvrf)
3053 continue;
3054
3055 zebra_vxlan_print_vrf_vni(vty, zvrf, json_vrfs);
3056 }
3057
3058 if (uj) {
3059 json_object_object_add(json, "vrfs", json_vrfs);
3060 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3061 json, JSON_C_TO_STRING_PRETTY));
3062 json_object_free(json);
3063 }
3064
3065 return CMD_SUCCESS;
3066 }
3067
3068 DEFUN (show_evpn_global,
3069 show_evpn_global_cmd,
3070 "show evpn [json]",
3071 SHOW_STR
3072 "EVPN\n"
3073 JSON_STR)
3074 {
3075 uint8_t uj = use_json(argc, argv);
3076
3077 zebra_vxlan_print_evpn(vty, uj);
3078 return CMD_SUCCESS;
3079 }
3080
3081 DEFUN (show_evpn_vni,
3082 show_evpn_vni_cmd,
3083 "show evpn vni [json]",
3084 SHOW_STR
3085 "EVPN\n"
3086 "VxLAN information\n"
3087 JSON_STR)
3088 {
3089 struct zebra_vrf *zvrf;
3090 uint8_t uj = use_json(argc, argv);
3091
3092 zvrf = vrf_info_lookup(VRF_DEFAULT);
3093 zebra_vxlan_print_vnis(vty, zvrf, uj);
3094 return CMD_SUCCESS;
3095 }
3096
3097 DEFUN (show_evpn_vni_vni,
3098 show_evpn_vni_vni_cmd,
3099 "show evpn vni " CMD_VNI_RANGE "[json]",
3100 SHOW_STR
3101 "EVPN\n"
3102 "VxLAN Network Identifier\n"
3103 "VNI number\n"
3104 JSON_STR)
3105 {
3106 struct zebra_vrf *zvrf;
3107 vni_t vni;
3108 uint8_t uj = use_json(argc, argv);
3109
3110 vni = strtoul(argv[3]->arg, NULL, 10);
3111 zvrf = vrf_info_lookup(VRF_DEFAULT);
3112 zebra_vxlan_print_vni(vty, zvrf, vni, uj);
3113 return CMD_SUCCESS;
3114 }
3115
3116 DEFUN (show_evpn_rmac_vni_mac,
3117 show_evpn_rmac_vni_mac_cmd,
3118 "show evpn rmac vni " CMD_VNI_RANGE " mac WORD [json]",
3119 SHOW_STR
3120 "EVPN\n"
3121 "RMAC\n"
3122 "L3 VNI\n"
3123 "VNI number\n"
3124 "MAC\n"
3125 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3126 JSON_STR)
3127 {
3128 vni_t l3vni = 0;
3129 struct ethaddr mac;
3130 uint8_t uj = use_json(argc, argv);
3131
3132 l3vni = strtoul(argv[4]->arg, NULL, 10);
3133 if (!prefix_str2mac(argv[6]->arg, &mac)) {
3134 vty_out(vty, "%% Malformed MAC address\n");
3135 return CMD_WARNING;
3136 }
3137 zebra_vxlan_print_specific_rmac_l3vni(vty, l3vni, &mac, uj);
3138 return CMD_SUCCESS;
3139 }
3140
3141 DEFUN (show_evpn_rmac_vni,
3142 show_evpn_rmac_vni_cmd,
3143 "show evpn rmac vni " CMD_VNI_RANGE "[json]",
3144 SHOW_STR
3145 "EVPN\n"
3146 "RMAC\n"
3147 "L3 VNI\n"
3148 "VNI number\n"
3149 JSON_STR)
3150 {
3151 vni_t l3vni = 0;
3152 uint8_t uj = use_json(argc, argv);
3153
3154 l3vni = strtoul(argv[4]->arg, NULL, 10);
3155 zebra_vxlan_print_rmacs_l3vni(vty, l3vni, uj);
3156
3157 return CMD_SUCCESS;
3158 }
3159
3160 DEFUN (show_evpn_rmac_vni_all,
3161 show_evpn_rmac_vni_all_cmd,
3162 "show evpn rmac vni all [json]",
3163 SHOW_STR
3164 "EVPN\n"
3165 "RMAC addresses\n"
3166 "L3 VNI\n"
3167 "All VNIs\n"
3168 JSON_STR)
3169 {
3170 uint8_t uj = use_json(argc, argv);
3171
3172 zebra_vxlan_print_rmacs_all_l3vni(vty, uj);
3173
3174 return CMD_SUCCESS;
3175 }
3176
3177 DEFUN (show_evpn_nh_vni_ip,
3178 show_evpn_nh_vni_ip_cmd,
3179 "show evpn next-hops vni " CMD_VNI_RANGE " ip WORD [json]",
3180 SHOW_STR
3181 "EVPN\n"
3182 "Remote Vteps\n"
3183 "L3 VNI\n"
3184 "VNI number\n"
3185 "Ip address\n"
3186 "Host address (ipv4 or ipv6)\n"
3187 JSON_STR)
3188 {
3189 vni_t l3vni;
3190 struct ipaddr ip;
3191 uint8_t uj = use_json(argc, argv);
3192
3193 l3vni = strtoul(argv[4]->arg, NULL, 10);
3194 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
3195 if (!uj)
3196 vty_out(vty, "%% Malformed Neighbor address\n");
3197 return CMD_WARNING;
3198 }
3199 zebra_vxlan_print_specific_nh_l3vni(vty, l3vni, &ip, uj);
3200
3201 return CMD_SUCCESS;
3202 }
3203
3204 DEFUN (show_evpn_nh_vni,
3205 show_evpn_nh_vni_cmd,
3206 "show evpn next-hops vni " CMD_VNI_RANGE "[json]",
3207 SHOW_STR
3208 "EVPN\n"
3209 "Remote Vteps\n"
3210 "L3 VNI\n"
3211 "VNI number\n"
3212 JSON_STR)
3213 {
3214 vni_t l3vni;
3215 uint8_t uj = use_json(argc, argv);
3216
3217 l3vni = strtoul(argv[4]->arg, NULL, 10);
3218 zebra_vxlan_print_nh_l3vni(vty, l3vni, uj);
3219
3220 return CMD_SUCCESS;
3221 }
3222
3223 DEFUN (show_evpn_nh_vni_all,
3224 show_evpn_nh_vni_all_cmd,
3225 "show evpn next-hops vni all [json]",
3226 SHOW_STR
3227 "EVPN\n"
3228 "Remote VTEPs\n"
3229 "L3 VNI\n"
3230 "All VNIs\n"
3231 JSON_STR)
3232 {
3233 uint8_t uj = use_json(argc, argv);
3234
3235 zebra_vxlan_print_nh_all_l3vni(vty, uj);
3236
3237 return CMD_SUCCESS;
3238 }
3239
3240 DEFUN (show_evpn_mac_vni,
3241 show_evpn_mac_vni_cmd,
3242 "show evpn mac vni " CMD_VNI_RANGE "[json]",
3243 SHOW_STR
3244 "EVPN\n"
3245 "MAC addresses\n"
3246 "VxLAN Network Identifier\n"
3247 "VNI number\n"
3248 JSON_STR)
3249 {
3250 struct zebra_vrf *zvrf;
3251 vni_t vni;
3252 uint8_t uj = use_json(argc, argv);
3253
3254 vni = strtoul(argv[4]->arg, NULL, 10);
3255 zvrf = vrf_info_lookup(VRF_DEFAULT);
3256 zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj);
3257 return CMD_SUCCESS;
3258 }
3259
3260 DEFUN (show_evpn_mac_vni_all,
3261 show_evpn_mac_vni_all_cmd,
3262 "show evpn mac vni all [json]",
3263 SHOW_STR
3264 "EVPN\n"
3265 "MAC addresses\n"
3266 "VxLAN Network Identifier\n"
3267 "All VNIs\n"
3268 JSON_STR)
3269 {
3270 struct zebra_vrf *zvrf;
3271 uint8_t uj = use_json(argc, argv);
3272
3273 zvrf = vrf_info_lookup(VRF_DEFAULT);
3274 zebra_vxlan_print_macs_all_vni(vty, zvrf, uj);
3275 return CMD_SUCCESS;
3276 }
3277
3278 DEFUN (show_evpn_mac_vni_all_vtep,
3279 show_evpn_mac_vni_all_vtep_cmd,
3280 "show evpn mac vni all vtep A.B.C.D [json]",
3281 SHOW_STR
3282 "EVPN\n"
3283 "MAC addresses\n"
3284 "VxLAN Network Identifier\n"
3285 "All VNIs\n"
3286 "Remote VTEP\n"
3287 "Remote VTEP IP address\n"
3288 JSON_STR)
3289 {
3290 struct zebra_vrf *zvrf;
3291 struct in_addr vtep_ip;
3292 uint8_t uj = use_json(argc, argv);
3293
3294 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
3295 if (!uj)
3296 vty_out(vty, "%% Malformed VTEP IP address\n");
3297 return CMD_WARNING;
3298 }
3299 zvrf = vrf_info_lookup(VRF_DEFAULT);
3300 zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip, uj);
3301
3302 return CMD_SUCCESS;
3303 }
3304
3305
3306 DEFUN (show_evpn_mac_vni_mac,
3307 show_evpn_mac_vni_mac_cmd,
3308 "show evpn mac vni " CMD_VNI_RANGE " mac WORD",
3309 SHOW_STR
3310 "EVPN\n"
3311 "MAC addresses\n"
3312 "VxLAN Network Identifier\n"
3313 "VNI number\n"
3314 "MAC\n"
3315 "MAC address (e.g., 00:e0:ec:20:12:62)\n")
3316 {
3317 struct zebra_vrf *zvrf;
3318 vni_t vni;
3319 struct ethaddr mac;
3320
3321 vni = strtoul(argv[4]->arg, NULL, 10);
3322 if (!prefix_str2mac(argv[6]->arg, &mac)) {
3323 vty_out(vty, "%% Malformed MAC address");
3324 return CMD_WARNING;
3325 }
3326 zvrf = vrf_info_lookup(VRF_DEFAULT);
3327 zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac);
3328 return CMD_SUCCESS;
3329 }
3330
3331 DEFUN (show_evpn_mac_vni_vtep,
3332 show_evpn_mac_vni_vtep_cmd,
3333 "show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D" "[json]",
3334 SHOW_STR
3335 "EVPN\n"
3336 "MAC addresses\n"
3337 "VxLAN Network Identifier\n"
3338 "VNI number\n"
3339 "Remote VTEP\n"
3340 "Remote VTEP IP address\n"
3341 JSON_STR)
3342 {
3343 struct zebra_vrf *zvrf;
3344 vni_t vni;
3345 struct in_addr vtep_ip;
3346 uint8_t uj = use_json(argc, argv);
3347
3348 vni = strtoul(argv[4]->arg, NULL, 10);
3349 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
3350 if (!uj)
3351 vty_out(vty, "%% Malformed VTEP IP address\n");
3352 return CMD_WARNING;
3353 }
3354
3355 zvrf = vrf_info_lookup(VRF_DEFAULT);
3356 zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
3357 return CMD_SUCCESS;
3358 }
3359
3360 DEFUN (show_evpn_neigh_vni,
3361 show_evpn_neigh_vni_cmd,
3362 "show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
3363 SHOW_STR
3364 "EVPN\n"
3365 "ARP and ND cache\n"
3366 "VxLAN Network Identifier\n"
3367 "VNI number\n"
3368 JSON_STR)
3369 {
3370 struct zebra_vrf *zvrf;
3371 vni_t vni;
3372 uint8_t uj = use_json(argc, argv);
3373
3374 vni = strtoul(argv[4]->arg, NULL, 10);
3375 zvrf = vrf_info_lookup(VRF_DEFAULT);
3376 zebra_vxlan_print_neigh_vni(vty, zvrf, vni, uj);
3377 return CMD_SUCCESS;
3378 }
3379
3380 DEFUN (show_evpn_neigh_vni_all,
3381 show_evpn_neigh_vni_all_cmd,
3382 "show evpn arp-cache vni all [json]",
3383 SHOW_STR
3384 "EVPN\n"
3385 "ARP and ND cache\n"
3386 "VxLAN Network Identifier\n"
3387 "All VNIs\n"
3388 JSON_STR)
3389 {
3390 struct zebra_vrf *zvrf;
3391 uint8_t uj = use_json(argc, argv);
3392
3393 zvrf = vrf_info_lookup(VRF_DEFAULT);
3394 zebra_vxlan_print_neigh_all_vni(vty, zvrf, uj);
3395 return CMD_SUCCESS;
3396 }
3397
3398 DEFUN (show_evpn_neigh_vni_neigh,
3399 show_evpn_neigh_vni_neigh_cmd,
3400 "show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD [json]",
3401 SHOW_STR
3402 "EVPN\n"
3403 "ARP and ND cache\n"
3404 "VxLAN Network Identifier\n"
3405 "VNI number\n"
3406 "Neighbor\n"
3407 "Neighbor address (IPv4 or IPv6 address)\n"
3408 JSON_STR)
3409 {
3410 struct zebra_vrf *zvrf;
3411 vni_t vni;
3412 struct ipaddr ip;
3413 uint8_t uj = use_json(argc, argv);
3414
3415 vni = strtoul(argv[4]->arg, NULL, 10);
3416 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
3417 if (!uj)
3418 vty_out(vty, "%% Malformed Neighbor address\n");
3419 return CMD_WARNING;
3420 }
3421 zvrf = vrf_info_lookup(VRF_DEFAULT);
3422 zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip, uj);
3423 return CMD_SUCCESS;
3424 }
3425
3426 DEFUN (show_evpn_neigh_vni_vtep,
3427 show_evpn_neigh_vni_vtep_cmd,
3428 "show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D [json]",
3429 SHOW_STR
3430 "EVPN\n"
3431 "ARP and ND cache\n"
3432 "VxLAN Network Identifier\n"
3433 "VNI number\n"
3434 "Remote VTEP\n"
3435 "Remote VTEP IP address\n"
3436 JSON_STR)
3437 {
3438 struct zebra_vrf *zvrf;
3439 vni_t vni;
3440 struct in_addr vtep_ip;
3441 uint8_t uj = use_json(argc, argv);
3442
3443 vni = strtoul(argv[4]->arg, NULL, 10);
3444 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
3445 if (!uj)
3446 vty_out(vty, "%% Malformed VTEP IP address\n");
3447 return CMD_WARNING;
3448 }
3449
3450 zvrf = vrf_info_lookup(VRF_DEFAULT);
3451 zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
3452 return CMD_SUCCESS;
3453 }
3454
3455 /* policy routing contexts */
3456 DEFUN (show_pbr_ipset,
3457 show_pbr_ipset_cmd,
3458 "show pbr ipset [WORD]",
3459 SHOW_STR
3460 "Policy-Based Routing\n"
3461 "IPset Context information\n"
3462 "IPset Name information\n")
3463 {
3464 int idx = 0;
3465 int found = 0;
3466 found = argv_find(argv, argc, "WORD", &idx);
3467 if (!found)
3468 zebra_pbr_show_ipset_list(vty, NULL);
3469 else
3470 zebra_pbr_show_ipset_list(vty, argv[idx]->arg);
3471 return CMD_SUCCESS;
3472 }
3473
3474 /* policy routing contexts */
3475 DEFUN (show_pbr_iptable,
3476 show_pbr_iptable_cmd,
3477 "show pbr iptable [WORD]",
3478 SHOW_STR
3479 "Policy-Based Routing\n"
3480 "IPtable Context information\n"
3481 "IPtable Name information\n")
3482 {
3483 int idx = 0;
3484 int found = 0;
3485
3486 found = argv_find(argv, argc, "WORD", &idx);
3487 if (!found)
3488 zebra_pbr_show_iptable(vty, NULL);
3489 else
3490 zebra_pbr_show_iptable(vty, argv[idx]->arg);
3491 return CMD_SUCCESS;
3492 }
3493
3494 /* Static ip route configuration write function. */
3495 static int zebra_ip_config(struct vty *vty)
3496 {
3497 int write = 0;
3498
3499 write += zebra_import_table_config(vty);
3500
3501 return write;
3502 }
3503
3504 DEFUN (ip_zebra_import_table_distance,
3505 ip_zebra_import_table_distance_cmd,
3506 "ip import-table (1-252) [distance (1-255)] [route-map WORD]",
3507 IP_STR
3508 "import routes from non-main kernel table\n"
3509 "kernel routing table id\n"
3510 "Distance for imported routes\n"
3511 "Default distance value\n"
3512 "route-map for filtering\n"
3513 "route-map name\n")
3514 {
3515 uint32_t table_id = 0;
3516
3517 table_id = strtoul(argv[2]->arg, NULL, 10);
3518 int distance = ZEBRA_TABLE_DISTANCE_DEFAULT;
3519 char *rmap =
3520 strmatch(argv[argc - 2]->text, "route-map")
3521 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg)
3522 : NULL;
3523 int ret;
3524
3525 if (argc == 7 || (argc == 5 && !rmap))
3526 distance = strtoul(argv[4]->arg, NULL, 10);
3527
3528 if (!is_zebra_valid_kernel_table(table_id)) {
3529 vty_out(vty,
3530 "Invalid routing table ID, %d. Must be in range 1-252\n",
3531 table_id);
3532 if (rmap)
3533 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3534 return CMD_WARNING;
3535 }
3536
3537 if (is_zebra_main_routing_table(table_id)) {
3538 vty_out(vty,
3539 "Invalid routing table ID, %d. Must be non-default table\n",
3540 table_id);
3541 if (rmap)
3542 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3543 return CMD_WARNING;
3544 }
3545
3546 ret = zebra_import_table(AFI_IP, table_id, distance, rmap, 1);
3547 if (rmap)
3548 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3549
3550 return ret;
3551 }
3552
3553 DEFUN_HIDDEN (zebra_packet_process,
3554 zebra_packet_process_cmd,
3555 "zebra zapi-packets (1-10000)",
3556 ZEBRA_STR
3557 "Zapi Protocol\n"
3558 "Number of packets to process before relinquishing thread\n")
3559 {
3560 uint32_t packets = strtoul(argv[2]->arg, NULL, 10);
3561
3562 atomic_store_explicit(&zebrad.packets_to_process, packets,
3563 memory_order_relaxed);
3564
3565 return CMD_SUCCESS;
3566 }
3567
3568 DEFUN_HIDDEN (no_zebra_packet_process,
3569 no_zebra_packet_process_cmd,
3570 "no zebra zapi-packets [(1-10000)]",
3571 NO_STR
3572 ZEBRA_STR
3573 "Zapi Protocol\n"
3574 "Number of packets to process before relinquishing thread\n")
3575 {
3576 atomic_store_explicit(&zebrad.packets_to_process,
3577 ZEBRA_ZAPI_PACKETS_TO_PROCESS,
3578 memory_order_relaxed);
3579
3580 return CMD_SUCCESS;
3581 }
3582
3583 DEFUN_HIDDEN (zebra_workqueue_timer,
3584 zebra_workqueue_timer_cmd,
3585 "zebra work-queue (0-10000)",
3586 ZEBRA_STR
3587 "Work Queue\n"
3588 "Time in milliseconds\n")
3589 {
3590 uint32_t timer = strtoul(argv[2]->arg, NULL, 10);
3591 zebrad.ribq->spec.hold = timer;
3592
3593 return CMD_SUCCESS;
3594 }
3595
3596 DEFUN_HIDDEN (no_zebra_workqueue_timer,
3597 no_zebra_workqueue_timer_cmd,
3598 "no zebra work-queue [(0-10000)]",
3599 NO_STR
3600 ZEBRA_STR
3601 "Work Queue\n"
3602 "Time in milliseconds\n")
3603 {
3604 zebrad.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
3605
3606 return CMD_SUCCESS;
3607 }
3608
3609 DEFUN (no_ip_zebra_import_table,
3610 no_ip_zebra_import_table_cmd,
3611 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3612 NO_STR
3613 IP_STR
3614 "import routes from non-main kernel table\n"
3615 "kernel routing table id\n"
3616 "Distance for imported routes\n"
3617 "Default distance value\n"
3618 "route-map for filtering\n"
3619 "route-map name\n")
3620 {
3621 uint32_t table_id = 0;
3622 table_id = strtoul(argv[3]->arg, NULL, 10);
3623
3624 if (!is_zebra_valid_kernel_table(table_id)) {
3625 vty_out(vty,
3626 "Invalid routing table ID. Must be in range 1-252\n");
3627 return CMD_WARNING;
3628 }
3629
3630 if (is_zebra_main_routing_table(table_id)) {
3631 vty_out(vty,
3632 "Invalid routing table ID, %d. Must be non-default table\n",
3633 table_id);
3634 return CMD_WARNING;
3635 }
3636
3637 if (!is_zebra_import_table_enabled(AFI_IP, table_id))
3638 return CMD_SUCCESS;
3639
3640 return (zebra_import_table(AFI_IP, table_id, 0, NULL, 0));
3641 }
3642
3643 static int config_write_protocol(struct vty *vty)
3644 {
3645 if (allow_delete)
3646 vty_out(vty, "allow-external-route-update\n");
3647
3648 if (zebra_rnh_ip_default_route)
3649 vty_out(vty, "ip nht resolve-via-default\n");
3650
3651 if (zebra_rnh_ipv6_default_route)
3652 vty_out(vty, "ipv6 nht resolve-via-default\n");
3653
3654 if (zebrad.ribq->spec.hold != ZEBRA_RIB_PROCESS_HOLD_TIME)
3655 vty_out(vty, "zebra work-queue %u\n", zebrad.ribq->spec.hold);
3656
3657 if (zebrad.packets_to_process != ZEBRA_ZAPI_PACKETS_TO_PROCESS)
3658 vty_out(vty, "zebra zapi-packets %u\n",
3659 zebrad.packets_to_process);
3660
3661 enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get();
3662
3663 if (ipv4_multicast_mode != MCAST_NO_CONFIG)
3664 vty_out(vty, "ip multicast rpf-lookup-mode %s\n",
3665 ipv4_multicast_mode == MCAST_URIB_ONLY
3666 ? "urib-only"
3667 : ipv4_multicast_mode == MCAST_MRIB_ONLY
3668 ? "mrib-only"
3669 : ipv4_multicast_mode
3670 == MCAST_MIX_MRIB_FIRST
3671 ? "mrib-then-urib"
3672 : ipv4_multicast_mode
3673 == MCAST_MIX_DISTANCE
3674 ? "lower-distance"
3675 : "longer-prefix");
3676
3677 zebra_routemap_config_write_protocol(vty);
3678
3679 return 1;
3680 }
3681
3682 #ifdef HAVE_NETLINK
3683 /* Display default rtm_table for all clients. */
3684 DEFUN (show_table,
3685 show_table_cmd,
3686 "show table",
3687 SHOW_STR
3688 "default routing table to use for all clients\n")
3689 {
3690 vty_out(vty, "table %d\n", zebrad.rtm_table_default);
3691 return CMD_SUCCESS;
3692 }
3693
3694 DEFUN (config_table,
3695 config_table_cmd,
3696 "table TABLENO",
3697 "Configure target kernel routing table\n"
3698 "TABLE integer\n")
3699 {
3700 zebrad.rtm_table_default = strtol(argv[1]->arg, (char **)0, 10);
3701 return CMD_SUCCESS;
3702 }
3703
3704 DEFUN (no_config_table,
3705 no_config_table_cmd,
3706 "no table [TABLENO]",
3707 NO_STR
3708 "Configure target kernel routing table\n"
3709 "TABLE integer\n")
3710 {
3711 zebrad.rtm_table_default = 0;
3712 return CMD_SUCCESS;
3713 }
3714 #endif
3715
3716 DEFUN (show_zebra,
3717 show_zebra_cmd,
3718 "show zebra",
3719 SHOW_STR
3720 ZEBRA_STR)
3721 {
3722 struct vrf *vrf;
3723
3724 vty_out(vty,
3725 " Route Route Neighbor LSP LSP\n");
3726 vty_out(vty,
3727 "VRF Installs Removals Updates Installs Removals\n");
3728
3729 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3730 struct zebra_vrf *zvrf = vrf->info;
3731
3732 vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64
3733 " %10" PRIu64 " %10" PRIu64 "\n",
3734 vrf->name, zvrf->installs, zvrf->removals,
3735 zvrf->neigh_updates, zvrf->lsp_installs,
3736 zvrf->lsp_removals);
3737 }
3738
3739 return CMD_SUCCESS;
3740 }
3741
3742 DEFUN (ip_forwarding,
3743 ip_forwarding_cmd,
3744 "ip forwarding",
3745 IP_STR
3746 "Turn on IP forwarding\n")
3747 {
3748 int ret;
3749
3750 ret = ipforward();
3751 if (ret == 0)
3752 ret = ipforward_on();
3753
3754 if (ret == 0) {
3755 vty_out(vty, "Can't turn on IP forwarding\n");
3756 return CMD_WARNING_CONFIG_FAILED;
3757 }
3758
3759 return CMD_SUCCESS;
3760 }
3761
3762 DEFUN (no_ip_forwarding,
3763 no_ip_forwarding_cmd,
3764 "no ip forwarding",
3765 NO_STR
3766 IP_STR
3767 "Turn off IP forwarding\n")
3768 {
3769 int ret;
3770
3771 ret = ipforward();
3772 if (ret != 0)
3773 ret = ipforward_off();
3774
3775 if (ret != 0) {
3776 vty_out(vty, "Can't turn off IP forwarding\n");
3777 return CMD_WARNING_CONFIG_FAILED;
3778 }
3779
3780 return CMD_SUCCESS;
3781 }
3782
3783 /* Only display ip forwarding is enabled or not. */
3784 DEFUN (show_ip_forwarding,
3785 show_ip_forwarding_cmd,
3786 "show ip forwarding",
3787 SHOW_STR
3788 IP_STR
3789 "IP forwarding status\n")
3790 {
3791 int ret;
3792
3793 ret = ipforward();
3794
3795 if (ret == 0)
3796 vty_out(vty, "IP forwarding is off\n");
3797 else
3798 vty_out(vty, "IP forwarding is on\n");
3799 return CMD_SUCCESS;
3800 }
3801
3802 /* Only display ipv6 forwarding is enabled or not. */
3803 DEFUN (show_ipv6_forwarding,
3804 show_ipv6_forwarding_cmd,
3805 "show ipv6 forwarding",
3806 SHOW_STR
3807 "IPv6 information\n"
3808 "Forwarding status\n")
3809 {
3810 int ret;
3811
3812 ret = ipforward_ipv6();
3813
3814 switch (ret) {
3815 case -1:
3816 vty_out(vty, "ipv6 forwarding is unknown\n");
3817 break;
3818 case 0:
3819 vty_out(vty, "ipv6 forwarding is %s\n", "off");
3820 break;
3821 case 1:
3822 vty_out(vty, "ipv6 forwarding is %s\n", "on");
3823 break;
3824 default:
3825 vty_out(vty, "ipv6 forwarding is %s\n", "off");
3826 break;
3827 }
3828 return CMD_SUCCESS;
3829 }
3830
3831 DEFUN (ipv6_forwarding,
3832 ipv6_forwarding_cmd,
3833 "ipv6 forwarding",
3834 IPV6_STR
3835 "Turn on IPv6 forwarding\n")
3836 {
3837 int ret;
3838
3839 ret = ipforward_ipv6();
3840 if (ret == 0)
3841 ret = ipforward_ipv6_on();
3842
3843 if (ret == 0) {
3844 vty_out(vty, "Can't turn on IPv6 forwarding\n");
3845 return CMD_WARNING_CONFIG_FAILED;
3846 }
3847
3848 return CMD_SUCCESS;
3849 }
3850
3851 DEFUN (no_ipv6_forwarding,
3852 no_ipv6_forwarding_cmd,
3853 "no ipv6 forwarding",
3854 NO_STR
3855 IPV6_STR
3856 "Turn off IPv6 forwarding\n")
3857 {
3858 int ret;
3859
3860 ret = ipforward_ipv6();
3861 if (ret != 0)
3862 ret = ipforward_ipv6_off();
3863
3864 if (ret != 0) {
3865 vty_out(vty, "Can't turn off IPv6 forwarding\n");
3866 return CMD_WARNING_CONFIG_FAILED;
3867 }
3868
3869 return CMD_SUCCESS;
3870 }
3871
3872 /* Table configuration write function. */
3873 static int config_write_table(struct vty *vty)
3874 {
3875 if (zebrad.rtm_table_default)
3876 vty_out(vty, "table %d\n", zebrad.rtm_table_default);
3877 return 0;
3878 }
3879
3880 /* IPForwarding configuration write function. */
3881 static int config_write_forwarding(struct vty *vty)
3882 {
3883 /* FIXME: Find better place for that. */
3884 router_id_write(vty);
3885
3886 if (!ipforward())
3887 vty_out(vty, "no ip forwarding\n");
3888 if (!ipforward_ipv6())
3889 vty_out(vty, "no ipv6 forwarding\n");
3890 vty_out(vty, "!\n");
3891 return 0;
3892 }
3893
3894 /* IP node for static routes. */
3895 static struct cmd_node ip_node = {IP_NODE, "", 1};
3896 static struct cmd_node protocol_node = {PROTOCOL_NODE, "", 1};
3897 /* table node for routing tables. */
3898 static struct cmd_node table_node = {TABLE_NODE,
3899 "", /* This node has no interface. */
3900 1};
3901 static struct cmd_node forwarding_node = {FORWARDING_NODE,
3902 "", /* This node has no interface. */
3903 1};
3904
3905 /* Route VTY. */
3906 void zebra_vty_init(void)
3907 {
3908 /* Install configuration write function. */
3909 install_node(&table_node, config_write_table);
3910 install_node(&forwarding_node, config_write_forwarding);
3911
3912 install_element(VIEW_NODE, &show_ip_forwarding_cmd);
3913 install_element(CONFIG_NODE, &ip_forwarding_cmd);
3914 install_element(CONFIG_NODE, &no_ip_forwarding_cmd);
3915 install_element(ENABLE_NODE, &show_zebra_cmd);
3916
3917 #ifdef HAVE_NETLINK
3918 install_element(VIEW_NODE, &show_table_cmd);
3919 install_element(CONFIG_NODE, &config_table_cmd);
3920 install_element(CONFIG_NODE, &no_config_table_cmd);
3921 #endif /* HAVE_NETLINK */
3922
3923 install_element(VIEW_NODE, &show_ipv6_forwarding_cmd);
3924 install_element(CONFIG_NODE, &ipv6_forwarding_cmd);
3925 install_element(CONFIG_NODE, &no_ipv6_forwarding_cmd);
3926
3927 /* Route-map */
3928 zebra_route_map_init();
3929
3930 install_node(&ip_node, zebra_ip_config);
3931 install_node(&protocol_node, config_write_protocol);
3932
3933 install_element(CONFIG_NODE, &allow_external_route_update_cmd);
3934 install_element(CONFIG_NODE, &no_allow_external_route_update_cmd);
3935 install_element(CONFIG_NODE, &ip_mroute_dist_cmd);
3936 install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
3937 install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
3938 install_element(CONFIG_NODE, &ip_route_blackhole_cmd);
3939 install_element(CONFIG_NODE,
3940 &ip_route_address_interface_cmd);
3941 install_element(CONFIG_NODE, &ip_route_cmd);
3942 install_element(VRF_NODE, &ip_route_blackhole_vrf_cmd);
3943 install_element(VRF_NODE, &ip_route_address_interface_vrf_cmd);
3944 install_element(VRF_NODE, &ip_route_vrf_cmd);
3945
3946 install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
3947 install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
3948 install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);
3949 install_element(CONFIG_NODE, &no_zebra_workqueue_timer_cmd);
3950 install_element(CONFIG_NODE, &zebra_packet_process_cmd);
3951 install_element(CONFIG_NODE, &no_zebra_packet_process_cmd);
3952
3953 install_element(VIEW_NODE, &show_vrf_cmd);
3954 install_element(VIEW_NODE, &show_vrf_vni_cmd);
3955 install_element(VIEW_NODE, &show_route_cmd);
3956 install_element(VIEW_NODE, &show_route_table_cmd);
3957 if (vrf_is_backend_netns())
3958 install_element(VIEW_NODE, &show_route_table_vrf_cmd);
3959 install_element(VIEW_NODE, &show_route_detail_cmd);
3960 install_element(VIEW_NODE, &show_route_summary_cmd);
3961 install_element(VIEW_NODE, &show_ip_nht_cmd);
3962 install_element(VIEW_NODE, &show_ip_nht_vrf_all_cmd);
3963 install_element(VIEW_NODE, &show_ipv6_nht_cmd);
3964 install_element(VIEW_NODE, &show_ipv6_nht_vrf_all_cmd);
3965
3966 install_element(VIEW_NODE, &show_ip_rpf_cmd);
3967 install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
3968
3969 install_element(CONFIG_NODE,
3970 &ipv6_route_blackhole_cmd);
3971 install_element(CONFIG_NODE,
3972 &ipv6_route_address_interface_cmd);
3973 install_element(CONFIG_NODE, &ipv6_route_cmd);
3974 install_element(VRF_NODE, &ipv6_route_blackhole_vrf_cmd);
3975 install_element(VRF_NODE,
3976 &ipv6_route_address_interface_vrf_cmd);
3977 install_element(VRF_NODE, &ipv6_route_vrf_cmd);
3978 install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
3979 install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
3980 install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
3981 install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd);
3982 install_element(VIEW_NODE, &show_ipv6_mroute_cmd);
3983
3984 /* Commands for VRF */
3985 install_element(VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd);
3986
3987 install_element(VIEW_NODE, &show_evpn_global_cmd);
3988 install_element(VIEW_NODE, &show_evpn_vni_cmd);
3989 install_element(VIEW_NODE, &show_evpn_vni_vni_cmd);
3990 install_element(VIEW_NODE, &show_evpn_rmac_vni_mac_cmd);
3991 install_element(VIEW_NODE, &show_evpn_rmac_vni_cmd);
3992 install_element(VIEW_NODE, &show_evpn_rmac_vni_all_cmd);
3993 install_element(VIEW_NODE, &show_evpn_nh_vni_ip_cmd);
3994 install_element(VIEW_NODE, &show_evpn_nh_vni_cmd);
3995 install_element(VIEW_NODE, &show_evpn_nh_vni_all_cmd);
3996 install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
3997 install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
3998 install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
3999 install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
4000 install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
4001 install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
4002 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
4003 install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
4004 install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
4005
4006 install_element(VIEW_NODE, &show_pbr_ipset_cmd);
4007 install_element(VIEW_NODE, &show_pbr_iptable_cmd);
4008
4009 install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
4010 install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
4011 install_element(VRF_NODE, &vrf_vni_mapping_cmd);
4012 install_element(VRF_NODE, &no_vrf_vni_mapping_cmd);
4013
4014 static_list = list_new();
4015 static_list->cmp = (int (*)(void *, void *))static_list_compare;
4016 static_list->del = (void (*)(void *))static_list_delete;
4017 }