mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 14:05:31 +00:00
isisd: Add unpack function for SRv6 Locator TLV
Add a function to unpack an SRv6 Locator TLV and all its Sub-TLVs (RFC 9352 section #7.1). Signed-off-by: Carmine Scarpitta <carmine.scarpitta@uniroma2.it>
This commit is contained in:
parent
b2f0b7d0b0
commit
0225f908e8
@ -5625,6 +5625,103 @@ static int pack_item_srv6_locator(struct isis_item *i, struct stream *s,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int unpack_item_srv6_locator(uint16_t mtid, uint8_t len,
|
||||||
|
struct stream *s, struct sbuf *log,
|
||||||
|
void *dest, int indent)
|
||||||
|
{
|
||||||
|
struct isis_tlvs *tlvs = dest;
|
||||||
|
struct isis_srv6_locator_tlv *rv = NULL;
|
||||||
|
size_t consume;
|
||||||
|
uint8_t subtlv_len;
|
||||||
|
struct isis_item_list *items;
|
||||||
|
|
||||||
|
items = isis_get_mt_items(&tlvs->srv6_locator, mtid);
|
||||||
|
|
||||||
|
sbuf_push(log, indent, "Unpacking SRv6 Locator...\n");
|
||||||
|
consume = 7;
|
||||||
|
if (len < consume) {
|
||||||
|
sbuf_push(
|
||||||
|
log, indent,
|
||||||
|
"Not enough data left. (expected 7 or more bytes, got %hhu)\n",
|
||||||
|
len);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv = XCALLOC(MTYPE_ISIS_TLV, sizeof(*rv));
|
||||||
|
|
||||||
|
rv->metric = stream_getl(s);
|
||||||
|
rv->flags = stream_getc(s);
|
||||||
|
rv->algorithm = stream_getc(s);
|
||||||
|
|
||||||
|
rv->prefix.family = AF_INET6;
|
||||||
|
rv->prefix.prefixlen = stream_getc(s);
|
||||||
|
if (rv->prefix.prefixlen > IPV6_MAX_BITLEN) {
|
||||||
|
sbuf_push(log, indent, "Loc Size %u is implausible for SRv6\n",
|
||||||
|
rv->prefix.prefixlen);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
consume += PSIZE(rv->prefix.prefixlen);
|
||||||
|
if (len < consume) {
|
||||||
|
sbuf_push(
|
||||||
|
log, indent,
|
||||||
|
"Expected %u bytes of prefix, but only %u bytes available.\n",
|
||||||
|
PSIZE(rv->prefix.prefixlen), len - 7);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
stream_get(&rv->prefix.prefix.s6_addr, s, PSIZE(rv->prefix.prefixlen));
|
||||||
|
|
||||||
|
struct in6_addr orig_locator = rv->prefix.prefix;
|
||||||
|
apply_mask_ipv6(&rv->prefix);
|
||||||
|
if (memcmp(&orig_locator, &rv->prefix.prefix, sizeof(orig_locator)))
|
||||||
|
sbuf_push(log, indent + 2,
|
||||||
|
"WARNING: SRv6 Locator had hostbits set.\n");
|
||||||
|
format_item_srv6_locator(mtid, (struct isis_item *)rv, log, NULL,
|
||||||
|
indent + 2);
|
||||||
|
|
||||||
|
consume += 1;
|
||||||
|
if (len < consume) {
|
||||||
|
sbuf_push(
|
||||||
|
log, indent,
|
||||||
|
"Expected 1 byte of subtlv len, but no more data persent.\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
subtlv_len = stream_getc(s);
|
||||||
|
|
||||||
|
if (subtlv_len) {
|
||||||
|
consume += subtlv_len;
|
||||||
|
if (len < consume) {
|
||||||
|
sbuf_push(
|
||||||
|
log, indent,
|
||||||
|
"Expected %hhu bytes of subtlvs, but only %u bytes available.\n",
|
||||||
|
subtlv_len,
|
||||||
|
len - 7 - PSIZE(rv->prefix.prefixlen));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
rv->subtlvs =
|
||||||
|
isis_alloc_subtlvs(ISIS_CONTEXT_SUBTLV_SRV6_LOCATOR);
|
||||||
|
|
||||||
|
bool unpacked_known_tlvs = false;
|
||||||
|
if (unpack_tlvs(ISIS_CONTEXT_SUBTLV_SRV6_LOCATOR, subtlv_len, s,
|
||||||
|
log, rv->subtlvs, indent + 4,
|
||||||
|
&unpacked_known_tlvs)) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (!unpacked_known_tlvs) {
|
||||||
|
isis_free_subtlvs(rv->subtlvs);
|
||||||
|
rv->subtlvs = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
append_item(items, (struct isis_item *)rv);
|
||||||
|
return 0;
|
||||||
|
out:
|
||||||
|
if (rv)
|
||||||
|
free_item_srv6_locator((struct isis_item *)rv);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Functions related to tlvs in general */
|
/* Functions related to tlvs in general */
|
||||||
|
|
||||||
struct isis_tlvs *isis_alloc_tlvs(void)
|
struct isis_tlvs *isis_alloc_tlvs(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user