lib, zebra: Add new api to specify a label associated with the vrf

For L3VPN's we need to create a label associated with the specified
vrf to be installed into the kernel to allow a pop and lookup
operation.

The new api is:
zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id,
                       mpls_label_t label);

For the specified vrf_id associate the specified label for
a pop and lookup operation for forwarding.

To setup a POP and Forward use MPLS_LABEL_IMPLICIT_NULL
If the same label is passed in we ignore the call.
If the label is different we update entry.
If the label is MPLS_LABEL_NONE we remove
the entry.

This sets up the api.  Future commits will have the functionality
to actually install into the kernel.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2018-01-30 13:30:36 -05:00
parent 44bdf1590d
commit c83c5e4482
5 changed files with 78 additions and 0 deletions

View File

@ -929,6 +929,7 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_VRF_UNREGISTER),
DESC_ENTRY(ZEBRA_VRF_ADD),
DESC_ENTRY(ZEBRA_VRF_DELETE),
DESC_ENTRY(ZEBRA_VRF_LABEL),
DESC_ENTRY(ZEBRA_INTERFACE_VRF_UPDATE),
DESC_ENTRY(ZEBRA_BFD_CLIENT_REGISTER),
DESC_ENTRY(ZEBRA_INTERFACE_ENABLE_RADV),

View File

@ -363,6 +363,20 @@ static int zebra_hello_send(struct zclient *zclient)
return 0;
}
void zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id,
mpls_label_t label)
{
struct stream *s;
s = zclient->obuf;
stream_reset(s);
zclient_create_header(s, ZEBRA_VRF_LABEL, vrf_id);
stream_putl(s, label);
stream_putw_at(s, 0, stream_get_endp(s));
zclient_send_message(zclient);
}
/* Send register requests to zebra daemon for the information in a VRF. */
void zclient_send_reg_requests(struct zclient *zclient, vrf_id_t vrf_id)
{

View File

@ -93,6 +93,7 @@ typedef enum {
ZEBRA_VRF_UNREGISTER,
ZEBRA_VRF_ADD,
ZEBRA_VRF_DELETE,
ZEBRA_VRF_LABEL,
ZEBRA_INTERFACE_VRF_UPDATE,
ZEBRA_BFD_CLIENT_REGISTER,
ZEBRA_INTERFACE_ENABLE_RADV,
@ -382,6 +383,17 @@ extern u_short *redist_check_instance(struct redist_proto *, u_short);
extern void redist_add_instance(struct redist_proto *, u_short);
extern void redist_del_instance(struct redist_proto *, u_short);
/*
* Send to zebra that the specified vrf is using label to resolve
* itself for L3VPN's. Repeated calls of this function with
* different labels will cause an effective update of the
* label for lookup. If you pass in MPLS_V4_EXP_NULL_LABEL
* we will cause a delete action and remove this label pop
* operation.
*/
extern void zclient_send_vrf_label(struct zclient *zclient, vrf_id_t vrf_id,
mpls_label_t label);
extern void zclient_send_reg_requests(struct zclient *, vrf_id_t);
extern void zclient_send_dereg_requests(struct zclient *, vrf_id_t);

View File

@ -79,6 +79,9 @@ struct zebra_vrf {
*/
struct zebra_ns *zns;
/* MPLS Label to handle L3VPN <-> vrf popping */
mpls_label_t label;
/* MPLS static LSP config table */
struct hash *slsp_table;

View File

@ -2486,6 +2486,51 @@ stream_failure:
return 1;
}
static void zread_vrf_label(struct zserv *client,
struct zebra_vrf *zvrf)
{
struct interface *ifp;
mpls_label_t nlabel;
struct stream *s;
struct zebra_vrf *def_zvrf;
s = client->ibuf;
STREAM_GETL(s, nlabel);
if (nlabel == zvrf->label) {
/*
* Nothing to do here move along
*/
return;
}
if (zvrf->vrf->vrf_id != VRF_DEFAULT)
ifp = if_lookup_by_name(zvrf->vrf->name, zvrf->vrf->vrf_id);
else
ifp = if_lookup_by_name("lo", VRF_DEFAULT);
if (!ifp) {
zlog_debug("Unable to find specified Interface for %s",
zvrf->vrf->name);
return;
}
def_zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
if (zvrf->label != MPLS_LABEL_IPV4NULL)
mpls_lsp_uninstall(def_zvrf, ZEBRA_LSP_STATIC,
zvrf->label, NEXTHOP_TYPE_IFINDEX,
NULL, ifp->ifindex);
if (nlabel != MPLS_LABEL_IPV4NULL)
mpls_lsp_install(def_zvrf, ZEBRA_LSP_STATIC, nlabel,
MPLS_LABEL_IMPLICIT_NULL, NEXTHOP_TYPE_IFINDEX, NULL, ifp->ifindex);
zvrf->label = nlabel;
stream_failure:
return;
}
static inline void zserv_handle_commands(struct zserv *client,
uint16_t command,
uint16_t length,
@ -2570,6 +2615,9 @@ static inline void zserv_handle_commands(struct zserv *client,
case ZEBRA_VRF_UNREGISTER:
zread_vrf_unregister(client, length, zvrf);
break;
case ZEBRA_VRF_LABEL:
zread_vrf_label(client, zvrf);
break;
case ZEBRA_BFD_CLIENT_REGISTER:
zebra_ptm_bfd_client_register(client, length);
break;