* [PATCH mptcp-next 0/2] mptcp: minor out optimization @ 2021-07-23 17:06 Paolo Abeni 2021-07-23 17:06 ` [PATCH mptcp-next 1/2] mptcp: optimize out option generation Paolo Abeni 2021-07-23 17:06 ` [PATCH mptcp-next 2/2] mptcp: shrink mptcp_out_options struct Paolo Abeni 0 siblings, 2 replies; 7+ messages in thread From: Paolo Abeni @ 2021-07-23 17:06 UTC (permalink / raw) To: mptcp This series implements a few ideas discussed in the past mtg, specifcally: https://github.com/multipath-tcp/mptcp_net-next/issues/15 https://github.com/multipath-tcp/mptcp_net-next/issues/42 The final goal is shrink the mptcp_out_options struct, which is always zeroed by the plain TCP protocol in the output path. Only lightly tested. Paolo Abeni (2): mptcp: optimize out option generation mptcp: shrink mptcp_out_options struct include/net/mptcp.h | 26 +++-- net/mptcp/options.c | 225 ++++++++++++++++++++++--------------------- net/mptcp/pm.c | 9 +- net/mptcp/protocol.h | 1 + 4 files changed, 139 insertions(+), 122 deletions(-) -- 2.26.3 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH mptcp-next 1/2] mptcp: optimize out option generation 2021-07-23 17:06 [PATCH mptcp-next 0/2] mptcp: minor out optimization Paolo Abeni @ 2021-07-23 17:06 ` Paolo Abeni 2021-07-26 3:21 ` Geliang Tang 2021-07-23 17:06 ` [PATCH mptcp-next 2/2] mptcp: shrink mptcp_out_options struct Paolo Abeni 1 sibling, 1 reply; 7+ messages in thread From: Paolo Abeni @ 2021-07-23 17:06 UTC (permalink / raw) To: mptcp Currently we have several protocol contraint on MPTCP option generation (e.g. MPC and MPJ subopt are mutually exclusive) and some additionall ones required by our implementation (e.g. almost all ADD_ADDR variant are mutually exclusive with everything else). We can leverage the above to optimize the out option generation: we check DSS/MPC/MPJ presencence in a mutually exclusive way, avoiding many unneeded conditionals in the common case. Additionally extend the existing constraint on ADD_ADDR opt on all subvariant, so that it become fully mutually exclusive with the above and we can skip another conditional statement the common case. This change is also need by the next patch. Signed-off-by: Paolo Abeni <pabeni@redhat.com> -- side node: we could probably optimize the conditionals in mptcp_established_options() --- net/mptcp/options.c | 225 ++++++++++++++++++++++--------------------- net/mptcp/pm.c | 9 +- net/mptcp/protocol.h | 1 + 3 files changed, 122 insertions(+), 113 deletions(-) diff --git a/net/mptcp/options.c b/net/mptcp/options.c index eafdb9408f3a..38f324667761 100644 --- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -592,6 +592,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, dss_size = map_size; if (skb && snd_data_fin_enable) mptcp_write_data_fin(subflow, skb, &opts->ext_copy); + opts->suboptions = OPTION_MPTCP_DSS; ret = true; } @@ -615,6 +616,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, opts->ext_copy.ack64 = 0; } opts->ext_copy.use_ack = 1; + opts->suboptions = OPTION_MPTCP_DSS; WRITE_ONCE(msk->old_wspace, __mptcp_space((struct sock *)msk)); /* Add kind/length/subtype/flag overhead if mapping is not populated */ @@ -663,9 +665,9 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff * struct mptcp_sock *msk = mptcp_sk(subflow->conn); bool drop_other_suboptions = false; unsigned int opt_size = *size; + unsigned int len; bool echo; bool port; - int len; if (!mptcp_pm_should_add_signal(msk) || !mptcp_pm_add_addr_signal(msk, skb, opt_size, remaining, opts, @@ -687,11 +689,12 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff * *size -= opt_size; } opts->suboptions |= OPTION_MPTCP_ADD_ADDR; - if (!echo) { + if (!echo) opts->ahmac = add_addr_generate_hmac(msk->local_key, msk->remote_key, &opts->addr); - } + else + opts->ahmac = 0; pr_debug("addr_id=%d, addr_port=%d, ahmac=%llu, echo=%d", opts->addr.id, ntohs(opts->addr.port), opts->ahmac, echo); @@ -735,7 +738,12 @@ static bool mptcp_established_options_mp_prio(struct sock *sk, { struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); - if (!subflow->send_mp_prio) + /* can't send MP_PRIO with MPC, as they share the same option space: + * 'backup'. Also it makes no sense at all + */ + if (!subflow->send_mp_prio || + ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | + OPTION_MPTCP_MPC_ACK) & opts->suboptions)) return false; /* account for the trailing 'nop' option */ @@ -1198,7 +1206,73 @@ static u16 mptcp_make_csum(const struct mptcp_ext *mpext) void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, struct mptcp_out_options *opts) { - if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | + /* RST is mutually exclusive with everything else */ + if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) { + *ptr++ = mptcp_option(MPTCPOPT_RST, + TCPOLEN_MPTCP_RST, + opts->reset_transient, + opts->reset_reason); + return; + } + + /* DSS, MPC, MPJ and ADD_ADDR are mutually exclusive, see + * mptcp_established_options*() + */ + if (likely(OPTION_MPTCP_DSS & opts->suboptions)) { + struct mptcp_ext *mpext = &opts->ext_copy; + u8 len = TCPOLEN_MPTCP_DSS_BASE; + u8 flags = 0; + + if (mpext->use_ack) { + flags = MPTCP_DSS_HAS_ACK; + if (mpext->ack64) { + len += TCPOLEN_MPTCP_DSS_ACK64; + flags |= MPTCP_DSS_ACK64; + } else { + len += TCPOLEN_MPTCP_DSS_ACK32; + } + } + + if (mpext->use_map) { + len += TCPOLEN_MPTCP_DSS_MAP64; + + /* Use only 64-bit mapping flags for now, add + * support for optional 32-bit mappings later. + */ + flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64; + if (mpext->data_fin) + flags |= MPTCP_DSS_DATA_FIN; + + if (opts->csum_reqd) + len += TCPOLEN_MPTCP_DSS_CHECKSUM; + } + + *ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags); + + if (mpext->use_ack) { + if (mpext->ack64) { + put_unaligned_be64(mpext->data_ack, ptr); + ptr += 2; + } else { + put_unaligned_be32(mpext->data_ack32, ptr); + ptr += 1; + } + } + + if (mpext->use_map) { + put_unaligned_be64(mpext->data_seq, ptr); + ptr += 2; + put_unaligned_be32(mpext->subflow_seq, ptr); + ptr += 1; + if (opts->csum_reqd) { + put_unaligned_be32(mpext->data_len << 16 | + mptcp_make_csum(mpext), ptr); + } else { + put_unaligned_be32(mpext->data_len << 16 | + TCPOPT_NOP << 8 | TCPOPT_NOP, ptr); + } + } + } else if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | OPTION_MPTCP_MPC_ACK) & opts->suboptions) { u8 len, flag = MPTCP_CAP_HMAC_SHA256; @@ -1246,10 +1320,31 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, TCPOPT_NOP << 8 | TCPOPT_NOP, ptr); } ptr += 1; - } -mp_capable_done: - if (OPTION_MPTCP_ADD_ADDR & opts->suboptions) { + /* MPC is additionally mutually exclusive with MP_PRIO */ + goto mp_capable_done; + } else if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) { + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, + TCPOLEN_MPTCP_MPJ_SYN, + opts->backup, opts->join_id); + put_unaligned_be32(opts->token, ptr); + ptr += 1; + put_unaligned_be32(opts->nonce, ptr); + ptr += 1; + } else if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) { + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, + TCPOLEN_MPTCP_MPJ_SYNACK, + opts->backup, opts->join_id); + put_unaligned_be64(opts->thmac, ptr); + ptr += 2; + put_unaligned_be32(opts->nonce, ptr); + ptr += 1; + } else if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) { + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, + TCPOLEN_MPTCP_MPJ_ACK, 0, 0); + memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN); + ptr += 5; + } else if (OPTION_MPTCP_ADD_ADDR & opts->suboptions) { struct mptcp_addr_info *addr = &opts->addr; u8 len = TCPOLEN_MPTCP_ADD_ADDR_BASE; u8 echo = MPTCP_ADDR_ECHO; @@ -1308,6 +1403,19 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, } } + if (OPTION_MPTCP_PRIO & opts->suboptions) { + const struct sock *ssk = (const struct sock *)tp; + struct mptcp_subflow_context *subflow; + + subflow = mptcp_subflow_ctx(ssk); + subflow->send_mp_prio = 0; + + *ptr++ = mptcp_option(MPTCPOPT_MP_PRIO, + TCPOLEN_MPTCP_PRIO, + opts->backup, TCPOPT_NOP); + } + +mp_capable_done: if (OPTION_MPTCP_RM_ADDR & opts->suboptions) { u8 i = 1; @@ -1328,107 +1436,6 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, } } - if (OPTION_MPTCP_PRIO & opts->suboptions) { - const struct sock *ssk = (const struct sock *)tp; - struct mptcp_subflow_context *subflow; - - subflow = mptcp_subflow_ctx(ssk); - subflow->send_mp_prio = 0; - - *ptr++ = mptcp_option(MPTCPOPT_MP_PRIO, - TCPOLEN_MPTCP_PRIO, - opts->backup, TCPOPT_NOP); - } - - if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) { - *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, - TCPOLEN_MPTCP_MPJ_SYN, - opts->backup, opts->join_id); - put_unaligned_be32(opts->token, ptr); - ptr += 1; - put_unaligned_be32(opts->nonce, ptr); - ptr += 1; - } - - if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) { - *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, - TCPOLEN_MPTCP_MPJ_SYNACK, - opts->backup, opts->join_id); - put_unaligned_be64(opts->thmac, ptr); - ptr += 2; - put_unaligned_be32(opts->nonce, ptr); - ptr += 1; - } - - if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) { - *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, - TCPOLEN_MPTCP_MPJ_ACK, 0, 0); - memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN); - ptr += 5; - } - - if (OPTION_MPTCP_RST & opts->suboptions) - *ptr++ = mptcp_option(MPTCPOPT_RST, - TCPOLEN_MPTCP_RST, - opts->reset_transient, - opts->reset_reason); - - if (opts->ext_copy.use_ack || opts->ext_copy.use_map) { - struct mptcp_ext *mpext = &opts->ext_copy; - u8 len = TCPOLEN_MPTCP_DSS_BASE; - u8 flags = 0; - - if (mpext->use_ack) { - flags = MPTCP_DSS_HAS_ACK; - if (mpext->ack64) { - len += TCPOLEN_MPTCP_DSS_ACK64; - flags |= MPTCP_DSS_ACK64; - } else { - len += TCPOLEN_MPTCP_DSS_ACK32; - } - } - - if (mpext->use_map) { - len += TCPOLEN_MPTCP_DSS_MAP64; - - /* Use only 64-bit mapping flags for now, add - * support for optional 32-bit mappings later. - */ - flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64; - if (mpext->data_fin) - flags |= MPTCP_DSS_DATA_FIN; - - if (opts->csum_reqd) - len += TCPOLEN_MPTCP_DSS_CHECKSUM; - } - - *ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags); - - if (mpext->use_ack) { - if (mpext->ack64) { - put_unaligned_be64(mpext->data_ack, ptr); - ptr += 2; - } else { - put_unaligned_be32(mpext->data_ack32, ptr); - ptr += 1; - } - } - - if (mpext->use_map) { - put_unaligned_be64(mpext->data_seq, ptr); - ptr += 2; - put_unaligned_be32(mpext->subflow_seq, ptr); - ptr += 1; - if (opts->csum_reqd) { - put_unaligned_be32(mpext->data_len << 16 | - mptcp_make_csum(mpext), ptr); - } else { - put_unaligned_be32(mpext->data_len << 16 | - TCPOPT_NOP << 8 | TCPOPT_NOP, ptr); - } - } - } - if (tp) mptcp_set_rwin(tp); } diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c index 4d1828fd2482..baf2d6e524bd 100644 --- a/net/mptcp/pm.c +++ b/net/mptcp/pm.c @@ -266,10 +266,11 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, struct sk_buff *skb, if (!mptcp_pm_should_add_signal(msk)) goto out_unlock; - if (((msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_ECHO)) || - ((msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_SIGNAL)) && - (msk->pm.local.family == AF_INET6 || msk->pm.local.port))) && - skb && skb_is_tcp_pure_ack(skb)) { + /* always drop every other options for pure ack ADD_ADDR; this is + * plain dup-ack from TCP perspective. The other MPTCP-relevant info, + * if any, will be carried by the other pure ack + */ + if (skb && skb_is_tcp_pure_ack(skb)) { remaining += opt_size; *drop_other_suboptions = true; } diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 34ad1c4bc29f..d960d8b8a8ce 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -26,6 +26,7 @@ #define OPTION_MPTCP_FASTCLOSE BIT(8) #define OPTION_MPTCP_PRIO BIT(9) #define OPTION_MPTCP_RST BIT(10) +#define OPTION_MPTCP_DSS BIT(11) /* MPTCP option subtypes */ #define MPTCPOPT_MP_CAPABLE 0 -- 2.26.3 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH mptcp-next 1/2] mptcp: optimize out option generation 2021-07-23 17:06 ` [PATCH mptcp-next 1/2] mptcp: optimize out option generation Paolo Abeni @ 2021-07-26 3:21 ` Geliang Tang 2021-07-26 9:44 ` Paolo Abeni 2021-07-26 10:06 ` Paolo Abeni 0 siblings, 2 replies; 7+ messages in thread From: Geliang Tang @ 2021-07-26 3:21 UTC (permalink / raw) To: Paolo Abeni; +Cc: mptcp Hi Paolo, Thanks for this patchset, and I have some small comments. Paolo Abeni <pabeni@redhat.com> 于2021年7月24日周六 上午1:06写道: > > Currently we have several protocol contraint on MPTCP option > generation (e.g. MPC and MPJ subopt are mutually exclusive) > and some additionall ones required by our implementation > (e.g. almost all ADD_ADDR variant are mutually exclusive with > everything else). > > We can leverage the above to optimize the out option generation: > we check DSS/MPC/MPJ presencence in a mutually exclusive way, > avoiding many unneeded conditionals in the common case. > > Additionally extend the existing constraint on ADD_ADDR opt on > all subvariant, so that it become fully mutually exclusive with > the above and we can skip another conditional statement the common > case. > > This change is also need by the next patch. > > Signed-off-by: Paolo Abeni <pabeni@redhat.com> > -- > side node: we could probably optimize the conditionals in > mptcp_established_options() > --- > net/mptcp/options.c | 225 ++++++++++++++++++++++--------------------- > net/mptcp/pm.c | 9 +- > net/mptcp/protocol.h | 1 + > 3 files changed, 122 insertions(+), 113 deletions(-) > > diff --git a/net/mptcp/options.c b/net/mptcp/options.c > index eafdb9408f3a..38f324667761 100644 > --- a/net/mptcp/options.c > +++ b/net/mptcp/options.c > @@ -592,6 +592,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, > dss_size = map_size; > if (skb && snd_data_fin_enable) > mptcp_write_data_fin(subflow, skb, &opts->ext_copy); > + opts->suboptions = OPTION_MPTCP_DSS; > ret = true; > } > > @@ -615,6 +616,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, > opts->ext_copy.ack64 = 0; > } > opts->ext_copy.use_ack = 1; > + opts->suboptions = OPTION_MPTCP_DSS; > WRITE_ONCE(msk->old_wspace, __mptcp_space((struct sock *)msk)); > > /* Add kind/length/subtype/flag overhead if mapping is not populated */ > @@ -663,9 +665,9 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff * I think no need to modify the code in mptcp_established_options_add_addr. > struct mptcp_sock *msk = mptcp_sk(subflow->conn); > bool drop_other_suboptions = false; > unsigned int opt_size = *size; > + unsigned int len; > bool echo; > bool port; > - int len; I prefer to keep the type of len unchanged. > > if (!mptcp_pm_should_add_signal(msk) || > !mptcp_pm_add_addr_signal(msk, skb, opt_size, remaining, opts, > @@ -687,11 +689,12 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff * > *size -= opt_size; > } > opts->suboptions |= OPTION_MPTCP_ADD_ADDR; > - if (!echo) { > + if (!echo) > opts->ahmac = add_addr_generate_hmac(msk->local_key, > msk->remote_key, > &opts->addr); > - } > + else > + opts->ahmac = 0; opts->ahmac had been set to zero in mptcp_get_options, no need to clear it again. > pr_debug("addr_id=%d, addr_port=%d, ahmac=%llu, echo=%d", > opts->addr.id, ntohs(opts->addr.port), opts->ahmac, echo); > > @@ -735,7 +738,12 @@ static bool mptcp_established_options_mp_prio(struct sock *sk, > { > struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); > > - if (!subflow->send_mp_prio) > + /* can't send MP_PRIO with MPC, as they share the same option space: > + * 'backup'. Also it makes no sense at all > + */ > + if (!subflow->send_mp_prio || > + ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | > + OPTION_MPTCP_MPC_ACK) & opts->suboptions)) > return false; > > /* account for the trailing 'nop' option */ > @@ -1198,7 +1206,73 @@ static u16 mptcp_make_csum(const struct mptcp_ext *mpext) > void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, > struct mptcp_out_options *opts) > { > - if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | > + /* RST is mutually exclusive with everything else */ > + if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) { > + *ptr++ = mptcp_option(MPTCPOPT_RST, > + TCPOLEN_MPTCP_RST, > + opts->reset_transient, > + opts->reset_reason); > + return; > + } > + > + /* DSS, MPC, MPJ and ADD_ADDR are mutually exclusive, see > + * mptcp_established_options*() > + */ > + if (likely(OPTION_MPTCP_DSS & opts->suboptions)) { > + struct mptcp_ext *mpext = &opts->ext_copy; > + u8 len = TCPOLEN_MPTCP_DSS_BASE; > + u8 flags = 0; > + > + if (mpext->use_ack) { > + flags = MPTCP_DSS_HAS_ACK; > + if (mpext->ack64) { > + len += TCPOLEN_MPTCP_DSS_ACK64; > + flags |= MPTCP_DSS_ACK64; > + } else { > + len += TCPOLEN_MPTCP_DSS_ACK32; > + } > + } > + > + if (mpext->use_map) { > + len += TCPOLEN_MPTCP_DSS_MAP64; > + > + /* Use only 64-bit mapping flags for now, add > + * support for optional 32-bit mappings later. > + */ > + flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64; > + if (mpext->data_fin) > + flags |= MPTCP_DSS_DATA_FIN; > + > + if (opts->csum_reqd) > + len += TCPOLEN_MPTCP_DSS_CHECKSUM; > + } > + > + *ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags); > + > + if (mpext->use_ack) { > + if (mpext->ack64) { > + put_unaligned_be64(mpext->data_ack, ptr); > + ptr += 2; > + } else { > + put_unaligned_be32(mpext->data_ack32, ptr); > + ptr += 1; > + } > + } > + > + if (mpext->use_map) { > + put_unaligned_be64(mpext->data_seq, ptr); > + ptr += 2; > + put_unaligned_be32(mpext->subflow_seq, ptr); > + ptr += 1; > + if (opts->csum_reqd) { > + put_unaligned_be32(mpext->data_len << 16 | > + mptcp_make_csum(mpext), ptr); > + } else { > + put_unaligned_be32(mpext->data_len << 16 | > + TCPOPT_NOP << 8 | TCPOPT_NOP, ptr); > + } > + } > + } else if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | > OPTION_MPTCP_MPC_ACK) & opts->suboptions) { > u8 len, flag = MPTCP_CAP_HMAC_SHA256; > > @@ -1246,10 +1320,31 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, > TCPOPT_NOP << 8 | TCPOPT_NOP, ptr); > } > ptr += 1; > - } > > -mp_capable_done: > - if (OPTION_MPTCP_ADD_ADDR & opts->suboptions) { > + /* MPC is additionally mutually exclusive with MP_PRIO */ > + goto mp_capable_done; > + } else if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) { > + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > + TCPOLEN_MPTCP_MPJ_SYN, > + opts->backup, opts->join_id); > + put_unaligned_be32(opts->token, ptr); > + ptr += 1; > + put_unaligned_be32(opts->nonce, ptr); > + ptr += 1; > + } else if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) { > + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > + TCPOLEN_MPTCP_MPJ_SYNACK, > + opts->backup, opts->join_id); > + put_unaligned_be64(opts->thmac, ptr); > + ptr += 2; > + put_unaligned_be32(opts->nonce, ptr); > + ptr += 1; > + } else if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) { > + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > + TCPOLEN_MPTCP_MPJ_ACK, 0, 0); > + memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN); > + ptr += 5; > + } else if (OPTION_MPTCP_ADD_ADDR & opts->suboptions) { > struct mptcp_addr_info *addr = &opts->addr; > u8 len = TCPOLEN_MPTCP_ADD_ADDR_BASE; > u8 echo = MPTCP_ADDR_ECHO; > @@ -1308,6 +1403,19 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, > } > } > > + if (OPTION_MPTCP_PRIO & opts->suboptions) { > + const struct sock *ssk = (const struct sock *)tp; > + struct mptcp_subflow_context *subflow; > + > + subflow = mptcp_subflow_ctx(ssk); > + subflow->send_mp_prio = 0; > + > + *ptr++ = mptcp_option(MPTCPOPT_MP_PRIO, > + TCPOLEN_MPTCP_PRIO, > + opts->backup, TCPOPT_NOP); > + } > + > +mp_capable_done: > if (OPTION_MPTCP_RM_ADDR & opts->suboptions) { > u8 i = 1; > > @@ -1328,107 +1436,6 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, > } > } > > - if (OPTION_MPTCP_PRIO & opts->suboptions) { > - const struct sock *ssk = (const struct sock *)tp; > - struct mptcp_subflow_context *subflow; > - > - subflow = mptcp_subflow_ctx(ssk); > - subflow->send_mp_prio = 0; > - > - *ptr++ = mptcp_option(MPTCPOPT_MP_PRIO, > - TCPOLEN_MPTCP_PRIO, > - opts->backup, TCPOPT_NOP); > - } > - > - if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) { > - *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > - TCPOLEN_MPTCP_MPJ_SYN, > - opts->backup, opts->join_id); > - put_unaligned_be32(opts->token, ptr); > - ptr += 1; > - put_unaligned_be32(opts->nonce, ptr); > - ptr += 1; > - } > - > - if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) { > - *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > - TCPOLEN_MPTCP_MPJ_SYNACK, > - opts->backup, opts->join_id); > - put_unaligned_be64(opts->thmac, ptr); > - ptr += 2; > - put_unaligned_be32(opts->nonce, ptr); > - ptr += 1; > - } > - > - if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) { > - *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > - TCPOLEN_MPTCP_MPJ_ACK, 0, 0); > - memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN); > - ptr += 5; > - } > - > - if (OPTION_MPTCP_RST & opts->suboptions) > - *ptr++ = mptcp_option(MPTCPOPT_RST, > - TCPOLEN_MPTCP_RST, > - opts->reset_transient, > - opts->reset_reason); > - > - if (opts->ext_copy.use_ack || opts->ext_copy.use_map) { > - struct mptcp_ext *mpext = &opts->ext_copy; > - u8 len = TCPOLEN_MPTCP_DSS_BASE; > - u8 flags = 0; > - > - if (mpext->use_ack) { > - flags = MPTCP_DSS_HAS_ACK; > - if (mpext->ack64) { > - len += TCPOLEN_MPTCP_DSS_ACK64; > - flags |= MPTCP_DSS_ACK64; > - } else { > - len += TCPOLEN_MPTCP_DSS_ACK32; > - } > - } > - > - if (mpext->use_map) { > - len += TCPOLEN_MPTCP_DSS_MAP64; > - > - /* Use only 64-bit mapping flags for now, add > - * support for optional 32-bit mappings later. > - */ > - flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64; > - if (mpext->data_fin) > - flags |= MPTCP_DSS_DATA_FIN; > - > - if (opts->csum_reqd) > - len += TCPOLEN_MPTCP_DSS_CHECKSUM; > - } > - > - *ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags); > - > - if (mpext->use_ack) { > - if (mpext->ack64) { > - put_unaligned_be64(mpext->data_ack, ptr); > - ptr += 2; > - } else { > - put_unaligned_be32(mpext->data_ack32, ptr); > - ptr += 1; > - } > - } > - > - if (mpext->use_map) { > - put_unaligned_be64(mpext->data_seq, ptr); > - ptr += 2; > - put_unaligned_be32(mpext->subflow_seq, ptr); > - ptr += 1; > - if (opts->csum_reqd) { > - put_unaligned_be32(mpext->data_len << 16 | > - mptcp_make_csum(mpext), ptr); > - } else { > - put_unaligned_be32(mpext->data_len << 16 | > - TCPOPT_NOP << 8 | TCPOPT_NOP, ptr); > - } > - } > - } > - > if (tp) > mptcp_set_rwin(tp); > } > diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c > index 4d1828fd2482..baf2d6e524bd 100644 > --- a/net/mptcp/pm.c > +++ b/net/mptcp/pm.c > @@ -266,10 +266,11 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, struct sk_buff *skb, > if (!mptcp_pm_should_add_signal(msk)) > goto out_unlock; > > - if (((msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_ECHO)) || > - ((msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_SIGNAL)) && > - (msk->pm.local.family == AF_INET6 || msk->pm.local.port))) && > - skb && skb_is_tcp_pure_ack(skb)) { > + /* always drop every other options for pure ack ADD_ADDR; this is > + * plain dup-ack from TCP perspective. The other MPTCP-relevant info, > + * if any, will be carried by the other pure ack > + */ > + if (skb && skb_is_tcp_pure_ack(skb)) { > remaining += opt_size; > *drop_other_suboptions = true; > } This part in pm.c should be squashed to the patch "mptcp: move drop_other_suboptions check under pm lock". WDYT? Thanks, -Geliang > diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h > index 34ad1c4bc29f..d960d8b8a8ce 100644 > --- a/net/mptcp/protocol.h > +++ b/net/mptcp/protocol.h > @@ -26,6 +26,7 @@ > #define OPTION_MPTCP_FASTCLOSE BIT(8) > #define OPTION_MPTCP_PRIO BIT(9) > #define OPTION_MPTCP_RST BIT(10) > +#define OPTION_MPTCP_DSS BIT(11) > > /* MPTCP option subtypes */ > #define MPTCPOPT_MP_CAPABLE 0 > -- > 2.26.3 > > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH mptcp-next 1/2] mptcp: optimize out option generation 2021-07-26 3:21 ` Geliang Tang @ 2021-07-26 9:44 ` Paolo Abeni 2021-07-26 10:02 ` Geliang Tang 2021-07-26 10:06 ` Paolo Abeni 1 sibling, 1 reply; 7+ messages in thread From: Paolo Abeni @ 2021-07-26 9:44 UTC (permalink / raw) To: Geliang Tang; +Cc: mptcp On Mon, 2021-07-26 at 11:21 +0800, Geliang Tang wrote: > Hi Paolo, > > Thanks for this patchset, and I have some small comments. > > Paolo Abeni <pabeni@redhat.com> 于2021年7月24日周六 上午1:06写道: > > Currently we have several protocol contraint on MPTCP option > > generation (e.g. MPC and MPJ subopt are mutually exclusive) > > and some additionall ones required by our implementation > > (e.g. almost all ADD_ADDR variant are mutually exclusive with > > everything else). > > > > We can leverage the above to optimize the out option generation: > > we check DSS/MPC/MPJ presencence in a mutually exclusive way, > > avoiding many unneeded conditionals in the common case. > > > > Additionally extend the existing constraint on ADD_ADDR opt on > > all subvariant, so that it become fully mutually exclusive with > > the above and we can skip another conditional statement the common > > case. > > > > This change is also need by the next patch. > > > > Signed-off-by: Paolo Abeni <pabeni@redhat.com> > > -- > > side node: we could probably optimize the conditionals in > > mptcp_established_options() > > --- > > net/mptcp/options.c | 225 ++++++++++++++++++++++--------------------- > > net/mptcp/pm.c | 9 +- > > net/mptcp/protocol.h | 1 + > > 3 files changed, 122 insertions(+), 113 deletions(-) > > > > diff --git a/net/mptcp/options.c b/net/mptcp/options.c > > index eafdb9408f3a..38f324667761 100644 > > --- a/net/mptcp/options.c > > +++ b/net/mptcp/options.c > > @@ -592,6 +592,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, > > dss_size = map_size; > > if (skb && snd_data_fin_enable) > > mptcp_write_data_fin(subflow, skb, &opts->ext_copy); > > + opts->suboptions = OPTION_MPTCP_DSS; > > ret = true; > > } > > > > @@ -615,6 +616,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, > > opts->ext_copy.ack64 = 0; > > } > > opts->ext_copy.use_ack = 1; > > + opts->suboptions = OPTION_MPTCP_DSS; > > WRITE_ONCE(msk->old_wspace, __mptcp_space((struct sock *)msk)); > > > > /* Add kind/length/subtype/flag overhead if mapping is not populated */ > > @@ -663,9 +665,9 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff * > > I think no need to modify the code in mptcp_established_options_add_addr. > > > struct mptcp_sock *msk = mptcp_sk(subflow->conn); > > bool drop_other_suboptions = false; > > unsigned int opt_size = *size; > > + unsigned int len; > > bool echo; > > bool port; > > - int len; > > I prefer to keep the type of len unchanged. OK. > > > if (!mptcp_pm_should_add_signal(msk) || > > !mptcp_pm_add_addr_signal(msk, skb, opt_size, remaining, opts, > > @@ -687,11 +689,12 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff * > > *size -= opt_size; > > } > > opts->suboptions |= OPTION_MPTCP_ADD_ADDR; > > - if (!echo) { > > + if (!echo) > > opts->ahmac = add_addr_generate_hmac(msk->local_key, > > msk->remote_key, > > &opts->addr); > > - } > > + else > > + opts->ahmac = 0; > > opts->ahmac had been set to zero in mptcp_get_options, no need to clear it > again. This is for the output path, mptcp_get_options() is not invoked. 'ops' has been cleared by the TCP caller. Sice a few fields are aliased, and the add_addr is added after the DSS, the latter could have already modified the underlaying memory. Without this assignment we will end-up appending the hmac even for add_addr 'echo', and a bunch of tests will fail. Perhaps is better adding some comments explaining why such set operation is needed... > > > pr_debug("addr_id=%d, addr_port=%d, ahmac=%llu, echo=%d", > > opts->addr.id, ntohs(opts->addr.port), opts->ahmac, echo); > > > > @@ -735,7 +738,12 @@ static bool mptcp_established_options_mp_prio(struct sock *sk, > > { > > struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); > > > > - if (!subflow->send_mp_prio) > > + /* can't send MP_PRIO with MPC, as they share the same option space: > > + * 'backup'. Also it makes no sense at all > > + */ > > + if (!subflow->send_mp_prio || > > + ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | > > + OPTION_MPTCP_MPC_ACK) & opts->suboptions)) > > return false; > > > > /* account for the trailing 'nop' option */ > > @@ -1198,7 +1206,73 @@ static u16 mptcp_make_csum(const struct mptcp_ext *mpext) > > void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, > > struct mptcp_out_options *opts) > > { > > - if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | > > + /* RST is mutually exclusive with everything else */ > > + if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) { > > + *ptr++ = mptcp_option(MPTCPOPT_RST, > > + TCPOLEN_MPTCP_RST, > > + opts->reset_transient, > > + opts->reset_reason); > > + return; > > + } > > + > > + /* DSS, MPC, MPJ and ADD_ADDR are mutually exclusive, see > > + * mptcp_established_options*() > > + */ > > + if (likely(OPTION_MPTCP_DSS & opts->suboptions)) { > > + struct mptcp_ext *mpext = &opts->ext_copy; > > + u8 len = TCPOLEN_MPTCP_DSS_BASE; > > + u8 flags = 0; > > + > > + if (mpext->use_ack) { > > + flags = MPTCP_DSS_HAS_ACK; > > + if (mpext->ack64) { > > + len += TCPOLEN_MPTCP_DSS_ACK64; > > + flags |= MPTCP_DSS_ACK64; > > + } else { > > + len += TCPOLEN_MPTCP_DSS_ACK32; > > + } > > + } > > + > > + if (mpext->use_map) { > > + len += TCPOLEN_MPTCP_DSS_MAP64; > > + > > + /* Use only 64-bit mapping flags for now, add > > + * support for optional 32-bit mappings later. > > + */ > > + flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64; > > + if (mpext->data_fin) > > + flags |= MPTCP_DSS_DATA_FIN; > > + > > + if (opts->csum_reqd) > > + len += TCPOLEN_MPTCP_DSS_CHECKSUM; > > + } > > + > > + *ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags); > > + > > + if (mpext->use_ack) { > > + if (mpext->ack64) { > > + put_unaligned_be64(mpext->data_ack, ptr); > > + ptr += 2; > > + } else { > > + put_unaligned_be32(mpext->data_ack32, ptr); > > + ptr += 1; > > + } > > + } > > + > > + if (mpext->use_map) { > > + put_unaligned_be64(mpext->data_seq, ptr); > > + ptr += 2; > > + put_unaligned_be32(mpext->subflow_seq, ptr); > > + ptr += 1; > > + if (opts->csum_reqd) { > > + put_unaligned_be32(mpext->data_len << 16 | > > + mptcp_make_csum(mpext), ptr); > > + } else { > > + put_unaligned_be32(mpext->data_len << 16 | > > + TCPOPT_NOP << 8 | TCPOPT_NOP, ptr); > > + } > > + } > > + } else if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | > > OPTION_MPTCP_MPC_ACK) & opts->suboptions) { > > u8 len, flag = MPTCP_CAP_HMAC_SHA256; > > > > @@ -1246,10 +1320,31 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, > > TCPOPT_NOP << 8 | TCPOPT_NOP, ptr); > > } > > ptr += 1; > > - } > > > > -mp_capable_done: > > - if (OPTION_MPTCP_ADD_ADDR & opts->suboptions) { > > + /* MPC is additionally mutually exclusive with MP_PRIO */ > > + goto mp_capable_done; > > + } else if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) { > > + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > > + TCPOLEN_MPTCP_MPJ_SYN, > > + opts->backup, opts->join_id); > > + put_unaligned_be32(opts->token, ptr); > > + ptr += 1; > > + put_unaligned_be32(opts->nonce, ptr); > > + ptr += 1; > > + } else if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) { > > + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > > + TCPOLEN_MPTCP_MPJ_SYNACK, > > + opts->backup, opts->join_id); > > + put_unaligned_be64(opts->thmac, ptr); > > + ptr += 2; > > + put_unaligned_be32(opts->nonce, ptr); > > + ptr += 1; > > + } else if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) { > > + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > > + TCPOLEN_MPTCP_MPJ_ACK, 0, 0); > > + memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN); > > + ptr += 5; > > + } else if (OPTION_MPTCP_ADD_ADDR & opts->suboptions) { > > struct mptcp_addr_info *addr = &opts->addr; > > u8 len = TCPOLEN_MPTCP_ADD_ADDR_BASE; > > u8 echo = MPTCP_ADDR_ECHO; > > @@ -1308,6 +1403,19 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, > > } > > } > > > > + if (OPTION_MPTCP_PRIO & opts->suboptions) { > > + const struct sock *ssk = (const struct sock *)tp; > > + struct mptcp_subflow_context *subflow; > > + > > + subflow = mptcp_subflow_ctx(ssk); > > + subflow->send_mp_prio = 0; > > + > > + *ptr++ = mptcp_option(MPTCPOPT_MP_PRIO, > > + TCPOLEN_MPTCP_PRIO, > > + opts->backup, TCPOPT_NOP); > > + } > > + > > +mp_capable_done: > > if (OPTION_MPTCP_RM_ADDR & opts->suboptions) { > > u8 i = 1; > > > > @@ -1328,107 +1436,6 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, > > } > > } > > > > - if (OPTION_MPTCP_PRIO & opts->suboptions) { > > - const struct sock *ssk = (const struct sock *)tp; > > - struct mptcp_subflow_context *subflow; > > - > > - subflow = mptcp_subflow_ctx(ssk); > > - subflow->send_mp_prio = 0; > > - > > - *ptr++ = mptcp_option(MPTCPOPT_MP_PRIO, > > - TCPOLEN_MPTCP_PRIO, > > - opts->backup, TCPOPT_NOP); > > - } > > - > > - if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) { > > - *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > > - TCPOLEN_MPTCP_MPJ_SYN, > > - opts->backup, opts->join_id); > > - put_unaligned_be32(opts->token, ptr); > > - ptr += 1; > > - put_unaligned_be32(opts->nonce, ptr); > > - ptr += 1; > > - } > > - > > - if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) { > > - *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > > - TCPOLEN_MPTCP_MPJ_SYNACK, > > - opts->backup, opts->join_id); > > - put_unaligned_be64(opts->thmac, ptr); > > - ptr += 2; > > - put_unaligned_be32(opts->nonce, ptr); > > - ptr += 1; > > - } > > - > > - if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) { > > - *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > > - TCPOLEN_MPTCP_MPJ_ACK, 0, 0); > > - memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN); > > - ptr += 5; > > - } > > - > > - if (OPTION_MPTCP_RST & opts->suboptions) > > - *ptr++ = mptcp_option(MPTCPOPT_RST, > > - TCPOLEN_MPTCP_RST, > > - opts->reset_transient, > > - opts->reset_reason); > > - > > - if (opts->ext_copy.use_ack || opts->ext_copy.use_map) { > > - struct mptcp_ext *mpext = &opts->ext_copy; > > - u8 len = TCPOLEN_MPTCP_DSS_BASE; > > - u8 flags = 0; > > - > > - if (mpext->use_ack) { > > - flags = MPTCP_DSS_HAS_ACK; > > - if (mpext->ack64) { > > - len += TCPOLEN_MPTCP_DSS_ACK64; > > - flags |= MPTCP_DSS_ACK64; > > - } else { > > - len += TCPOLEN_MPTCP_DSS_ACK32; > > - } > > - } > > - > > - if (mpext->use_map) { > > - len += TCPOLEN_MPTCP_DSS_MAP64; > > - > > - /* Use only 64-bit mapping flags for now, add > > - * support for optional 32-bit mappings later. > > - */ > > - flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64; > > - if (mpext->data_fin) > > - flags |= MPTCP_DSS_DATA_FIN; > > - > > - if (opts->csum_reqd) > > - len += TCPOLEN_MPTCP_DSS_CHECKSUM; > > - } > > - > > - *ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags); > > - > > - if (mpext->use_ack) { > > - if (mpext->ack64) { > > - put_unaligned_be64(mpext->data_ack, ptr); > > - ptr += 2; > > - } else { > > - put_unaligned_be32(mpext->data_ack32, ptr); > > - ptr += 1; > > - } > > - } > > - > > - if (mpext->use_map) { > > - put_unaligned_be64(mpext->data_seq, ptr); > > - ptr += 2; > > - put_unaligned_be32(mpext->subflow_seq, ptr); > > - ptr += 1; > > - if (opts->csum_reqd) { > > - put_unaligned_be32(mpext->data_len << 16 | > > - mptcp_make_csum(mpext), ptr); > > - } else { > > - put_unaligned_be32(mpext->data_len << 16 | > > - TCPOPT_NOP << 8 | TCPOPT_NOP, ptr); > > - } > > - } > > - } > > - > > if (tp) > > mptcp_set_rwin(tp); > > } > > diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c > > index 4d1828fd2482..baf2d6e524bd 100644 > > --- a/net/mptcp/pm.c > > +++ b/net/mptcp/pm.c > > @@ -266,10 +266,11 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, struct sk_buff *skb, > > if (!mptcp_pm_should_add_signal(msk)) > > goto out_unlock; > > > > - if (((msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_ECHO)) || > > - ((msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_SIGNAL)) && > > - (msk->pm.local.family == AF_INET6 || msk->pm.local.port))) && > > - skb && skb_is_tcp_pure_ack(skb)) { > > + /* always drop every other options for pure ack ADD_ADDR; this is > > + * plain dup-ack from TCP perspective. The other MPTCP-relevant info, > > + * if any, will be carried by the other pure ack > > + */ > > + if (skb && skb_is_tcp_pure_ack(skb)) { > > remaining += opt_size; > > *drop_other_suboptions = true; > > } > > This part in pm.c should be squashed to the patch "mptcp: move > drop_other_suboptions check under pm lock". > > WDYT? I was wondering if that chunk would deserve a separate patch. Squashing the change in another patch would still mix multiple intens in a single change, but the modifications are indeed related. Overall agreed ;) /P ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH mptcp-next 1/2] mptcp: optimize out option generation 2021-07-26 9:44 ` Paolo Abeni @ 2021-07-26 10:02 ` Geliang Tang 0 siblings, 0 replies; 7+ messages in thread From: Geliang Tang @ 2021-07-26 10:02 UTC (permalink / raw) To: Paolo Abeni; +Cc: mptcp Paolo Abeni <pabeni@redhat.com> 于2021年7月26日周一 下午5:44写道: > > On Mon, 2021-07-26 at 11:21 +0800, Geliang Tang wrote: > > Hi Paolo, > > > > Thanks for this patchset, and I have some small comments. > > > > Paolo Abeni <pabeni@redhat.com> 于2021年7月24日周六 上午1:06写道: > > > Currently we have several protocol contraint on MPTCP option > > > generation (e.g. MPC and MPJ subopt are mutually exclusive) > > > and some additionall ones required by our implementation > > > (e.g. almost all ADD_ADDR variant are mutually exclusive with > > > everything else). > > > > > > We can leverage the above to optimize the out option generation: > > > we check DSS/MPC/MPJ presencence in a mutually exclusive way, > > > avoiding many unneeded conditionals in the common case. > > > > > > Additionally extend the existing constraint on ADD_ADDR opt on > > > all subvariant, so that it become fully mutually exclusive with > > > the above and we can skip another conditional statement the common > > > case. > > > > > > This change is also need by the next patch. > > > > > > Signed-off-by: Paolo Abeni <pabeni@redhat.com> > > > -- > > > side node: we could probably optimize the conditionals in > > > mptcp_established_options() > > > --- > > > net/mptcp/options.c | 225 ++++++++++++++++++++++--------------------- > > > net/mptcp/pm.c | 9 +- > > > net/mptcp/protocol.h | 1 + > > > 3 files changed, 122 insertions(+), 113 deletions(-) > > > > > > diff --git a/net/mptcp/options.c b/net/mptcp/options.c > > > index eafdb9408f3a..38f324667761 100644 > > > --- a/net/mptcp/options.c > > > +++ b/net/mptcp/options.c > > > @@ -592,6 +592,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, > > > dss_size = map_size; > > > if (skb && snd_data_fin_enable) > > > mptcp_write_data_fin(subflow, skb, &opts->ext_copy); > > > + opts->suboptions = OPTION_MPTCP_DSS; > > > ret = true; > > > } > > > > > > @@ -615,6 +616,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, > > > opts->ext_copy.ack64 = 0; > > > } > > > opts->ext_copy.use_ack = 1; > > > + opts->suboptions = OPTION_MPTCP_DSS; > > > WRITE_ONCE(msk->old_wspace, __mptcp_space((struct sock *)msk)); > > > > > > /* Add kind/length/subtype/flag overhead if mapping is not populated */ > > > @@ -663,9 +665,9 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff * > > > > I think no need to modify the code in mptcp_established_options_add_addr. > > > > > struct mptcp_sock *msk = mptcp_sk(subflow->conn); > > > bool drop_other_suboptions = false; > > > unsigned int opt_size = *size; > > > + unsigned int len; > > > bool echo; > > > bool port; > > > - int len; > > > > I prefer to keep the type of len unchanged. > > OK. > > > > > > if (!mptcp_pm_should_add_signal(msk) || > > > !mptcp_pm_add_addr_signal(msk, skb, opt_size, remaining, opts, > > > @@ -687,11 +689,12 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff * > > > *size -= opt_size; > > > } > > > opts->suboptions |= OPTION_MPTCP_ADD_ADDR; > > > - if (!echo) { > > > + if (!echo) > > > opts->ahmac = add_addr_generate_hmac(msk->local_key, > > > msk->remote_key, > > > &opts->addr); > > > - } > > > + else > > > + opts->ahmac = 0; > > > > opts->ahmac had been set to zero in mptcp_get_options, no need to clear it > > again. > > This is for the output path, mptcp_get_options() is not invoked. 'ops' Sorry, my fault. > has been cleared by the TCP caller. Sice a few fields are aliased, and > the add_addr is added after the DSS, the latter could have already > modified the underlaying memory. > > Without this assignment we will end-up appending the hmac even for > add_addr 'echo', and a bunch of tests will fail. > > Perhaps is better adding some comments explaining why such set > operation is needed... Yes, that's helpful. > > > > > pr_debug("addr_id=%d, addr_port=%d, ahmac=%llu, echo=%d", > > > opts->addr.id, ntohs(opts->addr.port), opts->ahmac, echo); > > > > > > @@ -735,7 +738,12 @@ static bool mptcp_established_options_mp_prio(struct sock *sk, > > > { > > > struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); > > > > > > - if (!subflow->send_mp_prio) > > > + /* can't send MP_PRIO with MPC, as they share the same option space: > > > + * 'backup'. Also it makes no sense at all > > > + */ > > > + if (!subflow->send_mp_prio || > > > + ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | > > > + OPTION_MPTCP_MPC_ACK) & opts->suboptions)) > > > return false; > > > > > > /* account for the trailing 'nop' option */ > > > @@ -1198,7 +1206,73 @@ static u16 mptcp_make_csum(const struct mptcp_ext *mpext) > > > void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, > > > struct mptcp_out_options *opts) > > > { > > > - if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | > > > + /* RST is mutually exclusive with everything else */ > > > + if (unlikely(OPTION_MPTCP_RST & opts->suboptions)) { > > > + *ptr++ = mptcp_option(MPTCPOPT_RST, > > > + TCPOLEN_MPTCP_RST, > > > + opts->reset_transient, > > > + opts->reset_reason); > > > + return; > > > + } > > > + > > > + /* DSS, MPC, MPJ and ADD_ADDR are mutually exclusive, see > > > + * mptcp_established_options*() > > > + */ > > > + if (likely(OPTION_MPTCP_DSS & opts->suboptions)) { > > > + struct mptcp_ext *mpext = &opts->ext_copy; > > > + u8 len = TCPOLEN_MPTCP_DSS_BASE; > > > + u8 flags = 0; > > > + > > > + if (mpext->use_ack) { > > > + flags = MPTCP_DSS_HAS_ACK; > > > + if (mpext->ack64) { > > > + len += TCPOLEN_MPTCP_DSS_ACK64; > > > + flags |= MPTCP_DSS_ACK64; > > > + } else { > > > + len += TCPOLEN_MPTCP_DSS_ACK32; > > > + } > > > + } > > > + > > > + if (mpext->use_map) { > > > + len += TCPOLEN_MPTCP_DSS_MAP64; > > > + > > > + /* Use only 64-bit mapping flags for now, add > > > + * support for optional 32-bit mappings later. > > > + */ > > > + flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64; > > > + if (mpext->data_fin) > > > + flags |= MPTCP_DSS_DATA_FIN; > > > + > > > + if (opts->csum_reqd) > > > + len += TCPOLEN_MPTCP_DSS_CHECKSUM; > > > + } > > > + > > > + *ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags); > > > + > > > + if (mpext->use_ack) { > > > + if (mpext->ack64) { > > > + put_unaligned_be64(mpext->data_ack, ptr); > > > + ptr += 2; > > > + } else { > > > + put_unaligned_be32(mpext->data_ack32, ptr); > > > + ptr += 1; > > > + } > > > + } > > > + > > > + if (mpext->use_map) { > > > + put_unaligned_be64(mpext->data_seq, ptr); > > > + ptr += 2; > > > + put_unaligned_be32(mpext->subflow_seq, ptr); > > > + ptr += 1; > > > + if (opts->csum_reqd) { > > > + put_unaligned_be32(mpext->data_len << 16 | > > > + mptcp_make_csum(mpext), ptr); > > > + } else { > > > + put_unaligned_be32(mpext->data_len << 16 | > > > + TCPOPT_NOP << 8 | TCPOPT_NOP, ptr); > > > + } > > > + } > > > + } else if ((OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_SYNACK | > > > OPTION_MPTCP_MPC_ACK) & opts->suboptions) { > > > u8 len, flag = MPTCP_CAP_HMAC_SHA256; > > > > > > @@ -1246,10 +1320,31 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, > > > TCPOPT_NOP << 8 | TCPOPT_NOP, ptr); > > > } > > > ptr += 1; > > > - } > > > > > > -mp_capable_done: > > > - if (OPTION_MPTCP_ADD_ADDR & opts->suboptions) { > > > + /* MPC is additionally mutually exclusive with MP_PRIO */ > > > + goto mp_capable_done; > > > + } else if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) { > > > + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > > > + TCPOLEN_MPTCP_MPJ_SYN, > > > + opts->backup, opts->join_id); > > > + put_unaligned_be32(opts->token, ptr); > > > + ptr += 1; > > > + put_unaligned_be32(opts->nonce, ptr); > > > + ptr += 1; > > > + } else if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) { > > > + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > > > + TCPOLEN_MPTCP_MPJ_SYNACK, > > > + opts->backup, opts->join_id); > > > + put_unaligned_be64(opts->thmac, ptr); > > > + ptr += 2; > > > + put_unaligned_be32(opts->nonce, ptr); > > > + ptr += 1; > > > + } else if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) { > > > + *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > > > + TCPOLEN_MPTCP_MPJ_ACK, 0, 0); > > > + memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN); > > > + ptr += 5; > > > + } else if (OPTION_MPTCP_ADD_ADDR & opts->suboptions) { > > > struct mptcp_addr_info *addr = &opts->addr; > > > u8 len = TCPOLEN_MPTCP_ADD_ADDR_BASE; > > > u8 echo = MPTCP_ADDR_ECHO; > > > @@ -1308,6 +1403,19 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, > > > } > > > } > > > > > > + if (OPTION_MPTCP_PRIO & opts->suboptions) { > > > + const struct sock *ssk = (const struct sock *)tp; > > > + struct mptcp_subflow_context *subflow; > > > + > > > + subflow = mptcp_subflow_ctx(ssk); > > > + subflow->send_mp_prio = 0; > > > + > > > + *ptr++ = mptcp_option(MPTCPOPT_MP_PRIO, > > > + TCPOLEN_MPTCP_PRIO, > > > + opts->backup, TCPOPT_NOP); > > > + } > > > + > > > +mp_capable_done: > > > if (OPTION_MPTCP_RM_ADDR & opts->suboptions) { > > > u8 i = 1; > > > > > > @@ -1328,107 +1436,6 @@ void mptcp_write_options(__be32 *ptr, const struct tcp_sock *tp, > > > } > > > } > > > > > > - if (OPTION_MPTCP_PRIO & opts->suboptions) { > > > - const struct sock *ssk = (const struct sock *)tp; > > > - struct mptcp_subflow_context *subflow; > > > - > > > - subflow = mptcp_subflow_ctx(ssk); > > > - subflow->send_mp_prio = 0; > > > - > > > - *ptr++ = mptcp_option(MPTCPOPT_MP_PRIO, > > > - TCPOLEN_MPTCP_PRIO, > > > - opts->backup, TCPOPT_NOP); > > > - } > > > - > > > - if (OPTION_MPTCP_MPJ_SYN & opts->suboptions) { > > > - *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > > > - TCPOLEN_MPTCP_MPJ_SYN, > > > - opts->backup, opts->join_id); > > > - put_unaligned_be32(opts->token, ptr); > > > - ptr += 1; > > > - put_unaligned_be32(opts->nonce, ptr); > > > - ptr += 1; > > > - } > > > - > > > - if (OPTION_MPTCP_MPJ_SYNACK & opts->suboptions) { > > > - *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > > > - TCPOLEN_MPTCP_MPJ_SYNACK, > > > - opts->backup, opts->join_id); > > > - put_unaligned_be64(opts->thmac, ptr); > > > - ptr += 2; > > > - put_unaligned_be32(opts->nonce, ptr); > > > - ptr += 1; > > > - } > > > - > > > - if (OPTION_MPTCP_MPJ_ACK & opts->suboptions) { > > > - *ptr++ = mptcp_option(MPTCPOPT_MP_JOIN, > > > - TCPOLEN_MPTCP_MPJ_ACK, 0, 0); > > > - memcpy(ptr, opts->hmac, MPTCPOPT_HMAC_LEN); > > > - ptr += 5; > > > - } > > > - > > > - if (OPTION_MPTCP_RST & opts->suboptions) > > > - *ptr++ = mptcp_option(MPTCPOPT_RST, > > > - TCPOLEN_MPTCP_RST, > > > - opts->reset_transient, > > > - opts->reset_reason); > > > - > > > - if (opts->ext_copy.use_ack || opts->ext_copy.use_map) { > > > - struct mptcp_ext *mpext = &opts->ext_copy; > > > - u8 len = TCPOLEN_MPTCP_DSS_BASE; > > > - u8 flags = 0; > > > - > > > - if (mpext->use_ack) { > > > - flags = MPTCP_DSS_HAS_ACK; > > > - if (mpext->ack64) { > > > - len += TCPOLEN_MPTCP_DSS_ACK64; > > > - flags |= MPTCP_DSS_ACK64; > > > - } else { > > > - len += TCPOLEN_MPTCP_DSS_ACK32; > > > - } > > > - } > > > - > > > - if (mpext->use_map) { > > > - len += TCPOLEN_MPTCP_DSS_MAP64; > > > - > > > - /* Use only 64-bit mapping flags for now, add > > > - * support for optional 32-bit mappings later. > > > - */ > > > - flags |= MPTCP_DSS_HAS_MAP | MPTCP_DSS_DSN64; > > > - if (mpext->data_fin) > > > - flags |= MPTCP_DSS_DATA_FIN; > > > - > > > - if (opts->csum_reqd) > > > - len += TCPOLEN_MPTCP_DSS_CHECKSUM; > > > - } > > > - > > > - *ptr++ = mptcp_option(MPTCPOPT_DSS, len, 0, flags); > > > - > > > - if (mpext->use_ack) { > > > - if (mpext->ack64) { > > > - put_unaligned_be64(mpext->data_ack, ptr); > > > - ptr += 2; > > > - } else { > > > - put_unaligned_be32(mpext->data_ack32, ptr); > > > - ptr += 1; > > > - } > > > - } > > > - > > > - if (mpext->use_map) { > > > - put_unaligned_be64(mpext->data_seq, ptr); > > > - ptr += 2; > > > - put_unaligned_be32(mpext->subflow_seq, ptr); > > > - ptr += 1; > > > - if (opts->csum_reqd) { > > > - put_unaligned_be32(mpext->data_len << 16 | > > > - mptcp_make_csum(mpext), ptr); > > > - } else { > > > - put_unaligned_be32(mpext->data_len << 16 | > > > - TCPOPT_NOP << 8 | TCPOPT_NOP, ptr); > > > - } > > > - } > > > - } > > > - > > > if (tp) > > > mptcp_set_rwin(tp); > > > } > > > diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c > > > index 4d1828fd2482..baf2d6e524bd 100644 > > > --- a/net/mptcp/pm.c > > > +++ b/net/mptcp/pm.c > > > @@ -266,10 +266,11 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, struct sk_buff *skb, > > > if (!mptcp_pm_should_add_signal(msk)) > > > goto out_unlock; > > > > > > - if (((msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_ECHO)) || > > > - ((msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_SIGNAL)) && > > > - (msk->pm.local.family == AF_INET6 || msk->pm.local.port))) && > > > - skb && skb_is_tcp_pure_ack(skb)) { > > > + /* always drop every other options for pure ack ADD_ADDR; this is > > > + * plain dup-ack from TCP perspective. The other MPTCP-relevant info, > > > + * if any, will be carried by the other pure ack > > > + */ > > > + if (skb && skb_is_tcp_pure_ack(skb)) { > > > remaining += opt_size; > > > *drop_other_suboptions = true; > > > } > > > > This part in pm.c should be squashed to the patch "mptcp: move > > drop_other_suboptions check under pm lock". > > > > WDYT? > > I was wondering if that chunk would deserve a separate patch. Sure, a separate patch is fine. Thanks, -Geliang > > Squashing the change in another patch would still mix multiple intens > in a single change, but the modifications are indeed related. Overall > agreed ;) > > /P > > > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH mptcp-next 1/2] mptcp: optimize out option generation 2021-07-26 3:21 ` Geliang Tang 2021-07-26 9:44 ` Paolo Abeni @ 2021-07-26 10:06 ` Paolo Abeni 1 sibling, 0 replies; 7+ messages in thread From: Paolo Abeni @ 2021-07-26 10:06 UTC (permalink / raw) To: Geliang Tang; +Cc: mptcp On Mon, 2021-07-26 at 11:21 +0800, Geliang Tang wrote: > Hi Paolo, > > Thanks for this patchset, and I have some small comments. > > Paolo Abeni <pabeni@redhat.com> 于2021年7月24日周六 上午1:06写道: > > Currently we have several protocol contraint on MPTCP option > > generation (e.g. MPC and MPJ subopt are mutually exclusive) > > and some additionall ones required by our implementation > > (e.g. almost all ADD_ADDR variant are mutually exclusive with > > everything else). > > > > We can leverage the above to optimize the out option generation: > > we check DSS/MPC/MPJ presencence in a mutually exclusive way, > > avoiding many unneeded conditionals in the common case. > > > > Additionally extend the existing constraint on ADD_ADDR opt on > > all subvariant, so that it become fully mutually exclusive with > > the above and we can skip another conditional statement the common > > case. > > > > This change is also need by the next patch. > > > > Signed-off-by: Paolo Abeni <pabeni@redhat.com> > > -- > > side node: we could probably optimize the conditionals in > > mptcp_established_options() > > --- > > net/mptcp/options.c | 225 ++++++++++++++++++++++--------------------- > > net/mptcp/pm.c | 9 +- > > net/mptcp/protocol.h | 1 + > > 3 files changed, 122 insertions(+), 113 deletions(-) > > > > diff --git a/net/mptcp/options.c b/net/mptcp/options.c > > index eafdb9408f3a..38f324667761 100644 > > --- a/net/mptcp/options.c > > +++ b/net/mptcp/options.c > > @@ -592,6 +592,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, > > dss_size = map_size; > > if (skb && snd_data_fin_enable) > > mptcp_write_data_fin(subflow, skb, &opts->ext_copy); > > + opts->suboptions = OPTION_MPTCP_DSS; > > ret = true; > > } > > > > @@ -615,6 +616,7 @@ static bool mptcp_established_options_dss(struct sock *sk, struct sk_buff *skb, > > opts->ext_copy.ack64 = 0; > > } > > opts->ext_copy.use_ack = 1; > > + opts->suboptions = OPTION_MPTCP_DSS; > > WRITE_ONCE(msk->old_wspace, __mptcp_space((struct sock *)msk)); > > > > /* Add kind/length/subtype/flag overhead if mapping is not populated */ > > @@ -663,9 +665,9 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff * > > I think no need to modify the code in mptcp_established_options_add_addr. Uhmmm... I just noted with need an additional change in there: avoid clearing 'ext_copy'. /P ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH mptcp-next 2/2] mptcp: shrink mptcp_out_options struct 2021-07-23 17:06 [PATCH mptcp-next 0/2] mptcp: minor out optimization Paolo Abeni 2021-07-23 17:06 ` [PATCH mptcp-next 1/2] mptcp: optimize out option generation Paolo Abeni @ 2021-07-23 17:06 ` Paolo Abeni 1 sibling, 0 replies; 7+ messages in thread From: Paolo Abeni @ 2021-07-23 17:06 UTC (permalink / raw) To: mptcp After the previous patch we can alias with an union several fields in mptcp_out_options. Such struct is stack allocated and memset() for each plain TCP out packet. Every saved byted counts. Before: pahole -EC mptcp_out_options # ... /* size: 136, cachelines: 3, members: 17 */ After: pahole -EC mptcp_out_options # ... /* size: 56, cachelines: 1, members: 9 */ Signed-off-by: Paolo Abeni <pabeni@redhat.com> --- include/net/mptcp.h | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/include/net/mptcp.h b/include/net/mptcp.h index 8b5af683a818..3236010afa29 100644 --- a/include/net/mptcp.h +++ b/include/net/mptcp.h @@ -58,10 +58,6 @@ struct mptcp_addr_info { struct mptcp_out_options { #if IS_ENABLED(CONFIG_MPTCP) u16 suboptions; - u64 sndr_key; - u64 rcvr_key; - u64 ahmac; - struct mptcp_addr_info addr; struct mptcp_rm_list rm_list; u8 join_id; u8 backup; @@ -69,11 +65,23 @@ struct mptcp_out_options { reset_transient:1, csum_reqd:1, allow_join_id0:1; - u32 nonce; - u64 thmac; - u32 token; - u8 hmac[20]; - struct mptcp_ext ext_copy; + union { + struct { + u64 sndr_key; + u64 rcvr_key; + }; + struct { + struct mptcp_addr_info addr; + u64 ahmac; + }; + struct mptcp_ext ext_copy; + struct { + u32 nonce; + u32 token; + u64 thmac; + u8 hmac[20]; + }; + }; #endif }; -- 2.26.3 ^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2021-07-26 10:07 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-07-23 17:06 [PATCH mptcp-next 0/2] mptcp: minor out optimization Paolo Abeni 2021-07-23 17:06 ` [PATCH mptcp-next 1/2] mptcp: optimize out option generation Paolo Abeni 2021-07-26 3:21 ` Geliang Tang 2021-07-26 9:44 ` Paolo Abeni 2021-07-26 10:02 ` Geliang Tang 2021-07-26 10:06 ` Paolo Abeni 2021-07-23 17:06 ` [PATCH mptcp-next 2/2] mptcp: shrink mptcp_out_options struct Paolo Abeni
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).