diff options
| -rw-r--r-- | isisd/isis_lsp.c | 102 | ||||
| -rw-r--r-- | isisd/isis_tlvs.c | 421 | ||||
| -rw-r--r-- | isisd/isis_tlvs.h | 48 | ||||
| -rw-r--r-- | tests/isisd/test_common.c | 25 | 
4 files changed, 526 insertions, 70 deletions
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 08fa845e8e..c07083a06d 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 368973dfd9..4ad877ce0f 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 331cad93e9..03e2b2edcc 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); diff --git a/tests/isisd/test_common.c b/tests/isisd/test_common.c index 5c1debca8d..e47456965e 100644 --- a/tests/isisd/test_common.c +++ b/tests/isisd/test_common.c @@ -163,31 +163,32 @@ static void lsp_add_reach(struct isis_lsp *lsp,  static void lsp_add_router_capability(struct isis_lsp *lsp,  				      const struct isis_test_node *tnode)  { -	struct isis_router_cap cap = {}; +	struct isis_router_cap *cap;  	if (!tnode->router_id)  		return; -	if (inet_pton(AF_INET, tnode->router_id, &cap.router_id) != 1) { +	cap = isis_tlvs_init_router_capability(lsp->tlvs); + +	if (inet_pton(AF_INET, tnode->router_id, &cap->router_id) != 1) {  		zlog_debug("%s: invalid router-id: %s", __func__,  			   tnode->router_id);  		return;  	}  	if (CHECK_FLAG(tnode->flags, F_ISIS_TEST_NODE_SR)) { -		cap.srgb.flags = +		cap->srgb.flags =  			ISIS_SUBTLV_SRGB_FLAG_I | ISIS_SUBTLV_SRGB_FLAG_V; -		cap.srgb.lower_bound = tnode->srgb.lower_bound -					       ? tnode->srgb.lower_bound -					       : SRGB_DFTL_LOWER_BOUND; -		cap.srgb.range_size = tnode->srgb.range_size -					      ? tnode->srgb.range_size -					      : SRGB_DFTL_RANGE_SIZE; -		cap.algo[0] = SR_ALGORITHM_SPF; -		cap.algo[1] = SR_ALGORITHM_UNSET; +		cap->srgb.lower_bound = tnode->srgb.lower_bound +						? tnode->srgb.lower_bound +						: SRGB_DFTL_LOWER_BOUND; +		cap->srgb.range_size = tnode->srgb.range_size +					       ? tnode->srgb.range_size +					       : SRGB_DFTL_RANGE_SIZE; +		cap->algo[0] = SR_ALGORITHM_SPF; +		cap->algo[1] = SR_ALGORITHM_UNSET;  	} -	isis_tlvs_set_router_capability(lsp->tlvs, &cap);  }  static void lsp_add_mt_router_info(struct isis_lsp *lsp,  | 
