mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-19 23:06:11 +07:00
Merge branch 'tcp_fast_open_synack_fin'
Eric Dumazet says: ==================== tcp: fastopen: accept data/FIN present in SYNACK Implements RFC 7413 (TCP Fast Open) 4.2.2, accepting payload and/or FIN in SYNACK messages, and prepare removal of SYN flag in tcp_recvmsg() ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ef44967850
@ -1437,6 +1437,7 @@ void tcp_free_fastopen_req(struct tcp_sock *tp);
|
||||
|
||||
extern struct tcp_fastopen_context __rcu *tcp_fastopen_ctx;
|
||||
int tcp_fastopen_reset_cipher(void *key, unsigned int len);
|
||||
void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb);
|
||||
struct sock *tcp_try_fastopen(struct sock *sk, struct sk_buff *skb,
|
||||
struct request_sock *req,
|
||||
struct tcp_fastopen_cookie *foc,
|
||||
|
@ -1466,8 +1466,10 @@ static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
|
||||
|
||||
while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) {
|
||||
offset = seq - TCP_SKB_CB(skb)->seq;
|
||||
if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)
|
||||
if (unlikely(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)) {
|
||||
pr_err_once("%s: found a SYN, please report !\n", __func__);
|
||||
offset--;
|
||||
}
|
||||
if (offset < skb->len || (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)) {
|
||||
*off = offset;
|
||||
return skb;
|
||||
@ -1657,8 +1659,10 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
|
||||
break;
|
||||
|
||||
offset = *seq - TCP_SKB_CB(skb)->seq;
|
||||
if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)
|
||||
if (unlikely(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)) {
|
||||
pr_err_once("%s: found a SYN, please report !\n", __func__);
|
||||
offset--;
|
||||
}
|
||||
if (offset < skb->len)
|
||||
goto found_ok_skb;
|
||||
if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
|
||||
|
@ -124,6 +124,38 @@ static bool tcp_fastopen_cookie_gen(struct request_sock *req,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* If an incoming SYN or SYNACK frame contains a payload and/or FIN,
|
||||
* queue this additional data / FIN.
|
||||
*/
|
||||
void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
|
||||
if (TCP_SKB_CB(skb)->end_seq == tp->rcv_nxt)
|
||||
return;
|
||||
|
||||
skb = skb_clone(skb, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
skb_dst_drop(skb);
|
||||
__skb_pull(skb, tcp_hdrlen(skb));
|
||||
skb_set_owner_r(skb, sk);
|
||||
|
||||
TCP_SKB_CB(skb)->seq++;
|
||||
TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_SYN;
|
||||
|
||||
tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
|
||||
__skb_queue_tail(&sk->sk_receive_queue, skb);
|
||||
tp->syn_data_acked = 1;
|
||||
|
||||
/* u64_stats_update_begin(&tp->syncp) not needed here,
|
||||
* as we certainly are not changing upper 32bit value (0)
|
||||
*/
|
||||
tp->bytes_received = skb->len;
|
||||
}
|
||||
|
||||
static struct sock *tcp_fastopen_create_child(struct sock *sk,
|
||||
struct sk_buff *skb,
|
||||
struct dst_entry *dst,
|
||||
@ -132,7 +164,6 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk,
|
||||
struct tcp_sock *tp;
|
||||
struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;
|
||||
struct sock *child;
|
||||
u32 end_seq;
|
||||
bool own_req;
|
||||
|
||||
req->num_retrans = 0;
|
||||
@ -178,35 +209,11 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk,
|
||||
tcp_init_metrics(child);
|
||||
tcp_init_buffer_space(child);
|
||||
|
||||
/* Queue the data carried in the SYN packet.
|
||||
* We used to play tricky games with skb_get().
|
||||
* With lockless listener, it is a dead end.
|
||||
* Do not think about it.
|
||||
*
|
||||
* XXX (TFO) - we honor a zero-payload TFO request for now,
|
||||
* (any reason not to?) but no need to queue the skb since
|
||||
* there is no data. How about SYN+FIN?
|
||||
*/
|
||||
end_seq = TCP_SKB_CB(skb)->end_seq;
|
||||
if (end_seq != TCP_SKB_CB(skb)->seq + 1) {
|
||||
struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
|
||||
tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
|
||||
|
||||
if (likely(skb2)) {
|
||||
skb_dst_drop(skb2);
|
||||
__skb_pull(skb2, tcp_hdrlen(skb));
|
||||
skb_set_owner_r(skb2, child);
|
||||
__skb_queue_tail(&child->sk_receive_queue, skb2);
|
||||
tp->syn_data_acked = 1;
|
||||
tcp_fastopen_add_skb(child, skb);
|
||||
|
||||
/* u64_stats_update_begin(&tp->syncp) not needed here,
|
||||
* as we certainly are not changing upper 32bit value (0)
|
||||
*/
|
||||
tp->bytes_received = end_seq - TCP_SKB_CB(skb)->seq - 1;
|
||||
} else {
|
||||
end_seq = TCP_SKB_CB(skb)->seq + 1;
|
||||
}
|
||||
}
|
||||
tcp_rsk(req)->rcv_nxt = tp->rcv_nxt = end_seq;
|
||||
tcp_rsk(req)->rcv_nxt = tp->rcv_nxt;
|
||||
/* tcp_conn_request() is sending the SYNACK,
|
||||
* and queues the child into listener accept queue.
|
||||
*/
|
||||
|
@ -5509,6 +5509,9 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
|
||||
tp->syn_data_acked = tp->syn_data;
|
||||
if (tp->syn_data_acked)
|
||||
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE);
|
||||
|
||||
tcp_fastopen_add_skb(sk, synack);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user