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")
-DEFINE_MTYPE_STATIC(ZEBRA, SNHLFE_IFNAME, "MPLS static nexthop ifname")
int mpls_enabled;
/* Free lsp; sets caller's pointer to NULL */
static void lsp_free(struct hash *lsp_table, zebra_lsp_t **plsp);
-static char *nhlfe2str(zebra_nhlfe_t *nhlfe, char *buf, int size);
+static char *nhlfe2str(const zebra_nhlfe_t *nhlfe, char *buf, int size);
+static char *nhlfe_config_str(const zebra_nhlfe_t *nhlfe, char *buf, int size);
static int nhlfe_nhop_match(zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype,
const union g_addr *gate, ifindex_t ifindex);
static zebra_nhlfe_t *nhlfe_find(struct nhlfe_list_head *list,
static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty,
const char *indent);
static void lsp_print(struct vty *vty, zebra_lsp_t *lsp);
-static void *slsp_alloc(void *p);
-static int snhlfe_match(zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype,
- const union g_addr *gate, ifindex_t ifindex);
-static zebra_snhlfe_t *snhlfe_find(zebra_slsp_t *slsp,
- enum nexthop_types_t gtype,
- const union g_addr *gate, ifindex_t ifindex);
-static zebra_snhlfe_t *snhlfe_add(zebra_slsp_t *slsp,
- enum nexthop_types_t gtype,
- const union g_addr *gate, ifindex_t ifindex,
- mpls_label_t out_label);
-static int snhlfe_del(zebra_snhlfe_t *snhlfe);
-static int snhlfe_del_all(zebra_slsp_t *slsp);
-static char *snhlfe2str(zebra_snhlfe_t *snhlfe, char *buf, int size);
static void mpls_lsp_uninstall_all_type(struct hash_bucket *bucket, void *ctxt);
static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
int afi, enum lsp_types_t lsp_type);
static int lsp_backup_znh_install(zebra_lsp_t *lsp, enum lsp_types_t type,
const struct zapi_nexthop *znh);
-/* List implementations - declare internal linkage */
-DECLARE_DLIST(snhlfe_list, struct zebra_snhlfe_t_, list);
-
/* Static functions */
/*
/*
* Create printable string for NHLFE entry.
*/
-static char *nhlfe2str(zebra_nhlfe_t *nhlfe, char *buf, int size)
+static char *nhlfe2str(const zebra_nhlfe_t *nhlfe, char *buf, int size)
{
- struct nexthop *nexthop;
+ const struct nexthop *nexthop;
buf[0] = '\0';
nexthop = nhlfe->nexthop;
continue;
if (IS_ZEBRA_DEBUG_MPLS) {
- nhlfe2str(nhlfe, buf, BUFSIZ);
+ nhlfe2str(nhlfe, buf, sizeof(buf));
zlog_debug(
"Del LSP in-label %u type %d nexthop %s flags 0x%x",
lsp->ile.in_label, type, buf, nhlfe->flags);
continue;
if (IS_ZEBRA_DEBUG_MPLS) {
- nhlfe2str(nhlfe, buf, BUFSIZ);
+ nhlfe2str(nhlfe, buf, sizeof(buf));
zlog_debug(
"Del backup LSP in-label %u type %d nexthop %s flags 0x%x",
lsp->ile.in_label, type, buf, nhlfe->flags);
return 0;
}
-/*
- * Callback to allocate static LSP.
- */
-static void *slsp_alloc(void *p)
-{
- const zebra_ile_t *ile = p;
- zebra_slsp_t *slsp;
-
- slsp = XCALLOC(MTYPE_SLSP, sizeof(zebra_slsp_t));
- slsp->ile = *ile;
- snhlfe_list_init(&slsp->snhlfe_list);
-
- return ((void *)slsp);
-}
-
-/*
- * Compare two static LSPs based on their label values.
- */
-static int slsp_cmp(const zebra_slsp_t *slsp1, const zebra_slsp_t *slsp2)
-{
- if (slsp1->ile.in_label < slsp2->ile.in_label)
- return -1;
-
- if (slsp1->ile.in_label > slsp2->ile.in_label)
- return 1;
-
- return 0;
-}
-
-/*
- * Check if static NHLFE matches with search info passed.
- */
-static int snhlfe_match(zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype,
- const union g_addr *gate, ifindex_t ifindex)
-{
- int cmp = 1;
-
- if (snhlfe->gtype != gtype)
- return 1;
-
- switch (snhlfe->gtype) {
- case NEXTHOP_TYPE_IPV4:
- cmp = memcmp(&(snhlfe->gate.ipv4), &(gate->ipv4),
- sizeof(struct in_addr));
- break;
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- cmp = memcmp(&(snhlfe->gate.ipv6), &(gate->ipv6),
- sizeof(struct in6_addr));
- if (!cmp && snhlfe->gtype == NEXTHOP_TYPE_IPV6_IFINDEX)
- cmp = !(snhlfe->ifindex == ifindex);
- break;
- default:
- break;
- }
-
- return cmp;
-}
-
-/*
- * Locate static NHLFE that matches with passed info.
- */
-static zebra_snhlfe_t *snhlfe_find(zebra_slsp_t *slsp,
- enum nexthop_types_t gtype,
- const union g_addr *gate, ifindex_t ifindex)
-{
- zebra_snhlfe_t *snhlfe;
-
- if (!slsp)
- return NULL;
-
- frr_each_safe(snhlfe_list, &slsp->snhlfe_list, snhlfe) {
- if (!snhlfe_match(snhlfe, gtype, gate, ifindex))
- break;
- }
-
- return snhlfe;
-}
-
-
-/*
- * Add static NHLFE. Base LSP config entry must have been created
- * and duplicate check done.
- */
-static zebra_snhlfe_t *snhlfe_add(zebra_slsp_t *slsp,
- enum nexthop_types_t gtype,
- const union g_addr *gate, ifindex_t ifindex,
- mpls_label_t out_label)
-{
- zebra_snhlfe_t *snhlfe;
-
- if (!slsp)
- return NULL;
-
- snhlfe = XCALLOC(MTYPE_SNHLFE, sizeof(zebra_snhlfe_t));
- snhlfe->slsp = slsp;
- snhlfe->out_label = out_label;
- snhlfe->gtype = gtype;
- switch (gtype) {
- case NEXTHOP_TYPE_IPV4:
- snhlfe->gate.ipv4 = gate->ipv4;
- break;
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- snhlfe->gate.ipv6 = gate->ipv6;
- if (ifindex)
- snhlfe->ifindex = ifindex;
- break;
- default:
- XFREE(MTYPE_SNHLFE, snhlfe);
- return NULL;
- }
-
- snhlfe_list_add_head(&slsp->snhlfe_list, snhlfe);
-
- return snhlfe;
-}
-
-/*
- * Delete static NHLFE. Entry must be present on list.
- */
-static int snhlfe_del(zebra_snhlfe_t *snhlfe)
-{
- zebra_slsp_t *slsp;
-
- if (!snhlfe)
- return -1;
-
- slsp = snhlfe->slsp;
- if (!slsp)
- return -1;
-
- snhlfe_list_del(&slsp->snhlfe_list, snhlfe);
-
- XFREE(MTYPE_SNHLFE_IFNAME, snhlfe->ifname);
- XFREE(MTYPE_SNHLFE, snhlfe);
-
- return 0;
-}
-
-/*
- * Delete all static NHLFE entries for this LSP (in label).
- */
-static int snhlfe_del_all(zebra_slsp_t *slsp)
-{
- zebra_snhlfe_t *snhlfe;
-
- if (!slsp)
- return -1;
-
- frr_each_safe(snhlfe_list, &slsp->snhlfe_list, snhlfe) {
- snhlfe_del(snhlfe);
- }
-
- return 0;
-}
-
-/*
- * Create printable string for NHLFE configuration.
- */
-static char *snhlfe2str(zebra_snhlfe_t *snhlfe, char *buf, int size)
-{
- buf[0] = '\0';
- switch (snhlfe->gtype) {
- case NEXTHOP_TYPE_IPV4:
- inet_ntop(AF_INET, &snhlfe->gate.ipv4, buf, size);
- break;
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- inet_ntop(AF_INET6, &snhlfe->gate.ipv6, buf, size);
- if (snhlfe->ifindex)
- strlcat(buf,
- ifindex2ifname(snhlfe->ifindex, VRF_DEFAULT),
- size);
- break;
- default:
- break;
- }
-
- return buf;
-}
-
/*
* Initialize work queue for processing changed LSPs.
*/
{
struct hash *slsp_table;
zebra_ile_t tmp_ile;
- zebra_slsp_t *slsp;
- zebra_snhlfe_t *snhlfe;
+ zebra_lsp_t *lsp;
+ zebra_nhlfe_t *nhlfe;
+ const struct nexthop *nh;
/* Lookup table. */
slsp_table = zvrf->slsp_table;
/* If entry is not present, exit. */
tmp_ile.in_label = in_label;
- slsp = hash_lookup(slsp_table, &tmp_ile);
- if (!slsp)
+ lsp = hash_lookup(slsp_table, &tmp_ile);
+ if (!lsp)
return 1;
- snhlfe = snhlfe_find(slsp, gtype, gate, ifindex);
- if (snhlfe) {
- if (snhlfe->out_label == out_label)
+ nhlfe = nhlfe_find(&lsp->nhlfe_list, ZEBRA_LSP_STATIC,
+ gtype, gate, ifindex);
+ if (nhlfe) {
+ nh = nhlfe->nexthop;
+
+ if (nh == NULL || nh->nh_label == NULL)
+ return 0;
+
+ if (nh->nh_label->label[0] == out_label)
return 1;
/* If not only NHLFE, cannot allow label change. */
- if (snhlfe != snhlfe_list_first(&slsp->snhlfe_list) ||
- snhlfe_list_next(&slsp->snhlfe_list, snhlfe) != NULL)
+ if (nhlfe != nhlfe_list_first(&lsp->nhlfe_list) ||
+ nhlfe_list_next(&lsp->nhlfe_list, nhlfe) != NULL)
return 0;
} else {
/* If other NHLFEs exist, label operation must match. */
- snhlfe = snhlfe_list_first(&slsp->snhlfe_list);
- if (snhlfe != NULL) {
+ nhlfe = nhlfe_list_first(&lsp->nhlfe_list);
+ if (nhlfe != NULL) {
int cur_op, new_op;
- cur_op = (snhlfe->out_label ==
+ nh = nhlfe->nexthop;
+
+ if (nh == NULL || nh->nh_label == NULL)
+ return 0;
+
+ cur_op = (nh->nh_label->label[0] ==
MPLS_LABEL_IMPLICIT_NULL);
new_op = (out_label == MPLS_LABEL_IMPLICIT_NULL);
if (cur_op != new_op)
{
struct hash *slsp_table;
zebra_ile_t tmp_ile;
- zebra_slsp_t *slsp;
- zebra_snhlfe_t *snhlfe;
+ zebra_lsp_t *lsp;
+ zebra_nhlfe_t *nhlfe;
char buf[BUFSIZ];
/* Lookup table. */
/* Find or create LSP. */
tmp_ile.in_label = in_label;
- slsp = hash_get(slsp_table, &tmp_ile, slsp_alloc);
- if (!slsp)
+ lsp = hash_get(slsp_table, &tmp_ile, lsp_alloc);
+ if (!lsp)
return -1;
- snhlfe = snhlfe_find(slsp, gtype, gate, ifindex);
- if (snhlfe) {
- if (snhlfe->out_label == out_label)
+ nhlfe = nhlfe_find(&lsp->nhlfe_list, ZEBRA_LSP_STATIC, gtype, gate,
+ ifindex);
+ if (nhlfe) {
+ struct nexthop *nh = nhlfe->nexthop;
+
+ assert(nh);
+ assert(nh->nh_label);
+
+ /* Compare existing nexthop */
+ if (nh->nh_label->num_labels == 1 &&
+ nh->nh_label->label[0] == out_label)
/* No change */
return 0;
if (IS_ZEBRA_DEBUG_MPLS) {
- snhlfe2str(snhlfe, buf, sizeof(buf));
+ nhlfe2str(nhlfe, buf, sizeof(buf));
zlog_debug(
"Upd static LSP in-label %u nexthop %s out-label %u (old %u)",
- in_label, buf, out_label, snhlfe->out_label);
+ in_label, buf, out_label,
+ nh->nh_label->label[0]);
+ }
+ if (nh->nh_label->num_labels == 1)
+ nh->nh_label->label[0] = out_label;
+ else {
+ nexthop_del_labels(nh);
+ nexthop_add_labels(nh, ZEBRA_LSP_STATIC, 1, &out_label);
}
- snhlfe->out_label = out_label;
+
} else {
/* Add static LSP entry to this nexthop */
- snhlfe = snhlfe_add(slsp, gtype, gate, ifindex, out_label);
- if (!snhlfe)
+ nhlfe = nhlfe_add(lsp, ZEBRA_LSP_STATIC, gtype, gate,
+ ifindex, 1, &out_label, false /*backup*/);
+ if (!nhlfe)
return -1;
if (IS_ZEBRA_DEBUG_MPLS) {
- snhlfe2str(snhlfe, buf, sizeof(buf));
+ nhlfe2str(nhlfe, buf, sizeof(buf));
zlog_debug(
"Add static LSP in-label %u nexthop %s out-label %u",
in_label, buf, out_label);
{
struct hash *slsp_table;
zebra_ile_t tmp_ile;
- zebra_slsp_t *slsp;
- zebra_snhlfe_t *snhlfe;
+ zebra_lsp_t *lsp;
+ zebra_nhlfe_t *nhlfe;
/* Lookup table. */
slsp_table = zvrf->slsp_table;
/* If entry is not present, exit. */
tmp_ile.in_label = in_label;
- slsp = hash_lookup(slsp_table, &tmp_ile);
- if (!slsp)
+ lsp = hash_lookup(slsp_table, &tmp_ile);
+ if (!lsp)
return 0;
/* Is it delete of entire LSP or a specific NHLFE? */
mpls_static_lsp_uninstall_all(zvrf, in_label);
/* Delete all static NHLFEs */
- snhlfe_del_all(slsp);
+ frr_each_safe(nhlfe_list, &lsp->nhlfe_list, nhlfe) {
+ nhlfe_del(nhlfe);
+ }
} else {
/* Find specific NHLFE, exit if not found. */
- snhlfe = snhlfe_find(slsp, gtype, gate, ifindex);
- if (!snhlfe)
+ nhlfe = nhlfe_find(&lsp->nhlfe_list, ZEBRA_LSP_STATIC,
+ gtype, gate, ifindex);
+ if (!nhlfe)
return 0;
if (IS_ZEBRA_DEBUG_MPLS) {
char buf[BUFSIZ];
- snhlfe2str(snhlfe, buf, BUFSIZ);
+ nhlfe2str(nhlfe, buf, sizeof(buf));
zlog_debug("Del static LSP in-label %u nexthop %s",
in_label, buf);
}
gate, ifindex, false);
/* Delete static LSP NHLFE */
- snhlfe_del(snhlfe);
+ nhlfe_del(nhlfe);
}
/* Remove entire static LSP entry if no NHLFE - valid in either case
- * above. */
- if (snhlfe_list_first(&slsp->snhlfe_list) == NULL) {
- slsp = hash_release(slsp_table, &tmp_ile);
- XFREE(MTYPE_SLSP, slsp);
+ * above.
+ */
+ if (nhlfe_list_first(&lsp->nhlfe_list) == NULL) {
+ lsp = hash_release(slsp_table, &tmp_ile);
+ XFREE(MTYPE_LSP, lsp);
}
return 0;
list_delete(&lsp_list);
}
+/*
+ * Create printable string for static LSP configuration.
+ */
+static char *nhlfe_config_str(const zebra_nhlfe_t *nhlfe, char *buf, int size)
+{
+ const struct nexthop *nh;
+
+ nh = nhlfe->nexthop;
+
+ buf[0] = '\0';
+ switch (nh->type) {
+ case NEXTHOP_TYPE_IPV4:
+ inet_ntop(AF_INET, &nh->gate.ipv4, buf, size);
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ inet_ntop(AF_INET6, &nh->gate.ipv6, buf, size);
+ if (nh->ifindex)
+ strlcat(buf,
+ ifindex2ifname(nh->ifindex, VRF_DEFAULT),
+ size);
+ break;
+ default:
+ break;
+ }
+
+ return buf;
+}
+
/*
* Display MPLS LSP configuration of all static LSPs (VTY command handler).
*/
int zebra_mpls_write_lsp_config(struct vty *vty, struct zebra_vrf *zvrf)
{
- zebra_slsp_t *slsp;
- zebra_snhlfe_t *snhlfe;
+ zebra_lsp_t *lsp;
+ zebra_nhlfe_t *nhlfe;
+ struct nexthop *nh;
struct listnode *node;
struct list *slsp_list =
- hash_get_sorted_list(zvrf->slsp_table, slsp_cmp);
+ hash_get_sorted_list(zvrf->slsp_table, lsp_cmp);
- for (ALL_LIST_ELEMENTS_RO(slsp_list, node, slsp)) {
- frr_each(snhlfe_list, &slsp->snhlfe_list, snhlfe) {
+ for (ALL_LIST_ELEMENTS_RO(slsp_list, node, lsp)) {
+ frr_each(nhlfe_list, &lsp->nhlfe_list, nhlfe) {
char buf[BUFSIZ];
char lstr[30];
- snhlfe2str(snhlfe, buf, sizeof(buf));
- switch (snhlfe->out_label) {
+ nh = nhlfe->nexthop;
+ if (nh == NULL || nh->nh_label == NULL)
+ continue;
+
+ nhlfe_config_str(nhlfe, buf, sizeof(buf));
+
+ switch (nh->nh_label->label[0]) {
case MPLS_LABEL_IPV4_EXPLICIT_NULL:
case MPLS_LABEL_IPV6_EXPLICIT_NULL:
strlcpy(lstr, "explicit-null", sizeof(lstr));
break;
default:
snprintf(lstr, sizeof(lstr), "%u",
- snhlfe->out_label);
+ nh->nh_label->label[0]);
break;
}
- vty_out(vty, "mpls lsp %u %s %s\n", slsp->ile.in_label,
+ vty_out(vty, "mpls lsp %u %s %s\n", lsp->ile.in_label,
buf, lstr);
}
}