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.c486
1 files changed, 306 insertions, 180 deletions
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 3e84114772..8f18f326d1 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -99,15 +99,10 @@ nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
static int
nhlfe_del (zebra_nhlfe_t *snhlfe);
static int
-static_lsp_install (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);
+mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp,
+ enum lsp_types_t type);
static int
-static_lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t in_label,
- enum nexthop_types_t gtype, union g_addr *gate,
- char *ifname, ifindex_t ifindex);
-static int
-static_lsp_uninstall_all (struct zebra_vrf *zvrf, mpls_label_t in_label);
+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
@@ -684,7 +679,7 @@ nhlfe_add (zebra_lsp_t *lsp, enum lsp_types_t lsp_type,
XFREE (MTYPE_NHLFE, nhlfe);
return NULL;
}
- nexthop_add_labels (nexthop, 1, &out_label);
+ nexthop_add_labels (nexthop, lsp_type, 1, &out_label);
nexthop->type = gtype;
switch (nexthop->type)
@@ -746,190 +741,28 @@ nhlfe_del (zebra_nhlfe_t *nhlfe)
return 0;
}
-
-/*
- * Install/update a static NHLFE for an LSP in the forwarding table. This may
- * be a new LSP entry or a new NHLFE for an existing in-label or an update of
- * the out-label for an existing NHLFE (update case).
- */
static int
-static_lsp_install (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)
+mpls_lsp_uninstall_all (struct hash *lsp_table, zebra_lsp_t *lsp,
+ enum lsp_types_t type)
{
- struct hash *lsp_table;
- zebra_ile_t tmp_ile;
- zebra_lsp_t *lsp;
- zebra_nhlfe_t *nhlfe;
- char buf[BUFSIZ];
-
- /* Lookup table. */
- lsp_table = zvrf->lsp_table;
- if (!lsp_table)
- return -1;
-
- /* If entry is present, exit. */
- tmp_ile.in_label = in_label;
- lsp = hash_get (lsp_table, &tmp_ile, lsp_alloc);
- if (!lsp)
- return -1;
- nhlfe = nhlfe_find (lsp, ZEBRA_LSP_STATIC, gtype, gate, ifname, ifindex);
- if (nhlfe)
- {
- struct nexthop *nh = nhlfe->nexthop;
-
- assert (nh);
- assert (nh->nh_label);
-
- /* Clear deleted flag (in case it was set) */
- UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED);
- if (nh->nh_label->label[0] == out_label)
- /* No change */
- return 0;
-
- if (IS_ZEBRA_DEBUG_MPLS)
- {
- nhlfe2str (nhlfe, buf, BUFSIZ);
- zlog_debug ("LSP in-label %u type %d nexthop %s "
- "out-label changed to %u (old %u)",
- in_label, ZEBRA_LSP_STATIC, buf,
- out_label, nh->nh_label->label[0]);
- }
-
- /* Update out label, trigger processing. */
- nh->nh_label->label[0] = out_label;
- }
- else
- {
- /* Add LSP entry to this nexthop */
- nhlfe = nhlfe_add (lsp, ZEBRA_LSP_STATIC, gtype, gate,
- ifname, ifindex, out_label);
- 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",
- in_label, ZEBRA_LSP_STATIC, buf,
- out_label);
- }
-
- lsp->addr_family = NHLFE_FAMILY (nhlfe);
- }
-
- /* Mark NHLFE, queue LSP for processing. */
- SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED);
- if (lsp_processq_add (lsp))
- return -1;
-
- return 0;
-}
-
-/*
- * Uninstall a particular static NHLFE in the forwarding table. If this is
- * the only NHLFE, the entire LSP forwarding entry has to be deleted.
- */
-static int
-static_lsp_uninstall (struct zebra_vrf *zvrf, mpls_label_t in_label,
- enum nexthop_types_t gtype, union g_addr *gate,
- char *ifname, ifindex_t ifindex)
-{
- struct hash *lsp_table;
- zebra_ile_t tmp_ile;
- zebra_lsp_t *lsp;
- zebra_nhlfe_t *nhlfe;
- 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 = in_label;
- lsp = hash_lookup (lsp_table, &tmp_ile);
- if (!lsp)
- return 0;
- nhlfe = nhlfe_find (lsp, ZEBRA_LSP_STATIC, gtype, gate, ifname, ifindex);
- if (!nhlfe)
- return 0;
-
- if (IS_ZEBRA_DEBUG_MPLS)
- {
- nhlfe2str (nhlfe, buf, BUFSIZ);
- zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x",
- in_label, ZEBRA_LSP_STATIC, buf, nhlfe->flags);
- }
-
- /* Mark NHLFE for delete or directly delete, as appropriate. */
- if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED))
- {
- UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED);
- SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED);
- if (lsp_processq_add (lsp))
- return -1;
- }
- else
- {
- nhlfe_del (nhlfe);
-
- /* Free LSP entry if no other NHLFEs and not scheduled. */
- 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 static NHLFEs for a particular LSP forwarding entry.
- * If no other NHLFEs exist, the entry would be deleted.
- */
-static int
-static_lsp_uninstall_all (struct zebra_vrf *zvrf, mpls_label_t in_label)
-{
- struct hash *lsp_table;
- zebra_ile_t tmp_ile;
- zebra_lsp_t *lsp;
zebra_nhlfe_t *nhlfe, *nhlfe_next;
int schedule_lsp = 0;
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 = in_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 non-static NHLFEs */
- if (nhlfe->type != ZEBRA_LSP_STATIC)
+ if (nhlfe->type != type)
continue;
if (IS_ZEBRA_DEBUG_MPLS)
{
nhlfe2str (nhlfe, buf, BUFSIZ);
zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x",
- in_label, ZEBRA_LSP_STATIC, buf, nhlfe->flags);
+ lsp->ile.in_label, type, buf, nhlfe->flags);
}
if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED))
@@ -965,6 +798,31 @@ static_lsp_uninstall_all (struct zebra_vrf *zvrf, mpls_label_t in_label)
return 0;
}
+/*
+ * Uninstall all static NHLFEs for a particular LSP forwarding entry.
+ * If no other NHLFEs exist, the entry would be deleted.
+ */
+static int
+mpls_static_lsp_uninstall_all (struct zebra_vrf *zvrf, mpls_label_t in_label)
+{
+ struct hash *lsp_table;
+ zebra_ile_t tmp_ile;
+ zebra_lsp_t *lsp;
+
+ /* Lookup table. */
+ lsp_table = zvrf->lsp_table;
+ if (!lsp_table)
+ return -1;
+
+ /* If entry is not present, exit. */
+ tmp_ile.in_label = in_label;
+ lsp = hash_lookup (lsp_table, &tmp_ile);
+ if (!lsp || !lsp->nhlfe_list)
+ return 0;
+
+ return mpls_lsp_uninstall_all (lsp_table, lsp, ZEBRA_LSP_STATIC);
+}
+
static json_object *
nhlfe_json (zebra_nhlfe_t *nhlfe)
{
@@ -1395,6 +1253,274 @@ mpls_label2str (u_int8_t num_labels, mpls_label_t *labels,
}
/*
+ * Install/uninstall a FEC-To-NHLFE (FTN) binding.
+ */
+int
+mpls_ftn_update (int add, struct zebra_vrf *zvrf, enum lsp_types_t type,
+ struct prefix *prefix, union g_addr *gate, u_int8_t distance,
+ mpls_label_t out_label)
+{
+ struct route_table *table;
+ struct route_node *rn;
+ struct rib *rib;
+ struct nexthop *nexthop;
+
+ /* Lookup table. */
+ table = zebra_vrf_table (family2afi(prefix->family), SAFI_UNICAST, zvrf->vrf_id);
+ if (! table)
+ return -1;
+
+ /* Lookup existing route */
+ rn = route_node_get (table, prefix);
+ RNODE_FOREACH_RIB (rn, rib)
+ {
+ if (CHECK_FLAG (rib->status, RIB_ENTRY_REMOVED))
+ continue;
+ if (rib->distance == distance)
+ break;
+ }
+
+ if (rib == NULL)
+ return -1;
+
+ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+ switch (prefix->family)
+ {
+ case AF_INET:
+ if (nexthop->type != NEXTHOP_TYPE_IPV4 &&
+ nexthop->type != NEXTHOP_TYPE_IPV4_IFINDEX)
+ continue;
+ if (! IPV4_ADDR_SAME (&nexthop->gate.ipv4, &gate->ipv4))
+ continue;
+ goto found;
+ break;
+ case AF_INET6:
+ if (nexthop->type != NEXTHOP_TYPE_IPV6 &&
+ nexthop->type != NEXTHOP_TYPE_IPV6_IFINDEX)
+ continue;
+ if (! IPV6_ADDR_SAME (&nexthop->gate.ipv6, &gate->ipv6))
+ continue;
+ goto found;
+ break;
+ default:
+ break;
+ }
+ /* nexthop not found */
+ return -1;
+
+ found:
+ if (add)
+ nexthop_add_labels (nexthop, type, 1, &out_label);
+ else
+ nexthop_del_labels (nexthop);
+
+ SET_FLAG (rib->status, RIB_ENTRY_CHANGED);
+ SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED);
+ rib_queue_add (rn);
+
+ return 0;
+}
+
+/*
+ * Install/update a NHLFE for an LSP in the forwarding table. This may be
+ * a new LSP entry or a new NHLFE for an existing in-label or an update of
+ * 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,
+ char *ifname, ifindex_t ifindex)
+{
+ struct hash *lsp_table;
+ zebra_ile_t tmp_ile;
+ zebra_lsp_t *lsp;
+ zebra_nhlfe_t *nhlfe;
+ char buf[BUFSIZ];
+
+ /* Lookup table. */
+ lsp_table = zvrf->lsp_table;
+ if (!lsp_table)
+ return -1;
+
+ /* If entry is present, exit. */
+ tmp_ile.in_label = in_label;
+ lsp = hash_get (lsp_table, &tmp_ile, lsp_alloc);
+ if (!lsp)
+ return -1;
+ nhlfe = nhlfe_find (lsp, type, gtype, gate, ifname, ifindex);
+ if (nhlfe)
+ {
+ struct nexthop *nh = nhlfe->nexthop;
+
+ assert (nh);
+ assert (nh->nh_label);
+
+ /* Clear deleted flag (in case it was set) */
+ UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED);
+ if (nh->nh_label->label[0] == out_label)
+ /* No change */
+ return 0;
+
+ if (IS_ZEBRA_DEBUG_MPLS)
+ {
+ nhlfe2str (nhlfe, buf, BUFSIZ);
+ 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]);
+ }
+
+ /* Update out label, trigger processing. */
+ nh->nh_label->label[0] = out_label;
+ }
+ else
+ {
+ /* Add LSP entry to this nexthop */
+ nhlfe = nhlfe_add (lsp, type, gtype, gate,
+ ifname, ifindex, out_label);
+ 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", in_label, type, buf, out_label);
+ }
+
+ lsp->addr_family = NHLFE_FAMILY (nhlfe);
+ }
+
+ /* Mark NHLFE, queue LSP for processing. */
+ SET_FLAG(nhlfe->flags, NHLFE_FLAG_CHANGED);
+ if (lsp_processq_add (lsp))
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Uninstall a particular NHLFE in the forwarding table. If this is
+ * the only NHLFE, the entire LSP forwarding entry has to be deleted.
+ */
+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)
+{
+ struct hash *lsp_table;
+ zebra_ile_t tmp_ile;
+ zebra_lsp_t *lsp;
+ zebra_nhlfe_t *nhlfe;
+ 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 = in_label;
+ lsp = hash_lookup (lsp_table, &tmp_ile);
+ if (!lsp)
+ return 0;
+ nhlfe = nhlfe_find (lsp, type, gtype, gate, ifname, ifindex);
+ if (!nhlfe)
+ return 0;
+
+ if (IS_ZEBRA_DEBUG_MPLS)
+ {
+ nhlfe2str (nhlfe, buf, BUFSIZ);
+ zlog_debug ("Del LSP in-label %u type %d nexthop %s flags 0x%x",
+ in_label, type, buf, nhlfe->flags);
+ }
+
+ /* Mark NHLFE for delete or directly delete, as appropriate. */
+ if (CHECK_FLAG(nhlfe->flags, NHLFE_FLAG_INSTALLED))
+ {
+ UNSET_FLAG (nhlfe->flags, NHLFE_FLAG_CHANGED);
+ SET_FLAG (nhlfe->flags, NHLFE_FLAG_DELETED);
+ if (lsp_processq_add (lsp))
+ return -1;
+ }
+ else
+ {
+ nhlfe_del (nhlfe);
+
+ /* Free LSP entry if no other NHLFEs and not scheduled. */
+ 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 LDP NHLFEs for a particular LSP forwarding entry.
+ * If no other NHLFEs exist, the entry would be deleted.
+ */
+void
+mpls_ldp_lsp_uninstall_all (struct hash_backet *backet, void *ctxt)
+{
+ zebra_lsp_t *lsp;
+ struct hash *lsp_table;
+
+ lsp = (zebra_lsp_t *) backet->data;
+ if (!lsp || !lsp->nhlfe_list)
+ return;
+
+ lsp_table = ctxt;
+ if (!lsp_table)
+ return;
+
+ mpls_lsp_uninstall_all (lsp_table, lsp, ZEBRA_LSP_LDP);
+}
+
+/*
+ * Uninstall all LDP FEC-To-NHLFE (FTN) bindings of the given address-family.
+ */
+void
+mpls_ldp_ftn_uninstall_all (struct zebra_vrf *zvrf, int afi)
+{
+ struct route_table *table;
+ struct route_node *rn;
+ struct rib *rib;
+ struct nexthop *nexthop;
+ int update;
+
+ /* Process routes of interested address-families. */
+ table = zebra_vrf_table (afi, SAFI_UNICAST, zvrf->vrf_id);
+ if (!table)
+ return;
+
+ for (rn = route_top (table); rn; rn = route_next (rn))
+ {
+ update = 0;
+ RNODE_FOREACH_RIB (rn, rib)
+ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)
+ if (nexthop->nh_label_type == ZEBRA_LSP_LDP)
+ {
+ nexthop_del_labels (nexthop);
+ SET_FLAG (rib->status, RIB_ENTRY_CHANGED);
+ SET_FLAG (rib->status, RIB_ENTRY_NEXTHOPS_CHANGED);
+ update = 1;
+ }
+
+ if (update)
+ rib_queue_add (rn);
+ }
+}
+
+/*
* Check that the label values used in LSP creation are consistent. The
* main criteria is that if there is ECMP, the label operation must still
* be consistent - i.e., all paths either do a swap or do PHP. This is due
@@ -1511,8 +1637,8 @@ zebra_mpls_static_lsp_add (struct zebra_vrf *zvrf, mpls_label_t in_label,
}
/* (Re)Install LSP in the main table. */
- if (static_lsp_install (zvrf, in_label, out_label, gtype,
- gate, ifname, ifindex))
+ if (mpls_lsp_install (zvrf, ZEBRA_LSP_STATIC, in_label, out_label, gtype,
+ gate, ifname, ifindex))
return -1;
return 0;
@@ -1553,7 +1679,7 @@ zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label,
zlog_debug ("Del static LSP in-label %u", in_label);
/* Uninstall entire LSP from the main table. */
- static_lsp_uninstall_all (zvrf, in_label);
+ mpls_static_lsp_uninstall_all (zvrf, in_label);
/* Delete all static NHLFEs */
snhlfe_del_all (slsp);
@@ -1574,8 +1700,8 @@ zebra_mpls_static_lsp_del (struct zebra_vrf *zvrf, mpls_label_t in_label,
}
/* Uninstall LSP from the main table. */
- static_lsp_uninstall (zvrf, in_label, gtype,
- gate, ifname, ifindex);
+ mpls_lsp_uninstall (zvrf, ZEBRA_LSP_STATIC, in_label, gtype, gate,
+ ifname, ifindex);
/* Delete static LSP NHLFE */
snhlfe_del (snhlfe);