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_memory.h"
37 #include "static_vty.h"
38 #include "static_routes.h"
39 #include "static_debug.h"
40 #ifndef VTYSH_EXTRACT_PL
41 #include "staticd/static_vty_clippy.c"
43 #include "static_nb.h"
45 #define STATICD_STR "Static route daemon\n"
47 static int static_route_leak(struct vty
*vty
, const char *svrf
,
48 const char *nh_svrf
, afi_t afi
, safi_t safi
,
49 const char *negate
, const char *dest_str
,
50 const char *mask_str
, const char *src_str
,
51 const char *gate_str
, const char *ifname
,
52 const char *flag_str
, const char *tag_str
,
53 const char *distance_str
, const char *label_str
,
54 const char *table_str
, bool onlink
,
55 const char *color_str
)
62 char xpath_prefix
[XPATH_MAXLEN
];
63 char xpath_nexthop
[XPATH_MAXLEN
];
64 char xpath_mpls
[XPATH_MAXLEN
];
65 char xpath_label
[XPATH_MAXLEN
];
66 char ab_xpath
[XPATH_MAXLEN
];
67 char buf_prefix
[PREFIX_STRLEN
];
68 char buf_src_prefix
[PREFIX_STRLEN
];
69 char buf_nh_type
[PREFIX_STRLEN
];
70 char buf_tag
[PREFIX_STRLEN
];
71 uint8_t label_stack_id
= 0;
72 const char *buf_gate_str
;
73 uint8_t distance
= ZEBRA_STATIC_DISTANCE_DEFAULT
;
75 uint32_t table_id
= 0;
76 const struct lyd_node
*dnode
;
78 memset(buf_src_prefix
, 0, PREFIX_STRLEN
);
79 memset(buf_nh_type
, 0, PREFIX_STRLEN
);
81 ret
= str2prefix(dest_str
, &p
);
83 vty_out(vty
, "%% Malformed address\n");
84 return CMD_WARNING_CONFIG_FAILED
;
89 /* Cisco like mask notation. */
91 ret
= inet_aton(mask_str
, &mask
);
93 vty_out(vty
, "%% Malformed address\n");
94 return CMD_WARNING_CONFIG_FAILED
;
96 p
.prefixlen
= ip_masklen(mask
);
100 /* srcdest routing */
102 ret
= str2prefix(src_str
, &src
);
103 if (ret
<= 0 || src
.family
!= AF_INET6
) {
104 vty_out(vty
, "%% Malformed source address\n");
105 return CMD_WARNING_CONFIG_FAILED
;
113 /* Apply mask for given prefix. */
116 prefix2str(&p
, buf_prefix
, sizeof(buf_prefix
));
119 prefix2str(&src
, buf_src_prefix
, sizeof(buf_src_prefix
));
121 buf_gate_str
= gate_str
;
125 if (gate_str
== NULL
&& ifname
== NULL
)
126 type
= STATIC_BLACKHOLE
;
127 else if (gate_str
&& ifname
) {
129 type
= STATIC_IPV4_GATEWAY_IFNAME
;
131 type
= STATIC_IPV6_GATEWAY_IFNAME
;
133 type
= STATIC_IFNAME
;
136 type
= STATIC_IPV4_GATEWAY
;
138 type
= STATIC_IPV6_GATEWAY
;
141 /* Administrative distance. */
143 distance
= atoi(distance_str
);
145 distance
= ZEBRA_STATIC_DISTANCE_DEFAULT
;
149 tag
= strtoul(tag_str
, NULL
, 10);
153 table_id
= atol(table_str
);
155 static_get_nh_type(type
, buf_nh_type
, PREFIX_STRLEN
);
157 /* route + path procesing */
159 snprintf(xpath_prefix
, sizeof(xpath_prefix
),
160 FRR_S_ROUTE_SRC_INFO_KEY_XPATH
,
161 "frr-staticd:staticd", "staticd", svrf
,
163 yang_afi_safi_value2identity(afi
, safi
),
164 buf_src_prefix
, table_id
, distance
);
166 snprintf(xpath_prefix
, sizeof(xpath_prefix
),
167 FRR_STATIC_ROUTE_INFO_KEY_XPATH
,
168 "frr-staticd:staticd", "staticd", svrf
,
170 yang_afi_safi_value2identity(afi
, safi
),
173 nb_cli_enqueue_change(vty
, xpath_prefix
, NB_OP_CREATE
, NULL
);
176 snprintf(buf_tag
, sizeof(buf_tag
), "%u", tag
);
177 strlcpy(ab_xpath
, xpath_prefix
, sizeof(ab_xpath
));
178 strlcat(ab_xpath
, FRR_STATIC_ROUTE_PATH_TAG_XPATH
,
180 nb_cli_enqueue_change(vty
, ab_xpath
, NB_OP_MODIFY
, buf_tag
);
182 /* nexthop processing */
184 snprintf(ab_xpath
, sizeof(ab_xpath
),
185 FRR_STATIC_ROUTE_NH_KEY_XPATH
, buf_nh_type
, nh_svrf
,
186 buf_gate_str
, ifname
);
187 strlcpy(xpath_nexthop
, xpath_prefix
, sizeof(xpath_nexthop
));
188 strlcat(xpath_nexthop
, ab_xpath
, sizeof(xpath_nexthop
));
189 nb_cli_enqueue_change(vty
, xpath_nexthop
, NB_OP_CREATE
, NULL
);
191 if (type
== STATIC_BLACKHOLE
) {
192 strlcpy(ab_xpath
, xpath_nexthop
, sizeof(ab_xpath
));
193 strlcat(ab_xpath
, FRR_STATIC_ROUTE_NH_BH_XPATH
,
198 switch (flag_str
[0]) {
212 nb_cli_enqueue_change(vty
, ab_xpath
,
213 NB_OP_MODIFY
, bh_type
);
215 nb_cli_enqueue_change(vty
, ab_xpath
,
216 NB_OP_MODIFY
, "null");
219 if (type
== STATIC_IPV4_GATEWAY_IFNAME
220 || type
== STATIC_IPV6_GATEWAY_IFNAME
) {
221 strlcpy(ab_xpath
, xpath_nexthop
, sizeof(ab_xpath
));
222 strlcat(ab_xpath
, FRR_STATIC_ROUTE_NH_ONLINK_XPATH
,
226 nb_cli_enqueue_change(vty
, ab_xpath
,
227 NB_OP_MODIFY
, "true");
229 nb_cli_enqueue_change(vty
, ab_xpath
,
230 NB_OP_MODIFY
, "false");
232 if (type
== STATIC_IPV4_GATEWAY
233 || type
== STATIC_IPV6_GATEWAY
234 || type
== STATIC_IPV4_GATEWAY_IFNAME
235 || type
== STATIC_IPV6_GATEWAY_IFNAME
) {
236 strlcpy(ab_xpath
, xpath_nexthop
, sizeof(ab_xpath
));
237 strlcat(ab_xpath
, FRR_STATIC_ROUTE_NH_COLOR_XPATH
,
240 nb_cli_enqueue_change(vty
, ab_xpath
,
241 NB_OP_MODIFY
, color_str
);
244 /* copy of label string (start) */
246 /* pointer to next segment */
249 strlcpy(xpath_mpls
, xpath_nexthop
, sizeof(xpath_mpls
));
250 strlcat(xpath_mpls
, FRR_STATIC_ROUTE_NH_LABEL_XPATH
,
253 nb_cli_enqueue_change(vty
, xpath_mpls
, NB_OP_DESTROY
,
256 ostr
= XSTRDUP(MTYPE_TMP
, label_str
);
257 while ((nump
= strsep(&ostr
, "/")) != NULL
) {
258 snprintf(ab_xpath
, sizeof(ab_xpath
),
259 FRR_STATIC_ROUTE_NHLB_KEY_XPATH
,
261 strlcpy(xpath_label
, xpath_mpls
,
262 sizeof(xpath_label
));
263 strlcat(xpath_label
, ab_xpath
,
264 sizeof(xpath_label
));
265 nb_cli_enqueue_change(vty
, xpath_label
,
269 XFREE(MTYPE_TMP
, ostr
);
271 strlcpy(xpath_mpls
, xpath_nexthop
, sizeof(xpath_mpls
));
272 strlcat(xpath_mpls
, FRR_STATIC_ROUTE_NH_LABEL_XPATH
,
274 nb_cli_enqueue_change(vty
, xpath_mpls
, NB_OP_DESTROY
,
277 ret
= nb_cli_apply_changes(vty
, xpath_prefix
);
280 snprintf(ab_xpath
, sizeof(ab_xpath
),
281 FRR_DEL_S_ROUTE_SRC_NH_KEY_XPATH
,
282 "frr-staticd:staticd", "staticd", svrf
,
284 yang_afi_safi_value2identity(afi
, safi
),
285 buf_src_prefix
, table_id
, distance
,
286 buf_nh_type
, nh_svrf
, buf_gate_str
, ifname
);
288 snprintf(ab_xpath
, sizeof(ab_xpath
),
289 FRR_DEL_S_ROUTE_NH_KEY_XPATH
,
290 "frr-staticd:staticd", "staticd", svrf
,
292 yang_afi_safi_value2identity(afi
, safi
),
293 table_id
, distance
, buf_nh_type
, nh_svrf
,
294 buf_gate_str
, ifname
);
296 dnode
= yang_dnode_get(vty
->candidate_config
->dnode
, ab_xpath
);
300 dnode
= yang_get_subtree_with_no_sibling(dnode
);
302 yang_dnode_get_path(dnode
, ab_xpath
, XPATH_MAXLEN
);
304 nb_cli_enqueue_change(vty
, ab_xpath
, NB_OP_DESTROY
, NULL
);
305 ret
= nb_cli_apply_changes(vty
, ab_xpath
);
310 static int static_route(struct vty
*vty
, afi_t afi
, safi_t safi
,
311 const char *negate
, const char *dest_str
,
312 const char *mask_str
, const char *src_str
,
313 const char *gate_str
, const char *ifname
,
314 const char *flag_str
, const char *tag_str
,
315 const char *distance_str
, const char *vrf_name
,
316 const char *label_str
, const char *table_str
)
319 vrf_name
= VRF_DEFAULT_NAME
;
321 return static_route_leak(vty
, vrf_name
, vrf_name
, afi
, safi
, negate
,
322 dest_str
, mask_str
, src_str
, gate_str
, ifname
,
323 flag_str
, tag_str
, distance_str
, label_str
,
324 table_str
, false, NULL
);
327 /* Write static route configuration. */
328 int static_config(struct vty
*vty
, struct static_vrf
*svrf
, afi_t afi
,
329 safi_t safi
, const char *cmd
)
332 struct route_node
*rn
;
333 struct static_nexthop
*nh
;
334 struct static_path
*pn
;
335 struct route_table
*stable
;
336 struct static_route_info
*si
;
337 char buf
[SRCDEST2STR_BUFFER
];
339 struct stable_info
*info
;
341 stable
= svrf
->stable
[afi
][safi
];
345 snprintf(spacing
, sizeof(spacing
), "%s%s",
346 (svrf
->vrf
->vrf_id
== VRF_DEFAULT
) ? "" : " ", cmd
);
348 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
)) {
349 si
= static_route_info_from_rnode(rn
);
352 info
= static_get_stable_info(rn
);
353 frr_each(static_path_list
, &si
->path_list
, pn
) {
354 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
355 vty_out(vty
, "%s %s", spacing
,
356 srcdest_rnode2str(rn
, buf
,
360 case STATIC_IPV4_GATEWAY
:
361 vty_out(vty
, " %pI4", &nh
->addr
.ipv4
);
363 case STATIC_IPV6_GATEWAY
:
370 vty_out(vty
, " %s", nh
->ifname
);
372 case STATIC_BLACKHOLE
:
373 switch (nh
->bh_type
) {
374 case STATIC_BLACKHOLE_DROP
:
375 vty_out(vty
, " blackhole");
377 case STATIC_BLACKHOLE_NULL
:
378 vty_out(vty
, " Null0");
380 case STATIC_BLACKHOLE_REJECT
:
381 vty_out(vty
, " reject");
385 case STATIC_IPV4_GATEWAY_IFNAME
:
386 vty_out(vty
, " %s %s",
392 case STATIC_IPV6_GATEWAY_IFNAME
:
393 vty_out(vty
, " %s %s",
402 vty_out(vty
, " tag %" ROUTE_TAG_PRI
,
406 != ZEBRA_STATIC_DISTANCE_DEFAULT
)
407 vty_out(vty
, " %u", pn
->distance
);
409 /* Label information */
410 if (nh
->snh_label
.num_labels
)
411 vty_out(vty
, " label %s",
416 buf
, sizeof(buf
), 0));
418 if (!strmatch(nh
->nh_vrfname
,
419 info
->svrf
->vrf
->name
))
420 vty_out(vty
, " nexthop-vrf %s",
424 * table ID from VRF overrides
428 && svrf
->vrf
->data
.l
.table_id
430 vty_out(vty
, " table %u", pn
->table_id
);
433 vty_out(vty
, " onlink");
439 vty_out(vty
, " color %u", nh
->color
);
450 /* Static unicast routes for multicast RPF lookup. */
451 DEFPY_YANG (ip_mroute_dist
,
453 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
456 "Configure static unicast route into MRIB for multicast RPF lookup\n"
457 "IP destination prefix (e.g. 10.0.0.0/8)\n"
459 "Nexthop interface name\n"
462 return static_route(vty
, AFI_IP
, SAFI_MULTICAST
, no
, prefix_str
,
463 NULL
, NULL
, gate_str
, ifname
, NULL
, NULL
,
464 distance_str
, NULL
, NULL
, NULL
);
467 /* Static route configuration. */
468 DEFPY_YANG(ip_route_blackhole
,
469 ip_route_blackhole_cmd
,
471 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
472 <reject|blackhole>$flag \
478 |table (1-4294967295) \
481 "Establish static routes\n"
482 "IP destination prefix (e.g. 10.0.0.0/8)\n"
483 "IP destination prefix\n"
484 "IP destination prefix mask\n"
485 "Emit an ICMP unreachable when matched\n"
486 "Silently discard pkts when matched\n"
487 "Set tag for this route\n"
489 "Distance value for this route\n"
492 "Table to configure\n"
493 "The table number to configure\n")
495 return static_route(vty
, AFI_IP
, SAFI_UNICAST
, no
, prefix
,
496 mask_str
, NULL
, NULL
, NULL
, flag
, tag_str
,
497 distance_str
, vrf
, label
, table_str
);
500 DEFPY_YANG(ip_route_blackhole_vrf
,
501 ip_route_blackhole_vrf_cmd
,
503 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
504 <reject|blackhole>$flag \
509 |table (1-4294967295) \
512 "Establish static routes\n"
513 "IP destination prefix (e.g. 10.0.0.0/8)\n"
514 "IP destination prefix\n"
515 "IP destination prefix mask\n"
516 "Emit an ICMP unreachable when matched\n"
517 "Silently discard pkts when matched\n"
518 "Set tag for this route\n"
520 "Distance value for this route\n"
522 "Table to configure\n"
523 "The table number to configure\n")
525 const struct lyd_node
*vrf_dnode
;
529 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
531 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
532 return CMD_WARNING_CONFIG_FAILED
;
534 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
536 * Coverity is complaining that prefix could
537 * be dereferenced, but we know that prefix will
538 * valid. Add an assert to make it happy
541 return static_route_leak(vty
, vrfname
, vrfname
, AFI_IP
, SAFI_UNICAST
,
542 no
, prefix
, mask_str
, NULL
, NULL
, NULL
, flag
,
543 tag_str
, distance_str
, label
, table_str
,
547 DEFPY_YANG(ip_route_address_interface
,
548 ip_route_address_interface_cmd
,
550 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
552 <INTERFACE|Null0>$ifname \
558 |table (1-4294967295) \
561 |color (1-4294967295) \
564 "Establish static routes\n"
565 "IP destination prefix (e.g. 10.0.0.0/8)\n"
566 "IP destination prefix\n"
567 "IP destination prefix mask\n"
568 "IP gateway address\n"
569 "IP gateway interface name\n"
571 "Set tag for this route\n"
573 "Distance value for this route\n"
576 "Table to configure\n"
577 "The table number to configure\n"
579 "Treat the nexthop as directly attached to the interface\n"
581 "The SR-TE color to configure\n")
584 const char *flag
= NULL
;
586 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
591 vrf
= VRF_DEFAULT_NAME
;
594 nh_vrf
= nexthop_vrf
;
598 return static_route_leak(vty
, vrf
, nh_vrf
, AFI_IP
, SAFI_UNICAST
, no
,
599 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
600 tag_str
, distance_str
, label
, table_str
,
601 !!onlink
, color_str
);
604 DEFPY_YANG(ip_route_address_interface_vrf
,
605 ip_route_address_interface_vrf_cmd
,
607 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
609 <INTERFACE|Null0>$ifname \
614 |table (1-4294967295) \
617 |color (1-4294967295) \
620 "Establish static routes\n"
621 "IP destination prefix (e.g. 10.0.0.0/8)\n"
622 "IP destination prefix\n"
623 "IP destination prefix mask\n"
624 "IP gateway address\n"
625 "IP gateway interface name\n"
627 "Set tag for this route\n"
629 "Distance value for this route\n"
631 "Table to configure\n"
632 "The table number to configure\n"
634 "Treat the nexthop as directly attached to the interface\n"
636 "The SR-TE color to configure\n")
639 const char *flag
= NULL
;
640 const struct lyd_node
*vrf_dnode
;
644 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
646 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
647 return CMD_WARNING_CONFIG_FAILED
;
649 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
651 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
656 nh_vrf
= nexthop_vrf
;
660 return static_route_leak(vty
, vrfname
, nh_vrf
, AFI_IP
, SAFI_UNICAST
, no
,
661 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
662 tag_str
, distance_str
, label
, table_str
,
663 !!onlink
, color_str
);
669 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
670 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
676 |table (1-4294967295) \
678 |color (1-4294967295) \
681 "Establish static routes\n"
682 "IP destination prefix (e.g. 10.0.0.0/8)\n"
683 "IP destination prefix\n"
684 "IP destination prefix mask\n"
685 "IP gateway address\n"
686 "IP gateway interface name\n"
688 "Set tag for this route\n"
690 "Distance value for this route\n"
693 "Table to configure\n"
694 "The table number to configure\n"
697 "The SR-TE color to configure\n")
700 const char *flag
= NULL
;
702 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
708 vrf
= VRF_DEFAULT_NAME
;
711 nh_vrf
= nexthop_vrf
;
715 return static_route_leak(vty
, vrf
, nh_vrf
, AFI_IP
, SAFI_UNICAST
, no
,
716 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
717 tag_str
, distance_str
, label
, table_str
,
721 DEFPY_YANG(ip_route_vrf
,
724 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
725 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
730 |table (1-4294967295) \
732 |color (1-4294967295) \
735 "Establish static routes\n"
736 "IP destination prefix (e.g. 10.0.0.0/8)\n"
737 "IP destination prefix\n"
738 "IP destination prefix mask\n"
739 "IP gateway address\n"
740 "IP gateway interface name\n"
742 "Set tag for this route\n"
744 "Distance value for this route\n"
746 "Table to configure\n"
747 "The table number to configure\n"
750 "The SR-TE color to configure\n")
753 const char *flag
= NULL
;
754 const struct lyd_node
*vrf_dnode
;
758 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
760 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
761 return CMD_WARNING_CONFIG_FAILED
;
764 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
766 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
771 nh_vrf
= nexthop_vrf
;
775 return static_route_leak(vty
, vrfname
, nh_vrf
, AFI_IP
, SAFI_UNICAST
, no
,
776 prefix
, mask_str
, NULL
, gate_str
, ifname
, flag
,
777 tag_str
, distance_str
, label
, table_str
,
781 DEFPY_YANG(ipv6_route_blackhole
,
782 ipv6_route_blackhole_cmd
,
783 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
784 <reject|blackhole>$flag \
790 |table (1-4294967295) \
794 "Establish static routes\n"
795 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
796 "IPv6 source-dest route\n"
797 "IPv6 source prefix\n"
798 "Emit an ICMP unreachable when matched\n"
799 "Silently discard pkts when matched\n"
800 "Set tag for this route\n"
802 "Distance value for this prefix\n"
805 "Table to configure\n"
806 "The table number to configure\n")
808 return static_route(vty
, AFI_IP6
, SAFI_UNICAST
, no
, prefix_str
,
809 NULL
, from_str
, NULL
, NULL
, flag
, tag_str
,
810 distance_str
, vrf
, label
, table_str
);
813 DEFPY_YANG(ipv6_route_blackhole_vrf
,
814 ipv6_route_blackhole_vrf_cmd
,
815 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
816 <reject|blackhole>$flag \
821 |table (1-4294967295) \
825 "Establish static routes\n"
826 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
827 "IPv6 source-dest route\n"
828 "IPv6 source prefix\n"
829 "Emit an ICMP unreachable when matched\n"
830 "Silently discard pkts when matched\n"
831 "Set tag for this route\n"
833 "Distance value for this prefix\n"
835 "Table to configure\n"
836 "The table number to configure\n")
838 const struct lyd_node
*vrf_dnode
;
842 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
844 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
845 return CMD_WARNING_CONFIG_FAILED
;
847 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
850 * Coverity is complaining that prefix could
851 * be dereferenced, but we know that prefix will
852 * valid. Add an assert to make it happy
856 return static_route_leak(vty
, vrfname
, vrfname
, AFI_IP6
, SAFI_UNICAST
,
857 no
, prefix_str
, NULL
, from_str
, NULL
, NULL
,
858 flag
, tag_str
, distance_str
, label
, table_str
,
862 DEFPY_YANG(ipv6_route_address_interface
,
863 ipv6_route_address_interface_cmd
,
864 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
866 <INTERFACE|Null0>$ifname \
872 |table (1-4294967295) \
875 |color (1-4294967295) \
879 "Establish static routes\n"
880 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
881 "IPv6 source-dest route\n"
882 "IPv6 source prefix\n"
883 "IPv6 gateway address\n"
884 "IPv6 gateway interface name\n"
886 "Set tag for this route\n"
888 "Distance value for this prefix\n"
891 "Table to configure\n"
892 "The table number to configure\n"
894 "Treat the nexthop as directly attached to the interface\n"
896 "The SR-TE color to configure\n")
899 const char *flag
= NULL
;
901 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
907 vrf
= VRF_DEFAULT_NAME
;
910 nh_vrf
= nexthop_vrf
;
914 return static_route_leak(vty
, vrf
, nh_vrf
, AFI_IP6
, SAFI_UNICAST
, no
,
915 prefix_str
, NULL
, from_str
, gate_str
, ifname
,
916 flag
, tag_str
, distance_str
, label
, table_str
,
917 !!onlink
, color_str
);
920 DEFPY_YANG(ipv6_route_address_interface_vrf
,
921 ipv6_route_address_interface_vrf_cmd
,
922 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
924 <INTERFACE|Null0>$ifname \
929 |table (1-4294967295) \
932 |color (1-4294967295) \
936 "Establish static routes\n"
937 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
938 "IPv6 source-dest route\n"
939 "IPv6 source prefix\n"
940 "IPv6 gateway address\n"
941 "IPv6 gateway interface name\n"
943 "Set tag for this route\n"
945 "Distance value for this prefix\n"
947 "Table to configure\n"
948 "The table number to configure\n"
950 "Treat the nexthop as directly attached to the interface\n"
952 "The SR-TE color to configure\n")
955 const char *flag
= NULL
;
956 const struct lyd_node
*vrf_dnode
;
960 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
962 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
963 return CMD_WARNING_CONFIG_FAILED
;
965 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
968 nh_vrf
= nexthop_vrf
;
972 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
976 return static_route_leak(vty
, vrfname
, nh_vrf
, AFI_IP6
, SAFI_UNICAST
,
977 no
, prefix_str
, NULL
, from_str
, gate_str
,
978 ifname
, flag
, tag_str
, distance_str
, label
,
979 table_str
, !!onlink
, color_str
);
982 DEFPY_YANG(ipv6_route
,
984 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
985 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
991 |table (1-4294967295) \
993 |color (1-4294967295) \
997 "Establish static routes\n"
998 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
999 "IPv6 source-dest route\n"
1000 "IPv6 source prefix\n"
1001 "IPv6 gateway address\n"
1002 "IPv6 gateway interface name\n"
1004 "Set tag for this route\n"
1006 "Distance value for this prefix\n"
1009 "Table to configure\n"
1010 "The table number to configure\n"
1013 "The SR-TE color to configure\n")
1016 const char *flag
= NULL
;
1019 vrf
= VRF_DEFAULT_NAME
;
1022 nh_vrf
= nexthop_vrf
;
1026 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1030 return static_route_leak(vty
, vrf
, nh_vrf
, AFI_IP6
, SAFI_UNICAST
, no
,
1031 prefix_str
, NULL
, from_str
, gate_str
, ifname
,
1032 flag
, tag_str
, distance_str
, label
, table_str
,
1036 DEFPY_YANG(ipv6_route_vrf
,
1038 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1039 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
1041 tag (1-4294967295) \
1044 |table (1-4294967295) \
1046 |color (1-4294967295) \
1050 "Establish static routes\n"
1051 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1052 "IPv6 source-dest route\n"
1053 "IPv6 source prefix\n"
1054 "IPv6 gateway address\n"
1055 "IPv6 gateway interface name\n"
1057 "Set tag for this route\n"
1059 "Distance value for this prefix\n"
1061 "Table to configure\n"
1062 "The table number to configure\n"
1065 "The SR-TE color to configure\n")
1068 const char *flag
= NULL
;
1069 const struct lyd_node
*vrf_dnode
;
1070 const char *vrfname
;
1073 yang_dnode_get(vty
->candidate_config
->dnode
, VTY_CURR_XPATH
);
1075 vty_out(vty
, "%% Failed to get vrf dnode in candidate db\n");
1076 return CMD_WARNING_CONFIG_FAILED
;
1078 vrfname
= yang_dnode_get_string(vrf_dnode
, "./name");
1081 nh_vrf
= nexthop_vrf
;
1085 if (ifname
&& !strncasecmp(ifname
, "Null0", 5)) {
1089 return static_route_leak(vty
, vrfname
, nh_vrf
, AFI_IP6
, SAFI_UNICAST
,
1090 no
, prefix_str
, NULL
, from_str
, gate_str
,
1091 ifname
, flag
, tag_str
, distance_str
, label
,
1092 table_str
, false, color_str
);
1094 DEFPY_YANG(debug_staticd
, debug_staticd_cmd
,
1095 "[no] debug static [{events$events|route$route}]",
1096 NO_STR DEBUG_STR STATICD_STR
1100 /* If no specific category, change all */
1101 if (strmatch(argv
[argc
- 1]->text
, "static"))
1102 static_debug_set(vty
->node
, !no
, true, true);
1104 static_debug_set(vty
->node
, !no
, !!events
, !!route
);
1109 DEFUN_NOSH (show_debugging_static
,
1110 show_debugging_static_cmd
,
1111 "show debugging [static]",
1114 "Static Information\n")
1116 vty_out(vty
, "Staticd debugging status\n");
1118 static_debug_status_write(vty
);
1123 static struct cmd_node debug_node
= {
1127 .config_write
= static_config_write_debug
,
1130 void static_vty_init(void)
1132 install_node(&debug_node
);
1134 install_element(CONFIG_NODE
, &ip_mroute_dist_cmd
);
1136 install_element(CONFIG_NODE
, &ip_route_blackhole_cmd
);
1137 install_element(VRF_NODE
, &ip_route_blackhole_vrf_cmd
);
1138 install_element(CONFIG_NODE
, &ip_route_address_interface_cmd
);
1139 install_element(VRF_NODE
, &ip_route_address_interface_vrf_cmd
);
1140 install_element(CONFIG_NODE
, &ip_route_cmd
);
1141 install_element(VRF_NODE
, &ip_route_vrf_cmd
);
1143 install_element(CONFIG_NODE
, &ipv6_route_blackhole_cmd
);
1144 install_element(VRF_NODE
, &ipv6_route_blackhole_vrf_cmd
);
1145 install_element(CONFIG_NODE
, &ipv6_route_address_interface_cmd
);
1146 install_element(VRF_NODE
, &ipv6_route_address_interface_vrf_cmd
);
1147 install_element(CONFIG_NODE
, &ipv6_route_cmd
);
1148 install_element(VRF_NODE
, &ipv6_route_vrf_cmd
);
1150 install_element(ENABLE_NODE
, &show_debugging_static_cmd
);
1151 install_element(ENABLE_NODE
, &debug_staticd_cmd
);
1152 install_element(CONFIG_NODE
, &debug_staticd_cmd
);