connect problems on SMP

Joerg Sonnenberger joerg at britannica.bec.de
Mon Apr 5 10:39:20 PDT 2004


Attached is Jeffrey's work-in-progress patch with same additions to get
a working kernel. This works fine for me.

Joerg
Index: kern/uipc_msg.c
===================================================================
RCS file: /extern/Daten/Sources/repository/dragonflybsd/src/sys/kern/uipc_msg.c,v
retrieving revision 1.5
diff -u -r1.5 uipc_msg.c
--- kern/uipc_msg.c	24 Mar 2004 21:58:44 -0000	1.5
+++ kern/uipc_msg.c	5 Apr 2004 13:44:45 -0000
@@ -139,7 +139,7 @@
 	if (!so->so_proto->pr_mport)
 		return ((*so->so_proto->pr_usrreqs->pru_connect)(so, nam, td));
 
-	port = so->so_proto->pr_mport(so, NULL);
+	port = so->so_proto->pr_mport(so, nam);
 	lwkt_initmsg(&msg.nm_lmsg, CMD_NETMSG_PRU_CONNECT);
 	msg.nm_handler = netmsg_pru_dispatcher;
 	msg.nm_prufn = so->so_proto->pr_usrreqs->pru_connect;
Index: netinet/in_pcb.c
===================================================================
RCS file: /extern/Daten/Sources/repository/dragonflybsd/src/sys/netinet/in_pcb.c,v
retrieving revision 1.16
diff -u -r1.16 in_pcb.c
--- netinet/in_pcb.c	31 Mar 2004 00:43:09 -0000	1.16
+++ netinet/in_pcb.c	5 Apr 2004 13:44:45 -0000
@@ -538,7 +538,7 @@
 	}
 	inp->inp_faddr = sin->sin_addr;
 	inp->inp_fport = sin->sin_port;
-	in_pcbinsconnhash(inp);
+	in_pcbinsconnhash(inp, inp->inp_pcbinfo);
 	return (0);
 }
 
@@ -559,12 +559,12 @@
 	struct inpcb *inp;
 {
 	struct socket *so = inp->inp_socket;
-	struct inpcbinfo *ipi = inp->inp_pcbinfo;
+	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 
 #ifdef IPSEC
 	ipsec4_delete_pcbpolicy(inp);
 #endif /*IPSEC*/
-	inp->inp_gencnt = ++ipi->ipi_gencnt;
+	inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
 	in_pcbremlists(inp);
 	so->so_pcb = 0;
 	sofree(so);
@@ -574,7 +574,7 @@
 		rtfree(inp->inp_route.ro_rt);
 	ip_freemoptions(inp->inp_moptions);
 	inp->inp_vflag = 0;
-	zfree(ipi->ipi_zone, inp);
+	zfree(pcbinfo->ipi_zone, inp);
 }
 
 /*
@@ -908,9 +908,8 @@
  * Insert PCB into connection hash table.
  */
 void
-in_pcbinsconnhash(struct inpcb *inp)
+in_pcbinsconnhash(struct inpcb *inp, struct inpcbinfo *pcbinfo)
 {
-	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 	struct inpcbhead *bucket;
 	u_int32_t hashkey_faddr, hashkey_laddr;
 
Index: netinet/in_pcb.h
===================================================================
RCS file: /extern/Daten/Sources/repository/dragonflybsd/src/sys/netinet/in_pcb.h,v
retrieving revision 1.9
diff -u -r1.9 in_pcb.h
--- netinet/in_pcb.h	31 Mar 2004 00:43:09 -0000	1.9
+++ netinet/in_pcb.h	5 Apr 2004 13:44:45 -0000
@@ -329,7 +329,7 @@
 void	in_pcbdetach (struct inpcb *);
 void	in_pcbdisconnect (struct inpcb *);
 void	in_pcbinswildcardhash(struct inpcb *inp);
-void	in_pcbinsconnhash(struct inpcb *inp);
+void	in_pcbinsconnhash(struct inpcb *inp, struct inpcbinfo *);
 int	in_pcbinsporthash (struct inpcb *);
 int	in_pcbladdr (struct inpcb *, struct sockaddr *,
 	    struct sockaddr_in **);
Index: netinet/in_proto.c
===================================================================
RCS file: /extern/Daten/Sources/repository/dragonflybsd/src/sys/netinet/in_proto.c,v
retrieving revision 1.6
diff -u -r1.6 in_proto.c
--- netinet/in_proto.c	6 Mar 2004 01:58:55 -0000	1.6
+++ netinet/in_proto.c	5 Apr 2004 14:30:31 -0000
@@ -48,6 +48,7 @@
 #include <sys/protosw.h>
 #include <sys/queue.h>
 #include <sys/sysctl.h>
+#include <sys/thread.h>
 
 #include <net/if.h>
 #include <net/route.h>
Index: netinet/ip_demux.c
===================================================================
RCS file: /extern/Daten/Sources/repository/dragonflybsd/src/sys/netinet/ip_demux.c,v
retrieving revision 1.14
diff -u -r1.14 ip_demux.c
--- netinet/ip_demux.c	5 Apr 2004 09:17:48 -0000	1.14
+++ netinet/ip_demux.c	5 Apr 2004 14:36:59 -0000
@@ -166,7 +166,7 @@
 	 *   attach() has a null socket parameter
 	 *   Fast and slow timeouts pass in two NULLs
 	 */
-	if (nam != NULL || so == NULL)
+	if (so == NULL || nam != NULL)
 		return (&tcp_thread[0].td_msgport);
 
 	/*
@@ -189,6 +189,13 @@
 	    inp->inp_laddr.s_addr, inp->inp_fport, inp->inp_lport)].td_msgport);
 }
 
+lwkt_port_t
+tcp_addrport(in_addr_t faddr, in_port_t fport, in_addr_t laddr, in_port_t lport)
+{
+	return (&tcp_thread[tcp_addrcpu(faddr, fport,
+					laddr, lport)].td_msgport);
+}
+
 /*
  * Map a UDP socket to a protocol processing thread.
  */
Index: netinet/tcp_output.c
===================================================================
RCS file: /extern/Daten/Sources/repository/dragonflybsd/src/sys/netinet/tcp_output.c,v
retrieving revision 1.10
diff -u -r1.10 tcp_output.c
--- netinet/tcp_output.c	8 Mar 2004 00:36:30 -0000	1.10
+++ netinet/tcp_output.c	5 Apr 2004 14:30:54 -0000
@@ -49,6 +49,7 @@
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/in_cksum.h>
+#include <sys/thread.h>
 
 #include <net/route.h>
 
Index: netinet/tcp_timer.c
===================================================================
RCS file: /extern/Daten/Sources/repository/dragonflybsd/src/sys/netinet/tcp_timer.c,v
retrieving revision 1.6
diff -u -r1.6 tcp_timer.c
--- netinet/tcp_timer.c	8 Mar 2004 00:39:00 -0000	1.6
+++ netinet/tcp_timer.c	5 Apr 2004 14:31:14 -0000
@@ -48,7 +48,7 @@
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/protosw.h>
-
+#include <sys/thread.h>
 #include <machine/cpu.h>	/* before tcp_seq.h, for tcp_random18() */
 
 #include <net/route.h>
Index: netinet/tcp_usrreq.c
===================================================================
RCS file: /extern/Daten/Sources/repository/dragonflybsd/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.10
diff -u -r1.10 tcp_usrreq.c
--- netinet/tcp_usrreq.c	31 Mar 2004 10:23:10 -0000	1.10
+++ netinet/tcp_usrreq.c	5 Apr 2004 14:32:41 -0000
@@ -42,6 +42,7 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/malloc.h>
 #include <sys/sysctl.h>
 #include <sys/globaldata.h>
 #include <sys/thread.h>
@@ -54,7 +55,10 @@
 #include <sys/socketvar.h>
 #include <sys/protosw.h>
 
+#include <sys/msgport2.h>
+
 #include <net/if.h>
+#include <net/netisr.h>
 #include <net/route.h>
 
 #include <netinet/in.h>
@@ -694,47 +698,29 @@
 };
 #endif /* INET6 */
 
-/*
- * Common subroutine to open a TCP connection to remote host specified
- * by struct sockaddr_in in mbuf *nam.  Call in_pcbbind to assign a local
- * port number if needed.  Call in_pcbladdr to do the routing and to choose
- * a local host address (interface).  If there is an existing incarnation
- * of the same connection in TIME-WAIT state and if the remote host was
- * sending CC options and if the connection duration was < MSL, then
- * truncate the previous TIME-WAIT state and proceed.
- * Initialize connection parameters and enter SYN-SENT state.
- */
+struct netmsg_tcp_connect {
+	struct lwkt_msg		nm_lmsg;
+	netisr_fn_t		nm_handler;
+	struct tcpcb		*nm_tp;
+	struct sockaddr_in	*nm_sin;
+	struct sockaddr_in	*nm_ifsin;
+};
+
 static int
-tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
+tcp_connect_oncpu(struct tcpcb *tp, struct sockaddr_in *sin,
+    struct sockaddr_in *if_sin)
 {
 	struct inpcb *inp = tp->t_inpcb, *oinp;
 	struct socket *so = inp->inp_socket;
 	struct tcpcb *otp;
-	struct sockaddr_in *sin = (struct sockaddr_in *)nam;
-	struct sockaddr_in *if_sin;
 	struct rmxp_tao *taop;
 	struct rmxp_tao tao_noncached;
-	int error;
-
-	if (inp->inp_lport == 0) {
-		error = in_pcbbind(inp, (struct sockaddr *)0, td);
-		if (error)
-			return (error);
-	}
 
-	/*
-	 * Cannot simply call in_pcbconnect, because there might be an
-	 * earlier incarnation of this same connection still in
-	 * TIME_WAIT state, creating an ADDRINUSE error.
-	 */
-	error = in_pcbladdr(inp, nam, &if_sin);
-	if (error)
-		return (error);
-	oinp = in_pcblookup_hash(inp->inp_pcbinfo,
+	oinp = in_pcblookup_hash(&tcbinfo[mycpu->gd_cpuid],
 	    sin->sin_addr, sin->sin_port,
 	    inp->inp_laddr.s_addr != INADDR_ANY ?
 	        inp->inp_laddr : if_sin->sin_addr,
-	    inp->inp_lport,  0, NULL);
+	    inp->inp_lport, 0, NULL);
 	if (oinp != NULL) {
 		if (oinp != inp && (otp = intotcpcb(oinp)) != NULL &&
 		    otp->t_state == TCPS_TIME_WAIT &&
@@ -748,7 +734,7 @@
 		inp->inp_laddr = if_sin->sin_addr;
 	inp->inp_faddr = sin->sin_addr;
 	inp->inp_fport = sin->sin_port;
-	in_pcbinsconnhash(inp);
+	in_pcbinsconnhash(inp, &tcbinfo[mycpu->gd_cpuid]);
 
 	/* Compute window scaling to request.  */
 	while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
@@ -784,6 +770,82 @@
 	return (0);
 }
 
+static int
+tcp_connect_handler(struct netmsg *msg0)
+{
+	struct netmsg_tcp_connect *msg = (struct netmsg_tcp_connect *)msg0;
+	int error;
+
+	error = tcp_connect_oncpu(msg->nm_tp, msg->nm_sin, msg->nm_ifsin);
+	return (error);
+}
+
+/*
+ * Common subroutine to open a TCP connection to remote host specified
+ * by struct sockaddr_in in mbuf *nam.  Call in_pcbbind to assign a local
+ * port number if needed.  Call in_pcbladdr to do the routing and to choose
+ * a local host address (interface).  If there is an existing incarnation
+ * of the same connection in TIME-WAIT state and if the remote host was
+ * sending CC options and if the connection duration was < MSL, then
+ * truncate the previous TIME-WAIT state and proceed.
+ * Initialize connection parameters and enter SYN-SENT state.
+ */
+static int
+tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
+{
+	struct inpcb *inp = tp->t_inpcb;
+	struct sockaddr_in *sin = (struct sockaddr_in *)nam;
+	struct sockaddr_in *if_sin;
+	int error;
+	boolean_t didbind = FALSE;
+	lwkt_port_t port;
+
+	if (inp->inp_lport == 0) {
+		error = in_pcbbind(inp, (struct sockaddr *)NULL, td);
+		if (error)
+			return (error);
+		didbind = TRUE;
+	}
+
+	/*
+	 * Cannot simply call in_pcbconnect, because there might be an
+	 * earlier incarnation of this same connection still in
+	 * TIME_WAIT state, creating an ADDRINUSE error.
+	 */
+	error = in_pcbladdr(inp, nam, &if_sin);
+	if (error)
+		return (error);
+
+	port = tcp_addrport(sin->sin_addr.s_addr, sin->sin_port,
+	    inp->inp_laddr.s_addr ?
+		inp->inp_laddr.s_addr : if_sin->sin_addr.s_addr,
+	    inp->inp_lport);
+
+	if (port->mp_td == curthread) {
+		error = tcp_connect_oncpu(tp, sin, if_sin);
+	} else {
+		struct netmsg_tcp_connect *msg;
+
+		msg = malloc(sizeof(struct netmsg_tcp_connect), M_LWKTMSG,
+		    M_NOWAIT);
+		if (msg == NULL) {
+			if (didbind) {	/* need to unwind bind */
+				inp->inp_lport = 0;
+				inp->inp_laddr.s_addr = INADDR_ANY;
+			}
+			return (ENOMEM);
+		}
+		lwkt_initmsg(&msg->nm_lmsg, CMD_NETMSG_ONCPU);
+		msg->nm_handler = tcp_connect_handler;
+		msg->nm_tp = tp;
+		msg->nm_sin = sin;
+		msg->nm_ifsin = if_sin;
+		error = lwkt_domsg(port, &msg->nm_lmsg);
+	}
+
+	return (error);
+}
+
 #ifdef INET6
 static int
 tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
@@ -831,7 +893,7 @@
 	inp->inp_fport = sin6->sin6_port;
 	if ((sin6->sin6_flowinfo & IPV6_FLOWINFO_MASK) != NULL)
 		inp->in6p_flowinfo = sin6->sin6_flowinfo;
-	in_pcbinsconnhash(inp);
+	in_pcbinsconnhash(inp, &tcbinfo[mycpu->gd_cpuid]);
 
 	/* Compute window scaling to request.  */
 	while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
Index: netinet/tcp_var.h
===================================================================
RCS file: /extern/Daten/Sources/repository/dragonflybsd/src/sys/netinet/tcp_var.h,v
retrieving revision 1.15
diff -u -r1.15 tcp_var.h
--- netinet/tcp_var.h	14 Mar 2004 08:21:53 -0000	1.15
+++ netinet/tcp_var.h	5 Apr 2004 13:44:45 -0000
@@ -467,6 +467,9 @@
 
 int	 tcp_addrcpu(in_addr_t faddr, in_port_t fport,
 	    in_addr_t laddr, in_port_t lport);
+lwkt_port_t
+	tcp_addrport(in_addr_t faddr, in_port_t fport,
+	    in_addr_t laddr, in_port_t lport);
 void	 tcp_canceltimers (struct tcpcb *);
 struct tcpcb *
 	 tcp_close (struct tcpcb *);
Index: netinet6/in6_pcb.c
===================================================================
RCS file: /extern/Daten/Sources/repository/dragonflybsd/src/sys/netinet6/in6_pcb.c,v
retrieving revision 1.12
diff -u -r1.12 in6_pcb.c
--- netinet6/in6_pcb.c	31 Mar 2004 00:43:09 -0000	1.12
+++ netinet6/in6_pcb.c	5 Apr 2004 14:33:51 -0000
@@ -372,7 +372,7 @@
 		inp->in6p_flowinfo |=
 		    (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
 
-	in_pcbinsconnhash(inp);
+	in_pcbinsconnhash(inp, inp->inp_pcbinfo);
 	return (0);
 }
 
Index: netinet6/in6_proto.c
===================================================================
RCS file: /extern/Daten/Sources/repository/dragonflybsd/src/sys/netinet6/in6_proto.c,v
retrieving revision 1.5
diff -u -r1.5 in6_proto.c
--- netinet6/in6_proto.c	6 Mar 2004 01:58:56 -0000	1.5
+++ netinet6/in6_proto.c	5 Apr 2004 14:34:15 -0000
@@ -79,6 +79,7 @@
 #include <sys/mbuf.h>
 #include <sys/systm.h>
 #include <sys/sysctl.h>
+#include <sys/thread.h>
 
 #include <net/if.h>
 #include <net/radix.h>
Index: netinet6/in6_rmx.c
===================================================================
RCS file: /extern/Daten/Sources/repository/dragonflybsd/src/sys/netinet6/in6_rmx.c,v
retrieving revision 1.4
diff -u -r1.4 in6_rmx.c
--- netinet6/in6_rmx.c	7 Jan 2004 11:07:04 -0000	1.4
+++ netinet6/in6_rmx.c	5 Apr 2004 14:34:32 -0000
@@ -83,6 +83,7 @@
 #include <sys/socketvar.h>
 #include <sys/mbuf.h>
 #include <sys/syslog.h>
+#include <sys/thread.h>
 
 #include <net/if.h>
 #include <net/route.h>




More information about the Bugs mailing list