Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bgpd: Fix crash in bgp_labelpool (backport #18079) #18145

Merged
merged 1 commit into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion bgpd/bgp_label.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,8 @@ void bgp_reg_dereg_for_label(struct bgp_dest *dest, struct bgp_path_info *pi,
*/
if (!have_label_to_reg) {
SET_FLAG(dest->flags, BGP_NODE_LABEL_REQUESTED);
struct bgp_table *table;

if (BGP_DEBUG(labelpool, LABELPOOL))
zlog_debug(
"%s: Requesting label from LP for %pFX",
Expand All @@ -396,7 +398,9 @@ void bgp_reg_dereg_for_label(struct bgp_dest *dest, struct bgp_path_info *pi,
* the pool. This means we'll never register
* FECs withoutvalid labels.
*/
bgp_lp_get(LP_TYPE_BGP_LU, dest,
table = bgp_dest_table(dest);

bgp_lp_get(LP_TYPE_BGP_LU, dest, table->bgp->vrf_id,
bgp_reg_for_label_callback);
return;
}
Expand Down
24 changes: 15 additions & 9 deletions bgpd/bgp_labelpool.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ struct lp_lcb {
mpls_label_t label; /* MPLS_LABEL_NONE = not allocated */
int type;
void *labelid; /* unique ID */
vrf_id_t vrf_id;
/*
* callback for label allocation and loss
*
Expand All @@ -97,6 +98,7 @@ struct lp_cbq_item {
int type;
mpls_label_t label;
void *labelid;
vrf_id_t vrf_id;
bool allocated; /* false = lost */
};

Expand All @@ -105,6 +107,7 @@ static wq_item_status lp_cbq_docallback(struct work_queue *wq, void *data)
struct lp_cbq_item *lcbq = data;
int rc;
int debug = BGP_DEBUG(labelpool, LABELPOOL);
struct bgp *bgp = bgp_lookup_by_vrf_id(lcbq->vrf_id);

if (debug)
zlog_debug("%s: calling callback with labelid=%p label=%u allocated=%d",
Expand All @@ -117,6 +120,9 @@ static wq_item_status lp_cbq_docallback(struct work_queue *wq, void *data)
return WQ_SUCCESS;
}

if (!bgp)
return WQ_SUCCESS;

rc = (*(lcbq->cbfunc))(lcbq->label, lcbq->labelid, lcbq->allocated);

if (lcbq->allocated && rc) {
Expand Down Expand Up @@ -320,10 +326,8 @@ static mpls_label_t get_label_from_pool(void *labelid)
/*
* Success indicated by value of "label" field in returned LCB
*/
static struct lp_lcb *lcb_alloc(
int type,
void *labelid,
int (*cbfunc)(mpls_label_t label, void *labelid, bool allocated))
static struct lp_lcb *lcb_alloc(int type, void *labelid, vrf_id_t vrf_id,
int (*cbfunc)(mpls_label_t label, void *labelid, bool allocated))
{
/*
* Set up label control block
Expand All @@ -334,6 +338,7 @@ static struct lp_lcb *lcb_alloc(
new->label = get_label_from_pool(labelid);
new->type = type;
new->labelid = labelid;
new->vrf_id = vrf_id;
new->cbfunc = cbfunc;

return new;
Expand Down Expand Up @@ -365,10 +370,8 @@ static struct lp_lcb *lcb_alloc(
* Prior requests for a given labelid are detected so that requests and
* assignments are not duplicated.
*/
void bgp_lp_get(
int type,
void *labelid,
int (*cbfunc)(mpls_label_t label, void *labelid, bool allocated))
void bgp_lp_get(int type, void *labelid, vrf_id_t vrf_id,
int (*cbfunc)(mpls_label_t label, void *labelid, bool allocated))
{
struct lp_lcb *lcb;
int requested = 0;
Expand All @@ -383,7 +386,7 @@ void bgp_lp_get(
if (!skiplist_search(lp->ledger, labelid, (void **)&lcb)) {
requested = 1;
} else {
lcb = lcb_alloc(type, labelid, cbfunc);
lcb = lcb_alloc(type, labelid, vrf_id, cbfunc);
if (debug)
zlog_debug("%s: inserting lcb=%p label=%u",
__func__, lcb, lcb->label);
Expand Down Expand Up @@ -413,6 +416,7 @@ void bgp_lp_get(
q->type = lcb->type;
q->label = lcb->label;
q->labelid = lcb->labelid;
q->vrf_id = lcb->vrf_id;
q->allocated = true;

/* if this is a LU request, lock node before queueing */
Expand Down Expand Up @@ -580,6 +584,7 @@ static void bgp_sync_label_manager(struct event *e)
q->type = lcb->type;
q->label = lcb->label;
q->labelid = lcb->labelid;
q->vrf_id = lcb->vrf_id;
q->allocated = true;

if (debug)
Expand Down Expand Up @@ -693,6 +698,7 @@ void bgp_lp_event_zebra_up(void)
q->type = lcb->type;
q->label = lcb->label;
q->labelid = lcb->labelid;
q->vrf_id = lcb->vrf_id;
q->allocated = false;
check_bgp_lu_cb_lock(lcb);
work_queue_add(lp->callback_q, q);
Expand Down
4 changes: 2 additions & 2 deletions bgpd/bgp_labelpool.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ struct labelpool {

extern void bgp_lp_init(struct event_loop *master, struct labelpool *pool);
extern void bgp_lp_finish(void);
extern void bgp_lp_get(int type, void *labelid,
int (*cbfunc)(mpls_label_t label, void *labelid, bool allocated));
extern void bgp_lp_get(int type, void *labelid, vrf_id_t vrf_id,
int (*cbfunc)(mpls_label_t label, void *labelid, bool allocated));
extern void bgp_lp_release(int type, void *labelid, mpls_label_t label);
extern void bgp_lp_event_chunk(uint32_t first, uint32_t last);
extern void bgp_lp_event_zebra_down(void);
Expand Down
7 changes: 4 additions & 3 deletions bgpd/bgp_mplsvpn.c
Original file line number Diff line number Diff line change
Expand Up @@ -1399,7 +1399,7 @@ _vpn_leak_from_vrf_get_per_nexthop_label(struct bgp_path_info *pi,
/* request a label to zebra for this nexthop
* the response from zebra will trigger the callback
*/
bgp_lp_get(LP_TYPE_NEXTHOP, blnc,
bgp_lp_get(LP_TYPE_NEXTHOP, blnc, from_bgp->vrf_id,
bgp_mplsvpn_get_label_per_nexthop_cb);
}

Expand Down Expand Up @@ -1439,7 +1439,8 @@ static mpls_label_t bgp_mplsvpn_get_vpn_label(struct vpn_policy *bgp_policy)
{
if (bgp_policy->tovpn_label == MPLS_LABEL_NONE &&
CHECK_FLAG(bgp_policy->flags, BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
bgp_lp_get(LP_TYPE_VRF, bgp_policy, vpn_leak_label_callback);
bgp_lp_get(LP_TYPE_VRF, bgp_policy, bgp_policy->bgp->vrf_id,
vpn_leak_label_callback);
return MPLS_INVALID_LABEL;
}
return bgp_policy->tovpn_label;
Expand Down Expand Up @@ -4245,7 +4246,7 @@ void bgp_mplsvpn_nh_label_bind_register_local_label(struct bgp *bgp,
label);
bmnc->bgp_vpn = bgp;
bmnc->allocation_in_progress = true;
bgp_lp_get(LP_TYPE_BGP_L3VPN_BIND, bmnc,
bgp_lp_get(LP_TYPE_BGP_L3VPN_BIND, bmnc, bgp->vrf_id,
bgp_mplsvpn_nh_label_bind_get_local_label_cb);
}

Expand Down
Loading