<div dir="ltr"><div>My bad.</div><div><br></div><div>I ended up trying it again and it worked as you described after a machinectl reboot. Maybe that was the issue. networkctl reload/reconfigure seemed to sometimes behave inconsistently.</div><div>Thank you very much for your help and explanations.<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, 12 Jul 2023 at 11:46, Andrei Borzenkov <<a href="mailto:arvidjaar@gmail.com">arvidjaar@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Please either use reply to all or reply to list. Do not send personal<br>
replies to public list discussion.<br>
<br>
On Wed, Jul 12, 2023 at 12:01 PM LunarLambda <<a href="mailto:lunarlambda@gmail.com" target="_blank">lunarlambda@gmail.com</a>> wrote:<br>
><br>
> What about the GatewayOnLink= inside the container? Isn't it meant for exactly this? Why does ip r ... onlink work but doing it via networkd doesn't?<br>
><br>
<br>
Not sure. I tested it on openSUSE Tumbleweed with systemd 253.5 and it<br>
seems to work<br>
<br>
tumbleweed:/run/systemd/network # cat dummy.netdev<br>
[NetDev]<br>
Kind=dummy<br>
Name=dummy0<br>
MACAddress=none<br>
tumbleweed:/run/systemd/network # cat dummy0.network<br>
[Match]<br>
Name=dummy0<br>
<br>
[Network]<br>
Address=<a href="http://92.0.0.1/32" rel="noreferrer" target="_blank">92.0.0.1/32</a><br>
<br>
[Route]<br>
Gateway=37.0.0.2<br>
GatewayOnLink=true<br>
tumbleweed:/run/systemd/network # ip a<br>
5: dummy0: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state<br>
UNKNOWN group default qlen 1000<br>
    link/ether be:3a:49:74:6b:7a brd ff:ff:ff:ff:ff:ff<br>
    inet <a href="http://92.0.0.1/32" rel="noreferrer" target="_blank">92.0.0.1/32</a> scope global dummy0<br>
       valid_lft forever preferred_lft forever<br>
    inet6 fe80::bc3a:49ff:fe74:6b7a/64 scope link<br>
       valid_lft forever preferred_lft forever<br>
tumbleweed:/run/systemd/network # ip r<br>
default via 37.0.0.2 dev dummy0 proto static onlink<br>
tumbleweed:/run/systemd/network #<br>
<br>
> The old setup used<br>
> ip r add 91.x.x.x dev br0 src 37.x.x.x<br>
><br>
> Via commands issued in /etc/network/interfaces.<br>
><br>
> The old route looks like this:<br>
> 91.x.x.x dev br0 scope link src 37.x.x.x<br>
><br>
> The route created by the network configuration looks like this:<br>
> 91.x.x.x dev br0 proto static<br>
><br>
> Although I'm not sure this represents a meaningful difference.<br>
><br>
> On Wed, 12 Jul 2023 at 10:29, Andrei Borzenkov <<a href="mailto:arvidjaar@gmail.com" target="_blank">arvidjaar@gmail.com</a>> wrote:<br>
>><br>
>> On Wed, Jul 12, 2023 at 10:44 AM LunarLambda <<a href="mailto:lunarlambda@gmail.com" target="_blank">lunarlambda@gmail.com</a>> wrote:<br>
>> ><br>
>> > Hello,<br>
>> ><br>
>> > I was recently tasked with moving existing network configuration for a machine and some nspawn containers from iupdown to networkd.<br>
>> ><br>
>> > The situation looks as follows:<br>
>> ><br>
>> > A single VPS has 3 IPs. One 37.x.x.x/22, and two 91.x.x.x/32. The 37-ip is to be routed to the main server, whereas the two 91-ips should be routed directly to nspawn containers running on the server. The server uses systemd 247 and the container uses systemd 252, both Debian.<br>
>> ><br>
>> > I created a bridge netdev like so:<br>
>> ><br>
>> > [NetDev]<br>
>> > Name=br0<br>
>> > Type=bridge<br>
>> > # Matches physical network card<br>
>> > MACAddress=AA:BB:CC:DD:EE:FF<br>
>> ><br>
>> > Bound the physical ethernet to it like so:<br>
>> ><br>
>> > [Match]<br>
>> > Name=ens3<br>
>> ><br>
>> > [Network]<br>
>> > Bridge=br0<br>
>> ><br>
>> > And set up the main IP for the bridge like so:<br>
>> ><br>
>> > [Match]<br>
>> > Name=br0<br>
>> ><br>
>> > [Network]<br>
>> > DNS=...<br>
>> > DNS=...<br>
>> > Address=37.x.x.x/22<br>
>> > Gateway=37.x.x.1<br>
>> ><br>
>> > The nspawn containers are added to the bridge via<br>
>> ><br>
>> > [Network]<br>
>> > Bridge=br0<br>
>> ><br>
>> > Up until this point everything works. However, configuring networking between the host and containers proved quite difficult and I'm unsure whether I'm doing something wrong or networkd is.<br>
>> ><br>
>> > What I tried was the following, inside the container:<br>
>> ><br>
>> > [Match]<br>
>> > Virtualization=container<br>
>> > Name=host0<br>
>> ><br>
>> > [Address]<br>
>> > Address=91.x.x.x/32<br>
>> ><br>
>> > [Route]<br>
>> > Gateway=37.x.x.x<br>
>> > GatewayOnLink=true<br>
>> ><br>
>> > However, this did not create any usable routes to the host, nor did it throw any errors in the journal. Pinging the host does not work.<br>
>> ><br>
>> > Manually creating the routes with ip route did work:<br>
>> ><br>
>> > ip r add 37.x.x.x dev host0 onlink<br>
>> > ip r add default dev host0 via 37.x.x.x<br>
>> ><br>
>> > I tried a variety of different combinations of options in the .network file, Scope, Type, etc...<br>
>> ><br>
>> > The only thing that successfully created any routes was the following:<br>
>> ><br>
>> > [Match]<br>
>> > Virtualization=container<br>
>> > Name=host0<br>
>> ><br>
>> > [Address]<br>
>> > Address=91.x.x.x/32<br>
>> > Peer=37.x.x.x/32<br>
>> ><br>
>> > [Network]<br>
>> > Gateway=37.x.x.x<br>
>> ><br>
>> > This strikes me as odd because nowhere in the documentation, nor in any online searching could I find this described as necessary (beyond the manpage mentioning that Peer= exists)<br>
>> ><br>
>><br>
>> How is your Linux container supposed to know that to reach host<br>
>> 37.x.x.x it needs to send a packet via interface with address<br>
>> 91.x.x.x? That is not how Linux routing normally works. You must have<br>
>> a routing entry that tells kernel how to forward packet and assigning<br>
>> address 91.x.x.x to your interface does not magically create any route<br>
>> entry to the network 37.x.x.x. Adding a peer address is one<br>
>> possibility which does it. Another possibility is creating the<br>
>> necessary routes manually like you did.<br>
>><br>
>> > On the host side, I thought the bridge device, acting on Layer 2, would automatically figure out routes to the containers (via ARP),<br>
>><br>
>> Bridge (physical or virtual) has nothing to do with routing, it is<br>
>> only using MAC addresses. ARP is used by the kernel to find out the L2<br>
>> address for the destination L3 address which is on the broadcast<br>
>> network. It happens way after the routing decision was already made.<br>
>> So the kernel needs to know that network 37.x.x.x is directly<br>
>> reachable on the broadcast segment to which the interface is connected<br>
>> before the kernel even attempts ARP. That is exactly what your "ip r<br>
>> add 37.x.x.x dev host0 onlink" does. Alternative way is specifying a<br>
>> peer address which implicitly creates a similar routing entry (and<br>
>> peer can be the whole network).<br>
>><br>
>> > or that nspawn and networkd would interact in some way to add routes. However, this didn't seem to happen, so I also had to add the following to the bridge's .network file:<br>
>> ><br>
>> > [Route]<br>
>> > Source=37.x.x.x<br>
>> > Destination=91.x.x.A<br>
>> ><br>
>> > [Route]<br>
>> > Source=37.x.x.x<br>
>> > Destination=91.x.x.B<br>
>> ><br>
>><br>
>> Same as above. Host must know how to forward packets to the addresses<br>
>> 91.x.x.x and without routing entries nothing will tell the host how to<br>
>> do it. Routing is bidirectional; a container knowing how to forward<br>
>> traffic to the host does not automatically imply that the host knows<br>
>> how to forward traffic to the container.<br>
>><br>
>> > With all of this, everything works fine now. However, since the routes, both host-to-container and container-to-host, differ somewhat from the old (also working) setup,<br>
>><br>
>> Your working setup must have created the same routing entries because<br>
>> otherwise it would not work. Care to show your old configuration?<br>
>><br>
>> > and some of the steps necessary I could not find described anywhere, I am left wondering if I fundamentally misunderstand something about how Linux networking works, or if perhaps networkd is behaving oddly because of the IP addresses being considered in different networks.<br>
>><br>
>> You misunderstand how IP networking works. Nothing in your description<br>
>> is Linux specific.<br>
>><br>
>> ><br>
>> > I would love to find a conclusive answer to this, especially because I want to make sure I understood the fundamental concepts involved correctly.<br>
</blockquote></div>