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