From: Matthieu Baerts (NGI0) Date: Fri, 5 Jun 2026 09:21:47 +0000 (+1000) Subject: mptcp: pm: avoid computing add_addr size twice X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=06c62385be856bc96acc0f49465a85fd047c77ad;p=thirdparty%2Flinux.git mptcp: pm: avoid computing add_addr size twice mptcp_add_addr_len helper was called twice: in mptcp_pm_add_addr_signal, then just after in mptcp_established_options_add_addr. Both to check the remaining space. The second call is not needed: if there is not enough space, mptcp_pm_add_addr_signal will return false, and the caller, mptcp_established_options_add_addr, will do the same without re-checking the size again. Instead, mptcp_pm_add_addr_signal can directly set the size. Note that the returned size can be negative when other suboptions are dropped, e.g. to send an echo ADD_ADDR with a v4 address, and no port. While at it: - move mptcp_add_addr_len to pm.c, as it is now only used from there - use 'int' in mptcp_add_addr_len for the size, instead of having a mix - use a bool for 'ret' in mptcp_pm_add_addr_signal Reviewed-by: Mat Martineau Signed-off-by: Matthieu Baerts (NGI0) Link: https://patch.msgid.link/20260605-net-next-mptcp-add-addr6-port-ts-v2-3-758e7ca73f4d@kernel.org Signed-off-by: Jakub Kicinski --- diff --git a/net/mptcp/options.c b/net/mptcp/options.c index e44db4768f6c..2e4b6aafbad5 100644 --- a/net/mptcp/options.c +++ b/net/mptcp/options.c @@ -663,10 +663,8 @@ static bool mptcp_established_options_add_addr(struct sock *sk, { struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); struct mptcp_sock *msk = mptcp_sk(subflow->conn); - unsigned int opt_size = *size; struct mptcp_addr_info addr; bool echo; - int len; /* add addr will strip the existing options, be sure to avoid breaking * MPC/MPJ handshakes @@ -674,21 +672,12 @@ static bool mptcp_established_options_add_addr(struct sock *sk, if (!mptcp_pm_should_add_signal(msk) || (opts->suboptions & (OPTION_MPTCP_MPJ_ACK | OPTION_MPTCP_MPC_ACK)) || !skb || !skb_is_tcp_pure_ack(skb) || - !mptcp_pm_add_addr_signal(msk, opt_size, remaining, &addr, &echo)) + !mptcp_pm_add_addr_signal(msk, size, remaining, &addr, &echo)) return false; - remaining += opt_size; - - len = mptcp_add_addr_len(addr.family, echo, !!addr.port); - if (remaining < len) - return false; - - *size = len; pr_debug("drop other suboptions\n"); - opts->suboptions = 0; - *size -= opt_size; + opts->suboptions = OPTION_MPTCP_ADD_ADDR; opts->addr = addr; - opts->suboptions |= OPTION_MPTCP_ADD_ADDR; if (!echo) { MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDRTX); opts->ahmac = add_addr_generate_hmac(READ_ONCE(msk->local_key), diff --git a/net/mptcp/pm.c b/net/mptcp/pm.c index 4bc380c6f0e1..59dc598d343d 100644 --- a/net/mptcp/pm.c +++ b/net/mptcp/pm.c @@ -887,13 +887,28 @@ void mptcp_pm_mp_fail_received(struct sock *sk, u64 fail_seq) } } -bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int opt_size, - unsigned int remaining, +static int mptcp_add_addr_len(int family, bool echo, bool port) +{ + int len = TCPOLEN_MPTCP_ADD_ADDR_BASE; + + if (family == AF_INET6) + len = TCPOLEN_MPTCP_ADD_ADDR6_BASE; + if (!echo) + len += MPTCPOPT_THMAC_LEN; + /* account for 2 trailing 'nop' options */ + if (port) + len += TCPOLEN_MPTCP_PORT_LEN + TCPOLEN_MPTCP_PORT_ALIGN; + + return len; +} + +bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, int *size, int remaining, struct mptcp_addr_info *addr, bool *echo) { bool skip_add_addr = false; - int ret = false; + bool ret = false; u8 add_addr; + int len = 0; u8 family; bool port; @@ -907,7 +922,7 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int opt_size, * plain dup-ack from TCP perspective. The other MPTCP-relevant info, * if any, will be carried by the 'original' TCP ack */ - remaining += opt_size; + len -= *size; *echo = mptcp_pm_should_add_signal_echo(msk); if (*echo) { @@ -922,7 +937,8 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int opt_size, family = msk->pm.local.family; } - if (remaining < mptcp_add_addr_len(family, *echo, port)) { + len += mptcp_add_addr_len(family, *echo, port); + if (len > remaining) { struct net *net = sock_net((struct sock *)msk); if (*echo) { @@ -935,6 +951,7 @@ bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int opt_size, } ret = true; + *size = len; drop_signal_mark: WRITE_ONCE(msk->pm.addr_signal, add_addr); diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h index 75c5faaf4486..4dfea209ac16 100644 --- a/net/mptcp/protocol.h +++ b/net/mptcp/protocol.h @@ -1206,23 +1206,7 @@ static inline bool mptcp_pm_is_kernel(const struct mptcp_sock *msk) return READ_ONCE(msk->pm.pm_type) == MPTCP_PM_TYPE_KERNEL; } -static inline unsigned int mptcp_add_addr_len(int family, bool echo, bool port) -{ - u8 len = TCPOLEN_MPTCP_ADD_ADDR_BASE; - - if (family == AF_INET6) - len = TCPOLEN_MPTCP_ADD_ADDR6_BASE; - if (!echo) - len += MPTCPOPT_THMAC_LEN; - /* account for 2 trailing 'nop' options */ - if (port) - len += TCPOLEN_MPTCP_PORT_LEN + TCPOLEN_MPTCP_PORT_ALIGN; - - return len; -} - -bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, unsigned int opt_size, - unsigned int remaining, +bool mptcp_pm_add_addr_signal(struct mptcp_sock *msk, int *size, int remaining, struct mptcp_addr_info *addr, bool *echo); bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining, struct mptcp_rm_list *rm_list, int *len);