summaryrefslogtreecommitdiff
path: root/isisd
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2023-12-22 11:35:09 +0100
committerPhilippe Guibert <philippe.guibert@6wind.com>2024-07-11 09:14:34 +0200
commit4e76df05476e728d3bdd53821c0f20e4139db1f8 (patch)
tree7e66d56d07b57f9b2734423b00204d4d338a8d42 /isisd
parentebf05b4ee18a94086a15207f14b00b05df5a5dde (diff)
isis, lib: add isis srv6 end sid to ls_prefix
According to draft-ietf-lsr-isis-srv6-extensions draft, the End SID should be available in link state prefix information. Add the SID information in the link state prefix, by getting the END SID from the locator TLV information. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Diffstat (limited to 'isisd')
-rw-r--r--isisd/isis_lsp.c50
-rw-r--r--isisd/isis_lsp.h2
-rw-r--r--isisd/isis_te.c45
-rw-r--r--isisd/isis_te.h1
4 files changed, 96 insertions, 2 deletions
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index bda7ed89a4..391d42fba1 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -2341,6 +2341,56 @@ static int lsp_handle_adj_state_change(struct isis_adjacency *adj)
}
/*
+ * Iterate over all SRv6 locator TLVs
+ */
+int isis_lsp_iterate_srv6_locator(struct isis_lsp *lsp, uint16_t mtid,
+ lsp_ip_reach_iter_cb cb, void *arg)
+{
+ bool pseudo_lsp = LSP_PSEUDO_ID(lsp->hdr.lsp_id);
+ struct isis_lsp *frag;
+ struct listnode *node;
+
+ if (lsp->hdr.seqno == 0 || lsp->hdr.rem_lifetime == 0)
+ return LSP_ITER_CONTINUE;
+
+ /* Parse LSP */
+ if (lsp->tlvs) {
+ if (!pseudo_lsp) {
+ struct isis_item_list *srv6_locator_reachs;
+ struct isis_srv6_locator_tlv *r;
+
+ srv6_locator_reachs =
+ isis_lookup_mt_items(&lsp->tlvs->srv6_locator,
+ mtid);
+
+ for (r = srv6_locator_reachs
+ ? (struct isis_srv6_locator_tlv *)
+ srv6_locator_reachs->head
+ : NULL;
+ r; r = r->next) {
+ if ((*cb)((struct prefix *)&r->prefix,
+ r->metric, false /* ignore */,
+ r->subtlvs, arg) == LSP_ITER_STOP)
+ return LSP_ITER_STOP;
+ }
+ }
+ }
+
+ /* Parse LSP fragments if it is not a fragment itself */
+ if (!LSP_FRAGMENT(lsp->hdr.lsp_id))
+ for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) {
+ if (!frag->tlvs)
+ continue;
+
+ if (isis_lsp_iterate_srv6_locator(frag, mtid, cb,
+ arg) == LSP_ITER_STOP)
+ return LSP_ITER_STOP;
+ }
+
+ return LSP_ITER_CONTINUE;
+}
+
+/*
* Iterate over all IP reachability TLVs in a LSP (all fragments) of the given
* address-family and MT-ID.
*/
diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h
index 3839a9504c..15db88b02f 100644
--- a/isisd/isis_lsp.h
+++ b/isisd/isis_lsp.h
@@ -143,6 +143,8 @@ int isis_lsp_iterate_ip_reach(struct isis_lsp *lsp, int family, uint16_t mtid,
lsp_ip_reach_iter_cb cb, void *arg);
int isis_lsp_iterate_is_reach(struct isis_lsp *lsp, uint16_t mtid,
lsp_is_reach_iter_cb cb, void *arg);
+int isis_lsp_iterate_srv6_locator(struct isis_lsp *lsp, uint16_t mtid,
+ lsp_ip_reach_iter_cb cb, void *arg);
#define lsp_flood(lsp, circuit) \
_lsp_flood((lsp), (circuit), __func__, __FILE__, __LINE__)
diff --git a/isisd/isis_te.c b/isisd/isis_te.c
index 3683f74558..bb73a44257 100644
--- a/isisd/isis_te.c
+++ b/isisd/isis_te.c
@@ -1258,8 +1258,11 @@ static int lsp_to_subnet_cb(const struct prefix *prefix, uint32_t metric,
if (!args || !prefix)
return LSP_ITER_CONTINUE;
- te_debug(" |- Process Extended %s Reachability %pFX",
- prefix->family == AF_INET ? "IP" : "IPv6", prefix);
+ if (args->srv6_locator)
+ te_debug(" |- Process SRv6 Locator %pFX", prefix);
+ else
+ te_debug(" |- Process Extended %s Reachability %pFX",
+ prefix->family == AF_INET ? "IP" : "IPv6", prefix);
vertex = args->vertex;
@@ -1386,6 +1389,38 @@ static int lsp_to_subnet_cb(const struct prefix *prefix, uint32_t metric,
}
}
+ /* Update SRv6 SID and locator if any */
+ if (subtlvs && subtlvs->srv6_end_sids.count != 0) {
+ struct isis_srv6_end_sid_subtlv *psid;
+ struct ls_srv6_sid sr = {};
+
+ psid = (struct isis_srv6_end_sid_subtlv *)
+ subtlvs->srv6_end_sids.head;
+ sr.behavior = psid->behavior;
+ sr.flags = psid->flags;
+ memcpy(&sr.sid, &psid->sid, sizeof(struct in6_addr));
+
+ if (!CHECK_FLAG(ls_pref->flags, LS_PREF_SRV6) ||
+ memcmp(&ls_pref->srv6, &sr, sizeof(struct ls_srv6_sid))) {
+ memcpy(&ls_pref->srv6, &sr, sizeof(struct ls_srv6_sid));
+ SET_FLAG(ls_pref->flags, LS_PREF_SRV6);
+ if (subnet->status != NEW)
+ subnet->status = UPDATE;
+ } else {
+ if (subnet->status == ORPHAN)
+ subnet->status = SYNC;
+ }
+ } else {
+ if (CHECK_FLAG(ls_pref->flags, LS_PREF_SRV6)) {
+ UNSET_FLAG(ls_pref->flags, LS_PREF_SRV6);
+ if (subnet->status != NEW)
+ subnet->status = UPDATE;
+ } else {
+ if (subnet->status == ORPHAN)
+ subnet->status = SYNC;
+ }
+ }
+
/* Update status and Export Link State Edge if needed */
if (subnet->status != SYNC) {
if (args->export)
@@ -1454,12 +1489,18 @@ static void isis_te_parse_lsp(struct mpls_te_area *mta, struct isis_lsp *lsp)
&args);
/* Process all Extended IP (v4 & v6) in LSP (all fragments) */
+ args.srv6_locator = false;
isis_lsp_iterate_ip_reach(lsp, AF_INET, ISIS_MT_IPV4_UNICAST,
lsp_to_subnet_cb, &args);
isis_lsp_iterate_ip_reach(lsp, AF_INET6, ISIS_MT_IPV6_UNICAST,
lsp_to_subnet_cb, &args);
isis_lsp_iterate_ip_reach(lsp, AF_INET6, ISIS_MT_IPV4_UNICAST,
lsp_to_subnet_cb, &args);
+ args.srv6_locator = true;
+ isis_lsp_iterate_srv6_locator(lsp, ISIS_MT_STANDARD, lsp_to_subnet_cb,
+ &args);
+ isis_lsp_iterate_srv6_locator(lsp, ISIS_MT_IPV6_UNICAST,
+ lsp_to_subnet_cb, &args);
/* Clean remaining Orphan Edges or Subnets */
if (IS_EXPORT_TE(mta))
diff --git a/isisd/isis_te.h b/isisd/isis_te.h
index bf1dc2b9bb..532a24e7e4 100644
--- a/isisd/isis_te.h
+++ b/isisd/isis_te.h
@@ -103,6 +103,7 @@ struct isis_te_args {
struct ls_ted *ted;
struct ls_vertex *vertex;
bool export;
+ bool srv6_locator;
};
enum lsp_event { LSP_UNKNOWN, LSP_ADD, LSP_UPD, LSP_DEL, LSP_INC, LSP_TICK };