/* static function declarations */
+static int
+lsp_install (struct zebra_vrf *zvrf, mpls_label_t label,
+ struct route_node *rn, struct rib *rib);
+static int
+lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t label);
+static int
+fec_change_update_lsp (struct zebra_vrf *zvrf, zebra_fec_t *fec, mpls_label_t old_label);
static int
fec_send (zebra_fec_t *fec, struct zserv *client);
static void
static zebra_fec_t *
fec_find (struct route_table *table, struct prefix *p);
static zebra_fec_t *
-fec_add (struct route_table *table, struct prefix *p, u_int32_t label,
+fec_add (struct route_table *table, struct prefix *p, mpls_label_t label,
u_int32_t flags);
static int
fec_del (zebra_fec_t *fec);
nhlfe2str (zebra_nhlfe_t *nhlfe, char *buf, int size);
static int
nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype,
- union g_addr *gate, char *ifname, ifindex_t ifindex);
+ union g_addr *gate, ifindex_t ifindex);
static zebra_nhlfe_t *
nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
enum nexthop_types_t gtype, union g_addr *gate,
- char *ifname, ifindex_t ifindex);
+ 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,
- char *ifname, ifindex_t ifindex, mpls_label_t out_label);
+ ifindex_t ifindex, mpls_label_t out_label);
static int
nhlfe_del (zebra_nhlfe_t *snhlfe);
+static void
+nhlfe_out_label_update (zebra_nhlfe_t *nhlfe, struct nexthop_label *nh_label);
static int
mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp,
enum lsp_types_t type);
slsp_alloc (void *p);
static int
snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype,
- union g_addr *gate, char *ifname, ifindex_t ifindex);
+ union g_addr *gate, ifindex_t ifindex);
static zebra_snhlfe_t *
snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
- union g_addr *gate, char *ifname, ifindex_t ifindex);
+ union g_addr *gate, ifindex_t ifindex);
static zebra_snhlfe_t *
snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
- union g_addr *gate, char *ifname, ifindex_t ifindex,
- mpls_label_t out_label);
+ union g_addr *gate, ifindex_t ifindex, mpls_label_t out_label);
static int
snhlfe_del (zebra_snhlfe_t *snhlfe);
static int
/* Static functions */
+/*
+ * Install label forwarding entry based on labeled-route entry.
+ */
+static int
+lsp_install (struct zebra_vrf *zvrf, mpls_label_t label,
+ struct route_node *rn, struct rib *rib)
+{
+ struct hash *lsp_table;
+ zebra_ile_t tmp_ile;
+ zebra_lsp_t *lsp;
+ zebra_nhlfe_t *nhlfe;
+ struct nexthop *nexthop;
+ enum lsp_types_t lsp_type;
+ char buf[BUFSIZ];
+ int added, changed;
+
+ /* Lookup table. */
+ lsp_table = zvrf->lsp_table;
+ if (!lsp_table)
+ return -1;
+
+ /* See if route entry is selected; we really expect only 1 entry here. */
+ if (!CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+ return 0;
+
+ lsp_type = lsp_type_from_rib_type (rib->type);
+ added = changed = 0;
+
+ /* Locate or allocate LSP entry. */
+ tmp_ile.in_label = label;
+ lsp = hash_get (lsp_table, &tmp_ile, lsp_alloc);
+ if (!lsp)
+ return -1;
+
+ /* For each active nexthop, create NHLFE. Note that we deliberately skip
+ * recursive nexthops right now, because intermediate hops won't understand
+ * the label advertised by the recursive nexthop (plus we don't have the
+ * logic yet to push multiple labels).
+ */
+ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+ {
+ /* Skip inactive and recursive entries. */
+ if (!CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ continue;
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ continue;
+
+ nhlfe = nhlfe_find (lsp, lsp_type, nexthop->type, &nexthop->gate,
+ nexthop->ifindex);
+ if (nhlfe)
+ {
+ /* Clear deleted flag (in case it was set) */
+ UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED);
+ if (nexthop_labels_match (nhlfe->nexthop, nexthop))
+ /* No change */
+ continue;
+
+
+ if (IS_ZEBRA_DEBUG_MPLS)
+ {
+ nhlfe2str (nhlfe, buf, BUFSIZ);
+ zlog_debug ("LSP in-label %u type %d nexthop %s "
+ "out-label changed",
+ lsp->ile.in_label, lsp_type, buf);
+ }
+
+ /* Update out label, trigger processing. */
+ nhlfe_out_label_update (nhlfe, nexthop->nh_label);
+ SET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED);
+ changed++;
+ }
+ else
+ {
+ /* Add LSP entry to this nexthop */
+ nhlfe = nhlfe_add (lsp, lsp_type, nexthop->type,
+ &nexthop->gate, nexthop->ifindex,
+ nexthop->nh_label->label[0]);
+ if (!nhlfe)
+ return -1;
+
+ if (IS_ZEBRA_DEBUG_MPLS)
+ {
+ nhlfe2str (nhlfe, buf, BUFSIZ);
+ zlog_debug ("Add LSP in-label %u type %d nexthop %s "
+ "out-label %u",
+ lsp->ile.in_label, lsp_type, buf,
+ nexthop->nh_label->label[0]);
+ }
+
+ lsp->addr_family = NHLFE_FAMILY (nhlfe);
+
+ /* Mark NHLFE as changed. */
+ SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED);
+ added++;
+ }
+ }
+
+ /* Queue LSP for processing if necessary. If no NHLFE got added (special
+ * case), delete the LSP entry; this case results in somewhat ugly logging.
+ */
+ if (added || changed)
+ {
+ if (lsp_processq_add (lsp))
+ return -1;
+ }
+ else if (!lsp->nhlfe_list &&
+ !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED))
+ {
+ if (IS_ZEBRA_DEBUG_MPLS)
+ zlog_debug ("Free LSP in-label %u flags 0x%x",
+ lsp->ile.in_label, lsp->flags);
+
+ lsp = hash_release(lsp_table, &lsp->ile);
+ if (lsp)
+ XFREE(MTYPE_LSP, lsp);
+ }
+
+ return 0;
+}
+
+/*
+ * Uninstall all non-static NHLFEs of a label forwarding entry. If all
+ * NHLFEs are removed, the entire entry is deleted.
+ */
+static int
+lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t label)
+{
+ struct hash *lsp_table;
+ zebra_ile_t tmp_ile;
+ zebra_lsp_t *lsp;
+ zebra_nhlfe_t *nhlfe, *nhlfe_next;
+ char buf[BUFSIZ];
+
+ /* Lookup table. */
+ lsp_table = zvrf->lsp_table;
+ if (!lsp_table)
+ return -1;
+
+ /* If entry is not present, exit. */
+ tmp_ile.in_label = label;
+ lsp = hash_lookup (lsp_table, &tmp_ile);
+ if (!lsp || !lsp->nhlfe_list)
+ return 0;
+
+ /* Mark NHLFEs for delete or directly delete, as appropriate. */
+ for (nhlfe = lsp->nhlfe_list; nhlfe; nhlfe = nhlfe_next)
+ {
+ nhlfe_next = nhlfe->next;
+
+ /* Skip static NHLFEs */
+ if (nhlfe->type == ZEBRA_LSP_STATIC)
+ continue;
+
+ if (IS_ZEBRA_DEBUG_MPLS)
+ {
+ nhlfe2str (nhlfe, buf, BUFSIZ);
+ zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x",
+ label, nhlfe->type, buf, nhlfe->flags);
+ }
+
+ if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_SELECTED))
+ {
+ UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED);
+ SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED);
+ }
+ else
+ {
+ nhlfe_del (nhlfe);
+ }
+ }
+
+ /* Queue LSP for processing, if needed, else delete. */
+ if (CHECK_FLAG(lsp->flags, LSP_FLAG_INSTALLED))
+ {
+ if (lsp_processq_add (lsp))
+ return -1;
+ }
+ else if (!lsp->nhlfe_list &&
+ !CHECK_FLAG (lsp->flags, LSP_FLAG_SCHEDULED))
+ {
+ if (IS_ZEBRA_DEBUG_MPLS)
+ zlog_debug ("Del LSP in-label %u flags 0x%x",
+ lsp->ile.in_label, lsp->flags);
+
+ lsp = hash_release(lsp_table, &lsp->ile);
+ if (lsp)
+ XFREE(MTYPE_LSP, lsp);
+ }
+
+ return 0;
+}
+
+/*
+ * There is a change for this FEC. Install or uninstall label forwarding
+ * entries, as appropriate.
+ */
+static int
+fec_change_update_lsp (struct zebra_vrf *zvrf, zebra_fec_t *fec, mpls_label_t old_label)
+{
+ struct route_table *table;
+ struct route_node *rn;
+ struct rib *rib;
+ afi_t afi;
+
+ /* Uninstall label forwarding entry, if previously installed. */
+ if (old_label != MPLS_INVALID_LABEL &&
+ old_label != MPLS_IMP_NULL_LABEL)
+ lsp_uninstall (zvrf, old_label);
+
+ /* Install label forwarding entry corr. to new label, if needed. */
+ if (fec->label == MPLS_INVALID_LABEL ||
+ fec->label == MPLS_IMP_NULL_LABEL)
+ return 0;
+
+ afi = family2afi(PREFIX_FAMILY(&fec->rn->p));
+ table = zebra_vrf_table (afi, SAFI_UNICAST, zvrf_id (zvrf));
+ if (!table)
+ return 0;
+
+ /* See if labeled route exists. */
+ rn = route_node_lookup (table, &fec->rn->p);
+ if (!rn)
+ return 0;
+
+ RNODE_FOREACH_RIB (rn, rib)
+ {
+ if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_SELECTED))
+ break;
+ }
+
+ if (!rib || !zebra_rib_labeled_unicast (rib))
+ return 0;
+
+ if (lsp_install (zvrf, fec->label, rn, rib))
+ return -1;
+
+ return 0;
+}
+
/*
* Inform about FEC to a registered client.
*/
*/
static int
nhlfe_nhop_match (zebra_nhlfe_t *nhlfe, enum nexthop_types_t gtype,
- union g_addr *gate, char *ifname, ifindex_t ifindex)
+ union g_addr *gate, ifindex_t ifindex)
{
struct nexthop *nhop;
int cmp = 1;
static zebra_nhlfe_t *
nhlfe_find (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
enum nexthop_types_t gtype, union g_addr *gate,
- char *ifname, ifindex_t ifindex)
+ ifindex_t ifindex)
{
zebra_nhlfe_t *nhlfe;
{
if (nhlfe->type != lsp_type)
continue;
- if (!nhlfe_nhop_match (nhlfe, gtype, gate, ifname, ifindex))
+ if (!nhlfe_nhop_match (nhlfe, gtype, gate, ifindex))
break;
}
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,
- char *ifname, ifindex_t ifindex, mpls_label_t out_label)
+ ifindex_t ifindex, mpls_label_t out_label)
{
zebra_nhlfe_t *nhlfe;
struct nexthop *nexthop;
return 0;
}
+/*
+ * Update label for NHLFE entry.
+ */
+static void
+nhlfe_out_label_update (zebra_nhlfe_t *nhlfe, struct nexthop_label *nh_label)
+{
+ nhlfe->nexthop->nh_label->label[0] = nh_label->label[0];
+}
+
static int
mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp,
enum lsp_types_t type)
*/
static int
snhlfe_match (zebra_snhlfe_t *snhlfe, enum nexthop_types_t gtype,
- union g_addr *gate, char *ifname, ifindex_t ifindex)
+ union g_addr *gate, ifindex_t ifindex)
{
int cmp = 1;
*/
static zebra_snhlfe_t *
snhlfe_find (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
- union g_addr *gate, char *ifname, ifindex_t ifindex)
+ union g_addr *gate, ifindex_t ifindex)
{
zebra_snhlfe_t *snhlfe;
for (snhlfe = slsp->snhlfe_list; snhlfe; snhlfe = snhlfe->next)
{
- if (!snhlfe_match (snhlfe, gtype, gate, ifname, ifindex))
+ if (!snhlfe_match (snhlfe, gtype, gate, ifindex))
break;
}
*/
static zebra_snhlfe_t *
snhlfe_add (zebra_slsp_t *slsp, enum nexthop_types_t gtype,
- union g_addr *gate, char *ifname, ifindex_t ifindex,
+ union g_addr *gate, ifindex_t ifindex,
mpls_label_t out_label)
{
zebra_snhlfe_t *snhlfe;
*num_labels = 0;
for (i = 0; i < MPLS_MAX_LABELS; i++)
{
- u_int32_t label;
+ mpls_label_t label;
label = strtoul(label_str, &endp, 0);
return buf;
}
+/*
+ * Install dynamic LSP entry.
+ */
+int
+zebra_mpls_lsp_install (struct zebra_vrf *zvrf, struct route_node *rn, struct rib *rib)
+{
+ struct route_table *table;
+ zebra_fec_t *fec;
+
+ table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))];
+ if (!table)
+ return -1;
+
+ /* See if there is a configured label binding for this FEC. */
+ fec = fec_find (table, &rn->p);
+ if (!fec || fec->label == MPLS_INVALID_LABEL)
+ return 0;
+
+ /* We cannot install a label forwarding entry if local label is the
+ * implicit-null label.
+ */
+ if (fec->label == MPLS_IMP_NULL_LABEL)
+ return 0;
+
+ if (lsp_install (zvrf, fec->label, rn, rib))
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Uninstall dynamic LSP entry, if any.
+ */
+int
+zebra_mpls_lsp_uninstall (struct zebra_vrf *zvrf, struct route_node *rn, struct rib *rib)
+{
+ struct route_table *table;
+ zebra_fec_t *fec;
+
+ table = zvrf->fec_table[family2afi(PREFIX_FAMILY(&rn->p))];
+ if (!table)
+ return -1;
+
+ /* See if there is a configured label binding for this FEC. */
+ fec = fec_find (table, &rn->p);
+ if (!fec || fec->label == MPLS_INVALID_LABEL)
+ return 0;
+
+ /* Uninstall always removes all dynamic NHLFEs. */
+ return lsp_uninstall (zvrf, fec->label);
+}
+
/*
* Registration from a client for the label binding for a FEC. If a binding
* already exists, it is informed to the client.
/*
* Add static FEC to label binding. If there are clients registered for this
- * FEC, notify them.
+ * FEC, notify them. If there are labeled routes for this FEC, install the
+ * label forwarding entry.
*/
int
zebra_mpls_static_fec_add (struct zebra_vrf *zvrf, struct prefix *p,
struct route_table *table;
zebra_fec_t *fec;
char buf[BUFSIZ];
+ mpls_label_t old_label;
int ret = 0;
table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))];
return 0;
/* Label change, update clients. */
+ old_label = fec->label;
if (IS_ZEBRA_DEBUG_MPLS)
zlog_debug ("Update fec %s new label %u", buf, in_label);
fec->label = in_label;
fec_update_clients (fec);
+
+ /* Update label forwarding entries appropriately */
+ ret = fec_change_update_lsp (zvrf, fec, old_label);
}
return ret;
{
struct route_table *table;
zebra_fec_t *fec;
+ mpls_label_t old_label;
char buf[BUFSIZ];
table = zvrf->fec_table[family2afi(PREFIX_FAMILY(p))];
zlog_debug ("Delete fec %s", buf);
}
+ old_label = fec->label;
fec->flags &= ~FEC_FLAG_CONFIGURED;
fec->label = MPLS_INVALID_LABEL;
fec_update_clients (fec);
- return 0;
+ /* Update label forwarding entries appropriately */
+ return fec_change_update_lsp (zvrf, fec, old_label);
}
/*
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,
- char *ifname, ifindex_t ifindex)
+ ifindex_t ifindex)
{
struct hash *lsp_table;
zebra_ile_t tmp_ile;
lsp = hash_get (lsp_table, &tmp_ile, lsp_alloc);
if (!lsp)
return -1;
- nhlfe = nhlfe_find (lsp, type, gtype, gate, ifname, ifindex);
+ nhlfe = nhlfe_find (lsp, type, gtype, gate, ifindex);
if (nhlfe)
{
struct nexthop *nh = nhlfe->nexthop;
else
{
/* Add LSP entry to this nexthop */
- nhlfe = nhlfe_add (lsp, type, gtype, gate,
- ifname, ifindex, out_label);
+ nhlfe = nhlfe_add (lsp, type, gtype, gate, ifindex, out_label);
if (!nhlfe)
return -1;
int
mpls_lsp_uninstall (struct zebra_vrf *zvrf, enum lsp_types_t type,
mpls_label_t in_label, enum nexthop_types_t gtype,
- union g_addr *gate, char *ifname, ifindex_t ifindex)
+ union g_addr *gate, ifindex_t ifindex)
{
struct hash *lsp_table;
zebra_ile_t tmp_ile;
lsp = hash_lookup (lsp_table, &tmp_ile);
if (!lsp)
return 0;
- nhlfe = nhlfe_find (lsp, type, gtype, gate, ifname, ifindex);
+ nhlfe = nhlfe_find (lsp, type, gtype, gate, ifindex);
if (!nhlfe)
return 0;
int
zebra_mpls_lsp_label_consistent (struct zebra_vrf *zvrf, mpls_label_t in_label,
mpls_label_t out_label, enum nexthop_types_t gtype,
- union g_addr *gate, char *ifname, ifindex_t ifindex)
+ union g_addr *gate, ifindex_t ifindex)
{
struct hash *slsp_table;
zebra_ile_t tmp_ile;
if (!slsp)
return 1;
- snhlfe = snhlfe_find (slsp, gtype, gate, ifname, ifindex);
+ snhlfe = snhlfe_find (slsp, gtype, gate, ifindex);
if (snhlfe)
{
if (snhlfe->out_label == out_label)
int
zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label,
mpls_label_t out_label, enum nexthop_types_t gtype,
- union g_addr *gate, char *ifname, ifindex_t ifindex)
+ union g_addr *gate, ifindex_t ifindex)
{
struct hash *slsp_table;
zebra_ile_t tmp_ile;
slsp = hash_get (slsp_table, &tmp_ile, slsp_alloc);
if (!slsp)
return -1;
- snhlfe = snhlfe_find (slsp, gtype, gate, ifname, ifindex);
+ snhlfe = snhlfe_find (slsp, gtype, gate, ifindex);
if (snhlfe)
{
if (snhlfe->out_label == out_label)
else
{
/* Add static LSP entry to this nexthop */
- snhlfe = snhlfe_add (slsp, gtype, gate, ifname, ifindex, out_label);
+ snhlfe = snhlfe_add (slsp, gtype, gate, ifindex, out_label);
if (!snhlfe)
return -1;
/* (Re)Install LSP in the main table. */
if (mpls_lsp_install (zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype,
- gate, ifname, ifindex))
+ gate, ifindex))
return -1;
return 0;
int
zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label,
enum nexthop_types_t gtype, union g_addr *gate,
- char *ifname, ifindex_t ifindex)
+ ifindex_t ifindex)
{
struct hash *slsp_table;
zebra_ile_t tmp_ile;
else
{
/* Find specific NHLFE, exit if not found. */
- snhlfe = snhlfe_find (slsp, gtype, gate, ifname, ifindex);
+ snhlfe = snhlfe_find (slsp, gtype, gate, ifindex);
if (!snhlfe)
return 0;
/* Uninstall LSP from the main table. */
mpls_lsp_uninstall (zvrf, ZEBRA_LSP_STATIC, in_label, gtype, gate,
- ifname, ifindex);
+ ifindex);
/* Delete static LSP NHLFE */
snhlfe_del (snhlfe);
struct rib *rib;
struct prefix p;
u_char message;
- struct in_addr nexthop;
+ struct in_addr nhop_addr;
u_char nexthop_num;
u_char nexthop_type;
struct stream *s;
ifindex_t ifindex;
safi_t safi;
int ret;
+ mpls_label_t label;
+ struct nexthop *nexthop;
/* Get input stream. */
s = client->ibuf;
rib_nexthop_ifindex_add (rib, ifindex);
break;
case NEXTHOP_TYPE_IPV4:
- nexthop.s_addr = stream_get_ipv4 (s);
- rib_nexthop_ipv4_add (rib, &nexthop, NULL);
+ nhop_addr.s_addr = stream_get_ipv4 (s);
+ nexthop = rib_nexthop_ipv4_add (rib, &nhop_addr, NULL);
+ /* For labeled-unicast, each nexthop is followed by label. */
+ if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL))
+ {
+ label = (mpls_label_t)stream_getl (s);
+ nexthop_add_labels (nexthop, nexthop->nh_label_type, 1, &label);
+ }
break;
case NEXTHOP_TYPE_IPV4_IFINDEX:
- nexthop.s_addr = stream_get_ipv4 (s);
+ nhop_addr.s_addr = stream_get_ipv4 (s);
ifindex = stream_getl (s);
- rib_nexthop_ipv4_ifindex_add (rib, &nexthop, NULL, ifindex);
+ rib_nexthop_ipv4_ifindex_add (rib, &nhop_addr, NULL, ifindex);
break;
case NEXTHOP_TYPE_IPV6:
stream_forward_getp (s, IPV6_MAX_BYTELEN);
break;
case NEXTHOP_TYPE_IPV4:
nexthop.s_addr = stream_get_ipv4 (s);
+ /* For labeled-unicast, each nexthop is followed by label, but
+ * we don't care for delete.
+ */
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_LABEL))
+ stream_forward_getp (s, sizeof(u_int32_t));
nexthop_p = (union g_addr *)&nexthop;
break;
case NEXTHOP_TYPE_IPV4_IFINDEX:
{
unsigned int i;
struct stream *s;
- struct in6_addr nexthop;
+ struct in6_addr nhop_addr;
struct rib *rib;
u_char message;
u_char nexthop_num;
static struct in6_addr nexthops[MULTIPATH_NUM];
static unsigned int ifindices[MULTIPATH_NUM];
int ret;
+ static mpls_label_t labels[MULTIPATH_NUM];
+ mpls_label_t label;
+ struct nexthop *nexthop;
/* Get input stream. */
s = client->ibuf;
- memset (&nexthop, 0, sizeof (struct in6_addr));
+ memset (&nhop_addr, 0, sizeof (struct in6_addr));
/* Allocate new rib. */
rib = XCALLOC (MTYPE_RIB, sizeof (struct rib));
switch (nexthop_type)
{
case NEXTHOP_TYPE_IPV6:
- stream_get (&nexthop, s, 16);
- if (nh_count < multipath_num) {
- nexthops[nh_count++] = nexthop;
- }
+ stream_get (&nhop_addr, s, 16);
+ if (nh_count < MULTIPATH_NUM)
+ {
+ /* For labeled-unicast, each nexthop is followed by label. */
+ if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL))
+ {
+ label = (mpls_label_t)stream_getl (s);
+ labels[nh_count++] = label;
+ }
+ nexthops[nh_count++] = nhop_addr;
+ }
break;
case NEXTHOP_TYPE_IFINDEX:
if (if_count < multipath_num) {
{
if ((i < nh_count) && !IN6_IS_ADDR_UNSPECIFIED (&nexthops[i])) {
if ((i < if_count) && ifindices[i])
- rib_nexthop_ipv6_ifindex_add (rib, &nexthops[i], ifindices[i]);
+ nexthop = rib_nexthop_ipv6_ifindex_add (rib, &nexthops[i], ifindices[i]);
else
- rib_nexthop_ipv6_add (rib, &nexthops[i]);
+ nexthop = rib_nexthop_ipv6_add (rib, &nexthops[i]);
+ if (CHECK_FLAG (message, ZAPI_MESSAGE_LABEL))
+ nexthop_add_labels (nexthop, nexthop->nh_label_type, 1, &labels[i]);
}
else {
if ((i < if_count) && ifindices[i])
{
case NEXTHOP_TYPE_IPV6:
stream_get (&nexthop, s, 16);
+ /* For labeled-unicast, each nexthop is followed by label, but
+ * we don't care for delete.
+ */
+ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_LABEL))
+ stream_forward_getp (s, sizeof(u_int32_t));
pnexthop = (union g_addr *)&nexthop;
break;
case NEXTHOP_TYPE_IFINDEX:
if (command == ZEBRA_MPLS_LABELS_ADD)
{
mpls_lsp_install (zvrf, type, in_label, out_label, gtype, &gate,
- NULL, ifindex);
+ ifindex);
if (out_label != MPLS_IMP_NULL_LABEL)
mpls_ftn_update (1, zvrf, type, &prefix, gtype, &gate, ifindex,
distance, out_label);
}
else if (command == ZEBRA_MPLS_LABELS_DELETE)
{
- mpls_lsp_uninstall (zvrf, type, in_label, gtype, &gate, NULL, ifindex);
+ mpls_lsp_uninstall (zvrf, type, in_label, gtype, &gate, ifindex);
if (out_label != MPLS_IMP_NULL_LABEL)
mpls_ftn_update (0, zvrf, type, &prefix, gtype, &gate, ifindex,
distance, out_label);