]> git.proxmox.com Git - mirror_frr.git/blame - pceplib/pcep_msg_messages.c
Merge pull request #8248 from volta-networks/fix_ospf6_chunk_msgs
[mirror_frr.git] / pceplib / pcep_msg_messages.c
CommitLineData
74971473
JG
1/*
2 * This file is part of the PCEPlib, a PCEP protocol library.
3 *
4 * Copyright (C) 2020 Volta Networks https://voltanet.io/
5 *
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.
10 *
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.
15 *
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/>.
18 *
19 * Author : Brady Johnson <brady@voltanet.io>
20 *
21 */
22
23
24/*
25 * This is the implementation of a High Level PCEP message API.
26 */
27
28#include <string.h>
29#include <arpa/inet.h>
30#include <stdarg.h>
31#include <unistd.h>
32
33#include "pcep_msg_encoding.h"
34#include "pcep_msg_messages.h"
35#include "pcep_msg_objects.h"
36#include "pcep_utils_double_linked_list.h"
37#include "pcep_utils_logging.h"
38#include "pcep_utils_memory.h"
39
40static struct pcep_message *
41pcep_msg_create_common_with_obj_list(enum pcep_message_types msg_type,
42 double_linked_list *obj_list)
43{
44 struct pcep_message *message =
45 pceplib_malloc(PCEPLIB_MESSAGES, sizeof(struct pcep_message));
46 memset(message, 0, sizeof(struct pcep_message));
47 message->msg_header = pceplib_malloc(
48 PCEPLIB_MESSAGES, sizeof(struct pcep_message_header));
49 memset(message->msg_header, 0, sizeof(struct pcep_message_header));
50 message->msg_header->type = msg_type;
51 message->msg_header->pcep_version = PCEP_MESSAGE_HEADER_VERSION;
52 message->obj_list = ((obj_list == NULL) ? dll_initialize() : obj_list);
53
54 return message;
55}
56
57static struct pcep_message *
58pcep_msg_create_common(enum pcep_message_types msg_type)
59{
60 return pcep_msg_create_common_with_obj_list(msg_type, NULL);
61}
62
63struct pcep_message *pcep_msg_create_open(uint8_t keepalive, uint8_t deadtimer,
64 uint8_t sid)
65{
66 struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_OPEN);
67 dll_append(message->obj_list,
68 pcep_obj_create_open(keepalive, deadtimer, sid, NULL));
69
70 return message;
71}
72
73struct pcep_message *
74pcep_msg_create_open_with_tlvs(uint8_t keepalive, uint8_t deadtimer,
75 uint8_t sid, double_linked_list *tlv_list)
76{
77 struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_OPEN);
78 dll_append(message->obj_list,
79 pcep_obj_create_open(keepalive, deadtimer, sid, tlv_list));
80
81 return message;
82}
83
84
85struct pcep_message *
86pcep_msg_create_request(struct pcep_object_rp *rp,
87 struct pcep_object_endpoints_ipv4 *endpoints,
88 double_linked_list *object_list)
89{
90 if ((rp == NULL) || (endpoints == NULL)) {
91 return NULL;
92 }
93
94 struct pcep_message *message = pcep_msg_create_common_with_obj_list(
95 PCEP_TYPE_PCREQ, object_list);
96 dll_prepend(message->obj_list, endpoints);
97 dll_prepend(message->obj_list, rp);
98
99 return message;
100}
101
102struct pcep_message *
103pcep_msg_create_request_ipv6(struct pcep_object_rp *rp,
104 struct pcep_object_endpoints_ipv6 *endpoints,
105 double_linked_list *object_list)
106{
107 if ((rp == NULL) || (endpoints == NULL)) {
108 return NULL;
109 }
110
111 struct pcep_message *message = pcep_msg_create_common_with_obj_list(
112 PCEP_TYPE_PCREQ, object_list);
113 dll_prepend(message->obj_list, endpoints);
114 dll_prepend(message->obj_list, rp);
115
116 return message;
117}
118
119struct pcep_message *pcep_msg_create_reply(struct pcep_object_rp *rp,
120 double_linked_list *object_list)
121{
122 struct pcep_message *message = pcep_msg_create_common_with_obj_list(
123 PCEP_TYPE_PCREP, object_list);
124
125 if (rp != NULL) {
126 dll_prepend(message->obj_list, rp);
127 }
128
129 return message;
130}
131
132struct pcep_message *pcep_msg_create_close(uint8_t reason)
133{
134 struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_CLOSE);
135 dll_append(message->obj_list, pcep_obj_create_close(reason));
136
137 return message;
138}
139
140struct pcep_message *pcep_msg_create_error(uint8_t error_type,
141 uint8_t error_value)
142{
143 struct pcep_message *message = pcep_msg_create_common(PCEP_TYPE_ERROR);
144 dll_append(message->obj_list,
145 pcep_obj_create_error(error_type, error_value));
146
147 return message;
148}
149
150struct pcep_message *
151pcep_msg_create_error_with_objects(uint8_t error_type, uint8_t error_value,
152 double_linked_list *object_list)
153{
154 struct pcep_message *message = pcep_msg_create_common_with_obj_list(
155 PCEP_TYPE_ERROR, object_list);
156 dll_prepend(message->obj_list,
157 pcep_obj_create_error(error_type, error_value));
158
159 return message;
160}
161
162struct pcep_message *pcep_msg_create_keepalive()
163{
164 return (pcep_msg_create_common(PCEP_TYPE_KEEPALIVE));
165}
166
167struct pcep_message *
168pcep_msg_create_report(double_linked_list *state_report_object_list)
169{
170 return (state_report_object_list == NULL
171 ? NULL
172 : pcep_msg_create_common_with_obj_list(
173 PCEP_TYPE_REPORT, state_report_object_list));
174}
175
176struct pcep_message *
177pcep_msg_create_update(double_linked_list *update_request_object_list)
178{
179 if (update_request_object_list == NULL) {
180 pcep_log(
181 LOG_INFO,
182 "%s: pcep_msg_create_update NULL update_request_object_list",
183 __func__);
184 return NULL;
185 }
186
187 /* There must be at least 3 objects:
188 * These 3 are mandatory: SRP, LSP, and ERO. The ERO may be empty */
189 if (update_request_object_list->num_entries < 3) {
190 pcep_log(
191 LOG_INFO,
192 "%s: pcep_msg_create_update there must be at least 3 update objects",
193 __func__);
194 return NULL;
195 }
196
197 double_linked_list_node *node = update_request_object_list->head;
198 struct pcep_object_header *obj_hdr =
199 (struct pcep_object_header *)node->data;
200
201 /* Check for the mandatory first SRP object */
202 if (obj_hdr->object_class != PCEP_OBJ_CLASS_SRP) {
203 /* If the SRP object is missing, the receiving PCC MUST send a
204 * PCErr message with Error-type=6 (Mandatory Object missing)
205 * and Error-value=10 (SRP object missing). */
206 pcep_log(
207 LOG_INFO,
208 "%s: pcep_msg_create_update missing mandatory first SRP object",
209 __func__);
210 return NULL;
211 }
212
213 /* Check for the mandatory 2nd LSP object */
214 node = node->next_node;
215 obj_hdr = (struct pcep_object_header *)node->data;
216 if (obj_hdr->object_class != PCEP_OBJ_CLASS_LSP) {
217 /* If the LSP object is missing, the receiving PCC MUST send a
218 * PCErr message with Error-type=6 (Mandatory Object missing)
219 * and Error-value=8 (LSP object missing). */
220 pcep_log(
221 LOG_INFO,
222 "%s: pcep_msg_create_update missing mandatory second LSP object",
223 __func__);
224 return NULL;
225 }
226
227 /* Check for the mandatory 3rd ERO object */
228 node = node->next_node;
229 obj_hdr = (struct pcep_object_header *)node->data;
230 if (obj_hdr->object_class != PCEP_OBJ_CLASS_ERO) {
231 /* If the ERO object is missing, the receiving PCC MUST send a
232 * PCErr message with Error-type=6 (Mandatory Object missing)
233 * and Error-value=9 (ERO object missing). */
234 pcep_log(
235 LOG_INFO,
236 "%s: pcep_msg_create_update missing mandatory third ERO object",
237 __func__);
238 return NULL;
239 }
240
241 return (pcep_msg_create_common_with_obj_list(
242 PCEP_TYPE_UPDATE, update_request_object_list));
243}
244
245struct pcep_message *
246pcep_msg_create_initiate(double_linked_list *lsp_object_list)
247{
248 if (lsp_object_list == NULL) {
249 pcep_log(
250 LOG_INFO,
251 "%s: pcep_msg_create_initiate NULL update_request_object_list",
252 __func__);
253 return NULL;
254 }
255
256 /* There must be at least 2 objects: SRP and LSP. */
257 if (lsp_object_list->num_entries < 2) {
258 pcep_log(
259 LOG_INFO,
260 "%s: pcep_msg_create_initiate there must be at least 2 objects",
261 __func__);
262 return NULL;
263 }
264
265 double_linked_list_node *node = lsp_object_list->head;
266 struct pcep_object_header *obj_hdr =
267 (struct pcep_object_header *)node->data;
268
269 /* Check for the mandatory first SRP object */
270 if (obj_hdr->object_class != PCEP_OBJ_CLASS_SRP) {
271 pcep_log(
272 LOG_INFO,
273 "%s: pcep_msg_create_initiate missing mandatory first SRP object",
274 __func__);
275 return NULL;
276 }
277
278 /* Check for the mandatory 2nd LSP object */
279 node = node->next_node;
280 obj_hdr = (struct pcep_object_header *)node->data;
281 if (obj_hdr->object_class != PCEP_OBJ_CLASS_LSP) {
282 pcep_log(
283 LOG_INFO,
284 "%s: pcep_msg_create_initiate missing mandatory second LSP object",
285 __func__);
286 return NULL;
287 }
288
289 return (pcep_msg_create_common_with_obj_list(PCEP_TYPE_INITIATE,
290 lsp_object_list));
291}
292
293struct pcep_message *pcep_msg_create_notify(struct pcep_object_notify *notify,
294 double_linked_list *object_list)
295{
296 if (notify == NULL) {
297 pcep_log(LOG_INFO,
298 "%s: pcep_msg_create_notify NULL notify object",
299 __func__);
300 return NULL;
301 }
302
303 struct pcep_message *message = pcep_msg_create_common_with_obj_list(
304 PCEP_TYPE_PCNOTF, object_list);
305 dll_prepend(message->obj_list, notify);
306
307 return message;
308}