3 * Copyright (C) 2018 Cumulus Networks, Inc.
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)
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
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
28 #include "srcdest_table.h"
30 #include "northbound.h"
32 #include "routing_nb.h"
33 #include "northbound_cli.h"
35 #include "static_vrf.h"
36 #include "static_vty.h"
37 #include "static_routes.h"
38 #include "static_debug.h"
39 #ifndef VTYSH_EXTRACT_PL
40 #include "staticd/static_vty_clippy.c"
42 #include "static_nb.h"
44 #define STATICD_STR "Static route daemon\n"
46 static int static_route_leak(struct vty
*vty
, const char *svrf
,
47 const char *nh_svrf
, afi_t afi
, safi_t safi
,
48 const char *negate
, const char *dest_str
,
49 const char *mask_str
, const char *src_str
,
50 const char *gate_str
, const char *ifname
,
51 const char *flag_str
, const char *tag_str
,
52 const char *distance_str
, const char *label_str
,
53 const char *table_str
, bool onlink
,
54 const char *color_str
)
61 char xpath_prefix
[XPATH_MAXLEN
];
62 char xpath_nexthop
[XPATH_MAXLEN
];
63 char xpath_mpls
[XPATH_MAXLEN
];
64 char xpath_label
[XPATH_MAXLEN
];
65 char ab_xpath
[XPATH_MAXLEN
];
66 char buf_prefix
[PREFIX_STRLEN
];
67 char buf_src_prefix
[PREFIX_STRLEN
];
68 char buf_nh_type
[PREFIX_STRLEN
];
69 char buf_tag
[PREFIX_STRLEN
];
70 uint8_t label_stack_id
= 0;
71 const char *buf_gate_str
;
72 uint8_t distance
= ZEBRA_STATIC_DISTANCE_DEFAULT
;
74 uint32_t table_id
= 0;
75 const struct lyd_node
*dnode
;
77 memset(buf_src_prefix
, 0, PREFIX_STRLEN
);
78 memset(buf_nh_type
, 0, PREFIX_STRLEN
);
80 ret
= str2prefix(dest_str
, &p
);
82 vty_out(vty
, "%% Malformed address\n");
83 return CMD_WARNING_CONFIG_FAILED
;
88 /* Cisco like mask notation. */
90 ret
= inet_aton(mask_str
, &mask
);
92 vty_out(vty
, "%% Malformed address\n");
93 return CMD_WARNING_CONFIG_FAILED
;
95 p
.prefixlen
= ip_masklen(mask
);
101 ret
= str2prefix(src_str
, &src
);
102 if (ret
<= 0 || src
.family
!= AF_INET6
) {
103 vty_out(vty
, "%% Malformed source address\n");
104 return CMD_WARNING_CONFIG_FAILED
;
112 /* Apply mask for given prefix. */
115 prefix2str(&p
, buf_prefix
, sizeof(buf_prefix
));
118 prefix2str(&src
, buf_src_prefix
, sizeof(buf_src_prefix
));
120 buf_gate_str
= gate_str
;
124 if (gate_str
== NULL
&& ifname
== NULL
)
125 type
= STATIC_BLACKHOLE
;
126 else if (gate_str
&& ifname
) {
128 type
= STATIC_IPV4_GATEWAY_IFNAME
;
130 type
= STATIC_IPV6_GATEWAY_IFNAME
;
132 type
= STATIC_IFNAME
;
135 type
= STATIC_IPV4_GATEWAY
;
137 type
= STATIC_IPV6_GATEWAY
;
140 /* Administrative distance. */
142 distance
= atoi(distance_str
);
144 distance
= ZEBRA_STATIC_DISTANCE_DEFAULT
;
148 tag
= strtoul(tag_str
, NULL
, 10);
152 table_id
= atol(table_str
);
154 static_get_nh_type(type
, buf_nh_type
, PREFIX_STRLEN
);
156 /* route + path procesing */
158 snprintf(xpath_prefix
, sizeof(xpath_prefix
),
159 FRR_S_ROUTE_SRC_INFO_KEY_XPATH
,
160 "frr-staticd:staticd", "staticd", svrf
,
162 yang_afi_safi_value2identity(afi
, safi
),
163 buf_src_prefix
, table_id
, distance
);
165 snprintf(xpath_prefix
, sizeof(xpath_prefix
),
166 FRR_STATIC_ROUTE_INFO_KEY_XPATH
,
167 "frr-staticd:staticd", "staticd", svrf
,
169 yang_afi_safi_value2identity(afi
, safi
),
172 nb_cli_enqueue_change(vty
, xpath_prefix
, NB_OP_CREATE
, NULL
);
175 snprintf(buf_tag
, sizeof(buf_tag
), "%u", tag
);
176 strlcpy(ab_xpath
, xpath_prefix
, sizeof(ab_xpath
));
177 strlcat(ab_xpath
, FRR_STATIC_ROUTE_PATH_TAG_XPATH
,
179 nb_cli_enqueue_change(vty
, ab_xpath
, NB_OP_MODIFY
, buf_tag
);
181 /* nexthop processing */
183 snprintf(ab_xpath
, sizeof(ab_xpath
),
184 FRR_STATIC_ROUTE_NH_KEY_XPATH
, buf_nh_type
, nh_svrf
,
185 buf_gate_str
, ifname
);
186 strlcpy(xpath_nexthop
, xpath_prefix
, sizeof(xpath_nexthop
));
187 strlcat(xpath_nexthop
, ab_xpath
, sizeof(xpath_nexthop
));
188 nb_cli_enqueue_change(vty
, xpath_nexthop
, NB_OP_CREATE
, NULL
);
190 if (type
== STATIC_BLACKHOLE
) {
191 strlcpy(ab_xpath
, xpath_nexthop
, sizeof(ab_xpath
));
192 strlcat(ab_xpath
, FRR_STATIC_ROUTE_NH_BH_XPATH
,
197 switch (flag_str
[0]) {
211 nb_cli_enqueue_change(vty
, ab_xpath
,
212 NB_OP_MODIFY
, bh_type
);
214 nb_cli_enqueue_change(vty
, ab_xpath
,
215 NB_OP_MODIFY
, "null");
218 if (type
== STATIC_IPV4_GATEWAY_IFNAME
219 || type
== STATIC_IPV6_GATEWAY_IFNAME
) {
220 strlcpy(ab_xpath
, xpath_nexthop
, sizeof(ab_xpath
));
221 strlcat(ab_xpath
, FRR_STATIC_ROUTE_NH_ONLINK_XPATH
,
225 nb_cli_enqueue_change(vty
, ab_xpath
,
226 NB_OP_MODIFY
, "true");
228 nb_cli_enqueue_change(vty
, ab_xpath
,
229 NB_OP_MODIFY
, "false");
231 if (type
== STATIC_IPV4_GATEWAY
232 || type
== STATIC_IPV6_GATEWAY
233 || type
== STATIC_IPV4_GATEWAY_IFNAME
234 || type
== STATIC_IPV6_GATEWAY_IFNAME
) {
235 strlcpy(ab_xpath
, xpath_nexthop
, sizeof(ab_xpath
));
236 strlcat(ab_xpath
, FRR_STATIC_ROUTE_NH_COLOR_XPATH
,
239 nb_cli_enqueue_change(vty
, ab_xpath
,
240 NB_OP_MODIFY
, color_str
);
243 /* copy of label string (start) */
245 /* pointer to next segment */
248 strlcpy(xpath_mpls
, xpath_nexthop
, sizeof(xpath_mpls
));
249 strlcat(xpath_mpls
, FRR_STATIC_ROUTE_NH_LABEL_XPATH
,
252 nb_cli_enqueue_change(vty
, xpath_mpls
, NB_OP_DESTROY
,
255 ostr
= XSTRDUP(MTYPE_TMP
, label_str
);
256 while ((nump
= strsep(&ostr
, "/")) != NULL
) {
257 snprintf(ab_xpath
, sizeof(ab_xpath
),
258 FRR_STATIC_ROUTE_NHLB_KEY_XPATH
,
260 strlcpy(xpath_label
, xpath_mpls
,
261 sizeof(xpath_label
));
262 strlcat(xpath_label
, ab_xpath
,
263 sizeof(xpath_label
));
264 nb_cli_enqueue_change(vty
, xpath_label
,
268 XFREE(MTYPE_TMP
, ostr
);
270 strlcpy(xpath_mpls
, xpath_nexthop
, sizeof(xpath_mpls
));
271 strlcat(xpath_mpls
, FRR_STATIC_ROUTE_NH_LABEL_XPATH
,
273 nb_cli_enqueue_change(vty
, xpath_mpls
, NB_OP_DESTROY
,
276 ret
= nb_cli_apply_changes(vty
, xpath_prefix
);
279 snprintf(ab_xpath
, sizeof(ab_xpath
),
280 FRR_DEL_S_ROUTE_SRC_NH_KEY_XPATH
,
281 "frr-staticd:staticd", "staticd", svrf
,
283 yang_afi_safi_value2identity(afi
, safi
),
284 buf_src_prefix
, table_id
, distance
,
285 buf_nh_type
, nh_svrf
, buf_gate_str
, ifname
);
287 snprintf(ab_xpath
, sizeof(ab_xpath
),
288 FRR_DEL_S_ROUTE_NH_KEY_XPATH
,
289 "frr-staticd:staticd", "staticd", svrf
,
291 yang_afi_safi_value2identity(afi
, safi
),
292 table_id
, distance
, buf_nh_type
, nh_svrf
,
293 buf_gate_str
, ifname
);
295 dnode
= yang_dnode_get(vty
->candidate_config
->dnode
, ab_xpath
);
298 "%% Refusing to remove a non-existent route\n");
302 dnode
= yang_get_subtree_with_no_sibling(dnode
);
304 yang_dnode_get_path(dnode
, ab_xpath
, XPATH_MAXLEN
);
306 nb_cli_enqueue_change(vty
, ab_xpath
, NB_OP_DESTROY
, NULL
);
307 ret
= nb_cli_apply_changes(vty
, ab_xpath
);
312 static int static_route(struct vty
*vty
, afi_t afi
, safi_t safi
,
313 const char *negate
, const char *dest_str
,
314 const char *mask_str
, const char *src_str
,
315 const char *gate_str
, const char *ifname
,
316 const char *flag_str
, const char *tag_str
,
317 const char *distance_str
, const char *vrf_name
,
318 const char *label_str
, const char *table_str
)
321 vrf_name
= VRF_DEFAULT_NAME
;
323 return static_route_leak(vty
, vrf_name
, vrf_name
, afi
, safi
, negate
,
324 dest_str
, mask_str
, src_str
, gate_str
, ifname
,
325 flag_str
, tag_str
, distance_str
, label_str
,
326 table_str
, false, NULL
);
329 /* Write static route configuration. */
330 int static_config(struct vty
*vty
, struct static_vrf
*svrf
, afi_t afi
,
331 safi_t safi
, const char *cmd
)
334 struct route_node
*rn
;
335 struct static_nexthop
*nh
;
336 struct static_path
*pn
;
337 struct route_table
*stable
;
338 struct static_route_info
*si
;
339 char buf
[SRCDEST2STR_BUFFER
];
341 struct stable_info
*info
;
343 stable
= svrf
->stable
[afi
][safi
];
347 snprintf(spacing
, sizeof(spacing
), "%s%s",
348 (svrf
->vrf
->vrf_id
== VRF_DEFAULT
) ? "" : " ", cmd
);
350 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
)) {
351 si
= static_route_info_from_rnode(rn
);
354 info
= static_get_stable_info(rn
);
355 frr_each(static_path_list
, &si
->path_list
, pn
) {
356 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
357 vty_out(vty
, "%s %s", spacing
,
358 srcdest_rnode2str(rn
, buf
,
362 case STATIC_IPV4_GATEWAY
:
363 vty_out(vty
, " %pI4", &nh
->addr
.ipv4
);
365 case STATIC_IPV6_GATEWAY
:
372 vty_out(vty
, " %s", nh
->ifname
);
374 case STATIC_BLACKHOLE
:
375 switch (nh
->bh_type
) {
376 case STATIC_BLACKHOLE_DROP
:
377 vty_out(vty
, " blackhole");
379 case STATIC_BLACKHOLE_NULL
:
380 vty_out(vty
, " Null0");
382 case STATIC_BLACKHOLE_REJECT
:
383 vty_out(vty
, " reject");
387 case STATIC_IPV4_GATEWAY_IFNAME
:
388 vty_out(vty
, " %s %s",
394 case STATIC_IPV6_GATEWAY_IFNAME
:
395 vty_out(vty
, " %s %s",
404 vty_out(vty
, " tag %" ROUTE_TAG_PRI
,
408 != ZEBRA_STATIC_DISTANCE_DEFAULT
)
409 vty_out(vty
, " %u", pn
->distance
);
411 /* Label information */
412 if (nh
->snh_label
.num_labels
)
413 vty_out(vty
, " label %s",
418 buf
, sizeof(buf
), 0));
420 if (!strmatch(nh
->nh_vrfname
,
421 info
->svrf
->vrf
->name
))
422 vty_out(vty
, " nexthop-vrf %s",
426 * table ID from VRF overrides
430 && svrf
->vrf
->data
.l
.table_id
432 vty_out(vty
, " table %u", pn
->table_id
);
435 vty_out(vty
, " onlink");
441 vty_out(vty
, " color %u", nh
->color
);
452 /* Static unicast routes for multicast RPF lookup. */
453 DEFPY_YANG (ip_mroute_dist
,
455 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
458 "Configure static unicast route into MRIB for multicast RPF lookup\n"
459 "IP destination prefix (e.g. 10.0.0.0/8)\n"
461 "Nexthop interface name\n"
464 return static_route(vty
, AFI_IP
, SAFI_MULTICAST
, no
, prefix_str
,
465 NULL
, NULL
, gate_str
, ifname
, NULL
, NULL
,
466 distance_str
, NULL
, NULL
, NULL
);
469 /* Static route configuration. */
470 DEFPY_YANG(ip_route_blackhole
,
471 ip_route_blackhole_cmd
,
473 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
474 <reject|blackhole>$flag \
480 |table (1-4294967295) \
483 "Establish static routes\n"
484 "IP destination prefix (e.g. 10.0.0.0/8)\n"
485 "IP destination prefix\n"
486 "IP destination prefix mask\n"
487 "Emit an ICMP unreachable when matched\n"
488 "Silently discard pkts when matched\n"
489 "Set tag for this route\n"
491 "Distance value for this route\n"
494 "Table to configure\n"
495 "The table number to configure\n")
497 return static_route(vty
, AFI_IP
, SAFI_UNICAST
, no
, prefix
,
498 mask_str
, NULL
, NULL
, NULL
, flag
, tag_str
,
499 distance_str
, vrf
, label
, table_str
);
502 DEFPY_YANG(ip_route_blackhole_vrf
,
503 ip_route_blackhole_vrf_cmd
,
505 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
506 <reject|blackhole>$flag \
511 |table (1-4294967295) \
514 "Establish static routes\n"
515 "IP destination prefix (e.g. 10.0.0.0/8)\n"
516 "IP destination prefix\n"
517 "IP destination prefix mask\n"
518 "Emit an ICMP unreachable when matched\n"
519 "Silently discard pkts when matched\n"
520 "Set tag for this route\n"
522 "Distance value for this route\n"
524 "Table to configure\n"
525 "The table number to configure\n")
527 const struct lyd_node
*vrf_dnode
;
531 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
533 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
534 return CMD_WARNING_CONFIG_FAILED
;
536 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
538 * Coverity is complaining that prefix could
539 * be dereferenced, but we know that prefix will
540 * valid. Add an assert to make it happy
543 return static_route_leak(vty
, vrfname
, vrfname
, AFI_IP
, SAFI_UNICAST
,
544 no
, prefix
, mask_str
, NULL
, NULL
, NULL
, flag
,
545 tag_str
, distance_str
, label
, table_str
,
549 DEFPY_YANG(ip_route_address_interface
,
550 ip_route_address_interface_cmd
,
552 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
554 <INTERFACE|Null0>$ifname \
560 |table (1-4294967295) \
563 |color (1-4294967295) \
566 "Establish static routes\n"
567 "IP destination prefix (e.g. 10.0.0.0/8)\n"
568 "IP destination prefix\n"
569 "IP destination prefix mask\n"
570 "IP gateway address\n"
571 "IP gateway interface name\n"
573 "Set tag for this route\n"
575 "Distance value for this route\n"
578 "Table to configure\n"
579 "The table number to configure\n"
581 "Treat the nexthop as directly attached to the interface\n"
583 "The SR-TE color to configure\n")
586 const char *flag
= NULL
;
588 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
593 vrf
= VRF_DEFAULT_NAME
;
596 nh_vrf
= nexthop_vrf
;
600 return static_route_leak(vty
, vrf
, nh_vrf
, AFI_IP
, SAFI_UNICAST
, no
,
601 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
602 tag_str
, distance_str
, label
, table_str
,
603 !!onlink
, color_str
);
606 DEFPY_YANG(ip_route_address_interface_vrf
,
607 ip_route_address_interface_vrf_cmd
,
609 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
611 <INTERFACE|Null0>$ifname \
616 |table (1-4294967295) \
619 |color (1-4294967295) \
622 "Establish static routes\n"
623 "IP destination prefix (e.g. 10.0.0.0/8)\n"
624 "IP destination prefix\n"
625 "IP destination prefix mask\n"
626 "IP gateway address\n"
627 "IP gateway interface name\n"
629 "Set tag for this route\n"
631 "Distance value for this route\n"
633 "Table to configure\n"
634 "The table number to configure\n"
636 "Treat the nexthop as directly attached to the interface\n"
638 "The SR-TE color to configure\n")
641 const char *flag
= NULL
;
642 const struct lyd_node
*vrf_dnode
;
646 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
648 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
649 return CMD_WARNING_CONFIG_FAILED
;
651 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
653 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
658 nh_vrf
= nexthop_vrf
;
662 return static_route_leak(vty
, vrfname
, nh_vrf
, AFI_IP
, SAFI_UNICAST
, no
,
663 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
664 tag_str
, distance_str
, label
, table_str
,
665 !!onlink
, color_str
);
671 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
672 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
678 |table (1-4294967295) \
680 |color (1-4294967295) \
683 "Establish static routes\n"
684 "IP destination prefix (e.g. 10.0.0.0/8)\n"
685 "IP destination prefix\n"
686 "IP destination prefix mask\n"
687 "IP gateway address\n"
688 "IP gateway interface name\n"
690 "Set tag for this route\n"
692 "Distance value for this route\n"
695 "Table to configure\n"
696 "The table number to configure\n"
699 "The SR-TE color to configure\n")
702 const char *flag
= NULL
;
704 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
710 vrf
= VRF_DEFAULT_NAME
;
713 nh_vrf
= nexthop_vrf
;
717 return static_route_leak(vty
, vrf
, nh_vrf
, AFI_IP
, SAFI_UNICAST
, no
,
718 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
719 tag_str
, distance_str
, label
, table_str
,
723 DEFPY_YANG(ip_route_vrf
,
726 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
727 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
732 |table (1-4294967295) \
734 |color (1-4294967295) \
737 "Establish static routes\n"
738 "IP destination prefix (e.g. 10.0.0.0/8)\n"
739 "IP destination prefix\n"
740 "IP destination prefix mask\n"
741 "IP gateway address\n"
742 "IP gateway interface name\n"
744 "Set tag for this route\n"
746 "Distance value for this route\n"
748 "Table to configure\n"
749 "The table number to configure\n"
752 "The SR-TE color to configure\n")
755 const char *flag
= NULL
;
756 const struct lyd_node
*vrf_dnode
;
760 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
762 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
763 return CMD_WARNING_CONFIG_FAILED
;
766 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
768 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
773 nh_vrf
= nexthop_vrf
;
777 return static_route_leak(vty
, vrfname
, nh_vrf
, AFI_IP
, SAFI_UNICAST
, no
,
778 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
779 tag_str
, distance_str
, label
, table_str
,
783 DEFPY_YANG(ipv6_route_blackhole
,
784 ipv6_route_blackhole_cmd
,
785 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
786 <reject|blackhole>$flag \
792 |table (1-4294967295) \
796 "Establish static routes\n"
797 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
798 "IPv6 source-dest route\n"
799 "IPv6 source prefix\n"
800 "Emit an ICMP unreachable when matched\n"
801 "Silently discard pkts when matched\n"
802 "Set tag for this route\n"
804 "Distance value for this prefix\n"
807 "Table to configure\n"
808 "The table number to configure\n")
810 return static_route(vty
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
,
811 NULL
, from_str
, NULL
, NULL
, flag
, tag_str
,
812 distance_str
, vrf
, label
, table_str
);
815 DEFPY_YANG(ipv6_route_blackhole_vrf
,
816 ipv6_route_blackhole_vrf_cmd
,
817 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
818 <reject|blackhole>$flag \
823 |table (1-4294967295) \
827 "Establish static routes\n"
828 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
829 "IPv6 source-dest route\n"
830 "IPv6 source prefix\n"
831 "Emit an ICMP unreachable when matched\n"
832 "Silently discard pkts when matched\n"
833 "Set tag for this route\n"
835 "Distance value for this prefix\n"
837 "Table to configure\n"
838 "The table number to configure\n")
840 const struct lyd_node
*vrf_dnode
;
844 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
846 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
847 return CMD_WARNING_CONFIG_FAILED
;
849 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
852 * Coverity is complaining that prefix could
853 * be dereferenced, but we know that prefix will
854 * valid. Add an assert to make it happy
858 return static_route_leak(vty
, vrfname
, vrfname
, AFI_IP6
, SAFI_UNICAST
,
859 no
, prefix_str
, NULL
, from_str
, NULL
, NULL
,
860 flag
, tag_str
, distance_str
, label
, table_str
,
864 DEFPY_YANG(ipv6_route_address_interface
,
865 ipv6_route_address_interface_cmd
,
866 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
868 <INTERFACE|Null0>$ifname \
874 |table (1-4294967295) \
877 |color (1-4294967295) \
881 "Establish static routes\n"
882 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
883 "IPv6 source-dest route\n"
884 "IPv6 source prefix\n"
885 "IPv6 gateway address\n"
886 "IPv6 gateway interface name\n"
888 "Set tag for this route\n"
890 "Distance value for this prefix\n"
893 "Table to configure\n"
894 "The table number to configure\n"
896 "Treat the nexthop as directly attached to the interface\n"
898 "The SR-TE color to configure\n")
901 const char *flag
= NULL
;
903 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
909 vrf
= VRF_DEFAULT_NAME
;
912 nh_vrf
= nexthop_vrf
;
916 return static_route_leak(vty
, vrf
, nh_vrf
, AFI_IP6
, SAFI_UNICAST
, no
,
917 prefix_str
, NULL
, from_str
, gate_str
, ifname
,
918 flag
, tag_str
, distance_str
, label
, table_str
,
919 !!onlink
, color_str
);
922 DEFPY_YANG(ipv6_route_address_interface_vrf
,
923 ipv6_route_address_interface_vrf_cmd
,
924 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
926 <INTERFACE|Null0>$ifname \
931 |table (1-4294967295) \
934 |color (1-4294967295) \
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"
945 "Set tag for this route\n"
947 "Distance value for this prefix\n"
949 "Table to configure\n"
950 "The table number to configure\n"
952 "Treat the nexthop as directly attached to the interface\n"
954 "The SR-TE color to configure\n")
957 const char *flag
= NULL
;
958 const struct lyd_node
*vrf_dnode
;
962 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
964 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
965 return CMD_WARNING_CONFIG_FAILED
;
967 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
970 nh_vrf
= nexthop_vrf
;
974 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
978 return static_route_leak(vty
, vrfname
, nh_vrf
, AFI_IP6
, SAFI_UNICAST
,
979 no
, prefix_str
, NULL
, from_str
, gate_str
,
980 ifname
, flag
, tag_str
, distance_str
, label
,
981 table_str
, !!onlink
, color_str
);
984 DEFPY_YANG(ipv6_route
,
986 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
987 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
993 |table (1-4294967295) \
995 |color (1-4294967295) \
999 "Establish static routes\n"
1000 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1001 "IPv6 source-dest route\n"
1002 "IPv6 source prefix\n"
1003 "IPv6 gateway address\n"
1004 "IPv6 gateway interface name\n"
1006 "Set tag for this route\n"
1008 "Distance value for this prefix\n"
1011 "Table to configure\n"
1012 "The table number to configure\n"
1015 "The SR-TE color to configure\n")
1018 const char *flag
= NULL
;
1021 vrf
= VRF_DEFAULT_NAME
;
1024 nh_vrf
= nexthop_vrf
;
1028 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1032 return static_route_leak(vty
, vrf
, nh_vrf
, AFI_IP6
, SAFI_UNICAST
, no
,
1033 prefix_str
, NULL
, from_str
, gate_str
, ifname
,
1034 flag
, tag_str
, distance_str
, label
, table_str
,
1038 DEFPY_YANG(ipv6_route_vrf
,
1040 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1041 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
1043 tag (1-4294967295) \
1046 |table (1-4294967295) \
1048 |color (1-4294967295) \
1052 "Establish static routes\n"
1053 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1054 "IPv6 source-dest route\n"
1055 "IPv6 source prefix\n"
1056 "IPv6 gateway address\n"
1057 "IPv6 gateway interface name\n"
1059 "Set tag for this route\n"
1061 "Distance value for this prefix\n"
1063 "Table to configure\n"
1064 "The table number to configure\n"
1067 "The SR-TE color to configure\n")
1070 const char *flag
= NULL
;
1071 const struct lyd_node
*vrf_dnode
;
1072 const char *vrfname
;
1075 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
1077 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
1078 return CMD_WARNING_CONFIG_FAILED
;
1080 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
1083 nh_vrf
= nexthop_vrf
;
1087 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1091 return static_route_leak(vty
, vrfname
, nh_vrf
, AFI_IP6
, SAFI_UNICAST
,
1092 no
, prefix_str
, NULL
, from_str
, gate_str
,
1093 ifname
, flag
, tag_str
, distance_str
, label
,
1094 table_str
, false, color_str
);
1096 DEFPY_YANG(debug_staticd
, debug_staticd_cmd
,
1097 "[no] debug static [{events$events|route$route}]",
1098 NO_STR DEBUG_STR STATICD_STR
1102 /* If no specific category, change all */
1103 if (strmatch(argv
[argc
- 1]->text
, "static"))
1104 static_debug_set(vty
->node
, !no
, true, true);
1106 static_debug_set(vty
->node
, !no
, !!events
, !!route
);
1111 DEFUN_NOSH (show_debugging_static
,
1112 show_debugging_static_cmd
,
1113 "show debugging [static]",
1116 "Static Information\n")
1118 vty_out(vty
, "Staticd debugging status\n");
1120 static_debug_status_write(vty
);
1125 static struct cmd_node debug_node
= {
1129 .config_write
= static_config_write_debug
,
1132 void static_vty_init(void)
1134 install_node(&debug_node
);
1136 install_element(CONFIG_NODE
, &ip_mroute_dist_cmd
);
1138 install_element(CONFIG_NODE
, &ip_route_blackhole_cmd
);
1139 install_element(VRF_NODE
, &ip_route_blackhole_vrf_cmd
);
1140 install_element(CONFIG_NODE
, &ip_route_address_interface_cmd
);
1141 install_element(VRF_NODE
, &ip_route_address_interface_vrf_cmd
);
1142 install_element(CONFIG_NODE
, &ip_route_cmd
);
1143 install_element(VRF_NODE
, &ip_route_vrf_cmd
);
1145 install_element(CONFIG_NODE
, &ipv6_route_blackhole_cmd
);
1146 install_element(VRF_NODE
, &ipv6_route_blackhole_vrf_cmd
);
1147 install_element(CONFIG_NODE
, &ipv6_route_address_interface_cmd
);
1148 install_element(VRF_NODE
, &ipv6_route_address_interface_vrf_cmd
);
1149 install_element(CONFIG_NODE
, &ipv6_route_cmd
);
1150 install_element(VRF_NODE
, &ipv6_route_vrf_cmd
);
1152 install_element(ENABLE_NODE
, &show_debugging_static_cmd
);
1153 install_element(ENABLE_NODE
, &debug_staticd_cmd
);
1154 install_element(CONFIG_NODE
, &debug_staticd_cmd
);