diff options
author | Hiroki Shirokura <hiroki.shirokura@linecorp.com> | 2022-01-04 02:31:45 +0100 |
---|---|---|
committer | Louis Scalbert <louis.scalbert@6wind.com> | 2023-04-18 11:33:15 +0200 |
commit | 78774bbcd51b1cb461b2d8622545d4b8136f2344 (patch) | |
tree | f750e0a072454063829ab09698487121a1a44021 /isisd | |
parent | isisd: add ASLA support (diff) | |
download | frr-78774bbcd51b1cb461b2d8622545d4b8136f2344.tar.xz frr-78774bbcd51b1cb461b2d8622545d4b8136f2344.zip |
isisd: add isis flex-algo lsp advertisement
Deal with the packing and unpacking of following Flex-Algo
Sub-Sub-TLVs:
- Router Capability (already defined TLV 242)
- List of the Flex-Algo Definitions (Sub-TLV 26)
- Exclude admin group (Sub-Sub-TLV 1)
- Include-any admin group (Sub-Sub-TLV 2)
- Include-all admin group (Sub-Sub-TLV 3)
- Flags (for prefix-metric) (Sub-Sub-TLV 4)
This commit splits data into multiple router capability TLVs if needed
because a TLV cannot contains more than 255 bytes.
Note that the list of SR Algorithm (Sub-TLV 19) within Router Capability
(TLV 242) is already set in a previous commit.
Signed-off-by: Hiroki Shirokura <hiroki.shirokura@linecorp.com>
Signed-off-by: Eric Kinzie <ekinzie@labn.net>
Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
Diffstat (limited to 'isisd')
-rw-r--r-- | isisd/isis_lsp.c | 102 | ||||
-rw-r--r-- | isisd/isis_tlvs.c | 421 | ||||
-rw-r--r-- | isisd/isis_tlvs.h | 48 |
3 files changed, 513 insertions, 58 deletions
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 08fa845e8..c07083a06 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -46,6 +46,7 @@ #include "isisd/fabricd.h" #include "isisd/isis_tx_queue.h" #include "isisd/isis_nb.h" +#include "isisd/isis_flex_algo.h" DEFINE_MTYPE_STATIC(ISISD, ISIS_LSP, "ISIS LSP"); @@ -898,9 +899,15 @@ static void lsp_build_internal_reach_ipv4(struct isis_lsp *lsp, area->area_tag, ipv4); if (area->srdb.enabled) - for (int i = 0; i < SR_ALGORITHM_COUNT; i++) + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) { +#ifndef FABRICD + if (flex_algo_id_valid(i) && + !isis_flex_algo_elected_supported(i, area)) + continue; +#endif /* ifndef FABRICD */ pcfgs[i] = isis_sr_cfg_prefix_find(area, ipv4, i); + } isis_tlvs_add_extended_ip_reach(lsp->tlvs, ipv4, metric, false, pcfgs); @@ -918,8 +925,14 @@ static void lsp_build_internal_reach_ipv6(struct isis_lsp *lsp, area->area_tag, ipv6); if (area->srdb.enabled) - for (int i = 0; i < SR_ALGORITHM_COUNT; i++) + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) { +#ifndef FABRICD + if (flex_algo_id_valid(i) && + !isis_flex_algo_elected_supported(i, area)) + continue; +#endif /* ifndef FABRICD */ pcfgs[i] = isis_sr_cfg_prefix_find(area, ipv6, i); + } isis_tlvs_add_ipv6_reach(lsp->tlvs, isis_area_ipv6_topology(area), ipv6, metric, false, pcfgs); @@ -955,9 +968,16 @@ static void lsp_build_ext_reach_ipv4(struct isis_lsp *lsp, NULL}; if (area->srdb.enabled) - for (int i = 0; i < SR_ALGORITHM_COUNT; i++) + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) { +#ifndef FABRICD + if (flex_algo_id_valid(i) && + !isis_flex_algo_elected_supported( + i, area)) + continue; +#endif /* ifndef FABRICD */ pcfgs[i] = isis_sr_cfg_prefix_find( area, ipv4, i); + } isis_tlvs_add_extended_ip_reach(lsp->tlvs, ipv4, metric, true, pcfgs); @@ -992,9 +1012,16 @@ static void lsp_build_ext_reach_ipv6(struct isis_lsp *lsp, NULL}; if (area->srdb.enabled) - for (int i = 0; i < SR_ALGORITHM_COUNT; i++) + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) { +#ifndef FABRICD + if (flex_algo_id_valid(i) && + !isis_flex_algo_elected_supported( + i, area)) + continue; +#endif /* ifndef FABRICD */ pcfgs[i] = isis_sr_cfg_prefix_find( area, p, i); + } isis_tlvs_add_ipv6_reach(lsp->tlvs, isis_area_ipv6_topology(area), @@ -1115,13 +1142,30 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) /* Add Router Capability TLV. */ if (area->isis->router_id != 0) { - struct isis_router_cap cap = {}; + struct isis_router_cap *rcap; +#ifndef FABRICD + struct isis_router_cap_fad *rcap_fad; + struct listnode *node; + struct flex_algo *fa; +#endif /* ifndef FABRICD */ - /* init SR algo list content to the default value */ - for (int i = 0; i < SR_ALGORITHM_COUNT; i++) - cap.algo[i] = SR_ALGORITHM_UNSET; + rcap = isis_tlvs_init_router_capability(lsp->tlvs); - cap.router_id.s_addr = area->isis->router_id; + rcap->router_id.s_addr = area->isis->router_id; + +#ifndef FABRICD + /* Set flex-algo definitions */ + for (ALL_LIST_ELEMENTS_RO(area->flex_algos->flex_algos, node, + fa)) { + if (!fa->advertise_definition) + continue; + lsp_debug("ISIS (%s): Flex-Algo Definition %u", + area->area_tag, fa->algorithm); + isis_tlvs_set_router_capability_fad(lsp->tlvs, fa, + fa->algorithm, + area->isis->sysid); + } +#endif /* ifndef FABRICD */ /* Add SR Sub-TLVs if SR is enabled. */ if (area->srdb.enabled) { @@ -1131,26 +1175,38 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) /* SRGB first */ range_size = srdb->config.srgb_upper_bound - srdb->config.srgb_lower_bound + 1; - cap.srgb.flags = ISIS_SUBTLV_SRGB_FLAG_I - | ISIS_SUBTLV_SRGB_FLAG_V; - cap.srgb.range_size = range_size; - cap.srgb.lower_bound = srdb->config.srgb_lower_bound; + rcap->srgb.flags = ISIS_SUBTLV_SRGB_FLAG_I | + ISIS_SUBTLV_SRGB_FLAG_V; + rcap->srgb.range_size = range_size; + rcap->srgb.lower_bound = srdb->config.srgb_lower_bound; /* Then Algorithm */ - cap.algo[0] = SR_ALGORITHM_SPF; - cap.algo[1] = SR_ALGORITHM_UNSET; + rcap->algo[0] = SR_ALGORITHM_SPF; + rcap->algo[1] = SR_ALGORITHM_UNSET; +#ifndef FABRICD + for (ALL_LIST_ELEMENTS_RO(area->flex_algos->flex_algos, + node, fa)) { + if (fa->advertise_definition) + rcap_fad = rcap->fads[fa->algorithm]; + else + rcap_fad = NULL; + + if (!isis_flex_algo_elected_supported_local_fad( + fa->algorithm, area, &rcap_fad)) + continue; + lsp_debug("ISIS (%s): SR Algorithm %u", + area->area_tag, fa->algorithm); + rcap->algo[fa->algorithm] = fa->algorithm; + } +#endif /* ifndef FABRICD */ /* SRLB */ - cap.srlb.flags = 0; + rcap->srlb.flags = 0; range_size = srdb->config.srlb_upper_bound - srdb->config.srlb_lower_bound + 1; - cap.srlb.range_size = range_size; - cap.srlb.lower_bound = srdb->config.srlb_lower_bound; + rcap->srlb.range_size = range_size; + rcap->srlb.lower_bound = srdb->config.srlb_lower_bound; /* And finally MSD */ - cap.msd = srdb->config.msd; + rcap->msd = srdb->config.msd; } - - isis_tlvs_set_router_capability(lsp->tlvs, &cap); - lsp_debug("ISIS (%s): Adding Router Capabilities information", - area->area_tag); } /* IPv4 address and TE router ID TLVs. diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c index 368973dfd..4ad877ce0 100644 --- a/isisd/isis_tlvs.c +++ b/isisd/isis_tlvs.c @@ -29,6 +29,7 @@ #include "isisd/isis_lsp.h" #include "isisd/isis_te.h" #include "isisd/isis_sr.h" +#include "isisd/isis_flex_algo.h" #define TLV_SIZE_MISMATCH(log, indent, target) \ sbuf_push(log, indent, \ @@ -36,6 +37,7 @@ DEFINE_MTYPE_STATIC(ISISD, ISIS_TLV, "ISIS TLVs"); DEFINE_MTYPE(ISISD, ISIS_SUBTLV, "ISIS Sub-TLVs"); +DEFINE_MTYPE_STATIC(ISISD, ISIS_SUBSUBTLV, "ISIS Sub-Sub-TLVs"); DEFINE_MTYPE_STATIC(ISISD, ISIS_MT_ITEM_LIST, "ISIS MT Item Lists"); typedef int (*unpack_tlv_func)(enum isis_tlv_context context, uint8_t tlv_type, @@ -381,7 +383,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts, exts->adm_group); json_object_string_add(json, "adm-group", aux_buf); } else { - sbuf_push(buf, indent, "Administrative Group: 0x%x\n", + sbuf_push(buf, indent, "Admin Group: 0x%08x\n", exts->adm_group); sbuf_push(buf, indent + 2, "Bit positions: %s\n", admin_group_standard_print( @@ -3912,6 +3914,39 @@ static struct isis_router_cap *copy_tlv_router_cap( memcpy(rv, router_cap, sizeof(*rv)); +#ifndef FABRICD + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) { + struct isis_router_cap_fad *sc_fad; + struct isis_router_cap_fad *rv_fad; + + sc_fad = router_cap->fads[i]; + if (!sc_fad) + continue; + rv_fad = XMALLOC(MTYPE_ISIS_TLV, + sizeof(struct isis_router_cap_fad)); + *rv_fad = *sc_fad; + rv_fad->fad.admin_group_exclude_any.bitmap.data = NULL; + rv_fad->fad.admin_group_include_any.bitmap.data = NULL; + rv_fad->fad.admin_group_include_all.bitmap.data = NULL; + + assert(bf_is_inited( + sc_fad->fad.admin_group_exclude_any.bitmap)); + assert(bf_is_inited( + sc_fad->fad.admin_group_include_any.bitmap)); + assert(bf_is_inited( + sc_fad->fad.admin_group_include_all.bitmap)); + + admin_group_copy(&rv_fad->fad.admin_group_exclude_any, + &sc_fad->fad.admin_group_exclude_any); + admin_group_copy(&rv_fad->fad.admin_group_include_any, + &sc_fad->fad.admin_group_include_any); + admin_group_copy(&rv_fad->fad.admin_group_include_all, + &sc_fad->fad.admin_group_include_all); + + rv->fads[i] = rv_fad; + } +#endif /* ifndef FABRICD */ + return rv; } @@ -4031,37 +4066,178 @@ static void format_tlv_router_cap(const struct isis_router_cap *router_cap, if (router_cap->msd != 0) sbuf_push(buf, indent, " Node Maximum SID Depth: %u\n", router_cap->msd); + +#ifndef FABRICD + /* Flex-Algo */ + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) { + char admin_group_buf[ADMIN_GROUP_PRINT_MAX_SIZE]; + int indent2; + struct admin_group *admin_group; + struct isis_router_cap_fad *fad; + + fad = router_cap->fads[i]; + if (!fad) + continue; + + sbuf_push(buf, indent, " Flex-Algo Definition: %d\n", + fad->fad.algorithm); + sbuf_push(buf, indent, " Metric-Type: %d\n", + fad->fad.metric_type); + sbuf_push(buf, indent, " Calc-Type: %d\n", + fad->fad.calc_type); + sbuf_push(buf, indent, " Priority: %d\n", fad->fad.priority); + + indent2 = indent + strlen(" Exclude-Any: "); + admin_group = &fad->fad.admin_group_exclude_any; + sbuf_push(buf, indent, " Exclude-Any: "); + sbuf_push(buf, 0, "%s\n", + admin_group_string(admin_group_buf, + ADMIN_GROUP_PRINT_MAX_SIZE, + indent2, admin_group)); + + indent2 = indent + strlen(" Include-Any: "); + admin_group = &fad->fad.admin_group_include_any; + sbuf_push(buf, indent, " Include-Any: "); + sbuf_push(buf, 0, "%s\n", + admin_group_string(admin_group_buf, + ADMIN_GROUP_PRINT_MAX_SIZE, + indent2, admin_group)); + + indent2 = indent + strlen(" Include-All: "); + admin_group = &fad->fad.admin_group_include_all; + sbuf_push(buf, indent, " Include-All: "); + sbuf_push(buf, 0, "%s\n", + admin_group_string(admin_group_buf, + ADMIN_GROUP_PRINT_MAX_SIZE, + indent2, admin_group)); + + sbuf_push(buf, indent, " M-Flag: %c\n", + CHECK_FLAG(fad->fad.flags, FAD_FLAG_M) ? '1' : '0'); + + if (fad->fad.flags != 0 && fad->fad.flags != FAD_FLAG_M) + sbuf_push(buf, indent, " Flags: 0x%x\n", + fad->fad.flags); + if (fad->fad.exclude_srlg) + sbuf_push(buf, indent, " Exclude SRLG: Enabled\n"); + if (fad->fad.unsupported_subtlv) + sbuf_push(buf, indent, + " Got an unsupported sub-TLV: Yes\n"); + } +#endif /* ifndef FABRICD */ } static void free_tlv_router_cap(struct isis_router_cap *router_cap) { + if (!router_cap) + return; + +#ifndef FABRICD + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) { + struct isis_router_cap_fad *fad; + + fad = router_cap->fads[i]; + if (!fad) + continue; + admin_group_term(&fad->fad.admin_group_exclude_any); + admin_group_term(&fad->fad.admin_group_include_any); + admin_group_term(&fad->fad.admin_group_include_all); + XFREE(MTYPE_ISIS_TLV, fad); + } +#endif /* ifndef FABRICD */ + XFREE(MTYPE_ISIS_TLV, router_cap); } +#ifndef FABRICD +static size_t +isis_router_cap_fad_sub_tlv_len(const struct isis_router_cap_fad *fad) +{ + size_t sz = ISIS_SUBTLV_FAD_MIN_SIZE; + uint32_t admin_group_length; + + admin_group_length = + admin_group_nb_words(&fad->fad.admin_group_exclude_any); + if (admin_group_length) + sz += sizeof(uint32_t) * admin_group_length + 2; + + admin_group_length = + admin_group_nb_words(&fad->fad.admin_group_include_any); + if (admin_group_length) + sz += sizeof(uint32_t) * admin_group_length + 2; + + admin_group_length = + admin_group_nb_words(&fad->fad.admin_group_include_all); + if (admin_group_length) + sz += sizeof(uint32_t) * admin_group_length + 2; + + if (fad->fad.flags != 0) + sz += ISIS_SUBTLV_FAD_SUBSUBTLV_FLAGS_SIZE + 2; + + /* TODO: add exclude SRLG sub-sub-TLV length when supported */ + + return sz; +} +#endif /* ifndef FABRICD */ + +static size_t isis_router_cap_tlv_size(const struct isis_router_cap *router_cap) +{ + size_t sz = 2 + ISIS_ROUTER_CAP_SIZE; +#ifndef FABRICD + size_t fad_sz; +#endif /* ifndef FABRICD */ + int nb_algo; + + if ((router_cap->srgb.range_size != 0) && + (router_cap->srgb.lower_bound != 0)) { + sz += 2 + ISIS_SUBTLV_SID_LABEL_RANGE_SIZE; + sz += 2 + ISIS_SUBTLV_SID_LABEL_SIZE; + + nb_algo = isis_tlvs_sr_algo_count(router_cap); + if (nb_algo != 0) + sz += 2 + nb_algo; + + if ((router_cap->srlb.range_size != 0) && + (router_cap->srlb.lower_bound != 0)) { + sz += 2 + ISIS_SUBTLV_SID_LABEL_RANGE_SIZE; + sz += 2 + ISIS_SUBTLV_SID_LABEL_SIZE; + } + + if (router_cap->msd != 0) + sz += 2 + ISIS_SUBTLV_NODE_MSD_SIZE; + } + +#ifndef FABRICD + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) { + if (!router_cap->fads[i]) + continue; + fad_sz = 2 + + isis_router_cap_fad_sub_tlv_len(router_cap->fads[i]); + if (((sz + fad_sz) % 256) < (sz % 256)) + sz += 2 + ISIS_ROUTER_CAP_SIZE + fad_sz; + else + sz += fad_sz; + } +#endif /* ifndef FABRICD */ + + return sz; +} + static int pack_tlv_router_cap(const struct isis_router_cap *router_cap, struct stream *s) { - size_t tlv_len = ISIS_ROUTER_CAP_SIZE; - size_t len_pos; + size_t tlv_len, len_pos; uint8_t nb_algo; if (!router_cap) return 0; - /* Compute Maximum TLV size */ - tlv_len += ISIS_SUBTLV_SID_LABEL_RANGE_SIZE - + ISIS_SUBTLV_HDR_SIZE - + ISIS_SUBTLV_ALGORITHM_SIZE - + ISIS_SUBTLV_NODE_MSD_SIZE; - - if (STREAM_WRITEABLE(s) < (unsigned int)(2 + tlv_len)) + if (STREAM_WRITEABLE(s) < isis_router_cap_tlv_size(router_cap)) return 1; /* Add Router Capability TLV 242 with Router ID and Flags */ stream_putc(s, ISIS_TLV_ROUTER_CAPABILITY); - /* Real length will be adjusted later */ len_pos = stream_get_endp(s); - stream_putc(s, tlv_len); + stream_putc(s, 0); /* Real length will be adjusted later */ stream_put_ipv4(s, router_cap->router_id.s_addr); stream_putc(s, router_cap->flags); @@ -4108,6 +4284,80 @@ static int pack_tlv_router_cap(const struct isis_router_cap *router_cap, } } +#ifndef FABRICD + /* Flex Algo Definitions */ + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) { + struct isis_router_cap_fad *fad; + size_t subtlv_len; + struct admin_group *ag; + uint32_t admin_group_length; + + fad = router_cap->fads[i]; + if (!fad) + continue; + + subtlv_len = isis_router_cap_fad_sub_tlv_len(fad); + + if ((stream_get_endp(s) - len_pos - 1) > 250) { + /* Adjust TLV length which depends on subTLVs presence + */ + tlv_len = stream_get_endp(s) - len_pos - 1; + stream_putc_at(s, len_pos, tlv_len); + + /* Add Router Capability TLV 242 with Router ID and + * Flags + */ + stream_putc(s, ISIS_TLV_ROUTER_CAPABILITY); + /* Real length will be adjusted later */ + len_pos = stream_get_endp(s); + stream_putc(s, 0); + stream_put_ipv4(s, router_cap->router_id.s_addr); + stream_putc(s, router_cap->flags); + } + + stream_putc(s, ISIS_SUBTLV_FAD); + stream_putc(s, subtlv_len); /* length will be filled later */ + + stream_putc(s, fad->fad.algorithm); + stream_putc(s, fad->fad.metric_type); + stream_putc(s, fad->fad.calc_type); + stream_putc(s, fad->fad.priority); + + ag = &fad->fad.admin_group_exclude_any; + admin_group_length = admin_group_nb_words(ag); + if (admin_group_length) { + stream_putc(s, ISIS_SUBTLV_FAD_SUBSUBTLV_EXCAG); + stream_putc(s, sizeof(uint32_t) * admin_group_length); + for (size_t i = 0; i < admin_group_length; i++) + stream_putl(s, admin_group_get_offset(ag, i)); + } + + ag = &fad->fad.admin_group_include_any; + admin_group_length = admin_group_nb_words(ag); + if (admin_group_length) { + stream_putc(s, ISIS_SUBTLV_FAD_SUBSUBTLV_INCANYAG); + stream_putc(s, sizeof(uint32_t) * admin_group_length); + for (size_t i = 0; i < admin_group_length; i++) + stream_putl(s, admin_group_get_offset(ag, i)); + } + + ag = &fad->fad.admin_group_include_all; + admin_group_length = admin_group_nb_words(ag); + if (admin_group_length) { + stream_putc(s, ISIS_SUBTLV_FAD_SUBSUBTLV_INCALLAG); + stream_putc(s, sizeof(uint32_t) * admin_group_length); + for (size_t i = 0; i < admin_group_length; i++) + stream_putl(s, admin_group_get_offset(ag, i)); + } + + if (fad->fad.flags != 0) { + stream_putc(s, ISIS_SUBTLV_FAD_SUBSUBTLV_FLAGS); + stream_putc(s, ISIS_SUBTLV_FAD_SUBSUBTLV_FLAGS_SIZE); + stream_putc(s, fad->fad.flags); + } + } +#endif /* ifndef FABRICD */ + /* Adjust TLV length which depends on subTLVs presence */ tlv_len = stream_get_endp(s) - len_pos - 1; stream_putc_at(s, len_pos, tlv_len); @@ -4134,18 +4384,16 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, return 0; } - if (tlvs->router_cap) { - sbuf_push(log, indent, - "WARNING: Router Capability TLV present multiple times.\n"); - stream_forward_getp(s, tlv_len); - return 0; + if (tlvs->router_cap) + /* Multiple Router Capability found */ + rcap = tlvs->router_cap; + else { + /* Allocate router cap structure and initialize SR Algorithms */ + rcap = XCALLOC(MTYPE_ISIS_TLV, sizeof(struct isis_router_cap)); + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) + rcap->algo[i] = SR_ALGORITHM_UNSET; } - /* Allocate router cap structure and initialize SR Algorithms */ - rcap = XCALLOC(MTYPE_ISIS_TLV, sizeof(struct isis_router_cap)); - for (int i = 0; i < SR_ALGORITHM_COUNT; i++) - rcap->algo[i] = SR_ALGORITHM_UNSET; - /* Get Router ID and Flags */ rcap->router_id.s_addr = stream_get_ipv4(s); rcap->flags = stream_getc(s); @@ -4153,6 +4401,10 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, /* Parse remaining part of the TLV if present */ subtlv_len = tlv_len - ISIS_ROUTER_CAP_SIZE; while (subtlv_len > 2) { +#ifndef FABRICD + struct isis_router_cap_fad *fad; + uint8_t subsubtlvs_len; +#endif /* ifndef FABRICD */ uint8_t msd_type; type = stream_getc(s); @@ -4306,6 +4558,80 @@ static int unpack_tlv_router_cap(enum isis_tlv_context context, if (length > MSD_TLV_SIZE) stream_forward_getp(s, length - MSD_TLV_SIZE); break; +#ifndef FABRICD + case ISIS_SUBTLV_FAD: + fad = XCALLOC(MTYPE_ISIS_TLV, + sizeof(struct isis_router_cap_fad)); + fad->fad.algorithm = stream_getc(s); + fad->fad.metric_type = stream_getc(s); + fad->fad.calc_type = stream_getc(s); + fad->fad.priority = stream_getc(s); + rcap->fads[fad->fad.algorithm] = fad; + admin_group_init(&fad->fad.admin_group_exclude_any); + admin_group_init(&fad->fad.admin_group_include_any); + admin_group_init(&fad->fad.admin_group_include_all); + + subsubtlvs_len = length - 4; + while (subsubtlvs_len > 2) { + struct admin_group *ag; + uint8_t subsubtlv_type; + uint8_t subsubtlv_len; + uint32_t v; + int n_ag, i; + + subsubtlv_type = stream_getc(s); + subsubtlv_len = stream_getc(s); + + switch (subsubtlv_type) { + case ISIS_SUBTLV_FAD_SUBSUBTLV_EXCAG: + ag = &fad->fad.admin_group_exclude_any; + n_ag = subsubtlv_len / sizeof(uint32_t); + for (i = 0; i < n_ag; i++) { + v = stream_getl(s); + admin_group_bulk_set(ag, v, i); + } + break; + case ISIS_SUBTLV_FAD_SUBSUBTLV_INCANYAG: + ag = &fad->fad.admin_group_include_any; + n_ag = subsubtlv_len / sizeof(uint32_t); + for (i = 0; i < n_ag; i++) { + v = stream_getl(s); + admin_group_bulk_set(ag, v, i); + } + break; + case ISIS_SUBTLV_FAD_SUBSUBTLV_INCALLAG: + ag = &fad->fad.admin_group_include_all; + n_ag = subsubtlv_len / sizeof(uint32_t); + for (i = 0; i < n_ag; i++) { + v = stream_getl(s); + admin_group_bulk_set(ag, v, i); + } + break; + case ISIS_SUBTLV_FAD_SUBSUBTLV_FLAGS: + if (subsubtlv_len == 0) + break; + + fad->fad.flags = stream_getc(s); + for (i = subsubtlv_len - 1; i > 0; --i) + stream_getc(s); + break; + case ISIS_SUBTLV_FAD_SUBSUBTLV_ESRLG: + fad->fad.exclude_srlg = true; + stream_forward_getp(s, subsubtlv_len); + break; + default: + sbuf_push( + log, indent, + "Received an unsupported Flex-Algo sub-TLV type %u\n", + subsubtlv_type); + fad->fad.unsupported_subtlv = true; + stream_forward_getp(s, subsubtlv_len); + break; + } + subsubtlvs_len -= 2 + subsubtlv_len; + } + break; +#endif /* ifndef FABRICD */ default: stream_forward_getp(s, length); break; @@ -6253,17 +6579,52 @@ void isis_tlvs_set_dynamic_hostname(struct isis_tlvs *tlvs, tlvs->hostname = XSTRDUP(MTYPE_ISIS_TLV, hostname); } -/* Set Router Capability TLV parameters */ -void isis_tlvs_set_router_capability(struct isis_tlvs *tlvs, - const struct isis_router_cap *cap) +/* Init Router Capability TLV parameters */ +struct isis_router_cap *isis_tlvs_init_router_capability(struct isis_tlvs *tlvs) { - XFREE(MTYPE_ISIS_TLV, tlvs->router_cap); - if (!cap) - return; - tlvs->router_cap = XCALLOC(MTYPE_ISIS_TLV, sizeof(*tlvs->router_cap)); - *tlvs->router_cap = *cap; + + /* init SR algo list content to the default value */ + for (int i = 0; i < SR_ALGORITHM_COUNT; i++) + tlvs->router_cap->algo[i] = SR_ALGORITHM_UNSET; + + return tlvs->router_cap; +} + +#ifndef FABRICD +void isis_tlvs_set_router_capability_fad(struct isis_tlvs *tlvs, + struct flex_algo *fa, int algorithm, + uint8_t *sysid) +{ + struct isis_router_cap_fad *rcap_fad; + + assert(tlvs->router_cap); + + rcap_fad = tlvs->router_cap->fads[algorithm]; + + if (!rcap_fad) + rcap_fad = XCALLOC(MTYPE_ISIS_TLV, + sizeof(struct isis_router_cap_fad)); + + memset(rcap_fad->sysid, 0, ISIS_SYS_ID_LEN + 2); + memcpy(rcap_fad->sysid, sysid, ISIS_SYS_ID_LEN); + + memcpy(&rcap_fad->fad, fa, sizeof(struct flex_algo)); + + rcap_fad->fad.admin_group_exclude_any.bitmap.data = NULL; + rcap_fad->fad.admin_group_include_any.bitmap.data = NULL; + rcap_fad->fad.admin_group_include_all.bitmap.data = NULL; + + admin_group_copy(&rcap_fad->fad.admin_group_exclude_any, + &fa->admin_group_exclude_any); + admin_group_copy(&rcap_fad->fad.admin_group_include_any, + &fa->admin_group_include_any); + admin_group_copy(&rcap_fad->fad.admin_group_include_all, + &fa->admin_group_include_all); + + tlvs->router_cap->fads[algorithm] = rcap_fad; } +#endif /* ifndef FABRICD */ int isis_tlvs_sr_algo_count(const struct isis_router_cap *cap) { diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h index 331cad93e..03e2b2edc 100644 --- a/isisd/isis_tlvs.h +++ b/isisd/isis_tlvs.h @@ -13,6 +13,8 @@ #include "openbsd-tree.h" #include "prefix.h" #include "flex_algo.h" +#include "affinitymap.h" + DECLARE_MTYPE(ISIS_SUBTLV); @@ -400,10 +402,22 @@ enum isis_tlv_type { ISIS_SUBTLV_AVA_BW = 38, ISIS_SUBTLV_USE_BW = 39, + /* RFC 7308 */ + ISIS_SUBTLV_EXT_ADMIN_GRP = 14, + /* RFC 8919 */ ISIS_SUBTLV_ASLA = 16, + /* draft-ietf-lsr-isis-srv6-extensions */ + ISIS_SUBTLV_SID_END = 5, + ISIS_SUBTLV_SID_END_X = 43, + ISIS_SUBTLV_MAX = 40, + + /* draft-ietf-lsr-isis-srv6-extensions */ + ISIS_SUBSUBTLV_SID_STRUCTURE = 1, + + ISIS_SUBSUBTLV_MAX = 256, }; /* subTLVs size for TE and SR */ @@ -431,15 +445,31 @@ enum ext_subtlv_size { /* RFC 7810 */ ISIS_SUBTLV_MM_DELAY_SIZE = 8, + /* RFC9350 - Flex-Algorithm */ + ISIS_SUBTLV_FAD = 26, + ISIS_SUBTLV_FAD_MIN_SIZE = 4, + ISIS_SUBTLV_HDR_SIZE = 2, ISIS_SUBTLV_DEF_SIZE = 4, - /* RFC 7308 */ - ISIS_SUBTLV_EXT_ADMIN_GRP = 14, + ISIS_SUBTLV_MAX_SIZE = 180, + + /* draft-ietf-lsr-isis-srv6-extensions */ + ISIS_SUBSUBTLV_SID_STRUCTURE_SIZE = 4, ISIS_SUBSUBTLV_HDR_SIZE = 2, + ISIS_SUBSUBTLV_MAX_SIZE = 180, - ISIS_SUBTLV_MAX_SIZE = 180, + /* RFC9350 - Flex-Algorithm */ + ISIS_SUBTLV_FAD_SUBSUBTLV_FLAGS_SIZE = 1, +}; + +enum ext_subsubtlv_types { + ISIS_SUBTLV_FAD_SUBSUBTLV_EXCAG = 1, + ISIS_SUBTLV_FAD_SUBSUBTLV_INCANYAG = 2, + ISIS_SUBTLV_FAD_SUBSUBTLV_INCALLAG = 3, + ISIS_SUBTLV_FAD_SUBSUBTLV_FLAGS = 4, + ISIS_SUBTLV_FAD_SUBSUBTLV_ESRLG = 5, }; /* Macros to manage the optional presence of EXT subTLVs */ @@ -625,8 +655,16 @@ void isis_tlvs_add_csnp_entries(struct isis_tlvs *tlvs, uint8_t *start_id, struct isis_lsp **last_lsp); void isis_tlvs_set_dynamic_hostname(struct isis_tlvs *tlvs, const char *hostname); -void isis_tlvs_set_router_capability(struct isis_tlvs *tlvs, - const struct isis_router_cap *cap); +struct isis_router_cap * +isis_tlvs_init_router_capability(struct isis_tlvs *tlvs); + +struct isis_area; +struct isis_flex_algo; +void isis_tlvs_set_router_capability_fad(struct isis_tlvs *tlvs, + struct flex_algo *fa, int algorithm, + uint8_t *sysid); + +struct isis_area; int isis_tlvs_sr_algo_count(const struct isis_router_cap *cap); |