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
));
1343 obj
->enterprise_number
= ntohl(*((uint32_t *)(obj_buf
)));
1344 obj
->enterprise_specific_info
= ntohl(*((uint32_t *)(obj_buf
+ 4)));
1345 if (obj
->enterprise_number
== ENTERPRISE_NUMBER_CISCO
1346 && obj
->enterprise_specific_info
== ENTERPRISE_COLOR_CISCO
)
1347 obj
->enterprise_specific_info1
=
1348 ntohl(*((uint32_t *)(obj_buf
+ 8)));
1350 obj
->enterprise_specific_info1
= 0;
1352 return (struct pcep_object_header
*)obj
;
1355 struct pcep_object_header
*
1356 pcep_decode_obj_inter_layer(struct pcep_object_header
*hdr
,
1357 const uint8_t *obj_buf
)
1359 struct pcep_object_inter_layer
*obj
=
1360 (struct pcep_object_inter_layer
*)common_object_create(
1361 hdr
, sizeof(struct pcep_object_inter_layer
));
1362 obj
->flag_t
= (obj_buf
[3] & OBJECT_INTER_LAYER_FLAG_T
);
1363 obj
->flag_m
= (obj_buf
[3] & OBJECT_INTER_LAYER_FLAG_M
);
1364 obj
->flag_i
= (obj_buf
[3] & OBJECT_INTER_LAYER_FLAG_I
);
1366 return (struct pcep_object_header
*)obj
;
1369 struct pcep_object_header
*
1370 pcep_decode_obj_switch_layer(struct pcep_object_header
*hdr
,
1371 const uint8_t *obj_buf
)
1373 struct pcep_object_switch_layer
*obj
=
1374 (struct pcep_object_switch_layer
*)common_object_create(
1375 hdr
, sizeof(struct pcep_object_switch_layer
));
1376 obj
->switch_layer_rows
= dll_initialize();
1377 int num_rows
= ((hdr
->encoded_object_length
- 4) / 4);
1378 uint8_t buf_index
= 0;
1381 for (; i
< num_rows
; i
++) {
1382 struct pcep_object_switch_layer_row
*row
= pceplib_malloc(
1384 sizeof(struct pcep_object_switch_layer_row
));
1385 row
->lsp_encoding_type
= obj_buf
[buf_index
];
1386 row
->switching_type
= obj_buf
[buf_index
+ 1];
1388 (obj_buf
[buf_index
+ 3] & OBJECT_SWITCH_LAYER_FLAG_I
);
1389 dll_append(obj
->switch_layer_rows
, row
);
1391 buf_index
+= LENGTH_1WORD
;
1394 return (struct pcep_object_header
*)obj
;
1397 struct pcep_object_header
*
1398 pcep_decode_obj_req_adap_cap(struct pcep_object_header
*hdr
,
1399 const uint8_t *obj_buf
)
1401 struct pcep_object_req_adap_cap
*obj
=
1402 (struct pcep_object_req_adap_cap
*)common_object_create(
1403 hdr
, sizeof(struct pcep_object_req_adap_cap
));
1405 obj
->switching_capability
= obj_buf
[0];
1406 obj
->encoding
= obj_buf
[1];
1408 return (struct pcep_object_header
*)obj
;
1411 struct pcep_object_header
*
1412 pcep_decode_obj_server_ind(struct pcep_object_header
*hdr
,
1413 const uint8_t *obj_buf
)
1415 struct pcep_object_server_indication
*obj
=
1416 (struct pcep_object_server_indication
*)common_object_create(
1417 hdr
, sizeof(struct pcep_object_server_indication
));
1419 obj
->switching_capability
= obj_buf
[0];
1420 obj
->encoding
= obj_buf
[1];
1422 return (struct pcep_object_header
*)obj
;
1425 struct pcep_object_header
*
1426 pcep_decode_obj_objective_function(struct pcep_object_header
*hdr
,
1427 const uint8_t *obj_buf
)
1429 struct pcep_object_objective_function
*obj
=
1430 (struct pcep_object_objective_function
*)common_object_create(
1431 hdr
, sizeof(struct pcep_object_objective_function
));
1433 uint16_t *uint16_ptr
= (uint16_t *)obj_buf
;
1434 obj
->of_code
= ntohs(*uint16_ptr
);
1436 return (struct pcep_object_header
*)obj
;
1439 void set_ro_subobj_fields(struct pcep_object_ro_subobj
*subobj
, bool flag_l
,
1440 uint8_t subobj_type
)
1442 subobj
->flag_subobj_loose_hop
= flag_l
;
1443 subobj
->ro_subobj_type
= subobj_type
;
1446 void decode_ipv6(const uint32_t *src
, struct in6_addr
*dst_ipv6
)
1448 memcpy(dst_ipv6
, src
, sizeof(struct in6_addr
));
1450 struct pcep_object_header
*pcep_decode_obj_ro(struct pcep_object_header
*hdr
,
1451 const uint8_t *obj_buf
)
1453 struct pcep_object_ro
*obj
=
1454 (struct pcep_object_ro
*)common_object_create(
1455 hdr
, sizeof(struct pcep_object_ro
));
1456 obj
->sub_objects
= dll_initialize();
1458 /* RO Subobject format
1461 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
1462 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
1463 * |L| Type | Length | (Subobject contents) |
1464 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------//----------------+
1467 uint16_t read_count
= 0;
1468 int num_sub_objects
= 1;
1469 uint32_t *uint32_ptr
;
1470 uint16_t obj_body_length
=
1471 hdr
->encoded_object_length
- OBJECT_HEADER_LENGTH
;
1473 while ((obj_body_length
- read_count
) > OBJECT_RO_SUBOBJ_HEADER_LENGTH
1474 && num_sub_objects
< MAX_ITERATIONS
) {
1476 /* Read the Sub-Object Header */
1477 bool flag_l
= (obj_buf
[read_count
] & 0x80);
1478 uint8_t subobj_type
= (obj_buf
[read_count
++] & 0x7f);
1479 uint8_t subobj_length
= obj_buf
[read_count
++];
1481 if (subobj_length
<= OBJECT_RO_SUBOBJ_HEADER_LENGTH
) {
1483 "%s: Invalid ro subobj type [%d] length [%d]",
1484 __func__
, subobj_type
, subobj_length
);
1485 pceplib_free(PCEPLIB_MESSAGES
, obj
);
1489 switch (subobj_type
) {
1490 case RO_SUBOBJ_TYPE_IPV4
: {
1491 struct pcep_ro_subobj_ipv4
*ipv4
= pceplib_malloc(
1493 sizeof(struct pcep_ro_subobj_ipv4
));
1494 ipv4
->ro_subobj
.flag_subobj_loose_hop
= flag_l
;
1495 ipv4
->ro_subobj
.ro_subobj_type
= subobj_type
;
1496 uint32_ptr
= (uint32_t *)(obj_buf
+ read_count
);
1497 ipv4
->ip_addr
.s_addr
= *uint32_ptr
;
1498 read_count
+= LENGTH_1WORD
;
1499 ipv4
->prefix_length
= obj_buf
[read_count
++];
1500 ipv4
->flag_local_protection
=
1501 (obj_buf
[read_count
++]
1502 & OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT
);
1504 dll_append(obj
->sub_objects
, ipv4
);
1507 case RO_SUBOBJ_TYPE_IPV6
: {
1508 struct pcep_ro_subobj_ipv6
*ipv6
= pceplib_malloc(
1510 sizeof(struct pcep_ro_subobj_ipv6
));
1511 ipv6
->ro_subobj
.flag_subobj_loose_hop
= flag_l
;
1512 ipv6
->ro_subobj
.ro_subobj_type
= subobj_type
;
1513 decode_ipv6((uint32_t *)obj_buf
, &ipv6
->ip_addr
);
1514 read_count
+= LENGTH_4WORDS
;
1515 ipv6
->prefix_length
= obj_buf
[read_count
++];
1516 ipv6
->flag_local_protection
=
1517 (obj_buf
[read_count
++]
1518 & OBJECT_SUBOBJ_IP_FLAG_LOCAL_PROT
);
1520 dll_append(obj
->sub_objects
, ipv6
);
1523 case RO_SUBOBJ_TYPE_LABEL
: {
1524 struct pcep_ro_subobj_32label
*label
= pceplib_malloc(
1526 sizeof(struct pcep_ro_subobj_32label
));
1527 label
->ro_subobj
.flag_subobj_loose_hop
= flag_l
;
1528 label
->ro_subobj
.ro_subobj_type
= subobj_type
;
1529 label
->flag_global_label
=
1530 (obj_buf
[read_count
++]
1531 & OBJECT_SUBOBJ_LABEL_FLAG_GLOGAL
);
1532 label
->class_type
= obj_buf
[read_count
++];
1533 label
->label
= ntohl(obj_buf
[read_count
]);
1534 read_count
+= LENGTH_1WORD
;
1536 dll_append(obj
->sub_objects
, label
);
1539 case RO_SUBOBJ_TYPE_UNNUM
: {
1540 struct pcep_ro_subobj_unnum
*unum
= pceplib_malloc(
1542 sizeof(struct pcep_ro_subobj_unnum
));
1543 unum
->ro_subobj
.flag_subobj_loose_hop
= flag_l
;
1544 unum
->ro_subobj
.ro_subobj_type
= subobj_type
;
1545 set_ro_subobj_fields(
1546 (struct pcep_object_ro_subobj
*)unum
, flag_l
,
1548 uint32_ptr
= (uint32_t *)(obj_buf
+ read_count
);
1549 unum
->interface_id
= ntohl(uint32_ptr
[0]);
1550 unum
->router_id
.s_addr
= uint32_ptr
[1];
1553 dll_append(obj
->sub_objects
, unum
);
1556 case RO_SUBOBJ_TYPE_ASN
: {
1557 struct pcep_ro_subobj_asn
*asn
= pceplib_malloc(
1559 sizeof(struct pcep_ro_subobj_asn
));
1560 asn
->ro_subobj
.flag_subobj_loose_hop
= flag_l
;
1561 asn
->ro_subobj
.ro_subobj_type
= subobj_type
;
1562 uint16_t *uint16_ptr
=
1563 (uint16_t *)(obj_buf
+ read_count
);
1564 asn
->asn
= ntohs(*uint16_ptr
);
1567 dll_append(obj
->sub_objects
, asn
);
1570 case RO_SUBOBJ_TYPE_SR
: {
1571 /* SR-ERO subobject format
1574 * 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1575 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1576 * |L| Type=36 | Length | NT | Flags
1578 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1579 * | SID (optional) |
1580 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1581 * // NAI (variable, optional) //
1582 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1585 struct pcep_ro_subobj_sr
*sr_subobj
= pceplib_malloc(
1587 sizeof(struct pcep_ro_subobj_sr
));
1588 sr_subobj
->ro_subobj
.flag_subobj_loose_hop
= flag_l
;
1589 sr_subobj
->ro_subobj
.ro_subobj_type
= subobj_type
;
1590 dll_append(obj
->sub_objects
, sr_subobj
);
1592 sr_subobj
->nai_list
= dll_initialize();
1593 sr_subobj
->nai_type
=
1594 ((obj_buf
[read_count
++] >> 4) & 0x0f);
1596 (obj_buf
[read_count
] & OBJECT_SUBOBJ_SR_FLAG_F
);
1598 (obj_buf
[read_count
] & OBJECT_SUBOBJ_SR_FLAG_S
);
1600 (obj_buf
[read_count
] & OBJECT_SUBOBJ_SR_FLAG_C
);
1602 (obj_buf
[read_count
] & OBJECT_SUBOBJ_SR_FLAG_M
);
1605 /* If the sid_absent flag is true, then dont decode the
1607 uint32_ptr
= (uint32_t *)(obj_buf
+ read_count
);
1608 if (sr_subobj
->flag_s
== false) {
1609 sr_subobj
->sid
= ntohl(*uint32_ptr
);
1610 read_count
+= LENGTH_1WORD
;
1614 switch (sr_subobj
->nai_type
) {
1615 case PCEP_SR_SUBOBJ_NAI_IPV4_NODE
: {
1616 struct in_addr
*ipv4
=
1617 pceplib_malloc(PCEPLIB_MESSAGES
,
1618 sizeof(struct in_addr
));
1619 ipv4
->s_addr
= *uint32_ptr
;
1620 dll_append(sr_subobj
->nai_list
, ipv4
);
1621 read_count
+= LENGTH_1WORD
;
1624 case PCEP_SR_SUBOBJ_NAI_IPV6_NODE
: {
1625 struct in6_addr
*ipv6
=
1626 pceplib_malloc(PCEPLIB_MESSAGES
,
1627 sizeof(struct in6_addr
));
1628 decode_ipv6(uint32_ptr
, ipv6
);
1629 dll_append(sr_subobj
->nai_list
, ipv6
);
1630 read_count
+= LENGTH_4WORDS
;
1633 case PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY
: {
1634 struct in_addr
*ipv4
=
1635 pceplib_malloc(PCEPLIB_MESSAGES
,
1636 sizeof(struct in_addr
));
1637 ipv4
->s_addr
= uint32_ptr
[0];
1638 dll_append(sr_subobj
->nai_list
, ipv4
);
1640 ipv4
= pceplib_malloc(PCEPLIB_MESSAGES
,
1641 sizeof(struct in_addr
));
1642 ipv4
->s_addr
= uint32_ptr
[1];
1643 dll_append(sr_subobj
->nai_list
, ipv4
);
1645 ipv4
= pceplib_malloc(PCEPLIB_MESSAGES
,
1646 sizeof(struct in_addr
));
1647 ipv4
->s_addr
= uint32_ptr
[2];
1648 dll_append(sr_subobj
->nai_list
, ipv4
);
1650 ipv4
= pceplib_malloc(PCEPLIB_MESSAGES
,
1651 sizeof(struct in_addr
));
1652 ipv4
->s_addr
= uint32_ptr
[3];
1653 dll_append(sr_subobj
->nai_list
, ipv4
);
1655 read_count
+= LENGTH_4WORDS
;
1658 case PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY
: {
1659 struct in_addr
*ipv4
=
1660 pceplib_malloc(PCEPLIB_MESSAGES
,
1661 sizeof(struct in_addr
));
1662 ipv4
->s_addr
= uint32_ptr
[0];
1663 dll_append(sr_subobj
->nai_list
, ipv4
);
1665 ipv4
= pceplib_malloc(PCEPLIB_MESSAGES
,
1666 sizeof(struct in_addr
));
1667 ipv4
->s_addr
= uint32_ptr
[1];
1668 dll_append(sr_subobj
->nai_list
, ipv4
);
1670 read_count
+= LENGTH_2WORDS
;
1673 case PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY
: {
1674 struct in6_addr
*ipv6
=
1675 pceplib_malloc(PCEPLIB_MESSAGES
,
1676 sizeof(struct in6_addr
));
1677 decode_ipv6(uint32_ptr
, ipv6
);
1678 dll_append(sr_subobj
->nai_list
, ipv6
);
1680 ipv6
= pceplib_malloc(PCEPLIB_MESSAGES
,
1681 sizeof(struct in6_addr
));
1682 decode_ipv6(uint32_ptr
+ 4, ipv6
);
1683 dll_append(sr_subobj
->nai_list
, ipv6
);
1685 read_count
+= LENGTH_8WORDS
;
1688 case PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY
: {
1689 struct in6_addr
*ipv6
=
1690 pceplib_malloc(PCEPLIB_MESSAGES
,
1691 sizeof(struct in6_addr
));
1692 decode_ipv6(uint32_ptr
, ipv6
);
1693 dll_append(sr_subobj
->nai_list
, ipv6
);
1695 struct in_addr
*ipv4
=
1696 pceplib_malloc(PCEPLIB_MESSAGES
,
1697 sizeof(struct in_addr
));
1698 ipv4
->s_addr
= uint32_ptr
[4];
1699 dll_append(sr_subobj
->nai_list
, ipv4
);
1701 ipv6
= pceplib_malloc(PCEPLIB_MESSAGES
,
1702 sizeof(struct in6_addr
));
1703 decode_ipv6(uint32_ptr
+ 5, ipv6
);
1704 dll_append(sr_subobj
->nai_list
, ipv6
);
1706 ipv4
= pceplib_malloc(PCEPLIB_MESSAGES
,
1707 sizeof(struct in_addr
));
1708 ipv4
->s_addr
= uint32_ptr
[9];
1709 dll_append(sr_subobj
->nai_list
, ipv4
);
1711 read_count
+= LENGTH_10WORDS
;
1714 case PCEP_SR_SUBOBJ_NAI_ABSENT
:
1723 "%s: pcep_decode_obj_ro skipping unrecognized sub-object type [%d]",
1724 __func__
, subobj_type
);
1725 read_count
+= subobj_length
;
1730 return (struct pcep_object_header
*)obj
;