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