summaryrefslogtreecommitdiff
path: root/isisd/isis_tlvs.c
diff options
context:
space:
mode:
authorCarmine Scarpitta <carmine.scarpitta@uniroma2.it>2023-05-25 15:21:50 +0200
committerCarmine Scarpitta <carmine.scarpitta@uniroma2.it>2023-09-11 22:11:45 +0200
commitd56c0d23b0c5b60e2ae9f2ae1af9c143b49a4539 (patch)
tree324aad4022bd8cf591b56cac7dea29a44580cfba /isisd/isis_tlvs.c
parent8b6a73c3068ed356f2eeb48c087940d2be54d351 (diff)
isisd: Unpack SRv6 (LAN) End.X SID Sub-TLV
Extend the Extended IS Reachability TLV unpack function to unpack the SRv6 End.X SID Sub-TLV and SRv6 LAN End.X SID Sub-TLV, if present. Signed-off-by: Carmine Scarpitta <carmine.scarpitta@uniroma2.it>
Diffstat (limited to 'isisd/isis_tlvs.c')
-rw-r--r--isisd/isis_tlvs.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index f164453849..918bb9b9d9 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -120,6 +120,10 @@ static void isis_format_subsubtlvs(struct isis_subsubtlvs *subsubtlvs,
int indent);
static int isis_pack_subsubtlvs(struct isis_subsubtlvs *subsubtlvs,
struct stream *s);
+static int unpack_tlvs(enum isis_tlv_context context, size_t avail_len,
+ struct stream *stream, struct sbuf *log, void *dest,
+ int indent, bool *unpacked_known_tlvs);
+static void isis_free_subsubtlvs(struct isis_subsubtlvs *subsubtlvs);
/* For tests/isisd, TLV text requires ipv4-unicast instead of standard */
static const char *isis_mtid2str_fake(uint16_t mtid)
@@ -1656,6 +1660,7 @@ static int unpack_item_ext_subtlvs(uint16_t mtid, uint8_t len, struct stream *s,
uint8_t sum = 0;
uint8_t subtlv_type;
uint8_t subtlv_len;
+ uint8_t subsubtlv_len;
size_t nb_groups;
uint32_t val;
@@ -1994,6 +1999,92 @@ static int unpack_item_ext_subtlvs(uint16_t mtid, uint8_t len, struct stream *s,
SET_SUBTLV(exts, EXT_LAN_ADJ_SID);
}
break;
+ /* SRv6 End.X SID as per RFC9352 section #8.1 */
+ case ISIS_SUBTLV_SRV6_ENDX_SID:
+ if (subtlv_len < ISIS_SUBTLV_SRV6_ENDX_SID_SIZE) {
+ TLV_SIZE_MISMATCH(log, indent,
+ "SRv6 End.X SID");
+ stream_forward_getp(s, subtlv_len);
+ } else {
+ struct isis_srv6_endx_sid_subtlv *adj;
+
+ adj = XCALLOC(
+ MTYPE_ISIS_SUBTLV,
+ sizeof(struct
+ isis_srv6_endx_sid_subtlv));
+ adj->flags = stream_getc(s);
+ adj->algorithm = stream_getc(s);
+ adj->weight = stream_getc(s);
+ adj->behavior = stream_getw(s);
+ stream_get(&adj->sid, s, IPV6_MAX_BYTELEN);
+ subsubtlv_len = stream_getc(s);
+
+ adj->subsubtlvs = isis_alloc_subsubtlvs(
+ ISIS_CONTEXT_SUBSUBTLV_SRV6_ENDX_SID);
+
+ bool unpacked_known_tlvs = false;
+ if (unpack_tlvs(
+ ISIS_CONTEXT_SUBSUBTLV_SRV6_ENDX_SID,
+ subsubtlv_len, s, log,
+ adj->subsubtlvs, indent + 4,
+ &unpacked_known_tlvs)) {
+ XFREE(MTYPE_ISIS_SUBTLV, adj);
+ break;
+ }
+ if (!unpacked_known_tlvs) {
+ isis_free_subsubtlvs(adj->subsubtlvs);
+ adj->subsubtlvs = NULL;
+ }
+
+ append_item(&exts->srv6_endx_sid,
+ (struct isis_item *)adj);
+ SET_SUBTLV(exts, EXT_SRV6_ENDX_SID);
+ }
+ break;
+ /* SRv6 LAN End.X SID as per RFC9352 section #8.2 */
+ case ISIS_SUBTLV_SRV6_LAN_ENDX_SID:
+ if (subtlv_len < ISIS_SUBTLV_SRV6_LAN_ENDX_SID_SIZE) {
+ TLV_SIZE_MISMATCH(log, indent,
+ "SRv6 LAN End.X SID");
+ stream_forward_getp(s, subtlv_len);
+ } else {
+ struct isis_srv6_lan_endx_sid_subtlv *lan;
+
+ lan = XCALLOC(
+ MTYPE_ISIS_SUBTLV,
+ sizeof(struct
+ isis_srv6_lan_endx_sid_subtlv));
+ stream_get(&(lan->neighbor_id), s,
+ ISIS_SYS_ID_LEN);
+ lan->flags = stream_getc(s);
+ lan->algorithm = stream_getc(s);
+ lan->weight = stream_getc(s);
+ lan->behavior = stream_getw(s);
+ stream_get(&lan->sid, s, IPV6_MAX_BYTELEN);
+ subsubtlv_len = stream_getc(s);
+
+ lan->subsubtlvs = isis_alloc_subsubtlvs(
+ ISIS_CONTEXT_SUBSUBTLV_SRV6_ENDX_SID);
+
+ bool unpacked_known_tlvs = false;
+ if (unpack_tlvs(
+ ISIS_CONTEXT_SUBSUBTLV_SRV6_ENDX_SID,
+ subsubtlv_len, s, log,
+ lan->subsubtlvs, indent + 4,
+ &unpacked_known_tlvs)) {
+ XFREE(MTYPE_ISIS_SUBTLV, lan);
+ break;
+ }
+ if (!unpacked_known_tlvs) {
+ isis_free_subsubtlvs(lan->subsubtlvs);
+ lan->subsubtlvs = NULL;
+ }
+
+ append_item(&exts->srv6_lan_endx_sid,
+ (struct isis_item *)lan);
+ SET_SUBTLV(exts, EXT_SRV6_LAN_ENDX_SID);
+ }
+ break;
case ISIS_SUBTLV_ASLA:
if (unpack_item_ext_subtlv_asla(mtid, subtlv_len, s,
log, indent,
@@ -7147,6 +7238,12 @@ static const struct tlv_ops *const tlv_table[ISIS_CONTEXT_MAX][ISIS_TLV_MAX] = {
},
[ISIS_CONTEXT_SUBSUBTLV_SRV6_END_SID] = {
[ISIS_SUBSUBTLV_SRV6_SID_STRUCTURE] = &subsubtlv_srv6_sid_structure_ops,
+ },
+ [ISIS_CONTEXT_SUBSUBTLV_SRV6_ENDX_SID] = {
+ [ISIS_SUBSUBTLV_SRV6_SID_STRUCTURE] = &subsubtlv_srv6_sid_structure_ops,
+ },
+ [ISIS_CONTEXT_SUBSUBTLV_SRV6_LAN_ENDX_SID] = {
+ [ISIS_SUBSUBTLV_SRV6_SID_STRUCTURE] = &subsubtlv_srv6_sid_structure_ops,
}
};