Skip to content

Commit 26d3192

Browse files
NicolasDichteldavem330
authored andcommitted
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>
1 parent bf1c3ab commit 26d3192

File tree

2 files changed

+27
-1
lines changed

2 files changed

+27
-1
lines changed

drivers/net/tun.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1254,6 +1254,21 @@ static int tun_xdp(struct net_device *dev, struct netdev_bpf *xdp)
12541254
}
12551255
}
12561256

1257+
static int tun_net_change_carrier(struct net_device *dev, bool new_carrier)
1258+
{
1259+
if (new_carrier) {
1260+
struct tun_struct *tun = netdev_priv(dev);
1261+
1262+
if (!tun->numqueues)
1263+
return -EPERM;
1264+
1265+
netif_carrier_on(dev);
1266+
} else {
1267+
netif_carrier_off(dev);
1268+
}
1269+
return 0;
1270+
}
1271+
12571272
static const struct net_device_ops tun_netdev_ops = {
12581273
.ndo_uninit = tun_net_uninit,
12591274
.ndo_open = tun_net_open,
@@ -1263,6 +1278,7 @@ static const struct net_device_ops tun_netdev_ops = {
12631278
.ndo_select_queue = tun_select_queue,
12641279
.ndo_set_rx_headroom = tun_set_headroom,
12651280
.ndo_get_stats64 = tun_net_get_stats64,
1281+
.ndo_change_carrier = tun_net_change_carrier,
12661282
};
12671283

12681284
static void __tun_xdp_flush_tfile(struct tun_file *tfile)
@@ -1345,6 +1361,7 @@ static const struct net_device_ops tap_netdev_ops = {
13451361
.ndo_get_stats64 = tun_net_get_stats64,
13461362
.ndo_bpf = tun_xdp,
13471363
.ndo_xdp_xmit = tun_xdp_xmit,
1364+
.ndo_change_carrier = tun_net_change_carrier,
13481365
};
13491366

13501367
static void tun_flow_init(struct tun_struct *tun)
@@ -3002,12 +3019,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
30023019
struct net *net = sock_net(&tfile->sk);
30033020
struct tun_struct *tun;
30043021
void __user* argp = (void __user*)arg;
3022+
unsigned int ifindex, carrier;
30053023
struct ifreq ifr;
30063024
kuid_t owner;
30073025
kgid_t group;
30083026
int sndbuf;
30093027
int vnet_hdr_sz;
3010-
unsigned int ifindex;
30113028
int le;
30123029
int ret;
30133030
bool do_notify = false;
@@ -3291,6 +3308,14 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
32913308
ret = tun_set_ebpf(tun, &tun->filter_prog, argp);
32923309
break;
32933310

3311+
case TUNSETCARRIER:
3312+
ret = -EFAULT;
3313+
if (copy_from_user(&carrier, argp, sizeof(carrier)))
3314+
goto unlock;
3315+
3316+
ret = tun_net_change_carrier(tun->dev, (bool)carrier);
3317+
break;
3318+
32943319
default:
32953320
ret = -EINVAL;
32963321
break;

include/uapi/linux/if_tun.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#define TUNGETVNETBE _IOR('T', 223, int)
6060
#define TUNSETSTEERINGEBPF _IOR('T', 224, int)
6161
#define TUNSETFILTEREBPF _IOR('T', 225, int)
62+
#define TUNSETCARRIER _IOW('T', 226, int)
6263

6364
/* TUNSETIFF ifr flags */
6465
#define IFF_TUN 0x0001

0 commit comments

Comments
 (0)