]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: fix hardset l3vpn label available in mpls pool
authorPhilippe Guibert <philippe.guibert@6wind.com>
Fri, 1 Sep 2023 15:14:06 +0000 (17:14 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Wed, 18 Oct 2023 07:41:02 +0000 (09:41 +0200)
Today, when configuring BGP L3VPN mpls, the operator may
use that command to hardset a label value:

> router bgp 65500 vrf vrf1
> address-family ipv4 unicast
> label vpn export <hardset_label_value>

Today, BGP uses this value without checks, leading to potential
conflicts with other control planes like LDP. For instance, if
LDP initiates with a label chunk of [16;72] and BGP also uses the
50 label value, a conflict arises.

The 'label manager' service in zebra oversees label allocations.
While all the control plane daemons use it, BGP doesn't when a
hardset label is in place.

This update fixes this problem. Now, when a hardset label is set for
l3vpn export, a request is made to the label manager for approval,
ensuring no conflicts with other daemons. But, this means some existing
BGP configurations might become non-operational if they conflict with
labels already allocated to another daemon but not used.

note: Labels below 16 are reserved and won't be checked for consistency
by the label manager.

Fixes: ddb5b4880ba8 ("bgpd: vpn-vrf route leaking")
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
bgpd/bgp_labelpool.c
bgpd/bgp_mplsvpn.h
bgpd/bgp_vty.c
bgpd/bgp_zebra.c
bgpd/bgp_zebra.h
bgpd/bgpd.h

index 883338610c64711e7dbf2116d6aa0d9197dc94f6..d33f14ac4192bb78de59f04f5c52ee4fd7a3013b 100644 (file)
@@ -448,7 +448,7 @@ void bgp_lp_get(
 
        if (lp_fifo_count(&lp->requests) > lp->pending_count) {
                if (!bgp_zebra_request_label_range(MPLS_LABEL_BASE_ANY,
-                                                  lp->next_chunksize))
+                                                  lp->next_chunksize, true))
                        return;
 
                lp->pending_count += lp->next_chunksize;
@@ -650,7 +650,8 @@ void bgp_lp_event_zebra_up(void)
         */
        list_delete_all_node(lp->chunks);
 
-       if (!bgp_zebra_request_label_range(MPLS_LABEL_BASE_ANY, labels_needed))
+       if (!bgp_zebra_request_label_range(MPLS_LABEL_BASE_ANY, labels_needed,
+                                          true))
                return;
 
        lp->pending_count = labels_needed;
index 19b6f4eb777e4e3547b90235eee1631f375ed5ca..b2bdfcec00fe641714c795ff9a75ccd658b98027 100644 (file)
@@ -13,6 +13,7 @@
 #include "bgpd/bgp_rd.h"
 #include "bgpd/bgp_zebra.h"
 #include "bgpd/bgp_vty.h"
+#include "bgpd/bgp_label.h"
 
 #define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION)
 #define MPLS_LABEL_IS_NULL(label)                                              \
@@ -165,6 +166,25 @@ static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
                return 0;
        }
 
+       /* Is there a "manual" export label that isn't allocated yet? */
+       if (!CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
+                       BGP_VPN_POLICY_TOVPN_LABEL_AUTO) &&
+           bgp_vrf->vpn_policy[afi].tovpn_label != BGP_PREVENT_VRF_2_VRF_LEAK &&
+           bgp_vrf->vpn_policy[afi].tovpn_label != MPLS_LABEL_NONE &&
+           (bgp_vrf->vpn_policy[afi].tovpn_label >= MPLS_LABEL_UNRESERVED_MIN &&
+            !CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
+                        BGP_VPN_POLICY_TOVPN_LABEL_MANUAL_REG))) {
+               if (!bgp_zebra_request_label_range(bgp_vrf->vpn_policy[afi]
+                                                          .tovpn_label,
+                                                  1, false)) {
+                       if (pmsg)
+                               *pmsg = "manual label could not be allocated";
+                       return 0;
+               }
+               SET_FLAG(bgp_vrf->vpn_policy[afi].flags,
+                        BGP_VPN_POLICY_TOVPN_LABEL_MANUAL_REG);
+       }
+
        return 1;
 }
 
index 48eaf1ed777be93ab8abbbbc0c65b98b9293e4f4..1ec66824c32c9259d0b43b28bc64f567d458f782 100644 (file)
@@ -9471,9 +9471,16 @@ DEFPY (af_label_vpn_export,
        vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
                           bgp_get_default(), bgp);
 
-       /* release any previous auto label */
        if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
-                      BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
+                      BGP_VPN_POLICY_TOVPN_LABEL_MANUAL_REG)) {
+               bgp_zebra_release_label_range(bgp->vpn_policy[afi].tovpn_label,
+                                             bgp->vpn_policy[afi].tovpn_label);
+               UNSET_FLAG(bgp->vpn_policy[afi].flags,
+                          BGP_VPN_POLICY_TOVPN_LABEL_MANUAL_REG);
+
+       } else if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
+                             BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
+               /* release any previous auto label */
                if (bgp->vpn_policy[afi].tovpn_label != MPLS_LABEL_NONE) {
 
                        /*
@@ -9501,9 +9508,16 @@ DEFPY (af_label_vpn_export,
                        bgp_lp_get(LP_TYPE_VRF, &bgp->vpn_policy[afi],
                                   vpn_leak_label_callback);
                } else {
+                       bgp->vpn_policy[afi].tovpn_label = label;
                        UNSET_FLAG(bgp->vpn_policy[afi].flags,
                                   BGP_VPN_POLICY_TOVPN_LABEL_AUTO);
-                       bgp->vpn_policy[afi].tovpn_label = label;
+                       if (bgp->vpn_policy[afi].tovpn_label >=
+                                   MPLS_LABEL_UNRESERVED_MIN &&
+                           bgp_zebra_request_label_range(bgp->vpn_policy[afi]
+                                                                 .tovpn_label,
+                                                         1, false))
+                               SET_FLAG(bgp->vpn_policy[afi].flags,
+                                        BGP_VPN_POLICY_TOVPN_LABEL_MANUAL_REG);
                }
        } else {
                UNSET_FLAG(bgp->vpn_policy[afi].flags,
index 212b7f398b4c3254433110fdbc73dfb19b0479a5..e53416044e0d62dc5da3564cc88067a4889b3b97 100644 (file)
@@ -3423,6 +3423,9 @@ static bool bgp_zebra_label_manager_connect(void)
        /* tell label pool that zebra is connected */
        bgp_lp_event_zebra_up();
 
+       /* tell BGP L3VPN that label manager is available */
+       if (bgp_get_default())
+               vpn_leak_postchange_all();
        return true;
 }
 
@@ -3921,7 +3924,8 @@ void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
        zebra_send_mpls_labels(zclient, cmd, &zl);
 }
 
-bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size)
+bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size,
+                                  bool label_auto)
 {
        int ret;
        uint32_t start, end;
@@ -3943,7 +3947,13 @@ bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size)
                return false;
        }
 
-       bgp_lp_event_chunk(start, end);
+       if (label_auto)
+               /* label automatic is serviced by the bgp label pool
+                * manager, which allocates label chunks in
+                * pre-pools, and which needs to be notified about
+                * new chunks availability
+                */
+               bgp_lp_event_chunk(start, end);
 
        return true;
 }
index 0edae041d2f9d1f063dd5e30bea760e531982a2f..4696e4dc44cb2142955754a4e51e234cbea31912 100644 (file)
@@ -124,6 +124,7 @@ extern void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
                                         enum lsp_types_t ltype,
                                         struct prefix *p, uint32_t num_labels,
                                         mpls_label_t out_labels[]);
-extern bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size);
+extern bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size,
+                                         bool label_auto);
 extern void bgp_zebra_release_label_range(uint32_t start, uint32_t end);
 #endif /* _QUAGGA_BGP_ZEBRA_H */
index bc2008b78ba279410d55d1ebc03ab64392b1f7a8..0dd421b46255ea524e7ec5d77b457de5adfd0b28 100644 (file)
@@ -217,6 +217,8 @@ struct vpn_policy {
 #define BGP_VPN_POLICY_TOVPN_NEXTHOP_SET       (1 << 2)
 #define BGP_VPN_POLICY_TOVPN_SID_AUTO          (1 << 3)
 #define BGP_VPN_POLICY_TOVPN_LABEL_PER_NEXTHOP (1 << 4)
+/* Manual label is registered with zebra label manager */
+#define BGP_VPN_POLICY_TOVPN_LABEL_MANUAL_REG (1 << 5)
 
        /*
         * If we are importing another vrf into us keep a list of