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