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 #include "staticd/static_vty_clippy.c"
40 #include "static_nb.h"
42 #define STATICD_STR "Static route daemon\n"
44 /** All possible route parameters available in CLI. */
45 struct static_route_args
{
48 /** Is VRF obtained from XPath? */
56 const char *nexthop_vrf
;
58 const char *prefix_mask
;
61 const char *interface_name
;
71 const char *bfd_source
;
72 const char *bfd_profile
;
75 static int static_route_nb_run(struct vty
*vty
, struct static_route_args
*args
)
80 enum static_nh_type type
;
82 char xpath_prefix
[XPATH_MAXLEN
];
83 char xpath_nexthop
[XPATH_MAXLEN
];
84 char xpath_mpls
[XPATH_MAXLEN
];
85 char xpath_label
[XPATH_MAXLEN
];
86 char ab_xpath
[XPATH_MAXLEN
];
87 char buf_prefix
[PREFIX_STRLEN
];
88 char buf_src_prefix
[PREFIX_STRLEN
] = {};
89 char buf_nh_type
[PREFIX_STRLEN
] = {};
90 char buf_tag
[PREFIX_STRLEN
];
91 uint8_t label_stack_id
= 0;
92 const char *buf_gate_str
;
93 uint8_t distance
= ZEBRA_STATIC_DISTANCE_DEFAULT
;
95 uint32_t table_id
= 0;
96 const struct lyd_node
*dnode
;
97 const struct lyd_node
*vrf_dnode
;
99 if (args
->xpath_vrf
) {
100 vrf_dnode
= yang_dnode_get(vty
->candidate_config
->dnode
,
102 if (vrf_dnode
== NULL
) {
104 "%% Failed to get vrf dnode in candidate db\n");
105 return CMD_WARNING_CONFIG_FAILED
;
108 args
->vrf
= yang_dnode_get_string(vrf_dnode
, "./name");
110 if (args
->vrf
== NULL
)
111 args
->vrf
= VRF_DEFAULT_NAME
;
113 if (args
->nexthop_vrf
== NULL
)
114 args
->nexthop_vrf
= args
->vrf
;
116 if (args
->interface_name
&&
117 !strcasecmp(args
->interface_name
, "Null0")) {
118 args
->flag
= "Null0";
119 args
->interface_name
= NULL
;
122 assert(!!str2prefix(args
->prefix
, &p
));
126 /* Cisco like mask notation. */
127 if (args
->prefix_mask
) {
128 assert(inet_pton(AF_INET
, args
->prefix_mask
, &mask
) ==
130 p
.prefixlen
= ip_masklen(mask
);
134 /* srcdest routing */
136 assert(!!str2prefix(args
->source
, &src
));
142 /* Apply mask for given prefix. */
144 prefix2str(&p
, buf_prefix
, sizeof(buf_prefix
));
146 if (args
->bfd
&& args
->gateway
== NULL
) {
147 vty_out(vty
, "%% Route monitoring requires a gateway\n");
148 return CMD_WARNING_CONFIG_FAILED
;
152 prefix2str(&src
, buf_src_prefix
, sizeof(buf_src_prefix
));
154 buf_gate_str
= args
->gateway
;
158 if (args
->gateway
== NULL
&& args
->interface_name
== NULL
)
159 type
= STATIC_BLACKHOLE
;
160 else if (args
->gateway
&& args
->interface_name
) {
161 if (args
->afi
== AFI_IP
)
162 type
= STATIC_IPV4_GATEWAY_IFNAME
;
164 type
= STATIC_IPV6_GATEWAY_IFNAME
;
165 } else if (args
->interface_name
)
166 type
= STATIC_IFNAME
;
168 if (args
->afi
== AFI_IP
)
169 type
= STATIC_IPV4_GATEWAY
;
171 type
= STATIC_IPV6_GATEWAY
;
174 /* Administrative distance. */
176 distance
= strtol(args
->distance
, NULL
, 10);
180 tag
= strtoul(args
->tag
, NULL
, 10);
184 table_id
= strtol(args
->table
, NULL
, 10);
186 static_get_nh_type(type
, buf_nh_type
, sizeof(buf_nh_type
));
189 snprintf(ab_xpath
, sizeof(ab_xpath
),
190 FRR_DEL_S_ROUTE_SRC_NH_KEY_NO_DISTANCE_XPATH
,
191 "frr-staticd:staticd", "staticd", args
->vrf
,
193 yang_afi_safi_value2identity(args
->afi
,
195 buf_src_prefix
, table_id
, buf_nh_type
,
196 args
->nexthop_vrf
, buf_gate_str
,
197 args
->interface_name
);
199 snprintf(ab_xpath
, sizeof(ab_xpath
),
200 FRR_DEL_S_ROUTE_NH_KEY_NO_DISTANCE_XPATH
,
201 "frr-staticd:staticd", "staticd", args
->vrf
,
203 yang_afi_safi_value2identity(args
->afi
,
205 table_id
, buf_nh_type
, args
->nexthop_vrf
,
206 buf_gate_str
, args
->interface_name
);
209 * If there's already the same nexthop but with a different
210 * distance, then remove it for the replacement.
212 dnode
= yang_dnode_get(vty
->candidate_config
->dnode
, ab_xpath
);
214 dnode
= yang_get_subtree_with_no_sibling(dnode
);
216 yang_dnode_get_path(dnode
, ab_xpath
, XPATH_MAXLEN
);
218 nb_cli_enqueue_change(vty
, ab_xpath
, NB_OP_DESTROY
,
222 /* route + path procesing */
224 snprintf(xpath_prefix
, sizeof(xpath_prefix
),
225 FRR_S_ROUTE_SRC_INFO_KEY_XPATH
,
226 "frr-staticd:staticd", "staticd", args
->vrf
,
228 yang_afi_safi_value2identity(args
->afi
,
230 buf_src_prefix
, table_id
, distance
);
232 snprintf(xpath_prefix
, sizeof(xpath_prefix
),
233 FRR_STATIC_ROUTE_INFO_KEY_XPATH
,
234 "frr-staticd:staticd", "staticd", args
->vrf
,
236 yang_afi_safi_value2identity(args
->afi
,
240 nb_cli_enqueue_change(vty
, xpath_prefix
, NB_OP_CREATE
, NULL
);
243 snprintf(buf_tag
, sizeof(buf_tag
), "%u", tag
);
244 strlcpy(ab_xpath
, xpath_prefix
, sizeof(ab_xpath
));
245 strlcat(ab_xpath
, FRR_STATIC_ROUTE_PATH_TAG_XPATH
,
247 nb_cli_enqueue_change(vty
, ab_xpath
, NB_OP_MODIFY
, buf_tag
);
249 /* nexthop processing */
251 snprintf(ab_xpath
, sizeof(ab_xpath
),
252 FRR_STATIC_ROUTE_NH_KEY_XPATH
, buf_nh_type
,
253 args
->nexthop_vrf
, buf_gate_str
, args
->interface_name
);
254 strlcpy(xpath_nexthop
, xpath_prefix
, sizeof(xpath_nexthop
));
255 strlcat(xpath_nexthop
, ab_xpath
, sizeof(xpath_nexthop
));
256 nb_cli_enqueue_change(vty
, xpath_nexthop
, NB_OP_CREATE
, NULL
);
258 if (type
== STATIC_BLACKHOLE
) {
259 strlcpy(ab_xpath
, xpath_nexthop
, sizeof(ab_xpath
));
260 strlcat(ab_xpath
, FRR_STATIC_ROUTE_NH_BH_XPATH
,
265 switch (args
->flag
[0]) {
279 nb_cli_enqueue_change(vty
, ab_xpath
,
280 NB_OP_MODIFY
, bh_type
);
282 nb_cli_enqueue_change(vty
, ab_xpath
,
283 NB_OP_MODIFY
, "null");
286 if (type
== STATIC_IPV4_GATEWAY_IFNAME
287 || type
== STATIC_IPV6_GATEWAY_IFNAME
) {
288 strlcpy(ab_xpath
, xpath_nexthop
, sizeof(ab_xpath
));
289 strlcat(ab_xpath
, FRR_STATIC_ROUTE_NH_ONLINK_XPATH
,
293 nb_cli_enqueue_change(vty
, ab_xpath
,
294 NB_OP_MODIFY
, "true");
296 nb_cli_enqueue_change(vty
, ab_xpath
,
297 NB_OP_MODIFY
, "false");
299 if (type
== STATIC_IPV4_GATEWAY
300 || type
== STATIC_IPV6_GATEWAY
301 || type
== STATIC_IPV4_GATEWAY_IFNAME
302 || type
== STATIC_IPV6_GATEWAY_IFNAME
) {
303 strlcpy(ab_xpath
, xpath_nexthop
, sizeof(ab_xpath
));
304 strlcat(ab_xpath
, FRR_STATIC_ROUTE_NH_COLOR_XPATH
,
307 nb_cli_enqueue_change(vty
, ab_xpath
,
312 /* copy of label string (start) */
314 /* pointer to next segment */
317 strlcpy(xpath_mpls
, xpath_nexthop
, sizeof(xpath_mpls
));
318 strlcat(xpath_mpls
, FRR_STATIC_ROUTE_NH_LABEL_XPATH
,
321 nb_cli_enqueue_change(vty
, xpath_mpls
, NB_OP_DESTROY
,
324 ostr
= XSTRDUP(MTYPE_TMP
, args
->label
);
325 while ((nump
= strsep(&ostr
, "/")) != NULL
) {
326 snprintf(ab_xpath
, sizeof(ab_xpath
),
327 FRR_STATIC_ROUTE_NHLB_KEY_XPATH
,
329 strlcpy(xpath_label
, xpath_mpls
,
330 sizeof(xpath_label
));
331 strlcat(xpath_label
, ab_xpath
,
332 sizeof(xpath_label
));
333 nb_cli_enqueue_change(vty
, xpath_label
,
337 XFREE(MTYPE_TMP
, ostr
);
339 strlcpy(xpath_mpls
, xpath_nexthop
, sizeof(xpath_mpls
));
340 strlcat(xpath_mpls
, FRR_STATIC_ROUTE_NH_LABEL_XPATH
,
342 nb_cli_enqueue_change(vty
, xpath_mpls
, NB_OP_DESTROY
,
347 char xpath_bfd
[XPATH_MAXLEN
];
349 if (args
->bfd_source
) {
350 strlcpy(xpath_bfd
, xpath_nexthop
,
353 "/frr-staticd:bfd-monitoring/source",
355 nb_cli_enqueue_change(vty
, xpath_bfd
,
360 strlcpy(xpath_bfd
, xpath_nexthop
, sizeof(xpath_bfd
));
362 "/frr-staticd:bfd-monitoring/multi-hop",
364 nb_cli_enqueue_change(vty
, xpath_bfd
, NB_OP_MODIFY
,
365 args
->bfd_multi_hop
? "true"
368 if (args
->bfd_profile
) {
369 strlcpy(xpath_bfd
, xpath_nexthop
,
372 "/frr-staticd:bfd-monitoring/profile",
374 nb_cli_enqueue_change(vty
, xpath_bfd
,
380 ret
= nb_cli_apply_changes(vty
, "%s", xpath_prefix
);
383 snprintf(ab_xpath
, sizeof(ab_xpath
),
384 FRR_DEL_S_ROUTE_SRC_NH_KEY_NO_DISTANCE_XPATH
,
385 "frr-staticd:staticd", "staticd", args
->vrf
,
387 yang_afi_safi_value2identity(args
->afi
,
389 buf_src_prefix
, table_id
, buf_nh_type
,
390 args
->nexthop_vrf
, buf_gate_str
,
391 args
->interface_name
);
393 snprintf(ab_xpath
, sizeof(ab_xpath
),
394 FRR_DEL_S_ROUTE_NH_KEY_NO_DISTANCE_XPATH
,
395 "frr-staticd:staticd", "staticd", args
->vrf
,
397 yang_afi_safi_value2identity(args
->afi
,
399 table_id
, buf_nh_type
, args
->nexthop_vrf
,
400 buf_gate_str
, args
->interface_name
);
402 dnode
= yang_dnode_get(vty
->candidate_config
->dnode
, ab_xpath
);
405 "%% Refusing to remove a non-existent route\n");
409 dnode
= yang_get_subtree_with_no_sibling(dnode
);
411 yang_dnode_get_path(dnode
, ab_xpath
, XPATH_MAXLEN
);
413 nb_cli_enqueue_change(vty
, ab_xpath
, NB_OP_DESTROY
, NULL
);
414 ret
= nb_cli_apply_changes(vty
, "%s", ab_xpath
);
420 /* Static unicast routes for multicast RPF lookup. */
421 DEFPY_YANG (ip_mroute_dist
,
423 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [{"
425 "|bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}]"
429 "Configure static unicast route into MRIB for multicast RPF lookup\n"
430 "IP destination prefix (e.g. 10.0.0.0/8)\n"
432 "Nexthop interface name\n"
435 BFD_INTEGRATION_MULTI_HOP_STR
436 BFD_INTEGRATION_SOURCE_STR
437 BFD_INTEGRATION_SOURCEV4_STR
439 BFD_PROFILE_NAME_STR
)
441 struct static_route_args args
= {
444 .safi
= SAFI_MULTICAST
,
445 .prefix
= prefix_str
,
447 .interface_name
= ifname
,
448 .distance
= distance_str
,
450 .bfd_multi_hop
= !!bfd_multi_hop
,
451 .bfd_source
= bfd_source_str
,
452 .bfd_profile
= bfd_profile
,
455 return static_route_nb_run(vty
, &args
);
458 /* Static route configuration. */
459 DEFPY_YANG(ip_route_blackhole
,
460 ip_route_blackhole_cmd
,
462 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
463 <reject|blackhole>$flag \
469 |table (1-4294967295) \
472 "Establish static routes\n"
473 "IP destination prefix (e.g. 10.0.0.0/8)\n"
474 "IP destination prefix\n"
475 "IP destination prefix mask\n"
476 "Emit an ICMP unreachable when matched\n"
477 "Silently discard pkts when matched\n"
478 "Set tag for this route\n"
480 "Distance value for this route\n"
483 "Table to configure\n"
484 "The table number to configure\n")
486 struct static_route_args args
= {
489 .safi
= SAFI_UNICAST
,
491 .prefix_mask
= mask_str
,
494 .distance
= distance_str
,
500 return static_route_nb_run(vty
, &args
);
503 DEFPY_YANG(ip_route_blackhole_vrf
,
504 ip_route_blackhole_vrf_cmd
,
506 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
507 <reject|blackhole>$flag \
512 |table (1-4294967295) \
515 "Establish static routes\n"
516 "IP destination prefix (e.g. 10.0.0.0/8)\n"
517 "IP destination prefix\n"
518 "IP destination prefix mask\n"
519 "Emit an ICMP unreachable when matched\n"
520 "Silently discard pkts when matched\n"
521 "Set tag for this route\n"
523 "Distance value for this route\n"
525 "Table to configure\n"
526 "The table number to configure\n")
528 struct static_route_args args
= {
531 .safi
= SAFI_UNICAST
,
533 .prefix_mask
= mask_str
,
536 .distance
= distance_str
,
543 * Coverity is complaining that prefix could
544 * be dereferenced, but we know that prefix will
545 * valid. Add an assert to make it happy
549 return static_route_nb_run(vty
, &args
);
552 DEFPY_YANG(ip_route_address_interface
,
553 ip_route_address_interface_cmd
,
555 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
557 <INTERFACE|Null0>$ifname \
563 |table (1-4294967295) \
566 |color (1-4294967295) \
567 |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
570 "Establish static routes\n"
571 "IP destination prefix (e.g. 10.0.0.0/8)\n"
572 "IP destination prefix\n"
573 "IP destination prefix mask\n"
574 "IP gateway address\n"
575 "IP gateway interface name\n"
577 "Set tag for this route\n"
579 "Distance value for this route\n"
582 "Table to configure\n"
583 "The table number to configure\n"
585 "Treat the nexthop as directly attached to the interface\n"
587 "The SR-TE color to configure\n"
589 BFD_INTEGRATION_MULTI_HOP_STR
590 BFD_INTEGRATION_SOURCE_STR
591 BFD_INTEGRATION_SOURCEV4_STR
593 BFD_PROFILE_NAME_STR
)
595 struct static_route_args args
= {
598 .safi
= SAFI_UNICAST
,
600 .prefix_mask
= mask_str
,
602 .interface_name
= ifname
,
604 .distance
= distance_str
,
610 .nexthop_vrf
= nexthop_vrf
,
612 .bfd_multi_hop
= !!bfd_multi_hop
,
613 .bfd_source
= bfd_source_str
,
614 .bfd_profile
= bfd_profile
,
617 return static_route_nb_run(vty
, &args
);
620 DEFPY_YANG(ip_route_address_interface_vrf
,
621 ip_route_address_interface_vrf_cmd
,
623 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
625 <INTERFACE|Null0>$ifname \
630 |table (1-4294967295) \
633 |color (1-4294967295) \
634 |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
637 "Establish static routes\n"
638 "IP destination prefix (e.g. 10.0.0.0/8)\n"
639 "IP destination prefix\n"
640 "IP destination prefix mask\n"
641 "IP gateway address\n"
642 "IP gateway interface name\n"
644 "Set tag for this route\n"
646 "Distance value for this route\n"
648 "Table to configure\n"
649 "The table number to configure\n"
651 "Treat the nexthop as directly attached to the interface\n"
653 "The SR-TE color to configure\n"
655 BFD_INTEGRATION_MULTI_HOP_STR
656 BFD_INTEGRATION_SOURCE_STR
657 BFD_INTEGRATION_SOURCEV4_STR
659 BFD_PROFILE_NAME_STR
)
661 struct static_route_args args
= {
664 .safi
= SAFI_UNICAST
,
666 .prefix_mask
= mask_str
,
668 .interface_name
= ifname
,
670 .distance
= distance_str
,
676 .nexthop_vrf
= nexthop_vrf
,
678 .bfd_multi_hop
= !!bfd_multi_hop
,
679 .bfd_source
= bfd_source_str
,
680 .bfd_profile
= bfd_profile
,
683 return static_route_nb_run(vty
, &args
);
689 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
690 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
696 |table (1-4294967295) \
698 |color (1-4294967295) \
699 |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
702 "Establish static routes\n"
703 "IP destination prefix (e.g. 10.0.0.0/8)\n"
704 "IP destination prefix\n"
705 "IP destination prefix mask\n"
706 "IP gateway address\n"
707 "IP gateway interface name\n"
709 "Set tag for this route\n"
711 "Distance value for this route\n"
714 "Table to configure\n"
715 "The table number to configure\n"
718 "The SR-TE color to configure\n"
720 BFD_INTEGRATION_MULTI_HOP_STR
721 BFD_INTEGRATION_SOURCE_STR
722 BFD_INTEGRATION_SOURCEV4_STR
724 BFD_PROFILE_NAME_STR
)
726 struct static_route_args args
= {
729 .safi
= SAFI_UNICAST
,
731 .prefix_mask
= mask_str
,
733 .interface_name
= ifname
,
735 .distance
= distance_str
,
740 .nexthop_vrf
= nexthop_vrf
,
742 .bfd_multi_hop
= !!bfd_multi_hop
,
743 .bfd_source
= bfd_source_str
,
744 .bfd_profile
= bfd_profile
,
747 return static_route_nb_run(vty
, &args
);
750 DEFPY_YANG(ip_route_vrf
,
753 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
754 <A.B.C.D$gate|<INTERFACE|Null0>$ifname> \
759 |table (1-4294967295) \
761 |color (1-4294967295) \
762 |bfd$bfd [{multi-hop$bfd_multi_hop|source A.B.C.D$bfd_source|profile BFDPROF$bfd_profile}] \
765 "Establish static routes\n"
766 "IP destination prefix (e.g. 10.0.0.0/8)\n"
767 "IP destination prefix\n"
768 "IP destination prefix mask\n"
769 "IP gateway address\n"
770 "IP gateway interface name\n"
772 "Set tag for this route\n"
774 "Distance value for this route\n"
776 "Table to configure\n"
777 "The table number to configure\n"
780 "The SR-TE color to configure\n"
782 BFD_INTEGRATION_MULTI_HOP_STR
783 BFD_INTEGRATION_SOURCE_STR
784 BFD_INTEGRATION_SOURCEV4_STR
786 BFD_PROFILE_NAME_STR
)
788 struct static_route_args args
= {
791 .safi
= SAFI_UNICAST
,
793 .prefix_mask
= mask_str
,
795 .interface_name
= ifname
,
797 .distance
= distance_str
,
802 .nexthop_vrf
= nexthop_vrf
,
804 .bfd_multi_hop
= !!bfd_multi_hop
,
805 .bfd_source
= bfd_source_str
,
806 .bfd_profile
= bfd_profile
,
809 return static_route_nb_run(vty
, &args
);
812 DEFPY_YANG(ipv6_route_blackhole
,
813 ipv6_route_blackhole_cmd
,
814 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
815 <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"
836 "Table to configure\n"
837 "The table number to configure\n")
839 struct static_route_args args
= {
842 .safi
= SAFI_UNICAST
,
843 .prefix
= prefix_str
,
847 .distance
= distance_str
,
853 return static_route_nb_run(vty
, &args
);
856 DEFPY_YANG(ipv6_route_blackhole_vrf
,
857 ipv6_route_blackhole_vrf_cmd
,
858 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
859 <reject|blackhole>$flag \
864 |table (1-4294967295) \
868 "Establish static routes\n"
869 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
870 "IPv6 source-dest route\n"
871 "IPv6 source prefix\n"
872 "Emit an ICMP unreachable when matched\n"
873 "Silently discard pkts when matched\n"
874 "Set tag for this route\n"
876 "Distance value for this prefix\n"
878 "Table to configure\n"
879 "The table number to configure\n")
881 struct static_route_args args
= {
884 .safi
= SAFI_UNICAST
,
885 .prefix
= prefix_str
,
889 .distance
= distance_str
,
896 * Coverity is complaining that prefix could
897 * be dereferenced, but we know that prefix will
898 * valid. Add an assert to make it happy
902 return static_route_nb_run(vty
, &args
);
905 DEFPY_YANG(ipv6_route_address_interface
,
906 ipv6_route_address_interface_cmd
,
907 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
909 <INTERFACE|Null0>$ifname \
915 |table (1-4294967295) \
918 |color (1-4294967295) \
919 |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
923 "Establish static routes\n"
924 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
925 "IPv6 source-dest route\n"
926 "IPv6 source prefix\n"
927 "IPv6 gateway address\n"
928 "IPv6 gateway interface name\n"
930 "Set tag for this route\n"
932 "Distance value for this prefix\n"
935 "Table to configure\n"
936 "The table number to configure\n"
938 "Treat the nexthop as directly attached to the interface\n"
940 "The SR-TE color to configure\n"
942 BFD_INTEGRATION_MULTI_HOP_STR
943 BFD_INTEGRATION_SOURCE_STR
944 BFD_INTEGRATION_SOURCEV4_STR
946 BFD_PROFILE_NAME_STR
)
948 struct static_route_args args
= {
951 .safi
= SAFI_UNICAST
,
952 .prefix
= prefix_str
,
955 .interface_name
= ifname
,
957 .distance
= distance_str
,
963 .nexthop_vrf
= nexthop_vrf
,
965 .bfd_multi_hop
= !!bfd_multi_hop
,
966 .bfd_source
= bfd_source_str
,
967 .bfd_profile
= bfd_profile
,
970 return static_route_nb_run(vty
, &args
);
973 DEFPY_YANG(ipv6_route_address_interface_vrf
,
974 ipv6_route_address_interface_vrf_cmd
,
975 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
977 <INTERFACE|Null0>$ifname \
982 |table (1-4294967295) \
985 |color (1-4294967295) \
986 |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
990 "Establish static routes\n"
991 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
992 "IPv6 source-dest route\n"
993 "IPv6 source prefix\n"
994 "IPv6 gateway address\n"
995 "IPv6 gateway interface name\n"
997 "Set tag for this route\n"
999 "Distance value for this prefix\n"
1001 "Table to configure\n"
1002 "The table number to configure\n"
1004 "Treat the nexthop as directly attached to the interface\n"
1006 "The SR-TE color to configure\n"
1008 BFD_INTEGRATION_MULTI_HOP_STR
1009 BFD_INTEGRATION_SOURCE_STR
1010 BFD_INTEGRATION_SOURCEV4_STR
1012 BFD_PROFILE_NAME_STR
)
1014 struct static_route_args args
= {
1017 .safi
= SAFI_UNICAST
,
1018 .prefix
= prefix_str
,
1020 .gateway
= gate_str
,
1021 .interface_name
= ifname
,
1023 .distance
= distance_str
,
1029 .nexthop_vrf
= nexthop_vrf
,
1031 .bfd_multi_hop
= !!bfd_multi_hop
,
1032 .bfd_source
= bfd_source_str
,
1033 .bfd_profile
= bfd_profile
,
1036 return static_route_nb_run(vty
, &args
);
1039 DEFPY_YANG(ipv6_route
,
1041 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1042 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
1044 tag (1-4294967295) \
1048 |table (1-4294967295) \
1050 |color (1-4294967295) \
1051 |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
1055 "Establish static routes\n"
1056 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1057 "IPv6 source-dest route\n"
1058 "IPv6 source prefix\n"
1059 "IPv6 gateway address\n"
1060 "IPv6 gateway interface name\n"
1062 "Set tag for this route\n"
1064 "Distance value for this prefix\n"
1067 "Table to configure\n"
1068 "The table number to configure\n"
1071 "The SR-TE color to configure\n"
1073 BFD_INTEGRATION_MULTI_HOP_STR
1074 BFD_INTEGRATION_SOURCE_STR
1075 BFD_INTEGRATION_SOURCEV4_STR
1077 BFD_PROFILE_NAME_STR
)
1079 struct static_route_args args
= {
1082 .safi
= SAFI_UNICAST
,
1083 .prefix
= prefix_str
,
1085 .gateway
= gate_str
,
1086 .interface_name
= ifname
,
1088 .distance
= distance_str
,
1093 .nexthop_vrf
= nexthop_vrf
,
1095 .bfd_multi_hop
= !!bfd_multi_hop
,
1096 .bfd_source
= bfd_source_str
,
1097 .bfd_profile
= bfd_profile
,
1100 return static_route_nb_run(vty
, &args
);
1103 DEFPY_YANG(ipv6_route_vrf
,
1105 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
1106 <X:X::X:X$gate|<INTERFACE|Null0>$ifname> \
1108 tag (1-4294967295) \
1111 |table (1-4294967295) \
1113 |color (1-4294967295) \
1114 |bfd$bfd [{multi-hop$bfd_multi_hop|source X:X::X:X$bfd_source|profile BFDPROF$bfd_profile}] \
1118 "Establish static routes\n"
1119 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
1120 "IPv6 source-dest route\n"
1121 "IPv6 source prefix\n"
1122 "IPv6 gateway address\n"
1123 "IPv6 gateway interface name\n"
1125 "Set tag for this route\n"
1127 "Distance value for this prefix\n"
1129 "Table to configure\n"
1130 "The table number to configure\n"
1133 "The SR-TE color to configure\n"
1135 BFD_INTEGRATION_MULTI_HOP_STR
1136 BFD_INTEGRATION_SOURCE_STR
1137 BFD_INTEGRATION_SOURCEV4_STR
1139 BFD_PROFILE_NAME_STR
)
1141 struct static_route_args args
= {
1144 .safi
= SAFI_UNICAST
,
1145 .prefix
= prefix_str
,
1147 .gateway
= gate_str
,
1148 .interface_name
= ifname
,
1150 .distance
= distance_str
,
1155 .nexthop_vrf
= nexthop_vrf
,
1157 .bfd_multi_hop
= !!bfd_multi_hop
,
1158 .bfd_source
= bfd_source_str
,
1159 .bfd_profile
= bfd_profile
,
1162 return static_route_nb_run(vty
, &args
);
1165 void static_cli_show(struct vty
*vty
, const struct lyd_node
*dnode
,
1170 vrf
= yang_dnode_get_string(dnode
, "../vrf");
1171 if (strcmp(vrf
, VRF_DEFAULT_NAME
))
1172 vty_out(vty
, "vrf %s\n", vrf
);
1175 void static_cli_show_end(struct vty
*vty
, const struct lyd_node
*dnode
)
1179 vrf
= yang_dnode_get_string(dnode
, "../vrf");
1180 if (strcmp(vrf
, VRF_DEFAULT_NAME
))
1181 vty_out(vty
, "exit-vrf\n");
1184 struct mpls_label_iter
{
1189 static int mpls_label_iter_cb(const struct lyd_node
*dnode
, void *arg
)
1191 struct mpls_label_iter
*iter
= arg
;
1193 if (yang_dnode_exists(dnode
, "./label")) {
1195 vty_out(iter
->vty
, " label %s",
1196 yang_dnode_get_string(dnode
, "./label"));
1198 vty_out(iter
->vty
, "/%s",
1199 yang_dnode_get_string(dnode
, "./label"));
1200 iter
->first
= false;
1203 return YANG_ITER_CONTINUE
;
1206 static void nexthop_cli_show(struct vty
*vty
, const struct lyd_node
*route
,
1207 const struct lyd_node
*src
,
1208 const struct lyd_node
*path
,
1209 const struct lyd_node
*nexthop
, bool show_defaults
)
1212 const char *afi_safi
;
1215 enum static_nh_type nh_type
;
1216 enum static_blackhole_type bh_type
;
1219 struct mpls_label_iter iter
;
1220 const char *nexthop_vrf
;
1224 vrf
= yang_dnode_get_string(route
, "../../vrf");
1226 afi_safi
= yang_dnode_get_string(route
, "./afi-safi");
1227 yang_afi_safi_identity2value(afi_safi
, &afi
, &safi
);
1230 vty_out(vty
, "%sip",
1231 strmatch(vrf
, VRF_DEFAULT_NAME
) ? "" : " ");
1233 vty_out(vty
, "%sipv6",
1234 strmatch(vrf
, VRF_DEFAULT_NAME
) ? "" : " ");
1236 if (safi
== SAFI_UNICAST
)
1237 vty_out(vty
, " route");
1239 vty_out(vty
, " mroute");
1241 vty_out(vty
, " %s", yang_dnode_get_string(route
, "./prefix"));
1244 vty_out(vty
, " from %s",
1245 yang_dnode_get_string(src
, "./src-prefix"));
1247 nh_type
= yang_dnode_get_enum(nexthop
, "./nh-type");
1251 yang_dnode_get_string(nexthop
, "./interface"));
1253 case STATIC_IPV4_GATEWAY
:
1254 case STATIC_IPV6_GATEWAY
:
1256 yang_dnode_get_string(nexthop
, "./gateway"));
1258 case STATIC_IPV4_GATEWAY_IFNAME
:
1259 case STATIC_IPV6_GATEWAY_IFNAME
:
1261 yang_dnode_get_string(nexthop
, "./gateway"));
1263 yang_dnode_get_string(nexthop
, "./interface"));
1265 case STATIC_BLACKHOLE
:
1266 bh_type
= yang_dnode_get_enum(nexthop
, "./bh-type");
1268 case STATIC_BLACKHOLE_DROP
:
1269 vty_out(vty
, " blackhole");
1271 case STATIC_BLACKHOLE_NULL
:
1272 vty_out(vty
, " Null0");
1274 case STATIC_BLACKHOLE_REJECT
:
1275 vty_out(vty
, " reject");
1281 if (yang_dnode_exists(path
, "./tag")) {
1282 tag
= yang_dnode_get_uint32(path
, "./tag");
1283 if (tag
!= 0 || show_defaults
)
1284 vty_out(vty
, " tag %" PRIu32
, tag
);
1287 distance
= yang_dnode_get_uint8(path
, "./distance");
1288 if (distance
!= ZEBRA_STATIC_DISTANCE_DEFAULT
|| show_defaults
)
1289 vty_out(vty
, " %" PRIu8
, distance
);
1293 yang_dnode_iterate(mpls_label_iter_cb
, &iter
, nexthop
,
1294 "./mpls-label-stack/entry");
1296 nexthop_vrf
= yang_dnode_get_string(nexthop
, "./vrf");
1297 if (strcmp(vrf
, nexthop_vrf
))
1298 vty_out(vty
, " nexthop-vrf %s", nexthop_vrf
);
1300 table_id
= yang_dnode_get_uint32(path
, "./table-id");
1301 if (table_id
|| show_defaults
)
1302 vty_out(vty
, " table %" PRIu32
, table_id
);
1304 if (yang_dnode_exists(nexthop
, "./onlink")) {
1305 onlink
= yang_dnode_get_bool(nexthop
, "./onlink");
1307 vty_out(vty
, " onlink");
1310 if (yang_dnode_exists(nexthop
, "./srte-color"))
1311 vty_out(vty
, " color %s",
1312 yang_dnode_get_string(nexthop
, "./srte-color"));
1314 if (yang_dnode_exists(nexthop
, "./bfd-monitoring")) {
1315 const struct lyd_node
*bfd_dnode
=
1316 yang_dnode_get(nexthop
, "./bfd-monitoring");
1318 if (yang_dnode_get_bool(bfd_dnode
, "./multi-hop")) {
1319 vty_out(vty
, " bfd multi-hop");
1321 if (yang_dnode_exists(bfd_dnode
, "./source"))
1322 vty_out(vty
, " source %s",
1323 yang_dnode_get_string(bfd_dnode
,
1326 vty_out(vty
, " bfd");
1328 if (yang_dnode_exists(bfd_dnode
, "./profile"))
1329 vty_out(vty
, " profile %s",
1330 yang_dnode_get_string(bfd_dnode
, "./profile"));
1336 void static_nexthop_cli_show(struct vty
*vty
, const struct lyd_node
*dnode
,
1339 const struct lyd_node
*path
= yang_dnode_get_parent(dnode
, "path-list");
1340 const struct lyd_node
*route
=
1341 yang_dnode_get_parent(path
, "route-list");
1343 nexthop_cli_show(vty
, route
, NULL
, path
, dnode
, show_defaults
);
1346 void static_src_nexthop_cli_show(struct vty
*vty
, const struct lyd_node
*dnode
,
1349 const struct lyd_node
*path
= yang_dnode_get_parent(dnode
, "path-list");
1350 const struct lyd_node
*src
= yang_dnode_get_parent(path
, "src-list");
1351 const struct lyd_node
*route
= yang_dnode_get_parent(src
, "route-list");
1353 nexthop_cli_show(vty
, route
, src
, path
, dnode
, show_defaults
);
1356 int static_nexthop_cli_cmp(const struct lyd_node
*dnode1
,
1357 const struct lyd_node
*dnode2
)
1359 enum static_nh_type nh_type1
, nh_type2
;
1360 struct prefix prefix1
, prefix2
;
1363 nh_type1
= yang_dnode_get_enum(dnode1
, "./nh-type");
1364 nh_type2
= yang_dnode_get_enum(dnode2
, "./nh-type");
1366 if (nh_type1
!= nh_type2
)
1367 return (int)nh_type1
- (int)nh_type2
;
1371 ret
= if_cmp_name_func(
1372 yang_dnode_get_string(dnode1
, "./interface"),
1373 yang_dnode_get_string(dnode2
, "./interface"));
1375 case STATIC_IPV4_GATEWAY
:
1376 case STATIC_IPV6_GATEWAY
:
1377 yang_dnode_get_prefix(&prefix1
, dnode1
, "./gateway");
1378 yang_dnode_get_prefix(&prefix2
, dnode2
, "./gateway");
1379 ret
= prefix_cmp(&prefix1
, &prefix2
);
1381 case STATIC_IPV4_GATEWAY_IFNAME
:
1382 case STATIC_IPV6_GATEWAY_IFNAME
:
1383 yang_dnode_get_prefix(&prefix1
, dnode1
, "./gateway");
1384 yang_dnode_get_prefix(&prefix2
, dnode2
, "./gateway");
1385 ret
= prefix_cmp(&prefix1
, &prefix2
);
1387 ret
= if_cmp_name_func(
1388 yang_dnode_get_string(dnode1
, "./interface"),
1389 yang_dnode_get_string(dnode2
, "./interface"));
1391 case STATIC_BLACKHOLE
:
1392 /* There's only one blackhole nexthop per route */
1400 return if_cmp_name_func(yang_dnode_get_string(dnode1
, "./vrf"),
1401 yang_dnode_get_string(dnode2
, "./vrf"));
1404 int static_route_list_cli_cmp(const struct lyd_node
*dnode1
,
1405 const struct lyd_node
*dnode2
)
1407 const char *afi_safi1
, *afi_safi2
;
1409 safi_t safi1
, safi2
;
1410 struct prefix prefix1
, prefix2
;
1412 afi_safi1
= yang_dnode_get_string(dnode1
, "./afi-safi");
1413 yang_afi_safi_identity2value(afi_safi1
, &afi1
, &safi1
);
1415 afi_safi2
= yang_dnode_get_string(dnode2
, "./afi-safi");
1416 yang_afi_safi_identity2value(afi_safi2
, &afi2
, &safi2
);
1419 return (int)afi1
- (int)afi2
;
1422 return (int)safi1
- (int)safi2
;
1424 yang_dnode_get_prefix(&prefix1
, dnode1
, "./prefix");
1425 yang_dnode_get_prefix(&prefix2
, dnode2
, "./prefix");
1427 return prefix_cmp(&prefix1
, &prefix2
);
1430 int static_src_list_cli_cmp(const struct lyd_node
*dnode1
,
1431 const struct lyd_node
*dnode2
)
1433 struct prefix prefix1
, prefix2
;
1435 yang_dnode_get_prefix(&prefix1
, dnode1
, "./src-prefix");
1436 yang_dnode_get_prefix(&prefix2
, dnode2
, "./src-prefix");
1438 return prefix_cmp(&prefix1
, &prefix2
);
1441 int static_path_list_cli_cmp(const struct lyd_node
*dnode1
,
1442 const struct lyd_node
*dnode2
)
1444 uint32_t table_id1
, table_id2
;
1445 uint8_t distance1
, distance2
;
1447 table_id1
= yang_dnode_get_uint32(dnode1
, "./table-id");
1448 table_id2
= yang_dnode_get_uint32(dnode2
, "./table-id");
1450 if (table_id1
!= table_id2
)
1451 return (int)table_id1
- (int)table_id2
;
1453 distance1
= yang_dnode_get_uint8(dnode1
, "./distance");
1454 distance2
= yang_dnode_get_uint8(dnode2
, "./distance");
1456 return (int)distance1
- (int)distance2
;
1459 DEFPY_YANG(debug_staticd
, debug_staticd_cmd
,
1460 "[no] debug static [{events$events|route$route|bfd$bfd}]",
1461 NO_STR DEBUG_STR STATICD_STR
1466 /* If no specific category, change all */
1467 if (strmatch(argv
[argc
- 1]->text
, "static"))
1468 static_debug_set(vty
->node
, !no
, true, true, true);
1470 static_debug_set(vty
->node
, !no
, !!events
, !!route
, !!bfd
);
1475 DEFPY(staticd_show_bfd_routes
, staticd_show_bfd_routes_cmd
,
1476 "show bfd static route [json]$isjson",
1483 static_bfd_show(vty
, !!isjson
);
1487 DEFUN_NOSH (show_debugging_static
,
1488 show_debugging_static_cmd
,
1489 "show debugging [static]",
1492 "Static Information\n")
1494 vty_out(vty
, "Staticd debugging status\n");
1496 static_debug_status_write(vty
);
1498 cmd_show_lib_debugs(vty
);
1503 static struct cmd_node debug_node
= {
1507 .config_write
= static_config_write_debug
,
1510 void static_vty_init(void)
1512 install_node(&debug_node
);
1514 install_element(CONFIG_NODE
, &ip_mroute_dist_cmd
);
1516 install_element(CONFIG_NODE
, &ip_route_blackhole_cmd
);
1517 install_element(VRF_NODE
, &ip_route_blackhole_vrf_cmd
);
1518 install_element(CONFIG_NODE
, &ip_route_address_interface_cmd
);
1519 install_element(VRF_NODE
, &ip_route_address_interface_vrf_cmd
);
1520 install_element(CONFIG_NODE
, &ip_route_cmd
);
1521 install_element(VRF_NODE
, &ip_route_vrf_cmd
);
1523 install_element(CONFIG_NODE
, &ipv6_route_blackhole_cmd
);
1524 install_element(VRF_NODE
, &ipv6_route_blackhole_vrf_cmd
);
1525 install_element(CONFIG_NODE
, &ipv6_route_address_interface_cmd
);
1526 install_element(VRF_NODE
, &ipv6_route_address_interface_vrf_cmd
);
1527 install_element(CONFIG_NODE
, &ipv6_route_cmd
);
1528 install_element(VRF_NODE
, &ipv6_route_vrf_cmd
);
1530 install_element(ENABLE_NODE
, &show_debugging_static_cmd
);
1531 install_element(ENABLE_NODE
, &debug_staticd_cmd
);
1532 install_element(CONFIG_NODE
, &debug_staticd_cmd
);
1534 install_element(ENABLE_NODE
, &staticd_show_bfd_routes_cmd
);