Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mptcp: MP_FAIL suboption sending

This patch added the MP_FAIL suboption sending support.

Add a new flag named send_mp_fail in struct mptcp_subflow_context. If
this flag is set, send out MP_FAIL suboption.

Add a new member fail_seq in struct mptcp_out_options to save the data
sequence number to put into the MP_FAIL suboption.

An MP_FAIL option could be included in a RST or on the subflow-level
ACK.

Suggested-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Geliang Tang <geliangtang@xiaomi.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Geliang Tang and committed by
David S. Miller
c25aeb4e d7b26908

+62 -5
+4 -1
include/net/mptcp.h
··· 74 74 struct mptcp_addr_info addr; 75 75 u64 ahmac; 76 76 }; 77 - struct mptcp_ext ext_copy; 77 + struct { 78 + struct mptcp_ext ext_copy; 79 + u64 fail_seq; 80 + }; 78 81 struct { 79 82 u32 nonce; 80 83 u32 token;
+55 -4
net/mptcp/options.c
··· 767 767 return true; 768 768 } 769 769 770 - static noinline void mptcp_established_options_rst(struct sock *sk, struct sk_buff *skb, 770 + static noinline bool mptcp_established_options_rst(struct sock *sk, struct sk_buff *skb, 771 771 unsigned int *size, 772 772 unsigned int remaining, 773 773 struct mptcp_out_options *opts) ··· 775 775 const struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); 776 776 777 777 if (remaining < TCPOLEN_MPTCP_RST) 778 - return; 778 + return false; 779 779 780 780 *size = TCPOLEN_MPTCP_RST; 781 781 opts->suboptions |= OPTION_MPTCP_RST; 782 782 opts->reset_transient = subflow->reset_transient; 783 783 opts->reset_reason = subflow->reset_reason; 784 + 785 + return true; 786 + } 787 + 788 + static bool mptcp_established_options_mp_fail(struct sock *sk, 789 + unsigned int *size, 790 + unsigned int remaining, 791 + struct mptcp_out_options *opts) 792 + { 793 + struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); 794 + 795 + if (likely(!subflow->send_mp_fail)) 796 + return false; 797 + 798 + if (remaining < TCPOLEN_MPTCP_FAIL) 799 + return false; 800 + 801 + *size = TCPOLEN_MPTCP_FAIL; 802 + opts->suboptions |= OPTION_MPTCP_FAIL; 803 + opts->fail_seq = subflow->map_seq; 804 + 805 + pr_debug("MP_FAIL fail_seq=%llu", opts->fail_seq); 806 + 807 + return true; 784 808 } 785 809 786 810 bool mptcp_established_options(struct sock *sk, struct sk_buff *skb, ··· 823 799 return false; 824 800 825 801 if (unlikely(skb && TCP_SKB_CB(skb)->tcp_flags & TCPHDR_RST)) { 826 - mptcp_established_options_rst(sk, skb, size, remaining, opts); 802 + if (mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) { 803 + *size += opt_size; 804 + remaining -= opt_size; 805 + } 806 + if (mptcp_established_options_rst(sk, skb, &opt_size, remaining, opts)) { 807 + *size += opt_size; 808 + remaining -= opt_size; 809 + } 827 810 return true; 828 811 } 829 812 830 813 snd_data_fin = mptcp_data_fin_enabled(msk); 831 814 if (mptcp_established_options_mp(sk, skb, snd_data_fin, &opt_size, remaining, opts)) 832 815 ret = true; 833 - else if (mptcp_established_options_dss(sk, skb, snd_data_fin, &opt_size, remaining, opts)) 816 + else if (mptcp_established_options_dss(sk, skb, snd_data_fin, &opt_size, remaining, opts)) { 834 817 ret = true; 818 + if (mptcp_established_options_mp_fail(sk, &opt_size, remaining, opts)) { 819 + *size += opt_size; 820 + remaining -= opt_size; 821 + return true; 822 + } 823 + } 835 824 836 825 /* we reserved enough space for the above options, and exceeding the 837 826 * TCP option space would be fatal ··· 1247 1210 void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, 1248 1211 struct mptcp_out_options *opts) 1249 1212 { 1213 + if (unlikely(OPTION_MPTCP_FAIL & opts->suboptions)) { 1214 + const struct sock *ssk = (const struct sock *)tp; 1215 + struct mptcp_subflow_context *subflow; 1216 + 1217 + subflow = mptcp_subflow_ctx(ssk); 1218 + subflow->send_mp_fail = 0; 1219 + 1220 + *ptr++ = mptcp_option(MPTCPOPT_MP_FAIL, 1221 + TCPOLEN_MPTCP_FAIL, 1222 + 0, 0); 1223 + put_unaligned_be64(opts->fail_seq, ptr); 1224 + ptr += 2; 1225 + } 1226 + 1250 1227 /* RST is mutually exclusive with everything else */ 1251 1228 if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) { 1252 1229 *ptr++ = mptcp_option(MPTCPOPT_RST,
+3
net/mptcp/protocol.h
··· 27 27 #define OPTION_MPTCP_PRIO BIT(9) 28 28 #define OPTION_MPTCP_RST BIT(10) 29 29 #define OPTION_MPTCP_DSS BIT(11) 30 + #define OPTION_MPTCP_FAIL BIT(12) 30 31 31 32 /* MPTCP option subtypes */ 32 33 #define MPTCPOPT_MP_CAPABLE 0 ··· 69 68 #define TCPOLEN_MPTCP_PRIO_ALIGN 4 70 69 #define TCPOLEN_MPTCP_FASTCLOSE 12 71 70 #define TCPOLEN_MPTCP_RST 4 71 + #define TCPOLEN_MPTCP_FAIL 12 72 72 73 73 #define TCPOLEN_MPTCP_MPC_ACK_DATA_CSUM (TCPOLEN_MPTCP_DSS_CHECKSUM + TCPOLEN_MPTCP_MPC_ACK_DATA) 74 74 ··· 431 429 mpc_map : 1, 432 430 backup : 1, 433 431 send_mp_prio : 1, 432 + send_mp_fail : 1, 434 433 rx_eof : 1, 435 434 can_ack : 1, /* only after processing the remote a key */ 436 435 disposable : 1, /* ctx can be free at ulp release time */