From: Jeffrey Hsu Date: Sat, 10 Apr 2004 00:10:42 +0000 (+0000) Subject: Send connects to the right processor. X-Git-Tag: v2.0.1~11546 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/7fe56515c78f0ca5bf3bee601fd1cf82e9fd02bc Send connects to the right processor. --- diff --git a/sys/kern/uipc_msg.c b/sys/kern/uipc_msg.c index 4c619b1360..b32e2ff265 100644 --- a/sys/kern/uipc_msg.c +++ b/sys/kern/uipc_msg.c @@ -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 @@ -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; diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 69f50cfc11..49afc0312b 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -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; diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index 480caea18d..3ed5622491 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -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 */ diff --git a/sys/netinet/ip_demux.c b/sys/netinet/ip_demux.c index df9ead07c4..db61674264 100644 --- a/sys/netinet/ip_demux.c +++ b/sys/netinet/ip_demux.c @@ -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. */ diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 324ecc80f7..2742f9d7d4 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -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 #include #include +#include #include #include #include @@ -55,7 +56,10 @@ #include #include +#include + #include +#include #include #include @@ -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, diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 2df5e99977..d62f34a54b 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -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 *); diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c index bfb399aa7b..a4b62ec2cd 100644 --- a/sys/netinet6/in6_pcb.c +++ b/sys/netinet6/in6_pcb.c @@ -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,