kernel - Replace zalloc zones with kmalloc for PCBs
[dragonfly.git] / sys / netinet / tcp_syncache.c
index f16ab8b..9ff269d 100644 (file)
 #define        IPSEC
 #endif /*FAST_IPSEC*/
 
-#include <vm/vm_zone.h>
-
 static int tcp_syncookies = 1;
 SYSCTL_INT(_net_inet_tcp, OID_AUTO, syncookies, CTLFLAG_RW,
     &tcp_syncookies, 0,
@@ -176,7 +174,6 @@ struct msgrec {
 static void syncache_timer_handler(netmsg_t);
 
 struct tcp_syncache {
-       struct  vm_zone *zone;
        u_int   hashsize;
        u_int   hashmask;
        u_int   bucket_limit;
@@ -279,8 +276,7 @@ syncache_free(struct syncache *sc)
                                  rt_mask(rt), rt->rt_flags, NULL);
                RTFREE(rt);
        }
-
-       zfree(tcp_syncache.zone, sc);
+       kfree(sc, M_SYNCACHE);
 }
 
 void
@@ -337,19 +333,10 @@ syncache_init(void)
                        syncache_percpu->mrec[i].msg.nm_mrec =
                            &syncache_percpu->mrec[i];
                        netmsg_init(&syncache_percpu->mrec[i].msg.nm_netmsg,
-                                   &syncache_null_rport, 0,
-                                   syncache_timer_handler);
+                                   NULL, &syncache_null_rport,
+                                   0, syncache_timer_handler);
                }
        }
-
-       /*
-        * Allocate the syncache entries.  Allow the zone to allocate one
-        * more entry than cache limit, so a new entry can bump out an
-        * older one.
-        */
-       tcp_syncache.zone = zinit("syncache", sizeof(struct syncache),
-           tcp_syncache.cache_limit * ncpus2, ZONE_INTERRUPT, 0);
-       tcp_syncache.cache_limit -= 1;
 }
 
 static void
@@ -628,6 +615,8 @@ syncache_unreach(struct in_conninfo *inc, struct tcphdr *th)
 
 /*
  * Build a new TCP socket structure from a syncache entry.
+ *
+ * This is called from the context of the SYN+ACK
  */
 static struct socket *
 syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
@@ -635,6 +624,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
        struct inpcb *inp = NULL, *linp;
        struct socket *so;
        struct tcpcb *tp;
+       lwkt_port_t port;
 #ifdef INET6
        const boolean_t isipv6 = sc->sc_inc.inc_isipv6;
 #else
@@ -657,11 +647,16 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
                goto abort;
        }
 
-       inp = so->so_pcb;
+       /*
+        * Set the protocol processing port for the socket to the current
+        * port (that the connection came in on).
+        */
+       sosetport(so, &curthread->td_msgport);
 
        /*
         * Insert new socket into hash list.
         */
+       inp = so->so_pcb;
        inp->inp_inc.inc_isipv6 = sc->sc_inc.inc_isipv6;
        if (isipv6) {
                inp->in6p_laddr = sc->sc_inc.inc6_laddr;
@@ -669,6 +664,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
 #ifdef INET6
                inp->inp_vflag &= ~INP_IPV6;
                inp->inp_vflag |= INP_IPV4;
+               inp->inp_flags &= ~IN6P_IPV6_V6ONLY;
 #endif
                inp->inp_laddr = sc->sc_inc.inc_laddr;
        }
@@ -748,6 +744,22 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
                }
        }
 
+       /*
+        * The current port should be in the context of the SYN+ACK and
+        * so should match the tcp address port.
+        *
+        * XXX we may be running on the netisr thread instead of a tcp
+        *     thread, in which case port will not match
+        *     curthread->td_msgport.
+        */
+       if (isipv6) {
+               port = tcp6_addrport();
+       } else {
+               port = tcp_addrport(inp->inp_faddr.s_addr, inp->inp_fport,
+                                   inp->inp_laddr.s_addr, inp->inp_lport);
+       }
+       /*KKASSERT(port == &curthread->td_msgport);*/
+
        tp = intotcpcb(inp);
        tp->t_state = TCPS_SYN_RECEIVED;
        tp->iss = sc->sc_iss;
@@ -772,16 +784,6 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
                tp->ts_recent = sc->sc_tsrecent;
                tp->ts_recent_age = ticks;
        }
-       if (sc->sc_flags & SCF_CC) {
-               /*
-                * Initialization of the tcpcb for transaction;
-                *   set SND.WND = SEG.WND,
-                *   initialize CCsend and CCrecv.
-                */
-               tp->t_flags |= TF_REQ_CC | TF_RCVD_CC;
-               tp->cc_send = sc->sc_cc_send;
-               tp->cc_recv = sc->sc_cc_recv;
-       }
        if (sc->sc_flags & SCF_SACK_PERMITTED)
                tp->t_flags |= TF_SACK_PERMITTED;
 
@@ -792,7 +794,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, port);
        tcp_callout_reset(tp, tp->tt_keep, tcp_keepinit, tcp_timer_keep);
 
        tcpstat.tcps_accepts++;
@@ -800,7 +802,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
 
 abort:
        if (so != NULL)
-               soaborta(so);
+               soabort_oncpu(so);
        return (NULL);
 }
 
@@ -889,7 +891,6 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
        struct syncache *sc = NULL;
        struct syncache_head *sch;
        struct mbuf *ipopts = NULL;
-       struct rmxp_tao *taop;
        int win;
 
        syncache_percpu = &tcp_syncache_percpu[mycpu->gd_cpuid];
@@ -952,15 +953,10 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
                return (1);
        }
 
-       /*
-        * This allocation is guaranteed to succeed because we
-        * preallocate one more syncache entry than cache_limit.
-        */
-       sc = zalloc(tcp_syncache.zone);
-
        /*
         * Fill in the syncache values.
         */
+       sc = kmalloc(sizeof(struct syncache), M_SYNCACHE, M_WAITOK|M_ZERO);
        sc->sc_tp = tp;
        sc->sc_inp_gencnt = tp->t_inpcb->inp_gencnt;
        sc->sc_ipopts = ipopts;
@@ -1003,80 +999,23 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
                        sc->sc_flags |= SCF_TIMESTAMP;
                }
                if (to->to_flags & TOF_SCALE) {
-                       int wscale = 0;
+                       int wscale = TCP_MIN_WINSHIFT;
 
                        /* Compute proper scaling value from buffer space */
                        while (wscale < TCP_MAX_WINSHIFT &&
-                           (TCP_MAXWIN << wscale) < so->so_rcv.ssb_hiwat)
+                           (TCP_MAXWIN << wscale) < so->so_rcv.ssb_hiwat) {
                                wscale++;
+                       }
                        sc->sc_request_r_scale = wscale;
                        sc->sc_requested_s_scale = to->to_requested_s_scale;
                        sc->sc_flags |= SCF_WINSCALE;
                }
        }
-       if (tcp_do_rfc1644) {
-               /*
-                * A CC or CC.new option received in a SYN makes
-                * it ok to send CC in subsequent segments.
-                */
-               if (to->to_flags & (TOF_CC | TOF_CCNEW)) {
-                       sc->sc_cc_recv = to->to_cc;
-                       sc->sc_cc_send = CC_INC(tcp_ccgen);
-                       sc->sc_flags |= SCF_CC;
-               }
-       }
        if (tcp_do_sack && (to->to_flags & TOF_SACK_PERMITTED))
                sc->sc_flags |= SCF_SACK_PERMITTED;
        if (tp->t_flags & TF_NOOPT)
                sc->sc_flags = SCF_NOOPT;
 
-       /*
-        * XXX
-        * We have the option here of not doing TAO (even if the segment
-        * qualifies) and instead fall back to a normal 3WHS via the syncache.
-        * This allows us to apply synflood protection to TAO-qualifying SYNs
-        * also. However, there should be a hueristic to determine when to
-        * do this, and is not present at the moment.
-        */
-
-       /*
-        * Perform TAO test on incoming CC (SEG.CC) option, if any.
-        * - compare SEG.CC against cached CC from the same host, if any.
-        * - if SEG.CC > chached value, SYN must be new and is accepted
-        *      immediately: save new CC in the cache, mark the socket
-        *      connected, enter ESTABLISHED state, turn on flag to
-        *      send a SYN in the next segment.
-        *      A virtual advertised window is set in rcv_adv to
-        *      initialize SWS prevention.  Then enter normal segment
-        *      processing: drop SYN, process data and FIN.
-        * - otherwise do a normal 3-way handshake.
-        */
-       taop = tcp_gettaocache(&sc->sc_inc);
-       if (to->to_flags & TOF_CC) {
-               if ((tp->t_flags & TF_NOPUSH) &&
-                   sc->sc_flags & SCF_CC &&
-                   taop != NULL && taop->tao_cc != 0 &&
-                   CC_GT(to->to_cc, taop->tao_cc)) {
-                       sc->sc_rxtslot = 0;
-                       so = syncache_socket(sc, *sop, m);
-                       if (so != NULL) {
-                               taop->tao_cc = to->to_cc;
-                               *sop = so;
-                       }
-                       syncache_free(sc);
-                       return (so != NULL);
-               }
-       } else {
-               /*
-                * No CC option, but maybe CC.NEW: invalidate cached value.
-                */
-               if (taop != NULL)
-                       taop->tao_cc = 0;
-       }
-       /*
-        * TAO test failed or there was no CC option,
-        *    do a standard 3-way handshake.
-        */
        if (syncache_respond(sc, m) == 0) {
                syncache_insert(sc, sch);
                tcpstat.tcps_sndacks++;
@@ -1130,7 +1069,6 @@ syncache_respond(struct syncache *sc, struct mbuf *m)
                optlen = TCPOLEN_MAXSEG +
                    ((sc->sc_flags & SCF_WINSCALE) ? 4 : 0) +
                    ((sc->sc_flags & SCF_TIMESTAMP) ? TCPOLEN_TSTAMP_APPA : 0) +
-                   ((sc->sc_flags & SCF_CC) ? TCPOLEN_CC_APPA * 2 : 0) +
                    ((sc->sc_flags & SCF_SACK_PERMITTED) ?
                        TCPOLEN_SACK_PERMITTED_ALIGNED : 0);
        }
@@ -1233,19 +1171,6 @@ syncache_respond(struct syncache *sc, struct mbuf *m)
                optp += TCPOLEN_TSTAMP_APPA;
        }
 
-       /*
-        * Send CC and CC.echo if we received CC from our peer.
-        */
-       if (sc->sc_flags & SCF_CC) {
-               u_int32_t *lp = (u_int32_t *)(optp);
-
-               *lp++ = htonl(TCPOPT_CC_HDR(TCPOPT_CC));
-               *lp++ = htonl(sc->sc_cc_send);
-               *lp++ = htonl(TCPOPT_CC_HDR(TCPOPT_CCECHO));
-               *lp   = htonl(sc->sc_cc_recv);
-               optp += TCPOLEN_CC_APPA * 2;
-       }
-
        if (sc->sc_flags & SCF_SACK_PERMITTED) {
                *((u_int32_t *)optp) = htonl(TCPOPT_SACK_PERMITTED_ALIGNED);
                optp += TCPOLEN_SACK_PERMITTED_ALIGNED;
@@ -1413,16 +1338,11 @@ syncookie_lookup(struct in_conninfo *inc, struct tcphdr *th, struct socket *so)
                return (NULL);
        data = data >> SYNCOOKIE_WNDBITS;
 
-       /*
-        * This allocation is guaranteed to succeed because we
-        * preallocate one more syncache entry than cache_limit.
-        */
-       sc = zalloc(tcp_syncache.zone);
-
        /*
         * Fill in the syncache values.
         * XXX duplicate code from syncache_add
         */
+       sc = kmalloc(sizeof(struct syncache), M_SYNCACHE, M_WAITOK|M_ZERO);
        sc->sc_ipopts = NULL;
        sc->sc_inc.inc_fport = inc->inc_fport;
        sc->sc_inc.inc_lport = inc->inc_lport;