tun: implement carrier change
The userspace may need to control the carrier state. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: Didier Pallard <didier.pallard@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
bf1c3ab8d3
commit
26d31925cd
|
@ -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 = {
|
||||||
.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 = {
|
||||||
.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,
|
||||||
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,
|
||||||
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 @@
|
||||||
#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
|
||||||
|
|
Loading…
Reference in New Issue