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;
51 table
= zebra_vrf_table(afi
, safi
, si
->vrf_id
);
55 memset(&nh_p
, 0, sizeof(nh_p
));
56 if (si
->type
== STATIC_BLACKHOLE
) {
57 switch (si
->bh_type
) {
58 case STATIC_BLACKHOLE_DROP
:
59 case STATIC_BLACKHOLE_NULL
:
60 bh_type
= BLACKHOLE_NULL
;
62 case STATIC_BLACKHOLE_REJECT
:
63 bh_type
= BLACKHOLE_REJECT
;
68 /* Lookup existing route */
69 rn
= srcdest_rnode_get(table
, p
, src_p
);
70 RNODE_FOREACH_RE (rn
, re
) {
71 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_REMOVED
))
74 if (re
->type
== ZEBRA_ROUTE_STATIC
75 && re
->distance
== si
->distance
)
80 /* if tag value changed , update old value in RIB */
81 if (re
->tag
!= si
->tag
)
84 /* Same distance static route is there. Update it with new
86 route_unlock_node(rn
);
88 case STATIC_IPV4_GATEWAY
:
89 nexthop
= route_entry_nexthop_ipv4_add(
90 re
, &si
->addr
.ipv4
, NULL
);
91 nh_p
.family
= AF_INET
;
92 nh_p
.prefixlen
= IPV4_MAX_BITLEN
;
93 nh_p
.u
.prefix4
= si
->addr
.ipv4
;
94 zebra_register_rnh_static_nh(si
->vrf_id
, &nh_p
, rn
);
96 case STATIC_IPV4_GATEWAY_IFNAME
:
97 nexthop
= route_entry_nexthop_ipv4_ifindex_add(
98 re
, &si
->addr
.ipv4
, NULL
, si
->ifindex
);
101 nexthop
= route_entry_nexthop_ifindex_add(re
,
104 case STATIC_BLACKHOLE
:
105 nexthop
= route_entry_nexthop_blackhole_add(
108 case STATIC_IPV6_GATEWAY
:
109 nexthop
= route_entry_nexthop_ipv6_add(re
,
111 nh_p
.family
= AF_INET6
;
112 nh_p
.prefixlen
= IPV6_MAX_BITLEN
;
113 nh_p
.u
.prefix6
= si
->addr
.ipv6
;
114 zebra_register_rnh_static_nh(si
->vrf_id
, &nh_p
, rn
);
116 case STATIC_IPV6_GATEWAY_IFNAME
:
117 nexthop
= route_entry_nexthop_ipv6_ifindex_add(
118 re
, &si
->addr
.ipv6
, si
->ifindex
);
121 /* Update label(s), if present. */
122 if (si
->snh_label
.num_labels
)
123 nexthop_add_labels(nexthop
, ZEBRA_LSP_STATIC
,
124 si
->snh_label
.num_labels
,
125 &si
->snh_label
.label
[0]);
127 if (IS_ZEBRA_DEBUG_RIB
) {
128 char buf
[INET6_ADDRSTRLEN
];
129 if (IS_ZEBRA_DEBUG_RIB
) {
130 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
133 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
134 si
->vrf_id
, buf
, p
->prefixlen
, rn
, re
,
139 re
->uptime
= time(NULL
);
140 /* Schedule route for processing or invoke NHT, as appropriate.
142 if (si
->type
== STATIC_IPV4_GATEWAY
143 || si
->type
== STATIC_IPV6_GATEWAY
)
144 zebra_evaluate_rnh(si
->vrf_id
, nh_p
.family
, 1,
145 RNH_NEXTHOP_TYPE
, &nh_p
);
149 /* This is new static route. */
150 re
= XCALLOC(MTYPE_RE
, sizeof(struct route_entry
));
152 re
->type
= ZEBRA_ROUTE_STATIC
;
154 re
->distance
= si
->distance
;
157 re
->vrf_id
= si
->vrf_id
;
160 ? (zebra_vrf_lookup_by_id(si
->vrf_id
))->table_id
161 : zebrad
.rtm_table_default
;
166 case STATIC_IPV4_GATEWAY
:
167 nexthop
= route_entry_nexthop_ipv4_add(
168 re
, &si
->addr
.ipv4
, NULL
);
169 nh_p
.family
= AF_INET
;
170 nh_p
.prefixlen
= IPV4_MAX_BITLEN
;
171 nh_p
.u
.prefix4
= si
->addr
.ipv4
;
172 zebra_register_rnh_static_nh(si
->vrf_id
, &nh_p
, rn
);
174 case STATIC_IPV4_GATEWAY_IFNAME
:
175 nexthop
= route_entry_nexthop_ipv4_ifindex_add(
176 re
, &si
->addr
.ipv4
, NULL
, si
->ifindex
);
179 nexthop
= route_entry_nexthop_ifindex_add(re
,
182 case STATIC_BLACKHOLE
:
183 nexthop
= route_entry_nexthop_blackhole_add(
186 case STATIC_IPV6_GATEWAY
:
187 nexthop
= route_entry_nexthop_ipv6_add(re
,
189 nh_p
.family
= AF_INET6
;
190 nh_p
.prefixlen
= IPV6_MAX_BITLEN
;
191 nh_p
.u
.prefix6
= si
->addr
.ipv6
;
192 zebra_register_rnh_static_nh(si
->vrf_id
, &nh_p
, rn
);
194 case STATIC_IPV6_GATEWAY_IFNAME
:
195 nexthop
= route_entry_nexthop_ipv6_ifindex_add(
196 re
, &si
->addr
.ipv6
, si
->ifindex
);
199 /* Update label(s), if present. */
200 if (si
->snh_label
.num_labels
)
201 nexthop_add_labels(nexthop
, ZEBRA_LSP_STATIC
,
202 si
->snh_label
.num_labels
,
203 &si
->snh_label
.label
[0]);
205 if (IS_ZEBRA_DEBUG_RIB
) {
206 char buf
[INET6_ADDRSTRLEN
];
207 if (IS_ZEBRA_DEBUG_RIB
) {
208 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
211 "%u:%s/%d: Inserting route rn %p, re %p (type %d)",
212 si
->vrf_id
, buf
, p
->prefixlen
, rn
, re
,
216 re
->uptime
= time(NULL
);
217 /* Link this re to the tree. Schedule for processing or invoke
221 if (si
->type
== STATIC_IPV4_GATEWAY
222 || si
->type
== STATIC_IPV6_GATEWAY
) {
223 rib_addnode(rn
, re
, 0);
224 zebra_evaluate_rnh(si
->vrf_id
, nh_p
.family
, 1,
225 RNH_NEXTHOP_TYPE
, &nh_p
);
227 rib_addnode(rn
, re
, 1);
231 /* this works correctly with IFNAME<>IFINDEX because a static route on a
232 * non-active interface will have IFINDEX_INTERNAL and thus compare false
234 static int static_nexthop_same(struct nexthop
*nexthop
, struct static_route
*si
)
236 if (nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
237 && si
->type
== STATIC_BLACKHOLE
)
240 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
241 && si
->type
== STATIC_IPV4_GATEWAY
242 && IPV4_ADDR_SAME(&nexthop
->gate
.ipv4
, &si
->addr
.ipv4
))
244 else if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
245 && si
->type
== STATIC_IPV4_GATEWAY_IFNAME
246 && IPV4_ADDR_SAME(&nexthop
->gate
.ipv4
, &si
->addr
.ipv4
)
247 && nexthop
->ifindex
== si
->ifindex
)
249 else if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
250 && si
->type
== STATIC_IFNAME
251 && nexthop
->ifindex
== si
->ifindex
)
253 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6
254 && si
->type
== STATIC_IPV6_GATEWAY
255 && IPV6_ADDR_SAME(&nexthop
->gate
.ipv6
, &si
->addr
.ipv6
))
257 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
258 && si
->type
== STATIC_IPV6_GATEWAY_IFNAME
259 && IPV6_ADDR_SAME(&nexthop
->gate
.ipv6
, &si
->addr
.ipv6
)
260 && nexthop
->ifindex
== si
->ifindex
)
266 /* Uninstall static route from RIB. */
267 void static_uninstall_route(afi_t afi
, safi_t safi
, struct prefix
*p
,
268 struct prefix_ipv6
*src_p
, struct static_route
*si
)
270 struct route_node
*rn
;
271 struct route_entry
*re
;
272 struct nexthop
*nexthop
;
273 struct route_table
*table
;
277 table
= zebra_vrf_table(afi
, safi
, si
->vrf_id
);
281 /* Lookup existing route with type and distance. */
282 rn
= srcdest_rnode_lookup(table
, p
, src_p
);
286 RNODE_FOREACH_RE (rn
, re
) {
287 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_REMOVED
))
290 if (re
->type
== ZEBRA_ROUTE_STATIC
291 && re
->distance
== si
->distance
&& re
->tag
== si
->tag
)
296 route_unlock_node(rn
);
300 /* Lookup nexthop. */
301 for (nexthop
= re
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
302 if (static_nexthop_same(nexthop
, si
))
305 /* Can't find nexthop. */
307 route_unlock_node(rn
);
312 if (re
->nexthop_num
== 1)
315 /* Mark this nexthop as inactive and reinstall the route. Then,
317 * the nexthop. There is no need to re-evaluate the route for
321 if (IS_ZEBRA_DEBUG_RIB
) {
322 char buf
[INET6_ADDRSTRLEN
];
323 if (IS_ZEBRA_DEBUG_RIB
) {
324 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
327 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
328 si
->vrf_id
, buf
, p
->prefixlen
, rn
, re
,
332 UNSET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
333 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)) {
334 /* If there are other active nexthops, do an update. */
335 if (re
->nexthop_active_num
> 1) {
336 /* Update route in kernel if it's in fib */
337 if (CHECK_FLAG(re
->status
,
338 ROUTE_ENTRY_SELECTED_FIB
))
339 rib_install_kernel(rn
, re
, re
);
340 /* Update redistribution if it's selected */
341 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
343 p
, (struct prefix
*)src_p
, re
,
346 /* Remove from redistribute if selected route
347 * becomes inactive */
348 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
350 p
, (struct prefix
*)src_p
, re
);
351 /* Remove from kernel if fib route becomes
353 if (CHECK_FLAG(re
->status
,
354 ROUTE_ENTRY_SELECTED_FIB
))
355 rib_uninstall_kernel(rn
, re
);
360 /* Delete the nexthop and dereg from NHT */
361 nh_p
.family
= AF_INET
;
362 nh_p
.prefixlen
= IPV4_MAX_BITLEN
;
363 nh_p
.u
.prefix4
= nexthop
->gate
.ipv4
;
365 nh_p
.family
= AF_INET6
;
366 nh_p
.prefixlen
= IPV6_MAX_BITLEN
;
367 nh_p
.u
.prefix6
= nexthop
->gate
.ipv6
;
369 route_entry_nexthop_delete(re
, nexthop
);
370 zebra_deregister_rnh_static_nh(si
->vrf_id
, &nh_p
, rn
);
371 nexthop_free(nexthop
);
374 route_unlock_node(rn
);
377 int static_add_route(afi_t afi
, safi_t safi
, u_char type
, struct prefix
*p
,
378 struct prefix_ipv6
*src_p
, union g_addr
*gate
,
379 const char *ifname
, enum static_blackhole_type bh_type
,
380 route_tag_t tag
, u_char distance
, struct zebra_vrf
*zvrf
,
381 struct static_nh_label
*snh_label
)
383 struct route_node
*rn
;
384 struct static_route
*si
;
385 struct static_route
*pp
;
386 struct static_route
*cp
;
387 struct static_route
*update
= NULL
;
388 struct route_table
*stable
= zvrf
->stable
[afi
][safi
];
394 && (type
== STATIC_IPV4_GATEWAY
395 || type
== STATIC_IPV4_GATEWAY_IFNAME
396 || type
== STATIC_IPV6_GATEWAY
397 || type
== STATIC_IPV6_GATEWAY_IFNAME
))
401 && (type
== STATIC_IFNAME
402 || type
== STATIC_IPV4_GATEWAY_IFNAME
403 || type
== STATIC_IPV6_GATEWAY_IFNAME
))
406 /* Lookup static route prefix. */
407 rn
= srcdest_rnode_get(stable
, p
, src_p
);
409 /* Do nothing if there is a same static route. */
410 for (si
= rn
->info
; si
; si
= si
->next
) {
412 && (!gate
|| ((afi
== AFI_IP
413 && IPV4_ADDR_SAME(&gate
->ipv4
, &si
->addr
.ipv4
))
415 && IPV6_ADDR_SAME(gate
, &si
->addr
.ipv6
))))
416 && (!strcmp (ifname
? ifname
: "", si
->ifname
))) {
417 if ((distance
== si
->distance
) && (tag
== si
->tag
)
418 && !memcmp(&si
->snh_label
, snh_label
,
419 sizeof(struct static_nh_label
))
420 && si
->bh_type
== bh_type
) {
421 route_unlock_node(rn
);
428 /* Distance or tag or label changed, delete existing first. */
430 static_delete_route(afi
, safi
, type
, p
, src_p
, gate
, ifname
,
431 update
->tag
, update
->distance
, zvrf
,
434 /* Make new static route structure. */
435 si
= XCALLOC(MTYPE_STATIC_ROUTE
, sizeof(struct static_route
));
438 si
->distance
= distance
;
439 si
->bh_type
= bh_type
;
441 si
->vrf_id
= zvrf_id(zvrf
);
443 strlcpy(si
->ifname
, ifname
, sizeof(si
->ifname
));
444 si
->ifindex
= IFINDEX_INTERNAL
;
447 case STATIC_IPV4_GATEWAY
:
448 case STATIC_IPV4_GATEWAY_IFNAME
:
449 si
->addr
.ipv4
= gate
->ipv4
;
451 case STATIC_IPV6_GATEWAY
:
452 case STATIC_IPV6_GATEWAY_IFNAME
:
453 si
->addr
.ipv6
= gate
->ipv6
;
459 /* Save labels, if any. */
460 memcpy(&si
->snh_label
, snh_label
, sizeof(struct static_nh_label
));
462 /* Add new static route information to the tree with sort by
463 distance value and gateway address. */
464 for (pp
= NULL
, cp
= rn
->info
; cp
; pp
= cp
, cp
= cp
->next
) {
465 if (si
->distance
< cp
->distance
)
467 if (si
->distance
> cp
->distance
)
469 if (si
->type
== STATIC_IPV4_GATEWAY
470 && cp
->type
== STATIC_IPV4_GATEWAY
) {
471 if (ntohl(si
->addr
.ipv4
.s_addr
)
472 < ntohl(cp
->addr
.ipv4
.s_addr
))
474 if (ntohl(si
->addr
.ipv4
.s_addr
)
475 > ntohl(cp
->addr
.ipv4
.s_addr
))
480 /* Make linked list. */
490 /* check whether interface exists in system & install if it does */
492 static_install_route(afi
, safi
, p
, src_p
, si
);
494 struct interface
*ifp
;
496 ifp
= if_lookup_by_name(ifname
, zvrf_id(zvrf
));
497 if (ifp
&& ifp
->ifindex
!= IFINDEX_INTERNAL
) {
498 si
->ifindex
= ifp
->ifindex
;
499 static_install_route(afi
, safi
, p
, src_p
, si
);
506 int static_delete_route(afi_t afi
, safi_t safi
, u_char type
, struct prefix
*p
,
507 struct prefix_ipv6
*src_p
, union g_addr
*gate
,
508 const char *ifname
, route_tag_t tag
, u_char distance
,
509 struct zebra_vrf
*zvrf
,
510 struct static_nh_label
*snh_label
)
512 struct route_node
*rn
;
513 struct static_route
*si
;
514 struct route_table
*stable
;
517 stable
= zebra_vrf_static_table(afi
, safi
, zvrf
);
521 /* Lookup static route prefix. */
522 rn
= srcdest_rnode_lookup(stable
, p
, src_p
);
526 /* Find same static route is the tree */
527 for (si
= rn
->info
; si
; si
= si
->next
)
529 && (!gate
|| ((afi
== AFI_IP
530 && IPV4_ADDR_SAME(&gate
->ipv4
, &si
->addr
.ipv4
))
532 && IPV6_ADDR_SAME(gate
, &si
->addr
.ipv6
))))
533 && (!strcmp(ifname
? ifname
: "", si
->ifname
))
534 && (!tag
|| (tag
== si
->tag
))
535 && (!snh_label
->num_labels
536 || !memcmp(&si
->snh_label
, snh_label
,
537 sizeof(struct static_nh_label
))))
540 /* Can't find static route. */
542 route_unlock_node(rn
);
546 /* Uninstall from rib. */
547 if (!si
->ifname
[0] || si
->ifindex
!= IFINDEX_INTERNAL
)
548 static_uninstall_route(afi
, safi
, p
, src_p
, si
);
550 /* Unlink static route from linked list. */
552 si
->prev
->next
= si
->next
;
556 si
->next
->prev
= si
->prev
;
557 route_unlock_node(rn
);
559 /* Free static route configuration. */
560 XFREE(MTYPE_STATIC_ROUTE
, si
);
562 route_unlock_node(rn
);
567 static void static_ifindex_update_af(struct interface
*ifp
, bool up
,
568 afi_t afi
, safi_t safi
)
570 struct route_table
*stable
;
571 struct zebra_vrf
*zvrf
= zebra_vrf_lookup_by_id(ifp
->vrf_id
);
572 struct route_node
*rn
;
573 struct static_route
*si
;
574 struct prefix
*p
, *src_pp
;
575 struct prefix_ipv6
*src_p
;
577 stable
= zebra_vrf_static_table(afi
, safi
, zvrf
);
581 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
)) {
582 srcdest_rnode_prefixes(rn
, &p
, &src_pp
);
583 src_p
= (struct prefix_ipv6
*)src_pp
;
585 for (si
= rn
->info
; si
; si
= si
->next
) {
589 if (strcmp(si
->ifname
, ifp
->name
))
591 si
->ifindex
= ifp
->ifindex
;
592 static_install_route(afi
, safi
, p
, src_p
, si
);
594 if (si
->ifindex
!= ifp
->ifindex
)
596 static_uninstall_route(afi
, safi
, p
, src_p
,
598 si
->ifindex
= IFINDEX_INTERNAL
;
604 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
605 void static_ifindex_update(struct interface
*ifp
, bool up
)
607 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_UNICAST
);
608 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_MULTICAST
);
609 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_UNICAST
);
610 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_MULTICAST
);