diff options
-rw-r--r-- | bgpd/bgp_mplsvpn.c | 59 | ||||
-rw-r--r-- | bgpd/bgp_mplsvpn.h | 12 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 59 | ||||
-rw-r--r-- | bgpd/bgp_zebra.c | 4 | ||||
-rw-r--r-- | bgpd/bgpd.c | 6 | ||||
-rw-r--r-- | bgpd/bgpd.h | 36 | ||||
-rw-r--r-- | doc/user/bgp.rst | 13 |
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. |