]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zebra_mpls.c
Merge pull request #5793 from ton31337/fix/formatting_show_bgp_summary_failed
[mirror_frr.git] / zebra / zebra_mpls.c
index ef1bd02608be3c13344ab4d03f164d62f5745873..d5d424732acbfccc9b9a7bbd6147336d5521770e 100644 (file)
@@ -102,7 +102,8 @@ static zebra_nhlfe_t *nhlfe_find(zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
                                 ifindex_t ifindex);
 static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
                                enum nexthop_types_t gtype, union g_addr *gate,
-                               ifindex_t ifindex, mpls_label_t out_label);
+                               ifindex_t ifindex, uint8_t num_labels,
+                               mpls_label_t *labels);
 static int nhlfe_del(zebra_nhlfe_t *snhlfe);
 static void nhlfe_out_label_update(zebra_nhlfe_t *nhlfe,
                                   struct mpls_label_stack *nh_label);
@@ -185,7 +186,8 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
         * the label advertised by the recursive nexthop (plus we don't have the
         * logic yet to push multiple labels).
         */
-       for (nexthop = re->ng->nexthop; nexthop; nexthop = nexthop->next) {
+       for (nexthop = re->nhe->nhg->nexthop;
+            nexthop; nexthop = nexthop->next) {
                /* Skip inactive and recursive entries. */
                if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
                        continue;
@@ -218,7 +220,8 @@ static int lsp_install(struct zebra_vrf *zvrf, mpls_label_t label,
                        /* Add LSP entry to this nexthop */
                        nhlfe = nhlfe_add(lsp, lsp_type, nexthop->type,
                                          &nexthop->gate, nexthop->ifindex,
-                                         nexthop->nh_label->label[0]);
+                                         nexthop->nh_label->num_labels,
+                                         nexthop->nh_label->label);
                        if (!nhlfe)
                                return -1;
 
@@ -635,7 +638,7 @@ static int nhlfe_nexthop_active_ipv4(zebra_nhlfe_t *nhlfe,
                    || !CHECK_FLAG(match->flags, ZEBRA_FLAG_SELECTED))
                        continue;
 
-               for (match_nh = match->ng->nexthop; match_nh;
+               for (match_nh = match->nhe->nhg->nexthop; match_nh;
                     match_nh = match_nh->next) {
                        if (match->type == ZEBRA_ROUTE_CONNECT
                            || nexthop->ifindex == match_nh->ifindex) {
@@ -686,10 +689,10 @@ static int nhlfe_nexthop_active_ipv6(zebra_nhlfe_t *nhlfe,
                        break;
        }
 
-       if (!match || !match->ng->nexthop)
+       if (!match || !match->nhe->nhg->nexthop)
                return 0;
 
-       nexthop->ifindex = match->ng->nexthop->ifindex;
+       nexthop->ifindex = match->nhe->nhg->nexthop->ifindex;
        return 1;
 }
 
@@ -1197,7 +1200,8 @@ static zebra_nhlfe_t *nhlfe_find(zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
  */
 static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
                                enum nexthop_types_t gtype, union g_addr *gate,
-                               ifindex_t ifindex, mpls_label_t out_label)
+                               ifindex_t ifindex, uint8_t num_labels,
+                               mpls_label_t labels[])
 {
        zebra_nhlfe_t *nhlfe;
        struct nexthop *nexthop;
@@ -1216,7 +1220,7 @@ static zebra_nhlfe_t *nhlfe_add(zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
                XFREE(MTYPE_NHLFE, nhlfe);
                return NULL;
        }
-       nexthop_add_labels(nexthop, lsp_type, 1, &out_label);
+       nexthop_add_labels(nexthop, lsp_type, num_labels, labels);
 
        nexthop->vrf_id = VRF_DEFAULT;
        nexthop->type = gtype;
@@ -2083,10 +2087,12 @@ zebra_nhlfe_t *zebra_mpls_lsp_add_nhlfe(zebra_lsp_t *lsp,
                                        enum nexthop_types_t gtype,
                                        union g_addr *gate,
                                        ifindex_t ifindex,
-                                       mpls_label_t out_label)
+                                       uint8_t num_labels,
+                                       mpls_label_t out_labels[])
 {
        /* Just a public pass-through to the internal implementation */
-       return nhlfe_add(lsp, lsp_type, gtype, gate, ifindex, out_label);
+       return nhlfe_add(lsp, lsp_type, gtype, gate, ifindex, num_labels,
+                        out_labels);
 }
 
 /*
@@ -2565,6 +2571,16 @@ void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf,
        fec_print(rn->info, vty);
 }
 
+static void mpls_zebra_nhg_update(struct route_entry *re, afi_t afi,
+                                 struct nexthop_group *new_grp)
+{
+       struct nhg_hash_entry *nhe;
+
+       nhe = zebra_nhg_rib_find(0, new_grp, afi);
+
+       route_entry_update_nhe(re, nhe);
+}
+
 static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop,
                                    enum lsp_types_t type, mpls_label_t label)
 {
@@ -2591,7 +2607,6 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
        struct route_entry *re;
        struct nexthop *nexthop;
        struct nexthop_group new_grp = {};
-       struct nhg_hash_entry *nhe = NULL;
        bool found;
        afi_t afi = family2afi(prefix->family);
 
@@ -2617,7 +2632,7 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
         * We can't just change the values here since we are hashing
         * on labels. We need to create a whole new group
         */
-       nexthop_group_copy(&new_grp, re->ng);
+       nexthop_group_copy(&new_grp, re->nhe->nhg);
 
        found = false;
        for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next) {
@@ -2658,12 +2673,11 @@ int mpls_ftn_update(int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
        }
 
        if (found) {
-               nhe = zebra_nhg_rib_find(0, &new_grp, afi);
-
-               zebra_nhg_re_update_ref(re, nhe);
-
                SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
                SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
+
+               mpls_zebra_nhg_update(re, afi, &new_grp);
+
                rib_queue_add(rn);
        }
 
@@ -2680,10 +2694,11 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
        struct route_node *rn;
        struct route_entry *re;
        struct nexthop *nexthop;
+       struct nexthop_group new_grp = {};
+       afi_t afi = family2afi(prefix->family);
 
        /* Lookup table.  */
-       table = zebra_vrf_table(family2afi(prefix->family), SAFI_UNICAST,
-                               zvrf_id(zvrf));
+       table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf));
        if (!table)
                return -1;
 
@@ -2698,11 +2713,18 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
        if (re == NULL)
                return -1;
 
-       for (nexthop = re->ng->nexthop; nexthop; nexthop = nexthop->next)
+       nexthop_group_copy(&new_grp, re->nhe->nhg);
+
+       for (nexthop = new_grp.nexthop; nexthop; nexthop = nexthop->next)
                nexthop_del_labels(nexthop);
 
        SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
        SET_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED);
+
+       mpls_zebra_nhg_update(re, afi, &new_grp);
+
+       nexthops_free(new_grp.nexthop);
+
        rib_queue_add(rn);
 
        return 0;
@@ -2714,9 +2736,9 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
  * the out-label for an existing NHLFE (update case).
  */
 int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
-                    mpls_label_t in_label, mpls_label_t out_label,
-                    enum nexthop_types_t gtype, union g_addr *gate,
-                    ifindex_t ifindex)
+                    mpls_label_t in_label, uint8_t num_out_labels,
+                    mpls_label_t out_labels[], enum nexthop_types_t gtype,
+                    union g_addr *gate, ifindex_t ifindex)
 {
        struct hash *lsp_table;
        zebra_ile_t tmp_ile;
@@ -2743,33 +2765,56 @@ int mpls_lsp_install(struct zebra_vrf *zvrf, enum lsp_types_t type,
 
                /* Clear deleted flag (in case it was set) */
                UNSET_FLAG(nhlfe->flags, NHLFE_FLAG_DELETED);
-               if (nh->nh_label->label[0] == out_label)
+               if (nh->nh_label->num_labels == num_out_labels
+                   && !memcmp(nh->nh_label->label, out_labels,
+                              sizeof(mpls_label_t) * num_out_labels))
                        /* No change */
                        return 0;
 
                if (IS_ZEBRA_DEBUG_MPLS) {
+                       char buf2[BUFSIZ];
+                       char buf3[BUFSIZ];
+
                        nhlfe2str(nhlfe, buf, BUFSIZ);
+                       mpls_label2str(num_out_labels, out_labels, buf2,
+                                      sizeof(buf2), 0);
+                       mpls_label2str(nh->nh_label->num_labels,
+                                      nh->nh_label->label, buf3, sizeof(buf3),
+                                      0);
+
                        zlog_debug(
                                "LSP in-label %u type %d nexthop %s "
-                               "out-label changed to %u (old %u)",
-                               in_label, type, buf, out_label,
-                               nh->nh_label->label[0]);
+                               "out-label(s) changed to %s (old %s)",
+                               in_label, type, buf, buf2, buf3);
                }
 
-               /* Update out label, trigger processing. */
-               nh->nh_label->label[0] = out_label;
+               /* Update out label(s), trigger processing. */
+               if (nh->nh_label->num_labels == num_out_labels)
+                       memcpy(nh->nh_label->label, out_labels,
+                              sizeof(mpls_label_t) * num_out_labels);
+               else {
+                       nexthop_del_labels(nh);
+                       nexthop_add_labels(nh, type, num_out_labels,
+                                          out_labels);
+               }
        } else {
                /* Add LSP entry to this nexthop */
-               nhlfe = nhlfe_add(lsp, type, gtype, gate, ifindex, out_label);
+               nhlfe = nhlfe_add(lsp, type, gtype, gate, ifindex,
+                                 num_out_labels, out_labels);
                if (!nhlfe)
                        return -1;
 
                if (IS_ZEBRA_DEBUG_MPLS) {
+                       char buf2[BUFSIZ];
+
                        nhlfe2str(nhlfe, buf, BUFSIZ);
+                       mpls_label2str(num_out_labels, out_labels, buf2,
+                                      sizeof(buf2), 0);
+
                        zlog_debug(
                                "Add LSP in-label %u type %d nexthop %s "
-                               "out-label %u",
-                               in_label, type, buf, out_label);
+                               "out-label(s) %s",
+                               in_label, type, buf, buf2);
                }
 
                lsp->addr_family = NHLFE_FAMILY(nhlfe);
@@ -2904,9 +2949,8 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
                update = 0;
                RNODE_FOREACH_RE (rn, re) {
                        struct nexthop_group new_grp = {};
-                       struct nhg_hash_entry *nhe = NULL;
 
-                       nexthop_group_copy(&new_grp, re->ng);
+                       nexthop_group_copy(&new_grp, re->nhe->nhg);
 
                        for (nexthop = new_grp.nexthop; nexthop;
                             nexthop = nexthop->next) {
@@ -2920,11 +2964,8 @@ static void mpls_ftn_uninstall_all(struct zebra_vrf *zvrf,
                                update = 1;
                        }
 
-                       if (CHECK_FLAG(re->status,
-                                      ROUTE_ENTRY_LABELS_CHANGED)) {
-                               nhe = zebra_nhg_rib_find(0, &new_grp, afi);
-                               zebra_nhg_re_update_ref(re, nhe);
-                       }
+                       if (CHECK_FLAG(re->status, ROUTE_ENTRY_LABELS_CHANGED))
+                               mpls_zebra_nhg_update(re, afi, &new_grp);
 
                        nexthops_free(new_grp.nexthop);
                }
@@ -3046,8 +3087,8 @@ int zebra_mpls_static_lsp_add(struct zebra_vrf *zvrf, mpls_label_t in_label,
        }
 
        /* (Re)Install LSP in the main table. */
-       if (mpls_lsp_install(zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype,
-                            gate, ifindex))
+       if (mpls_lsp_install(zvrf, ZEBRA_LSP_STATIC, in_label, 1, &out_label,
+                            gtype, gate, ifindex))
                return -1;
 
        return 0;