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
;
50 table
= zebra_vrf_table(afi
, safi
, si
->vrf_id
);
54 memset(&nh_p
, 0, sizeof(nh_p
));
56 /* Lookup existing route */
57 rn
= srcdest_rnode_get(table
, p
, src_p
);
58 RNODE_FOREACH_RE(rn
, re
)
60 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_REMOVED
))
63 if (re
->type
== ZEBRA_ROUTE_STATIC
64 && re
->distance
== si
->distance
)
69 /* if tag value changed , update old value in RIB */
70 if (re
->tag
!= si
->tag
)
73 /* Same distance static route is there. Update it with new
75 route_unlock_node(rn
);
77 case STATIC_IPV4_GATEWAY
:
78 nexthop
= route_entry_nexthop_ipv4_add(
79 re
, &si
->addr
.ipv4
, NULL
);
80 nh_p
.family
= AF_INET
;
81 nh_p
.prefixlen
= IPV4_MAX_BITLEN
;
82 nh_p
.u
.prefix4
= si
->addr
.ipv4
;
83 zebra_register_rnh_static_nh(si
->vrf_id
, &nh_p
, rn
);
85 case STATIC_IPV4_GATEWAY_IFNAME
:
86 nexthop
= route_entry_nexthop_ipv4_ifindex_add(
87 re
, &si
->addr
.ipv4
, NULL
, si
->ifindex
);
90 nexthop
= route_entry_nexthop_ifindex_add(re
,
93 case STATIC_BLACKHOLE
:
94 nexthop
= route_entry_nexthop_blackhole_add(re
);
96 case STATIC_IPV6_GATEWAY
:
97 nexthop
= route_entry_nexthop_ipv6_add(re
,
99 nh_p
.family
= AF_INET6
;
100 nh_p
.prefixlen
= IPV6_MAX_BITLEN
;
101 nh_p
.u
.prefix6
= si
->addr
.ipv6
;
102 zebra_register_rnh_static_nh(si
->vrf_id
, &nh_p
, rn
);
104 case STATIC_IPV6_GATEWAY_IFNAME
:
105 nexthop
= route_entry_nexthop_ipv6_ifindex_add(
106 re
, &si
->addr
.ipv6
, si
->ifindex
);
109 /* Update label(s), if present. */
110 if (si
->snh_label
.num_labels
)
111 nexthop_add_labels(nexthop
, ZEBRA_LSP_STATIC
,
112 si
->snh_label
.num_labels
,
113 &si
->snh_label
.label
[0]);
115 if (IS_ZEBRA_DEBUG_RIB
) {
116 char buf
[INET6_ADDRSTRLEN
];
117 if (IS_ZEBRA_DEBUG_RIB
) {
118 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
121 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
122 si
->vrf_id
, buf
, p
->prefixlen
, rn
, re
,
126 /* Schedule route for processing or invoke NHT, as appropriate.
128 if (si
->type
== STATIC_IPV4_GATEWAY
129 || si
->type
== STATIC_IPV6_GATEWAY
)
130 zebra_evaluate_rnh(si
->vrf_id
, nh_p
.family
, 1,
131 RNH_NEXTHOP_TYPE
, &nh_p
);
135 /* This is new static route. */
136 re
= XCALLOC(MTYPE_RE
, sizeof(struct route_entry
));
138 re
->type
= ZEBRA_ROUTE_STATIC
;
140 re
->distance
= si
->distance
;
143 re
->vrf_id
= si
->vrf_id
;
146 ? (zebra_vrf_lookup_by_id(si
->vrf_id
))->table_id
147 : zebrad
.rtm_table_default
;
152 case STATIC_IPV4_GATEWAY
:
153 nexthop
= route_entry_nexthop_ipv4_add(
154 re
, &si
->addr
.ipv4
, NULL
);
155 nh_p
.family
= AF_INET
;
156 nh_p
.prefixlen
= IPV4_MAX_BITLEN
;
157 nh_p
.u
.prefix4
= si
->addr
.ipv4
;
158 zebra_register_rnh_static_nh(si
->vrf_id
, &nh_p
, rn
);
160 case STATIC_IPV4_GATEWAY_IFNAME
:
161 nexthop
= route_entry_nexthop_ipv4_ifindex_add(
162 re
, &si
->addr
.ipv4
, NULL
, si
->ifindex
);
165 nexthop
= route_entry_nexthop_ifindex_add(re
,
168 case STATIC_BLACKHOLE
:
169 nexthop
= route_entry_nexthop_blackhole_add(re
);
171 case STATIC_IPV6_GATEWAY
:
172 nexthop
= route_entry_nexthop_ipv6_add(re
,
174 nh_p
.family
= AF_INET6
;
175 nh_p
.prefixlen
= IPV6_MAX_BITLEN
;
176 nh_p
.u
.prefix6
= si
->addr
.ipv6
;
177 zebra_register_rnh_static_nh(si
->vrf_id
, &nh_p
, rn
);
179 case STATIC_IPV6_GATEWAY_IFNAME
:
180 nexthop
= route_entry_nexthop_ipv6_ifindex_add(
181 re
, &si
->addr
.ipv6
, si
->ifindex
);
184 /* Update label(s), if present. */
185 if (si
->snh_label
.num_labels
)
186 nexthop_add_labels(nexthop
, ZEBRA_LSP_STATIC
,
187 si
->snh_label
.num_labels
,
188 &si
->snh_label
.label
[0]);
190 /* Save the flags of this static routes (reject, blackhole) */
191 re
->flags
= si
->flags
;
193 if (IS_ZEBRA_DEBUG_RIB
) {
194 char buf
[INET6_ADDRSTRLEN
];
195 if (IS_ZEBRA_DEBUG_RIB
) {
196 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
199 "%u:%s/%d: Inserting route rn %p, re %p (type %d)",
200 si
->vrf_id
, buf
, p
->prefixlen
, rn
, re
,
204 /* Link this re to the tree. Schedule for processing or invoke
208 if (si
->type
== STATIC_IPV4_GATEWAY
209 || si
->type
== STATIC_IPV6_GATEWAY
) {
210 rib_addnode(rn
, re
, 0);
211 zebra_evaluate_rnh(si
->vrf_id
, nh_p
.family
, 1,
212 RNH_NEXTHOP_TYPE
, &nh_p
);
214 rib_addnode(rn
, re
, 1);
218 /* this works correctly with IFNAME<>IFINDEX because a static route on a
219 * non-active interface will have IFINDEX_INTERNAL and thus compare false
221 static int static_nexthop_same(struct nexthop
*nexthop
, struct static_route
*si
)
223 if (nexthop
->type
== NEXTHOP_TYPE_BLACKHOLE
224 && si
->type
== STATIC_BLACKHOLE
)
227 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
228 && si
->type
== STATIC_IPV4_GATEWAY
229 && IPV4_ADDR_SAME(&nexthop
->gate
.ipv4
, &si
->addr
.ipv4
))
231 else if (nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
232 && si
->type
== STATIC_IPV4_GATEWAY_IFNAME
233 && IPV4_ADDR_SAME(&nexthop
->gate
.ipv4
, &si
->addr
.ipv4
)
234 && nexthop
->ifindex
== si
->ifindex
)
236 else if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
237 && si
->type
== STATIC_IFNAME
238 && nexthop
->ifindex
== si
->ifindex
)
240 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6
241 && si
->type
== STATIC_IPV6_GATEWAY
242 && IPV6_ADDR_SAME(&nexthop
->gate
.ipv6
, &si
->addr
.ipv6
))
244 else if (nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
245 && si
->type
== STATIC_IPV6_GATEWAY_IFNAME
246 && IPV6_ADDR_SAME(&nexthop
->gate
.ipv6
, &si
->addr
.ipv6
)
247 && nexthop
->ifindex
== si
->ifindex
)
253 /* Uninstall static route from RIB. */
254 void static_uninstall_route(afi_t afi
, safi_t safi
, struct prefix
*p
,
255 struct prefix_ipv6
*src_p
, struct static_route
*si
)
257 struct route_node
*rn
;
258 struct route_entry
*re
;
259 struct nexthop
*nexthop
;
260 struct route_table
*table
;
264 table
= zebra_vrf_table(afi
, safi
, si
->vrf_id
);
268 /* Lookup existing route with type and distance. */
269 rn
= srcdest_rnode_lookup(table
, p
, src_p
);
273 RNODE_FOREACH_RE(rn
, re
)
275 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_REMOVED
))
278 if (re
->type
== ZEBRA_ROUTE_STATIC
279 && re
->distance
== si
->distance
&& re
->tag
== si
->tag
)
284 route_unlock_node(rn
);
288 /* Lookup nexthop. */
289 for (nexthop
= re
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
290 if (static_nexthop_same(nexthop
, si
))
293 /* Can't find nexthop. */
295 route_unlock_node(rn
);
300 if (re
->nexthop_num
== 1)
303 /* Mark this nexthop as inactive and reinstall the route. Then,
305 * the nexthop. There is no need to re-evaluate the route for
309 if (IS_ZEBRA_DEBUG_RIB
) {
310 char buf
[INET6_ADDRSTRLEN
];
311 if (IS_ZEBRA_DEBUG_RIB
) {
312 inet_ntop(p
->family
, &p
->u
.prefix
, buf
,
315 "%u:%s/%d: Modifying route rn %p, re %p (type %d)",
316 si
->vrf_id
, buf
, p
->prefixlen
, rn
, re
,
320 UNSET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
321 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
)) {
322 /* If there are other active nexthops, do an update. */
323 if (re
->nexthop_active_num
> 1) {
324 /* Update route in kernel if it's in fib */
325 if (CHECK_FLAG(re
->status
,
326 ROUTE_ENTRY_SELECTED_FIB
))
327 rib_install_kernel(rn
, re
, re
);
328 /* Update redistribution if it's selected */
329 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
331 p
, (struct prefix
*)src_p
, re
,
334 /* Remove from redistribute if selected route
335 * becomes inactive */
336 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
338 p
, (struct prefix
*)src_p
, re
);
339 /* Remove from kernel if fib route becomes
341 if (CHECK_FLAG(re
->status
,
342 ROUTE_ENTRY_SELECTED_FIB
))
343 rib_uninstall_kernel(rn
, re
);
348 /* Delete the nexthop and dereg from NHT */
349 nh_p
.family
= AF_INET
;
350 nh_p
.prefixlen
= IPV4_MAX_BITLEN
;
351 nh_p
.u
.prefix4
= nexthop
->gate
.ipv4
;
353 nh_p
.family
= AF_INET6
;
354 nh_p
.prefixlen
= IPV6_MAX_BITLEN
;
355 nh_p
.u
.prefix6
= nexthop
->gate
.ipv6
;
357 route_entry_nexthop_delete(re
, nexthop
);
358 zebra_deregister_rnh_static_nh(si
->vrf_id
, &nh_p
, rn
);
359 nexthop_free(nexthop
);
362 route_unlock_node(rn
);
365 int static_add_route(afi_t afi
, safi_t safi
, u_char type
, struct prefix
*p
,
366 struct prefix_ipv6
*src_p
, union g_addr
*gate
,
367 const char *ifname
, u_char flags
,
368 route_tag_t tag
, u_char distance
, struct zebra_vrf
*zvrf
,
369 struct static_nh_label
*snh_label
)
371 struct route_node
*rn
;
372 struct static_route
*si
;
373 struct static_route
*pp
;
374 struct static_route
*cp
;
375 struct static_route
*update
= NULL
;
376 struct route_table
*stable
= zvrf
->stable
[afi
][safi
];
382 && (type
== STATIC_IPV4_GATEWAY
383 || type
== STATIC_IPV4_GATEWAY_IFNAME
384 || type
== STATIC_IPV6_GATEWAY
385 || type
== STATIC_IPV6_GATEWAY_IFNAME
))
389 && (type
== STATIC_IFNAME
390 || type
== STATIC_IPV4_GATEWAY_IFNAME
391 || type
== STATIC_IPV6_GATEWAY_IFNAME
))
394 /* Lookup static route prefix. */
395 rn
= srcdest_rnode_get(stable
, p
, src_p
);
397 /* Do nothing if there is a same static route. */
398 for (si
= rn
->info
; si
; si
= si
->next
) {
400 && (!gate
|| ((afi
== AFI_IP
401 && IPV4_ADDR_SAME(gate
, &si
->addr
.ipv4
))
403 && IPV6_ADDR_SAME(gate
, &si
->addr
.ipv6
))))
404 && (!strcmp (ifname
? ifname
: "", si
->ifname
))) {
405 if ((distance
== si
->distance
) && (tag
== si
->tag
)
406 && !memcmp(&si
->snh_label
, snh_label
,
407 sizeof(struct static_nh_label
))
408 && si
->flags
== flags
) {
409 route_unlock_node(rn
);
416 /* Distance or tag or label changed, delete existing first. */
418 static_delete_route(afi
, safi
, type
, p
, src_p
, gate
, ifname
,
419 update
->tag
, update
->distance
, zvrf
,
422 /* Make new static route structure. */
423 si
= XCALLOC(MTYPE_STATIC_ROUTE
, sizeof(struct static_route
));
426 si
->distance
= distance
;
429 si
->vrf_id
= zvrf_id(zvrf
);
431 strlcpy(si
->ifname
, ifname
, sizeof(si
->ifname
));
432 si
->ifindex
= IFINDEX_INTERNAL
;
435 case STATIC_IPV4_GATEWAY
:
436 case STATIC_IPV4_GATEWAY_IFNAME
:
437 si
->addr
.ipv4
= gate
->ipv4
;
439 case STATIC_IPV6_GATEWAY
:
440 case STATIC_IPV6_GATEWAY_IFNAME
:
441 si
->addr
.ipv6
= gate
->ipv6
;
447 /* Save labels, if any. */
448 memcpy(&si
->snh_label
, snh_label
, sizeof(struct static_nh_label
));
450 /* Add new static route information to the tree with sort by
451 distance value and gateway address. */
452 for (pp
= NULL
, cp
= rn
->info
; cp
; pp
= cp
, cp
= cp
->next
) {
453 if (si
->distance
< cp
->distance
)
455 if (si
->distance
> cp
->distance
)
457 if (si
->type
== STATIC_IPV4_GATEWAY
458 && cp
->type
== STATIC_IPV4_GATEWAY
) {
459 if (ntohl(si
->addr
.ipv4
.s_addr
)
460 < ntohl(cp
->addr
.ipv4
.s_addr
))
462 if (ntohl(si
->addr
.ipv4
.s_addr
)
463 > ntohl(cp
->addr
.ipv4
.s_addr
))
468 /* Make linked list. */
478 /* check whether interface exists in system & install if it does */
480 static_install_route(afi
, safi
, p
, src_p
, si
);
482 struct interface
*ifp
;
484 ifp
= if_lookup_by_name(ifname
, zvrf_id(zvrf
));
485 if (ifp
&& ifp
->ifindex
!= IFINDEX_INTERNAL
) {
486 si
->ifindex
= ifp
->ifindex
;
487 static_install_route(afi
, safi
, p
, src_p
, si
);
494 int static_delete_route(afi_t afi
, safi_t safi
, u_char type
, struct prefix
*p
,
495 struct prefix_ipv6
*src_p
, union g_addr
*gate
,
496 const char *ifname
, route_tag_t tag
, u_char distance
,
497 struct zebra_vrf
*zvrf
,
498 struct static_nh_label
*snh_label
)
500 struct route_node
*rn
;
501 struct static_route
*si
;
502 struct route_table
*stable
;
505 stable
= zebra_vrf_static_table(afi
, safi
, zvrf
);
509 /* Lookup static route prefix. */
510 rn
= srcdest_rnode_lookup(stable
, p
, src_p
);
514 /* Find same static route is the tree */
515 for (si
= rn
->info
; si
; si
= si
->next
)
517 && (!gate
|| ((afi
== AFI_IP
518 && IPV4_ADDR_SAME(gate
, &si
->addr
.ipv4
))
520 && IPV6_ADDR_SAME(gate
, &si
->addr
.ipv6
))))
521 && (!strcmp(ifname
? ifname
: "", si
->ifname
))
522 && (!tag
|| (tag
== si
->tag
))
523 && (!snh_label
->num_labels
524 || !memcmp(&si
->snh_label
, snh_label
,
525 sizeof(struct static_nh_label
))))
528 /* Can't find static route. */
530 route_unlock_node(rn
);
534 /* Uninstall from rib. */
535 if (!si
->ifname
[0] || si
->ifindex
!= IFINDEX_INTERNAL
)
536 static_uninstall_route(afi
, safi
, p
, src_p
, si
);
538 /* Unlink static route from linked list. */
540 si
->prev
->next
= si
->next
;
544 si
->next
->prev
= si
->prev
;
545 route_unlock_node(rn
);
547 /* Free static route configuration. */
548 XFREE(MTYPE_STATIC_ROUTE
, si
);
550 route_unlock_node(rn
);
555 static void static_ifindex_update_af(struct interface
*ifp
, bool up
,
556 afi_t afi
, safi_t safi
)
558 struct route_table
*stable
;
559 struct zebra_vrf
*zvrf
= zebra_vrf_lookup_by_id(ifp
->vrf_id
);
560 struct route_node
*rn
;
561 struct static_route
*si
;
562 struct prefix
*p
, *src_pp
;
563 struct prefix_ipv6
*src_p
;
565 stable
= zebra_vrf_static_table(afi
, safi
, zvrf
);
569 for (rn
= route_top(stable
); rn
; rn
= srcdest_route_next(rn
)) {
570 srcdest_rnode_prefixes(rn
, &p
, &src_pp
);
571 src_p
= (struct prefix_ipv6
*)src_pp
;
573 for (si
= rn
->info
; si
; si
= si
->next
) {
577 if (strcmp(si
->ifname
, ifp
->name
))
579 si
->ifindex
= ifp
->ifindex
;
580 static_install_route(afi
, safi
, p
, src_p
, si
);
582 if (si
->ifindex
!= ifp
->ifindex
)
584 static_uninstall_route(afi
, safi
, p
, src_p
,
586 si
->ifindex
= IFINDEX_INTERNAL
;
592 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
593 void static_ifindex_update(struct interface
*ifp
, bool up
)
595 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_UNICAST
);
596 static_ifindex_update_af(ifp
, up
, AFI_IP
, SAFI_MULTICAST
);
597 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_UNICAST
);
598 static_ifindex_update_af(ifp
, up
, AFI_IP6
, SAFI_MULTICAST
);