Hello! I seem to have hit a strange inconsistency when OSPFv2 does not create routes for its PtP transit interfaces and am not sure whether I am misunderstanding the protocol. I managed to reduce my case into the following setup (full Linux netns reproducer script is at the end): There are three machines, called Local, Remote and Foreign and OSPFv2 running among them. Local is the middle one, having a virtual ethernet to Foreign (IP addresses 10.2.0.0/24) and a 4in6 tunnel to Remote (10.1.0.1 and 10.1.0.2). Moreover, the Local and Remote machines have a dummy interface with another local address (10.0.0.1, 10.0.0.2). In this case, OSPF converges, but the routing tables on Local and Remote are missing the route for 10.1.0.0/30: ``` Table master4: 10.2.0.0/24 unicast [ospf1 03:24:08.362] * I (10/100) [0.0.0.3] dev en_f 10.0.0.1/32 unicast [ospf1 03:23:27.361] * I (10/0) [0.0.0.1] dev dummy0 10.0.0.2/32 unicast [ospf1 03:23:43.363] * I (10/100) [0.0.0.2] via 10.1.0.2 on tun0 ``` OSPF is about the 10.1.0.0/30 addresses, breaking connection between Foreign and Remote. Surprisingly, if the tunnel interface is marked as stub, then the route is imported in the same manner as the route on the veth (but the toy network now has two independent instances of OSPF, effectively being split). The missing route can be added by enabling the Direct protocols but this feels quite off, as the route should not be external to OSPF. Also, the Direct protocol documentation suggests that this should not be necessary: “OSPF protocol creates device routes for its interfaces itself […]”. My reproducer runs on Arch Linux with BIRD 3.1.1, but also appears on my router running BIRD 2.13.1. Am I misunderstanding something, or is this actually a bug? Best regards, LEdoian --- #!/bin/bash # intended to be run inside `unshare -rnmpf --mount-proc` # uses tmux to keep sessions and to run BIRDs in background set -e dir="$(mktemp -d)" mount -t tmpfs bird-repro "$dir" trap 'cd / && umount --recursive "$dir" && rmdir "$dir"' EXIT # does not work cd "$dir" cat >bird.inc <<GO log stderr all; debug protocols all; protocol device { } protocol direct{ ipv4; disabled; } protocol kernel ker4 { learn; ipv4 { preference 100; import all; export all; }; } protocol ospf v2 { ipv4 { preference 10; import all; export all; }; area 0 { interface "tun*" { cost 100; #stub; }; interface "dummy*" { cost 100; stub; }; interface "en*" { cost 100; }; }; } GO cat >local.conf <<GO router id 0.0.0.1; include "bird.inc"; GO cat >remote.conf <<GO router id 0.0.0.2; include "bird.inc"; GO cat >foreign.conf <<GO router id 0.0.0.3; include "bird.inc"; GO for x in remote local; do touch $x unshare --net=$x ip link add dummy0 type dummy nsenter --net=$x ip link set dummy0 up done nsenter --net=local ip addr add 10.0.0.1/32 dev dummy0 nsenter --net=remote ip addr add 10.0.0.2/32 dev dummy0 ip link add name ve0 type veth peer ve1 ip link set ve0 netns ./local ip link set ve1 name ve0 ip link set ve0 netns ./remote nsenter --net=local ip addr add fd00::1/64 dev ve0 nsenter --net=remote ip addr add fd00::2/64 dev ve0 nsenter --net=local ip link set ve0 up nsenter --net=remote ip link set ve0 up nsenter --net=local ip link add tun0 type ip6tnl mode ipip6 local fd00::1 remote fd00::2 nsenter --net=local ip link set tun0 up nsenter --net=local ip addr add 10.1.0.1 dev tun0 peer 10.1.0.2 nsenter --net=remote ip link add tun0 type ip6tnl mode ipip6 local fd00::2 remote fd00::1 nsenter --net=remote ip link set tun0 up nsenter --net=remote ip addr add 10.1.0.2 dev tun0 peer 10.1.0.1 touch foreign unshare --net=foreign true ip link add name en_f type veth peer en_l ip link set en_f netns ./local ip link set en_l netns ./foreign nsenter --net=foreign ip link set en_l up nsenter --net=foreign ip addr add 10.2.0.3/24 dev en_l nsenter --net=local ip link set en_f up nsenter --net=local ip addr add 10.2.0.2/24 dev en_f nsenter --net=local sysctl net.ipv4.conf.all.forwarding=1 for x in local remote foreign; do nsenter --net=$x tmux -S $x.tmux new-session -d bird -d -c $x.conf -s $x.bird done tmux