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