This patch adds support for binding to a local address in vxlan sockets.
It achieves this by using vxlan_addr union to represent a local address
to bind to, and copying it to udp_port_cfg in vxlan_create_sock.
Signed-off-by: Richard Gobert <richardbgobert@gmail.com>
---
drivers/net/vxlan/vxlan_core.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 16106e088c63..b5f3f946ebcd 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -3479,8 +3479,9 @@ static const struct ethtool_ops vxlan_ethtool_ops = {
.get_link_ksettings = vxlan_get_link_ksettings,
};
-static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
- __be16 port, u32 flags, int ifindex)
+static struct socket *vxlan_create_sock(struct net *net, bool ipv6, __be16 port,
+ u32 flags, int ifindex,
+ union vxlan_addr addr)
{
struct socket *sock;
struct udp_port_cfg udp_conf;
@@ -3493,8 +3494,15 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
udp_conf.use_udp6_rx_checksums =
!(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
udp_conf.ipv6_v6only = 1;
+ memcpy(&udp_conf.local_ip6.s6_addr32,
+ &addr.sin6.sin6_addr.s6_addr32,
+ sizeof(addr.sin6.sin6_addr.s6_addr32));
} else {
udp_conf.family = AF_INET;
+ udp_conf.local_ip.s_addr = addr.sin.sin_addr.s_addr;
+ memcpy(&udp_conf.local_ip.s_addr,
+ &addr.sin.sin_addr.s_addr,
+ sizeof(addr.sin.sin_addr.s_addr));
}
udp_conf.local_udp_port = port;
@@ -3512,7 +3520,8 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
/* Create new listen socket if needed */
static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
__be16 port, u32 flags,
- int ifindex)
+ int ifindex,
+ union vxlan_addr addr)
{
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
struct vxlan_sock *vs;
@@ -3527,7 +3536,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
for (h = 0; h < VNI_HASH_SIZE; ++h)
INIT_HLIST_HEAD(&vs->vni_list[h]);
- sock = vxlan_create_sock(net, ipv6, port, flags, ifindex);
+ sock = vxlan_create_sock(net, ipv6, port, flags, ifindex, addr);
if (IS_ERR(sock)) {
kfree(vs);
return ERR_CAST(sock);
@@ -3591,7 +3600,7 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
if (!vs)
vs = vxlan_socket_create(vxlan->net, ipv6,
vxlan->cfg.dst_port, vxlan->cfg.flags,
- l3mdev_index);
+ l3mdev_index, vxlan->cfg.saddr);
if (IS_ERR(vs))
return PTR_ERR(vs);
#if IS_ENABLED(CONFIG_IPV6)
--
2.36.1
Hi Richard,
kernel test robot noticed the following build errors:
[auto build test ERROR on net-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/Richard-Gobert/net-vxlan-enable-local-address-bind-for-vxlan-sockets/20240223-045600
base: net-next/main
patch link: https://lore.kernel.org/r/a4cd1adb-74d4-4eea-9f74-0d0ac3d79e44%40gmail.com
patch subject: [PATCH net-next 1/2] net: vxlan: enable local address bind for vxlan sockets
config: x86_64-randconfig-122-20240224 (https://download.01.org/0day-ci/archive/20240224/202402241309.eGUSV2aI-lkp@intel.com/config)
compiler: clang version 17.0.6 (https://github.com/llvm/llvm-project 6009708b4367171ccdbf4b5905cb6a803753fe18)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240224/202402241309.eGUSV2aI-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202402241309.eGUSV2aI-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/net/vxlan/vxlan_core.c:3498:20: error: no member named 'local_ip6' in 'struct udp_port_cfg'
3498 | memcpy(&udp_conf.local_ip6.s6_addr32,
| ~~~~~~~~ ^
include/linux/fortify-string.h:639:17: note: expanded from macro 'memcpy'
639 | __struct_size(p), __struct_size(q), \
| ^
include/linux/compiler_types.h:358:56: note: expanded from macro '__struct_size'
358 | #define __struct_size(p) __builtin_dynamic_object_size(p, 0)
| ^
include/linux/fortify-string.h:582:27: note: expanded from macro '__fortify_memcpy_chk'
582 | const size_t __p_size = (p_size); \
| ^~~~~~
>> drivers/net/vxlan/vxlan_core.c:3498:20: error: no member named 'local_ip6' in 'struct udp_port_cfg'
3498 | memcpy(&udp_conf.local_ip6.s6_addr32,
| ~~~~~~~~ ^
include/linux/fortify-string.h:640:17: note: expanded from macro 'memcpy'
640 | __member_size(p), __member_size(q), \
| ^
include/linux/compiler_types.h:359:56: note: expanded from macro '__member_size'
359 | #define __member_size(p) __builtin_dynamic_object_size(p, 1)
| ^
include/linux/fortify-string.h:584:33: note: expanded from macro '__fortify_memcpy_chk'
584 | const size_t __p_size_field = (p_size_field); \
| ^~~~~~~~~~~~
>> drivers/net/vxlan/vxlan_core.c:3498:20: error: no member named 'local_ip6' in 'struct udp_port_cfg'
3498 | memcpy(&udp_conf.local_ip6.s6_addr32,
| ~~~~~~~~ ^
include/linux/fortify-string.h:638:47: note: expanded from macro 'memcpy'
638 | #define memcpy(p, q, s) __fortify_memcpy_chk(p, q, s, \
| ^
include/linux/fortify-string.h:593:20: note: expanded from macro '__fortify_memcpy_chk'
593 | __underlying_##op(p, q, __fortify_size); \
| ^
3 errors generated.
vim +3498 drivers/net/vxlan/vxlan_core.c
3482
3483 static struct socket *vxlan_create_sock(struct net *net, bool ipv6, __be16 port,
3484 u32 flags, int ifindex,
3485 union vxlan_addr addr)
3486 {
3487 struct socket *sock;
3488 struct udp_port_cfg udp_conf;
3489 int err;
3490
3491 memset(&udp_conf, 0, sizeof(udp_conf));
3492
3493 if (ipv6) {
3494 udp_conf.family = AF_INET6;
3495 udp_conf.use_udp6_rx_checksums =
3496 !(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
3497 udp_conf.ipv6_v6only = 1;
> 3498 memcpy(&udp_conf.local_ip6.s6_addr32,
3499 &addr.sin6.sin6_addr.s6_addr32,
3500 sizeof(addr.sin6.sin6_addr.s6_addr32));
3501 } else {
3502 udp_conf.family = AF_INET;
3503 udp_conf.local_ip.s_addr = addr.sin.sin_addr.s_addr;
3504 memcpy(&udp_conf.local_ip.s_addr,
3505 &addr.sin.sin_addr.s_addr,
3506 sizeof(addr.sin.sin_addr.s_addr));
3507 }
3508
3509 udp_conf.local_udp_port = port;
3510 udp_conf.bind_ifindex = ifindex;
3511
3512 /* Open UDP socket */
3513 err = udp_sock_create(net, &udp_conf, &sock);
3514 if (err < 0)
3515 return ERR_PTR(err);
3516
3517 udp_allow_gso(sock->sk);
3518 return sock;
3519 }
3520
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Hi Richard,
kernel test robot noticed the following build errors:
[auto build test ERROR on net-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/Richard-Gobert/net-vxlan-enable-local-address-bind-for-vxlan-sockets/20240223-045600
base: net-next/main
patch link: https://lore.kernel.org/r/a4cd1adb-74d4-4eea-9f74-0d0ac3d79e44%40gmail.com
patch subject: [PATCH net-next 1/2] net: vxlan: enable local address bind for vxlan sockets
config: arc-randconfig-r133-20240223 (https://download.01.org/0day-ci/archive/20240224/202402240119.AR4eT8mt-lkp@intel.com/config)
compiler: arc-elf-gcc (GCC) 13.2.0
reproduce: (https://download.01.org/0day-ci/archive/20240224/202402240119.AR4eT8mt-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202402240119.AR4eT8mt-lkp@intel.com/
All errors (new ones prefixed by >>):
drivers/net/vxlan/vxlan_core.c: In function 'vxlan_create_sock':
>> drivers/net/vxlan/vxlan_core.c:3498:34: error: 'struct udp_port_cfg' has no member named 'local_ip6'; did you mean 'local_ip'?
3498 | memcpy(&udp_conf.local_ip6.s6_addr32,
| ^~~~~~~~~
| local_ip
vim +3498 drivers/net/vxlan/vxlan_core.c
3482
3483 static struct socket *vxlan_create_sock(struct net *net, bool ipv6, __be16 port,
3484 u32 flags, int ifindex,
3485 union vxlan_addr addr)
3486 {
3487 struct socket *sock;
3488 struct udp_port_cfg udp_conf;
3489 int err;
3490
3491 memset(&udp_conf, 0, sizeof(udp_conf));
3492
3493 if (ipv6) {
3494 udp_conf.family = AF_INET6;
3495 udp_conf.use_udp6_rx_checksums =
3496 !(flags & VXLAN_F_UDP_ZERO_CSUM6_RX);
3497 udp_conf.ipv6_v6only = 1;
> 3498 memcpy(&udp_conf.local_ip6.s6_addr32,
3499 &addr.sin6.sin6_addr.s6_addr32,
3500 sizeof(addr.sin6.sin6_addr.s6_addr32));
3501 } else {
3502 udp_conf.family = AF_INET;
3503 udp_conf.local_ip.s_addr = addr.sin.sin_addr.s_addr;
3504 memcpy(&udp_conf.local_ip.s_addr,
3505 &addr.sin.sin_addr.s_addr,
3506 sizeof(addr.sin.sin_addr.s_addr));
3507 }
3508
3509 udp_conf.local_udp_port = port;
3510 udp_conf.bind_ifindex = ifindex;
3511
3512 /* Open UDP socket */
3513 err = udp_sock_create(net, &udp_conf, &sock);
3514 if (err < 0)
3515 return ERR_PTR(err);
3516
3517 udp_allow_gso(sock->sk);
3518 return sock;
3519 }
3520
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
© 2016 - 2026 Red Hat, Inc.