1 // SPDX-License-Identifier: LGPL-2.1-or-later
3 * This file is part of the PCEPlib, a PCEP protocol library.
5 * Copyright (C) 2020 Volta Networks https://voltanet.io/
7 * Author : Brady Johnson <brady@voltanet.io>
13 * This is the implementation of a High Level PCEP message object TLV API.
25 #include "pcep_msg_tlvs.h"
26 #include "pcep_msg_encoding.h"
27 #include "pcep_utils_memory.h"
29 static struct pcep_object_tlv_header
*
30 pcep_tlv_common_create(enum pcep_object_tlv_types type
, uint16_t size
)
32 struct pcep_object_tlv_header
*tlv
=
33 pceplib_malloc(PCEPLIB_MESSAGES
, size
);
44 struct pcep_object_tlv_stateful_pce_capability
*
45 pcep_tlv_create_stateful_pce_capability(
46 bool flag_u_lsp_update_capability
, bool flag_s_include_db_version
,
47 bool flag_i_lsp_instantiation_capability
, bool flag_t_triggered_resync
,
48 bool flag_d_delta_lsp_sync
, bool flag_f_triggered_initial_sync
)
50 struct pcep_object_tlv_stateful_pce_capability
*tlv
=
51 (struct pcep_object_tlv_stateful_pce_capability
*)
52 pcep_tlv_common_create(
53 PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY
,
55 pcep_object_tlv_stateful_pce_capability
));
56 tlv
->flag_u_lsp_update_capability
= flag_u_lsp_update_capability
;
57 tlv
->flag_s_include_db_version
= flag_s_include_db_version
;
58 tlv
->flag_i_lsp_instantiation_capability
=
59 flag_i_lsp_instantiation_capability
;
60 tlv
->flag_t_triggered_resync
= flag_t_triggered_resync
;
61 tlv
->flag_d_delta_lsp_sync
= flag_d_delta_lsp_sync
;
62 tlv
->flag_f_triggered_initial_sync
= flag_f_triggered_initial_sync
;
67 struct pcep_object_tlv_lsp_db_version
*
68 pcep_tlv_create_lsp_db_version(uint64_t lsp_db_version
)
70 struct pcep_object_tlv_lsp_db_version
*tlv
=
71 (struct pcep_object_tlv_lsp_db_version
*)pcep_tlv_common_create(
72 PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION
,
73 sizeof(struct pcep_object_tlv_lsp_db_version
));
74 tlv
->lsp_db_version
= lsp_db_version
;
79 struct pcep_object_tlv_speaker_entity_identifier
*
80 pcep_tlv_create_speaker_entity_id(double_linked_list
*speaker_entity_id_list
)
82 if (speaker_entity_id_list
== NULL
) {
86 if (speaker_entity_id_list
->num_entries
== 0) {
90 struct pcep_object_tlv_speaker_entity_identifier
*tlv
=
91 (struct pcep_object_tlv_speaker_entity_identifier
*)
92 pcep_tlv_common_create(
93 PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID
,
95 pcep_object_tlv_speaker_entity_identifier
));
96 tlv
->speaker_entity_id_list
= speaker_entity_id_list
;
101 struct pcep_object_tlv_path_setup_type
*
102 pcep_tlv_create_path_setup_type(uint8_t pst
)
104 struct pcep_object_tlv_path_setup_type
*tlv
=
105 (struct pcep_object_tlv_path_setup_type
*)
106 pcep_tlv_common_create(
107 PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE
,
108 sizeof(struct pcep_object_tlv_path_setup_type
));
109 tlv
->path_setup_type
= pst
;
114 struct pcep_object_tlv_path_setup_type_capability
*
115 pcep_tlv_create_path_setup_type_capability(double_linked_list
*pst_list
,
116 double_linked_list
*sub_tlv_list
)
118 if (pst_list
== NULL
) {
122 if (pst_list
->num_entries
== 0) {
126 struct pcep_object_tlv_path_setup_type_capability
*tlv
=
127 (struct pcep_object_tlv_path_setup_type_capability
*)
128 pcep_tlv_common_create(
129 PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY
,
131 pcep_object_tlv_path_setup_type_capability
));
133 tlv
->pst_list
= pst_list
;
134 tlv
->sub_tlv_list
= sub_tlv_list
;
139 struct pcep_object_tlv_sr_pce_capability
*
140 pcep_tlv_create_sr_pce_capability(bool flag_n
, bool flag_x
,
141 uint8_t max_sid_depth
)
143 struct pcep_object_tlv_sr_pce_capability
*tlv
=
144 (struct pcep_object_tlv_sr_pce_capability
*)
145 pcep_tlv_common_create(
146 PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY
,
148 pcep_object_tlv_sr_pce_capability
));
149 tlv
->flag_n
= flag_n
;
150 tlv
->flag_x
= flag_x
;
151 tlv
->max_sid_depth
= max_sid_depth
;
156 struct pcep_object_tlv_of_list
*
157 pcep_tlv_create_of_list(double_linked_list
*of_list
)
159 if (of_list
== NULL
) {
163 struct pcep_object_tlv_of_list
*tlv
=
164 (struct pcep_object_tlv_of_list
*)pcep_tlv_common_create(
165 PCEP_OBJ_TLV_TYPE_OBJECTIVE_FUNCTION_LIST
,
166 sizeof(struct pcep_object_tlv_of_list
));
168 tlv
->of_list
= of_list
;
177 struct pcep_object_tlv_ipv4_lsp_identifier
*
178 pcep_tlv_create_ipv4_lsp_identifiers(struct in_addr
*ipv4_tunnel_sender
,
179 struct in_addr
*ipv4_tunnel_endpoint
,
180 uint16_t lsp_id
, uint16_t tunnel_id
,
181 struct in_addr
*extended_tunnel_id
)
183 if (ipv4_tunnel_sender
== NULL
|| ipv4_tunnel_endpoint
== NULL
) {
187 struct pcep_object_tlv_ipv4_lsp_identifier
*tlv
=
188 (struct pcep_object_tlv_ipv4_lsp_identifier
*)
189 pcep_tlv_common_create(
190 PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS
,
192 pcep_object_tlv_ipv4_lsp_identifier
));
193 tlv
->ipv4_tunnel_sender
.s_addr
= ipv4_tunnel_sender
->s_addr
;
194 tlv
->ipv4_tunnel_endpoint
.s_addr
= ipv4_tunnel_endpoint
->s_addr
;
195 tlv
->lsp_id
= lsp_id
;
196 tlv
->tunnel_id
= tunnel_id
;
197 tlv
->extended_tunnel_id
.s_addr
=
198 (extended_tunnel_id
== NULL
? INADDR_ANY
199 : extended_tunnel_id
->s_addr
);
204 struct pcep_object_tlv_ipv6_lsp_identifier
*
205 pcep_tlv_create_ipv6_lsp_identifiers(struct in6_addr
*ipv6_tunnel_sender
,
206 struct in6_addr
*ipv6_tunnel_endpoint
,
207 uint16_t lsp_id
, uint16_t tunnel_id
,
208 struct in6_addr
*extended_tunnel_id
)
210 if (ipv6_tunnel_sender
== NULL
|| ipv6_tunnel_endpoint
== NULL
) {
214 struct pcep_object_tlv_ipv6_lsp_identifier
*tlv
=
215 (struct pcep_object_tlv_ipv6_lsp_identifier
*)
216 pcep_tlv_common_create(
217 PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS
,
219 pcep_object_tlv_ipv6_lsp_identifier
));
221 memcpy(&tlv
->ipv6_tunnel_sender
, ipv6_tunnel_sender
,
222 sizeof(struct in6_addr
));
224 tlv
->tunnel_id
= tunnel_id
;
225 tlv
->lsp_id
= lsp_id
;
227 memcpy(&tlv
->extended_tunnel_id
, extended_tunnel_id
,
228 sizeof(struct in6_addr
));
230 memcpy(&tlv
->ipv6_tunnel_endpoint
, ipv6_tunnel_endpoint
,
231 sizeof(struct in6_addr
));
236 struct pcep_object_tlv_symbolic_path_name
*
237 pcep_tlv_create_symbolic_path_name(const char *symbolic_path_name
,
238 uint16_t symbolic_path_name_length
)
240 /* symbolic_path_name_length should NOT include the null terminator and
242 if (symbolic_path_name
== NULL
|| symbolic_path_name_length
== 0) {
246 struct pcep_object_tlv_symbolic_path_name
*tlv
=
247 (struct pcep_object_tlv_symbolic_path_name
*)
248 pcep_tlv_common_create(
249 PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME
,
251 pcep_object_tlv_symbolic_path_name
));
253 uint16_t length
= (symbolic_path_name_length
> MAX_SYMBOLIC_PATH_NAME
)
254 ? MAX_SYMBOLIC_PATH_NAME
255 : symbolic_path_name_length
;
256 memcpy(tlv
->symbolic_path_name
, symbolic_path_name
, length
);
257 tlv
->symbolic_path_name_length
= length
;
262 struct pcep_object_tlv_lsp_error_code
*
263 pcep_tlv_create_lsp_error_code(enum pcep_tlv_lsp_error_codes lsp_error_code
)
265 struct pcep_object_tlv_lsp_error_code
*tlv
=
266 (struct pcep_object_tlv_lsp_error_code
*)pcep_tlv_common_create(
267 PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE
,
268 sizeof(struct pcep_object_tlv_lsp_error_code
));
269 tlv
->lsp_error_code
= lsp_error_code
;
274 struct pcep_object_tlv_rsvp_error_spec
*
275 pcep_tlv_create_rsvp_ipv4_error_spec(struct in_addr
*error_node_ip
,
276 uint8_t error_code
, uint16_t error_value
)
278 if (error_node_ip
== NULL
) {
282 struct pcep_object_tlv_rsvp_error_spec
*tlv
=
283 (struct pcep_object_tlv_rsvp_error_spec
*)
284 pcep_tlv_common_create(
285 PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC
,
286 sizeof(struct pcep_object_tlv_rsvp_error_spec
));
288 tlv
->c_type
= RSVP_ERROR_SPEC_IPV4_CTYPE
;
289 tlv
->class_num
= RSVP_ERROR_SPEC_CLASS_NUM
;
290 tlv
->error_code
= error_code
;
291 tlv
->error_value
= error_value
;
292 tlv
->error_spec_ip
.ipv4_error_node_address
.s_addr
=
293 error_node_ip
->s_addr
;
298 struct pcep_object_tlv_rsvp_error_spec
*
299 pcep_tlv_create_rsvp_ipv6_error_spec(struct in6_addr
*error_node_ip
,
300 uint8_t error_code
, uint16_t error_value
)
302 if (error_node_ip
== NULL
) {
306 struct pcep_object_tlv_rsvp_error_spec
*tlv
=
307 (struct pcep_object_tlv_rsvp_error_spec
*)
308 pcep_tlv_common_create(
309 PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC
,
310 sizeof(struct pcep_object_tlv_rsvp_error_spec
));
312 tlv
->c_type
= RSVP_ERROR_SPEC_IPV6_CTYPE
;
313 tlv
->class_num
= RSVP_ERROR_SPEC_CLASS_NUM
;
314 tlv
->error_code
= error_code
;
315 tlv
->error_value
= error_value
;
316 memcpy(&tlv
->error_spec_ip
, error_node_ip
, sizeof(struct in6_addr
));
321 struct pcep_object_tlv_nopath_vector
*
322 pcep_tlv_create_nopath_vector(uint32_t error_code
)
324 struct pcep_object_tlv_nopath_vector
*tlv
=
325 (struct pcep_object_tlv_nopath_vector
*)pcep_tlv_common_create(
326 PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR
,
327 sizeof(struct pcep_object_tlv_nopath_vector
));
329 tlv
->error_code
= error_code
;
334 struct pcep_object_tlv_vendor_info
*
335 pcep_tlv_create_vendor_info(uint32_t enterprise_number
,
336 uint32_t enterprise_specific_info
)
338 struct pcep_object_tlv_vendor_info
*tlv
=
339 (struct pcep_object_tlv_vendor_info
*)pcep_tlv_common_create(
340 PCEP_OBJ_TLV_TYPE_VENDOR_INFO
,
341 sizeof(struct pcep_object_tlv_vendor_info
));
343 tlv
->enterprise_number
= enterprise_number
;
344 tlv
->enterprise_specific_info
= enterprise_specific_info
;
350 * SRPAG (SR Association Group) TLVs
353 struct pcep_object_tlv_srpag_pol_id
*
354 pcep_tlv_create_srpag_pol_id_ipv4(uint32_t color
, struct in_addr
*ipv4
)
356 struct pcep_object_tlv_srpag_pol_id
*tlv
=
357 (struct pcep_object_tlv_srpag_pol_id
*)pcep_tlv_common_create(
358 PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID
,
359 sizeof(struct pcep_object_tlv_srpag_pol_id
));
362 memcpy(&tlv
->end_point
.ipv4
.s_addr
, ipv4
, sizeof(struct in_addr
));
367 struct pcep_object_tlv_srpag_pol_id
*
368 pcep_tlv_create_srpag_pol_id_ipv6(uint32_t color
, struct in6_addr
*ipv6
)
370 struct pcep_object_tlv_srpag_pol_id
*tlv
=
371 (struct pcep_object_tlv_srpag_pol_id
*)pcep_tlv_common_create(
372 PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID
,
373 sizeof(struct pcep_object_tlv_srpag_pol_id
));
375 tlv
->is_ipv4
= false;
376 memcpy(&tlv
->end_point
.ipv6
, ipv6
, sizeof(struct in6_addr
));
382 struct pcep_object_tlv_srpag_pol_name
*
383 pcep_tlv_create_srpag_pol_name(const char *pol_name
, uint16_t pol_name_length
)
385 if (pol_name
== NULL
) {
388 struct pcep_object_tlv_srpag_pol_name
*tlv
=
389 (struct pcep_object_tlv_srpag_pol_name
*)pcep_tlv_common_create(
390 PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME
,
391 sizeof(struct pcep_object_tlv_srpag_pol_name
));
393 (normalize_pcep_tlv_length(pol_name_length
) > MAX_POLICY_NAME
)
396 memcpy(tlv
->name
, pol_name
, length
);
397 tlv
->name_length
= length
;
401 struct pcep_object_tlv_srpag_cp_id
*
402 pcep_tlv_create_srpag_cp_id(uint8_t proto_origin
, uint32_t asn
,
403 struct in6_addr
*in6_addr_with_mapped_ipv4
,
404 uint32_t discriminator
)
406 if (!in6_addr_with_mapped_ipv4
) {
410 struct pcep_object_tlv_srpag_cp_id
*tlv
=
411 (struct pcep_object_tlv_srpag_cp_id
*)pcep_tlv_common_create(
412 PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID
,
413 sizeof(struct pcep_object_tlv_srpag_cp_id
));
414 tlv
->proto
= proto_origin
;
416 memcpy(&(tlv
->orig_addres
), in6_addr_with_mapped_ipv4
,
417 sizeof(*in6_addr_with_mapped_ipv4
));
418 tlv
->discriminator
= discriminator
;
422 struct pcep_object_tlv_srpag_cp_pref
*
423 pcep_tlv_create_srpag_cp_pref(uint32_t pref
)
426 struct pcep_object_tlv_srpag_cp_pref
*tlv
=
427 (struct pcep_object_tlv_srpag_cp_pref
*)pcep_tlv_common_create(
428 PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE
,
429 sizeof(struct pcep_object_tlv_srpag_cp_pref
));
430 tlv
->preference
= pref
;
435 struct pcep_object_tlv_arbitrary
*
436 pcep_tlv_create_tlv_arbitrary(const char *data
, uint16_t data_length
,
439 if (data
== NULL
|| data_length
== 0) {
443 struct pcep_object_tlv_arbitrary
*tlv
=
444 (struct pcep_object_tlv_arbitrary
*)pcep_tlv_common_create(
445 PCEP_OBJ_TLV_TYPE_ARBITRARY
,
446 sizeof(struct pcep_object_tlv_arbitrary
));
448 uint16_t length
= (data_length
> MAX_ARBITRARY_SIZE
)
451 memcpy(tlv
->data
, data
, length
);
452 tlv
->data_length
= length
;
453 tlv
->arbitraty_type
= tlv_id
;