diff options
author | Sowmini Varadhan <Sowmini.Varadhan@Sun.COM> | 2010-05-06 21:52:58 -0400 |
---|---|---|
committer | Sowmini Varadhan <Sowmini.Varadhan@Sun.COM> | 2010-05-06 21:52:58 -0400 |
commit | 5328776712fa5baa7a1fa74420d5682c66309dbe (patch) | |
tree | 733678e7520927b3e331260657e2ddfa75f54fd7 /usr/src/uts/common/inet | |
parent | dea05b66b1fa2d0242e78345542e72df4f14a55f (diff) | |
download | illumos-gate-5328776712fa5baa7a1fa74420d5682c66309dbe.tar.gz |
6948276 assertion failed: ixa->ixa_dce != NULL, file: ../../common/inet/ip/ip_output.c, line: 150
6948860 nce_timer() checks for return value from arp_request() are broken
Diffstat (limited to 'usr/src/uts/common/inet')
-rw-r--r-- | usr/src/uts/common/inet/ip/ip.c | 45 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip6.c | 74 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip_ire.c | 27 | ||||
-rw-r--r-- | usr/src/uts/common/inet/ip/ip_ndp.c | 6 |
4 files changed, 82 insertions, 70 deletions
diff --git a/usr/src/uts/common/inet/ip/ip.c b/usr/src/uts/common/inet/ip/ip.c index 0e64927e93..4a43ee4734 100644 --- a/usr/src/uts/common/inet/ip/ip.c +++ b/usr/src/uts/common/inet/ip/ip.c @@ -3459,6 +3459,31 @@ ip_set_destination_v4(ipaddr_t *src_addrp, ipaddr_t dst_addr, ipaddr_t firsthop, ixa->ixa_ire_generation = generation; /* + * Ensure that ixa_dce is always set any time that ixa_ire is set, + * since some callers will send a packet to conn_ip_output() even if + * there's an error. + */ + if (flags & IPDF_UNIQUE_DCE) { + /* Fallback to the default dce if allocation fails */ + dce = dce_lookup_and_add_v4(dst_addr, ipst); + if (dce != NULL) + generation = dce->dce_generation; + else + dce = dce_lookup_v4(dst_addr, ipst, &generation); + } else { + dce = dce_lookup_v4(dst_addr, ipst, &generation); + } + ASSERT(dce != NULL); + if (ixa->ixa_dce != NULL) + dce_refrele_notr(ixa->ixa_dce); +#ifdef DEBUG + dce_refhold_notr(dce); + dce_refrele(dce); +#endif + ixa->ixa_dce = dce; + ixa->ixa_dce_generation = generation; + + /* * For multicast with multirt we have a flag passed back from * ire_lookup_multi_ill_v4 since we don't have an IRE for each * possible multicast address. @@ -3562,26 +3587,6 @@ ip_set_destination_v4(ipaddr_t *src_addrp, ipaddr_t dst_addr, ipaddr_t firsthop, ixa->ixa_src_generation = generation; } - if (flags & IPDF_UNIQUE_DCE) { - /* Fallback to the default dce if allocation fails */ - dce = dce_lookup_and_add_v4(dst_addr, ipst); - if (dce != NULL) - generation = dce->dce_generation; - else - dce = dce_lookup_v4(dst_addr, ipst, &generation); - } else { - dce = dce_lookup_v4(dst_addr, ipst, &generation); - } - ASSERT(dce != NULL); - if (ixa->ixa_dce != NULL) - dce_refrele_notr(ixa->ixa_dce); -#ifdef DEBUG - dce_refhold_notr(dce); - dce_refrele(dce); -#endif - ixa->ixa_dce = dce; - ixa->ixa_dce_generation = generation; - /* * Make sure we don't leave an unreachable ixa_nce in place * since ip_select_route is used when we unplumb i.e., remove diff --git a/usr/src/uts/common/inet/ip/ip6.c b/usr/src/uts/common/inet/ip/ip6.c index c03e10b642..d89a7cc5c5 100644 --- a/usr/src/uts/common/inet/ip/ip6.c +++ b/usr/src/uts/common/inet/ip/ip6.c @@ -19,10 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2010 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ -/* + * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1990 Mentat Inc. */ @@ -2076,6 +2073,43 @@ ip_set_destination_v6(in6_addr_t *src_addrp, const in6_addr_t *dst_addr, ixa->ixa_ire_generation = generation; /* + * Ensure that ixa_dce is always set any time that ixa_ire is set, + * since some callers will send a packet to conn_ip_output() even if + * there's an error. + */ + ifindex = 0; + if (IN6_IS_ADDR_LINKSCOPE(dst_addr)) { + /* If we are creating a DCE we'd better have an ifindex */ + if (ill != NULL) + ifindex = ill->ill_phyint->phyint_ifindex; + else + flags &= ~IPDF_UNIQUE_DCE; + } + + if (flags & IPDF_UNIQUE_DCE) { + /* Fallback to the default dce if allocation fails */ + dce = dce_lookup_and_add_v6(dst_addr, ifindex, ipst); + if (dce != NULL) { + generation = dce->dce_generation; + } else { + dce = dce_lookup_v6(dst_addr, ifindex, ipst, + &generation); + } + } else { + dce = dce_lookup_v6(dst_addr, ifindex, ipst, &generation); + } + ASSERT(dce != NULL); + if (ixa->ixa_dce != NULL) + dce_refrele_notr(ixa->ixa_dce); +#ifdef DEBUG + dce_refhold_notr(dce); + dce_refrele(dce); +#endif + ixa->ixa_dce = dce; + ixa->ixa_dce_generation = generation; + + + /* * For multicast with multirt we have a flag passed back from * ire_lookup_multi_ill_v6 since we don't have an IRE for each * possible multicast address. @@ -2180,38 +2214,6 @@ ip_set_destination_v6(in6_addr_t *src_addrp, const in6_addr_t *dst_addr, ixa->ixa_ire_generation = IRE_GENERATION_VERIFY; } - - ifindex = 0; - if (IN6_IS_ADDR_LINKSCOPE(dst_addr)) { - /* If we are creating a DCE we'd better have an ifindex */ - if (ill != NULL) - ifindex = ill->ill_phyint->phyint_ifindex; - else - flags &= ~IPDF_UNIQUE_DCE; - } - - if (flags & IPDF_UNIQUE_DCE) { - /* Fallback to the default dce if allocation fails */ - dce = dce_lookup_and_add_v6(dst_addr, ifindex, ipst); - if (dce != NULL) { - generation = dce->dce_generation; - } else { - dce = dce_lookup_v6(dst_addr, ifindex, ipst, - &generation); - } - } else { - dce = dce_lookup_v6(dst_addr, ifindex, ipst, &generation); - } - ASSERT(dce != NULL); - if (ixa->ixa_dce != NULL) - dce_refrele_notr(ixa->ixa_dce); -#ifdef DEBUG - dce_refhold_notr(dce); - dce_refrele(dce); -#endif - ixa->ixa_dce = dce; - ixa->ixa_dce_generation = generation; - /* * Note that IPv6 multicast supports PMTU discovery unlike IPv4 * multicast. But pmtu discovery is only enabled for connected diff --git a/usr/src/uts/common/inet/ip/ip_ire.c b/usr/src/uts/common/inet/ip/ip_ire.c index 0e600f2a45..4d671d53dd 100644 --- a/usr/src/uts/common/inet/ip/ip_ire.c +++ b/usr/src/uts/common/inet/ip/ip_ire.c @@ -1262,10 +1262,16 @@ ire_add_v4(ire_t *ire) * after adding, we return a held ire. This will * avoid a lookup in the caller again. If the callers * don't want to use it, they need to do a REFRELE. + * + * We only allow exactly one IRE_IF_CLONE for any dst, + * so, if the is an IF_CLONE, return the ire without + * an identical_ref, but with an ire_ref held. */ - atomic_add_32(&ire1->ire_identical_ref, 1); - DTRACE_PROBE2(ire__add__exist, ire_t *, ire1, - ire_t *, ire); + if (ire->ire_type != IRE_IF_CLONE) { + atomic_add_32(&ire1->ire_identical_ref, 1); + DTRACE_PROBE2(ire__add__exist, ire_t *, ire1, + ire_t *, ire); + } ire_refhold(ire1); ire_atomic_end(irb_ptr, ire); ire_delete(ire); @@ -3458,6 +3464,13 @@ ire_to_nce_pkt(ire_t *ire, mblk_t *mp) * Return the generation number. * Returns NULL is no memory for the IRE. * Handles both IPv4 and IPv6. + * + * IRE_IF_CLONE entries may only be created adn added by calling + * ire_create_if_clone(), and we depend on the fact that ire_add will + * atomically ensure that attempts to add multiple identical IRE_IF_CLONE + * entries will not result in duplicate (i.e., ire_identical_ref > 1) + * CLONE entries, so that a single ire_delete is sufficient to remove the + * CLONE. */ ire_t * ire_create_if_clone(ire_t *ire_if, const in6_addr_t *addr, uint_t *generationp) @@ -3508,14 +3521,6 @@ ire_create_if_clone(ire_t *ire_if, const in6_addr_t *addr, uint_t *generationp) if (generationp != NULL) *generationp = nire->ire_generation; - /* - * Make sure races don't add a duplicate by - * catching the case when an identical was returned. - */ - if (nire != ire) { - ASSERT(nire->ire_identical_ref > 1); - ire_delete(nire); - } return (nire); } diff --git a/usr/src/uts/common/inet/ip/ip_ndp.c b/usr/src/uts/common/inet/ip/ip_ndp.c index 37ce93d40a..c0be85cd62 100644 --- a/usr/src/uts/common/inet/ip/ip_ndp.c +++ b/usr/src/uts/common/inet/ip/ip_ndp.c @@ -2367,7 +2367,7 @@ nce_timer(void *arg) &sender6, &ncec->ncec_addr, NDP_UNICAST); } else { - dropped = arp_request(ncec, sender4, src_ill); + dropped = (arp_request(ncec, sender4, src_ill) == 0); mutex_exit(&ncec->ncec_lock); } if (!dropped) { @@ -2421,8 +2421,8 @@ nce_timer(void *arg) * the ARP request will be sent out * as a link-layer unicast. */ - dropped = arp_request(ncec, sender4, - src_ill); + dropped = (arp_request(ncec, sender4, + src_ill) == 0); mutex_exit(&ncec->ncec_lock); } if (!dropped) { |