Hello BIRDs!

I am trying out EVPN in a multi-vendor environment (namely against Arista and 
Huawei CE6881E) on an IPv4 underlay and I noticed that neither of these vendors 
are considering EVPN routes received from BIRD as valid.
When I inspect EVPN routes on Huawei it shows that the next-hop address is an 
IPv4 mapped to IPv6 on all routes from BIRD. To keep it short I'll only include 
one IMET route from Arista (10.10.10.1) and one from BIRD (10.10.10.3) where 
the route from Arista has IPv4 next-hop and route from BIRD does not.
-----
[~vx-4]displ bgp evpn all routing-table inclusive-route
Local AS number : 65000
BGP Local router ID is 10.10.10.2
Status codes: * - valid, > - best, d - damped, x - best external, a - add path,
h - history, i - internal, s - suppressed, S - Stale
Origin : i - IGP, e - EGP, ? - incomplete

Route Distinguisher: 10.10.10.1:10010
Network(EthTagId/IpAddrLen/OriginalIp) NextHop *>i 0:32:10.10.10.1 10.10.10.1
Route Distinguisher: 10.10.10.3:10010
Network(EthTagId/IpAddrLen/OriginalIp) NextHop i 0:32:10.10.10.3 
::FFFF:10.10.10.3
-----
I also checked with Wireshark and BIRD really sends an IPv6 next hop. I am 
using the following config for BGP:
-----
template bgp evpn_peer {
local as 65000;
source address 10.10.10.3;

ipv4 {
import none;
# routed by ospf in underlay
export none;
};

evpn {
import all;
export all;
};
}

protocol bgp bgp_Huawei from evpn_peer {
neighbor 10.10.10.2 as 65000;
}-----
Looking at the BIRD BGP docs I also tried explicitly setting "next hop address 
10.10.10.3" in the evpn block but the result was the same. I understand that 
this could technically fall under RFC 8950 and the "extended next hop <switch>" 
option in which case it would be okay to send the next hop as IPv6 however by 
default this option should be disabled in BIRD and even if I explicitly disable 
it I still see the next hop as IPv6. I looked over how the BGP packets are 
constructed and I think this comes down to the bgp_encode_next_hop_ip() 
function where the bgp_channel_is_ipv4(s->channel) only checks for BGP_AFI_IPV4 
and returns false for EVPN AF so it falls through and sets the next-hop address 
as IPv6. I've attached a patch which fixes this behavior but I'm certain it is 
far from perfect.
I also went back to my BIRD-only lab and I can see the same behavior. In this 
case however I think either the kernel is smart enough to figure out it is an 
IPv4 mapped to IPv6 and therefore treats it as IPv4 or BIRD handles it because 
the internal representation is the same.
Am I right to consider this as a bug or is there something I missed? I don't 
have any experience with other Address Families in BGP with BIRD so I am not 
sure how bird behaves there when setting the next-hop address.

With my patch applied I am happy to share that the EVPN control-plane works and 
I don't see any other issues. Received IMET and MAC routes are imported and get 
propagated into the linux bridge interface and routes exported by BIRD are also 
installed by the other two vendors. So far I'm only using L2 VNIs and I haven't 
yet configured Huawei/Arista to include IP address in the Type 2 routes, I 
expect that BIRD does not support this yet but I am at least curious if it can 
handle without crashing, or, when used as Route Reflector, if it can reflect 
such routes. If you have any other ideas what would be worth trying out, please 
let me know!

PS: Thank you Ondřej for including my previous bug report in the latest rebase 
of the oz-evpn branch!

Thank you and have a nice day!
Tomáš
From bda51a9456b4b3c4a07ddc04ecf026808b696259 Mon Sep 17 00:00:00 2001
From: tomasmatus <[email protected]>
Date: Fri, 20 Feb 2026 17:59:37 +0100
Subject: [PATCH] FIX: BGP EVPN AF always sets next-hop address in IPv6 format

---
 proto/bgp/packets.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index 694d2bf5..a13c4b3f 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -1389,6 +1389,12 @@ bgp_encode_next_hop_ip(struct bgp_write_state *s, eattr *a, byte *buf, uint size
     return 4;
   }
 
+  if (bgp_channel_is_l2vpn(s->channel) && ipa_is_ip4(nh[0]) && !s->channel->ext_next_hop)
+  {
+    put_ip4(buf, ipa_to_ip4(nh[0]));
+    return 4;
+  }
+
   /* Handle variants of link-local-only next hop */
   if (ipa_zero(nh[0]) && (len == 32))
   {
-- 
2.53.0

Reply via email to