Fake SNRs

With the addition of per-link signal levels that I added over the weekend, my wmediumd fork leveled up from “mere curiosity” to “potentially useful someday.” For the case of mesh, this means you can use signal levels to inform how HWMP will create the mesh paths.

For example, as a test I was able to validate this fix, by setting up a virtual 4-node mesh with a bad path and a good path. With the patch reverted, the bad path was almost always selected due to its PREQs being received at the target first. [In actuality, this test will exhibit frequent path swapping because the order in which the PREQs are received is essentially random, a finding in “Experimental evaluation of two open source solutions for wireless mesh routing at layer two” by Garroppo et al. Wmediumd doesn’t show this yet because frames are mostly received and queued in-order. At the time of the patch, I validated it in an actual 15-node mesh.]

There are still a couple of things that would be nice to have here. Today, we base the decision on whether a multicast frame is received by the signal level from the transmitter to us and the multicast rate. However, this means that with a low multicast rate, there is basically zero frame loss. In real life, loss happens much more frequently, and so we cannot test the effects of lost path request frames in wmediumd, which is the subject of at least one pending HWMP patch. Another problem is that the current setup works only with static setups; we might be interested in what happens with mobile nodes, for example. For that we’d need to be able to change the signal level periodically; how to easily specify that is a bit of a question mark.

tmux + wmediumd

Wmediumd gained the ability to do a simple contention simulation a while ago. It turned out to be a small change to the existing code: just ensure that any new frames are scheduled after any other queued frames of equal or higher priority from any other station.

Assuming the simulation is accurate, we might use this to gather some information about different kinds of wireless network topologies. For example: what is the throughput and latency like for a mesh network, as a function of hops?

The one sticking point is that it’s a bit of a pain to set up a bunch of mesh nodes with hwsim with their own IPs and routing tables. I’ve previously scripted this with send-to-self routing, but it’s a bit ugly. So I looked into doing this with network namespaces and controlling it all with tmux. The result is this fairly minimal script to launch a number of mesh nodes in a linear toplogy. From there one can easily run ping and iperf to gather some data, as in this chart:

This image shows the result, and is in line with measurements that Javier Cardona had done on actual hardware. We can see that throughput is roughly inversely proportional to the number of nodes, while latency is directly proportional.

This may seem pretty bad at first, but makes sense when you consider that a radio transceiver can only listen or talk at once — it is all about radio physics, nothing to do with mesh specifically (which is not to say that mesh has no inefficiencies). Also this level of performance is when all the nodes are in range of each other; in such a case you’d be unlikely to have so many hops because the nodes would instead just peer directly with each other. So we might design our networks to avoid many hops, reduce the number of nodes in a given interference area, use fancy phy algorithms to enhance spatial reuse, or use multiple channels.

My plan with wmediumd is to use it in a bit more automated fashion to evaluate things like changes to HWMP — I think if we can identify topologies that people care about then it’s a bit stronger to say “this change always makes things better” if we can show repeatable before-and-after results from wmediumd.

Weekend updates

More updates to speccy pushed to github this weekend. It gained the ability to toggle on-and-off line and scatter plots. Also, it now takes care of enabling spectral scan and then scanning channels (by exec()-ing iw, naughty me) so you can just tell it the device and it does the rest. Code is still ugly but gradually taking shape. There’s an animated gif for those that want to see what it currently looks like in operation.

I settled on (somewhat inefficiently) smoothing the line graph with a centered moving average using a 5-sample window length, which met the strict theoretical basis of “it looked kind of right.” I did not yet incorporate the time-based plot I was playing with.

It could certainly be faster. Profiling shows that the vast majority of time is spent drawing 9-pixel rectangles in Cairo. I suppose that even if Cairo was using an accelerated backend, which I don’t believe it is in my case, that this would be something more efficiently done by rendering to a client pixmap anyway. Lots of low-hanging fruit everywhere, but I’m resisting the urge to really optimize anything at this early stage.

Nicer serialAlso yesterday I finally cleaned up the somewhat messy serial port installation on one of my ath10k routers with the help of a drill. These cheap cables work well but do require a bit of attention with the glue gun — I find the plastic case around the USB port / converter board is always coming un-snapped and falling off otherwise.

time vs frequency

This is roughly what I had in mind for the time/frequency plot for my little spectrum visualizer. Time is on the y-axis and frequency on the x-axis. There are some interesting artifacts here, especially on the higher channels. Probably bugs in my implementation, but we’ll see as I develop it further.

Speccy with labels

I messed around with “speccy” a bit today to see what I could do with it to make it look slightly nicer. It really needed a grid so one can more easily see the frequencies and power levels. So now it looks like this:

(This is with iperf running on channel 6 to a nearby AP).

I have in mind a couple of other visualizations. An obvious one is to show the overall max or average power level rather than a scatter plot. This would be a cleaner display, although there could be co-channel interference sources you wouldn’t see that way. Here’s a first cut at that:

I am doing some averaging for multiple (~8) samples with the same subcarrier frequency, but clearly more smoothing is needed. Also I notice that I occasionally get some artifact where all the subcarriers have the exact same power level. Not sure what that is, but it wants filtering.

Another interesting visualization would be a scrolling chart of frequency vs time, with power level indicated by pixel intensity. Then you could get an idea of historical changes in the medium. (Oh hey, the neighbors are watching Netflix now.)

The code is still an ugly pile of hacks, which it will probably continue to be until I decide just what kind of processing needs doing on the raw samples. Sorry for that.

VHT mesh

…is a thing now.

# iw dev
phy#0
    Interface wlan0
		ifindex 4
		wdev 0x1
		addr 30:b5:c2:fb:34:d8
		type mesh point
		channel 149 (5745 MHz), width: 80 MHz, center1: 5775 MHz

# iperf -c 192.168.1.20
------------------------------------------------------------
Client connecting to 192.168.1.20, TCP port 5001
TCP window size: 43.8 KByte (default)
------------------------------------------------------------
[  3] local 192.168.1.21 port 34175 connected with 192.168.1.20 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   148 MBytes   124 Mbits/sec

DWM-W034 UART

In response to my previous post about UART access on the Alfa AWUS036NHA, I got a nice email from Jim Ewing about the DWM-W034, an ath9k_htc device that apparently is embedded inside HDTVs and readily available for $10. He found the TX/RX pins on the board, and it looks like it would be a bit easier to put a socket on one of these compared to the Alfa since there are no pesky chips nearby.

With his permission, and so that this information doesn’t get lost to the sands of time, here’s the pic he sent me. Enjoy!

Reserialized

I got a shiny new device today and the first thing I did was crack it open and heat it to 680 degrees. A good feeling.

The device in question is an ath9k_htc USB wifi dongle. A colleague suggested this one has an easy to access UART because they brought out the TX/RX pins out from the SoC to dedicated pads. He and I apparently have different definitions for “easy.” Unlike the TP-Link routers which give you through-holes to work with, these are simply SMT pads, and they are tiny in comparison. My soldering iron tip is at least double the size of the pad. Yes, it is somewhat better than trying to solder directly to the pins on the SoC, but not by a whole lot.

As it happens, this is my first attempt at soldering SMT. What could go wrong?

Because the pads are small I used some wire-wrap wire (30 gauge? All I know is that it’s at least two stops smaller than the smallest hole on my wire stripper: getting insulation off was “fun”). During my comedic attempts at getting the wires stuck in the right places, I managed to completely obliterate one of the two pads. Luckily, the one I screwed up was the RX pin, which I don’t really need or care about. Having got the TX and ground wires (badly) soldered in place, I made a some circumspect passes with the magnifying glass and continuity tester to convince myself there were no shorts.

Even so, I am as surprised as you are that it actually worked when I turned it on the first time. And the wifi still works too.

==>[cUSB_REQ_COMP]: 0x%08x
VendorCmd: DownloadComplete!
5. usb only!!
 A_WDT_INIT()
 ==>warm start<==
ALLOCRAM start 0x50d80c size 106484
Enable Tx Stream mode: 0x367
USB mode: 0xf
[+++Magpie_init]
[+++VBUF_init(100)]
[+++VBUF_init(100)]
: Attaching the driver
: Vendor id 0x168c Dev id 0x24
ath_pci_probe 24
 ath_hal = 0x00510928 

        =>[dnQ] 0x0050f288 
[       =>[upQ] 0x0050f264 
[       =>[hp dnQ] 0x0050f240 
[       =>[mp dnQ] 0x0050f21c 
[Tgt running]

mesh on ath10k

I’ve had my ath10k AP (TP-Link Archer C7 v2) since last October or so, with the goal of having a VHT-capable device with which to test (currently non-existent) VHT mesh. Unfortunately, for nearly all of that time, I’ve been stuck on a firmware crash shortly after bringing up the device. Not that I’ve spent a whole lot of time on it, but there’s only so much one can do when getting to the point of “firmware crashes and it has something to do with peers but that’s all I know and I don’t have the time, tools, or code to dig deeper.”

I think there’s some variant on rubber duck debugging where you complain publicly about some issue, and doing that makes you think about it more, and then the way forward is magically revealed. That, plus some helpful hints from the residents of the ath10k ML, got me over the hump, so now it works!

Next up, finding a spare mini PCIe slot for the other ath10k device I have, and getting the VHT bits done…

On Reddit

My lowly internet outpost wound up at the top of /r/programming on Reddit over Easter weekend due to my silly goto-in-bash hack. It turns out that that one page is probably the most searched-for out of anything on my website. There are a lot of frustrated shell programmers out there.

Regarding the critiques from the discussion, comments of the form “you’ve an X/Y problem” were least interesting to me. Yes, I know about Makefiles. Sometimes it is fun to do something different, which is known to be far from a best practice, just because one can.

Comments that improved my sed syntax, or provided a historical context, were most interesting. For the record: no, I didn’t intend to use branching in sed as a self-referential nod to the topic du jour, but I like pretending that I was that clever instead of the reality, which is that I just didn’t know the right sed magic. So, I’ll keep the branching.

See if you can spot the traffic spike: