]> git.proxmox.com Git - mirror_frr.git/blame - staticd/static_vty.c
staticd: add debug static bfd command
[mirror_frr.git] / staticd / static_vty.c
CommitLineData
7e24fdf3
DS
1/*
2 * STATICd - vty code
3 * Copyright (C) 2018 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
8d5cbee9
DS
6 * This program 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 Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
7e24fdf3 10 *
8d5cbee9
DS
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
7e24fdf3
DS
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20#include <zebra.h>
21
22#include "command.h"
23#include "vty.h"
24#include "vrf.h"
25#include "prefix.h"
26#include "nexthop.h"
27#include "table.h"
28#include "srcdest_table.h"
29#include "mpls.h"
88fa5104 30#include "northbound.h"
31#include "libfrr.h"
32#include "routing_nb.h"
33#include "northbound_cli.h"
7e24fdf3
DS
34
35#include "static_vrf.h"
7e24fdf3
DS
36#include "static_vty.h"
37#include "static_routes.h"
31ddf3b7 38#include "static_debug.h"
7e24fdf3 39#include "staticd/static_vty_clippy.c"
88fa5104 40#include "static_nb.h"
31ddf3b7
MS
41
42#define STATICD_STR "Static route daemon\n"
43
fc6f9d74
RZ
44/** All possible route parameters available in CLI. */
45struct static_route_args {
46 /** "no" command? */
47 bool delete;
48 /** Is VRF obtained from XPath? */
49 bool xpath_vrf;
50
51 bool onlink;
52 afi_t afi;
53 safi_t safi;
54
55 const char *vrf;
56 const char *nexthop_vrf;
57 const char *prefix;
58 const char *prefix_mask;
59 const char *source;
60 const char *gateway;
61 const char *interface_name;
62 const char *flag;
63 const char *tag;
64 const char *distance;
65 const char *label;
66 const char *table;
67 const char *color;
e280279d
RZ
68
69 bool bfd;
70 bool bfd_multi_hop;
71 const char *bfd_source;
72 const char *bfd_profile;
fc6f9d74
RZ
73};
74
75static int static_route_nb_run(struct vty *vty, struct static_route_args *args)
7e24fdf3 76{
7e24fdf3 77 int ret;
7e24fdf3 78 struct prefix p, src;
7e24fdf3 79 struct in_addr mask;
9ccaa12d 80 enum static_nh_type type;
88fa5104 81 const char *bh_type;
82 char xpath_prefix[XPATH_MAXLEN];
83 char xpath_nexthop[XPATH_MAXLEN];
84 char xpath_mpls[XPATH_MAXLEN];
85 char xpath_label[XPATH_MAXLEN];
86 char ab_xpath[XPATH_MAXLEN];
87 char buf_prefix[PREFIX_STRLEN];
fc6f9d74
RZ
88 char buf_src_prefix[PREFIX_STRLEN] = {};
89 char buf_nh_type[PREFIX_STRLEN] = {};
88fa5104 90 char buf_tag[PREFIX_STRLEN];
88fa5104 91 uint8_t label_stack_id = 0;
92 const char *buf_gate_str;
93 uint8_t distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
94 route_tag_t tag = 0;
7e24fdf3 95 uint32_t table_id = 0;
88fa5104 96 const struct lyd_node *dnode;
fc6f9d74 97 const struct lyd_node *vrf_dnode;
88fa5104 98
fc6f9d74
RZ
99 if (args->xpath_vrf) {
100 vrf_dnode = yang_dnode_get(vty->candidate_config->dnode,
101 VTY_CURR_XPATH);
102 if (vrf_dnode == NULL) {
103 vty_out(vty,
104 "%% Failed to get vrf dnode in candidate db\n");
105 return CMD_WARNING_CONFIG_FAILED;
106 }
7e24fdf3 107
fc6f9d74
RZ
108 args->vrf = yang_dnode_get_string(vrf_dnode, "./name");
109 } else {
110 if (args->vrf == NULL)
111 args->vrf = VRF_DEFAULT_NAME;
7e24fdf3 112 }
fc6f9d74
RZ
113 if (args->nexthop_vrf == NULL)
114 args->nexthop_vrf = args->vrf;
7e24fdf3 115
fc6f9d74
RZ
116 if (args->interface_name &&
117 !strcasecmp(args->interface_name, "Null0")) {
118 args->flag = "Null0";
119 args->interface_name = NULL;
120 }
121
122 assert(!!str2prefix(args->prefix, &p));
123
124 switch (args->afi) {
7e24fdf3
DS
125 case AFI_IP:
126 /* Cisco like mask notation. */
fc6f9d74
RZ
127 if (args->prefix_mask) {
128 assert(inet_pton(AF_INET, args->prefix_mask, &mask) ==
129 1);
7e24fdf3
DS
130 p.prefixlen = ip_masklen(mask);
131 }
132 break;
133 case AFI_IP6:
134 /* srcdest routing */
fc6f9d74
RZ
135 if (args->source)
136 assert(!!str2prefix(args->source, &src));
7e24fdf3
DS
137 break;
138 default:
139 break;
140 }
141
142 /* Apply mask for given prefix. */
143 apply_mask(&p);
88fa5104 144 prefix2str(&p, buf_prefix, sizeof(buf_prefix));
7e24fdf3 145
e280279d
RZ
146 if (args->bfd && args->gateway == NULL) {
147 vty_out(vty, "%% Route monitoring requires a gateway\n");
148 return CMD_WARNING_CONFIG_FAILED;
149 }
150
fc6f9d74 151 if (args->source)
88fa5104 152 prefix2str(&src, buf_src_prefix, sizeof(buf_src_prefix));
fc6f9d74
RZ
153 if (args->gateway)
154 buf_gate_str = args->gateway;
88fa5104 155 else
156 buf_gate_str = "";
157
fc6f9d74 158 if (args->gateway == NULL && args->interface_name == NULL)
88fa5104 159 type = STATIC_BLACKHOLE;
fc6f9d74
RZ
160 else if (args->gateway && args->interface_name) {
161 if (args->afi == AFI_IP)
88fa5104 162 type = STATIC_IPV4_GATEWAY_IFNAME;
163 else
164 type = STATIC_IPV6_GATEWAY_IFNAME;
fc6f9d74 165 } else if (args->interface_name)
88fa5104 166 type = STATIC_IFNAME;
167 else {
fc6f9d74 168 if (args->afi == AFI_IP)
88fa5104 169 type = STATIC_IPV4_GATEWAY;
170 else
171 type = STATIC_IPV6_GATEWAY;
7e24fdf3
DS
172 }
173
174 /* Administrative distance. */
fc6f9d74
RZ
175 if (args->distance)
176 distance = strtol(args->distance, NULL, 10);
7e24fdf3
DS
177
178 /* tag */
fc6f9d74
RZ
179 if (args->tag)
180 tag = strtoul(args->tag, NULL, 10);
7e24fdf3 181
7e24fdf3 182 /* TableID */
fc6f9d74
RZ
183 if (args->table)
184 table_id = strtol(args->table, NULL, 10);
7e24fdf3 185
fc6f9d74
RZ
186 static_get_nh_type(type, buf_nh_type, sizeof(buf_nh_type));
187 if (!args->delete) {
188 if (args->source)
e1ea6b20
IR
189 snprintf(ab_xpath, sizeof(ab_xpath),
190 FRR_DEL_S_ROUTE_SRC_NH_KEY_NO_DISTANCE_XPATH,
fc6f9d74 191 "frr-staticd:staticd", "staticd", args->vrf,
e1ea6b20 192 buf_prefix,
fc6f9d74
RZ
193 yang_afi_safi_value2identity(args->afi,
194 args->safi),
195 buf_src_prefix, table_id, buf_nh_type,
196 args->nexthop_vrf, buf_gate_str,
197 args->interface_name);
e1ea6b20
IR
198 else
199 snprintf(ab_xpath, sizeof(ab_xpath),
200 FRR_DEL_S_ROUTE_NH_KEY_NO_DISTANCE_XPATH,
fc6f9d74 201 "frr-staticd:staticd", "staticd", args->vrf,
e1ea6b20 202 buf_prefix,
fc6f9d74
RZ
203 yang_afi_safi_value2identity(args->afi,
204 args->safi),
205 table_id, buf_nh_type, args->nexthop_vrf,
206 buf_gate_str, args->interface_name);
e1ea6b20
IR
207
208 /*
209 * If there's already the same nexthop but with a different
210 * distance, then remove it for the replacement.
211 */
212 dnode = yang_dnode_get(vty->candidate_config->dnode, ab_xpath);
213 if (dnode) {
214 dnode = yang_get_subtree_with_no_sibling(dnode);
215 assert(dnode);
216 yang_dnode_get_path(dnode, ab_xpath, XPATH_MAXLEN);
217
218 nb_cli_enqueue_change(vty, ab_xpath, NB_OP_DESTROY,
219 NULL);
220 }
221
88fa5104 222 /* route + path procesing */
fc6f9d74 223 if (args->source)
88fa5104 224 snprintf(xpath_prefix, sizeof(xpath_prefix),
225 FRR_S_ROUTE_SRC_INFO_KEY_XPATH,
fc6f9d74 226 "frr-staticd:staticd", "staticd", args->vrf,
88fa5104 227 buf_prefix,
fc6f9d74
RZ
228 yang_afi_safi_value2identity(args->afi,
229 args->safi),
ef4b6b22 230 buf_src_prefix, table_id, distance);
88fa5104 231 else
232 snprintf(xpath_prefix, sizeof(xpath_prefix),
233 FRR_STATIC_ROUTE_INFO_KEY_XPATH,
fc6f9d74 234 "frr-staticd:staticd", "staticd", args->vrf,
88fa5104 235 buf_prefix,
fc6f9d74
RZ
236 yang_afi_safi_value2identity(args->afi,
237 args->safi),
ef4b6b22 238 table_id, distance);
88fa5104 239
240 nb_cli_enqueue_change(vty, xpath_prefix, NB_OP_CREATE, NULL);
241
242 /* Tag processing */
243 snprintf(buf_tag, sizeof(buf_tag), "%u", tag);
244 strlcpy(ab_xpath, xpath_prefix, sizeof(ab_xpath));
245 strlcat(ab_xpath, FRR_STATIC_ROUTE_PATH_TAG_XPATH,
246 sizeof(ab_xpath));
247 nb_cli_enqueue_change(vty, ab_xpath, NB_OP_MODIFY, buf_tag);
248
88fa5104 249 /* nexthop processing */
250
251 snprintf(ab_xpath, sizeof(ab_xpath),
fc6f9d74
RZ
252 FRR_STATIC_ROUTE_NH_KEY_XPATH, buf_nh_type,
253 args->nexthop_vrf, buf_gate_str, args->interface_name);
88fa5104 254 strlcpy(xpath_nexthop, xpath_prefix, sizeof(xpath_nexthop));
255 strlcat(xpath_nexthop, ab_xpath, sizeof(xpath_nexthop));
256 nb_cli_enqueue_change(vty, xpath_nexthop, NB_OP_CREATE, NULL);
257
258 if (type == STATIC_BLACKHOLE) {
259 strlcpy(ab_xpath, xpath_nexthop, sizeof(ab_xpath));
260 strlcat(ab_xpath, FRR_STATIC_ROUTE_NH_BH_XPATH,
261 sizeof(ab_xpath));
262
263 /* Route flags */
fc6f9d74
RZ
264 if (args->flag) {
265 switch (args->flag[0]) {
88fa5104 266 case 'r':
267 bh_type = "reject";
268 break;
269 case 'b':
270 bh_type = "unspec";
271 break;
272 case 'N':
273 bh_type = "null";
274 break;
275 default:
276 bh_type = NULL;
277 break;
278 }
279 nb_cli_enqueue_change(vty, ab_xpath,
280 NB_OP_MODIFY, bh_type);
281 } else {
282 nb_cli_enqueue_change(vty, ab_xpath,
283 NB_OP_MODIFY, "null");
284 }
7e24fdf3 285 }
88fa5104 286 if (type == STATIC_IPV4_GATEWAY_IFNAME
287 || type == STATIC_IPV6_GATEWAY_IFNAME) {
288 strlcpy(ab_xpath, xpath_nexthop, sizeof(ab_xpath));
289 strlcat(ab_xpath, FRR_STATIC_ROUTE_NH_ONLINK_XPATH,
290 sizeof(ab_xpath));
291
fc6f9d74 292 if (args->onlink)
88fa5104 293 nb_cli_enqueue_change(vty, ab_xpath,
294 NB_OP_MODIFY, "true");
7e24fdf3 295 else
88fa5104 296 nb_cli_enqueue_change(vty, ab_xpath,
297 NB_OP_MODIFY, "false");
7e24fdf3 298 }
065276ae
SM
299 if (type == STATIC_IPV4_GATEWAY
300 || type == STATIC_IPV6_GATEWAY
301 || type == STATIC_IPV4_GATEWAY_IFNAME
302 || type == STATIC_IPV6_GATEWAY_IFNAME) {
303 strlcpy(ab_xpath, xpath_nexthop, sizeof(ab_xpath));
304 strlcat(ab_xpath, FRR_STATIC_ROUTE_NH_COLOR_XPATH,
305 sizeof(ab_xpath));
fc6f9d74 306 if (args->color)
77463bc8 307 nb_cli_enqueue_change(vty, ab_xpath,
fc6f9d74
RZ
308 NB_OP_MODIFY,
309 args->color);
065276ae 310 }
fc6f9d74 311 if (args->label) {
88fa5104 312 /* copy of label string (start) */
313 char *ostr;
314 /* pointer to next segment */
315 char *nump;
316
317 strlcpy(xpath_mpls, xpath_nexthop, sizeof(xpath_mpls));
318 strlcat(xpath_mpls, FRR_STATIC_ROUTE_NH_LABEL_XPATH,
319 sizeof(xpath_mpls));
320
321 nb_cli_enqueue_change(vty, xpath_mpls, NB_OP_DESTROY,
322 NULL);
323
fc6f9d74 324 ostr = XSTRDUP(MTYPE_TMP, args->label);
88fa5104 325 while ((nump = strsep(&ostr, "/")) != NULL) {
326 snprintf(ab_xpath, sizeof(ab_xpath),
327 FRR_STATIC_ROUTE_NHLB_KEY_XPATH,
328 label_stack_id);
329 strlcpy(xpath_label, xpath_mpls,
330 sizeof(xpath_label));
331 strlcat(xpath_label, ab_xpath,
332 sizeof(xpath_label));
333 nb_cli_enqueue_change(vty, xpath_label,
334 NB_OP_MODIFY, nump);
335 label_stack_id++;
336 }
337 XFREE(MTYPE_TMP, ostr);
338 } else {
339 strlcpy(xpath_mpls, xpath_nexthop, sizeof(xpath_mpls));
340 strlcat(xpath_mpls, FRR_STATIC_ROUTE_NH_LABEL_XPATH,
341 sizeof(xpath_mpls));
342 nb_cli_enqueue_change(vty, xpath_mpls, NB_OP_DESTROY,
343 NULL);
b1ab2876 344 }
e280279d
RZ
345
346 if (args->bfd) {
347 char xpath_bfd[XPATH_MAXLEN];
348
349 if (args->bfd_source) {
350 strlcpy(xpath_bfd, xpath_nexthop,
351 sizeof(xpath_bfd));
352 strlcat(xpath_bfd,
353 "/frr-staticd:bfd-monitoring/source",
354 sizeof(xpath_bfd));
355 nb_cli_enqueue_change(vty, xpath_bfd,
356 NB_OP_MODIFY,
357 args->bfd_source);
358 }
359
360 strlcpy(xpath_bfd, xpath_nexthop, sizeof(xpath_bfd));
361 strlcat(xpath_bfd,
362 "/frr-staticd:bfd-monitoring/multi-hop",
363 sizeof(xpath_bfd));
364 nb_cli_enqueue_change(vty, xpath_bfd, NB_OP_MODIFY,
365 args->bfd_multi_hop ? "true"
366 : "false");
367
368 if (args->bfd_profile) {
369 strlcpy(xpath_bfd, xpath_nexthop,
370 sizeof(xpath_bfd));
371 strlcat(xpath_bfd,
372 "/frr-staticd:bfd-monitoring/profile",
373 sizeof(xpath_bfd));
374 nb_cli_enqueue_change(vty, xpath_bfd,
375 NB_OP_MODIFY,
376 args->bfd_profile);
377 }
378 }
379
88fa5104 380 ret = nb_cli_apply_changes(vty, xpath_prefix);
7e24fdf3 381 } else {
fc6f9d74 382 if (args->source)
88fa5104 383 snprintf(ab_xpath, sizeof(ab_xpath),
e1ea6b20 384 FRR_DEL_S_ROUTE_SRC_NH_KEY_NO_DISTANCE_XPATH,
fc6f9d74 385 "frr-staticd:staticd", "staticd", args->vrf,
88fa5104 386 buf_prefix,
fc6f9d74
RZ
387 yang_afi_safi_value2identity(args->afi,
388 args->safi),
389 buf_src_prefix, table_id, buf_nh_type,
390 args->nexthop_vrf, buf_gate_str,
391 args->interface_name);
88fa5104 392 else
393 snprintf(ab_xpath, sizeof(ab_xpath),
e1ea6b20 394 FRR_DEL_S_ROUTE_NH_KEY_NO_DISTANCE_XPATH,
fc6f9d74 395 "frr-staticd:staticd", "staticd", args->vrf,
88fa5104 396 buf_prefix,
fc6f9d74
RZ
397 yang_afi_safi_value2identity(args->afi,
398 args->safi),
399 table_id, buf_nh_type, args->nexthop_vrf,
400 buf_gate_str, args->interface_name);
88fa5104 401
402 dnode = yang_dnode_get(vty->candidate_config->dnode, ab_xpath);
ff0e8ee8 403 if (!dnode) {
65c99282
WC
404 vty_out(vty,
405 "%% Refusing to remove a non-existent route\n");
f4194241 406 return CMD_SUCCESS;
ff0e8ee8 407 }
88fa5104 408
409 dnode = yang_get_subtree_with_no_sibling(dnode);
410 assert(dnode);
411 yang_dnode_get_path(dnode, ab_xpath, XPATH_MAXLEN);
412
413 nb_cli_enqueue_change(vty, ab_xpath, NB_OP_DESTROY, NULL);
414 ret = nb_cli_apply_changes(vty, ab_xpath);
7e24fdf3
DS
415 }
416
88fa5104 417 return ret;
7e24fdf3 418}
7e24fdf3 419
7e24fdf3 420/* Static unicast routes for multicast RPF lookup. */
ca77b518 421DEFPY_YANG (ip_mroute_dist,
7e24fdf3 422 ip_mroute_dist_cmd,
e280279d
RZ
423 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [{"
424 "(1-255)$distance"
425 "|bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}]"
426 "}]",
7e24fdf3
DS
427 NO_STR
428 IP_STR
429 "Configure static unicast route into MRIB for multicast RPF lookup\n"
430 "IP destination prefix (e.g. 10.0.0.0/8)\n"
431 "Nexthop address\n"
432 "Nexthop interface name\n"
e280279d
RZ
433 "Distance\n"
434 BFD_INTEGRATION_STR
435 BFD_INTEGRATION_MULTI_HOP_STR
436 BFD_INTEGRATION_SOURCE_STR
437 BFD_INTEGRATION_SOURCEV4_STR
438 BFD_PROFILE_STR
439 BFD_PROFILE_NAME_STR)
7e24fdf3 440{
fc6f9d74
RZ
441 struct static_route_args args = {
442 .delete = !!no,
443 .afi = AFI_IP,
444 .safi = SAFI_MULTICAST,
445 .prefix = prefix_str,
446 .gateway = gate_str,
447 .interface_name = ifname,
448 .distance = distance_str,
e280279d
RZ
449 .bfd = !!bfd,
450 .bfd_multi_hop = !!bfd_multi_hop,
451 .bfd_source = bfd_source_str,
452 .bfd_profile = bfd_profile,
fc6f9d74
RZ
453 };
454
455 return static_route_nb_run(vty, &args);
7e24fdf3
DS
456}
457
458/* Static route configuration. */
ca77b518 459DEFPY_YANG(ip_route_blackhole,
7e24fdf3
DS
460 ip_route_blackhole_cmd,
461 "[no] ip route\
462 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
463 <reject|blackhole>$flag \
464 [{ \
465 tag (1-4294967295) \
466 |(1-255)$distance \
467 |vrf NAME \
468 |label WORD \
469 |table (1-4294967295) \
470 }]",
471 NO_STR IP_STR
472 "Establish static routes\n"
473 "IP destination prefix (e.g. 10.0.0.0/8)\n"
474 "IP destination prefix\n"
475 "IP destination prefix mask\n"
476 "Emit an ICMP unreachable when matched\n"
477 "Silently discard pkts when matched\n"
478 "Set tag for this route\n"
479 "Tag value\n"
480 "Distance value for this route\n"
481 VRF_CMD_HELP_STR
482 MPLS_LABEL_HELPSTR
483 "Table to configure\n"
484 "The table number to configure\n")
485{
fc6f9d74
RZ
486 struct static_route_args args = {
487 .delete = !!no,
488 .afi = AFI_IP,
489 .safi = SAFI_UNICAST,
490 .prefix = prefix,
491 .prefix_mask = mask_str,
492 .flag = flag,
493 .tag = tag_str,
494 .distance = distance_str,
495 .label = label,
496 .table = table_str,
497 .vrf = vrf,
498 };
499
500 return static_route_nb_run(vty, &args);
7e24fdf3
DS
501}
502
ca77b518 503DEFPY_YANG(ip_route_blackhole_vrf,
7e24fdf3
DS
504 ip_route_blackhole_vrf_cmd,
505 "[no] ip route\
506 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
507 <reject|blackhole>$flag \
508 [{ \
509 tag (1-4294967295) \
510 |(1-255)$distance \
511 |label WORD \
512 |table (1-4294967295) \
513 }]",
514 NO_STR IP_STR
515 "Establish static routes\n"
516 "IP destination prefix (e.g. 10.0.0.0/8)\n"
517 "IP destination prefix\n"
518 "IP destination prefix mask\n"
519 "Emit an ICMP unreachable when matched\n"
520 "Silently discard pkts when matched\n"
521 "Set tag for this route\n"
522 "Tag value\n"
523 "Distance value for this route\n"
524 MPLS_LABEL_HELPSTR
525 "Table to configure\n"
526 "The table number to configure\n")
527{
fc6f9d74
RZ
528 struct static_route_args args = {
529 .delete = !!no,
530 .afi = AFI_IP,
531 .safi = SAFI_UNICAST,
532 .prefix = prefix,
533 .prefix_mask = mask_str,
534 .flag = flag,
535 .tag = tag_str,
536 .distance = distance_str,
537 .label = label,
538 .table = table_str,
539 .xpath_vrf = true,
540 };
7e24fdf3 541
7e24fdf3
DS
542 /*
543 * Coverity is complaining that prefix could
544 * be dereferenced, but we know that prefix will
545 * valid. Add an assert to make it happy
546 */
fc6f9d74
RZ
547 assert(args.prefix);
548
549 return static_route_nb_run(vty, &args);
7e24fdf3
DS
550}
551
ca77b518 552DEFPY_YANG(ip_route_address_interface,
7e24fdf3
DS
553 ip_route_address_interface_cmd,
554 "[no] ip route\
555 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
556 A.B.C.D$gate \
54a3d7cb 557 <INTERFACE|Null0>$ifname \
7e24fdf3
DS
558 [{ \
559 tag (1-4294967295) \
560 |(1-255)$distance \
561 |vrf NAME \
562 |label WORD \
563 |table (1-4294967295) \
564 |nexthop-vrf NAME \
02dc8ba3 565 |onlink$onlink \
065276ae 566 |color (1-4294967295) \
e280279d 567 |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
7e24fdf3
DS
568 }]",
569 NO_STR IP_STR
570 "Establish static routes\n"
571 "IP destination prefix (e.g. 10.0.0.0/8)\n"
572 "IP destination prefix\n"
573 "IP destination prefix mask\n"
574 "IP gateway address\n"
54a3d7cb
QY
575 "IP gateway interface name\n"
576 "Null interface\n"
7e24fdf3
DS
577 "Set tag for this route\n"
578 "Tag value\n"
579 "Distance value for this route\n"
580 VRF_CMD_HELP_STR
581 MPLS_LABEL_HELPSTR
582 "Table to configure\n"
583 "The table number to configure\n"
02dc8ba3 584 VRF_CMD_HELP_STR
065276ae
SM
585 "Treat the nexthop as directly attached to the interface\n"
586 "SR-TE color\n"
e280279d
RZ
587 "The SR-TE color to configure\n"
588 BFD_INTEGRATION_STR
589 BFD_INTEGRATION_MULTI_HOP_STR
590 BFD_INTEGRATION_SOURCE_STR
591 BFD_INTEGRATION_SOURCEV4_STR
592 BFD_PROFILE_STR
593 BFD_PROFILE_NAME_STR)
7e24fdf3 594{
fc6f9d74
RZ
595 struct static_route_args args = {
596 .delete = !!no,
597 .afi = AFI_IP,
598 .safi = SAFI_UNICAST,
599 .prefix = prefix,
600 .prefix_mask = mask_str,
601 .gateway = gate_str,
602 .interface_name = ifname,
603 .tag = tag_str,
604 .distance = distance_str,
605 .label = label,
606 .table = table_str,
607 .color = color_str,
608 .onlink = !!onlink,
609 .vrf = vrf,
610 .nexthop_vrf = nexthop_vrf,
e280279d
RZ
611 .bfd = !!bfd,
612 .bfd_multi_hop = !!bfd_multi_hop,
613 .bfd_source = bfd_source_str,
614 .bfd_profile = bfd_profile,
fc6f9d74
RZ
615 };
616
617 return static_route_nb_run(vty, &args);
7e24fdf3
DS
618}
619
ca77b518 620DEFPY_YANG(ip_route_address_interface_vrf,
7e24fdf3
DS
621 ip_route_address_interface_vrf_cmd,
622 "[no] ip route\
623 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
624 A.B.C.D$gate \
54a3d7cb 625 <INTERFACE|Null0>$ifname \
7e24fdf3
DS
626 [{ \
627 tag (1-4294967295) \
628 |(1-255)$distance \
629 |label WORD \
630 |table (1-4294967295) \
631 |nexthop-vrf NAME \
02dc8ba3 632 |onlink$onlink \
065276ae 633 |color (1-4294967295) \
e280279d 634 |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
065276ae 635 }]",
7e24fdf3
DS
636 NO_STR IP_STR
637 "Establish static routes\n"
638 "IP destination prefix (e.g. 10.0.0.0/8)\n"
639 "IP destination prefix\n"
640 "IP destination prefix mask\n"
641 "IP gateway address\n"
54a3d7cb
QY
642 "IP gateway interface name\n"
643 "Null interface\n"
7e24fdf3
DS
644 "Set tag for this route\n"
645 "Tag value\n"
646 "Distance value for this route\n"
647 MPLS_LABEL_HELPSTR
648 "Table to configure\n"
649 "The table number to configure\n"
02dc8ba3 650 VRF_CMD_HELP_STR
065276ae
SM
651 "Treat the nexthop as directly attached to the interface\n"
652 "SR-TE color\n"
e280279d
RZ
653 "The SR-TE color to configure\n"
654 BFD_INTEGRATION_STR
655 BFD_INTEGRATION_MULTI_HOP_STR
656 BFD_INTEGRATION_SOURCE_STR
657 BFD_INTEGRATION_SOURCEV4_STR
658 BFD_PROFILE_STR
659 BFD_PROFILE_NAME_STR)
7e24fdf3 660{
fc6f9d74
RZ
661 struct static_route_args args = {
662 .delete = !!no,
663 .afi = AFI_IP,
664 .safi = SAFI_UNICAST,
665 .prefix = prefix,
666 .prefix_mask = mask_str,
667 .gateway = gate_str,
668 .interface_name = ifname,
669 .tag = tag_str,
670 .distance = distance_str,
671 .label = label,
672 .table = table_str,
673 .color = color_str,
674 .onlink = !!onlink,
675 .xpath_vrf = true,
676 .nexthop_vrf = nexthop_vrf,
e280279d
RZ
677 .bfd = !!bfd,
678 .bfd_multi_hop = !!bfd_multi_hop,
679 .bfd_source = bfd_source_str,
680 .bfd_profile = bfd_profile,
fc6f9d74
RZ
681 };
682
683 return static_route_nb_run(vty, &args);
7e24fdf3
DS
684}
685
ca77b518 686DEFPY_YANG(ip_route,
7e24fdf3
DS
687 ip_route_cmd,
688 "[no] ip route\
689 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
54a3d7cb 690 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
7e24fdf3
DS
691 [{ \
692 tag (1-4294967295) \
693 |(1-255)$distance \
694 |vrf NAME \
695 |label WORD \
696 |table (1-4294967295) \
697 |nexthop-vrf NAME \
065276ae 698 |color (1-4294967295) \
e280279d 699 |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
7e24fdf3
DS
700 }]",
701 NO_STR IP_STR
702 "Establish static routes\n"
703 "IP destination prefix (e.g. 10.0.0.0/8)\n"
704 "IP destination prefix\n"
705 "IP destination prefix mask\n"
706 "IP gateway address\n"
707 "IP gateway interface name\n"
54a3d7cb 708 "Null interface\n"
7e24fdf3
DS
709 "Set tag for this route\n"
710 "Tag value\n"
711 "Distance value for this route\n"
712 VRF_CMD_HELP_STR
713 MPLS_LABEL_HELPSTR
714 "Table to configure\n"
715 "The table number to configure\n"
065276ae
SM
716 VRF_CMD_HELP_STR
717 "SR-TE color\n"
e280279d
RZ
718 "The SR-TE color to configure\n"
719 BFD_INTEGRATION_STR
720 BFD_INTEGRATION_MULTI_HOP_STR
721 BFD_INTEGRATION_SOURCE_STR
722 BFD_INTEGRATION_SOURCEV4_STR
723 BFD_PROFILE_STR
724 BFD_PROFILE_NAME_STR)
7e24fdf3 725{
fc6f9d74
RZ
726 struct static_route_args args = {
727 .delete = !!no,
728 .afi = AFI_IP,
729 .safi = SAFI_UNICAST,
730 .prefix = prefix,
731 .prefix_mask = mask_str,
732 .gateway = gate_str,
733 .interface_name = ifname,
734 .tag = tag_str,
735 .distance = distance_str,
736 .label = label,
737 .table = table_str,
738 .color = color_str,
739 .vrf = vrf,
740 .nexthop_vrf = nexthop_vrf,
e280279d
RZ
741 .bfd = !!bfd,
742 .bfd_multi_hop = !!bfd_multi_hop,
743 .bfd_source = bfd_source_str,
744 .bfd_profile = bfd_profile,
fc6f9d74
RZ
745 };
746
747 return static_route_nb_run(vty, &args);
7e24fdf3
DS
748}
749
ca77b518 750DEFPY_YANG(ip_route_vrf,
7e24fdf3
DS
751 ip_route_vrf_cmd,
752 "[no] ip route\
753 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
54a3d7cb 754 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
7e24fdf3
DS
755 [{ \
756 tag (1-4294967295) \
757 |(1-255)$distance \
758 |label WORD \
759 |table (1-4294967295) \
760 |nexthop-vrf NAME \
065276ae 761 |color (1-4294967295) \
e280279d 762 |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
7e24fdf3
DS
763 }]",
764 NO_STR IP_STR
765 "Establish static routes\n"
766 "IP destination prefix (e.g. 10.0.0.0/8)\n"
767 "IP destination prefix\n"
768 "IP destination prefix mask\n"
769 "IP gateway address\n"
770 "IP gateway interface name\n"
54a3d7cb 771 "Null interface\n"
7e24fdf3
DS
772 "Set tag for this route\n"
773 "Tag value\n"
774 "Distance value for this route\n"
775 MPLS_LABEL_HELPSTR
776 "Table to configure\n"
777 "The table number to configure\n"
065276ae
SM
778 VRF_CMD_HELP_STR
779 "SR-TE color\n"
e280279d
RZ
780 "The SR-TE color to configure\n"
781 BFD_INTEGRATION_STR
782 BFD_INTEGRATION_MULTI_HOP_STR
783 BFD_INTEGRATION_SOURCE_STR
784 BFD_INTEGRATION_SOURCEV4_STR
785 BFD_PROFILE_STR
786 BFD_PROFILE_NAME_STR)
7e24fdf3 787{
fc6f9d74
RZ
788 struct static_route_args args = {
789 .delete = !!no,
790 .afi = AFI_IP,
791 .safi = SAFI_UNICAST,
792 .prefix = prefix,
793 .prefix_mask = mask_str,
794 .gateway = gate_str,
795 .interface_name = ifname,
796 .tag = tag_str,
797 .distance = distance_str,
798 .label = label,
799 .table = table_str,
800 .color = color_str,
801 .xpath_vrf = true,
802 .nexthop_vrf = nexthop_vrf,
e280279d
RZ
803 .bfd = !!bfd,
804 .bfd_multi_hop = !!bfd_multi_hop,
805 .bfd_source = bfd_source_str,
806 .bfd_profile = bfd_profile,
fc6f9d74
RZ
807 };
808
809 return static_route_nb_run(vty, &args);
7e24fdf3
DS
810}
811
ca77b518 812DEFPY_YANG(ipv6_route_blackhole,
7e24fdf3
DS
813 ipv6_route_blackhole_cmd,
814 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
54a3d7cb 815 <reject|blackhole>$flag \
7e24fdf3
DS
816 [{ \
817 tag (1-4294967295) \
818 |(1-255)$distance \
819 |vrf NAME \
820 |label WORD \
821 |table (1-4294967295) \
822 }]",
823 NO_STR
824 IPV6_STR
825 "Establish static routes\n"
826 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
827 "IPv6 source-dest route\n"
828 "IPv6 source prefix\n"
7e24fdf3
DS
829 "Emit an ICMP unreachable when matched\n"
830 "Silently discard pkts when matched\n"
831 "Set tag for this route\n"
832 "Tag value\n"
833 "Distance value for this prefix\n"
834 VRF_CMD_HELP_STR
835 MPLS_LABEL_HELPSTR
836 "Table to configure\n"
837 "The table number to configure\n")
838{
fc6f9d74
RZ
839 struct static_route_args args = {
840 .delete = !!no,
841 .afi = AFI_IP6,
842 .safi = SAFI_UNICAST,
843 .prefix = prefix_str,
844 .source = from_str,
845 .flag = flag,
846 .tag = tag_str,
847 .distance = distance_str,
848 .label = label,
849 .table = table_str,
850 .vrf = vrf,
851 };
852
853 return static_route_nb_run(vty, &args);
7e24fdf3
DS
854}
855
ca77b518 856DEFPY_YANG(ipv6_route_blackhole_vrf,
7e24fdf3
DS
857 ipv6_route_blackhole_vrf_cmd,
858 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
54a3d7cb 859 <reject|blackhole>$flag \
7e24fdf3
DS
860 [{ \
861 tag (1-4294967295) \
862 |(1-255)$distance \
863 |label WORD \
864 |table (1-4294967295) \
865 }]",
866 NO_STR
867 IPV6_STR
868 "Establish static routes\n"
869 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
870 "IPv6 source-dest route\n"
871 "IPv6 source prefix\n"
7e24fdf3
DS
872 "Emit an ICMP unreachable when matched\n"
873 "Silently discard pkts when matched\n"
874 "Set tag for this route\n"
875 "Tag value\n"
876 "Distance value for this prefix\n"
877 MPLS_LABEL_HELPSTR
878 "Table to configure\n"
879 "The table number to configure\n")
880{
fc6f9d74
RZ
881 struct static_route_args args = {
882 .delete = !!no,
883 .afi = AFI_IP6,
884 .safi = SAFI_UNICAST,
885 .prefix = prefix_str,
886 .source = from_str,
887 .flag = flag,
888 .tag = tag_str,
889 .distance = distance_str,
890 .label = label,
891 .table = table_str,
892 .xpath_vrf = true,
893 };
7e24fdf3
DS
894
895 /*
896 * Coverity is complaining that prefix could
897 * be dereferenced, but we know that prefix will
898 * valid. Add an assert to make it happy
899 */
fc6f9d74 900 assert(args.prefix);
88fa5104 901
fc6f9d74 902 return static_route_nb_run(vty, &args);
7e24fdf3
DS
903}
904
ca77b518 905DEFPY_YANG(ipv6_route_address_interface,
7e24fdf3
DS
906 ipv6_route_address_interface_cmd,
907 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
908 X:X::X:X$gate \
54a3d7cb 909 <INTERFACE|Null0>$ifname \
7e24fdf3
DS
910 [{ \
911 tag (1-4294967295) \
912 |(1-255)$distance \
913 |vrf NAME \
914 |label WORD \
915 |table (1-4294967295) \
916 |nexthop-vrf NAME \
02dc8ba3 917 |onlink$onlink \
065276ae 918 |color (1-4294967295) \
e280279d 919 |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
7e24fdf3
DS
920 }]",
921 NO_STR
922 IPV6_STR
923 "Establish static routes\n"
924 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
925 "IPv6 source-dest route\n"
926 "IPv6 source prefix\n"
927 "IPv6 gateway address\n"
928 "IPv6 gateway interface name\n"
54a3d7cb 929 "Null interface\n"
7e24fdf3
DS
930 "Set tag for this route\n"
931 "Tag value\n"
932 "Distance value for this prefix\n"
933 VRF_CMD_HELP_STR
934 MPLS_LABEL_HELPSTR
935 "Table to configure\n"
936 "The table number to configure\n"
02dc8ba3 937 VRF_CMD_HELP_STR
065276ae
SM
938 "Treat the nexthop as directly attached to the interface\n"
939 "SR-TE color\n"
e280279d
RZ
940 "The SR-TE color to configure\n"
941 BFD_INTEGRATION_STR
942 BFD_INTEGRATION_MULTI_HOP_STR
943 BFD_INTEGRATION_SOURCE_STR
944 BFD_INTEGRATION_SOURCEV4_STR
945 BFD_PROFILE_STR
946 BFD_PROFILE_NAME_STR)
7e24fdf3 947{
fc6f9d74
RZ
948 struct static_route_args args = {
949 .delete = !!no,
950 .afi = AFI_IP6,
951 .safi = SAFI_UNICAST,
952 .prefix = prefix_str,
953 .source = from_str,
954 .gateway = gate_str,
955 .interface_name = ifname,
956 .tag = tag_str,
957 .distance = distance_str,
958 .label = label,
959 .table = table_str,
960 .color = color_str,
961 .onlink = !!onlink,
962 .vrf = vrf,
963 .nexthop_vrf = nexthop_vrf,
e280279d
RZ
964 .bfd = !!bfd,
965 .bfd_multi_hop = !!bfd_multi_hop,
966 .bfd_source = bfd_source_str,
967 .bfd_profile = bfd_profile,
fc6f9d74
RZ
968 };
969
970 return static_route_nb_run(vty, &args);
7e24fdf3
DS
971}
972
ca77b518 973DEFPY_YANG(ipv6_route_address_interface_vrf,
7e24fdf3
DS
974 ipv6_route_address_interface_vrf_cmd,
975 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
976 X:X::X:X$gate \
54a3d7cb 977 <INTERFACE|Null0>$ifname \
7e24fdf3
DS
978 [{ \
979 tag (1-4294967295) \
980 |(1-255)$distance \
981 |label WORD \
982 |table (1-4294967295) \
983 |nexthop-vrf NAME \
02dc8ba3 984 |onlink$onlink \
065276ae 985 |color (1-4294967295) \
e280279d 986 |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
7e24fdf3
DS
987 }]",
988 NO_STR
989 IPV6_STR
990 "Establish static routes\n"
991 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
992 "IPv6 source-dest route\n"
993 "IPv6 source prefix\n"
994 "IPv6 gateway address\n"
995 "IPv6 gateway interface name\n"
54a3d7cb 996 "Null interface\n"
7e24fdf3
DS
997 "Set tag for this route\n"
998 "Tag value\n"
999 "Distance value for this prefix\n"
1000 MPLS_LABEL_HELPSTR
1001 "Table to configure\n"
1002 "The table number to configure\n"
02dc8ba3 1003 VRF_CMD_HELP_STR
065276ae
SM
1004 "Treat the nexthop as directly attached to the interface\n"
1005 "SR-TE color\n"
e280279d
RZ
1006 "The SR-TE color to configure\n"
1007 BFD_INTEGRATION_STR
1008 BFD_INTEGRATION_MULTI_HOP_STR
1009 BFD_INTEGRATION_SOURCE_STR
1010 BFD_INTEGRATION_SOURCEV4_STR
1011 BFD_PROFILE_STR
1012 BFD_PROFILE_NAME_STR)
7e24fdf3 1013{
fc6f9d74
RZ
1014 struct static_route_args args = {
1015 .delete = !!no,
1016 .afi = AFI_IP6,
1017 .safi = SAFI_UNICAST,
1018 .prefix = prefix_str,
1019 .source = from_str,
1020 .gateway = gate_str,
1021 .interface_name = ifname,
1022 .tag = tag_str,
1023 .distance = distance_str,
1024 .label = label,
1025 .table = table_str,
1026 .color = color_str,
1027 .onlink = !!onlink,
1028 .xpath_vrf = true,
1029 .nexthop_vrf = nexthop_vrf,
e280279d
RZ
1030 .bfd = !!bfd,
1031 .bfd_multi_hop = !!bfd_multi_hop,
1032 .bfd_source = bfd_source_str,
1033 .bfd_profile = bfd_profile,
fc6f9d74
RZ
1034 };
1035
1036 return static_route_nb_run(vty, &args);
7e24fdf3
DS
1037}
1038
ca77b518 1039DEFPY_YANG(ipv6_route,
7e24fdf3
DS
1040 ipv6_route_cmd,
1041 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
54a3d7cb 1042 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
7e24fdf3
DS
1043 [{ \
1044 tag (1-4294967295) \
1045 |(1-255)$distance \
1046 |vrf NAME \
1047 |label WORD \
1048 |table (1-4294967295) \
1049 |nexthop-vrf NAME \
065276ae 1050 |color (1-4294967295) \
e280279d 1051 |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
7e24fdf3
DS
1052 }]",
1053 NO_STR
1054 IPV6_STR
1055 "Establish static routes\n"
1056 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1057 "IPv6 source-dest route\n"
1058 "IPv6 source prefix\n"
1059 "IPv6 gateway address\n"
1060 "IPv6 gateway interface name\n"
54a3d7cb 1061 "Null interface\n"
7e24fdf3
DS
1062 "Set tag for this route\n"
1063 "Tag value\n"
1064 "Distance value for this prefix\n"
1065 VRF_CMD_HELP_STR
1066 MPLS_LABEL_HELPSTR
1067 "Table to configure\n"
1068 "The table number to configure\n"
065276ae
SM
1069 VRF_CMD_HELP_STR
1070 "SR-TE color\n"
e280279d
RZ
1071 "The SR-TE color to configure\n"
1072 BFD_INTEGRATION_STR
1073 BFD_INTEGRATION_MULTI_HOP_STR
1074 BFD_INTEGRATION_SOURCE_STR
1075 BFD_INTEGRATION_SOURCEV4_STR
1076 BFD_PROFILE_STR
1077 BFD_PROFILE_NAME_STR)
7e24fdf3 1078{
fc6f9d74
RZ
1079 struct static_route_args args = {
1080 .delete = !!no,
1081 .afi = AFI_IP6,
1082 .safi = SAFI_UNICAST,
1083 .prefix = prefix_str,
1084 .source = from_str,
1085 .gateway = gate_str,
1086 .interface_name = ifname,
1087 .tag = tag_str,
1088 .distance = distance_str,
1089 .label = label,
1090 .table = table_str,
1091 .color = color_str,
1092 .vrf = vrf,
1093 .nexthop_vrf = nexthop_vrf,
e280279d
RZ
1094 .bfd = !!bfd,
1095 .bfd_multi_hop = !!bfd_multi_hop,
1096 .bfd_source = bfd_source_str,
1097 .bfd_profile = bfd_profile,
fc6f9d74
RZ
1098 };
1099
1100 return static_route_nb_run(vty, &args);
7e24fdf3
DS
1101}
1102
ca77b518 1103DEFPY_YANG(ipv6_route_vrf,
7e24fdf3
DS
1104 ipv6_route_vrf_cmd,
1105 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
54a3d7cb 1106 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
7e24fdf3
DS
1107 [{ \
1108 tag (1-4294967295) \
1109 |(1-255)$distance \
1110 |label WORD \
1111 |table (1-4294967295) \
1112 |nexthop-vrf NAME \
065276ae 1113 |color (1-4294967295) \
e280279d 1114 |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
7e24fdf3
DS
1115 }]",
1116 NO_STR
1117 IPV6_STR
1118 "Establish static routes\n"
1119 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1120 "IPv6 source-dest route\n"
1121 "IPv6 source prefix\n"
1122 "IPv6 gateway address\n"
1123 "IPv6 gateway interface name\n"
54a3d7cb 1124 "Null interface\n"
7e24fdf3
DS
1125 "Set tag for this route\n"
1126 "Tag value\n"
1127 "Distance value for this prefix\n"
1128 MPLS_LABEL_HELPSTR
1129 "Table to configure\n"
1130 "The table number to configure\n"
065276ae
SM
1131 VRF_CMD_HELP_STR
1132 "SR-TE color\n"
e280279d
RZ
1133 "The SR-TE color to configure\n"
1134 BFD_INTEGRATION_STR
1135 BFD_INTEGRATION_MULTI_HOP_STR
1136 BFD_INTEGRATION_SOURCE_STR
1137 BFD_INTEGRATION_SOURCEV4_STR
1138 BFD_PROFILE_STR
1139 BFD_PROFILE_NAME_STR)
7e24fdf3 1140{
fc6f9d74
RZ
1141 struct static_route_args args = {
1142 .delete = !!no,
1143 .afi = AFI_IP6,
1144 .safi = SAFI_UNICAST,
1145 .prefix = prefix_str,
1146 .source = from_str,
1147 .gateway = gate_str,
1148 .interface_name = ifname,
1149 .tag = tag_str,
1150 .distance = distance_str,
1151 .label = label,
1152 .table = table_str,
1153 .color = color_str,
1154 .xpath_vrf = true,
1155 .nexthop_vrf = nexthop_vrf,
e280279d
RZ
1156 .bfd = !!bfd,
1157 .bfd_multi_hop = !!bfd_multi_hop,
1158 .bfd_source = bfd_source_str,
1159 .bfd_profile = bfd_profile,
fc6f9d74
RZ
1160 };
1161
1162 return static_route_nb_run(vty, &args);
7e24fdf3 1163}
6cc73dad 1164
25605051 1165void static_cli_show(struct vty *vty, const struct lyd_node *dnode,
6cc73dad
IR
1166 bool show_defaults)
1167{
1168 const char *vrf;
1169
1170 vrf = yang_dnode_get_string(dnode, "../vrf");
1171 if (strcmp(vrf, VRF_DEFAULT_NAME))
1172 vty_out(vty, "vrf %s\n", vrf);
1173}
1174
25605051 1175void static_cli_show_end(struct vty *vty, const struct lyd_node *dnode)
6cc73dad
IR
1176{
1177 const char *vrf;
1178
1179 vrf = yang_dnode_get_string(dnode, "../vrf");
1180 if (strcmp(vrf, VRF_DEFAULT_NAME))
1181 vty_out(vty, "exit-vrf\n");
1182}
1183
1184struct mpls_label_iter {
1185 struct vty *vty;
1186 bool first;
1187};
1188
1189static int mpls_label_iter_cb(const struct lyd_node *dnode, void *arg)
1190{
1191 struct mpls_label_iter *iter = arg;
1192
1193 if (yang_dnode_exists(dnode, "./label")) {
1194 if (iter->first)
1195 vty_out(iter->vty, " label %s",
1196 yang_dnode_get_string(dnode, "./label"));
1197 else
1198 vty_out(iter->vty, "/%s",
1199 yang_dnode_get_string(dnode, "./label"));
1200 iter->first = false;
1201 }
1202
1203 return YANG_ITER_CONTINUE;
1204}
1205
1206static void nexthop_cli_show(struct vty *vty, const struct lyd_node *route,
1207 const struct lyd_node *src,
1208 const struct lyd_node *path,
1209 const struct lyd_node *nexthop, bool show_defaults)
1210{
1211 const char *vrf;
1212 const char *afi_safi;
1213 afi_t afi;
1214 safi_t safi;
1215 enum static_nh_type nh_type;
1216 enum static_blackhole_type bh_type;
1217 uint32_t tag;
1218 uint8_t distance;
1219 struct mpls_label_iter iter;
1220 const char *nexthop_vrf;
1221 uint32_t table_id;
1222 bool onlink;
1223
1224 vrf = yang_dnode_get_string(route, "../../vrf");
1225
1226 afi_safi = yang_dnode_get_string(route, "./afi-safi");
1227 yang_afi_safi_identity2value(afi_safi, &afi, &safi);
1228
1229 if (afi == AFI_IP)
1230 vty_out(vty, "%sip",
1231 strmatch(vrf, VRF_DEFAULT_NAME) ? "" : " ");
1232 else
1233 vty_out(vty, "%sipv6",
1234 strmatch(vrf, VRF_DEFAULT_NAME) ? "" : " ");
1235
1236 if (safi == SAFI_UNICAST)
1237 vty_out(vty, " route");
1238 else
1239 vty_out(vty, " mroute");
1240
1241 vty_out(vty, " %s", yang_dnode_get_string(route, "./prefix"));
1242
1243 if (src)
1244 vty_out(vty, " from %s",
1245 yang_dnode_get_string(src, "./src-prefix"));
1246
1247 nh_type = yang_dnode_get_enum(nexthop, "./nh-type");
1248 switch (nh_type) {
1249 case STATIC_IFNAME:
1250 vty_out(vty, " %s",
1251 yang_dnode_get_string(nexthop, "./interface"));
1252 break;
1253 case STATIC_IPV4_GATEWAY:
1254 case STATIC_IPV6_GATEWAY:
1255 vty_out(vty, " %s",
1256 yang_dnode_get_string(nexthop, "./gateway"));
1257 break;
1258 case STATIC_IPV4_GATEWAY_IFNAME:
1259 case STATIC_IPV6_GATEWAY_IFNAME:
1260 vty_out(vty, " %s",
1261 yang_dnode_get_string(nexthop, "./gateway"));
1262 vty_out(vty, " %s",
1263 yang_dnode_get_string(nexthop, "./interface"));
1264 break;
1265 case STATIC_BLACKHOLE:
1266 bh_type = yang_dnode_get_enum(nexthop, "./bh-type");
1267 switch (bh_type) {
1268 case STATIC_BLACKHOLE_DROP:
1269 vty_out(vty, " blackhole");
1270 break;
1271 case STATIC_BLACKHOLE_NULL:
1272 vty_out(vty, " Null0");
1273 break;
1274 case STATIC_BLACKHOLE_REJECT:
1275 vty_out(vty, " reject");
1276 break;
1277 }
1278 break;
1279 }
1280
1281 if (yang_dnode_exists(path, "./tag")) {
1282 tag = yang_dnode_get_uint32(path, "./tag");
1283 if (tag != 0 || show_defaults)
1284 vty_out(vty, " tag %" PRIu32, tag);
1285 }
1286
1287 distance = yang_dnode_get_uint8(path, "./distance");
1288 if (distance != ZEBRA_STATIC_DISTANCE_DEFAULT || show_defaults)
1289 vty_out(vty, " %" PRIu8, distance);
1290
1291 iter.vty = vty;
1292 iter.first = true;
1293 yang_dnode_iterate(mpls_label_iter_cb, &iter, nexthop,
1294 "./mpls-label-stack/entry");
1295
1296 nexthop_vrf = yang_dnode_get_string(nexthop, "./vrf");
1297 if (strcmp(vrf, nexthop_vrf))
1298 vty_out(vty, " nexthop-vrf %s", nexthop_vrf);
1299
1300 table_id = yang_dnode_get_uint32(path, "./table-id");
1301 if (table_id || show_defaults)
1302 vty_out(vty, " table %" PRIu32, table_id);
1303
1304 if (yang_dnode_exists(nexthop, "./onlink")) {
1305 onlink = yang_dnode_get_bool(nexthop, "./onlink");
1306 if (onlink)
1307 vty_out(vty, " onlink");
1308 }
1309
1310 if (yang_dnode_exists(nexthop, "./srte-color"))
1311 vty_out(vty, " color %s",
1312 yang_dnode_get_string(nexthop, "./srte-color"));
1313
e280279d
RZ
1314 if (yang_dnode_exists(nexthop, "./bfd-monitoring")) {
1315 const struct lyd_node *bfd_dnode =
1316 yang_dnode_get(nexthop, "./bfd-monitoring");
1317
1318 if (yang_dnode_get_bool(bfd_dnode, "./multi-hop")) {
1319 vty_out(vty, " bfd multi-hop");
1320
1321 if (yang_dnode_exists(bfd_dnode, "./source"))
1322 vty_out(vty, " source %s",
1323 yang_dnode_get_string(bfd_dnode,
1324 "./source"));
1325 } else
1326 vty_out(vty, " bfd");
1327
1328 if (yang_dnode_exists(bfd_dnode, "./profile"))
1329 vty_out(vty, " profile %s",
1330 yang_dnode_get_string(bfd_dnode, "./profile"));
1331 }
1332
6cc73dad
IR
1333 vty_out(vty, "\n");
1334}
1335
25605051 1336void static_nexthop_cli_show(struct vty *vty, const struct lyd_node *dnode,
6cc73dad
IR
1337 bool show_defaults)
1338{
1339 const struct lyd_node *path = yang_dnode_get_parent(dnode, "path-list");
1340 const struct lyd_node *route =
1341 yang_dnode_get_parent(path, "route-list");
1342
1343 nexthop_cli_show(vty, route, NULL, path, dnode, show_defaults);
1344}
1345
25605051 1346void static_src_nexthop_cli_show(struct vty *vty, const struct lyd_node *dnode,
6cc73dad
IR
1347 bool show_defaults)
1348{
1349 const struct lyd_node *path = yang_dnode_get_parent(dnode, "path-list");
1350 const struct lyd_node *src = yang_dnode_get_parent(path, "src-list");
1351 const struct lyd_node *route = yang_dnode_get_parent(src, "route-list");
1352
1353 nexthop_cli_show(vty, route, src, path, dnode, show_defaults);
1354}
1355
25605051
IR
1356int static_nexthop_cli_cmp(const struct lyd_node *dnode1,
1357 const struct lyd_node *dnode2)
6cc73dad
IR
1358{
1359 enum static_nh_type nh_type1, nh_type2;
1360 struct prefix prefix1, prefix2;
1361 int ret = 0;
1362
1363 nh_type1 = yang_dnode_get_enum(dnode1, "./nh-type");
1364 nh_type2 = yang_dnode_get_enum(dnode2, "./nh-type");
1365
1366 if (nh_type1 != nh_type2)
1367 return (int)nh_type1 - (int)nh_type2;
1368
1369 switch (nh_type1) {
1370 case STATIC_IFNAME:
1371 ret = if_cmp_name_func(
1372 yang_dnode_get_string(dnode1, "./interface"),
1373 yang_dnode_get_string(dnode2, "./interface"));
1374 break;
1375 case STATIC_IPV4_GATEWAY:
1376 case STATIC_IPV6_GATEWAY:
1377 yang_dnode_get_prefix(&prefix1, dnode1, "./gateway");
1378 yang_dnode_get_prefix(&prefix2, dnode2, "./gateway");
1379 ret = prefix_cmp(&prefix1, &prefix2);
1380 break;
1381 case STATIC_IPV4_GATEWAY_IFNAME:
1382 case STATIC_IPV6_GATEWAY_IFNAME:
1383 yang_dnode_get_prefix(&prefix1, dnode1, "./gateway");
1384 yang_dnode_get_prefix(&prefix2, dnode2, "./gateway");
1385 ret = prefix_cmp(&prefix1, &prefix2);
1386 if (!ret)
1387 ret = if_cmp_name_func(
1388 yang_dnode_get_string(dnode1, "./interface"),
1389 yang_dnode_get_string(dnode2, "./interface"));
1390 break;
1391 case STATIC_BLACKHOLE:
1392 /* There's only one blackhole nexthop per route */
1393 ret = 0;
1394 break;
1395 }
1396
1397 if (ret)
1398 return ret;
1399
1400 return if_cmp_name_func(yang_dnode_get_string(dnode1, "./vrf"),
1401 yang_dnode_get_string(dnode2, "./vrf"));
1402}
1403
25605051
IR
1404int static_route_list_cli_cmp(const struct lyd_node *dnode1,
1405 const struct lyd_node *dnode2)
6cc73dad
IR
1406{
1407 const char *afi_safi1, *afi_safi2;
1408 afi_t afi1, afi2;
1409 safi_t safi1, safi2;
1410 struct prefix prefix1, prefix2;
1411
1412 afi_safi1 = yang_dnode_get_string(dnode1, "./afi-safi");
1413 yang_afi_safi_identity2value(afi_safi1, &afi1, &safi1);
1414
1415 afi_safi2 = yang_dnode_get_string(dnode2, "./afi-safi");
1416 yang_afi_safi_identity2value(afi_safi2, &afi2, &safi2);
1417
1418 if (afi1 != afi2)
1419 return (int)afi1 - (int)afi2;
1420
1421 if (safi1 != safi2)
1422 return (int)safi1 - (int)safi2;
1423
1424 yang_dnode_get_prefix(&prefix1, dnode1, "./prefix");
1425 yang_dnode_get_prefix(&prefix2, dnode2, "./prefix");
1426
1427 return prefix_cmp(&prefix1, &prefix2);
1428}
1429
25605051
IR
1430int static_src_list_cli_cmp(const struct lyd_node *dnode1,
1431 const struct lyd_node *dnode2)
6cc73dad
IR
1432{
1433 struct prefix prefix1, prefix2;
1434
1435 yang_dnode_get_prefix(&prefix1, dnode1, "./src-prefix");
1436 yang_dnode_get_prefix(&prefix2, dnode2, "./src-prefix");
1437
1438 return prefix_cmp(&prefix1, &prefix2);
1439}
1440
25605051
IR
1441int static_path_list_cli_cmp(const struct lyd_node *dnode1,
1442 const struct lyd_node *dnode2)
6cc73dad
IR
1443{
1444 uint32_t table_id1, table_id2;
1445 uint8_t distance1, distance2;
1446
1447 table_id1 = yang_dnode_get_uint32(dnode1, "./table-id");
1448 table_id2 = yang_dnode_get_uint32(dnode2, "./table-id");
1449
1450 if (table_id1 != table_id2)
1451 return (int)table_id1 - (int)table_id2;
1452
1453 distance1 = yang_dnode_get_uint8(dnode1, "./distance");
1454 distance2 = yang_dnode_get_uint8(dnode2, "./distance");
1455
1456 return (int)distance1 - (int)distance2;
1457}
1458
b2f6ab67 1459DEFPY_YANG(debug_staticd, debug_staticd_cmd,
b27499d6 1460 "[no] debug static [{events$events|route$route|bfd$bfd}]",
b2f6ab67 1461 NO_STR DEBUG_STR STATICD_STR
1462 "Debug events\n"
b27499d6
PG
1463 "Debug route\n"
1464 "Debug bfd\n")
31ddf3b7
MS
1465{
1466 /* If no specific category, change all */
1467 if (strmatch(argv[argc - 1]->text, "static"))
b27499d6 1468 static_debug_set(vty->node, !no, true, true, true);
31ddf3b7 1469 else
b27499d6 1470 static_debug_set(vty->node, !no, !!events, !!route, !!bfd);
7e24fdf3 1471
31ddf3b7
MS
1472 return CMD_SUCCESS;
1473}
1474
d8c78a8d
RZ
1475DEFPY(staticd_show_bfd_routes, staticd_show_bfd_routes_cmd,
1476 "show bfd static route [json]$isjson",
1477 SHOW_STR
1478 BFD_INTEGRATION_STR
1479 STATICD_STR
1480 ROUTE_STR
1481 JSON_STR)
1482{
1483 static_bfd_show(vty, !!isjson);
1484 return CMD_SUCCESS;
1485}
1486
31ddf3b7
MS
1487DEFUN_NOSH (show_debugging_static,
1488 show_debugging_static_cmd,
e60b527e
DS
1489 "show debugging [static]",
1490 SHOW_STR
1491 DEBUG_STR
1492 "Static Information\n")
1493{
31ddf3b7
MS
1494 vty_out(vty, "Staticd debugging status\n");
1495
1496 static_debug_status_write(vty);
e60b527e 1497
cf00164b
DS
1498 cmd_show_lib_debugs(vty);
1499
e60b527e
DS
1500 return CMD_SUCCESS;
1501}
1502
62b346ee 1503static struct cmd_node debug_node = {
f4b8291f 1504 .name = "debug",
62b346ee
DL
1505 .node = DEBUG_NODE,
1506 .prompt = "",
612c2c15 1507 .config_write = static_config_write_debug,
62b346ee 1508};
31ddf3b7 1509
7e24fdf3
DS
1510void static_vty_init(void)
1511{
612c2c15 1512 install_node(&debug_node);
31ddf3b7 1513
7e24fdf3
DS
1514 install_element(CONFIG_NODE, &ip_mroute_dist_cmd);
1515
1516 install_element(CONFIG_NODE, &ip_route_blackhole_cmd);
1517 install_element(VRF_NODE, &ip_route_blackhole_vrf_cmd);
1518 install_element(CONFIG_NODE, &ip_route_address_interface_cmd);
1519 install_element(VRF_NODE, &ip_route_address_interface_vrf_cmd);
1520 install_element(CONFIG_NODE, &ip_route_cmd);
1521 install_element(VRF_NODE, &ip_route_vrf_cmd);
1522
1523 install_element(CONFIG_NODE, &ipv6_route_blackhole_cmd);
1524 install_element(VRF_NODE, &ipv6_route_blackhole_vrf_cmd);
1525 install_element(CONFIG_NODE, &ipv6_route_address_interface_cmd);
1526 install_element(VRF_NODE, &ipv6_route_address_interface_vrf_cmd);
1527 install_element(CONFIG_NODE, &ipv6_route_cmd);
1528 install_element(VRF_NODE, &ipv6_route_vrf_cmd);
1529
dd73744d 1530 install_element(ENABLE_NODE, &show_debugging_static_cmd);
eed041e8 1531 install_element(ENABLE_NODE, &debug_staticd_cmd);
31ddf3b7 1532 install_element(CONFIG_NODE, &debug_staticd_cmd);
d8c78a8d
RZ
1533
1534 install_element(ENABLE_NODE, &staticd_show_bfd_routes_cmd);
7e24fdf3 1535}