]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
tcp: parse mptcp options contained in reset packets
authorFlorian Westphal <fw@strlen.de>
Thu, 10 Dec 2020 22:25:03 +0000 (14:25 -0800)
committerJakub Kicinski <kuba@kernel.org>
Tue, 15 Dec 2020 01:30:06 +0000 (17:30 -0800)
Because TCP-level resets only affect the subflow, there is a MPTCP
option to indicate that the MPTCP-level connection should be closed
immediately without a mptcp-level fin exchange.

This is the 'MPTCP fast close option'.  It can be carried on ack
segments or TCP resets.  In the latter case, its needed to parse mptcp
options also for reset packets so that MPTCP can act accordingly.

Next patch will add receive side fastclose support in MPTCP.

Acked-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/tcp.h
net/ipv4/tcp_input.c
net/ipv4/tcp_minisocks.c

index a62fb7f8a1e3c1e18c1bbf83e2b687ea40d709f7..b1a05f8b35f0cd000210fe49ff747fcb79f4b5c2 100644 (file)
@@ -611,7 +611,7 @@ void tcp_skb_collapse_tstamp(struct sk_buff *skb,
 /* tcp_input.c */
 void tcp_rearm_rto(struct sock *sk);
 void tcp_synack_rtt_meas(struct sock *sk, struct request_sock *req);
-void tcp_reset(struct sock *sk);
+void tcp_reset(struct sock *sk, struct sk_buff *skb);
 void tcp_skb_mark_lost_uncond_verify(struct tcp_sock *tp, struct sk_buff *skb);
 void tcp_fin(struct sock *sk);
 
index d6ad3b5c38e78715e85f1ea19ee9132f31b6656a..48ee476aa031f49b25be2bff4a794b92a96b6664 100644 (file)
@@ -4218,10 +4218,13 @@ static inline bool tcp_sequence(const struct tcp_sock *tp, u32 seq, u32 end_seq)
 }
 
 /* When we get a reset we do this. */
-void tcp_reset(struct sock *sk)
+void tcp_reset(struct sock *sk, struct sk_buff *skb)
 {
        trace_tcp_receive_reset(sk);
 
+       if (sk_is_mptcp(sk))
+               mptcp_incoming_options(sk, skb);
+
        /* We want the right error as BSD sees it (and indeed as we do). */
        switch (sk->sk_state) {
        case TCP_SYN_SENT:
@@ -5604,7 +5607,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
                                                  &tp->last_oow_ack_time))
                                tcp_send_dupack(sk, skb);
                } else if (tcp_reset_check(sk, skb)) {
-                       tcp_reset(sk);
+                       tcp_reset(sk, skb);
                }
                goto discard;
        }
@@ -5640,7 +5643,7 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
                }
 
                if (rst_seq_match)
-                       tcp_reset(sk);
+                       tcp_reset(sk, skb);
                else {
                        /* Disable TFO if RST is out-of-order
                         * and no data has been received
@@ -6077,7 +6080,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
                 */
 
                if (th->rst) {
-                       tcp_reset(sk);
+                       tcp_reset(sk, skb);
                        goto discard;
                }
 
@@ -6519,7 +6522,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb)
                        if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
                            after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
                                NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONDATA);
-                               tcp_reset(sk);
+                               tcp_reset(sk, skb);
                                return 1;
                        }
                }
index 495dda2449fe5a87f78b8b03f32328328c6b8a01..0055ae0a3bf840c737f5f61fb1ef683208387e32 100644 (file)
@@ -801,7 +801,7 @@ embryonic_reset:
                req->rsk_ops->send_reset(sk, skb);
        } else if (fastopen) { /* received a valid RST pkt */
                reqsk_fastopen_remove(sk, req, true);
-               tcp_reset(sk);
+               tcp_reset(sk, skb);
        }
        if (!fastopen) {
                inet_csk_reqsk_queue_drop(sk, req);