2 * Static Routing Information code
3 * Copyright (C) 2016 Cumulus Networks
6 * This file is part of Quagga.
8 * Quagga is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
13 * Quagga is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 #include <lib/nexthop.h>
25 #include <lib/memory.h>
26 #include <lib/srcdest_table.h>
30 #include "zebra/debug.h"
31 #include "zebra/rib.h"
32 #include "zebra/zserv.h"
33 #include "zebra/zebra_vrf.h"
34 #include "zebra/zebra_static.h"
35 #include "zebra/zebra_rnh.h"
36 #include "zebra/redistribute.h"
37 #include "zebra/zebra_memory.h"
39 /* Install static route into rib. */
40 void static_install_route(afi_t afi
, safi_t safi
, struct prefix
*p
,
41 struct prefix_ipv6
*src_p
, struct static_route
*si
)
43 struct route_entry
*re
;
44 struct route_node
*rn
;
45 struct route_table
*table
;
47 struct nexthop
*nexthop
= NULL
;
48 enum blackhole_type bh_type
= 0;
52 table
= zebra_vrf_table(afi
, safi
, si
->vrf_id
);
57 * If a specific vrf is coming up and the nexthop vrf we are
58 * looking at using hasn't been brought up yet, just don't
59 * install the static route yet.
60 * When the nexthop vrf comes up we will get another call
61 * back to do the right thing. I'm putting this check
62 * here because we are calling static_install_route a bunch
63 * from a bunch of different callpaths.
65 nh_vrf
= vrf_lookup_by_id(si
->nh_vrf_id
);
69 memset(&nh_p
, 0, sizeof(nh_p
));
70 if (si
->type
== STATIC_BLACKHOLE
) {
71 switch (si
->bh_type
) {
72 case STATIC_BLACKHOLE_DROP
:
73 case STATIC_BLACKHOLE_NULL
:
74 bh_type
= BLACKHOLE_NULL
;
76 case STATIC_BLACKHOLE_REJECT
:
77 bh_type
= BLACKHOLE_REJECT
;
82 /* Lookup existing route */
83 rn
= srcdest_rnode_get(table
, p
, src_p
);
84 RNODE_FOREACH_RE (rn
, re
) {
85 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_REMOVED
))
88 if (re
->type
== ZEBRA_ROUTE_STATIC
89 && re
->distance
== si
->distance
)
94 /* if tag value changed , update old value in RIB */
95 if (re
->tag
!= si
->tag
)
98 /* Same distance static route is there. Update it with new
100 route_unlock_node(rn
);
102 case STATIC_IPV4_GATEWAY
:
103 nexthop
= route_entry_nexthop_ipv4_add(
104 re
, &si
->addr
.ipv4
, NULL
, si
->nh_vrf_id
);
105 nh_p
.family
= AF_INET
;
106 nh_p
.prefixlen
= IPV4_MAX_BITLEN
;
107 nh_p
.u
.prefix4
= si
->addr
.ipv4
;
108 zebra_register_rnh_static_nh(si
->nh_vrf_id
, &nh_p
, rn
);
110 case STATIC_IPV4_GATEWAY_IFNAME
:
111 nexthop
= route_entry_nexthop_ipv4_ifindex_add(
112 re
, &si
->addr
.ipv4
, NULL
, si
->ifindex
,
116 nexthop
= route_entry_nexthop_ifindex_add(
117 re
, si
->ifindex
, si
->nh_vrf_id
);
119 case STATIC_BLACKHOLE
:
121 route_entry_nexthop_blackhole_add(re
, bh_type
);
123 case STATIC_IPV6_GATEWAY
:
124 nexthop
= route_entry_nexthop_ipv6_add(
125 re
, &si
->addr
.ipv6
, si
->nh_vrf_id
);
126 nh_p
.family
= AF_INET6
;
127 nh_p
.prefixlen
= IPV6_MAX_BITLEN
;
128 nh_p
.u
.prefix6
= si
->addr
.ipv6
;
129 zebra_register_rnh_static_nh(si
->nh_vrf_id
, &nh_p
, rn
);
131 case STATIC_IPV6_GATEWAY_IFNAME
:
132 nexthop
= route_entry_nexthop_ipv6_ifindex_add(
133 re
, &si
->addr
.ipv6
, si
->ifindex
, si
->nh_vrf_id
);
136 /* Update label(s), if present. */
137 if (si
->snh_label
.num_labels
)
138 nexthop_add_labels(nexthop
, ZEBRA_LSP_STATIC
,
139 si
->snh_label
.num_labels
,
140 &si
->snh_label
.label
[0]);
142 if (IS_ZEBRA_DEBUG_RIB
) {
143 char buf
[INET6_ADDRSTRLEN
];
144 if (IS_ZEBRA_DEBUG_RIB
) {
145 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
148 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
149 si
->vrf_id
, buf
, p
->prefixlen
, rn
, re
,
154 re
->uptime
= time(NULL
);
155 /* Schedule route for processing or invoke NHT, as appropriate.
157 if (si
->type
== STATIC_IPV4_GATEWAY
158 || si
->type
== STATIC_IPV6_GATEWAY
)
159 zebra_evaluate_rnh(si
->nh_vrf_id
, nh_p
.family
, 1,
160 RNH_NEXTHOP_TYPE
, &nh_p
);
164 /* This is new static route. */
165 re
= XCALLOC(MTYPE_RE
, sizeof(struct route_entry
));
167 re
->type
= ZEBRA_ROUTE_STATIC
;
169 re
->distance
= si
->distance
;
172 re
->vrf_id
= si
->vrf_id
;
174 (si
->vrf_id
!= VRF_DEFAULT
)
175 ? (zebra_vrf_lookup_by_id(si
->vrf_id
))->table_id
176 : zebrad
.rtm_table_default
;
181 case STATIC_IPV4_GATEWAY
:
182 nexthop
= route_entry_nexthop_ipv4_add(
183 re
, &si
->addr
.ipv4
, NULL
, si
->nh_vrf_id
);
184 nh_p
.family
= AF_INET
;
185 nh_p
.prefixlen
= IPV4_MAX_BITLEN
;
186 nh_p
.u
.prefix4
= si
->addr
.ipv4
;
187 zebra_register_rnh_static_nh(si
->nh_vrf_id
, &nh_p
, rn
);
189 case STATIC_IPV4_GATEWAY_IFNAME
:
190 nexthop
= route_entry_nexthop_ipv4_ifindex_add(
191 re
, &si
->addr
.ipv4
, NULL
, si
->ifindex
,
195 nexthop
= route_entry_nexthop_ifindex_add(
196 re
, si
->ifindex
, si
->nh_vrf_id
);
198 case STATIC_BLACKHOLE
:
200 route_entry_nexthop_blackhole_add(re
, bh_type
);
202 case STATIC_IPV6_GATEWAY
:
203 nexthop
= route_entry_nexthop_ipv6_add(
204 re
, &si
->addr
.ipv6
, si
->nh_vrf_id
);
205 nh_p
.family
= AF_INET6
;
206 nh_p
.prefixlen
= IPV6_MAX_BITLEN
;
207 nh_p
.u
.prefix6
= si
->addr
.ipv6
;
208 zebra_register_rnh_static_nh(si
->nh_vrf_id
, &nh_p
, rn
);
210 case STATIC_IPV6_GATEWAY_IFNAME
:
211 nexthop
= route_entry_nexthop_ipv6_ifindex_add(
212 re
, &si
->addr
.ipv6
, si
->ifindex
, si
->nh_vrf_id
);
215 /* Update label(s), if present. */
216 if (si
->snh_label
.num_labels
)
217 nexthop_add_labels(nexthop
, ZEBRA_LSP_STATIC
,
218 si
->snh_label
.num_labels
,
219 &si
->snh_label
.label
[0]);
221 if (IS_ZEBRA_DEBUG_RIB
) {
222 char buf
[INET6_ADDRSTRLEN
];
223 if (IS_ZEBRA_DEBUG_RIB
) {
224 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
227 "%u:%s/%d: Inserting route rn %p, re %p (type %d)",
228 si
->vrf_id
, buf
, p
->prefixlen
, rn
, re
,
232 re
->uptime
= time(NULL
);
233 /* Link this re to the tree. Schedule for processing or invoke
237 if (si
->type
== STATIC_IPV4_GATEWAY
238 || si
->type
== STATIC_IPV6_GATEWAY
) {
239 rib_addnode(rn
, re
, 0);
240 zebra_evaluate_rnh(si
->nh_vrf_id
, nh_p
.family
, 1,
241 RNH_NEXTHOP_TYPE
, &nh_p
);
243 rib_addnode(rn
, re
, 1);
247 /* this works correctly with IFNAME<>IFINDEX because a static route on a
248 * non-active interface will have IFINDEX_INTERNAL and thus compare false
250 static int static_nexthop_same(struct nexthop
*nexthop
, struct static_route
*si
)
252 if (nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
253 && si
->type
== STATIC_BLACKHOLE
)
256 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
257 && si
->type
== STATIC_IPV4_GATEWAY
258 && IPV4_ADDR_SAME(&nexthop
->gate
.ipv4
, &si
->addr
.ipv4
))
260 else if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
261 && si
->type
== STATIC_IPV4_GATEWAY_IFNAME
262 && IPV4_ADDR_SAME(&nexthop
->gate
.ipv4
, &si
->addr
.ipv4
)
263 && nexthop
->ifindex
== si
->ifindex
)
265 else if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
266 && si
->type
== STATIC_IFNAME
267 && nexthop
->ifindex
== si
->ifindex
)
269 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6
270 && si
->type
== STATIC_IPV6_GATEWAY
271 && IPV6_ADDR_SAME(&nexthop
->gate
.ipv6
, &si
->addr
.ipv6
))
273 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
274 && si
->type
== STATIC_IPV6_GATEWAY_IFNAME
275 && IPV6_ADDR_SAME(&nexthop
->gate
.ipv6
, &si
->addr
.ipv6
)
276 && nexthop
->ifindex
== si
->ifindex
)
282 /* Uninstall static route from RIB. */
283 void static_uninstall_route(afi_t afi
, safi_t safi
, struct prefix
*p
,
284 struct prefix_ipv6
*src_p
, struct static_route
*si
)
286 struct route_node
*rn
;
287 struct route_entry
*re
;
288 struct nexthop
*nexthop
;
289 struct route_table
*table
;
293 table
= zebra_vrf_table(afi
, safi
, si
->vrf_id
);
297 /* Lookup existing route with type and distance. */
298 rn
= srcdest_rnode_lookup(table
, p
, src_p
);
302 RNODE_FOREACH_RE (rn
, re
) {
303 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_REMOVED
))
306 if (re
->type
== ZEBRA_ROUTE_STATIC
307 && re
->distance
== si
->distance
&& re
->tag
== si
->tag
)
312 route_unlock_node(rn
);
316 /* Lookup nexthop. */
317 for (nexthop
= re
->ng
.nexthop
; nexthop
; nexthop
= nexthop
->next
)
318 if (static_nexthop_same(nexthop
, si
))
321 /* Can't find nexthop. */
323 route_unlock_node(rn
);
328 if (re
->nexthop_num
== 1)
331 /* Mark this nexthop as inactive and reinstall the route. Then,
333 * the nexthop. There is no need to re-evaluate the route for
337 if (IS_ZEBRA_DEBUG_RIB
) {
338 char buf
[INET6_ADDRSTRLEN
];
339 if (IS_ZEBRA_DEBUG_RIB
) {
340 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
343 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
344 si
->vrf_id
, buf
, p
->prefixlen
, rn
, re
,
348 UNSET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
349 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)) {
350 rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
352 /* If there are other active nexthops, do an update. */
353 if (re
->nexthop_active_num
> 1) {
354 /* Update route in kernel if it's in fib */
355 if (dest
->selected_fib
)
356 rib_install_kernel(rn
, re
, re
);
357 /* Update redistribution if it's selected */
358 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
360 p
, (struct prefix
*)src_p
, re
,
363 /* Remove from redistribute if selected route
364 * becomes inactive */
365 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
367 p
, (struct prefix
*)src_p
, re
);
368 /* Remove from kernel if fib route becomes
370 if (dest
->selected_fib
)
371 rib_uninstall_kernel(rn
, re
);
376 /* Delete the nexthop and dereg from NHT */
377 nh_p
.family
= AF_INET
;
378 nh_p
.prefixlen
= IPV4_MAX_BITLEN
;
379 nh_p
.u
.prefix4
= nexthop
->gate
.ipv4
;
381 nh_p
.family
= AF_INET6
;
382 nh_p
.prefixlen
= IPV6_MAX_BITLEN
;
383 nh_p
.u
.prefix6
= nexthop
->gate
.ipv6
;
385 route_entry_nexthop_delete(re
, nexthop
);
386 zebra_deregister_rnh_static_nh(si
->nh_vrf_id
, &nh_p
, rn
);
387 nexthop_free(nexthop
);
390 route_unlock_node(rn
);
393 int static_add_route(afi_t afi
, safi_t safi
, uint8_t type
, struct prefix
*p
,
394 struct prefix_ipv6
*src_p
, union g_addr
*gate
,
395 const char *ifname
, enum static_blackhole_type bh_type
,
396 route_tag_t tag
, uint8_t distance
, struct zebra_vrf
*zvrf
,
397 struct zebra_vrf
*nh_zvrf
,
398 struct static_nh_label
*snh_label
)
400 struct route_node
*rn
;
401 struct static_route
*si
;
402 struct static_route
*pp
;
403 struct static_route
*cp
;
404 struct static_route
*update
= NULL
;
405 struct route_table
*stable
= zvrf
->stable
[afi
][safi
];
410 if (!gate
&& (type
== STATIC_IPV4_GATEWAY
411 || type
== STATIC_IPV4_GATEWAY_IFNAME
412 || type
== STATIC_IPV6_GATEWAY
413 || type
== STATIC_IPV6_GATEWAY_IFNAME
))
417 && (type
== STATIC_IFNAME
|| type
== STATIC_IPV4_GATEWAY_IFNAME
418 || type
== STATIC_IPV6_GATEWAY_IFNAME
))
421 /* Lookup static route prefix. */
422 rn
= srcdest_rnode_get(stable
, p
, src_p
);
424 /* Do nothing if there is a same static route. */
425 for (si
= rn
->info
; si
; si
= si
->next
) {
429 && IPV4_ADDR_SAME(&gate
->ipv4
, &si
->addr
.ipv4
))
431 && IPV6_ADDR_SAME(gate
, &si
->addr
.ipv6
))))
432 && (!strcmp(ifname
? ifname
: "", si
->ifname
))) {
433 if ((distance
== si
->distance
) && (tag
== si
->tag
)
434 && !memcmp(&si
->snh_label
, snh_label
,
435 sizeof(struct static_nh_label
))
436 && si
->bh_type
== bh_type
) {
437 route_unlock_node(rn
);
444 /* Distance or tag or label changed, delete existing first. */
446 static_delete_route(afi
, safi
, type
, p
, src_p
, gate
, ifname
,
447 update
->tag
, update
->distance
, zvrf
,
450 /* Make new static route structure. */
451 si
= XCALLOC(MTYPE_STATIC_ROUTE
, sizeof(struct static_route
));
454 si
->distance
= distance
;
455 si
->bh_type
= bh_type
;
457 si
->vrf_id
= zvrf_id(zvrf
);
458 si
->nh_vrf_id
= zvrf_id(nh_zvrf
);
459 strcpy(si
->nh_vrfname
, nh_zvrf
->vrf
->name
);
462 strlcpy(si
->ifname
, ifname
, sizeof(si
->ifname
));
463 si
->ifindex
= IFINDEX_INTERNAL
;
466 case STATIC_IPV4_GATEWAY
:
467 case STATIC_IPV4_GATEWAY_IFNAME
:
468 si
->addr
.ipv4
= gate
->ipv4
;
470 case STATIC_IPV6_GATEWAY
:
471 case STATIC_IPV6_GATEWAY_IFNAME
:
472 si
->addr
.ipv6
= gate
->ipv6
;
478 /* Save labels, if any. */
479 memcpy(&si
->snh_label
, snh_label
, sizeof(struct static_nh_label
));
481 /* Add new static route information to the tree with sort by
482 distance value and gateway address. */
483 for (pp
= NULL
, cp
= rn
->info
; cp
; pp
= cp
, cp
= cp
->next
) {
484 if (si
->distance
< cp
->distance
)
486 if (si
->distance
> cp
->distance
)
488 if (si
->type
== STATIC_IPV4_GATEWAY
489 && cp
->type
== STATIC_IPV4_GATEWAY
) {
490 if (ntohl(si
->addr
.ipv4
.s_addr
)
491 < ntohl(cp
->addr
.ipv4
.s_addr
))
493 if (ntohl(si
->addr
.ipv4
.s_addr
)
494 > ntohl(cp
->addr
.ipv4
.s_addr
))
499 /* Make linked list. */
509 /* check whether interface exists in system & install if it does */
511 static_install_route(afi
, safi
, p
, src_p
, si
);
513 struct interface
*ifp
;
515 ifp
= if_lookup_by_name(ifname
, zvrf_id(nh_zvrf
));
516 if (ifp
&& ifp
->ifindex
!= IFINDEX_INTERNAL
) {
517 si
->ifindex
= ifp
->ifindex
;
518 static_install_route(afi
, safi
, p
, src_p
, si
);
520 zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf",
527 int static_delete_route(afi_t afi
, safi_t safi
, uint8_t type
, struct prefix
*p
,
528 struct prefix_ipv6
*src_p
, union g_addr
*gate
,
529 const char *ifname
, route_tag_t tag
, uint8_t distance
,
530 struct zebra_vrf
*zvrf
,
531 struct static_nh_label
*snh_label
)
533 struct route_node
*rn
;
534 struct static_route
*si
;
535 struct route_table
*stable
;
538 stable
= zebra_vrf_static_table(afi
, safi
, zvrf
);
542 /* Lookup static route prefix. */
543 rn
= srcdest_rnode_lookup(stable
, p
, src_p
);
547 /* Find same static route is the tree */
548 for (si
= rn
->info
; si
; si
= si
->next
)
552 && IPV4_ADDR_SAME(&gate
->ipv4
, &si
->addr
.ipv4
))
554 && IPV6_ADDR_SAME(gate
, &si
->addr
.ipv6
))))
555 && (!strcmp(ifname
? ifname
: "", si
->ifname
))
556 && (!tag
|| (tag
== si
->tag
))
557 && (!snh_label
->num_labels
558 || !memcmp(&si
->snh_label
, snh_label
,
559 sizeof(struct static_nh_label
))))
562 /* Can't find static route. */
564 route_unlock_node(rn
);
568 /* Uninstall from rib. */
569 if (!si
->ifname
[0] || si
->ifindex
!= IFINDEX_INTERNAL
)
570 static_uninstall_route(afi
, safi
, p
, src_p
, si
);
572 /* Unlink static route from linked list. */
574 si
->prev
->next
= si
->next
;
578 si
->next
->prev
= si
->prev
;
579 route_unlock_node(rn
);
581 /* Free static route configuration. */
582 XFREE(MTYPE_STATIC_ROUTE
, si
);
584 route_unlock_node(rn
);
589 static void static_ifindex_update_af(struct interface
*ifp
, bool up
, afi_t afi
,
592 struct route_table
*stable
;
593 struct route_node
*rn
;
594 struct static_route
*si
;
595 struct prefix
*p
, *src_pp
;
596 struct prefix_ipv6
*src_p
;
599 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
600 struct zebra_vrf
*zvrf
;
604 stable
= zebra_vrf_static_table(afi
, safi
, zvrf
);
608 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
)) {
609 srcdest_rnode_prefixes(rn
, &p
, &src_pp
);
610 src_p
= (struct prefix_ipv6
*)src_pp
;
612 for (si
= rn
->info
; si
; si
= si
->next
) {
616 if (strcmp(si
->ifname
, ifp
->name
))
618 si
->ifindex
= ifp
->ifindex
;
619 static_install_route(afi
, safi
, p
, src_p
, si
);
621 if (si
->ifindex
!= ifp
->ifindex
)
623 static_uninstall_route(afi
, safi
, p
, src_p
, si
);
624 si
->ifindex
= IFINDEX_INTERNAL
;
632 * This function looks at a zvrf's stable and notices if any of the
633 * nexthops we are using are part of the vrf coming up.
634 * If we are using them then cleanup the nexthop vrf id
635 * to be the new value and then re-installs them
638 * stable -> The table we are looking at.
639 * zvrf -> The newly changed vrf.
640 * afi -> The afi to look at
641 * safi -> the safi to look at
643 static void static_fixup_vrf(struct zebra_vrf
*zvrf
,
644 struct route_table
*stable
, afi_t afi
, safi_t safi
)
646 struct route_node
*rn
;
647 struct static_route
*si
;
648 struct interface
*ifp
;
650 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
651 for (si
= rn
->info
; si
; si
= si
->next
) {
652 if (strcmp(zvrf
->vrf
->name
, si
->nh_vrfname
) != 0)
655 si
->nh_vrf_id
= zvrf
->vrf
->vrf_id
;
657 ifp
= if_lookup_by_name(si
->ifname
,
660 si
->ifindex
= ifp
->ifindex
;
664 static_install_route(afi
, safi
, &rn
->p
, NULL
, si
);
670 * This function enables static routes in a zvrf as it
671 * is coming up. It sets the new vrf_id as appropriate.
673 * zvrf -> The zvrf that is being brought up and enabled by the kernel
674 * stable -> The stable we are looking at.
675 * afi -> the afi in question
676 * safi -> the safi in question
678 static void static_enable_vrf(struct zebra_vrf
*zvrf
,
679 struct route_table
*stable
,
680 afi_t afi
, safi_t safi
)
682 struct route_node
*rn
;
683 struct static_route
*si
;
684 struct interface
*ifp
;
685 struct vrf
*vrf
= zvrf
->vrf
;
687 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
688 for (si
= rn
->info
; si
; si
= si
->next
) {
689 si
->vrf_id
= vrf
->vrf_id
;
691 ifp
= if_lookup_by_name(si
->ifname
,
694 si
->ifindex
= ifp
->ifindex
;
698 static_install_route(afi
, safi
, &rn
->p
, NULL
, si
);
704 * When a vrf is being enabled by the kernel, go through all the
705 * static routes in the system that use this vrf (both nexthops vrfs
706 * and the routes vrf )
708 * enable_zvrf -> the vrf being enabled
710 void static_fixup_vrf_ids(struct zebra_vrf
*enable_zvrf
)
712 struct route_table
*stable
;
717 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
718 struct zebra_vrf
*zvrf
;
721 /* Install any static routes configured for this VRF. */
722 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
723 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
724 stable
= zvrf
->stable
[afi
][safi
];
728 static_fixup_vrf(enable_zvrf
, stable
,
731 if (enable_zvrf
== zvrf
)
732 static_enable_vrf(zvrf
, stable
,
740 * Look at the specified stable and if any of the routes in
741 * this table are using the zvrf as the nexthop, uninstall
744 * zvrf -> the vrf being disabled
745 * stable -> the table we need to look at.
746 * afi -> the afi in question
747 * safi -> the safi in question
749 static void static_cleanup_vrf(struct zebra_vrf
*zvrf
,
750 struct route_table
*stable
,
751 afi_t afi
, safi_t safi
)
753 struct route_node
*rn
;
754 struct static_route
*si
;
756 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
757 for (si
= rn
->info
; si
; si
= si
->next
) {
758 if (strcmp(zvrf
->vrf
->name
, si
->nh_vrfname
) != 0)
761 static_uninstall_route(afi
, safi
, &rn
->p
, NULL
, si
);
767 * Look at all static routes in this table and uninstall
770 * stable -> The table to uninstall from
771 * afi -> The afi in question
772 * safi -> the safi in question
774 static void static_disable_vrf(struct route_table
*stable
,
775 afi_t afi
, safi_t safi
)
777 struct route_node
*rn
;
778 struct static_route
*si
;
780 for (rn
= route_top(stable
); rn
; rn
= route_next(rn
)) {
781 for (si
= rn
->info
; si
; si
= si
->next
) {
782 static_uninstall_route(afi
, safi
, &rn
->p
, NULL
, si
);
788 * When the disable_zvrf is shutdown by the kernel, we call
789 * this function and it cleans up all static routes using
790 * this vrf as a nexthop as well as all static routes
793 * disable_zvrf - The vrf being disabled
795 void static_cleanup_vrf_ids(struct zebra_vrf
*disable_zvrf
)
801 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
802 struct zebra_vrf
*zvrf
;
806 /* Uninstall any static routes configured for this VRF. */
807 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++) {
808 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
809 struct route_table
*stable
;
811 stable
= zvrf
->stable
[afi
][safi
];
815 static_cleanup_vrf(disable_zvrf
, stable
,
818 if (disable_zvrf
== zvrf
)
819 static_disable_vrf(stable
, afi
, safi
);
825 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
826 void static_ifindex_update(struct interface
*ifp
, bool up
)
828 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_UNICAST
);
829 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_MULTICAST
);
830 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_UNICAST
);
831 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_MULTICAST
);