Skip to content

Commit

Permalink
isisd: Add unpack function for SRv6 Locator TLV
Browse files Browse the repository at this point in the history
Add a function to unpack an SRv6 Locator TLV and all its Sub-TLVs
(RFC 9352 section sonic-net#7.1).

Signed-off-by: Carmine Scarpitta <[email protected]>
  • Loading branch information
cscarpitta committed Sep 11, 2023
1 parent b2f0b7d commit 0225f90
Showing 1 changed file with 97 additions and 0 deletions.
97 changes: 97 additions & 0 deletions isisd/isis_tlvs.c
Original file line number Diff line number Diff line change
Expand Up @@ -5625,6 +5625,103 @@ static int pack_item_srv6_locator(struct isis_item *i, struct stream *s,
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 */

struct isis_tlvs *isis_alloc_tlvs(void)
Expand Down

0 comments on commit 0225f90

Please sign in to comment.