diary @ telent

A surfiet of services#

Tue 09 Jul 2024 08:36:58 PM UTC

Topics: liminix

It feels like a while since I wrote one of these, but this might be because [checks post history] it has indeed been a while since I wrote one of these. Sorry about that. It's been a bit of a slog.

What I've been working on for the past ~~several hundred years~~ couple of months is service failover. Specifically (although, hopefully, the mechanisms developed will be useful more generally): if my PPPoE internet connection goes down, I want to use the LTE modem instead.

There are, as always, details - and anyone else who wants to construct a similar configuration will need to consider whether their details match mine.

So, the requirement is to run PPOE until it goes down, then start an L2TP LAC ("L2TP Access Concentrator", the L2TP jargon for the end of a connection that calls the other end) - for which we need some kind of internet connection and a route to the LNS (L2TP Network Server, a.k.a the other end) and some DNS service so we can look up the address of the LNS, and maybe a route to the DNS - although actually I cheated there and assumed it would be on the same network as the wwan device. We can start all of those things in parallel with PPPoE, it's only the actual L2TP service that we have to delay until the primary connection dies.

LTE WWAN

Configuring the modem was a great test of the uevent controlled services I described last time, and I'd say we passed maybe 80%?

  1. When the USB stick is plugged in, it identifies as a USB mass storage device with usb id 12d1:14fe. We then need to run USB ModeSwitch which sends it some sequence of magic USB commands (undocumented and reverse-engineered from the Windows drivers)

  2. ... that causes it to detach from the USB bus and re-attach providing a network device and a serial device, with a different USB id (1201:1506 if you're keeping score). When it reappears, then we open the serial port and send it some (mostly-documented) AT commands to configure APN, username, password, etc

  3. then the network is "up" and we can run DHCP to get an IP address and the whereabouts of a nameserver and do whatever else

So we need two uevent controlled services: one to run on initial insertion that does the modeswitch, and the second to run when the "switched" device appears that sends it AT commands. To implement the second we had to extend uevent-watch/devout so that it would match on "sysfs attributes" not only on fields in the uevent message, because there isn't a uevent field that contains the name of the serial port - that information is only in sysfs.

Why do I say 80%? Because there's a kludge. After my dogged insistence in the previous post that this is conceptually better than udev because udev "allows arbitrary commands on each event and it doesn’t have symmetry" - it is fated that I find an apparent need for exactly that. Consider the modeswitch service:

I am still very much in favour of the constraint that device events can only start/stop services and not just do whatever they like, but I don't yet have a good way to model this particular one. The bad way is to add the modeswitch service to buildInputs of the AT command service.

up the tree

We also had to write a new command s6-rc-up-tree to bring up a service and some but perhaps not all of the services it depends on - and some logic to avoid bringing those services up on boot. Why? Suppose you have a network device that's hotplugged and a route service depending on it. When the device disappears we stop the service and s6-rc knows how to stop all the services that depend on it - but when we start the service, s6-rc will start only that service and not the other services it enables. So we have to go through all the things that hang off it and start each of them too - except for the ones that also depend on some other controlled service if that other controlled service is down.

If that sounds hard to understand, it was hard to understand.

Failover

To accomplish failover we made a new kind of service controller, that accepts a set of services and runs each of them in turn until it falls over, then stops it and starts the next one. To detect that a service has died we watch its outputs directory using inotify to see when it goes away. We had to make sure the services would actually die when connectivity is lost:

One point to watch out for: in s6-rc there is a distinction between a process being started (fork and exec have happened) and a service being ready, which the process itself signals to the supervisor by writing to a particular file descriptor. The s6-rc -u change command that starts a service will not return until either the service is ready or a timeout has expired, and until the timeout has elapsed it will attempt to restart the process - perhaps several times - if it dies without first becoming ready. That can be confusing if you're looking at the logs wondering why you see service A, A, A, A being invoked and failing repeatedly when you were expecting A, B, A, B ... but it's not a bad thing when you know it's happening.

Note there is no automated recovery. It would be simple enough to add an alarm of some kind that kills the secondary service after a decent interval so that the primary is tried again, but that falls squarely in "policy not mechanism" and I haven't decided what policy I want.

Current status: it works on the testbed but I've not integrated it into a full system config yet, and there is oodles of cleanup to do.

In other news

I ran deadnix and nixfmt across the entire Liminix codebase, so now the commas are at the end of the parameters in function argument lists instead of at the start. I didn't merge all the changes that nixfmt wanted to make, just the ones I thought were unambiguous improvements.

Sorry if you had long-running branches that no longer apply.

F is for Folly#

Sat 13 Jul 2024 06:33:44 PM UTC

Topics: ride-report motorbike

Gateway and folly. Formerly S entrance to Gobions houses (dem.1836). Circa 1740 for Sir Jeremy Sambrooke, probably by James Gibbs. Red brick. Large round-headed arch and thin square turrets. Battlemented. The arch has rusticated voussoirs. The turrets are in 3 stages and have slit windows in deep chamfered surrounds with gauged brick heads. 3 floor bands. Modillioned cornice imitating machicolation. Same arch, different angle F is for Folly - specifically, Folly Arch: "a prominent North Mymms landmark since the first half of the 18th century."

Half the route was boring town riding, but once past Enfield it gets quite scenic-twisty-country-lane with bad sightlines and occasional gravel. The fuel light came on at about 120 miles, so I filled the tank but forgot to reset the trip counter.

Detoured on the journey home to visit my aunt and uncle near Hertford (hi, if you're reading this, and thank you for coffee and cake) which was not only great to see them but also the roads between North Mymms and them are a lot more fun than between home and North Mymms.

Home from Hertford down the A10 and A406, which is direct if nothing else. Direct and nothing much else, in truth.

Filtered a bit, when the opportunity presented itself. Rode the bike up the kerb and into the front garden without stalling it at all, which I think is a milestone in throttle/clutch control

One weird thing: a few times I felt the back of the bike move sideways unexpectedly, not unlike tramlining on a pedal cycle. At least one of those occasions was on gravel, which seems like a partial explanation, so maybe the others were gravel I didn't see, or crosswinds? Not scary, just a bit puzzling

I mean, maybe this is how its supposed to be but the tyres were underinflated previously.

I did consider it could be actual tramlining but I'd have thought the tyre was far too wide for that to be a thing on motorbikes

Note to self: reset the trip counter at 155 miles

The European Union must keep funding free software#

Tue 16 Jul 2024 09:56:18 PM UTC

Topics:

This is an open letter initially published in French by the Petites Singularités association. To co-sign it, please publish it on your website if your preferred language, then add yourself to this table.

Thanks to Jeremiah Lee for the easy-to-copy-paste HTML version.


Since 2020, the Next Generation Internet (NGI) program, part of European Commission’s Horizon program, funded free software in Europe using a cascade funding mechanism (see for example NLnet’s calls). This year, according to the Horizon Europe working draft detailing funding programs for 2025, we noticed the Next Generation Internet is not mentioned as part of Cluster 4.

NGI programs have demonstrated their strength and importance in supporting the European software infrastructure, as a generic funding instrument to fund digital commons and ensure their long-term sustainability. We find this transformation incomprehensible, moreover when NGI has proven efficient and ecomomical to support free software as a whole, from the smallest to the most established initiatives. This ecosystem diversity backs the strength of European technological innovation. Maintaining the NGI initiative to provide structural support to software projects at the heart of worldwide innovation is key to enforce the sovereignty of a European infrastructure. Contrary to common perception, technical innovations often originate from European rather than North American programming communities and are mostly initiated by small-scaled organizations.

Previous Cluster 4 allocated 27 millions euros to:

In the name of these challenges, more than 500 projects received NGI0 funding in the first 5 years, backed by 18 organizations managing these European funding consortia.

NGI contributes to a vast ecosystem, as most of its budget is allocated to fund third parties by the means of open calls, to structure commons that cover the whole Internet scope—from hardware to application, operating systems, digital identities, or data traffic supervision. This third-party funding is not renewed in the current program, leaving many projects short on resources for research and innovation in Europe.

Moreover, NGI allows exchanges and collaborations across all the EU zone, as well as “widening countries”1, currently both a success and an ongoing progress, like the Erasmus program before us. NGI0 also contributes to opening and maintaining longer relationships than strict project funding does. It encourages the implementation of funded projects through pilots and supports collaboration within intiatives, as well as the identification and reuse of common elements across projects, interoperability in identification systems and beyond, and the establishment of development models that integrate other sources of financings at different scales in Europe.

While the USA, China, or Russia deploy huge public and private resources to develop software and infrastructure that massively capture private consumer data, the EU can’t afford this renunciation. Free and open source software, as supported by NGI since 2020, is by design the opposite of potential vectors for foreign interference. It lets us keep our data local and favors a community-wide economy and know-how, while allowing an international collaboration. This is all the more essential in the current geopolitical context: the challenge of technological sovereignty is central and free software makes it possible to respond to it while acting for peace and sovereignty in the digital world as a whole.

In this perpective, we urgently ask you to call for the preservation of the NGI program in the 2025 funding program.


1 As defined by Horizon Europe, widening Member States are Bulgaria, Croatia, Cyprus, Czechia, Estonia, Greece, Hungary, Latvia, Lituania, Malta, Poland, Portugal, Romania, Slovakia, and Slovenia. Widening associated countries (under condition of an association agreement) include Albania, Armenia, Bosnia, Feroe Islands, Georgia, Kosovo, Moldavia, Montenegro, Morocco, North Macedonia, Serbia, Tunisia, Turkeye, and Ukraine. Widening overseas regions are Guadeloupe, French Guyana, Martinique, Reunion Island, Mayotte, Saint-Martin, The Azores, Madeira, the Canary Islands. ↩︎