6940729 gate machine panic in ip.c: assertion failed: pkt_len == msgdsize(mp)
authorErik Nordmark <Erik.Nordmark@Sun.COM>
Tue, 27 Apr 2010 02:41:28 -0700
changeset 12266 d0c06a2b2de5
parent 12265 f199783d527a
child 12267 d8d8f3abf889
6940729 gate machine panic in ip.c: assertion failed: pkt_len == msgdsize(mp) 6936196 Missing IXAF_IS_IPV4 flag causes punchin to go boom
usr/src/uts/common/inet/ip/icmp.c
usr/src/uts/common/inet/iptun/iptun.c
usr/src/uts/common/inet/tcp/tcp_output.c
usr/src/uts/common/inet/udp/udp.c
--- a/usr/src/uts/common/inet/ip/icmp.c	Mon Apr 26 18:41:02 2010 -0700
+++ b/usr/src/uts/common/inet/ip/icmp.c	Tue Apr 27 02:41:28 2010 -0700
@@ -19,8 +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. */
 
@@ -709,6 +708,7 @@
 	in6_addr_t	v6dst;
 	uint32_t	flowinfo;
 	ip_xmit_attr_t	*ixa;
+	ip_xmit_attr_t	*oldixa;
 	uint_t		scopeid = 0;
 	uint_t		srcid = 0;
 	in6_addr_t	v6src = connp->conn_saddr_v6;
@@ -764,8 +764,10 @@
 	 * conn_ixa and prevent any other thread from using/changing it.
 	 * Once connect() is done other threads can use conn_ixa since the
 	 * refcnt will be back at one.
+	 * We defer updating conn_ixa until later to handle any concurrent
+	 * conn_ixa_cleanup thread.
 	 */
-	ixa = conn_get_ixa(connp, B_TRUE);
+	ixa = conn_get_ixa(connp, B_FALSE);
 	if (ixa == NULL)
 		return (ENOMEM);
 
@@ -895,7 +897,10 @@
 	connp->conn_lastsrcid = srcid;
 	/* Also remember a source to use together with lastdst */
 	connp->conn_v6lastsrc = v6src;
+
+	oldixa = conn_replace_ixa(connp, ixa);
 	mutex_exit(&connp->conn_lock);
+	ixa_refrele(oldixa);
 
 	ixa_refrele(ixa);
 	return (0);
--- a/usr/src/uts/common/inet/iptun/iptun.c	Mon Apr 26 18:41:02 2010 -0700
+++ b/usr/src/uts/common/inet/iptun/iptun.c	Tue Apr 27 02:41:28 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -707,11 +706,16 @@
 	conn_t			*connp = iptun->iptun_connp;
 	int			error = 0;
 	ip_xmit_attr_t		*ixa;
+	ip_xmit_attr_t		*oldixa;
 	iulp_t			uinfo;
 	ip_stack_t		*ipst = connp->conn_netstack->netstack_ip;
 
-	/* Get an exclusive ixa for this thread, and replace conn_ixa */
-	ixa = conn_get_ixa(connp, B_TRUE);
+	/*
+	 * Get an exclusive ixa for this thread.
+	 * We defer updating conn_ixa until later to handle any concurrent
+	 * conn_ixa_cleanup thread.
+	 */
+	ixa = conn_get_ixa(connp, B_FALSE);
 	if (ixa == NULL)
 		return (ENOMEM);
 	ASSERT(ixa->ixa_refcnt >= 2);
@@ -818,10 +822,18 @@
 	if (error != 0)
 		goto done;
 
+	/* Atomically update v6lastdst and conn_ixa */
+	mutex_enter(&connp->conn_lock);
 	/* Record this as the "last" send even though we haven't sent any */
 	connp->conn_v6lastdst = connp->conn_faddr_v6;
 
 	iptun->iptun_flags |= IPTUN_BOUND;
+
+	oldixa = conn_replace_ixa(connp, ixa);
+	/* Done with conn_t */
+	mutex_exit(&connp->conn_lock);
+	ixa_refrele(oldixa);
+
 	/*
 	 * Now that we're bound with ip below us, this is a good
 	 * time to initialize the destination path MTU and to
--- a/usr/src/uts/common/inet/tcp/tcp_output.c	Mon Apr 26 18:41:02 2010 -0700
+++ b/usr/src/uts/common/inet/tcp/tcp_output.c	Tue Apr 27 02:41:28 2010 -0700
@@ -1703,6 +1703,7 @@
 {
 	conn_t	*econnp = (conn_t *)arg;
 	tcp_t	*tcp = econnp->conn_tcp;
+	ip_xmit_attr_t *ixa = econnp->conn_ixa;
 
 	/* Guard against a RST having blown it away while on the squeue */
 	if (tcp->tcp_state == TCPS_CLOSED) {
@@ -1710,7 +1711,14 @@
 		return;
 	}
 
-	(void) conn_ip_output(mp, econnp->conn_ixa);
+	/*
+	 * In the off-chance that the eager received and responded to
+	 * some other packet while the SYN|ACK was queued, we recalculate
+	 * the ixa_pktlen. It would be better to fix the SYN/accept
+	 * multithreading scheme to avoid this complexity.
+	 */
+	ixa->ixa_pktlen = msgdsize(mp);
+	(void) conn_ip_output(mp, ixa);
 }
 
 /*
--- a/usr/src/uts/common/inet/udp/udp.c	Mon Apr 26 18:41:02 2010 -0700
+++ b/usr/src/uts/common/inet/udp/udp.c	Tue Apr 27 02:41:28 2010 -0700
@@ -19,8 +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. */
 
@@ -5886,6 +5885,7 @@
 	int		error;
 	conn_t		*connp1;
 	ip_xmit_attr_t	*ixa;
+	ip_xmit_attr_t	*oldixa;
 	uint_t		scopeid = 0;
 	uint_t		srcid = 0;
 	in6_addr_t	v6src = connp->conn_saddr_v6;
@@ -5956,8 +5956,10 @@
 	 * conn_ixa and prevent any other thread from using/changing it.
 	 * Once connect() is done other threads can use conn_ixa since the
 	 * refcnt will be back at one.
+	 * We defer updating conn_ixa until later to handle any concurrent
+	 * conn_ixa_cleanup thread.
 	 */
-	ixa = conn_get_ixa(connp, B_TRUE);
+	ixa = conn_get_ixa(connp, B_FALSE);
 	if (ixa == NULL)
 		return (ENOMEM);
 
@@ -6095,7 +6097,10 @@
 	connp->conn_lastsrcid = srcid;
 	/* Also remember a source to use together with lastdst */
 	connp->conn_v6lastsrc = v6src;
+
+	oldixa = conn_replace_ixa(connp, ixa);
 	mutex_exit(&connp->conn_lock);
+	ixa_refrele(oldixa);
 
 	/*
 	 * We've picked a source address above. Now we can