tcp timer: Remember tcpcb owner thread's msgport, so timer message could
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Wed, 13 May 2009 13:14:15 +0000 (21:14 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sun, 17 May 2009 08:20:53 +0000 (16:20 +0800)
be delivered to the correct msgport.

While I am here, move tcp timer message creation for TCP IPv6 socket from
tcp_newtcpcb() to tcp6_connect().

Preliminary IPv6 test done by hasso@

Dragonfly-issue: http://bugs.dragonflybsd.org/issue1361

sys/netinet/tcp_subr.c
sys/netinet/tcp_syncache.c
sys/netinet/tcp_timer.c
sys/netinet/tcp_timer.h
sys/netinet/tcp_usrreq.c

index c0f736d..7c08586 100644 (file)
@@ -713,18 +713,13 @@ tcp_newtcpcb(struct inpcb *inp)
        tp->tt_delack = &it->inp_tp_delack;
        tcp_inittimers(tp);
 
+       /*
+        * Zero out timer message.  We don't create it here,
+        * since the current CPU may not be the owner of this
+        * inpcb.
+        */
        tp->tt_msg = &it->inp_tp_timermsg;
-       if (isipv6) {
-               /* Don't mess with IPv6; always create timer message */
-               tcp_create_timermsg(tp);
-       } else {
-               /*
-                * Zero out timer message.  We don't create it here,
-                * since the current CPU may not be the owner of this
-                * inpcb.
-                */
-               bzero(tp->tt_msg, sizeof(*tp->tt_msg));
-       }
+       bzero(tp->tt_msg, sizeof(*tp->tt_msg));
 
        if (tcp_do_rfc1323)
                tp->t_flags = (TF_REQ_SCALE | TF_REQ_TSTMP);
index 727e354..8cd7ebd 100644 (file)
@@ -792,7 +792,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
         */
        if (sc->sc_rxtslot != 0)
                tp->snd_cwnd = tp->t_maxseg;
-       tcp_create_timermsg(tp);
+       tcp_create_timermsg(tp, &curthread->td_msgport);
        tcp_callout_reset(tp, tp->tt_keep, tcp_keepinit, tcp_timer_keep);
 
        tcpstat.tcps_accepts++;
index 1aeb860..1a74e28 100644 (file)
@@ -230,7 +230,7 @@ tcp_send_timermsg(struct tcpcb *tp, uint32_t task)
 
        tmsg->tt_tasks |= task;
        if (tmsg->tt_nmsg.nm_lmsg.ms_flags & MSGF_DONE)
-               lwkt_sendmsg(tcp_cport(mycpuid), &tmsg->tt_nmsg.nm_lmsg);
+               lwkt_sendmsg(tmsg->tt_msgport, &tmsg->tt_nmsg.nm_lmsg);
 }
 
 int    tcp_syn_backoff[TCP_MAXRXTSHIFT + 1] =
@@ -696,13 +696,14 @@ tcp_timer_handler(struct netmsg *nmsg)
 }
 
 void
-tcp_create_timermsg(struct tcpcb *tp)
+tcp_create_timermsg(struct tcpcb *tp, struct lwkt_port *msgport)
 {
        struct netmsg_tcp_timer *tmsg = tp->tt_msg;
 
        netmsg_init(&tmsg->tt_nmsg, &netisr_adone_rport,
                    MSGF_DROPABLE | MSGF_PRIORITY, tcp_timer_handler);
        tmsg->tt_cpuid = mycpuid;
+       tmsg->tt_msgport = msgport;
        tmsg->tt_tcb = tp;
        tmsg->tt_tasks = 0;
 }
index f3cfc96..30ad18f 100644 (file)
@@ -135,6 +135,7 @@ struct netmsg_tcp_timer {
        struct netmsg   tt_nmsg;
        struct tcpcb    *tt_tcb;
        int             tt_cpuid;               /* owner cpuid */
+       lwkt_port_t     tt_msgport;             /* owner msgport */
        uint32_t        tt_tasks;               /* pending tasks */
        uint32_t        tt_running_tasks;       /* running tasks */
        uint32_t        tt_prev_tasks;          /* prev pending tasks (debug) */
@@ -164,7 +165,8 @@ void        tcp_timer_rexmt(void *xtp);
 void   tcp_timer_delack(void *xtp);
 void   tcp_inittimers(struct tcpcb *);
 
-void   tcp_create_timermsg(struct tcpcb *);
+struct lwkt_port;
+void   tcp_create_timermsg(struct tcpcb *, struct lwkt_port *);
 void   tcp_destroy_timermsg(struct tcpcb *);
 
 #endif /* _KERNEL */
index a6159df..d0b27a2 100644 (file)
@@ -955,7 +955,11 @@ tcp_connect_oncpu(struct tcpcb *tp, struct sockaddr_in *sin,
                rtalloc(ro);
        }
 
-       tcp_create_timermsg(tp);
+       /*
+        * Create TCP timer message now; we are on the tcpcb's owner
+        * CPU/thread.
+        */
+       tcp_create_timermsg(tp, &curthread->td_msgport);
 
        /* Compute window scaling to request.  */
        while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
@@ -1128,6 +1132,9 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
                inp->in6p_flowinfo = sin6->sin6_flowinfo;
        in_pcbinsconnhash(inp);
 
+       /* NOTE: must be done in tcpcb's owner thread */
+       tcp_create_timermsg(tp, &curthread->td_msgport);
+
        /* Compute window scaling to request.  */
        while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
            (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.ssb_hiwat)