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)