Skip to content

Instantly share code, notes, and snippets.

@requinix
Last active August 11, 2023 03:34
Show Gist options
  • Save requinix/4167ac09242684ac23f484543ac8bbcd to your computer and use it in GitHub Desktop.
Save requinix/4167ac09242684ac23f484543ac8bbcd to your computer and use it in GitHub Desktop.
batman-adv with Netplan on Ubuntu

Setting up B.A.T.M.A.N. on Ubuntu using Netplan instead of ifupdown

...is a lie

If you're here then I'm going to assume you already know about B.A.T.M.A.N and Netplan, and probably also about ifupdown (or at least /etc/network/interfaces).

Bad news: Netplan cannot currently (2023) set up batman-adv interfaces. Simply no support for it. This suggests that, in order to have batman-adv interfaces, you have to uninstall Netplan and switch back to ifupdown.

Good news: Netplan uses systemd-networkd under the hood, and it does have support. You'll bypass the Netplan configurations and write your own, but it's not too hard. So you can keep Netplan installed and managing your non-batman interfaces.

Example Scenario

While a mesh network is frequently used for wireless networking, I wanted it to apply to my wired point-to-point network. There's no difference between the two besides the interface names you attach to it - a mesh is a mesh.

  • batman-adv interface name: bat0 (which is the default for batctl commands, and besides, it's the most logical choice of name)
  • An existing regular interface I do not want in the mesh: eth0
  • The interfaces to include in the bridged mesh: eth1 and eth2
  • The mesh network will be 192.168.1.0/24, and the server I'm on will be assigned specifically 192.168.1.111

1. Update Netplan

systemd-networkd only allows a single configuration for an interface, so make sure that Netplan is not already covering the interfaces you want to include in the mesh. If you had these interfaces present when you installed Ubuntu then the installer will likely have discovered them and set them up for you.

Sample diff of /etc/netplan/NN-whatever.yaml:

  network:
    ethernets:
      eth0:
        # an existing configuration for eth0 that will be left alone
        # ...
-     eth1:
-       # whatever existed here before...
-       dhcp4: false
-     eth2:
-       # whatever existed here before...
-       dhcp4: false

⬇️

network:
  ethernets:
    eth0:
      # an existing configuration for eth0 that will be left alone
      # ...

Remember to run netplan apply after making changes.

You actually don't have to do that right now: since applying the configuration also causes systemd-networkd to reload, and since we'll want to do that same reload after making our own additions, you could do this later and cover both at once.

You can view Netplan's generated output in /run/systemd/network, which is one of the places that systemd-networkd can read files from; /run isn't persistent so we'll be using a different place.

2. Create the bat0 device

systemd-networkd uses configuration files like every other Linux thing that exists. There are multiple types of files intended for different purposes, all using an INI-style syntax and differentiated by file extension, and we'll need three. These files can be stored in a handful of places, with the most convenient one being /etc/systemd/network.

First is a .netdev file. It can define a device that doesn't naturally exist, like a bridge.

See systemd.netdev(5)

/etc/systemd/network/bat0.netdev 1:

[Match]
# No conditions needed on how to match the current environment (unless you want some)

[NetDev]
# Create a device named bat0
Name = bat0
# It's a "batadv" kind of device - one of the specific values listed in systemd.netdev(5)
Kind = batadv

[BatmanAdvanced]
# There are multiple routing algorithms possible...
RoutingAlgorithm = batman-iv

Note: The default routing algorithm is batman-v, but you need to check if this is actually supported by your system first. On mine, only batman-iv is available:

$ batctl ra
Selected routing algorithm (used when next batX interface is created):
 => BATMAN_IV

Available routing algorithms:
 * BATMAN_IV

If you pick one that doesn't exist, systemd-networkd will complain in its journalctl logs of an "invalid parameter".

3. Assign a network to bat0

The second file is a .network which takes the interface and gives it a basic network configuration - such as an IP address.

See systemd.network(5)

/etc/systemd/network/bat0.network:

[Match]
# Apply this configuration to the bat0 device
Name = bat0

[Network]
# Assign the desired address, and include the subnet prefix
Address = 192.168.1.111/24

4. Assign interfaces

The third is another .network which handles the interfaces you want to include in the bat0 mesh.

/etc/systemd/network/bat0-interfaces.network:

[Match]
# Apply to all of these interfaces, separated by spaces
Name = eth1 eth2

[Link]
# Increase the MTU because batman-adv uses slightly larger packets than normal
MTUBytes = 1560

[Network]
# Assign to bat0
BatmanAdvanced = bat0

Note: Only one .network file can apply to an interface at a time; files can be overridden in a different directory, but with multiple differently-named files only the first one found will be used. If you need special configuration for any of these interfaces then use separate .network files.

Note: batman-adv's packets are larger than the MTU's typical 1500 bytes, which means they'll fragment, which will impact performance. If the driver detects an MTU value too low then it will mention so in the kernel log:

[nnn.nnnnnn] batman_adv: bat0: Adding interface: eth1
[nnn.nnnnnn] batman_adv: bat0: The MTU of interface eth1 is too small (1500) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to 1560 would solve the problem.
[nnn.nnnnnn] batman_adv: bat0: Interface activated: eth1

5. Apply and Verify

After making sure you're accessing the server in question through a means that will continue to work even if the configuration is wrong, such as via SSH through that eth0 interface which was left unchanged,

Apply the configuration: do a netplan apply if you didn't do that earlier, or else systemctl reload systemd-networkd.

Once applied, give batman-adv a few minutes to get up to speed. Maybe step away and fix yourself a nice sandwich to eat. When you're ready to verify that it's working (and if it doesn't seem to be, wait a little longer and try again),

  • Verifying through ip
# Summary list of interfaces
$ ip link

# Detailed information
$ ip addr

There are a few things to confirm in the list of interfaces and their statuses:

  1. That bat0 exists, is up, and (with ip addr:) has an IP address
  2. That the meshed interfaces have their new MTU values and are master-ed to bat0

bat0 may be in an "UNKNOWN" state but that doesn't seem to be a problem.

  • Verifying through the kernel logs
$ dmesg

# or manually,
$ less /var/log/kern.log

Check the kernel logs to see what happened: there should be plenty of output from batman_adv about what it did along the way.

  • Verifying through journalctl
$ journalctl -xeu systemd-networkd

systemd-networkd also wrote some information as it reloaded. The normal messages aren't full of detail, but if there was a problem then it should definitely be covered in these logs.

  • Verifying with real traffic

When you have multiple servers connected and configured, you should be able to send traffic between them. Obviously.

Pretending that 192.168.1.222 is another node located somewhere in the mesh,

# A regular ping, if it's not being blocked
$ ping 192.168.1.222

# Test a port that's known to be open, like 22/ssh or 80/http or 443/https
$ nc -zv 192.168.1.222 22
  • Verifying with batctl

batctl is the primary batman-adv utility and has a number of functions available, most of which being useful only when you have an actual mesh up and running.

See batctl(8)

A few highlights:

# List of mesh neighbors
$ batctl n

# Trace a route to another node
$ batctl tr 192.168.1.222

# L2 ping of another node
$ batctl ping 192.168.1.222

# Throughput test (needs a MAC address)
$ batctl tp 00:11:22:33:44:55
  • Or anything else that suits you.

6. Celebrate

Because you're done. 🎉

Footnotes

  1. The documentation recommends the standard NN-name.ext naming pattern that's commonly used elsewhere, as the ordering of configuration files is important, but if you're not using many files that have dependencies on each other then the exact name won't matter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment