This will be used to transition to the appropriate state on close and
determine if a DATA_FIN needs to be sent for that state transition.

Signed-off-by: Mat Martineau <mathew.j.martin...@linux.intel.com>
---
 net/mptcp/protocol.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index e1c71bfd61a3..51370b69e30b 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -1498,6 +1498,33 @@ static void mptcp_subflow_shutdown(struct sock *ssk, int 
how)
        release_sock(ssk);
 }
 
+static const unsigned char new_state[16] = {
+       /* current state:     new state:      action:   */
+       [0 /* (Invalid) */] = TCP_CLOSE,
+       [TCP_ESTABLISHED]   = TCP_FIN_WAIT1 | TCP_ACTION_FIN,
+       [TCP_SYN_SENT]      = TCP_CLOSE,
+       [TCP_SYN_RECV]      = TCP_FIN_WAIT1 | TCP_ACTION_FIN,
+       [TCP_FIN_WAIT1]     = TCP_FIN_WAIT1,
+       [TCP_FIN_WAIT2]     = TCP_FIN_WAIT2,
+       [TCP_TIME_WAIT]     = TCP_CLOSE,        /* should not happen ! */
+       [TCP_CLOSE]         = TCP_CLOSE,
+       [TCP_CLOSE_WAIT]    = TCP_LAST_ACK  | TCP_ACTION_FIN,
+       [TCP_LAST_ACK]      = TCP_LAST_ACK,
+       [TCP_LISTEN]        = TCP_CLOSE,
+       [TCP_CLOSING]       = TCP_CLOSING,
+       [TCP_NEW_SYN_RECV]  = TCP_CLOSE,        /* should not happen ! */
+};
+
+static int mptcp_close_state(struct sock *sk)
+{
+       int next = (int)new_state[sk->sk_state];
+       int ns = next & TCP_STATE_MASK;
+
+       inet_sk_state_store(sk, ns);
+
+       return next & TCP_ACTION_FIN;
+}
+
 static void mptcp_close(struct sock *sk, long timeout)
 {
        struct mptcp_subflow_context *subflow, *tmp;
-- 
2.28.0

Reply via email to