@@ -25,6 +25,8 @@ static void mptcp_parse_option(const struct sock *sk,
const unsigned char *ptr, int opsize,
struct mptcp_options_received *mp_opt)
{
+ struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
+ struct mptcp_sock *msk = mptcp_sk(subflow->conn);
u8 subtype = *ptr >> 4;
int expected_opsize;
u8 version;
@@ -35,10 +37,13 @@ static void mptcp_parse_option(const struct sock *sk,
case MPTCPOPT_MP_CAPABLE:
/* strict size checking */
if (!(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN)) {
- if (skb->len > tcp_hdr(skb)->doff << 2)
+ if (skb->len > tcp_hdr(skb)->doff << 2) {
expected_opsize = TCPOLEN_MPTCP_MPC_ACK_DATA;
- else
+ if (READ_ONCE(msk->csum_enabled))
+ expected_opsize += TCPOLEN_MPTCP_DSS_CHECKSUM;
+ } else {
expected_opsize = TCPOLEN_MPTCP_MPC_ACK;
+ }
} else {
if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_ACK)
expected_opsize = TCPOLEN_MPTCP_MPC_SYNACK;
@@ -85,7 +90,7 @@ static void mptcp_parse_option(const struct sock *sk,
mp_opt->rcvr_key = get_unaligned_be64(ptr);
ptr += 8;
}
- if (opsize == TCPOLEN_MPTCP_MPC_ACK_DATA) {
+ if (opsize >= TCPOLEN_MPTCP_MPC_ACK_DATA) {
/* Section 3.1.:
* "the data parameters in a MP_CAPABLE are semantically
* equivalent to those in a DSS option and can be used
@@ -97,9 +102,13 @@ static void mptcp_parse_option(const struct sock *sk,
mp_opt->data_len = get_unaligned_be16(ptr);
ptr += 2;
}
- pr_debug("MP_CAPABLE version=%x, flags=%x, optlen=%d sndr=%llu, rcvr=%llu len=%d",
+ if (opsize == TCPOLEN_MPTCP_MPC_ACK_DATA + TCPOLEN_MPTCP_DSS_CHECKSUM) {
+ mp_opt->csum = (__force __sum16)get_unaligned_be16(ptr);
+ ptr += 2;
+ }
+ pr_debug("MP_CAPABLE version=%x, flags=%x, optlen=%d sndr=%llu, rcvr=%llu len=%d csum=%u",
version, flags, opsize, mp_opt->sndr_key,
- mp_opt->rcvr_key, mp_opt->data_len);
+ mp_opt->rcvr_key, mp_opt->data_len, mp_opt->csum);
break;
case MPTCPOPT_MP_JOIN:
@@ -343,6 +352,7 @@ void mptcp_get_options(const struct sock *sk,
mp_opt->mp_prio = 0;
mp_opt->reset = 0;
mp_opt->csum_reqd = 0;
+ mp_opt->csum = 0;
length = (th->doff * 4) - sizeof(struct tcphdr);
ptr = (const unsigned char *)(th + 1);
@@ -1110,6 +1120,9 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
}
mpext->data_len = mp_opt.data_len;
mpext->use_map = 1;
+
+ if (READ_ONCE(msk->csum_enabled))
+ mpext->csum = mp_opt.csum;
}
}
@@ -123,6 +123,7 @@ struct mptcp_options_received {
u64 data_seq;
u32 subflow_seq;
u16 data_len;
+ __sum16 csum;
u16 mp_capable : 1,
mp_join : 1,
fastclose : 1,
This patch added a new member named csum in struct mptcp_options_received. When parsing the MP_CAPABLE with data, if the checksum is enabled, adjust the expected_opsize. If the receiving option length matches the length with the data checksum, get the checksum value and save it in mp_opt->csum. And in mptcp_incoming_options, pass it to mpext->csum. Signed-off-by: Geliang Tang <geliangtang@gmail.com> --- net/mptcp/options.c | 23 ++++++++++++++++++----- net/mptcp/protocol.h | 1 + 2 files changed, 19 insertions(+), 5 deletions(-)