bgpd: vpn-vrf leaking: use dynamic label pool for "auto" labels

Add support for CLI "auto" keyword in vrf->vpn export label:

    router bgp NNN vrf FOO
	address-family ipv4 unicast
	    label vpn export auto
	exit-address-family

Signed-off-by: G. Paul Ziemba <paulz@labn.net>
This commit is contained in:
G. Paul Ziemba 2018-04-07 11:32:52 -07:00
parent 955bfd984f
commit e70e9f8e24
7 changed files with 157 additions and 32 deletions

View File

@ -310,6 +310,65 @@ void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi)
bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent = label;
}
int vpn_leak_label_callback(
mpls_label_t label,
void *labelid,
bool allocated)
{
struct vpn_policy *vp = (struct vpn_policy *)labelid;
int debug = BGP_DEBUG(vpn, VPN_LEAK_LABEL);
if (debug)
zlog_debug("%s: label=%u, allocated=%d",
__func__, label, allocated);
if (!allocated) {
/*
* previously-allocated label is now invalid
*/
if (CHECK_FLAG(vp->flags, BGP_VPN_POLICY_TOVPN_LABEL_AUTO) &&
(vp->tovpn_label != MPLS_LABEL_NONE)) {
vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN,
vp->afi, bgp_get_default(), vp->bgp);
vp->tovpn_label = MPLS_LABEL_NONE;
vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN,
vp->afi, bgp_get_default(), vp->bgp);
}
return 0;
}
/*
* New label allocation
*/
if (!CHECK_FLAG(vp->flags, BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
/*
* not currently configured for auto label, reject allocation
*/
return -1;
}
if (vp->tovpn_label != MPLS_LABEL_NONE) {
if (label == vp->tovpn_label) {
/* already have same label, accept but do nothing */
return 0;
}
/* Shouldn't happen: different label allocation */
zlog_err("%s: %s had label %u but got new assignment %u",
__func__, vp->bgp->name_pretty, vp->tovpn_label, label);
/* use new one */
}
vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN,
vp->afi, bgp_get_default(), vp->bgp);
vp->tovpn_label = label;
vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN,
vp->afi, bgp_get_default(), vp->bgp);
return 0;
}
static int ecom_intersect(struct ecommunity *e1, struct ecommunity *e2)
{
int i;

View File

@ -77,6 +77,7 @@ extern void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn,
extern void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi);
extern void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi);
extern int vpn_leak_label_callback(mpls_label_t label, void *lblid, bool alloc);
static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
const char **pmsg)
@ -111,6 +112,17 @@ static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
*pmsg = "rd not defined";
return 0;
}
/* Is there an "auto" 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 == MPLS_LABEL_NONE)) {
if (pmsg)
*pmsg = "auto label not allocated";
return 0;
}
return 1;
}

View File

@ -6245,12 +6245,13 @@ ALIAS (af_rd_vpn_export,
DEFPY (af_label_vpn_export,
af_label_vpn_export_cmd,
"[no] label vpn export (0-1048575)$label_val",
"[no] label vpn export <(0-1048575)$label_val|auto$label_auto>",
NO_STR
"label value for VRF\n"
"Between current address-family and vpn\n"
"For routes leaked from current address-family to vpn\n"
"Label Value <0-1048575>\n")
"Label Value <0-1048575>\n"
"Automatically assign a label\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
mpls_label_t label = MPLS_LABEL_NONE;
@ -6263,8 +6264,10 @@ DEFPY (af_label_vpn_export,
if (argv_find(argv, argc, "no", &idx))
yes = 0;
if (yes)
label = label_val; /* rely on parser to force unsigned */
if (yes) {
if (!label_auto)
label = label_val; /* parser should force unsigned */
}
ret = vpn_policy_getafi(vty, doafi);
if (ret != CMD_SUCCESS)
@ -6274,13 +6277,48 @@ DEFPY (af_label_vpn_export,
if (!doafi[afi])
continue;
if (label_auto && CHECK_FLAG(bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_LABEL_AUTO))
continue; /* no change */
/*
* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
*/
vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
bgp_get_default(), bgp);
if (!label_auto && CHECK_FLAG(bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
if (bgp->vpn_policy[afi].tovpn_label !=
MPLS_LABEL_NONE) {
/*
* label has previously been automatically
* assigned by labelpool: release it
*
* NB if tovpn_label == MPLS_LABEL_NONE it
* means the automatic assignment is in flight
* and therefore the labelpool callback must
* detect that the auto label is not needed.
*/
bgp_lp_release(LP_TYPE_VRF,
&bgp->vpn_policy[afi],
bgp->vpn_policy[afi].tovpn_label);
}
UNSET_FLAG(bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_LABEL_AUTO);
}
bgp->vpn_policy[afi].tovpn_label = label;
if (label_auto) {
SET_FLAG(bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_LABEL_AUTO);
bgp_lp_get(LP_TYPE_VRF, &bgp->vpn_policy[afi],
vpn_leak_label_callback);
}
/* post-change: re-export vpn routes */
vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
@ -11706,9 +11744,16 @@ void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
{
int indent = 2;
if (bgp->vpn_policy[afi].tovpn_label != MPLS_LABEL_NONE) {
vty_out(vty, "%*slabel vpn export %u\n", indent, "",
bgp->vpn_policy[afi].tovpn_label);
if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
vty_out(vty, "%*slabel vpn export %s\n", indent, "", "auto");
} else {
if (bgp->vpn_policy[afi].tovpn_label != MPLS_LABEL_NONE) {
vty_out(vty, "%*slabel vpn export %u\n", indent, "",
bgp->vpn_policy[afi].tovpn_label);
}
}
if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_RD_SET)) {

View File

@ -1878,7 +1878,7 @@ static void bgp_zebra_connected(struct zclient *zclient)
bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
/* tell label pool that zebra is connected */
lp_event_zebra_up();
bgp_lp_event_zebra_up();
/* TODO - What if we have peers and networks configured, do we have to
* kick-start them?
@ -2075,7 +2075,7 @@ static void bgp_zebra_process_label_chunk(
first, last, response_keep);
}
lp_event_chunk(response_keep, first, last);
bgp_lp_event_chunk(response_keep, first, last);
stream_failure: /* for STREAM_GETX */
return;

View File

@ -2951,6 +2951,8 @@ static struct bgp *bgp_create(as_t *as, const char *name,
#endif /* ENABLE_BGP_VNC */
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
bgp->vpn_policy[afi].bgp = bgp;
bgp->vpn_policy[afi].afi = afi;
bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent =
MPLS_LABEL_NONE;
@ -7537,7 +7539,7 @@ void bgp_master_init(struct thread_master *master)
bgp_option_set(BGP_OPT_MULTIPLE_INSTANCE);
/* mpls label dynamic allocation pool */
lp_init(bm->master, &bm->labelpool);
bgp_lp_init(bm->master, &bm->labelpool);
QOBJ_REG(bm, bgp_master);
}
@ -7718,5 +7720,5 @@ void bgp_terminate(void)
if (bm->t_rmap_update)
BGP_TIMER_OFF(bm->t_rmap_update);
lp_finish();
bgp_lp_finish();
}

View File

@ -171,6 +171,25 @@ typedef enum {
BGP_VPN_POLICY_DIR_MAX = 2
} vpn_policy_direction_t;
struct vpn_policy {
struct bgp *bgp; /* parent */
afi_t afi;
struct ecommunity *rtlist[BGP_VPN_POLICY_DIR_MAX];
struct ecommunity *import_redirect_rtlist;
char *rmap_name[BGP_VPN_POLICY_DIR_MAX];
struct route_map *rmap[BGP_VPN_POLICY_DIR_MAX];
/* should be mpls_label_t? */
uint32_t tovpn_label; /* may be MPLS_LABEL_NONE */
uint32_t tovpn_zebra_vrf_label_last_sent;
struct prefix_rd tovpn_rd;
struct prefix tovpn_nexthop; /* unset => set to 0 */
uint32_t flags;
#define BGP_VPN_POLICY_TOVPN_LABEL_AUTO (1 << 0)
#define BGP_VPN_POLICY_TOVPN_RD_SET (1 << 1)
#define BGP_VPN_POLICY_TOVPN_NEXTHOP_SET (1 << 2)
};
/*
* Type of 'struct bgp'.
* - Default: The default instance
@ -469,22 +488,7 @@ struct bgp {
/* route map for advertise ipv4/ipv6 unicast (type-5 routes) */
struct bgp_rmap adv_cmd_rmap[AFI_MAX][SAFI_MAX];
/* vpn-policy */
struct {
struct ecommunity *rtlist[BGP_VPN_POLICY_DIR_MAX];
struct ecommunity *import_redirect_rtlist;
char *rmap_name[BGP_VPN_POLICY_DIR_MAX];
struct route_map *rmap[BGP_VPN_POLICY_DIR_MAX];
/* should be mpls_label_t? */
uint32_t tovpn_label; /* may be MPLS_LABEL_NONE */
uint32_t tovpn_zebra_vrf_label_last_sent;
struct prefix_rd tovpn_rd;
struct prefix tovpn_nexthop; /* unset => set to 0 */
uint32_t flags;
#define BGP_VPN_POLICY_TOVPN_RD_SET 0x00000004
#define BGP_VPN_POLICY_TOVPN_NEXTHOP_SET 0x00000008
} vpn_policy[AFI_MAX];
struct vpn_policy vpn_policy[AFI_MAX];
QOBJ_FIELDS
};

View File

@ -1606,14 +1606,17 @@ address-family:
Deletes any previously-configured import or export route-target list.
.. index:: label vpn export (0..1048575)
.. clicmd:: label vpn export (0..1048575)
.. index:: label vpn export (0..1048575)|auto
.. clicmd:: label vpn export (0..1048575)|auto
Specifies an optional MPLS label to be attached to a route exported from the
current unicast VRF to VPN.
current unicast VRF to VPN. If label is specified as ``auto``, the label
value is automatically assigned from a pool maintained by the zebra
daemon. If zebra is not running, automatic label assignment will not
complete, which will block corresponding route export.
.. index:: no label vpn export [(0..1048575)]
.. clicmd:: no label vpn export [(0..1048575)]
.. index:: no label vpn export [(0..1048575)|auto]
.. clicmd:: no label vpn export [(0..1048575)|auto]
Deletes any previously-configured export label.