]> git.proxmox.com Git - mirror_frr.git/blame - pceplib/pcep_msg_messages.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / pceplib / pcep_msg_messages.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: LGPL-2.1-or-later
74971473
JG
2/*
3 * This file is part of the PCEPlib, a PCEP protocol library.
4 *
5 * Copyright (C) 2020 Volta Networks https://voltanet.io/
6 *
74971473
JG
7 * Author : Brady Johnson <brady@voltanet.io>
8 *
9 */
10
11
12/*
13 * This is the implementation of a High Level PCEP message API.
14 */
15
1f8031f7
DL
16#ifdef HAVE_CONFIG_H
17#include "config.h"
18#endif
19
74971473
JG
20#include <string.h>
21#include <arpa/inet.h>
22#include <stdarg.h>
23#include <unistd.h>
24
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"
31
32static struct pcep_message *
33pcep_msg_create_common_with_obj_list(enum pcep_message_types msg_type,
34 double_linked_list *obj_list)
35{
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);
45
46 return message;
47}
48
49static struct pcep_message *
50pcep_msg_create_common(enum pcep_message_types msg_type)
51{
52 return pcep_msg_create_common_with_obj_list(msg_type, NULL);
53}
54
55struct pcep_message *pcep_msg_create_open(uint8_t keepalive, uint8_t deadtimer,
56 uint8_t sid)
57{
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));
61
62 return message;
63}
64
65struct pcep_message *
66pcep_msg_create_open_with_tlvs(uint8_t keepalive, uint8_t deadtimer,
67 uint8_t sid, double_linked_list *tlv_list)
68{
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));
72
73 return message;
74}
75
76
77struct pcep_message *
78pcep_msg_create_request(struct pcep_object_rp *rp,
79 struct pcep_object_endpoints_ipv4 *endpoints,
80 double_linked_list *object_list)
81{
82 if ((rp == NULL) || (endpoints == NULL)) {
83 return NULL;
84 }
85
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);
90
91 return message;
92}
93
94struct pcep_message *
95pcep_msg_create_request_ipv6(struct pcep_object_rp *rp,
96 struct pcep_object_endpoints_ipv6 *endpoints,
97 double_linked_list *object_list)
98{
99 if ((rp == NULL) || (endpoints == NULL)) {
100 return NULL;
101 }
102
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);
107
108 return message;
109}
110
111struct pcep_message *pcep_msg_create_reply(struct pcep_object_rp *rp,
112 double_linked_list *object_list)
113{
114 struct pcep_message *message = pcep_msg_create_common_with_obj_list(
115 PCEP_TYPE_PCREP, object_list);
116
117 if (rp != NULL) {
118 dll_prepend(message->obj_list, rp);
119 }
120
121 return message;
122}
123
124struct pcep_message *pcep_msg_create_close(uint8_t reason)
125{
126 struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_CLOSE);
127 dll_append(message->obj_list, pcep_obj_create_close(reason));
128
129 return message;
130}
131
132struct pcep_message *pcep_msg_create_error(uint8_t error_type,
133 uint8_t error_value)
134{
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));
138
139 return message;
140}
141
142struct pcep_message *
143pcep_msg_create_error_with_objects(uint8_t error_type, uint8_t error_value,
144 double_linked_list *object_list)
145{
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));
150
151 return message;
152}
153
2816045a 154struct pcep_message *pcep_msg_create_keepalive(void)
74971473
JG
155{
156 return (pcep_msg_create_common(PCEP_TYPE_KEEPALIVE));
157}
158
159struct pcep_message *
160pcep_msg_create_report(double_linked_list *state_report_object_list)
161{
162 return (state_report_object_list == NULL
163 ? NULL
164 : pcep_msg_create_common_with_obj_list(
165 PCEP_TYPE_REPORT, state_report_object_list));
166}
167
168struct pcep_message *
169pcep_msg_create_update(double_linked_list *update_request_object_list)
170{
171 if (update_request_object_list == NULL) {
172 pcep_log(
173 LOG_INFO,
174 "%s: pcep_msg_create_update NULL update_request_object_list",
175 __func__);
176 return NULL;
177 }
178
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) {
182 pcep_log(
183 LOG_INFO,
184 "%s: pcep_msg_create_update there must be at least 3 update objects",
185 __func__);
186 return NULL;
187 }
188
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;
192
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). */
198 pcep_log(
199 LOG_INFO,
200 "%s: pcep_msg_create_update missing mandatory first SRP object",
201 __func__);
202 return NULL;
203 }
204
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). */
212 pcep_log(
213 LOG_INFO,
214 "%s: pcep_msg_create_update missing mandatory second LSP object",
215 __func__);
216 return NULL;
217 }
218
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). */
226 pcep_log(
227 LOG_INFO,
228 "%s: pcep_msg_create_update missing mandatory third ERO object",
229 __func__);
230 return NULL;
231 }
232
233 return (pcep_msg_create_common_with_obj_list(
234 PCEP_TYPE_UPDATE, update_request_object_list));
235}
236
237struct pcep_message *
238pcep_msg_create_initiate(double_linked_list *lsp_object_list)
239{
240 if (lsp_object_list == NULL) {
241 pcep_log(
242 LOG_INFO,
243 "%s: pcep_msg_create_initiate NULL update_request_object_list",
244 __func__);
245 return NULL;
246 }
247
248 /* There must be at least 2 objects: SRP and LSP. */
249 if (lsp_object_list->num_entries < 2) {
250 pcep_log(
251 LOG_INFO,
252 "%s: pcep_msg_create_initiate there must be at least 2 objects",
253 __func__);
254 return NULL;
255 }
256
257 double_linked_list_node *node = lsp_object_list->head;
258 struct pcep_object_header *obj_hdr =
259 (struct pcep_object_header *)node->data;
260
261 /* Check for the mandatory first SRP object */
262 if (obj_hdr->object_class != PCEP_OBJ_CLASS_SRP) {
263 pcep_log(
264 LOG_INFO,
265 "%s: pcep_msg_create_initiate missing mandatory first SRP object",
266 __func__);
267 return NULL;
268 }
269
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) {
274 pcep_log(
275 LOG_INFO,
276 "%s: pcep_msg_create_initiate missing mandatory second LSP object",
277 __func__);
278 return NULL;
279 }
280
281 return (pcep_msg_create_common_with_obj_list(PCEP_TYPE_INITIATE,
282 lsp_object_list));
283}
284
285struct pcep_message *pcep_msg_create_notify(struct pcep_object_notify *notify,
286 double_linked_list *object_list)
287{
288 if (notify == NULL) {
289 pcep_log(LOG_INFO,
290 "%s: pcep_msg_create_notify NULL notify object",
291 __func__);
292 return NULL;
293 }
294
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);
298
299 return message;
300}