1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-03-09 15:40:20 +00:00

Update MPTCP

This commit is contained in:
Ycarus (Yannick Chabanois) 2022-04-26 17:01:24 +02:00
parent 7de4038cb0
commit b715716984

View file

@ -287,10 +287,10 @@ index 34c4436fd18f..828f79528b32 100644
union { union {
diff --git a/include/net/mptcp.h b/include/net/mptcp.h diff --git a/include/net/mptcp.h b/include/net/mptcp.h
new file mode 100644 new file mode 100644
index 000000000000..c90d1b53b9d4 index 000000000000..bb18dacc310f
--- /dev/null --- /dev/null
+++ b/include/net/mptcp.h +++ b/include/net/mptcp.h
@@ -0,0 +1,1540 @@ @@ -0,0 +1,1549 @@
+/* +/*
+ * MPTCP implementation + * MPTCP implementation
+ * + *
@ -1593,13 +1593,22 @@ index 000000000000..c90d1b53b9d4
+ mptcp_sub_close(sk, 0); + mptcp_sub_close(sk, 0);
+} +}
+ +
+static inline void mptcp_fallback_close(struct mptcp_cb *mpcb, +/* Returns true if all subflows were closed */
+static inline bool mptcp_fallback_close(struct mptcp_cb *mpcb,
+ struct sock *except) + struct sock *except)
+{ +{
+ /* It can happen that the meta is already closed. In that case, don't
+ * keep the subflow alive - close everything!
+ */
+ if (mpcb->meta_sk->sk_state == TCP_CLOSE)
+ except = NULL;
+
+ mptcp_sub_force_close_all(mpcb, except); + mptcp_sub_force_close_all(mpcb, except);
+ +
+ if (mpcb->pm_ops->close_session) + if (mpcb->pm_ops->close_session)
+ mpcb->pm_ops->close_session(mptcp_meta_sk(except)); + mpcb->pm_ops->close_session(mptcp_meta_sk(except));
+
+ return !except;
+} +}
+ +
+static inline bool mptcp_v6_is_v4_mapped(const struct sock *sk) +static inline bool mptcp_v6_is_v4_mapped(const struct sock *sk)
@ -2089,7 +2098,7 @@ index cb8ced4380a6..0aa0d10af2ce 100644
#define TCP_MIB_MAX __TCP_MIB_MAX #define TCP_MIB_MAX __TCP_MIB_MAX
struct tcp_mib { struct tcp_mib {
diff --git a/include/net/sock.h b/include/net/sock.h diff --git a/include/net/sock.h b/include/net/sock.h
index 079b5f6f13d8..8ae33ecd9d0a 100644 index 7f213cfcb3cc..c1be2daccb54 100644
--- a/include/net/sock.h --- a/include/net/sock.h
+++ b/include/net/sock.h +++ b/include/net/sock.h
@@ -821,6 +821,7 @@ enum sock_flags { @@ -821,6 +821,7 @@ enum sock_flags {
@ -2586,10 +2595,10 @@ index cf97f6339acb..cf48dc87a734 100644
#endif /* _TRACE_TCP_H */ #endif /* _TRACE_TCP_H */
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 63038eb23560..7150eb62db86 100644 index cb0631098f91..b9de598828e9 100644
--- a/include/uapi/linux/bpf.h --- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h
@@ -3438,6 +3438,7 @@ enum { @@ -3439,6 +3439,7 @@ enum {
BPF_TCP_LISTEN, BPF_TCP_LISTEN,
BPF_TCP_CLOSING, /* Now a valid state */ BPF_TCP_CLOSING, /* Now a valid state */
BPF_TCP_NEW_SYN_RECV, BPF_TCP_NEW_SYN_RECV,
@ -2626,11 +2635,11 @@ index 60e1241d4b77..ff6185b1d79f 100644
#endif #endif
diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h
new file mode 100644 new file mode 100644
index 000000000000..02078c80c846 index 000000000000..f268e9805fe1
--- /dev/null --- /dev/null
+++ b/include/uapi/linux/mptcp.h +++ b/include/uapi/linux/mptcp.h
@@ -0,0 +1,151 @@ @@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/* +/*
+ * Netlink API for Multipath TCP + * Netlink API for Multipath TCP
+ * + *
@ -2908,7 +2917,7 @@ index a03036456221..aebb337662c3 100644
IFF_ALLMULTI)); IFF_ALLMULTI));
diff --git a/net/core/filter.c b/net/core/filter.c diff --git a/net/core/filter.c b/net/core/filter.c
index d39518f691b4..fbb69a50b8a9 100644 index e16b2b5cda98..d038517091c6 100644
--- a/net/core/filter.c --- a/net/core/filter.c
+++ b/net/core/filter.c +++ b/net/core/filter.c
@@ -73,6 +73,7 @@ @@ -73,6 +73,7 @@
@ -2996,7 +3005,7 @@ index 5bdb3cd20d61..d430e46373f3 100644
struct sk_buff *list; struct sk_buff *list;
diff --git a/net/core/sock.c b/net/core/sock.c diff --git a/net/core/sock.c b/net/core/sock.c
index 57b7a10703c3..8d716113e273 100644 index c84f68bff7f5..44675ce7e8de 100644
--- a/net/core/sock.c --- a/net/core/sock.c
+++ b/net/core/sock.c +++ b/net/core/sock.c
@@ -135,6 +135,11 @@ @@ -135,6 +135,11 @@
@ -3031,7 +3040,17 @@ index 57b7a10703c3..8d716113e273 100644
} }
break; break;
@@ -1563,6 +1581,23 @@ int sock_getsockopt(struct socket *sock, int level, int optname, @@ -1135,7 +1153,8 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
if (!((sk->sk_type == SOCK_STREAM &&
sk->sk_protocol == IPPROTO_TCP) ||
(sk->sk_type == SOCK_DGRAM &&
- sk->sk_protocol == IPPROTO_UDP)))
+ sk->sk_protocol == IPPROTO_UDP)) ||
+ sock_flag(sk, SOCK_MPTCP))
ret = -ENOTSUPP;
} else if (sk->sk_family != PF_RDS) {
ret = -ENOTSUPP;
@@ -1563,6 +1582,23 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
*/ */
static inline void sock_lock_init(struct sock *sk) static inline void sock_lock_init(struct sock *sk)
{ {
@ -3055,7 +3074,7 @@ index 57b7a10703c3..8d716113e273 100644
if (sk->sk_kern_sock) if (sk->sk_kern_sock)
sock_lock_init_class_and_name( sock_lock_init_class_and_name(
sk, sk,
@@ -1611,8 +1646,12 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority, @@ -1611,8 +1647,12 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO); sk = kmem_cache_alloc(slab, priority & ~__GFP_ZERO);
if (!sk) if (!sk)
return sk; return sk;
@ -3070,7 +3089,7 @@ index 57b7a10703c3..8d716113e273 100644
} else } else
sk = kmalloc(prot->obj_size, priority); sk = kmalloc(prot->obj_size, priority);
@@ -1846,6 +1885,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) @@ -1846,6 +1886,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
atomic_set(&newsk->sk_zckey, 0); atomic_set(&newsk->sk_zckey, 0);
sock_reset_flag(newsk, SOCK_DONE); sock_reset_flag(newsk, SOCK_DONE);
@ -3479,7 +3498,7 @@ index 2b45d1455592..d2d2427e1883 100644
* Normal sockets get it right from inet_csk_route_child_sock() * Normal sockets get it right from inet_csk_route_child_sock()
*/ */
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 9f53d25e047e..a48d9b394b11 100644 index 4815cf72569e..61469ec77734 100644
--- a/net/ipv4/tcp.c --- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c
@@ -270,6 +270,7 @@ @@ -270,6 +270,7 @@
@ -3678,7 +3697,7 @@ index 9f53d25e047e..a48d9b394b11 100644
/* Send ACK now, if this read freed lots of space /* Send ACK now, if this read freed lots of space
* in our buffer. Certainly, new_window is new window. * in our buffer. Certainly, new_window is new window.
@@ -1688,7 +1758,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, @@ -1690,7 +1760,7 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
/* Clean up data we have read: This will do ACK frames. */ /* Clean up data we have read: This will do ACK frames. */
if (copied > 0) { if (copied > 0) {
tcp_recv_skb(sk, seq, &offset); tcp_recv_skb(sk, seq, &offset);
@ -3687,7 +3706,7 @@ index 9f53d25e047e..a48d9b394b11 100644
} }
return copied; return copied;
} }
@@ -1979,6 +2049,16 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, @@ -1981,6 +2051,16 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
lock_sock(sk); lock_sock(sk);
@ -3704,7 +3723,7 @@ index 9f53d25e047e..a48d9b394b11 100644
err = -ENOTCONN; err = -ENOTCONN;
if (sk->sk_state == TCP_LISTEN) if (sk->sk_state == TCP_LISTEN)
goto out; goto out;
@@ -2097,7 +2177,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, @@ -2099,7 +2179,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
} }
} }
@ -3713,7 +3732,7 @@ index 9f53d25e047e..a48d9b394b11 100644
if (copied >= target) { if (copied >= target) {
/* Do not sleep, just process backlog. */ /* Do not sleep, just process backlog. */
@@ -2189,7 +2269,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, @@ -2191,7 +2271,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
*/ */
/* Clean up data we have read: This will do ACK frames. */ /* Clean up data we have read: This will do ACK frames. */
@ -3722,7 +3741,7 @@ index 9f53d25e047e..a48d9b394b11 100644
release_sock(sk); release_sock(sk);
@@ -2248,8 +2328,11 @@ void tcp_set_state(struct sock *sk, int state) @@ -2250,8 +2330,11 @@ void tcp_set_state(struct sock *sk, int state)
switch (state) { switch (state) {
case TCP_ESTABLISHED: case TCP_ESTABLISHED:
@ -3735,7 +3754,7 @@ index 9f53d25e047e..a48d9b394b11 100644
break; break;
case TCP_CLOSE: case TCP_CLOSE:
@@ -2262,8 +2345,11 @@ void tcp_set_state(struct sock *sk, int state) @@ -2264,8 +2347,11 @@ void tcp_set_state(struct sock *sk, int state)
inet_put_port(sk); inet_put_port(sk);
/* fall through */ /* fall through */
default: default:
@ -3748,7 +3767,7 @@ index 9f53d25e047e..a48d9b394b11 100644
} }
/* Change state AFTER socket is unhashed to avoid closed /* Change state AFTER socket is unhashed to avoid closed
@@ -2295,9 +2381,10 @@ void tcp_set_state(struct sock *sk, int state) @@ -2297,9 +2383,10 @@ void tcp_set_state(struct sock *sk, int state)
[TCP_LISTEN] = TCP_CLOSE, [TCP_LISTEN] = TCP_CLOSE,
[TCP_CLOSING] = TCP_CLOSING, [TCP_CLOSING] = TCP_CLOSING,
[TCP_NEW_SYN_RECV] = TCP_CLOSE, /* should not happen ! */ [TCP_NEW_SYN_RECV] = TCP_CLOSE, /* should not happen ! */
@ -3760,7 +3779,7 @@ index 9f53d25e047e..a48d9b394b11 100644
{ {
int next = (int)new_state[sk->sk_state]; int next = (int)new_state[sk->sk_state];
int ns = next & TCP_STATE_MASK; int ns = next & TCP_STATE_MASK;
@@ -2327,7 +2414,7 @@ void tcp_shutdown(struct sock *sk, int how) @@ -2329,7 +2416,7 @@ void tcp_shutdown(struct sock *sk, int how)
TCPF_SYN_RECV | TCPF_CLOSE_WAIT)) { TCPF_SYN_RECV | TCPF_CLOSE_WAIT)) {
/* Clear out any half completed packets. FIN if needed. */ /* Clear out any half completed packets. FIN if needed. */
if (tcp_close_state(sk)) if (tcp_close_state(sk))
@ -3769,7 +3788,7 @@ index 9f53d25e047e..a48d9b394b11 100644
} }
} }
EXPORT_SYMBOL(tcp_shutdown); EXPORT_SYMBOL(tcp_shutdown);
@@ -2352,6 +2439,17 @@ void tcp_close(struct sock *sk, long timeout) @@ -2354,6 +2441,17 @@ void tcp_close(struct sock *sk, long timeout)
int data_was_unread = 0; int data_was_unread = 0;
int state; int state;
@ -3787,7 +3806,7 @@ index 9f53d25e047e..a48d9b394b11 100644
lock_sock(sk); lock_sock(sk);
sk->sk_shutdown = SHUTDOWN_MASK; sk->sk_shutdown = SHUTDOWN_MASK;
@@ -2396,7 +2494,7 @@ void tcp_close(struct sock *sk, long timeout) @@ -2398,7 +2496,7 @@ void tcp_close(struct sock *sk, long timeout)
/* Unread data was tossed, zap the connection. */ /* Unread data was tossed, zap the connection. */
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONCLOSE); NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPABORTONCLOSE);
tcp_set_state(sk, TCP_CLOSE); tcp_set_state(sk, TCP_CLOSE);
@ -3796,7 +3815,7 @@ index 9f53d25e047e..a48d9b394b11 100644
} else if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) { } else if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
/* Check zero linger _after_ checking for unread data. */ /* Check zero linger _after_ checking for unread data. */
sk->sk_prot->disconnect(sk, 0); sk->sk_prot->disconnect(sk, 0);
@@ -2470,7 +2568,7 @@ void tcp_close(struct sock *sk, long timeout) @@ -2472,7 +2570,7 @@ void tcp_close(struct sock *sk, long timeout)
struct tcp_sock *tp = tcp_sk(sk); struct tcp_sock *tp = tcp_sk(sk);
if (tp->linger2 < 0) { if (tp->linger2 < 0) {
tcp_set_state(sk, TCP_CLOSE); tcp_set_state(sk, TCP_CLOSE);
@ -3805,7 +3824,7 @@ index 9f53d25e047e..a48d9b394b11 100644
__NET_INC_STATS(sock_net(sk), __NET_INC_STATS(sock_net(sk),
LINUX_MIB_TCPABORTONLINGER); LINUX_MIB_TCPABORTONLINGER);
} else { } else {
@@ -2480,7 +2578,8 @@ void tcp_close(struct sock *sk, long timeout) @@ -2482,7 +2580,8 @@ void tcp_close(struct sock *sk, long timeout)
inet_csk_reset_keepalive_timer(sk, inet_csk_reset_keepalive_timer(sk,
tmo - TCP_TIMEWAIT_LEN); tmo - TCP_TIMEWAIT_LEN);
} else { } else {
@ -3815,7 +3834,7 @@ index 9f53d25e047e..a48d9b394b11 100644
goto out; goto out;
} }
} }
@@ -2489,7 +2588,7 @@ void tcp_close(struct sock *sk, long timeout) @@ -2491,7 +2590,7 @@ void tcp_close(struct sock *sk, long timeout)
sk_mem_reclaim(sk); sk_mem_reclaim(sk);
if (tcp_check_oom(sk, 0)) { if (tcp_check_oom(sk, 0)) {
tcp_set_state(sk, TCP_CLOSE); tcp_set_state(sk, TCP_CLOSE);
@ -3824,7 +3843,7 @@ index 9f53d25e047e..a48d9b394b11 100644
__NET_INC_STATS(sock_net(sk), __NET_INC_STATS(sock_net(sk),
LINUX_MIB_TCPABORTONMEMORY); LINUX_MIB_TCPABORTONMEMORY);
} else if (!check_net(sock_net(sk))) { } else if (!check_net(sock_net(sk))) {
@@ -2521,15 +2620,6 @@ void tcp_close(struct sock *sk, long timeout) @@ -2523,15 +2622,6 @@ void tcp_close(struct sock *sk, long timeout)
} }
EXPORT_SYMBOL(tcp_close); EXPORT_SYMBOL(tcp_close);
@ -3840,7 +3859,7 @@ index 9f53d25e047e..a48d9b394b11 100644
static void tcp_rtx_queue_purge(struct sock *sk) static void tcp_rtx_queue_purge(struct sock *sk)
{ {
struct rb_node *p = rb_first(&sk->tcp_rtx_queue); struct rb_node *p = rb_first(&sk->tcp_rtx_queue);
@@ -2551,6 +2641,10 @@ void tcp_write_queue_purge(struct sock *sk) @@ -2553,6 +2643,10 @@ void tcp_write_queue_purge(struct sock *sk)
{ {
struct sk_buff *skb; struct sk_buff *skb;
@ -3851,7 +3870,7 @@ index 9f53d25e047e..a48d9b394b11 100644
tcp_chrono_stop(sk, TCP_CHRONO_BUSY); tcp_chrono_stop(sk, TCP_CHRONO_BUSY);
while ((skb = __skb_dequeue(&sk->sk_write_queue)) != NULL) { while ((skb = __skb_dequeue(&sk->sk_write_queue)) != NULL) {
tcp_skb_tsorted_anchor_cleanup(skb); tcp_skb_tsorted_anchor_cleanup(skb);
@@ -2569,6 +2663,36 @@ void tcp_write_queue_purge(struct sock *sk) @@ -2571,6 +2665,36 @@ void tcp_write_queue_purge(struct sock *sk)
inet_csk(sk)->icsk_backoff = 0; inet_csk(sk)->icsk_backoff = 0;
} }
@ -3888,7 +3907,7 @@ index 9f53d25e047e..a48d9b394b11 100644
int tcp_disconnect(struct sock *sk, int flags) int tcp_disconnect(struct sock *sk, int flags)
{ {
struct inet_sock *inet = inet_sk(sk); struct inet_sock *inet = inet_sk(sk);
@@ -2591,7 +2715,7 @@ int tcp_disconnect(struct sock *sk, int flags) @@ -2593,7 +2717,7 @@ int tcp_disconnect(struct sock *sk, int flags)
/* The last check adjusts for discrepancy of Linux wrt. RFC /* The last check adjusts for discrepancy of Linux wrt. RFC
* states * states
*/ */
@ -3897,7 +3916,7 @@ index 9f53d25e047e..a48d9b394b11 100644
sk->sk_err = ECONNRESET; sk->sk_err = ECONNRESET;
} else if (old_state == TCP_SYN_SENT) } else if (old_state == TCP_SYN_SENT)
sk->sk_err = ECONNRESET; sk->sk_err = ECONNRESET;
@@ -2613,11 +2737,16 @@ int tcp_disconnect(struct sock *sk, int flags) @@ -2615,11 +2739,16 @@ int tcp_disconnect(struct sock *sk, int flags)
if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK)) if (!(sk->sk_userlocks & SOCK_BINDADDR_LOCK))
inet_reset_saddr(sk); inet_reset_saddr(sk);
@ -3917,7 +3936,7 @@ index 9f53d25e047e..a48d9b394b11 100644
seq = tp->write_seq + tp->max_window + 2; seq = tp->write_seq + tp->max_window + 2;
if (!seq) if (!seq)
@@ -2627,21 +2756,14 @@ int tcp_disconnect(struct sock *sk, int flags) @@ -2629,21 +2758,14 @@ int tcp_disconnect(struct sock *sk, int flags)
icsk->icsk_backoff = 0; icsk->icsk_backoff = 0;
tp->snd_cwnd = 2; tp->snd_cwnd = 2;
icsk->icsk_probes_out = 0; icsk->icsk_probes_out = 0;
@ -3942,7 +3961,7 @@ index 9f53d25e047e..a48d9b394b11 100644
inet_csk_delack_init(sk); inet_csk_delack_init(sk);
/* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0 /* Initialize rcv_mss to TCP_MIN_MSS to avoid division by 0
* issue in __tcp_select_window() * issue in __tcp_select_window()
@@ -2653,14 +2775,6 @@ int tcp_disconnect(struct sock *sk, int flags) @@ -2655,14 +2777,6 @@ int tcp_disconnect(struct sock *sk, int flags)
sk->sk_rx_dst = NULL; sk->sk_rx_dst = NULL;
tcp_saved_syn_free(tp); tcp_saved_syn_free(tp);
tp->compressed_ack = 0; tp->compressed_ack = 0;
@ -3957,7 +3976,7 @@ index 9f53d25e047e..a48d9b394b11 100644
tp->duplicate_sack[0].start_seq = 0; tp->duplicate_sack[0].start_seq = 0;
tp->duplicate_sack[0].end_seq = 0; tp->duplicate_sack[0].end_seq = 0;
tp->dsack_dups = 0; tp->dsack_dups = 0;
@@ -2669,8 +2783,6 @@ int tcp_disconnect(struct sock *sk, int flags) @@ -2671,8 +2785,6 @@ int tcp_disconnect(struct sock *sk, int flags)
tp->sacked_out = 0; tp->sacked_out = 0;
tp->tlp_high_seq = 0; tp->tlp_high_seq = 0;
tp->last_oow_ack_time = 0; tp->last_oow_ack_time = 0;
@ -3966,7 +3985,7 @@ index 9f53d25e047e..a48d9b394b11 100644
tp->rack.mstamp = 0; tp->rack.mstamp = 0;
tp->rack.advanced = 0; tp->rack.advanced = 0;
tp->rack.reo_wnd_steps = 1; tp->rack.reo_wnd_steps = 1;
@@ -2704,7 +2816,7 @@ int tcp_disconnect(struct sock *sk, int flags) @@ -2706,7 +2818,7 @@ int tcp_disconnect(struct sock *sk, int flags)
static inline bool tcp_can_repair_sock(const struct sock *sk) static inline bool tcp_can_repair_sock(const struct sock *sk)
{ {
return ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN) && return ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN) &&
@ -3975,7 +3994,7 @@ index 9f53d25e047e..a48d9b394b11 100644
} }
static int tcp_repair_set_window(struct tcp_sock *tp, char __user *optbuf, int len) static int tcp_repair_set_window(struct tcp_sock *tp, char __user *optbuf, int len)
@@ -2735,6 +2847,7 @@ static int tcp_repair_set_window(struct tcp_sock *tp, char __user *optbuf, int l @@ -2737,6 +2849,7 @@ static int tcp_repair_set_window(struct tcp_sock *tp, char __user *optbuf, int l
tp->rcv_wnd = opt.rcv_wnd; tp->rcv_wnd = opt.rcv_wnd;
tp->rcv_wup = opt.rcv_wup; tp->rcv_wup = opt.rcv_wup;
@ -3983,7 +4002,7 @@ index 9f53d25e047e..a48d9b394b11 100644
return 0; return 0;
} }
@@ -2873,6 +2986,61 @@ static int do_tcp_setsockopt(struct sock *sk, int level, @@ -2875,6 +2988,61 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
return tcp_fastopen_reset_cipher(net, sk, key, backup_key); return tcp_fastopen_reset_cipher(net, sk, key, backup_key);
} }
@ -4045,7 +4064,7 @@ index 9f53d25e047e..a48d9b394b11 100644
default: default:
/* fallthru */ /* fallthru */
break; break;
@@ -3062,6 +3230,12 @@ static int do_tcp_setsockopt(struct sock *sk, int level, @@ -3064,6 +3232,12 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
break; break;
case TCP_DEFER_ACCEPT: case TCP_DEFER_ACCEPT:
@ -4058,7 +4077,7 @@ index 9f53d25e047e..a48d9b394b11 100644
/* Translate value in seconds to number of retransmits */ /* Translate value in seconds to number of retransmits */
icsk->icsk_accept_queue.rskq_defer_accept = icsk->icsk_accept_queue.rskq_defer_accept =
secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ, secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ,
@@ -3089,7 +3263,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level, @@ -3091,7 +3265,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) && (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) &&
inet_csk_ack_scheduled(sk)) { inet_csk_ack_scheduled(sk)) {
icsk->icsk_ack.pending |= ICSK_ACK_PUSHED; icsk->icsk_ack.pending |= ICSK_ACK_PUSHED;
@ -4067,7 +4086,7 @@ index 9f53d25e047e..a48d9b394b11 100644
if (!(val & 1)) if (!(val & 1))
inet_csk_enter_pingpong_mode(sk); inet_csk_enter_pingpong_mode(sk);
} }
@@ -3099,7 +3273,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level, @@ -3101,7 +3275,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
#ifdef CONFIG_TCP_MD5SIG #ifdef CONFIG_TCP_MD5SIG
case TCP_MD5SIG: case TCP_MD5SIG:
case TCP_MD5SIG_EXT: case TCP_MD5SIG_EXT:
@ -4079,14 +4098,15 @@ index 9f53d25e047e..a48d9b394b11 100644
break; break;
#endif #endif
case TCP_USER_TIMEOUT: case TCP_USER_TIMEOUT:
@@ -3155,6 +3332,32 @@ static int do_tcp_setsockopt(struct sock *sk, int level, @@ -3157,6 +3334,33 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
tp->notsent_lowat = val; tp->notsent_lowat = val;
sk->sk_write_space(sk); sk->sk_write_space(sk);
break; break;
+#ifdef CONFIG_MPTCP +#ifdef CONFIG_MPTCP
+ case MPTCP_ENABLED: + case MPTCP_ENABLED:
+ if (mptcp_init_failed || !sysctl_mptcp_enabled || + if (mptcp_init_failed || !sysctl_mptcp_enabled ||
+ sk->sk_state != TCP_CLOSE + sk->sk_state != TCP_CLOSE ||
+ sock_flag(sk, SOCK_ZEROCOPY)
+#ifdef CONFIG_TCP_MD5SIG +#ifdef CONFIG_TCP_MD5SIG
+ || rcu_access_pointer(tp->md5sig_info) + || rcu_access_pointer(tp->md5sig_info)
+#endif +#endif
@ -4112,7 +4132,7 @@ index 9f53d25e047e..a48d9b394b11 100644
case TCP_INQ: case TCP_INQ:
if (val > 1 || val < 0) if (val > 1 || val < 0)
err = -EINVAL; err = -EINVAL;
@@ -3219,7 +3422,7 @@ static void tcp_get_info_chrono_stats(const struct tcp_sock *tp, @@ -3221,7 +3425,7 @@ static void tcp_get_info_chrono_stats(const struct tcp_sock *tp,
} }
/* Return information about state of tcp endpoint in API format. */ /* Return information about state of tcp endpoint in API format. */
@ -4121,7 +4141,7 @@ index 9f53d25e047e..a48d9b394b11 100644
{ {
const struct tcp_sock *tp = tcp_sk(sk); /* iff sk_type == SOCK_STREAM */ const struct tcp_sock *tp = tcp_sk(sk); /* iff sk_type == SOCK_STREAM */
const struct inet_connection_sock *icsk = inet_csk(sk); const struct inet_connection_sock *icsk = inet_csk(sk);
@@ -3256,7 +3459,8 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) @@ -3258,7 +3462,8 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
return; return;
} }
@ -4131,7 +4151,7 @@ index 9f53d25e047e..a48d9b394b11 100644
info->tcpi_ca_state = icsk->icsk_ca_state; info->tcpi_ca_state = icsk->icsk_ca_state;
info->tcpi_retransmits = icsk->icsk_retransmits; info->tcpi_retransmits = icsk->icsk_retransmits;
@@ -3332,7 +3536,9 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info) @@ -3334,7 +3539,9 @@ void tcp_get_info(struct sock *sk, struct tcp_info *info)
info->tcpi_reord_seen = tp->reord_seen; info->tcpi_reord_seen = tp->reord_seen;
info->tcpi_rcv_ooopack = tp->rcv_ooopack; info->tcpi_rcv_ooopack = tp->rcv_ooopack;
info->tcpi_snd_wnd = tp->snd_wnd; info->tcpi_snd_wnd = tp->snd_wnd;
@ -4142,7 +4162,7 @@ index 9f53d25e047e..a48d9b394b11 100644
} }
EXPORT_SYMBOL_GPL(tcp_get_info); EXPORT_SYMBOL_GPL(tcp_get_info);
@@ -3479,7 +3685,7 @@ static int do_tcp_getsockopt(struct sock *sk, int level, @@ -3481,7 +3688,7 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
if (get_user(len, optlen)) if (get_user(len, optlen))
return -EFAULT; return -EFAULT;
@ -4151,7 +4171,7 @@ index 9f53d25e047e..a48d9b394b11 100644
len = min_t(unsigned int, len, sizeof(info)); len = min_t(unsigned int, len, sizeof(info));
if (put_user(len, optlen)) if (put_user(len, optlen))
@@ -3668,6 +3874,87 @@ static int do_tcp_getsockopt(struct sock *sk, int level, @@ -3670,6 +3877,87 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
} }
return 0; return 0;
} }
@ -4239,7 +4259,7 @@ index 9f53d25e047e..a48d9b394b11 100644
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
case TCP_ZEROCOPY_RECEIVE: { case TCP_ZEROCOPY_RECEIVE: {
struct tcp_zerocopy_receive zc; struct tcp_zerocopy_receive zc;
@@ -3873,7 +4160,9 @@ void tcp_done(struct sock *sk) @@ -3875,7 +4163,9 @@ void tcp_done(struct sock *sk)
if (sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV) if (sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV)
TCP_INC_STATS(sock_net(sk), TCP_MIB_ATTEMPTFAILS); TCP_INC_STATS(sock_net(sk), TCP_MIB_ATTEMPTFAILS);
@ -4249,7 +4269,7 @@ index 9f53d25e047e..a48d9b394b11 100644
tcp_clear_xmit_timers(sk); tcp_clear_xmit_timers(sk);
if (req) if (req)
reqsk_fastopen_remove(sk, req, false); reqsk_fastopen_remove(sk, req, false);
@@ -3889,6 +4178,8 @@ void tcp_done(struct sock *sk) @@ -3891,6 +4181,8 @@ void tcp_done(struct sock *sk)
int tcp_abort(struct sock *sk, int err) int tcp_abort(struct sock *sk, int err)
{ {
@ -4258,7 +4278,7 @@ index 9f53d25e047e..a48d9b394b11 100644
if (!sk_fullsock(sk)) { if (!sk_fullsock(sk)) {
if (sk->sk_state == TCP_NEW_SYN_RECV) { if (sk->sk_state == TCP_NEW_SYN_RECV) {
struct request_sock *req = inet_reqsk(sk); struct request_sock *req = inet_reqsk(sk);
@@ -3902,7 +4193,7 @@ int tcp_abort(struct sock *sk, int err) @@ -3904,7 +4196,7 @@ int tcp_abort(struct sock *sk, int err)
} }
/* Don't race with userspace socket closes such as tcp_close. */ /* Don't race with userspace socket closes such as tcp_close. */
@ -4267,7 +4287,7 @@ index 9f53d25e047e..a48d9b394b11 100644
if (sk->sk_state == TCP_LISTEN) { if (sk->sk_state == TCP_LISTEN) {
tcp_set_state(sk, TCP_CLOSE); tcp_set_state(sk, TCP_CLOSE);
@@ -3911,7 +4202,7 @@ int tcp_abort(struct sock *sk, int err) @@ -3913,7 +4205,7 @@ int tcp_abort(struct sock *sk, int err)
/* Don't race with BH socket closes such as inet_csk_listen_stop. */ /* Don't race with BH socket closes such as inet_csk_listen_stop. */
local_bh_disable(); local_bh_disable();
@ -4276,7 +4296,7 @@ index 9f53d25e047e..a48d9b394b11 100644
if (!sock_flag(sk, SOCK_DEAD)) { if (!sock_flag(sk, SOCK_DEAD)) {
sk->sk_err = err; sk->sk_err = err;
@@ -3919,14 +4210,14 @@ int tcp_abort(struct sock *sk, int err) @@ -3921,14 +4213,14 @@ int tcp_abort(struct sock *sk, int err)
smp_wmb(); smp_wmb();
sk->sk_error_report(sk); sk->sk_error_report(sk);
if (tcp_need_reset(sk->sk_state)) if (tcp_need_reset(sk->sk_state))
@ -6078,7 +6098,7 @@ index 194743bd3fc1..b35942faf7df 100644
return ret; return ret;
} }
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 638d7b49ad71..d246e537e686 100644 index 139e962d1aef..5a037f4e58e5 100644
--- a/net/ipv4/tcp_output.c --- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c
@@ -37,6 +37,12 @@ @@ -37,6 +37,12 @@
@ -6669,7 +6689,7 @@ index 638d7b49ad71..d246e537e686 100644
} }
static void tcp_connect_queue_skb(struct sock *sk, struct sk_buff *skb) static void tcp_connect_queue_skb(struct sock *sk, struct sk_buff *skb)
@@ -3731,6 +3817,7 @@ void tcp_send_ack(struct sock *sk) @@ -3734,6 +3820,7 @@ void tcp_send_ack(struct sock *sk)
{ {
__tcp_send_ack(sk, tcp_sk(sk)->rcv_nxt); __tcp_send_ack(sk, tcp_sk(sk)->rcv_nxt);
} }
@ -6677,7 +6697,7 @@ index 638d7b49ad71..d246e537e686 100644
/* This routine sends a packet with an out of date sequence /* This routine sends a packet with an out of date sequence
* number. It assumes the other end will try to ack it. * number. It assumes the other end will try to ack it.
@@ -3743,7 +3830,7 @@ void tcp_send_ack(struct sock *sk) @@ -3746,7 +3833,7 @@ void tcp_send_ack(struct sock *sk)
* one is with SEG.SEQ=SND.UNA to deliver urgent pointer, another is * one is with SEG.SEQ=SND.UNA to deliver urgent pointer, another is
* out-of-date with SND.UNA-1 to probe window. * out-of-date with SND.UNA-1 to probe window.
*/ */
@ -6686,7 +6706,7 @@ index 638d7b49ad71..d246e537e686 100644
{ {
struct tcp_sock *tp = tcp_sk(sk); struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb; struct sk_buff *skb;
@@ -3830,7 +3917,7 @@ void tcp_send_probe0(struct sock *sk) @@ -3833,7 +3920,7 @@ void tcp_send_probe0(struct sock *sk)
unsigned long timeout; unsigned long timeout;
int err; int err;
@ -6911,7 +6931,7 @@ index fa2ae96ecdc4..d2b3e30b8788 100644
} }
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d1f29a3eb70b..78554dcb8532 100644 index 69aef71f32ea..9d8b765cccce 100644
--- a/net/ipv6/addrconf.c --- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c
@@ -967,6 +967,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) @@ -967,6 +967,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
@ -9393,10 +9413,10 @@ index 000000000000..9eb7628053f6
+MODULE_VERSION("0.1"); +MODULE_VERSION("0.1");
diff --git a/net/mptcp/mptcp_ctrl.c b/net/mptcp/mptcp_ctrl.c diff --git a/net/mptcp/mptcp_ctrl.c b/net/mptcp/mptcp_ctrl.c
new file mode 100644 new file mode 100644
index 000000000000..ddb58a5f6d4d index 000000000000..f344ff5e0407
--- /dev/null --- /dev/null
+++ b/net/mptcp/mptcp_ctrl.c +++ b/net/mptcp/mptcp_ctrl.c
@@ -0,0 +1,3310 @@ @@ -0,0 +1,3346 @@
+/* +/*
+ * MPTCP implementation - MPTCP-control + * MPTCP implementation - MPTCP-control
+ * + *
@ -10696,19 +10716,44 @@ index 000000000000..ddb58a5f6d4d
+ meta_tp->is_master_sk = 1; + meta_tp->is_master_sk = 1;
+ master_sk = sk_clone_lock(meta_sk, GFP_ATOMIC | __GFP_ZERO); + master_sk = sk_clone_lock(meta_sk, GFP_ATOMIC | __GFP_ZERO);
+ meta_tp->is_master_sk = 0; + meta_tp->is_master_sk = 0;
+ if (!master_sk) + if (!master_sk) {
+ net_err_ratelimited("%s Could not allocate master_sk on meta %p\n",
+ __func__, meta_sk);
+ goto err_alloc_master; + goto err_alloc_master;
+ }
+ +
+ /* Same as in inet_csk_clone_lock - need to init to 0 */ + /* Same as in inet_csk_clone_lock - need to init to 0 */
+ memset(&inet_csk(master_sk)->icsk_accept_queue, 0, + memset(&inet_csk(master_sk)->icsk_accept_queue, 0,
+ sizeof(inet_csk(master_sk)->icsk_accept_queue)); + sizeof(inet_csk(master_sk)->icsk_accept_queue));
+ +
+ /* icsk_bind_hash inherited from the meta, but it will be properly set
+ * in mptcp_create_master_sk. Same operation is done in
+ * inet_csk_clone_lock.
+ */
+ inet_csk(master_sk)->icsk_bind_hash = NULL;
+
+ master_tp = tcp_sk(master_sk); + master_tp = tcp_sk(master_sk);
+ master_tp->inside_tk_table = 0; + master_tp->inside_tk_table = 0;
+ +
+ master_tp->mptcp = kmem_cache_zalloc(mptcp_sock_cache, GFP_ATOMIC);
+ if (!master_tp->mptcp) {
+ net_err_ratelimited("%s Could not allocate mptcp_tcp_sock on meta %p\n",
+ __func__, meta_sk);
+ goto err_alloc_mptcp;
+ }
+
+ mpcb = kmem_cache_zalloc(mptcp_cb_cache, GFP_ATOMIC); + mpcb = kmem_cache_zalloc(mptcp_cb_cache, GFP_ATOMIC);
+ if (!mpcb) + if (!mpcb) {
+ net_err_ratelimited("%s Could not allocate mpcb on meta %p\n",
+ __func__, meta_sk);
+ goto err_alloc_mpcb; + goto err_alloc_mpcb;
+ }
+
+ if (__inet_inherit_port(meta_sk, master_sk) < 0) {
+ net_err_ratelimited("%s Could not inherit port on meta %p\n",
+ __func__, meta_sk);
+ goto err_inherit_port;
+ }
+ +
+ /* Store the mptcp version agreed on initial handshake */ + /* Store the mptcp version agreed on initial handshake */
+ mpcb->mptcp_ver = mptcp_ver; + mpcb->mptcp_ver = mptcp_ver;
@ -10860,10 +10905,6 @@ index 000000000000..ddb58a5f6d4d
+ master_tp->fastopen_req = NULL; + master_tp->fastopen_req = NULL;
+ +
+ master_sk->sk_tsq_flags = 0; + master_sk->sk_tsq_flags = 0;
+ /* icsk_bind_hash inherited from the meta, but it will be properly set in
+ * mptcp_create_master_sk. Same operation is done in inet_csk_clone_lock.
+ */
+ inet_csk(master_sk)->icsk_bind_hash = NULL;
+ +
+ /* Init the accept_queue structure, we support a queue of 32 pending + /* Init the accept_queue structure, we support a queue of 32 pending
+ * connections, it does not need to be huge, since we only store here + * connections, it does not need to be huge, since we only store here
@ -10910,7 +10951,21 @@ index 000000000000..ddb58a5f6d4d
+err_insert_token: +err_insert_token:
+ kmem_cache_free(mptcp_cb_cache, mpcb); + kmem_cache_free(mptcp_cb_cache, mpcb);
+ +
+ kmem_cache_free(mptcp_sock_cache, master_tp->mptcp);
+ master_tp->mptcp = NULL;
+
+ inet_csk_prepare_forced_close(master_sk);
+ tcp_done(master_sk);
+ return -EINVAL;
+
+err_inherit_port:
+ kmem_cache_free(mptcp_cb_cache, mpcb);
+
+err_alloc_mpcb: +err_alloc_mpcb:
+ kmem_cache_free(mptcp_sock_cache, master_tp->mptcp);
+ master_tp->mptcp = NULL;
+
+err_alloc_mptcp:
+ inet_sk(master_sk)->inet_opt = NULL; + inet_sk(master_sk)->inet_opt = NULL;
+ master_sk->sk_state = TCP_CLOSE; + master_sk->sk_state = TCP_CLOSE;
+ sock_orphan(master_sk); + sock_orphan(master_sk);
@ -10944,13 +10999,19 @@ index 000000000000..ddb58a5f6d4d
+ struct mptcp_cb *mpcb = tcp_sk(meta_sk)->mpcb; + struct mptcp_cb *mpcb = tcp_sk(meta_sk)->mpcb;
+ struct tcp_sock *tp = tcp_sk(sk); + struct tcp_sock *tp = tcp_sk(sk);
+ +
+ tp->mptcp = kmem_cache_zalloc(mptcp_sock_cache, flags); + /* Could have been allocated by mptcp_alloc_mpcb */
+ if (!tp->mptcp) + if (!tp->mptcp) {
+ return -ENOMEM; + tp->mptcp = kmem_cache_zalloc(mptcp_sock_cache, flags);
+
+ if (!tp->mptcp)
+ return -ENOMEM;
+ }
+ +
+ tp->mptcp->path_index = mptcp_set_new_pathindex(mpcb); + tp->mptcp->path_index = mptcp_set_new_pathindex(mpcb);
+ /* No more space for more subflows? */ + /* No more space for more subflows? */
+ if (!tp->mptcp->path_index) { + if (!tp->mptcp->path_index) {
+ WARN_ON(is_master_tp(tp));
+
+ kmem_cache_free(mptcp_sock_cache, tp->mptcp); + kmem_cache_free(mptcp_sock_cache, tp->mptcp);
+ return -EPERM; + return -EPERM;
+ } + }
@ -11595,11 +11656,10 @@ index 000000000000..ddb58a5f6d4d
+ master_sk = tcp_sk(meta_sk)->mpcb->master_sk; + master_sk = tcp_sk(meta_sk)->mpcb->master_sk;
+ master_tp = tcp_sk(master_sk); + master_tp = tcp_sk(master_sk);
+ +
+ if (mptcp_add_sock(meta_sk, master_sk, 0, 0, GFP_ATOMIC)) + if (mptcp_add_sock(meta_sk, master_sk, 0, 0, GFP_ATOMIC)) {
+ goto err_add_sock; + WARN_ON(1);
+ + return -EINVAL;
+ if (__inet_inherit_port(meta_sk, master_sk) < 0) + }
+ goto err_add_sock;
+ +
+ meta_sk->sk_prot->unhash(meta_sk); + meta_sk->sk_prot->unhash(meta_sk);
+ inet_ehash_nolisten(master_sk, NULL); + inet_ehash_nolisten(master_sk, NULL);
@ -11608,10 +11668,6 @@ index 000000000000..ddb58a5f6d4d
+ +
+ return 0; + return 0;
+ +
+err_add_sock:
+ inet_csk_prepare_forced_close(master_sk);
+ tcp_done(master_sk);
+
+err_alloc_mpcb: +err_alloc_mpcb:
+ return -ENOBUFS; + return -ENOBUFS;
+} +}
@ -14852,10 +14908,10 @@ index 000000000000..65e2cd9bf630
+MODULE_VERSION("0.88"); +MODULE_VERSION("0.88");
diff --git a/net/mptcp/mptcp_input.c b/net/mptcp/mptcp_input.c diff --git a/net/mptcp/mptcp_input.c b/net/mptcp/mptcp_input.c
new file mode 100644 new file mode 100644
index 000000000000..18bbecad2441 index 000000000000..7ce97409e1e2
--- /dev/null --- /dev/null
+++ b/net/mptcp/mptcp_input.c +++ b/net/mptcp/mptcp_input.c
@@ -0,0 +1,2616 @@ @@ -0,0 +1,2630 @@
+/* +/*
+ * MPTCP implementation - Sending side + * MPTCP implementation - Sending side
+ * + *
@ -15270,9 +15326,10 @@ index 000000000000..18bbecad2441
+ kfree_skb(tmp); + kfree_skb(tmp);
+ } + }
+ +
+ mptcp_fallback_close(tp->mpcb, sk); + if (mptcp_fallback_close(tp->mpcb, sk))
+ + ans = -1;
+ ans = 0; + else
+ ans = 0;
+ } + }
+ } + }
+ +
@ -15448,7 +15505,8 @@ index 000000000000..18bbecad2441
+ mpcb->infinite_mapping_rcv = 1; + mpcb->infinite_mapping_rcv = 1;
+ mpcb->infinite_rcv_seq = mptcp_get_rcv_nxt_64(mptcp_meta_tp(tp)); + mpcb->infinite_rcv_seq = mptcp_get_rcv_nxt_64(mptcp_meta_tp(tp));
+ +
+ mptcp_fallback_close(mpcb, sk); + if (mptcp_fallback_close(mpcb, sk))
+ return 1;
+ +
+ /* We do a seamless fallback and should not send a inf.mapping. */ + /* We do a seamless fallback and should not send a inf.mapping. */
+ mpcb->send_infinite_mapping = 0; + mpcb->send_infinite_mapping = 0;
@ -15624,7 +15682,8 @@ index 000000000000..18bbecad2441
+ data_len = skb->len + (mptcp_is_data_fin(skb) ? 1 : 0); + data_len = skb->len + (mptcp_is_data_fin(skb) ? 1 : 0);
+ sub_seq = tcb->seq; + sub_seq = tcb->seq;
+ +
+ mptcp_fallback_close(mpcb, sk); + if (mptcp_fallback_close(mpcb, sk))
+ return 1;
+ +
+ mptcp_restart_sending(tp->meta_sk, meta_tp->snd_una); + mptcp_restart_sending(tp->meta_sk, meta_tp->snd_una);
+ +
@ -16301,7 +16360,7 @@ index 000000000000..18bbecad2441
+ } + }
+} +}
+ +
+/* Handle the DATA_ACK */ +/* Return false if we can continue processing packets. True, otherwise */
+static bool mptcp_process_data_ack(struct sock *sk, const struct sk_buff *skb) +static bool mptcp_process_data_ack(struct sock *sk, const struct sk_buff *skb)
+{ +{
+ struct sock *meta_sk = mptcp_meta_sk(sk); + struct sock *meta_sk = mptcp_meta_sk(sk);
@ -16458,6 +16517,7 @@ index 000000000000..18bbecad2441
+ return false; + return false;
+} +}
+ +
+/* Return false if we can continue processing packets. True, otherwise */
+bool mptcp_handle_ack_in_infinite(struct sock *sk, const struct sk_buff *skb, +bool mptcp_handle_ack_in_infinite(struct sock *sk, const struct sk_buff *skb,
+ int flag) + int flag)
+{ +{
@ -16500,27 +16560,35 @@ index 000000000000..18bbecad2441
+ if (!(flag & MPTCP_FLAG_DATA_ACKED)) + if (!(flag & MPTCP_FLAG_DATA_ACKED))
+ return false; + return false;
+ +
+ pr_debug("%s %#x will fallback - pi %d, src %pI4:%u dst %pI4:%u rcv_nxt %u from %pS\n", + pr_debug("%s %#x will fallback - pi %d, src %pI4:%u dst %pI4:%u rcv_nxt %u\n",
+ __func__, mpcb->mptcp_loc_token, tp->mptcp->path_index, + __func__, mpcb->mptcp_loc_token, tp->mptcp->path_index,
+ &inet_sk(sk)->inet_saddr, ntohs(inet_sk(sk)->inet_sport), + &inet_sk(sk)->inet_saddr, ntohs(inet_sk(sk)->inet_sport),
+ &inet_sk(sk)->inet_daddr, ntohs(inet_sk(sk)->inet_dport), + &inet_sk(sk)->inet_daddr, ntohs(inet_sk(sk)->inet_dport),
+ tp->rcv_nxt, __builtin_return_address(0)); + tp->rcv_nxt);
+ if (!is_master_tp(tp)) { + if (!is_master_tp(tp)) {
+ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_FBACKSUB); + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_FBACKSUB);
+ return true; + return true;
+ } + }
+ +
+ /* We have sent more than what has ever been sent on the master subflow.
+ * This means, we won't be able to seamlessly fallback because there
+ * will now be a hole in the sequence space.
+ */
+ if (before(tp->mptcp->last_end_data_seq, meta_tp->snd_una))
+ return true;
+
+ mpcb->infinite_mapping_snd = 1; + mpcb->infinite_mapping_snd = 1;
+ mpcb->infinite_mapping_rcv = 1; + mpcb->infinite_mapping_rcv = 1;
+ mpcb->infinite_rcv_seq = mptcp_get_rcv_nxt_64(mptcp_meta_tp(tp)); + mpcb->infinite_rcv_seq = mptcp_get_rcv_nxt_64(mptcp_meta_tp(tp));
+ tp->mptcp->fully_established = 1; + tp->mptcp->fully_established = 1;
+ +
+ mptcp_fallback_close(mpcb, sk); + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_FBACKINIT);
+
+ if (mptcp_fallback_close(mpcb, sk))
+ return true;
+ +
+ mptcp_restart_sending(tp->meta_sk, tp->mptcp->last_end_data_seq); + mptcp_restart_sending(tp->meta_sk, tp->mptcp->last_end_data_seq);
+ +
+ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_FBACKINIT);
+
+ /* The acknowledged data-seq at the subflow-level is: + /* The acknowledged data-seq at the subflow-level is:
+ * last_end_data_seq - (tp->snd_nxt - tp->snd_una) + * last_end_data_seq - (tp->snd_nxt - tp->snd_una)
+ * + *
@ -16537,9 +16605,8 @@ index 000000000000..18bbecad2441
+ } + }
+ +
+exit: +exit:
+ mptcp_process_data_ack(sk, skb);
+ +
+ return false; + return mptcp_process_data_ack(sk, skb);
+} +}
+ +
+/**** static functions used by mptcp_parse_options */ +/**** static functions used by mptcp_parse_options */
@ -17100,7 +17167,8 @@ index 000000000000..18bbecad2441
+ return true; + return true;
+} +}
+ +
+static void mptcp_mp_fail_rcvd(struct sock *sk, const struct tcphdr *th) +/* Returns true if we should stop processing NOW */
+static bool mptcp_mp_fail_rcvd(struct sock *sk, const struct tcphdr *th)
+{ +{
+ struct mptcp_tcp_sock *mptcp = tcp_sk(sk)->mptcp; + struct mptcp_tcp_sock *mptcp = tcp_sk(sk)->mptcp;
+ struct sock *meta_sk = mptcp_meta_sk(sk); + struct sock *meta_sk = mptcp_meta_sk(sk);
@ -17114,8 +17182,10 @@ index 000000000000..18bbecad2441
+ +
+ mptcp_restart_sending(meta_sk, tcp_sk(meta_sk)->snd_una); + mptcp_restart_sending(meta_sk, tcp_sk(meta_sk)->snd_una);
+ +
+ mptcp_fallback_close(mpcb, sk); + return mptcp_fallback_close(mpcb, sk);
+ } + }
+
+ return false;
+} +}
+ +
+static inline void mptcp_path_array_check(struct sock *meta_sk) +static inline void mptcp_path_array_check(struct sock *meta_sk)
@ -17149,8 +17219,8 @@ index 000000000000..18bbecad2441
+ mptcp_initialize_recv_vars(mptcp_meta_tp(tp), tp->mpcb, + mptcp_initialize_recv_vars(mptcp_meta_tp(tp), tp->mpcb,
+ mopt->mptcp_sender_key); + mopt->mptcp_sender_key);
+ +
+ if (unlikely(mopt->mp_fail)) + if (unlikely(mopt->mp_fail) && mptcp_mp_fail_rcvd(sk, th))
+ mptcp_mp_fail_rcvd(sk, th); + return true;
+ +
+ /* RFC 6824, Section 3.3: + /* RFC 6824, Section 3.3:
+ * If a checksum is not present when its use has been negotiated, the + * If a checksum is not present when its use has been negotiated, the
@ -24137,7 +24207,7 @@ index 94358566c9d1..a26eeeda2b4d 100644
* Now to bump the refcnt of the [loadable] module that owns this * Now to bump the refcnt of the [loadable] module that owns this
* socket at sock_release time we decrement its refcnt. * socket at sock_release time we decrement its refcnt.
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 63038eb23560..7150eb62db86 100644 index 0bfad86ec960..ed7013398991 100644
--- a/tools/include/uapi/linux/bpf.h --- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h
@@ -3438,6 +3438,7 @@ enum { @@ -3438,6 +3438,7 @@ enum {