mirror of https://github.com/OpenIPC/firmware.git
124 lines
3.5 KiB
Diff
124 lines
3.5 KiB
Diff
diff -drupN a/net/ipv4/tcp.c b/net/ipv4/tcp.c
|
|
--- a/net/ipv4/tcp.c 2018-08-06 17:23:04.000000000 +0300
|
|
+++ b/net/ipv4/tcp.c 2022-06-12 05:28:14.000000000 +0300
|
|
@@ -538,6 +538,12 @@ unsigned int tcp_poll(struct file *file,
|
|
|
|
if (tp->urg_data & TCP_URG_VALID)
|
|
mask |= POLLPRI;
|
|
+ } else if (state == TCP_SYN_SENT && inet_sk(sk)->defer_connect) {
|
|
+ /* Active TCP fastopen socket with defer_connect
|
|
+ * Return POLLOUT so application can call write()
|
|
+ * in order for kernel to generate SYN+data
|
|
+ */
|
|
+ mask |= POLLOUT | POLLWRNORM;
|
|
}
|
|
/* This barrier is coupled with smp_wmb() in tcp_reset() */
|
|
smp_rmb();
|
|
@@ -1079,6 +1085,7 @@ static int tcp_sendmsg_fastopen(struct s
|
|
int *copied, size_t size)
|
|
{
|
|
struct tcp_sock *tp = tcp_sk(sk);
|
|
+ struct inet_sock *inet = inet_sk(sk);
|
|
struct sockaddr *uaddr = msg->msg_name;
|
|
int err, flags;
|
|
|
|
@@ -1096,11 +1103,26 @@ static int tcp_sendmsg_fastopen(struct s
|
|
tp->fastopen_req->data = msg;
|
|
tp->fastopen_req->size = size;
|
|
|
|
+ if (inet->defer_connect) {
|
|
+ err = tcp_connect(sk);
|
|
+ /* Same failure procedure as in tcp_v4/6_connect */
|
|
+ if (err) {
|
|
+ tcp_set_state(sk, TCP_CLOSE);
|
|
+ inet->inet_dport = 0;
|
|
+ sk->sk_route_caps = 0;
|
|
+ }
|
|
+ }
|
|
flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
|
|
err = __inet_stream_connect(sk->sk_socket, uaddr,
|
|
msg->msg_namelen, flags);
|
|
- *copied = tp->fastopen_req->copied;
|
|
- tcp_free_fastopen_req(tp);
|
|
+ /* fastopen_req could already be freed in __inet_stream_connect
|
|
+ * if the connection times out or gets rst
|
|
+ */
|
|
+ if (tp->fastopen_req) {
|
|
+ *copied = tp->fastopen_req->copied;
|
|
+ tcp_free_fastopen_req(tp);
|
|
+ inet->defer_connect = 0;
|
|
+ }
|
|
return err;
|
|
}
|
|
|
|
@@ -1118,7 +1140,7 @@ int tcp_sendmsg(struct sock *sk, struct
|
|
lock_sock(sk);
|
|
|
|
flags = msg->msg_flags;
|
|
- if ((flags & MSG_FASTOPEN) && !tp->repair) {
|
|
+ if (unlikely(flags & MSG_FASTOPEN || inet_sk(sk)->defer_connect)) {
|
|
err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size);
|
|
if (err == -EINPROGRESS && copied_syn > 0)
|
|
goto out;
|
|
@@ -2300,7 +2322,6 @@ int tcp_disconnect(struct sock *sk, int
|
|
tp->snd_cwnd_cnt = 0;
|
|
tp->window_clamp = 0;
|
|
tcp_set_ca_state(sk, TCP_CA_Open);
|
|
- tp->is_sack_reneg = 0;
|
|
tcp_clear_retrans(tp);
|
|
inet_csk_delack_init(sk);
|
|
/* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0
|
|
@@ -2314,6 +2335,10 @@ int tcp_disconnect(struct sock *sk, int
|
|
sk->sk_rx_dst = NULL;
|
|
tcp_saved_syn_free(tp);
|
|
|
|
+ /* Clean up fastopen related fields */
|
|
+ tcp_free_fastopen_req(tp);
|
|
+ inet->defer_connect = 0;
|
|
+
|
|
WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);
|
|
|
|
if (sk->sk_frag.page) {
|
|
@@ -2688,6 +2713,18 @@ static int do_tcp_setsockopt(struct sock
|
|
err = -EINVAL;
|
|
}
|
|
break;
|
|
+ case TCP_FASTOPEN_CONNECT:
|
|
+ if (val > 1 || val < 0) {
|
|
+ err = -EINVAL;
|
|
+ } else if (sysctl_tcp_fastopen & TFO_CLIENT_ENABLE) {
|
|
+ if (sk->sk_state == TCP_CLOSE)
|
|
+ tp->fastopen_connect = val;
|
|
+ else
|
|
+ err = -EINVAL;
|
|
+ } else {
|
|
+ err = -EOPNOTSUPP;
|
|
+ }
|
|
+ break;
|
|
case TCP_TIMESTAMP:
|
|
if (!tp->repair)
|
|
err = -EPERM;
|
|
@@ -3001,6 +3038,10 @@ static int do_tcp_getsockopt(struct sock
|
|
val = icsk->icsk_accept_queue.fastopenq.max_qlen;
|
|
break;
|
|
|
|
+ case TCP_FASTOPEN_CONNECT:
|
|
+ val = tp->fastopen_connect;
|
|
+ break;
|
|
+
|
|
case TCP_TIMESTAMP:
|
|
val = tcp_time_stamp + tp->tsoffset;
|
|
break;
|
|
@@ -3276,7 +3317,11 @@ EXPORT_SYMBOL_GPL(tcp_abort);
|
|
|
|
extern struct tcp_congestion_ops tcp_reno;
|
|
|
|
+#ifdef CONFIG_BASE_SMALL
|
|
+static __initdata unsigned long thash_entries = 16;
|
|
+#else
|
|
static __initdata unsigned long thash_entries;
|
|
+#endif
|
|
static int __init set_thash_entries(char *str)
|
|
{
|
|
ssize_t ret;
|