If the ipv6 module is loaded, then destroying a tap interface that has recently been disabled will cause close to block (in unregister_netdevice) until precisely 30 seconds have elapsed since the interface was disabled. This behavior does not occur if the ipv6 module is not loaded, nor if the tap interface is still enabled when calling close, nor if the tap interface has never been enabled.

If close is called less than 20 seconds after the interface has been disabled (so that it blocks for >10 seconds), then the following message is output:

  Message from [EMAIL PROTECTED] at Tue May  8 19:01:04 2007 ...
  bs18 kernel: unregister_netdevice: waiting for tap0 to become free. Usage 
count = 3

The attached Python script reliably reproduces this problem. The timestamps in the output show the 30 second delay between running 'ip link set tap0 down' and the subsequent call to close returning.

I have tested on two machines, both running Fedora Core 6, one with kernel 2.6.19 and one with kernel 2.6.20, and both machines exhibit the same symptoms.

  $ cat /proc/version
  Linux version 2.6.19-1.2895.fc6 ([EMAIL PROTECTED]) (gcc version 4.1.1 
20070105 (Red Hat 4.1.1-51)) #1 SMP Wed Jan 10 19:28:18 EST 2007
  Linux version 2.6.20-1.2933.fc6 ([EMAIL PROTECTED]) (gcc version 4.1.1 
20070105 (Red Hat 4.1.1-51)) #1 SMP Mon Mar 19 11:38:26 EDT 2007

I have also found the same symptoms to occur on a qemu virtual machine (running a custom 2.6.20 kernel) with minimal user-space code running (just syslogd, klogd, udevd, login and bash), which suggests that this isn't related to any badly-behaving user-space code.

Please cc any responses to me, as I'm not on the mailing list.  Thanks.

James.
#!/usr/bin/python
import os, time, struct, fcntl

# The following are from linux/if_tun.h
TUNSETIFF = 0x400454ca     # ioctl to configure a TUN/TAP interface
IFF_TAP = 0x0002           # Ethernet-level tunnel interface
IFF_NO_PI = 0x1000         # Protocol information header for tap interfaces

intf = 'tap0'

# Create a tap interface.
tapFd = os.open( '/dev/net/tun', os.O_RDWR )
ioctlData = struct.pack( '16s H 14x', intf, IFF_TAP | IFF_NO_PI )
fcntl.ioctl( tapFd, TUNSETIFF, ioctlData )

# Enable then disable the tap interface.
os.system( 'ip link set %s up' % intf )
print 'Enabled tap interface at', time.ctime( time.time() )
time.sleep( 1 )  # A delay here seems to be necessary to trigger the bug.
os.system( 'ip link set %s down' % intf )
print 'Disabled tap interface at', time.ctime( time.time() )
time.sleep( 17 ) # A delay here is not necessary, but illustrates that the 30 
second
                 # interval starts when the interface is disabled, not when 
close is
                 # called.

# Destroy the tap interface.
print 'About to close tap FD at', time.ctime( time.time() )
os.close( tapFd )
print 'Closed tap FD at', time.ctime( time.time() )

Reply via email to