forked from Mirror/frr
Merge pull request #15797 from pguibert6WIND/isis_srv6_ls_subnet
isis, lib: add isis srv6 end sid to ls_prefix
This commit is contained in:
commit
7f10381374
|
@ -2340,6 +2340,56 @@ static int lsp_handle_adj_state_change(struct isis_adjacency *adj)
|
||||||
return 0;
|
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
|
* Iterate over all IP reachability TLVs in a LSP (all fragments) of the given
|
||||||
* address-family and MT-ID.
|
* address-family and MT-ID.
|
||||||
|
|
|
@ -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);
|
lsp_ip_reach_iter_cb cb, void *arg);
|
||||||
int isis_lsp_iterate_is_reach(struct isis_lsp *lsp, uint16_t mtid,
|
int isis_lsp_iterate_is_reach(struct isis_lsp *lsp, uint16_t mtid,
|
||||||
lsp_is_reach_iter_cb cb, void *arg);
|
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) \
|
#define lsp_flood(lsp, circuit) \
|
||||||
_lsp_flood((lsp), (circuit), __func__, __FILE__, __LINE__)
|
_lsp_flood((lsp), (circuit), __func__, __FILE__, __LINE__)
|
||||||
|
|
|
@ -1258,8 +1258,11 @@ static int lsp_to_subnet_cb(const struct prefix *prefix, uint32_t metric,
|
||||||
if (!args || !prefix)
|
if (!args || !prefix)
|
||||||
return LSP_ITER_CONTINUE;
|
return LSP_ITER_CONTINUE;
|
||||||
|
|
||||||
te_debug(" |- Process Extended %s Reachability %pFX",
|
if (args->srv6_locator)
|
||||||
prefix->family == AF_INET ? "IP" : "IPv6", prefix);
|
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;
|
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 */
|
/* Update status and Export Link State Edge if needed */
|
||||||
if (subnet->status != SYNC) {
|
if (subnet->status != SYNC) {
|
||||||
if (args->export)
|
if (args->export)
|
||||||
|
@ -1454,12 +1489,18 @@ static void isis_te_parse_lsp(struct mpls_te_area *mta, struct isis_lsp *lsp)
|
||||||
&args);
|
&args);
|
||||||
|
|
||||||
/* Process all Extended IP (v4 & v6) in LSP (all fragments) */
|
/* 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,
|
isis_lsp_iterate_ip_reach(lsp, AF_INET, ISIS_MT_IPV4_UNICAST,
|
||||||
lsp_to_subnet_cb, &args);
|
lsp_to_subnet_cb, &args);
|
||||||
isis_lsp_iterate_ip_reach(lsp, AF_INET6, ISIS_MT_IPV6_UNICAST,
|
isis_lsp_iterate_ip_reach(lsp, AF_INET6, ISIS_MT_IPV6_UNICAST,
|
||||||
lsp_to_subnet_cb, &args);
|
lsp_to_subnet_cb, &args);
|
||||||
isis_lsp_iterate_ip_reach(lsp, AF_INET6, ISIS_MT_IPV4_UNICAST,
|
isis_lsp_iterate_ip_reach(lsp, AF_INET6, ISIS_MT_IPV4_UNICAST,
|
||||||
lsp_to_subnet_cb, &args);
|
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 */
|
/* Clean remaining Orphan Edges or Subnets */
|
||||||
if (IS_EXPORT_TE(mta))
|
if (IS_EXPORT_TE(mta))
|
||||||
|
|
|
@ -103,6 +103,7 @@ struct isis_te_args {
|
||||||
struct ls_ted *ted;
|
struct ls_ted *ted;
|
||||||
struct ls_vertex *vertex;
|
struct ls_vertex *vertex;
|
||||||
bool export;
|
bool export;
|
||||||
|
bool srv6_locator;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum lsp_event { LSP_UNKNOWN, LSP_ADD, LSP_UPD, LSP_DEL, LSP_INC, LSP_TICK };
|
enum lsp_event { LSP_UNKNOWN, LSP_ADD, LSP_UPD, LSP_DEL, LSP_INC, LSP_TICK };
|
||||||
|
|
|
@ -414,6 +414,13 @@ int ls_prefix_same(struct ls_prefix *p1, struct ls_prefix *p2)
|
||||||
|| (p1->sr.sid_flag != p2->sr.sid_flag))
|
|| (p1->sr.sid_flag != p2->sr.sid_flag))
|
||||||
return 0;
|
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 */
|
/* OK, p1 & p2 are equal */
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -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.sid_flag);
|
||||||
STREAM_GETC(s, ls_pref->sr.algo);
|
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;
|
return ls_pref;
|
||||||
|
|
||||||
|
@ -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.sid_flag);
|
||||||
stream_putc(s, ls_pref->sr.algo);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -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",
|
sbuf_push(&sbuf, 4, "SID: %d\tAlgorithm: %d\tFlags: 0x%x\n",
|
||||||
pref->sr.sid, pref->sr.algo, pref->sr.sid_flag);
|
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:
|
end:
|
||||||
vty_out(vty, "%s\n", sbuf_buf(&sbuf));
|
vty_out(vty, "%s\n", sbuf_buf(&sbuf));
|
||||||
sbuf_free(&sbuf);
|
sbuf_free(&sbuf);
|
||||||
|
@ -2757,7 +2781,7 @@ static void ls_show_subnet_json(struct ls_subnet *subnet,
|
||||||
struct json_object *json)
|
struct json_object *json)
|
||||||
{
|
{
|
||||||
struct ls_prefix *pref;
|
struct ls_prefix *pref;
|
||||||
json_object *jsr;
|
json_object *jsr, *jsrv6;
|
||||||
char buf[INET6_BUFSIZ];
|
char buf[INET6_BUFSIZ];
|
||||||
|
|
||||||
pref = subnet->ls_pref;
|
pref = subnet->ls_pref;
|
||||||
|
@ -2787,6 +2811,16 @@ static void ls_show_subnet_json(struct ls_subnet *subnet,
|
||||||
snprintfrr(buf, INET6_BUFSIZ, "0x%x", pref->sr.sid_flag);
|
snprintfrr(buf, INET6_BUFSIZ, "0x%x", pref->sr.sid_flag);
|
||||||
json_object_string_add(jsr, "flags", buf);
|
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,
|
void ls_show_subnet(struct ls_subnet *subnet, struct vty *vty,
|
||||||
|
|
|
@ -243,6 +243,7 @@ struct ls_attributes {
|
||||||
#define LS_PREF_EXTENDED_TAG 0x04
|
#define LS_PREF_EXTENDED_TAG 0x04
|
||||||
#define LS_PREF_METRIC 0x08
|
#define LS_PREF_METRIC 0x08
|
||||||
#define LS_PREF_SR 0x10
|
#define LS_PREF_SR 0x10
|
||||||
|
#define LS_PREF_SRV6 0x20
|
||||||
|
|
||||||
/* Link State Prefix */
|
/* Link State Prefix */
|
||||||
struct ls_prefix {
|
struct ls_prefix {
|
||||||
|
@ -258,6 +259,11 @@ struct ls_prefix {
|
||||||
uint8_t sid_flag; /* Segment Routing Flags */
|
uint8_t sid_flag; /* Segment Routing Flags */
|
||||||
uint8_t algo; /* Algorithm for Segment Routing */
|
uint8_t algo; /* Algorithm for Segment Routing */
|
||||||
} sr;
|
} 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue