Category Archives: 802.11n

FreeBSD on the TP-Link TL-WR1043nd!

I've now included (almost) all of the support needed to run FreeBSD natively on the TP-Link TL-WR1043nd. It's a 3-antenna, 2x2 stream 2.4ghz 802.11n AP which you can get for under AUD $100.

It supports hostap mode (which is what I bet most of you want to use) and I'm currently using it at home alongside my Ubiquiti Routerstation Pro based hostap (which is what I use to test out all the other pre-11n and 11n NICs that I currently own.)

I currently get around 50mbit TCP throughput - but I leave full FreeBSD-HEAD debugging on. I'm sure I can push the unit closer to 100mbit. (Compare to the Routerstation Pro + AR9160 hostap - where I routinely get 160mbit of TCP throughput.)

What works (read: what I've tested):
  • Ethernet (at least the WAN port);
  • Wireless - 802.11bgn - 20/40mhz operation as well as legacy operation (and both, if that's what you need);
  • Serial console - if you've soldered in one.

The firmware image stores the configuration in a 64k flash partition which is read upon boot. You can modify files in /etc and then save these to flash via "cfg_save".

What isn't supported:
  • The onboard switch - so I believe the only port available at the present moment is the WLAN port;
  • The GPIO lines aren't being configured, so the WLAN, status and USB/QSS buttons don't function.
I haven't tested out Multi-SSID mode yet. The earlier AR9130 revisions have some issues with multi-SSID mode and handling block-ack tracking, so I _think_ I'll need to somehow disable aggregation on the second and later VAP interfaces. Just keep that in mind if you're tinkering.

Further details about the hardware and how to build the software for yourself can be found here in my FreeBSD wifi development project wiki.

No, I won't (yet) be putting up firmware images for people to test. Things are changing quite rapidly and there's no easy way to reflash a unit once you've placed FreeBSD on it - you'll need to have added a serial console to the device.

FreeBSD 802.11n update: 27 November 2011.

I've merged in most of the reset related fixes from my git tree into FreeBSD-HEAD. This means that normal resets (eg stuck beacon, calibration resets, etc) shouldn't drop frames any longer.

Frames are still dropped during things like channel/operation mode changes and channel scanning (which does do a channel change.) I'll have to look into that at a later stage. If you're using this in station mode you will likely need to disable background scanning or your aggregation sessions may occasionally drop. You'll have random messages logged when frames are dropping during a flush or reset, so just check your system dmesg log for anything from the ath driver.

I'll be next working on correctly handling failed/filtered frames and then adding some transition stuff to net80211 so the TIM/ATIM bitmaps can be kept correctly up to date. This should fix some of the power saving issues that I'm sure exist.

Unfortunately transmitting BAR frames is still quite a bit off. There's a lot more tidying up that I'd like to do before I start down the path of handling BAR TX, including trying to figure out how to better handle packet transmission and reception when the NIC is off-channel (eg when doing a background channel scan.)

I also have a long list of things I'd like to do to the rate control code and all the surrounding code which sets up rates and creates aggregates. The code I ported/wrote is a little too verbose and duplicate-y for me. That likely will occur after the christmas break.

Enjoy!

FreeBSD is now doing (even more) 802.11n..

I held off merging in my 802.11n work as much as possible but I decided that I'd like to get it done before the end of the year. Even though 9.0-RELEASE is still around the corner, I decided that it would be better to merge in what I have into -HEAD and then tidy that up then wait for what could be a few more months.

So, it's in there, bugs and all, supporting both station and hostap mode. No, wds, adhoc, mesh and TDMA aren't currently supported (I have enough bugs to worry about for the time being, without trying to debug the other operating modes. But I'd like to.)

What works:
  • TX and RX aggregation!
  • The rest of the 802.11n negotiation stuff, mostly thanks to Bernhard Schmidt who fixed up a lot of the net80211 quirks.
  • Lots of ANI changes which hopefully make noisy environments more stable.

What doesn't yet work:

  • Interface resets cause frames to be dropped from the RX and TX queues. This messes up aggregation and causes sessions to hang. I'm fixing that up in a git branch at the moment.
  • BAR TX - I'll implement BAR TX soon - it's just tricky to get right.
  • Filtered frames - ie, TX failed frames from the hardware. Instead of the current method of "always try", the hardware supports failing the current and subsequent frames in a set. That way a hostap seeing a station going into power saving mode can quickly abort all TX frames to said station and then only retransmit them when the station indicates it's again awake. If I don't do this then the hardware will constantly fail a lot of frames, causing BAR frames to be TXed when they likely shouldn't be.

But it's enough to try. So if you have an AR5416, AR9160, AR9220, AR9280, AR9285, AR9227 or AR9287, give it a whirl. If you have a pre-11n NIC then please, give it a go too. I'd like to ensure that the hardware support for earlier chipsets hasn't broken.

If you'd like to use this in production on a hostap then please keep in mind that power saving support isn't entirely functional and featured, so stations which go into frequent power saving mode may have some performance issues. I'll tinker with this some more soon.

Finally, thank you very much to Hobnob, Inc. for sponsoring this work and Qualcomm Atheros for providing me source code, documentation and assistance in understanding how all of this works.

Wireless update – 802.11n development

A few of us have been working towards 802.11n support in FreeBSD. Bernhard Schmidt and I were hoping to get 802.11n support up to scratch before 9.0-RELEASE but a combination of timing constraints and work constraints has hampered things somewhat.

But that said, we the net80211 support for 802.11n is in a lot better shape than it was in previous releases. Bernhard has been working out the kinks in the intel driver (if_iwn) and has 802.11n support mostly stable for those NICs. Someone else has been working on if_ral 802.11n support and has had quite a bit of success there. And I've been working on if_ath/ath_hal support.

(As a side-note, I've ordered some Marvell if_mwl compatible NICs to do some testing with.)

The 802.11n support in the FreeBSD atheros driver is already mostly usable for testing - 802.11n TX and RX works, but 802.11n TX aggregation doesn't work. So if you'd like to test it out in 9.0-RELEASE, you can do this:

* build a kernel with "options ATH_ENABLE_11N";
* ifconfig wlan0 -ampdutx
* associate as per normal to an 802.11n network.

Your download speeds will be good (as RX aggregation works) but as TX aggregation doesn't, you won't be getting full speed.

Now, as for the current work I'm doing. I've been porting over (and reimplementing in places) the 802.11n TX aggregation support, based on a combination of the atheros reference/carrier codebases and what's filtered through to the Linux ath9k driver.

In short - so far, so good. There's a lot to do, but basic TX aggregation is working in both station and hostap mode. My current test setup is:
  • A routerstation pro with an AR9160 NIC, running locally built firmware (FreeBSD) in hostap mode;
  • An EEEPC 701 retrofitted with an AR9280 NIC, running FreeBSD, as a station;
  • My macbook pro (broadcom 802.11n) as a station.
So far it's performing well - 200mbit TX/RX UDP in 5ghz HT/40 2x2 stream mode; and 130-140mbit TX/RX TCP.

I'm currently doing the work in a FreeBSD user svn branch. The details are in the Wiki - http://wiki.freebsd.org/AdrianChadd/AtherosTxAgg . I currently have exactly one tester (AR5416 STA, AR9280 hostap) who is reporting excellent success. I'd obviously like a few more. :)

There's still a lot of work to be done before this can be merged into HEAD. I'm sorry to say it won't happen before 9.0-RELEASE as there are some upcoming net80211 changes which will be rather intrusive and a bit risky to throw into the release at this late stage. It may also be difficult to backport as some changes will break kernel ABI.

But don't let anyone tell you FreeBSD doesn't support 802.11n. 9.0-RELEASE may not have much support, but all the key pieces are there. Once the release has been cut, I'll do some chasing up to get the Intel, Marvell and Ralink 802.11n support updated. (If someone would like to take charge of the broadcom NIC drivers, please drop freebsd-wireless@ a line.)

The next 6 months will be very interesting in the FreeBSD 802.11 world. :)

Finally, none of this current work would've been possible without the support of the sponsor paying me to get FreeBSD's net80211 and ath support updated - Hobnob, Inc. They contacted me a few months ago to help work out kinks in the Atheros NIC they're using in FreeBSD and seem impressed enough by my work to sponsor general net80211/ath improvements which they'll likely roll into future products. So when you're using Atheros 802.11n hardware in FreeBSD and getting that nice 140-150mbit TCP throughput, please give them thanks. :)

And finally finally, Qualcomm Atheros and the Linux ath9k developers have been instrumental in this work. The documentation, reference code and general interactive discussions have allowed me to get all of this work done in such a short period of time. (Yes, I did say "Atheros", "Documentation" and "Source Code" there, in the context of open source. Honest.)

Wireless update – DFS wrapup

Now that the DFS work has been completed, tested and paid for, I guess I can now write about it.

The DFS work was sponsored by KBC Networks, a wireless product company based in the USA. The eventual aim is to integrate this DFS work into their mesh product. I can't talk any further about what's going on there, except to say that they very graciously allowed the FreeBSD work to be released back to the community.

So FreeBSD now has:

  • Updated DFS master (hostap) and DFS slave (station) support in net80211;
  • Updated regulatory domain entries for the USS ("FCC3");
  • Changes to the ath(4) driver to fix corner cases in DFS master and DFS slave modes.
All of this work is now in FreeBSD-HEAD and will be available in FreeBSD-9.0.

Future work will hopefully include DFS IBSS and DFS mesh functionality. This work didn't include 802.11n DFS - but that's not too difficult to do (hint: if someone would like the mini-project, please contact me!)

Along with that was a port of the Atheros radar detection code (from Fusion, their earlier carrier codebase) which is currently proprietary. The Linux wireless developers have been working towards DFS compliance for a while, but haven't yet integrated working radar detection into any drivers. So this was a good exercise in uncharted territory to see how difficult it would be.

It turns out that it wasn't terribly difficult at all. After spending a bit of time chasing down missing bits in the FreeBSD atheros HAL driver, the third party doing said radar code porting managed to get FreeBSD doing radar detection at the same level as the commercial firmware.

During this particular exercise we discovered a few things about the software radar detection, which I think the community at large should know about.

The process of getting a device FCC/ETSI certified is just that - the whole device. This includes the NIC, the internal cabling, the enclosure, the antenna(s) and any external cabling. Maybe even whether it's indoors or outdoors, I wasn't involved in that. This likely has repercussions for any open source DFS implementation - although the DFS machinery in a specific FreeBSD release could be certified, the software based radar matching code may need tuning for the specific hardware used. So it's likely that Linux/FreeBSD can't just publish a single "ath_dfs" source module that will work for all Atheros NICs - or even a single NIC. It's likely that things will need tuning based on how a given NIC is used, the environment it's intending to be used in, and a variety of other things I haven't even thought about yet.

So if/when this does occur, the open source wireless community (FreeBSD, Linux, NetBSD, OpenBSD, DragonflyBSD, whatever..) will have to be responsible and not just simply run an "ath_dfs" radar module, assuming that it works. For complete, correct, certified behaviour, it's going to likely need the community to work with vendors and users in order to create "working, certified" combinations of hardware and software. So, if a vendor (call them U) wishes to release a new "SR-M" NIC, they could work with the open source wireless community to create a certified NIC+board+enclosure+antenna combination and publish a set of radar patterns and settings. They could leverage the proposed existing open source radar pattern matching code and simply add whatever configuration is needed. Users should then be responsible - they should only use the given radar dfs code with the correct setup. If they wish to run a modified setup, they should work with the vendor and upstream community to get things re-certified.

This way the DFS and radar pattern matching code is open source - what then changes is the radar patterns and configuration, which depends upon the NIC, cabling, antenna and environment.

For home users/developers, having a set of certified hardware combinations will make things easier for them.

For commercial vendors, if they adopt open-source FreeBSD or Linux on their platforms then (in an ideal world) they could get their equipment certified once (which as I note, they have to do anyway) and then publish the relevant radar patterns and configuration. The rest of the driver (including the radar pattern matching source and the general DFS support) would already be open source. Users can then use this when running their own kernel/distribution/OS on that platform.

I know this is all very fluffy and assumes that vendors/users act in a responsible, open manner. But I think this is what needs to occur if the open source community wishes to see stable, supported DFS regulatory compliance in their open source project.

To wrap this up, if you're a company wishing to leverage open source on their (Atheros) wireless platform and are interested in regulatory compliance, please drop me a line. I'll put you in contact with the relevant people inside Qualcomm Atheros to discuss how to best achieve this.

Implementing 11n TX aggregation, why it’s not so easy..

The only real missing bit from the initial 11n support for ath(4) in FreeBSD is now TX aggregation. This is also quite a tricky thing to do right, because (like everything related to these Atheros NICs) it's all done in software.

I'm about half way through the first part - implementing per-node, per-TID software queues. Since A-MPDU sessions are implemented using TIDs (although in net80211 they're linked to WME access classes (AC), hm!) traffic for each TID has to be individually managed.

The basic premise is quite simple. Frames are queued based on the destination node and TID. Non-QoS frames to a unicast destination (ie, a known station) go to the "non-QoS TID" (TID 16 in FreeBSD's net80211 stack.) Multicast frames go to the software-driven multicast/content-after-beacon (cabq) queue. Then a separate task handles de-queuing packets form these queues and queuing them to the hardware.

The reality however is a little more difficult than that.

Firstly, frames are queued from multiple contexts. The most obvious is the per-interface queue (ie wlanX). These may run in parallel and target the same hardware, so now I need to add locking to the per-node structure. Previously this wasn't (much) of a problem since the TX code simply directly dispatched to the hardware, and these queues are correctly locked. However now there's software-driven queues (which need new locks) along with some more per-node state. That all needs locking.

Next, the rate control code wasn't at all locked. I've begun wrapping them in per-node locks. Making sure I get this correct isn't easy.

Then there's the question of marking nodes and TIDs that have traffic to send. Right now that's done by adding each node to a linked list of "ready nodes". I then check all the TIDs for that node and dequeue what packets I have to. It's ugly code, but it works well enough for testing. I'll finish off implementing what ath9k and the Atheros reference code does (ie, maintaining both a "node" and "TID" linked list, so I can directly walk which TIDs need walking), but there's implications here for getting "QoS" right. (Ie, which order do you dequeue packets? How many do you dequeue from which queue in order for things to be "fair" ?) I'm going to leave all of these questions unanswered for now (as they're not handled in the current code anyway) and hope someone else steps up to it!

At this point I now have a mostly-clean (for values of "clean") implementation of per-node, per-TID software queues. I'm still in the process of tidying all of this up in preparation to commit to -HEAD before I begin the aggregation code. I'll cover that in a moment.

Then there's handling the aggregation session stuff.

Firstly, there's handling the ADDBA exchange (ie, establishing an A-MPDU session.) When this is done, any unicast traffic pending to that node/TID needs to be paused and kept around until the ADDBA request/response occurs. This is known as "pausing" the queue. I've a hack in place to do this and will implement a correct "pause" API soon to clean it up.

Next there's handling packets already queued to the hardware. This crept up on me without warning.

Firstly - a little background. The ADDBA exchange establishes the initial sequence number and window size to use as the "window" for subsequent data exchanges. After that, any packets being queued to the destination must fall within this window (typically say 64 sequence numbers long.) The window stays a fixed size, but the window itself slides along when TX packets are successfully completed. Since packets may be lost at any time (whether aggregate or not), the window doesn't move until the sequence numbers at the beginning of the window are successfully received.

So for example, say my window begins at "0", my window size is "4" and the station sends 4 packets with sequence numbers "0", "1", "2", "3". If I receive all four packets correctly and thus send back a block-ACK indicating this, the new window position will begin at "4". I can then send packets "4", "5", "6" and "7". I can't send "8", even if I have it in my queue.

But say the other end only received "0", "1" and "3". "2" wasn't received, so I have to retransmit it. I can only advance the window to "2". I can't advance it to "3", since I didn't receive "2". I could advance it to "1", but that'd be pointless as I've already received it. So in this instance, both the station and access point would advance the window position to "2" and the station would then retransmit "2". If it's coded correctly, it could transmit "2", "4", "5". It can't transmit "6", as that's outside the window size of 4 packets. It could just retransmit "2" if it wanted to and not the others. In fact, it could transmit "4", "5" and "2" - the receiver would then be responsible for re-ordering the packets and only passing them up to the network layer once all the packets in the correct order are available.

Finally, if I don't receive "2" (say I just can't seem to transmit it), the STA need to do a few things. It first has to pause the queue so no further packets are queued to the hardware. At this point, packets may be queued to the hardware, but they'll be for sequence numbers greater than "2" but still within the block-ack window. Once the hardware has finished completing packets (successfully or not), it needs to send a "BAR" frame to the access point to establish a new starting point for the sequence number window. In this instance it could set it to "3", but what if "3" was already in the hardware queue and was successfully transmitted? That would confuse the hell out of the other end. So it looks at the last successfully transmitted sequence number was, then sends the "BAR" with a starting sequence number 1 after that.

So, if "2" came back as having failed too many times, but "3" and "4" were in the hardware TX queue, the driver will pause the queue, wait for pending frames to complete, then look at what happened. If "3" and "4" were successfully transmitted, it would send a BAR with the sequence beginning at "5". If "3" was successfully transmitted but not "4", it would send a BAR with the sequence beginning at "4". But if "3" failed, and "4" didn't - it would set the BAR at "3" and then try retransmitting it. Finally (and this is another strange corner case I have to handle!) if "3" came back as having failed - and it failed too many times! - but "4" TX'ed ok, then I have to set the initial sequence number at "5" and send the BAR.

The other end (in this instance, the hostap) would then receive the BAR, set the new expected sequence number to be whatever was sent (say "5" in this instance), flush all pending packets in the reorder queue - even if there are missing packets (in the above example, "3" may be missing but "4" was received ok, so the receive stack would've been waiting for "3" to be received before sending it all up to the network layer!) and send back a block-ACK to the STA confirming the new window position.

Now (phew!) given all of that, you can see what kind of complicated stuff is needed to properly handle all corner cases when doing software (re)transmitting of packets. I haven't even begun to talk about how to handle sending and re-sending aggregate frames! All of the above needs to be implemented before I can do that.

So! The above is what I'm now working on. Once that's done, I'll work on handling what's known as "filtered frames" (and that'll be brain-dumped in a future blog post, but it has to do with handling power save stations correctly, or A-MPDU sessions will be torn down prematurely!) and then when THAT is all done and stable, I'll look at handling aggregates.

And when I handle aggregates correctly, we'll finally have fast 11n TX in FreeBSD. Then I can enable "ATH_ENABLE_11N" by default. :-)

AR9287 update

I finally gave in and whacked a FreeBSD-HEAD snapshot on my EEEPC so I can test the ath 802.11n code out with the various mini-PCIe NICs I have.ath0: mem 0xfbef0000-0xfbefffff irq 18 at device 0.0 on pci1ath0: [HT] enabling HT modesath0: [HT] 2 RX streams; 2 TX streamsath0: AR9287 mac 384.2 RF5133 phy 15.15.. andwlan0: flags=8843 metric 0 mtu 1500 ether b4:82:fe:33:95:53 inet 10.61.8.27 netmask 0xffffff00 broadcast 10.61.8.255 media: IEEE 802.11 Wireless Ethernet MCS mode 11ng status: associated ssid CACHEBOY_RS channel 1 (2412 MHz 11g ht/40+) bssid 00:1b:b1:58:f6:f0 regdomain ROW country AU indoor ecm authmode WPA2/802.11i privacy ON deftxkey UNDEF AES-CCM 2:128-bit AES-CCM 3:128-bit txpower 30 bmiss 7 scanvalid 450 bgscan bgscanintvl 300 bgscanidle 250 roam:rssi 7 roam:rate 64 protmode CTS -ampdu ampdulimit 32k ampdudensity 8 -amsdu shortgi wme burst roaming MANUAL(Yes, there's no TX aggregation support for now so I've disabled ampdu.)And:ADDR AID CHAN RATE RSSI IDLE TXSEQ RXSEQ CAPS FLAG00:1b:b1:58:f6:f0 1 1 216M 24.5 0 30271 30064 EPS AQEHTRS RSN HTCAP WPA WMEIt's happily sitting at MCS12 from my bedroom (which is what I expect given the noise on the 2.4ghz band where I live.)

AR9287 update

I finally gave in and whacked a FreeBSD-HEAD snapshot on my EEEPC so I can test the ath 802.11n code out with the various mini-PCIe NICs I have.

ath0: mem 0xfbef0000-0xfbefffff irq 18 at device 0.0 on pci1
ath0: [HT] enabling HT modes
ath0: [HT] 2 RX streams; 2 TX streams
ath0: AR9287 mac 384.2 RF5133 phy 15.15

.. and

wlan0: flags=8843 metric 0 mtu 1500
ether b4:82:fe:33:95:53
inet 10.61.8.27 netmask 0xffffff00 broadcast 10.61.8.255
media: IEEE 802.11 Wireless Ethernet MCS mode 11ng
status: associated
ssid CACHEBOY_RS channel 1 (2412 MHz 11g ht/40+) bssid 00:1b:b1:58:f6:f0
regdomain ROW country AU indoor ecm authmode WPA2/802.11i privacy ON
deftxkey UNDEF AES-CCM 2:128-bit AES-CCM 3:128-bit txpower 30 bmiss 7
scanvalid 450 bgscan bgscanintvl 300 bgscanidle 250 roam:rssi 7
roam:rate 64 protmode CTS -ampdu ampdulimit 32k ampdudensity 8 -amsdu
shortgi wme burst roaming MANUAL

(Yes, there's no TX aggregation support for now so I've disabled ampdu.)

And:

ADDR AID CHAN RATE RSSI IDLE TXSEQ RXSEQ CAPS FLAG
00:1b:b1:58:f6:f0 1 1 216M 24.5 0 30271 30064 EPS AQEHTRS RSN HTCAP WPA WME

It's happily sitting at MCS12 from my bedroom (which is what I expect given the noise on the 2.4ghz band where I live.)

AR9160 11n performance – finally!

I've made some good progress with the AR9160 802.11n hostap mode in FreeBSD.Firstly, the A-MPDU density setting needed tuning. "0" or "N/A" isn't appropriate for the AR9160 (and likely not appropriate for anything earlier than the AR9300/AR9400 series.) Once set to 8 microseconds, the number of A-MPDU retransmits dropped dramatically.I found that there was some missing code to do with disabling RIFS (reduced inter-frame spacing) RX on the AR9160 which I committed to FreeBSD-HEAD. This has eliminated all of the baseband lockups I've been seeing, rare as they were now.Then I found there were packets being dropped by if_arge on TX. It turns out the default TX/RX ring buffer size for if_arge was 128 packets - definitely not enough given the uncoupled interrupt/process driven forwarding engine in UNIX these days.The background: since NIC drivers aren't doing their work in an interrupt or shared process context, they only do their work when their TX/RX tasks get scheduled. Since they don't have any way to signal each other to "back off" via flow control when the queues are getting filled, it's quite possible to have a very busy device (in this instance wlan0 RX'ing anything more than around 100mbit) queue enough packets to the devices' TX queue faster than the TX task can be scheduled to process packets.Bumping if_arge's default TX/RX ring buffer size from 128 to 1024 did the trick - no more packet drops on TX.Now I'm getting ~ 105mbit TCP RX in HT/40 5GHz hostap mode (since A-MPDU RX is implemented and working) and ~ 210mbit UDP RX before I begin to drop packets. Anything more than 210mbit starts resulting in the infamous "stuck beacon", but that could be for a variety of reasons. I don't think I'm saturating the PCI bus (read: the CPU scheduler does show about 30% idle clock cycles during a UDP RX test) so there's something else to be blamed.Next is figuring out whether there's some scheduling issues with the device TX/RX tasks.I find it quite creepy that I can get ~ 100mbit of 802.11n throughput to my macbook pro whilst lying in bed. But that's what 802.11n is for, right? :)

AR9160 11n performance – finally!

I've made some good progress with the AR9160 802.11n hostap mode in FreeBSD.

Firstly, the A-MPDU density setting needed tuning. "0" or "N/A" isn't appropriate for the AR9160 (and likely not appropriate for anything earlier than the AR9300/AR9400 series.) Once set to 8 microseconds, the number of A-MPDU retransmits dropped dramatically.

I found that there was some missing code to do with disabling RIFS (reduced inter-frame spacing) RX on the AR9160 which I committed to FreeBSD-HEAD. This has eliminated all of the baseband lockups I've been seeing, rare as they were now.

Then I found there were packets being dropped by if_arge on TX. It turns out the default TX/RX ring buffer size for if_arge was 128 packets - definitely not enough given the uncoupled interrupt/process driven forwarding engine in UNIX these days.

The background: since NIC drivers aren't doing their work in an interrupt or shared process context, they only do their work when their TX/RX tasks get scheduled. Since they don't have any way to signal each other to "back off" via flow control when the queues are getting filled, it's quite possible to have a very busy device (in this instance wlan0 RX'ing anything more than around 100mbit) queue enough packets to the devices' TX queue faster than the TX task can be scheduled to process packets.

Bumping if_arge's default TX/RX ring buffer size from 128 to 1024 did the trick - no more packet drops on TX.

Now I'm getting ~ 105mbit TCP RX in HT/40 5GHz hostap mode (since A-MPDU RX is implemented and working) and ~ 210mbit UDP RX before I begin to drop packets. Anything more than 210mbit starts resulting in the infamous "stuck beacon", but that could be for a variety of reasons. I don't think I'm saturating the PCI bus (read: the CPU scheduler does show about 30% idle clock cycles during a UDP RX test) so there's something else to be blamed.

Next is figuring out whether there's some scheduling issues with the device TX/RX tasks.

I find it quite creepy that I can get ~ 100mbit of 802.11n throughput to my macbook pro whilst lying in bed. But that's what 802.11n is for, right? :)

FreeBSD-HEAD on the PB92 + AR9280

Here's FreeBSD-HEAD up on the Atheros PB92 reference board (AR7242), complete with an AR9280 mini-PCIe NIC.I'm still only getting around 70mbit in HT/40 mode TCP tests and 90mbit in HT/40 UDP mode; but it's only (currently) connected at 100mbit ethernet. I'll tinker some more with gigabit-connected stuff soon. I hope the UDP throughput maxes out above 100mbit.It's a far cry from where it should be throughput-wise, but it's getting there.Another developer has -HEAD + a small patch working on the Ubiquiti Rocket M5 (AR7240 + AR9280 on-board), which is also great progress.# dmesg | grep athath0: at device 0.0 on pci0ath0: [HT] enabling HT modesath0: [HT] 2 RX streams; 2 TX streamsath0: AR9280 mac 128.2 RF5133 phy 13.0# uname -a FreeBSD TEST_AP 9.0-CURRENT FreeBSD 9.0-CURRENT #19 r220911:221321M: Mon May 2 22:46:32 WST 2011 adrian@pcbsd-3114:/data/freebsd/mips/head/obj/mipseb/mips.mipseb/data/freebsd/mips/head/src/sys/PB92 mips# ifconfig wlan0 list staADDR AID CHAN RATE RSSI IDLE TXSEQ RXSEQ CAPS FLAG 00:15:6d:84:05:52 1 157 240M 15.5 120 27094 58288 EP AQHTR HTCAP WPA WME8c:7b:9d:d6:65:ba 2 157 270M 21.5 0 56040 64688 EP AQHTRS RSN HTCAP WME#

FreeBSD-HEAD on the PB92 + AR9280

Here's FreeBSD-HEAD up on the Atheros PB92 reference board (AR7242), complete with an AR9280 mini-PCIe NIC.

I'm still only getting around 70mbit in HT/40 mode TCP tests and 90mbit in HT/40 UDP mode; but it's only (currently) connected at 100mbit ethernet. I'll tinker some more with gigabit-connected stuff soon. I hope the UDP throughput maxes out above 100mbit.

It's a far cry from where it should be throughput-wise, but it's getting there.

Another developer has -HEAD + a small patch working on the Ubiquiti Rocket M5 (AR7240 + AR9280 on-board), which is also great progress.


# dmesg | grep ath

ath0: at device 0.0 on pci0
ath0: [HT] enabling HT modes
ath0: [HT] 2 RX streams; 2 TX streams
ath0: AR9280 mac 128.2 RF5133 phy 13.0
# uname -a
FreeBSD TEST_AP 9.0-CURRENT FreeBSD 9.0-CURRENT #19 r220911:221321M: Mon May 2 22:46:32 WST 2011 adria
n@pcbsd-3114:/data/freebsd/mips/head/obj/mipseb/mips.mipseb/data/freebsd/mips/head/src/sys/PB92 mips
# ifconfig wlan0 list sta
ADDR AID CHAN RATE RSSI IDLE TXSEQ RXSEQ CAPS FLAG
00:15:6d:84:05:52 1 157 240M 15.5 120 27094 58288 EP AQHTR HTCAP WPA WME
8c:7b:9d:d6:65:ba 2 157 270M 21.5 0 56040 64688 EP AQHTRS RSN HTCAP WME
#

AR913x support in -HEAD, or TP-Link WR-1043nd

In summary:KDB: debugger backends: ddbKDB: current backend: ddbCopyright (c) 1992-2011 The FreeBSD Project.Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 The Regents of the University of California. All rights reserved.FreeBSD is a registered trademark of The FreeBSD Foundation.FreeBSD 9.0-CURRENT #6 r220911:221160M: Thu Apr 28 20:09:28 WST 2011 adrian@pcbsd-3114:/data/freebsd/mips/head/obj/mipseb/mips.mipseb/data/freebsd/mips/head/src/sys/TP-WN1043ND mipsreal memory = 33554432 (32768K bytes)avail memory = 21123072 (20MB)nexus0: clock0: on nexus0Timecounter "MIPS32" frequency 200000000 Hz quality 800Event timer "MIPS32" frequency 200000000 Hz quality 800apb0 at irq 4 on nexus0uart0: <16550 or compatible> on apb0uart0: console (115200,n,8,1)ehci0: at mem 0x1b000100-0x1bffffff irq 1 on nexus0usbus0: set host controller modeusbus0: EHCI version 1.0usbus0: set host controller modeusbus0: on ehci0arge0: at mem 0x19000000-0x19000fff irq 2 on nexus0arge0: Overriding MAC from EEPROMarge0: Ethernet address: 94:0c:6d:fe:4f:20arge1: at mem 0x1a000000-0x1a000fff irq 3 on nexus0device_attach: arge1 attach returned 22ath0: at mem 0x180c0000-0x180effff irq 0 on nexus0ath0: eeprom @ 0x1fff1000ath0: eeprom data @ 0xbfff1000ath0: [HT] enabling HT modesath0: [HT] 2 RX streams; 2 TX streamsath0: AR9130 mac 20.1 RF2133 phy 10.2spi0: at mem 0x1f000000-0x1f00000f on nexus0spibus0: on spi0mx25l0: at cs 0 on spibus0mx25l0: s25sl064a, sector 65536 bytes, 128 sectorsar71xx_wdog0: on nexus0ar71xx_wdog0: Previous reset was due to watchdog timeoutTimecounters tick every 1.000 msecusbus0: 480Mbps High Speed USB v2.0md0.uzip: 855 x 16384 blocksugen0.1: at usbus0uhub0: on usbus0Root mount waiting for: usbus0uhub0: 1 port with 1 removable, self poweredRoot mount waiting for: usbus0ugen0.2: at usbus0umass0: on usbus0umass0: SCSI over Bulk-Only; quirks = 0x0000Root mount waiting for: usbus0umass0:0:0:-1: Attached to scbus0Trying to mount root from ufs:/dev/md0 []...da0 at umass-sim0 bus 0 scbus0 target 0 lun 0da0: Removable Direct Access SCSI-0 deviceda0: 40.000MB/s transfersda0: 3835MB (7856127 512 byte sectors: 255H 63S/T 489C)Mounting from ufs:/dev/md0 failed with error 22.Trying to mount root from ufs:/dev/md0.uzip []...warning: no time-of-day clock registered, system time will not be set accuratelybridge0: Ethernet address: 06:26:1a:6f:d5:e7wlan0: Ethernet address: 00:19:e0:66:66:68And the wireless:# ifconfig wlan0wlan0: flags=8943 metric 0 mtu 1500 ether 00:19:e0:66:66:68 inet6 fe80::219:e0ff:fe66:6668%wlan0 prefixlen 64 scopeid 0x6 nd6 options=21 media: IEEE 802.11 Wireless Ethernet autoselect mode 11ng status: running ssid CACHEBOY_RS channel 6 (2437 MHz 11g ht/40+) bssid 00:19:e0:66:66:68 regdomain ROW country AU ecm authmode WPA1+WPA2/802.11i privacy MIXED deftxkey 2 TKIP 2:128-bit txpower 30 scanvalid 60 protmode CTS -ampdutx ampdurx ampdulimit 64k -amsdu shortgi wme burst dtimperiod 1 -dfsI'll see about sneaking this into -HEAD soon.

AR913x support in -HEAD, or TP-Link WR-1043nd

In summary:

KDB: debugger backends: ddb
KDB: current backend: ddb
Copyright (c) 1992-2011 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
The Regents of the University of California. All rights reserved.
FreeBSD is a registered trademark of The FreeBSD Foundation.
FreeBSD 9.0-CURRENT #6 r220911:221160M: Thu Apr 28 20:09:28 WST 2011
adrian@pcbsd-3114:/data/freebsd/mips/head/obj/mipseb/mips.mipseb/data/freebsd/mips/head/src/sys/TP-WN1043ND mips
real memory = 33554432 (32768K bytes)
avail memory = 21123072 (20MB)
nexus0:
clock0: on nexus0
Timecounter "MIPS32" frequency 200000000 Hz quality 800
Event timer "MIPS32" frequency 200000000 Hz quality 800
apb0 at irq 4 on nexus0
uart0: <16550 or compatible> on apb0
uart0: console (115200,n,8,1)
ehci0: at mem 0x1b000100-0x1bffffff irq 1 on nexus0
usbus0: set host controller mode
usbus0: EHCI version 1.0
usbus0: set host controller mode
usbus0: on ehci0
arge0: at mem 0x19000000-0x19000fff irq 2 on nexus0
arge0: Overriding MAC from EEPROM
arge0: Ethernet address: 94:0c:6d:fe:4f:20
arge1: at mem 0x1a000000-0x1a000fff irq 3 on nexus0
device_attach: arge1 attach returned 22
ath0: at mem 0x180c0000-0x180effff irq 0 on nexus0
ath0: eeprom @ 0x1fff1000
ath0: eeprom data @ 0xbfff1000
ath0: [HT] enabling HT modes
ath0: [HT] 2 RX streams; 2 TX streams
ath0: AR9130 mac 20.1 RF2133 phy 10.2
spi0: at mem 0x1f000000-0x1f00000f on nexus0
spibus0: on spi0
mx25l0: at cs 0 on spibus0
mx25l0: s25sl064a, sector 65536 bytes, 128 sectors
ar71xx_wdog0: on nexus0
ar71xx_wdog0: Previous reset was due to watchdog timeout
Timecounters tick every 1.000 msec
usbus0: 480Mbps High Speed USB v2.0
md0.uzip: 855 x 16384 blocks
ugen0.1: at usbus0
uhub0: on usbus0
Root mount waiting for: usbus0
uhub0: 1 port with 1 removable, self powered
Root mount waiting for: usbus0
ugen0.2: at usbus0
umass0: on usbus0
umass0: SCSI over Bulk-Only; quirks = 0x0000
Root mount waiting for: usbus0
umass0:0:0:-1: Attached to scbus0
Trying to mount root from ufs:/dev/md0 []...
da0 at umass-sim0 bus 0 scbus0 target 0 lun 0
da0: Removable Direct Access SCSI-0 device
da0: 40.000MB/s transfers
da0: 3835MB (7856127 512 byte sectors: 255H 63S/T 489C)
Mounting from ufs:/dev/md0 failed with error 22.
Trying to mount root from ufs:/dev/md0.uzip []...
warning: no time-of-day clock registered, system time will not be set accurately
bridge0: Ethernet address: 06:26:1a:6f:d5:e7
wlan0: Ethernet address: 00:19:e0:66:66:68


And the wireless:

# ifconfig wlan0
wlan0: flags=8943 metric 0 mtu 1500
ether 00:19:e0:66:66:68
inet6 fe80::219:e0ff:fe66:6668%wlan0 prefixlen 64 scopeid 0x6
nd6 options=21
media: IEEE 802.11 Wireless Ethernet autoselect mode 11ng
status: running
ssid CACHEBOY_RS channel 6 (2437 MHz 11g ht/40+) bssid 00:19:e0:66:66:68
regdomain ROW country AU ecm authmode WPA1+WPA2/802.11i privacy MIXED
deftxkey 2 TKIP 2:128-bit txpower 30 scanvalid 60 protmode CTS
-ampdutx ampdurx ampdulimit 64k -amsdu shortgi wme burst dtimperiod 1
-dfs

I'll see about sneaking this into -HEAD soon.

11n TX and RX experiments..

My experiments so far are as follows (all in 5GHz mode - 2GHz is just too busy in my apartment complex):
  • FreeBSD <-> FreeBSD 11n is stable on the AR9160 and AR9220. TX aggregation is disabled, so it reaches around 35-40mbit in HT/20 and 45mbit in HT/40 mode. I'm getting MCS13 between an AP and STA which are in different rooms in my apartment. MCS15 is achievable if the units are close to each other.
  • Short-GI in 40MHz works fine.
  • When RX aggregation is enabled, and IEEE80211_AMPDU_AGE is enabled with net.wlan.ampdu_age set to 5 (it defaults to 500), I get ~ 55mbit RX in HT/20 and ~ 75mbit RX in HT/40 mode. There's problems with out of order packets that are appearing -before- the calculated block-ack window and net80211 is dropping those. I'll investigate why at some point.
  • FreeBSD works fine as an 11n AP, obviously with A-MPDU TX disabled.
There's lots of stuff that needs to be tested at this point, including:
  • 2GHz operation, obviously!
  • 11n and legacy co-operation.
  • Other chipsets - AR5416, AR9280, AR9285.
  • Behaviour in the presence of noise, busy channel, etc.
  • Make sure that HT/40 mode is -correctly- protecting frames on both channels and is correctly waiting to make sure both channels are free before transmitting!
And stuff that needs to be implemented before we enable it by default:
  • A-MPDU TX aggregation, for STA, AP, Mesh and adhoc modes - this one is really needed and is going to take some time to do.
  • HT RTS frame protection - I have code for this which I'll commit soon.

11n TX and RX experiments..

My experiments so far are as follows (all in 5GHz mode - 2GHz is just too busy in my apartment complex):
  • FreeBSD <-> FreeBSD 11n is stable on the AR9160 and AR9220. TX aggregation is disabled, so it reaches around 35-40mbit in HT/20 and 45mbit in HT/40 mode. I'm getting MCS13 between an AP and STA which are in different rooms in my apartment. MCS15 is achievable if the units are close to each other.
  • Short-GI in 40MHz works fine.
  • When RX aggregation is enabled, and IEEE80211_AMPDU_AGE is enabled with net.wlan.ampdu_age set to 5 (it defaults to 500), I get ~ 55mbit RX in HT/20 and ~ 75mbit RX in HT/40 mode. There's problems with out of order packets that are appearing -before- the calculated block-ack window and net80211 is dropping those. I'll investigate why at some point.
  • FreeBSD works fine as an 11n AP, obviously with A-MPDU TX disabled.
There's lots of stuff that needs to be tested at this point, including:
  • 2GHz operation, obviously!
  • 11n and legacy co-operation.
  • Other chipsets - AR5416, AR9280, AR9285.
  • Behaviour in the presence of noise, busy channel, etc.
  • Make sure that HT/40 mode is -correctly- protecting frames on both channels and is correctly waiting to make sure both channels are free before transmitting!
And stuff that needs to be implemented before we enable it by default:
  • A-MPDU TX aggregation, for STA, AP, Mesh and adhoc modes - this one is really needed and is going to take some time to do.
  • HT RTS frame protection - I have code for this which I'll commit soon.

(More) wireless hackery

So instead of doing what I should be doing, I did some more wifi hackery.
The short summary version (all 802.11g 2.4ghz testing):
  • AR5416 TX is still unhappy and unpredictable. It's also like that with ath9k. AR5416 RX is perfectly fine.
  • AR9160 TX/RX is fine.
  • AR9220 (Ubiquiti SR71-12 and Ubiquiti-SR71-15) TX/RX is now fine.
  • AR9280 closed and open-loop TX is fine, RX is also fine.
  • AR9285 TX/RX is fine and stable now.
I'll now go and test out 5GHz AP/STA modes with the above (where appropriate) and see how they behave. I hope they'll be just as stable now.
Bernard has been making inroads into fleshing out the missing parts of the net80211 802.11n support. Many thanks to him for taking the time to dissect the 802.11n spec, the Linux 802.11 stack and spend time with some APs determining what they're doing.

(More) wireless hackery

So instead of doing what I should be doing, I did some more wifi hackery.

The short summary version (all 802.11g 2.4ghz testing):
  • AR5416 TX is still unhappy and unpredictable. It's also like that with ath9k. AR5416 RX is perfectly fine.
  • AR9160 TX/RX is fine.
  • AR9220 (Ubiquiti SR71-12 and Ubiquiti-SR71-15) TX/RX is now fine.
  • AR9280 closed and open-loop TX is fine, RX is also fine.
  • AR9285 TX/RX is fine and stable now.
I'll now go and test out 5GHz AP/STA modes with the above (where appropriate) and see how they behave. I hope they'll be just as stable now.

Bernard has been making inroads into fleshing out the missing parts of the net80211 802.11n support. Many thanks to him for taking the time to dissect the 802.11n spec, the Linux 802.11 stack and spend time with some APs determining what they're doing.