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
;
158 re
->nh_vrf_id
= si
->vrf_id
;
161 ? (zebra_vrf_lookup_by_id(si
->vrf_id
))->table_id
162 : zebrad
.rtm_table_default
;
167 case STATIC_IPV4_GATEWAY
:
168 nexthop
= route_entry_nexthop_ipv4_add(
169 re
, &si
->addr
.ipv4
, NULL
);
170 nh_p
.family
= AF_INET
;
171 nh_p
.prefixlen
= IPV4_MAX_BITLEN
;
172 nh_p
.u
.prefix4
= si
->addr
.ipv4
;
173 zebra_register_rnh_static_nh(si
->vrf_id
, &nh_p
, rn
);
175 case STATIC_IPV4_GATEWAY_IFNAME
:
176 nexthop
= route_entry_nexthop_ipv4_ifindex_add(
177 re
, &si
->addr
.ipv4
, NULL
, si
->ifindex
);
180 nexthop
= route_entry_nexthop_ifindex_add(re
,
183 case STATIC_BLACKHOLE
:
184 nexthop
= route_entry_nexthop_blackhole_add(
187 case STATIC_IPV6_GATEWAY
:
188 nexthop
= route_entry_nexthop_ipv6_add(re
,
190 nh_p
.family
= AF_INET6
;
191 nh_p
.prefixlen
= IPV6_MAX_BITLEN
;
192 nh_p
.u
.prefix6
= si
->addr
.ipv6
;
193 zebra_register_rnh_static_nh(si
->vrf_id
, &nh_p
, rn
);
195 case STATIC_IPV6_GATEWAY_IFNAME
:
196 nexthop
= route_entry_nexthop_ipv6_ifindex_add(
197 re
, &si
->addr
.ipv6
, si
->ifindex
);
200 /* Update label(s), if present. */
201 if (si
->snh_label
.num_labels
)
202 nexthop_add_labels(nexthop
, ZEBRA_LSP_STATIC
,
203 si
->snh_label
.num_labels
,
204 &si
->snh_label
.label
[0]);
206 if (IS_ZEBRA_DEBUG_RIB
) {
207 char buf
[INET6_ADDRSTRLEN
];
208 if (IS_ZEBRA_DEBUG_RIB
) {
209 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
212 "%u:%s/%d: Inserting route rn %p, re %p (type %d)",
213 si
->vrf_id
, buf
, p
->prefixlen
, rn
, re
,
217 re
->uptime
= time(NULL
);
218 /* Link this re to the tree. Schedule for processing or invoke
222 if (si
->type
== STATIC_IPV4_GATEWAY
223 || si
->type
== STATIC_IPV6_GATEWAY
) {
224 rib_addnode(rn
, re
, 0);
225 zebra_evaluate_rnh(si
->vrf_id
, nh_p
.family
, 1,
226 RNH_NEXTHOP_TYPE
, &nh_p
);
228 rib_addnode(rn
, re
, 1);
232 /* this works correctly with IFNAME<>IFINDEX because a static route on a
233 * non-active interface will have IFINDEX_INTERNAL and thus compare false
235 static int static_nexthop_same(struct nexthop
*nexthop
, struct static_route
*si
)
237 if (nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
238 && si
->type
== STATIC_BLACKHOLE
)
241 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
242 && si
->type
== STATIC_IPV4_GATEWAY
243 && IPV4_ADDR_SAME(&nexthop
->gate
.ipv4
, &si
->addr
.ipv4
))
245 else if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
246 && si
->type
== STATIC_IPV4_GATEWAY_IFNAME
247 && IPV4_ADDR_SAME(&nexthop
->gate
.ipv4
, &si
->addr
.ipv4
)
248 && nexthop
->ifindex
== si
->ifindex
)
250 else if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
251 && si
->type
== STATIC_IFNAME
252 && nexthop
->ifindex
== si
->ifindex
)
254 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6
255 && si
->type
== STATIC_IPV6_GATEWAY
256 && IPV6_ADDR_SAME(&nexthop
->gate
.ipv6
, &si
->addr
.ipv6
))
258 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
259 && si
->type
== STATIC_IPV6_GATEWAY_IFNAME
260 && IPV6_ADDR_SAME(&nexthop
->gate
.ipv6
, &si
->addr
.ipv6
)
261 && nexthop
->ifindex
== si
->ifindex
)
267 /* Uninstall static route from RIB. */
268 void static_uninstall_route(afi_t afi
, safi_t safi
, struct prefix
*p
,
269 struct prefix_ipv6
*src_p
, struct static_route
*si
)
271 struct route_node
*rn
;
272 struct route_entry
*re
;
273 struct nexthop
*nexthop
;
274 struct route_table
*table
;
278 table
= zebra_vrf_table(afi
, safi
, si
->vrf_id
);
282 /* Lookup existing route with type and distance. */
283 rn
= srcdest_rnode_lookup(table
, p
, src_p
);
287 RNODE_FOREACH_RE (rn
, re
) {
288 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_REMOVED
))
291 if (re
->type
== ZEBRA_ROUTE_STATIC
292 && re
->distance
== si
->distance
&& re
->tag
== si
->tag
)
297 route_unlock_node(rn
);
301 /* Lookup nexthop. */
302 for (nexthop
= re
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
303 if (static_nexthop_same(nexthop
, si
))
306 /* Can't find nexthop. */
308 route_unlock_node(rn
);
313 if (re
->nexthop_num
== 1)
316 /* Mark this nexthop as inactive and reinstall the route. Then,
318 * the nexthop. There is no need to re-evaluate the route for
322 if (IS_ZEBRA_DEBUG_RIB
) {
323 char buf
[INET6_ADDRSTRLEN
];
324 if (IS_ZEBRA_DEBUG_RIB
) {
325 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
328 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
329 si
->vrf_id
, buf
, p
->prefixlen
, rn
, re
,
333 UNSET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
334 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)) {
335 rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
337 /* If there are other active nexthops, do an update. */
338 if (re
->nexthop_active_num
> 1) {
339 /* Update route in kernel if it's in fib */
340 if (dest
->selected_fib
)
341 rib_install_kernel(rn
, re
, re
);
342 /* Update redistribution if it's selected */
343 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
345 p
, (struct prefix
*)src_p
, re
,
348 /* Remove from redistribute if selected route
349 * becomes inactive */
350 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
352 p
, (struct prefix
*)src_p
, re
);
353 /* Remove from kernel if fib route becomes
355 if (dest
->selected_fib
)
356 rib_uninstall_kernel(rn
, re
);
361 /* Delete the nexthop and dereg from NHT */
362 nh_p
.family
= AF_INET
;
363 nh_p
.prefixlen
= IPV4_MAX_BITLEN
;
364 nh_p
.u
.prefix4
= nexthop
->gate
.ipv4
;
366 nh_p
.family
= AF_INET6
;
367 nh_p
.prefixlen
= IPV6_MAX_BITLEN
;
368 nh_p
.u
.prefix6
= nexthop
->gate
.ipv6
;
370 route_entry_nexthop_delete(re
, nexthop
);
371 zebra_deregister_rnh_static_nh(si
->vrf_id
, &nh_p
, rn
);
372 nexthop_free(nexthop
);
375 route_unlock_node(rn
);
378 int static_add_route(afi_t afi
, safi_t safi
, u_char type
, struct prefix
*p
,
379 struct prefix_ipv6
*src_p
, union g_addr
*gate
,
380 const char *ifname
, enum static_blackhole_type bh_type
,
381 route_tag_t tag
, u_char distance
, struct zebra_vrf
*zvrf
,
382 struct static_nh_label
*snh_label
)
384 struct route_node
*rn
;
385 struct static_route
*si
;
386 struct static_route
*pp
;
387 struct static_route
*cp
;
388 struct static_route
*update
= NULL
;
389 struct route_table
*stable
= zvrf
->stable
[afi
][safi
];
395 && (type
== STATIC_IPV4_GATEWAY
396 || type
== STATIC_IPV4_GATEWAY_IFNAME
397 || type
== STATIC_IPV6_GATEWAY
398 || type
== STATIC_IPV6_GATEWAY_IFNAME
))
402 && (type
== STATIC_IFNAME
403 || type
== STATIC_IPV4_GATEWAY_IFNAME
404 || type
== STATIC_IPV6_GATEWAY_IFNAME
))
407 /* Lookup static route prefix. */
408 rn
= srcdest_rnode_get(stable
, p
, src_p
);
410 /* Do nothing if there is a same static route. */
411 for (si
= rn
->info
; si
; si
= si
->next
) {
413 && (!gate
|| ((afi
== AFI_IP
414 && IPV4_ADDR_SAME(&gate
->ipv4
, &si
->addr
.ipv4
))
416 && IPV6_ADDR_SAME(gate
, &si
->addr
.ipv6
))))
417 && (!strcmp (ifname
? ifname
: "", si
->ifname
))) {
418 if ((distance
== si
->distance
) && (tag
== si
->tag
)
419 && !memcmp(&si
->snh_label
, snh_label
,
420 sizeof(struct static_nh_label
))
421 && si
->bh_type
== bh_type
) {
422 route_unlock_node(rn
);
429 /* Distance or tag or label changed, delete existing first. */
431 static_delete_route(afi
, safi
, type
, p
, src_p
, gate
, ifname
,
432 update
->tag
, update
->distance
, zvrf
,
435 /* Make new static route structure. */
436 si
= XCALLOC(MTYPE_STATIC_ROUTE
, sizeof(struct static_route
));
439 si
->distance
= distance
;
440 si
->bh_type
= bh_type
;
442 si
->vrf_id
= zvrf_id(zvrf
);
444 strlcpy(si
->ifname
, ifname
, sizeof(si
->ifname
));
445 si
->ifindex
= IFINDEX_INTERNAL
;
448 case STATIC_IPV4_GATEWAY
:
449 case STATIC_IPV4_GATEWAY_IFNAME
:
450 si
->addr
.ipv4
= gate
->ipv4
;
452 case STATIC_IPV6_GATEWAY
:
453 case STATIC_IPV6_GATEWAY_IFNAME
:
454 si
->addr
.ipv6
= gate
->ipv6
;
460 /* Save labels, if any. */
461 memcpy(&si
->snh_label
, snh_label
, sizeof(struct static_nh_label
));
463 /* Add new static route information to the tree with sort by
464 distance value and gateway address. */
465 for (pp
= NULL
, cp
= rn
->info
; cp
; pp
= cp
, cp
= cp
->next
) {
466 if (si
->distance
< cp
->distance
)
468 if (si
->distance
> cp
->distance
)
470 if (si
->type
== STATIC_IPV4_GATEWAY
471 && cp
->type
== STATIC_IPV4_GATEWAY
) {
472 if (ntohl(si
->addr
.ipv4
.s_addr
)
473 < ntohl(cp
->addr
.ipv4
.s_addr
))
475 if (ntohl(si
->addr
.ipv4
.s_addr
)
476 > ntohl(cp
->addr
.ipv4
.s_addr
))
481 /* Make linked list. */
491 /* check whether interface exists in system & install if it does */
493 static_install_route(afi
, safi
, p
, src_p
, si
);
495 struct interface
*ifp
;
497 ifp
= if_lookup_by_name(ifname
, zvrf_id(zvrf
));
498 if (ifp
&& ifp
->ifindex
!= IFINDEX_INTERNAL
) {
499 si
->ifindex
= ifp
->ifindex
;
500 static_install_route(afi
, safi
, p
, src_p
, si
);
507 int static_delete_route(afi_t afi
, safi_t safi
, u_char type
, struct prefix
*p
,
508 struct prefix_ipv6
*src_p
, union g_addr
*gate
,
509 const char *ifname
, route_tag_t tag
, u_char distance
,
510 struct zebra_vrf
*zvrf
,
511 struct static_nh_label
*snh_label
)
513 struct route_node
*rn
;
514 struct static_route
*si
;
515 struct route_table
*stable
;
518 stable
= zebra_vrf_static_table(afi
, safi
, zvrf
);
522 /* Lookup static route prefix. */
523 rn
= srcdest_rnode_lookup(stable
, p
, src_p
);
527 /* Find same static route is the tree */
528 for (si
= rn
->info
; si
; si
= si
->next
)
530 && (!gate
|| ((afi
== AFI_IP
531 && IPV4_ADDR_SAME(&gate
->ipv4
, &si
->addr
.ipv4
))
533 && IPV6_ADDR_SAME(gate
, &si
->addr
.ipv6
))))
534 && (!strcmp(ifname
? ifname
: "", si
->ifname
))
535 && (!tag
|| (tag
== si
->tag
))
536 && (!snh_label
->num_labels
537 || !memcmp(&si
->snh_label
, snh_label
,
538 sizeof(struct static_nh_label
))))
541 /* Can't find static route. */
543 route_unlock_node(rn
);
547 /* Uninstall from rib. */
548 if (!si
->ifname
[0] || si
->ifindex
!= IFINDEX_INTERNAL
)
549 static_uninstall_route(afi
, safi
, p
, src_p
, si
);
551 /* Unlink static route from linked list. */
553 si
->prev
->next
= si
->next
;
557 si
->next
->prev
= si
->prev
;
558 route_unlock_node(rn
);
560 /* Free static route configuration. */
561 XFREE(MTYPE_STATIC_ROUTE
, si
);
563 route_unlock_node(rn
);
568 static void static_ifindex_update_af(struct interface
*ifp
, bool up
,
569 afi_t afi
, safi_t safi
)
571 struct route_table
*stable
;
572 struct zebra_vrf
*zvrf
= zebra_vrf_lookup_by_id(ifp
->vrf_id
);
573 struct route_node
*rn
;
574 struct static_route
*si
;
575 struct prefix
*p
, *src_pp
;
576 struct prefix_ipv6
*src_p
;
578 stable
= zebra_vrf_static_table(afi
, safi
, zvrf
);
582 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
)) {
583 srcdest_rnode_prefixes(rn
, &p
, &src_pp
);
584 src_p
= (struct prefix_ipv6
*)src_pp
;
586 for (si
= rn
->info
; si
; si
= si
->next
) {
590 if (strcmp(si
->ifname
, ifp
->name
))
592 si
->ifindex
= ifp
->ifindex
;
593 static_install_route(afi
, safi
, p
, src_p
, si
);
595 if (si
->ifindex
!= ifp
->ifindex
)
597 static_uninstall_route(afi
, safi
, p
, src_p
,
599 si
->ifindex
= IFINDEX_INTERNAL
;
605 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
606 void static_ifindex_update(struct interface
*ifp
, bool up
)
608 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_UNICAST
);
609 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_MULTICAST
);
610 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_UNICAST
);
611 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_MULTICAST
);