Commit ec10fc4f3a for frr
commit ec10fc4f3a13cca20eecf153d0c8ffa9c7fdfab4
Author: Philippe Guibert <philippe.guibert@6wind.com>
Date: Wed Oct 7 17:33:00 2026 +0200
bgpd: fix mpls vpn nh label bind cache comparison
With 'mpls bgp l3vpn-multi-domain-switching', an ASBR receiving MPLS VPN
routes from several next-hops may fail to find an existing entry of the
nexthop label bind cache. A second entry is then created for the same
(nexthop, label) pair, with a second local label and a second MPLS
entry. This was found by code review, the issue becomes possible as soon
as the tree has to be rebalanced, i.e. with three distinct nexthops or
more.
bgp_mplsvpn_nh_label_bind_cmp() returns 1 whenever the two nexthops
differ, whatever the order given by prefix_cmp(). The comparison is not
antisymmetric: cmp(a, b) and cmp(b, a) both return 1. After a rotation
of the red-black tree, an entry with a different nexthop may be located
in the left subtree, whereas the lookup always goes right.
Return the result of prefix_cmp() when the nexthops differ.
Fixes: 29b49f67eb3c ("bgpd: add mpls vpn nh label bind cache struct and apis")
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 97aadf0aac..ff18935657 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -4389,8 +4389,11 @@ int bgp_mplsvpn_nh_label_bind_cmp(
const struct bgp_mplsvpn_nh_label_bind_cache *a,
const struct bgp_mplsvpn_nh_label_bind_cache *b)
{
- if (prefix_cmp(&a->nexthop, &b->nexthop))
- return 1;
+ int ret;
+
+ ret = prefix_cmp(&a->nexthop, &b->nexthop);
+ if (ret)
+ return ret;
if (a->orig_label > b->orig_label)
return 1;
if (a->orig_label < b->orig_label)