3 * Copyright (C) 2018 Cumulus Networks, Inc.
6 * FRR 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
8 * Free Software Foundation; either version 2, or (at your option) any
11 * FRR is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
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>
30 #include "static_vrf.h"
31 #include "static_routes.h"
32 #include "static_memory.h"
33 #include "static_zebra.h"
35 /* Install static route into rib. */
36 static void static_install_route(struct route_node
*rn
, safi_t safi
)
38 struct static_route
*si
;
40 for (si
= rn
->info
; si
; si
= si
->next
)
41 static_zebra_nht_register(si
, true);
45 static_zebra_route_add(rn
, si
->vrf_id
, safi
, true);
49 /* Uninstall static route from RIB. */
50 static void static_uninstall_route(vrf_id_t vrf_id
, safi_t safi
,
51 struct route_node
*rn
)
55 static_zebra_route_add(rn
, vrf_id
, safi
, true);
57 static_zebra_route_add(rn
, vrf_id
, safi
, false);
60 int static_add_route(afi_t afi
, safi_t safi
, uint8_t type
, struct prefix
*p
,
61 struct prefix_ipv6
*src_p
, union g_addr
*gate
,
62 const char *ifname
, enum static_blackhole_type bh_type
,
63 route_tag_t tag
, uint8_t distance
, struct static_vrf
*svrf
,
64 struct static_vrf
*nh_svrf
,
65 struct static_nh_label
*snh_label
,
68 struct route_node
*rn
;
69 struct static_route
*si
;
70 struct static_route
*pp
;
71 struct static_route
*cp
;
72 struct static_route
*update
= NULL
;
73 struct route_table
*stable
= svrf
->stable
[afi
][safi
];
78 if (!gate
&& (type
== STATIC_IPV4_GATEWAY
79 || type
== STATIC_IPV4_GATEWAY_IFNAME
80 || type
== STATIC_IPV6_GATEWAY
81 || type
== STATIC_IPV6_GATEWAY_IFNAME
))
85 && (type
== STATIC_IFNAME
|| type
== STATIC_IPV4_GATEWAY_IFNAME
86 || type
== STATIC_IPV6_GATEWAY_IFNAME
))
89 /* Lookup static route prefix. */
90 rn
= srcdest_rnode_get(stable
, p
, src_p
);
92 /* Do nothing if there is a same static route. */
93 for (si
= rn
->info
; si
; si
= si
->next
) {
97 && IPV4_ADDR_SAME(&gate
->ipv4
, &si
->addr
.ipv4
))
99 && IPV6_ADDR_SAME(gate
, &si
->addr
.ipv6
))))
100 && (!strcmp(ifname
? ifname
: "", si
->ifname
))) {
101 if ((distance
== si
->distance
) && (tag
== si
->tag
)
102 && (table_id
== si
->table_id
)
103 && !memcmp(&si
->snh_label
, snh_label
,
104 sizeof(struct static_nh_label
))
105 && si
->bh_type
== bh_type
) {
106 route_unlock_node(rn
);
113 /* Distance or tag or label changed, delete existing first. */
115 static_delete_route(afi
, safi
, type
, p
, src_p
, gate
, ifname
,
116 update
->tag
, update
->distance
, svrf
,
117 &update
->snh_label
, table_id
);
119 /* Make new static route structure. */
120 si
= XCALLOC(MTYPE_STATIC_ROUTE
, sizeof(struct static_route
));
123 si
->distance
= distance
;
124 si
->bh_type
= bh_type
;
126 si
->vrf_id
= svrf
->vrf
->vrf_id
;
127 si
->nh_vrf_id
= nh_svrf
->vrf
->vrf_id
;
128 strcpy(si
->nh_vrfname
, nh_svrf
->vrf
->name
);
129 si
->table_id
= table_id
;
132 strlcpy(si
->ifname
, ifname
, sizeof(si
->ifname
));
133 si
->ifindex
= IFINDEX_INTERNAL
;
136 case STATIC_IPV4_GATEWAY
:
137 case STATIC_IPV4_GATEWAY_IFNAME
:
138 si
->addr
.ipv4
= gate
->ipv4
;
140 case STATIC_IPV6_GATEWAY
:
141 case STATIC_IPV6_GATEWAY_IFNAME
:
142 si
->addr
.ipv6
= gate
->ipv6
;
148 /* Save labels, if any. */
149 memcpy(&si
->snh_label
, snh_label
, sizeof(struct static_nh_label
));
152 * Add new static route information to the tree with sort by
153 * distance value and gateway address.
155 for (pp
= NULL
, cp
= rn
->info
; cp
; pp
= cp
, cp
= cp
->next
) {
156 if (si
->distance
< cp
->distance
)
158 if (si
->distance
> cp
->distance
)
160 if (si
->type
== STATIC_IPV4_GATEWAY
161 && cp
->type
== STATIC_IPV4_GATEWAY
) {
162 if (ntohl(si
->addr
.ipv4
.s_addr
)
163 < ntohl(cp
->addr
.ipv4
.s_addr
))
165 if (ntohl(si
->addr
.ipv4
.s_addr
)
166 > ntohl(cp
->addr
.ipv4
.s_addr
))
171 /* Make linked list. */
181 /* check whether interface exists in system & install if it does */
183 static_install_route(rn
, safi
);
185 struct interface
*ifp
;
187 ifp
= if_lookup_by_name(ifname
, nh_svrf
->vrf
->vrf_id
);
188 if (ifp
&& ifp
->ifindex
!= IFINDEX_INTERNAL
) {
189 si
->ifindex
= ifp
->ifindex
;
190 static_install_route(rn
, safi
);
192 zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf",
199 int static_delete_route(afi_t afi
, safi_t safi
, uint8_t type
, struct prefix
*p
,
200 struct prefix_ipv6
*src_p
, union g_addr
*gate
,
201 const char *ifname
, route_tag_t tag
, uint8_t distance
,
202 struct static_vrf
*svrf
,
203 struct static_nh_label
*snh_label
,
206 struct route_node
*rn
;
207 struct static_route
*si
;
208 struct route_table
*stable
;
211 stable
= static_vrf_static_table(afi
, safi
, svrf
);
215 /* Lookup static route prefix. */
216 rn
= srcdest_rnode_lookup(stable
, p
, src_p
);
220 /* Find same static route is the tree */
221 for (si
= rn
->info
; si
; si
= si
->next
)
225 && IPV4_ADDR_SAME(&gate
->ipv4
, &si
->addr
.ipv4
))
227 && IPV6_ADDR_SAME(gate
, &si
->addr
.ipv6
))))
228 && (!strcmp(ifname
? ifname
: "", si
->ifname
))
229 && (!tag
|| (tag
== si
->tag
))
230 && (table_id
== si
->table_id
)
231 && (!snh_label
->num_labels
232 || !memcmp(&si
->snh_label
, snh_label
,
233 sizeof(struct static_nh_label
))))
236 /* Can't find static route. */
238 route_unlock_node(rn
);
242 static_zebra_nht_register(si
, false);
244 /* Unlink static route from linked list. */
246 si
->prev
->next
= si
->next
;
250 si
->next
->prev
= si
->prev
;
253 * If we have other si nodes then route replace
254 * else delete the route
256 static_uninstall_route(si
->vrf_id
, safi
, rn
);
257 route_unlock_node(rn
);
259 /* Free static route configuration. */
260 XFREE(MTYPE_STATIC_ROUTE
, si
);
262 route_unlock_node(rn
);
267 static void static_ifindex_update_af(struct interface
*ifp
, bool up
, afi_t afi
,
270 struct route_table
*stable
;
271 struct route_node
*rn
;
272 struct static_route
*si
;
275 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
276 struct static_vrf
*svrf
;
280 stable
= static_vrf_static_table(afi
, safi
, svrf
);
284 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
)) {
285 for (si
= rn
->info
; si
; si
= si
->next
) {
289 if (strcmp(si
->ifname
, ifp
->name
))
291 si
->ifindex
= ifp
->ifindex
;
293 if (si
->ifindex
!= ifp
->ifindex
)
295 si
->ifindex
= IFINDEX_INTERNAL
;
299 static_install_route(rn
, safi
);
305 * This function looks at a svrf's stable and notices if any of the
306 * nexthops we are using are part of the vrf coming up.
307 * If we are using them then cleanup the nexthop vrf id
308 * to be the new value and then re-installs them
311 * stable -> The table we are looking at.
312 * svrf -> The newly changed vrf.
313 * afi -> The afi to look at
314 * safi -> the safi to look at
316 static void static_fixup_vrf(struct static_vrf
*svrf
,
317 struct route_table
*stable
, afi_t afi
, safi_t safi
)
319 struct route_node
*rn
;
320 struct static_route
*si
;
321 struct interface
*ifp
;
324 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
326 for (si
= rn
->info
; si
; si
= si
->next
) {
327 if (strcmp(svrf
->vrf
->name
, si
->nh_vrfname
) != 0)
330 si
->nh_vrf_id
= svrf
->vrf
->vrf_id
;
333 ifp
= if_lookup_by_name(si
->ifname
,
336 si
->ifindex
= ifp
->ifindex
;
343 static_install_route(rn
, safi
);
348 * This function enables static routes in a svrf as it
349 * is coming up. It sets the new vrf_id as appropriate.
351 * svrf -> The svrf that is being brought up and enabled by the kernel
352 * stable -> The stable we are looking at.
353 * afi -> the afi in question
354 * safi -> the safi in question
356 static void static_enable_vrf(struct static_vrf
*svrf
,
357 struct route_table
*stable
,
358 afi_t afi
, safi_t safi
)
360 struct route_node
*rn
;
361 struct static_route
*si
;
362 struct interface
*ifp
;
363 struct vrf
*vrf
= svrf
->vrf
;
366 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
368 for (si
= rn
->info
; si
; si
= si
->next
) {
369 si
->vrf_id
= vrf
->vrf_id
;
371 ifp
= if_lookup_by_name(si
->ifname
,
374 si
->ifindex
= ifp
->ifindex
;
382 static_install_route(rn
, safi
);
387 * When a vrf is being enabled by the kernel, go through all the
388 * static routes in the system that use this vrf (both nexthops vrfs
389 * and the routes vrf )
391 * enable_svrf -> the vrf being enabled
393 void static_fixup_vrf_ids(struct static_vrf
*enable_svrf
)
395 struct route_table
*stable
;
400 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
401 struct static_vrf
*svrf
;
404 /* Install any static routes configured for this VRF. */
405 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
406 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
407 stable
= svrf
->stable
[afi
][safi
];
411 static_fixup_vrf(enable_svrf
, stable
,
414 if (enable_svrf
== svrf
)
415 static_enable_vrf(svrf
, stable
,
423 * Look at the specified stable and if any of the routes in
424 * this table are using the svrf as the nexthop, uninstall
427 * svrf -> the vrf being disabled
428 * stable -> the table we need to look at.
429 * afi -> the afi in question
430 * safi -> the safi in question
432 static void static_cleanup_vrf(struct static_vrf
*svrf
,
433 struct route_table
*stable
,
434 afi_t afi
, safi_t safi
)
436 struct route_node
*rn
;
437 struct static_route
*si
;
439 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
440 for (si
= rn
->info
; si
; si
= si
->next
) {
441 if (strcmp(svrf
->vrf
->name
, si
->nh_vrfname
) != 0)
444 static_uninstall_route(si
->vrf_id
, safi
, rn
);
450 * Look at all static routes in this table and uninstall
453 * stable -> The table to uninstall from
454 * afi -> The afi in question
455 * safi -> the safi in question
457 static void static_disable_vrf(struct route_table
*stable
,
458 afi_t afi
, safi_t safi
)
460 struct route_node
*rn
;
461 struct static_route
*si
;
463 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
))
464 for (si
= rn
->info
; si
; si
= si
->next
)
465 static_uninstall_route(si
->vrf_id
, safi
, rn
);
469 * When the disable_svrf is shutdown by the kernel, we call
470 * this function and it cleans up all static routes using
471 * this vrf as a nexthop as well as all static routes
474 * disable_svrf - The vrf being disabled
476 void static_cleanup_vrf_ids(struct static_vrf
*disable_svrf
)
482 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
483 struct static_vrf
*svrf
;
487 /* Uninstall any static routes configured for this VRF. */
488 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
489 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
490 struct route_table
*stable
;
492 stable
= svrf
->stable
[afi
][safi
];
496 static_cleanup_vrf(disable_svrf
, stable
,
499 if (disable_svrf
== svrf
)
500 static_disable_vrf(stable
, afi
, safi
);
506 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
507 void static_ifindex_update(struct interface
*ifp
, bool up
)
509 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_UNICAST
);
510 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_MULTICAST
);
511 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_UNICAST
);
512 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_MULTICAST
);