Skip to contentSkip to conversation

How to find an unused TAP device with kernel 3.8 ?

PATCH Superseded Toralf Förster 4 participants 8 messages Jan 26, 2013 – Feb 2, 2013

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

With kernel 3.8. I just realized that all pre-defined TAP devices are RUNNING even if no virtual linux system is using it. Now I'm wondering whether this is a new feature of the upcoming kernel, a bug of the old - and how I can avoid that.

Background : When I start a user mode linux instance, I currently grep for the next free tap device in this way :

Code:
for t in $(ifconfig | grep "^tap" | cut -f1 -d:)
do
ethtool $t | grep -q 'Link detected: no'
if [[ $? -eq 0 ]]; then

      NET="tuntap,$t"
      break

fi
done

but this doesn't work now anymore.

Here is the diff in dmesg

$ diff 3.7.1 3.8.0-rc1+ | grep UP

< br0: flags=4355<UP,BROADCAST,PROMISC,MULTICAST> mtu 1500

Quoted 1 line

br0: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500

< tap0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500

Quoted 1 line

tap0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500

more details : http://forums.gentoo.org/viewtopic-p-7211498.html#7211498

Signature · 3 lines
MfG/Sincerely
Toralf Förster
pgp finger print: 7B1A 07F4 EC82 0F90 D4C2 8936 872A E508 7DB6 9DA3
#1 lore raw
Quoted 26 lines · Toralf Förster

With kernel 3.8. I just realized that all pre-defined TAP devices are RUNNING even if no virtual linux system is using it. Now I'm wondering whether this is a new feature of the upcoming kernel, a bug of the old - and how I can avoid that.

Background : When I start a user mode linux instance, I currently grep for the next free tap device in this way :

Code:
for t in $(ifconfig | grep "^tap" | cut -f1 -d:)
do
ethtool $t | grep -q 'Link detected: no'
if [[ $? -eq 0 ]]; then

      NET="tuntap,$t"
      break

fi
done

but this doesn't work now anymore.

Here is the diff in dmesg

$ diff 3.7.1 3.8.0-rc1+ | grep UP

< br0: flags=4355<UP,BROADCAST,PROMISC,MULTICAST> mtu 1500

Quoted 7 lines
Quoted 1 line

br0: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500

< tap0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500

Quoted 1 line

tap0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500

more details : http://forums.gentoo.org/viewtopic-p-7211498.html#7211498

Looks like something wrong with the carrier detection of tap.

Please try the following patch to see if it helps.

Thanks.

drivers/net/tun.c +5 -0
index cc09b67..d8a53c3 100644                                                                                                                                             
@@ -438,6 +438,9 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
                sock_put(&tfile->sk);                                                                                                                                     
        }                                                                                                                                                                 
                                                                                                                                                                          
+       if (tun && tun->numqueues == 0)                                                                                                                                   
+               netif_carrier_off(tun->dev);                                                                                                                              
+                                                                                                                                                                         
        if (clean) {                                                                                                                                                      
                if (tun && tun->numqueues == 0 && tun->numdisabled == 0 &&                                                                                                
                    !(tun->flags & TUN_PERSIST))                                                                                                                          
@@ -473,6 +476,7 @@ static void tun_detach_all(struct net_device *dev)
        BUG_ON(tun->numqueues != 0);                                                                                                                                      
                                                                                                                                                                          
        synchronize_net();                                                                                                                                                
+       netif_carrier_off(dev);                                                                                                                                           
        for (i = 0; i < n; i++) {                                                                                                                                         
                tfile = rtnl_dereference(tun->tfiles[i]);                                                                                                                 
                /* Drop read queue */                                                                                                                                     
@@ -531,6 +535,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
                sock_hold(&tfile->sk);                                                                                                                                    
                                                                                                                                                                          
        tun_set_real_num_queues(tun);                                                                                                                                     
+       netif_carrier_on(tun->dev);                                                                                                                                       
                                                                                                                                                                          
        /* device is allowed to go away first, so no need to hold extra                                                                                                   
         * refcnt.                                                                                                                                                        
Signature · 1 line
1.7.1  
#2 lore raw

PATCH 1/1 tun: fix carrier on/off status

Commit c8d68e6be1c3b242f1c598595830890b65cea64a removed carrier off call from tun_detach since it's now called on queue disable and not only on tun close. This confuses userspace which used this flag to detect a free tun. To fix, move on/off calls to setiff/close respectively.

---

Quoted 65 lines · Jason Wang
Quoted 27 lines · Toralf Förster

Re: How to find an unused TAP device with kernel 3.8 ?
With kernel 3.8. I just realized that all pre-defined TAP devices are RUNNING even if no virtual linux system is using it. Now I'm wondering whether this is a new feature of the upcoming kernel, a bug of the old - and how I can avoid that.

Background : When I start a user mode linux instance, I currently grep for the next free tap device in this way :

Code:
for t in $(ifconfig | grep "^tap" | cut -f1 -d:)
do
ethtool $t | grep -q 'Link detected: no'
if [[ $? -eq 0 ]]; then

      NET="tuntap,$t"
      break

fi
done

but this doesn't work now anymore.

Here is the diff in dmesg

$ diff 3.7.1 3.8.0-rc1+ | grep UP

< br0: flags=4355<UP,BROADCAST,PROMISC,MULTICAST> mtu 1500

Quoted 7 lines
Quoted 1 line

br0: flags=4419<UP,BROADCAST,RUNNING,PROMISC,MULTICAST> mtu 1500

< tap0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500

Quoted 1 line

tap0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500

more details : http://forums.gentoo.org/viewtopic-p-7211498.html#7211498

Looks like something wrong with the carrier detection of tap.

Please try the following patch to see if it helps.

Thanks.

drivers/net/tun.c +4 -0
index cc09b67..d8a53c3 100644                                                                                                                                             
@@ -438,6 +438,9 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
                sock_put(&tfile->sk);                                                                                                                                     
        }                                                                                                                                                                 
 
+       if (tun && tun->numqueues == 0)                                                                                                                                   
+               netif_carrier_off(tun->dev);                                                                                                                              
+                                                                                                                                                                         
        if (clean) {                                                                                                                                                      
                if (tun && tun->numqueues == 0 && tun->numdisabled == 0 &&                                                                                                
                    !(tun->flags & TUN_PERSIST))                                                                                                                          
@@ -473,6 +476,7 @@ static void tun_detach_all(struct net_device *dev)
        BUG_ON(tun->numqueues != 0);                                                                                                                                      
 
        synchronize_net();                                                                                                                                                
+       netif_carrier_off(dev);                                                                                                                                           
        for (i = 0; i < n; i++) {                                                                                                                                         
                tfile = rtnl_dereference(tun->tfiles[i]);                                                                                                                 
                /* Drop read queue */                                                                                                                                     

drivers/net/tun.c static int tun_attach(struct tun_struct *tun, struct file *file) · line 541

Quoted 7 lines
drivers/net/tun.c +1 -0
@@ -531,6 +535,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file)
                sock_hold(&tfile->sk);                                                                                                                                    
 
        tun_set_real_num_queues(tun);                                                                                                                                     
+       netif_carrier_on(tun->dev);                                                                                                                                       
 
        /* device is allowed to go away first, so no need to hold extra                                                                                                   
         * refcnt.                                                                                                                                                        

This will set carrier off if all queues are disabled, which I think is a problem as it would confuse the script. How about the following instead:

drivers/net/tun.c +4 -2
index af372d0..00dfdad 100644
@@ -1644,10 +1644,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 		    device_create_file(&tun->dev->dev, &dev_attr_owner) ||
 		    device_create_file(&tun->dev->dev, &dev_attr_group))
 			pr_err("Failed to create tun sysfs files\n");
-
-		netif_carrier_on(tun->dev);
 	}
 
+	netif_carrier_on(tun->dev);
+
 	tun_debug(KERN_INFO, tun, "tun_set_iff\n");
 
 	if (ifr->ifr_flags & IFF_NO_PI)
@@ -2124,6 +2124,8 @@ static int tun_chr_close(struct inode *inode, struct file *file)
 	struct tun_file *tfile = file->private_data;
 	struct net *net = tfile->net;
 
+	netif_carrier_off(tun->dev);
+
 	tun_detach(tfile, true);
 	put_net(net);
 
Signature · 1 line
MST
#3 lore raw

PATCH v2 1/1 tun: fix carrier on/off status

Commit c8d68e6be1c3b242f1c598595830890b65cea64a removed carrier off call from tun_detach since it's now called on queue disable and not only on tun close. This confuses userspace which used this flag to detect a free tun. To fix, put this back but under if (clean).

---

Changes from v1:
Don't set carrier off unless all queues are closed.

Note: didn't test in MQ mode - Jason, care checking this does the right thing there?

drivers/net/tun.c +8 -5
index af372d0..06b2723 100644
@@ -434,10 +434,13 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
 	}
 
 	if (clean) {
-		if (tun && tun->numqueues == 0 && tun->numdisabled == 0 &&
-		    !(tun->flags & TUN_PERSIST))
-			if (tun->dev->reg_state == NETREG_REGISTERED)
+		if (tun && tun->numqueues == 0 && tun->numdisabled == 0) {
+			netif_carrier_off(tun->dev);
+
+			if (!(tun->flags & TUN_PERSIST) &&
+			    tun->dev->reg_state == NETREG_REGISTERED)
 				unregister_netdevice(tun->dev);
+		}
 
 		BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED,
 				 &tfile->socket.flags));
@@ -1644,10 +1647,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 		    device_create_file(&tun->dev->dev, &dev_attr_owner) ||
 		    device_create_file(&tun->dev->dev, &dev_attr_group))
 			pr_err("Failed to create tun sysfs files\n");
-
-		netif_carrier_on(tun->dev);
 	}
 
+	netif_carrier_on(tun->dev);
+
 	tun_debug(KERN_INFO, tun, "tun_set_iff\n");
 
 	if (ifr->ifr_flags & IFF_NO_PI)
Tested-by Acked-by on v2 1/1
#4 lore raw

Re: [PATCHv2] tun: fix carrier on/off status

Quoted 7 lines · Michael S. Tsirkin

Commit c8d68e6be1c3b242f1c598595830890b65cea64a removed carrier off call from tun_detach since it's now called on queue disable and not only on tun close. This confuses userspace which used this flag to detect a free tun. To fix, put this back but under if (clean).

Quoted 7 lines

---

Changes from v1:
Don't set carrier off unless all queues are closed.

Note: didn't test in MQ mode - Jason, care checking this does the right thing there?

Quoted 40 lines
drivers/net/tun.c +8 -6
index af372d0..06b2723 100644
@@ -434,10 +434,13 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
 	}
 
 	if (clean) {
-		if (tun && tun->numqueues == 0 && tun->numdisabled == 0 &&
-		    !(tun->flags & TUN_PERSIST))
-			if (tun->dev->reg_state == NETREG_REGISTERED)
+		if (tun && tun->numqueues == 0 && tun->numdisabled == 0) {
+			netif_carrier_off(tun->dev);
+
+			if (!(tun->flags & TUN_PERSIST) &&
+			    tun->dev->reg_state == NETREG_REGISTERED)
 				unregister_netdevice(tun->dev);
+		}
 
 		BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED,
 				 &tfile->socket.flags));
@@ -1644,10 +1647,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 		    device_create_file(&tun->dev->dev, &dev_attr_owner) ||
 		    device_create_file(&tun->dev->dev, &dev_attr_group))
 			pr_err("Failed to create tun sysfs files\n");
-
-		netif_carrier_on(tun->dev);
 	}
 
+	netif_carrier_on(tun->dev);
+
 	tun_debug(KERN_INFO, tun, "tun_set_iff\n");
 
 	if (ifr->ifr_flags & IFF_NO_PI)
--

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

author Tested-by on v2 1/1
#5 lore raw

Re: [PATCHv2] tun: fix carrier on/off status

In reply to Michael S. Tsirkin
Quoted 50 lines · Michael S. Tsirkin

Commit c8d68e6be1c3b242f1c598595830890b65cea64a removed carrier off call from tun_detach since it's now called on queue disable and not only on tun close. This confuses userspace which used this flag to detect a free tun. To fix, put this back but under if (clean).

---

Changes from v1:
Don't set carrier off unless all queues are closed.

Note: didn't test in MQ mode - Jason, care checking this does the right thing there?

drivers/net/tun.c +8 -5
index af372d0..06b2723 100644
@@ -434,10 +434,13 @@ static void __tun_detach(struct tun_file *tfile, bool clean)
 	}
 
 	if (clean) {
-		if (tun && tun->numqueues == 0 && tun->numdisabled == 0 &&
-		    !(tun->flags & TUN_PERSIST))
-			if (tun->dev->reg_state == NETREG_REGISTERED)
+		if (tun && tun->numqueues == 0 && tun->numdisabled == 0) {
+			netif_carrier_off(tun->dev);
+
+			if (!(tun->flags & TUN_PERSIST) &&
+			    tun->dev->reg_state == NETREG_REGISTERED)
 				unregister_netdevice(tun->dev);
+		}
 
 		BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED,
 				 &tfile->socket.flags));
@@ -1644,10 +1647,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 		    device_create_file(&tun->dev->dev, &dev_attr_owner) ||
 		    device_create_file(&tun->dev->dev, &dev_attr_group))
 			pr_err("Failed to create tun sysfs files\n");
-
-		netif_carrier_on(tun->dev);
 	}
 
+	netif_carrier_on(tun->dev);
+
 	tun_debug(KERN_INFO, tun, "tun_set_iff\n");
 
 	if (ifr->ifr_flags & IFF_NO_PI)
Signature · 3 lines
MfG/Sincerely
Toralf Förster
pgp finger print: 7B1A 07F4 EC82 0F90 D4C2 8936 872A E508 7DB6 9DA3
maintainer Applied
#6 lore raw

Re: [PATCHv2] tun: fix carrier on/off status

In reply to Michael S. Tsirkin

From: "Michael S. Tsirkin" <[email protected]>
Date: Mon, 28 Jan 2013 12:38:02 +0200

Quoted 6 lines

Commit c8d68e6be1c3b242f1c598595830890b65cea64a removed carrier off call from tun_detach since it's now called on queue disable and not only on tun close. This confuses userspace which used this flag to detect a free tun. To fix, put this back but under if (clean).

Applied.

#7 lore raw

Re: [PATCHv2] tun: fix carrier on/off status

In reply to Michael S. Tsirkin

Between v3.8.0-rc5+ and v3.8.0-rc6+ the following dmesg are new :

Quoted 8 lines

br0: port 4(tap3) entered forwarding state
br0: port 4(tap3) entered forwarding state
br0: port 3(tap2) entered forwarding state
br0: port 3(tap2) entered forwarding state
br0: port 2(tap1) entered forwarding state
br0: port 2(tap1) entered forwarding state
br0: port 1(tap0) entered forwarding state
br0: port 1(tap0) entered forwarding state

Is this related to the original mail too ?

Signature · 3 lines
MfG/Sincerely
Toralf Förster
pgp finger print: 7B1A 07F4 EC82 0F90 D4C2 8936 872A E508 7DB6 9DA3