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
];
132 /* Lookup static route prefix. */
133 rn
= srcdest_rnode_get(stable
, p
, src_p
);
135 si
= XCALLOC(MTYPE_STATIC_ROUTE
, sizeof(struct static_route_info
));
139 static_path_list_init(&(si
->path_list
));
146 /* To delete the srcnodes */
147 static void static_del_src_route(struct route_node
*rn
)
149 struct static_path
*pn
;
150 struct static_route_info
*si
;
154 frr_each_safe(static_path_list
, &si
->path_list
, pn
) {
158 XFREE(MTYPE_STATIC_ROUTE
, rn
->info
);
159 route_unlock_node(rn
);
162 void static_del_route(struct route_node
*rn
)
164 struct static_path
*pn
;
165 struct static_route_info
*si
;
166 struct route_table
*src_table
;
167 struct route_node
*src_node
;
171 frr_each_safe(static_path_list
, &si
->path_list
, pn
) {
175 /* clean up for dst table */
176 src_table
= srcdest_srcnode_table(rn
);
178 /* This means the route_node is part of the top hierarchy
179 * and refers to a destination prefix.
181 for (src_node
= route_top(src_table
); src_node
;
182 src_node
= route_next(src_node
)) {
183 static_del_src_route(src_node
);
186 XFREE(MTYPE_STATIC_ROUTE
, rn
->info
);
187 route_unlock_node(rn
);
190 bool static_add_nexthop_validate(const char *nh_vrf_name
, static_types 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_lookup_exact_address(&ipaddr
->ipaddr_v4
, AF_INET
,
206 case STATIC_IPV6_GATEWAY
:
207 case STATIC_IPV6_GATEWAY_IFNAME
:
208 if (if_lookup_exact_address(&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
,
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
:
338 ifp
= if_lookup_by_name(ifname
, nh
->nh_vrf_id
);
339 if (ifp
&& ifp
->ifindex
!= IFINDEX_INTERNAL
)
340 nh
->ifindex
= ifp
->ifindex
;
343 "Static Route using %s interface not installed because the interface does not exist in specified vrf",
348 ifp
= if_lookup_by_name(ifname
, nh
->nh_vrf_id
);
349 if (ifp
&& ifp
->ifindex
!= IFINDEX_INTERNAL
) {
350 nh
->ifindex
= ifp
->ifindex
;
353 "Static Route using %s interface not installed because the interface does not exist in specified vrf",
361 void static_install_nexthop(struct static_nexthop
*nh
)
363 struct static_path
*pn
= nh
->pn
;
364 struct route_node
*rn
= pn
->rn
;
365 struct interface
*ifp
;
367 if (nh
->nh_vrf_id
== VRF_UNKNOWN
) {
368 char nexthop_str
[NEXTHOP_STR
];
370 static_get_nh_str(nh
, nexthop_str
, sizeof(nexthop_str
));
371 DEBUGD(&static_dbg_route
,
372 "Static Route %pFX not installed for %s vrf %s is unknown",
373 &rn
->p
, nexthop_str
, nh
->nh_vrfname
);
377 /* check whether interface exists in system & install if it does */
379 case STATIC_IPV4_GATEWAY
:
380 case STATIC_IPV6_GATEWAY
:
381 if (!static_zebra_nh_update(nh
))
382 static_zebra_nht_register(nh
, true);
384 case STATIC_IPV4_GATEWAY_IFNAME
:
385 case STATIC_IPV6_GATEWAY_IFNAME
:
386 if (!static_zebra_nh_update(nh
))
387 static_zebra_nht_register(nh
, true);
389 case STATIC_BLACKHOLE
:
390 static_install_path(pn
);
393 ifp
= if_lookup_by_name(nh
->ifname
, nh
->nh_vrf_id
);
394 if (ifp
&& ifp
->ifindex
!= IFINDEX_INTERNAL
)
395 static_install_path(pn
);
401 void static_delete_nexthop(struct static_nexthop
*nh
)
403 struct static_path
*pn
= nh
->pn
;
404 struct route_node
*rn
= pn
->rn
;
406 static_nexthop_list_del(&(pn
->nexthop_list
), nh
);
408 if (nh
->nh_vrf_id
== VRF_UNKNOWN
)
411 static_zebra_nht_register(nh
, false);
413 * If we have other si nodes then route replace
414 * else delete the route
416 static_uninstall_path(pn
);
419 route_unlock_node(rn
);
420 /* Free static route configuration. */
421 XFREE(MTYPE_STATIC_NEXTHOP
, nh
);
424 static void static_ifindex_update_nh(struct interface
*ifp
, bool up
,
425 struct route_node
*rn
,
426 struct static_path
*pn
,
427 struct static_nexthop
*nh
,
428 struct static_vrf
*svrf
, safi_t safi
)
433 if (strcmp(nh
->ifname
, ifp
->name
))
435 if (nh
->nh_vrf_id
!= ifp
->vrf_id
)
437 nh
->ifindex
= ifp
->ifindex
;
439 if (nh
->ifindex
!= ifp
->ifindex
)
441 if (nh
->nh_vrf_id
!= ifp
->vrf_id
)
443 nh
->ifindex
= IFINDEX_INTERNAL
;
446 static_install_path(pn
);
449 static void static_ifindex_update_af(struct interface
*ifp
, bool up
, afi_t afi
,
452 struct route_table
*stable
;
453 struct route_node
*rn
;
454 struct static_nexthop
*nh
;
455 struct static_path
*pn
;
457 struct static_route_info
*si
;
459 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
460 struct static_vrf
*svrf
;
464 stable
= static_vrf_static_table(afi
, safi
, svrf
);
467 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
)) {
468 si
= static_route_info_from_rnode(rn
);
471 frr_each(static_path_list
, &si
->path_list
, pn
) {
472 frr_each(static_nexthop_list
,
473 &pn
->nexthop_list
, nh
) {
474 static_ifindex_update_nh(ifp
, up
, rn
,
484 * This function looks at a svrf's stable and notices if any of the
485 * nexthops we are using are part of the vrf coming up.
486 * If we are using them then cleanup the nexthop vrf id
487 * to be the new value and then re-installs them
490 * stable -> The table we are looking at.
491 * svrf -> The newly changed vrf.
492 * afi -> The afi to look at
493 * safi -> the safi to look at
495 static void static_fixup_vrf(struct static_vrf
*svrf
,
496 struct route_table
*stable
, afi_t afi
, safi_t safi
)
498 struct route_node
*rn
;
499 struct static_nexthop
*nh
;
500 struct interface
*ifp
;
501 struct static_path
*pn
;
502 struct static_route_info
*si
;
504 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
505 si
= static_route_info_from_rnode(rn
);
508 frr_each(static_path_list
, &si
->path_list
, pn
) {
509 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
510 if (strcmp(svrf
->vrf
->name
, nh
->nh_vrfname
)
514 nh
->nh_vrf_id
= svrf
->vrf
->vrf_id
;
515 nh
->nh_registered
= false;
517 ifp
= if_lookup_by_name(nh
->ifname
,
520 nh
->ifindex
= ifp
->ifindex
;
525 static_install_path(pn
);
532 * This function enables static routes in a svrf as it
533 * is coming up. It sets the new vrf_id as appropriate.
535 * svrf -> The svrf that is being brought up and enabled by the kernel
536 * stable -> The stable we are looking at.
537 * afi -> the afi in question
538 * safi -> the safi in question
540 static void static_enable_vrf(struct static_vrf
*svrf
,
541 struct route_table
*stable
, afi_t afi
,
544 struct route_node
*rn
;
545 struct static_nexthop
*nh
;
546 struct interface
*ifp
;
547 struct static_path
*pn
;
548 struct static_route_info
*si
;
550 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
551 si
= static_route_info_from_rnode(rn
);
554 frr_each(static_path_list
, &si
->path_list
, pn
) {
555 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
557 ifp
= if_lookup_by_name(nh
->ifname
,
560 nh
->ifindex
= ifp
->ifindex
;
564 if (nh
->nh_vrf_id
== VRF_UNKNOWN
)
566 static_install_path(pn
);
573 * When a vrf is being enabled by the kernel, go through all the
574 * static routes in the system that use this vrf (both nexthops vrfs
575 * and the routes vrf )
577 * enable_svrf -> the vrf being enabled
579 void static_fixup_vrf_ids(struct static_vrf
*enable_svrf
)
581 struct route_table
*stable
;
586 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
587 struct static_vrf
*svrf
;
590 /* Install any static routes configured for this VRF. */
591 FOREACH_AFI_SAFI (afi
, safi
) {
592 stable
= svrf
->stable
[afi
][safi
];
596 static_fixup_vrf(enable_svrf
, stable
, afi
, safi
);
598 if (enable_svrf
== svrf
)
599 static_enable_vrf(svrf
, stable
, afi
, safi
);
605 * Look at the specified stable and if any of the routes in
606 * this table are using the svrf as the nexthop, uninstall
609 * svrf -> the vrf being disabled
610 * stable -> the table we need to look at.
611 * afi -> the afi in question
612 * safi -> the safi in question
614 static void static_cleanup_vrf(struct static_vrf
*svrf
,
615 struct route_table
*stable
,
616 afi_t afi
, safi_t safi
)
618 struct route_node
*rn
;
619 struct static_nexthop
*nh
;
620 struct static_path
*pn
;
621 struct static_route_info
*si
;
623 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
624 si
= static_route_info_from_rnode(rn
);
627 frr_each(static_path_list
, &si
->path_list
, pn
) {
628 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
629 if (strcmp(svrf
->vrf
->name
, nh
->nh_vrfname
)
633 static_uninstall_path(pn
);
640 * Look at all static routes in this table and uninstall
643 * stable -> The table to uninstall from
644 * afi -> The afi in question
645 * safi -> the safi in question
647 static void static_disable_vrf(struct route_table
*stable
,
648 afi_t afi
, safi_t safi
)
650 struct route_node
*rn
;
651 struct static_nexthop
*nh
;
652 struct static_path
*pn
;
653 struct static_route_info
*si
;
655 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
656 si
= static_route_info_from_rnode(rn
);
659 frr_each(static_path_list
, &si
->path_list
, pn
) {
660 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
661 static_uninstall_path(pn
);
668 * When the disable_svrf is shutdown by the kernel, we call
669 * this function and it cleans up all static routes using
670 * this vrf as a nexthop as well as all static routes
673 * disable_svrf - The vrf being disabled
675 void static_cleanup_vrf_ids(struct static_vrf
*disable_svrf
)
681 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
682 struct static_vrf
*svrf
;
686 /* Uninstall any static routes configured for this VRF. */
687 FOREACH_AFI_SAFI (afi
, safi
) {
688 struct route_table
*stable
;
690 stable
= svrf
->stable
[afi
][safi
];
694 static_cleanup_vrf(disable_svrf
, stable
, afi
, safi
);
696 if (disable_svrf
== svrf
)
697 static_disable_vrf(stable
, afi
, safi
);
703 * This function enables static routes when an interface it relies
704 * on in a different vrf is coming up.
706 * stable -> The stable we are looking at.
707 * ifp -> interface coming up
708 * afi -> the afi in question
709 * safi -> the safi in question
711 static void static_fixup_intf_nh(struct route_table
*stable
,
712 struct interface
*ifp
,
713 afi_t afi
, safi_t safi
)
715 struct route_node
*rn
;
716 struct static_nexthop
*nh
;
717 struct static_path
*pn
;
718 struct static_route_info
*si
;
720 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
721 si
= static_route_info_from_rnode(rn
);
724 frr_each(static_path_list
, &si
->path_list
, pn
) {
725 frr_each(static_nexthop_list
, &pn
->nexthop_list
, nh
) {
726 if (nh
->nh_vrf_id
!= ifp
->vrf_id
)
729 if (nh
->ifindex
!= ifp
->ifindex
)
732 static_install_path(pn
);
739 * This function enables static routes that rely on an interface in
740 * a different vrf when that interface comes up.
742 void static_install_intf_nh(struct interface
*ifp
)
744 struct route_table
*stable
;
749 RB_FOREACH(vrf
, vrf_name_head
, &vrfs_by_name
) {
750 struct static_vrf
*svrf
= vrf
->info
;
752 /* Not needed if same vrf since happens naturally */
753 if (vrf
->vrf_id
== ifp
->vrf_id
)
756 /* Install any static routes configured for this interface. */
757 FOREACH_AFI_SAFI (afi
, safi
) {
758 stable
= svrf
->stable
[afi
][safi
];
762 static_fixup_intf_nh(stable
, ifp
, afi
, safi
);
767 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
768 void static_ifindex_update(struct interface
*ifp
, bool up
)
770 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_UNICAST
);
771 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_MULTICAST
);
772 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_UNICAST
);
773 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_MULTICAST
);
776 void static_get_nh_type(static_types stype
, char *type
, size_t size
)
780 strlcpy(type
, "ifindex", size
);
782 case STATIC_IPV4_GATEWAY
:
783 strlcpy(type
, "ip4", size
);
785 case STATIC_IPV4_GATEWAY_IFNAME
:
786 strlcpy(type
, "ip4-ifindex", size
);
788 case STATIC_BLACKHOLE
:
789 strlcpy(type
, "blackhole", size
);
791 case STATIC_IPV6_GATEWAY
:
792 strlcpy(type
, "ip6", size
);
794 case STATIC_IPV6_GATEWAY_IFNAME
:
795 strlcpy(type
, "ip6-ifindex", size
);
800 struct stable_info
*static_get_stable_info(struct route_node
*rn
)
802 struct route_table
*table
;
804 table
= srcdest_rnode_table(rn
);
808 void static_get_nh_str(struct static_nexthop
*nh
, char *nexthop
, size_t size
)
812 snprintfrr(nexthop
, size
, "ifindex : %s", nh
->ifname
);
814 case STATIC_IPV4_GATEWAY
:
815 snprintfrr(nexthop
, size
, "ip4 : %pI4", &nh
->addr
.ipv4
);
817 case STATIC_IPV4_GATEWAY_IFNAME
:
818 snprintfrr(nexthop
, size
, "ip4-ifindex : %pI4 : %s",
819 &nh
->addr
.ipv4
, nh
->ifname
);
821 case STATIC_BLACKHOLE
:
822 snprintfrr(nexthop
, size
, "blackhole : %d", nh
->bh_type
);
824 case STATIC_IPV6_GATEWAY
:
825 snprintfrr(nexthop
, size
, "ip6 : %pI6", &nh
->addr
.ipv6
);
827 case STATIC_IPV6_GATEWAY_IFNAME
:
828 snprintfrr(nexthop
, size
, "ip6-ifindex : %pI6 : %s",
829 &nh
->addr
.ipv6
, nh
->ifname
);