summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/zebra_nhg.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 4763d7741..1354f6813 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -1811,6 +1811,8 @@ static int resolve_backup_nexthops(const struct nexthop *nexthop,
int i, j, idx;
const struct nexthop *bnh;
struct nexthop *nh, *newnh;
+ mpls_label_t labels[MPLS_MAX_LABELS];
+ uint8_t num_labels;
assert(nexthop->backup_num <= NEXTHOP_MAX_BACKUPS);
@@ -1861,6 +1863,40 @@ static int resolve_backup_nexthops(const struct nexthop *nexthop,
/* Update backup info in the resolving nexthop and its nhe */
newnh = nexthop_dup_no_recurse(bnh, NULL);
+ /* We may need some special handling for mpls labels: the new
+ * backup needs to carry the recursive nexthop's labels,
+ * if any: they may be vrf labels e.g.
+ * The original/inner labels are in the stack of 'resolve_nhe',
+ * if that is longer than the stack in 'nexthop'.
+ */
+ if (newnh->nh_label && resolved->nh_label &&
+ nexthop->nh_label) {
+ if (resolved->nh_label->num_labels >
+ nexthop->nh_label->num_labels) {
+ /* Prepare new label stack */
+ num_labels = 0;
+ for (j = 0; j < newnh->nh_label->num_labels;
+ j++) {
+ labels[j] = newnh->nh_label->label[j];
+ num_labels++;
+ }
+
+ /* Include inner labels */
+ for (j = nexthop->nh_label->num_labels;
+ j < resolved->nh_label->num_labels;
+ j++) {
+ labels[num_labels] =
+ resolved->nh_label->label[j];
+ num_labels++;
+ }
+
+ /* Replace existing label stack in the backup */
+ nexthop_del_labels(newnh);
+ nexthop_add_labels(newnh, bnh->nh_label_type,
+ num_labels, labels);
+ }
+ }
+
/* Need to compute the new backup index in the new
* backup list, and add to map struct.
*/