mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 07:23:41 +00:00
zebra: static label binding
Implement static label binding of a label to a prefix (FEC). Note: Currently, only binding to a prefix is supported, the nexthop and/or other parameters are not considered. This was cherry-picked by hand from an earlier mpls branch. Signed-off-by: Don Slice <dslice@cumulusnetworks.com>
This commit is contained in:
parent
bc7268d524
commit
f31e084c7c
@ -47,6 +47,7 @@
|
|||||||
#include "zebra/zebra_mpls.h"
|
#include "zebra/zebra_mpls.h"
|
||||||
|
|
||||||
DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object")
|
DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object")
|
||||||
|
DEFINE_MTYPE_STATIC(ZEBRA, FEC, "MPLS FEC object")
|
||||||
DEFINE_MTYPE_STATIC(ZEBRA, SLSP, "MPLS static LSP config")
|
DEFINE_MTYPE_STATIC(ZEBRA, SLSP, "MPLS static LSP config")
|
||||||
DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object")
|
DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object")
|
||||||
DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE, "MPLS static nexthop object")
|
DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE, "MPLS static nexthop object")
|
||||||
@ -58,6 +59,17 @@ int mpls_enabled;
|
|||||||
extern struct zebra_t zebrad;
|
extern struct zebra_t zebrad;
|
||||||
|
|
||||||
/* static function declarations */
|
/* static function declarations */
|
||||||
|
|
||||||
|
static void
|
||||||
|
fec_print (zebra_fec_t *fec, struct vty *vty);
|
||||||
|
static zebra_fec_t *
|
||||||
|
fec_find (struct route_table *table, struct prefix *p);
|
||||||
|
static zebra_fec_t *
|
||||||
|
fec_add (struct route_table *table, struct prefix *p, u_int32_t label,
|
||||||
|
u_int32_t flags);
|
||||||
|
static int
|
||||||
|
fec_del (zebra_fec_t *fec);
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
label_hash (void *p);
|
label_hash (void *p);
|
||||||
static int
|
static int
|
||||||
@ -68,6 +80,7 @@ static int
|
|||||||
nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop);
|
nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop);
|
||||||
static int
|
static int
|
||||||
nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe);
|
nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
lsp_select_best_nhlfe (zebra_lsp_t *lsp);
|
lsp_select_best_nhlfe (zebra_lsp_t *lsp);
|
||||||
static void
|
static void
|
||||||
@ -84,6 +97,7 @@ static int
|
|||||||
lsp_processq_add (zebra_lsp_t *lsp);
|
lsp_processq_add (zebra_lsp_t *lsp);
|
||||||
static void *
|
static void *
|
||||||
lsp_alloc (void *p);
|
lsp_alloc (void *p);
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size);
|
nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size);
|
||||||
static int
|
static int
|
||||||
@ -134,6 +148,88 @@ mpls_processq_init (struct zebra_t *zebra);
|
|||||||
|
|
||||||
/* Static functions */
|
/* Static functions */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a FEC-label binding entry.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
fec_print (zebra_fec_t *fec, struct vty *vty)
|
||||||
|
{
|
||||||
|
struct route_node *rn;
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
|
||||||
|
rn = fec->rn;
|
||||||
|
prefix2str(&rn->p, buf, BUFSIZ);
|
||||||
|
vty_out(vty, "%s%s", buf, VTY_NEWLINE);
|
||||||
|
vty_out(vty, " Label: %s", label2str(fec->label, buf, BUFSIZ));
|
||||||
|
vty_out(vty, "%s", VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Locate FEC-label binding that matches with passed info.
|
||||||
|
*/
|
||||||
|
static zebra_fec_t *
|
||||||
|
fec_find (struct route_table *table, struct prefix *p)
|
||||||
|
{
|
||||||
|
struct route_node *rn;
|
||||||
|
|
||||||
|
apply_mask (p);
|
||||||
|
rn = route_node_lookup(table, p);
|
||||||
|
if (!rn)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
route_unlock_node(rn);
|
||||||
|
return (rn->info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a FEC.
|
||||||
|
*/
|
||||||
|
static zebra_fec_t *
|
||||||
|
fec_add (struct route_table *table, struct prefix *p,
|
||||||
|
mpls_label_t label, u_int32_t flags)
|
||||||
|
{
|
||||||
|
struct route_node *rn;
|
||||||
|
zebra_fec_t *fec;
|
||||||
|
|
||||||
|
apply_mask (p);
|
||||||
|
|
||||||
|
/* Lookup (or add) route node.*/
|
||||||
|
rn = route_node_get (table, p);
|
||||||
|
if (!rn)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
fec = rn->info;
|
||||||
|
|
||||||
|
if (!fec)
|
||||||
|
{
|
||||||
|
fec = XCALLOC (MTYPE_FEC, sizeof(zebra_fec_t));
|
||||||
|
if (!fec)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
rn->info = fec;
|
||||||
|
fec->rn = rn;
|
||||||
|
fec->label = label;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
route_unlock_node (rn); /* for the route_node_get */
|
||||||
|
|
||||||
|
fec->flags = flags;
|
||||||
|
|
||||||
|
return fec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Delete a FEC.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
fec_del (zebra_fec_t *fec)
|
||||||
|
{
|
||||||
|
fec->rn->info = NULL;
|
||||||
|
route_unlock_node (fec->rn);
|
||||||
|
XFREE (MTYPE_FEC, fec);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Hash function for label.
|
* Hash function for label.
|
||||||
*/
|
*/
|
||||||
@ -1274,6 +1370,215 @@ mpls_label2str (u_int8_t num_labels, mpls_label_t *labels,
|
|||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return FEC (if any) to which this label is bound.
|
||||||
|
* Note: Only works for per-prefix binding and when the label is not
|
||||||
|
* implicit-null.
|
||||||
|
* TODO: Currently walks entire table, can optimize later with another
|
||||||
|
* hash..
|
||||||
|
*/
|
||||||
|
zebra_fec_t *
|
||||||
|
zebra_mpls_fec_for_label (struct zebra_vrf *zvrf, mpls_label_t label)
|
||||||
|
{
|
||||||
|
struct route_node *rn;
|
||||||
|
zebra_fec_t *fec;
|
||||||
|
int af;
|
||||||
|
|
||||||
|
for (af = AFI_IP; af < AFI_MAX; af++)
|
||||||
|
{
|
||||||
|
if (zvrf->fec_table[af] == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn))
|
||||||
|
{
|
||||||
|
if (!rn->info)
|
||||||
|
continue;
|
||||||
|
fec = rn->info;
|
||||||
|
if (fec->label == label)
|
||||||
|
return fec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inform if specified label is currently bound to a FEC or not.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
zebra_mpls_label_already_bound (struct zebra_vrf *zvrf, mpls_label_t label)
|
||||||
|
{
|
||||||
|
return (zebra_mpls_fec_for_label (zvrf, label) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add static FEC to label binding.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p,
|
||||||
|
mpls_label_t in_label)
|
||||||
|
{
|
||||||
|
struct route_table *table;
|
||||||
|
zebra_fec_t *fec;
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))];
|
||||||
|
if (!table)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_MPLS)
|
||||||
|
prefix2str(p, buf, BUFSIZ);
|
||||||
|
|
||||||
|
/* Update existing FEC or create a new one. */
|
||||||
|
fec = fec_find (table, p);
|
||||||
|
if (!fec)
|
||||||
|
{
|
||||||
|
fec = fec_add (table, p, in_label, FEC_FLAG_CONFIGURED);
|
||||||
|
if (!fec)
|
||||||
|
{
|
||||||
|
prefix2str(p, buf, BUFSIZ);
|
||||||
|
zlog_err ("Failed to add FEC %s upon config", buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_MPLS)
|
||||||
|
zlog_debug ("Add fec %s label %u", buf, in_label);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fec->flags |= FEC_FLAG_CONFIGURED;
|
||||||
|
if (fec->label == in_label)
|
||||||
|
/* Duplicate config */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_MPLS)
|
||||||
|
zlog_debug ("Update fec %s new label %u", buf, in_label);
|
||||||
|
|
||||||
|
fec->label = in_label;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove static FEC to label binding.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
zebra_mpls_static_fec_del (struct zebra_vrf *zvrf, struct prefix *p)
|
||||||
|
{
|
||||||
|
struct route_table *table;
|
||||||
|
zebra_fec_t *fec;
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
|
||||||
|
table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))];
|
||||||
|
if (!table)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
fec = fec_find (table, p);
|
||||||
|
if (!fec)
|
||||||
|
{
|
||||||
|
prefix2str(p, buf, BUFSIZ);
|
||||||
|
zlog_err("Failed to find FEC %s upon delete", buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IS_ZEBRA_DEBUG_MPLS)
|
||||||
|
{
|
||||||
|
prefix2str(p, buf, BUFSIZ);
|
||||||
|
zlog_debug ("Delete fec %s", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
fec_del (fec);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display MPLS FEC to label binding configuration (VTY command handler).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
zebra_mpls_write_fec_config (struct vty *vty, struct zebra_vrf *zvrf)
|
||||||
|
{
|
||||||
|
struct route_node *rn;
|
||||||
|
int af;
|
||||||
|
zebra_fec_t *fec;
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
int write = 0;
|
||||||
|
|
||||||
|
for (af = AFI_IP; af < AFI_MAX; af++)
|
||||||
|
{
|
||||||
|
if (zvrf->fec_table[af] == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn))
|
||||||
|
{
|
||||||
|
if (!rn->info)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
char lstr[BUFSIZ];
|
||||||
|
fec = rn->info;
|
||||||
|
|
||||||
|
if (!(fec->flags & FEC_FLAG_CONFIGURED))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
write = 1;
|
||||||
|
prefix2str(&rn->p, buf, BUFSIZ);
|
||||||
|
vty_out(vty, "mpls label bind %s %s%s", buf,
|
||||||
|
label2str(fec->label, lstr, BUFSIZ), VTY_NEWLINE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return write;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display MPLS FEC to label binding (VTY command handler).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
zebra_mpls_print_fec_table (struct vty *vty, struct zebra_vrf *zvrf)
|
||||||
|
{
|
||||||
|
struct route_node *rn;
|
||||||
|
int af;
|
||||||
|
|
||||||
|
for (af = AFI_IP; af < AFI_MAX; af++)
|
||||||
|
{
|
||||||
|
if (zvrf->fec_table[af] == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (rn = route_top(zvrf->fec_table[af]); rn; rn = route_next(rn))
|
||||||
|
{
|
||||||
|
if (!rn->info)
|
||||||
|
continue;
|
||||||
|
fec_print (rn->info, vty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display MPLS FEC to label binding for a specific FEC (VTY command handler).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
zebra_mpls_print_fec (struct vty *vty, struct zebra_vrf *zvrf, struct prefix *p)
|
||||||
|
{
|
||||||
|
struct route_table *table;
|
||||||
|
struct route_node *rn;
|
||||||
|
|
||||||
|
table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))];
|
||||||
|
if (!table)
|
||||||
|
return;
|
||||||
|
|
||||||
|
apply_mask (p);
|
||||||
|
rn = route_node_lookup(table, p);
|
||||||
|
if (!rn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
route_unlock_node(rn);
|
||||||
|
if (!rn->info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fec_print (rn->info, vty);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Install/uninstall a FEC-To-NHLFE (FTN) binding.
|
* Install/uninstall a FEC-To-NHLFE (FTN) binding.
|
||||||
*/
|
*/
|
||||||
@ -1927,6 +2232,8 @@ zebra_mpls_init_tables (struct zebra_vrf *zvrf)
|
|||||||
return;
|
return;
|
||||||
zvrf->slsp_table = hash_create(label_hash, label_cmp);
|
zvrf->slsp_table = hash_create(label_hash, label_cmp);
|
||||||
zvrf->lsp_table = hash_create(label_hash, label_cmp);
|
zvrf->lsp_table = hash_create(label_hash, label_cmp);
|
||||||
|
zvrf->fec_table[AFI_IP] = route_table_init();
|
||||||
|
zvrf->fec_table[AFI_IP6] = route_table_init();
|
||||||
zvrf->mpls_flags = 0;
|
zvrf->mpls_flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ typedef struct zebra_snhlfe_t_ zebra_snhlfe_t;
|
|||||||
typedef struct zebra_slsp_t_ zebra_slsp_t;
|
typedef struct zebra_slsp_t_ zebra_slsp_t;
|
||||||
typedef struct zebra_nhlfe_t_ zebra_nhlfe_t;
|
typedef struct zebra_nhlfe_t_ zebra_nhlfe_t;
|
||||||
typedef struct zebra_lsp_t_ zebra_lsp_t;
|
typedef struct zebra_lsp_t_ zebra_lsp_t;
|
||||||
|
typedef struct zebra_fec_t_ zebra_fec_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (Outgoing) nexthop label forwarding entry configuration
|
* (Outgoing) nexthop label forwarding entry configuration
|
||||||
@ -147,6 +148,21 @@ struct zebra_lsp_t_
|
|||||||
u_char addr_family;
|
u_char addr_family;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FEC to label binding.
|
||||||
|
*/
|
||||||
|
struct zebra_fec_t_
|
||||||
|
{
|
||||||
|
/* FEC (prefix) */
|
||||||
|
struct route_node *rn;
|
||||||
|
|
||||||
|
/* In-label - either statically bound or derived from label block. */
|
||||||
|
mpls_label_t label;
|
||||||
|
|
||||||
|
/* Flags. */
|
||||||
|
u_int32_t flags;
|
||||||
|
#define FEC_FLAG_CONFIGURED (1 << 0)
|
||||||
|
};
|
||||||
|
|
||||||
/* Function declarations. */
|
/* Function declarations. */
|
||||||
|
|
||||||
@ -164,6 +180,53 @@ char *
|
|||||||
mpls_label2str (u_int8_t num_labels, mpls_label_t *labels,
|
mpls_label2str (u_int8_t num_labels, mpls_label_t *labels,
|
||||||
char *buf, int len);
|
char *buf, int len);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return FEC (if any) to which this label is bound.
|
||||||
|
* Note: Only works for per-prefix binding and when the label is not
|
||||||
|
* implicit-null.
|
||||||
|
* TODO: Currently walks entire table, can optimize later with another
|
||||||
|
* hash..
|
||||||
|
*/
|
||||||
|
zebra_fec_t *
|
||||||
|
zebra_mpls_fec_for_label (struct zebra_vrf *zvrf, mpls_label_t label);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inform if specified label is currently bound to a FEC or not.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
zebra_mpls_label_already_bound (struct zebra_vrf *zvrf, mpls_label_t label);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add static FEC to label binding.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p,
|
||||||
|
mpls_label_t in_label);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove static FEC to label binding.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
zebra_mpls_static_fec_del (struct zebra_vrf *zvrf, struct prefix *p);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display MPLS FEC to label binding configuration (VTY command handler).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
zebra_mpls_write_fec_config (struct vty *vty, struct zebra_vrf *zvrf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display MPLS FEC to label binding (VTY command handler).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
zebra_mpls_print_fec_table (struct vty *vty, struct zebra_vrf *zvrf);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Display MPLS FEC to label binding for a specific FEC (VTY command handler).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
zebra_mpls_print_fec (struct vty *vty, struct zebra_vrf *zvrf, struct prefix *p);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Install/uninstall a FEC-To-NHLFE (FTN) binding.
|
* Install/uninstall a FEC-To-NHLFE (FTN) binding.
|
||||||
*/
|
*/
|
||||||
|
@ -209,6 +209,101 @@ DEFUN (no_mpls_transit_lsp_all,
|
|||||||
return zebra_mpls_transit_lsp (vty, 0, argv[3]->arg, NULL, NULL, NULL);
|
return zebra_mpls_transit_lsp (vty, 0, argv[3]->arg, NULL, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
zebra_mpls_bind (struct vty *vty, int add_cmd, const char *prefix,
|
||||||
|
const char *label_str)
|
||||||
|
{
|
||||||
|
struct zebra_vrf *zvrf;
|
||||||
|
struct prefix p;
|
||||||
|
u_int32_t label;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
||||||
|
if (!zvrf)
|
||||||
|
{
|
||||||
|
vty_out (vty, "%% Default VRF does not exist%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&p, 0, sizeof(struct prefix));
|
||||||
|
ret = str2prefix(prefix, &p);
|
||||||
|
if (ret <= 0)
|
||||||
|
{
|
||||||
|
vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add_cmd)
|
||||||
|
{
|
||||||
|
if (!label_str)
|
||||||
|
{
|
||||||
|
vty_out (vty, "%% No label binding specified%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(label_str, "implicit-null"))
|
||||||
|
label = MPLS_IMP_NULL_LABEL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label = atoi(label_str);
|
||||||
|
if (!IS_MPLS_UNRESERVED_LABEL(label))
|
||||||
|
{
|
||||||
|
vty_out (vty, "%% Invalid label%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
if (zebra_mpls_label_already_bound (zvrf, label))
|
||||||
|
{
|
||||||
|
vty_out (vty, "%% Label already bound to a FEC%s",
|
||||||
|
VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = zebra_mpls_static_fec_add (zvrf, &p, label);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = zebra_mpls_static_fec_del (zvrf, &p);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
vty_out (vty, "%% FEC to label binding cannot be %s%s",
|
||||||
|
add_cmd ? "added" : "deleted", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (mpls_label_bind,
|
||||||
|
mpls_label_bind_cmd,
|
||||||
|
"mpls label bind <A.B.C.D/M|X:X::X:X/M> <(16-1048575)|implicit-null>",
|
||||||
|
MPLS_STR
|
||||||
|
"Label configuration\n"
|
||||||
|
"Establish FEC to label binding\n"
|
||||||
|
"IPv4 prefix\n"
|
||||||
|
"IPv6 prefix\n"
|
||||||
|
"MPLS Label to bind\n"
|
||||||
|
"Use Implicit-Null Label\n")
|
||||||
|
{
|
||||||
|
return zebra_mpls_bind (vty, 1, argv[3]->arg, argv[4]->arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (no_mpls_label_bind,
|
||||||
|
no_mpls_label_bind_cmd,
|
||||||
|
"no mpls label bind <A.B.C.D/M|X:X::X:X/M> [<(16-1048575)|implicit-null>]",
|
||||||
|
NO_STR
|
||||||
|
MPLS_STR
|
||||||
|
"Label configuration\n"
|
||||||
|
"Establish FEC to label binding\n"
|
||||||
|
"IPv4 prefix\n"
|
||||||
|
"IPv6 prefix\n"
|
||||||
|
"MPLS Label to bind\n"
|
||||||
|
"Use Implicit-Null Label\n")
|
||||||
|
|
||||||
|
{
|
||||||
|
return zebra_mpls_bind (vty, 0, argv[4]->arg, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Static route configuration. */
|
/* Static route configuration. */
|
||||||
DEFUN (ip_route_label,
|
DEFUN (ip_route_label,
|
||||||
ip_route_label_cmd,
|
ip_route_label_cmd,
|
||||||
@ -777,9 +872,44 @@ zebra_mpls_config (struct vty *vty)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
write += zebra_mpls_write_lsp_config(vty, zvrf);
|
write += zebra_mpls_write_lsp_config(vty, zvrf);
|
||||||
|
write += zebra_mpls_write_fec_config(vty, zvrf);
|
||||||
return write;
|
return write;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN (show_mpls_fec,
|
||||||
|
show_mpls_fec_cmd,
|
||||||
|
"show mpls fec [<A.B.C.D/M|X:X::X:X/M>]",
|
||||||
|
SHOW_STR
|
||||||
|
MPLS_STR
|
||||||
|
"MPLS FEC table\n"
|
||||||
|
"FEC to display information about\n"
|
||||||
|
"FEC to display information about\n")
|
||||||
|
{
|
||||||
|
struct zebra_vrf *zvrf;
|
||||||
|
struct prefix p;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
zvrf = vrf_info_lookup(VRF_DEFAULT);
|
||||||
|
if (!zvrf)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (argc == 3)
|
||||||
|
zebra_mpls_print_fec_table(vty, zvrf);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(&p, 0, sizeof(struct prefix));
|
||||||
|
ret = str2prefix(argv[3]->arg, &p);
|
||||||
|
if (ret <= 0)
|
||||||
|
{
|
||||||
|
vty_out (vty, "%% Malformed address%s", VTY_NEWLINE);
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
|
zebra_mpls_print_fec (vty, zvrf, &p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
DEFUN (show_mpls_table,
|
DEFUN (show_mpls_table,
|
||||||
show_mpls_table_cmd,
|
show_mpls_table_cmd,
|
||||||
"show mpls table [json]",
|
"show mpls table [json]",
|
||||||
@ -876,7 +1006,10 @@ zebra_mpls_vty_init (void)
|
|||||||
install_element (CONFIG_NODE, &no_mpls_transit_lsp_cmd);
|
install_element (CONFIG_NODE, &no_mpls_transit_lsp_cmd);
|
||||||
install_element (CONFIG_NODE, &no_mpls_transit_lsp_out_label_cmd);
|
install_element (CONFIG_NODE, &no_mpls_transit_lsp_out_label_cmd);
|
||||||
install_element (CONFIG_NODE, &no_mpls_transit_lsp_all_cmd);
|
install_element (CONFIG_NODE, &no_mpls_transit_lsp_all_cmd);
|
||||||
|
install_element (CONFIG_NODE, &mpls_label_bind_cmd);
|
||||||
|
install_element (CONFIG_NODE, &no_mpls_label_bind_cmd);
|
||||||
|
|
||||||
install_element (VIEW_NODE, &show_mpls_table_cmd);
|
install_element (VIEW_NODE, &show_mpls_table_cmd);
|
||||||
install_element (VIEW_NODE, &show_mpls_table_lsp_cmd);
|
install_element (VIEW_NODE, &show_mpls_table_lsp_cmd);
|
||||||
|
install_element (VIEW_NODE, &show_mpls_fec_cmd);
|
||||||
}
|
}
|
||||||
|
@ -79,6 +79,9 @@ struct zebra_vrf
|
|||||||
/* MPLS label forwarding table */
|
/* MPLS label forwarding table */
|
||||||
struct hash *lsp_table;
|
struct hash *lsp_table;
|
||||||
|
|
||||||
|
/* MPLS FEC binding table */
|
||||||
|
struct route_table *fec_table[AFI_MAX];
|
||||||
|
|
||||||
/* MPLS processing flags */
|
/* MPLS processing flags */
|
||||||
u_int16_t mpls_flags;
|
u_int16_t mpls_flags;
|
||||||
#define MPLS_FLAG_SCHEDULE_LSPS (1 << 0)
|
#define MPLS_FLAG_SCHEDULE_LSPS (1 << 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user