From 73dcde4b986eabe8f26b8c2cac83e6dc1915158d Mon Sep 17 00:00:00 2001
From: tomasmatus <tomatus777@tomatus.cz>
Date: Fri, 20 Mar 2026 10:39:38 +0100
Subject: [PATCH] evpn: handle multiple routes for the same host

Allow installing multiple routes from EVPN table into ETH table.
Install the current best route from ETH table into kernel bridge.
---
 proto/bridge/bridge.c | 13 ++++++++++---
 proto/evpn/evpn.c     |  7 ++++---
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/proto/bridge/bridge.c b/proto/bridge/bridge.c
index 231fc699..bfa9a890 100644
--- a/proto/bridge/bridge.c
+++ b/proto/bridge/bridge.c
@@ -127,9 +127,16 @@ kbr_rt_notify(struct proto *P, struct channel *c0 UNUSED, net *net, rte *new, rt
     return;
   }
 
-  /* For regular routes, we have one bridge entry, perhaps also one tunnel entry */
-  kbr_replace_fdb(n, new, old, 0);
-  kbr_replace_fdb(n, new_gw, old_gw, 1);
+  /*
+   * For regular routes, we have one bridge entry, perhaps also one tunnel entry.
+   *
+   * Multiple routes from different PEs may exist for multihomed hosts,
+   * install the current best route available.
+   */
+  rte *best = net->routes;
+  rte *best_gw = (best && ipa_nonzero(best->attrs->nh.gw)) ? best : NULL;
+  kbr_replace_fdb(n, best, old, 0);
+  kbr_replace_fdb(n, best_gw, old_gw, 1);
 }
 
 static inline int
diff --git a/proto/evpn/evpn.c b/proto/evpn/evpn.c
index 10f1a3da..1f532112 100644
--- a/proto/evpn/evpn.c
+++ b/proto/evpn/evpn.c
@@ -301,6 +301,7 @@ static void
 evpn_receive_mac(struct evpn_proto *p, const net_addr_evpn_mac *n0, rte *new)
 {
   struct channel *c = p->eth_channel;
+  struct rte_src *s = rt_get_source(&p->p, rd_to_u64(n0->rd));
   struct evpn_vlan *v = evpn_get_vlan_by_tag(p, n0->tag);
 
   net_addr *n = alloca(sizeof(net_addr_eth));
@@ -338,13 +339,13 @@ evpn_receive_mac(struct evpn_proto *p, const net_addr_evpn_mac *n0, rte *new)
     /* Hack to handle src_vni in bridge code */
     ea_set_attr_u32(&a->eattrs, tmp_linpool, EA_MPLS_LABEL, 0, EAF_TYPE_INT, v->vni);
 
-    rte *e = rte_get_temp(a, p->p.main_source);
-    rte_update2(c, n, e, p->p.main_source);
+    rte *e = rte_get_temp(a, s);
+    rte_update2(c, n, e, s);
   }
   else
   {
   withdraw:
-    rte_update2(c, n, NULL, p->p.main_source);
+    rte_update2(c, n, NULL, s);
   }
 }
 
-- 
2.53.0

