Commit 26d31925 authored by Nicolas Dichtel's avatar Nicolas Dichtel Committed by David S. Miller

tun: implement carrier change

The userspace may need to control the carrier state.
Signed-off-by: default avatarNicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: default avatarDidier Pallard <didier.pallard@6wind.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bf1c3ab8
...@@ -1254,6 +1254,21 @@ static int tun_xdp(struct net_device *dev, struct netdev_bpf *xdp) ...@@ -1254,6 +1254,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 = { static const struct net_device_ops tun_netdev_ops = {
.ndo_uninit = tun_net_uninit, .ndo_uninit = tun_net_uninit,
.ndo_open = tun_net_open, .ndo_open = tun_net_open,
...@@ -1263,6 +1278,7 @@ static const struct net_device_ops tun_netdev_ops = { ...@@ -1263,6 +1278,7 @@ static const struct net_device_ops tun_netdev_ops = {
.ndo_select_queue = tun_select_queue, .ndo_select_queue = tun_select_queue,
.ndo_set_rx_headroom = tun_set_headroom, .ndo_set_rx_headroom = tun_set_headroom,
.ndo_get_stats64 = tun_net_get_stats64, .ndo_get_stats64 = tun_net_get_stats64,
.ndo_change_carrier = tun_net_change_carrier,
}; };
static void __tun_xdp_flush_tfile(struct tun_file *tfile) static void __tun_xdp_flush_tfile(struct tun_file *tfile)
...@@ -1345,6 +1361,7 @@ static const struct net_device_ops tap_netdev_ops = { ...@@ -1345,6 +1361,7 @@ static const struct net_device_ops tap_netdev_ops = {
.ndo_get_stats64 = tun_net_get_stats64, .ndo_get_stats64 = tun_net_get_stats64,
.ndo_bpf = tun_xdp, .ndo_bpf = tun_xdp,
.ndo_xdp_xmit = tun_xdp_xmit, .ndo_xdp_xmit = tun_xdp_xmit,
.ndo_change_carrier = tun_net_change_carrier,
}; };
static void tun_flow_init(struct tun_struct *tun) static void tun_flow_init(struct tun_struct *tun)
...@@ -3002,12 +3019,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ...@@ -3002,12 +3019,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
struct net *net = sock_net(&tfile->sk); struct net *net = sock_net(&tfile->sk);
struct tun_struct *tun; struct tun_struct *tun;
void __user* argp = (void __user*)arg; void __user* argp = (void __user*)arg;
unsigned int ifindex, carrier;
struct ifreq ifr; struct ifreq ifr;
kuid_t owner; kuid_t owner;
kgid_t group; kgid_t group;
int sndbuf; int sndbuf;
int vnet_hdr_sz; int vnet_hdr_sz;
unsigned int ifindex;
int le; int le;
int ret; int ret;
bool do_notify = false; bool do_notify = false;
...@@ -3291,6 +3308,14 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ...@@ -3291,6 +3308,14 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
ret = tun_set_ebpf(tun, &tun->filter_prog, argp); ret = tun_set_ebpf(tun, &tun->filter_prog, argp);
break; 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: default:
ret = -EINVAL; ret = -EINVAL;
break; break;
......
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
#define TUNGETVNETBE _IOR('T', 223, int) #define TUNGETVNETBE _IOR('T', 223, int)
#define TUNSETSTEERINGEBPF _IOR('T', 224, int) #define TUNSETSTEERINGEBPF _IOR('T', 224, int)
#define TUNSETFILTEREBPF _IOR('T', 225, int) #define TUNSETFILTEREBPF _IOR('T', 225, int)
#define TUNSETCARRIER _IOW('T', 226, int)
/* TUNSETIFF ifr flags */ /* TUNSETIFF ifr flags */
#define IFF_TUN 0x0001 #define IFF_TUN 0x0001
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment