Lines Matching +full:fail +full:- +full:fast
1 /*-
2 * Copyright (c) 2015-2017 Patrick Kelsey
28 * This is an implementation of TCP Fast Open (TFO) [RFC7413]. To include
34 * The generated TFO cookies are the 64-bit output of
35 * SipHash24(key=<16-byte-key>, msg=<client-ip>). Multiple concurrent valid
36 * keys are supported so that time-based rolling cookie invalidation
41 * options TCP_RFC7413_MAX_KEYS=<num-keys>
45 * supports a pre-shared key (PSK) mode of operation in which the TFO server
55 * client-supplied cookie to equal SipHash24(key=<16-byte-psk>,
56 * msg=<cookie-sent-to-client>).
58 * Multiple concurrent valid pre-shared keys are supported so that
59 * time-based rolling PSK invalidation policies can be implemented in the
60 * system. The default number of concurrent pre-shared keys is 2. This can
63 * options TCP_RFC7413_MAX_PSKS=<num-psks>
66 * The following TFO-specific sysctls are defined:
69 * When non-zero, all client-supplied TFO cookies will be considered to
73 * When this and net.inet.tcp.fastopen.server_enable are non-zero, a new
101 * The maximum number of pre-shared keys supported.
107 * The current number of pre-shared keys installed.
114 * forced to be non-TFO for this many seconds. Note that the path
121 * When non-zero, pre-shared key (PSK) mode is enabled for all TFO
123 * pre-shared keys are removed.
128 * keys and pre-shared keys are removed. On the transition from
129 * disabled to enabled, if net.inet.tcp.fastopen.autokey is non-zero and
140 * Install a new pre-shared key by writing net.inet.tcp.fastopen.keylen
150 * For passively-created sockets, the TCP_FASTOPEN socket option can be
153 * back to using a non-TFO SYN|ACK will have the TCP_FASTOPEN socket option
157 * that can be in the SYN_RECEIVED state on a per listen-socket basis.
159 * serviced as non-TFO requests. Without such a limit, given a valid TFO
206 * Because a PSK-mode setsockopt() uses tcpcb.t_tfo_cookie.client to hold
262 SYSCTL_NODE(_net_inet_tcp, OID_AUTO, fastopen, CTLFLAG_RW, 0, "TCP Fast Open");
268 "Accept any non-empty cookie");
276 "Number of seconds between auto-generation of a new key; zero disables");
296 "Enable/disable TCP Fast Open client functionality");
308 "Maximum number of pre-shared keys supported");
320 "Number of pre-shared keys installed");
335 "Enable/disable TCP Fast Open server pre-shared key mode");
342 "Enable/disable TCP Fast Open server functionality");
354 "Install a new pre-shared key");
384 #define CCB_LOCK(ccb) mtx_lock(&(ccb)->ccb_mtx)
385 #define CCB_UNLOCK(ccb) mtx_unlock(&(ccb)->ccb_mtx)
386 #define CCB_LOCK_ASSERT(ccb) mtx_assert(&(ccb)->ccb_mtx, MA_OWNED)
402 V_tcp_fastopen_keys.newest = TCP_FASTOPEN_MAX_KEYS - 1; in tcp_fastopen_init()
403 V_tcp_fastopen_keys.newest_psk = TCP_FASTOPEN_MAX_PSKS - 1; in tcp_fastopen_init()
405 /* May already be non-zero if kernel tunable was set */ in tcp_fastopen_init()
410 /* May already be non-zero if kernel tunable was set */ in tcp_fastopen_init()
418 V_tcp_fastopen_ccache.mask = V_tcp_fastopen_ccache.buckets - 1; in tcp_fastopen_init()
434 V_tcp_fastopen_ccache.base[i].ccb_num_entries = -1; in tcp_fastopen_init()
446 * present in each UMA per-CPU cache for this zone. in tcp_fastopen_init()
464 mtx_destroy(&ccb->ccb_mtx); in tcp_fastopen_destroy()
481 * are "pending" (i.e., in the SYN-RCVD state). This counter is
482 * heap-allocated because the connections may decrement it upon
556 CURVNET_SET(ctx->v);
558 callout_reset(&ctx->c, V_tcp_fastopen_autokey * hz,
572 switch (inc->inc_flags & INC_ISIPV6) {
575 SipHash_Update(&ctx, &inc->inc_faddr, sizeof(inc->inc_faddr));
580 SipHash_Update(&ctx, &inc->inc6_faddr, sizeof(inc->inc6_faddr));
623 psk_index = TCP_FASTOPEN_MAX_PSKS - 1;
625 psk_index--;
637 * -1 the cookie is invalid and no valid cookie is available
667 return -1; in tcp_fastopen_check_cookie()
680 rv = -1; in tcp_fastopen_check_cookie()
698 key_index = TCP_FASTOPEN_MAX_KEYS - 1; in tcp_fastopen_check_cookie()
700 key_index--; in tcp_fastopen_check_cookie()
719 if (error == 0 && req->newptr) {
747 if (error == 0 && req->newptr) {
749 /* enabled -> disabled */
753 TCP_FASTOPEN_MAX_PSKS - 1;
757 /* disabled -> enabled */
774 if (error == 0 && req->newptr) {
776 /* enabled -> disabled */
779 V_tcp_fastopen_keys.newest = TCP_FASTOPEN_MAX_KEYS - 1;
784 TCP_FASTOPEN_MAX_PSKS - 1;
788 /* disabled -> enabled */
811 if (req->oldptr != NULL || req->oldlen != 0)
813 if (req->newptr == NULL)
815 if (req->newlen != sizeof(newkey))
834 if (req->oldptr != NULL || req->oldlen != 0)
836 if (req->newptr == NULL)
838 if (req->newlen != sizeof(newpsk))
861 if (error == 0 && req->newptr) {
888 if (error == 0 && req->newptr) {
890 /* enabled -> disabled */
893 KASSERT(ccb->ccb_num_entries > -1,
894 ("%s: ccb->ccb_num_entries %d is negative",
895 __func__, ccb->ccb_num_entries));
900 /* disabled -> enabled */
904 KASSERT(TAILQ_EMPTY(&ccb->ccb_entries),
905 ("%s: ccb->ccb_entries not empty", __func__));
906 KASSERT(ccb->ccb_num_entries == -1,
907 ("%s: ccb->ccb_num_entries %d not -1", __func__,
908 ccb->ccb_num_entries));
909 ccb->ccb_num_entries = 0; /* enable bucket */
928 * cookie requests. Therefore, we leave tp->t_maxseg at in tcp_fastopen_connect()
929 * the default value instead of calling tcp_mss(tp, -1) in tcp_fastopen_connect()
930 * and we set tp->snd_wnd as if there is a cache hit. in tcp_fastopen_connect()
932 tp->snd_wnd = tp->t_maxseg; in tcp_fastopen_connect()
943 inp = tp->t_inpcb; in tcp_fastopen_connect()
944 cce = tcp_fastopen_ccache_lookup(&inp->inp_inc, &ccb); in tcp_fastopen_connect()
946 if (cce->disable_time == 0) { in tcp_fastopen_connect()
947 if ((cce->cookie_len > 0) && in tcp_fastopen_connect()
948 (tp->t_tfo_client_cookie_len == in tcp_fastopen_connect()
952 tp->t_tfo_cookie.client, in tcp_fastopen_connect()
953 cce->cookie, cce->cookie_len); in tcp_fastopen_connect()
955 tp->t_tfo_client_cookie_len = cce->cookie_len; in tcp_fastopen_connect()
956 memcpy(tp->t_tfo_cookie.client, cce->cookie, in tcp_fastopen_connect()
957 cce->cookie_len); in tcp_fastopen_connect()
959 server_mss = cce->server_mss; in tcp_fastopen_connect()
961 if (tp->t_tfo_client_cookie_len == in tcp_fastopen_connect()
963 tp->t_tfo_client_cookie_len = in tcp_fastopen_connect()
965 memcpy(tp->t_tfo_cookie.client, &psk_cookie, in tcp_fastopen_connect()
968 tcp_mss(tp, server_mss ? server_mss : -1); in tcp_fastopen_connect()
969 tp->snd_wnd = tp->t_maxseg; in tcp_fastopen_connect()
973 * possibly re-enable. in tcp_fastopen_connect()
976 if (now - cce->disable_time > in tcp_fastopen_connect()
979 * Re-enable path. Force a TFO cookie in tcp_fastopen_connect()
984 cce->disable_time = 0; in tcp_fastopen_connect()
985 cce->server_mss = 0; in tcp_fastopen_connect()
986 cce->cookie_len = 0; in tcp_fastopen_connect()
988 * tp->t_tfo... cookie details are already in tcp_fastopen_connect()
996 tp->t_flags &= ~TF_FASTOPEN; in tcp_fastopen_connect()
999 tcp_mss(tp, -1); in tcp_fastopen_connect()
1002 * a TFO cookie request or disabling TFO - either in tcp_fastopen_connect()
1012 tcp_mss(tp, -1); in tcp_fastopen_connect()
1025 struct in_conninfo *inc = &tp->t_inpcb->inp_inc; in tcp_fastopen_disable_path()
1031 cce->server_mss = 0; in tcp_fastopen_disable_path()
1032 cce->cookie_len = 0; in tcp_fastopen_disable_path()
1037 if (cce->disable_time == 0) in tcp_fastopen_disable_path()
1038 cce->disable_time = getsbinuptime(); in tcp_fastopen_disable_path()
1045 tp->t_flags &= ~TF_FASTOPEN; in tcp_fastopen_disable_path()
1053 struct in_conninfo *inc = &tp->t_inpcb->inp_inc; in tcp_fastopen_update_cache()
1062 cce->server_mss = mss; in tcp_fastopen_update_cache()
1063 cce->cookie_len = cookie_len; in tcp_fastopen_update_cache()
1064 memcpy(cce->cookie, cookie, cookie_len); in tcp_fastopen_update_cache()
1065 cce->disable_time = 0; in tcp_fastopen_update_cache()
1068 cce->server_mss = 0; in tcp_fastopen_update_cache()
1069 cce->cookie_len = 0; in tcp_fastopen_update_cache()
1074 if (cce->disable_time == 0) in tcp_fastopen_update_cache()
1075 cce->disable_time = getsbinuptime(); in tcp_fastopen_update_cache()
1095 hash = jenkins_hash32((uint32_t *)&inc->inc_ie.ie_dependladdr, 4,
1097 hash = jenkins_hash32((uint32_t *)&inc->inc_ie.ie_dependfaddr, 4,
1099 last_word = inc->inc_fport;
1108 TAILQ_FOREACH(cce, &ccb->ccb_entries, cce_link)
1109 if ((!(cce->af == AF_INET6) == !(inc->inc_flags & INC_ISIPV6)) &&
1110 (cce->server_port == inc->inc_ie.ie_fport) &&
1111 (((cce->af == AF_INET) &&
1112 (cce->cce_client_ip.v4.s_addr == inc->inc_laddr.s_addr) &&
1113 (cce->cce_server_ip.v4.s_addr == inc->inc_faddr.s_addr)) ||
1114 ((cce->af == AF_INET6) &&
1115 IN6_ARE_ADDR_EQUAL(&cce->cce_client_ip.v6, &inc->inc6_laddr) &&
1116 IN6_ARE_ADDR_EQUAL(&cce->cce_server_ip.v6, &inc->inc6_faddr))))
1131 * 3. Fail
1137 if (ccb->ccb_num_entries < V_tcp_fastopen_ccache.bucket_limit)
1142 * At bucket limit, or out of memory - reclaim last
1145 cce = TAILQ_LAST(&ccb->ccb_entries, bucket_entries);
1151 TAILQ_REMOVE(&ccb->ccb_entries, cce, cce_link);
1153 ccb->ccb_num_entries++;
1155 TAILQ_INSERT_HEAD(&ccb->ccb_entries, cce, cce_link);
1156 cce->af = (inc->inc_flags & INC_ISIPV6) ? AF_INET6 : AF_INET;
1157 if (cce->af == AF_INET) {
1158 cce->cce_client_ip.v4 = inc->inc_laddr;
1159 cce->cce_server_ip.v4 = inc->inc_faddr;
1161 cce->cce_client_ip.v6 = inc->inc6_laddr;
1162 cce->cce_server_ip.v6 = inc->inc6_faddr;
1164 cce->server_port = inc->inc_fport;
1168 cce->server_mss = mss;
1169 cce->cookie_len = cookie_len;
1170 memcpy(cce->cookie, cookie, cookie_len);
1171 cce->disable_time = 0;
1174 cce->server_mss = 0;
1175 cce->cookie_len = 0;
1176 cce->disable_time = getsbinuptime();
1191 TAILQ_FOREACH_SAFE(cce, &ccb->ccb_entries, cce_link, cce_tmp) {
1196 KASSERT(ccb->ccb_num_entries <= (int)limit,
1197 ("%s: ccb->ccb_num_entries %d exceeds limit %d", __func__,
1198 ccb->ccb_num_entries, limit));
1200 KASSERT(TAILQ_EMPTY(&ccb->ccb_entries),
1201 ("%s: ccb->ccb_entries not empty", __func__));
1202 ccb->ccb_num_entries = -1; /* disable bucket */
1214 TAILQ_REMOVE(&ccb->ccb_entries, cce, cce_link);
1215 ccb->ccb_num_entries--;
1235 if (jailed_without_vnet(curthread->td_ucred) != 0)
1239 if (curthread->td_ucred->cr_uid != 0)
1246 if (ccb->ccb_num_entries > 0)
1247 num_entries += ccb->ccb_num_entries;
1261 TAILQ_FOREACH(cce, &ccb->ccb_entries, cce_link) {
1262 if (cce->disable_time != 0) {
1263 duration = now - cce->disable_time;
1265 duration = limit - duration;
1271 "%-20s %-20s %5u %5u ",
1272 inet_ntop(cce->af, &cce->cce_client_ip,
1274 inet_ntop(cce->af, &cce->cce_server_ip,
1276 ntohs(cce->server_port),
1277 cce->server_mss);
1282 for (j = 0; j < cce->cookie_len; j++)
1283 sbuf_printf(&sb, "%02x", cce->cookie[j]);