From d56c0d23b0c5b60e2ae9f2ae1af9c143b49a4539 Mon Sep 17 00:00:00 2001 From: Carmine Scarpitta Date: Thu, 25 May 2023 15:21:50 +0200 Subject: [PATCH] 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 --- isisd/isis_tlvs.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++ isisd/isis_tlvs.h | 2 + 2 files changed, 99 insertions(+) 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, } }; diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h index 38072719f4..825610ed35 100644 --- a/isisd/isis_tlvs.h +++ b/isisd/isis_tlvs.h @@ -423,6 +423,8 @@ enum isis_tlv_context { ISIS_CONTEXT_SUBTLV_IPV6_REACH, ISIS_CONTEXT_SUBTLV_SRV6_LOCATOR, ISIS_CONTEXT_SUBSUBTLV_SRV6_END_SID, + ISIS_CONTEXT_SUBSUBTLV_SRV6_ENDX_SID, + ISIS_CONTEXT_SUBSUBTLV_SRV6_LAN_ENDX_SID, ISIS_CONTEXT_MAX, };