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