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