]>
Commit | Line | Data |
---|---|---|
74971473 JG |
1 | /* |
2 | * This file is part of the PCEPlib, a PCEP protocol library. | |
3 | * | |
4 | * Copyright (C) 2020 Volta Networks https://voltanet.io/ | |
5 | * | |
6 | * This library is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU Lesser General Public | |
8 | * License as published by the Free Software Foundation; either | |
9 | * version 2 of the License, or (at your option) any later version. | |
10 | * | |
11 | * This library is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * Lesser General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU Lesser General Public License | |
17 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | |
18 | * | |
19 | * Author : Brady Johnson <brady@voltanet.io> | |
20 | * | |
21 | */ | |
22 | ||
23 | ||
24 | /* | |
25 | * This is the implementation of a High Level PCEP message object TLV API. | |
26 | */ | |
27 | ||
1f8031f7 DL |
28 | #ifdef HAVE_CONFIG_H |
29 | #include "config.h" | |
30 | #endif | |
31 | ||
74971473 JG |
32 | #include <stdbool.h> |
33 | #include <stdint.h> | |
34 | #include <string.h> | |
35 | #include <unistd.h> | |
36 | ||
37 | #include "pcep_msg_tlvs.h" | |
38 | #include "pcep_msg_encoding.h" | |
39 | #include "pcep_utils_memory.h" | |
40 | ||
41 | static struct pcep_object_tlv_header * | |
42 | pcep_tlv_common_create(enum pcep_object_tlv_types type, uint16_t size) | |
43 | { | |
44 | struct pcep_object_tlv_header *tlv = | |
45 | pceplib_malloc(PCEPLIB_MESSAGES, size); | |
46 | memset(tlv, 0, size); | |
47 | tlv->type = type; | |
48 | ||
49 | return tlv; | |
50 | } | |
51 | ||
52 | /* | |
53 | * Open Object TLVs | |
54 | */ | |
55 | ||
56 | struct pcep_object_tlv_stateful_pce_capability * | |
57 | pcep_tlv_create_stateful_pce_capability( | |
58 | bool flag_u_lsp_update_capability, bool flag_s_include_db_version, | |
59 | bool flag_i_lsp_instantiation_capability, bool flag_t_triggered_resync, | |
60 | bool flag_d_delta_lsp_sync, bool flag_f_triggered_initial_sync) | |
61 | { | |
62 | struct pcep_object_tlv_stateful_pce_capability *tlv = | |
63 | (struct pcep_object_tlv_stateful_pce_capability *) | |
64 | pcep_tlv_common_create( | |
65 | PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY, | |
66 | sizeof(struct | |
67 | pcep_object_tlv_stateful_pce_capability)); | |
68 | tlv->flag_u_lsp_update_capability = flag_u_lsp_update_capability; | |
69 | tlv->flag_s_include_db_version = flag_s_include_db_version; | |
70 | tlv->flag_i_lsp_instantiation_capability = | |
71 | flag_i_lsp_instantiation_capability; | |
72 | tlv->flag_t_triggered_resync = flag_t_triggered_resync; | |
73 | tlv->flag_d_delta_lsp_sync = flag_d_delta_lsp_sync; | |
74 | tlv->flag_f_triggered_initial_sync = flag_f_triggered_initial_sync; | |
75 | ||
76 | return tlv; | |
77 | } | |
78 | ||
79 | struct pcep_object_tlv_lsp_db_version * | |
80 | pcep_tlv_create_lsp_db_version(uint64_t lsp_db_version) | |
81 | { | |
82 | struct pcep_object_tlv_lsp_db_version *tlv = | |
83 | (struct pcep_object_tlv_lsp_db_version *)pcep_tlv_common_create( | |
84 | PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION, | |
85 | sizeof(struct pcep_object_tlv_lsp_db_version)); | |
86 | tlv->lsp_db_version = lsp_db_version; | |
87 | ||
88 | return tlv; | |
89 | } | |
90 | ||
91 | struct pcep_object_tlv_speaker_entity_identifier * | |
92 | pcep_tlv_create_speaker_entity_id(double_linked_list *speaker_entity_id_list) | |
93 | { | |
94 | if (speaker_entity_id_list == NULL) { | |
95 | return NULL; | |
96 | } | |
97 | ||
98 | if (speaker_entity_id_list->num_entries == 0) { | |
99 | return NULL; | |
100 | } | |
101 | ||
102 | struct pcep_object_tlv_speaker_entity_identifier *tlv = | |
103 | (struct pcep_object_tlv_speaker_entity_identifier *) | |
104 | pcep_tlv_common_create( | |
105 | PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID, | |
106 | sizeof(struct | |
107 | pcep_object_tlv_speaker_entity_identifier)); | |
108 | tlv->speaker_entity_id_list = speaker_entity_id_list; | |
109 | ||
110 | return tlv; | |
111 | } | |
112 | ||
113 | struct pcep_object_tlv_path_setup_type * | |
114 | pcep_tlv_create_path_setup_type(uint8_t pst) | |
115 | { | |
116 | struct pcep_object_tlv_path_setup_type *tlv = | |
117 | (struct pcep_object_tlv_path_setup_type *) | |
118 | pcep_tlv_common_create( | |
119 | PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE, | |
120 | sizeof(struct pcep_object_tlv_path_setup_type)); | |
121 | tlv->path_setup_type = pst; | |
122 | ||
123 | return tlv; | |
124 | } | |
125 | ||
126 | struct pcep_object_tlv_path_setup_type_capability * | |
127 | pcep_tlv_create_path_setup_type_capability(double_linked_list *pst_list, | |
128 | double_linked_list *sub_tlv_list) | |
129 | { | |
130 | if (pst_list == NULL) { | |
131 | return NULL; | |
132 | } | |
133 | ||
134 | if (pst_list->num_entries == 0) { | |
135 | return NULL; | |
136 | } | |
137 | ||
138 | struct pcep_object_tlv_path_setup_type_capability *tlv = | |
139 | (struct pcep_object_tlv_path_setup_type_capability *) | |
140 | pcep_tlv_common_create( | |
141 | PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY, | |
142 | sizeof(struct | |
143 | pcep_object_tlv_path_setup_type_capability)); | |
144 | ||
145 | tlv->pst_list = pst_list; | |
146 | tlv->sub_tlv_list = sub_tlv_list; | |
147 | ||
148 | return tlv; | |
149 | } | |
150 | ||
151 | struct pcep_object_tlv_sr_pce_capability * | |
152 | pcep_tlv_create_sr_pce_capability(bool flag_n, bool flag_x, | |
153 | uint8_t max_sid_depth) | |
154 | { | |
155 | struct pcep_object_tlv_sr_pce_capability *tlv = | |
156 | (struct pcep_object_tlv_sr_pce_capability *) | |
157 | pcep_tlv_common_create( | |
158 | PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY, | |
159 | sizeof(struct | |
160 | pcep_object_tlv_sr_pce_capability)); | |
161 | tlv->flag_n = flag_n; | |
162 | tlv->flag_x = flag_x; | |
163 | tlv->max_sid_depth = max_sid_depth; | |
164 | ||
165 | return tlv; | |
166 | } | |
167 | ||
168 | struct pcep_object_tlv_of_list * | |
169 | pcep_tlv_create_of_list(double_linked_list *of_list) | |
170 | { | |
171 | if (of_list == NULL) { | |
172 | return NULL; | |
173 | } | |
174 | ||
175 | struct pcep_object_tlv_of_list *tlv = | |
176 | (struct pcep_object_tlv_of_list *)pcep_tlv_common_create( | |
177 | PCEP_OBJ_TLV_TYPE_OBJECTIVE_FUNCTION_LIST, | |
178 | sizeof(struct pcep_object_tlv_of_list)); | |
179 | ||
180 | tlv->of_list = of_list; | |
181 | ||
182 | return tlv; | |
183 | } | |
184 | ||
185 | /* | |
186 | * LSP Object TLVs | |
187 | */ | |
188 | ||
189 | struct pcep_object_tlv_ipv4_lsp_identifier * | |
190 | pcep_tlv_create_ipv4_lsp_identifiers(struct in_addr *ipv4_tunnel_sender, | |
191 | struct in_addr *ipv4_tunnel_endpoint, | |
192 | uint16_t lsp_id, uint16_t tunnel_id, | |
193 | struct in_addr *extended_tunnel_id) | |
194 | { | |
195 | if (ipv4_tunnel_sender == NULL || ipv4_tunnel_endpoint == NULL) { | |
196 | return NULL; | |
197 | } | |
198 | ||
199 | struct pcep_object_tlv_ipv4_lsp_identifier *tlv = | |
200 | (struct pcep_object_tlv_ipv4_lsp_identifier *) | |
201 | pcep_tlv_common_create( | |
202 | PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS, | |
203 | sizeof(struct | |
204 | pcep_object_tlv_ipv4_lsp_identifier)); | |
205 | tlv->ipv4_tunnel_sender.s_addr = ipv4_tunnel_sender->s_addr; | |
206 | tlv->ipv4_tunnel_endpoint.s_addr = ipv4_tunnel_endpoint->s_addr; | |
207 | tlv->lsp_id = lsp_id; | |
208 | tlv->tunnel_id = tunnel_id; | |
209 | tlv->extended_tunnel_id.s_addr = | |
210 | (extended_tunnel_id == NULL ? INADDR_ANY | |
211 | : extended_tunnel_id->s_addr); | |
212 | ||
213 | return tlv; | |
214 | } | |
215 | ||
216 | struct pcep_object_tlv_ipv6_lsp_identifier * | |
217 | pcep_tlv_create_ipv6_lsp_identifiers(struct in6_addr *ipv6_tunnel_sender, | |
218 | struct in6_addr *ipv6_tunnel_endpoint, | |
219 | uint16_t lsp_id, uint16_t tunnel_id, | |
220 | struct in6_addr *extended_tunnel_id) | |
221 | { | |
222 | if (ipv6_tunnel_sender == NULL || ipv6_tunnel_endpoint == NULL) { | |
223 | return NULL; | |
224 | } | |
225 | ||
226 | struct pcep_object_tlv_ipv6_lsp_identifier *tlv = | |
227 | (struct pcep_object_tlv_ipv6_lsp_identifier *) | |
228 | pcep_tlv_common_create( | |
229 | PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS, | |
230 | sizeof(struct | |
231 | pcep_object_tlv_ipv6_lsp_identifier)); | |
232 | ||
233 | memcpy(&tlv->ipv6_tunnel_sender, ipv6_tunnel_sender, | |
234 | sizeof(struct in6_addr)); | |
235 | ||
236 | tlv->tunnel_id = tunnel_id; | |
237 | tlv->lsp_id = lsp_id; | |
238 | ||
239 | memcpy(&tlv->extended_tunnel_id, extended_tunnel_id, | |
240 | sizeof(struct in6_addr)); | |
241 | ||
242 | memcpy(&tlv->ipv6_tunnel_endpoint, ipv6_tunnel_endpoint, | |
243 | sizeof(struct in6_addr)); | |
244 | ||
245 | return tlv; | |
246 | } | |
247 | ||
248 | struct pcep_object_tlv_symbolic_path_name * | |
249 | pcep_tlv_create_symbolic_path_name(const char *symbolic_path_name, | |
250 | uint16_t symbolic_path_name_length) | |
251 | { | |
252 | /* symbolic_path_name_length should NOT include the null terminator and | |
253 | * cannot be zero */ | |
254 | if (symbolic_path_name == NULL || symbolic_path_name_length == 0) { | |
255 | return NULL; | |
256 | } | |
257 | ||
258 | struct pcep_object_tlv_symbolic_path_name *tlv = | |
259 | (struct pcep_object_tlv_symbolic_path_name *) | |
260 | pcep_tlv_common_create( | |
261 | PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME, | |
262 | sizeof(struct | |
263 | pcep_object_tlv_symbolic_path_name)); | |
264 | ||
265 | uint16_t length = (symbolic_path_name_length > MAX_SYMBOLIC_PATH_NAME) | |
266 | ? MAX_SYMBOLIC_PATH_NAME | |
267 | : symbolic_path_name_length; | |
268 | memcpy(tlv->symbolic_path_name, symbolic_path_name, length); | |
269 | tlv->symbolic_path_name_length = length; | |
270 | ||
271 | return tlv; | |
272 | } | |
273 | ||
274 | struct pcep_object_tlv_lsp_error_code * | |
275 | pcep_tlv_create_lsp_error_code(enum pcep_tlv_lsp_error_codes lsp_error_code) | |
276 | { | |
277 | struct pcep_object_tlv_lsp_error_code *tlv = | |
278 | (struct pcep_object_tlv_lsp_error_code *)pcep_tlv_common_create( | |
279 | PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE, | |
280 | sizeof(struct pcep_object_tlv_lsp_error_code)); | |
281 | tlv->lsp_error_code = lsp_error_code; | |
282 | ||
283 | return tlv; | |
284 | } | |
285 | ||
286 | struct pcep_object_tlv_rsvp_error_spec * | |
287 | pcep_tlv_create_rsvp_ipv4_error_spec(struct in_addr *error_node_ip, | |
288 | uint8_t error_code, uint16_t error_value) | |
289 | { | |
290 | if (error_node_ip == NULL) { | |
291 | return NULL; | |
292 | } | |
293 | ||
294 | struct pcep_object_tlv_rsvp_error_spec *tlv = | |
295 | (struct pcep_object_tlv_rsvp_error_spec *) | |
296 | pcep_tlv_common_create( | |
297 | PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC, | |
298 | sizeof(struct pcep_object_tlv_rsvp_error_spec)); | |
299 | ||
300 | tlv->c_type = RSVP_ERROR_SPEC_IPV4_CTYPE; | |
301 | tlv->class_num = RSVP_ERROR_SPEC_CLASS_NUM; | |
302 | tlv->error_code = error_code; | |
303 | tlv->error_value = error_value; | |
304 | tlv->error_spec_ip.ipv4_error_node_address.s_addr = | |
305 | error_node_ip->s_addr; | |
306 | ||
307 | return tlv; | |
308 | } | |
309 | ||
310 | struct pcep_object_tlv_rsvp_error_spec * | |
311 | pcep_tlv_create_rsvp_ipv6_error_spec(struct in6_addr *error_node_ip, | |
312 | uint8_t error_code, uint16_t error_value) | |
313 | { | |
314 | if (error_node_ip == NULL) { | |
315 | return NULL; | |
316 | } | |
317 | ||
318 | struct pcep_object_tlv_rsvp_error_spec *tlv = | |
319 | (struct pcep_object_tlv_rsvp_error_spec *) | |
320 | pcep_tlv_common_create( | |
321 | PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC, | |
322 | sizeof(struct pcep_object_tlv_rsvp_error_spec)); | |
323 | ||
324 | tlv->c_type = RSVP_ERROR_SPEC_IPV6_CTYPE; | |
325 | tlv->class_num = RSVP_ERROR_SPEC_CLASS_NUM; | |
326 | tlv->error_code = error_code; | |
327 | tlv->error_value = error_value; | |
328 | memcpy(&tlv->error_spec_ip, error_node_ip, sizeof(struct in6_addr)); | |
329 | ||
330 | return tlv; | |
331 | } | |
332 | ||
333 | struct pcep_object_tlv_nopath_vector * | |
334 | pcep_tlv_create_nopath_vector(uint32_t error_code) | |
335 | { | |
336 | struct pcep_object_tlv_nopath_vector *tlv = | |
337 | (struct pcep_object_tlv_nopath_vector *)pcep_tlv_common_create( | |
338 | PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR, | |
339 | sizeof(struct pcep_object_tlv_nopath_vector)); | |
340 | ||
341 | tlv->error_code = error_code; | |
342 | ||
343 | return tlv; | |
344 | } | |
345 | ||
346 | struct pcep_object_tlv_vendor_info * | |
347 | pcep_tlv_create_vendor_info(uint32_t enterprise_number, | |
348 | uint32_t enterprise_specific_info) | |
349 | { | |
350 | struct pcep_object_tlv_vendor_info *tlv = | |
351 | (struct pcep_object_tlv_vendor_info *)pcep_tlv_common_create( | |
352 | PCEP_OBJ_TLV_TYPE_VENDOR_INFO, | |
353 | sizeof(struct pcep_object_tlv_vendor_info)); | |
354 | ||
355 | tlv->enterprise_number = enterprise_number; | |
356 | tlv->enterprise_specific_info = enterprise_specific_info; | |
357 | ||
358 | return tlv; | |
359 | } | |
360 | ||
361 | /* | |
362 | * SRPAG (SR Association Group) TLVs | |
363 | */ | |
364 | ||
365 | struct pcep_object_tlv_srpag_pol_id * | |
366 | pcep_tlv_create_srpag_pol_id_ipv4(uint32_t color, struct in_addr *ipv4) | |
367 | { | |
368 | struct pcep_object_tlv_srpag_pol_id *tlv = | |
369 | (struct pcep_object_tlv_srpag_pol_id *)pcep_tlv_common_create( | |
370 | PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID, | |
371 | sizeof(struct pcep_object_tlv_srpag_pol_id)); | |
372 | tlv->color = color; | |
373 | tlv->is_ipv4 = true; | |
374 | memcpy(&tlv->end_point.ipv4.s_addr, ipv4, sizeof(struct in_addr)); | |
375 | ||
376 | return tlv; | |
377 | } | |
378 | ||
379 | struct pcep_object_tlv_srpag_pol_id * | |
380 | pcep_tlv_create_srpag_pol_id_ipv6(uint32_t color, struct in6_addr *ipv6) | |
381 | { | |
382 | struct pcep_object_tlv_srpag_pol_id *tlv = | |
383 | (struct pcep_object_tlv_srpag_pol_id *)pcep_tlv_common_create( | |
384 | PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID, | |
385 | sizeof(struct pcep_object_tlv_srpag_pol_id)); | |
386 | tlv->color = color; | |
387 | tlv->is_ipv4 = false; | |
388 | memcpy(&tlv->end_point.ipv6, ipv6, sizeof(struct in6_addr)); | |
389 | ||
390 | return tlv; | |
391 | } | |
392 | ||
393 | ||
394 | struct pcep_object_tlv_srpag_pol_name * | |
395 | pcep_tlv_create_srpag_pol_name(const char *pol_name, uint16_t pol_name_length) | |
396 | { | |
397 | if (pol_name == NULL) { | |
398 | return NULL; | |
399 | } | |
400 | struct pcep_object_tlv_srpag_pol_name *tlv = | |
401 | (struct pcep_object_tlv_srpag_pol_name *)pcep_tlv_common_create( | |
402 | PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME, | |
403 | sizeof(struct pcep_object_tlv_srpag_pol_name)); | |
404 | uint16_t length = | |
405 | (normalize_pcep_tlv_length(pol_name_length) > MAX_POLICY_NAME) | |
406 | ? MAX_POLICY_NAME | |
407 | : pol_name_length; | |
7ed8c4b1 | 408 | memcpy(tlv->name, pol_name, length); |
74971473 JG |
409 | tlv->name_length = length; |
410 | ||
411 | return tlv; | |
412 | } | |
413 | struct pcep_object_tlv_srpag_cp_id * | |
414 | pcep_tlv_create_srpag_cp_id(uint8_t proto_origin, uint32_t asn, | |
415 | struct in6_addr *in6_addr_with_mapped_ipv4, | |
416 | uint32_t discriminator) | |
417 | { | |
418 | if (!in6_addr_with_mapped_ipv4) { | |
419 | return NULL; | |
420 | } | |
421 | ||
422 | struct pcep_object_tlv_srpag_cp_id *tlv = | |
423 | (struct pcep_object_tlv_srpag_cp_id *)pcep_tlv_common_create( | |
424 | PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID, | |
425 | sizeof(struct pcep_object_tlv_srpag_cp_id)); | |
426 | tlv->proto = proto_origin; | |
427 | tlv->orig_asn = asn; | |
428 | memcpy(&(tlv->orig_addres), in6_addr_with_mapped_ipv4, | |
429 | sizeof(*in6_addr_with_mapped_ipv4)); | |
430 | tlv->discriminator = discriminator; | |
431 | ||
432 | return tlv; | |
433 | } | |
434 | struct pcep_object_tlv_srpag_cp_pref * | |
435 | pcep_tlv_create_srpag_cp_pref(uint32_t pref) | |
436 | { | |
437 | ||
438 | struct pcep_object_tlv_srpag_cp_pref *tlv = | |
439 | (struct pcep_object_tlv_srpag_cp_pref *)pcep_tlv_common_create( | |
440 | PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE, | |
441 | sizeof(struct pcep_object_tlv_srpag_cp_pref)); | |
442 | tlv->preference = pref; | |
443 | ||
444 | return tlv; | |
445 | } | |
446 | ||
447 | struct pcep_object_tlv_arbitrary * | |
448 | pcep_tlv_create_tlv_arbitrary(const char *data, uint16_t data_length, | |
449 | int tlv_id) | |
450 | { | |
451 | if (data == NULL || data_length == 0) { | |
452 | return NULL; | |
453 | } | |
454 | ||
455 | struct pcep_object_tlv_arbitrary *tlv = | |
456 | (struct pcep_object_tlv_arbitrary *)pcep_tlv_common_create( | |
457 | PCEP_OBJ_TLV_TYPE_ARBITRARY, | |
458 | sizeof(struct pcep_object_tlv_arbitrary)); | |
459 | ||
460 | uint16_t length = (data_length > MAX_ARBITRARY_SIZE) | |
461 | ? MAX_ARBITRARY_SIZE | |
462 | : data_length; | |
7ed8c4b1 | 463 | memcpy(tlv->data, data, length); |
74971473 JG |
464 | tlv->data_length = length; |
465 | tlv->arbitraty_type = tlv_id; | |
466 | ||
467 | return tlv; | |
468 | } |