1 // SPDX-License-Identifier: LGPL-2.1-or-later
3 * This file is part of the PCEPlib, a PCEP protocol library.
5 * Copyright (C) 2020 Volta Networks https://voltanet.io/
7 * Author : Brady Johnson <brady@voltanet.io>
13 * This is the implementation of a High Level PCEP message API.
21 #include <arpa/inet.h>
25 #include "pcep_msg_encoding.h"
26 #include "pcep_msg_messages.h"
27 #include "pcep_msg_objects.h"
28 #include "pcep_utils_double_linked_list.h"
29 #include "pcep_utils_logging.h"
30 #include "pcep_utils_memory.h"
32 static struct pcep_message
*
33 pcep_msg_create_common_with_obj_list(enum pcep_message_types msg_type
,
34 double_linked_list
*obj_list
)
36 struct pcep_message
*message
=
37 pceplib_malloc(PCEPLIB_MESSAGES
, sizeof(struct pcep_message
));
38 memset(message
, 0, sizeof(struct pcep_message
));
39 message
->msg_header
= pceplib_malloc(
40 PCEPLIB_MESSAGES
, sizeof(struct pcep_message_header
));
41 memset(message
->msg_header
, 0, sizeof(struct pcep_message_header
));
42 message
->msg_header
->type
= msg_type
;
43 message
->msg_header
->pcep_version
= PCEP_MESSAGE_HEADER_VERSION
;
44 message
->obj_list
= ((obj_list
== NULL
) ? dll_initialize() : obj_list
);
49 static struct pcep_message
*
50 pcep_msg_create_common(enum pcep_message_types msg_type
)
52 return pcep_msg_create_common_with_obj_list(msg_type
, NULL
);
55 struct pcep_message
*pcep_msg_create_open(uint8_t keepalive
, uint8_t deadtimer
,
58 struct pcep_message
*message
= pcep_msg_create_common(PCEP_TYPE_OPEN
);
59 dll_append(message
->obj_list
,
60 pcep_obj_create_open(keepalive
, deadtimer
, sid
, NULL
));
66 pcep_msg_create_open_with_tlvs(uint8_t keepalive
, uint8_t deadtimer
,
67 uint8_t sid
, double_linked_list
*tlv_list
)
69 struct pcep_message
*message
= pcep_msg_create_common(PCEP_TYPE_OPEN
);
70 dll_append(message
->obj_list
,
71 pcep_obj_create_open(keepalive
, deadtimer
, sid
, tlv_list
));
78 pcep_msg_create_request(struct pcep_object_rp
*rp
,
79 struct pcep_object_endpoints_ipv4
*endpoints
,
80 double_linked_list
*object_list
)
82 if ((rp
== NULL
) || (endpoints
== NULL
)) {
86 struct pcep_message
*message
= pcep_msg_create_common_with_obj_list(
87 PCEP_TYPE_PCREQ
, object_list
);
88 dll_prepend(message
->obj_list
, endpoints
);
89 dll_prepend(message
->obj_list
, rp
);
95 pcep_msg_create_request_ipv6(struct pcep_object_rp
*rp
,
96 struct pcep_object_endpoints_ipv6
*endpoints
,
97 double_linked_list
*object_list
)
99 if ((rp
== NULL
) || (endpoints
== NULL
)) {
103 struct pcep_message
*message
= pcep_msg_create_common_with_obj_list(
104 PCEP_TYPE_PCREQ
, object_list
);
105 dll_prepend(message
->obj_list
, endpoints
);
106 dll_prepend(message
->obj_list
, rp
);
111 struct pcep_message
*pcep_msg_create_reply(struct pcep_object_rp
*rp
,
112 double_linked_list
*object_list
)
114 struct pcep_message
*message
= pcep_msg_create_common_with_obj_list(
115 PCEP_TYPE_PCREP
, object_list
);
118 dll_prepend(message
->obj_list
, rp
);
124 struct pcep_message
*pcep_msg_create_close(uint8_t reason
)
126 struct pcep_message
*message
= pcep_msg_create_common(PCEP_TYPE_CLOSE
);
127 dll_append(message
->obj_list
, pcep_obj_create_close(reason
));
132 struct pcep_message
*pcep_msg_create_error(uint8_t error_type
,
135 struct pcep_message
*message
= pcep_msg_create_common(PCEP_TYPE_ERROR
);
136 dll_append(message
->obj_list
,
137 pcep_obj_create_error(error_type
, error_value
));
142 struct pcep_message
*
143 pcep_msg_create_error_with_objects(uint8_t error_type
, uint8_t error_value
,
144 double_linked_list
*object_list
)
146 struct pcep_message
*message
= pcep_msg_create_common_with_obj_list(
147 PCEP_TYPE_ERROR
, object_list
);
148 dll_prepend(message
->obj_list
,
149 pcep_obj_create_error(error_type
, error_value
));
154 struct pcep_message
*pcep_msg_create_keepalive(void)
156 return (pcep_msg_create_common(PCEP_TYPE_KEEPALIVE
));
159 struct pcep_message
*
160 pcep_msg_create_report(double_linked_list
*state_report_object_list
)
162 return (state_report_object_list
== NULL
164 : pcep_msg_create_common_with_obj_list(
165 PCEP_TYPE_REPORT
, state_report_object_list
));
168 struct pcep_message
*
169 pcep_msg_create_update(double_linked_list
*update_request_object_list
)
171 if (update_request_object_list
== NULL
) {
174 "%s: pcep_msg_create_update NULL update_request_object_list",
179 /* There must be at least 3 objects:
180 * These 3 are mandatory: SRP, LSP, and ERO. The ERO may be empty */
181 if (update_request_object_list
->num_entries
< 3) {
184 "%s: pcep_msg_create_update there must be at least 3 update objects",
189 double_linked_list_node
*node
= update_request_object_list
->head
;
190 struct pcep_object_header
*obj_hdr
=
191 (struct pcep_object_header
*)node
->data
;
193 /* Check for the mandatory first SRP object */
194 if (obj_hdr
->object_class
!= PCEP_OBJ_CLASS_SRP
) {
195 /* If the SRP object is missing, the receiving PCC MUST send a
196 * PCErr message with Error-type=6 (Mandatory Object missing)
197 * and Error-value=10 (SRP object missing). */
200 "%s: pcep_msg_create_update missing mandatory first SRP object",
205 /* Check for the mandatory 2nd LSP object */
206 node
= node
->next_node
;
207 obj_hdr
= (struct pcep_object_header
*)node
->data
;
208 if (obj_hdr
->object_class
!= PCEP_OBJ_CLASS_LSP
) {
209 /* If the LSP object is missing, the receiving PCC MUST send a
210 * PCErr message with Error-type=6 (Mandatory Object missing)
211 * and Error-value=8 (LSP object missing). */
214 "%s: pcep_msg_create_update missing mandatory second LSP object",
219 /* Check for the mandatory 3rd ERO object */
220 node
= node
->next_node
;
221 obj_hdr
= (struct pcep_object_header
*)node
->data
;
222 if (obj_hdr
->object_class
!= PCEP_OBJ_CLASS_ERO
) {
223 /* If the ERO object is missing, the receiving PCC MUST send a
224 * PCErr message with Error-type=6 (Mandatory Object missing)
225 * and Error-value=9 (ERO object missing). */
228 "%s: pcep_msg_create_update missing mandatory third ERO object",
233 return (pcep_msg_create_common_with_obj_list(
234 PCEP_TYPE_UPDATE
, update_request_object_list
));
237 struct pcep_message
*
238 pcep_msg_create_initiate(double_linked_list
*lsp_object_list
)
240 if (lsp_object_list
== NULL
) {
243 "%s: pcep_msg_create_initiate NULL update_request_object_list",
248 /* There must be at least 2 objects: SRP and LSP. */
249 if (lsp_object_list
->num_entries
< 2) {
252 "%s: pcep_msg_create_initiate there must be at least 2 objects",
257 double_linked_list_node
*node
= lsp_object_list
->head
;
258 struct pcep_object_header
*obj_hdr
=
259 (struct pcep_object_header
*)node
->data
;
261 /* Check for the mandatory first SRP object */
262 if (obj_hdr
->object_class
!= PCEP_OBJ_CLASS_SRP
) {
265 "%s: pcep_msg_create_initiate missing mandatory first SRP object",
270 /* Check for the mandatory 2nd LSP object */
271 node
= node
->next_node
;
272 obj_hdr
= (struct pcep_object_header
*)node
->data
;
273 if (obj_hdr
->object_class
!= PCEP_OBJ_CLASS_LSP
) {
276 "%s: pcep_msg_create_initiate missing mandatory second LSP object",
281 return (pcep_msg_create_common_with_obj_list(PCEP_TYPE_INITIATE
,
285 struct pcep_message
*pcep_msg_create_notify(struct pcep_object_notify
*notify
,
286 double_linked_list
*object_list
)
288 if (notify
== NULL
) {
290 "%s: pcep_msg_create_notify NULL notify object",
295 struct pcep_message
*message
= pcep_msg_create_common_with_obj_list(
296 PCEP_TYPE_PCNOTF
, object_list
);
297 dll_prepend(message
->obj_list
, notify
);