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