2 * This file is part of the PCEPlib, a PCEP protocol library.
4 * Copyright (C) 2020 Volta Networks https://voltanet.io/
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.
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.
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/>.
19 * Author : Brady Johnson <brady@voltanet.io>
25 * Encoding and decoding for PCEP Objects.
35 #include "pcep_msg_objects.h"
36 #include "pcep_msg_encoding.h"
37 #include "pcep_utils_logging.h"
38 #include "pcep_utils_memory.h"
40 void write_object_header(struct pcep_object_header
*object_hdr
,
41 uint16_t object_length
, uint8_t *buf
);
42 void pcep_decode_object_hdr(const uint8_t *obj_buf
,
43 struct pcep_object_header
*obj_hdr
);
44 void set_ro_subobj_fields(struct pcep_object_ro_subobj
*subobj
, bool flag_l
,
48 * forward declarations for initialize_object_encoders()
50 uint16_t pcep_encode_obj_open(struct pcep_object_header
*obj
,
51 struct pcep_versioning
*versioning
, uint8_t *buf
);
52 uint16_t pcep_encode_obj_rp(struct pcep_object_header
*obj
,
53 struct pcep_versioning
*versioning
, uint8_t *buf
);
54 uint16_t pcep_encode_obj_nopath(struct pcep_object_header
*obj
,
55 struct pcep_versioning
*versioning
,
57 uint16_t pcep_encode_obj_endpoints(struct pcep_object_header
*obj
,
58 struct pcep_versioning
*versioning
,
60 uint16_t pcep_encode_obj_association(struct pcep_object_header
*obj
,
61 struct pcep_versioning
*versioning
,
63 uint16_t pcep_encode_obj_bandwidth(struct pcep_object_header
*obj
,
64 struct pcep_versioning
*versioning
,
66 uint16_t pcep_encode_obj_metric(struct pcep_object_header
*obj
,
67 struct pcep_versioning
*versioning
,
69 uint16_t pcep_encode_obj_ro(struct pcep_object_header
*obj
,
70 struct pcep_versioning
*versioning
, uint8_t *buf
);
71 uint16_t pcep_encode_obj_lspa(struct pcep_object_header
*obj
,
72 struct pcep_versioning
*versioning
, uint8_t *buf
);
73 uint16_t pcep_encode_obj_svec(struct pcep_object_header
*obj
,
74 struct pcep_versioning
*versioning
, uint8_t *buf
);
75 uint16_t pcep_encode_obj_notify(struct pcep_object_header
*obj
,
76 struct pcep_versioning
*versioning
,
78 uint16_t pcep_encode_obj_error(struct pcep_object_header
*error
,
79 struct pcep_versioning
*versioning
,
81 uint16_t pcep_encode_obj_close(struct pcep_object_header
*close
,
82 struct pcep_versioning
*versioning
,
84 uint16_t pcep_encode_obj_srp(struct pcep_object_header
*obj
,
85 struct pcep_versioning
*versioning
, uint8_t *buf
);
86 uint16_t pcep_encode_obj_lsp(struct pcep_object_header
*obj
,
87 struct pcep_versioning
*versioning
, uint8_t *buf
);
88 uint16_t pcep_encode_obj_vendor_info(struct pcep_object_header
*obj
,
89 struct pcep_versioning
*versioning
,
91 uint16_t pcep_encode_obj_inter_layer(struct pcep_object_header
*obj
,
92 struct pcep_versioning
*versioning
,
94 uint16_t pcep_encode_obj_switch_layer(struct pcep_object_header
*obj
,
95 struct pcep_versioning
*versioning
,
97 uint16_t pcep_encode_obj_req_adap_cap(struct pcep_object_header
*obj
,
98 struct pcep_versioning
*versioning
,
100 uint16_t pcep_encode_obj_server_ind(struct pcep_object_header
*obj
,
101 struct pcep_versioning
*versioning
,
103 uint16_t pcep_encode_obj_objective_function(struct pcep_object_header
*obj
,
104 struct pcep_versioning
*versioning
,
106 typedef uint16_t (*object_encoder_funcptr
)(struct pcep_object_header
*,
107 struct pcep_versioning
*versioning
,
110 #define MAX_OBJECT_ENCODER_INDEX 64
112 #define PCEP_ENCODERS_ARGS \
113 struct pcep_object_header *, struct pcep_versioning *versioning, \
115 uint16_t (*const object_encoders
[MAX_OBJECT_ENCODER_INDEX
])(
116 PCEP_ENCODERS_ARGS
) = {
117 [PCEP_OBJ_CLASS_OPEN
] = pcep_encode_obj_open
,
118 [PCEP_OBJ_CLASS_RP
] = pcep_encode_obj_rp
,
119 [PCEP_OBJ_CLASS_NOPATH
] = pcep_encode_obj_nopath
,
120 [PCEP_OBJ_CLASS_ENDPOINTS
] = pcep_encode_obj_endpoints
,
121 [PCEP_OBJ_CLASS_BANDWIDTH
] = pcep_encode_obj_bandwidth
,
122 [PCEP_OBJ_CLASS_METRIC
] = pcep_encode_obj_metric
,
123 [PCEP_OBJ_CLASS_ERO
] = pcep_encode_obj_ro
,
124 [PCEP_OBJ_CLASS_RRO
] = pcep_encode_obj_ro
,
125 [PCEP_OBJ_CLASS_LSPA
] = pcep_encode_obj_lspa
,
126 [PCEP_OBJ_CLASS_IRO
] = pcep_encode_obj_ro
,
127 [PCEP_OBJ_CLASS_SVEC
] = pcep_encode_obj_svec
,
128 [PCEP_OBJ_CLASS_NOTF
] = pcep_encode_obj_notify
,
129 [PCEP_OBJ_CLASS_ERROR
] = pcep_encode_obj_error
,
130 [PCEP_OBJ_CLASS_CLOSE
] = pcep_encode_obj_close
,
131 [PCEP_OBJ_CLASS_LSP
] = pcep_encode_obj_lsp
,
132 [PCEP_OBJ_CLASS_SRP
] = pcep_encode_obj_srp
,
133 [PCEP_OBJ_CLASS_ASSOCIATION
] = pcep_encode_obj_association
,
134 [PCEP_OBJ_CLASS_INTER_LAYER
] = pcep_encode_obj_inter_layer
,
135 [PCEP_OBJ_CLASS_SWITCH_LAYER
] = pcep_encode_obj_switch_layer
,
136 [PCEP_OBJ_CLASS_REQ_ADAP_CAP
] = pcep_encode_obj_req_adap_cap
,
137 [PCEP_OBJ_CLASS_SERVER_IND
] = pcep_encode_obj_server_ind
,
138 [PCEP_OBJ_CLASS_VENDOR_INFO
] = pcep_encode_obj_vendor_info
,
139 [PCEP_OBJ_CLASS_OF
] = pcep_encode_obj_objective_function
,
142 * forward declarations for initialize_object_decoders()
144 struct pcep_object_header
*pcep_decode_obj_open(struct pcep_object_header
*hdr
,
146 struct pcep_object_header
*pcep_decode_obj_rp(struct pcep_object_header
*hdr
,
148 struct pcep_object_header
*
149 pcep_decode_obj_nopath(struct pcep_object_header
*hdr
, const uint8_t *buf
);
150 struct pcep_object_header
*
151 pcep_decode_obj_endpoints(struct pcep_object_header
*hdr
, const uint8_t *buf
);
152 struct pcep_object_header
*
153 pcep_decode_obj_association(struct pcep_object_header
*hdr
, const uint8_t *buf
);
154 struct pcep_object_header
*
155 pcep_decode_obj_bandwidth(struct pcep_object_header
*hdr
, const uint8_t *buf
);
156 struct pcep_object_header
*
157 pcep_decode_obj_metric(struct pcep_object_header
*hdr
, const uint8_t *buf
);
158 struct pcep_object_header
*pcep_decode_obj_ro(struct pcep_object_header
*hdr
,
160 struct pcep_object_header
*pcep_decode_obj_lspa(struct pcep_object_header
*hdr
,
162 struct pcep_object_header
*pcep_decode_obj_svec(struct pcep_object_header
*hdr
,
164 struct pcep_object_header
*
165 pcep_decode_obj_notify(struct pcep_object_header
*hdr
, const uint8_t *buf
);
166 struct pcep_object_header
*pcep_decode_obj_error(struct pcep_object_header
*hdr
,
168 struct pcep_object_header
*pcep_decode_obj_close(struct pcep_object_header
*hdr
,
170 struct pcep_object_header
*pcep_decode_obj_srp(struct pcep_object_header
*hdr
,
172 struct pcep_object_header
*pcep_decode_obj_lsp(struct pcep_object_header
*hdr
,
174 struct pcep_object_header
*
175 pcep_decode_obj_vendor_info(struct pcep_object_header
*hdr
, const uint8_t *buf
);
176 struct pcep_object_header
*
177 pcep_decode_obj_inter_layer(struct pcep_object_header
*hdr
, const uint8_t *buf
);
178 struct pcep_object_header
*
179 pcep_decode_obj_switch_layer(struct pcep_object_header
*hdr
,
181 struct pcep_object_header
*
182 pcep_decode_obj_req_adap_cap(struct pcep_object_header
*hdr
,
184 struct pcep_object_header
*
185 pcep_decode_obj_server_ind(struct pcep_object_header
*hdr
, const uint8_t *buf
);
186 struct pcep_object_header
*
187 pcep_decode_obj_objective_function(struct pcep_object_header
*hdr
,
189 typedef struct pcep_object_header
*(*object_decoder_funcptr
)(
190 struct pcep_object_header
*, const uint8_t *buf
);
192 #define PCEP_DECODERS_ARGS struct pcep_object_header *, const uint8_t *buf
194 struct pcep_object_header
*(*const object_decoders
[MAX_OBJECT_ENCODER_INDEX
])(
195 PCEP_DECODERS_ARGS
) = {
196 [PCEP_OBJ_CLASS_OPEN
] = pcep_decode_obj_open
,
197 [PCEP_OBJ_CLASS_RP
] = pcep_decode_obj_rp
,
198 [PCEP_OBJ_CLASS_NOPATH
] = pcep_decode_obj_nopath
,
199 [PCEP_OBJ_CLASS_ENDPOINTS
] = pcep_decode_obj_endpoints
,
200 [PCEP_OBJ_CLASS_BANDWIDTH
] = pcep_decode_obj_bandwidth
,
201 [PCEP_OBJ_CLASS_METRIC
] = pcep_decode_obj_metric
,
202 [PCEP_OBJ_CLASS_ERO
] = pcep_decode_obj_ro
,
203 [PCEP_OBJ_CLASS_RRO
] = pcep_decode_obj_ro
,
204 [PCEP_OBJ_CLASS_LSPA
] = pcep_decode_obj_lspa
,
205 [PCEP_OBJ_CLASS_IRO
] = pcep_decode_obj_ro
,
206 [PCEP_OBJ_CLASS_SVEC
] = pcep_decode_obj_svec
,
207 [PCEP_OBJ_CLASS_NOTF
] = pcep_decode_obj_notify
,
208 [PCEP_OBJ_CLASS_ERROR
] = pcep_decode_obj_error
,
209 [PCEP_OBJ_CLASS_CLOSE
] = pcep_decode_obj_close
,
210 [PCEP_OBJ_CLASS_LSP
] = pcep_decode_obj_lsp
,
211 [PCEP_OBJ_CLASS_SRP
] = pcep_decode_obj_srp
,
212 [PCEP_OBJ_CLASS_ASSOCIATION
] = pcep_decode_obj_association
,
213 [PCEP_OBJ_CLASS_INTER_LAYER
] = pcep_decode_obj_inter_layer
,
214 [PCEP_OBJ_CLASS_SWITCH_LAYER
] = pcep_decode_obj_switch_layer
,
215 [PCEP_OBJ_CLASS_REQ_ADAP_CAP
] = pcep_decode_obj_req_adap_cap
,
216 [PCEP_OBJ_CLASS_SERVER_IND
] = pcep_decode_obj_server_ind
,
217 [PCEP_OBJ_CLASS_VENDOR_INFO
] = pcep_decode_obj_vendor_info
,
218 [PCEP_OBJ_CLASS_OF
] = pcep_decode_obj_objective_function
,
221 /* Object lengths, including the Object Header.
222 * Used by pcep_object_get_length() and pcep_object_has_tlvs() */
223 static uint8_t pcep_object_class_lengths
[] = {
224 0, /* Object class 0 unused */
225 8, /* PCEP_OBJ_CLASS_OPEN = 1 */
226 12, /* PCEP_OBJ_CLASS_RP = 2 */
227 16, /* PCEP_OBJ_CLASS_NOPATH = 3, includes 8 for mandatory TLV */
228 0, /* PCEP_OBJ_CLASS_ENDPOINTS = 4, could be ipv4 or ipv6, setting to 0
230 8, /* PCEP_OBJ_CLASS_BANDWIDTH = 5 */
231 12, /* PCEP_OBJ_CLASS_METRIC = 6 */
232 0, /* PCEP_OBJ_CLASS_ERO = 7, setting 0, ROs cannot have TLVs */
233 0, /* PCEP_OBJ_CLASS_RRO = 8, setting 0, ROs cannot have TLVs */
234 20, /* PCEP_OBJ_CLASS_LSPA = 9 */
235 0, /* PCEP_OBJ_CLASS_IRO = 10, setting 0, ROs cannot have TLVs */
236 0, /* PCEP_OBJ_CLASS_SVEC = 11, SVECs cannot have TLVs */
237 8, /* PCEP_OBJ_CLASS_NOTF = 12 */
238 8, /* PCEP_OBJ_CLASS_ERROR = 13 */
239 0, /* Object class 14 unused */
240 8, /* PCEP_OBJ_CLASS_CLOSE = 15 */
241 0, 0, 0, 0, 0, /* Object classes 16 - 20 are not used */
242 8, /* PCEP_OBJ_CLASS_OF = 21 */
243 0, 0, 0, 0, 0, /* Object classes 22 - 26 are not used */
244 0, 0, 0, 0, 0, /* Object classes 27 - 31 are not used */
245 8, /* PCEP_OBJ_CLASS_LSP = 32 */
246 12, /* PCEP_OBJ_CLASS_SRP = 33 */
247 12, /* PCEP_OBJ_CLASS_VENDOR_INFO = 34 */
248 0, /* Object class 35 unused */
249 0, /* PCEP_OBJ_CLASS_INTER_LAYER = 36, cannot have TLVs */
250 0, /* PCEP_OBJ_CLASS_SWITCH_LAYER = 37, cannot have TLVs */
251 0, /* PCEP_OBJ_CLASS_REQ_ADAP_CAP = 38, cannot have TLVs*/
252 8, /* PCEP_OBJ_CLASS_SERVER_IND = 39 */
253 0, /* PCEP_OBJ_CLASS_ASSOCIATION = 40, cannot have TLVs */
257 * The TLVs can have strange length values, since they do not include padding in
258 * the TLV header length, but that extra padding must be taken into account by
259 * the enclosing object by rounding up to the next 4 byte boundary.
260 * Example returned lengths:
261 * normalize_length(4) = 4, normalize_length(5) = 8, normalize_length(6)
262 * = 8, normalize_length(7) = 8, normalize_length(8) = 8
263 * normalize_length(9) = 12, normalize_length(10) = 12, normalize_length(11) =
264 * 12, normalize_length(12) = 12, normalize_length(13) = 13...
266 uint16_t normalize_pcep_tlv_length(uint16_t length
)
268 return (length
% 4 == 0) ? length
: (length
+ (4 - (length
% 4)));
274 uint16_t pcep_encode_object(struct pcep_object_header
*object_hdr
,
275 struct pcep_versioning
*versioning
, uint8_t *buf
)
278 if (object_hdr
->object_class
>= MAX_OBJECT_ENCODER_INDEX
) {
280 "%s: Cannot encode unknown Object class [%d]",
281 __func__
, object_hdr
->object_class
);
285 object_encoder_funcptr obj_encoder
=
286 object_encoders
[object_hdr
->object_class
];
287 if (obj_encoder
== NULL
) {
289 "%s: No object encoder found for Object class [%d]",
290 __func__
, object_hdr
->object_class
);
294 uint16_t object_length
= OBJECT_HEADER_LENGTH
295 + obj_encoder(object_hdr
, versioning
,
296 buf
+ OBJECT_HEADER_LENGTH
);
297 double_linked_list_node
*node
=
298 (object_hdr
->tlv_list
== NULL
? NULL
299 : object_hdr
->tlv_list
->head
);
300 for (; node
!= NULL
; node
= node
->next_node
) {
301 /* Returns the length of the TLV, including the TLV header */
302 object_length
+= pcep_encode_tlv(
303 (struct pcep_object_tlv_header
*)node
->data
, versioning
,
304 buf
+ object_length
);
306 object_length
= normalize_pcep_tlv_length(object_length
);
307 write_object_header(object_hdr
, object_length
, buf
);
308 object_hdr
->encoded_object
= buf
;
309 object_hdr
->encoded_object_length
= object_length
;
311 return object_length
;
318 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
319 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
320 * | Object-Class | OT |Res|P|I| Object Length (bytes) |
321 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
323 * // (Object body) //
325 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
329 void write_object_header(struct pcep_object_header
*object_hdr
,
330 uint16_t object_length
, uint8_t *buf
)
332 buf
[0] = object_hdr
->object_class
;
333 buf
[1] = ((object_hdr
->object_type
<< 4)
334 | (object_hdr
->flag_p
? OBJECT_HEADER_FLAG_P
: 0x00)
335 | (object_hdr
->flag_i
? OBJECT_HEADER_FLAG_I
: 0x00));
336 uint16_t net_order_length
= htons(object_length
);
337 memcpy(buf
+ 2, &net_order_length
, sizeof(net_order_length
));
342 * Functions to encode objects
343 * - they will be passed a pointer to a buffer to write the object body,
344 * which is past the object header.
345 * - they should return the object body length, not including the object header
349 uint16_t pcep_encode_obj_open(struct pcep_object_header
*hdr
,
350 struct pcep_versioning
*versioning
,
351 uint8_t *obj_body_buf
)
354 struct pcep_object_open
*open
= (struct pcep_object_open
*)hdr
;
355 obj_body_buf
[0] = (open
->open_version
<< 5) & 0xe0;
356 obj_body_buf
[1] = open
->open_keepalive
;
357 obj_body_buf
[2] = open
->open_deadtimer
;
358 obj_body_buf
[3] = open
->open_sid
;
363 uint16_t pcep_encode_obj_rp(struct pcep_object_header
*hdr
,
364 struct pcep_versioning
*versioning
,
365 uint8_t *obj_body_buf
)
368 struct pcep_object_rp
*rp
= (struct pcep_object_rp
*)hdr
;
369 obj_body_buf
[3] = ((rp
->flag_strict
? OBJECT_RP_FLAG_O
: 0x00)
370 | (rp
->flag_bidirectional
? OBJECT_RP_FLAG_B
: 0x00)
371 | (rp
->flag_reoptimization
? OBJECT_RP_FLAG_R
: 0x00)
372 | (rp
->flag_of
? OBJECT_RP_FLAG_OF
: 0x00)
373 | (rp
->priority
& 0x07));
374 uint32_t *uint32_ptr
= (uint32_t *)(obj_body_buf
+ 4);
375 *uint32_ptr
= htonl(rp
->request_id
);
377 return LENGTH_2WORDS
;
380 uint16_t pcep_encode_obj_notify(struct pcep_object_header
*hdr
,
381 struct pcep_versioning
*versioning
,
382 uint8_t *obj_body_buf
)
385 struct pcep_object_notify
*notify
= (struct pcep_object_notify
*)hdr
;
386 obj_body_buf
[2] = notify
->notification_type
;
387 obj_body_buf
[3] = notify
->notification_value
;
392 uint16_t pcep_encode_obj_nopath(struct pcep_object_header
*hdr
,
393 struct pcep_versioning
*versioning
,
394 uint8_t *obj_body_buf
)
397 struct pcep_object_nopath
*nopath
= (struct pcep_object_nopath
*)hdr
;
398 obj_body_buf
[0] = nopath
->ni
;
399 obj_body_buf
[1] = ((nopath
->flag_c
) ? OBJECT_NOPATH_FLAG_C
: 0x00);
404 uint16_t pcep_encode_obj_association(struct pcep_object_header
*hdr
,
405 struct pcep_versioning
*versioning
,
406 uint8_t *obj_body_buf
)
409 uint16_t *uint16_ptr
= (uint16_t *)obj_body_buf
;
410 uint32_t *uint32_ptr
= (uint32_t *)obj_body_buf
;
411 if (hdr
->object_type
== PCEP_OBJ_TYPE_ASSOCIATION_IPV4
) {
412 struct pcep_object_association_ipv4
*ipv4
=
413 (struct pcep_object_association_ipv4
*)hdr
;
415 (ipv4
->R_flag
? OBJECT_ASSOCIATION_FLAG_R
: 0x00);
416 uint16_ptr
[2] = htons(ipv4
->association_type
);
417 uint16_ptr
[3] = htons(ipv4
->association_id
);
418 uint32_ptr
[2] = ipv4
->src
.s_addr
;
420 return LENGTH_3WORDS
;
422 struct pcep_object_association_ipv6
*ipv6
=
423 (struct pcep_object_association_ipv6
*)hdr
;
425 (ipv6
->R_flag
? OBJECT_ASSOCIATION_FLAG_R
: 0x00);
426 uint16_ptr
[2] = htons(ipv6
->association_type
);
427 uint16_ptr
[3] = htons(ipv6
->association_id
);
428 memcpy(uint32_ptr
, &ipv6
->src
, sizeof(struct in6_addr
));
430 return LENGTH_6WORDS
;
434 uint16_t pcep_encode_obj_endpoints(struct pcep_object_header
*hdr
,
435 struct pcep_versioning
*versioning
,
436 uint8_t *obj_body_buf
)
439 uint32_t *uint32_ptr
= (uint32_t *)obj_body_buf
;
440 if (hdr
->object_type
== PCEP_OBJ_TYPE_ENDPOINT_IPV4
) {
441 struct pcep_object_endpoints_ipv4
*ipv4
=
442 (struct pcep_object_endpoints_ipv4
*)hdr
;
443 uint32_ptr
[0] = ipv4
->src_ipv4
.s_addr
;
444 uint32_ptr
[1] = ipv4
->dst_ipv4
.s_addr
;
446 return LENGTH_2WORDS
;
448 struct pcep_object_endpoints_ipv6
*ipv6
=
449 (struct pcep_object_endpoints_ipv6
*)hdr
;
450 memcpy(uint32_ptr
, &ipv6
->src_ipv6
, sizeof(struct in6_addr
));
451 memcpy(&uint32_ptr
[4], &ipv6
->dst_ipv6
,
452 sizeof(struct in6_addr
));
454 return LENGTH_8WORDS
;
458 uint16_t pcep_encode_obj_bandwidth(struct pcep_object_header
*hdr
,
459 struct pcep_versioning
*versioning
,
460 uint8_t *obj_body_buf
)
463 struct pcep_object_bandwidth
*bandwidth
=
464 (struct pcep_object_bandwidth
*)hdr
;
465 uint32_t *uint32_ptr
= (uint32_t *)obj_body_buf
;
466 /* Seems like the compiler doesnt correctly copy the float, so memcpy()
468 memcpy(uint32_ptr
, &(bandwidth
->bandwidth
), sizeof(uint32_t));
469 *uint32_ptr
= htonl(*uint32_ptr
);
474 uint16_t pcep_encode_obj_metric(struct pcep_object_header
*hdr
,
475 struct pcep_versioning
*versioning
,
476 uint8_t *obj_body_buf
)
479 struct pcep_object_metric
*metric
= (struct pcep_object_metric
*)hdr
;
480 obj_body_buf
[2] = ((metric
->flag_c
? OBJECT_METRIC_FLAC_C
: 0x00)
481 | (metric
->flag_b
? OBJECT_METRIC_FLAC_B
: 0x00));
482 obj_body_buf
[3] = metric
->type
;
483 uint32_t *uint32_ptr
= (uint32_t *)(obj_body_buf
+ 4);
484 /* Seems like the compiler doesnt correctly copy the float, so memcpy()
486 memcpy(uint32_ptr
, &(metric
->value
), sizeof(uint32_t));
487 *uint32_ptr
= htonl(*uint32_ptr
);
489 return LENGTH_2WORDS
;
492 uint16_t pcep_encode_obj_lspa(struct pcep_object_header
*hdr
,
493 struct pcep_versioning
*versioning
,
494 uint8_t *obj_body_buf
)
497 struct pcep_object_lspa
*lspa
= (struct pcep_object_lspa
*)hdr
;
498 uint32_t *uint32_ptr
= (uint32_t *)obj_body_buf
;
499 uint32_ptr
[0] = htonl(lspa
->lspa_exclude_any
);
500 uint32_ptr
[1] = htonl(lspa
->lspa_include_any
);
501 uint32_ptr
[2] = htonl(lspa
->lspa_include_all
);
502 obj_body_buf
[12] = lspa
->setup_priority
;
503 obj_body_buf
[13] = lspa
->holding_priority
;
505 (lspa
->flag_local_protection
? OBJECT_LSPA_FLAG_L
: 0x00);
507 return LENGTH_4WORDS
;
510 uint16_t pcep_encode_obj_svec(struct pcep_object_header
*hdr
,
511 struct pcep_versioning
*versioning
,
512 uint8_t *obj_body_buf
)
515 struct pcep_object_svec
*svec
= (struct pcep_object_svec
*)hdr
;
517 ((svec
->flag_srlg_diverse
? OBJECT_SVEC_FLAG_S
: 0x00)
518 | (svec
->flag_node_diverse
? OBJECT_SVEC_FLAG_N
: 0x00)
519 | (svec
->flag_link_diverse
? OBJECT_SVEC_FLAG_L
: 0x00));
521 if (svec
->request_id_list
== NULL
) {
526 uint32_t *uint32_ptr
= (uint32_t *)obj_body_buf
;
527 double_linked_list_node
*node
= svec
->request_id_list
->head
;
528 for (; node
!= NULL
; node
= node
->next_node
) {
529 uint32_ptr
[index
++] = htonl(*((uint32_t *)(node
->data
)));
533 + (svec
->request_id_list
->num_entries
* sizeof(uint32_t));
536 uint16_t pcep_encode_obj_error(struct pcep_object_header
*hdr
,
537 struct pcep_versioning
*versioning
,
538 uint8_t *obj_body_buf
)
541 struct pcep_object_error
*error
= (struct pcep_object_error
*)hdr
;
542 obj_body_buf
[2] = error
->error_type
;
543 obj_body_buf
[3] = error
->error_value
;
548 uint16_t pcep_encode_obj_close(struct pcep_object_header
*hdr
,
549 struct pcep_versioning
*versioning
,
550 uint8_t *obj_body_buf
)
553 struct pcep_object_close
*close
= (struct pcep_object_close
*)hdr
;
554 obj_body_buf
[3] = close
->reason
;
559 uint16_t pcep_encode_obj_srp(struct pcep_object_header
*hdr
,
560 struct pcep_versioning
*versioning
,
561 uint8_t *obj_body_buf
)
564 struct pcep_object_srp
*srp
= (struct pcep_object_srp
*)hdr
;
565 obj_body_buf
[3] = (srp
->flag_lsp_remove
? OBJECT_SRP_FLAG_R
: 0x00);
566 uint32_t *uint32_ptr
= (uint32_t *)(obj_body_buf
+ 4);
567 *uint32_ptr
= htonl(srp
->srp_id_number
);
569 return LENGTH_2WORDS
;
572 uint16_t pcep_encode_obj_lsp(struct pcep_object_header
*hdr
,
573 struct pcep_versioning
*versioning
,
574 uint8_t *obj_body_buf
)
577 struct pcep_object_lsp
*lsp
= (struct pcep_object_lsp
*)hdr
;
578 uint32_t *uint32_ptr
= (uint32_t *)obj_body_buf
;
579 uint32_ptr
[0] = htonl((lsp
->plsp_id
<< 12) & 0xfffff000);
580 obj_body_buf
[3] = ((lsp
->flag_c
? OBJECT_LSP_FLAG_C
: 0x00)
581 | ((lsp
->operational_status
<< 4) & 0x70)
582 | (lsp
->flag_a
? OBJECT_LSP_FLAG_A
: 0x00)
583 | (lsp
->flag_r
? OBJECT_LSP_FLAG_R
: 0x00)
584 | (lsp
->flag_s
? OBJECT_LSP_FLAG_S
: 0x00)
585 | (lsp
->flag_d
? OBJECT_LSP_FLAG_D
: 0x00));
590 uint16_t pcep_encode_obj_vendor_info(struct pcep_object_header
*hdr
,
591 struct pcep_versioning
*versioning
,
592 uint8_t *obj_body_buf
)
595 struct pcep_object_vendor_info
*obj
=
596 (struct pcep_object_vendor_info
*)hdr
;
597 uint32_t *uint32_ptr
= (uint32_t *)obj_body_buf
;
598 uint32_ptr
[0] = htonl(obj
->enterprise_number
);
599 uint32_ptr
[1] = htonl(obj
->enterprise_specific_info
);
601 return LENGTH_2WORDS
;
604 uint16_t pcep_encode_obj_inter_layer(struct pcep_object_header
*hdr
,
605 struct pcep_versioning
*versioning
,
606 uint8_t *obj_body_buf
)
609 struct pcep_object_inter_layer
*obj
=
610 (struct pcep_object_inter_layer
*)hdr
;
611 obj_body_buf
[3] = ((obj
->flag_i
? OBJECT_INTER_LAYER_FLAG_I
: 0x00)
612 | (obj
->flag_m
? OBJECT_INTER_LAYER_FLAG_M
: 0x00)
613 | (obj
->flag_t
? OBJECT_INTER_LAYER_FLAG_T
: 0x00));
618 uint16_t pcep_encode_obj_switch_layer(struct pcep_object_header
*hdr
,
619 struct pcep_versioning
*versioning
,
620 uint8_t *obj_body_buf
)
623 struct pcep_object_switch_layer
*obj
=
624 (struct pcep_object_switch_layer
*)hdr
;
625 uint8_t buf_index
= 0;
627 double_linked_list_node
*node
= obj
->switch_layer_rows
->head
;
628 while (node
!= NULL
) {
629 struct pcep_object_switch_layer_row
*row
= node
->data
;
634 obj_body_buf
[buf_index
] = row
->lsp_encoding_type
;
635 obj_body_buf
[buf_index
+ 1] = row
->switching_type
;
636 obj_body_buf
[buf_index
+ 3] =
637 (row
->flag_i
? OBJECT_SWITCH_LAYER_FLAG_I
: 0x00);
639 buf_index
+= LENGTH_1WORD
;
645 uint16_t pcep_encode_obj_req_adap_cap(struct pcep_object_header
*hdr
,
646 struct pcep_versioning
*versioning
,
647 uint8_t *obj_body_buf
)
650 struct pcep_object_req_adap_cap
*obj
=
651 (struct pcep_object_req_adap_cap
*)hdr
;
653 obj_body_buf
[0] = obj
->switching_capability
;
654 obj_body_buf
[1] = obj
->encoding
;
659 uint16_t pcep_encode_obj_server_ind(struct pcep_object_header
*hdr
,
660 struct pcep_versioning
*versioning
,
661 uint8_t *obj_body_buf
)
664 struct pcep_object_server_indication
*obj
=
665 (struct pcep_object_server_indication
*)hdr
;
667 obj_body_buf
[0] = obj
->switching_capability
;
668 obj_body_buf
[1] = obj
->encoding
;
673 uint16_t pcep_encode_obj_objective_function(struct pcep_object_header
*hdr
,
674 struct pcep_versioning
*versioning
,
675 uint8_t *obj_body_buf
)
678 struct pcep_object_objective_function
*obj
=
679 (struct pcep_object_objective_function
*)hdr
;
681 uint16_t *uint16_ptr
= (uint16_t *)obj_body_buf
;
682 *uint16_ptr
= htons(obj
->of_code
);
687 uint16_t pcep_encode_obj_ro(struct pcep_object_header
*hdr
,
688 struct pcep_versioning
*versioning
,
689 uint8_t *obj_body_buf
)
692 struct pcep_object_ro
*ro
= (struct pcep_object_ro
*)hdr
;
693 if (ro
== NULL
|| ro
->sub_objects
== NULL
) {
697 /* RO Subobject format
700 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
701 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
702 * |L| Type | Length | (Subobject contents) |
703 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
707 double_linked_list_node
*node
= ro
->sub_objects
->head
;
708 for (; node
!= NULL
; node
= node
->next_node
) {
709 struct pcep_object_ro_subobj
*ro_subobj
= node
->data
;
710 obj_body_buf
[index
++] =
711 ((ro_subobj
->flag_subobj_loose_hop
? 0x80 : 0x00)
712 | (ro_subobj
->ro_subobj_type
));
713 /* The length will be written below, depending on the subobj
715 uint8_t *length_ptr
= &(obj_body_buf
[index
++]);
716 uint32_t *uint32_ptr
= (uint32_t *)(obj_body_buf
+ index
);
718 /* - The index has already been incremented past the header,
719 * and now points to the ro_subobj body. Below it just needs
720 * to be incremented past the body.
722 * - Each section below needs to write the total length,
723 * including the 2 byte subobj header. */
725 switch (ro_subobj
->ro_subobj_type
) {
726 case RO_SUBOBJ_TYPE_IPV4
: {
727 struct pcep_ro_subobj_ipv4
*ipv4
=
728 (struct pcep_ro_subobj_ipv4
*)ro_subobj
;
729 uint32_ptr
[0] = ipv4
->ip_addr
.s_addr
;
730 index
+= LENGTH_1WORD
;
731 obj_body_buf
[index
++] = ipv4
->prefix_length
;
732 obj_body_buf
[index
++] =
733 (ipv4
->flag_local_protection
734 ? OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT
736 *length_ptr
= LENGTH_2WORDS
;
739 case RO_SUBOBJ_TYPE_IPV6
: {
740 struct pcep_ro_subobj_ipv6
*ipv6
=
741 (struct pcep_ro_subobj_ipv6
*)ro_subobj
;
742 encode_ipv6(&ipv6
->ip_addr
, uint32_ptr
);
743 index
+= LENGTH_4WORDS
;
744 obj_body_buf
[index
++] = ipv6
->prefix_length
;
745 obj_body_buf
[index
++] =
746 (ipv6
->flag_local_protection
747 ? OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT
749 *length_ptr
= LENGTH_5WORDS
;
752 case RO_SUBOBJ_TYPE_LABEL
: {
753 struct pcep_ro_subobj_32label
*label
=
754 (struct pcep_ro_subobj_32label
*)ro_subobj
;
755 obj_body_buf
[index
++] =
756 (label
->flag_global_label
757 ? OBJECT_SUBOBJ_LABEL_FLAG_GLOGAL
759 obj_body_buf
[index
++] = label
->class_type
;
760 uint32_ptr
= (uint32_t *)(obj_body_buf
+ index
);
761 *uint32_ptr
= htonl(label
->label
);
762 *length_ptr
= LENGTH_2WORDS
;
763 index
+= LENGTH_1WORD
;
766 case RO_SUBOBJ_TYPE_UNNUM
: {
767 struct pcep_ro_subobj_unnum
*unum
=
768 (struct pcep_ro_subobj_unnum
*)ro_subobj
;
769 index
+= 2; /* increment past 2 reserved bytes */
770 uint32_ptr
= (uint32_t *)(obj_body_buf
+ index
);
771 uint32_ptr
[0] = unum
->router_id
.s_addr
;
772 uint32_ptr
[1] = htonl(unum
->interface_id
);
773 *length_ptr
= LENGTH_3WORDS
;
774 index
+= LENGTH_2WORDS
;
777 case RO_SUBOBJ_TYPE_ASN
: {
778 struct pcep_ro_subobj_asn
*asn
=
779 (struct pcep_ro_subobj_asn
*)ro_subobj
;
780 uint16_t *uint16_ptr
=
781 (uint16_t *)(obj_body_buf
+ index
);
782 *uint16_ptr
= htons(asn
->asn
);
783 *length_ptr
= LENGTH_1WORD
;
787 case RO_SUBOBJ_TYPE_SR
: {
788 /* SR-ERO subobject format
791 * 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
792 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
793 * |L| Type=36 | Length | NT | Flags
795 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
797 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
798 * // NAI (variable, optional) //
799 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
802 struct pcep_ro_subobj_sr
*sr_subobj
=
803 (struct pcep_ro_subobj_sr
*)ro_subobj
;
804 obj_body_buf
[index
++] =
805 ((sr_subobj
->nai_type
<< 4) & 0xf0);
806 obj_body_buf
[index
++] =
807 ((sr_subobj
->flag_f
? OBJECT_SUBOBJ_SR_FLAG_F
809 | (sr_subobj
->flag_s
? OBJECT_SUBOBJ_SR_FLAG_S
811 | (sr_subobj
->flag_c
? OBJECT_SUBOBJ_SR_FLAG_C
813 | (sr_subobj
->flag_m
? OBJECT_SUBOBJ_SR_FLAG_M
815 uint32_ptr
= (uint32_t *)(obj_body_buf
+ index
);
816 /* Start with LENGTH_1WORD for the SubObj HDR + NT +
818 uint8_t sr_base_length
= LENGTH_1WORD
;
819 /* If the sid_absent flag is true, then dont convert the
821 if (sr_subobj
->flag_s
== false) {
822 uint32_ptr
[0] = htonl(sr_subobj
->sid
);
823 index
+= LENGTH_1WORD
;
824 uint32_ptr
= (uint32_t *)(obj_body_buf
+ index
);
825 sr_base_length
+= LENGTH_1WORD
;
828 /* The lengths below need to include:
829 * - sr_base_length: set above to include SR SubObj Hdr
830 * and the SID if present
831 * - Number of bytes written to the NAI
832 * The index will only be incremented below by the
833 * number of bytes written to the NAI, since the RO SR
834 * subobj header and the SID have already been written.
837 double_linked_list_node
*nai_node
=
838 (sr_subobj
->nai_list
== NULL
840 : sr_subobj
->nai_list
->head
);
841 if (nai_node
== NULL
) {
842 if (sr_subobj
->nai_type
843 == PCEP_SR_SUBOBJ_NAI_ABSENT
) {
844 *length_ptr
= sr_base_length
;
850 switch (sr_subobj
->nai_type
) {
851 case PCEP_SR_SUBOBJ_NAI_IPV4_NODE
:
853 ((struct in_addr
*)nai_node
->data
)
855 *length_ptr
= sr_base_length
+ LENGTH_1WORD
;
856 index
+= LENGTH_1WORD
;
859 case PCEP_SR_SUBOBJ_NAI_IPV6_NODE
:
860 encode_ipv6((struct in6_addr
*)nai_node
->data
,
862 *length_ptr
= sr_base_length
+ LENGTH_4WORDS
;
863 index
+= LENGTH_4WORDS
;
866 case PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY
:
868 ((struct in_addr
*)nai_node
->data
)
870 nai_node
= nai_node
->next_node
;
872 ((struct in_addr
*)nai_node
->data
)
874 nai_node
= nai_node
->next_node
;
876 ((struct in_addr
*)nai_node
->data
)
878 nai_node
= nai_node
->next_node
;
880 ((struct in_addr
*)nai_node
->data
)
882 *length_ptr
= sr_base_length
+ LENGTH_4WORDS
;
883 index
+= LENGTH_4WORDS
;
886 case PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY
:
888 ((struct in_addr
*)nai_node
->data
)
890 nai_node
= nai_node
->next_node
;
892 ((struct in_addr
*)nai_node
->data
)
894 *length_ptr
= sr_base_length
+ LENGTH_2WORDS
;
895 index
+= LENGTH_2WORDS
;
898 case PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY
:
899 encode_ipv6((struct in6_addr
*)nai_node
->data
,
901 nai_node
= nai_node
->next_node
;
902 encode_ipv6((struct in6_addr
*)nai_node
->data
,
904 *length_ptr
= sr_base_length
+ LENGTH_8WORDS
;
905 index
+= LENGTH_8WORDS
;
908 case PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY
:
909 encode_ipv6((struct in6_addr
*)nai_node
->data
,
911 nai_node
= nai_node
->next_node
;
913 ((struct in_addr
*)nai_node
->data
)
915 nai_node
= nai_node
->next_node
;
916 encode_ipv6((struct in6_addr
*)nai_node
->data
,
918 nai_node
= nai_node
->next_node
;
920 ((struct in_addr
*)nai_node
->data
)
922 *length_ptr
= sr_base_length
+ LENGTH_10WORDS
;
923 index
+= LENGTH_10WORDS
;
939 void encode_ipv6(struct in6_addr
*src_ipv6
, uint32_t *dst
)
941 memcpy(dst
, src_ipv6
, sizeof(struct in6_addr
));
945 * Decoding functions.
948 void pcep_decode_object_hdr(const uint8_t *obj_buf
,
949 struct pcep_object_header
*obj_hdr
)
951 memset(obj_hdr
, 0, sizeof(struct pcep_object_header
));
953 obj_hdr
->object_class
= obj_buf
[0];
954 obj_hdr
->object_type
= (obj_buf
[1] >> 4) & 0x0f;
955 obj_hdr
->flag_p
= (obj_buf
[1] & OBJECT_HEADER_FLAG_P
);
956 obj_hdr
->flag_i
= (obj_buf
[1] & OBJECT_HEADER_FLAG_I
);
957 uint16_t net_order_length
;
958 memcpy(&net_order_length
, obj_buf
+ 2, sizeof(net_order_length
));
959 obj_hdr
->encoded_object_length
= ntohs(net_order_length
);
960 obj_hdr
->encoded_object
= obj_buf
;
963 uint16_t pcep_object_get_length(enum pcep_object_classes object_class
,
964 enum pcep_object_types object_type
)
966 uint8_t object_length
= pcep_object_class_lengths
[object_class
];
967 if (object_length
== 0) {
968 if (object_class
== PCEP_OBJ_CLASS_ENDPOINTS
) {
969 if (object_type
== PCEP_OBJ_TYPE_ENDPOINT_IPV4
) {
971 } else if (object_type
== PCEP_OBJ_TYPE_ENDPOINT_IPV6
) {
979 return object_length
;
982 uint16_t pcep_object_get_length_by_hdr(struct pcep_object_header
*object_hdr
)
984 return (pcep_object_get_length(object_hdr
->object_class
,
985 object_hdr
->object_type
));
988 bool pcep_object_has_tlvs(struct pcep_object_header
*object_hdr
)
990 uint8_t object_length
= pcep_object_get_length_by_hdr(object_hdr
);
991 if (object_length
== 0) {
995 return (object_hdr
->encoded_object_length
- object_length
) > 0;
998 struct pcep_object_header
*pcep_decode_object(const uint8_t *obj_buf
)
1001 struct pcep_object_header object_hdr
;
1002 /* Only initializes and decodes the Object Header: class, type, flags,
1004 pcep_decode_object_hdr(obj_buf
, &object_hdr
);
1006 if (object_hdr
.object_class
>= MAX_OBJECT_ENCODER_INDEX
) {
1008 "%s: Cannot decode unknown Object class [%d]",
1009 __func__
, object_hdr
.object_class
);
1013 object_decoder_funcptr obj_decoder
=
1014 object_decoders
[object_hdr
.object_class
];
1015 if (obj_decoder
== NULL
) {
1017 "%s: No object decoder found for Object class [%d]",
1018 __func__
, object_hdr
.object_class
);
1022 /* The object decoders will start decoding the object body, if
1023 * anything from the header is needed, they have the object_hdr */
1024 struct pcep_object_header
*object
=
1025 obj_decoder(&object_hdr
, obj_buf
+ OBJECT_HEADER_LENGTH
);
1026 if (object
== NULL
) {
1027 pcep_log(LOG_INFO
, "%s: Unable to decode Object class [%d].",
1028 __func__
, object_hdr
.object_class
);
1032 if (pcep_object_has_tlvs(&object_hdr
)) {
1033 object
->tlv_list
= dll_initialize();
1034 int num_iterations
= 0;
1035 uint16_t tlv_index
= pcep_object_get_length_by_hdr(&object_hdr
);
1036 while ((object
->encoded_object_length
- tlv_index
) > 0
1037 && num_iterations
++ < MAX_ITERATIONS
) {
1038 struct pcep_object_tlv_header
*tlv
=
1039 pcep_decode_tlv(obj_buf
+ tlv_index
);
1041 /* TODO should we do anything else here ? */
1045 /* The TLV length does not include the TLV header */
1046 tlv_index
+= normalize_pcep_tlv_length(
1047 tlv
->encoded_tlv_length
+ TLV_HEADER_LENGTH
);
1048 dll_append(object
->tlv_list
, tlv
);
1055 static struct pcep_object_header
*
1056 common_object_create(struct pcep_object_header
*hdr
, uint16_t new_obj_length
)
1058 struct pcep_object_header
*new_object
=
1059 pceplib_malloc(PCEPLIB_MESSAGES
, new_obj_length
);
1060 memset(new_object
, 0, new_obj_length
);
1061 memcpy(new_object
, hdr
, sizeof(struct pcep_object_header
));
1070 struct pcep_object_header
*pcep_decode_obj_open(struct pcep_object_header
*hdr
,
1071 const uint8_t *obj_buf
)
1073 struct pcep_object_open
*obj
=
1074 (struct pcep_object_open
*)common_object_create(
1075 hdr
, sizeof(struct pcep_object_open
));
1077 obj
->open_version
= (obj_buf
[0] >> 5) & 0x07;
1078 obj
->open_keepalive
= obj_buf
[1];
1079 obj
->open_deadtimer
= obj_buf
[2];
1080 obj
->open_sid
= obj_buf
[3];
1082 return (struct pcep_object_header
*)obj
;
1085 struct pcep_object_header
*pcep_decode_obj_rp(struct pcep_object_header
*hdr
,
1086 const uint8_t *obj_buf
)
1088 struct pcep_object_rp
*obj
=
1089 (struct pcep_object_rp
*)common_object_create(
1090 hdr
, sizeof(struct pcep_object_rp
));
1092 obj
->flag_reoptimization
= (obj_buf
[3] & OBJECT_RP_FLAG_R
);
1093 obj
->flag_bidirectional
= (obj_buf
[3] & OBJECT_RP_FLAG_B
);
1094 obj
->flag_strict
= (obj_buf
[3] & OBJECT_RP_FLAG_O
);
1095 obj
->flag_of
= (obj_buf
[3] & OBJECT_RP_FLAG_OF
);
1096 obj
->priority
= (obj_buf
[3] & 0x07);
1097 obj
->request_id
= ntohl(*((uint32_t *)(obj_buf
+ 4)));
1099 return (struct pcep_object_header
*)obj
;
1102 struct pcep_object_header
*
1103 pcep_decode_obj_notify(struct pcep_object_header
*hdr
, const uint8_t *obj_buf
)
1105 struct pcep_object_notify
*obj
=
1106 (struct pcep_object_notify
*)common_object_create(
1107 hdr
, sizeof(struct pcep_object_notify
));
1109 obj
->notification_type
= obj_buf
[2];
1110 obj
->notification_value
= obj_buf
[3];
1112 return (struct pcep_object_header
*)obj
;
1115 struct pcep_object_header
*
1116 pcep_decode_obj_nopath(struct pcep_object_header
*hdr
, const uint8_t *obj_buf
)
1118 struct pcep_object_nopath
*obj
=
1119 (struct pcep_object_nopath
*)common_object_create(
1120 hdr
, sizeof(struct pcep_object_nopath
));
1122 obj
->ni
= (obj_buf
[0] >> 1);
1123 obj
->flag_c
= (obj_buf
[0] & OBJECT_NOPATH_FLAG_C
);
1125 return (struct pcep_object_header
*)obj
;
1128 struct pcep_object_header
*
1129 pcep_decode_obj_association(struct pcep_object_header
*hdr
,
1130 const uint8_t *obj_buf
)
1132 uint16_t *uint16_ptr
= (uint16_t *)obj_buf
;
1133 uint32_t *uint32_ptr
= (uint32_t *)obj_buf
;
1135 if (hdr
->object_type
== PCEP_OBJ_TYPE_ASSOCIATION_IPV4
) {
1136 struct pcep_object_association_ipv4
*obj
=
1137 (struct pcep_object_association_ipv4
*)
1138 common_object_create(
1141 pcep_object_association_ipv4
));
1142 obj
->R_flag
= (obj_buf
[3] & OBJECT_ASSOCIATION_FLAG_R
);
1143 obj
->association_type
= ntohs(uint16_ptr
[2]);
1144 obj
->association_id
= ntohs(uint16_ptr
[3]);
1145 obj
->src
.s_addr
= uint32_ptr
[2];
1147 return (struct pcep_object_header
*)obj
;
1148 } else if (hdr
->object_type
== PCEP_OBJ_TYPE_ENDPOINT_IPV6
) {
1149 struct pcep_object_association_ipv6
*obj
=
1150 (struct pcep_object_association_ipv6
*)
1151 common_object_create(
1154 pcep_object_association_ipv6
));
1156 obj
->R_flag
= (obj_buf
[3] & OBJECT_ASSOCIATION_FLAG_R
);
1157 obj
->association_type
= ntohs(uint16_ptr
[2]);
1158 obj
->association_id
= ntohs(uint16_ptr
[3]);
1159 memcpy(&obj
->src
, &uint32_ptr
[2], sizeof(struct in6_addr
));
1161 return (struct pcep_object_header
*)obj
;
1166 struct pcep_object_header
*
1167 pcep_decode_obj_endpoints(struct pcep_object_header
*hdr
,
1168 const uint8_t *obj_buf
)
1170 uint32_t *uint32_ptr
= (uint32_t *)obj_buf
;
1172 if (hdr
->object_type
== PCEP_OBJ_TYPE_ENDPOINT_IPV4
) {
1173 struct pcep_object_endpoints_ipv4
*obj
=
1174 (struct pcep_object_endpoints_ipv4
*)
1175 common_object_create(
1178 pcep_object_endpoints_ipv4
));
1179 obj
->src_ipv4
.s_addr
= uint32_ptr
[0];
1180 obj
->dst_ipv4
.s_addr
= uint32_ptr
[1];
1182 return (struct pcep_object_header
*)obj
;
1183 } else if (hdr
->object_type
== PCEP_OBJ_TYPE_ENDPOINT_IPV6
) {
1184 struct pcep_object_endpoints_ipv6
*obj
=
1185 (struct pcep_object_endpoints_ipv6
*)
1186 common_object_create(
1189 pcep_object_endpoints_ipv6
));
1191 memcpy(&obj
->src_ipv6
, &uint32_ptr
[0], sizeof(struct in6_addr
));
1192 memcpy(&obj
->dst_ipv6
, &uint32_ptr
[4], sizeof(struct in6_addr
));
1194 return (struct pcep_object_header
*)obj
;
1200 struct pcep_object_header
*
1201 pcep_decode_obj_bandwidth(struct pcep_object_header
*hdr
,
1202 const uint8_t *obj_buf
)
1204 struct pcep_object_bandwidth
*obj
=
1205 (struct pcep_object_bandwidth
*)common_object_create(
1206 hdr
, sizeof(struct pcep_object_bandwidth
));
1208 uint32_t value
= ntohl(*((uint32_t *)obj_buf
));
1209 /* Seems like the compiler doesnt correctly copy to the float, so
1211 memcpy(&obj
->bandwidth
, &value
, sizeof(uint32_t));
1213 return (struct pcep_object_header
*)obj
;
1216 struct pcep_object_header
*
1217 pcep_decode_obj_metric(struct pcep_object_header
*hdr
, const uint8_t *obj_buf
)
1219 struct pcep_object_metric
*obj
=
1220 (struct pcep_object_metric
*)common_object_create(
1221 hdr
, sizeof(struct pcep_object_metric
));
1222 obj
->flag_b
= (obj_buf
[2] & OBJECT_METRIC_FLAC_B
);
1223 obj
->flag_c
= (obj_buf
[2] & OBJECT_METRIC_FLAC_C
);
1224 obj
->type
= obj_buf
[3];
1225 uint32_t value
= ntohl(*((uint32_t *)(obj_buf
+ 4)));
1226 /* Seems like the compiler doesnt correctly copy to the float, so
1228 memcpy(&obj
->value
, &value
, sizeof(uint32_t));
1230 return (struct pcep_object_header
*)obj
;
1233 struct pcep_object_header
*pcep_decode_obj_lspa(struct pcep_object_header
*hdr
,
1234 const uint8_t *obj_buf
)
1236 struct pcep_object_lspa
*obj
=
1237 (struct pcep_object_lspa
*)common_object_create(
1238 hdr
, sizeof(struct pcep_object_lspa
));
1239 uint32_t *uint32_ptr
= (uint32_t *)obj_buf
;
1241 obj
->lspa_exclude_any
= ntohl(uint32_ptr
[0]);
1242 obj
->lspa_include_any
= ntohl(uint32_ptr
[1]);
1243 obj
->lspa_include_all
= ntohl(uint32_ptr
[2]);
1244 obj
->setup_priority
= obj_buf
[12];
1245 obj
->holding_priority
= obj_buf
[13];
1246 obj
->flag_local_protection
= (obj_buf
[14] & OBJECT_LSPA_FLAG_L
);
1248 return (struct pcep_object_header
*)obj
;
1251 struct pcep_object_header
*pcep_decode_obj_svec(struct pcep_object_header
*hdr
,
1252 const uint8_t *obj_buf
)
1254 struct pcep_object_svec
*obj
=
1255 (struct pcep_object_svec
*)common_object_create(
1256 hdr
, sizeof(struct pcep_object_svec
));
1258 obj
->flag_link_diverse
= (obj_buf
[3] & OBJECT_SVEC_FLAG_L
);
1259 obj
->flag_node_diverse
= (obj_buf
[3] & OBJECT_SVEC_FLAG_N
);
1260 obj
->flag_srlg_diverse
= (obj_buf
[3] & OBJECT_SVEC_FLAG_S
);
1262 if (hdr
->encoded_object_length
> LENGTH_2WORDS
) {
1263 obj
->request_id_list
= dll_initialize();
1265 uint32_t *uint32_ptr
= (uint32_t *)obj_buf
;
1267 index
< ((hdr
->encoded_object_length
- LENGTH_2WORDS
) / 4);
1269 uint32_t *req_id_ptr
= pceplib_malloc(PCEPLIB_MESSAGES
,
1271 *req_id_ptr
= uint32_ptr
[index
];
1272 dll_append(obj
->request_id_list
, req_id_ptr
);
1276 return (struct pcep_object_header
*)obj
;
1279 struct pcep_object_header
*pcep_decode_obj_error(struct pcep_object_header
*hdr
,
1280 const uint8_t *obj_buf
)
1282 struct pcep_object_error
*obj
=
1283 (struct pcep_object_error
*)common_object_create(
1284 hdr
, sizeof(struct pcep_object_error
));
1286 obj
->error_type
= obj_buf
[2];
1287 obj
->error_value
= obj_buf
[3];
1289 return (struct pcep_object_header
*)obj
;
1292 struct pcep_object_header
*pcep_decode_obj_close(struct pcep_object_header
*hdr
,
1293 const uint8_t *obj_buf
)
1295 struct pcep_object_close
*obj
=
1296 (struct pcep_object_close
*)common_object_create(
1297 hdr
, sizeof(struct pcep_object_close
));
1299 obj
->reason
= obj_buf
[3];
1301 return (struct pcep_object_header
*)obj
;
1304 struct pcep_object_header
*pcep_decode_obj_srp(struct pcep_object_header
*hdr
,
1305 const uint8_t *obj_buf
)
1307 struct pcep_object_srp
*obj
=
1308 (struct pcep_object_srp
*)common_object_create(
1309 hdr
, sizeof(struct pcep_object_srp
));
1311 obj
->flag_lsp_remove
= (obj_buf
[3] & OBJECT_SRP_FLAG_R
);
1312 obj
->srp_id_number
= ntohl(*((uint32_t *)(obj_buf
+ 4)));
1314 return (struct pcep_object_header
*)obj
;
1317 struct pcep_object_header
*pcep_decode_obj_lsp(struct pcep_object_header
*hdr
,
1318 const uint8_t *obj_buf
)
1320 struct pcep_object_lsp
*obj
=
1321 (struct pcep_object_lsp
*)common_object_create(
1322 hdr
, sizeof(struct pcep_object_lsp
));
1324 obj
->flag_d
= (obj_buf
[3] & OBJECT_LSP_FLAG_D
);
1325 obj
->flag_s
= (obj_buf
[3] & OBJECT_LSP_FLAG_S
);
1326 obj
->flag_r
= (obj_buf
[3] & OBJECT_LSP_FLAG_R
);
1327 obj
->flag_a
= (obj_buf
[3] & OBJECT_LSP_FLAG_A
);
1328 obj
->flag_c
= (obj_buf
[3] & OBJECT_LSP_FLAG_C
);
1329 obj
->operational_status
= ((obj_buf
[3] >> 4) & 0x07);
1330 obj
->plsp_id
= ((ntohl(*((uint32_t *)obj_buf
)) >> 12) & 0x000fffff);
1332 return (struct pcep_object_header
*)obj
;
1335 struct pcep_object_header
*
1336 pcep_decode_obj_vendor_info(struct pcep_object_header
*hdr
,
1337 const uint8_t *obj_buf
)
1339 struct pcep_object_vendor_info
*obj
=
1340 (struct pcep_object_vendor_info
*)common_object_create(
1341 hdr
, sizeof(struct pcep_object_vendor_info
));
1342 obj
->enterprise_number
= ntohl(*((uint32_t *)(obj_buf
)));
1343 obj
->enterprise_specific_info
= ntohl(*((uint32_t *)(obj_buf
+ 4)));
1345 return (struct pcep_object_header
*)obj
;
1348 struct pcep_object_header
*
1349 pcep_decode_obj_inter_layer(struct pcep_object_header
*hdr
,
1350 const uint8_t *obj_buf
)
1352 struct pcep_object_inter_layer
*obj
=
1353 (struct pcep_object_inter_layer
*)common_object_create(
1354 hdr
, sizeof(struct pcep_object_inter_layer
));
1355 obj
->flag_t
= (obj_buf
[3] & OBJECT_INTER_LAYER_FLAG_T
);
1356 obj
->flag_m
= (obj_buf
[3] & OBJECT_INTER_LAYER_FLAG_M
);
1357 obj
->flag_i
= (obj_buf
[3] & OBJECT_INTER_LAYER_FLAG_I
);
1359 return (struct pcep_object_header
*)obj
;
1362 struct pcep_object_header
*
1363 pcep_decode_obj_switch_layer(struct pcep_object_header
*hdr
,
1364 const uint8_t *obj_buf
)
1366 struct pcep_object_switch_layer
*obj
=
1367 (struct pcep_object_switch_layer
*)common_object_create(
1368 hdr
, sizeof(struct pcep_object_switch_layer
));
1369 obj
->switch_layer_rows
= dll_initialize();
1370 int num_rows
= ((hdr
->encoded_object_length
- 4) / 4);
1371 uint8_t buf_index
= 0;
1374 for (; i
< num_rows
; i
++) {
1375 struct pcep_object_switch_layer_row
*row
= pceplib_malloc(
1377 sizeof(struct pcep_object_switch_layer_row
));
1378 row
->lsp_encoding_type
= obj_buf
[buf_index
];
1379 row
->switching_type
= obj_buf
[buf_index
+ 1];
1381 (obj_buf
[buf_index
+ 3] & OBJECT_SWITCH_LAYER_FLAG_I
);
1382 dll_append(obj
->switch_layer_rows
, row
);
1384 buf_index
+= LENGTH_1WORD
;
1387 return (struct pcep_object_header
*)obj
;
1390 struct pcep_object_header
*
1391 pcep_decode_obj_req_adap_cap(struct pcep_object_header
*hdr
,
1392 const uint8_t *obj_buf
)
1394 struct pcep_object_req_adap_cap
*obj
=
1395 (struct pcep_object_req_adap_cap
*)common_object_create(
1396 hdr
, sizeof(struct pcep_object_req_adap_cap
));
1398 obj
->switching_capability
= obj_buf
[0];
1399 obj
->encoding
= obj_buf
[1];
1401 return (struct pcep_object_header
*)obj
;
1404 struct pcep_object_header
*
1405 pcep_decode_obj_server_ind(struct pcep_object_header
*hdr
,
1406 const uint8_t *obj_buf
)
1408 struct pcep_object_server_indication
*obj
=
1409 (struct pcep_object_server_indication
*)common_object_create(
1410 hdr
, sizeof(struct pcep_object_server_indication
));
1412 obj
->switching_capability
= obj_buf
[0];
1413 obj
->encoding
= obj_buf
[1];
1415 return (struct pcep_object_header
*)obj
;
1418 struct pcep_object_header
*
1419 pcep_decode_obj_objective_function(struct pcep_object_header
*hdr
,
1420 const uint8_t *obj_buf
)
1422 struct pcep_object_objective_function
*obj
=
1423 (struct pcep_object_objective_function
*)common_object_create(
1424 hdr
, sizeof(struct pcep_object_objective_function
));
1426 uint16_t *uint16_ptr
= (uint16_t *)obj_buf
;
1427 obj
->of_code
= ntohs(*uint16_ptr
);
1429 return (struct pcep_object_header
*)obj
;
1432 void set_ro_subobj_fields(struct pcep_object_ro_subobj
*subobj
, bool flag_l
,
1433 uint8_t subobj_type
)
1435 subobj
->flag_subobj_loose_hop
= flag_l
;
1436 subobj
->ro_subobj_type
= subobj_type
;
1439 void decode_ipv6(const uint32_t *src
, struct in6_addr
*dst_ipv6
)
1441 memcpy(dst_ipv6
, src
, sizeof(struct in6_addr
));
1443 struct pcep_object_header
*pcep_decode_obj_ro(struct pcep_object_header
*hdr
,
1444 const uint8_t *obj_buf
)
1446 struct pcep_object_ro
*obj
=
1447 (struct pcep_object_ro
*)common_object_create(
1448 hdr
, sizeof(struct pcep_object_ro
));
1449 obj
->sub_objects
= dll_initialize();
1451 /* RO Subobject format
1454 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
1455 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
1456 * |L| Type | Length | (Subobject contents) |
1457 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
1460 uint16_t read_count
= 0;
1461 int num_sub_objects
= 1;
1462 uint32_t *uint32_ptr
;
1463 uint16_t obj_body_length
=
1464 hdr
->encoded_object_length
- OBJECT_HEADER_LENGTH
;
1466 while ((obj_body_length
- read_count
) > OBJECT_RO_SUBOBJ_HEADER_LENGTH
1467 && num_sub_objects
< MAX_ITERATIONS
) {
1469 /* Read the Sub-Object Header */
1470 bool flag_l
= (obj_buf
[read_count
] & 0x80);
1471 uint8_t subobj_type
= (obj_buf
[read_count
++] & 0x7f);
1472 uint8_t subobj_length
= obj_buf
[read_count
++];
1474 if (subobj_length
<= OBJECT_RO_SUBOBJ_HEADER_LENGTH
) {
1476 "%s: Invalid ro subobj type [%d] length [%d]",
1477 __func__
, subobj_type
, subobj_length
);
1478 pceplib_free(PCEPLIB_MESSAGES
, obj
);
1482 switch (subobj_type
) {
1483 case RO_SUBOBJ_TYPE_IPV4
: {
1484 struct pcep_ro_subobj_ipv4
*ipv4
= pceplib_malloc(
1486 sizeof(struct pcep_ro_subobj_ipv4
));
1487 ipv4
->ro_subobj
.flag_subobj_loose_hop
= flag_l
;
1488 ipv4
->ro_subobj
.ro_subobj_type
= subobj_type
;
1489 uint32_ptr
= (uint32_t *)(obj_buf
+ read_count
);
1490 ipv4
->ip_addr
.s_addr
= *uint32_ptr
;
1491 read_count
+= LENGTH_1WORD
;
1492 ipv4
->prefix_length
= obj_buf
[read_count
++];
1493 ipv4
->flag_local_protection
=
1494 (obj_buf
[read_count
++]
1495 & OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT
);
1497 dll_append(obj
->sub_objects
, ipv4
);
1500 case RO_SUBOBJ_TYPE_IPV6
: {
1501 struct pcep_ro_subobj_ipv6
*ipv6
= pceplib_malloc(
1503 sizeof(struct pcep_ro_subobj_ipv6
));
1504 ipv6
->ro_subobj
.flag_subobj_loose_hop
= flag_l
;
1505 ipv6
->ro_subobj
.ro_subobj_type
= subobj_type
;
1506 decode_ipv6((uint32_t *)obj_buf
, &ipv6
->ip_addr
);
1507 read_count
+= LENGTH_4WORDS
;
1508 ipv6
->prefix_length
= obj_buf
[read_count
++];
1509 ipv6
->flag_local_protection
=
1510 (obj_buf
[read_count
++]
1511 & OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT
);
1513 dll_append(obj
->sub_objects
, ipv6
);
1516 case RO_SUBOBJ_TYPE_LABEL
: {
1517 struct pcep_ro_subobj_32label
*label
= pceplib_malloc(
1519 sizeof(struct pcep_ro_subobj_32label
));
1520 label
->ro_subobj
.flag_subobj_loose_hop
= flag_l
;
1521 label
->ro_subobj
.ro_subobj_type
= subobj_type
;
1522 label
->flag_global_label
=
1523 (obj_buf
[read_count
++]
1524 & OBJECT_SUBOBJ_LABEL_FLAG_GLOGAL
);
1525 label
->class_type
= obj_buf
[read_count
++];
1526 label
->label
= ntohl(obj_buf
[read_count
]);
1527 read_count
+= LENGTH_1WORD
;
1529 dll_append(obj
->sub_objects
, label
);
1532 case RO_SUBOBJ_TYPE_UNNUM
: {
1533 struct pcep_ro_subobj_unnum
*unum
= pceplib_malloc(
1535 sizeof(struct pcep_ro_subobj_unnum
));
1536 unum
->ro_subobj
.flag_subobj_loose_hop
= flag_l
;
1537 unum
->ro_subobj
.ro_subobj_type
= subobj_type
;
1538 set_ro_subobj_fields(
1539 (struct pcep_object_ro_subobj
*)unum
, flag_l
,
1541 uint32_ptr
= (uint32_t *)(obj_buf
+ read_count
);
1542 unum
->interface_id
= ntohl(uint32_ptr
[0]);
1543 unum
->router_id
.s_addr
= uint32_ptr
[1];
1546 dll_append(obj
->sub_objects
, unum
);
1549 case RO_SUBOBJ_TYPE_ASN
: {
1550 struct pcep_ro_subobj_asn
*asn
= pceplib_malloc(
1552 sizeof(struct pcep_ro_subobj_asn
));
1553 asn
->ro_subobj
.flag_subobj_loose_hop
= flag_l
;
1554 asn
->ro_subobj
.ro_subobj_type
= subobj_type
;
1555 uint16_t *uint16_ptr
=
1556 (uint16_t *)(obj_buf
+ read_count
);
1557 asn
->asn
= ntohs(*uint16_ptr
);
1560 dll_append(obj
->sub_objects
, asn
);
1563 case RO_SUBOBJ_TYPE_SR
: {
1564 /* SR-ERO subobject format
1567 * 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
1568 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1569 * |L| Type=36 | Length | NT | Flags
1571 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1572 * | SID (optional) |
1573 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1574 * // NAI (variable, optional) //
1575 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1578 struct pcep_ro_subobj_sr
*sr_subobj
= pceplib_malloc(
1580 sizeof(struct pcep_ro_subobj_sr
));
1581 sr_subobj
->ro_subobj
.flag_subobj_loose_hop
= flag_l
;
1582 sr_subobj
->ro_subobj
.ro_subobj_type
= subobj_type
;
1583 dll_append(obj
->sub_objects
, sr_subobj
);
1585 sr_subobj
->nai_list
= dll_initialize();
1586 sr_subobj
->nai_type
=
1587 ((obj_buf
[read_count
++] >> 4) & 0x0f);
1589 (obj_buf
[read_count
] & OBJECT_SUBOBJ_SR_FLAG_F
);
1591 (obj_buf
[read_count
] & OBJECT_SUBOBJ_SR_FLAG_S
);
1593 (obj_buf
[read_count
] & OBJECT_SUBOBJ_SR_FLAG_C
);
1595 (obj_buf
[read_count
] & OBJECT_SUBOBJ_SR_FLAG_M
);
1598 /* If the sid_absent flag is true, then dont decode the
1600 uint32_ptr
= (uint32_t *)(obj_buf
+ read_count
);
1601 if (sr_subobj
->flag_s
== false) {
1602 sr_subobj
->sid
= ntohl(*uint32_ptr
);
1603 read_count
+= LENGTH_1WORD
;
1607 switch (sr_subobj
->nai_type
) {
1608 case PCEP_SR_SUBOBJ_NAI_IPV4_NODE
: {
1609 struct in_addr
*ipv4
=
1610 pceplib_malloc(PCEPLIB_MESSAGES
,
1611 sizeof(struct in_addr
));
1612 ipv4
->s_addr
= *uint32_ptr
;
1613 dll_append(sr_subobj
->nai_list
, ipv4
);
1614 read_count
+= LENGTH_1WORD
;
1617 case PCEP_SR_SUBOBJ_NAI_IPV6_NODE
: {
1618 struct in6_addr
*ipv6
=
1619 pceplib_malloc(PCEPLIB_MESSAGES
,
1620 sizeof(struct in6_addr
));
1621 decode_ipv6(uint32_ptr
, ipv6
);
1622 dll_append(sr_subobj
->nai_list
, ipv6
);
1623 read_count
+= LENGTH_4WORDS
;
1626 case PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY
: {
1627 struct in_addr
*ipv4
=
1628 pceplib_malloc(PCEPLIB_MESSAGES
,
1629 sizeof(struct in_addr
));
1630 ipv4
->s_addr
= uint32_ptr
[0];
1631 dll_append(sr_subobj
->nai_list
, ipv4
);
1633 ipv4
= pceplib_malloc(PCEPLIB_MESSAGES
,
1634 sizeof(struct in_addr
));
1635 ipv4
->s_addr
= uint32_ptr
[1];
1636 dll_append(sr_subobj
->nai_list
, ipv4
);
1638 ipv4
= pceplib_malloc(PCEPLIB_MESSAGES
,
1639 sizeof(struct in_addr
));
1640 ipv4
->s_addr
= uint32_ptr
[2];
1641 dll_append(sr_subobj
->nai_list
, ipv4
);
1643 ipv4
= pceplib_malloc(PCEPLIB_MESSAGES
,
1644 sizeof(struct in_addr
));
1645 ipv4
->s_addr
= uint32_ptr
[3];
1646 dll_append(sr_subobj
->nai_list
, ipv4
);
1648 read_count
+= LENGTH_4WORDS
;
1651 case PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY
: {
1652 struct in_addr
*ipv4
=
1653 pceplib_malloc(PCEPLIB_MESSAGES
,
1654 sizeof(struct in_addr
));
1655 ipv4
->s_addr
= uint32_ptr
[0];
1656 dll_append(sr_subobj
->nai_list
, ipv4
);
1658 ipv4
= pceplib_malloc(PCEPLIB_MESSAGES
,
1659 sizeof(struct in_addr
));
1660 ipv4
->s_addr
= uint32_ptr
[1];
1661 dll_append(sr_subobj
->nai_list
, ipv4
);
1663 read_count
+= LENGTH_2WORDS
;
1666 case PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY
: {
1667 struct in6_addr
*ipv6
=
1668 pceplib_malloc(PCEPLIB_MESSAGES
,
1669 sizeof(struct in6_addr
));
1670 decode_ipv6(uint32_ptr
, ipv6
);
1671 dll_append(sr_subobj
->nai_list
, ipv6
);
1673 ipv6
= pceplib_malloc(PCEPLIB_MESSAGES
,
1674 sizeof(struct in6_addr
));
1675 decode_ipv6(uint32_ptr
+ 4, ipv6
);
1676 dll_append(sr_subobj
->nai_list
, ipv6
);
1678 read_count
+= LENGTH_8WORDS
;
1681 case PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY
: {
1682 struct in6_addr
*ipv6
=
1683 pceplib_malloc(PCEPLIB_MESSAGES
,
1684 sizeof(struct in6_addr
));
1685 decode_ipv6(uint32_ptr
, ipv6
);
1686 dll_append(sr_subobj
->nai_list
, ipv6
);
1688 struct in_addr
*ipv4
=
1689 pceplib_malloc(PCEPLIB_MESSAGES
,
1690 sizeof(struct in_addr
));
1691 ipv4
->s_addr
= uint32_ptr
[4];
1692 dll_append(sr_subobj
->nai_list
, ipv4
);
1694 ipv6
= pceplib_malloc(PCEPLIB_MESSAGES
,
1695 sizeof(struct in6_addr
));
1696 decode_ipv6(uint32_ptr
+ 5, ipv6
);
1697 dll_append(sr_subobj
->nai_list
, ipv6
);
1699 ipv4
= pceplib_malloc(PCEPLIB_MESSAGES
,
1700 sizeof(struct in_addr
));
1701 ipv4
->s_addr
= uint32_ptr
[9];
1702 dll_append(sr_subobj
->nai_list
, ipv4
);
1704 read_count
+= LENGTH_10WORDS
;
1707 case PCEP_SR_SUBOBJ_NAI_ABSENT
:
1716 "%s: pcep_decode_obj_ro skipping unrecognized sub-object type [%d]",
1717 __func__
, subobj_type
);
1718 read_count
+= subobj_length
;
1723 return (struct pcep_object_header
*)obj
;