]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blobdiff - net/ipv4/tcp_output.c
net-tcp: Fast Open base
[mirror_ubuntu-hirsute-kernel.git] / net / ipv4 / tcp_output.c
index 03854abfd9d87f6a6adc5485a3f373c2b91df016..4849be76ccd646dc5a517a1089956aeb59dd44e5 100644 (file)
@@ -385,15 +385,17 @@ static inline bool tcp_urg_mode(const struct tcp_sock *tp)
 #define OPTION_MD5             (1 << 2)
 #define OPTION_WSCALE          (1 << 3)
 #define OPTION_COOKIE_EXTENSION        (1 << 4)
+#define OPTION_FAST_OPEN_COOKIE        (1 << 8)
 
 struct tcp_out_options {
-       u8 options;             /* bit field of OPTION_* */
+       u16 options;            /* bit field of OPTION_* */
+       u16 mss;                /* 0 to disable */
        u8 ws;                  /* window scale, 0 to disable */
        u8 num_sack_blocks;     /* number of SACK blocks to include */
        u8 hash_size;           /* bytes in hash_location */
-       u16 mss;                /* 0 to disable */
-       __u32 tsval, tsecr;     /* need to include OPTION_TS */
        __u8 *hash_location;    /* temporary pointer, overloaded */
+       __u32 tsval, tsecr;     /* need to include OPTION_TS */
+       struct tcp_fastopen_cookie *fastopen_cookie;    /* Fast open cookie */
 };
 
 /* The sysctl int routines are generic, so check consistency here.
@@ -442,7 +444,7 @@ static u8 tcp_cookie_size_check(u8 desired)
 static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
                              struct tcp_out_options *opts)
 {
-       u8 options = opts->options;     /* mungable copy */
+       u16 options = opts->options;    /* mungable copy */
 
        /* Having both authentication and cookies for security is redundant,
         * and there's certainly not enough room.  Instead, the cookie-less
@@ -564,6 +566,21 @@ static void tcp_options_write(__be32 *ptr, struct tcp_sock *tp,
 
                tp->rx_opt.dsack = 0;
        }
+
+       if (unlikely(OPTION_FAST_OPEN_COOKIE & options)) {
+               struct tcp_fastopen_cookie *foc = opts->fastopen_cookie;
+
+               *ptr++ = htonl((TCPOPT_EXP << 24) |
+                              ((TCPOLEN_EXP_FASTOPEN_BASE + foc->len) << 16) |
+                              TCPOPT_FASTOPEN_MAGIC);
+
+               memcpy(ptr, foc->val, foc->len);
+               if ((foc->len & 3) == 2) {
+                       u8 *align = ((u8 *)ptr) + foc->len;
+                       align[0] = align[1] = TCPOPT_NOP;
+               }
+               ptr += (foc->len + 3) >> 2;
+       }
 }
 
 /* Compute TCP options for SYN packets. This is not the final
@@ -838,7 +855,7 @@ static void tcp_tasklet_func(unsigned long data)
                if (!sock_owned_by_user(sk)) {
                        if ((1 << sk->sk_state) &
                            (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 |
-                            TCPF_CLOSING | TCPF_CLOSE_WAIT))
+                            TCPF_CLOSING | TCPF_CLOSE_WAIT | TCPF_LAST_ACK))
                                tcp_write_xmit(sk,
                                               tcp_current_mss(sk),
                                               0, 0,
@@ -868,7 +885,7 @@ void tcp_release_cb(struct sock *sk)
        if (test_and_clear_bit(TSQ_OWNED, &tp->tsq_flags)) {
                if ((1 << sk->sk_state) &
                    (TCPF_ESTABLISHED | TCPF_FIN_WAIT1 |
-                    TCPF_CLOSING | TCPF_CLOSE_WAIT))
+                    TCPF_CLOSING | TCPF_CLOSE_WAIT | TCPF_LAST_ACK))
                        tcp_write_xmit(sk,
                                       tcp_current_mss(sk),
                                       0, 0,