mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 15:33:56 +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;
|
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)
|
static int ecom_intersect(struct ecommunity *e1, struct ecommunity *e2)
|
||||||
{
|
{
|
||||||
int i;
|
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_update(struct bgp *bgp, afi_t afi);
|
||||||
extern void vpn_leak_zebra_vrf_label_withdraw(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,
|
static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
|
||||||
const char **pmsg)
|
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";
|
*pmsg = "rd not defined";
|
||||||
return 0;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6245,12 +6245,13 @@ ALIAS (af_rd_vpn_export,
|
|||||||
|
|
||||||
DEFPY (af_label_vpn_export,
|
DEFPY (af_label_vpn_export,
|
||||||
af_label_vpn_export_cmd,
|
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
|
NO_STR
|
||||||
"label value for VRF\n"
|
"label value for VRF\n"
|
||||||
"Between current address-family and vpn\n"
|
"Between current address-family and vpn\n"
|
||||||
"For routes leaked from current address-family to 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);
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
mpls_label_t label = MPLS_LABEL_NONE;
|
mpls_label_t label = MPLS_LABEL_NONE;
|
||||||
@ -6263,8 +6264,10 @@ DEFPY (af_label_vpn_export,
|
|||||||
if (argv_find(argv, argc, "no", &idx))
|
if (argv_find(argv, argc, "no", &idx))
|
||||||
yes = 0;
|
yes = 0;
|
||||||
|
|
||||||
if (yes)
|
if (yes) {
|
||||||
label = label_val; /* rely on parser to force unsigned */
|
if (!label_auto)
|
||||||
|
label = label_val; /* parser should force unsigned */
|
||||||
|
}
|
||||||
|
|
||||||
ret = vpn_policy_getafi(vty, doafi);
|
ret = vpn_policy_getafi(vty, doafi);
|
||||||
if (ret != CMD_SUCCESS)
|
if (ret != CMD_SUCCESS)
|
||||||
@ -6274,13 +6277,48 @@ DEFPY (af_label_vpn_export,
|
|||||||
if (!doafi[afi])
|
if (!doafi[afi])
|
||||||
continue;
|
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)
|
* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
|
||||||
*/
|
*/
|
||||||
vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
bgp_get_default(), bgp);
|
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;
|
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 */
|
/* post-change: re-export vpn routes */
|
||||||
vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
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;
|
int indent = 2;
|
||||||
|
|
||||||
if (bgp->vpn_policy[afi].tovpn_label != MPLS_LABEL_NONE) {
|
if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
|
||||||
vty_out(vty, "%*slabel vpn export %u\n", indent, "",
|
BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
|
||||||
bgp->vpn_policy[afi].tovpn_label);
|
|
||||||
|
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,
|
if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
|
||||||
BGP_VPN_POLICY_TOVPN_RD_SET)) {
|
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);
|
bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
|
||||||
|
|
||||||
/* tell label pool that zebra is connected */
|
/* 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
|
/* TODO - What if we have peers and networks configured, do we have to
|
||||||
* kick-start them?
|
* kick-start them?
|
||||||
@ -2075,7 +2075,7 @@ static void bgp_zebra_process_label_chunk(
|
|||||||
first, last, response_keep);
|
first, last, response_keep);
|
||||||
}
|
}
|
||||||
|
|
||||||
lp_event_chunk(response_keep, first, last);
|
bgp_lp_event_chunk(response_keep, first, last);
|
||||||
|
|
||||||
stream_failure: /* for STREAM_GETX */
|
stream_failure: /* for STREAM_GETX */
|
||||||
return;
|
return;
|
||||||
|
@ -2951,6 +2951,8 @@ static struct bgp *bgp_create(as_t *as, const char *name,
|
|||||||
#endif /* ENABLE_BGP_VNC */
|
#endif /* ENABLE_BGP_VNC */
|
||||||
|
|
||||||
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
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_label = MPLS_LABEL_NONE;
|
||||||
bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent =
|
bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent =
|
||||||
MPLS_LABEL_NONE;
|
MPLS_LABEL_NONE;
|
||||||
@ -7537,7 +7539,7 @@ void bgp_master_init(struct thread_master *master)
|
|||||||
bgp_option_set(BGP_OPT_MULTIPLE_INSTANCE);
|
bgp_option_set(BGP_OPT_MULTIPLE_INSTANCE);
|
||||||
|
|
||||||
/* mpls label dynamic allocation pool */
|
/* mpls label dynamic allocation pool */
|
||||||
lp_init(bm->master, &bm->labelpool);
|
bgp_lp_init(bm->master, &bm->labelpool);
|
||||||
|
|
||||||
QOBJ_REG(bm, bgp_master);
|
QOBJ_REG(bm, bgp_master);
|
||||||
}
|
}
|
||||||
@ -7718,5 +7720,5 @@ void bgp_terminate(void)
|
|||||||
if (bm->t_rmap_update)
|
if (bm->t_rmap_update)
|
||||||
BGP_TIMER_OFF(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
|
BGP_VPN_POLICY_DIR_MAX = 2
|
||||||
} vpn_policy_direction_t;
|
} 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'.
|
* Type of 'struct bgp'.
|
||||||
* - Default: The default instance
|
* - Default: The default instance
|
||||||
@ -469,22 +488,7 @@ struct bgp {
|
|||||||
/* route map for advertise ipv4/ipv6 unicast (type-5 routes) */
|
/* route map for advertise ipv4/ipv6 unicast (type-5 routes) */
|
||||||
struct bgp_rmap adv_cmd_rmap[AFI_MAX][SAFI_MAX];
|
struct bgp_rmap adv_cmd_rmap[AFI_MAX][SAFI_MAX];
|
||||||
|
|
||||||
/* vpn-policy */
|
struct vpn_policy vpn_policy[AFI_MAX];
|
||||||
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];
|
|
||||||
|
|
||||||
QOBJ_FIELDS
|
QOBJ_FIELDS
|
||||||
};
|
};
|
||||||
|
@ -1606,14 +1606,17 @@ address-family:
|
|||||||
|
|
||||||
Deletes any previously-configured import or export route-target list.
|
Deletes any previously-configured import or export route-target list.
|
||||||
|
|
||||||
.. index:: label vpn export (0..1048575)
|
.. index:: label vpn export (0..1048575)|auto
|
||||||
.. clicmd:: label vpn export (0..1048575)
|
.. clicmd:: label vpn export (0..1048575)|auto
|
||||||
|
|
||||||
Specifies an optional MPLS label to be attached to a route exported from the
|
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)]
|
.. index:: no label vpn export [(0..1048575)|auto]
|
||||||
.. clicmd:: no label vpn export [(0..1048575)]
|
.. clicmd:: no label vpn export [(0..1048575)|auto]
|
||||||
|
|
||||||
Deletes any previously-configured export label.
|
Deletes any previously-configured export label.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user