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