From nobody Mon Oct 6 19:04:10 2025 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2D5DF29B792; Thu, 17 Jul 2025 11:54:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752753285; cv=none; b=LonsxT6/i0owKWah+tmMfYXuJoClwmwUO2wkO2AQfZY4vUSA6l0SQ+8QmftRlPW1O9DcHQmGNxx/JQOGdXna6H4RqubeRFW8/wbr/RvGqCLrVz+P4y1cMPjOd03n9GtFk7vpTveHW2DNfQf46TcrE0pQ3aT5vTxwZPGZSCdz4Go= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752753285; c=relaxed/simple; bh=+KnzwoKbA1GtBdrTr//kfdTYJsbn0oZ8P1T5y+ypoxk=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=B1k1rW5W6v8QN8owrmEnuRaCcL/N1/3aNV1Lmvw/wfgSktSSHU4N2uivbLv12YGPXm2PI1SxxnUHC6OkD8OzMwjt76uP/P115ZeJ+Z7ThZ5VTUT6TxdSvHHglJgzCayAkyM0IbmfqTafRmVzMuiTSKZKLH2vjJ0rXGVzI64kZ8g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=g+0nAcmy; arc=none smtp.client-ip=209.85.128.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="g+0nAcmy" Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-4555f89b236so7937675e9.1; Thu, 17 Jul 2025 04:54:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1752753280; x=1753358080; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=gJmbqKfhPmGmgPRu3RIwXN3mEJ4fXgB708Rx4HkKDQU=; b=g+0nAcmySIGbOtGC6kNQZpjGfFADTXayie60AHaRpCGckTZU5IYoqfv3+Upx3xBtnX tWhYDor0v807lCwJHG/12qpR1t2YN6vjym5BLPdkmaLnbCiVDilhU3YTpLbrZ7UFExkj HYpdAdddgx3ccv/+m3XE3c1D21Ix7tuKGXKH9EQjWMZNunCfw0+lp1xVwW493QscYgrK OLfoSqfiNB8jB7p83NqKhATeJdjm43ex/l2JZbLJuRi8ZH5vAuP7XQTRMkBhm8kkXtV2 MKMbEZ+g/Q44jQ5KQlGMXSNUyytfNNyYNOPH4cE984EH2QUMX9x7oC5546/oOFvIl6Hx 9aQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752753280; x=1753358080; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gJmbqKfhPmGmgPRu3RIwXN3mEJ4fXgB708Rx4HkKDQU=; b=UkN5AvTsMD6CoftuG7g0ioVfHb8uHma0DQwsXYeHwQquddV1JW4SX5Ox5HusUhHG1D QzM4VX17TeszHK+PUfN/udaE51KB3NKTlPFF5tUu624wBCh14lUhpnZLmvcx2DC4sLHD IygXwL8I6s3byWD8tqwgKvrGzX1mAW+fY7k36uDotAD3fd01mAJZIFEHNm3MWOrfkmtS 8zAPtMLoZal4kyWQ3xgjsDoYY0uRZoYb3VZWkD2P+QqEBUWvx5UEfTKBRfK8Gnt0cr+6 qTc33aRU7EASWju/Cb9q/PIa5vv28bFPRGql1tkC3Tk3M9l0OqD9qK+A9bjSBdmudaN3 yjFw== X-Forwarded-Encrypted: i=1; AJvYcCWl60ZAsUa+S3aBnP8ZVy/aX/zgwnsaKgHvTLKVl5zh1Rna6uUHn9rYVL/i3b20JawOUbro8PBa@vger.kernel.org, AJvYcCXkZHptDO1qYyEpfVH66N4l7jboGXyqUiy911xzdIkBv/R4hFe5K3FIq+IAiVpnqPXhVfIxzHrM+xN4EMs=@vger.kernel.org X-Gm-Message-State: AOJu0Yx8KZzA6EZOKsQMFS8QqdnX/+IJMYncZMBfXiCoiK85sz+EUC6k /cVIyD8rHMGa8kaIIGjmXlzGvap/qpIcs502lIYDq3pogMQCh3sYiv0q X-Gm-Gg: ASbGncvojh6C+b8mXaHjv/1o66ILk+mzBj+Eiw32M+vKDa09gXZObZ1Ssx9reXEzeQj 5/x5HQOeEEBnPkJL25ENURoAawRJfnIv1mc06YDuF/amlpVyHoBqjs4YZyk8Ugeljp3veNlJTTH p8CY07pZUHkCP9Gy7zygYStB4L5qqbPfS4Wkr81tmNFEBg1qhdDjaTo4EfU31rIpSv9YNKXfM5H WsmjTU8yBCp8fbUcnPx6J9XuWAbNA+ju41+lc+v9Szm1bgSokK++l7UxNZ6bEydd3WmoP78+H+N iHDNiND0whtAl/n+a4AEtwZq3/yepnRhcugh2l41cLsjetHyB8WMw8SsqXauNmwh X-Google-Smtp-Source: AGHT+IGWrPQzGiDdX0wG60SM5rZE5oC7xzLcgSv0XPdx+0D3l5a9RscQO3V10lmbQ1ehLAI+6EcAfA== X-Received: by 2002:a05:600c:45d1:b0:456:1204:e7ec with SMTP id 5b1f17b1804b1-4562e372643mr78763665e9.10.1752753280096; Thu, 17 Jul 2025 04:54:40 -0700 (PDT) Received: from localhost ([45.84.137.104]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3b5e8e0d727sm20720317f8f.51.2025.07.17.04.54.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Jul 2025 04:54:39 -0700 (PDT) From: Richard Gobert To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, dsahern@kernel.org, razor@blackwall.org, idosch@nvidia.com, petrm@nvidia.com, menglong8.dong@gmail.com, richardbgobert@gmail.com, daniel@iogearbox.net, martin.lau@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v4 1/4] net: udp: add freebind option to udp_sock_create Date: Thu, 17 Jul 2025 13:54:09 +0200 Message-Id: <20250717115412.11424-2-richardbgobert@gmail.com> In-Reply-To: <20250717115412.11424-1-richardbgobert@gmail.com> References: <20250717115412.11424-1-richardbgobert@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" udp_sock_create creates a UDP socket and binds it according to udp_port_cfg. Add a freebind option to udp_port_cfg that allows a socket to be bound as though IP_FREEBIND is set. This change is required for binding vxlan sockets to their local address when the outgoing interface is down. Signed-off-by: Richard Gobert --- include/net/udp_tunnel.h | 3 ++- net/ipv4/udp_tunnel_core.c | 1 + net/ipv6/ip6_udp_tunnel.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h index 9acef2fbd2fd..6c1362aa3576 100644 --- a/include/net/udp_tunnel.h +++ b/include/net/udp_tunnel.h @@ -34,7 +34,8 @@ struct udp_port_cfg { unsigned int use_udp_checksums:1, use_udp6_tx_checksums:1, use_udp6_rx_checksums:1, - ipv6_v6only:1; + ipv6_v6only:1, + freebind:1; }; =20 int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg, diff --git a/net/ipv4/udp_tunnel_core.c b/net/ipv4/udp_tunnel_core.c index fce945f23069..147fd8ff4f49 100644 --- a/net/ipv4/udp_tunnel_core.c +++ b/net/ipv4/udp_tunnel_core.c @@ -28,6 +28,7 @@ int udp_sock_create4(struct net *net, struct udp_port_cfg= *cfg, udp_addr.sin_family =3D AF_INET; udp_addr.sin_addr =3D cfg->local_ip; udp_addr.sin_port =3D cfg->local_udp_port; + inet_assign_bit(FREEBIND, sock->sk, cfg->freebind); err =3D kernel_bind(sock, (struct sockaddr *)&udp_addr, sizeof(udp_addr)); if (err < 0) diff --git a/net/ipv6/ip6_udp_tunnel.c b/net/ipv6/ip6_udp_tunnel.c index 0ff547a4bff7..65ff44c274b8 100644 --- a/net/ipv6/ip6_udp_tunnel.c +++ b/net/ipv6/ip6_udp_tunnel.c @@ -40,6 +40,7 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg= *cfg, memcpy(&udp6_addr.sin6_addr, &cfg->local_ip6, sizeof(udp6_addr.sin6_addr)); udp6_addr.sin6_port =3D cfg->local_udp_port; + inet_assign_bit(FREEBIND, sock->sk, cfg->freebind); err =3D kernel_bind(sock, (struct sockaddr *)&udp6_addr, sizeof(udp6_addr)); if (err < 0) --=20 2.36.1 From nobody Mon Oct 6 19:04:10 2025 Received: from mail-wr1-f45.google.com (mail-wr1-f45.google.com [209.85.221.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A5EC29B8C6; Thu, 17 Jul 2025 11:54:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752753293; cv=none; b=NnpppR14oU+CxhuW8zzbk7mCsu9sVIbUhdfu2RqSl6vjwEEDzyhGde0m918p14/o+KcIreRgF4LM46AzEBTckPoU0P+f8WB/C/1QRYAArCS8MaEqYl0r+1r2VFMu04oiUG/4vGLCWRdSwQ3ZO2CKFTHjatBnHho8SA09S4AVi+g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752753293; c=relaxed/simple; bh=ZFTE9/tnzFVqQ/jpUyc9fn2dWpNVca7VzfF8id7e4ME=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=bonXBga2XwjysFa3QSyTsW6Szp6+osfwk3l1gPd5LZqt0knx4fj/5exYLa8XZ8c/33+pMUJOQtkkJhHafOoeItEmvqZAbbAmDQ6kCHs7gNzjJvWDyg7smq/3QwdXB0DRqHLNctay6iY92mO4myMcd5i9b39kGwhLH5ukn1c7o0c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=d0Z2LcwG; arc=none smtp.client-ip=209.85.221.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="d0Z2LcwG" Received: by mail-wr1-f45.google.com with SMTP id ffacd0b85a97d-3ab112dea41so487859f8f.1; Thu, 17 Jul 2025 04:54:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1752753289; x=1753358089; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=O8Mfc0zC4ruO3OtFu2emQU/6si00PFdROnoPrUh9e2g=; b=d0Z2LcwGU9c+7mRocx54WRqCjqEiAZ+rLZ3jx9otzRz4TXfUQz8tDQDghwuldRobcg G+djiqVvCkXR2dGg38SfKhXkWPNFHhRUZgc6RfPkfxOmxsX3Z+XGuv+At5m7tKrXyp3p vSxJnUeUBaAfhOFqj+CNq119Kcj+NMZRRFTlu2IUPMJwKkCYn8yo0GXYkCMjP8YFfKW5 vkK8D6vMNDG5kTpE8Z4OqlFakzYt+9o1Kp3F88xe4z2dDFbtIjn0n5OjB1KVZ9pPEXWc tOUcn5zOeAvULNDCRFqf291PAfWsPgQXA9X0rMlNc7XrG3KdkVkc16xt1Xv/RgE8jtpG STvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752753289; x=1753358089; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=O8Mfc0zC4ruO3OtFu2emQU/6si00PFdROnoPrUh9e2g=; b=ntdFewFYjyYhuZQ2BOR1Ra4MS9MnlAN2pcWDH5h9DN7GxIZsC02KPeGV8O0v++k3BD dPA/bWoeScGhAJn/y5xujy3zqfbqrNd9r8teM1SlA8QQzt8Jv1wg1e3zinlmuZNPSoph zOwFGESUoQAeVFfsWQNs+xgP6hXjyqMRj9ZkSvCZIBSL5XZ3CD/xPt6Bwbs6XAI7nu0u tpLrw/lllqQI5BxoqfvOso4qFqzQ16c09d1uZa6uh8OCJKkXCGUCmZ36gwo+DajfgSs/ 8avGkcrHG7TDVfsEpnAE+rf9WCmCwmfM82HmrqN1mdXed8bJn74RqFsVc/DbO6lYvjbG /6qA== X-Forwarded-Encrypted: i=1; AJvYcCUV0asUc22C6HNWLxweWTtjRO3WNpP+BEdXyXELs5CFtolUPRYzfD73r/YhrqbK2rsvKWmBR3XLRB0LPYs=@vger.kernel.org, AJvYcCVwQXAmq7EQqG+rcLzMP5qkm4etGa6Wj4dPhWw86SKlaAsoY/FbPJNnVHbq0bhsQaHxywqec4CU@vger.kernel.org X-Gm-Message-State: AOJu0YzPx61UPR0x1uUnFJxQ53fn6+UWttxC9JUYZHgB33pVWWlAHd8f YXQ3cYRzehZymKgyL04gFloToTKIdxzKd8j5xqZPhqqtw2s22LxDyhia X-Gm-Gg: ASbGnctbXdxH+6jizfVRQX5TDmnygzRkh9N90FVFp+qUENyAXA9/1HOFJRGK9+F7ifd kW0brklCWX8pjCbnkgNlpZwoXXSWxS/pOyVMOM4iJDttyNoUjS8h7E85EXDa3q8OMeieoiqAMG1 Z/0ARGNNbxFMr6WJ3IFj5xStotFuBqdEBI/yqqUyTCLa83W45cATXX53125EbhD24CTqrDIMi0S JpeGeAJltTKO6BYLLrxkIZU+UNiW5ATMlBpGlowd6AXyTwyoOfhq7WHUbxGCozMGX+xn8UIFNIH 5O8ZFSlFdKPugZT+0LbDtkJXYzSicSpYLaGjLHXhQtcA9CkbvZ/P5I+CarI6SiLE+3QyYo7O05Q = X-Google-Smtp-Source: AGHT+IFlF7Ulk737hZOgnk1vPg2m+0Ci7dbyi5Qm7lCWMR24A4HwlV4HDqyguvUQ3ePsFuK2AbCmAQ== X-Received: by 2002:a05:6000:4606:b0:3a5:3af1:e21b with SMTP id ffacd0b85a97d-3b60dd9988amr4870756f8f.47.1752753289242; Thu, 17 Jul 2025 04:54:49 -0700 (PDT) Received: from localhost ([45.84.137.104]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3b5e8dc2131sm20196347f8f.29.2025.07.17.04.54.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Jul 2025 04:54:48 -0700 (PDT) From: Richard Gobert To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, dsahern@kernel.org, razor@blackwall.org, idosch@nvidia.com, petrm@nvidia.com, menglong8.dong@gmail.com, richardbgobert@gmail.com, daniel@iogearbox.net, martin.lau@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v4 2/4] net: vxlan: add netlink option to bind vxlan sockets to local addresses Date: Thu, 17 Jul 2025 13:54:10 +0200 Message-Id: <20250717115412.11424-3-richardbgobert@gmail.com> In-Reply-To: <20250717115412.11424-1-richardbgobert@gmail.com> References: <20250717115412.11424-1-richardbgobert@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Currently, VXLAN sockets always bind to 0.0.0.0, even when a local address is defined. This commit changes this behavior. If two VXLAN endpoints are connected through two separate subnets, they are each able to receive traffic through both subnets, regardless of the local address. This commit breaks this behavior. Add a netlink option to configure the new behavior. Since the scenario described above is unrealistic, default to binding the socket to the local address. It is highly unlikely this change will break any networks. Signed-off-by: Richard Gobert --- drivers/net/vxlan/vxlan_core.c | 23 ++++++++++++++++++++++- include/net/vxlan.h | 1 + include/uapi/linux/if_link.h | 1 + tools/include/uapi/linux/if_link.h | 1 + 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index bcde95cb2a2e..667ff17c4569 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -3406,6 +3406,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLA= N_MAX + 1] =3D { [IFLA_VXLAN_LABEL_POLICY] =3D NLA_POLICY_MAX(NLA_U32, VXLAN_LABEL_M= AX), [IFLA_VXLAN_RESERVED_BITS] =3D NLA_POLICY_EXACT_LEN(sizeof(struct vxlanhd= r)), [IFLA_VXLAN_MC_ROUTE] =3D NLA_POLICY_MAX(NLA_U8, 1), + [IFLA_VXLAN_LOCALBIND] =3D { .type =3D NLA_U8 }, }; =20 static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[], @@ -4071,6 +4072,9 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct = nlattr *data[], if (changelink && (conf->saddr.sa.sa_family !=3D AF_INET)) { NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL], "New local address fa= mily does not match old"); return -EOPNOTSUPP; + } else if (changelink && (conf->flags & VXLAN_F_LOCALBIND)) { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL], "Cannot change local = address when bound locally"); + return -EOPNOTSUPP; } =20 conf->saddr.sin.sin_addr.s_addr =3D nla_get_in_addr(data[IFLA_VXLAN_LOCA= L]); @@ -4084,6 +4088,9 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct = nlattr *data[], if (changelink && (conf->saddr.sa.sa_family !=3D AF_INET6)) { NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL6], "New local address f= amily does not match old"); return -EOPNOTSUPP; + } else if (changelink && (conf->flags & VXLAN_F_LOCALBIND)) { + NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_LOCAL6], "Cannot change local= address when bound locally"); + return -EOPNOTSUPP; } =20 /* TODO: respect scope id */ @@ -4354,6 +4361,17 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct= nlattr *data[], } } =20 + if (data[IFLA_VXLAN_LOCALBIND]) { + err =3D vxlan_nl2flag(conf, data, IFLA_VXLAN_LOCALBIND, + VXLAN_F_LOCALBIND, changelink, + false, extack); + if (err) + return err; + } else { + /* default to bind to the local address on a new device */ + conf->flags |=3D VXLAN_F_LOCALBIND; + } + return 0; } =20 @@ -4517,6 +4535,7 @@ static size_t vxlan_get_size(const struct net_device = *dev) nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_VNIFILTER */ /* IFLA_VXLAN_RESERVED_BITS */ nla_total_size(sizeof(struct vxlanhdr)) + + nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LOCALBIND */ 0; } =20 @@ -4596,7 +4615,9 @@ static int vxlan_fill_info(struct sk_buff *skb, const= struct net_device *dev) nla_put_u8(skb, IFLA_VXLAN_REMCSUM_RX, !!(vxlan->cfg.flags & VXLAN_F_REMCSUM_RX)) || nla_put_u8(skb, IFLA_VXLAN_LOCALBYPASS, - !!(vxlan->cfg.flags & VXLAN_F_LOCALBYPASS))) + !!(vxlan->cfg.flags & VXLAN_F_LOCALBYPASS)) || + nla_put_u8(skb, IFLA_VXLAN_LOCALBIND, + !!(vxlan->cfg.flags & VXLAN_F_LOCALBIND))) goto nla_put_failure; =20 if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports)) diff --git a/include/net/vxlan.h b/include/net/vxlan.h index 0ee50785f4f1..e356b5294535 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -333,6 +333,7 @@ struct vxlan_dev { #define VXLAN_F_MDB 0x40000 #define VXLAN_F_LOCALBYPASS 0x80000 #define VXLAN_F_MC_ROUTE 0x100000 +#define VXLAN_F_LOCALBIND 0x200000 =20 /* Flags that are used in the receive path. These flags must match in * order for a socket to be shareable diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 784ace3a519c..7350129b1444 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -1399,6 +1399,7 @@ enum { IFLA_VXLAN_LABEL_POLICY, /* IPv6 flow label policy; ifla_vxlan_label_poli= cy */ IFLA_VXLAN_RESERVED_BITS, IFLA_VXLAN_MC_ROUTE, + IFLA_VXLAN_LOCALBIND, __IFLA_VXLAN_MAX }; #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/= if_link.h index 7e46ca4cd31b..eee934cc2cf4 100644 --- a/tools/include/uapi/linux/if_link.h +++ b/tools/include/uapi/linux/if_link.h @@ -1396,6 +1396,7 @@ enum { IFLA_VXLAN_VNIFILTER, /* only applicable with COLLECT_METADATA mode */ IFLA_VXLAN_LOCALBYPASS, IFLA_VXLAN_LABEL_POLICY, /* IPv6 flow label policy; ifla_vxlan_label_poli= cy */ + IFLA_VXLAN_LOCALBIND, __IFLA_VXLAN_MAX }; #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) --=20 2.36.1 From nobody Mon Oct 6 19:04:10 2025 Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C0F6229B8D2; Thu, 17 Jul 2025 11:55:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752753304; cv=none; b=jEfcG1cebWEBXEKvaoTaWhwWbAsY271t74Lso3R0ISUHV7JXYM/9JeCZQ2vD8V4sSxyXmk/q0dx1ohCnwNdwNjhssMNlxChqyWxMsl1UOpNEuAiSdBknrF6Da1Bt+KegyJc8FRHHMyz6WGaja9csYs9JuD8+PwZ5bqQeBQ3DXoo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752753304; c=relaxed/simple; bh=ck2YVulw2iEuywaFnIjCn2hm4WJu8P7vguDe3iMiTS4=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dbzO4einziPJBhqZO/vaF17u9B40GRcO/N4BfXX20xKeSDx+9P3HzbJ51pMb6KRRJR7Ba8tkQL1y3c6AlpF2yt+KqJS88eSOrf3X5CAy0FKpt72OLkhEq+ukD4kYEghFAnnAeSHGTf18CtB2wXuGZ3Dm5MwrLslFhfanuxlHKCk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=m4QKO+0W; arc=none smtp.client-ip=209.85.214.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="m4QKO+0W" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-234c5b57557so7139895ad.3; Thu, 17 Jul 2025 04:55:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1752753302; x=1753358102; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=sKKOfH1gpvJ1IeaYm9TchsbmE2xV2KT6bJpFjZntGC4=; b=m4QKO+0WwX8Hl1pSVsgdLhwM+9VYD6kq9r1KOqqtqvDS08DefRhAQTXeNKXWJmAIcj GO4HnqX3z8TIpjlsR564mhKBSMiDjO7M2YGIZ2P45OrWmpgE5LnBBzpxBkmfVbT9zekq cDI0rrfNUMW6nAr2hSB8emg8PqiHVYiN8Xf2wlfc77wg9VcrpSwgiv10tmsl1lRMiRr/ j+J4EX7SeccYoGXdQBHyvSOv/xlCaBhv1C8934xg98692OtvBBR17XICaERnpAUIWEBc Hd0LWgfVDbog+sulpEDVi6j9BbppNbns12T81UwioLlsM2kxTQg+Kuniia/ubZXaXP0S agIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752753302; x=1753358102; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=sKKOfH1gpvJ1IeaYm9TchsbmE2xV2KT6bJpFjZntGC4=; b=XLG+u/+7KGGypg13WcQ96w5P7OX1ggdN4EP2uZbHYix9NbeMXQydB5w1nbWe4iqaXa 0qj7vzWMXmAozaXffBPh0saJCLToAeMKyDwzmWwoSUfktd3yJxBXOD3cjZ4YTM8JSUnU QAO6jxuPXq9bwLhvhHM+tWeyrVcXaHP/bUFZ076FFXS/e+4FfB023Ec0ioQeMfr6itPX 9T0qhTepUTylYqKSYD53h8RvcJJhKrK4Fa2MDRYgHatHSVwoveKfpEKguS/n1PhZb0Nx 9ktbwUk5fVV+Ac+DLoCp+v3O4+M1k00Y3skaoekpwJ0/LwiAwpFcAkxY7OOXNZlwi2pO UkfA== X-Forwarded-Encrypted: i=1; AJvYcCVQlJE5UpjjCQpiiD2R8v8Fzu3aIzp1wACqHSUMrWqjVYsPRVp6IIcZIapfW8bH2ajawQfPdi/5npmLUHU=@vger.kernel.org, AJvYcCXzCGzpxkk8CxgNyZSDvrPFOnfujvrpNIpMbAqNbDl8FmSNNS1igzQHoiX+l4ZZ09S0Azi/INtV@vger.kernel.org X-Gm-Message-State: AOJu0YzeXbjoA0xrSAkTcukbm548I6QxkCx8v1cTfXjjPi2eeSAyjDgd hNvhbvSpc3rtF9WPmpC0ruWDMBUJYviVmSS3hwax3MIBtUKPkRyJb4sz X-Gm-Gg: ASbGncsfDjlAhu9vlqQAzcKdxkeHj4gKGDUVnZJRk5mXDzn9nj6CBEpFRaKAShWNlDR ZtXOxGoapBx3L3UWm7EENVgyOLAwDGr9YpqAB+d0o5lkdXjtOE7p1xpydPAGIUCjXrM3FiWspua 9gxAL5tqc9aCaUHR5QPMP+uEFy8sIOkR3XNoYVgLny97a4aXZrTJ61KyNSPUnUo0qnvDdMxGCpL cDwwRlaY9DIuq1Ba+JOeDO3DFb+gmxniAY+86g/Ejw+3lHU891xxF+ytcO/9bdodyp7htKeZHHy jx51LRJQ+Phok4l4jbuAQ2n95jLyVp/qGuZQ5skViT5s3/Aj+H/+W1A+TXhrGeOdD++Ij3S85A7 iBcG9sU7wEA== X-Google-Smtp-Source: AGHT+IG5JOx3+z3jkn908wqvYEyARJGcTd4Wq+0SCyTrlBlZpZYwXr4OLdseMQuOeZWlGbwLIQfOxA== X-Received: by 2002:a17:903:2a83:b0:237:cadf:9aac with SMTP id d9443c01a7336-23e2572ff8amr99070035ad.29.1752753301937; Thu, 17 Jul 2025 04:55:01 -0700 (PDT) Received: from localhost ([45.84.137.104]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-23de433d4a8sm142372375ad.169.2025.07.17.04.54.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Jul 2025 04:55:01 -0700 (PDT) From: Richard Gobert To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, dsahern@kernel.org, razor@blackwall.org, idosch@nvidia.com, petrm@nvidia.com, menglong8.dong@gmail.com, richardbgobert@gmail.com, daniel@iogearbox.net, martin.lau@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v4 3/4] net: vxlan: bind vxlan sockets to their local address Date: Thu, 17 Jul 2025 13:54:11 +0200 Message-Id: <20250717115412.11424-4-richardbgobert@gmail.com> In-Reply-To: <20250717115412.11424-1-richardbgobert@gmail.com> References: <20250717115412.11424-1-richardbgobert@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Bind VXLAN sockets to the local addresses if the IFLA_VXLAN_LOCALBIND option is set. This is the new default. Change vxlan_find_sock to search for the socket using the listening address. This is implemented by copying the VXLAN local address to the udp_port_cfg passed to udp_sock_create. The freebind option is set because VXLAN interfaces may be UP before their outgoing interface is. This fixes multiple VXLAN selftests that fail because of that race. Signed-off-by: Richard Gobert --- drivers/net/vxlan/vxlan_core.c | 58 ++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index 667ff17c4569..cc22844fcc4c 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -78,18 +78,33 @@ static inline bool vxlan_collect_metadata(struct vxlan_= sock *vs) } =20 /* Find VXLAN socket based on network namespace, address family, UDP port, - * enabled unshareable flags and socket device binding (see l3mdev with - * non-default VRF). + * bound address, enabled unshareable flags and socket device binding + * (see l3mdev with non-default VRF). */ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t fam= ily, - __be16 port, u32 flags, int ifindex) + __be16 port, u32 flags, int ifindex, + union vxlan_addr *saddr) { struct vxlan_sock *vs; =20 flags &=3D VXLAN_F_RCV_FLAGS; =20 hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) { - if (inet_sk(vs->sock->sk)->inet_sport =3D=3D port && + struct sock *sk =3D vs->sock->sk; + struct inet_sock *inet =3D inet_sk(sk); + + if (flags & VXLAN_F_LOCALBIND) { + if (family =3D=3D AF_INET && + inet->inet_rcv_saddr !=3D saddr->sin.sin_addr.s_addr) + continue; +#if IS_ENABLED(CONFIG_IPV6) + else if (ipv6_addr_cmp(&sk->sk_v6_rcv_saddr, + &saddr->sin6.sin6_addr) !=3D 0) + continue; +#endif + } + + if (inet->inet_sport =3D=3D port && vxlan_get_sk_family(vs) =3D=3D family && vs->flags =3D=3D flags && vs->sock->sk->sk_bound_dev_if =3D=3D ifindex) @@ -141,11 +156,12 @@ static struct vxlan_dev *vxlan_vs_find_vni(struct vxl= an_sock *vs, /* Look up VNI in a per net namespace table */ static struct vxlan_dev *vxlan_find_vni(struct net *net, int ifindex, __be32 vni, sa_family_t family, - __be16 port, u32 flags) + __be16 port, u32 flags, + union vxlan_addr *saddr) { struct vxlan_sock *vs; =20 - vs =3D vxlan_find_sock(net, family, port, flags, ifindex); + vs =3D vxlan_find_sock(net, family, port, flags, ifindex, saddr); if (!vs) return NULL; =20 @@ -2309,7 +2325,7 @@ static int encap_bypass_if_local(struct sk_buff *skb,= struct net_device *dev, dst_release(dst); dst_vxlan =3D vxlan_find_vni(vxlan->net, dst_ifindex, vni, addr_family, dst_port, - vxlan->cfg.flags); + vxlan->cfg.flags, &vxlan->cfg.saddr); if (!dst_vxlan) { DEV_STATS_INC(dev, tx_errors); vxlan_vnifilter_count(vxlan, vni, NULL, @@ -3508,8 +3524,9 @@ static const struct ethtool_ops vxlan_ethtool_ops =3D= { .get_link_ksettings =3D vxlan_get_link_ksettings, }; =20 -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; @@ -3526,6 +3543,20 @@ static struct socket *vxlan_create_sock(struct net *= net, bool ipv6, udp_conf.family =3D AF_INET; } =20 + if (flags & VXLAN_F_LOCALBIND) { + if (ipv6) { +#if IS_ENABLED(CONFIG_IPV6) + memcpy(&udp_conf.local_ip6.s6_addr32, + &addr->sin6.sin6_addr.s6_addr32, + sizeof(addr->sin6.sin6_addr.s6_addr32)); +#endif + } else { + udp_conf.local_ip.s_addr =3D addr->sin.sin_addr.s_addr; + } + + udp_conf.freebind =3D 1; + } + udp_conf.local_udp_port =3D port; udp_conf.bind_ifindex =3D ifindex; =20 @@ -3541,7 +3572,8 @@ static struct socket *vxlan_create_sock(struct net *n= et, 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_sock *vs; struct socket *sock; @@ -3557,7 +3589,7 @@ static struct vxlan_sock *vxlan_socket_create(struct = net *net, bool ipv6, for (h =3D 0; h < VNI_HASH_SIZE; ++h) INIT_HLIST_HEAD(&vs->vni_list[h]); =20 - sock =3D vxlan_create_sock(net, ipv6, port, flags, ifindex); + sock =3D vxlan_create_sock(net, ipv6, port, flags, ifindex, addr); if (IS_ERR(sock)) { kfree(vs); return ERR_CAST(sock); @@ -3610,7 +3642,7 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, = bool ipv6) rcu_read_lock(); vs =3D vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET, vxlan->cfg.dst_port, vxlan->cfg.flags, - l3mdev_index); + l3mdev_index, &vxlan->cfg.saddr); if (vs && !refcount_inc_not_zero(&vs->refcnt)) { rcu_read_unlock(); return -EBUSY; @@ -3620,7 +3652,7 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, = bool ipv6) if (!vs) vs =3D 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) --=20 2.36.1 From nobody Mon Oct 6 19:04:10 2025 Received: from mail-wr1-f44.google.com (mail-wr1-f44.google.com [209.85.221.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C53D136358; Thu, 17 Jul 2025 11:55:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752753315; cv=none; b=oAe9Ke+770CdB0NLf0rs4qfN/LgADzChT+0JShNREwJo4q1MeotWdI100UKho6Le2t3FtP9FjmWV1dnUd3F5H0DzB0uyE6o5p9rdHiiEf725hxxEbRWV9xGBCdQ/7xtckfN1vuVvdiNGtZPFxEICxYqWyLeTERGnFc6isDZaYDs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752753315; c=relaxed/simple; bh=eE6ITxDuIJfEiD0MPyo74zQJCWbgv/+KNDuj42o3f4o=; h=From:To:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=gMiRpCY/izSPxUyUyAKkQfI3/BwU5OJb0IWrblH6dVyD/XMONah41myigErtVsPKkVwfZUQSv/FHFdT3RPKdLLwhin7cl29yr8fgfCWCk0Ld5uIlCtWirmICkmSVtmEZ2YzBlLTjsHuuuAUgzGvHkMiJm4zCp7OoegnrR6Z9K+Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Npy2UPfZ; arc=none smtp.client-ip=209.85.221.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Npy2UPfZ" Received: by mail-wr1-f44.google.com with SMTP id ffacd0b85a97d-3a4f379662cso646811f8f.0; Thu, 17 Jul 2025 04:55:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1752753312; x=1753358112; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=flDybFiyCaDc4poe3ad+U4bvumYcoJHYkl7fFvJ0otI=; b=Npy2UPfZJCYjXlP0iE0Z5F1C3DFYW36UXAWAvY+QoQKE9t5f1F/VrP7BAv9XeTR54h Z86YJVkq2SBpBDSx8MCbyWxdcj0KOr13c9Nicx5LNY1w7BasKydyyoLfAUAeNUqngZv6 eINQ4CRe31lLwJqyQCDVCJWknkiinepYmlsZGS6qDR5t5Cf5lpkYucdOOEWRzbl2xuoa yx1+xlUxCSWFScqX8dXEUGKBmYcEQoUimeq8HHFEe0GRIgSZkLngbKSDTHSqn/brvjw4 1N3pbWiXobtIqEV//ueWMbC4BScz7/gnIeRxTLp3nyl6ZFsX4oeMTX/lbNodWF6AAnSl KfgQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752753312; x=1753358112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=flDybFiyCaDc4poe3ad+U4bvumYcoJHYkl7fFvJ0otI=; b=gKvPjTwnWDPYSJuECMTtlps22UmZLJHus5rV1TzrLnOgCoTJO2i6Ig/qhmzpjOIA/r bghH+nWo0/H6zG6b9jhvK2hTGo2X4X0UeY+nWne9RTAI7nZVZXN+hsZoN8wryVtRCU2k 4X90ibF0ufQYfSBcqnnGh+Vb/wTZE+msqBIOhKC5J2e5LQP6kxWnzjTHjw5oVS/7xKeR XLqRqaT4HTPkNU3C8vR+MImJ13e1C1zx3+Mz+7CoQ0vqf7mZzr1lOJo/9yuo4CWna8Sq nbiO90inqvoDp8BGQTJgQ6lfPofNcMpxG43/pGLw/VSqQRjG9THQIMPM3vqKUl5B6dnx NfLQ== X-Forwarded-Encrypted: i=1; AJvYcCU84KioPw/daJXURBMNPmxpiTKvJO4ldioJv1A2wUmuYEtkHSo23NQXiYJOgIt1R/ZJVeNBnWM47gYhfM0=@vger.kernel.org, AJvYcCWdp+Cyd6Puc0JEqD54wTrJoMNvX6uMwNIk7t5CaXtBY6a5wvzm35aNq+hsh/lNdPvtdZ+7RJ91@vger.kernel.org X-Gm-Message-State: AOJu0YyFIrT6Qz6s24gQan2jscW+MmBzIEWMddDy2E9JXjV6DFF4J6Kj uLiD+vk1M8i5OHpnRx0/fUnQHlGXJAt3m3Elm0iKai+fOFRV6VrOW0WX X-Gm-Gg: ASbGnctRx3yWhFf7ggVrx2NyIk9rEOL0r/U0KwYAtMyMqdL+zeOzRJkRZ9TfyYmFT73 IQdcc03Pvv4f8FSDTiv51prI/3lzHXKpaEKMKKdGUUm6vZuCGtZ0wYJP6A/DhHBKudgKOlbM21+ /0x0hQXBOT0Quu0xb/xqvxBEllDqQeAGjbxlz2JhzAfYhp/ODcJ/tP0TTi8DgUP1dV08OSoXQCF Y+QfweFVv55QVM5JHnUTCX70Db+LmqDfztcmhJxr5Eld5UC8qtcJeg57YruoAkB+4ZbL44RTdeO 5YTsXI3rjTlT9dV8ypTH9s55Hh3GRoCMnAnfKmVCsCMWAD9gN9HdcvcxBu8amJoF X-Google-Smtp-Source: AGHT+IGIKfh4UTQ2Yhz/05JGa5MRm0R4h9gb11NzCJ+FgcdoRBhzp7NO+ZZam7qCZw+LjhLURgBtDQ== X-Received: by 2002:a05:6000:4801:b0:3a4:f7d9:3f56 with SMTP id ffacd0b85a97d-3b60e4b831fmr4778902f8f.2.1752753311437; Thu, 17 Jul 2025 04:55:11 -0700 (PDT) Received: from localhost ([45.84.137.104]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3b5e8dc3a62sm20393530f8f.40.2025.07.17.04.55.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Jul 2025 04:55:11 -0700 (PDT) From: Richard Gobert To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, dsahern@kernel.org, razor@blackwall.org, idosch@nvidia.com, petrm@nvidia.com, menglong8.dong@gmail.com, richardbgobert@gmail.com, daniel@iogearbox.net, martin.lau@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v4 4/4] net: geneve: enable binding geneve sockets to local addresses Date: Thu, 17 Jul 2025 13:54:12 +0200 Message-Id: <20250717115412.11424-5-richardbgobert@gmail.com> In-Reply-To: <20250717115412.11424-1-richardbgobert@gmail.com> References: <20250717115412.11424-1-richardbgobert@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Allow binding geneve sockets to local addresses, similar to the VXLAN "local" option. Add a netlink option to configure the local address. Like VXLAN, Geneve sockets can be bound to non-local addresses, meaning they may be UP before their outgoing interfaces. Signed-off-by: Richard Gobert --- drivers/net/geneve.c | 80 +++++++++++++++++++++++++++--- include/net/geneve.h | 6 +++ include/uapi/linux/if_link.h | 2 + tools/include/uapi/linux/if_link.h | 2 + 4 files changed, 82 insertions(+), 8 deletions(-) diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 54384f9b3872..bc88b9a52410 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -61,6 +61,7 @@ struct geneve_config { bool inner_proto_inherit; u16 port_min; u16 port_max; + union geneve_addr saddr; }; =20 /* Pseudo network device */ @@ -465,7 +466,8 @@ static int geneve_udp_encap_err_lookup(struct sock *sk,= struct sk_buff *skb) } =20 static struct socket *geneve_create_sock(struct net *net, bool ipv6, - __be16 port, bool ipv6_rx_csum) + __be16 port, bool ipv6_rx_csum, + union geneve_addr *local_addr) { struct socket *sock; struct udp_port_cfg udp_conf; @@ -477,11 +479,20 @@ static struct socket *geneve_create_sock(struct net *= net, bool ipv6, udp_conf.family =3D AF_INET6; udp_conf.ipv6_v6only =3D 1; udp_conf.use_udp6_rx_checksums =3D ipv6_rx_csum; +#if IS_ENABLED(CONFIG_IPV6) + memcpy(&udp_conf.local_ip6, + &local_addr->sin6.sin6_addr, + sizeof(local_addr->sin6.sin6_addr)); +#endif } else { udp_conf.family =3D AF_INET; udp_conf.local_ip.s_addr =3D htonl(INADDR_ANY); + memcpy(&udp_conf.local_ip, + &local_addr->sin.sin_addr, + sizeof(local_addr->sin.sin_addr)); } =20 + udp_conf.freebind =3D 1; udp_conf.local_udp_port =3D port; =20 /* Open UDP socket */ @@ -586,7 +597,8 @@ static int geneve_gro_complete(struct sock *sk, struct = sk_buff *skb, =20 /* Create new listen socket if needed */ static struct geneve_sock *geneve_socket_create(struct net *net, __be16 po= rt, - bool ipv6, bool ipv6_rx_csum) + bool ipv6, bool ipv6_rx_csum, + union geneve_addr *local_addr) { struct geneve_net *gn =3D net_generic(net, geneve_net_id); struct geneve_sock *gs; @@ -598,7 +610,7 @@ static struct geneve_sock *geneve_socket_create(struct = net *net, __be16 port, if (!gs) return ERR_PTR(-ENOMEM); =20 - sock =3D geneve_create_sock(net, ipv6, port, ipv6_rx_csum); + sock =3D geneve_create_sock(net, ipv6, port, ipv6_rx_csum, local_addr); if (IS_ERR(sock)) { kfree(gs); return ERR_CAST(sock); @@ -657,12 +669,24 @@ static void geneve_sock_release(struct geneve_dev *ge= neve) =20 static struct geneve_sock *geneve_find_sock(struct geneve_net *gn, sa_family_t family, - __be16 dst_port) + __be16 dst_port, + union geneve_addr *saddr) { struct geneve_sock *gs; =20 list_for_each_entry(gs, &gn->sock_list, list) { - if (inet_sk(gs->sock->sk)->inet_sport =3D=3D dst_port && + struct sock *sk =3D gs->sock->sk; + struct inet_sock *inet =3D inet_sk(sk); + + if (family =3D=3D AF_INET && + inet->inet_rcv_saddr !=3D saddr->sin.sin_addr.s_addr) + continue; + + else if (ipv6_addr_cmp(&sk->sk_v6_rcv_saddr, + &saddr->sin6.sin6_addr) !=3D 0) + continue; + + if (inet->inet_sport =3D=3D dst_port && geneve_get_sk_family(gs) =3D=3D family) { return gs; } @@ -679,14 +703,16 @@ static int geneve_sock_add(struct geneve_dev *geneve,= bool ipv6) __u8 vni[3]; __u32 hash; =20 - gs =3D geneve_find_sock(gn, ipv6 ? AF_INET6 : AF_INET, geneve->cfg.info.k= ey.tp_dst); + gs =3D geneve_find_sock(gn, ipv6 ? AF_INET6 : AF_INET, + geneve->cfg.info.key.tp_dst, &geneve->cfg.saddr); if (gs) { gs->refcnt++; goto out; } =20 gs =3D geneve_socket_create(net, geneve->cfg.info.key.tp_dst, ipv6, - geneve->cfg.use_udp6_rx_checksums); + geneve->cfg.use_udp6_rx_checksums, + &geneve->cfg.saddr); if (IS_ERR(gs)) return PTR_ERR(gs); =20 @@ -1246,6 +1272,8 @@ static const struct nla_policy geneve_policy[IFLA_GEN= EVE_MAX + 1] =3D { [IFLA_GENEVE_DF] =3D { .type =3D NLA_U8 }, [IFLA_GENEVE_INNER_PROTO_INHERIT] =3D { .type =3D NLA_FLAG }, [IFLA_GENEVE_PORT_RANGE] =3D NLA_POLICY_EXACT_LEN(sizeof(struct ifla_gene= ve_port_range)), + [IFLA_GENEVE_LOCAL] =3D NLA_POLICY_EXACT_LEN(sizeof_field(struct iphdr, s= addr)), + [IFLA_GENEVE_LOCAL6] =3D NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)), }; =20 static int geneve_validate(struct nlattr *tb[], struct nlattr *data[], @@ -1596,6 +1624,32 @@ static int geneve_nl2info(struct nlattr *tb[], struc= t nlattr *data[], cfg->inner_proto_inherit =3D true; } =20 + if (data[IFLA_GENEVE_LOCAL]) { + if (changelink && (ip_tunnel_info_af(info) !=3D AF_INET)) { + attrtype =3D IFLA_GENEVE_LOCAL; + goto change_notsup; + } + + cfg->saddr.sin.sin_addr.s_addr =3D nla_get_in_addr(data[IFLA_GENEVE_LOCA= L]); + cfg->saddr.sa.sa_family =3D AF_INET; + } + + if (data[IFLA_GENEVE_LOCAL6]) { +#if IS_ENABLED(CONFIG_IPV6) + if (changelink && (ip_tunnel_info_af(info) !=3D AF_INET6)) { + attrtype =3D IFLA_GENEVE_LOCAL6; + goto change_notsup; + } + + cfg->saddr.sin6.sin6_addr =3D nla_get_in6_addr(data[IFLA_GENEVE_LOCAL6]); + cfg->saddr.sa.sa_family =3D AF_INET6; +#else + NL_SET_ERR_MSG_ATTR(extack, data[IFLA_GENEVE_LOCAL6], + "IPv6 support not enabled in the kernel"); + return -EPFNOSUPPORT; +#endif + } + return 0; change_notsup: NL_SET_ERR_MSG_ATTR(extack, data[attrtype], @@ -1782,6 +1836,7 @@ static size_t geneve_get_size(const struct net_device= *dev) nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TTL_INHERIT */ nla_total_size(0) + /* IFLA_GENEVE_INNER_PROTO_INHERIT */ nla_total_size(sizeof(struct ifla_geneve_port_range)) + /* IFLA_GENEVE_P= ORT_RANGE */ + nla_total_size(sizeof(struct in6_addr)) + /* IFLA_GENEVE_LOCAL{6} */ 0; } =20 @@ -1807,16 +1862,25 @@ static int geneve_fill_info(struct sk_buff *skb, co= nst struct net_device *dev) if (nla_put_in_addr(skb, IFLA_GENEVE_REMOTE, info->key.u.ipv4.dst)) goto nla_put_failure; + + if (nla_put_in_addr(skb, IFLA_GENEVE_LOCAL, + info->key.u.ipv4.src)) + goto nla_put_failure; + if (nla_put_u8(skb, IFLA_GENEVE_UDP_CSUM, test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags))) goto nla_put_failure; - #if IS_ENABLED(CONFIG_IPV6) } else if (!metadata) { if (nla_put_in6_addr(skb, IFLA_GENEVE_REMOTE6, &info->key.u.ipv6.dst)) goto nla_put_failure; + + if (nla_put_in6_addr(skb, IFLA_GENEVE_LOCAL6, + &info->key.u.ipv6.src)) + goto nla_put_failure; + if (nla_put_u8(skb, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, !test_bit(IP_TUNNEL_CSUM_BIT, info->key.tun_flags))) diff --git a/include/net/geneve.h b/include/net/geneve.h index 5c96827a487e..7b12c70db11f 100644 --- a/include/net/geneve.h +++ b/include/net/geneve.h @@ -62,6 +62,12 @@ struct genevehdr { u8 options[]; }; =20 +union geneve_addr { + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr sa; +}; + static inline bool netif_is_geneve(const struct net_device *dev) { return dev->rtnl_link_ops && diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h index 7350129b1444..ff362d76a0d4 100644 --- a/include/uapi/linux/if_link.h +++ b/include/uapi/linux/if_link.h @@ -1442,6 +1442,8 @@ enum { IFLA_GENEVE_DF, IFLA_GENEVE_INNER_PROTO_INHERIT, IFLA_GENEVE_PORT_RANGE, + IFLA_GENEVE_LOCAL, + IFLA_GENEVE_LOCAL6, __IFLA_GENEVE_MAX }; #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/= if_link.h index eee934cc2cf4..894a1aa91133 100644 --- a/tools/include/uapi/linux/if_link.h +++ b/tools/include/uapi/linux/if_link.h @@ -1438,6 +1438,8 @@ enum { IFLA_GENEVE_TTL_INHERIT, IFLA_GENEVE_DF, IFLA_GENEVE_INNER_PROTO_INHERIT, + IFLA_GENEVE_LOCAL, + IFLA_GENEVE_LOCAL6, __IFLA_GENEVE_MAX }; #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) --=20 2.36.1