Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Nicolas Dichtel and committed by
David S. Miller
26d31925 bf1c3ab8

+27 -1
+26 -1
drivers/net/tun.c
··· 1254 1254 } 1255 1255 } 1256 1256 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 + 1257 1272 static const struct net_device_ops tun_netdev_ops = { 1258 1273 .ndo_uninit = tun_net_uninit, 1259 1274 .ndo_open = tun_net_open, ··· 1278 1263 .ndo_select_queue = tun_select_queue, 1279 1264 .ndo_set_rx_headroom = tun_set_headroom, 1280 1265 .ndo_get_stats64 = tun_net_get_stats64, 1266 + .ndo_change_carrier = tun_net_change_carrier, 1281 1267 }; 1282 1268 1283 1269 static void __tun_xdp_flush_tfile(struct tun_file *tfile) ··· 1361 1345 .ndo_get_stats64 = tun_net_get_stats64, 1362 1346 .ndo_bpf = tun_xdp, 1363 1347 .ndo_xdp_xmit = tun_xdp_xmit, 1348 + .ndo_change_carrier = tun_net_change_carrier, 1364 1349 }; 1365 1350 1366 1351 static void tun_flow_init(struct tun_struct *tun) ··· 3019 3002 struct net *net = sock_net(&tfile->sk); 3020 3003 struct tun_struct *tun; 3021 3004 void __user* argp = (void __user*)arg; 3005 + unsigned int ifindex, carrier; 3022 3006 struct ifreq ifr; 3023 3007 kuid_t owner; 3024 3008 kgid_t group; 3025 3009 int sndbuf; 3026 3010 int vnet_hdr_sz; 3027 - unsigned int ifindex; 3028 3011 int le; 3029 3012 int ret; 3030 3013 bool do_notify = false; ··· 3306 3289 3307 3290 case TUNSETFILTEREBPF: 3308 3291 ret = tun_set_ebpf(tun, &tun->filter_prog, argp); 3292 + break; 3293 + 3294 + case TUNSETCARRIER: 3295 + ret = -EFAULT; 3296 + if (copy_from_user(&carrier, argp, sizeof(carrier))) 3297 + goto unlock; 3298 + 3299 + ret = tun_net_change_carrier(tun->dev, (bool)carrier); 3309 3300 break; 3310 3301 3311 3302 default:
+1
include/uapi/linux/if_tun.h
··· 59 59 #define TUNGETVNETBE _IOR('T', 223, int) 60 60 #define TUNSETSTEERINGEBPF _IOR('T', 224, int) 61 61 #define TUNSETFILTEREBPF _IOR('T', 225, int) 62 + #define TUNSETCARRIER _IOW('T', 226, int) 62 63 63 64 /* TUNSETIFF ifr flags */ 64 65 #define IFF_TUN 0x0001