mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 21:47:15 +02:00
isisd: add ASLA support
Add the support of ASLA with the following TLV: - Extended IS Reachability (already defined TLV 22) - Application-Specific Link Attributes (Sub-TLV 16) (to enable the Flex-Algo flag on a link) - Admin-group (Sub-Sub-TLV 3) - Extended Admin-group (Sub-Sub-TLV 14) Signed-off-by: Louis Scalbert <louis.scalbert@6wind.com>
This commit is contained in:
parent
f46e34f838
commit
5749ac83a8
170
isisd/isis_te.c
170
isisd/isis_te.c
|
@ -164,6 +164,154 @@ void isis_mpls_te_term(struct isis_area *area)
|
|||
XFREE(MTYPE_ISIS_MPLS_TE, area->mta);
|
||||
}
|
||||
|
||||
static void isis_link_params_update_asla(struct isis_circuit *circuit,
|
||||
struct interface *ifp)
|
||||
{
|
||||
struct isis_asla_subtlvs *asla;
|
||||
struct listnode *node, *nnode;
|
||||
struct isis_ext_subtlvs *ext = circuit->ext;
|
||||
int i;
|
||||
|
||||
if (!HAS_LINK_PARAMS(ifp)) {
|
||||
list_delete_all_node(ext->aslas);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef FABRICD
|
||||
/* RFC 8919 Application Specific Link-Attributes
|
||||
* is required by flex-algo application ISIS_SABM_FLAG_X
|
||||
*/
|
||||
if (list_isempty(circuit->area->flex_algos->flex_algos))
|
||||
isis_tlvs_free_asla(ext, ISIS_SABM_FLAG_X);
|
||||
else
|
||||
isis_tlvs_find_alloc_asla(ext, ISIS_SABM_FLAG_X);
|
||||
#endif /* ifndef FABRICD */
|
||||
|
||||
if (list_isempty(ext->aslas))
|
||||
return;
|
||||
|
||||
for (ALL_LIST_ELEMENTS(ext->aslas, node, nnode, asla)) {
|
||||
asla->legacy = circuit->area->asla_legacy_flag;
|
||||
RESET_SUBTLV(asla);
|
||||
|
||||
if (asla->legacy)
|
||||
continue;
|
||||
|
||||
/* Fulfill ASLA subTLVs from interface link parameters */
|
||||
if (IS_PARAM_SET(ifp->link_params, LP_ADM_GRP)) {
|
||||
asla->admin_group = ifp->link_params->admin_grp;
|
||||
SET_SUBTLV(asla, EXT_ADM_GRP);
|
||||
} else
|
||||
UNSET_SUBTLV(asla, EXT_ADM_GRP);
|
||||
|
||||
if (IS_PARAM_SET(ifp->link_params, LP_EXTEND_ADM_GRP)) {
|
||||
admin_group_copy(&asla->ext_admin_group,
|
||||
&ifp->link_params->ext_admin_grp);
|
||||
SET_SUBTLV(asla, EXT_EXTEND_ADM_GRP);
|
||||
} else
|
||||
UNSET_SUBTLV(asla, EXT_EXTEND_ADM_GRP);
|
||||
|
||||
/* Send admin-group zero for better compatibility
|
||||
* https://www.rfc-editor.org/rfc/rfc7308#section-2.3.2
|
||||
*/
|
||||
if (circuit->area->admin_group_send_zero &&
|
||||
!IS_SUBTLV(asla, EXT_ADM_GRP) &&
|
||||
!IS_SUBTLV(asla, EXT_EXTEND_ADM_GRP)) {
|
||||
asla->admin_group = 0;
|
||||
SET_SUBTLV(asla, EXT_ADM_GRP);
|
||||
admin_group_clear(&asla->ext_admin_group);
|
||||
admin_group_allow_explicit_zero(&asla->ext_admin_group);
|
||||
SET_SUBTLV(asla, EXT_EXTEND_ADM_GRP);
|
||||
}
|
||||
|
||||
if (IS_PARAM_SET(ifp->link_params, LP_TE_METRIC)) {
|
||||
asla->te_metric = ifp->link_params->te_metric;
|
||||
SET_SUBTLV(asla, EXT_TE_METRIC);
|
||||
} else
|
||||
UNSET_SUBTLV(asla, EXT_TE_METRIC);
|
||||
|
||||
if (IS_PARAM_SET(ifp->link_params, LP_DELAY)) {
|
||||
asla->delay = ifp->link_params->av_delay;
|
||||
SET_SUBTLV(asla, EXT_DELAY);
|
||||
} else
|
||||
UNSET_SUBTLV(asla, EXT_DELAY);
|
||||
|
||||
if (IS_PARAM_SET(ifp->link_params, LP_MM_DELAY)) {
|
||||
asla->min_delay = ifp->link_params->min_delay;
|
||||
asla->max_delay = ifp->link_params->max_delay;
|
||||
SET_SUBTLV(asla, EXT_MM_DELAY);
|
||||
} else {
|
||||
UNSET_SUBTLV(asla, EXT_MM_DELAY);
|
||||
}
|
||||
|
||||
if (asla->standard_apps == ISIS_SABM_FLAG_X)
|
||||
/* Flex-Algo ASLA does not need the following TE
|
||||
* sub-TLVs
|
||||
*/
|
||||
continue;
|
||||
|
||||
if (IS_PARAM_SET(ifp->link_params, LP_MAX_BW)) {
|
||||
asla->max_bw = ifp->link_params->max_bw;
|
||||
SET_SUBTLV(asla, EXT_MAX_BW);
|
||||
} else
|
||||
UNSET_SUBTLV(asla, EXT_MAX_BW);
|
||||
|
||||
if (IS_PARAM_SET(ifp->link_params, LP_MAX_RSV_BW)) {
|
||||
asla->max_rsv_bw = ifp->link_params->max_rsv_bw;
|
||||
SET_SUBTLV(asla, EXT_MAX_RSV_BW);
|
||||
} else
|
||||
UNSET_SUBTLV(asla, EXT_MAX_RSV_BW);
|
||||
|
||||
if (IS_PARAM_SET(ifp->link_params, LP_UNRSV_BW)) {
|
||||
for (i = 0; i < MAX_CLASS_TYPE; i++)
|
||||
asla->unrsv_bw[i] =
|
||||
ifp->link_params->unrsv_bw[i];
|
||||
SET_SUBTLV(asla, EXT_UNRSV_BW);
|
||||
} else
|
||||
UNSET_SUBTLV(asla, EXT_UNRSV_BW);
|
||||
|
||||
if (IS_PARAM_SET(ifp->link_params, LP_DELAY_VAR)) {
|
||||
asla->delay_var = ifp->link_params->delay_var;
|
||||
SET_SUBTLV(asla, EXT_DELAY_VAR);
|
||||
} else
|
||||
UNSET_SUBTLV(asla, EXT_DELAY_VAR);
|
||||
|
||||
if (IS_PARAM_SET(ifp->link_params, LP_PKT_LOSS)) {
|
||||
asla->pkt_loss = ifp->link_params->pkt_loss;
|
||||
SET_SUBTLV(asla, EXT_PKT_LOSS);
|
||||
} else
|
||||
UNSET_SUBTLV(asla, EXT_PKT_LOSS);
|
||||
|
||||
if (IS_PARAM_SET(ifp->link_params, LP_RES_BW)) {
|
||||
asla->res_bw = ifp->link_params->res_bw;
|
||||
SET_SUBTLV(asla, EXT_RES_BW);
|
||||
} else
|
||||
UNSET_SUBTLV(asla, EXT_RES_BW);
|
||||
|
||||
if (IS_PARAM_SET(ifp->link_params, LP_AVA_BW)) {
|
||||
asla->ava_bw = ifp->link_params->ava_bw;
|
||||
SET_SUBTLV(asla, EXT_AVA_BW);
|
||||
} else
|
||||
UNSET_SUBTLV(asla, EXT_AVA_BW);
|
||||
|
||||
if (IS_PARAM_SET(ifp->link_params, LP_USE_BW)) {
|
||||
asla->use_bw = ifp->link_params->use_bw;
|
||||
SET_SUBTLV(asla, EXT_USE_BW);
|
||||
} else
|
||||
UNSET_SUBTLV(asla, EXT_USE_BW);
|
||||
}
|
||||
|
||||
|
||||
for (ALL_LIST_ELEMENTS(ext->aslas, node, nnode, asla)) {
|
||||
if (!asla->legacy && NO_SUBTLV(asla) &&
|
||||
admin_group_nb_words(&asla->ext_admin_group) == 0)
|
||||
/* remove ASLA without info from the list of ASLAs to
|
||||
* not send void ASLA
|
||||
*/
|
||||
isis_tlvs_del_asla_flex_algo(ext, asla);
|
||||
}
|
||||
}
|
||||
|
||||
/* Main initialization / update function of the MPLS TE Circuit context */
|
||||
/* Call when interface TE Link parameters are modified */
|
||||
void isis_link_params_update(struct isis_circuit *circuit,
|
||||
|
@ -210,6 +358,19 @@ void isis_link_params_update(struct isis_circuit *circuit,
|
|||
} else
|
||||
UNSET_SUBTLV(ext, EXT_EXTEND_ADM_GRP);
|
||||
|
||||
/* Send admin-group zero for better compatibility
|
||||
* https://www.rfc-editor.org/rfc/rfc7308#section-2.3.2
|
||||
*/
|
||||
if (circuit->area->admin_group_send_zero &&
|
||||
!IS_SUBTLV(ext, EXT_ADM_GRP) &&
|
||||
!IS_SUBTLV(ext, EXT_EXTEND_ADM_GRP)) {
|
||||
ext->adm_group = 0;
|
||||
SET_SUBTLV(ext, EXT_ADM_GRP);
|
||||
admin_group_clear(&ext->ext_admin_group);
|
||||
admin_group_allow_explicit_zero(&ext->ext_admin_group);
|
||||
SET_SUBTLV(ext, EXT_EXTEND_ADM_GRP);
|
||||
}
|
||||
|
||||
/* If known, register local IPv4 addr from ip_addr list */
|
||||
if (listcount(circuit->ip_addrs) != 0) {
|
||||
addr = (struct prefix_ipv4 *)listgetdata(
|
||||
|
@ -331,6 +492,8 @@ void isis_link_params_update(struct isis_circuit *circuit,
|
|||
ext->status = 0;
|
||||
}
|
||||
|
||||
isis_link_params_update_asla(circuit, ifp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -503,7 +666,12 @@ int isis_mpls_te_update(struct interface *ifp)
|
|||
isis_link_params_update(circuit, ifp);
|
||||
|
||||
/* ... and LSP */
|
||||
if (circuit->area && IS_MPLS_TE(circuit->area->mta))
|
||||
if (circuit->area &&
|
||||
(IS_MPLS_TE(circuit->area->mta)
|
||||
#ifndef FABRICD
|
||||
|| !list_isempty(circuit->area->flex_algos->flex_algos)
|
||||
#endif /* ifndef FABRICD */
|
||||
))
|
||||
lsp_regenerate_schedule(circuit->area, circuit->is_type, 0);
|
||||
|
||||
rc = 0;
|
||||
|
|
|
@ -123,6 +123,7 @@ struct isis_ext_subtlvs *isis_alloc_ext_subtlvs(void)
|
|||
ext = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(struct isis_ext_subtlvs));
|
||||
init_item_list(&ext->adj_sid);
|
||||
init_item_list(&ext->lan_sid);
|
||||
ext->aslas = list_new();
|
||||
|
||||
admin_group_init(&ext->ext_admin_group);
|
||||
|
||||
|
@ -132,6 +133,8 @@ struct isis_ext_subtlvs *isis_alloc_ext_subtlvs(void)
|
|||
void isis_del_ext_subtlvs(struct isis_ext_subtlvs *ext)
|
||||
{
|
||||
struct isis_item *item, *next_item;
|
||||
struct listnode *node, *nnode;
|
||||
struct isis_asla_subtlvs *asla;
|
||||
|
||||
if (!ext)
|
||||
return;
|
||||
|
@ -146,6 +149,11 @@ void isis_del_ext_subtlvs(struct isis_ext_subtlvs *ext)
|
|||
XFREE(MTYPE_ISIS_SUBTLV, item);
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS(ext->aslas, node, nnode, asla))
|
||||
isis_tlvs_del_asla_flex_algo(ext, asla);
|
||||
|
||||
list_delete(&ext->aslas);
|
||||
|
||||
admin_group_term(&ext->ext_admin_group);
|
||||
|
||||
XFREE(MTYPE_ISIS_SUBTLV, ext);
|
||||
|
@ -162,6 +170,8 @@ copy_item_ext_subtlvs(struct isis_ext_subtlvs *exts, uint16_t mtid)
|
|||
struct isis_ext_subtlvs *rv = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*rv));
|
||||
struct isis_adj_sid *adj;
|
||||
struct isis_lan_adj_sid *lan;
|
||||
struct listnode *node, *nnode;
|
||||
struct isis_asla_subtlvs *new_asla, *asla;
|
||||
|
||||
/* Copy the Extended IS main part */
|
||||
memcpy(rv, exts, sizeof(struct isis_ext_subtlvs));
|
||||
|
@ -226,12 +236,133 @@ copy_item_ext_subtlvs(struct isis_ext_subtlvs *exts, uint16_t mtid)
|
|||
SET_SUBTLV(rv, EXT_LAN_ADJ_SID);
|
||||
}
|
||||
|
||||
rv->aslas = list_new();
|
||||
|
||||
for (ALL_LIST_ELEMENTS(exts->aslas, node, nnode, asla)) {
|
||||
new_asla = XCALLOC(MTYPE_ISIS_SUBTLV,
|
||||
sizeof(struct isis_asla_subtlvs));
|
||||
memcpy(new_asla, asla, sizeof(struct isis_asla_subtlvs));
|
||||
|
||||
new_asla->ext_admin_group.bitmap.data = NULL;
|
||||
admin_group_copy(&new_asla->ext_admin_group,
|
||||
&asla->ext_admin_group);
|
||||
|
||||
listnode_add(rv->aslas, new_asla);
|
||||
}
|
||||
|
||||
rv->ext_admin_group.bitmap.data = NULL;
|
||||
admin_group_copy(&rv->ext_admin_group, &exts->ext_admin_group);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void format_item_asla_subtlvs(struct isis_asla_subtlvs *asla,
|
||||
struct sbuf *buf, int indent)
|
||||
{
|
||||
char admin_group_buf[ADMIN_GROUP_PRINT_MAX_SIZE];
|
||||
|
||||
sbuf_push(buf, indent, "Application Specific Link Attributes:\n");
|
||||
sbuf_push(buf, indent + 2,
|
||||
"L flag: %u, SA-Length: %u, UDA-Length: %u\n", asla->legacy,
|
||||
asla->standard_apps_length, asla->user_def_apps_length);
|
||||
sbuf_push(buf, indent + 2, "Standard Applications: 0x%02x",
|
||||
asla->standard_apps);
|
||||
if (asla->standard_apps) {
|
||||
uint8_t bit = asla->standard_apps;
|
||||
if (bit & ISIS_SABM_FLAG_R)
|
||||
sbuf_push(buf, 0, " RSVP-TE");
|
||||
if (bit & ISIS_SABM_FLAG_S)
|
||||
sbuf_push(buf, 0, " SR-Policy");
|
||||
if (bit & ISIS_SABM_FLAG_L)
|
||||
sbuf_push(buf, 0, " Loop-Free-Alternate");
|
||||
if (bit & ISIS_SABM_FLAG_X)
|
||||
sbuf_push(buf, 0, " Flex-Algo");
|
||||
}
|
||||
sbuf_push(buf, 0, "\n");
|
||||
sbuf_push(buf, indent + 2, "User Defined Applications: 0x%02x\n",
|
||||
asla->user_def_apps);
|
||||
|
||||
if (IS_SUBTLV(asla, EXT_ADM_GRP)) {
|
||||
sbuf_push(buf, indent + 2, "Admin Group: 0x%08x\n",
|
||||
asla->admin_group);
|
||||
sbuf_push(buf, indent + 4, "Bit positions: %s\n",
|
||||
admin_group_standard_print(
|
||||
admin_group_buf,
|
||||
indent + 2 + strlen("Admin Group: "),
|
||||
asla->admin_group));
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_EXTEND_ADM_GRP) &&
|
||||
admin_group_nb_words(&asla->ext_admin_group) != 0) {
|
||||
sbuf_push(buf, indent + 2, "Ext Admin Group: %s\n",
|
||||
admin_group_string(
|
||||
admin_group_buf, ADMIN_GROUP_PRINT_MAX_SIZE,
|
||||
indent + 2 + strlen("Ext Admin Group: "),
|
||||
&asla->ext_admin_group));
|
||||
admin_group_print(admin_group_buf,
|
||||
indent + 2 + strlen("Ext Admin Group: "),
|
||||
&asla->ext_admin_group);
|
||||
if (admin_group_buf[0] != '\0' &&
|
||||
(buf->pos + strlen(admin_group_buf) +
|
||||
SBUF_DEFAULT_SIZE / 2) < buf->size)
|
||||
sbuf_push(buf, indent + 4, "Bit positions: %s\n",
|
||||
admin_group_buf);
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_MAX_BW))
|
||||
sbuf_push(buf, indent + 2,
|
||||
"Maximum Bandwidth: %g (Bytes/sec)\n", asla->max_bw);
|
||||
if (IS_SUBTLV(asla, EXT_MAX_RSV_BW))
|
||||
sbuf_push(buf, indent + 2,
|
||||
"Maximum Reservable Bandwidth: %g (Bytes/sec)\n",
|
||||
asla->max_rsv_bw);
|
||||
if (IS_SUBTLV(asla, EXT_UNRSV_BW)) {
|
||||
sbuf_push(buf, indent + 2, "Unreserved Bandwidth:\n");
|
||||
for (int j = 0; j < MAX_CLASS_TYPE; j += 2) {
|
||||
sbuf_push(
|
||||
buf, indent + 2,
|
||||
"[%d]: %g (Bytes/sec),\t[%d]: %g (Bytes/sec)\n",
|
||||
j, asla->unrsv_bw[j], j + 1,
|
||||
asla->unrsv_bw[j + 1]);
|
||||
}
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_TE_METRIC))
|
||||
sbuf_push(buf, indent + 2, "Traffic Engineering Metric: %u\n",
|
||||
asla->te_metric);
|
||||
/* Extended metrics */
|
||||
if (IS_SUBTLV(asla, EXT_DELAY))
|
||||
sbuf_push(buf, indent + 2,
|
||||
"%s Average Link Delay: %u (micro-sec)\n",
|
||||
IS_ANORMAL(asla->delay) ? "Anomalous" : "Normal",
|
||||
asla->delay);
|
||||
if (IS_SUBTLV(asla, EXT_MM_DELAY)) {
|
||||
sbuf_push(buf, indent + 2,
|
||||
"%s Min/Max Link Delay: %u / %u (micro-sec)\n",
|
||||
IS_ANORMAL(asla->min_delay) ? "Anomalous" : "Normal",
|
||||
asla->min_delay & TE_EXT_MASK,
|
||||
asla->max_delay & TE_EXT_MASK);
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_DELAY_VAR)) {
|
||||
sbuf_push(buf, indent + 2, "Delay Variation: %u (micro-sec)\n",
|
||||
asla->delay_var & TE_EXT_MASK);
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_PKT_LOSS))
|
||||
sbuf_push(buf, indent + 2, "%s Link Packet Loss: %g (%%)\n",
|
||||
IS_ANORMAL(asla->pkt_loss) ? "Anomalous" : "Normal",
|
||||
(float)((asla->pkt_loss & TE_EXT_MASK) *
|
||||
LOSS_PRECISION));
|
||||
if (IS_SUBTLV(asla, EXT_RES_BW))
|
||||
sbuf_push(buf, indent + 2,
|
||||
"Unidir. Residual Bandwidth: %g (Bytes/sec)\n",
|
||||
asla->res_bw);
|
||||
if (IS_SUBTLV(asla, EXT_AVA_BW))
|
||||
sbuf_push(buf, indent + 2,
|
||||
"Unidir. Available Bandwidth: %g (Bytes/sec)\n",
|
||||
asla->ava_bw);
|
||||
if (IS_SUBTLV(asla, EXT_USE_BW))
|
||||
sbuf_push(buf, indent + 2,
|
||||
"Unidir. Utilized Bandwidth: %g (Bytes/sec)\n",
|
||||
asla->use_bw);
|
||||
}
|
||||
|
||||
/* mtid parameter is used to manage multi-topology i.e. IPv4 / IPv6 */
|
||||
static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
|
||||
struct sbuf *buf, struct json_object *json,
|
||||
|
@ -240,6 +371,8 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
|
|||
char admin_group_buf[ADMIN_GROUP_PRINT_MAX_SIZE];
|
||||
char aux_buf[255];
|
||||
char cnt_buf[255];
|
||||
struct isis_asla_subtlvs *asla;
|
||||
struct listnode *node;
|
||||
|
||||
/* Standard metrics */
|
||||
if (IS_SUBTLV(exts, EXT_ADM_GRP)) {
|
||||
|
@ -688,6 +821,8 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
|
|||
lan->neighbor_id);
|
||||
}
|
||||
}
|
||||
for (ALL_LIST_ELEMENTS_RO(exts->aslas, node, asla))
|
||||
format_item_asla_subtlvs(asla, buf, indent);
|
||||
}
|
||||
|
||||
static void free_item_ext_subtlvs(struct isis_ext_subtlvs *exts)
|
||||
|
@ -695,10 +830,124 @@ static void free_item_ext_subtlvs(struct isis_ext_subtlvs *exts)
|
|||
isis_del_ext_subtlvs(exts);
|
||||
}
|
||||
|
||||
static int pack_item_ext_subtlv_asla(struct isis_asla_subtlvs *asla,
|
||||
struct stream *s, size_t *min_len)
|
||||
{
|
||||
size_t subtlv_len;
|
||||
size_t subtlv_len_pos;
|
||||
|
||||
/* Sub TLV header */
|
||||
stream_putc(s, ISIS_SUBTLV_ASLA);
|
||||
|
||||
subtlv_len_pos = stream_get_endp(s);
|
||||
stream_putc(s, 0); /* length will be filled later */
|
||||
|
||||
/* SABM Flag/Length */
|
||||
if (asla->legacy)
|
||||
stream_putc(s, ASLA_LEGACY_FLAG | asla->standard_apps_length);
|
||||
else
|
||||
stream_putc(s, asla->standard_apps_length);
|
||||
stream_putc(s, asla->user_def_apps_length); /* UDABM Flag/Length */
|
||||
stream_putc(s, asla->standard_apps);
|
||||
stream_putc(s, asla->user_def_apps);
|
||||
|
||||
/* Administrative Group */
|
||||
if (IS_SUBTLV(asla, EXT_ADM_GRP)) {
|
||||
stream_putc(s, ISIS_SUBTLV_ADMIN_GRP);
|
||||
stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
|
||||
stream_putl(s, asla->admin_group);
|
||||
}
|
||||
|
||||
/* Extended Administrative Group */
|
||||
if (IS_SUBTLV(asla, EXT_EXTEND_ADM_GRP) &&
|
||||
admin_group_nb_words(&asla->ext_admin_group) != 0) {
|
||||
size_t ag_length;
|
||||
size_t ag_length_pos;
|
||||
struct admin_group *ag;
|
||||
|
||||
stream_putc(s, ISIS_SUBTLV_EXT_ADMIN_GRP);
|
||||
ag_length_pos = stream_get_endp(s);
|
||||
stream_putc(s, 0); /* length will be filled later*/
|
||||
|
||||
ag = &asla->ext_admin_group;
|
||||
for (size_t i = 0; i < admin_group_nb_words(ag); i++)
|
||||
stream_putl(s, ag->bitmap.data[i]);
|
||||
|
||||
ag_length = stream_get_endp(s) - ag_length_pos - 1;
|
||||
stream_putc_at(s, ag_length_pos, ag_length);
|
||||
}
|
||||
|
||||
if (IS_SUBTLV(asla, EXT_MAX_BW)) {
|
||||
stream_putc(s, ISIS_SUBTLV_MAX_BW);
|
||||
stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
|
||||
stream_putf(s, asla->max_bw);
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_MAX_RSV_BW)) {
|
||||
stream_putc(s, ISIS_SUBTLV_MAX_RSV_BW);
|
||||
stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
|
||||
stream_putf(s, asla->max_rsv_bw);
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_UNRSV_BW)) {
|
||||
stream_putc(s, ISIS_SUBTLV_UNRSV_BW);
|
||||
stream_putc(s, ISIS_SUBTLV_UNRSV_BW_SIZE);
|
||||
for (int j = 0; j < MAX_CLASS_TYPE; j++)
|
||||
stream_putf(s, asla->unrsv_bw[j]);
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_TE_METRIC)) {
|
||||
stream_putc(s, ISIS_SUBTLV_TE_METRIC);
|
||||
stream_putc(s, ISIS_SUBTLV_TE_METRIC_SIZE);
|
||||
stream_put3(s, asla->te_metric);
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_DELAY)) {
|
||||
stream_putc(s, ISIS_SUBTLV_AV_DELAY);
|
||||
stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
|
||||
stream_putl(s, asla->delay);
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_MM_DELAY)) {
|
||||
stream_putc(s, ISIS_SUBTLV_MM_DELAY);
|
||||
stream_putc(s, ISIS_SUBTLV_MM_DELAY_SIZE);
|
||||
stream_putl(s, asla->min_delay);
|
||||
stream_putl(s, asla->max_delay);
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_DELAY_VAR)) {
|
||||
stream_putc(s, ISIS_SUBTLV_DELAY_VAR);
|
||||
stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
|
||||
stream_putl(s, asla->delay_var);
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_PKT_LOSS)) {
|
||||
stream_putc(s, ISIS_SUBTLV_PKT_LOSS);
|
||||
stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
|
||||
stream_putl(s, asla->pkt_loss);
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_RES_BW)) {
|
||||
stream_putc(s, ISIS_SUBTLV_RES_BW);
|
||||
stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
|
||||
stream_putf(s, asla->res_bw);
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_AVA_BW)) {
|
||||
stream_putc(s, ISIS_SUBTLV_AVA_BW);
|
||||
stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
|
||||
stream_putf(s, asla->ava_bw);
|
||||
}
|
||||
if (IS_SUBTLV(asla, EXT_USE_BW)) {
|
||||
stream_putc(s, ISIS_SUBTLV_USE_BW);
|
||||
stream_putc(s, ISIS_SUBTLV_DEF_SIZE);
|
||||
stream_putf(s, asla->use_bw);
|
||||
}
|
||||
|
||||
subtlv_len = stream_get_endp(s) - subtlv_len_pos - 1;
|
||||
stream_putc_at(s, subtlv_len_pos, subtlv_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pack_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
|
||||
struct stream *s, size_t *min_len)
|
||||
{
|
||||
struct isis_asla_subtlvs *asla;
|
||||
struct listnode *node;
|
||||
uint8_t size;
|
||||
int ret;
|
||||
|
||||
if (STREAM_WRITEABLE(s) < ISIS_SUBTLV_MAX_SIZE) {
|
||||
*min_len = ISIS_SUBTLV_MAX_SIZE;
|
||||
|
@ -862,6 +1111,219 @@ static int pack_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
|
|||
}
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(exts->aslas, node, asla)) {
|
||||
ret = pack_item_ext_subtlv_asla(asla, s, min_len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unpack_item_ext_subtlv_asla(uint16_t mtid, uint8_t subtlv_len,
|
||||
struct stream *s, struct sbuf *log,
|
||||
int indent,
|
||||
struct isis_ext_subtlvs *exts)
|
||||
{
|
||||
/* Standard App Identifier Bit Flags/Length */
|
||||
uint8_t sabm_flag_len;
|
||||
/* User-defined App Identifier Bit Flags/Length */
|
||||
uint8_t uabm_flag_len;
|
||||
uint8_t sabm[ASLA_APP_IDENTIFIER_BIT_LENGTH] = {0};
|
||||
uint8_t uabm[ASLA_APP_IDENTIFIER_BIT_LENGTH] = {0};
|
||||
uint8_t readable;
|
||||
uint8_t subsubtlv_type;
|
||||
uint8_t subsubtlv_len;
|
||||
size_t nb_groups;
|
||||
struct isis_asla_subtlvs *asla;
|
||||
|
||||
if (subtlv_len < ISIS_SUBSUBTLV_HDR_SIZE) {
|
||||
TLV_SIZE_MISMATCH(log, indent, "ASLA");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
asla = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(*asla));
|
||||
|
||||
admin_group_init(&asla->ext_admin_group);
|
||||
|
||||
|
||||
sabm_flag_len = stream_getc(s);
|
||||
uabm_flag_len = stream_getc(s);
|
||||
asla->legacy = CHECK_FLAG(sabm_flag_len, ASLA_LEGACY_FLAG);
|
||||
asla->standard_apps_length = ASLA_APPS_LENGTH_MASK & sabm_flag_len;
|
||||
asla->user_def_apps_length = ASLA_APPS_LENGTH_MASK & uabm_flag_len;
|
||||
|
||||
for (int i = 0; i < asla->standard_apps_length; i++)
|
||||
sabm[i] = stream_getc(s);
|
||||
for (int i = 0; i < asla->user_def_apps_length; i++)
|
||||
uabm[i] = stream_getc(s);
|
||||
|
||||
asla->standard_apps = sabm[0];
|
||||
asla->user_def_apps = uabm[0];
|
||||
|
||||
readable = subtlv_len - 4;
|
||||
while (readable > 0) {
|
||||
if (readable < ISIS_SUBSUBTLV_HDR_SIZE) {
|
||||
TLV_SIZE_MISMATCH(log, indent, "ASLA Sub TLV");
|
||||
return -1;
|
||||
}
|
||||
|
||||
subsubtlv_type = stream_getc(s);
|
||||
subsubtlv_len = stream_getc(s);
|
||||
readable -= ISIS_SUBSUBTLV_HDR_SIZE;
|
||||
|
||||
|
||||
switch (subsubtlv_type) {
|
||||
case ISIS_SUBTLV_ADMIN_GRP:
|
||||
if (subsubtlv_len != ISIS_SUBTLV_DEF_SIZE) {
|
||||
TLV_SIZE_MISMATCH(log, indent,
|
||||
"ASLA Adm Group");
|
||||
stream_forward_getp(s, subsubtlv_len);
|
||||
} else {
|
||||
asla->admin_group = stream_getl(s);
|
||||
SET_SUBTLV(asla, EXT_ADM_GRP);
|
||||
}
|
||||
break;
|
||||
|
||||
case ISIS_SUBTLV_EXT_ADMIN_GRP:
|
||||
nb_groups = subsubtlv_len / sizeof(uint32_t);
|
||||
for (size_t i = 0; i < nb_groups; i++) {
|
||||
uint32_t val = stream_getl(s);
|
||||
|
||||
admin_group_bulk_set(&asla->ext_admin_group,
|
||||
val, i);
|
||||
}
|
||||
SET_SUBTLV(asla, EXT_EXTEND_ADM_GRP);
|
||||
break;
|
||||
case ISIS_SUBTLV_MAX_BW:
|
||||
if (subsubtlv_len != ISIS_SUBTLV_DEF_SIZE) {
|
||||
TLV_SIZE_MISMATCH(log, indent,
|
||||
"Maximum Bandwidth");
|
||||
stream_forward_getp(s, subsubtlv_len);
|
||||
} else {
|
||||
asla->max_bw = stream_getf(s);
|
||||
SET_SUBTLV(asla, EXT_MAX_BW);
|
||||
}
|
||||
break;
|
||||
case ISIS_SUBTLV_MAX_RSV_BW:
|
||||
if (subsubtlv_len != ISIS_SUBTLV_DEF_SIZE) {
|
||||
TLV_SIZE_MISMATCH(
|
||||
log, indent,
|
||||
"Maximum Reservable Bandwidth");
|
||||
stream_forward_getp(s, subsubtlv_len);
|
||||
} else {
|
||||
asla->max_rsv_bw = stream_getf(s);
|
||||
SET_SUBTLV(asla, EXT_MAX_RSV_BW);
|
||||
}
|
||||
break;
|
||||
case ISIS_SUBTLV_UNRSV_BW:
|
||||
if (subsubtlv_len != ISIS_SUBTLV_UNRSV_BW_SIZE) {
|
||||
TLV_SIZE_MISMATCH(log, indent,
|
||||
"Unreserved Bandwidth");
|
||||
stream_forward_getp(s, subsubtlv_len);
|
||||
} else {
|
||||
for (int i = 0; i < MAX_CLASS_TYPE; i++)
|
||||
asla->unrsv_bw[i] = stream_getf(s);
|
||||
SET_SUBTLV(asla, EXT_UNRSV_BW);
|
||||
}
|
||||
break;
|
||||
case ISIS_SUBTLV_TE_METRIC:
|
||||
if (subsubtlv_len != ISIS_SUBTLV_TE_METRIC_SIZE) {
|
||||
TLV_SIZE_MISMATCH(log, indent,
|
||||
"Traffic Engineering Metric");
|
||||
stream_forward_getp(s, subsubtlv_len);
|
||||
} else {
|
||||
asla->te_metric = stream_get3(s);
|
||||
SET_SUBTLV(asla, EXT_TE_METRIC);
|
||||
}
|
||||
break;
|
||||
/* Extended Metrics as defined in RFC 7810 */
|
||||
case ISIS_SUBTLV_AV_DELAY:
|
||||
if (subsubtlv_len != ISIS_SUBTLV_DEF_SIZE) {
|
||||
TLV_SIZE_MISMATCH(log, indent,
|
||||
"Average Link Delay");
|
||||
stream_forward_getp(s, subsubtlv_len);
|
||||
} else {
|
||||
asla->delay = stream_getl(s);
|
||||
SET_SUBTLV(asla, EXT_DELAY);
|
||||
}
|
||||
break;
|
||||
case ISIS_SUBTLV_MM_DELAY:
|
||||
if (subsubtlv_len != ISIS_SUBTLV_MM_DELAY_SIZE) {
|
||||
TLV_SIZE_MISMATCH(log, indent,
|
||||
"Min/Max Link Delay");
|
||||
stream_forward_getp(s, subsubtlv_len);
|
||||
} else {
|
||||
asla->min_delay = stream_getl(s);
|
||||
asla->max_delay = stream_getl(s);
|
||||
SET_SUBTLV(asla, EXT_MM_DELAY);
|
||||
}
|
||||
break;
|
||||
case ISIS_SUBTLV_DELAY_VAR:
|
||||
if (subsubtlv_len != ISIS_SUBTLV_DEF_SIZE) {
|
||||
TLV_SIZE_MISMATCH(log, indent,
|
||||
"Delay Variation");
|
||||
stream_forward_getp(s, subsubtlv_len);
|
||||
} else {
|
||||
asla->delay_var = stream_getl(s);
|
||||
SET_SUBTLV(asla, EXT_DELAY_VAR);
|
||||
}
|
||||
break;
|
||||
case ISIS_SUBTLV_PKT_LOSS:
|
||||
if (subsubtlv_len != ISIS_SUBTLV_DEF_SIZE) {
|
||||
TLV_SIZE_MISMATCH(log, indent,
|
||||
"Link Packet Loss");
|
||||
stream_forward_getp(s, subsubtlv_len);
|
||||
} else {
|
||||
asla->pkt_loss = stream_getl(s);
|
||||
SET_SUBTLV(asla, EXT_PKT_LOSS);
|
||||
}
|
||||
break;
|
||||
case ISIS_SUBTLV_RES_BW:
|
||||
if (subsubtlv_len != ISIS_SUBTLV_DEF_SIZE) {
|
||||
TLV_SIZE_MISMATCH(
|
||||
log, indent,
|
||||
"Unidirectional Residual Bandwidth");
|
||||
stream_forward_getp(s, subsubtlv_len);
|
||||
} else {
|
||||
asla->res_bw = stream_getf(s);
|
||||
SET_SUBTLV(asla, EXT_RES_BW);
|
||||
}
|
||||
break;
|
||||
case ISIS_SUBTLV_AVA_BW:
|
||||
if (subsubtlv_len != ISIS_SUBTLV_DEF_SIZE) {
|
||||
TLV_SIZE_MISMATCH(
|
||||
log, indent,
|
||||
"Unidirectional Available Bandwidth");
|
||||
stream_forward_getp(s, subsubtlv_len);
|
||||
} else {
|
||||
asla->ava_bw = stream_getf(s);
|
||||
SET_SUBTLV(asla, EXT_AVA_BW);
|
||||
}
|
||||
break;
|
||||
case ISIS_SUBTLV_USE_BW:
|
||||
if (subsubtlv_len != ISIS_SUBTLV_DEF_SIZE) {
|
||||
TLV_SIZE_MISMATCH(
|
||||
log, indent,
|
||||
"Unidirectional Utilized Bandwidth");
|
||||
stream_forward_getp(s, subsubtlv_len);
|
||||
} else {
|
||||
asla->use_bw = stream_getf(s);
|
||||
SET_SUBTLV(asla, EXT_USE_BW);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
zlog_debug("unknown (t,l)=(%u,%u)", subsubtlv_type,
|
||||
subsubtlv_len);
|
||||
stream_forward_getp(s, subsubtlv_len);
|
||||
break;
|
||||
}
|
||||
readable -= subsubtlv_len;
|
||||
}
|
||||
|
||||
listnode_add(exts->aslas, asla);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1209,6 +1671,13 @@ static int unpack_item_ext_subtlvs(uint16_t mtid, uint8_t len, struct stream *s,
|
|||
SET_SUBTLV(exts, EXT_LAN_ADJ_SID);
|
||||
}
|
||||
break;
|
||||
case ISIS_SUBTLV_ASLA:
|
||||
if (unpack_item_ext_subtlv_asla(mtid, subtlv_len, s,
|
||||
log, indent,
|
||||
exts) < 0) {
|
||||
sbuf_push(log, indent, "TLV parse error");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Skip unknown TLV */
|
||||
stream_forward_getp(s, subtlv_len);
|
||||
|
@ -5873,6 +6342,54 @@ void isis_tlvs_del_lan_adj_sid(struct isis_ext_subtlvs *exts,
|
|||
UNSET_SUBTLV(exts, EXT_LAN_ADJ_SID);
|
||||
}
|
||||
|
||||
void isis_tlvs_del_asla_flex_algo(struct isis_ext_subtlvs *ext,
|
||||
struct isis_asla_subtlvs *asla)
|
||||
{
|
||||
admin_group_term(&asla->ext_admin_group);
|
||||
listnode_delete(ext->aslas, asla);
|
||||
XFREE(MTYPE_ISIS_SUBTLV, asla);
|
||||
}
|
||||
|
||||
struct isis_asla_subtlvs *
|
||||
isis_tlvs_find_alloc_asla(struct isis_ext_subtlvs *ext, uint8_t standard_apps)
|
||||
{
|
||||
struct isis_asla_subtlvs *asla;
|
||||
struct listnode *node;
|
||||
|
||||
if (!list_isempty(ext->aslas)) {
|
||||
for (ALL_LIST_ELEMENTS_RO(ext->aslas, node, asla)) {
|
||||
if (CHECK_FLAG(asla->standard_apps, standard_apps))
|
||||
return asla;
|
||||
}
|
||||
}
|
||||
|
||||
asla = XCALLOC(MTYPE_ISIS_SUBTLV, sizeof(struct isis_asla_subtlvs));
|
||||
admin_group_init(&asla->ext_admin_group);
|
||||
SET_FLAG(asla->standard_apps, standard_apps);
|
||||
SET_FLAG(asla->user_def_apps, standard_apps);
|
||||
asla->standard_apps_length = ASLA_APP_IDENTIFIER_BIT_LENGTH;
|
||||
asla->user_def_apps_length = ASLA_APP_IDENTIFIER_BIT_LENGTH;
|
||||
|
||||
listnode_add(ext->aslas, asla);
|
||||
return asla;
|
||||
}
|
||||
|
||||
void isis_tlvs_free_asla(struct isis_ext_subtlvs *ext, uint8_t standard_apps)
|
||||
{
|
||||
struct isis_asla_subtlvs *asla;
|
||||
struct listnode *node;
|
||||
|
||||
if (!ext)
|
||||
return;
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO(ext->aslas, node, asla)) {
|
||||
if (!CHECK_FLAG(asla->standard_apps, standard_apps))
|
||||
continue;
|
||||
isis_tlvs_del_asla_flex_algo(ext, asla);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void isis_tlvs_add_extended_ip_reach(struct isis_tlvs *tlvs,
|
||||
struct prefix_ipv4 *dest, uint32_t metric,
|
||||
bool external,
|
||||
|
|
|
@ -400,6 +400,9 @@ enum isis_tlv_type {
|
|||
ISIS_SUBTLV_AVA_BW = 38,
|
||||
ISIS_SUBTLV_USE_BW = 39,
|
||||
|
||||
/* RFC 8919 */
|
||||
ISIS_SUBTLV_ASLA = 16,
|
||||
|
||||
ISIS_SUBTLV_MAX = 40,
|
||||
};
|
||||
|
||||
|
@ -434,6 +437,8 @@ enum ext_subtlv_size {
|
|||
/* RFC 7308 */
|
||||
ISIS_SUBTLV_EXT_ADMIN_GRP = 14,
|
||||
|
||||
ISIS_SUBSUBTLV_HDR_SIZE = 2,
|
||||
|
||||
ISIS_SUBTLV_MAX_SIZE = 180,
|
||||
};
|
||||
|
||||
|
@ -441,6 +446,8 @@ enum ext_subtlv_size {
|
|||
#define SET_SUBTLV(s, t) ((s->status) |= (t))
|
||||
#define UNSET_SUBTLV(s, t) ((s->status) &= ~(t))
|
||||
#define IS_SUBTLV(s, t) (s->status & t)
|
||||
#define RESET_SUBTLV(s) (s->status = 0)
|
||||
#define NO_SUBTLV(s) (s->status == 0)
|
||||
|
||||
#define EXT_DISABLE 0x000000
|
||||
#define EXT_ADM_GRP 0x000001
|
||||
|
@ -512,6 +519,45 @@ struct isis_ext_subtlvs {
|
|||
/* Segment Routing Adjacency & LAN Adjacency Segment ID */
|
||||
struct isis_item_list adj_sid;
|
||||
struct isis_item_list lan_sid;
|
||||
|
||||
struct list *aslas;
|
||||
};
|
||||
|
||||
/* RFC 8919 */
|
||||
#define ISIS_SABM_FLAG_R 0x80 /* RSVP-TE */
|
||||
#define ISIS_SABM_FLAG_S 0x40 /* Segment Routing Policy */
|
||||
#define ISIS_SABM_FLAG_L 0x20 /* Loop-Free Alternate */
|
||||
#define ISIS_SABM_FLAG_X 0x10 /* Flex-Algorithm - RFC9350 */
|
||||
|
||||
#define ASLA_APP_IDENTIFIER_BIT_LENGTH 1
|
||||
#define ASLA_LEGACY_FLAG 0x80
|
||||
#define ASLA_APPS_LENGTH_MASK 0x7f
|
||||
|
||||
struct isis_asla_subtlvs {
|
||||
uint32_t status;
|
||||
|
||||
/* Application Specific Link Attribute - RFC 8919 */
|
||||
bool legacy; /* L-Flag */
|
||||
uint8_t standard_apps_length;
|
||||
uint8_t user_def_apps_length;
|
||||
uint8_t standard_apps;
|
||||
uint8_t user_def_apps;
|
||||
|
||||
/* Sub-TLV list - rfc8919 section-3.1 */
|
||||
uint32_t admin_group;
|
||||
struct admin_group ext_admin_group; /* Res. Class/Color - RFC 7308 */
|
||||
float max_bw; /* Maximum Bandwidth - RFC 5305 */
|
||||
float max_rsv_bw; /* Maximum Reservable Bandwidth - RFC 5305 */
|
||||
float unrsv_bw[8]; /* Unreserved Bandwidth - RFC 5305 */
|
||||
uint32_t te_metric; /* Traffic Engineering Metric - RFC 5305 */
|
||||
uint32_t delay; /* Average Link Delay - RFC 8570 */
|
||||
uint32_t min_delay; /* Low Link Delay - RFC 8570 */
|
||||
uint32_t max_delay; /* High Link Delay - RFC 8570 */
|
||||
uint32_t delay_var; /* Link Delay Variation i.e. Jitter - RFC 8570 */
|
||||
uint32_t pkt_loss; /* Unidirectional Link Packet Loss - RFC 8570 */
|
||||
float res_bw; /* Unidirectional Residual Bandwidth - RFC 8570 */
|
||||
float ava_bw; /* Unidirectional Available Bandwidth - RFC 8570 */
|
||||
float use_bw; /* Unidirectional Utilized Bandwidth - RFC 8570 */
|
||||
};
|
||||
|
||||
#define IS_COMPAT_MT_TLV(tlv_type) \
|
||||
|
@ -542,6 +588,12 @@ struct list *isis_fragment_tlvs(struct isis_tlvs *tlvs, size_t size);
|
|||
#define ISIS_MT_AT_MASK 0x4000
|
||||
#endif
|
||||
|
||||
/* RFC 8919 */
|
||||
#define ISIS_SABM_FLAG_R 0x80 /* RSVP-TE */
|
||||
#define ISIS_SABM_FLAG_S 0x40 /* Segment Routing Policy */
|
||||
#define ISIS_SABM_FLAG_L 0x20 /* Loop-Free Alternate */
|
||||
#define ISIS_SABM_FLAG_X 0x10 /* Flex-Algorithm - RFC9350 */
|
||||
|
||||
void isis_tlvs_add_auth(struct isis_tlvs *tlvs, struct isis_passwd *passwd);
|
||||
void isis_tlvs_add_area_addresses(struct isis_tlvs *tlvs,
|
||||
struct list *addresses);
|
||||
|
@ -606,6 +658,12 @@ void isis_tlvs_add_lan_adj_sid(struct isis_ext_subtlvs *exts,
|
|||
void isis_tlvs_del_lan_adj_sid(struct isis_ext_subtlvs *exts,
|
||||
struct isis_lan_adj_sid *lan);
|
||||
|
||||
void isis_tlvs_del_asla_flex_algo(struct isis_ext_subtlvs *ext,
|
||||
struct isis_asla_subtlvs *asla);
|
||||
struct isis_asla_subtlvs *
|
||||
isis_tlvs_find_alloc_asla(struct isis_ext_subtlvs *ext, uint8_t standard_apps);
|
||||
void isis_tlvs_free_asla(struct isis_ext_subtlvs *ext, uint8_t standard_apps);
|
||||
|
||||
void isis_tlvs_add_oldstyle_reach(struct isis_tlvs *tlvs, uint8_t *id,
|
||||
uint8_t metric);
|
||||
void isis_tlvs_add_extended_reach(struct isis_tlvs *tlvs, uint16_t mtid,
|
||||
|
|
Loading…
Reference in a new issue