Skip to content

Commit aab8cc3

Browse files
Alexis Bauvindavem330
authored andcommitted
vxlan: add support for underlay in non-default VRF
Creating a VXLAN device with is underlay in the non-default VRF makes egress route lookup fail or incorrect since it will resolve in the default VRF, and ingress fail because the socket listens in the default VRF. This patch binds the underlying UDP tunnel socket to the l3mdev of the lower device of the VXLAN device. This will listen in the proper VRF and output traffic from said l3mdev, matching l3mdev routing rules and looking up the correct routing table. When the VXLAN device does not have a lower device, or the lower device is in the default VRF, the socket will not be bound to any interface, keeping the previous behaviour. The underlay l3mdev is deduced from the VXLAN lower device (IFLA_VXLAN_LINK). +----------+ +---------+ | | | | | vrf-blue | | vrf-red | | | | | +----+-----+ +----+----+ | | | | +----+-----+ +----+----+ | | | | | br-blue | | br-red | | | | | +----+-----+ +---+-+---+ | | | | +-----+ +-----+ | | | +----+-----+ +------+----+ +----+----+ | | lower device | | | | | eth0 | <- - - - - - - | vxlan-red | | tap-red | (... more taps) | | | | | | +----------+ +-----------+ +---------+ Signed-off-by: Alexis Bauvin <abauvin@scaleway.com> Reviewed-by: Amine Kherbouche <akherbouche@scaleway.com> Reviewed-by: David Ahern <dsahern@gmail.com> Tested-by: Amine Kherbouche <akherbouche@scaleway.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 6a6d668 commit aab8cc3

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

drivers/net/vxlan.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ static inline struct vxlan_rdst *first_remote_rtnl(struct vxlan_fdb *fdb)
188188
* and enabled unshareable flags.
189189
*/
190190
static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family,
191-
__be16 port, u32 flags)
191+
__be16 port, u32 flags, int ifindex)
192192
{
193193
struct vxlan_sock *vs;
194194

@@ -197,7 +197,8 @@ static struct vxlan_sock *vxlan_find_sock(struct net *net, sa_family_t family,
197197
hlist_for_each_entry_rcu(vs, vs_head(net, port), hlist) {
198198
if (inet_sk(vs->sock->sk)->inet_sport == port &&
199199
vxlan_get_sk_family(vs) == family &&
200-
vs->flags == flags)
200+
vs->flags == flags &&
201+
vs->sock->sk->sk_bound_dev_if == ifindex)
201202
return vs;
202203
}
203204
return NULL;
@@ -237,7 +238,7 @@ static struct vxlan_dev *vxlan_find_vni(struct net *net, int ifindex,
237238
{
238239
struct vxlan_sock *vs;
239240

240-
vs = vxlan_find_sock(net, family, port, flags);
241+
vs = vxlan_find_sock(net, family, port, flags, ifindex);
241242
if (!vs)
242243
return NULL;
243244

@@ -2288,6 +2289,9 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
22882289
struct rtable *rt;
22892290
__be16 df = 0;
22902291

2292+
if (!ifindex)
2293+
ifindex = sock4->sock->sk->sk_bound_dev_if;
2294+
22912295
rt = vxlan_get_route(vxlan, dev, sock4, skb, ifindex, tos,
22922296
dst->sin.sin_addr.s_addr,
22932297
&local_ip.sin.sin_addr.s_addr,
@@ -2337,6 +2341,9 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
23372341
} else {
23382342
struct vxlan_sock *sock6 = rcu_dereference(vxlan->vn6_sock);
23392343

2344+
if (!ifindex)
2345+
ifindex = sock6->sock->sk->sk_bound_dev_if;
2346+
23402347
ndst = vxlan6_get_route(vxlan, dev, sock6, skb, ifindex, tos,
23412348
label, &dst->sin6.sin6_addr,
23422349
&local_ip.sin6.sin6_addr,
@@ -2951,7 +2958,7 @@ static const struct ethtool_ops vxlan_ethtool_ops = {
29512958
};
29522959

29532960
static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
2954-
__be16 port, u32 flags)
2961+
__be16 port, u32 flags, int ifindex)
29552962
{
29562963
struct socket *sock;
29572964
struct udp_port_cfg udp_conf;
@@ -2969,6 +2976,7 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
29692976
}
29702977

29712978
udp_conf.local_udp_port = port;
2979+
udp_conf.bind_ifindex = ifindex;
29722980

29732981
/* Open UDP socket */
29742982
err = udp_sock_create(net, &udp_conf, &sock);
@@ -2980,7 +2988,8 @@ static struct socket *vxlan_create_sock(struct net *net, bool ipv6,
29802988

29812989
/* Create new listen socket if needed */
29822990
static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
2983-
__be16 port, u32 flags)
2991+
__be16 port, u32 flags,
2992+
int ifindex)
29842993
{
29852994
struct vxlan_net *vn = net_generic(net, vxlan_net_id);
29862995
struct vxlan_sock *vs;
@@ -2995,7 +3004,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
29953004
for (h = 0; h < VNI_HASH_SIZE; ++h)
29963005
INIT_HLIST_HEAD(&vs->vni_list[h]);
29973006

2998-
sock = vxlan_create_sock(net, ipv6, port, flags);
3007+
sock = vxlan_create_sock(net, ipv6, port, flags, ifindex);
29993008
if (IS_ERR(sock)) {
30003009
kfree(vs);
30013010
return ERR_CAST(sock);
@@ -3033,11 +3042,17 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
30333042
struct vxlan_net *vn = net_generic(vxlan->net, vxlan_net_id);
30343043
struct vxlan_sock *vs = NULL;
30353044
struct vxlan_dev_node *node;
3045+
int l3mdev_index = 0;
3046+
3047+
if (vxlan->cfg.remote_ifindex)
3048+
l3mdev_index = l3mdev_master_upper_ifindex_by_index(
3049+
vxlan->net, vxlan->cfg.remote_ifindex);
30363050

30373051
if (!vxlan->cfg.no_share) {
30383052
spin_lock(&vn->sock_lock);
30393053
vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET,
3040-
vxlan->cfg.dst_port, vxlan->cfg.flags);
3054+
vxlan->cfg.dst_port, vxlan->cfg.flags,
3055+
l3mdev_index);
30413056
if (vs && !refcount_inc_not_zero(&vs->refcnt)) {
30423057
spin_unlock(&vn->sock_lock);
30433058
return -EBUSY;
@@ -3046,7 +3061,8 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
30463061
}
30473062
if (!vs)
30483063
vs = vxlan_socket_create(vxlan->net, ipv6,
3049-
vxlan->cfg.dst_port, vxlan->cfg.flags);
3064+
vxlan->cfg.dst_port, vxlan->cfg.flags,
3065+
l3mdev_index);
30503066
if (IS_ERR(vs))
30513067
return PTR_ERR(vs);
30523068
#if IS_ENABLED(CONFIG_IPV6)

0 commit comments

Comments
 (0)