Explicitly reallocate the inpcb cached route freed due to different
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 20 Dec 2008 03:13:45 +0000 (11:13 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Sat, 20 Dec 2008 12:30:24 +0000 (20:30 +0800)
rtentry CPU ownership, e.g. in tcp_connect(), so we could make sure
that a RTF_PRCLONING rtentry will be cloned.

sys/netinet/tcp_usrreq.c

index 1acefbc..92e6376 100644 (file)
@@ -903,6 +903,7 @@ tcp_connect_oncpu(struct tcpcb *tp, struct sockaddr_in *sin,
 {
        struct inpcb *inp = tp->t_inpcb, *oinp;
        struct socket *so = inp->inp_socket;
+       struct route *ro = &inp->inp_route;
        struct tcpcb *otp;
        struct rmxp_tao *taop;
        struct rmxp_tao tao_noncached;
@@ -928,6 +929,23 @@ tcp_connect_oncpu(struct tcpcb *tp, struct sockaddr_in *sin,
        inp->inp_cpcbinfo = &tcbinfo[mycpu->gd_cpuid];
        in_pcbinsconnhash(inp);
 
+       /*
+        * We are now on the inpcb's owner CPU, if the cached route was
+        * freed because the rtentry's owner CPU is not the current CPU
+        * (e.g. in tcp_connect()), then we try to reallocate it here with
+        * the hope that a rtentry may be cloned from a RTF_PRCLONING
+        * rtentry.
+        */
+       if (!(inp->inp_socket->so_options & SO_DONTROUTE) && /*XXX*/
+           ro->ro_rt == NULL) {
+               bzero(&ro->ro_dst, sizeof(struct sockaddr_in));
+               ro->ro_dst.sa_family = AF_INET;
+               ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
+               ((struct sockaddr_in *)&ro->ro_dst)->sin_addr =
+                       sin->sin_addr;
+               rtalloc(ro);
+       }
+
        tcp_create_timermsg(tp);
 
        /* Compute window scaling to request.  */
@@ -1033,7 +1051,7 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
                /*
                 * in_pcbladdr() may have allocated a route entry for us
                 * on the current CPU, but we need a route entry on the
-                * target CPU, so free it here.
+                * inpcb's owner CPU, so free it here.
                 */
                if (ro->ro_rt != NULL)
                        RTFREE(ro->ro_rt);