changeset 12328:3c94f669d87d

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
author Sowmini Varadhan <Sowmini.Varadhan@Sun.COM>
date Thu, 06 May 2010 21:52:58 -0400
parents 4256c66fb5bf
children edd9b6e1b428
files usr/src/uts/common/inet/ip/ip.c usr/src/uts/common/inet/ip/ip6.c usr/src/uts/common/inet/ip/ip_ire.c usr/src/uts/common/inet/ip/ip_ndp.c
diffstat 4 files changed, 82 insertions(+), 70 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/inet/ip/ip.c	Thu May 06 16:50:06 2010 -0700
+++ b/usr/src/uts/common/inet/ip/ip.c	Thu May 06 21:52:58 2010 -0400
@@ -3459,6 +3459,31 @@
 	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 @@
 		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
--- a/usr/src/uts/common/inet/ip/ip6.c	Thu May 06 16:50:06 2010 -0700
+++ b/usr/src/uts/common/inet/ip/ip6.c	Thu May 06 21:52:58 2010 -0400
@@ -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 @@
 	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 @@
 		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
--- a/usr/src/uts/common/inet/ip/ip_ire.c	Thu May 06 16:50:06 2010 -0700
+++ b/usr/src/uts/common/inet/ip/ip_ire.c	Thu May 06 21:52:58 2010 -0400
@@ -1262,10 +1262,16 @@
 			 * 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 @@
  * 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 @@
 	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);
 }
 
--- a/usr/src/uts/common/inet/ip/ip_ndp.c	Thu May 06 16:50:06 2010 -0700
+++ b/usr/src/uts/common/inet/ip/ip_ndp.c	Thu May 06 21:52:58 2010 -0400
@@ -2367,7 +2367,7 @@
 			    &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 @@
 					 * 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) {