1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2018 Cumulus Networks, Inc.
9 #include <lib/nexthop.h>
10 #include <lib/memory.h>
11 #include <lib/srcdest_table.h>
15 #include <lib/memory.h>
19 #include "static_vrf.h"
20 #include "static_routes.h"
21 #include "static_zebra.h"
22 #include "static_debug.h"
24 DEFINE_MGROUP(STATIC
, "staticd");
26 DEFINE_MTYPE_STATIC(STATIC
, STATIC_ROUTE
, "Static Route Info");
27 DEFINE_MTYPE_STATIC(STATIC
, STATIC_PATH
, "Static Path");
28 DEFINE_MTYPE_STATIC(STATIC
, STATIC_NEXTHOP
, "Static Nexthop");
30 void zebra_stable_node_cleanup(struct route_table
*table
,
31 struct route_node
*node
)
33 struct static_nexthop
*nh
;
34 struct static_path
*pn
;
35 struct static_route_info
*si
;
36 struct route_table
*src_table
;
37 struct route_node
*src_node
;
38 struct static_path
*src_pn
;
39 struct static_route_info
*src_si
;
44 frr_each_safe(static_path_list
, &si
->path_list
, pn
) {
45 frr_each_safe(static_nexthop_list
, &pn
->nexthop_list
,
47 static_nexthop_list_del(&pn
->nexthop_list
, nh
);
48 XFREE(MTYPE_STATIC_NEXTHOP
, nh
);
50 static_path_list_del(&si
->path_list
, pn
);
51 XFREE(MTYPE_STATIC_PATH
, pn
);
54 /* clean up for dst table */
55 src_table
= srcdest_srcnode_table(node
);
57 /* This means the route_node is part of the top
58 * hierarchy and refers to a destination prefix.
60 for (src_node
= route_top(src_table
); src_node
;
61 src_node
= route_next(src_node
)) {
62 src_si
= src_node
->info
;
64 frr_each_safe(static_path_list
,
65 &src_si
->path_list
, src_pn
) {
66 frr_each_safe(static_nexthop_list
,
67 &src_pn
->nexthop_list
,
69 static_nexthop_list_del(
70 &src_pn
->nexthop_list
,
72 XFREE(MTYPE_STATIC_NEXTHOP
, nh
);
74 static_path_list_del(&src_si
->path_list
,
76 XFREE(MTYPE_STATIC_PATH
, src_pn
);
79 XFREE(MTYPE_STATIC_ROUTE
, src_node
->info
);
83 XFREE(MTYPE_STATIC_ROUTE
, node
->info
);
87 /* Install static path into rib. */
88 void static_install_path(struct static_path
*pn
)
90 struct static_nexthop
*nh
;
92 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
)
93 static_zebra_nht_register(nh
, true);
95 if (static_nexthop_list_count(&pn
->nexthop_list
))
96 static_zebra_route_add(pn
, true);
99 /* Uninstall static path from RIB. */
100 static void static_uninstall_path(struct static_path
*pn
)
102 if (static_nexthop_list_count(&pn
->nexthop_list
))
103 static_zebra_route_add(pn
, true);
105 static_zebra_route_add(pn
, false);
108 struct route_node
*static_add_route(afi_t afi
, safi_t safi
, struct prefix
*p
,
109 struct prefix_ipv6
*src_p
,
110 struct static_vrf
*svrf
)
112 struct route_node
*rn
;
113 struct static_route_info
*si
;
114 struct route_table
*stable
= svrf
->stable
[afi
][safi
];
118 /* Lookup static route prefix. */
119 rn
= srcdest_rnode_get(stable
, p
, src_p
);
121 si
= XCALLOC(MTYPE_STATIC_ROUTE
, sizeof(struct static_route_info
));
125 static_path_list_init(&(si
->path_list
));
132 /* To delete the srcnodes */
133 static void static_del_src_route(struct route_node
*rn
)
135 struct static_path
*pn
;
136 struct static_route_info
*si
;
140 frr_each_safe(static_path_list
, &si
->path_list
, pn
) {
144 XFREE(MTYPE_STATIC_ROUTE
, rn
->info
);
145 route_unlock_node(rn
);
148 void static_del_route(struct route_node
*rn
)
150 struct static_path
*pn
;
151 struct static_route_info
*si
;
152 struct route_table
*src_table
;
153 struct route_node
*src_node
;
157 frr_each_safe(static_path_list
, &si
->path_list
, pn
) {
161 /* clean up for dst table */
162 src_table
= srcdest_srcnode_table(rn
);
164 /* This means the route_node is part of the top hierarchy
165 * and refers to a destination prefix.
167 for (src_node
= route_top(src_table
); src_node
;
168 src_node
= route_next(src_node
)) {
169 static_del_src_route(src_node
);
172 XFREE(MTYPE_STATIC_ROUTE
, rn
->info
);
173 route_unlock_node(rn
);
176 bool static_add_nexthop_validate(const char *nh_vrf_name
,
177 enum static_nh_type type
,
178 struct ipaddr
*ipaddr
)
182 vrf
= vrf_lookup_by_name(nh_vrf_name
);
187 case STATIC_IPV4_GATEWAY
:
188 case STATIC_IPV4_GATEWAY_IFNAME
:
189 if (if_address_is_local(&ipaddr
->ipaddr_v4
, AF_INET
,
193 case STATIC_IPV6_GATEWAY
:
194 case STATIC_IPV6_GATEWAY_IFNAME
:
195 if (if_address_is_local(&ipaddr
->ipaddr_v6
, AF_INET6
,
200 case STATIC_BLACKHOLE
:
207 struct static_path
*static_add_path(struct route_node
*rn
, uint32_t table_id
,
210 struct static_path
*pn
;
211 struct static_route_info
*si
;
215 /* Make new static route structure. */
216 pn
= XCALLOC(MTYPE_STATIC_PATH
, sizeof(struct static_path
));
219 pn
->distance
= distance
;
220 pn
->table_id
= table_id
;
221 static_nexthop_list_init(&(pn
->nexthop_list
));
224 static_path_list_add_head(&(si
->path_list
), pn
);
229 void static_del_path(struct static_path
*pn
)
231 struct route_node
*rn
= pn
->rn
;
232 struct static_route_info
*si
;
233 struct static_nexthop
*nh
;
237 static_path_list_del(&si
->path_list
, pn
);
239 frr_each_safe(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
240 static_delete_nexthop(nh
);
243 route_unlock_node(rn
);
245 XFREE(MTYPE_STATIC_PATH
, pn
);
248 struct static_nexthop
*static_add_nexthop(struct static_path
*pn
,
249 enum static_nh_type type
,
250 struct ipaddr
*ipaddr
,
252 const char *nh_vrf
, uint32_t color
)
254 struct route_node
*rn
= pn
->rn
;
255 struct static_nexthop
*nh
;
256 struct static_vrf
*nh_svrf
;
257 struct interface
*ifp
;
258 struct static_nexthop
*cp
;
262 nh_svrf
= static_vrf_lookup_by_name(nh_vrf
);
264 /* Make new static route structure. */
265 nh
= XCALLOC(MTYPE_STATIC_NEXTHOP
, sizeof(struct static_nexthop
));
267 /* Copy back pointers. */
274 if (nh
->type
== STATIC_BLACKHOLE
)
275 nh
->bh_type
= STATIC_BLACKHOLE_NULL
;
277 nh
->nh_vrf_id
= nh_svrf
? nh_svrf
->vrf
->vrf_id
: VRF_UNKNOWN
;
278 strlcpy(nh
->nh_vrfname
, nh_vrf
, sizeof(nh
->nh_vrfname
));
281 strlcpy(nh
->ifname
, ifname
, sizeof(nh
->ifname
));
282 nh
->ifindex
= IFINDEX_INTERNAL
;
285 case STATIC_IPV4_GATEWAY
:
286 case STATIC_IPV4_GATEWAY_IFNAME
:
287 nh
->addr
.ipv4
= ipaddr
->ipaddr_v4
;
289 case STATIC_IPV6_GATEWAY
:
290 case STATIC_IPV6_GATEWAY_IFNAME
:
291 nh
->addr
.ipv6
= ipaddr
->ipaddr_v6
;
294 case STATIC_BLACKHOLE
:
298 * Add new static route information to the tree with sort by
301 frr_each(static_nexthop_list
, &pn
->nexthop_list
, cp
) {
302 if (nh
->type
== STATIC_IPV4_GATEWAY
303 && cp
->type
== STATIC_IPV4_GATEWAY
) {
304 if (ntohl(nh
->addr
.ipv4
.s_addr
)
305 < ntohl(cp
->addr
.ipv4
.s_addr
))
307 if (ntohl(nh
->addr
.ipv4
.s_addr
)
308 > ntohl(cp
->addr
.ipv4
.s_addr
))
312 static_nexthop_list_add_after(&(pn
->nexthop_list
), cp
, nh
);
314 if (nh
->nh_vrf_id
== VRF_UNKNOWN
) {
316 "Static Route to %pFX not installed currently because dependent config not fully available",
321 /* check whether interface exists in system & install if it does */
323 case STATIC_IPV4_GATEWAY
:
324 case STATIC_IPV6_GATEWAY
:
325 case STATIC_BLACKHOLE
:
327 case STATIC_IPV4_GATEWAY_IFNAME
:
328 case STATIC_IPV6_GATEWAY_IFNAME
:
330 ifp
= if_lookup_by_name(ifname
, nh
->nh_vrf_id
);
331 if (ifp
&& ifp
->ifindex
!= IFINDEX_INTERNAL
)
332 nh
->ifindex
= ifp
->ifindex
;
335 "Static Route using %s interface not installed because the interface does not exist in specified vrf",
343 void static_install_nexthop(struct static_nexthop
*nh
)
345 struct static_path
*pn
= nh
->pn
;
346 struct route_node
*rn
= pn
->rn
;
347 struct interface
*ifp
;
349 if (nh
->nh_vrf_id
== VRF_UNKNOWN
) {
350 char nexthop_str
[NEXTHOP_STR
];
352 static_get_nh_str(nh
, nexthop_str
, sizeof(nexthop_str
));
353 DEBUGD(&static_dbg_route
,
354 "Static Route %pFX not installed for %s vrf %s is unknown",
355 &rn
->p
, nexthop_str
, nh
->nh_vrfname
);
359 /* check whether interface exists in system & install if it does */
361 case STATIC_IPV4_GATEWAY
:
362 case STATIC_IPV6_GATEWAY
:
363 static_zebra_nht_register(nh
, true);
365 case STATIC_IPV4_GATEWAY_IFNAME
:
366 case STATIC_IPV6_GATEWAY_IFNAME
:
367 static_zebra_nht_register(nh
, true);
369 case STATIC_BLACKHOLE
:
370 static_install_path(pn
);
373 ifp
= if_lookup_by_name(nh
->ifname
, nh
->nh_vrf_id
);
374 if (ifp
&& ifp
->ifindex
!= IFINDEX_INTERNAL
)
375 static_install_path(pn
);
381 void static_delete_nexthop(struct static_nexthop
*nh
)
383 struct static_path
*pn
= nh
->pn
;
384 struct route_node
*rn
= pn
->rn
;
386 static_nexthop_list_del(&(pn
->nexthop_list
), nh
);
387 /* Remove BFD session/configuration if any. */
388 bfd_sess_free(&nh
->bsp
);
390 if (nh
->nh_vrf_id
== VRF_UNKNOWN
)
393 static_zebra_nht_register(nh
, false);
395 * If we have other si nodes then route replace
396 * else delete the route
398 static_uninstall_path(pn
);
401 route_unlock_node(rn
);
402 /* Free static route configuration. */
403 XFREE(MTYPE_STATIC_NEXTHOP
, nh
);
406 static void static_ifindex_update_nh(struct interface
*ifp
, bool up
,
407 struct route_node
*rn
,
408 struct static_path
*pn
,
409 struct static_nexthop
*nh
,
410 struct static_vrf
*svrf
, safi_t safi
)
415 if (strcmp(nh
->ifname
, ifp
->name
))
417 if (nh
->nh_vrf_id
!= ifp
->vrf
->vrf_id
)
419 nh
->ifindex
= ifp
->ifindex
;
421 if (nh
->ifindex
!= ifp
->ifindex
)
423 if (nh
->nh_vrf_id
!= ifp
->vrf
->vrf_id
)
425 nh
->ifindex
= IFINDEX_INTERNAL
;
428 /* Remove previously configured route if any. */
429 static_uninstall_path(pn
);
430 static_install_path(pn
);
433 static void static_ifindex_update_af(struct interface
*ifp
, bool up
, afi_t afi
,
436 struct route_table
*stable
;
437 struct route_node
*rn
;
438 struct static_nexthop
*nh
;
439 struct static_path
*pn
;
441 struct static_route_info
*si
;
443 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
444 struct static_vrf
*svrf
;
448 stable
= static_vrf_static_table(afi
, safi
, svrf
);
451 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
)) {
452 si
= static_route_info_from_rnode(rn
);
455 frr_each(static_path_list
, &si
->path_list
, pn
) {
456 frr_each(static_nexthop_list
,
457 &pn
->nexthop_list
, nh
) {
458 static_ifindex_update_nh(ifp
, up
, rn
,
468 * This function looks at a svrf's stable and notices if any of the
469 * nexthops we are using are part of the vrf coming up.
470 * If we are using them then cleanup the nexthop vrf id
471 * to be the new value and then re-installs them
474 * stable -> The table we are looking at.
475 * svrf -> The newly changed vrf.
476 * afi -> The afi to look at
477 * safi -> the safi to look at
479 static void static_fixup_vrf(struct static_vrf
*svrf
,
480 struct route_table
*stable
, afi_t afi
, safi_t safi
)
482 struct route_node
*rn
;
483 struct static_nexthop
*nh
;
484 struct interface
*ifp
;
485 struct static_path
*pn
;
486 struct static_route_info
*si
;
488 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
489 si
= static_route_info_from_rnode(rn
);
492 frr_each(static_path_list
, &si
->path_list
, pn
) {
493 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
494 if (strcmp(svrf
->vrf
->name
, nh
->nh_vrfname
)
498 nh
->nh_vrf_id
= svrf
->vrf
->vrf_id
;
499 nh
->nh_registered
= false;
501 ifp
= if_lookup_by_name(nh
->ifname
,
504 nh
->ifindex
= ifp
->ifindex
;
509 static_install_path(pn
);
516 * This function enables static routes in a svrf as it
517 * is coming up. It sets the new vrf_id as appropriate.
519 * svrf -> The svrf that is being brought up and enabled by the kernel
520 * stable -> The stable we are looking at.
521 * afi -> the afi in question
522 * safi -> the safi in question
524 static void static_enable_vrf(struct static_vrf
*svrf
,
525 struct route_table
*stable
, afi_t afi
,
528 struct route_node
*rn
;
529 struct static_nexthop
*nh
;
530 struct interface
*ifp
;
531 struct static_path
*pn
;
532 struct static_route_info
*si
;
534 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
535 si
= static_route_info_from_rnode(rn
);
538 frr_each(static_path_list
, &si
->path_list
, pn
) {
539 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
541 ifp
= if_lookup_by_name(nh
->ifname
,
544 nh
->ifindex
= ifp
->ifindex
;
548 if (nh
->nh_vrf_id
== VRF_UNKNOWN
)
550 static_install_path(pn
);
557 * When a vrf is being enabled by the kernel, go through all the
558 * static routes in the system that use this vrf (both nexthops vrfs
559 * and the routes vrf )
561 * enable_svrf -> the vrf being enabled
563 void static_fixup_vrf_ids(struct static_vrf
*enable_svrf
)
565 struct route_table
*stable
;
570 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
571 struct static_vrf
*svrf
;
574 /* Install any static routes configured for this VRF. */
575 FOREACH_AFI_SAFI (afi
, safi
) {
576 stable
= svrf
->stable
[afi
][safi
];
580 static_fixup_vrf(enable_svrf
, stable
, afi
, safi
);
582 if (enable_svrf
== svrf
)
583 static_enable_vrf(svrf
, stable
, afi
, safi
);
589 * Look at the specified stable and if any of the routes in
590 * this table are using the svrf as the nexthop, uninstall
593 * svrf -> the vrf being disabled
594 * stable -> the table we need to look at.
595 * afi -> the afi in question
596 * safi -> the safi in question
598 static void static_cleanup_vrf(struct static_vrf
*svrf
,
599 struct route_table
*stable
,
600 afi_t afi
, safi_t safi
)
602 struct route_node
*rn
;
603 struct static_nexthop
*nh
;
604 struct static_path
*pn
;
605 struct static_route_info
*si
;
607 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
608 si
= static_route_info_from_rnode(rn
);
611 frr_each(static_path_list
, &si
->path_list
, pn
) {
612 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
613 if (strcmp(svrf
->vrf
->name
, nh
->nh_vrfname
)
617 static_uninstall_path(pn
);
624 * Look at all static routes in this table and uninstall
627 * stable -> The table to uninstall from
628 * afi -> The afi in question
629 * safi -> the safi in question
631 static void static_disable_vrf(struct route_table
*stable
,
632 afi_t afi
, safi_t safi
)
634 struct route_node
*rn
;
635 struct static_nexthop
*nh
;
636 struct static_path
*pn
;
637 struct static_route_info
*si
;
639 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
640 si
= static_route_info_from_rnode(rn
);
643 frr_each(static_path_list
, &si
->path_list
, pn
) {
644 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
645 static_uninstall_path(pn
);
652 * When the disable_svrf is shutdown by the kernel, we call
653 * this function and it cleans up all static routes using
654 * this vrf as a nexthop as well as all static routes
657 * disable_svrf - The vrf being disabled
659 void static_cleanup_vrf_ids(struct static_vrf
*disable_svrf
)
665 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
666 struct static_vrf
*svrf
;
670 /* Uninstall any static routes configured for this VRF. */
671 FOREACH_AFI_SAFI (afi
, safi
) {
672 struct route_table
*stable
;
674 stable
= svrf
->stable
[afi
][safi
];
678 static_cleanup_vrf(disable_svrf
, stable
, afi
, safi
);
680 if (disable_svrf
== svrf
)
681 static_disable_vrf(stable
, afi
, safi
);
687 * This function enables static routes when an interface it relies
688 * on in a different vrf is coming up.
690 * stable -> The stable we are looking at.
691 * ifp -> interface coming up
692 * afi -> the afi in question
693 * safi -> the safi in question
695 static void static_fixup_intf_nh(struct route_table
*stable
,
696 struct interface
*ifp
,
697 afi_t afi
, safi_t safi
)
699 struct route_node
*rn
;
700 struct static_nexthop
*nh
;
701 struct static_path
*pn
;
702 struct static_route_info
*si
;
704 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
705 si
= static_route_info_from_rnode(rn
);
708 frr_each(static_path_list
, &si
->path_list
, pn
) {
709 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
710 if (nh
->nh_vrf_id
!= ifp
->vrf
->vrf_id
)
713 if (nh
->ifindex
!= ifp
->ifindex
)
716 static_install_path(pn
);
723 * This function enables static routes that rely on an interface in
724 * a different vrf when that interface comes up.
726 void static_install_intf_nh(struct interface
*ifp
)
728 struct route_table
*stable
;
733 RB_FOREACH(vrf
, vrf_name_head
, &vrfs_by_name
) {
734 struct static_vrf
*svrf
= vrf
->info
;
736 /* Not needed if same vrf since happens naturally */
737 if (vrf
->vrf_id
== ifp
->vrf
->vrf_id
)
740 /* Install any static routes configured for this interface. */
741 FOREACH_AFI_SAFI (afi
, safi
) {
742 stable
= svrf
->stable
[afi
][safi
];
746 static_fixup_intf_nh(stable
, ifp
, afi
, safi
);
751 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
752 void static_ifindex_update(struct interface
*ifp
, bool up
)
754 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_UNICAST
);
755 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_MULTICAST
);
756 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_UNICAST
);
757 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_MULTICAST
);
760 void static_get_nh_type(enum static_nh_type stype
, char *type
, size_t size
)
764 strlcpy(type
, "ifindex", size
);
766 case STATIC_IPV4_GATEWAY
:
767 strlcpy(type
, "ip4", size
);
769 case STATIC_IPV4_GATEWAY_IFNAME
:
770 strlcpy(type
, "ip4-ifindex", size
);
772 case STATIC_BLACKHOLE
:
773 strlcpy(type
, "blackhole", size
);
775 case STATIC_IPV6_GATEWAY
:
776 strlcpy(type
, "ip6", size
);
778 case STATIC_IPV6_GATEWAY_IFNAME
:
779 strlcpy(type
, "ip6-ifindex", size
);
784 struct stable_info
*static_get_stable_info(struct route_node
*rn
)
786 struct route_table
*table
;
788 table
= srcdest_rnode_table(rn
);
792 void static_get_nh_str(struct static_nexthop
*nh
, char *nexthop
, size_t size
)
796 snprintfrr(nexthop
, size
, "ifindex : %s", nh
->ifname
);
798 case STATIC_IPV4_GATEWAY
:
799 snprintfrr(nexthop
, size
, "ip4 : %pI4", &nh
->addr
.ipv4
);
801 case STATIC_IPV4_GATEWAY_IFNAME
:
802 snprintfrr(nexthop
, size
, "ip4-ifindex : %pI4 : %s",
803 &nh
->addr
.ipv4
, nh
->ifname
);
805 case STATIC_BLACKHOLE
:
806 snprintfrr(nexthop
, size
, "blackhole : %d", nh
->bh_type
);
808 case STATIC_IPV6_GATEWAY
:
809 snprintfrr(nexthop
, size
, "ip6 : %pI6", &nh
->addr
.ipv6
);
811 case STATIC_IPV6_GATEWAY_IFNAME
:
812 snprintfrr(nexthop
, size
, "ip6-ifindex : %pI6 : %s",
813 &nh
->addr
.ipv6
, nh
->ifname
);