Send connects to the right processor.
authorJeffrey Hsu <hsu@dragonflybsd.org>
Sat, 10 Apr 2004 00:10:42 +0000 (00:10 +0000)
committerJeffrey Hsu <hsu@dragonflybsd.org>
Sat, 10 Apr 2004 00:10:42 +0000 (00:10 +0000)
sys/kern/uipc_msg.c
sys/netinet/in_pcb.c
sys/netinet/in_pcb.h
sys/netinet/ip_demux.c
sys/netinet/tcp_usrreq.c
sys/netinet/tcp_var.h
sys/netinet6/in6_pcb.c

index 4c619b1..b32e2ff 100644 (file)
@@ -27,7 +27,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $DragonFly: src/sys/kern/uipc_msg.c,v 1.6 2004/04/09 22:34:09 hsu Exp $
+ * $DragonFly: src/sys/kern/uipc_msg.c,v 1.7 2004/04/10 00:10:42 hsu Exp $
  */
 
 #include <sys/param.h>
@@ -139,7 +139,7 @@ so_pru_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
        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 69f50cf..49afc03 100644 (file)
@@ -33,7 +33,7 @@
  *
  *     @(#)in_pcb.c    8.4 (Berkeley) 5/24/95
  * $FreeBSD: src/sys/netinet/in_pcb.c,v 1.59.2.27 2004/01/02 04:06:42 ambrisko Exp $
- * $DragonFly: src/sys/netinet/in_pcb.c,v 1.16 2004/03/31 00:43:09 hsu Exp $
+ * $DragonFly: src/sys/netinet/in_pcb.c,v 1.17 2004/04/10 00:10:42 hsu Exp $
  */
 
 #include "opt_ipsec.h"
@@ -166,7 +166,7 @@ in_pcballoc(struct socket *so, struct inpcbinfo *pcbinfo)
                return (ENOBUFS);
        bzero((caddr_t)inp, sizeof *inp);
        inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
-       inp->inp_pcbinfo = pcbinfo;
+       inp->inp_pcbinfo = inp->inp_cpcbinfo = pcbinfo;
        inp->inp_socket = so;
 #ifdef IPSEC
        error = ipsec_init_policy(so, &inp->inp_sp);
@@ -523,7 +523,7 @@ in_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct thread *td)
        if ((error = in_pcbladdr(inp, nam, &if_sin)) != 0)
                return (error);
 
-       if (in_pcblookup_hash(inp->inp_pcbinfo, sin->sin_addr, sin->sin_port,
+       if (in_pcblookup_hash(inp->inp_cpcbinfo, sin->sin_addr, sin->sin_port,
            inp->inp_laddr.s_addr ? inp->inp_laddr : if_sin->sin_addr,
            inp->inp_lport, FALSE, NULL) != NULL) {
                return (EADDRINUSE);
@@ -910,7 +910,7 @@ in_pcblookup_hash(pcbinfo, faddr, fport_arg, laddr, lport_arg, wildcard, ifp)
 void
 in_pcbinsconnhash(struct inpcb *inp)
 {
-       struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
+       struct inpcbinfo *pcbinfo = inp->inp_cpcbinfo;
        struct inpcbhead *bucket;
        u_int32_t hashkey_faddr, hashkey_laddr;
 
index 480caea..3ed5622 100644 (file)
@@ -33,7 +33,7 @@
  *
  *     @(#)in_pcb.h    8.1 (Berkeley) 6/10/93
  * $FreeBSD: src/sys/netinet/in_pcb.h,v 1.32.2.7 2003/01/24 05:11:34 sam Exp $
- * $DragonFly: src/sys/netinet/in_pcb.h,v 1.9 2004/03/31 00:43:09 hsu Exp $
+ * $DragonFly: src/sys/netinet/in_pcb.h,v 1.10 2004/04/10 00:10:42 hsu Exp $
  */
 
 #ifndef _NETINET_IN_PCB_H_
@@ -138,6 +138,7 @@ struct inpcb {
 
        caddr_t inp_ppcb;               /* pointer to per-protocol pcb */
        struct  inpcbinfo *inp_pcbinfo; /* PCB list info */
+       struct  inpcbinfo *inp_cpcbinfo;/* back pointer for connection table */
        struct  socket *inp_socket;     /* back pointer to socket */
                                        /* list for this PCB's local port */
        int     inp_flags;              /* generic IP/datagram flags */
index df9ead0..db61674 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2003 Jeffrey Hsu
  * All rights reserved.
  *
- * $DragonFly: src/sys/netinet/ip_demux.c,v 1.17 2004/04/09 23:33:02 hsu Exp $
+ * $DragonFly: src/sys/netinet/ip_demux.c,v 1.18 2004/04/10 00:10:42 hsu Exp $
  */
 
 #include "opt_inet.h"
@@ -190,6 +190,13 @@ tcp_soport(struct socket *so, struct sockaddr *nam)
            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 324ecc8..2742f9d 100644 (file)
@@ -32,7 +32,7 @@
  *
  *     From: @(#)tcp_usrreq.c  8.2 (Berkeley) 1/3/94
  * $FreeBSD: src/sys/netinet/tcp_usrreq.c,v 1.51.2.17 2002/10/11 11:46:44 ume Exp $
- * $DragonFly: src/sys/netinet/tcp_usrreq.c,v 1.12 2004/04/10 00:07:16 hsu Exp $
+ * $DragonFly: src/sys/netinet/tcp_usrreq.c,v 1.13 2004/04/10 00:10:42 hsu Exp $
  */
 
 #include "opt_ipsec.h"
@@ -43,6 +43,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>
 #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>
@@ -695,47 +699,29 @@ struct pr_usrreqs tcp6_usrreqs = {
 };
 #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 &&
@@ -749,6 +735,7 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
                inp->inp_laddr = if_sin->sin_addr;
        inp->inp_faddr = sin->sin_addr;
        inp->inp_fport = sin->sin_port;
+       inp->inp_cpcbinfo = &tcbinfo[mycpu->gd_cpuid];
        in_pcbinsconnhash(inp);
 
        /* Compute window scaling to request.  */
@@ -785,6 +772,86 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
        return (0);
 }
 
+static void
+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);
+       lwkt_replymsg(&msg0->nm_lmsg, 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;
+#ifdef SMP
+       lwkt_port_t port;
+#endif
+
+       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);
+
+#ifdef SMP
+       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) {
+               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;
+                               in_pcbremwildcardhash(inp);
+                       }
+                       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);
+       } else
+#endif
+               error = tcp_connect_oncpu(tp, sin, if_sin);
+
+       return (error);
+}
+
 #ifdef INET6
 static int
 tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
@@ -812,7 +879,7 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
        error = in6_pcbladdr(inp, nam, &addr6);
        if (error)
                return error;
-       oinp = in6_pcblookup_hash(inp->inp_pcbinfo,
+       oinp = in6_pcblookup_hash(inp->inp_cpcbinfo,
                                  &sin6->sin6_addr, sin6->sin6_port,
                                  IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) ?
                                      addr6 : &inp->in6p_laddr,
index 2df5e99..d62f34a 100644 (file)
@@ -33,7 +33,7 @@
  *
  *     @(#)tcp_var.h   8.4 (Berkeley) 5/24/95
  * $FreeBSD: src/sys/netinet/tcp_var.h,v 1.56.2.13 2003/02/03 02:34:07 hsu Exp $
- * $DragonFly: src/sys/netinet/tcp_var.h,v 1.16 2004/04/07 17:01:25 dillon Exp $
+ * $DragonFly: src/sys/netinet/tcp_var.h,v 1.17 2004/04/10 00:10:42 hsu Exp $
  */
 
 #ifndef _NETINET_TCP_VAR_H_
@@ -373,6 +373,9 @@ extern      int ss_fltsz_local;
 
 int     tcp_addrcpu(in_addr_t faddr, in_port_t fport,
            in_addr_t laddr, in_port_t lport);
+struct lwkt_port *
+       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 bfb399a..a4b62ec 100644 (file)
@@ -1,5 +1,5 @@
 /*     $FreeBSD: src/sys/netinet6/in6_pcb.c,v 1.10.2.9 2003/01/24 05:11:35 sam Exp $   */
-/*     $DragonFly: src/sys/netinet6/in6_pcb.c,v 1.12 2004/03/31 00:43:09 hsu Exp $     */
+/*     $DragonFly: src/sys/netinet6/in6_pcb.c,v 1.13 2004/04/10 00:10:42 hsu Exp $     */
 /*     $KAME: in6_pcb.c,v 1.31 2001/05/21 05:45:10 jinmei Exp $        */
   
 /*
@@ -349,7 +349,7 @@ in6_pcbconnect(struct inpcb *inp, struct sockaddr *nam, struct thread *td)
        if ((error = in6_pcbladdr(inp, nam, &addr6)) != 0)
                return(error);
 
-       if (in6_pcblookup_hash(inp->inp_pcbinfo, &sin6->sin6_addr,
+       if (in6_pcblookup_hash(inp->inp_cpcbinfo, &sin6->sin6_addr,
                               sin6->sin6_port,
                              IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
                              ? addr6 : &inp->in6p_laddr,