summaryrefslogtreecommitdiff
path: root/zebra/zebra_mpls.c
diff options
context:
space:
mode:
Diffstat (limited to 'zebra/zebra_mpls.c')
-rw-r--r--zebra/zebra_mpls.c152
1 files changed, 112 insertions, 40 deletions
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index e741268ebb..03b8c8de1f 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -47,6 +47,7 @@
#include "zebra/zebra_memory.h"
#include "zebra/zebra_vrf.h"
#include "zebra/zebra_mpls.h"
+#include "zebra/zebra_srte.h"
#include "zebra/zebra_errors.h"
DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object")
@@ -120,7 +121,8 @@ static int mpls_lsp_uninstall_all(struct hash *lsp_table, zebra_lsp_t *lsp,
enum lsp_types_t type);
static int mpls_static_lsp_uninstall_all(struct zebra_vrf *zvrf,
mpls_label_t in_label);
-static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty);
+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,
@@ -232,8 +234,7 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
if (IS_ZEBRA_DEBUG_MPLS) {
nhlfe2str(nhlfe, buf, BUFSIZ);
zlog_debug(
- "LSP in-label %u type %d nexthop %s "
- "out-label changed",
+ "LSP in-label %u type %d nexthop %s out-label changed",
lsp->ile.in_label, lsp_type, buf);
}
@@ -254,8 +255,7 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
if (IS_ZEBRA_DEBUG_MPLS) {
nhlfe2str(nhlfe, buf, BUFSIZ);
zlog_debug(
- "Add LSP in-label %u type %d nexthop %s "
- "out-label %u",
+ "Add LSP in-label %u type %d nexthop %s out-label %u",
lsp->ile.in_label, lsp_type, buf,
nexthop->nh_label->label[0]);
}
@@ -928,8 +928,7 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
if (newbest)
nhlfe2str(newbest, buf2, sizeof(buf2));
zlog_debug(
- "Process LSP in-label %u oldbest %s newbest %s "
- "flags 0x%x ecmp# %d",
+ "Process LSP in-label %u oldbest %s newbest %s flags 0x%x ecmp# %d",
lsp->ile.in_label, oldbest ? buf : "NULL",
newbest ? buf2 : "NULL", lsp->flags, lsp->num_ecmp);
}
@@ -957,9 +956,6 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
case ZEBRA_DPLANE_REQUEST_SUCCESS:
zvrf->lsp_installs++;
break;
- /* Should never happen */
- case ZEBRA_DPLANE_REQUEST_PENDING:
- break;
}
}
} else {
@@ -985,10 +981,6 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
case ZEBRA_DPLANE_REQUEST_SUCCESS:
zvrf->lsp_removals++;
break;
-
- /* Should never happen */
- case ZEBRA_DPLANE_REQUEST_PENDING:
- break;
}
} else if (CHECK_FLAG(lsp->flags, LSP_FLAG_CHANGED)) {
zebra_nhlfe_t *nhlfe;
@@ -1032,10 +1024,6 @@ static wq_item_status lsp_process(struct work_queue *wq, void *data)
case ZEBRA_DPLANE_REQUEST_SUCCESS:
zvrf->lsp_installs++;
break;
-
- /* Should never happen */
- case ZEBRA_DPLANE_REQUEST_PENDING:
- break;
}
}
}
@@ -1506,12 +1494,23 @@ static json_object *nhlfe_json(zebra_nhlfe_t *nhlfe)
{
char buf[BUFSIZ];
json_object *json_nhlfe = NULL;
+ json_object *json_backups = NULL;
+ json_object *json_label_stack;
struct nexthop *nexthop = nhlfe->nexthop;
+ int i;
json_nhlfe = json_object_new_object();
json_object_string_add(json_nhlfe, "type", nhlfe_type2str(nhlfe->type));
json_object_int_add(json_nhlfe, "outLabel",
nexthop->nh_label->label[0]);
+
+ json_label_stack = json_object_new_array();
+ json_object_object_add(json_nhlfe, "outLabelStack", json_label_stack);
+ for (i = 0; i < nexthop->nh_label->num_labels; i++)
+ json_object_array_add(
+ json_label_stack,
+ json_object_new_int(nexthop->nh_label->label[i]));
+
json_object_int_add(json_nhlfe, "distance", nhlfe->distance);
if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED))
@@ -1537,13 +1536,27 @@ static json_object *nhlfe_json(zebra_nhlfe_t *nhlfe)
default:
break;
}
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
+ json_backups = json_object_new_array();
+ for (i = 0; i < nexthop->backup_num; i++) {
+ json_object_array_add(
+ json_backups,
+ json_object_new_int(nexthop->backup_idx[i]));
+ }
+
+ json_object_object_add(json_nhlfe, "backupIndex",
+ json_backups);
+ }
+
return json_nhlfe;
}
/*
* Print the NHLFE for a LSP forwarding entry.
*/
-static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty)
+static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty,
+ const char *indent)
{
struct nexthop *nexthop;
char buf[MPLS_LABEL_STRLEN];
@@ -1558,6 +1571,10 @@ static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty)
nexthop->nh_label->label,
buf, sizeof(buf), 0),
nhlfe->distance);
+
+ if (indent)
+ vty_out(vty, "%s", indent);
+
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
@@ -1595,31 +1612,34 @@ static void nhlfe_print(zebra_nhlfe_t *nhlfe, struct vty *vty)
static void lsp_print(struct vty *vty, zebra_lsp_t *lsp)
{
zebra_nhlfe_t *nhlfe, *backup;
- int i;
+ int i, j;
vty_out(vty, "Local label: %u%s\n", lsp->ile.in_label,
CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED) ? " (installed)"
: "");
frr_each(nhlfe_list, &lsp->nhlfe_list, nhlfe) {
- nhlfe_print(nhlfe, vty);
+ nhlfe_print(nhlfe, vty, NULL);
- if (nhlfe->nexthop &&
- CHECK_FLAG(nhlfe->nexthop->flags,
- NEXTHOP_FLAG_HAS_BACKUP)) {
- /* Find backup in backup list */
+ if (nhlfe->nexthop == NULL ||
+ !CHECK_FLAG(nhlfe->nexthop->flags,
+ NEXTHOP_FLAG_HAS_BACKUP))
+ continue;
+ /* Backup nhlfes: find backups in backup list */
+
+ for (j = 0; j < nhlfe->nexthop->backup_num; j++) {
i = 0;
backup = NULL;
frr_each(nhlfe_list, &lsp->backup_nhlfe_list, backup) {
- if (i == nhlfe->nexthop->backup_idx)
+ if (i == nhlfe->nexthop->backup_idx[j])
break;
i++;
}
if (backup) {
vty_out(vty, " [backup %d]", i);
- nhlfe_print(backup, vty);
+ nhlfe_print(backup, vty, " ");
}
}
}
@@ -1643,6 +1663,19 @@ static json_object *lsp_json(zebra_lsp_t *lsp)
json_object_array_add(json_nhlfe_list, nhlfe_json(nhlfe));
json_object_object_add(json, "nexthops", json_nhlfe_list);
+ json_nhlfe_list = NULL;
+
+
+ frr_each(nhlfe_list, &lsp->backup_nhlfe_list, nhlfe) {
+ if (json_nhlfe_list == NULL)
+ json_nhlfe_list = json_object_new_array();
+
+ json_object_array_add(json_nhlfe_list, nhlfe_json(nhlfe));
+ }
+
+ if (json_nhlfe_list)
+ json_object_object_add(json, "backupNexthops", json_nhlfe_list);
+
return json;
}
@@ -1882,14 +1915,13 @@ static int mpls_processq_init(void)
}
-/* Public functions */
-
/*
* Process LSP update results from zebra dataplane.
*/
void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
{
struct zebra_vrf *zvrf;
+ mpls_label_t label;
zebra_ile_t tmp_ile;
struct hash *lsp_table;
zebra_lsp_t *lsp;
@@ -1897,6 +1929,7 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
struct nexthop *nexthop;
enum dplane_op_e op;
enum zebra_dplane_result status;
+ enum zebra_sr_policy_update_label_mode update_mode;
op = dplane_ctx_get_op(ctx);
status = dplane_ctx_get_status(ctx);
@@ -1907,6 +1940,8 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
dplane_ctx_get_in_label(ctx),
dplane_res2str(status));
+ label = dplane_ctx_get_in_label(ctx);
+
switch (op) {
case DPLANE_OP_LSP_INSTALL:
case DPLANE_OP_LSP_UPDATE:
@@ -1917,7 +1952,7 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
lsp_table = zvrf->lsp_table;
- tmp_ile.in_label = dplane_ctx_get_in_label(ctx);
+ tmp_ile.in_label = label;
lsp = hash_lookup(lsp_table, &tmp_ile);
if (lsp == NULL) {
if (IS_ZEBRA_DEBUG_DPLANE)
@@ -1951,13 +1986,21 @@ void zebra_mpls_lsp_dplane_result(struct zebra_dplane_ctx *ctx)
}
}
+ update_mode = (op == DPLANE_OP_LSP_INSTALL)
+ ? ZEBRA_SR_POLICY_LABEL_CREATED
+ : ZEBRA_SR_POLICY_LABEL_UPDATED;
+ zebra_sr_policy_label_update(label, update_mode);
break;
case DPLANE_OP_LSP_DELETE:
- if (status != ZEBRA_DPLANE_REQUEST_SUCCESS)
+ if (status != ZEBRA_DPLANE_REQUEST_SUCCESS) {
flog_warn(EC_ZEBRA_LSP_DELETE_FAILURE,
"LSP Deletion Failure: in-label %u",
dplane_ctx_get_in_label(ctx));
+ break;
+ }
+ zebra_sr_policy_label_update(label,
+ ZEBRA_SR_POLICY_LABEL_REMOVED);
break;
default:
@@ -2112,6 +2155,7 @@ static int update_nhlfes_from_ctx(struct nhlfe_list_head *nhlfe_head,
__func__, buf);
SET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
+ SET_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED);
} else {
if (is_debug)
@@ -2119,6 +2163,7 @@ static int update_nhlfes_from_ctx(struct nhlfe_list_head *nhlfe_head,
__func__, buf);
UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
+ UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED);
}
if (CHECK_FLAG(ctx_nhlfe->nexthop->flags,
@@ -2140,6 +2185,7 @@ static int update_nhlfes_from_ctx(struct nhlfe_list_head *nhlfe_head,
zlog_debug("%s: no match for lsp nhlfe %s",
__func__, buf);
UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED);
+ UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED);
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
}
@@ -3284,7 +3330,7 @@ lsp_add_nhlfe(zebra_lsp_t *lsp, enum lsp_types_t type,
/*
* Install an LSP and forwarding entry; used primarily
- * from zapi message processing.
+ * from vrf zapi message processing.
*/
int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
mpls_label_t in_label, uint8_t num_out_labels,
@@ -3335,8 +3381,19 @@ static int lsp_znh_install(zebra_lsp_t *lsp, enum lsp_types_t type,
/* Update backup info if present */
if (CHECK_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP)) {
- nhlfe->nexthop->backup_idx = znh->backup_idx;
+ if (znh->backup_num > NEXTHOP_MAX_BACKUPS) {
+ nhlfe_del(nhlfe);
+ return -1;
+ }
+
+ nhlfe->nexthop->backup_num = znh->backup_num;
+ memcpy(nhlfe->nexthop->backup_idx, znh->backup_idx,
+ znh->backup_num);
SET_FLAG(nhlfe->nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP);
+ } else {
+ /* Ensure there's no stale backup info */
+ UNSET_FLAG(nhlfe->nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP);
+ nhlfe->nexthop->backup_num = 0;
}
/* Queue LSP for processing. */
@@ -3371,6 +3428,21 @@ static int lsp_backup_znh_install(zebra_lsp_t *lsp, enum lsp_types_t type,
return 0;
}
+zebra_lsp_t *mpls_lsp_find(struct zebra_vrf *zvrf, mpls_label_t in_label)
+{
+ struct hash *lsp_table;
+ zebra_ile_t tmp_ile;
+
+ /* Lookup table. */
+ lsp_table = zvrf->lsp_table;
+ if (!lsp_table)
+ return NULL;
+
+ /* If entry is not present, exit. */
+ tmp_ile.in_label = in_label;
+ return hash_lookup(lsp_table, &tmp_ile);
+}
+
/*
* Uninstall a particular NHLFE in the forwarding table. If this is
* the only NHLFE, the entire LSP forwarding entry has to be deleted.
@@ -3408,7 +3480,7 @@ int mpls_lsp_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
return 0;
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",
in_label, type, buf, nhlfe->flags);
}
@@ -3639,10 +3711,9 @@ int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label,
return 0;
if (IS_ZEBRA_DEBUG_MPLS) {
- snhlfe2str(snhlfe, buf, BUFSIZ);
+ snhlfe2str(snhlfe, buf, sizeof(buf));
zlog_debug(
- "Upd static LSP in-label %u nexthop %s "
- "out-label %u (old %u)",
+ "Upd static LSP in-label %u nexthop %s out-label %u (old %u)",
in_label, buf, out_label, snhlfe->out_label);
}
snhlfe->out_label = out_label;
@@ -3653,7 +3724,7 @@ int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label,
return -1;
if (IS_ZEBRA_DEBUG_MPLS) {
- snhlfe2str(snhlfe, buf, BUFSIZ);
+ snhlfe2str(snhlfe, buf, sizeof(buf));
zlog_debug(
"Add static LSP in-label %u nexthop %s out-label %u",
in_label, buf, out_label);
@@ -3798,7 +3869,8 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp))
json_object_object_add(
- json, label2str(lsp->ile.in_label, buf, BUFSIZ),
+ json, label2str(lsp->ile.in_label, buf,
+ sizeof(buf)),
lsp_json(lsp));
vty_out(vty, "%s\n", json_object_to_json_string_ext(
@@ -3853,7 +3925,7 @@ void zebra_mpls_print_lsp_table(struct vty *vty, struct zebra_vrf *zvrf,
out_label_str = mpls_label2str(
nexthop->nh_label->num_labels,
&nexthop->nh_label->label[0],
- buf, BUFSIZ, 1);
+ buf, sizeof(buf), 1);
else
out_label_str = "-";