udp_tunnel: add config option to bind to a device
authorAlexis Bauvin <abauvin@scaleway.com>
Mon, 3 Dec 2018 09:54:38 +0000 (10:54 +0100)
committerDavid S. Miller <davem@davemloft.net>
Mon, 3 Dec 2018 22:15:26 +0000 (14:15 -0800)
UDP tunnel sockets are always opened unbound to a specific device. This
patch allow the socket to be bound on a custom device, which
incidentally makes UDP tunnels VRF-aware if binding to an l3mdev.

Signed-off-by: Alexis Bauvin <abauvin@scaleway.com>
Reviewed-by: Amine Kherbouche <akherbouche@scaleway.com>
Tested-by: Amine Kherbouche <akherbouche@scaleway.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/udp_tunnel.h
net/ipv4/udp_tunnel.c
net/ipv6/ip6_udp_tunnel.c

index dc8d804af3b4d283f88d0d68b7a8c5410cdaac16..b8137953fea31a377b3f5cc4aae99db932ad1ed4 100644 (file)
@@ -30,6 +30,7 @@ struct udp_port_cfg {
 
        __be16                  local_udp_port;
        __be16                  peer_udp_port;
+       int                     bind_ifindex;
        unsigned int            use_udp_checksums:1,
                                use_udp6_tx_checksums:1,
                                use_udp6_rx_checksums:1,
index d0c412fc56adcdff4c0df10d5e1546e6ba1368eb..be8b5b2157d8a50b7502d9f229e0e78f59b5bb5c 100644 (file)
@@ -20,6 +20,23 @@ int udp_sock_create4(struct net *net, struct udp_port_cfg *cfg,
        if (err < 0)
                goto error;
 
+       if (cfg->bind_ifindex) {
+               struct net_device *dev;
+
+               dev = dev_get_by_index(net, cfg->bind_ifindex);
+               if (!dev) {
+                       err = -ENODEV;
+                       goto error;
+               }
+
+               err = kernel_setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
+                                       dev->name, strlen(dev->name) + 1);
+               dev_put(dev);
+
+               if (err < 0)
+                       goto error;
+       }
+
        udp_addr.sin_family = AF_INET;
        udp_addr.sin_addr = cfg->local_ip;
        udp_addr.sin_port = cfg->local_udp_port;
index b283f293ee4ae7537da0bde51b5a4695a2e6f249..3965d5396b0a381a9d5883a97c467a9b1c3d408c 100644 (file)
@@ -31,6 +31,22 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg,
                if (err < 0)
                        goto error;
        }
+       if (cfg->bind_ifindex) {
+               struct net_device *dev;
+
+               dev = dev_get_by_index(net, cfg->bind_ifindex);
+               if (!dev) {
+                       err = -ENODEV;
+                       goto error;
+               }
+
+               err = kernel_setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
+                                       dev->name, strlen(dev->name) + 1);
+               dev_put(dev);
+
+               if (err < 0)
+                       goto error;
+       }
 
        udp6_addr.sin6_family = AF_INET6;
        memcpy(&udp6_addr.sin6_addr, &cfg->local_ip6,