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