forked from Mirror/frr
bgpd: fix hardset l3vpn label available in mpls pool
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: ddb5b4880b
("bgpd: vpn-vrf route leaking")
Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
parent
1c199f219d
commit
d162d5f6f5
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_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,
|
||||
|
|
|
@ -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,6 +3947,12 @@ bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size)
|
|||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue