]>
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 Objects. | |
26 | */ | |
27 | ||
1f8031f7 DL |
28 | #ifdef HAVE_CONFIG_H |
29 | #include "config.h" | |
30 | #endif | |
31 | ||
74971473 JG |
32 | #include <stdlib.h> |
33 | #include <string.h> | |
34 | ||
35 | #include "pcep_msg_objects.h" | |
36 | #include "pcep_msg_encoding.h" | |
37 | #include "pcep_utils_logging.h" | |
38 | #include "pcep_utils_memory.h" | |
39 | ||
40 | void write_object_header(struct pcep_object_header *object_hdr, | |
41 | uint16_t object_length, uint8_t *buf); | |
42 | void pcep_decode_object_hdr(const uint8_t *obj_buf, | |
43 | struct pcep_object_header *obj_hdr); | |
44 | void set_ro_subobj_fields(struct pcep_object_ro_subobj *subobj, bool flag_l, | |
45 | uint8_t subobj_type); | |
46 | ||
47 | /* | |
48 | * forward declarations for initialize_object_encoders() | |
49 | */ | |
50 | uint16_t pcep_encode_obj_open(struct pcep_object_header *obj, | |
51 | struct pcep_versioning *versioning, uint8_t *buf); | |
52 | uint16_t pcep_encode_obj_rp(struct pcep_object_header *obj, | |
53 | struct pcep_versioning *versioning, uint8_t *buf); | |
54 | uint16_t pcep_encode_obj_nopath(struct pcep_object_header *obj, | |
55 | struct pcep_versioning *versioning, | |
56 | uint8_t *buf); | |
57 | uint16_t pcep_encode_obj_endpoints(struct pcep_object_header *obj, | |
58 | struct pcep_versioning *versioning, | |
59 | uint8_t *buf); | |
60 | uint16_t pcep_encode_obj_association(struct pcep_object_header *obj, | |
61 | struct pcep_versioning *versioning, | |
62 | uint8_t *buf); | |
63 | uint16_t pcep_encode_obj_bandwidth(struct pcep_object_header *obj, | |
64 | struct pcep_versioning *versioning, | |
65 | uint8_t *buf); | |
66 | uint16_t pcep_encode_obj_metric(struct pcep_object_header *obj, | |
67 | struct pcep_versioning *versioning, | |
68 | uint8_t *buf); | |
69 | uint16_t pcep_encode_obj_ro(struct pcep_object_header *obj, | |
70 | struct pcep_versioning *versioning, uint8_t *buf); | |
71 | uint16_t pcep_encode_obj_lspa(struct pcep_object_header *obj, | |
72 | struct pcep_versioning *versioning, uint8_t *buf); | |
73 | uint16_t pcep_encode_obj_svec(struct pcep_object_header *obj, | |
74 | struct pcep_versioning *versioning, uint8_t *buf); | |
75 | uint16_t pcep_encode_obj_notify(struct pcep_object_header *obj, | |
76 | struct pcep_versioning *versioning, | |
77 | uint8_t *buf); | |
78 | uint16_t pcep_encode_obj_error(struct pcep_object_header *error, | |
79 | struct pcep_versioning *versioning, | |
80 | uint8_t *buf); | |
81 | uint16_t pcep_encode_obj_close(struct pcep_object_header *close, | |
82 | struct pcep_versioning *versioning, | |
83 | uint8_t *buf); | |
84 | uint16_t pcep_encode_obj_srp(struct pcep_object_header *obj, | |
85 | struct pcep_versioning *versioning, uint8_t *buf); | |
86 | uint16_t pcep_encode_obj_lsp(struct pcep_object_header *obj, | |
87 | struct pcep_versioning *versioning, uint8_t *buf); | |
88 | uint16_t pcep_encode_obj_vendor_info(struct pcep_object_header *obj, | |
89 | struct pcep_versioning *versioning, | |
90 | uint8_t *buf); | |
91 | uint16_t pcep_encode_obj_inter_layer(struct pcep_object_header *obj, | |
92 | struct pcep_versioning *versioning, | |
93 | uint8_t *buf); | |
94 | uint16_t pcep_encode_obj_switch_layer(struct pcep_object_header *obj, | |
95 | struct pcep_versioning *versioning, | |
96 | uint8_t *buf); | |
97 | uint16_t pcep_encode_obj_req_adap_cap(struct pcep_object_header *obj, | |
98 | struct pcep_versioning *versioning, | |
99 | uint8_t *buf); | |
100 | uint16_t pcep_encode_obj_server_ind(struct pcep_object_header *obj, | |
101 | struct pcep_versioning *versioning, | |
102 | uint8_t *buf); | |
103 | uint16_t pcep_encode_obj_objective_function(struct pcep_object_header *obj, | |
104 | struct pcep_versioning *versioning, | |
105 | uint8_t *buf); | |
106 | typedef uint16_t (*object_encoder_funcptr)(struct pcep_object_header *, | |
107 | struct pcep_versioning *versioning, | |
108 | uint8_t *buf); | |
109 | ||
110 | #define MAX_OBJECT_ENCODER_INDEX 64 | |
111 | ||
112 | #define PCEP_ENCODERS_ARGS \ | |
113 | struct pcep_object_header *, struct pcep_versioning *versioning, \ | |
114 | uint8_t *buf | |
115 | uint16_t (*const object_encoders[MAX_OBJECT_ENCODER_INDEX])( | |
116 | PCEP_ENCODERS_ARGS) = { | |
117 | [PCEP_OBJ_CLASS_OPEN] = pcep_encode_obj_open, | |
118 | [PCEP_OBJ_CLASS_RP] = pcep_encode_obj_rp, | |
119 | [PCEP_OBJ_CLASS_NOPATH] = pcep_encode_obj_nopath, | |
120 | [PCEP_OBJ_CLASS_ENDPOINTS] = pcep_encode_obj_endpoints, | |
121 | [PCEP_OBJ_CLASS_BANDWIDTH] = pcep_encode_obj_bandwidth, | |
122 | [PCEP_OBJ_CLASS_METRIC] = pcep_encode_obj_metric, | |
123 | [PCEP_OBJ_CLASS_ERO] = pcep_encode_obj_ro, | |
124 | [PCEP_OBJ_CLASS_RRO] = pcep_encode_obj_ro, | |
125 | [PCEP_OBJ_CLASS_LSPA] = pcep_encode_obj_lspa, | |
126 | [PCEP_OBJ_CLASS_IRO] = pcep_encode_obj_ro, | |
127 | [PCEP_OBJ_CLASS_SVEC] = pcep_encode_obj_svec, | |
128 | [PCEP_OBJ_CLASS_NOTF] = pcep_encode_obj_notify, | |
129 | [PCEP_OBJ_CLASS_ERROR] = pcep_encode_obj_error, | |
130 | [PCEP_OBJ_CLASS_CLOSE] = pcep_encode_obj_close, | |
131 | [PCEP_OBJ_CLASS_LSP] = pcep_encode_obj_lsp, | |
132 | [PCEP_OBJ_CLASS_SRP] = pcep_encode_obj_srp, | |
133 | [PCEP_OBJ_CLASS_ASSOCIATION] = pcep_encode_obj_association, | |
134 | [PCEP_OBJ_CLASS_INTER_LAYER] = pcep_encode_obj_inter_layer, | |
135 | [PCEP_OBJ_CLASS_SWITCH_LAYER] = pcep_encode_obj_switch_layer, | |
136 | [PCEP_OBJ_CLASS_REQ_ADAP_CAP] = pcep_encode_obj_req_adap_cap, | |
137 | [PCEP_OBJ_CLASS_SERVER_IND] = pcep_encode_obj_server_ind, | |
138 | [PCEP_OBJ_CLASS_VENDOR_INFO] = pcep_encode_obj_vendor_info, | |
139 | [PCEP_OBJ_CLASS_OF] = pcep_encode_obj_objective_function, | |
140 | }; | |
141 | /* | |
142 | * forward declarations for initialize_object_decoders() | |
143 | */ | |
144 | struct pcep_object_header *pcep_decode_obj_open(struct pcep_object_header *hdr, | |
145 | const uint8_t *buf); | |
146 | struct pcep_object_header *pcep_decode_obj_rp(struct pcep_object_header *hdr, | |
147 | const uint8_t *buf); | |
148 | struct pcep_object_header * | |
149 | pcep_decode_obj_nopath(struct pcep_object_header *hdr, const uint8_t *buf); | |
150 | struct pcep_object_header * | |
151 | pcep_decode_obj_endpoints(struct pcep_object_header *hdr, const uint8_t *buf); | |
152 | struct pcep_object_header * | |
153 | pcep_decode_obj_association(struct pcep_object_header *hdr, const uint8_t *buf); | |
154 | struct pcep_object_header * | |
155 | pcep_decode_obj_bandwidth(struct pcep_object_header *hdr, const uint8_t *buf); | |
156 | struct pcep_object_header * | |
157 | pcep_decode_obj_metric(struct pcep_object_header *hdr, const uint8_t *buf); | |
158 | struct pcep_object_header *pcep_decode_obj_ro(struct pcep_object_header *hdr, | |
159 | const uint8_t *buf); | |
160 | struct pcep_object_header *pcep_decode_obj_lspa(struct pcep_object_header *hdr, | |
161 | const uint8_t *buf); | |
162 | struct pcep_object_header *pcep_decode_obj_svec(struct pcep_object_header *hdr, | |
163 | const uint8_t *buf); | |
164 | struct pcep_object_header * | |
165 | pcep_decode_obj_notify(struct pcep_object_header *hdr, const uint8_t *buf); | |
166 | struct pcep_object_header *pcep_decode_obj_error(struct pcep_object_header *hdr, | |
167 | const uint8_t *buf); | |
168 | struct pcep_object_header *pcep_decode_obj_close(struct pcep_object_header *hdr, | |
169 | const uint8_t *buf); | |
170 | struct pcep_object_header *pcep_decode_obj_srp(struct pcep_object_header *hdr, | |
171 | const uint8_t *buf); | |
172 | struct pcep_object_header *pcep_decode_obj_lsp(struct pcep_object_header *hdr, | |
173 | const uint8_t *buf); | |
174 | struct pcep_object_header * | |
175 | pcep_decode_obj_vendor_info(struct pcep_object_header *hdr, const uint8_t *buf); | |
176 | struct pcep_object_header * | |
177 | pcep_decode_obj_inter_layer(struct pcep_object_header *hdr, const uint8_t *buf); | |
178 | struct pcep_object_header * | |
179 | pcep_decode_obj_switch_layer(struct pcep_object_header *hdr, | |
180 | const uint8_t *buf); | |
181 | struct pcep_object_header * | |
182 | pcep_decode_obj_req_adap_cap(struct pcep_object_header *hdr, | |
183 | const uint8_t *buf); | |
184 | struct pcep_object_header * | |
185 | pcep_decode_obj_server_ind(struct pcep_object_header *hdr, const uint8_t *buf); | |
186 | struct pcep_object_header * | |
187 | pcep_decode_obj_objective_function(struct pcep_object_header *hdr, | |
188 | const uint8_t *buf); | |
189 | typedef struct pcep_object_header *(*object_decoder_funcptr)( | |
190 | struct pcep_object_header *, const uint8_t *buf); | |
191 | ||
192 | #define PCEP_DECODERS_ARGS struct pcep_object_header *, const uint8_t *buf | |
193 | ||
194 | struct pcep_object_header *(*const object_decoders[MAX_OBJECT_ENCODER_INDEX])( | |
195 | PCEP_DECODERS_ARGS) = { | |
196 | [PCEP_OBJ_CLASS_OPEN] = pcep_decode_obj_open, | |
197 | [PCEP_OBJ_CLASS_RP] = pcep_decode_obj_rp, | |
198 | [PCEP_OBJ_CLASS_NOPATH] = pcep_decode_obj_nopath, | |
199 | [PCEP_OBJ_CLASS_ENDPOINTS] = pcep_decode_obj_endpoints, | |
200 | [PCEP_OBJ_CLASS_BANDWIDTH] = pcep_decode_obj_bandwidth, | |
201 | [PCEP_OBJ_CLASS_METRIC] = pcep_decode_obj_metric, | |
202 | [PCEP_OBJ_CLASS_ERO] = pcep_decode_obj_ro, | |
203 | [PCEP_OBJ_CLASS_RRO] = pcep_decode_obj_ro, | |
204 | [PCEP_OBJ_CLASS_LSPA] = pcep_decode_obj_lspa, | |
205 | [PCEP_OBJ_CLASS_IRO] = pcep_decode_obj_ro, | |
206 | [PCEP_OBJ_CLASS_SVEC] = pcep_decode_obj_svec, | |
207 | [PCEP_OBJ_CLASS_NOTF] = pcep_decode_obj_notify, | |
208 | [PCEP_OBJ_CLASS_ERROR] = pcep_decode_obj_error, | |
209 | [PCEP_OBJ_CLASS_CLOSE] = pcep_decode_obj_close, | |
210 | [PCEP_OBJ_CLASS_LSP] = pcep_decode_obj_lsp, | |
211 | [PCEP_OBJ_CLASS_SRP] = pcep_decode_obj_srp, | |
212 | [PCEP_OBJ_CLASS_ASSOCIATION] = pcep_decode_obj_association, | |
213 | [PCEP_OBJ_CLASS_INTER_LAYER] = pcep_decode_obj_inter_layer, | |
214 | [PCEP_OBJ_CLASS_SWITCH_LAYER] = pcep_decode_obj_switch_layer, | |
215 | [PCEP_OBJ_CLASS_REQ_ADAP_CAP] = pcep_decode_obj_req_adap_cap, | |
216 | [PCEP_OBJ_CLASS_SERVER_IND] = pcep_decode_obj_server_ind, | |
217 | [PCEP_OBJ_CLASS_VENDOR_INFO] = pcep_decode_obj_vendor_info, | |
218 | [PCEP_OBJ_CLASS_OF] = pcep_decode_obj_objective_function, | |
219 | }; | |
220 | ||
221 | /* Object lengths, including the Object Header. | |
222 | * Used by pcep_object_get_length() and pcep_object_has_tlvs() */ | |
223 | static uint8_t pcep_object_class_lengths[] = { | |
224 | 0, /* Object class 0 unused */ | |
225 | 8, /* PCEP_OBJ_CLASS_OPEN = 1 */ | |
226 | 12, /* PCEP_OBJ_CLASS_RP = 2 */ | |
227 | 16, /* PCEP_OBJ_CLASS_NOPATH = 3, includes 8 for mandatory TLV */ | |
228 | 0, /* PCEP_OBJ_CLASS_ENDPOINTS = 4, could be ipv4 or ipv6, setting to 0 | |
229 | */ | |
230 | 8, /* PCEP_OBJ_CLASS_BANDWIDTH = 5 */ | |
231 | 12, /* PCEP_OBJ_CLASS_METRIC = 6 */ | |
232 | 0, /* PCEP_OBJ_CLASS_ERO = 7, setting 0, ROs cannot have TLVs */ | |
233 | 0, /* PCEP_OBJ_CLASS_RRO = 8, setting 0, ROs cannot have TLVs */ | |
234 | 20, /* PCEP_OBJ_CLASS_LSPA = 9 */ | |
235 | 0, /* PCEP_OBJ_CLASS_IRO = 10, setting 0, ROs cannot have TLVs */ | |
236 | 0, /* PCEP_OBJ_CLASS_SVEC = 11, SVECs cannot have TLVs */ | |
237 | 8, /* PCEP_OBJ_CLASS_NOTF = 12 */ | |
238 | 8, /* PCEP_OBJ_CLASS_ERROR = 13 */ | |
239 | 0, /* Object class 14 unused */ | |
240 | 8, /* PCEP_OBJ_CLASS_CLOSE = 15 */ | |
241 | 0, 0, 0, 0, 0, /* Object classes 16 - 20 are not used */ | |
242 | 8, /* PCEP_OBJ_CLASS_OF = 21 */ | |
243 | 0, 0, 0, 0, 0, /* Object classes 22 - 26 are not used */ | |
244 | 0, 0, 0, 0, 0, /* Object classes 27 - 31 are not used */ | |
245 | 8, /* PCEP_OBJ_CLASS_LSP = 32 */ | |
246 | 12, /* PCEP_OBJ_CLASS_SRP = 33 */ | |
247 | 12, /* PCEP_OBJ_CLASS_VENDOR_INFO = 34 */ | |
248 | 0, /* Object class 35 unused */ | |
249 | 0, /* PCEP_OBJ_CLASS_INTER_LAYER = 36, cannot have TLVs */ | |
250 | 0, /* PCEP_OBJ_CLASS_SWITCH_LAYER = 37, cannot have TLVs */ | |
251 | 0, /* PCEP_OBJ_CLASS_REQ_ADAP_CAP = 38, cannot have TLVs*/ | |
252 | 8, /* PCEP_OBJ_CLASS_SERVER_IND = 39 */ | |
253 | 0, /* PCEP_OBJ_CLASS_ASSOCIATION = 40, cannot have TLVs */ | |
254 | }; | |
255 | ||
256 | /* | |
257 | * The TLVs can have strange length values, since they do not include padding in | |
258 | * the TLV header length, but that extra padding must be taken into account by | |
259 | * the enclosing object by rounding up to the next 4 byte boundary. | |
260 | * Example returned lengths: | |
261 | * normalize_length(4) = 4, normalize_length(5) = 8, normalize_length(6) | |
262 | * = 8, normalize_length(7) = 8, normalize_length(8) = 8 | |
263 | * normalize_length(9) = 12, normalize_length(10) = 12, normalize_length(11) = | |
264 | * 12, normalize_length(12) = 12, normalize_length(13) = 13... | |
265 | */ | |
266 | uint16_t normalize_pcep_tlv_length(uint16_t length) | |
267 | { | |
268 | return (length % 4 == 0) ? length : (length + (4 - (length % 4))); | |
269 | } | |
270 | ||
271 | /* | |
272 | * Encoding functions | |
273 | */ | |
274 | uint16_t pcep_encode_object(struct pcep_object_header *object_hdr, | |
275 | struct pcep_versioning *versioning, uint8_t *buf) | |
276 | { | |
277 | ||
278 | if (object_hdr->object_class >= MAX_OBJECT_ENCODER_INDEX) { | |
279 | pcep_log(LOG_INFO, | |
280 | "%s: Cannot encode unknown Object class [%d]", | |
281 | __func__, object_hdr->object_class); | |
282 | return 0; | |
283 | } | |
284 | ||
285 | object_encoder_funcptr obj_encoder = | |
286 | object_encoders[object_hdr->object_class]; | |
287 | if (obj_encoder == NULL) { | |
288 | pcep_log(LOG_INFO, | |
289 | "%s: No object encoder found for Object class [%d]", | |
290 | __func__, object_hdr->object_class); | |
291 | return 0; | |
292 | } | |
293 | ||
294 | uint16_t object_length = OBJECT_HEADER_LENGTH | |
295 | + obj_encoder(object_hdr, versioning, | |
296 | buf + OBJECT_HEADER_LENGTH); | |
297 | double_linked_list_node *node = | |
298 | (object_hdr->tlv_list == NULL ? NULL | |
299 | : object_hdr->tlv_list->head); | |
300 | for (; node != NULL; node = node->next_node) { | |
301 | /* Returns the length of the TLV, including the TLV header */ | |
302 | object_length += pcep_encode_tlv( | |
303 | (struct pcep_object_tlv_header *)node->data, versioning, | |
304 | buf + object_length); | |
305 | } | |
306 | object_length = normalize_pcep_tlv_length(object_length); | |
307 | write_object_header(object_hdr, object_length, buf); | |
308 | object_hdr->encoded_object = buf; | |
309 | object_hdr->encoded_object_length = object_length; | |
310 | ||
311 | return object_length; | |
312 | } | |
313 | ||
314 | ||
315 | /* Object Header | |
316 | * | |
317 | * 0 1 2 3 | |
318 | * 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 | |
319 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
320 | * | Object-Class | OT |Res|P|I| Object Length (bytes) | | |
321 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
322 | * | | | |
323 | * // (Object body) // | |
324 | * | | | |
325 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
326 | * | |
327 | */ | |
328 | ||
329 | void write_object_header(struct pcep_object_header *object_hdr, | |
330 | uint16_t object_length, uint8_t *buf) | |
331 | { | |
332 | buf[0] = object_hdr->object_class; | |
333 | buf[1] = ((object_hdr->object_type << 4) | |
334 | | (object_hdr->flag_p ? OBJECT_HEADER_FLAG_P : 0x00) | |
335 | | (object_hdr->flag_i ? OBJECT_HEADER_FLAG_I : 0x00)); | |
336 | uint16_t net_order_length = htons(object_length); | |
337 | memcpy(buf + 2, &net_order_length, sizeof(net_order_length)); | |
338 | } | |
339 | ||
340 | ||
341 | /* | |
342 | * Functions to encode objects | |
343 | * - they will be passed a pointer to a buffer to write the object body, | |
344 | * which is past the object header. | |
345 | * - they should return the object body length, not including the object header | |
346 | * length. | |
347 | */ | |
348 | ||
349 | uint16_t pcep_encode_obj_open(struct pcep_object_header *hdr, | |
350 | struct pcep_versioning *versioning, | |
351 | uint8_t *obj_body_buf) | |
352 | { | |
353 | (void)versioning; | |
354 | struct pcep_object_open *open = (struct pcep_object_open *)hdr; | |
355 | obj_body_buf[0] = (open->open_version << 5) & 0xe0; | |
356 | obj_body_buf[1] = open->open_keepalive; | |
357 | obj_body_buf[2] = open->open_deadtimer; | |
358 | obj_body_buf[3] = open->open_sid; | |
359 | ||
360 | return LENGTH_1WORD; | |
361 | } | |
362 | ||
363 | uint16_t pcep_encode_obj_rp(struct pcep_object_header *hdr, | |
364 | struct pcep_versioning *versioning, | |
365 | uint8_t *obj_body_buf) | |
366 | { | |
367 | (void)versioning; | |
368 | struct pcep_object_rp *rp = (struct pcep_object_rp *)hdr; | |
369 | obj_body_buf[3] = ((rp->flag_strict ? OBJECT_RP_FLAG_O : 0x00) | |
370 | | (rp->flag_bidirectional ? OBJECT_RP_FLAG_B : 0x00) | |
371 | | (rp->flag_reoptimization ? OBJECT_RP_FLAG_R : 0x00) | |
372 | | (rp->flag_of ? OBJECT_RP_FLAG_OF : 0x00) | |
373 | | (rp->priority & 0x07)); | |
374 | uint32_t *uint32_ptr = (uint32_t *)(obj_body_buf + 4); | |
375 | *uint32_ptr = htonl(rp->request_id); | |
376 | ||
377 | return LENGTH_2WORDS; | |
378 | } | |
379 | ||
380 | uint16_t pcep_encode_obj_notify(struct pcep_object_header *hdr, | |
381 | struct pcep_versioning *versioning, | |
382 | uint8_t *obj_body_buf) | |
383 | { | |
384 | (void)versioning; | |
385 | struct pcep_object_notify *notify = (struct pcep_object_notify *)hdr; | |
386 | obj_body_buf[2] = notify->notification_type; | |
387 | obj_body_buf[3] = notify->notification_value; | |
388 | ||
389 | return LENGTH_1WORD; | |
390 | } | |
391 | ||
392 | uint16_t pcep_encode_obj_nopath(struct pcep_object_header *hdr, | |
393 | struct pcep_versioning *versioning, | |
394 | uint8_t *obj_body_buf) | |
395 | { | |
396 | (void)versioning; | |
397 | struct pcep_object_nopath *nopath = (struct pcep_object_nopath *)hdr; | |
398 | obj_body_buf[0] = nopath->ni; | |
399 | obj_body_buf[1] = ((nopath->flag_c) ? OBJECT_NOPATH_FLAG_C : 0x00); | |
400 | ||
401 | return LENGTH_1WORD; | |
402 | } | |
403 | ||
404 | uint16_t pcep_encode_obj_association(struct pcep_object_header *hdr, | |
405 | struct pcep_versioning *versioning, | |
406 | uint8_t *obj_body_buf) | |
407 | { | |
408 | (void)versioning; | |
409 | uint16_t *uint16_ptr = (uint16_t *)obj_body_buf; | |
410 | uint32_t *uint32_ptr = (uint32_t *)obj_body_buf; | |
411 | if (hdr->object_type == PCEP_OBJ_TYPE_ASSOCIATION_IPV4) { | |
412 | struct pcep_object_association_ipv4 *ipv4 = | |
413 | (struct pcep_object_association_ipv4 *)hdr; | |
414 | obj_body_buf[3] = | |
415 | (ipv4->R_flag ? OBJECT_ASSOCIATION_FLAG_R : 0x00); | |
416 | uint16_ptr[2] = htons(ipv4->association_type); | |
417 | uint16_ptr[3] = htons(ipv4->association_id); | |
418 | uint32_ptr[2] = ipv4->src.s_addr; | |
419 | ||
420 | return LENGTH_3WORDS; | |
421 | } else { | |
422 | struct pcep_object_association_ipv6 *ipv6 = | |
423 | (struct pcep_object_association_ipv6 *)hdr; | |
424 | obj_body_buf[3] = | |
425 | (ipv6->R_flag ? OBJECT_ASSOCIATION_FLAG_R : 0x00); | |
426 | uint16_ptr[2] = htons(ipv6->association_type); | |
427 | uint16_ptr[3] = htons(ipv6->association_id); | |
428 | memcpy(uint32_ptr, &ipv6->src, sizeof(struct in6_addr)); | |
429 | ||
430 | return LENGTH_6WORDS; | |
431 | } | |
432 | } | |
433 | ||
434 | uint16_t pcep_encode_obj_endpoints(struct pcep_object_header *hdr, | |
435 | struct pcep_versioning *versioning, | |
436 | uint8_t *obj_body_buf) | |
437 | { | |
438 | (void)versioning; | |
439 | uint32_t *uint32_ptr = (uint32_t *)obj_body_buf; | |
440 | if (hdr->object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV4) { | |
441 | struct pcep_object_endpoints_ipv4 *ipv4 = | |
442 | (struct pcep_object_endpoints_ipv4 *)hdr; | |
443 | uint32_ptr[0] = ipv4->src_ipv4.s_addr; | |
444 | uint32_ptr[1] = ipv4->dst_ipv4.s_addr; | |
445 | ||
446 | return LENGTH_2WORDS; | |
447 | } else { | |
448 | struct pcep_object_endpoints_ipv6 *ipv6 = | |
449 | (struct pcep_object_endpoints_ipv6 *)hdr; | |
450 | memcpy(uint32_ptr, &ipv6->src_ipv6, sizeof(struct in6_addr)); | |
451 | memcpy(&uint32_ptr[4], &ipv6->dst_ipv6, | |
452 | sizeof(struct in6_addr)); | |
453 | ||
454 | return LENGTH_8WORDS; | |
455 | } | |
456 | } | |
457 | ||
458 | uint16_t pcep_encode_obj_bandwidth(struct pcep_object_header *hdr, | |
459 | struct pcep_versioning *versioning, | |
460 | uint8_t *obj_body_buf) | |
461 | { | |
462 | (void)versioning; | |
463 | struct pcep_object_bandwidth *bandwidth = | |
464 | (struct pcep_object_bandwidth *)hdr; | |
465 | uint32_t *uint32_ptr = (uint32_t *)obj_body_buf; | |
4c98b89e | 466 | /* Seems like the compiler doesn't correctly copy the float, so memcpy() |
74971473 JG |
467 | * it */ |
468 | memcpy(uint32_ptr, &(bandwidth->bandwidth), sizeof(uint32_t)); | |
469 | *uint32_ptr = htonl(*uint32_ptr); | |
470 | ||
471 | return LENGTH_1WORD; | |
472 | } | |
473 | ||
474 | uint16_t pcep_encode_obj_metric(struct pcep_object_header *hdr, | |
475 | struct pcep_versioning *versioning, | |
476 | uint8_t *obj_body_buf) | |
477 | { | |
478 | (void)versioning; | |
479 | struct pcep_object_metric *metric = (struct pcep_object_metric *)hdr; | |
480 | obj_body_buf[2] = ((metric->flag_c ? OBJECT_METRIC_FLAC_C : 0x00) | |
481 | | (metric->flag_b ? OBJECT_METRIC_FLAC_B : 0x00)); | |
482 | obj_body_buf[3] = metric->type; | |
483 | uint32_t *uint32_ptr = (uint32_t *)(obj_body_buf + 4); | |
4c98b89e | 484 | /* Seems like the compiler doesn't correctly copy the float, so memcpy() |
74971473 JG |
485 | * it */ |
486 | memcpy(uint32_ptr, &(metric->value), sizeof(uint32_t)); | |
487 | *uint32_ptr = htonl(*uint32_ptr); | |
488 | ||
489 | return LENGTH_2WORDS; | |
490 | } | |
491 | ||
492 | uint16_t pcep_encode_obj_lspa(struct pcep_object_header *hdr, | |
493 | struct pcep_versioning *versioning, | |
494 | uint8_t *obj_body_buf) | |
495 | { | |
496 | (void)versioning; | |
497 | struct pcep_object_lspa *lspa = (struct pcep_object_lspa *)hdr; | |
498 | uint32_t *uint32_ptr = (uint32_t *)obj_body_buf; | |
499 | uint32_ptr[0] = htonl(lspa->lspa_exclude_any); | |
500 | uint32_ptr[1] = htonl(lspa->lspa_include_any); | |
501 | uint32_ptr[2] = htonl(lspa->lspa_include_all); | |
502 | obj_body_buf[12] = lspa->setup_priority; | |
503 | obj_body_buf[13] = lspa->holding_priority; | |
504 | obj_body_buf[14] = | |
505 | (lspa->flag_local_protection ? OBJECT_LSPA_FLAG_L : 0x00); | |
506 | ||
507 | return LENGTH_4WORDS; | |
508 | } | |
509 | ||
510 | uint16_t pcep_encode_obj_svec(struct pcep_object_header *hdr, | |
511 | struct pcep_versioning *versioning, | |
512 | uint8_t *obj_body_buf) | |
513 | { | |
514 | (void)versioning; | |
515 | struct pcep_object_svec *svec = (struct pcep_object_svec *)hdr; | |
516 | obj_body_buf[3] = | |
517 | ((svec->flag_srlg_diverse ? OBJECT_SVEC_FLAG_S : 0x00) | |
518 | | (svec->flag_node_diverse ? OBJECT_SVEC_FLAG_N : 0x00) | |
519 | | (svec->flag_link_diverse ? OBJECT_SVEC_FLAG_L : 0x00)); | |
520 | ||
521 | if (svec->request_id_list == NULL) { | |
522 | return LENGTH_1WORD; | |
523 | } | |
524 | ||
525 | int index = 1; | |
526 | uint32_t *uint32_ptr = (uint32_t *)obj_body_buf; | |
527 | double_linked_list_node *node = svec->request_id_list->head; | |
528 | for (; node != NULL; node = node->next_node) { | |
529 | uint32_ptr[index++] = htonl(*((uint32_t *)(node->data))); | |
530 | } | |
531 | ||
532 | return LENGTH_1WORD | |
533 | + (svec->request_id_list->num_entries * sizeof(uint32_t)); | |
534 | } | |
535 | ||
536 | uint16_t pcep_encode_obj_error(struct pcep_object_header *hdr, | |
537 | struct pcep_versioning *versioning, | |
538 | uint8_t *obj_body_buf) | |
539 | { | |
540 | (void)versioning; | |
541 | struct pcep_object_error *error = (struct pcep_object_error *)hdr; | |
542 | obj_body_buf[2] = error->error_type; | |
543 | obj_body_buf[3] = error->error_value; | |
544 | ||
545 | return LENGTH_1WORD; | |
546 | } | |
547 | ||
548 | uint16_t pcep_encode_obj_close(struct pcep_object_header *hdr, | |
549 | struct pcep_versioning *versioning, | |
550 | uint8_t *obj_body_buf) | |
551 | { | |
552 | (void)versioning; | |
553 | struct pcep_object_close *close = (struct pcep_object_close *)hdr; | |
554 | obj_body_buf[3] = close->reason; | |
555 | ||
556 | return LENGTH_1WORD; | |
557 | } | |
558 | ||
559 | uint16_t pcep_encode_obj_srp(struct pcep_object_header *hdr, | |
560 | struct pcep_versioning *versioning, | |
561 | uint8_t *obj_body_buf) | |
562 | { | |
563 | (void)versioning; | |
564 | struct pcep_object_srp *srp = (struct pcep_object_srp *)hdr; | |
565 | obj_body_buf[3] = (srp->flag_lsp_remove ? OBJECT_SRP_FLAG_R : 0x00); | |
566 | uint32_t *uint32_ptr = (uint32_t *)(obj_body_buf + 4); | |
567 | *uint32_ptr = htonl(srp->srp_id_number); | |
568 | ||
569 | return LENGTH_2WORDS; | |
570 | } | |
571 | ||
572 | uint16_t pcep_encode_obj_lsp(struct pcep_object_header *hdr, | |
573 | struct pcep_versioning *versioning, | |
574 | uint8_t *obj_body_buf) | |
575 | { | |
576 | (void)versioning; | |
577 | struct pcep_object_lsp *lsp = (struct pcep_object_lsp *)hdr; | |
578 | uint32_t *uint32_ptr = (uint32_t *)obj_body_buf; | |
579 | uint32_ptr[0] = htonl((lsp->plsp_id << 12) & 0xfffff000); | |
580 | obj_body_buf[3] = ((lsp->flag_c ? OBJECT_LSP_FLAG_C : 0x00) | |
581 | | ((lsp->operational_status << 4) & 0x70) | |
582 | | (lsp->flag_a ? OBJECT_LSP_FLAG_A : 0x00) | |
583 | | (lsp->flag_r ? OBJECT_LSP_FLAG_R : 0x00) | |
584 | | (lsp->flag_s ? OBJECT_LSP_FLAG_S : 0x00) | |
585 | | (lsp->flag_d ? OBJECT_LSP_FLAG_D : 0x00)); | |
586 | ||
587 | return LENGTH_1WORD; | |
588 | } | |
589 | ||
590 | uint16_t pcep_encode_obj_vendor_info(struct pcep_object_header *hdr, | |
591 | struct pcep_versioning *versioning, | |
592 | uint8_t *obj_body_buf) | |
593 | { | |
594 | (void)versioning; | |
595 | struct pcep_object_vendor_info *obj = | |
596 | (struct pcep_object_vendor_info *)hdr; | |
597 | uint32_t *uint32_ptr = (uint32_t *)obj_body_buf; | |
598 | uint32_ptr[0] = htonl(obj->enterprise_number); | |
599 | uint32_ptr[1] = htonl(obj->enterprise_specific_info); | |
600 | ||
601 | return LENGTH_2WORDS; | |
602 | } | |
603 | ||
604 | uint16_t pcep_encode_obj_inter_layer(struct pcep_object_header *hdr, | |
605 | struct pcep_versioning *versioning, | |
606 | uint8_t *obj_body_buf) | |
607 | { | |
608 | (void)versioning; | |
609 | struct pcep_object_inter_layer *obj = | |
610 | (struct pcep_object_inter_layer *)hdr; | |
611 | obj_body_buf[3] = ((obj->flag_i ? OBJECT_INTER_LAYER_FLAG_I : 0x00) | |
612 | | (obj->flag_m ? OBJECT_INTER_LAYER_FLAG_M : 0x00) | |
613 | | (obj->flag_t ? OBJECT_INTER_LAYER_FLAG_T : 0x00)); | |
614 | ||
615 | return LENGTH_1WORD; | |
616 | } | |
617 | ||
618 | uint16_t pcep_encode_obj_switch_layer(struct pcep_object_header *hdr, | |
619 | struct pcep_versioning *versioning, | |
620 | uint8_t *obj_body_buf) | |
621 | { | |
622 | (void)versioning; | |
623 | struct pcep_object_switch_layer *obj = | |
624 | (struct pcep_object_switch_layer *)hdr; | |
625 | uint8_t buf_index = 0; | |
626 | ||
627 | double_linked_list_node *node = obj->switch_layer_rows->head; | |
628 | while (node != NULL) { | |
629 | struct pcep_object_switch_layer_row *row = node->data; | |
630 | if (row == NULL) { | |
631 | break; | |
632 | } | |
633 | ||
634 | obj_body_buf[buf_index] = row->lsp_encoding_type; | |
635 | obj_body_buf[buf_index + 1] = row->switching_type; | |
636 | obj_body_buf[buf_index + 3] = | |
637 | (row->flag_i ? OBJECT_SWITCH_LAYER_FLAG_I : 0x00); | |
638 | ||
639 | buf_index += LENGTH_1WORD; | |
640 | } | |
641 | ||
642 | return buf_index; | |
643 | } | |
644 | ||
645 | uint16_t pcep_encode_obj_req_adap_cap(struct pcep_object_header *hdr, | |
646 | struct pcep_versioning *versioning, | |
647 | uint8_t *obj_body_buf) | |
648 | { | |
649 | (void)versioning; | |
650 | struct pcep_object_req_adap_cap *obj = | |
651 | (struct pcep_object_req_adap_cap *)hdr; | |
652 | ||
653 | obj_body_buf[0] = obj->switching_capability; | |
654 | obj_body_buf[1] = obj->encoding; | |
655 | ||
656 | return LENGTH_1WORD; | |
657 | } | |
658 | ||
659 | uint16_t pcep_encode_obj_server_ind(struct pcep_object_header *hdr, | |
660 | struct pcep_versioning *versioning, | |
661 | uint8_t *obj_body_buf) | |
662 | { | |
663 | (void)versioning; | |
664 | struct pcep_object_server_indication *obj = | |
665 | (struct pcep_object_server_indication *)hdr; | |
666 | ||
667 | obj_body_buf[0] = obj->switching_capability; | |
668 | obj_body_buf[1] = obj->encoding; | |
669 | ||
670 | return LENGTH_1WORD; | |
671 | } | |
672 | ||
673 | uint16_t pcep_encode_obj_objective_function(struct pcep_object_header *hdr, | |
674 | struct pcep_versioning *versioning, | |
675 | uint8_t *obj_body_buf) | |
676 | { | |
677 | (void)versioning; | |
678 | struct pcep_object_objective_function *obj = | |
679 | (struct pcep_object_objective_function *)hdr; | |
680 | ||
681 | uint16_t *uint16_ptr = (uint16_t *)obj_body_buf; | |
682 | *uint16_ptr = htons(obj->of_code); | |
683 | ||
684 | return LENGTH_1WORD; | |
685 | } | |
686 | ||
687 | uint16_t pcep_encode_obj_ro(struct pcep_object_header *hdr, | |
688 | struct pcep_versioning *versioning, | |
689 | uint8_t *obj_body_buf) | |
690 | { | |
691 | (void)versioning; | |
692 | struct pcep_object_ro *ro = (struct pcep_object_ro *)hdr; | |
693 | if (ro == NULL || ro->sub_objects == NULL) { | |
694 | return 0; | |
695 | } | |
696 | ||
697 | /* RO Subobject format | |
698 | * | |
699 | * 0 1 | |
700 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 | |
701 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+ | |
702 | * |L| Type | Length | (Subobject contents) | | |
703 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+ | |
704 | */ | |
705 | ||
706 | uint16_t index = 0; | |
707 | double_linked_list_node *node = ro->sub_objects->head; | |
708 | for (; node != NULL; node = node->next_node) { | |
709 | struct pcep_object_ro_subobj *ro_subobj = node->data; | |
710 | obj_body_buf[index++] = | |
711 | ((ro_subobj->flag_subobj_loose_hop ? 0x80 : 0x00) | |
712 | | (ro_subobj->ro_subobj_type)); | |
713 | /* The length will be written below, depending on the subobj | |
714 | * type */ | |
715 | uint8_t *length_ptr = &(obj_body_buf[index++]); | |
716 | uint32_t *uint32_ptr = (uint32_t *)(obj_body_buf + index); | |
717 | ||
718 | /* - The index has already been incremented past the header, | |
719 | * and now points to the ro_subobj body. Below it just needs | |
720 | * to be incremented past the body. | |
721 | * | |
722 | * - Each section below needs to write the total length, | |
723 | * including the 2 byte subobj header. */ | |
724 | ||
725 | switch (ro_subobj->ro_subobj_type) { | |
726 | case RO_SUBOBJ_TYPE_IPV4: { | |
727 | struct pcep_ro_subobj_ipv4 *ipv4 = | |
728 | (struct pcep_ro_subobj_ipv4 *)ro_subobj; | |
729 | uint32_ptr[0] = ipv4->ip_addr.s_addr; | |
730 | index += LENGTH_1WORD; | |
731 | obj_body_buf[index++] = ipv4->prefix_length; | |
732 | obj_body_buf[index++] = | |
733 | (ipv4->flag_local_protection | |
734 | ? OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT | |
735 | : 0x00); | |
736 | *length_ptr = LENGTH_2WORDS; | |
737 | } break; | |
738 | ||
739 | case RO_SUBOBJ_TYPE_IPV6: { | |
740 | struct pcep_ro_subobj_ipv6 *ipv6 = | |
741 | (struct pcep_ro_subobj_ipv6 *)ro_subobj; | |
742 | encode_ipv6(&ipv6->ip_addr, uint32_ptr); | |
743 | index += LENGTH_4WORDS; | |
744 | obj_body_buf[index++] = ipv6->prefix_length; | |
745 | obj_body_buf[index++] = | |
746 | (ipv6->flag_local_protection | |
747 | ? OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT | |
748 | : 0x00); | |
749 | *length_ptr = LENGTH_5WORDS; | |
750 | } break; | |
751 | ||
752 | case RO_SUBOBJ_TYPE_LABEL: { | |
753 | struct pcep_ro_subobj_32label *label = | |
754 | (struct pcep_ro_subobj_32label *)ro_subobj; | |
755 | obj_body_buf[index++] = | |
756 | (label->flag_global_label | |
757 | ? OBJECT_SUBOBJ_LABEL_FLAG_GLOGAL | |
758 | : 0x00); | |
759 | obj_body_buf[index++] = label->class_type; | |
760 | uint32_ptr = (uint32_t *)(obj_body_buf + index); | |
761 | *uint32_ptr = htonl(label->label); | |
762 | *length_ptr = LENGTH_2WORDS; | |
763 | index += LENGTH_1WORD; | |
764 | } break; | |
765 | ||
766 | case RO_SUBOBJ_TYPE_UNNUM: { | |
767 | struct pcep_ro_subobj_unnum *unum = | |
768 | (struct pcep_ro_subobj_unnum *)ro_subobj; | |
769 | index += 2; /* increment past 2 reserved bytes */ | |
770 | uint32_ptr = (uint32_t *)(obj_body_buf + index); | |
771 | uint32_ptr[0] = unum->router_id.s_addr; | |
772 | uint32_ptr[1] = htonl(unum->interface_id); | |
773 | *length_ptr = LENGTH_3WORDS; | |
774 | index += LENGTH_2WORDS; | |
775 | } break; | |
776 | ||
777 | case RO_SUBOBJ_TYPE_ASN: { | |
778 | struct pcep_ro_subobj_asn *asn = | |
779 | (struct pcep_ro_subobj_asn *)ro_subobj; | |
780 | uint16_t *uint16_ptr = | |
781 | (uint16_t *)(obj_body_buf + index); | |
782 | *uint16_ptr = htons(asn->asn); | |
783 | *length_ptr = LENGTH_1WORD; | |
784 | index += 2; | |
785 | } break; | |
786 | ||
787 | case RO_SUBOBJ_TYPE_SR: { | |
788 | /* SR-ERO subobject format | |
789 | * | |
790 | * 0 1 2 3 0 1 2 3 4 | |
791 | * 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 | |
792 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
793 | * |L| Type=36 | Length | NT | Flags | |
794 | * |F|S|C|M| | |
795 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
796 | * | SID (optional) | | |
797 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
798 | * // NAI (variable, optional) // | |
799 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
800 | */ | |
801 | ||
802 | struct pcep_ro_subobj_sr *sr_subobj = | |
803 | (struct pcep_ro_subobj_sr *)ro_subobj; | |
804 | obj_body_buf[index++] = | |
805 | ((sr_subobj->nai_type << 4) & 0xf0); | |
806 | obj_body_buf[index++] = | |
807 | ((sr_subobj->flag_f ? OBJECT_SUBOBJ_SR_FLAG_F | |
808 | : 0x00) | |
809 | | (sr_subobj->flag_s ? OBJECT_SUBOBJ_SR_FLAG_S | |
810 | : 0x00) | |
811 | | (sr_subobj->flag_c ? OBJECT_SUBOBJ_SR_FLAG_C | |
812 | : 0x00) | |
813 | | (sr_subobj->flag_m ? OBJECT_SUBOBJ_SR_FLAG_M | |
814 | : 0x00)); | |
815 | uint32_ptr = (uint32_t *)(obj_body_buf + index); | |
816 | /* Start with LENGTH_1WORD for the SubObj HDR + NT + | |
817 | * Flags */ | |
818 | uint8_t sr_base_length = LENGTH_1WORD; | |
819 | /* If the sid_absent flag is true, then dont convert the | |
820 | * sid */ | |
821 | if (sr_subobj->flag_s == false) { | |
822 | uint32_ptr[0] = htonl(sr_subobj->sid); | |
823 | index += LENGTH_1WORD; | |
824 | uint32_ptr = (uint32_t *)(obj_body_buf + index); | |
825 | sr_base_length += LENGTH_1WORD; | |
826 | } | |
827 | ||
828 | /* The lengths below need to include: | |
829 | * - sr_base_length: set above to include SR SubObj Hdr | |
830 | * and the SID if present | |
831 | * - Number of bytes written to the NAI | |
832 | * The index will only be incremented below by the | |
833 | * number of bytes written to the NAI, since the RO SR | |
834 | * subobj header and the SID have already been written. | |
835 | */ | |
836 | ||
837 | double_linked_list_node *nai_node = | |
838 | (sr_subobj->nai_list == NULL | |
839 | ? NULL | |
840 | : sr_subobj->nai_list->head); | |
841 | if (nai_node == NULL) { | |
842 | if (sr_subobj->nai_type | |
843 | == PCEP_SR_SUBOBJ_NAI_ABSENT) { | |
844 | *length_ptr = sr_base_length; | |
845 | continue; | |
846 | } else { | |
847 | return 0; | |
848 | } | |
849 | } | |
850 | switch (sr_subobj->nai_type) { | |
851 | case PCEP_SR_SUBOBJ_NAI_IPV4_NODE: | |
852 | uint32_ptr[0] = | |
853 | ((struct in_addr *)nai_node->data) | |
854 | ->s_addr; | |
855 | *length_ptr = sr_base_length + LENGTH_1WORD; | |
856 | index += LENGTH_1WORD; | |
857 | break; | |
858 | ||
859 | case PCEP_SR_SUBOBJ_NAI_IPV6_NODE: | |
860 | encode_ipv6((struct in6_addr *)nai_node->data, | |
861 | uint32_ptr); | |
862 | *length_ptr = sr_base_length + LENGTH_4WORDS; | |
863 | index += LENGTH_4WORDS; | |
864 | break; | |
865 | ||
866 | case PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY: | |
867 | uint32_ptr[0] = | |
868 | ((struct in_addr *)nai_node->data) | |
869 | ->s_addr; | |
870 | nai_node = nai_node->next_node; | |
871 | uint32_ptr[1] = | |
872 | ((struct in_addr *)nai_node->data) | |
873 | ->s_addr; | |
874 | nai_node = nai_node->next_node; | |
875 | uint32_ptr[2] = | |
876 | ((struct in_addr *)nai_node->data) | |
877 | ->s_addr; | |
878 | nai_node = nai_node->next_node; | |
879 | uint32_ptr[3] = | |
880 | ((struct in_addr *)nai_node->data) | |
881 | ->s_addr; | |
882 | *length_ptr = sr_base_length + LENGTH_4WORDS; | |
883 | index += LENGTH_4WORDS; | |
884 | break; | |
885 | ||
886 | case PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY: | |
887 | uint32_ptr[0] = | |
888 | ((struct in_addr *)nai_node->data) | |
889 | ->s_addr; | |
890 | nai_node = nai_node->next_node; | |
891 | uint32_ptr[1] = | |
892 | ((struct in_addr *)nai_node->data) | |
893 | ->s_addr; | |
894 | *length_ptr = sr_base_length + LENGTH_2WORDS; | |
895 | index += LENGTH_2WORDS; | |
896 | break; | |
897 | ||
898 | case PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY: | |
899 | encode_ipv6((struct in6_addr *)nai_node->data, | |
900 | uint32_ptr); | |
901 | nai_node = nai_node->next_node; | |
902 | encode_ipv6((struct in6_addr *)nai_node->data, | |
903 | uint32_ptr + 4); | |
904 | *length_ptr = sr_base_length + LENGTH_8WORDS; | |
905 | index += LENGTH_8WORDS; | |
906 | break; | |
907 | ||
908 | case PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY: | |
909 | encode_ipv6((struct in6_addr *)nai_node->data, | |
910 | uint32_ptr); | |
911 | nai_node = nai_node->next_node; | |
912 | uint32_ptr[4] = | |
913 | ((struct in_addr *)nai_node->data) | |
914 | ->s_addr; | |
915 | nai_node = nai_node->next_node; | |
916 | encode_ipv6((struct in6_addr *)nai_node->data, | |
917 | uint32_ptr + 5); | |
918 | nai_node = nai_node->next_node; | |
919 | uint32_ptr[9] = | |
920 | ((struct in_addr *)nai_node->data) | |
921 | ->s_addr; | |
922 | *length_ptr = sr_base_length + LENGTH_10WORDS; | |
923 | index += LENGTH_10WORDS; | |
924 | break; | |
925 | ||
926 | default: | |
927 | break; | |
928 | } | |
929 | } break; | |
930 | ||
931 | default: | |
932 | break; | |
933 | } | |
934 | } | |
935 | ||
936 | return index; | |
937 | } | |
938 | ||
939 | void encode_ipv6(struct in6_addr *src_ipv6, uint32_t *dst) | |
940 | { | |
941 | memcpy(dst, src_ipv6, sizeof(struct in6_addr)); | |
942 | } | |
943 | ||
944 | /* | |
945 | * Decoding functions. | |
946 | */ | |
947 | ||
948 | void pcep_decode_object_hdr(const uint8_t *obj_buf, | |
949 | struct pcep_object_header *obj_hdr) | |
950 | { | |
951 | memset(obj_hdr, 0, sizeof(struct pcep_object_header)); | |
952 | ||
953 | obj_hdr->object_class = obj_buf[0]; | |
954 | obj_hdr->object_type = (obj_buf[1] >> 4) & 0x0f; | |
955 | obj_hdr->flag_p = (obj_buf[1] & OBJECT_HEADER_FLAG_P); | |
956 | obj_hdr->flag_i = (obj_buf[1] & OBJECT_HEADER_FLAG_I); | |
957 | uint16_t net_order_length; | |
958 | memcpy(&net_order_length, obj_buf + 2, sizeof(net_order_length)); | |
959 | obj_hdr->encoded_object_length = ntohs(net_order_length); | |
960 | obj_hdr->encoded_object = obj_buf; | |
961 | } | |
962 | ||
963 | uint16_t pcep_object_get_length(enum pcep_object_classes object_class, | |
964 | enum pcep_object_types object_type) | |
965 | { | |
966 | uint8_t object_length = pcep_object_class_lengths[object_class]; | |
967 | if (object_length == 0) { | |
968 | if (object_class == PCEP_OBJ_CLASS_ENDPOINTS) { | |
969 | if (object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV4) { | |
970 | return 12; | |
971 | } else if (object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV6) { | |
972 | return 36; | |
973 | } | |
974 | } | |
975 | ||
976 | return 0; | |
977 | } | |
978 | ||
979 | return object_length; | |
980 | } | |
981 | ||
982 | uint16_t pcep_object_get_length_by_hdr(struct pcep_object_header *object_hdr) | |
983 | { | |
984 | return (pcep_object_get_length(object_hdr->object_class, | |
985 | object_hdr->object_type)); | |
986 | } | |
987 | ||
988 | bool pcep_object_has_tlvs(struct pcep_object_header *object_hdr) | |
989 | { | |
990 | uint8_t object_length = pcep_object_get_length_by_hdr(object_hdr); | |
991 | if (object_length == 0) { | |
992 | return false; | |
993 | } | |
994 | ||
995 | return (object_hdr->encoded_object_length - object_length) > 0; | |
996 | } | |
997 | ||
998 | struct pcep_object_header *pcep_decode_object(const uint8_t *obj_buf) | |
999 | { | |
1000 | ||
1001 | struct pcep_object_header object_hdr; | |
1002 | /* Only initializes and decodes the Object Header: class, type, flags, | |
1003 | * and length */ | |
1004 | pcep_decode_object_hdr(obj_buf, &object_hdr); | |
1005 | ||
1006 | if (object_hdr.object_class >= MAX_OBJECT_ENCODER_INDEX) { | |
1007 | pcep_log(LOG_INFO, | |
1008 | "%s: Cannot decode unknown Object class [%d]", | |
1009 | __func__, object_hdr.object_class); | |
1010 | return NULL; | |
1011 | } | |
1012 | ||
1013 | object_decoder_funcptr obj_decoder = | |
1014 | object_decoders[object_hdr.object_class]; | |
1015 | if (obj_decoder == NULL) { | |
1016 | pcep_log(LOG_INFO, | |
1017 | "%s: No object decoder found for Object class [%d]", | |
1018 | __func__, object_hdr.object_class); | |
1019 | return NULL; | |
1020 | } | |
1021 | ||
1022 | /* The object decoders will start decoding the object body, if | |
1023 | * anything from the header is needed, they have the object_hdr */ | |
1024 | struct pcep_object_header *object = | |
1025 | obj_decoder(&object_hdr, obj_buf + OBJECT_HEADER_LENGTH); | |
1026 | if (object == NULL) { | |
1027 | pcep_log(LOG_INFO, "%s: Unable to decode Object class [%d].", | |
1028 | __func__, object_hdr.object_class); | |
1029 | return NULL; | |
1030 | } | |
1031 | ||
1032 | if (pcep_object_has_tlvs(&object_hdr)) { | |
1033 | object->tlv_list = dll_initialize(); | |
1034 | int num_iterations = 0; | |
1035 | uint16_t tlv_index = pcep_object_get_length_by_hdr(&object_hdr); | |
1036 | while ((object->encoded_object_length - tlv_index) > 0 | |
1037 | && num_iterations++ < MAX_ITERATIONS) { | |
1038 | struct pcep_object_tlv_header *tlv = | |
1039 | pcep_decode_tlv(obj_buf + tlv_index); | |
1040 | if (tlv == NULL) { | |
1041 | /* TODO should we do anything else here ? */ | |
1042 | return object; | |
1043 | } | |
1044 | ||
1045 | /* The TLV length does not include the TLV header */ | |
1046 | tlv_index += normalize_pcep_tlv_length( | |
1047 | tlv->encoded_tlv_length + TLV_HEADER_LENGTH); | |
1048 | dll_append(object->tlv_list, tlv); | |
1049 | } | |
1050 | } | |
1051 | ||
1052 | return object; | |
1053 | } | |
1054 | ||
1055 | static struct pcep_object_header * | |
1056 | common_object_create(struct pcep_object_header *hdr, uint16_t new_obj_length) | |
1057 | { | |
1058 | struct pcep_object_header *new_object = | |
1059 | pceplib_malloc(PCEPLIB_MESSAGES, new_obj_length); | |
1060 | memset(new_object, 0, new_obj_length); | |
1061 | memcpy(new_object, hdr, sizeof(struct pcep_object_header)); | |
1062 | ||
1063 | return new_object; | |
1064 | } | |
1065 | ||
1066 | /* | |
1067 | * Decoders | |
1068 | */ | |
1069 | ||
1070 | struct pcep_object_header *pcep_decode_obj_open(struct pcep_object_header *hdr, | |
1071 | const uint8_t *obj_buf) | |
1072 | { | |
1073 | struct pcep_object_open *obj = | |
1074 | (struct pcep_object_open *)common_object_create( | |
1075 | hdr, sizeof(struct pcep_object_open)); | |
1076 | ||
1077 | obj->open_version = (obj_buf[0] >> 5) & 0x07; | |
1078 | obj->open_keepalive = obj_buf[1]; | |
1079 | obj->open_deadtimer = obj_buf[2]; | |
1080 | obj->open_sid = obj_buf[3]; | |
1081 | ||
1082 | return (struct pcep_object_header *)obj; | |
1083 | } | |
1084 | ||
1085 | struct pcep_object_header *pcep_decode_obj_rp(struct pcep_object_header *hdr, | |
1086 | const uint8_t *obj_buf) | |
1087 | { | |
1088 | struct pcep_object_rp *obj = | |
1089 | (struct pcep_object_rp *)common_object_create( | |
1090 | hdr, sizeof(struct pcep_object_rp)); | |
1091 | ||
1092 | obj->flag_reoptimization = (obj_buf[3] & OBJECT_RP_FLAG_R); | |
1093 | obj->flag_bidirectional = (obj_buf[3] & OBJECT_RP_FLAG_B); | |
1094 | obj->flag_strict = (obj_buf[3] & OBJECT_RP_FLAG_O); | |
1095 | obj->flag_of = (obj_buf[3] & OBJECT_RP_FLAG_OF); | |
1096 | obj->priority = (obj_buf[3] & 0x07); | |
1097 | obj->request_id = ntohl(*((uint32_t *)(obj_buf + 4))); | |
1098 | ||
1099 | return (struct pcep_object_header *)obj; | |
1100 | } | |
1101 | ||
1102 | struct pcep_object_header * | |
1103 | pcep_decode_obj_notify(struct pcep_object_header *hdr, const uint8_t *obj_buf) | |
1104 | { | |
1105 | struct pcep_object_notify *obj = | |
1106 | (struct pcep_object_notify *)common_object_create( | |
1107 | hdr, sizeof(struct pcep_object_notify)); | |
1108 | ||
1109 | obj->notification_type = obj_buf[2]; | |
1110 | obj->notification_value = obj_buf[3]; | |
1111 | ||
1112 | return (struct pcep_object_header *)obj; | |
1113 | } | |
1114 | ||
1115 | struct pcep_object_header * | |
1116 | pcep_decode_obj_nopath(struct pcep_object_header *hdr, const uint8_t *obj_buf) | |
1117 | { | |
1118 | struct pcep_object_nopath *obj = | |
1119 | (struct pcep_object_nopath *)common_object_create( | |
1120 | hdr, sizeof(struct pcep_object_nopath)); | |
1121 | ||
1122 | obj->ni = (obj_buf[0] >> 1); | |
1123 | obj->flag_c = (obj_buf[0] & OBJECT_NOPATH_FLAG_C); | |
1124 | ||
1125 | return (struct pcep_object_header *)obj; | |
1126 | } | |
1127 | ||
1128 | struct pcep_object_header * | |
1129 | pcep_decode_obj_association(struct pcep_object_header *hdr, | |
1130 | const uint8_t *obj_buf) | |
1131 | { | |
1132 | uint16_t *uint16_ptr = (uint16_t *)obj_buf; | |
1133 | uint32_t *uint32_ptr = (uint32_t *)obj_buf; | |
1134 | ||
1135 | if (hdr->object_type == PCEP_OBJ_TYPE_ASSOCIATION_IPV4) { | |
1136 | struct pcep_object_association_ipv4 *obj = | |
1137 | (struct pcep_object_association_ipv4 *) | |
1138 | common_object_create( | |
1139 | hdr, | |
1140 | sizeof(struct | |
1141 | pcep_object_association_ipv4)); | |
1142 | obj->R_flag = (obj_buf[3] & OBJECT_ASSOCIATION_FLAG_R); | |
1143 | obj->association_type = ntohs(uint16_ptr[2]); | |
1144 | obj->association_id = ntohs(uint16_ptr[3]); | |
1145 | obj->src.s_addr = uint32_ptr[2]; | |
1146 | ||
1147 | return (struct pcep_object_header *)obj; | |
1148 | } else if (hdr->object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV6) { | |
1149 | struct pcep_object_association_ipv6 *obj = | |
1150 | (struct pcep_object_association_ipv6 *) | |
1151 | common_object_create( | |
1152 | hdr, | |
1153 | sizeof(struct | |
1154 | pcep_object_association_ipv6)); | |
1155 | ||
1156 | obj->R_flag = (obj_buf[3] & OBJECT_ASSOCIATION_FLAG_R); | |
1157 | obj->association_type = ntohs(uint16_ptr[2]); | |
1158 | obj->association_id = ntohs(uint16_ptr[3]); | |
1159 | memcpy(&obj->src, &uint32_ptr[2], sizeof(struct in6_addr)); | |
1160 | ||
1161 | return (struct pcep_object_header *)obj; | |
1162 | } | |
1163 | ||
1164 | return NULL; | |
1165 | } | |
1166 | struct pcep_object_header * | |
1167 | pcep_decode_obj_endpoints(struct pcep_object_header *hdr, | |
1168 | const uint8_t *obj_buf) | |
1169 | { | |
1170 | uint32_t *uint32_ptr = (uint32_t *)obj_buf; | |
1171 | ||
1172 | if (hdr->object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV4) { | |
1173 | struct pcep_object_endpoints_ipv4 *obj = | |
1174 | (struct pcep_object_endpoints_ipv4 *) | |
1175 | common_object_create( | |
1176 | hdr, | |
1177 | sizeof(struct | |
1178 | pcep_object_endpoints_ipv4)); | |
1179 | obj->src_ipv4.s_addr = uint32_ptr[0]; | |
1180 | obj->dst_ipv4.s_addr = uint32_ptr[1]; | |
1181 | ||
1182 | return (struct pcep_object_header *)obj; | |
1183 | } else if (hdr->object_type == PCEP_OBJ_TYPE_ENDPOINT_IPV6) { | |
1184 | struct pcep_object_endpoints_ipv6 *obj = | |
1185 | (struct pcep_object_endpoints_ipv6 *) | |
1186 | common_object_create( | |
1187 | hdr, | |
1188 | sizeof(struct | |
1189 | pcep_object_endpoints_ipv6)); | |
1190 | ||
1191 | memcpy(&obj->src_ipv6, &uint32_ptr[0], sizeof(struct in6_addr)); | |
1192 | memcpy(&obj->dst_ipv6, &uint32_ptr[4], sizeof(struct in6_addr)); | |
1193 | ||
1194 | return (struct pcep_object_header *)obj; | |
1195 | } | |
1196 | ||
1197 | return NULL; | |
1198 | } | |
1199 | ||
1200 | struct pcep_object_header * | |
1201 | pcep_decode_obj_bandwidth(struct pcep_object_header *hdr, | |
1202 | const uint8_t *obj_buf) | |
1203 | { | |
1204 | struct pcep_object_bandwidth *obj = | |
1205 | (struct pcep_object_bandwidth *)common_object_create( | |
1206 | hdr, sizeof(struct pcep_object_bandwidth)); | |
1207 | ||
1208 | uint32_t value = ntohl(*((uint32_t *)obj_buf)); | |
4c98b89e | 1209 | /* Seems like the compiler doesn't correctly copy to the float, so |
74971473 JG |
1210 | * memcpy() it */ |
1211 | memcpy(&obj->bandwidth, &value, sizeof(uint32_t)); | |
1212 | ||
1213 | return (struct pcep_object_header *)obj; | |
1214 | } | |
1215 | ||
1216 | struct pcep_object_header * | |
1217 | pcep_decode_obj_metric(struct pcep_object_header *hdr, const uint8_t *obj_buf) | |
1218 | { | |
1219 | struct pcep_object_metric *obj = | |
1220 | (struct pcep_object_metric *)common_object_create( | |
1221 | hdr, sizeof(struct pcep_object_metric)); | |
1222 | obj->flag_b = (obj_buf[2] & OBJECT_METRIC_FLAC_B); | |
1223 | obj->flag_c = (obj_buf[2] & OBJECT_METRIC_FLAC_C); | |
1224 | obj->type = obj_buf[3]; | |
1225 | uint32_t value = ntohl(*((uint32_t *)(obj_buf + 4))); | |
4c98b89e | 1226 | /* Seems like the compiler doesn't correctly copy to the float, so |
74971473 JG |
1227 | * memcpy() it */ |
1228 | memcpy(&obj->value, &value, sizeof(uint32_t)); | |
1229 | ||
1230 | return (struct pcep_object_header *)obj; | |
1231 | } | |
1232 | ||
1233 | struct pcep_object_header *pcep_decode_obj_lspa(struct pcep_object_header *hdr, | |
1234 | const uint8_t *obj_buf) | |
1235 | { | |
1236 | struct pcep_object_lspa *obj = | |
1237 | (struct pcep_object_lspa *)common_object_create( | |
1238 | hdr, sizeof(struct pcep_object_lspa)); | |
1239 | uint32_t *uint32_ptr = (uint32_t *)obj_buf; | |
1240 | ||
1241 | obj->lspa_exclude_any = ntohl(uint32_ptr[0]); | |
1242 | obj->lspa_include_any = ntohl(uint32_ptr[1]); | |
1243 | obj->lspa_include_all = ntohl(uint32_ptr[2]); | |
1244 | obj->setup_priority = obj_buf[12]; | |
1245 | obj->holding_priority = obj_buf[13]; | |
1246 | obj->flag_local_protection = (obj_buf[14] & OBJECT_LSPA_FLAG_L); | |
1247 | ||
1248 | return (struct pcep_object_header *)obj; | |
1249 | } | |
1250 | ||
1251 | struct pcep_object_header *pcep_decode_obj_svec(struct pcep_object_header *hdr, | |
1252 | const uint8_t *obj_buf) | |
1253 | { | |
1254 | struct pcep_object_svec *obj = | |
1255 | (struct pcep_object_svec *)common_object_create( | |
1256 | hdr, sizeof(struct pcep_object_svec)); | |
1257 | ||
1258 | obj->flag_link_diverse = (obj_buf[3] & OBJECT_SVEC_FLAG_L); | |
1259 | obj->flag_node_diverse = (obj_buf[3] & OBJECT_SVEC_FLAG_N); | |
1260 | obj->flag_srlg_diverse = (obj_buf[3] & OBJECT_SVEC_FLAG_S); | |
1261 | ||
1262 | if (hdr->encoded_object_length > LENGTH_2WORDS) { | |
1263 | obj->request_id_list = dll_initialize(); | |
1264 | uint16_t index = 1; | |
1265 | uint32_t *uint32_ptr = (uint32_t *)obj_buf; | |
1266 | for (; | |
1267 | index < ((hdr->encoded_object_length - LENGTH_2WORDS) / 4); | |
1268 | index++) { | |
1269 | uint32_t *req_id_ptr = pceplib_malloc(PCEPLIB_MESSAGES, | |
1270 | sizeof(uint32_t)); | |
1271 | *req_id_ptr = uint32_ptr[index]; | |
1272 | dll_append(obj->request_id_list, req_id_ptr); | |
1273 | } | |
1274 | } | |
1275 | ||
1276 | return (struct pcep_object_header *)obj; | |
1277 | } | |
1278 | ||
1279 | struct pcep_object_header *pcep_decode_obj_error(struct pcep_object_header *hdr, | |
1280 | const uint8_t *obj_buf) | |
1281 | { | |
1282 | struct pcep_object_error *obj = | |
1283 | (struct pcep_object_error *)common_object_create( | |
1284 | hdr, sizeof(struct pcep_object_error)); | |
1285 | ||
1286 | obj->error_type = obj_buf[2]; | |
1287 | obj->error_value = obj_buf[3]; | |
1288 | ||
1289 | return (struct pcep_object_header *)obj; | |
1290 | } | |
1291 | ||
1292 | struct pcep_object_header *pcep_decode_obj_close(struct pcep_object_header *hdr, | |
1293 | const uint8_t *obj_buf) | |
1294 | { | |
1295 | struct pcep_object_close *obj = | |
1296 | (struct pcep_object_close *)common_object_create( | |
1297 | hdr, sizeof(struct pcep_object_close)); | |
1298 | ||
1299 | obj->reason = obj_buf[3]; | |
1300 | ||
1301 | return (struct pcep_object_header *)obj; | |
1302 | } | |
1303 | ||
1304 | struct pcep_object_header *pcep_decode_obj_srp(struct pcep_object_header *hdr, | |
1305 | const uint8_t *obj_buf) | |
1306 | { | |
1307 | struct pcep_object_srp *obj = | |
1308 | (struct pcep_object_srp *)common_object_create( | |
1309 | hdr, sizeof(struct pcep_object_srp)); | |
1310 | ||
1311 | obj->flag_lsp_remove = (obj_buf[3] & OBJECT_SRP_FLAG_R); | |
1312 | obj->srp_id_number = ntohl(*((uint32_t *)(obj_buf + 4))); | |
1313 | ||
1314 | return (struct pcep_object_header *)obj; | |
1315 | } | |
1316 | ||
1317 | struct pcep_object_header *pcep_decode_obj_lsp(struct pcep_object_header *hdr, | |
1318 | const uint8_t *obj_buf) | |
1319 | { | |
1320 | struct pcep_object_lsp *obj = | |
1321 | (struct pcep_object_lsp *)common_object_create( | |
1322 | hdr, sizeof(struct pcep_object_lsp)); | |
1323 | ||
1324 | obj->flag_d = (obj_buf[3] & OBJECT_LSP_FLAG_D); | |
1325 | obj->flag_s = (obj_buf[3] & OBJECT_LSP_FLAG_S); | |
1326 | obj->flag_r = (obj_buf[3] & OBJECT_LSP_FLAG_R); | |
1327 | obj->flag_a = (obj_buf[3] & OBJECT_LSP_FLAG_A); | |
1328 | obj->flag_c = (obj_buf[3] & OBJECT_LSP_FLAG_C); | |
1329 | obj->operational_status = ((obj_buf[3] >> 4) & 0x07); | |
1330 | obj->plsp_id = ((ntohl(*((uint32_t *)obj_buf)) >> 12) & 0x000fffff); | |
1331 | ||
1332 | return (struct pcep_object_header *)obj; | |
1333 | } | |
1334 | ||
1335 | struct pcep_object_header * | |
1336 | pcep_decode_obj_vendor_info(struct pcep_object_header *hdr, | |
1337 | const uint8_t *obj_buf) | |
1338 | { | |
1339 | struct pcep_object_vendor_info *obj = | |
1340 | (struct pcep_object_vendor_info *)common_object_create( | |
1341 | hdr, sizeof(struct pcep_object_vendor_info)); | |
5fe7f5b4 | 1342 | |
74971473 JG |
1343 | obj->enterprise_number = ntohl(*((uint32_t *)(obj_buf))); |
1344 | obj->enterprise_specific_info = ntohl(*((uint32_t *)(obj_buf + 4))); | |
5fe7f5b4 JG |
1345 | if (obj->enterprise_number == ENTERPRISE_NUMBER_CISCO |
1346 | && obj->enterprise_specific_info == ENTERPRISE_COLOR_CISCO) | |
1347 | obj->enterprise_specific_info1 = | |
1348 | ntohl(*((uint32_t *)(obj_buf + 8))); | |
1349 | else | |
1350 | obj->enterprise_specific_info1 = 0; | |
74971473 JG |
1351 | |
1352 | return (struct pcep_object_header *)obj; | |
1353 | } | |
1354 | ||
1355 | struct pcep_object_header * | |
1356 | pcep_decode_obj_inter_layer(struct pcep_object_header *hdr, | |
1357 | const uint8_t *obj_buf) | |
1358 | { | |
1359 | struct pcep_object_inter_layer *obj = | |
1360 | (struct pcep_object_inter_layer *)common_object_create( | |
1361 | hdr, sizeof(struct pcep_object_inter_layer)); | |
1362 | obj->flag_t = (obj_buf[3] & OBJECT_INTER_LAYER_FLAG_T); | |
1363 | obj->flag_m = (obj_buf[3] & OBJECT_INTER_LAYER_FLAG_M); | |
1364 | obj->flag_i = (obj_buf[3] & OBJECT_INTER_LAYER_FLAG_I); | |
1365 | ||
1366 | return (struct pcep_object_header *)obj; | |
1367 | } | |
1368 | ||
1369 | struct pcep_object_header * | |
1370 | pcep_decode_obj_switch_layer(struct pcep_object_header *hdr, | |
1371 | const uint8_t *obj_buf) | |
1372 | { | |
1373 | struct pcep_object_switch_layer *obj = | |
1374 | (struct pcep_object_switch_layer *)common_object_create( | |
1375 | hdr, sizeof(struct pcep_object_switch_layer)); | |
1376 | obj->switch_layer_rows = dll_initialize(); | |
1377 | int num_rows = ((hdr->encoded_object_length - 4) / 4); | |
1378 | uint8_t buf_index = 0; | |
1379 | ||
1380 | int i = 0; | |
1381 | for (; i < num_rows; i++) { | |
1382 | struct pcep_object_switch_layer_row *row = pceplib_malloc( | |
1383 | PCEPLIB_MESSAGES, | |
1384 | sizeof(struct pcep_object_switch_layer_row)); | |
1385 | row->lsp_encoding_type = obj_buf[buf_index]; | |
1386 | row->switching_type = obj_buf[buf_index + 1]; | |
1387 | row->flag_i = | |
1388 | (obj_buf[buf_index + 3] & OBJECT_SWITCH_LAYER_FLAG_I); | |
1389 | dll_append(obj->switch_layer_rows, row); | |
1390 | ||
1391 | buf_index += LENGTH_1WORD; | |
1392 | } | |
1393 | ||
1394 | return (struct pcep_object_header *)obj; | |
1395 | } | |
1396 | ||
1397 | struct pcep_object_header * | |
1398 | pcep_decode_obj_req_adap_cap(struct pcep_object_header *hdr, | |
1399 | const uint8_t *obj_buf) | |
1400 | { | |
1401 | struct pcep_object_req_adap_cap *obj = | |
1402 | (struct pcep_object_req_adap_cap *)common_object_create( | |
1403 | hdr, sizeof(struct pcep_object_req_adap_cap)); | |
1404 | ||
1405 | obj->switching_capability = obj_buf[0]; | |
1406 | obj->encoding = obj_buf[1]; | |
1407 | ||
1408 | return (struct pcep_object_header *)obj; | |
1409 | } | |
1410 | ||
1411 | struct pcep_object_header * | |
1412 | pcep_decode_obj_server_ind(struct pcep_object_header *hdr, | |
1413 | const uint8_t *obj_buf) | |
1414 | { | |
1415 | struct pcep_object_server_indication *obj = | |
1416 | (struct pcep_object_server_indication *)common_object_create( | |
1417 | hdr, sizeof(struct pcep_object_server_indication)); | |
1418 | ||
1419 | obj->switching_capability = obj_buf[0]; | |
1420 | obj->encoding = obj_buf[1]; | |
1421 | ||
1422 | return (struct pcep_object_header *)obj; | |
1423 | } | |
1424 | ||
1425 | struct pcep_object_header * | |
1426 | pcep_decode_obj_objective_function(struct pcep_object_header *hdr, | |
1427 | const uint8_t *obj_buf) | |
1428 | { | |
1429 | struct pcep_object_objective_function *obj = | |
1430 | (struct pcep_object_objective_function *)common_object_create( | |
1431 | hdr, sizeof(struct pcep_object_objective_function)); | |
1432 | ||
1433 | uint16_t *uint16_ptr = (uint16_t *)obj_buf; | |
1434 | obj->of_code = ntohs(*uint16_ptr); | |
1435 | ||
1436 | return (struct pcep_object_header *)obj; | |
1437 | } | |
1438 | ||
1439 | void set_ro_subobj_fields(struct pcep_object_ro_subobj *subobj, bool flag_l, | |
1440 | uint8_t subobj_type) | |
1441 | { | |
1442 | subobj->flag_subobj_loose_hop = flag_l; | |
1443 | subobj->ro_subobj_type = subobj_type; | |
1444 | } | |
1445 | ||
1446 | void decode_ipv6(const uint32_t *src, struct in6_addr *dst_ipv6) | |
1447 | { | |
1448 | memcpy(dst_ipv6, src, sizeof(struct in6_addr)); | |
1449 | } | |
1450 | struct pcep_object_header *pcep_decode_obj_ro(struct pcep_object_header *hdr, | |
1451 | const uint8_t *obj_buf) | |
1452 | { | |
1453 | struct pcep_object_ro *obj = | |
1454 | (struct pcep_object_ro *)common_object_create( | |
1455 | hdr, sizeof(struct pcep_object_ro)); | |
1456 | obj->sub_objects = dll_initialize(); | |
1457 | ||
1458 | /* RO Subobject format | |
1459 | * | |
1460 | * 0 1 | |
1461 | * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 | |
1462 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+ | |
1463 | * |L| Type | Length | (Subobject contents) | | |
1464 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+ | |
1465 | */ | |
1466 | ||
1467 | uint16_t read_count = 0; | |
1468 | int num_sub_objects = 1; | |
1469 | uint32_t *uint32_ptr; | |
1470 | uint16_t obj_body_length = | |
1471 | hdr->encoded_object_length - OBJECT_HEADER_LENGTH; | |
1472 | ||
1473 | while ((obj_body_length - read_count) > OBJECT_RO_SUBOBJ_HEADER_LENGTH | |
1474 | && num_sub_objects < MAX_ITERATIONS) { | |
1475 | num_sub_objects++; | |
1476 | /* Read the Sub-Object Header */ | |
1477 | bool flag_l = (obj_buf[read_count] & 0x80); | |
1478 | uint8_t subobj_type = (obj_buf[read_count++] & 0x7f); | |
1479 | uint8_t subobj_length = obj_buf[read_count++]; | |
1480 | ||
1481 | if (subobj_length <= OBJECT_RO_SUBOBJ_HEADER_LENGTH) { | |
1482 | pcep_log(LOG_INFO, | |
1483 | "%s: Invalid ro subobj type [%d] length [%d]", | |
1484 | __func__, subobj_type, subobj_length); | |
1485 | pceplib_free(PCEPLIB_MESSAGES, obj); | |
1486 | return NULL; | |
1487 | } | |
1488 | ||
1489 | switch (subobj_type) { | |
1490 | case RO_SUBOBJ_TYPE_IPV4: { | |
1491 | struct pcep_ro_subobj_ipv4 *ipv4 = pceplib_malloc( | |
1492 | PCEPLIB_MESSAGES, | |
1493 | sizeof(struct pcep_ro_subobj_ipv4)); | |
1494 | ipv4->ro_subobj.flag_subobj_loose_hop = flag_l; | |
1495 | ipv4->ro_subobj.ro_subobj_type = subobj_type; | |
1496 | uint32_ptr = (uint32_t *)(obj_buf + read_count); | |
1497 | ipv4->ip_addr.s_addr = *uint32_ptr; | |
1498 | read_count += LENGTH_1WORD; | |
1499 | ipv4->prefix_length = obj_buf[read_count++]; | |
1500 | ipv4->flag_local_protection = | |
1501 | (obj_buf[read_count++] | |
1502 | & OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT); | |
1503 | ||
1504 | dll_append(obj->sub_objects, ipv4); | |
1505 | } break; | |
1506 | ||
1507 | case RO_SUBOBJ_TYPE_IPV6: { | |
1508 | struct pcep_ro_subobj_ipv6 *ipv6 = pceplib_malloc( | |
1509 | PCEPLIB_MESSAGES, | |
1510 | sizeof(struct pcep_ro_subobj_ipv6)); | |
1511 | ipv6->ro_subobj.flag_subobj_loose_hop = flag_l; | |
1512 | ipv6->ro_subobj.ro_subobj_type = subobj_type; | |
1513 | decode_ipv6((uint32_t *)obj_buf, &ipv6->ip_addr); | |
1514 | read_count += LENGTH_4WORDS; | |
1515 | ipv6->prefix_length = obj_buf[read_count++]; | |
1516 | ipv6->flag_local_protection = | |
1517 | (obj_buf[read_count++] | |
1518 | & OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT); | |
1519 | ||
1520 | dll_append(obj->sub_objects, ipv6); | |
1521 | } break; | |
1522 | ||
1523 | case RO_SUBOBJ_TYPE_LABEL: { | |
1524 | struct pcep_ro_subobj_32label *label = pceplib_malloc( | |
1525 | PCEPLIB_MESSAGES, | |
1526 | sizeof(struct pcep_ro_subobj_32label)); | |
1527 | label->ro_subobj.flag_subobj_loose_hop = flag_l; | |
1528 | label->ro_subobj.ro_subobj_type = subobj_type; | |
1529 | label->flag_global_label = | |
1530 | (obj_buf[read_count++] | |
1531 | & OBJECT_SUBOBJ_LABEL_FLAG_GLOGAL); | |
1532 | label->class_type = obj_buf[read_count++]; | |
1533 | label->label = ntohl(obj_buf[read_count]); | |
1534 | read_count += LENGTH_1WORD; | |
1535 | ||
1536 | dll_append(obj->sub_objects, label); | |
1537 | } break; | |
1538 | ||
1539 | case RO_SUBOBJ_TYPE_UNNUM: { | |
1540 | struct pcep_ro_subobj_unnum *unum = pceplib_malloc( | |
1541 | PCEPLIB_MESSAGES, | |
1542 | sizeof(struct pcep_ro_subobj_unnum)); | |
1543 | unum->ro_subobj.flag_subobj_loose_hop = flag_l; | |
1544 | unum->ro_subobj.ro_subobj_type = subobj_type; | |
1545 | set_ro_subobj_fields( | |
1546 | (struct pcep_object_ro_subobj *)unum, flag_l, | |
1547 | subobj_type); | |
1548 | uint32_ptr = (uint32_t *)(obj_buf + read_count); | |
1549 | unum->interface_id = ntohl(uint32_ptr[0]); | |
1550 | unum->router_id.s_addr = uint32_ptr[1]; | |
1551 | read_count += 2; | |
1552 | ||
1553 | dll_append(obj->sub_objects, unum); | |
1554 | } break; | |
1555 | ||
1556 | case RO_SUBOBJ_TYPE_ASN: { | |
1557 | struct pcep_ro_subobj_asn *asn = pceplib_malloc( | |
1558 | PCEPLIB_MESSAGES, | |
1559 | sizeof(struct pcep_ro_subobj_asn)); | |
1560 | asn->ro_subobj.flag_subobj_loose_hop = flag_l; | |
1561 | asn->ro_subobj.ro_subobj_type = subobj_type; | |
1562 | uint16_t *uint16_ptr = | |
1563 | (uint16_t *)(obj_buf + read_count); | |
1564 | asn->asn = ntohs(*uint16_ptr); | |
1565 | read_count += 2; | |
1566 | ||
1567 | dll_append(obj->sub_objects, asn); | |
1568 | } break; | |
1569 | ||
1570 | case RO_SUBOBJ_TYPE_SR: { | |
1571 | /* SR-ERO subobject format | |
1572 | * | |
1573 | * 0 1 2 3 0 1 2 3 4 | |
1574 | * 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 | |
1575 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
1576 | * |L| Type=36 | Length | NT | Flags | |
1577 | * |F|S|C|M| | |
1578 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
1579 | * | SID (optional) | | |
1580 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
1581 | * // NAI (variable, optional) // | |
1582 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
1583 | */ | |
1584 | ||
1585 | struct pcep_ro_subobj_sr *sr_subobj = pceplib_malloc( | |
1586 | PCEPLIB_MESSAGES, | |
1587 | sizeof(struct pcep_ro_subobj_sr)); | |
1588 | sr_subobj->ro_subobj.flag_subobj_loose_hop = flag_l; | |
1589 | sr_subobj->ro_subobj.ro_subobj_type = subobj_type; | |
1590 | dll_append(obj->sub_objects, sr_subobj); | |
1591 | ||
1592 | sr_subobj->nai_list = dll_initialize(); | |
1593 | sr_subobj->nai_type = | |
1594 | ((obj_buf[read_count++] >> 4) & 0x0f); | |
1595 | sr_subobj->flag_f = | |
1596 | (obj_buf[read_count] & OBJECT_SUBOBJ_SR_FLAG_F); | |
1597 | sr_subobj->flag_s = | |
1598 | (obj_buf[read_count] & OBJECT_SUBOBJ_SR_FLAG_S); | |
1599 | sr_subobj->flag_c = | |
1600 | (obj_buf[read_count] & OBJECT_SUBOBJ_SR_FLAG_C); | |
1601 | sr_subobj->flag_m = | |
1602 | (obj_buf[read_count] & OBJECT_SUBOBJ_SR_FLAG_M); | |
1603 | read_count++; | |
1604 | ||
1605 | /* If the sid_absent flag is true, then dont decode the | |
1606 | * sid */ | |
1607 | uint32_ptr = (uint32_t *)(obj_buf + read_count); | |
1608 | if (sr_subobj->flag_s == false) { | |
1609 | sr_subobj->sid = ntohl(*uint32_ptr); | |
1610 | read_count += LENGTH_1WORD; | |
1611 | uint32_ptr += 1; | |
1612 | } | |
1613 | ||
1614 | switch (sr_subobj->nai_type) { | |
1615 | case PCEP_SR_SUBOBJ_NAI_IPV4_NODE: { | |
1616 | struct in_addr *ipv4 = | |
1617 | pceplib_malloc(PCEPLIB_MESSAGES, | |
1618 | sizeof(struct in_addr)); | |
1619 | ipv4->s_addr = *uint32_ptr; | |
1620 | dll_append(sr_subobj->nai_list, ipv4); | |
1621 | read_count += LENGTH_1WORD; | |
1622 | } break; | |
1623 | ||
1624 | case PCEP_SR_SUBOBJ_NAI_IPV6_NODE: { | |
1625 | struct in6_addr *ipv6 = | |
1626 | pceplib_malloc(PCEPLIB_MESSAGES, | |
1627 | sizeof(struct in6_addr)); | |
1628 | decode_ipv6(uint32_ptr, ipv6); | |
1629 | dll_append(sr_subobj->nai_list, ipv6); | |
1630 | read_count += LENGTH_4WORDS; | |
1631 | } break; | |
1632 | ||
1633 | case PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY: { | |
1634 | struct in_addr *ipv4 = | |
1635 | pceplib_malloc(PCEPLIB_MESSAGES, | |
1636 | sizeof(struct in_addr)); | |
1637 | ipv4->s_addr = uint32_ptr[0]; | |
1638 | dll_append(sr_subobj->nai_list, ipv4); | |
1639 | ||
1640 | ipv4 = pceplib_malloc(PCEPLIB_MESSAGES, | |
1641 | sizeof(struct in_addr)); | |
1642 | ipv4->s_addr = uint32_ptr[1]; | |
1643 | dll_append(sr_subobj->nai_list, ipv4); | |
1644 | ||
1645 | ipv4 = pceplib_malloc(PCEPLIB_MESSAGES, | |
1646 | sizeof(struct in_addr)); | |
1647 | ipv4->s_addr = uint32_ptr[2]; | |
1648 | dll_append(sr_subobj->nai_list, ipv4); | |
1649 | ||
1650 | ipv4 = pceplib_malloc(PCEPLIB_MESSAGES, | |
1651 | sizeof(struct in_addr)); | |
1652 | ipv4->s_addr = uint32_ptr[3]; | |
1653 | dll_append(sr_subobj->nai_list, ipv4); | |
1654 | ||
1655 | read_count += LENGTH_4WORDS; | |
1656 | } break; | |
1657 | ||
1658 | case PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY: { | |
1659 | struct in_addr *ipv4 = | |
1660 | pceplib_malloc(PCEPLIB_MESSAGES, | |
1661 | sizeof(struct in_addr)); | |
1662 | ipv4->s_addr = uint32_ptr[0]; | |
1663 | dll_append(sr_subobj->nai_list, ipv4); | |
1664 | ||
1665 | ipv4 = pceplib_malloc(PCEPLIB_MESSAGES, | |
1666 | sizeof(struct in_addr)); | |
1667 | ipv4->s_addr = uint32_ptr[1]; | |
1668 | dll_append(sr_subobj->nai_list, ipv4); | |
1669 | ||
1670 | read_count += LENGTH_2WORDS; | |
1671 | } break; | |
1672 | ||
1673 | case PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY: { | |
1674 | struct in6_addr *ipv6 = | |
1675 | pceplib_malloc(PCEPLIB_MESSAGES, | |
1676 | sizeof(struct in6_addr)); | |
1677 | decode_ipv6(uint32_ptr, ipv6); | |
1678 | dll_append(sr_subobj->nai_list, ipv6); | |
1679 | ||
1680 | ipv6 = pceplib_malloc(PCEPLIB_MESSAGES, | |
1681 | sizeof(struct in6_addr)); | |
7ed8c4b1 | 1682 | decode_ipv6(uint32_ptr + 4, ipv6); |
74971473 JG |
1683 | dll_append(sr_subobj->nai_list, ipv6); |
1684 | ||
1685 | read_count += LENGTH_8WORDS; | |
1686 | } break; | |
1687 | ||
1688 | case PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY: { | |
1689 | struct in6_addr *ipv6 = | |
1690 | pceplib_malloc(PCEPLIB_MESSAGES, | |
1691 | sizeof(struct in6_addr)); | |
1692 | decode_ipv6(uint32_ptr, ipv6); | |
1693 | dll_append(sr_subobj->nai_list, ipv6); | |
1694 | ||
1695 | struct in_addr *ipv4 = | |
1696 | pceplib_malloc(PCEPLIB_MESSAGES, | |
1697 | sizeof(struct in_addr)); | |
7ed8c4b1 | 1698 | ipv4->s_addr = uint32_ptr[4]; |
74971473 JG |
1699 | dll_append(sr_subobj->nai_list, ipv4); |
1700 | ||
1701 | ipv6 = pceplib_malloc(PCEPLIB_MESSAGES, | |
1702 | sizeof(struct in6_addr)); | |
7ed8c4b1 | 1703 | decode_ipv6(uint32_ptr + 5, ipv6); |
74971473 JG |
1704 | dll_append(sr_subobj->nai_list, ipv6); |
1705 | ||
1706 | ipv4 = pceplib_malloc(PCEPLIB_MESSAGES, | |
1707 | sizeof(struct in_addr)); | |
7ed8c4b1 | 1708 | ipv4->s_addr = uint32_ptr[9]; |
74971473 JG |
1709 | dll_append(sr_subobj->nai_list, ipv4); |
1710 | ||
1711 | read_count += LENGTH_10WORDS; | |
1712 | } break; | |
1713 | ||
1714 | case PCEP_SR_SUBOBJ_NAI_ABSENT: | |
1715 | default: | |
1716 | break; | |
1717 | } | |
1718 | } break; | |
1719 | ||
1720 | default: | |
1721 | pcep_log( | |
1722 | LOG_INFO, | |
1723 | "%s: pcep_decode_obj_ro skipping unrecognized sub-object type [%d]", | |
1724 | __func__, subobj_type); | |
1725 | read_count += subobj_length; | |
1726 | break; | |
1727 | } | |
1728 | } | |
1729 | ||
1730 | return (struct pcep_object_header *)obj; | |
1731 | } |