struct tcp_fastopen_cookie {
        s8      len;
        u8      val[TCP_FASTOPEN_COOKIE_MAX];
+       bool    exp;    /* In RFC6994 experimental option format */
 };
 
 /* This defines a selective acknowledgement block. */
 
 #define TCPOPT_SACK             5       /* SACK Block */
 #define TCPOPT_TIMESTAMP       8       /* Better RTT estimations/PAWS */
 #define TCPOPT_MD5SIG          19      /* MD5 Signature (RFC2385) */
+#define TCPOPT_FASTOPEN                34      /* Fast open (RFC7413) */
 #define TCPOPT_EXP             254     /* Experimental */
 /* Magic number to be after the option value for sharing TCP
  * experimental options. See draft-ietf-tcpm-experimental-options-00.txt
 #define TCPOLEN_SACK_PERM      2
 #define TCPOLEN_TIMESTAMP      10
 #define TCPOLEN_MD5SIG         18
+#define TCPOLEN_FASTOPEN_BASE  2
 #define TCPOLEN_EXP_FASTOPEN_BASE  4
 
 /* But this is what stacks really send out. */
 
        } else if (foc->len > 0) /* Client presents an invalid cookie */
                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENPASSIVEFAIL);
 
+       valid_foc.exp = foc->exp;
        *foc = valid_foc;
        return false;
 }
 
        return 0;
 }
 
+static void tcp_parse_fastopen_option(int len, const unsigned char *cookie,
+                                     bool syn, struct tcp_fastopen_cookie *foc,
+                                     bool exp_opt)
+{
+       /* Valid only in SYN or SYN-ACK with an even length.  */
+       if (!foc || !syn || len < 0 || (len & 1))
+               return;
+
+       if (len >= TCP_FASTOPEN_COOKIE_MIN &&
+           len <= TCP_FASTOPEN_COOKIE_MAX)
+               memcpy(foc->val, cookie, len);
+       else if (len != 0)
+               len = -1;
+       foc->len = len;
+       foc->exp = exp_opt;
+}
+
 /* Look for tcp options. Normally only called on SYN and SYNACK packets.
  * But, this can also be called on packets in the established flow when
  * the fast version below fails.
                                 */
                                break;
 #endif
+                       case TCPOPT_FASTOPEN:
+                               tcp_parse_fastopen_option(
+                                       opsize - TCPOLEN_FASTOPEN_BASE,
+                                       ptr, th->syn, foc, false);
+                               break;
+
                        case TCPOPT_EXP:
                                /* Fast Open option shares code 254 using a
-                                * 16 bits magic number. It's valid only in
-                                * SYN or SYN-ACK with an even size.
+                                * 16 bits magic number.
                                 */
-                               if (opsize < TCPOLEN_EXP_FASTOPEN_BASE ||
-                                   get_unaligned_be16(ptr) != TCPOPT_FASTOPEN_MAGIC ||
-                                   !foc || !th->syn || (opsize & 1))
-                                       break;
-                               foc->len = opsize - TCPOLEN_EXP_FASTOPEN_BASE;
-                               if (foc->len >= TCP_FASTOPEN_COOKIE_MIN &&
-                                   foc->len <= TCP_FASTOPEN_COOKIE_MAX)
-                                       memcpy(foc->val, ptr + 2, foc->len);
-                               else if (foc->len != 0)
-                                       foc->len = -1;
+                               if (opsize >= TCPOLEN_EXP_FASTOPEN_BASE &&
+                                   get_unaligned_be16(ptr) ==
+                                   TCPOPT_FASTOPEN_MAGIC)
+                                       tcp_parse_fastopen_option(opsize -
+                                               TCPOLEN_EXP_FASTOPEN_BASE,
+                                               ptr + 2, th->syn, foc, true);
                                break;
 
                        }
 
 
        if (unlikely(OPTION_FAST_OPEN_COOKIE & options)) {
                struct tcp_fastopen_cookie *foc = opts->fastopen_cookie;
+               u8 *p = (u8 *)ptr;
+               u32 len; /* Fast Open option length */
+
+               if (foc->exp) {
+                       len = TCPOLEN_EXP_FASTOPEN_BASE + foc->len;
+                       *ptr = htonl((TCPOPT_EXP << 24) | (len << 16) |
+                                    TCPOPT_FASTOPEN_MAGIC);
+                       p += TCPOLEN_EXP_FASTOPEN_BASE;
+               } else {
+                       len = TCPOLEN_FASTOPEN_BASE + foc->len;
+                       *p++ = TCPOPT_FASTOPEN;
+                       *p++ = len;
+               }
 
-               *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;
+               memcpy(p, foc->val, foc->len);
+               if ((len & 3) == 2) {
+                       p[foc->len] = TCPOPT_NOP;
+                       p[foc->len + 1] = TCPOPT_NOP;
                }
-               ptr += (foc->len + 3) >> 2;
+               ptr += (len + 3) >> 2;
        }
 }
 
                if (unlikely(!ireq->tstamp_ok))
                        remaining -= TCPOLEN_SACKPERM_ALIGNED;
        }
-       if (foc && foc->len >= 0) {
-               u32 need = TCPOLEN_EXP_FASTOPEN_BASE + foc->len;
+       if (foc != NULL && foc->len >= 0) {
+               u32 need = foc->len;
+
+               need += foc->exp ? TCPOLEN_EXP_FASTOPEN_BASE :
+                                  TCPOLEN_FASTOPEN_BASE;
                need = (need + 3) & ~3U;  /* Align to 32 bits */
                if (remaining >= need) {
                        opts->options |= OPTION_FAST_OPEN_COOKIE;