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
22 #include <lib/nexthop.h>
23 #include <lib/memory.h>
24 #include <lib/srcdest_table.h>
28 #include <lib/memory.h>
32 #include "static_vrf.h"
33 #include "static_routes.h"
34 #include "static_zebra.h"
35 #include "static_debug.h"
37 DEFINE_MGROUP(STATIC
, "staticd");
39 DEFINE_MTYPE_STATIC(STATIC
, STATIC_ROUTE
, "Static Route Info");
40 DEFINE_MTYPE_STATIC(STATIC
, STATIC_PATH
, "Static Path");
41 DEFINE_MTYPE_STATIC(STATIC
, STATIC_NEXTHOP
, "Static Nexthop");
43 void zebra_stable_node_cleanup(struct route_table
*table
,
44 struct route_node
*node
)
46 struct static_nexthop
*nh
;
47 struct static_path
*pn
;
48 struct static_route_info
*si
;
49 struct route_table
*src_table
;
50 struct route_node
*src_node
;
51 struct static_path
*src_pn
;
52 struct static_route_info
*src_si
;
57 frr_each_safe(static_path_list
, &si
->path_list
, pn
) {
58 frr_each_safe(static_nexthop_list
, &pn
->nexthop_list
,
60 static_nexthop_list_del(&pn
->nexthop_list
, nh
);
61 XFREE(MTYPE_STATIC_NEXTHOP
, nh
);
63 static_path_list_del(&si
->path_list
, pn
);
64 XFREE(MTYPE_STATIC_PATH
, pn
);
67 /* clean up for dst table */
68 src_table
= srcdest_srcnode_table(node
);
70 /* This means the route_node is part of the top
71 * hierarchy and refers to a destination prefix.
73 for (src_node
= route_top(src_table
); src_node
;
74 src_node
= route_next(src_node
)) {
75 src_si
= src_node
->info
;
77 frr_each_safe(static_path_list
,
78 &src_si
->path_list
, src_pn
) {
79 frr_each_safe(static_nexthop_list
,
80 &src_pn
->nexthop_list
,
82 static_nexthop_list_del(
83 &src_pn
->nexthop_list
,
85 XFREE(MTYPE_STATIC_NEXTHOP
, nh
);
87 static_path_list_del(&src_si
->path_list
,
89 XFREE(MTYPE_STATIC_PATH
, src_pn
);
92 XFREE(MTYPE_STATIC_ROUTE
, src_node
->info
);
96 XFREE(MTYPE_STATIC_ROUTE
, node
->info
);
100 /* Install static path into rib. */
101 void static_install_path(struct static_path
*pn
)
103 struct static_nexthop
*nh
;
105 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
)
106 static_zebra_nht_register(nh
, true);
108 if (static_nexthop_list_count(&pn
->nexthop_list
))
109 static_zebra_route_add(pn
, true);
112 /* Uninstall static path from RIB. */
113 static void static_uninstall_path(struct static_path
*pn
)
115 if (static_nexthop_list_count(&pn
->nexthop_list
))
116 static_zebra_route_add(pn
, true);
118 static_zebra_route_add(pn
, false);
121 struct route_node
*static_add_route(afi_t afi
, safi_t safi
, struct prefix
*p
,
122 struct prefix_ipv6
*src_p
,
123 struct static_vrf
*svrf
)
125 struct route_node
*rn
;
126 struct static_route_info
*si
;
127 struct route_table
*stable
= svrf
->stable
[afi
][safi
];
131 /* Lookup static route prefix. */
132 rn
= srcdest_rnode_get(stable
, p
, src_p
);
134 si
= XCALLOC(MTYPE_STATIC_ROUTE
, sizeof(struct static_route_info
));
138 static_path_list_init(&(si
->path_list
));
145 /* To delete the srcnodes */
146 static void static_del_src_route(struct route_node
*rn
)
148 struct static_path
*pn
;
149 struct static_route_info
*si
;
153 frr_each_safe(static_path_list
, &si
->path_list
, pn
) {
157 XFREE(MTYPE_STATIC_ROUTE
, rn
->info
);
158 route_unlock_node(rn
);
161 void static_del_route(struct route_node
*rn
)
163 struct static_path
*pn
;
164 struct static_route_info
*si
;
165 struct route_table
*src_table
;
166 struct route_node
*src_node
;
170 frr_each_safe(static_path_list
, &si
->path_list
, pn
) {
174 /* clean up for dst table */
175 src_table
= srcdest_srcnode_table(rn
);
177 /* This means the route_node is part of the top hierarchy
178 * and refers to a destination prefix.
180 for (src_node
= route_top(src_table
); src_node
;
181 src_node
= route_next(src_node
)) {
182 static_del_src_route(src_node
);
185 XFREE(MTYPE_STATIC_ROUTE
, rn
->info
);
186 route_unlock_node(rn
);
189 bool static_add_nexthop_validate(const char *nh_vrf_name
,
190 enum static_nh_type type
,
191 struct ipaddr
*ipaddr
)
195 vrf
= vrf_lookup_by_name(nh_vrf_name
);
200 case STATIC_IPV4_GATEWAY
:
201 case STATIC_IPV4_GATEWAY_IFNAME
:
202 if (if_address_is_local(&ipaddr
->ipaddr_v4
, AF_INET
,
206 case STATIC_IPV6_GATEWAY
:
207 case STATIC_IPV6_GATEWAY_IFNAME
:
208 if (if_address_is_local(&ipaddr
->ipaddr_v6
, AF_INET6
,
219 struct static_path
*static_add_path(struct route_node
*rn
, uint32_t table_id
,
222 struct static_path
*pn
;
223 struct static_route_info
*si
;
227 /* Make new static route structure. */
228 pn
= XCALLOC(MTYPE_STATIC_PATH
, sizeof(struct static_path
));
231 pn
->distance
= distance
;
232 pn
->table_id
= table_id
;
233 static_nexthop_list_init(&(pn
->nexthop_list
));
236 static_path_list_add_head(&(si
->path_list
), pn
);
241 void static_del_path(struct static_path
*pn
)
243 struct route_node
*rn
= pn
->rn
;
244 struct static_route_info
*si
;
245 struct static_nexthop
*nh
;
249 static_path_list_del(&si
->path_list
, pn
);
251 frr_each_safe(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
252 static_delete_nexthop(nh
);
255 route_unlock_node(rn
);
257 XFREE(MTYPE_STATIC_PATH
, pn
);
260 struct static_nexthop
*static_add_nexthop(struct static_path
*pn
,
261 enum static_nh_type type
,
262 struct ipaddr
*ipaddr
,
264 const char *nh_vrf
, uint32_t color
)
266 struct route_node
*rn
= pn
->rn
;
267 struct static_nexthop
*nh
;
268 struct static_vrf
*nh_svrf
;
269 struct interface
*ifp
;
270 struct static_nexthop
*cp
;
274 nh_svrf
= static_vrf_lookup_by_name(nh_vrf
);
276 /* Make new static route structure. */
277 nh
= XCALLOC(MTYPE_STATIC_NEXTHOP
, sizeof(struct static_nexthop
));
284 if (nh
->type
== STATIC_BLACKHOLE
)
285 nh
->bh_type
= STATIC_BLACKHOLE_NULL
;
287 nh
->nh_vrf_id
= nh_svrf
? nh_svrf
->vrf
->vrf_id
: VRF_UNKNOWN
;
288 strlcpy(nh
->nh_vrfname
, nh_vrf
, sizeof(nh
->nh_vrfname
));
291 strlcpy(nh
->ifname
, ifname
, sizeof(nh
->ifname
));
292 nh
->ifindex
= IFINDEX_INTERNAL
;
295 case STATIC_IPV4_GATEWAY
:
296 case STATIC_IPV4_GATEWAY_IFNAME
:
297 nh
->addr
.ipv4
= ipaddr
->ipaddr_v4
;
299 case STATIC_IPV6_GATEWAY
:
300 case STATIC_IPV6_GATEWAY_IFNAME
:
301 nh
->addr
.ipv6
= ipaddr
->ipaddr_v6
;
307 * Add new static route information to the tree with sort by
310 frr_each(static_nexthop_list
, &pn
->nexthop_list
, cp
) {
311 if (nh
->type
== STATIC_IPV4_GATEWAY
312 && cp
->type
== STATIC_IPV4_GATEWAY
) {
313 if (ntohl(nh
->addr
.ipv4
.s_addr
)
314 < ntohl(cp
->addr
.ipv4
.s_addr
))
316 if (ntohl(nh
->addr
.ipv4
.s_addr
)
317 > ntohl(cp
->addr
.ipv4
.s_addr
))
321 static_nexthop_list_add_after(&(pn
->nexthop_list
), cp
, nh
);
323 if (nh
->nh_vrf_id
== VRF_UNKNOWN
) {
325 "Static Route to %pFX not installed currently because dependent config not fully available",
330 /* check whether interface exists in system & install if it does */
332 case STATIC_IPV4_GATEWAY
:
333 case STATIC_IPV6_GATEWAY
:
334 case STATIC_BLACKHOLE
:
336 case STATIC_IPV4_GATEWAY_IFNAME
:
337 case STATIC_IPV6_GATEWAY_IFNAME
:
339 ifp
= if_lookup_by_name(ifname
, nh
->nh_vrf_id
);
340 if (ifp
&& ifp
->ifindex
!= IFINDEX_INTERNAL
)
341 nh
->ifindex
= ifp
->ifindex
;
344 "Static Route using %s interface not installed because the interface does not exist in specified vrf",
352 void static_install_nexthop(struct static_nexthop
*nh
)
354 struct static_path
*pn
= nh
->pn
;
355 struct route_node
*rn
= pn
->rn
;
356 struct interface
*ifp
;
358 if (nh
->nh_vrf_id
== VRF_UNKNOWN
) {
359 char nexthop_str
[NEXTHOP_STR
];
361 static_get_nh_str(nh
, nexthop_str
, sizeof(nexthop_str
));
362 DEBUGD(&static_dbg_route
,
363 "Static Route %pFX not installed for %s vrf %s is unknown",
364 &rn
->p
, nexthop_str
, nh
->nh_vrfname
);
368 /* check whether interface exists in system & install if it does */
370 case STATIC_IPV4_GATEWAY
:
371 case STATIC_IPV6_GATEWAY
:
372 static_zebra_nht_register(nh
, true);
374 case STATIC_IPV4_GATEWAY_IFNAME
:
375 case STATIC_IPV6_GATEWAY_IFNAME
:
376 static_zebra_nht_register(nh
, true);
378 case STATIC_BLACKHOLE
:
379 static_install_path(pn
);
382 ifp
= if_lookup_by_name(nh
->ifname
, nh
->nh_vrf_id
);
383 if (ifp
&& ifp
->ifindex
!= IFINDEX_INTERNAL
)
384 static_install_path(pn
);
390 void static_delete_nexthop(struct static_nexthop
*nh
)
392 struct static_path
*pn
= nh
->pn
;
393 struct route_node
*rn
= pn
->rn
;
395 static_nexthop_list_del(&(pn
->nexthop_list
), nh
);
397 if (nh
->nh_vrf_id
== VRF_UNKNOWN
)
400 static_zebra_nht_register(nh
, false);
402 * If we have other si nodes then route replace
403 * else delete the route
405 static_uninstall_path(pn
);
408 route_unlock_node(rn
);
409 /* Free static route configuration. */
410 XFREE(MTYPE_STATIC_NEXTHOP
, nh
);
413 static void static_ifindex_update_nh(struct interface
*ifp
, bool up
,
414 struct route_node
*rn
,
415 struct static_path
*pn
,
416 struct static_nexthop
*nh
,
417 struct static_vrf
*svrf
, safi_t safi
)
422 if (strcmp(nh
->ifname
, ifp
->name
))
424 if (nh
->nh_vrf_id
!= ifp
->vrf
->vrf_id
)
426 nh
->ifindex
= ifp
->ifindex
;
428 if (nh
->ifindex
!= ifp
->ifindex
)
430 if (nh
->nh_vrf_id
!= ifp
->vrf
->vrf_id
)
432 nh
->ifindex
= IFINDEX_INTERNAL
;
435 static_install_path(pn
);
438 static void static_ifindex_update_af(struct interface
*ifp
, bool up
, afi_t afi
,
441 struct route_table
*stable
;
442 struct route_node
*rn
;
443 struct static_nexthop
*nh
;
444 struct static_path
*pn
;
446 struct static_route_info
*si
;
448 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
449 struct static_vrf
*svrf
;
453 stable
= static_vrf_static_table(afi
, safi
, svrf
);
456 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
)) {
457 si
= static_route_info_from_rnode(rn
);
460 frr_each(static_path_list
, &si
->path_list
, pn
) {
461 frr_each(static_nexthop_list
,
462 &pn
->nexthop_list
, nh
) {
463 static_ifindex_update_nh(ifp
, up
, rn
,
473 * This function looks at a svrf's stable and notices if any of the
474 * nexthops we are using are part of the vrf coming up.
475 * If we are using them then cleanup the nexthop vrf id
476 * to be the new value and then re-installs them
479 * stable -> The table we are looking at.
480 * svrf -> The newly changed vrf.
481 * afi -> The afi to look at
482 * safi -> the safi to look at
484 static void static_fixup_vrf(struct static_vrf
*svrf
,
485 struct route_table
*stable
, afi_t afi
, safi_t safi
)
487 struct route_node
*rn
;
488 struct static_nexthop
*nh
;
489 struct interface
*ifp
;
490 struct static_path
*pn
;
491 struct static_route_info
*si
;
493 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
494 si
= static_route_info_from_rnode(rn
);
497 frr_each(static_path_list
, &si
->path_list
, pn
) {
498 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
499 if (strcmp(svrf
->vrf
->name
, nh
->nh_vrfname
)
503 nh
->nh_vrf_id
= svrf
->vrf
->vrf_id
;
504 nh
->nh_registered
= false;
506 ifp
= if_lookup_by_name(nh
->ifname
,
509 nh
->ifindex
= ifp
->ifindex
;
514 static_install_path(pn
);
521 * This function enables static routes in a svrf as it
522 * is coming up. It sets the new vrf_id as appropriate.
524 * svrf -> The svrf that is being brought up and enabled by the kernel
525 * stable -> The stable we are looking at.
526 * afi -> the afi in question
527 * safi -> the safi in question
529 static void static_enable_vrf(struct static_vrf
*svrf
,
530 struct route_table
*stable
, afi_t afi
,
533 struct route_node
*rn
;
534 struct static_nexthop
*nh
;
535 struct interface
*ifp
;
536 struct static_path
*pn
;
537 struct static_route_info
*si
;
539 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
540 si
= static_route_info_from_rnode(rn
);
543 frr_each(static_path_list
, &si
->path_list
, pn
) {
544 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
546 ifp
= if_lookup_by_name(nh
->ifname
,
549 nh
->ifindex
= ifp
->ifindex
;
553 if (nh
->nh_vrf_id
== VRF_UNKNOWN
)
555 static_install_path(pn
);
562 * When a vrf is being enabled by the kernel, go through all the
563 * static routes in the system that use this vrf (both nexthops vrfs
564 * and the routes vrf )
566 * enable_svrf -> the vrf being enabled
568 void static_fixup_vrf_ids(struct static_vrf
*enable_svrf
)
570 struct route_table
*stable
;
575 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
576 struct static_vrf
*svrf
;
579 /* Install any static routes configured for this VRF. */
580 FOREACH_AFI_SAFI (afi
, safi
) {
581 stable
= svrf
->stable
[afi
][safi
];
585 static_fixup_vrf(enable_svrf
, stable
, afi
, safi
);
587 if (enable_svrf
== svrf
)
588 static_enable_vrf(svrf
, stable
, afi
, safi
);
594 * Look at the specified stable and if any of the routes in
595 * this table are using the svrf as the nexthop, uninstall
598 * svrf -> the vrf being disabled
599 * stable -> the table we need to look at.
600 * afi -> the afi in question
601 * safi -> the safi in question
603 static void static_cleanup_vrf(struct static_vrf
*svrf
,
604 struct route_table
*stable
,
605 afi_t afi
, safi_t safi
)
607 struct route_node
*rn
;
608 struct static_nexthop
*nh
;
609 struct static_path
*pn
;
610 struct static_route_info
*si
;
612 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
613 si
= static_route_info_from_rnode(rn
);
616 frr_each(static_path_list
, &si
->path_list
, pn
) {
617 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
618 if (strcmp(svrf
->vrf
->name
, nh
->nh_vrfname
)
622 static_uninstall_path(pn
);
629 * Look at all static routes in this table and uninstall
632 * stable -> The table to uninstall from
633 * afi -> The afi in question
634 * safi -> the safi in question
636 static void static_disable_vrf(struct route_table
*stable
,
637 afi_t afi
, safi_t safi
)
639 struct route_node
*rn
;
640 struct static_nexthop
*nh
;
641 struct static_path
*pn
;
642 struct static_route_info
*si
;
644 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
645 si
= static_route_info_from_rnode(rn
);
648 frr_each(static_path_list
, &si
->path_list
, pn
) {
649 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
650 static_uninstall_path(pn
);
657 * When the disable_svrf is shutdown by the kernel, we call
658 * this function and it cleans up all static routes using
659 * this vrf as a nexthop as well as all static routes
662 * disable_svrf - The vrf being disabled
664 void static_cleanup_vrf_ids(struct static_vrf
*disable_svrf
)
670 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
671 struct static_vrf
*svrf
;
675 /* Uninstall any static routes configured for this VRF. */
676 FOREACH_AFI_SAFI (afi
, safi
) {
677 struct route_table
*stable
;
679 stable
= svrf
->stable
[afi
][safi
];
683 static_cleanup_vrf(disable_svrf
, stable
, afi
, safi
);
685 if (disable_svrf
== svrf
)
686 static_disable_vrf(stable
, afi
, safi
);
692 * This function enables static routes when an interface it relies
693 * on in a different vrf is coming up.
695 * stable -> The stable we are looking at.
696 * ifp -> interface coming up
697 * afi -> the afi in question
698 * safi -> the safi in question
700 static void static_fixup_intf_nh(struct route_table
*stable
,
701 struct interface
*ifp
,
702 afi_t afi
, safi_t safi
)
704 struct route_node
*rn
;
705 struct static_nexthop
*nh
;
706 struct static_path
*pn
;
707 struct static_route_info
*si
;
709 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
710 si
= static_route_info_from_rnode(rn
);
713 frr_each(static_path_list
, &si
->path_list
, pn
) {
714 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
715 if (nh
->nh_vrf_id
!= ifp
->vrf
->vrf_id
)
718 if (nh
->ifindex
!= ifp
->ifindex
)
721 static_install_path(pn
);
728 * This function enables static routes that rely on an interface in
729 * a different vrf when that interface comes up.
731 void static_install_intf_nh(struct interface
*ifp
)
733 struct route_table
*stable
;
738 RB_FOREACH(vrf
, vrf_name_head
, &vrfs_by_name
) {
739 struct static_vrf
*svrf
= vrf
->info
;
741 /* Not needed if same vrf since happens naturally */
742 if (vrf
->vrf_id
== ifp
->vrf
->vrf_id
)
745 /* Install any static routes configured for this interface. */
746 FOREACH_AFI_SAFI (afi
, safi
) {
747 stable
= svrf
->stable
[afi
][safi
];
751 static_fixup_intf_nh(stable
, ifp
, afi
, safi
);
756 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
757 void static_ifindex_update(struct interface
*ifp
, bool up
)
759 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_UNICAST
);
760 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_MULTICAST
);
761 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_UNICAST
);
762 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_MULTICAST
);
765 void static_get_nh_type(enum static_nh_type stype
, char *type
, size_t size
)
769 strlcpy(type
, "ifindex", size
);
771 case STATIC_IPV4_GATEWAY
:
772 strlcpy(type
, "ip4", size
);
774 case STATIC_IPV4_GATEWAY_IFNAME
:
775 strlcpy(type
, "ip4-ifindex", size
);
777 case STATIC_BLACKHOLE
:
778 strlcpy(type
, "blackhole", size
);
780 case STATIC_IPV6_GATEWAY
:
781 strlcpy(type
, "ip6", size
);
783 case STATIC_IPV6_GATEWAY_IFNAME
:
784 strlcpy(type
, "ip6-ifindex", size
);
789 struct stable_info
*static_get_stable_info(struct route_node
*rn
)
791 struct route_table
*table
;
793 table
= srcdest_rnode_table(rn
);
797 void static_get_nh_str(struct static_nexthop
*nh
, char *nexthop
, size_t size
)
801 snprintfrr(nexthop
, size
, "ifindex : %s", nh
->ifname
);
803 case STATIC_IPV4_GATEWAY
:
804 snprintfrr(nexthop
, size
, "ip4 : %pI4", &nh
->addr
.ipv4
);
806 case STATIC_IPV4_GATEWAY_IFNAME
:
807 snprintfrr(nexthop
, size
, "ip4-ifindex : %pI4 : %s",
808 &nh
->addr
.ipv4
, nh
->ifname
);
810 case STATIC_BLACKHOLE
:
811 snprintfrr(nexthop
, size
, "blackhole : %d", nh
->bh_type
);
813 case STATIC_IPV6_GATEWAY
:
814 snprintfrr(nexthop
, size
, "ip6 : %pI6", &nh
->addr
.ipv6
);
816 case STATIC_IPV6_GATEWAY_IFNAME
:
817 snprintfrr(nexthop
, size
, "ip6-ifindex : %pI6 : %s",
818 &nh
->addr
.ipv6
, nh
->ifname
);