diff options
Diffstat (limited to 'zebra/zebra_mpls.c')
| -rw-r--r-- | zebra/zebra_mpls.c | 108 |
1 files changed, 74 insertions, 34 deletions
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index ef1bd02608..5146311c6a 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -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); @@ -218,7 +219,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; @@ -1197,7 +1199,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 +1219,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 +2086,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 +2570,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); + + zebra_nhg_re_update_ref(re, nhe); +} + static bool mpls_ftn_update_nexthop(int add, struct nexthop *nexthop, enum lsp_types_t type, mpls_label_t label) { @@ -2591,7 +2606,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); @@ -2658,12 +2672,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 +2693,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 +2712,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->ng); + + 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 +2735,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 +2764,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,7 +2948,6 @@ 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); @@ -2920,11 +2963,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 +3086,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; |
