summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/inet
diff options
context:
space:
mode:
authorSowmini Varadhan <Sowmini.Varadhan@Sun.COM>2010-05-06 21:52:58 -0400
committerSowmini Varadhan <Sowmini.Varadhan@Sun.COM>2010-05-06 21:52:58 -0400
commit5328776712fa5baa7a1fa74420d5682c66309dbe (patch)
tree733678e7520927b3e331260657e2ddfa75f54fd7 /usr/src/uts/common/inet
parentdea05b66b1fa2d0242e78345542e72df4f14a55f (diff)
downloadillumos-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.c45
-rw-r--r--usr/src/uts/common/inet/ip/ip6.c74
-rw-r--r--usr/src/uts/common/inet/ip/ip_ire.c27
-rw-r--r--usr/src/uts/common/inet/ip/ip_ndp.c6
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) {