mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 14:49:09 +00:00
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:
parent
955bfd984f
commit
e70e9f8e24
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
36
bgpd/bgpd.h
36
bgpd/bgpd.h
@ -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
|
||||
};
|
||||
|
@ -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.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user