Nov 282019
 

This is more of a brain dump for yours truly, since as a day job, I’m dealing with OpenThread a lot, and so there’s lots of little tricks out there for building it on various platforms and configurations. The following is not so much a how-to guide, but a quick brain dump of different things I’ve learned over the past year or so of messing with OpenThread.

Verbose builds

To get a print out of every invocation of the toolchain with all flags, specify V=1 on the call to make:

$ make -f examples/Makefile-${PLATFORM} …${ARGS}… V=1

Running one step at a time

To disable the parallel builds when debugging the build system, append BuildJobs=1 to your make call:

$ make -f examples/Makefile-${PLATFORM} …${ARGS}… BuildJobs=1

Building a border router NCP image

General case

$ make -f examples/Makefile-${PLATFORM} …${ARGS}… BORDER_AGENT=1 BORDER_ROUTER=1 COMMISSIONER=1 UDP_FORWARD=1

For TI CC2538

# Normal CC2538 (e.g. Zolertia Firefly)
$ make -f examples/Makefile-cc2538 BORDER_AGENT=1 BORDER_ROUTER=1 COMMISSIONER=1 UDP_FORWARD=1

# CC2538 + CC2592
$ make -f examples/Makefile-cc2538 BORDER_AGENT=1 BORDER_ROUTER=1 COMMISSIONER=1 UDP_FORWARD=1 CC2592=1

If you want to run the latter image on a WideSky Hub, you’ll need to edit examples/platform/cc2538/uart.c and comment out line 117 before compiling as it uses a simple diode for 5V to 3.3V level shifting, and this requires the internal pull-up to be enabled:

115     // rx pin
116     HWREG(IOC_UARTRXD_UART0) = IOC_PAD_IN_SEL_PA0;
117     HWREG(IOC_PA0_OVER)      = IOC_OVERRIDE_DIS; // ← comment out this to allow UART RX to work
118     HWREG(GPIO_A_BASE + GPIO_O_AFSEL) |= GPIO_PIN_0;

For Nordic nRF52840

# Nordic development board (PCA10056) via J2 (near battery)
$ make -f examples/Makefile-nrf52840 BORDER_AGENT=1 BORDER_ROUTER=1 COMMISSIONER=1 UDP_FORWARD=1

# Ditto, but instead using J3 (near middle of bottom edge)
$ make -f examples/Makefile-nrf52840 BORDER_AGENT=1 BORDER_ROUTER=1 COMMISSIONER=1 UDP_FORWARD=1 USB=1

# Nordic dongle (PCA10059)
$ make -f examples/Makefile-nrf52840 BORDER_AGENT=1 BORDER_ROUTER=1 COMMISSIONER=1 UDP_FORWARD=1 USB=1 BOOTLOADER=USB

I’m working on what needs to be done for the Fanstel BT840X… watch this space.

Building certification test images

For CC2538

$ make -f examples/Makefile-cc2538 BORDER_ROUTER=1 COMMISSIONER=1 DHCP6_CLIENT=1 JOINER=1
Nov 242019
 

The past few months have been quiet for this project, largely because Brisbane WICEN has had my spare time soaked up with an RFID system they are developing for tracking horse rides through the Imbil State Forest for the Stirling’s Crossing Endurance Club.

Ultimately, when we have some decent successes, I’ll probably be reporting more on this on WICEN’s website. Suffice to say, it’s very much a work-in-progress, but it has proved a valuable testing ground for aioax25. The messaging system being used is basically just plain APRS messaging, with digipeating thrown in as well.

Since I’ve had a moment to breathe, I’ve started filling out the features in aioax25, starting with connected-mode operation. The thinking is this might be useful for sending larger payloads. APRS messages are limited to a 63 character message size with only a subset of ASCII being permitted.

Thankfully that subset includes all of the Base64 character set, so I’m able to do things like tunnel NTP packets and CBOR blobs through it, so that stations out in the field can pull down configuration settings and the current time.

As for the RFID EPCs, we’re sending those in the canonical hexadecimal format, which works, but the EPC occupies most of the payload size. At 1200 bits per second, this does slow things down quite a bit. We get a slight improvement if we encode the EPCs as Base64. We’d get a 200% efficiency increase if we could send it as binary bytes instead. Sending a CBOR blob that way would be very efficient.

The thinking is that the nodes find each-other via APRS, then once they’ve discovered a path, they can switch to connected mode to send bulk transfers back to base.

Thus, I’ve been digging into connected mode operation. AX.25 2.2 is not the most well-written spec I’ve read. In fact, it is down-right confusing in places. It mixes up little-endian and big-endian fields, certain bits have different meanings in different contexts, and it uses concepts which are “foreign” to someone like myself who’s used to TCP/IP.

Right now I’m making progress, there’s an untested implementation in the connected-mode branch. I’m writing unit test cases based on what I understand the behaviour to be, but somehow I think this is going to need trials with some actual AX.25 implementations such as Direwolf, the Linux kernel stack, G8BPQ stack and the implementation on my Kantronics KPC3 and my Kenwood TH-D72A.

Some things I’m trying to get an answer to:

  • In the address fields at the start of a frame, you have what I’ve been calling the ch bit.
    On digipeater addresses, it’s called H and it is used to indicate that a frame has been digipeated by that digipeater.
    When seen in the source or destination addresses, it is called C, and it describes whether the frame is a “command” frame, or a “response” frame.

    An AX.25 2.x “command” frame sets the destination address’s C bit to 1, and the source address’s C bit to 0, whilst a “response” frame in AX.25 does the opposite (destination C is 0, source C is 1).

    In prior AX.25 versions, they were set identically. Question is, which is which? Is a frame a “command” when both bits are set to 1s and a “response” if both C bits are 0s? (Thankfully, I think my chances of meeting an AX.25 1.x station are very small!)
  • In the Control field, there’s a bit marked P/F (for Poll/Final), and I’ve called it pf in my code. Sometimes this field gets called “Poll”, sometimes it gets called “Final”. It’s not clear on what occasions it gets called “Poll” and when it is called “Final”. It isn’t as simple as assuming that pf=1 means poll and pf=0 means final. Which is which? Who knows?
  • AX.25 2.0 allowed up to 8 digipeaters, but AX.25 2.2 limits it to 2. AX.25 2.2 is supposed to be backward compatible, so what happens when it receives a frame from a digipeater that is more than 2 digipeater hops away? (I’m basically pretending the limitation doesn’t exist right now, so aioax25 will handle 8 digipeaters in AX.25 2.2 mode)
  • The table of PID values (figure 3.2 in the AX.25 2.2 spec) mentions several protocols, including “Link Quality Protocol”. What is that, and where is the spec for it?
  • Is there an “experimental” PID that can be used that says “this is a L3 protocol that is a work in progress” so I don’t blow up someone’s station with traffic they can’t understand? The spec says contact the ARRL, which I have done, we’ll see where that gets me.
  • What do APRS stations do with a PID they don’t recognise? (Hopefully ignore it!)

Right at this point, the Direwolf sources have proven quite handy. Already I am now aware of a potential gotcha with the AX.25 2.0 implementation on the Kantronics KPC3+ and the Kenwood TM-D710.

I suspect my hand-held (Kenwood TH-D72A) might do the same thing as the TM-D710, but given JVC-Kenwood have pulled out of the Australian market, I’m more like to just say F### you Kenwood and ignore the problem since these can do KISS mode, bypassing the buggy AX.25 implementation on a potentially resource-constrained device.

NET/ROM is going to be a whole different ball-game, and yes, that’s on the road map. Long-term, I’d like 6LoWHAM stations to be able to co-exist peacefully with other stations. Much like you can connect to a NET/ROM node using traditional AX.25, then issue connect commands to jump from there to any AX.25 or NET/ROM station; I intend to offer the same “feature” on a 6LoWHAM station — you’ll be able to spin up a service that accepts AX.25 and NET/ROM connections, and allows you to hit any AX.25, NET/ROM or 6LoWHAM station.

I might park the project for a bit, and get back onto the WICEN stuff, as what we have in aioax25 is doing okay, and there’s lots of work to be done on the base software that’ll keep me busy right up to when the horse rides re-start in 2020.

Oct 252019
 

In my last post, I mentioned that I was playing around with SDR a bit more, having bought a couple. Now, my experiments to date were low-hanging fruit: use some off-the-shelf software to receive an existing signal.

One of those off-the-shelf packages was CubicSDR, which gives me AM/FM/SSB/WFM reception, the other is qt-dab which receives DAB+. The long-term goal though is to be able to use GNURadio to make my own tools. Notably, I’d like to set up a Raspberry Pi 3 with a DRAWS board and a RTL-SDR, to control the FT-857D and implement dual-watch for emergency comms exercises, or use the RTL-SDR for DAB+ reception.

In the latter case, while I could use qt-dab, it’ll be rather cumbersome in that use case. So I’ll probably implement my own tool atop GNURadio that can talk to a small microcontroller to drive a keypad and display. As a first step, I thought I’d try a DIY FM stereo receiver. This is a mildly complex receiver that builds on what I learned at university many moons ago.

FM Stereo is actually surprisingly complex. Not DAB+ levels of complex, but still complex. The system is designed to be backward-compatible with mono FM sets. FM itself actually does not provide stereo on its own — a stereo FM station operates by multiplexing a “mono” signal, a “differential” signal, and a pilot signal. The pilot is just a plain 19kHz carrier. Both left and right channels are low-pass filtered to a band-width of 15kHz. The mono signal is generated from the summation of the left and right channels, whilst the differential is produced from the subtraction of the right from the left channel.

The pilot signal is then doubled and used as the carrier for a double-sideband suppressed carrier signal which is modulated by the differential signal. This is summed with the pilot and mono signal, and that is then frequency-modulated.

For reception, older mono sets just low-pass the raw FM discriminator output (or rely on the fact that most speakers won’t reproduce >18kHz well), whilst a stereo set performs the necessary signal processing to extract the left and right channels.

Below, is a flow-graph in GNURadio companion that shows this:

Flow graph for FM stereo reception

The signal comes in at the top-left via a RTL-SDR. We first low-pass filter it to receive just the station we want (in this case I’m receiving Triple M Brisbane at 104.5MHz). We then pass it through the WBFM de-modulator. At this point I pass a copy of this signal to a waterfall plot. A second copy gets low-passed at 15kHz and down-sampled to a 32kHz sample rate (my sound card doesn’t do 500kHz sample rates!).

A third copy is passed through a band-pass filter to isolate the differential signal, and a fourth, is filtered to isolate the pilot at 19kHz.

The pilot in a real receiver would ordinarily be full-wave-bridge-rectified, or passed through a PLL frequency synthesizer to generate a 38kHz carrier. Here, I used the abs math function, then band-passed it again to get a nice clean 38kHz carrier. This is then mixed with the differential signal I isolated before, then the result low-pass filtered to shift that differential signal to base band.

I now have the necessary signals to construct the two channels: M + D gives us (L+R) + (L-R) = 2L, and M – D = (L+R) – (L – R) = 2R. We have our stereo channels.

Below are the three waterfall diagrams showing (from top to bottom) the de-modulated differential signal, the 38kHz carrier for the differential signal and the raw output from the WBFM discriminator.

The constituent components of a FM stereo radio station.

Not decoded here is the RDS carrier which can be seen just above the differential signal in the third waterfall diagram.

Oct 122019
 

Recently, I’ve been doing a lot of work with 6LoWPAN on the 2.4GHz band. I didn’t have anything that would receive arbitrary signals on this frequency, so I decided to splurge. I got myself my first bit of tax-deductible amateur radio equipment: a HackRF One.

It’s been handy, fire up CubicSDR, and immediately you get a picture of what’s happening on the frequency. In the future I hope to get the WIME framework working so I can decode the 802.15.4 frames and pipe them to Wireshark, but so far, this has been handy.

Since I’m not using it every day, I also put it to a second use, DAB+ reception. I used to listen to various stations a lot, and whilst FM stereo is built into my phone, I’ve got nothing that will do medium-wave AM. The HackRF stops short at 1MHz (officially 10MHz), and needs a suitable antenna to do so. However, it occurred to me that it was more than capable of doing DAB+, so after some experimentation, I managed to get qt-dab working.

Since getting that working, I bought a second SDR, a RTL-SDR v3. The idea is I’d be setting this up on the bicycle with a Raspberry Pi 3 which also has a DRAWS board fitted (the successor to the UDRC). I figured I could use this as a second receiver for amateur radio stuff, or use it for FM stereo/DAB+, maybe short wave.

So today, I was testing this: using the RTL-SDR with a Pi 3, seeing whether it would perform acceptably for that task. Interestingly, CubicSDR will de-modulate FM stereo quite happily when you’re running it via a X11 session forwarded over SSH, but it stutters its way though if you try to run it natively. I think the waterfall displays are too much for the machine to cope with: it can render them, but painting them on the screen causes too much CPU load.

qt-dab however works quite well. It occupies about 60% CPU, which means you don’t want to be doing much else. Whether I can do AX.25 packet simultaneously as planned or not is a valid question. Audio quality through the PWM output on the Pi3 is good too — I did try this with an original Pi and got an aural assault courtesy of the noisy 3.3V power rail, but it seems this problem is largely fixed on the Pi3.

In truth, I’ll probably be using the GNURadio framework directly when I get to implementing this on the bicycle. That makes a custom tailored UI a little easier to implement.

The WTF moment though was whilst putting this rig through its paces… I noticed a new station:

ELF Radio, a station dedicated to Christmas Carols

A new station, “ELF Radio” had appeared in multiplex 9A (202.928MHz)… this is exactly what it sounds like, a station dedicated to Christmas carols. We’re not even half-way though October, and they’re already out to flog the genre to death.

Now, Christmas rage was not a thing when I was younger, it seems the marketing world is intent on ruining this tradition by making excuses for starting the sales earlier and earlier… and it seems the “ambience” is part of the package deal that they insist must start long before that Celtic tradition, Halloween! As a result, most of us are thoroughly fed up by the time December rolls around.

Here’s a hint advertisers: playing this crap so soon in the year will not result in higher sales. It’s a sales repellent!

Jul 182019
 

So, a few months back I had the failure of one of my storage nodes. Since I need 3 storage nodes to operate, but can get away with a single compute node, I did a board-shuffle. I just evacuated lithium of all its virtual machines, slapped the SSD, HDD and cover from hydrogen in/on it, and it became the new storage node.

Actually I took the opportunity to upgrade to 2TB HDDs at the same time, as well as adding two new storage nodes (Intel NUCs). I then ordered a new motherboard to get lithium back up again. Again, there was an opportunity to upgrade, so ~$1500 later I ordered a SuperMicro A2SDi-16C-HLN4F. 16 cores, and full-size DDR4 DIMMs, so much easier to get bits for. It also takes M.2 SATA.

The new board arrived a few weeks ago, but I was heavily snowed under with activities surrounding Brisbane Area WICEN Group and their efforts to assist the Stirling’s Crossing Endurance Club running the Tom Quilty 2019. So it got shoved to the side with the RAM I had purchased to be dealt with another day.

I found time on Monday to assemble the hardware, then had fun and games with the UEFI firmware on this board. Put simply, the legacy BIOS support on this board is totally and utterly broken. The UEFI shell is also riddled with bugs (e.g. ifconfig help describes how to bring up an interface via DHCP or statically, but doing so fails). And of course, PXE is not PXE when UEFI is involved.

I ended up using Ubuntu’s GRUB binary and netboot image to boot-strap the machine, after which I could copy my Gentoo install back in. I now have the machine back in the rack, and whilst I haven’t deployed any VMs to it yet, I will do so soon. I did however, give it a burn-in test updating the kernel:

  LD [M]  security/keys/encrypted-keys/encrypted-keys.ko
  MKPIGGY arch/x86/boot/compressed/piggy.S
  AS      arch/x86/boot/compressed/piggy.o
  LD      arch/x86/boot/compressed/vmlinux
ld: arch/x86/boot/compressed/head_64.o: warning: relocation in read-only section `.head.text'
ld: warning: creating a DT_TEXTREL in object.
  ZOFFSET arch/x86/boot/zoffset.h
  OBJCOPY arch/x86/boot/vmlinux.bin
  AS      arch/x86/boot/header.o
  LD      arch/x86/boot/setup.elf
  OBJCOPY arch/x86/boot/setup.bin
  BUILD   arch/x86/boot/bzImage
Setup is 16444 bytes (padded to 16896 bytes).
System is 6273 kB
CRC ca5d7cb3
Kernel: arch/x86/boot/bzImage is ready  (#1)

real    7m7.727s
user    62m6.396s
sys     5m8.970s
lithium /usr/src/linux-stable # git describe
v5.1.11

7m for make -j 17 to build a current Linux kernel is not bad at all!

May 292019
 

It’s been on my TO-DO list now for a long time to wire in some current shunts to monitor the solar input, replace the near useless Powertech solar controller with something better, and put in some more outlets.

Saturday, I finally got around to doing exactly that. I meant to also add a low-voltage disconnect to the rig … I’ve got the parts for this but haven’t yet built or tested it — I’d like to wait until I have done both,but I needed the power capacity. So I’m running a risk without the over-discharge protection, but I think I’ll take that gamble for now.

Right now:

  • The Powertech MP-3735 is permanently out, the Redarc BCDC-1225 is back in.
  • I have nearly a dozen spare 12V outlet points now.
  • There are current shunts on:
    • Raw solar input (50A)
    • Solar controller output (50A)
    • Battery (100A)
    • Load (100A)
  • The Meanwell HEP-600C-12 is mounted to the back of the server rack, freeing space from the top.
  • The janky spade lugs and undersized cable connecting the HEP-600C-12 to the battery has been replaced with a more substantial cable.

This is what it looks like now around the back:

Rear of the rack, after re-wiring

What difference has this made? I’ll let the graphs speak. This was the battery voltage this time last week:

Battery voltage for 2019-05-22

… and this was today…

Battery voltage 2019-05-29

Chalk-and-bloody-cheese! The weather has been quite consistent, and the solar output has greatly improved just replacing the controller. The panels actually got a bit overenthusiastic and overshot the 14.6V maximum… but not by much thankfully. I think once I get some more nodes on, it’ll come down a bit.

I’ve gone from about 8 hours off-grid to nearly 12! Expanding the battery capacity is an option, and could see the cluster possibly run overnight.

I need to get the two new nodes onto battery power (the two new NUCs) and the Netgear switch. Actually I’m waiting on a rack-mount kit for the Netgear as I have misplaced the one it came with, failing that I’ll hack one up out of aluminium angle — it doesn’t look hard!

A new motherboard is coming for the downed node, that will bring me back up to two compute nodes (one with 16 cores), and I have new 2TB HDDs to replace the aging 1TB drives. Once that’s done I’ll have:

  • 24 CPU cores and 64GB RAM in compute nodes
  • 28 CPU cores and 112GB RAM in storage nodes
  • 10TB of raw disk storage

I’ll have to pull my finger out on the power monitoring, there’s all the shunts in place now so I have no excuse but to make up those INA-219 boards and get everything going.

May 242019
 

Recently, I had a failure in the cluster, namely one of my nodes deciding to go the way of the dodo. I think I’ve mostly recovered everything from that episode.

I bought some new nodes which I can theoretically deploy as spare nodes, Core i5 Intel NUCs, and for now I’ve temporarily decommissioned one of my compute nodes (lithium) to re-purpose its motherboard to get the downed storage node back on-line. Whilst I was there, I went and put a new 2TB HDD in… and of course I left the 32GB RAM in, so it’s pretty much maxxed out.

I’d like to actually make use of these two new nodes, however I am out of switch capacity, with all 26 ports of the Linksys LGS-326AU occupied or otherwise reserved. I did buy a Netgear GS748T with the intention of moving across to it, but never got around to doing so.

The principle matter here being that the Netgear requires a wee bit more power. AC power ratings are 100-250V, 1.5A max. Now, presumably the 1.5A applies at the 100V scale, that’s ~150W. Some research suggested that internally, they run 12V, that corresponds to about 8.5A maximum current.

This is a bit beyond the capabilities of the MIC29712s.

I wound up buying a DC-DC power supply, an isolated one as that’s all I could get: the Meanwell SD-100A-12. This theoretically can take 9-18V in, and put out 12V at up to 8.5A. Perfect.

Due to lack of time, it sat there. Last week-end though, I realised I’d probably need to consider putting this thing to use. I started by popping open the cover and having a squiz inside. (Who needs warranties?)

The innards of the GS-748Tv5, ruler for scale

I identified the power connections. A probe around with the multimeter revealed that, like the Linksys, it too had paralleled conductors. There were no markings on the PSU module, but un-plugging it from the mainboard and hooking up the multimeter whilst powering it up confirmed it was a 12V output, and verified the polarity. The colour scheme was more sane: Red/Yellow were positive, Black/Blue were negative.

I made a note of the pin-out inside the case.

There’s further DC-DC converters on-board near the connector, what their input range is I have no idea. The connector on the mainboard intrigued me though… I had seen that sort of connector before on ATX power supplies.

The power supply connector, close up.

At the other end of the cable was a simple 4-pole “KK”-like connector with a wider pin spacing (I think ~3mm). Clearly designed with power capacity in mind. I figured I had three options:

  1. Find a mating connector for the mainboard socket.
  2. Find a mating header for the PSU connector.
  3. Ram wires into the plug and hot-glue in place.

As it happens, option (1) turned out easier than I thought it would be. When I first bought the parts for the cluster, the PicoPSU modules came with two cables: one had the standard SATA and Molex power connectors for powering disk drives, the other came out to a 4-pin connector not unlike the 6-pole version being used in the switch.

Now you’ll note of those 6 poles, only 4 are actually populated. I still had the 4-pole connectors, so I went digging, and found them this evening.

One of my 4-pole 12V connectors, with the target in the background.

As it happens, the connectors do fit un-modified, into the wrong 4 holes — if used unmodified, they would only make contact with 2 of the 4 pins. To make it fit, I had to do a slight modification, putting a small chamfer on one of the pins with a sharp knife.

After a slight modification, the connector fits where it is needed.

The wire gauge is close to that used by the original cable, and the colour coding is perfect… black corresponds to 0V, yellow to +12V. I snipped off the JST-style connector at the other end.

I thought about pulling out the original PSU, but then realised that there was a small hole meant for a Kensington-style lock which I wasn’t using. No sharp edges, perfect for feeding the DC cables through. I left the original PSU in-situ, and just unplugged its DC output.

The DC input leads snake through the hole that Netgear helpfully provided.

Bringing the DC power input to the outside.

Before putting the screws in, I decided to give this a test on the bench supply. The switch current fluctuates a bit when booting, but it seems to settle on about 1.75A or so. Not bad.

Testing the switch running on 12V

Terminating this, I decided to use XT-60 connectors. I wanted something other than the 30A “powerpoles” and their larger 50A cousins that are dotted throughout the cluster, as this needed to be regulated 12V. I did not want to get it mixed up with the raw 12V feed from the batteries.

I ran some heavier gauge cable to the DC-DC PSU, terminated with the mating XT-60 connector and hooked that up to my PSU. Providing it with 12V, I dialled the output to 12V exactly. I then gave it a no-load test: it held the output voltage pretty good.

Next, I hooked the switch up to the new PSU. It fired up and I measured the voltage now under load: it still remained at 12V. I wound the voltage down to 9V, then up to 15V… the voltage output never shifted. At 9V, the current consumption jumps up to about 3.5A, as one would expect.

Otherwise, it seemed to be content to draw under 2A so the efficiency of the DC-DC converter is pretty good.

I’ll need to wire in a new fuse box to power everything, but likely the plan will be to decommission the 16-port 100Mbps switch I use for the management network, slide the 48-port switch in its place, then gradually migrate everything across to the new switch.

Overall, the modding of this model switch was even less invasive than that of the Linksys. It’s 100% reversible. I dare say having posted this, there’ll be a GS748Tv6 that’ll move the 240V PSU to the mainboard, but for now at least, this is definitely a switch worth looking at if 12V operation is needed.

May 242019
 

So, in my workplace we’re developing a small energy/water metering device, which runs on a 6LoWPAN network and runs OpenThread-based firmware. The device itself is largely platform-agnostic, requiring a simple CoAP gateway to provide it with a configuration blob and history write end-point. The gateway service I’m running is intended to talk to WideSky.

One thorny issue we need to solve before deploying these things in the wild, is over-the-air updates. So we need a way to transfer the firmware image to the device over the mesh network. Obviously, this firmware image needs to be digitally signed and hashed using a strong cryptographic hash — I’ve taken care of this already. My problem is downloading an image that will be up to 512kB in size.

Thankfully, the IETF has thought of this, the solution to big(gish) files over CoAP is Block-wise transfers (RFC-7959). This specification gives you the ability to break up a large payload into smaller chunks that are powers of two in size between 16 and 2048 bytes.

6LoWPAN itself though has a limitation: the IEEE 802.15.4 radio specification it is built on cannot send frames bigger than 128 bytes. Thus, any message sent via this network must be that size or smaller. IPv6 has a minimum MTU of 1280 bytes, so how do they manage? They fragment the IPv6 datagram into multiple 802.15.4 frames. The end device re-assembles the fragments as it receives them.

The catch is, if a fragment is lost, you lose the entire datagram, there’s no repeats of individual fragments, the entire datagram must be re-sent. The question in my mind was this: Is it faster to rely on block-wise transfers to break the payload up and make lots of small requests, or is it faster to rely on 6LoWPAN fragmentation?

The test network here has a few parts:

  • The target device, which will be downloading a 512kB firmware image to a separate SPI flash chip.
  • The border router, which provides a secure IPv6 tunnel to a cloud host.
  • The cloud server which runs the CoAP service we’ll be talking to.

The latency between the office (in Brisbane) and the cloud server (in Sydney) isn’t bad, about 30~50ms. The CoAP service is built using node-coap and coap-polka.

My CoAP requests have some overheads:

  • The path being downloaded is about 19 bytes long.
  • There’s an authentication token given as a query string, so this adds an additional 12 bytes.

The data link is not 100% reliable, with the device itself dropping some messages. This is leading to some retransmits. The packet loss is not terrible, but probably in the region of around 5%. Over this slightly lossy link, I timed the download of my 512kB firmware image by my device with varying block size settings.

Note that node-coap seems to report a “Bad Option” error for szx=0 and szx=7, even though both are legitimately within specification. (I’d expect node-coap to pass szx=7 through and allow the application to clamp it to 6, but it seems node-coap‘s behaviour is to report “Bad option”, but then pass the payload through anyway.)

Size Exponent (szx)Block sizeStart time (UTC)End time (UTC)Effective data rate
6102403:27:0403:37:52809B/s
551203:41:2503:53:40713B/s
425603:57:1504:16:16458B/s
312804:17:4604:54:17239B/s
26404:56:0905:54:53150B/s
13223:31:3301:39:4468B/s

It remains to be seen how much multiple hops and outdoor atmospherics affect the situation. A factor here is how quickly the device can turn-around between processing a response and sending the next request, which in this case is governed by the speed of the SPI flash and its driver.

Effects on “busy” networks

So, I haven’t actually done any hard measurements here, but doing testing on a busier network with about 30 nodes, the block size equation tips more in favour of a smaller block size.

I’ll try to quantify the delays at some point, but right now 256 byte blocks are the clear winner, with 512 and 1024 byte block transfers proving highly unreliable. The speed advantage between 1k and 512 bytes in ideal conditions was a big over 10%… which really doesn’t count for much. At 256 bytes, the speed difference was about 43%, quite significant. You’re better off using 512-byte blocks if the network is quiet.

On a busy network, with all the retransmissions, smaller is better. No hard numbers yet, but right now at 256 byte blocks, the effective rate is around 118 bytes/sec. I’ll have to analyse the logs a bit to see where 512/1024 byte block sizes sat, but the fact they rarely completed says it all IMO.

Slow and steady beats fast and flakey!

May 182019
 

Seriously, if you think this is a good way to earn some yuan, think again. I just got this email this afternoon:


Dear CEO,
(It’s very urgent, please transfer this email to your CEO. If this email affects you, we are very sorry, please ignore this email. Thanks)
We are a Network Service Company which is the domain name registration center in China.
We received an application from Hua Hai Ltd on May 14
, 2019. They want to register ” stuartl.longlandclan ” as their Internet Keyword and ” stuartl.longlandclan .cn “、” stuartl.longlandclan .com.cn ” 、” stuartl.longlandclan .net.cn “、” stuartl.longlandclan .org.cn ” 、” stuartl.longlandclan .asia “、domain names, they are in China and Asia domain names. But after checking it, we find ” stuartl.longlandclan ” conflicts with your company. In order to deal with this matter better, so we send you email and confirm whether this company is your distributor or business partner in China or not?
 


Best Regards
**************************************
Mike Zhang | Service Manager
Cn YG Domain (Head Office)
Contact details censored as I do not wish to promote their business
*************************************

The wording is identical to that seen in this article on squelchdesign. Knowing this to be a scam, I did two things:

  1. As per my standard policy, I forwarded it to SpamCop. The source of the email was Baidu’s own network.
  2. I figured since it’s obviously a scam and since these people seemingly do not learn from the skirmishes with others, I’d have some fun with them:

On 18/5/19 11:46 am, Mike Zhang wrote:

Dear CEO, (It’s very urgent, please transfer this email to your CEO. If this email affects you, we are very sorry, please ignore this email. Thanks)

You want this to go to my CEO? Does every individual person in China have their own personal CEO? Is that why they have such a big population? Please keep in mind what the .id.au domain suffix is for: INDIVIDUALS.

We are a Network Service Company which is the domain name registration center in China.

Ahh, so you must know the rules around domain registrations, like the .id.au domain suffix being non-commercial.

We received an application from Hua Hai Ltd on May 14, 2019. They want to register ” stuartl.longlandclan ” as their Internet Keyword and ” stuartl.longlandclan .cn “、” stuartl.longlandclan .com.cn ” 、” stuartl.longlandclan .net.cn “、” stuartl.longlandclan .org.cn ” 、” stuartl.longlandclan .asia “、domain names, they are in China and Asia domain names.

They must be rich. They also wanted bellavitosi .cn, bellavitosi.com.cn, bellavitosi.net.cn, bellavitosi.org.cn, bellavitosi.asia, formula1-dictionary.cn, formula1-dictionary.com.cn, formula1-dictionary.net.cn, formula1-dictionary.org.cn and formula1-dictionary.asia.

What does this group do? Are they a subsiduary of BaoYuan Ltd? I hear pan xiaohong has wealth that rivals Jack Ma.

But after checking it, we find ” stuartl.longlandclan ” conflicts with your company. In order to deal with this matter better, so we send you email and confirm whether this company is your distributor or business partner in China or not?

Well, this “company” does not exist, so can’t possibly have a partner in China. I say to them, go ahead and register those domain names, I dare you, it’ll cost you a lot more than it will cost me.

Errm, yeah… the SEO spammers are slowly learning not to mess with me as I’ll just report the email as spam and will tweak mail server settings to ensure you stay blocked. Or I may choose to publicly ridicule you like I have done here.

The worst they can do is actually follow through and register all those domains, which will cost them an absolute bloody fortune (.asia domains are not cheap!) and my content is already well known with the search engines — it’s not like I rely on my online presence for an income anyway as I have a day job. Anything I do here is for self-education and training.

All this mob is doing, is destroying the image of some innocent company in Hong Kong, which are likely nothing to do with this scam. Seriously guys, get a real job!

Apr 112019
 

Lately, I had a need for a library that would talk to a KISS TNC and allow me to exchange UI frames over an AX.25 network.

This is part of a project being undertaken by Brisbane Area WICEN Group. We’ve been tasked with the job of reporting scans from RFID tag readers back to base… and naturally we’ll be using the AX.25 network we’re already familiar with. The plan is to use APRS messaging (to keep things simple) to submit the location, time and hardware address of each RFID read.

For this, I needed something I also need for this project, a tool to encode and decode the UI frames. I had initially thought of just using LinBPQ or similar to provide the interface to AX.25, but in the end, it was easier for me to write my own simple AX.25 stack from scratch.

aioax25 obviously is nowhere near a replacement for other AX.25 stacks in that it only encodes and decodes frames, but it’s a first step in that journey. This library is written for Python 3.4 and up using the asyncio module and pyserial. At the moment I have used it to somewhat crudely send and receive APRS messages, and so with a bit of work, it’ll suffice for the WICEN project.

That does mean I’m not shackled in terms of what bits I can set in my AX.25 headers. One limitation I have with my mapping of 6LoWHAM addresses to AX.25 addresses is that I cannot represent all characters or the “group” bit.

This lead to the limitation that if I defined a group called VK4BWI-0, that group may not have a participant with the call-sign of VK4BWI-0 because I would not be able to differentiate group messages from direct messages.

By writing my own AX.25 stack, I potentially can side-step that limitation: I can utilise the reserved bits in a call-sign/SSID to represent this information. I avoided their use before because the interfaces I planned on using did not expose them, but doing it myself means they’re directly accessible. The AX.25 protocol documentation states:

The bits marked “r” are reserved bits. They may be used in an agreed-upon manner in individual networks. When not implemented, they should be set to one.

https://www.tapr.org/pub_ax25.html

Now, the question is, if I set one to 0, would it reach the far end as a 0? If so, this could be a stand-in for the group bit — stored inverted so that a 1 represents a unicast destination and 0 represents a group.

The other option is to just prepend the left-over bits to the start of the message payload. This has the bonus that I can encode the full-callsign even if that call-sign does not fit in a standard AX.25 message.

So a message sent to VK4FACE-6 (let’s pretend F-calls can use packet for the sake of an example) would be sent to AX.25 SSID VK4FAC-6, and the first few bytes would encode the missing E and the group/unicast bit. If the station VK4FAC were also on frequency, the software stack at their end would need to filter based on those initial payload bytes.

We support 8-character call-signs, so we need to represent 2 left-over characters plus a group bit. Add space for two-more characters for the source call-sign (which may not be a group), we require about 3 bytes.

At this point we might as well use 4, store the extra bytes as 7-bit ASCII, with the spare MSBs of each byte encoding the group bit and one spare bit. An extra 8 bits is bugger all really even at 1200 baud.

Obviously, NET/ROM has no knowledge of this. Stations that are on the other side of a non-6LoWHAM digipeater need to explicitly source-route their hops to reach the rest of a mesh network, and the nodes the other side need to “remember” this source route.

This latter scheme also won’t work for connected mode, as there’s no scope to shoehorn those bytes in the information field and still remain AX.25 compatible — it will only work for 6LoWHAM UI frames.

Anyway, it’s food for thought.