mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 12:21:24 +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"
|
||||
|
||||
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, NHLFE, "MPLS nexthop object")
|
||||
DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE, "MPLS static nexthop object")
|
||||
@ -58,6 +59,17 @@ int mpls_enabled;
|
||||
extern struct zebra_t zebrad;
|
||||
|
||||
/* 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
|
||||
label_hash (void *p);
|
||||
static int
|
||||
@ -68,6 +80,7 @@ static int
|
||||
nhlfe_nexthop_active_ipv6 (zebra_nhlfe_t *nhlfe, struct nexthop *nexthop);
|
||||
static int
|
||||
nhlfe_nexthop_active (zebra_nhlfe_t *nhlfe);
|
||||
|
||||
static void
|
||||
lsp_select_best_nhlfe (zebra_lsp_t *lsp);
|
||||
static void
|
||||
@ -84,6 +97,7 @@ static int
|
||||
lsp_processq_add (zebra_lsp_t *lsp);
|
||||
static void *
|
||||
lsp_alloc (void *p);
|
||||
|
||||
static char *
|
||||
nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size);
|
||||
static int
|
||||
@ -134,6 +148,88 @@ mpls_processq_init (struct zebra_t *zebra);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
@ -1274,6 +1370,215 @@ mpls_label2str (u_int8_t num_labels, mpls_label_t *labels,
|
||||
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.
|
||||
*/
|
||||
@ -1927,6 +2232,8 @@ zebra_mpls_init_tables (struct zebra_vrf *zvrf)
|
||||
return;
|
||||
zvrf->slsp_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;
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,7 @@ typedef struct zebra_snhlfe_t_ zebra_snhlfe_t;
|
||||
typedef struct zebra_slsp_t_ zebra_slsp_t;
|
||||
typedef struct zebra_nhlfe_t_ zebra_nhlfe_t;
|
||||
typedef struct zebra_lsp_t_ zebra_lsp_t;
|
||||
typedef struct zebra_fec_t_ zebra_fec_t;
|
||||
|
||||
/*
|
||||
* (Outgoing) nexthop label forwarding entry configuration
|
||||
@ -147,6 +148,21 @@ struct zebra_lsp_t_
|
||||
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. */
|
||||
|
||||
@ -164,6 +180,53 @@ char *
|
||||
mpls_label2str (u_int8_t num_labels, mpls_label_t *labels,
|
||||
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.
|
||||
*/
|
||||
|
@ -209,6 +209,101 @@ DEFUN (no_mpls_transit_lsp_all,
|
||||
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. */
|
||||
DEFUN (ip_route_label,
|
||||
ip_route_label_cmd,
|
||||
@ -777,9 +872,44 @@ zebra_mpls_config (struct vty *vty)
|
||||
return 0;
|
||||
|
||||
write += zebra_mpls_write_lsp_config(vty, zvrf);
|
||||
write += zebra_mpls_write_fec_config(vty, zvrf);
|
||||
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,
|
||||
show_mpls_table_cmd,
|
||||
"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_out_label_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_lsp_cmd);
|
||||
install_element (VIEW_NODE, &show_mpls_fec_cmd);
|
||||
}
|
||||
|
@ -79,6 +79,9 @@ struct zebra_vrf
|
||||
/* MPLS label forwarding table */
|
||||
struct hash *lsp_table;
|
||||
|
||||
/* MPLS FEC binding table */
|
||||
struct route_table *fec_table[AFI_MAX];
|
||||
|
||||
/* MPLS processing flags */
|
||||
u_int16_t mpls_flags;
|
||||
#define MPLS_FLAG_SCHEDULE_LSPS (1 << 0)
|
||||
|
Loading…
Reference in New Issue
Block a user