]>
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 | * Encoding and decoding for PCEP Object TLVs. | |
26 | */ | |
27 | ||
0490ce41 DL |
28 | #ifdef HAVE_CONFIG_H |
29 | #include "config.h" | |
30 | #endif | |
31 | ||
32 | #ifdef __FreeBSD__ | |
33 | #include <sys/endian.h> | |
34 | #else | |
35 | #include <endian.h> | |
36 | #endif /* __FreeBSD__ */ | |
74971473 JG |
37 | #include <stdlib.h> |
38 | #include <string.h> | |
39 | ||
40 | #include "pcep.h" | |
41 | #include "pcep_msg_encoding.h" | |
42 | #include "pcep_msg_tlvs.h" | |
43 | #include "pcep_utils_logging.h" | |
44 | #include "pcep_utils_memory.h" | |
45 | ||
46 | void write_tlv_header(struct pcep_object_tlv_header *tlv_hdr, | |
47 | uint16_t tlv_length, struct pcep_versioning *versioning, | |
48 | uint8_t *buf); | |
49 | void pcep_decode_tlv_hdr(const uint8_t *tlv_buf, | |
50 | struct pcep_object_tlv_header *tlv_hdr); | |
51 | ||
52 | /* | |
53 | * forward declarations for initialize_tlv_encoders() | |
54 | */ | |
55 | uint16_t pcep_encode_tlv_no_path_vector(struct pcep_object_tlv_header *tlv, | |
56 | struct pcep_versioning *versioning, | |
57 | uint8_t *tlv_body_buf); | |
58 | uint16_t | |
59 | pcep_encode_tlv_stateful_pce_capability(struct pcep_object_tlv_header *tlv, | |
60 | struct pcep_versioning *versioning, | |
61 | uint8_t *tlv_body_buf); | |
62 | uint16_t pcep_encode_tlv_symbolic_path_name(struct pcep_object_tlv_header *tlv, | |
63 | struct pcep_versioning *versioning, | |
64 | uint8_t *tlv_body_buf); | |
65 | uint16_t | |
66 | pcep_encode_tlv_ipv4_lsp_identifiers(struct pcep_object_tlv_header *tlv, | |
67 | struct pcep_versioning *versioning, | |
68 | uint8_t *tlv_body_buf); | |
69 | uint16_t | |
70 | pcep_encode_tlv_ipv6_lsp_identifiers(struct pcep_object_tlv_header *tlv, | |
71 | struct pcep_versioning *versioning, | |
72 | uint8_t *tlv_body_buf); | |
73 | uint16_t pcep_encode_tlv_lsp_error_code(struct pcep_object_tlv_header *tlv, | |
74 | struct pcep_versioning *versioning, | |
75 | uint8_t *tlv_body_buf); | |
76 | uint16_t pcep_encode_tlv_rsvp_error_spec(struct pcep_object_tlv_header *tlv, | |
77 | struct pcep_versioning *versioning, | |
78 | uint8_t *tlv_body_buf); | |
79 | uint16_t pcep_encode_tlv_lsp_db_version(struct pcep_object_tlv_header *tlv, | |
80 | struct pcep_versioning *versioning, | |
81 | uint8_t *tlv_body_buf); | |
82 | uint16_t pcep_encode_tlv_speaker_entity_id(struct pcep_object_tlv_header *tlv, | |
83 | struct pcep_versioning *versioning, | |
84 | uint8_t *tlv_body_buf); | |
85 | uint16_t pcep_encode_tlv_sr_pce_capability(struct pcep_object_tlv_header *tlv, | |
86 | struct pcep_versioning *versioning, | |
87 | uint8_t *tlv_body_buf); | |
88 | uint16_t pcep_encode_tlv_path_setup_type(struct pcep_object_tlv_header *tlv, | |
89 | struct pcep_versioning *versioning, | |
90 | uint8_t *tlv_body_buf); | |
91 | uint16_t | |
92 | pcep_encode_tlv_path_setup_type_capability(struct pcep_object_tlv_header *tlv, | |
93 | struct pcep_versioning *versioning, | |
94 | uint8_t *tlv_body_buf); | |
95 | uint16_t pcep_encode_tlv_pol_id(struct pcep_object_tlv_header *tlv, | |
96 | struct pcep_versioning *versioning, | |
97 | uint8_t *tlv_body_buf); | |
98 | uint16_t pcep_encode_tlv_pol_name(struct pcep_object_tlv_header *tlv, | |
99 | struct pcep_versioning *versioning, | |
100 | uint8_t *tlv_body_buf); | |
101 | uint16_t pcep_encode_tlv_cpath_id(struct pcep_object_tlv_header *tlv, | |
102 | struct pcep_versioning *versioning, | |
103 | uint8_t *tlv_body_buf); | |
104 | uint16_t pcep_encode_tlv_cpath_preference(struct pcep_object_tlv_header *tlv, | |
105 | struct pcep_versioning *versioning, | |
106 | uint8_t *tlv_body_buf); | |
107 | uint16_t pcep_encode_tlv_vendor_info(struct pcep_object_tlv_header *tlv, | |
108 | struct pcep_versioning *versioning, | |
109 | uint8_t *tlv_body_buf); | |
110 | uint16_t pcep_encode_tlv_arbitrary(struct pcep_object_tlv_header *tlv, | |
111 | struct pcep_versioning *versioning, | |
112 | uint8_t *tlv_body_buf); | |
113 | uint16_t pcep_encode_tlv_of_list(struct pcep_object_tlv_header *tlv, | |
114 | struct pcep_versioning *versioning, | |
115 | uint8_t *tlv_body_buf); | |
116 | typedef uint16_t (*tlv_encoder_funcptr)(struct pcep_object_tlv_header *, | |
117 | struct pcep_versioning *versioning, | |
118 | uint8_t *tlv_body_buf); | |
119 | ||
120 | #define MAX_TLV_ENCODER_INDEX 65533 + 1 // 65 | |
121 | ||
122 | #define PCEP_TLV_ENCODERS_ARGS \ | |
123 | struct pcep_object_tlv_header *, struct pcep_versioning *versioning, \ | |
124 | uint8_t *tlv_body_buf | |
125 | uint16_t (*const tlv_encoders[MAX_TLV_ENCODER_INDEX])( | |
126 | PCEP_TLV_ENCODERS_ARGS) = { | |
127 | [PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR] = pcep_encode_tlv_no_path_vector, | |
128 | [PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY] = | |
129 | pcep_encode_tlv_stateful_pce_capability, | |
130 | [PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME] = | |
131 | pcep_encode_tlv_symbolic_path_name, | |
132 | [PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS] = | |
133 | pcep_encode_tlv_ipv4_lsp_identifiers, | |
134 | [PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS] = | |
135 | pcep_encode_tlv_ipv6_lsp_identifiers, | |
136 | [PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE] = pcep_encode_tlv_lsp_error_code, | |
137 | [PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC] = pcep_encode_tlv_rsvp_error_spec, | |
138 | [PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION] = pcep_encode_tlv_lsp_db_version, | |
139 | [PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID] = | |
140 | pcep_encode_tlv_speaker_entity_id, | |
141 | [PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY] = | |
142 | pcep_encode_tlv_sr_pce_capability, | |
143 | [PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE] = pcep_encode_tlv_path_setup_type, | |
144 | [PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY] = | |
145 | pcep_encode_tlv_path_setup_type_capability, | |
146 | [PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID] = pcep_encode_tlv_pol_id, | |
147 | [PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME] = pcep_encode_tlv_pol_name, | |
148 | [PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID] = pcep_encode_tlv_cpath_id, | |
149 | [PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE] = | |
150 | pcep_encode_tlv_cpath_preference, | |
151 | [PCEP_OBJ_TLV_TYPE_VENDOR_INFO] = pcep_encode_tlv_vendor_info, | |
152 | [PCEP_OBJ_TLV_TYPE_ARBITRARY] = pcep_encode_tlv_arbitrary, | |
153 | [PCEP_OBJ_TLV_TYPE_OBJECTIVE_FUNCTION_LIST] = pcep_encode_tlv_of_list, | |
154 | }; | |
155 | /* | |
156 | * forward declarations for initialize_tlv_decoders() | |
157 | */ | |
158 | struct pcep_object_tlv_header * | |
159 | pcep_decode_tlv_no_path_vector(struct pcep_object_tlv_header *tlv_hdr, | |
160 | const uint8_t *tlv_body_buf); | |
161 | struct pcep_object_tlv_header * | |
162 | pcep_decode_tlv_stateful_pce_capability(struct pcep_object_tlv_header *tlv_hdr, | |
163 | const uint8_t *tlv_body_buf); | |
164 | struct pcep_object_tlv_header * | |
165 | pcep_decode_tlv_symbolic_path_name(struct pcep_object_tlv_header *tlv_hdr, | |
166 | const uint8_t *tlv_body_buf); | |
167 | struct pcep_object_tlv_header * | |
168 | pcep_decode_tlv_ipv4_lsp_identifiers(struct pcep_object_tlv_header *tlv_hdr, | |
169 | const uint8_t *tlv_body_buf); | |
170 | struct pcep_object_tlv_header * | |
171 | pcep_decode_tlv_ipv6_lsp_identifiers(struct pcep_object_tlv_header *tlv_hdr, | |
172 | const uint8_t *tlv_body_buf); | |
173 | struct pcep_object_tlv_header * | |
174 | pcep_decode_tlv_lsp_error_code(struct pcep_object_tlv_header *tlv_hdr, | |
175 | const uint8_t *tlv_body_buf); | |
176 | struct pcep_object_tlv_header * | |
177 | pcep_decode_tlv_rsvp_error_spec(struct pcep_object_tlv_header *tlv_hdr, | |
178 | const uint8_t *tlv_body_buf); | |
179 | struct pcep_object_tlv_header * | |
180 | pcep_decode_tlv_lsp_db_version(struct pcep_object_tlv_header *tlv_hdr, | |
181 | const uint8_t *tlv_body_buf); | |
182 | struct pcep_object_tlv_header * | |
183 | pcep_decode_tlv_speaker_entity_id(struct pcep_object_tlv_header *tlv_hdr, | |
184 | const uint8_t *tlv_body_buf); | |
185 | struct pcep_object_tlv_header * | |
186 | pcep_decode_tlv_sr_pce_capability(struct pcep_object_tlv_header *tlv_hdr, | |
187 | const uint8_t *tlv_body_buf); | |
188 | struct pcep_object_tlv_header * | |
189 | pcep_decode_tlv_path_setup_type(struct pcep_object_tlv_header *tlv_hdr, | |
190 | const uint8_t *tlv_body_buf); | |
191 | struct pcep_object_tlv_header *pcep_decode_tlv_path_setup_type_capability( | |
192 | struct pcep_object_tlv_header *tlv_hdr, const uint8_t *tlv_body_buf); | |
193 | struct pcep_object_tlv_header * | |
194 | pcep_decode_tlv_pol_id(struct pcep_object_tlv_header *tlv_hdr, | |
195 | const uint8_t *tlv_body_buf); | |
196 | struct pcep_object_tlv_header * | |
197 | pcep_decode_tlv_pol_name(struct pcep_object_tlv_header *tlv_hdr, | |
198 | const uint8_t *tlv_body_buf); | |
199 | struct pcep_object_tlv_header * | |
200 | pcep_decode_tlv_cpath_id(struct pcep_object_tlv_header *tlv_hdr, | |
201 | const uint8_t *tlv_body_buf); | |
202 | struct pcep_object_tlv_header * | |
203 | pcep_decode_tlv_cpath_preference(struct pcep_object_tlv_header *tlv_hdr, | |
204 | const uint8_t *tlv_body_buf); | |
205 | struct pcep_object_tlv_header * | |
206 | pcep_decode_tlv_vendor_info(struct pcep_object_tlv_header *tlv_hdr, | |
207 | const uint8_t *tlv_body_buf); | |
208 | struct pcep_object_tlv_header * | |
209 | pcep_decode_tlv_arbitrary(struct pcep_object_tlv_header *tlv_hdr, | |
210 | const uint8_t *tlv_body_buf); | |
211 | struct pcep_object_tlv_header * | |
212 | pcep_decode_tlv_of_list(struct pcep_object_tlv_header *tlv_hdr, | |
213 | const uint8_t *tlv_body_buf); | |
214 | typedef struct pcep_object_tlv_header *(*tlv_decoder_funcptr)( | |
215 | struct pcep_object_tlv_header *tlv_hdr, const uint8_t *tlv_body_buf); | |
216 | ||
217 | // tlv_decoder_funcptr tlv_decoders[MAX_TLV_ENCODER_INDEX]; | |
218 | ||
219 | #define PCEP_TLV_DECODERS_ARGS \ | |
220 | struct pcep_object_tlv_header *tlv_hdr, const uint8_t *tlv_body_buf | |
221 | ||
222 | struct pcep_object_tlv_header *(*const tlv_decoders[MAX_TLV_ENCODER_INDEX])( | |
223 | PCEP_TLV_DECODERS_ARGS) = { | |
224 | [PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR] = pcep_decode_tlv_no_path_vector, | |
225 | [PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY] = | |
226 | pcep_decode_tlv_stateful_pce_capability, | |
227 | [PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME] = | |
228 | pcep_decode_tlv_symbolic_path_name, | |
229 | [PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS] = | |
230 | pcep_decode_tlv_ipv4_lsp_identifiers, | |
231 | [PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS] = | |
232 | pcep_decode_tlv_ipv6_lsp_identifiers, | |
233 | [PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE] = pcep_decode_tlv_lsp_error_code, | |
234 | [PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC] = pcep_decode_tlv_rsvp_error_spec, | |
235 | [PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION] = pcep_decode_tlv_lsp_db_version, | |
236 | [PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID] = | |
237 | pcep_decode_tlv_speaker_entity_id, | |
238 | [PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY] = | |
239 | pcep_decode_tlv_sr_pce_capability, | |
240 | [PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE] = pcep_decode_tlv_path_setup_type, | |
241 | [PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY] = | |
242 | pcep_decode_tlv_path_setup_type_capability, | |
243 | [PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID] = pcep_decode_tlv_pol_id, | |
244 | [PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME] = pcep_decode_tlv_pol_name, | |
245 | [PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID] = pcep_decode_tlv_cpath_id, | |
246 | [PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE] = | |
247 | pcep_decode_tlv_cpath_preference, | |
248 | [PCEP_OBJ_TLV_TYPE_VENDOR_INFO] = pcep_decode_tlv_vendor_info, | |
249 | [PCEP_OBJ_TLV_TYPE_ARBITRARY] = pcep_decode_tlv_arbitrary, | |
250 | [PCEP_OBJ_TLV_TYPE_OBJECTIVE_FUNCTION_LIST] = pcep_decode_tlv_of_list, | |
251 | }; | |
252 | ||
c17662db | 253 | static void initialize_tlv_coders(void) |
74971473 JG |
254 | { |
255 | static bool initialized = false; | |
256 | ||
257 | if (initialized == true) { | |
258 | return; | |
259 | } | |
260 | ||
261 | initialized = true; | |
262 | ||
263 | /* Encoders */ | |
264 | /* | |
265 | memset(tlv_encoders, 0, sizeof(tlv_encoder_funcptr) * | |
266 | MAX_TLV_ENCODER_INDEX); tlv_encoders[PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR] = | |
267 | pcep_encode_tlv_no_path_vector; | |
268 | tlv_encoders[PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY] = | |
269 | pcep_encode_tlv_stateful_pce_capability; | |
270 | tlv_encoders[PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME] = | |
271 | pcep_encode_tlv_symbolic_path_name; | |
272 | tlv_encoders[PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS] = | |
273 | pcep_encode_tlv_ipv4_lsp_identifiers; | |
274 | tlv_encoders[PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS] = | |
275 | pcep_encode_tlv_ipv6_lsp_identifiers; | |
276 | tlv_encoders[PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE] = | |
277 | pcep_encode_tlv_lsp_error_code; | |
278 | tlv_encoders[PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC] = | |
279 | pcep_encode_tlv_rsvp_error_spec; | |
280 | tlv_encoders[PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION] = | |
281 | pcep_encode_tlv_lsp_db_version; | |
282 | tlv_encoders[PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID] = | |
283 | pcep_encode_tlv_speaker_entity_id; | |
284 | tlv_encoders[PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY] = | |
285 | pcep_encode_tlv_sr_pce_capability; | |
286 | tlv_encoders[PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE] = | |
287 | pcep_encode_tlv_path_setup_type; | |
288 | tlv_encoders[PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY] = | |
289 | pcep_encode_tlv_path_setup_type_capability; | |
290 | tlv_encoders[PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID] = | |
291 | pcep_encode_tlv_pol_id; | |
292 | tlv_encoders[PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME] = | |
293 | pcep_encode_tlv_pol_name; | |
294 | tlv_encoders[PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID] = | |
295 | pcep_encode_tlv_cpath_id; | |
296 | tlv_encoders[PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE] = | |
297 | pcep_encode_tlv_cpath_preference; | |
298 | tlv_encoders[PCEP_OBJ_TLV_TYPE_VENDOR_INFO] = | |
299 | pcep_encode_tlv_vendor_info; tlv_encoders[PCEP_OBJ_TLV_TYPE_ARBITRARY] = | |
300 | pcep_encode_tlv_arbitrary; | |
301 | tlv_encoders[PCEP_OBJ_TLV_TYPE_OBJECTIVE_FUNCTION_LIST] = | |
302 | pcep_encode_tlv_of_list; | |
303 | */ | |
304 | ||
305 | /* Decoders */ | |
306 | /* | |
307 | memset(tlv_decoders, 0, sizeof(tlv_decoder_funcptr) * | |
308 | MAX_TLV_ENCODER_INDEX); tlv_decoders[PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR] = | |
309 | pcep_decode_tlv_no_path_vector; | |
310 | tlv_decoders[PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY] = | |
311 | pcep_decode_tlv_stateful_pce_capability; | |
312 | tlv_decoders[PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME] = | |
313 | pcep_decode_tlv_symbolic_path_name; | |
314 | tlv_decoders[PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS] = | |
315 | pcep_decode_tlv_ipv4_lsp_identifiers; | |
316 | tlv_decoders[PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS] = | |
317 | pcep_decode_tlv_ipv6_lsp_identifiers; | |
318 | tlv_decoders[PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE] = | |
319 | pcep_decode_tlv_lsp_error_code; | |
320 | tlv_decoders[PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC] = | |
321 | pcep_decode_tlv_rsvp_error_spec; | |
322 | tlv_decoders[PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION] = | |
323 | pcep_decode_tlv_lsp_db_version; | |
324 | tlv_decoders[PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID] = | |
325 | pcep_decode_tlv_speaker_entity_id; | |
326 | tlv_decoders[PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY] = | |
327 | pcep_decode_tlv_sr_pce_capability; | |
328 | tlv_decoders[PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE] = | |
329 | pcep_decode_tlv_path_setup_type; | |
330 | tlv_decoders[PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY] = | |
331 | pcep_decode_tlv_path_setup_type_capability; | |
332 | tlv_decoders[PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID] = | |
333 | pcep_decode_tlv_pol_id; | |
334 | tlv_decoders[PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME] = | |
335 | pcep_decode_tlv_pol_name; | |
336 | tlv_decoders[PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID] = | |
337 | pcep_decode_tlv_cpath_id; | |
338 | tlv_decoders[PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE] = | |
339 | pcep_decode_tlv_cpath_preference; | |
340 | tlv_decoders[PCEP_OBJ_TLV_TYPE_VENDOR_INFO] = | |
341 | pcep_decode_tlv_vendor_info; tlv_decoders[PCEP_OBJ_TLV_TYPE_ARBITRARY] = | |
342 | pcep_decode_tlv_arbitrary; | |
343 | tlv_decoders[PCEP_OBJ_TLV_TYPE_OBJECTIVE_FUNCTION_LIST] = | |
344 | pcep_decode_tlv_of_list; | |
345 | */ | |
346 | } | |
347 | ||
348 | uint16_t pcep_encode_tlv(struct pcep_object_tlv_header *tlv_hdr, | |
349 | struct pcep_versioning *versioning, uint8_t *buf) | |
350 | { | |
351 | initialize_tlv_coders(); | |
352 | ||
353 | if (tlv_hdr->type >= MAX_TLV_ENCODER_INDEX) { | |
354 | pcep_log(LOG_INFO, | |
355 | "%s: Cannot encode unknown Object class [%d]", | |
356 | __func__, tlv_hdr->type); | |
357 | return 0; | |
358 | } | |
359 | ||
360 | tlv_encoder_funcptr tlv_encoder = tlv_encoders[tlv_hdr->type]; | |
361 | if (tlv_encoder == NULL) { | |
362 | pcep_log(LOG_INFO, | |
363 | "%s: No object encoder found for Object class [%d]", | |
364 | __func__, tlv_hdr->type); | |
365 | return 0; | |
366 | } | |
367 | ||
368 | /* Notice: The length in the TLV header does not include the TLV header, | |
369 | * so the length returned from the tlv_encoder() is only the TLV body. | |
370 | */ | |
371 | uint16_t tlv_length = | |
372 | tlv_encoder(tlv_hdr, versioning, buf + TLV_HEADER_LENGTH); | |
373 | write_tlv_header(tlv_hdr, tlv_length, versioning, buf); | |
374 | tlv_hdr->encoded_tlv = buf; | |
375 | tlv_hdr->encoded_tlv_length = tlv_length; | |
376 | ||
377 | return normalize_pcep_tlv_length(tlv_length + TLV_HEADER_LENGTH); | |
378 | } | |
379 | ||
380 | /* TLV Header format | |
381 | * | |
382 | * 0 1 2 3 | |
383 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 | |
384 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
385 | * | Type (2 bytes) | Length (2 bytes) | | |
386 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
387 | * | Value (Variable) | | |
388 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
389 | */ | |
390 | ||
391 | void write_tlv_header(struct pcep_object_tlv_header *tlv_hdr, | |
392 | uint16_t tlv_length, struct pcep_versioning *versioning, | |
393 | uint8_t *buf) | |
394 | { | |
395 | (void)versioning; | |
396 | uint16_t *uint16_ptr = (uint16_t *)buf; | |
397 | uint16_ptr[0] = htons(tlv_hdr->type); | |
398 | uint16_ptr[1] = htons(tlv_length); | |
399 | } | |
400 | ||
401 | /* | |
402 | * Functions to encode TLVs | |
403 | */ | |
404 | ||
405 | uint16_t pcep_encode_tlv_no_path_vector(struct pcep_object_tlv_header *tlv, | |
406 | struct pcep_versioning *versioning, | |
407 | uint8_t *tlv_body_buf) | |
408 | { | |
409 | (void)versioning; | |
410 | struct pcep_object_tlv_nopath_vector *nopath_tlv = | |
411 | (struct pcep_object_tlv_nopath_vector *)tlv; | |
412 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
413 | *uint32_ptr = htonl(nopath_tlv->error_code); | |
414 | ||
415 | return LENGTH_1WORD; | |
416 | } | |
417 | ||
418 | uint16_t | |
419 | pcep_encode_tlv_stateful_pce_capability(struct pcep_object_tlv_header *tlv, | |
420 | struct pcep_versioning *versioning, | |
421 | uint8_t *tlv_body_buf) | |
422 | { | |
423 | (void)versioning; | |
424 | struct pcep_object_tlv_stateful_pce_capability *spc_tlv = | |
425 | (struct pcep_object_tlv_stateful_pce_capability *)tlv; | |
426 | tlv_body_buf[3] = | |
427 | ((spc_tlv->flag_f_triggered_initial_sync == true | |
428 | ? TLV_STATEFUL_PCE_CAP_FLAG_F | |
429 | : 0x00) | |
430 | | (spc_tlv->flag_d_delta_lsp_sync == true | |
431 | ? TLV_STATEFUL_PCE_CAP_FLAG_D | |
432 | : 0x00) | |
433 | | (spc_tlv->flag_t_triggered_resync == true | |
434 | ? TLV_STATEFUL_PCE_CAP_FLAG_T | |
435 | : 0x00) | |
436 | | (spc_tlv->flag_i_lsp_instantiation_capability == true | |
437 | ? TLV_STATEFUL_PCE_CAP_FLAG_I | |
438 | : 0x00) | |
439 | | (spc_tlv->flag_s_include_db_version == true | |
440 | ? TLV_STATEFUL_PCE_CAP_FLAG_S | |
441 | : 0x00) | |
442 | | (spc_tlv->flag_u_lsp_update_capability == true | |
443 | ? TLV_STATEFUL_PCE_CAP_FLAG_U | |
444 | : 0x00)); | |
445 | ||
446 | return LENGTH_1WORD; | |
447 | } | |
448 | ||
449 | uint16_t pcep_encode_tlv_symbolic_path_name(struct pcep_object_tlv_header *tlv, | |
450 | struct pcep_versioning *versioning, | |
451 | uint8_t *tlv_body_buf) | |
452 | { | |
453 | (void)versioning; | |
454 | struct pcep_object_tlv_symbolic_path_name *spn_tlv = | |
455 | (struct pcep_object_tlv_symbolic_path_name *)tlv; | |
456 | memcpy(tlv_body_buf, spn_tlv->symbolic_path_name, | |
457 | spn_tlv->symbolic_path_name_length); | |
458 | ||
459 | return spn_tlv->symbolic_path_name_length; | |
460 | } | |
461 | ||
462 | uint16_t | |
463 | pcep_encode_tlv_ipv4_lsp_identifiers(struct pcep_object_tlv_header *tlv, | |
464 | struct pcep_versioning *versioning, | |
465 | uint8_t *tlv_body_buf) | |
466 | { | |
467 | (void)versioning; | |
468 | struct pcep_object_tlv_ipv4_lsp_identifier *ipv4_lsp = | |
469 | (struct pcep_object_tlv_ipv4_lsp_identifier *)tlv; | |
470 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
471 | uint32_ptr[0] = ipv4_lsp->ipv4_tunnel_sender.s_addr; | |
472 | /* uint32_t[1] is lsp_id and tunnel_id, below */ | |
473 | uint32_ptr[2] = ipv4_lsp->extended_tunnel_id.s_addr; | |
474 | uint32_ptr[3] = ipv4_lsp->ipv4_tunnel_endpoint.s_addr; | |
475 | ||
476 | uint16_t *uint16_ptr = (uint16_t *)(tlv_body_buf + LENGTH_1WORD); | |
477 | uint16_ptr[0] = htons(ipv4_lsp->lsp_id); | |
478 | uint16_ptr[1] = htons(ipv4_lsp->tunnel_id); | |
479 | ||
480 | return LENGTH_4WORDS; | |
481 | } | |
482 | ||
483 | uint16_t | |
484 | pcep_encode_tlv_ipv6_lsp_identifiers(struct pcep_object_tlv_header *tlv, | |
485 | struct pcep_versioning *versioning, | |
486 | uint8_t *tlv_body_buf) | |
487 | { | |
488 | (void)versioning; | |
489 | struct pcep_object_tlv_ipv6_lsp_identifier *ipv6_lsp = | |
490 | (struct pcep_object_tlv_ipv6_lsp_identifier *)tlv; | |
491 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
492 | encode_ipv6(&ipv6_lsp->ipv6_tunnel_sender, uint32_ptr); | |
493 | encode_ipv6(&ipv6_lsp->extended_tunnel_id, uint32_ptr + 5); | |
494 | encode_ipv6(&ipv6_lsp->ipv6_tunnel_endpoint, uint32_ptr + 9); | |
495 | ||
496 | uint16_t *uint16_ptr = (uint16_t *)(tlv_body_buf + LENGTH_4WORDS); | |
497 | uint16_ptr[0] = htons(ipv6_lsp->lsp_id); | |
498 | uint16_ptr[1] = htons(ipv6_lsp->tunnel_id); | |
499 | ||
500 | return LENGTH_13WORDS; | |
501 | } | |
502 | ||
503 | uint16_t pcep_encode_tlv_lsp_error_code(struct pcep_object_tlv_header *tlv, | |
504 | struct pcep_versioning *versioning, | |
505 | uint8_t *tlv_body_buf) | |
506 | { | |
507 | (void)versioning; | |
508 | struct pcep_object_tlv_lsp_error_code *lsp_error_tlv = | |
509 | (struct pcep_object_tlv_lsp_error_code *)tlv; | |
510 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
511 | *uint32_ptr = htonl(lsp_error_tlv->lsp_error_code); | |
512 | ||
513 | return LENGTH_1WORD; | |
514 | } | |
515 | ||
516 | uint16_t pcep_encode_tlv_rsvp_error_spec(struct pcep_object_tlv_header *tlv, | |
517 | struct pcep_versioning *versioning, | |
518 | uint8_t *tlv_body_buf) | |
519 | { | |
520 | /* Same decode tlv function for both types: | |
521 | pcep_create_tlv_rsvp_ipv4_error_spec(tlv); | |
522 | pcep_create_tlv_rsvp_ipv6_error_spec(tlv); */ | |
523 | ||
524 | /* RSVP Object Header | |
525 | * | |
526 | * 0 1 2 3 | |
527 | * +-------------+-------------+-------------+-------------+ | |
528 | * | Length (bytes) | Class-Num | C-Type | | |
529 | * +-------------+-------------+-------------+-------------+ | |
530 | * | | | |
531 | * // (Object contents) // | |
532 | * | | | |
533 | * +-------------+-------------+-------------+-------------+ | |
534 | * | |
535 | * IPv4 ERROR_SPEC object: Class = 6, C-Type = 1 | |
536 | * +-------------+-------------+-------------+-------------+ | |
537 | * | IPv4 Error Node Address (4 bytes) | | |
538 | * +-------------+-------------+-------------+-------------+ | |
539 | * | Flags | Error Code | Error Value | | |
540 | * +-------------+-------------+-------------+-------------+ | |
541 | * | |
542 | * IPv6 ERROR_SPEC object: Class = 6, C-Type = 2 | |
543 | * +-------------+-------------+-------------+-------------+ | |
544 | * | IPv6 Error Node Address (16 bytes) | | |
545 | * +-------------+-------------+-------------+-------------+ | |
546 | * | Flags | Error Code | Error Value | | |
547 | * +-------------+-------------+-------------+-------------+ | |
548 | */ | |
549 | ||
550 | (void)versioning; | |
551 | struct pcep_object_tlv_rsvp_error_spec *rsvp_hdr = | |
552 | (struct pcep_object_tlv_rsvp_error_spec *)tlv; | |
553 | tlv_body_buf[2] = rsvp_hdr->class_num; | |
554 | tlv_body_buf[3] = rsvp_hdr->c_type; | |
555 | ||
556 | uint16_t *length_ptr = (uint16_t *)tlv_body_buf; | |
557 | uint32_t *uint32_ptr = (uint32_t *)(tlv_body_buf + LENGTH_1WORD); | |
558 | if (rsvp_hdr->c_type == RSVP_ERROR_SPEC_IPV4_CTYPE) { | |
559 | *length_ptr = htons(LENGTH_3WORDS); | |
560 | *uint32_ptr = | |
561 | rsvp_hdr->error_spec_ip.ipv4_error_node_address.s_addr; | |
562 | tlv_body_buf[LENGTH_2WORDS + 1] = rsvp_hdr->error_code; | |
563 | uint16_t *uint16_ptr = | |
564 | (uint16_t *)(tlv_body_buf + LENGTH_2WORDS + 2); | |
565 | *uint16_ptr = htons(rsvp_hdr->error_value); | |
566 | ||
567 | return LENGTH_3WORDS; | |
568 | } else if (rsvp_hdr->c_type == RSVP_ERROR_SPEC_IPV6_CTYPE) { | |
569 | *length_ptr = htons(LENGTH_6WORDS); | |
570 | encode_ipv6(&rsvp_hdr->error_spec_ip.ipv6_error_node_address, | |
571 | uint32_ptr); | |
572 | tlv_body_buf[LENGTH_5WORDS + 1] = rsvp_hdr->error_code; | |
573 | uint16_t *uint16_ptr = | |
574 | (uint16_t *)(tlv_body_buf + LENGTH_5WORDS + 2); | |
575 | *uint16_ptr = htons(rsvp_hdr->error_value); | |
576 | ||
577 | return LENGTH_6WORDS; | |
578 | } | |
579 | ||
580 | return 0; | |
581 | } | |
582 | ||
583 | uint16_t pcep_encode_tlv_lsp_db_version(struct pcep_object_tlv_header *tlv, | |
584 | struct pcep_versioning *versioning, | |
585 | uint8_t *tlv_body_buf) | |
586 | { | |
587 | (void)versioning; | |
588 | struct pcep_object_tlv_lsp_db_version *lsp_db_ver = | |
589 | (struct pcep_object_tlv_lsp_db_version *)tlv; | |
590 | *((uint64_t *)tlv_body_buf) = htobe64(lsp_db_ver->lsp_db_version); | |
591 | ||
592 | return LENGTH_2WORDS; | |
593 | } | |
594 | ||
595 | uint16_t pcep_encode_tlv_speaker_entity_id(struct pcep_object_tlv_header *tlv, | |
596 | struct pcep_versioning *versioning, | |
597 | uint8_t *tlv_body_buf) | |
598 | { | |
599 | (void)versioning; | |
600 | struct pcep_object_tlv_speaker_entity_identifier *speaker_id = | |
601 | (struct pcep_object_tlv_speaker_entity_identifier *)tlv; | |
602 | if (speaker_id->speaker_entity_id_list == NULL) { | |
603 | return 0; | |
604 | } | |
605 | ||
606 | int index = 0; | |
607 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
608 | double_linked_list_node *node = | |
609 | speaker_id->speaker_entity_id_list->head; | |
610 | for (; node != NULL; node = node->next_node) { | |
611 | uint32_ptr[index++] = htonl(*((uint32_t *)node->data)); | |
612 | } | |
613 | ||
614 | return speaker_id->speaker_entity_id_list->num_entries * LENGTH_1WORD; | |
615 | } | |
616 | ||
617 | uint16_t pcep_encode_tlv_sr_pce_capability(struct pcep_object_tlv_header *tlv, | |
618 | struct pcep_versioning *versioning, | |
619 | uint8_t *tlv_body_buf) | |
620 | { | |
621 | (void)versioning; | |
622 | struct pcep_object_tlv_sr_pce_capability *sr_pce_cap = | |
623 | (struct pcep_object_tlv_sr_pce_capability *)tlv; | |
624 | tlv_body_buf[2] = | |
625 | ((sr_pce_cap->flag_n == true ? TLV_SR_PCE_CAP_FLAG_N : 0x00) | |
626 | | (sr_pce_cap->flag_x == true ? TLV_SR_PCE_CAP_FLAG_X : 0x00)); | |
627 | tlv_body_buf[3] = sr_pce_cap->max_sid_depth; | |
628 | ||
629 | return LENGTH_1WORD; | |
630 | } | |
631 | ||
632 | uint16_t pcep_encode_tlv_path_setup_type(struct pcep_object_tlv_header *tlv, | |
633 | struct pcep_versioning *versioning, | |
634 | uint8_t *tlv_body_buf) | |
635 | { | |
636 | (void)versioning; | |
637 | struct pcep_object_tlv_path_setup_type *pst = | |
638 | (struct pcep_object_tlv_path_setup_type *)tlv; | |
639 | tlv_body_buf[3] = pst->path_setup_type; | |
640 | ||
641 | return LENGTH_1WORD; | |
642 | } | |
643 | ||
644 | uint16_t | |
645 | pcep_encode_tlv_path_setup_type_capability(struct pcep_object_tlv_header *tlv, | |
646 | struct pcep_versioning *versioning, | |
647 | uint8_t *tlv_body_buf) | |
648 | { | |
649 | (void)versioning; | |
650 | struct pcep_object_tlv_path_setup_type_capability *pst_cap = | |
651 | (struct pcep_object_tlv_path_setup_type_capability *)tlv; | |
652 | if (pst_cap->pst_list == NULL) { | |
653 | return 0; | |
654 | } | |
655 | ||
656 | tlv_body_buf[3] = pst_cap->pst_list->num_entries; | |
657 | ||
658 | /* Index past the reserved and NumPSTs fields */ | |
659 | int index = 4; | |
660 | double_linked_list_node *node = pst_cap->pst_list->head; | |
661 | for (; node != NULL; node = node->next_node) { | |
662 | tlv_body_buf[index++] = *((uint8_t *)node->data); | |
663 | } | |
664 | ||
665 | uint16_t pst_length = normalize_pcep_tlv_length( | |
666 | LENGTH_1WORD + pst_cap->pst_list->num_entries); | |
667 | if (pst_cap->sub_tlv_list == NULL) { | |
668 | return pst_length; | |
669 | } | |
670 | ||
671 | /* Any padding used for the PSTs should not be included in the tlv | |
672 | * header length */ | |
673 | index = normalize_pcep_tlv_length(index); | |
674 | uint16_t sub_tlvs_length = 0; | |
675 | node = pst_cap->sub_tlv_list->head; | |
676 | for (; node != NULL; node = node->next_node) { | |
677 | struct pcep_object_tlv_header *sub_tlv = | |
678 | (struct pcep_object_tlv_header *)node->data; | |
679 | uint16_t sub_tlv_length = pcep_encode_tlv(sub_tlv, versioning, | |
680 | tlv_body_buf + index); | |
681 | index += sub_tlv_length; | |
682 | sub_tlvs_length += sub_tlv_length; | |
683 | } | |
684 | ||
685 | return sub_tlvs_length + pst_length; | |
686 | } | |
687 | uint16_t pcep_encode_tlv_pol_id(struct pcep_object_tlv_header *tlv, | |
688 | struct pcep_versioning *versioning, | |
689 | uint8_t *tlv_body_buf) | |
690 | { | |
691 | (void)versioning; | |
692 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
693 | struct pcep_object_tlv_srpag_pol_id *ipv4 = | |
694 | (struct pcep_object_tlv_srpag_pol_id *)tlv; | |
695 | if (ipv4->is_ipv4) { | |
696 | uint32_ptr[0] = htonl(ipv4->color); | |
697 | uint32_ptr[1] = ipv4->end_point.ipv4.s_addr; | |
698 | return LENGTH_2WORDS; | |
699 | } else { | |
700 | struct pcep_object_tlv_srpag_pol_id *ipv6 = | |
701 | (struct pcep_object_tlv_srpag_pol_id *)tlv; | |
702 | uint32_ptr[0] = htonl(ipv6->color); | |
703 | encode_ipv6(&ipv6->end_point.ipv6, &uint32_ptr[1]); | |
704 | return LENGTH_5WORDS; | |
705 | } | |
706 | } | |
707 | ||
708 | uint16_t pcep_encode_tlv_pol_name(struct pcep_object_tlv_header *tlv, | |
709 | struct pcep_versioning *versioning, | |
710 | uint8_t *tlv_body_buf) | |
711 | { | |
712 | (void)versioning; | |
713 | struct pcep_object_tlv_srpag_pol_name *pol_name_tlv = | |
714 | (struct pcep_object_tlv_srpag_pol_name *)tlv; | |
715 | memcpy(tlv_body_buf, pol_name_tlv->name, pol_name_tlv->name_length); | |
716 | ||
717 | return normalize_pcep_tlv_length(pol_name_tlv->name_length); | |
718 | } | |
719 | ||
720 | uint16_t pcep_encode_tlv_cpath_id(struct pcep_object_tlv_header *tlv, | |
721 | struct pcep_versioning *versioning, | |
722 | uint8_t *tlv_body_buf) | |
723 | { | |
724 | (void)versioning; | |
725 | struct pcep_object_tlv_srpag_cp_id *cpath_id_tlv = | |
726 | (struct pcep_object_tlv_srpag_cp_id *)tlv; | |
727 | ||
728 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
729 | tlv_body_buf[0] = cpath_id_tlv->proto; | |
730 | uint32_ptr[1] = htonl(cpath_id_tlv->orig_asn); | |
731 | encode_ipv6(&cpath_id_tlv->orig_addres, &uint32_ptr[2]); | |
732 | uint32_ptr[6] = htonl(cpath_id_tlv->discriminator); | |
733 | ||
734 | return sizeof(cpath_id_tlv->proto) + sizeof(cpath_id_tlv->orig_asn) | |
735 | + sizeof(cpath_id_tlv->orig_addres) | |
736 | + sizeof(cpath_id_tlv->discriminator); | |
737 | } | |
738 | ||
739 | uint16_t pcep_encode_tlv_cpath_preference(struct pcep_object_tlv_header *tlv, | |
740 | struct pcep_versioning *versioning, | |
741 | uint8_t *tlv_body_buf) | |
742 | { | |
743 | (void)versioning; | |
744 | struct pcep_object_tlv_srpag_cp_pref *cpath_pref_tlv = | |
745 | (struct pcep_object_tlv_srpag_cp_pref *)tlv; | |
746 | ||
747 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
748 | uint32_ptr[0] = htonl(cpath_pref_tlv->preference); | |
749 | ||
750 | return sizeof(cpath_pref_tlv->preference); | |
751 | } | |
752 | ||
753 | uint16_t pcep_encode_tlv_vendor_info(struct pcep_object_tlv_header *tlv, | |
754 | struct pcep_versioning *versioning, | |
755 | uint8_t *tlv_body_buf) | |
756 | { | |
757 | (void)versioning; | |
758 | struct pcep_object_tlv_vendor_info *vendor_info = | |
759 | (struct pcep_object_tlv_vendor_info *)tlv; | |
760 | ||
761 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
762 | uint32_ptr[0] = htonl(vendor_info->enterprise_number); | |
763 | uint32_ptr[1] = htonl(vendor_info->enterprise_specific_info); | |
764 | ||
765 | return LENGTH_2WORDS; | |
766 | } | |
767 | ||
768 | uint16_t pcep_encode_tlv_arbitrary(struct pcep_object_tlv_header *tlv, | |
769 | struct pcep_versioning *versioning, | |
770 | uint8_t *tlv_body_buf) | |
771 | { | |
772 | (void)versioning; | |
773 | struct pcep_object_tlv_arbitrary *tlv_arbitrary = | |
774 | (struct pcep_object_tlv_arbitrary *)tlv; | |
775 | memcpy(tlv_body_buf, tlv_arbitrary->data, tlv_arbitrary->data_length); | |
776 | tlv->type = tlv_arbitrary->arbitraty_type; | |
777 | ||
778 | return tlv_arbitrary->data_length; | |
779 | } | |
780 | ||
781 | uint16_t pcep_encode_tlv_of_list(struct pcep_object_tlv_header *tlv, | |
782 | struct pcep_versioning *versioning, | |
783 | uint8_t *tlv_body_buf) | |
784 | { | |
785 | (void)versioning; | |
786 | struct pcep_object_tlv_of_list *of_list = | |
787 | (struct pcep_object_tlv_of_list *)tlv; | |
788 | ||
789 | if (of_list->of_list == NULL) { | |
790 | return 0; | |
791 | } | |
792 | ||
793 | int index = 0; | |
794 | double_linked_list_node *node = of_list->of_list->head; | |
795 | while (node != NULL) { | |
796 | uint16_t *of_code = (uint16_t *)node->data; | |
797 | if (of_code == NULL) { | |
798 | return 0; | |
799 | } | |
800 | ||
801 | uint16_t *uint16_ptr = (uint16_t *)(tlv_body_buf + index); | |
802 | *uint16_ptr = *of_code; | |
803 | index += 2; | |
804 | ||
805 | node = node->next_node; | |
806 | } | |
807 | ||
808 | return of_list->of_list->num_entries * 2; | |
809 | } | |
810 | ||
811 | /* | |
812 | * Decoding functions | |
813 | */ | |
814 | ||
815 | void pcep_decode_tlv_hdr(const uint8_t *tlv_buf, | |
816 | struct pcep_object_tlv_header *tlv_hdr) | |
817 | { | |
818 | memset(tlv_hdr, 0, sizeof(struct pcep_object_tlv_header)); | |
819 | ||
820 | uint16_t *uint16_ptr = (uint16_t *)tlv_buf; | |
821 | tlv_hdr->type = ntohs(uint16_ptr[0]); | |
822 | tlv_hdr->encoded_tlv_length = ntohs(uint16_ptr[1]); | |
823 | tlv_hdr->encoded_tlv = tlv_buf; | |
824 | } | |
825 | ||
826 | struct pcep_object_tlv_header *pcep_decode_tlv(const uint8_t *tlv_buf) | |
827 | { | |
828 | initialize_tlv_coders(); | |
829 | ||
830 | struct pcep_object_tlv_header tlv_hdr; | |
831 | /* Only initializes and decodes the Object Header: class, type, flags, | |
832 | * and length */ | |
833 | pcep_decode_tlv_hdr(tlv_buf, &tlv_hdr); | |
834 | ||
835 | if (tlv_hdr.type >= MAX_TLV_ENCODER_INDEX) { | |
836 | pcep_log(LOG_INFO, "%s: Cannot decode unknown TLV type [%d]", | |
837 | __func__, tlv_hdr.type); | |
838 | return NULL; | |
839 | } | |
840 | ||
5fe7f5b4 JG |
841 | tlv_decoder_funcptr tlv_decoder = NULL; |
842 | if (tlv_hdr.type == PCEP_OBJ_TYPE_CISCO_BSID) { | |
843 | pcep_log(LOG_INFO, | |
844 | "%s: Cisco BSID TLV decoder found for TLV type [%d]", | |
845 | __func__, tlv_hdr.type); | |
846 | tlv_decoder = tlv_decoders[PCEP_OBJ_TLV_TYPE_ARBITRARY]; | |
847 | } else { | |
848 | tlv_decoder = tlv_decoders[tlv_hdr.type]; | |
849 | } | |
74971473 JG |
850 | if (tlv_decoder == NULL) { |
851 | pcep_log(LOG_INFO, "%s: No TLV decoder found for TLV type [%d]", | |
852 | __func__, tlv_hdr.type); | |
853 | return NULL; | |
854 | } | |
855 | ||
856 | return tlv_decoder(&tlv_hdr, tlv_buf + LENGTH_1WORD); | |
857 | } | |
858 | ||
859 | static struct pcep_object_tlv_header * | |
860 | common_tlv_create(struct pcep_object_tlv_header *hdr, uint16_t new_tlv_length) | |
861 | { | |
862 | struct pcep_object_tlv_header *new_tlv = | |
863 | pceplib_malloc(PCEPLIB_MESSAGES, new_tlv_length); | |
864 | memset(new_tlv, 0, new_tlv_length); | |
865 | memcpy(new_tlv, hdr, sizeof(struct pcep_object_tlv_header)); | |
866 | ||
867 | return new_tlv; | |
868 | } | |
869 | ||
870 | struct pcep_object_tlv_header * | |
871 | pcep_decode_tlv_no_path_vector(struct pcep_object_tlv_header *tlv_hdr, | |
872 | const uint8_t *tlv_body_buf) | |
873 | { | |
874 | struct pcep_object_tlv_nopath_vector *tlv = | |
875 | (struct pcep_object_tlv_nopath_vector *)common_tlv_create( | |
876 | tlv_hdr, sizeof(struct pcep_object_tlv_nopath_vector)); | |
877 | ||
878 | tlv->error_code = ntohl(*((uint32_t *)tlv_body_buf)); | |
879 | ||
880 | return (struct pcep_object_tlv_header *)tlv; | |
881 | } | |
882 | ||
883 | struct pcep_object_tlv_header * | |
884 | pcep_decode_tlv_stateful_pce_capability(struct pcep_object_tlv_header *tlv_hdr, | |
885 | const uint8_t *tlv_body_buf) | |
886 | { | |
887 | struct pcep_object_tlv_stateful_pce_capability *tlv = | |
888 | (struct pcep_object_tlv_stateful_pce_capability *) | |
889 | common_tlv_create( | |
890 | tlv_hdr, | |
891 | sizeof(struct | |
892 | pcep_object_tlv_stateful_pce_capability)); | |
893 | ||
894 | tlv->flag_f_triggered_initial_sync = | |
895 | (tlv_body_buf[3] & TLV_STATEFUL_PCE_CAP_FLAG_F); | |
896 | tlv->flag_d_delta_lsp_sync = | |
897 | (tlv_body_buf[3] & TLV_STATEFUL_PCE_CAP_FLAG_D); | |
898 | tlv->flag_t_triggered_resync = | |
899 | (tlv_body_buf[3] & TLV_STATEFUL_PCE_CAP_FLAG_T); | |
900 | tlv->flag_i_lsp_instantiation_capability = | |
901 | (tlv_body_buf[3] & TLV_STATEFUL_PCE_CAP_FLAG_I); | |
902 | tlv->flag_s_include_db_version = | |
903 | (tlv_body_buf[3] & TLV_STATEFUL_PCE_CAP_FLAG_S); | |
904 | tlv->flag_u_lsp_update_capability = | |
905 | (tlv_body_buf[3] & TLV_STATEFUL_PCE_CAP_FLAG_U); | |
906 | ||
907 | return (struct pcep_object_tlv_header *)tlv; | |
908 | } | |
909 | ||
910 | struct pcep_object_tlv_header * | |
911 | pcep_decode_tlv_symbolic_path_name(struct pcep_object_tlv_header *tlv_hdr, | |
912 | const uint8_t *tlv_body_buf) | |
913 | { | |
914 | struct pcep_object_tlv_symbolic_path_name *tlv = | |
915 | (struct pcep_object_tlv_symbolic_path_name *)common_tlv_create( | |
916 | tlv_hdr, | |
917 | sizeof(struct pcep_object_tlv_symbolic_path_name)); | |
918 | ||
919 | uint16_t length = tlv_hdr->encoded_tlv_length; | |
920 | if (length > MAX_SYMBOLIC_PATH_NAME) { | |
921 | /* TODO should we also reset the tlv_hdr->encoded_tlv_length ? | |
922 | */ | |
923 | length = MAX_SYMBOLIC_PATH_NAME; | |
924 | pcep_log( | |
925 | LOG_INFO, | |
926 | "%s: Decoding Symbolic Path Name TLV, truncate path name from [%d] to [%d].\",", | |
927 | __func__, tlv_hdr->encoded_tlv_length, | |
928 | MAX_SYMBOLIC_PATH_NAME); | |
929 | } | |
930 | ||
931 | tlv->symbolic_path_name_length = length; | |
932 | memcpy(tlv->symbolic_path_name, tlv_body_buf, length); | |
933 | ||
934 | return (struct pcep_object_tlv_header *)tlv; | |
935 | } | |
936 | ||
937 | struct pcep_object_tlv_header * | |
938 | pcep_decode_tlv_ipv4_lsp_identifiers(struct pcep_object_tlv_header *tlv_hdr, | |
939 | const uint8_t *tlv_body_buf) | |
940 | { | |
941 | struct pcep_object_tlv_ipv4_lsp_identifier *tlv = | |
942 | (struct pcep_object_tlv_ipv4_lsp_identifier *)common_tlv_create( | |
943 | tlv_hdr, | |
944 | sizeof(struct pcep_object_tlv_ipv4_lsp_identifier)); | |
945 | ||
946 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
947 | tlv->ipv4_tunnel_sender.s_addr = uint32_ptr[0]; | |
948 | /* uint32_t[1] is lsp_id and tunnel_id, below */ | |
949 | tlv->extended_tunnel_id.s_addr = uint32_ptr[2]; | |
950 | tlv->ipv4_tunnel_endpoint.s_addr = uint32_ptr[3]; | |
951 | ||
952 | uint16_t *uint16_ptr = (uint16_t *)(tlv_body_buf + LENGTH_1WORD); | |
953 | tlv->lsp_id = ntohs(uint16_ptr[0]); | |
954 | tlv->tunnel_id = ntohs(uint16_ptr[1]); | |
955 | ||
956 | return (struct pcep_object_tlv_header *)tlv; | |
957 | } | |
958 | ||
959 | struct pcep_object_tlv_header * | |
960 | pcep_decode_tlv_ipv6_lsp_identifiers(struct pcep_object_tlv_header *tlv_hdr, | |
961 | const uint8_t *tlv_body_buf) | |
962 | { | |
963 | struct pcep_object_tlv_ipv6_lsp_identifier *tlv = | |
964 | (struct pcep_object_tlv_ipv6_lsp_identifier *)common_tlv_create( | |
965 | tlv_hdr, | |
966 | sizeof(struct pcep_object_tlv_ipv6_lsp_identifier)); | |
967 | ||
968 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
969 | decode_ipv6(uint32_ptr, &tlv->ipv6_tunnel_sender); | |
970 | decode_ipv6(uint32_ptr + 5, &tlv->extended_tunnel_id); | |
971 | decode_ipv6(uint32_ptr + 9, &tlv->ipv6_tunnel_endpoint); | |
972 | ||
973 | uint16_t *uint16_ptr = (uint16_t *)(tlv_body_buf + LENGTH_4WORDS); | |
974 | tlv->lsp_id = htons(uint16_ptr[0]); | |
975 | tlv->tunnel_id = htons(uint16_ptr[1]); | |
976 | ||
977 | return (struct pcep_object_tlv_header *)tlv; | |
978 | } | |
979 | ||
980 | struct pcep_object_tlv_header * | |
981 | pcep_decode_tlv_lsp_error_code(struct pcep_object_tlv_header *tlv_hdr, | |
982 | const uint8_t *tlv_body_buf) | |
983 | { | |
984 | struct pcep_object_tlv_lsp_error_code *tlv = | |
985 | (struct pcep_object_tlv_lsp_error_code *)common_tlv_create( | |
986 | tlv_hdr, sizeof(struct pcep_object_tlv_lsp_error_code)); | |
987 | ||
988 | tlv->lsp_error_code = ntohl(*((uint32_t *)tlv_body_buf)); | |
989 | ||
990 | return (struct pcep_object_tlv_header *)tlv; | |
991 | } | |
992 | ||
993 | struct pcep_object_tlv_header * | |
994 | pcep_decode_tlv_rsvp_error_spec(struct pcep_object_tlv_header *tlv_hdr, | |
995 | const uint8_t *tlv_body_buf) | |
996 | { | |
997 | uint8_t class_num = tlv_body_buf[2]; | |
998 | uint8_t ctype = tlv_body_buf[3]; | |
999 | ||
1000 | if (class_num != RSVP_ERROR_SPEC_CLASS_NUM) { | |
1001 | pcep_log( | |
1002 | LOG_INFO, | |
1003 | "%s: Decoding RSVP Error Spec TLV, unknown class num [%d]", | |
1004 | __func__, class_num); | |
1005 | return NULL; | |
1006 | } | |
1007 | ||
1008 | if (ctype != RSVP_ERROR_SPEC_IPV4_CTYPE | |
1009 | && ctype != RSVP_ERROR_SPEC_IPV6_CTYPE) { | |
1010 | pcep_log(LOG_INFO, | |
1011 | "%s: Decoding RSVP Error Spec TLV, unknown ctype [%d]", | |
1012 | __func__, ctype); | |
1013 | return NULL; | |
1014 | } | |
1015 | ||
1016 | struct pcep_object_tlv_rsvp_error_spec *tlv = | |
1017 | (struct pcep_object_tlv_rsvp_error_spec *)common_tlv_create( | |
1018 | tlv_hdr, | |
1019 | sizeof(struct pcep_object_tlv_rsvp_error_spec)); | |
1020 | ||
1021 | tlv->class_num = class_num; | |
1022 | tlv->c_type = ctype; | |
1023 | ||
1024 | uint32_t *uint32_ptr = (uint32_t *)(tlv_body_buf + LENGTH_1WORD); | |
1025 | if (ctype == RSVP_ERROR_SPEC_IPV4_CTYPE) { | |
1026 | tlv->error_spec_ip.ipv4_error_node_address.s_addr = *uint32_ptr; | |
1027 | tlv->error_code = tlv_body_buf[LENGTH_2WORDS + 1]; | |
1028 | tlv->error_value = ntohs( | |
1029 | *((uint16_t *)(tlv_body_buf + LENGTH_2WORDS + 2))); | |
1030 | } else /* RSVP_ERROR_SPEC_IPV6_CTYPE */ | |
1031 | { | |
1032 | decode_ipv6(uint32_ptr, | |
1033 | &tlv->error_spec_ip.ipv6_error_node_address); | |
1034 | tlv->error_code = tlv_body_buf[LENGTH_5WORDS + 1]; | |
1035 | tlv->error_value = ntohs( | |
1036 | *((uint16_t *)(tlv_body_buf + LENGTH_5WORDS + 2))); | |
1037 | } | |
1038 | ||
1039 | return (struct pcep_object_tlv_header *)tlv; | |
1040 | } | |
1041 | ||
1042 | struct pcep_object_tlv_header * | |
1043 | pcep_decode_tlv_lsp_db_version(struct pcep_object_tlv_header *tlv_hdr, | |
1044 | const uint8_t *tlv_body_buf) | |
1045 | { | |
1046 | struct pcep_object_tlv_lsp_db_version *tlv = | |
1047 | (struct pcep_object_tlv_lsp_db_version *)common_tlv_create( | |
1048 | tlv_hdr, sizeof(struct pcep_object_tlv_lsp_db_version)); | |
1049 | ||
1050 | tlv->lsp_db_version = be64toh(*((uint64_t *)tlv_body_buf)); | |
1051 | ||
1052 | return (struct pcep_object_tlv_header *)tlv; | |
1053 | } | |
1054 | ||
1055 | struct pcep_object_tlv_header * | |
1056 | pcep_decode_tlv_speaker_entity_id(struct pcep_object_tlv_header *tlv_hdr, | |
1057 | const uint8_t *tlv_body_buf) | |
1058 | { | |
1059 | struct pcep_object_tlv_speaker_entity_identifier *tlv = | |
1060 | (struct pcep_object_tlv_speaker_entity_identifier *) | |
1061 | common_tlv_create( | |
1062 | tlv_hdr, | |
1063 | sizeof(struct | |
1064 | pcep_object_tlv_speaker_entity_identifier)); | |
1065 | ||
1066 | uint8_t num_entity_ids = tlv_hdr->encoded_tlv_length / LENGTH_1WORD; | |
1067 | if (num_entity_ids > MAX_ITERATIONS) { | |
1068 | num_entity_ids = MAX_ITERATIONS; | |
1069 | pcep_log( | |
1070 | LOG_INFO, | |
1071 | "%s: Decode Speaker Entity ID, truncating num entities from [%d] to [%d].", | |
1072 | __func__, num_entity_ids, MAX_ITERATIONS); | |
1073 | } | |
1074 | ||
1075 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
1076 | tlv->speaker_entity_id_list = dll_initialize(); | |
1077 | int i; | |
1078 | for (i = 0; i < num_entity_ids; i++) { | |
1079 | uint32_t *entity_id = | |
1080 | pceplib_malloc(PCEPLIB_MESSAGES, sizeof(uint32_t)); | |
1081 | *entity_id = ntohl(uint32_ptr[i]); | |
1082 | dll_append(tlv->speaker_entity_id_list, entity_id); | |
1083 | } | |
1084 | ||
1085 | return (struct pcep_object_tlv_header *)tlv; | |
1086 | } | |
1087 | ||
1088 | struct pcep_object_tlv_header * | |
1089 | pcep_decode_tlv_sr_pce_capability(struct pcep_object_tlv_header *tlv_hdr, | |
1090 | const uint8_t *tlv_body_buf) | |
1091 | { | |
1092 | struct pcep_object_tlv_sr_pce_capability *tlv = | |
1093 | (struct pcep_object_tlv_sr_pce_capability *)common_tlv_create( | |
1094 | tlv_hdr, | |
1095 | sizeof(struct pcep_object_tlv_sr_pce_capability)); | |
1096 | ||
1097 | tlv->flag_n = (tlv_body_buf[2] & TLV_SR_PCE_CAP_FLAG_N); | |
1098 | tlv->flag_x = (tlv_body_buf[2] & TLV_SR_PCE_CAP_FLAG_X); | |
1099 | tlv->max_sid_depth = tlv_body_buf[3]; | |
1100 | ||
1101 | return (struct pcep_object_tlv_header *)tlv; | |
1102 | } | |
1103 | ||
1104 | struct pcep_object_tlv_header * | |
1105 | pcep_decode_tlv_path_setup_type(struct pcep_object_tlv_header *tlv_hdr, | |
1106 | const uint8_t *tlv_body_buf) | |
1107 | { | |
1108 | struct pcep_object_tlv_path_setup_type *tlv = | |
1109 | (struct pcep_object_tlv_path_setup_type *)common_tlv_create( | |
1110 | tlv_hdr, | |
1111 | sizeof(struct pcep_object_tlv_path_setup_type)); | |
1112 | ||
1113 | tlv->path_setup_type = tlv_body_buf[3]; | |
1114 | ||
1115 | return (struct pcep_object_tlv_header *)tlv; | |
1116 | } | |
1117 | ||
1118 | struct pcep_object_tlv_header *pcep_decode_tlv_path_setup_type_capability( | |
1119 | struct pcep_object_tlv_header *tlv_hdr, const uint8_t *tlv_body_buf) | |
1120 | { | |
1121 | struct pcep_object_tlv_path_setup_type_capability *tlv = | |
1122 | (struct pcep_object_tlv_path_setup_type_capability *) | |
1123 | common_tlv_create( | |
1124 | tlv_hdr, | |
1125 | sizeof(struct | |
1126 | pcep_object_tlv_path_setup_type_capability)); | |
1127 | ||
1128 | uint8_t num_psts = tlv_body_buf[3]; | |
1129 | if (num_psts > MAX_ITERATIONS) { | |
1130 | pcep_log( | |
1131 | LOG_INFO, | |
1132 | "%s: Decode Path Setup Type Capability num PSTs [%d] exceeds MAX [%d] continuing anyways", | |
1133 | __func__, num_psts, MAX_ITERATIONS); | |
1134 | } | |
1135 | ||
1136 | int i; | |
1137 | tlv->pst_list = dll_initialize(); | |
1138 | for (i = 0; i < num_psts; i++) { | |
1139 | uint8_t *pst = | |
1140 | pceplib_malloc(PCEPLIB_MESSAGES, sizeof(uint8_t)); | |
1141 | *pst = tlv_body_buf[i + LENGTH_1WORD]; | |
1142 | dll_append(tlv->pst_list, pst); | |
1143 | } | |
1144 | ||
1145 | if (tlv->header.encoded_tlv_length | |
1146 | == (TLV_HEADER_LENGTH + LENGTH_1WORD + num_psts)) { | |
1147 | return (struct pcep_object_tlv_header *)tlv; | |
1148 | } | |
1149 | ||
1150 | uint8_t num_iterations = 0; | |
1151 | tlv->sub_tlv_list = dll_initialize(); | |
1152 | uint16_t buf_index = normalize_pcep_tlv_length( | |
1153 | TLV_HEADER_LENGTH + LENGTH_1WORD + num_psts); | |
1154 | while ((tlv->header.encoded_tlv_length - buf_index) > TLV_HEADER_LENGTH | |
7ed8c4b1 | 1155 | && num_iterations++ < MAX_ITERATIONS) { |
74971473 JG |
1156 | struct pcep_object_tlv_header *sub_tlv = |
1157 | pcep_decode_tlv(tlv_body_buf + buf_index); | |
1158 | if (sub_tlv == NULL) { | |
1159 | pcep_log( | |
1160 | LOG_INFO, | |
1161 | "%s: Decode PathSetupType Capability sub-TLV decode returned NULL", | |
1162 | __func__); | |
1163 | return (struct pcep_object_tlv_header *)tlv; | |
1164 | } | |
1165 | ||
1166 | buf_index += | |
1167 | normalize_pcep_tlv_length(sub_tlv->encoded_tlv_length); | |
1168 | dll_append(tlv->sub_tlv_list, sub_tlv); | |
1169 | } | |
1170 | ||
1171 | return (struct pcep_object_tlv_header *)tlv; | |
1172 | } | |
1173 | struct pcep_object_tlv_header * | |
1174 | pcep_decode_tlv_pol_id(struct pcep_object_tlv_header *tlv_hdr, | |
1175 | const uint8_t *tlv_body_buf) | |
1176 | { | |
1177 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
1178 | struct pcep_object_tlv_srpag_pol_id *ipv4 = | |
1179 | (struct pcep_object_tlv_srpag_pol_id *)common_tlv_create( | |
1180 | tlv_hdr, sizeof(struct pcep_object_tlv_srpag_pol_id)); | |
1181 | if (tlv_hdr->encoded_tlv_length == 8) { | |
1182 | ipv4->is_ipv4 = true; | |
1183 | ipv4->color = ntohl(uint32_ptr[0]); | |
1184 | ipv4->end_point.ipv4.s_addr = uint32_ptr[1]; | |
1185 | return (struct pcep_object_tlv_header *)ipv4; | |
1186 | } else { | |
1187 | ipv4->is_ipv4 = false; | |
1188 | struct pcep_object_tlv_srpag_pol_id *ipv6 = | |
1189 | (struct pcep_object_tlv_srpag_pol_id *)ipv4; | |
1190 | ipv6->color = ntohl(uint32_ptr[0]); | |
1191 | decode_ipv6(&uint32_ptr[1], &ipv6->end_point.ipv6); | |
1192 | return (struct pcep_object_tlv_header *)ipv6; | |
1193 | } | |
1194 | } | |
1195 | struct pcep_object_tlv_header * | |
1196 | pcep_decode_tlv_pol_name(struct pcep_object_tlv_header *tlv_hdr, | |
1197 | const uint8_t *tlv_body_buf) | |
1198 | { | |
1199 | struct pcep_object_tlv_srpag_pol_name *tlv = | |
1200 | (struct pcep_object_tlv_srpag_pol_name *)common_tlv_create( | |
1201 | tlv_hdr, sizeof(struct pcep_object_tlv_srpag_pol_name)); | |
1202 | ||
1203 | memcpy(tlv->name, tlv_body_buf, tlv->header.encoded_tlv_length); | |
1204 | ||
1205 | return (struct pcep_object_tlv_header *)tlv; | |
1206 | } | |
1207 | struct pcep_object_tlv_header * | |
1208 | pcep_decode_tlv_cpath_id(struct pcep_object_tlv_header *tlv_hdr, | |
1209 | const uint8_t *tlv_body_buf) | |
1210 | { | |
1211 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
1212 | struct pcep_object_tlv_srpag_cp_id *tlv = | |
1213 | (struct pcep_object_tlv_srpag_cp_id *)common_tlv_create( | |
1214 | tlv_hdr, sizeof(struct pcep_object_tlv_srpag_cp_id)); | |
1215 | ||
1216 | tlv->proto = tlv_body_buf[0]; | |
1217 | tlv->orig_asn = ntohl(uint32_ptr[1]); | |
1218 | decode_ipv6(&uint32_ptr[2], &tlv->orig_addres); | |
1219 | tlv->discriminator = ntohl(uint32_ptr[6]); | |
1220 | ||
1221 | return (struct pcep_object_tlv_header *)tlv; | |
1222 | } | |
1223 | struct pcep_object_tlv_header * | |
1224 | pcep_decode_tlv_cpath_preference(struct pcep_object_tlv_header *tlv_hdr, | |
1225 | const uint8_t *tlv_body_buf) | |
1226 | { | |
1227 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
1228 | struct pcep_object_tlv_srpag_cp_pref *tlv = | |
1229 | (struct pcep_object_tlv_srpag_cp_pref *)common_tlv_create( | |
1230 | tlv_hdr, sizeof(struct pcep_object_tlv_srpag_cp_pref)); | |
1231 | ||
1232 | tlv->preference = ntohl(uint32_ptr[0]); | |
1233 | ||
1234 | return (struct pcep_object_tlv_header *)tlv; | |
1235 | } | |
1236 | ||
1237 | struct pcep_object_tlv_header * | |
1238 | pcep_decode_tlv_vendor_info(struct pcep_object_tlv_header *tlv_hdr, | |
1239 | const uint8_t *tlv_body_buf) | |
1240 | { | |
1241 | struct pcep_object_tlv_vendor_info *tlv = | |
1242 | (struct pcep_object_tlv_vendor_info *)common_tlv_create( | |
1243 | tlv_hdr, sizeof(struct pcep_object_tlv_vendor_info)); | |
1244 | ||
1245 | uint32_t *uint32_ptr = (uint32_t *)tlv_body_buf; | |
1246 | tlv->enterprise_number = ntohl(uint32_ptr[0]); | |
1247 | tlv->enterprise_specific_info = ntohl(uint32_ptr[1]); | |
1248 | ||
1249 | return (struct pcep_object_tlv_header *)tlv; | |
1250 | } | |
1251 | ||
1252 | struct pcep_object_tlv_header * | |
1253 | pcep_decode_tlv_arbitrary(struct pcep_object_tlv_header *tlv_hdr, | |
1254 | const uint8_t *tlv_body_buf) | |
1255 | { | |
1256 | struct pcep_object_tlv_arbitrary *tlv_arbitrary = | |
1257 | (struct pcep_object_tlv_arbitrary *)common_tlv_create( | |
1258 | tlv_hdr, sizeof(struct pcep_object_tlv_arbitrary)); | |
1259 | ||
1260 | uint16_t length = tlv_hdr->encoded_tlv_length; | |
1261 | if (length > MAX_ARBITRARY_SIZE) { | |
1262 | /* TODO should we also reset the tlv_hdr->encoded_tlv_length ? | |
1263 | */ | |
1264 | length = MAX_ARBITRARY_SIZE; | |
1265 | pcep_log( | |
1266 | LOG_INFO, | |
1267 | "%s: Decoding Arbitrary TLV , truncate path name from [%d] to [%d].\",", | |
1268 | __func__, tlv_hdr->encoded_tlv_length, | |
1269 | MAX_ARBITRARY_SIZE); | |
1270 | } | |
1271 | ||
1272 | tlv_arbitrary->data_length = length; | |
1273 | tlv_arbitrary->arbitraty_type = tlv_hdr->type; | |
1274 | tlv_hdr->type = PCEP_OBJ_TLV_TYPE_ARBITRARY; | |
1275 | memcpy(tlv_arbitrary->data, tlv_body_buf, length); | |
1276 | ||
1277 | return (struct pcep_object_tlv_header *)tlv_arbitrary; | |
1278 | } | |
1279 | ||
1280 | struct pcep_object_tlv_header * | |
1281 | pcep_decode_tlv_of_list(struct pcep_object_tlv_header *tlv_hdr, | |
1282 | const uint8_t *tlv_body_buf) | |
1283 | { | |
1284 | struct pcep_object_tlv_of_list *of_tlv = | |
1285 | (struct pcep_object_tlv_of_list *)common_tlv_create( | |
1286 | tlv_hdr, sizeof(struct pcep_object_tlv_of_list)); | |
1287 | ||
1288 | of_tlv->of_list = dll_initialize(); | |
1289 | uint16_t *uint16_ptr = (uint16_t *)tlv_body_buf; | |
1290 | int i = 0; | |
1291 | for (; i < tlv_hdr->encoded_tlv_length && i < MAX_ITERATIONS; i++) { | |
1292 | uint16_t *of_code_ptr = | |
1293 | pceplib_malloc(PCEPLIB_MESSAGES, sizeof(uint16_t)); | |
1294 | *of_code_ptr = ntohs(uint16_ptr[i]); | |
1295 | dll_append(of_tlv->of_list, of_code_ptr); | |
1296 | } | |
1297 | ||
1298 | return (struct pcep_object_tlv_header *)of_tlv; | |
1299 | } |