1 /* Zebra Nexthop Group Code.
2 * Copyright (C) 2019 Cumulus Networks, Inc.
6 * This file is part of FRR.
8 * FRR 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 * FRR 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
19 * along with FRR; see the file COPYING. If not, write to the Free
20 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 #include "lib/nexthop.h"
26 #include "lib/routemap.h"
28 #include "zebra/connected.h"
29 #include "zebra/debug.h"
30 #include "zebra/zebra_router.h"
31 #include "zebra/zebra_nhg.h"
32 #include "zebra/zebra_rnh.h"
33 #include "zebra/zebra_routemap.h"
36 static void nexthop_set_resolved(afi_t afi
, const struct nexthop
*newhop
,
37 struct nexthop
*nexthop
)
39 struct nexthop
*resolved_hop
;
41 resolved_hop
= nexthop_new();
42 SET_FLAG(resolved_hop
->flags
, NEXTHOP_FLAG_ACTIVE
);
44 resolved_hop
->vrf_id
= nexthop
->vrf_id
;
45 switch (newhop
->type
) {
46 case NEXTHOP_TYPE_IPV4
:
47 case NEXTHOP_TYPE_IPV4_IFINDEX
:
48 /* If the resolving route specifies a gateway, use it */
49 resolved_hop
->type
= newhop
->type
;
50 resolved_hop
->gate
.ipv4
= newhop
->gate
.ipv4
;
52 if (newhop
->ifindex
) {
53 resolved_hop
->type
= NEXTHOP_TYPE_IPV4_IFINDEX
;
54 resolved_hop
->ifindex
= newhop
->ifindex
;
57 case NEXTHOP_TYPE_IPV6
:
58 case NEXTHOP_TYPE_IPV6_IFINDEX
:
59 resolved_hop
->type
= newhop
->type
;
60 resolved_hop
->gate
.ipv6
= newhop
->gate
.ipv6
;
62 if (newhop
->ifindex
) {
63 resolved_hop
->type
= NEXTHOP_TYPE_IPV6_IFINDEX
;
64 resolved_hop
->ifindex
= newhop
->ifindex
;
67 case NEXTHOP_TYPE_IFINDEX
:
68 /* If the resolving route is an interface route,
69 * it means the gateway we are looking up is connected
70 * to that interface. (The actual network is _not_ onlink).
71 * Therefore, the resolved route should have the original
72 * gateway as nexthop as it is directly connected.
74 * On Linux, we have to set the onlink netlink flag because
75 * otherwise, the kernel won't accept the route.
77 resolved_hop
->flags
|= NEXTHOP_FLAG_ONLINK
;
79 resolved_hop
->type
= NEXTHOP_TYPE_IPV4_IFINDEX
;
80 resolved_hop
->gate
.ipv4
= nexthop
->gate
.ipv4
;
81 } else if (afi
== AFI_IP6
) {
82 resolved_hop
->type
= NEXTHOP_TYPE_IPV6_IFINDEX
;
83 resolved_hop
->gate
.ipv6
= nexthop
->gate
.ipv6
;
85 resolved_hop
->ifindex
= newhop
->ifindex
;
87 case NEXTHOP_TYPE_BLACKHOLE
:
88 resolved_hop
->type
= NEXTHOP_TYPE_BLACKHOLE
;
89 resolved_hop
->bh_type
= nexthop
->bh_type
;
93 if (newhop
->flags
& NEXTHOP_FLAG_ONLINK
)
94 resolved_hop
->flags
|= NEXTHOP_FLAG_ONLINK
;
96 /* Copy labels of the resolved route */
98 nexthop_add_labels(resolved_hop
, newhop
->nh_label_type
,
99 newhop
->nh_label
->num_labels
,
100 &newhop
->nh_label
->label
[0]);
102 resolved_hop
->rparent
= nexthop
;
103 nexthop_add(&nexthop
->resolved
, resolved_hop
);
107 * Given a nexthop we need to properly recursively resolve
108 * the route. As such, do a table lookup to find and match
109 * if at all possible. Set the nexthop->ifindex as appropriate
111 static int nexthop_active(afi_t afi
, struct route_entry
*re
,
112 struct nexthop
*nexthop
, struct route_node
*top
)
115 struct route_table
*table
;
116 struct route_node
*rn
;
117 struct route_entry
*match
= NULL
;
119 struct nexthop
*newhop
;
120 struct interface
*ifp
;
123 if ((nexthop
->type
== NEXTHOP_TYPE_IPV4
)
124 || nexthop
->type
== NEXTHOP_TYPE_IPV6
)
125 nexthop
->ifindex
= 0;
127 UNSET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
);
128 nexthops_free(nexthop
->resolved
);
129 nexthop
->resolved
= NULL
;
133 * If the kernel has sent us a route, then
134 * by golly gee whiz it's a good route.
136 if (re
->type
== ZEBRA_ROUTE_KERNEL
|| re
->type
== ZEBRA_ROUTE_SYSTEM
)
140 * Check to see if we should trust the passed in information
141 * for UNNUMBERED interfaces as that we won't find the GW
142 * address in the routing table.
143 * This check should suffice to handle IPv4 or IPv6 routes
144 * sourced from EVPN routes which are installed with the
145 * next hop as the remote VTEP IP.
147 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
)) {
148 ifp
= if_lookup_by_index(nexthop
->ifindex
, nexthop
->vrf_id
);
150 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
152 "\t%s: Onlink and interface: %u[%u] does not exist",
153 __PRETTY_FUNCTION__
, nexthop
->ifindex
,
157 if (connected_is_unnumbered(ifp
)) {
158 if (if_is_operative(ifp
))
161 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
163 "\t%s: Onlink and interface %s is not operative",
164 __PRETTY_FUNCTION__
, ifp
->name
);
168 if (!if_is_operative(ifp
)) {
169 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
171 "\t%s: Interface %s is not unnumbered",
172 __PRETTY_FUNCTION__
, ifp
->name
);
177 /* Make lookup prefix. */
178 memset(&p
, 0, sizeof(struct prefix
));
182 p
.prefixlen
= IPV4_MAX_PREFIXLEN
;
183 p
.u
.prefix4
= nexthop
->gate
.ipv4
;
187 p
.prefixlen
= IPV6_MAX_PREFIXLEN
;
188 p
.u
.prefix6
= nexthop
->gate
.ipv6
;
191 assert(afi
!= AFI_IP
&& afi
!= AFI_IP6
);
195 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, nexthop
->vrf_id
);
197 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
198 zlog_debug("\t%s: Table not found",
199 __PRETTY_FUNCTION__
);
203 rn
= route_node_match(table
, (struct prefix
*)&p
);
205 route_unlock_node(rn
);
207 /* Lookup should halt if we've matched against ourselves ('top',
208 * if specified) - i.e., we cannot have a nexthop NH1 is
209 * resolved by a route NH1. The exception is if the route is a
212 if (top
&& rn
== top
)
213 if (((afi
== AFI_IP
) && (rn
->p
.prefixlen
!= 32))
214 || ((afi
== AFI_IP6
) && (rn
->p
.prefixlen
!= 128))) {
215 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
217 "\t%s: Matched against ourself and prefix length is not max bit length",
218 __PRETTY_FUNCTION__
);
222 /* Pick up selected route. */
223 /* However, do not resolve over default route unless explicitly
225 if (is_default_prefix(&rn
->p
)
226 && !rnh_resolve_via_default(p
.family
)) {
227 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
229 "\t:%s: Resolved against default route",
230 __PRETTY_FUNCTION__
);
234 dest
= rib_dest_from_rnode(rn
);
235 if (dest
&& dest
->selected_fib
236 && !CHECK_FLAG(dest
->selected_fib
->status
,
238 && dest
->selected_fib
->type
!= ZEBRA_ROUTE_TABLE
)
239 match
= dest
->selected_fib
;
241 /* If there is no selected route or matched route is EGP, go up
246 } while (rn
&& rn
->info
== NULL
);
253 if (match
->type
== ZEBRA_ROUTE_CONNECT
) {
254 /* Directly point connected route. */
255 newhop
= match
->ng
.nexthop
;
257 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
258 || nexthop
->type
== NEXTHOP_TYPE_IPV6
)
259 nexthop
->ifindex
= newhop
->ifindex
;
262 } else if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_ALLOW_RECURSION
)) {
264 for (ALL_NEXTHOPS(match
->ng
, newhop
)) {
265 if (!CHECK_FLAG(match
->status
,
266 ROUTE_ENTRY_INSTALLED
))
268 if (CHECK_FLAG(newhop
->flags
,
269 NEXTHOP_FLAG_RECURSIVE
))
272 SET_FLAG(nexthop
->flags
,
273 NEXTHOP_FLAG_RECURSIVE
);
275 ROUTE_ENTRY_NEXTHOPS_CHANGED
);
276 nexthop_set_resolved(afi
, newhop
, nexthop
);
280 re
->nexthop_mtu
= match
->mtu
;
281 if (!resolved
&& IS_ZEBRA_DEBUG_RIB_DETAILED
)
282 zlog_debug("\t%s: Recursion failed to find",
283 __PRETTY_FUNCTION__
);
285 } else if (re
->type
== ZEBRA_ROUTE_STATIC
) {
287 for (ALL_NEXTHOPS(match
->ng
, newhop
)) {
288 if (!CHECK_FLAG(match
->status
,
289 ROUTE_ENTRY_INSTALLED
))
291 if (CHECK_FLAG(newhop
->flags
,
292 NEXTHOP_FLAG_RECURSIVE
))
295 SET_FLAG(nexthop
->flags
,
296 NEXTHOP_FLAG_RECURSIVE
);
297 nexthop_set_resolved(afi
, newhop
, nexthop
);
301 re
->nexthop_mtu
= match
->mtu
;
303 if (!resolved
&& IS_ZEBRA_DEBUG_RIB_DETAILED
)
305 "\t%s: Static route unable to resolve",
306 __PRETTY_FUNCTION__
);
309 if (IS_ZEBRA_DEBUG_RIB_DETAILED
) {
311 "\t%s: Route Type %s has not turned on recursion",
313 zebra_route_string(re
->type
));
314 if (re
->type
== ZEBRA_ROUTE_BGP
315 && !CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
))
317 "\tEBGP: see \"disable-ebgp-connected-route-check\" or \"disable-connected-check\"");
322 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
323 zlog_debug("\t%s: Nexthop did not lookup in table",
324 __PRETTY_FUNCTION__
);
328 /* This function verifies reachability of one given nexthop, which can be
329 * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored
330 * in nexthop->flags field. The nexthop->ifindex will be updated
331 * appropriately as well. An existing route map can turn
332 * (otherwise active) nexthop into inactive, but not vice versa.
334 * The return value is the final value of 'ACTIVE' flag.
336 static unsigned nexthop_active_check(struct route_node
*rn
,
337 struct route_entry
*re
,
338 struct nexthop
*nexthop
)
340 struct interface
*ifp
;
341 route_map_result_t ret
= RMAP_PERMITMATCH
;
343 char buf
[SRCDEST2STR_BUFFER
];
344 const struct prefix
*p
, *src_p
;
345 struct zebra_vrf
*zvrf
;
347 srcdest_rnode_prefixes(rn
, &p
, &src_p
);
349 if (rn
->p
.family
== AF_INET
)
351 else if (rn
->p
.family
== AF_INET6
)
355 switch (nexthop
->type
) {
356 case NEXTHOP_TYPE_IFINDEX
:
357 ifp
= if_lookup_by_index(nexthop
->ifindex
, nexthop
->vrf_id
);
358 if (ifp
&& if_is_operative(ifp
))
359 SET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
361 UNSET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
363 case NEXTHOP_TYPE_IPV4
:
364 case NEXTHOP_TYPE_IPV4_IFINDEX
:
366 if (nexthop_active(AFI_IP
, re
, nexthop
, rn
))
367 SET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
369 UNSET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
371 case NEXTHOP_TYPE_IPV6
:
373 if (nexthop_active(AFI_IP6
, re
, nexthop
, rn
))
374 SET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
376 UNSET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
378 case NEXTHOP_TYPE_IPV6_IFINDEX
:
379 /* RFC 5549, v4 prefix with v6 NH */
380 if (rn
->p
.family
!= AF_INET
)
382 if (IN6_IS_ADDR_LINKLOCAL(&nexthop
->gate
.ipv6
)) {
383 ifp
= if_lookup_by_index(nexthop
->ifindex
,
385 if (ifp
&& if_is_operative(ifp
))
386 SET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
388 UNSET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
390 if (nexthop_active(AFI_IP6
, re
, nexthop
, rn
))
391 SET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
393 UNSET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
396 case NEXTHOP_TYPE_BLACKHOLE
:
397 SET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
402 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
)) {
403 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
404 zlog_debug("\t%s: Unable to find a active nexthop",
405 __PRETTY_FUNCTION__
);
409 /* XXX: What exactly do those checks do? Do we support
410 * e.g. IPv4 routes with IPv6 nexthops or vice versa?
412 if (RIB_SYSTEM_ROUTE(re
) || (family
== AFI_IP
&& p
->family
!= AF_INET
)
413 || (family
== AFI_IP6
&& p
->family
!= AF_INET6
))
414 return CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
416 /* The original code didn't determine the family correctly
417 * e.g. for NEXTHOP_TYPE_IFINDEX. Retrieve the correct afi
418 * from the rib_table_info in those cases.
419 * Possibly it may be better to use only the rib_table_info
423 rib_table_info_t
*info
;
425 info
= srcdest_rnode_table_info(rn
);
429 memset(&nexthop
->rmap_src
.ipv6
, 0, sizeof(union g_addr
));
431 zvrf
= zebra_vrf_lookup_by_id(nexthop
->vrf_id
);
433 if (IS_ZEBRA_DEBUG_RIB_DETAILED
)
434 zlog_debug("\t%s: zvrf is NULL", __PRETTY_FUNCTION__
);
435 return CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
438 /* It'll get set if required inside */
439 ret
= zebra_route_map_check(family
, re
->type
, re
->instance
, p
, nexthop
,
441 if (ret
== RMAP_DENYMATCH
) {
442 if (IS_ZEBRA_DEBUG_RIB
) {
443 srcdest_rnode2str(rn
, buf
, sizeof(buf
));
445 "%u:%s: Filtering out with NH out %s due to route map",
447 ifindex2ifname(nexthop
->ifindex
,
450 UNSET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
452 return CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
456 * Iterate over all nexthops of the given RIB entry and refresh their
457 * ACTIVE flag. re->nexthop_active_num is updated accordingly. If any
458 * nexthop is found to toggle the ACTIVE flag, the whole re structure
459 * is flagged with ROUTE_ENTRY_CHANGED.
461 * Return value is the new number of active nexthops.
463 int nexthop_active_update(struct route_node
*rn
, struct route_entry
*re
)
465 struct nexthop
*nexthop
;
466 union g_addr prev_src
;
467 unsigned int prev_active
, new_active
;
468 ifindex_t prev_index
;
470 re
->nexthop_active_num
= 0;
471 UNSET_FLAG(re
->status
, ROUTE_ENTRY_CHANGED
);
473 for (nexthop
= re
->ng
.nexthop
; nexthop
; nexthop
= nexthop
->next
) {
474 /* No protocol daemon provides src and so we're skipping
476 prev_src
= nexthop
->rmap_src
;
477 prev_active
= CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
478 prev_index
= nexthop
->ifindex
;
480 * We need to respect the multipath_num here
481 * as that what we should be able to install from
482 * a multipath perpsective should not be a data plane
485 new_active
= nexthop_active_check(rn
, re
, nexthop
);
487 && re
->nexthop_active_num
>= zrouter
.multipath_num
) {
488 UNSET_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
);
492 re
->nexthop_active_num
++;
493 /* Don't allow src setting on IPv6 addr for now */
494 if (prev_active
!= new_active
|| prev_index
!= nexthop
->ifindex
495 || ((nexthop
->type
>= NEXTHOP_TYPE_IFINDEX
496 && nexthop
->type
< NEXTHOP_TYPE_IPV6
)
497 && prev_src
.ipv4
.s_addr
498 != nexthop
->rmap_src
.ipv4
.s_addr
)
499 || ((nexthop
->type
>= NEXTHOP_TYPE_IPV6
500 && nexthop
->type
< NEXTHOP_TYPE_BLACKHOLE
)
501 && !(IPV6_ADDR_SAME(&prev_src
.ipv6
,
502 &nexthop
->rmap_src
.ipv6
)))
503 || CHECK_FLAG(re
->status
, ROUTE_ENTRY_LABELS_CHANGED
)) {
504 SET_FLAG(re
->status
, ROUTE_ENTRY_CHANGED
);
505 SET_FLAG(re
->status
, ROUTE_ENTRY_NEXTHOPS_CHANGED
);
509 return re
->nexthop_active_num
;