4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 1990 Mentat Inc.
27 * This file contains routines that manipulate Internet Routing Entries (IREs).
29 #include <sys/types.h>
30 #include <sys/stream.h>
31 #include <sys/stropts.h>
33 #include <sys/cmn_err.h>
35 #include <sys/systm.h>
36 #include <sys/param.h>
37 #include <sys/socket.h>
39 #include <net/route.h>
40 #include <netinet/in.h>
41 #include <net/if_dl.h>
42 #include <netinet/ip6.h>
43 #include <netinet/icmp6.h>
45 #include <inet/common.h>
49 #include <inet/ip_ndp.h>
50 #include <inet/ip_if.h>
51 #include <inet/ip_ire.h>
52 #include <inet/ipclassifier.h>
54 #include <inet/tunables.h>
58 #include <sys/tsol/label.h>
59 #include <sys/tsol/tnet.h>
61 #define IS_DEFAULT_ROUTE_V6(ire) \
62 (((ire)->ire_type & IRE_DEFAULT) || \
63 (((ire)->ire_type & IRE_INTERFACE) && \
64 (IN6_IS_ADDR_UNSPECIFIED(&(ire)->ire_addr_v6))))
66 static ire_t ire_null
;
69 ire_ftable_lookup_impl_v6(const in6_addr_t
*addr
, const in6_addr_t
*mask
,
70 const in6_addr_t
*gateway
, int type
, const ill_t
*ill
,
71 zoneid_t zoneid
, const ts_label_t
*tsl
, int flags
,
75 * Initialize the ire that is specific to IPv6 part and call
76 * ire_init_common to finish it.
77 * Returns zero or errno.
80 ire_init_v6(ire_t
*ire
, const in6_addr_t
*v6addr
, const in6_addr_t
*v6mask
,
81 const in6_addr_t
*v6gateway
, ushort_t type
, ill_t
*ill
,
82 zoneid_t zoneid
, uint_t flags
, tsol_gc_t
*gc
, ip_stack_t
*ipst
)
87 * Reject IRE security attmakeribute creation/initialization
88 * if system is not running in Trusted mode.
90 if (gc
!= NULL
&& !is_system_labeled())
93 BUMP_IRE_STATS(ipst
->ips_ire_stats_v6
, ire_stats_alloced
);
95 ire
->ire_addr_v6
= *v6addr
;
96 if (v6gateway
!= NULL
)
97 ire
->ire_gateway_addr_v6
= *v6gateway
;
99 /* Make sure we don't have stray values in some fields */
105 ire
->ire_mask_v6
= ipv6_all_ones
;
106 ire
->ire_masklen
= IPV6_ABITS
;
110 case IRE_IF_RESOLVER
:
111 case IRE_IF_NORESOLVER
:
112 if (v6mask
!= NULL
) {
113 ire
->ire_mask_v6
= *v6mask
;
115 ip_mask_to_plen_v6(&ire
->ire_mask_v6
);
120 ASSERT(v6mask
== NULL
);
127 error
= ire_init_common(ire
, type
, ill
, zoneid
, flags
, IPV6_VERSION
,
132 /* Determine which function pointers to use */
133 ire
->ire_postfragfn
= ip_xmit
; /* Common case */
135 switch (ire
->ire_type
) {
137 ire
->ire_sendfn
= ire_send_local_v6
;
138 ire
->ire_recvfn
= ire_recv_local_v6
;
139 ASSERT(ire
->ire_ill
!= NULL
);
140 if (ire
->ire_ill
->ill_flags
& ILLF_NOACCEPT
)
141 ire
->ire_recvfn
= ire_recv_noaccept_v6
;
144 ire
->ire_sendfn
= ire_send_local_v6
;
145 ire
->ire_recvfn
= ire_recv_loopback_v6
;
148 ire
->ire_postfragfn
= ip_postfrag_loopcheck
;
149 ire
->ire_sendfn
= ire_send_multicast_v6
;
150 ire
->ire_recvfn
= ire_recv_multicast_v6
;
154 * For IRE_IF_ALL and IRE_OFFLINK we forward received
155 * packets by default.
157 ire
->ire_sendfn
= ire_send_wire_v6
;
158 ire
->ire_recvfn
= ire_recv_forward_v6
;
161 if (ire
->ire_flags
& (RTF_REJECT
|RTF_BLACKHOLE
)) {
162 ire
->ire_sendfn
= ire_send_noroute_v6
;
163 ire
->ire_recvfn
= ire_recv_noroute_v6
;
164 } else if (ire
->ire_flags
& RTF_MULTIRT
) {
165 ire
->ire_postfragfn
= ip_postfrag_multirt_v6
;
166 ire
->ire_sendfn
= ire_send_multirt_v6
;
167 ire
->ire_recvfn
= ire_recv_multirt_v6
;
169 ire
->ire_nce_capable
= ire_determine_nce_capable(ire
);
174 * ire_create_v6 is called to allocate and initialize a new IRE.
176 * NOTE : This is called as writer sometimes though not required
181 ire_create_v6(const in6_addr_t
*v6addr
, const in6_addr_t
*v6mask
,
182 const in6_addr_t
*v6gateway
, ushort_t type
, ill_t
*ill
, zoneid_t zoneid
,
183 uint_t flags
, tsol_gc_t
*gc
, ip_stack_t
*ipst
)
188 ASSERT(!IN6_IS_ADDR_V4MAPPED(v6addr
));
190 ire
= kmem_cache_alloc(ire_cache
, KM_NOSLEEP
);
192 DTRACE_PROBE(kmem__cache__alloc
);
197 error
= ire_init_v6(ire
, v6addr
, v6mask
, v6gateway
,
198 type
, ill
, zoneid
, flags
, gc
, ipst
);
201 DTRACE_PROBE2(ire__init__v6
, ire_t
*, ire
, int, error
);
202 kmem_cache_free(ire_cache
, ire
);
209 * Find the ill matching a multicast group.
210 * Allows different routes for multicast addresses
211 * in the unicast routing table (akin to FF::0/8 but could be more specific)
212 * which point at different interfaces. This is used when IPV6_MULTICAST_IF
213 * isn't specified (when sending) and when IPV6_JOIN_GROUP doesn't
214 * specify the interface to join on.
216 * Supports link-local addresses by using ire_route_recursive which follows
217 * the ill when recursing.
219 * To handle CGTP, since we don't have a separate IRE_MULTICAST for each group
220 * and the MULTIRT property can be different for different groups, we
221 * extract RTF_MULTIRT from the special unicast route added for a group
222 * with CGTP and pass that back in the multirtp argument.
223 * This is used in ip_set_destination etc to set ixa_postfragfn for multicast.
224 * We have a setsrcp argument for the same reason.
227 ire_lookup_multi_ill_v6(const in6_addr_t
*group
, zoneid_t zoneid
,
228 ip_stack_t
*ipst
, boolean_t
*multirtp
, in6_addr_t
*setsrcp
)
233 ire
= ire_route_recursive_v6(group
, 0, NULL
, zoneid
, NULL
,
234 MATCH_IRE_DSTONLY
, IRR_NONE
, 0, ipst
, setsrcp
, NULL
, NULL
);
237 if (ire
->ire_flags
& (RTF_REJECT
|RTF_BLACKHOLE
)) {
242 if (multirtp
!= NULL
)
243 *multirtp
= (ire
->ire_flags
& RTF_MULTIRT
) != 0;
245 ill
= ire_nexthop_ill(ire
);
251 * This function takes a mask and returns number of bits set in the
252 * mask (the represented prefix length). Assumes a contiguous mask.
255 ip_mask_to_plen_v6(const in6_addr_t
*v6mask
)
258 int plen
= IPV6_ABITS
;
261 for (i
= 3; i
>= 0; i
--) {
262 if (v6mask
->s6_addr32
[i
] == 0) {
266 bits
= ffs(ntohl(v6mask
->s6_addr32
[i
])) - 1;
276 * Convert a prefix length to the mask for that prefix.
277 * Returns the argument bitmask.
280 ip_plen_to_mask_v6(uint_t plen
, in6_addr_t
*bitmask
)
284 if (plen
< 0 || plen
> IPV6_ABITS
)
286 *bitmask
= ipv6_all_zeros
;
290 ptr
= (uint32_t *)bitmask
;
292 *ptr
++ = 0xffffffffU
;
295 *ptr
= htonl(0xffffffffU
<< (32 - plen
));
300 * Add a fully initialized IPv6 IRE to the forwarding table.
301 * This returns NULL on failure, or a held IRE on success.
302 * Normally the returned IRE is the same as the argument. But a different
303 * IRE will be returned if the added IRE is deemed identical to an existing
304 * one. In that case ire_identical_ref will be increased.
305 * The caller always needs to do an ire_refrele() on the returned IRE.
308 ire_add_v6(ire_t
*ire
)
311 int mask_table_index
;
316 ip_stack_t
*ipst
= ire
->ire_ipst
;
318 ASSERT(ire
->ire_ipversion
== IPV6_VERSION
);
320 /* Make sure the address is properly masked. */
321 V6_MASK_COPY(ire
->ire_addr_v6
, ire
->ire_mask_v6
, ire
->ire_addr_v6
);
323 mask_table_index
= ip_mask_to_plen_v6(&ire
->ire_mask_v6
);
324 if ((ipst
->ips_ip_forwarding_table_v6
[mask_table_index
]) == NULL
) {
328 ptr
= (irb_t
*)mi_zalloc((ipst
->ips_ip6_ftable_hash_size
*
334 for (i
= 0; i
< ipst
->ips_ip6_ftable_hash_size
; i
++) {
335 rw_init(&ptr
[i
].irb_lock
, NULL
, RW_DEFAULT
, NULL
);
336 ptr
[i
].irb_ipst
= ipst
;
338 mutex_enter(&ipst
->ips_ire_ft_init_lock
);
339 if (ipst
->ips_ip_forwarding_table_v6
[mask_table_index
] ==
341 ipst
->ips_ip_forwarding_table_v6
[mask_table_index
] =
343 mutex_exit(&ipst
->ips_ire_ft_init_lock
);
346 * Some other thread won the race in
347 * initializing the forwarding table at the
350 mutex_exit(&ipst
->ips_ire_ft_init_lock
);
351 for (i
= 0; i
< ipst
->ips_ip6_ftable_hash_size
; i
++) {
352 rw_destroy(&ptr
[i
].irb_lock
);
357 irb_ptr
= &(ipst
->ips_ip_forwarding_table_v6
[mask_table_index
][
358 IRE_ADDR_MASK_HASH_V6(ire
->ire_addr_v6
, ire
->ire_mask_v6
,
359 ipst
->ips_ip6_ftable_hash_size
)]);
361 match_flags
= (MATCH_IRE_MASK
| MATCH_IRE_TYPE
| MATCH_IRE_GW
);
362 if (ire
->ire_ill
!= NULL
)
363 match_flags
|= MATCH_IRE_ILL
;
365 * Start the atomic add of the ire. Grab the bucket lock and the
366 * ill lock. Check for condemned.
368 error
= ire_atomic_start(irb_ptr
, ire
);
375 * If we are creating a hidden IRE, make sure we search for
376 * hidden IREs when searching for duplicates below.
377 * Otherwise, we might find an IRE on some other interface
378 * that's not marked hidden.
380 if (ire
->ire_testhidden
)
381 match_flags
|= MATCH_IRE_TESTHIDDEN
;
384 * Atomically check for duplicate and insert in the table.
386 for (ire1
= irb_ptr
->irb_ire
; ire1
!= NULL
; ire1
= ire1
->ire_next
) {
387 if (IRE_IS_CONDEMNED(ire1
))
390 * Here we need an exact match on zoneid, i.e.,
391 * ire_match_args doesn't fit.
393 if (ire1
->ire_zoneid
!= ire
->ire_zoneid
)
396 if (ire1
->ire_type
!= ire
->ire_type
)
400 * Note: We do not allow multiple routes that differ only
401 * in the gateway security attributes; such routes are
402 * considered duplicates.
403 * To change that we explicitly have to treat them as
406 if (ire_match_args_v6(ire1
, &ire
->ire_addr_v6
,
407 &ire
->ire_mask_v6
, &ire
->ire_gateway_addr_v6
,
408 ire
->ire_type
, ire
->ire_ill
, ire
->ire_zoneid
, NULL
,
411 * Return the old ire after doing a REFHOLD.
412 * As most of the callers continue to use the IRE
413 * after adding, we return a held ire. This will
414 * avoid a lookup in the caller again. If the callers
415 * don't want to use it, they need to do a REFRELE.
417 * We only allow exactly one IRE_IF_CLONE for any dst,
418 * so, if the is an IF_CLONE, return the ire without
419 * an identical_ref, but with an ire_ref held.
421 if (ire
->ire_type
!= IRE_IF_CLONE
) {
422 atomic_add_32(&ire1
->ire_identical_ref
, 1);
423 DTRACE_PROBE2(ire__add__exist
, ire_t
*, ire1
,
426 ip1dbg(("found dup ire existing %p new %p",
427 (void *)ire1
, (void *)ire
));
429 ire_atomic_end(irb_ptr
, ire
);
436 * Normally we do head insertion since most things do not care about
437 * the order of the IREs in the bucket.
438 * However, due to shared-IP zones (and restrict_interzone_loopback)
439 * we can have an IRE_LOCAL as well as IRE_IF_CLONE for the same
440 * address. For that reason we do tail insertion for IRE_IF_CLONE.
442 irep
= (ire_t
**)irb_ptr
;
443 if (ire
->ire_type
& IRE_IF_CLONE
) {
444 while ((ire1
= *irep
) != NULL
)
445 irep
= &ire1
->ire_next
;
447 /* Insert at *irep */
450 ire1
->ire_ptpn
= &ire
->ire_next
;
451 ire
->ire_next
= ire1
;
452 /* Link the new one in. */
453 ire
->ire_ptpn
= irep
;
455 * ire_walk routines de-reference ire_next without holding
456 * a lock. Before we point to the new ire, we want to make
457 * sure the store that sets the ire_next of the new ire
458 * reaches global visibility, so that ire_walk routines
459 * don't see a truncated list of ires i.e if the ire_next
460 * of the new ire gets set after we do "*irep = ire" due
461 * to re-ordering, the ire_walk thread will see a NULL
462 * once it accesses the ire_next of the new ire.
463 * membar_producer() makes sure that the following store
464 * happens *after* all of the above stores.
468 ire
->ire_bucket
= irb_ptr
;
470 * We return a bumped up IRE above. Keep it symmetrical
471 * so that the callers will always have to release. This
472 * helps the callers of this function because they continue
473 * to use the IRE after adding and hence they don't have to
474 * lookup again after we return the IRE.
476 * NOTE : We don't have to use atomics as this is appearing
477 * in the list for the first time and no one else can bump
478 * up the reference count on this yet.
480 ire_refhold_locked(ire
);
481 BUMP_IRE_STATS(ipst
->ips_ire_stats_v6
, ire_stats_inserted
);
482 irb_ptr
->irb_ire_cnt
++;
484 if (ire
->ire_ill
!= NULL
) {
485 DTRACE_PROBE3(ill__incr__cnt
, (ill_t
*), ire
->ire_ill
,
486 (char *), "ire", (void *), ire
);
487 ire
->ire_ill
->ill_ire_cnt
++;
488 ASSERT(ire
->ire_ill
->ill_ire_cnt
!= 0); /* Wraparound */
490 ire_atomic_end(irb_ptr
, ire
);
492 /* Make any caching of the IREs be notified or updated */
493 ire_flush_cache_v6(ire
, IRE_FLUSH_ADD
);
499 * Search for all HOST REDIRECT routes that are
500 * pointing at the specified gateway and
501 * delete them. This routine is called only
502 * when a default gateway is going away.
505 ire_delete_host_redirects_v6(const in6_addr_t
*gateway
, ip_stack_t
*ipst
)
510 in6_addr_t gw_addr_v6
;
513 /* get the hash table for HOST routes */
514 irb_ptr
= ipst
->ips_ip_forwarding_table_v6
[(IP6_MASK_TABLE_SIZE
- 1)];
517 for (i
= 0; (i
< ipst
->ips_ip6_ftable_hash_size
); i
++) {
520 for (ire
= irb
->irb_ire
; ire
!= NULL
; ire
= ire
->ire_next
) {
521 if (!(ire
->ire_flags
& RTF_DYNAMIC
))
523 mutex_enter(&ire
->ire_lock
);
524 gw_addr_v6
= ire
->ire_gateway_addr_v6
;
525 mutex_exit(&ire
->ire_lock
);
526 if (IN6_ARE_ADDR_EQUAL(&gw_addr_v6
, gateway
))
534 * Delete the specified IRE.
535 * All calls should use ire_delete().
536 * Sometimes called as writer though not required by this function.
538 * NOTE : This function is called only if the ire was added
542 ire_delete_v6(ire_t
*ire
)
544 in6_addr_t gw_addr_v6
;
545 ip_stack_t
*ipst
= ire
->ire_ipst
;
548 * Make sure ire_generation increases from ire_flush_cache happen
549 * after any lookup/reader has read ire_generation.
550 * Since the rw_enter makes us wait until any lookup/reader has
551 * completed we can exit the lock immediately.
553 rw_enter(&ipst
->ips_ip6_ire_head_lock
, RW_WRITER
);
554 rw_exit(&ipst
->ips_ip6_ire_head_lock
);
556 ASSERT(ire
->ire_refcnt
>= 1);
557 ASSERT(ire
->ire_ipversion
== IPV6_VERSION
);
559 ire_flush_cache_v6(ire
, IRE_FLUSH_DELETE
);
561 if (ire
->ire_type
== IRE_DEFAULT
) {
563 * when a default gateway is going away
564 * delete all the host redirects pointing at that
567 mutex_enter(&ire
->ire_lock
);
568 gw_addr_v6
= ire
->ire_gateway_addr_v6
;
569 mutex_exit(&ire
->ire_lock
);
570 ire_delete_host_redirects_v6(&gw_addr_v6
, ipst
);
574 * If we are deleting an IRE_INTERFACE then we make sure we also
575 * delete any IRE_IF_CLONE that has been created from it.
576 * Those are always in ire_dep_children.
578 if ((ire
->ire_type
& IRE_INTERFACE
) && ire
->ire_dep_children
!= 0)
579 ire_dep_delete_if_clone(ire
);
581 /* Remove from parent dependencies and child */
582 rw_enter(&ipst
->ips_ire_dep_lock
, RW_WRITER
);
583 if (ire
->ire_dep_parent
!= NULL
) {
586 while (ire
->ire_dep_children
!= NULL
)
587 ire_dep_remove(ire
->ire_dep_children
);
588 rw_exit(&ipst
->ips_ire_dep_lock
);
592 * When an IRE is added or deleted this routine is called to make sure
593 * any caching of IRE information is notified or updated.
595 * The flag argument indicates if the flush request is due to addition
596 * of new route (IRE_FLUSH_ADD), deletion of old route (IRE_FLUSH_DELETE),
597 * or a change to ire_gateway_addr (IRE_FLUSH_GWCHANGE).
600 ire_flush_cache_v6(ire_t
*ire
, int flag
)
602 ip_stack_t
*ipst
= ire
->ire_ipst
;
605 * IRE_IF_CLONE ire's don't provide any new information
606 * than the parent from which they are cloned, so don't
607 * perturb the generation numbers.
609 if (ire
->ire_type
& IRE_IF_CLONE
)
613 * Ensure that an ire_add during a lookup serializes the updates of
614 * the generation numbers under ire_head_lock so that the lookup gets
615 * either the old ire and old generation number, or a new ire and new
618 rw_enter(&ipst
->ips_ip6_ire_head_lock
, RW_WRITER
);
621 * If a route was just added, we need to notify everybody that
622 * has cached an IRE_NOROUTE since there might now be a better
625 if (flag
== IRE_FLUSH_ADD
) {
626 ire_increment_generation(ipst
->ips_ire_reject_v6
);
627 ire_increment_generation(ipst
->ips_ire_blackhole_v6
);
630 /* Adding a default can't otherwise provide a better route */
631 if (ire
->ire_type
== IRE_DEFAULT
&& flag
== IRE_FLUSH_ADD
) {
632 rw_exit(&ipst
->ips_ip6_ire_head_lock
);
637 case IRE_FLUSH_DELETE
:
638 case IRE_FLUSH_GWCHANGE
:
640 * Update ire_generation for all ire_dep_children chains
641 * starting with this IRE
643 ire_dep_incr_generation(ire
);
645 case IRE_FLUSH_ADD
: {
648 ip_stack_t
*ipst
= ire
->ire_ipst
;
652 * Find an IRE which is a shorter match than the ire to be added
653 * For any such IRE (which we repeat) we update the
654 * ire_generation the same way as in the delete case.
656 addr
= ire
->ire_addr_v6
;
657 mask
= ire
->ire_mask_v6
;
658 masklen
= ip_mask_to_plen_v6(&mask
);
660 ire
= ire_ftable_lookup_impl_v6(&addr
, &mask
, NULL
, 0, NULL
,
661 ALL_ZONES
, NULL
, MATCH_IRE_SHORTERMASK
, ipst
);
662 while (ire
!= NULL
) {
663 /* We need to handle all in the same bucket */
664 irb_increment_generation(ire
->ire_bucket
);
666 mask
= ire
->ire_mask_v6
;
667 ASSERT(masklen
> ip_mask_to_plen_v6(&mask
));
668 masklen
= ip_mask_to_plen_v6(&mask
);
670 ire
= ire_ftable_lookup_impl_v6(&addr
, &mask
, NULL
, 0,
671 NULL
, ALL_ZONES
, NULL
, MATCH_IRE_SHORTERMASK
, ipst
);
676 rw_exit(&ipst
->ips_ip6_ire_head_lock
);
680 * Matches the arguments passed with the values in the ire.
682 * Note: for match types that match using "ill" passed in, ill
683 * must be checked for non-NULL before calling this routine.
686 ire_match_args_v6(ire_t
*ire
, const in6_addr_t
*addr
, const in6_addr_t
*mask
,
687 const in6_addr_t
*gateway
, int type
, const ill_t
*ill
, zoneid_t zoneid
,
688 const ts_label_t
*tsl
, int match_flags
)
690 in6_addr_t gw_addr_v6
;
691 ill_t
*ire_ill
= NULL
, *dst_ill
;
692 ip_stack_t
*ipst
= ire
->ire_ipst
;
694 ASSERT(ire
->ire_ipversion
== IPV6_VERSION
);
695 ASSERT(addr
!= NULL
);
696 ASSERT(mask
!= NULL
);
697 ASSERT((!(match_flags
& MATCH_IRE_GW
)) || gateway
!= NULL
);
698 ASSERT((!(match_flags
& (MATCH_IRE_ILL
|MATCH_IRE_SRC_ILL
))) ||
699 (ill
!= NULL
&& ill
->ill_isv6
));
702 * If MATCH_IRE_TESTHIDDEN is set, then only return the IRE if it
703 * is in fact hidden, to ensure the caller gets the right one.
705 if (ire
->ire_testhidden
) {
706 if (!(match_flags
& MATCH_IRE_TESTHIDDEN
))
710 if (zoneid
!= ALL_ZONES
&& zoneid
!= ire
->ire_zoneid
&&
711 ire
->ire_zoneid
!= ALL_ZONES
) {
713 * If MATCH_IRE_ZONEONLY has been set and the supplied zoneid
714 * does not match that of ire_zoneid, a failure to
715 * match is reported at this point. Otherwise, since some IREs
716 * that are available in the global zone can be used in local
717 * zones, additional checks need to be performed:
720 * entries should never be matched in this situation.
721 * Each zone has its own IRE_LOOPBACK.
724 * We allow them for any zoneid. ire_route_recursive
725 * does additional checks when
726 * ip_restrict_interzone_loopback is set.
728 * If ill_usesrc_ifindex is set
729 * Then we check if the zone has a valid source address
732 * If ire_ill is set, then check that the zone has an ipif
735 * Outside of this function (in ire_round_robin) we check
736 * that any IRE_OFFLINK has a gateway that reachable from the
737 * zone when we have multiple choices (ECMP).
739 if (match_flags
& MATCH_IRE_ZONEONLY
)
741 if (ire
->ire_type
& IRE_LOOPBACK
)
744 if (ire
->ire_type
& IRE_LOCAL
)
748 * The normal case of IRE_ONLINK has a matching zoneid.
749 * Here we handle the case when shared-IP zones have been
750 * configured with IP addresses on vniN. In that case it
751 * is ok for traffic from a zone to use IRE_ONLINK routes
752 * if the ill has a usesrc pointing at vniN
753 * Applies to IRE_INTERFACE.
755 dst_ill
= ire
->ire_ill
;
756 if (ire
->ire_type
& IRE_ONLINK
) {
760 * Note there is no IRE_INTERFACE on vniN thus
761 * can't do an IRE lookup for a matching route.
763 ifindex
= dst_ill
->ill_usesrc_ifindex
;
768 * If there is a usable source address in the
769 * zone, then it's ok to return this IRE_INTERFACE
771 if (!ipif_zone_avail(ifindex
, dst_ill
->ill_isv6
,
773 ip3dbg(("ire_match_args: no usrsrc for zone"
774 " dst_ill %p\n", (void *)dst_ill
));
780 * route add 11.0.0.0 gw1 -ifp bge0
781 * route add 11.0.0.0 gw2 -ifp bge1
782 * this code would differentiate based on
783 * where the sending zone has addresses.
784 * Only if the zone has an address on bge0 can it use the first
785 * route. It isn't clear if this behavior is documented
788 if (dst_ill
!= NULL
&& (ire
->ire_type
& IRE_OFFLINK
)) {
791 mutex_enter(&dst_ill
->ill_lock
);
792 for (tipif
= dst_ill
->ill_ipif
;
793 tipif
!= NULL
; tipif
= tipif
->ipif_next
) {
794 if (!IPIF_IS_CONDEMNED(tipif
) &&
795 (tipif
->ipif_flags
& IPIF_UP
) &&
796 (tipif
->ipif_zoneid
== zoneid
||
797 tipif
->ipif_zoneid
== ALL_ZONES
))
800 mutex_exit(&dst_ill
->ill_lock
);
807 ire_ill
= ire
->ire_ill
;
808 if (match_flags
& MATCH_IRE_GW
) {
809 mutex_enter(&ire
->ire_lock
);
810 gw_addr_v6
= ire
->ire_gateway_addr_v6
;
811 mutex_exit(&ire
->ire_lock
);
813 if (match_flags
& MATCH_IRE_ILL
) {
816 * If asked to match an ill, we *must* match
817 * on the ire_ill for ipmp test addresses, or
818 * any of the ill in the group for data addresses.
819 * If we don't, we may as well fail.
820 * However, we need an exception for IRE_LOCALs to ensure
821 * we loopback packets even sent to test addresses on different
822 * interfaces in the group.
824 if ((match_flags
& MATCH_IRE_TESTHIDDEN
) &&
825 !(ire
->ire_type
& IRE_LOCAL
)) {
826 if (ire
->ire_ill
!= ill
)
829 match_flags
&= ~MATCH_IRE_TESTHIDDEN
;
831 * We know that ill is not NULL, but ire_ill could be
834 if (ire_ill
== NULL
|| !IS_ON_SAME_LAN(ill
, ire_ill
))
838 if (match_flags
& MATCH_IRE_SRC_ILL
) {
841 if (!IS_ON_SAME_LAN(ill
, ire_ill
)) {
842 if (ire_ill
->ill_usesrc_ifindex
== 0 ||
843 (ire_ill
->ill_usesrc_ifindex
!=
844 ill
->ill_phyint
->phyint_ifindex
))
849 /* No ire_addr_v6 bits set past the mask */
850 ASSERT(V6_MASK_EQ(ire
->ire_addr_v6
, ire
->ire_mask_v6
,
852 if (V6_MASK_EQ(*addr
, *mask
, ire
->ire_addr_v6
) &&
853 ((!(match_flags
& MATCH_IRE_GW
)) ||
854 ((!(match_flags
& MATCH_IRE_DIRECT
)) ||
855 !(ire
->ire_flags
& RTF_INDIRECT
)) &&
856 IN6_ARE_ADDR_EQUAL(&gw_addr_v6
, gateway
)) &&
857 ((!(match_flags
& MATCH_IRE_TYPE
)) || (ire
->ire_type
& type
)) &&
858 ((!(match_flags
& MATCH_IRE_TESTHIDDEN
)) || ire
->ire_testhidden
) &&
859 ((!(match_flags
& MATCH_IRE_MASK
)) ||
860 (IN6_ARE_ADDR_EQUAL(&ire
->ire_mask_v6
, mask
))) &&
861 ((!(match_flags
& MATCH_IRE_SECATTR
)) ||
862 (!is_system_labeled()) ||
863 (tsol_ire_match_gwattr(ire
, tsl
) == 0))) {
864 /* We found the matched IRE */
871 * Check if the zoneid (not ALL_ZONES) has an IRE_INTERFACE for the specified
872 * gateway address. If ill is non-NULL we also match on it.
873 * The caller must hold a read lock on RADIX_NODE_HEAD if lock_held is set.
876 ire_gateway_ok_zone_v6(const in6_addr_t
*gateway
, zoneid_t zoneid
, ill_t
*ill
,
877 const ts_label_t
*tsl
, ip_stack_t
*ipst
, boolean_t lock_held
)
883 ASSERT(RW_READ_HELD(&ipst
->ips_ip6_ire_head_lock
));
885 rw_enter(&ipst
->ips_ip6_ire_head_lock
, RW_READER
);
887 match_flags
= MATCH_IRE_TYPE
| MATCH_IRE_SECATTR
;
889 match_flags
|= MATCH_IRE_ILL
;
891 ire
= ire_ftable_lookup_impl_v6(gateway
, &ipv6_all_zeros
,
892 &ipv6_all_zeros
, IRE_INTERFACE
, ill
, zoneid
, tsl
, match_flags
,
896 rw_exit(&ipst
->ips_ip6_ire_head_lock
);
906 * Lookup a route in forwarding table.
907 * specific lookup is indicated by passing the
908 * required parameters and indicating the
909 * match required in flag field.
911 * Supports link-local addresses by following the ipif/ill when recursing.
914 ire_ftable_lookup_v6(const in6_addr_t
*addr
, const in6_addr_t
*mask
,
915 const in6_addr_t
*gateway
, int type
, const ill_t
*ill
,
916 zoneid_t zoneid
, const ts_label_t
*tsl
, int flags
,
917 uint32_t xmit_hint
, ip_stack_t
*ipst
, uint_t
*generationp
)
921 ASSERT(addr
!= NULL
);
922 ASSERT((!(flags
& MATCH_IRE_MASK
)) || mask
!= NULL
);
923 ASSERT((!(flags
& MATCH_IRE_GW
)) || gateway
!= NULL
);
924 ASSERT(ill
== NULL
|| ill
->ill_isv6
);
926 ASSERT(!IN6_IS_ADDR_V4MAPPED(addr
));
929 * ire_match_args_v6() will dereference ill if MATCH_IRE_ILL
930 * or MATCH_IRE_SRC_ILL is set.
932 if ((flags
& (MATCH_IRE_ILL
|MATCH_IRE_SRC_ILL
)) && (ill
== NULL
))
935 rw_enter(&ipst
->ips_ip6_ire_head_lock
, RW_READER
);
936 ire
= ire_ftable_lookup_impl_v6(addr
, mask
, gateway
, type
, ill
, zoneid
,
939 rw_exit(&ipst
->ips_ip6_ire_head_lock
);
944 * round-robin only if we have more than one route in the bucket.
945 * ips_ip_ecmp_behavior controls when we do ECMP
947 * 1: for IRE_DEFAULT and /0 IRE_INTERFACE
950 * Note: if we found an IRE_IF_CLONE we won't look at the bucket with
951 * other ECMP IRE_INTERFACEs since the IRE_IF_CLONE is a /128 match
952 * and the IRE_INTERFACESs are likely to be shorter matches.
954 if (ire
->ire_bucket
->irb_ire_cnt
> 1 && !(flags
& MATCH_IRE_GW
)) {
955 if (ipst
->ips_ip_ecmp_behavior
== 2 ||
956 (ipst
->ips_ip_ecmp_behavior
== 1 &&
957 IS_DEFAULT_ROUTE_V6(ire
))) {
959 ire_ftable_args_t margs
;
961 bzero(&margs
, sizeof (margs
));
962 margs
.ift_addr_v6
= *addr
;
964 margs
.ift_mask_v6
= *mask
;
966 margs
.ift_gateway_v6
= *gateway
;
967 margs
.ift_type
= type
;
969 margs
.ift_zoneid
= zoneid
;
971 margs
.ift_flags
= flags
;
973 next_ire
= ire_round_robin(ire
->ire_bucket
, &margs
,
974 xmit_hint
, ire
, ipst
);
975 if (next_ire
== NULL
) {
976 /* keep ire if next_ire is null */
985 /* Return generation before dropping lock */
986 if (generationp
!= NULL
)
987 *generationp
= ire
->ire_generation
;
989 rw_exit(&ipst
->ips_ip6_ire_head_lock
);
992 * For shared-IP zones we need additional checks to what was
993 * done in ire_match_args to make sure IRE_LOCALs are handled.
995 * When ip_restrict_interzone_loopback is set, then
996 * we ensure that IRE_LOCAL are only used for loopback
997 * between zones when the logical "Ethernet" would
998 * have looped them back. That is, if in the absense of
999 * the IRE_LOCAL we would have sent to packet out the
1002 if ((ire
->ire_type
& IRE_LOCAL
) && zoneid
!= ALL_ZONES
&&
1003 ire
->ire_zoneid
!= zoneid
&& ire
->ire_zoneid
!= ALL_ZONES
&&
1004 ipst
->ips_ip_restrict_interzone_loopback
) {
1005 ire
= ire_alt_local(ire
, zoneid
, tsl
, ill
, generationp
);
1006 ASSERT(ire
!= NULL
);
1013 * Look up a single ire. The caller holds either the read or write lock.
1016 ire_ftable_lookup_impl_v6(const in6_addr_t
*addr
, const in6_addr_t
*mask
,
1017 const in6_addr_t
*gateway
, int type
, const ill_t
*ill
,
1018 zoneid_t zoneid
, const ts_label_t
*tsl
, int flags
,
1025 ASSERT(RW_LOCK_HELD(&ipst
->ips_ip6_ire_head_lock
));
1028 * If the mask is known, the lookup
1029 * is simple, if the mask is not known
1030 * we need to search.
1032 if (flags
& MATCH_IRE_MASK
) {
1035 masklen
= ip_mask_to_plen_v6(mask
);
1036 if (ipst
->ips_ip_forwarding_table_v6
[masklen
] == NULL
) {
1039 irb_ptr
= &(ipst
->ips_ip_forwarding_table_v6
[masklen
][
1040 IRE_ADDR_MASK_HASH_V6(*addr
, *mask
,
1041 ipst
->ips_ip6_ftable_hash_size
)]);
1042 rw_enter(&irb_ptr
->irb_lock
, RW_READER
);
1043 for (ire
= irb_ptr
->irb_ire
; ire
!= NULL
;
1044 ire
= ire
->ire_next
) {
1045 if (IRE_IS_CONDEMNED(ire
))
1047 if (ire_match_args_v6(ire
, addr
, mask
, gateway
, type
,
1048 ill
, zoneid
, tsl
, flags
))
1051 rw_exit(&irb_ptr
->irb_lock
);
1056 * In this case we don't know the mask, we need to
1057 * search the table assuming different mask sizes.
1059 if (flags
& MATCH_IRE_SHORTERMASK
) {
1060 masklen
= ip_mask_to_plen_v6(mask
);
1062 /* Nothing shorter than zero */
1067 masklen
= IP6_MASK_TABLE_SIZE
- 1;
1070 for (i
= masklen
; i
>= 0; i
--) {
1073 if ((ipst
->ips_ip_forwarding_table_v6
[i
]) == NULL
)
1075 (void) ip_plen_to_mask_v6(i
, &tmpmask
);
1076 irb_ptr
= &ipst
->ips_ip_forwarding_table_v6
[i
][
1077 IRE_ADDR_MASK_HASH_V6(*addr
, tmpmask
,
1078 ipst
->ips_ip6_ftable_hash_size
)];
1079 rw_enter(&irb_ptr
->irb_lock
, RW_READER
);
1080 for (ire
= irb_ptr
->irb_ire
; ire
!= NULL
;
1081 ire
= ire
->ire_next
) {
1082 if (IRE_IS_CONDEMNED(ire
))
1084 if (ire_match_args_v6(ire
, addr
,
1085 &ire
->ire_mask_v6
, gateway
, type
, ill
,
1086 zoneid
, tsl
, flags
))
1089 rw_exit(&irb_ptr
->irb_lock
);
1092 ASSERT(ire
== NULL
);
1093 ip1dbg(("ire_ftable_lookup_v6: returning NULL ire"));
1098 rw_exit(&irb_ptr
->irb_lock
);
1104 * This function is called by
1105 * ip_input/ire_route_recursive when doing a route lookup on only the
1106 * destination address.
1108 * The optimizations of this function over ire_ftable_lookup are:
1109 * o removing unnecessary flag matching
1110 * o doing longest prefix match instead of overloading it further
1111 * with the unnecessary "best_prefix_match"
1113 * If no route is found we return IRE_NOROUTE.
1116 ire_ftable_lookup_simple_v6(const in6_addr_t
*addr
, uint32_t xmit_hint
,
1117 ip_stack_t
*ipst
, uint_t
*generationp
)
1121 ire
= ire_ftable_lookup_v6(addr
, NULL
, NULL
, 0, NULL
, ALL_ZONES
, NULL
,
1122 MATCH_IRE_DSTONLY
, xmit_hint
, ipst
, generationp
);
1124 ire
= ire_reject(ipst
, B_TRUE
);
1125 if (generationp
!= NULL
)
1126 *generationp
= IRE_GENERATION_VERIFY
;
1128 /* ftable_lookup did round robin */
1133 ip_select_route_v6(const in6_addr_t
*dst
, const in6_addr_t src
,
1134 ip_xmit_attr_t
*ixa
, uint_t
*generationp
, in6_addr_t
*setsrcp
,
1135 int *errorp
, boolean_t
*multirtp
)
1137 ASSERT(!(ixa
->ixa_flags
& IXAF_IS_IPV4
));
1139 return (ip_select_route(dst
, src
, ixa
, generationp
, setsrcp
, errorp
,
1144 * Recursively look for a route to the destination. Can also match on
1145 * the zoneid, ill, and label. Used for the data paths. See also
1146 * ire_route_recursive_dstonly.
1148 * If IRR_ALLOCATE is not set then we will only inspect the existing IREs; never
1149 * create an IRE_IF_CLONE. This is used on the receive side when we are not
1151 * If IRR_INCOMPLETE is set then we return the IRE even if we can't correctly
1152 * resolve the gateway.
1154 * Note that this function never returns NULL. It returns an IRE_NOROUTE
1157 * If we find any IRE_LOCAL|BROADCAST etc past the first iteration it
1159 * Allow at most one RTF_INDIRECT.
1162 ire_route_recursive_impl_v6(ire_t
*ire
,
1163 const in6_addr_t
*nexthop
, uint_t ire_type
, const ill_t
*ill_arg
,
1164 zoneid_t zoneid
, const ts_label_t
*tsl
, uint_t match_args
,
1165 uint_t irr_flags
, uint32_t xmit_hint
, ip_stack_t
*ipst
,
1166 in6_addr_t
*setsrcp
, tsol_ire_gw_secattr_t
**gwattrp
, uint_t
*generationp
)
1169 in6_addr_t v6nexthop
= *nexthop
;
1170 ire_t
*ires
[MAX_IRE_RECURSION
];
1172 uint_t generations
[MAX_IRE_RECURSION
];
1173 boolean_t need_refrele
= B_FALSE
;
1174 boolean_t invalidate
= B_FALSE
;
1176 uint_t maskoff
= (IRE_LOCAL
|IRE_LOOPBACK
);
1178 if (setsrcp
!= NULL
)
1179 ASSERT(IN6_IS_ADDR_UNSPECIFIED(setsrcp
));
1180 if (gwattrp
!= NULL
)
1181 ASSERT(*gwattrp
== NULL
);
1184 * We iterate up to three times to resolve a route, even though
1185 * we have four slots in the array. The extra slot is for an
1186 * IRE_IF_CLONE we might need to create.
1189 while (i
< MAX_IRE_RECURSION
- 1) {
1190 /* ire_ftable_lookup handles round-robin/ECMP */
1192 ire
= ire_ftable_lookup_v6(&v6nexthop
, 0, 0, ire_type
,
1193 (ill
!= NULL
? ill
: ill_arg
), zoneid
, tsl
,
1194 match_args
, xmit_hint
, ipst
, &generation
);
1196 /* Caller passed it; extra hold since we will rele */
1198 if (generationp
!= NULL
)
1199 generation
= *generationp
;
1201 generation
= IRE_GENERATION_VERIFY
;
1205 if (i
> 0 && (irr_flags
& IRR_INCOMPLETE
)) {
1209 ire
= ire_reject(ipst
, B_TRUE
);
1214 /* Need to return the ire with RTF_REJECT|BLACKHOLE */
1215 if (ire
->ire_flags
& (RTF_REJECT
|RTF_BLACKHOLE
))
1218 ASSERT(!(ire
->ire_type
& IRE_MULTICAST
)); /* Not in ftable */
1220 * Verify that the IRE_IF_CLONE has a consistent generation
1223 if ((ire
->ire_type
& IRE_IF_CLONE
) && !ire_clone_verify(ire
)) {
1230 * Don't allow anything unusual past the first iteration.
1231 * After the first lookup, we should no longer look for
1232 * (IRE_LOCAL|IRE_LOOPBACK) or RTF_INDIRECT routes.
1234 * In addition, after we have found a direct IRE_OFFLINK,
1235 * we should only look for interface or clone routes.
1237 match_args
|= MATCH_IRE_DIRECT
; /* no more RTF_INDIRECTs */
1238 if ((ire
->ire_type
& IRE_OFFLINK
) &&
1239 !(ire
->ire_flags
& RTF_INDIRECT
)) {
1240 ire_type
= IRE_IF_ALL
;
1242 if (!(match_args
& MATCH_IRE_TYPE
))
1243 ire_type
= (IRE_OFFLINK
|IRE_ONLINK
);
1244 ire_type
&= ~maskoff
; /* no more LOCAL, LOOPBACK */
1246 match_args
|= MATCH_IRE_TYPE
;
1247 /* We have a usable IRE */
1249 generations
[i
] = generation
;
1252 /* The first RTF_SETSRC address is passed back if setsrcp */
1253 if ((ire
->ire_flags
& RTF_SETSRC
) &&
1254 setsrcp
!= NULL
&& IN6_IS_ADDR_UNSPECIFIED(setsrcp
)) {
1255 ASSERT(!IN6_IS_ADDR_UNSPECIFIED(
1256 &ire
->ire_setsrc_addr_v6
));
1257 *setsrcp
= ire
->ire_setsrc_addr_v6
;
1260 /* The first ire_gw_secattr is passed back if gwattrp */
1261 if (ire
->ire_gw_secattr
!= NULL
&&
1262 gwattrp
!= NULL
&& *gwattrp
== NULL
)
1263 *gwattrp
= ire
->ire_gw_secattr
;
1266 * Check if we have a short-cut pointer to an IRE for this
1267 * destination, and that the cached dependency isn't stale.
1268 * In that case we've rejoined an existing tree towards a
1269 * parent, thus we don't need to continue the loop to
1270 * discover the rest of the tree.
1272 mutex_enter(&ire
->ire_lock
);
1273 if (ire
->ire_dep_parent
!= NULL
&&
1274 ire
->ire_dep_parent
->ire_generation
==
1275 ire
->ire_dep_parent_generation
) {
1276 mutex_exit(&ire
->ire_lock
);
1280 mutex_exit(&ire
->ire_lock
);
1283 * If this type should have an ire_nce_cache (even if it
1284 * doesn't yet have one) then we are done. Includes
1285 * IRE_INTERFACE with a full 128 bit mask.
1287 if (ire
->ire_nce_capable
) {
1291 ASSERT(!(ire
->ire_type
& IRE_IF_CLONE
));
1293 * For an IRE_INTERFACE we create an IRE_IF_CLONE for this
1294 * particular destination
1296 if (ire
->ire_type
& IRE_INTERFACE
) {
1299 ASSERT(ire
->ire_masklen
!= IPV6_ABITS
);
1302 * In the case of ip_input and ILLF_FORWARDING not
1303 * being set, and in the case of RTM_GET, there is
1304 * no point in allocating an IRE_IF_CLONE. We return
1305 * the IRE_INTERFACE. Note that !IRR_ALLOCATE can
1306 * result in a ire_dep_parent which is IRE_IF_*
1307 * without an IRE_IF_CLONE.
1308 * We recover from that when we need to send packets
1309 * by ensuring that the generations become
1310 * IRE_GENERATION_VERIFY in this case.
1312 if (!(irr_flags
& IRR_ALLOCATE
)) {
1313 invalidate
= B_TRUE
;
1318 clone
= ire_create_if_clone(ire
, &v6nexthop
,
1320 if (clone
== NULL
) {
1322 * Temporary failure - no memory.
1323 * Don't want caller to cache IRE_NOROUTE.
1325 invalidate
= B_TRUE
;
1326 ire
= ire_blackhole(ipst
, B_TRUE
);
1330 * Make clone next to last entry and the
1331 * IRE_INTERFACE the last in the dependency
1332 * chain since the clone depends on the
1336 ASSERT(i
< MAX_IRE_RECURSION
);
1338 ires
[i
] = ires
[i
-1];
1339 generations
[i
] = generations
[i
-1];
1341 generations
[i
-1] = generation
;
1349 * We only match on the type and optionally ILL when
1350 * recursing. The type match is used by some callers
1351 * to exclude certain types (such as IRE_IF_CLONE or
1352 * IRE_LOCAL|IRE_LOOPBACK).
1354 * In the MATCH_IRE_SRC_ILL case, ill_arg may be the 'srcof'
1355 * ire->ire_ill, and we want to find the IRE_INTERFACE for
1356 * ire_ill, so we set ill to the ire_ill
1358 match_args
&= (MATCH_IRE_TYPE
| MATCH_IRE_DIRECT
);
1359 v6nexthop
= ire
->ire_gateway_addr_v6
;
1360 if (ill
== NULL
&& ire
->ire_ill
!= NULL
) {
1362 need_refrele
= B_TRUE
;
1364 match_args
|= MATCH_IRE_ILL
;
1368 ASSERT(ire
== NULL
);
1369 ire
= ire_reject(ipst
, B_TRUE
);
1372 ASSERT(ire
!= NULL
);
1377 * In the case of MULTIRT we want to try a different IRE the next
1378 * time. We let the next packet retry in that case.
1380 if (i
> 0 && (ires
[0]->ire_flags
& RTF_MULTIRT
))
1381 (void) ire_no_good(ires
[0]);
1384 /* cleanup ires[i] */
1385 ire_dep_unbuild(ires
, i
);
1386 for (j
= 0; j
< i
; j
++)
1387 ire_refrele(ires
[j
]);
1389 ASSERT((ire
->ire_flags
& (RTF_REJECT
|RTF_BLACKHOLE
)) ||
1390 (irr_flags
& IRR_INCOMPLETE
));
1392 * Use IRE_GENERATION_VERIFY to ensure that ip_output will redo the
1393 * ip_select_route since the reject or lack of memory might be gone.
1395 if (generationp
!= NULL
)
1396 *generationp
= IRE_GENERATION_VERIFY
;
1400 ASSERT(ire
== NULL
);
1404 /* Build dependencies */
1405 if (i
> 1 && !ire_dep_build(ires
, generations
, i
)) {
1406 /* Something in chain was condemned; tear it apart */
1407 ire
= ire_blackhole(ipst
, B_TRUE
);
1412 * Release all refholds except the one for ires[0] that we
1413 * will return to the caller.
1415 for (j
= 1; j
< i
; j
++)
1416 ire_refrele(ires
[j
]);
1420 * Since we needed to allocate but couldn't we need to make
1421 * sure that the dependency chain is rebuilt the next time.
1423 ire_dep_invalidate_generations(ires
[0]);
1424 generation
= IRE_GENERATION_VERIFY
;
1427 * IREs can have been added or deleted while we did the
1428 * recursive lookup and we can't catch those until we've built
1429 * the dependencies. We verify the stored
1430 * ire_dep_parent_generation to catch any such changes and
1431 * return IRE_GENERATION_VERIFY (which will cause
1432 * ip_select_route to be called again so we can redo the
1433 * recursive lookup next time we send a packet.
1435 if (ires
[0]->ire_dep_parent
== NULL
)
1436 generation
= ires
[0]->ire_generation
;
1438 generation
= ire_dep_validate_generations(ires
[0]);
1439 if (generations
[0] != ires
[0]->ire_generation
) {
1440 /* Something changed at the top */
1441 generation
= IRE_GENERATION_VERIFY
;
1444 if (generationp
!= NULL
)
1445 *generationp
= generation
;
1451 ire_route_recursive_v6(const in6_addr_t
*nexthop
, uint_t ire_type
,
1452 const ill_t
*ill
, zoneid_t zoneid
, const ts_label_t
*tsl
, uint_t match_args
,
1453 uint_t irr_flags
, uint32_t xmit_hint
, ip_stack_t
*ipst
,
1454 in6_addr_t
*setsrcp
, tsol_ire_gw_secattr_t
**gwattrp
, uint_t
*generationp
)
1456 return (ire_route_recursive_impl_v6(NULL
, nexthop
, ire_type
, ill
,
1457 zoneid
, tsl
, match_args
, irr_flags
, xmit_hint
, ipst
, setsrcp
,
1458 gwattrp
, generationp
));
1462 * Recursively look for a route to the destination.
1463 * We only handle a destination match here, yet we have the same arguments
1464 * as the full match to allow function pointers to select between the two.
1466 * Note that this function never returns NULL. It returns an IRE_NOROUTE
1469 * If we find any IRE_LOCAL|BROADCAST etc past the first iteration it
1471 * Allow at most one RTF_INDIRECT.
1474 ire_route_recursive_dstonly_v6(const in6_addr_t
*nexthop
, uint_t irr_flags
,
1475 uint32_t xmit_hint
, ip_stack_t
*ipst
)
1481 /* ire_ftable_lookup handles round-robin/ECMP */
1482 ire
= ire_ftable_lookup_simple_v6(nexthop
, xmit_hint
, ipst
,
1484 ASSERT(ire
!= NULL
);
1487 * If the IRE has a current cached parent we know that the whole
1488 * parent chain is current, hence we don't need to discover and
1489 * build any dependencies by doing a recursive lookup.
1491 mutex_enter(&ire
->ire_lock
);
1492 if (ire
->ire_dep_parent
!= NULL
) {
1493 if (ire
->ire_dep_parent
->ire_generation
==
1494 ire
->ire_dep_parent_generation
) {
1495 mutex_exit(&ire
->ire_lock
);
1498 mutex_exit(&ire
->ire_lock
);
1500 mutex_exit(&ire
->ire_lock
);
1502 * If this type should have an ire_nce_cache (even if it
1503 * doesn't yet have one) then we are done. Includes
1504 * IRE_INTERFACE with a full 128 bit mask.
1506 if (ire
->ire_nce_capable
)
1511 * Fallback to loop in the normal code starting with the ire
1512 * we found. Normally this would return the same ire.
1514 ire1
= ire_route_recursive_impl_v6(ire
, nexthop
, 0, NULL
, ALL_ZONES
,
1515 NULL
, MATCH_IRE_DSTONLY
, irr_flags
, xmit_hint
, ipst
, NULL
, NULL
,