diff options
| author | Carmine Scarpitta <carmine.scarpitta@uniroma2.it> | 2023-05-25 15:21:50 +0200 |
|---|---|---|
| committer | Carmine Scarpitta <carmine.scarpitta@uniroma2.it> | 2023-09-11 22:11:45 +0200 |
| commit | d56c0d23b0c5b60e2ae9f2ae1af9c143b49a4539 (patch) | |
| tree | 324aad4022bd8cf591b56cac7dea29a44580cfba /isisd/isis_tlvs.c | |
| parent | 8b6a73c3068ed356f2eeb48c087940d2be54d351 (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.c | 97 |
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, } }; |
