Skip to content

Commit

Permalink
isis, lib: add isis srv6 end sid to ls_prefix
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
pguibert6WIND committed Jun 25, 2024
1 parent e5faf01 commit 6a6abad
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 3 deletions.
50 changes: 50 additions & 0 deletions isisd/isis_lsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2335,6 +2335,56 @@ static int lsp_handle_adj_state_change(struct isis_adjacency *adj)
return 0;
}

/*
* 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.
Expand Down
2 changes: 2 additions & 0 deletions isisd/isis_lsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand Down
45 changes: 43 additions & 2 deletions isisd/isis_te.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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))
Expand Down
1 change: 1 addition & 0 deletions isisd/isis_te.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down
36 changes: 35 additions & 1 deletion lib/link_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,13 @@ int ls_prefix_same(struct ls_prefix *p1, struct ls_prefix *p2)
|| (p1->sr.sid_flag != p2->sr.sid_flag))
return 0;
}
if (CHECK_FLAG(p1->flags, LS_PREF_SRV6)) {
if (memcmp(&p1->srv6.sid, &p2->srv6.sid,
sizeof(struct in6_addr)) ||
(p1->srv6.flags != p2->srv6.flags) ||
(p1->srv6.behavior != p2->srv6.behavior))
return 0;
}

/* OK, p1 & p2 are equal */
return 1;
Expand Down Expand Up @@ -1388,6 +1395,11 @@ static struct ls_prefix *ls_parse_prefix(struct stream *s)
STREAM_GETC(s, ls_pref->sr.sid_flag);
STREAM_GETC(s, ls_pref->sr.algo);
}
if (CHECK_FLAG(ls_pref->flags, LS_PREF_SRV6)) {
STREAM_GET(&ls_pref->srv6.sid, s, sizeof(struct in6_addr));
STREAM_GETW(s, ls_pref->srv6.behavior);
STREAM_GETC(s, ls_pref->srv6.flags);
}

return ls_pref;

Expand Down Expand Up @@ -1632,6 +1644,11 @@ static int ls_format_prefix(struct stream *s, struct ls_prefix *ls_pref)
stream_putc(s, ls_pref->sr.sid_flag);
stream_putc(s, ls_pref->sr.algo);
}
if (CHECK_FLAG(ls_pref->flags, LS_PREF_SRV6)) {
stream_put(s, &ls_pref->srv6.sid, sizeof(struct in6_addr));
stream_putw(s, ls_pref->srv6.behavior);
stream_putc(s, ls_pref->srv6.flags);
}

return 0;
}
Expand Down Expand Up @@ -2748,6 +2765,13 @@ static void ls_show_subnet_vty(struct ls_subnet *subnet, struct vty *vty,
sbuf_push(&sbuf, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
pref->sr.sid, pref->sr.algo, pref->sr.sid_flag);

if (CHECK_FLAG(pref->flags, LS_PREF_SRV6))
sbuf_push(&sbuf, 4,
"SIDv6: %pI6\tEndpoint behavior: %s\tFlags: 0x%x\n",
&pref->srv6.sid,
seg6local_action2str(pref->srv6.behavior),
pref->srv6.flags);

end:
vty_out(vty, "%s\n", sbuf_buf(&sbuf));
sbuf_free(&sbuf);
Expand All @@ -2757,7 +2781,7 @@ static void ls_show_subnet_json(struct ls_subnet *subnet,
struct json_object *json)
{
struct ls_prefix *pref;
json_object *jsr;
json_object *jsr, *jsrv6;
char buf[INET6_BUFSIZ];

pref = subnet->ls_pref;
Expand Down Expand Up @@ -2787,6 +2811,16 @@ static void ls_show_subnet_json(struct ls_subnet *subnet,
snprintfrr(buf, INET6_BUFSIZ, "0x%x", pref->sr.sid_flag);
json_object_string_add(jsr, "flags", buf);
}
if (CHECK_FLAG(pref->flags, LS_PREF_SRV6)) {
jsrv6 = json_object_new_object();
json_object_object_add(json, "segment-routing-ipv6", jsrv6);
snprintfrr(buf, INET6_BUFSIZ, "%pI6", &pref->srv6.sid);
json_object_string_add(jsrv6, "sid", buf);
json_object_string_add(jsrv6, "behavior",
seg6local_action2str(pref->srv6.behavior));
snprintfrr(buf, INET6_BUFSIZ, "0x%x", pref->srv6.flags);
json_object_string_add(jsrv6, "flags", buf);
}
}

void ls_show_subnet(struct ls_subnet *subnet, struct vty *vty,
Expand Down
6 changes: 6 additions & 0 deletions lib/link_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ struct ls_attributes {
#define LS_PREF_EXTENDED_TAG 0x04
#define LS_PREF_METRIC 0x08
#define LS_PREF_SR 0x10
#define LS_PREF_SRV6 0x20

/* Link State Prefix */
struct ls_prefix {
Expand All @@ -258,6 +259,11 @@ struct ls_prefix {
uint8_t sid_flag; /* Segment Routing Flags */
uint8_t algo; /* Algorithm for Segment Routing */
} sr;
struct ls_srv6_sid {
struct in6_addr sid; /* Segment Routing ID */
uint16_t behavior; /* Endpoint behavior bound to the SID */
uint8_t flags; /* Flags */
} srv6;
};

/**
Expand Down

0 comments on commit 6a6abad

Please sign in to comment.