[B] [PATCH 1/1] tun: implement carrier change
Kai-Heng Feng
kai.heng.feng at canonical.com
Wed Mar 6 18:00:18 UTC 2019
From: Nicolas Dichtel <nicolas.dichtel at 6wind.com>
BugLink: https://bugs.launchpad.net/bugs/1806392
The userspace may need to control the carrier state.
Signed-off-by: Nicolas Dichtel <nicolas.dichtel at 6wind.com>
Signed-off-by: Didier Pallard <didier.pallard at 6wind.com>
Signed-off-by: David S. Miller <davem at davemloft.net>
(backported from commit 26d31925cd5ea4b5b168ed538b0326d63ccbb384)
Signed-off-by: Kai-Heng Feng <kai.heng.feng at canonical.com>
---
drivers/net/tun.c | 27 ++++++++++++++++++++++++++-
include/uapi/linux/if_tun.h | 1 +
2 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 4e5d038a252d..a0c7756e304c 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1164,6 +1164,21 @@ static int tun_xdp(struct net_device *dev, struct netdev_bpf *xdp)
}
}
+static int tun_net_change_carrier(struct net_device *dev, bool new_carrier)
+{
+ if (new_carrier) {
+ struct tun_struct *tun = netdev_priv(dev);
+
+ if (!tun->numqueues)
+ return -EPERM;
+
+ netif_carrier_on(dev);
+ } else {
+ netif_carrier_off(dev);
+ }
+ return 0;
+}
+
static const struct net_device_ops tun_netdev_ops = {
.ndo_uninit = tun_net_uninit,
.ndo_open = tun_net_open,
@@ -1176,6 +1191,7 @@ static const struct net_device_ops tun_netdev_ops = {
#endif
.ndo_set_rx_headroom = tun_set_headroom,
.ndo_get_stats64 = tun_net_get_stats64,
+ .ndo_change_carrier = tun_net_change_carrier,
};
static const struct net_device_ops tap_netdev_ops = {
@@ -1195,6 +1211,7 @@ static const struct net_device_ops tap_netdev_ops = {
.ndo_set_rx_headroom = tun_set_headroom,
.ndo_get_stats64 = tun_net_get_stats64,
.ndo_bpf = tun_xdp,
+ .ndo_change_carrier = tun_net_change_carrier,
};
static void tun_flow_init(struct tun_struct *tun)
@@ -2501,12 +2518,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
struct tun_file *tfile = file->private_data;
struct tun_struct *tun;
void __user* argp = (void __user*)arg;
+ unsigned int ifindex, carrier;
struct ifreq ifr;
kuid_t owner;
kgid_t group;
int sndbuf;
int vnet_hdr_sz;
- unsigned int ifindex;
int le;
int ret;
@@ -2771,6 +2788,14 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
ret = 0;
break;
+ case TUNSETCARRIER:
+ ret = -EFAULT;
+ if (copy_from_user(&carrier, argp, sizeof(carrier)))
+ goto unlock;
+
+ ret = tun_net_change_carrier(tun->dev, (bool)carrier);
+ break;
+
default:
ret = -EINVAL;
break;
diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
index 030d3e6d6029..438f87bfa504 100644
--- a/include/uapi/linux/if_tun.h
+++ b/include/uapi/linux/if_tun.h
@@ -57,6 +57,7 @@
*/
#define TUNSETVNETBE _IOW('T', 222, int)
#define TUNGETVNETBE _IOR('T', 223, int)
+#define TUNSETCARRIER _IOW('T', 226, int)
/* TUNSETIFF ifr flags */
#define IFF_TUN 0x0001
--
2.17.1
More information about the kernel-team
mailing list