summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_mplsvpn.c59
-rw-r--r--bgpd/bgp_mplsvpn.h12
-rw-r--r--bgpd/bgp_vty.c59
-rw-r--r--bgpd/bgp_zebra.c4
-rw-r--r--bgpd/bgpd.c6
-rw-r--r--bgpd/bgpd.h36
-rw-r--r--doc/user/bgp.rst13
7 files changed, 157 insertions, 32 deletions
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 06d82f654..072cdffbd 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -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;
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
index 64303325e..739855949 100644
--- a/bgpd/bgp_mplsvpn.h
+++ b/bgpd/bgp_mplsvpn.h
@@ -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;
}
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 3e577317a..17bb3fed9 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -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)) {
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 30ec0e96a..b564fccf4 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -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;
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 7c17cc3da..df0f1bd19 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -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();
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 2f3a732ac..680bac021 100644
--- a/bgpd/bgpd.h
+++ b/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
};
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 6504e7d20..f8d67526a 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -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.