Message ID | 20210811131523.6339-5-fw@strlen.de (mailing list archive) |
---|---|
State | Superseded, archived |
Delegated to: | Paolo Abeni |
Headers | show |
Series | mptcp: add SOL_MPTCP getsockopt support | expand |
Hi Florian, I love your patch! Yet something to improve: [auto build test ERROR on kselftest/next] [also build test ERROR on mptcp/export linus/master v5.14-rc5 next-20210811] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Florian-Westphal/mptcp-add-SOL_MPTCP-getsockopt-support/20210811-212510 base: https://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git next config: i386-randconfig-a004-20210811 (attached as .config) compiler: gcc-9 (Debian 9.3.0-22) 9.3.0 reproduce (this is a W=1 build): # https://github.com/0day-ci/linux/commit/bd7031682bfb2cfd717fde49bd7f943c09f7a9a5 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Florian-Westphal/mptcp-add-SOL_MPTCP-getsockopt-support/20210811-212510 git checkout bd7031682bfb2cfd717fde49bd7f943c09f7a9a5 # save the attached .config to linux build tree mkdir build_dir make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): In file included from <command-line>:32: >> ./usr/include/linux/mptcp.h:205:3: error: unknown type name 'sa_family_t' 205 | sa_family_t sa_family; | ^~~~~~~~~~~ >> ./usr/include/linux/mptcp.h:206:19: error: field 'sa_local' has incomplete type 206 | struct sockaddr sa_local; | ^~~~~~~~ >> ./usr/include/linux/mptcp.h:208:23: error: field 'sin6_local' has incomplete type 208 | struct sockaddr_in6 sin6_local; | ^~~~~~~~~~ >> ./usr/include/linux/mptcp.h:209:27: error: field 'ss_local' has incomplete type 209 | struct sockaddr_storage ss_local; | ^~~~~~~~ >> ./usr/include/linux/mptcp.h:212:19: error: field 'sa_remote' has incomplete type 212 | struct sockaddr sa_remote; | ^~~~~~~~~ >> ./usr/include/linux/mptcp.h:214:23: error: field 'sin6_remote' has incomplete type 214 | struct sockaddr_in6 sin6_remote; | ^~~~~~~~~~~ >> ./usr/include/linux/mptcp.h:215:27: error: field 'ss_remote' has incomplete type 215 | struct sockaddr_storage ss_remote; | ^~~~~~~~~ --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Hi Florian, I love your patch! Yet something to improve: [auto build test ERROR on kselftest/next] [also build test ERROR on mptcp/export linus/master v5.14-rc5 next-20210811] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Florian-Westphal/mptcp-add-SOL_MPTCP-getsockopt-support/20210811-212510 base: https://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git next config: x86_64-randconfig-a004-20210811 (attached as .config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project d39ebdae674c8efc84ebe8dc32716ec353220530) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/bd7031682bfb2cfd717fde49bd7f943c09f7a9a5 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Florian-Westphal/mptcp-add-SOL_MPTCP-getsockopt-support/20210811-212510 git checkout bd7031682bfb2cfd717fde49bd7f943c09f7a9a5 # save the attached .config to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross O=build_dir ARCH=x86_64 SHELL=/bin/bash If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): In file included from <built-in>:1: >> ./usr/include/linux/mptcp.h:205:3: error: unknown type name 'sa_family_t' sa_family_t sa_family; ^ >> ./usr/include/linux/mptcp.h:206:19: error: field has incomplete type 'struct sockaddr' struct sockaddr sa_local; ^ ./usr/include/linux/mptcp.h:206:10: note: forward declaration of 'struct sockaddr' struct sockaddr sa_local; ^ >> ./usr/include/linux/mptcp.h:208:23: error: field has incomplete type 'struct sockaddr_in6' struct sockaddr_in6 sin6_local; ^ ./usr/include/linux/mptcp.h:208:10: note: forward declaration of 'struct sockaddr_in6' struct sockaddr_in6 sin6_local; ^ >> ./usr/include/linux/mptcp.h:209:27: error: field has incomplete type 'struct sockaddr_storage' struct sockaddr_storage ss_local; ^ ./usr/include/linux/mptcp.h:209:10: note: forward declaration of 'struct sockaddr_storage' struct sockaddr_storage ss_local; ^ ./usr/include/linux/mptcp.h:212:19: error: field has incomplete type 'struct sockaddr' struct sockaddr sa_remote; ^ ./usr/include/linux/mptcp.h:206:10: note: forward declaration of 'struct sockaddr' struct sockaddr sa_local; ^ ./usr/include/linux/mptcp.h:214:23: error: field has incomplete type 'struct sockaddr_in6' struct sockaddr_in6 sin6_remote; ^ ./usr/include/linux/mptcp.h:208:10: note: forward declaration of 'struct sockaddr_in6' struct sockaddr_in6 sin6_local; ^ ./usr/include/linux/mptcp.h:215:27: error: field has incomplete type 'struct sockaddr_storage' struct sockaddr_storage ss_remote; ^ ./usr/include/linux/mptcp.h:209:10: note: forward declaration of 'struct sockaddr_storage' struct sockaddr_storage ss_local; ^ 7 errors generated. --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/include/uapi/linux/mptcp.h b/include/uapi/linux/mptcp.h index 7c368fccd83e..f6cfd2c4ca5b 100644 --- a/include/uapi/linux/mptcp.h +++ b/include/uapi/linux/mptcp.h @@ -201,8 +201,25 @@ struct mptcp_subflow_data { __u32 size_user; /* size of one element in data[] */ } __attribute__((aligned(8))); +struct mptcp_subflow_addrs { + union { + sa_family_t sa_family; + struct sockaddr sa_local; + struct sockaddr_in sin_local; + struct sockaddr_in6 sin6_local; + struct sockaddr_storage ss_local; + }; + union { + struct sockaddr sa_remote; + struct sockaddr_in sin_remote; + struct sockaddr_in6 sin6_remote; + struct sockaddr_storage ss_remote; + }; +}; + /* MPTCP socket options */ #define MPTCP_INFO 1 #define MPTCP_TCPINFO 2 +#define MPTCP_SUBFLOW_ADDRS 3 #endif /* _UAPI_MPTCP_H */ diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c index ac8e6823db4f..a30bc848ffcb 100644 --- a/net/mptcp/sockopt.c +++ b/net/mptcp/sockopt.c @@ -817,6 +817,100 @@ static int mptcp_getsockopt_tcpinfo(struct mptcp_sock *msk, char __user *optval, return 0; } +static void mptcp_get_sub_addrs(const struct sock *sk, struct mptcp_subflow_addrs *a) +{ + struct inet_sock *inet = inet_sk(sk); + + memset(a, 0, sizeof(*a)); + + if (sk->sk_family == AF_INET) { + a->sin_local.sin_family = AF_INET; + a->sin_local.sin_port = inet->inet_sport; + a->sin_local.sin_addr.s_addr = inet->inet_rcv_saddr; + + if (!a->sin_local.sin_addr.s_addr) + a->sin_local.sin_addr.s_addr = inet->inet_saddr; + + a->sin_remote.sin_family = AF_INET; + a->sin_remote.sin_port = inet->inet_dport; + a->sin_remote.sin_addr.s_addr = inet->inet_daddr; +#if IS_ENABLED(CONFIG_IPV6) + } else if (sk->sk_family == AF_INET6) { + const struct ipv6_pinfo *np = inet6_sk(sk); + + a->sin6_local.sin6_family = AF_INET6; + a->sin6_local.sin6_port = inet->inet_sport; + + if (ipv6_addr_any(&sk->sk_v6_rcv_saddr)) + a->sin6_local.sin6_addr = np->saddr; + else + a->sin6_local.sin6_addr = sk->sk_v6_rcv_saddr; + + a->sin6_remote.sin6_family = AF_INET6; + a->sin6_remote.sin6_port = inet->inet_dport; + a->sin6_remote.sin6_addr = sk->sk_v6_daddr; +#endif + } +} + +static int mptcp_getsockopt_subflow_addrs(struct mptcp_sock *msk, char __user *optval, + int __user *_u_optlen) +{ + struct mptcp_subflow_context *subflow; + struct sock *sk = &msk->sk.icsk_inet.sk; + unsigned int sfcount = 0, copied = 0; + struct mptcp_subflow_data sfd; + char __user *addrptr; + int len; + + len = mptcp_get_subflow_data(&sfd, optval, _u_optlen); + if (len < 0) + return len; + + sfd.size_kernel = sizeof(struct mptcp_subflow_addrs); + sfd.size_user = min_t(unsigned int, sfd.size_user, + sizeof(struct mptcp_subflow_addrs)); + + addrptr = optval + sfd.size_subflow_data; + + lock_sock(sk); + + mptcp_for_each_subflow(msk, subflow) { + struct sock *ssk = mptcp_subflow_tcp_sock(subflow); + + ++sfcount; + + if (len >= sfd.size_user) { + struct mptcp_subflow_addrs a; + + mptcp_get_sub_addrs(ssk, &a); + + if (copy_to_user(addrptr, &a, sfd.size_user)) { + release_sock(sk); + return -EFAULT; + } + + addrptr += sfd.size_user; + copied += sfd.size_user; + len -= sfd.size_user; + } + } + + release_sock(sk); + + copied += sfd.size_subflow_data; + + if (put_user(copied, _u_optlen)) + return -EFAULT; + + sfd.num_subflows = sfcount; + + if (copy_to_user(optval, &sfd, sfd.size_subflow_data)) + return -EFAULT; + + return 0; +} + static int mptcp_getsockopt_sol_tcp(struct mptcp_sock *msk, int optname, char __user *optval, int __user *optlen) { @@ -839,6 +933,8 @@ static int mptcp_getsockopt_sol_mptcp(struct mptcp_sock *msk, int optname, return mptcp_getsockopt_info(msk, optval, optlen); case MPTCP_TCPINFO: return mptcp_getsockopt_tcpinfo(msk, optval, optlen); + case MPTCP_SUBFLOW_ADDRS: + return mptcp_getsockopt_subflow_addrs(msk, optval, optlen); } return -EOPNOTSUPP;
This retrieves the address pairs of all subflows currently active for a given mptcp connection. It re-uses the same meta-header as for MPTCP_TCPINFO. A new structure is provided to hold the subflow address data: struct mptcp_subflow_addrs { union { sa_family_t sa_family; struct sockaddr sa_local; struct sockaddr_in sin_local; struct sockaddr_in6 sin6_local; struct sockaddr_storage ss_local; }; union { struct sockaddr sa_remote; struct sockaddr_in sin_remote; struct sockaddr_in6 sin6_remote; struct sockaddr_storage ss_remote; }; }; Usage of the new getsockopt is very similar to MPTCP_TCPINFO one. Userspace allocates a 'struct mptcp_subflow_data', followed by one or more 'struct mptcp_subflow_addrs', then inits the mptcp_subflow_data structure as follows: struct mptcp_subflow_addrs *sf_addr; struct mptcp_subflow_data *addr; socklen_t olen = sizeof(*addr) + (8 * sizeof(*sf_addr)); addr = malloc(olen); addr->size_subflow_data = sizeof(*addr); addr->num_subflows = 0; addr->size_kernel = 0; addr->size_user = sizeof(struct mptcp_subflow_addrs); sf_addr = (struct mptcp_subflow_addrs *)(addr + 1); and then retrieves the endpoint addresses via: ret = getsockopt(fd, SOL_MPTCP, MPTCP_SUBFLOW_ADDRS, addr, &olen); If the call succeeds, kernel will have added up to 8 endpoint addresses after the 'mptcp_subflow_data' header. Userspace needs to re-check 'olen' value to detect how many bytes have been filled in by the kernel. Userspace can check addr->num_subflows to discover when there were more subflows that available data space. Signed-off-by: Florian Westphal <fw@strlen.de> --- include/uapi/linux/mptcp.h | 17 +++++++ net/mptcp/sockopt.c | 96 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+)