On 5/11/2025 2:57 am, Ondrej Zajicek wrote:
On Tue, Nov 04, 2025 at 09:48:29PM +1100, William via Bird-users wrote:
Hi Ondrej,

Apologies on the delay, I'm testing when I have the brain space and my lab
is powered up.
Hi

Thanks for your feedback!
Always glad to be able to contribute back in some way 🙂
The "encapsulation vxlan" stanza is just for encompassing
encapsulation-specific options, to future-proof for possible
implementations of multiple encapsulations, but that should not matter
now.

Note that 'oz-evpn' is the main EVPN branch, while 'evpn' is more-less an old
snapshot.

There are some more changes in 'oz-evpn', like fix for BGP_PMSI_TUNNEL attribute flags (that is used in IMET routes) or announcing encapsulation extended communities.
The documentation is missing a chunk about the encapsulation, but I also had to resort to config.Y to find the VLAN definition block.

Adding vni <vni>; to the main protocol config breaks it, but works fine in the vlan <vid> block.  Still needed vid <vid> in the main protocol config though.  See attached working config for reference.

I've got mac-ip and imet routes floating around now, but the next issue is
that the wrong next-hop is being set on the imet (and mac-ip) routes.
Seems like a deviation on our side. EVPN protocol does not attach the
bgp_next_hop attribute, and such attribute is attached by BGP when
announced to BGP neighbor, based on BGP session endpoint address.

We should fix that, meanwhile you can workaround it by setting 'next hop address'
BGP channel option (in BGP EVPN channel) to the VNI address:

https://bird.nic.cz/doc/bird-2.17.2.html#bgp-next-hop-address
Did that as part of the evpn stanza in the EVPN BGP chunk and it worked a treat! (See attached config)


Here's the evpn protocol definition:
protocol evpn {
         eth {
                 table etab;
                 import all;
         };
         evpn { };
         rd 1005001:10040;
         import target (rt, 1004001, 10040);
         import target (rt, 1004003, 10040);
         export target (rt, 1005001, 10040);
Note that setting multiple 'import target' options just replace the previous ones with the last one.

You need to use a set syntax:

         import target [(rt, 1004001, 10040), (rt, 1004003, 10040)];

That is likely a bit confusing and at least should generate a warning.
That worked it a lot better :D

For what it's worth, 'bridge vlan add dev vxlan100 vid 40 tunnel_info id 40'
errors out.  The readme on
https://gitlab.nic.cz/labs/bird-tools/-/tree/master/netlab/cf-evpn-bgp has
typos in the commands too.
You mean typo del->add ?

instead of:  bridge vlan del dev $TUNNEL vid $VID tunnel_info id $VNI
should be:   bridge vlan add dev $TUNNEL vid $VID tunnel_info id $VNI

Note that with the latest 'oz-evpn' branch, BIRD configures VLANs on
VXLAN device automatically, but currently only for tagged vlans
(as in https://gitlab.nic.cz/labs/bird-tools/-/blob/master/netlab/cf-evpn-bgp-tags/bird_m12.conf )

That was correct, del needed to be changed to add.
I also found that bridge(8) won't let you set the tunnel info without the VLAN being defined first.

While everything *nearly* worked, after a couple of weeks I managed to work out that the bridge FDB entry that was being added was missing the source IP definition.  As a result the packet that entered the vxlan interface wasn't being forwarded upstream:

root@dc1-acc-1-deb:~# bridge fdb | grep vxlan
00:50:00:00:12:01 dev vxlan100 vlan 40 extern_learn master br1
42:a5:d1:11:88:4b dev vxlan100 vlan 40 master br1 permanent
42:a5:d1:11:88:4b dev vxlan100 master br1 permanent
00:00:00:00:00:00 dev vxlan100 dst 2001:db8:ffff:1ad::401 vni 10040 self extern_learn permanent 00:50:00:00:12:01 dev vxlan100 dst 2001:db8:ffff:1ad::401 vni 10040 self extern_learn permanent root@dc1-acc-1-deb:~# bridge fdb add 00:50:00:00:13:01 dev vxlan100 vni 10040 dst 2001:db8:ffff:1ad::401 via vxlan100 src_vni 10040 root@dc1-acc-1-deb:~# bridge fdb add 00:50:00:00:12:01 dev vxlan100 vni 10040 dst 2001:db8:ffff:1ad::401 via vxlan100 src_vni 10040
root@dc1-acc-1-deb:~#

With this in place it worked a treat:
root@dc1-acc-1-deb:~# bridge fdb | grep vxlan
00:50:00:00:12:01 dev vxlan100 vlan 40 extern_learn master br1
42:a5:d1:11:88:4b dev vxlan100 vlan 40 master br1 permanent
42:a5:d1:11:88:4b dev vxlan100 master br1 permanent
00:50:00:00:12:01 dev vxlan100 dst 2001:db8:ffff:1ad::401 vni 10040 src_vni 10040 via vxlan100 self permanent 00:00:00:00:00:00 dev vxlan100 dst 2001:db8:ffff:1ad::401 vni 10040 self extern_learn permanent 00:50:00:00:13:01 dev vxlan100 dst 2001:db8:ffff:1ad::401 vni 10040 src_vni 10040 via vxlan100 self permanent 00:50:00:00:12:01 dev vxlan100 dst 2001:db8:ffff:1ad::401 vni 10040 self extern_learn permanent
root@dc1-acc-1-deb:~#

can happily ping and throw traffic around now.  Haven't tried with extra VLANs/VNI's but I think it will be ok.

Probably worthy of another email, but bird segfaulted when br1 vanished (e.g. ip link delete br1).  I had noticed it previously when playing around, just replicated it for good measure.

2025-12-25T21:17:56.421191+11:00 dc1-acc-1-deb kernel: bird[1353]: segfault at 10 ip 00007f1c94833d6a sp 00007fff73a44ec8 error 4 in libc.so.6[182d6a,7f1c946d9000+165000] likely on CPU 2 (core 0, socket 2) 2025-12-25T21:17:56.421193+11:00 dc1-acc-1-deb kernel: Code: 8b 04 82 29 c8 c3 66 2e 0f 1f 84 00 00 00 00 00 89 f1 89 f8 48 83 e1 3f 48 83 e0 3f 83 f9 30 77 3f 83 f8 30 77 3a f3 0f 6f 0f <f3> 0f 6f 16 66 0f ef c0 66 0f 74 c1 66 0f 74 ca 66 0f f8 c8 66 0f

Merry Christmas, more work! :D

Regards,
William

--
This email has been checked for viruses by Avast antivirus software.
www.avast.com
log "/var/log/bird.log" { debug, trace, info, remote, warning, error, auth, 
fatal, bug };

router id 192.168.1.210;

debug protocols all;

evpn table evpntab;

eth table etab;

protocol device {
}

protocol direct {
        #ipv4;                  # Connect to default IPv4 table
        ipv6;                   # ... and to default IPv6 table
}

protocol kernel {
        ipv4 {                  # Connect protocol to IPv4 table by channel
              export all;       # Export to protocol. default is export none
        };
}

filter VXLAN_SRC {
        if net ~  [2001:db8:ffff:1ad::401/128, 2001:db8:ffff:1ad::201/128] then 
{
                krt_prefsrc = 2001:db8:ffff:1ad::501;
                accept;
        }
        accept;
}

protocol kernel {
        ipv6 {
                import all;
                #export filter VXLAN_SRC;
                export all;
         };
}

protocol static {
        ipv4;                   # Again, IPv4 channel with default options

}

filter SPINE_LO {
        if net.len = 128 then accept;
        reject;
}

protocol bgp SPINE1_BGP {
        ipv6 {
                import all;
                export filter SPINE_LO;
        };

        local 2001:db8:ffff:1f3::9 as 4201005001;
        neighbor 2001:db8:ffff:1f3::8 as 4201003001;
}

protocol bgp SPINE2_BGP {
        ipv6 {
                import all;
                export filter SPINE_LO;
        };

        local 2001:db8:ffff:1f3::109 as 4201005001;
        neighbor 2001:db8:ffff:1f3::108 as 4201003001;
        disabled;
}

protocol bgp SPINE1_EVPN {
        evpn {
                import all;
                #export filter { bgp_next_hop = 2001:db8:ffff:1ad::501; accept; 
};
                export all;
                next hop address 2001:db8:ffff:1ad::501;
        };

        local 2001:db8:ffff:1aa::501 as 4201005001;
        neighbor 2001:db8:ffff:1aa::1 as 4201003001;
        multihop;
}

protocol bgp SPINE2_EVPN {
        evpn {
                import all;
                export none;
        };

        local 2001:db8:ffff:1aa::501 as 4201005001;
        neighbor 2001:db8:ffff:1aa::2 as 4201003001;
        multihop;
        disabled;
}

protocol bridge {
        eth {
                table etab;
                import all;
                export all;
        };
        bridge device "br1";
        vlan filtering;
        debug all;
};

protocol evpn {
        eth {
                table etab;
                import all;
                export all;
        };
        evpn;

        encapsulation vxlan {
                tunnel device "vxlan100";
                #router address 2001:db8:ffff:1f3::9;
                router address 2001:db8:ffff:1ad::501;
        };

        rd 1005001:10040;
        import target [(rt, 1004001, 10040), (rt, 1004003, 10040)];
#import target (rt, 1004003, 10040);
        export target (rt, 1005001, 10040);

        vlan 40 {
                vni 10040;
                vid 40;
        };

#       vni 10040;
        vid 40;

        debug all;
};

Reply via email to