steel, a Toshiba Satellite 4060XCDT running Debian Etch, has a
Netgear MA401 Wireless pcmcia card. By default, the
orinoco_cs
driver was used for this card. While running
with a DHCP-assigned address, I had experienced no problems with it,
but when I assigned steel's eth0 port a static address (to expose it to the Internet), I noticed that every
six minutes, if there was no ethernet traffic, these messages would
appear:
Apr 26 10:23:51 steel kernel: eth0: New link status: Disconnected (0002) Apr 26 10:23:53 steel kernel: eth0: New link status: Connected (0001) Apr 26 10:29:51 steel kernel: eth0: New link status: Disconnected (0002) Apr 26 10:29:52 steel kernel: eth0: New link status: Connected (0001) Apr 26 10:35:51 steel kernel: eth0: New link status: Disconnected (0002) Apr 26 10:35:52 steel kernel: eth0: New link status: Connected (0001)
While looking for other reports of this behaviour, I found that the
hostap_cs
driver would also work with the Netgear card. I
had already noticed that both the orinoco_cs
and
hostap_cs
drivers were shown by lsmod
as loaded.
Maybe one was interfering with the other?
This lead to a slight detour, as I became interested in how the modules were chosen and loaded. Digging around in the udev material at http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html (link removed as kernel.org is down) gave me a lot of info; I also found a useful article which explained how the modalias system worked.
Back on track. To test the idea of module interference, I added
hostap_cs
to the /etc/modprobe.d/blacklist
file.
However, even without the hostap_driver
loaded, the same
disconnection pattern occurred. The next thing to try was to use
the hostap_cs
driver and see if that cured the problem.
This was slightly more tricky.
Firstly, I modified the /etc/modprobe.d/blacklist
file,
removing hostap_cs
and adding orinoco_cs
. Then I
had to modify the original udev
rules in
/etc/udev/rules.d/z25_persistent-net.rules
to comment out
the eth0 naming that was created when I first installed Debian:
# This file was automatically generated by the /lib/udev/write_net_rules # program, probably run by the persistent-net-generator.rules rules file. # # You can modify it, as long as you keep each rule on a single line. # MAC addresses must be written in lowercase. # PCI device 0x1179:0x060f (orinoco_cs) #SUBSYSTEM=="net", DRIVERS=="?*", ATTRS{address}=="00:09:5b:3b:90:23", NAME="eth0"
This is because the naming convention offered by hostap_cs
is wifi0 and wlan0. The also meant a matching modification to the
/etc/network/interfaces
file.
# This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). # The loopback network interface auto lo iface lo inet loopback # The primary network interface # This will be used for the wired ethernet card, and the Netgear MA401 # with the orinoco_cs driver (uncomment auto eth0 line to use) #auto eth0 allow-hotplug eth0 iface eth0 inet dhcp wireless-mode managed wireless-power off wireless-ap 00:16:E6:3C:B2:4B wireless-essid hydrus wireless-key1 deadbeef00 # Netgear MA401 wireless card with hostap_cs driver auto wlan0 allow-hotplug wlan0 iface wlan0 inet dhcp # wireless-* options are implemented by the wireless-tools package wireless-mode managed wireless-ap 00:16:E6:3C:B2:4B wireless-essid hydrus wireless-key1 deadbeef00
Then I stopped networking, soft ejected the wireless card, removed
the orinoco_cs
module and re-inserted the card:
/etc/init.d/networking stop pccardctl eject modprobe -r orinoco_cs pccardctl insert
resulting in the following messages, and a working
hostap_cs
driven wireless card:
Apr 27 11:20:16 steel kernel: pccard: card ejected from slot 0 Apr 27 11:20:22 steel kernel: pccard: PCMCIA card inserted into slot 0 Apr 27 11:20:22 steel kernel: pcmcia: registering new device pcmcia0.0 Apr 27 11:20:22 steel kernel: hostap_cs: Registered netdevice wifi0 Apr 27 11:20:22 steel kernel: hostap_cs: index 0x01: , irq 3, io 0x0100-0x013f Apr 27 11:20:22 steel kernel: wifi0: NIC: id=0x800c v1.0.0 Apr 27 11:20:22 steel kernel: wifi0: PRI: id=0x15 v1.0.7 Apr 27 11:20:22 steel kernel: wifi0: STA: id=0x1f v1.3.6
The /etc/udev/rules.d/z25_persistent-net.rules
now looked like this:
# This file was automatically generated by the /lib/udev/write_net_rules # program, probably run by the persistent-net-generator.rules rules file. # # You can modify it, as long as you keep each rule on a single line. # MAC addresses must be written in lowercase. # PCI device 0x1179:0x060f (orinoco_cs) #SUBSYSTEM=="net", DRIVERS=="?*", ATTRS{address}=="00:09:5b:3b:90:23", NAME="eth 0" # PCI device 0x1179:0x060f (hostap_cs) SUBSYSTEM=="net", DRIVERS=="?*", ATTRS{address}=="00:09:5b:3b:90:23", ATTRS{type }=="1", NAME="wlan0"
Sadly, while the reset behaviour changed, it was not eliminated, as
this extract from /var/log/messages
shows:
Apr 27 11:26:58 steel kernel: ADDRCONF(NETDEV_CHANGE): wifi0: link becomes ready Apr 27 11:34:57 steel kernel: ADDRCONF(NETDEV_CHANGE): wifi0: link becomes ready Apr 27 11:43:56 steel kernel: ADDRCONF(NETDEV_CHANGE): wifi0: link becomes ready Apr 27 11:52:55 steel kernel: ADDRCONF(NETDEV_CHANGE): wifi0: link becomes ready
Well, I can't blame the orinoco_cs
driver for the problem.
So, the ADDRCONF message comes from IPV6 and, if my digging through the
code is to be believed, it a symptom not a cause, as it is invoked
as the result of some device change.
I started the process to rebuild the hostap_cs
module with
debugging turned on, following this recipe, now a little outdated, so
here's a summary:
make clean make mrproper # make dep is no longer required make menuconfig make SUBDIRS=drivers/net/wireless/hostap modules
However, on examining the code, I realised debugging was already
turned on, as was obvious once I looked at /var/log/debug
.
This log showed that the hostap_cs
driver was doing exactly
the same thing as the orinoco_cs
driver:
Apr 27 12:57:04 steel kernel: wifi0: LinkStatus=2 (Disconnected) Apr 27 12:57:04 steel kernel: wifi0: LinkStatus: BSSID=00:16:e6:3c:b2:4b Apr 27 12:57:06 steel kernel: wifi0: LinkStatus=1 (Connected) Apr 27 12:57:06 steel kernel: wifi0: LinkStatus: BSSID=00:16:e6:3c:b2:4b Apr 27 13:03:03 steel kernel: wifi0: LinkStatus=2 (Disconnected) Apr 27 13:03:03 steel kernel: wifi0: LinkStatus: BSSID=00:16:e6:3c:b2:4b Apr 27 13:03:05 steel kernel: wifi0: LinkStatus=1 (Connected) Apr 27 13:03:05 steel kernel: wifi0: LinkStatus: BSSID=00:16:e6:3c:b2:4b
Looking at the hostap
code, it seemed the only way this
LinkStatus message could appear was in response to a device
interrupt, since it was issued via a tasklet.
Hmm, maybe the problem was my wireless router. I tested this by using an old wireless access point, a Dlink 900AP+. When the Netgear card was associated with this - no resets. So the problem must either reside entirely within the wireless router, or in the combination of the Netgear card and the router.
At this point I gave up and used the ugly fix, adding the following
line to /etc/crontab
:
*/5 * * * * root ping -c 1 78.32.224.137 >/dev/null
which had the effect of pinging the router every five minutes, ensuring whatever timer was being triggered was reset before it fired.
Switching from a default DHCP-assigned IP address to static address (for
exposure to the evils of the Internet) was slightly more complicated
with the hostap_cs
driver. With the orinoco_cs
driver, I could get away with issuing ifconfig
commands.
With the hostap_cs
driver, this caused various errors:
Apr 27 18:08:35 steel kernel: wlan0: MAC port 0 enabling failed Apr 27 18:08:35 steel kernel: wlan0: could not enable MAC port Apr 27 18:12:09 steel kernel: CNFWEPFLAGS reading failed Apr 27 18:12:27 steel kernel: hostap_cs: Shutdown failed Apr 27 18:12:28 steel kernel: hostap_cs: Initialization failed Apr 27 18:12:31 steel kernel: wifi0: interrupt delivery does not seem to work Apr 27 18:12:33 steel kernel: wifi0: interrupt delivery does not seem to work Apr 27 18:13:20 steel kernel: hostap_cs: wifi0: resetting card Apr 27 18:17:10 steel kernel: hostap_cs: wifi0: resetting card
I therefore used the following script to convert from a DHCP address to a static IP:
/etc/init.d/networking stop # bring down interface; stop dhclient pccardctl eject cp /root/interfaces.static /etc/network/interfaces pccardctl insert cat << >/etc/resolv.conf # have to use external nameservers search hydrus.org.uk nameserver 195.74.113.58 nameserver 195.74.113.62 EOF /etc/init.d/networking start cp /root/interfaces.dhcp /etc/network/interfaces
The interfaces.static
and interfaces.dhcp
contain
different interface specifications for static and dhcp setup
respectively.