]> git.proxmox.com Git - mirror_frr.git/blame - pathd/path_pcep_lib.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / pathd / path_pcep_lib.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
efba0985
SM
2/*
3 * Copyright (C) 2020 NetDEF, Inc.
efba0985
SM
4 */
5
74971473
JG
6#include <zebra.h>
7
c7479286
DL
8#include "memory.h"
9
efba0985 10#include <debug.h>
74971473
JG
11#include "pceplib/pcep_utils_counters.h"
12#include "pceplib/pcep_timers.h"
efba0985 13#include "pathd/path_errors.h"
efba0985
SM
14#include "pathd/path_pcep.h"
15#include "pathd/path_pcep_lib.h"
16#include "pathd/path_pcep_debug.h"
c7479286
DL
17
18DEFINE_MTYPE_STATIC(PATHD, PCEPLIB_INFRA, "PCEPlib Infrastructure");
19DEFINE_MTYPE_STATIC(PATHD, PCEPLIB_MESSAGES, "PCEPlib PCEP Messages");
efba0985
SM
20
21#define CLASS_TYPE(CLASS, TYPE) (((CLASS) << 16) | (TYPE))
22#define DEFAULT_LSAP_SETUP_PRIO 4
23#define DEFAULT_LSAP_HOLDING_PRIO 4
24#define DEFAULT_LSAP_LOCAL_PRETECTION false
56634922 25#define MAX_PATH_NAME_SIZE 255
efba0985
SM
26
27/* pceplib logging callback */
0f9de11a
DL
28static int pceplib_logging_cb(int level, const char *fmt, va_list args)
29 PRINTFRR(2, 0);
efba0985
SM
30
31/* Socket callbacks */
32static int pcep_lib_pceplib_socket_read_cb(void *fpt, void **thread, int fd,
33 void *payload);
34static int pcep_lib_pceplib_socket_write_cb(void *fpt, void **thread, int fd,
35 void *payload);
cc9f21da
DS
36static void pcep_lib_socket_read_ready(struct thread *thread);
37static void pcep_lib_socket_write_ready(struct thread *thread);
efba0985
SM
38
39/* pceplib pcep_event callbacks */
40static void pcep_lib_pceplib_event_cb(void *fpt, pcep_event *event);
41
42/* pceplib pthread creation callback */
43static int pcep_lib_pthread_create_cb(pthread_t *pthread_id,
44 const pthread_attr_t *attr,
45 void *(*start_routine)(void *),
46 void *data, const char *thread_name);
47void *pcep_lib_pthread_start_passthrough(void *data);
48int pcep_lib_pthread_stop_cb(struct frr_pthread *, void **);
49
50/* Internal functions */
51static double_linked_list *pcep_lib_format_path(struct pcep_caps *caps,
52 struct path *path);
53static void pcep_lib_format_constraints(struct path *path,
54 double_linked_list *objs);
55static void pcep_lib_parse_open(struct pcep_caps *caps,
56 struct pcep_object_open *open);
57static void
58pcep_lib_parse_open_pce_capability(struct pcep_caps *caps,
59 struct pcep_object_tlv_header *tlv_header);
60static void
61pcep_lib_parse_open_objfun_list(struct pcep_caps *caps,
62 struct pcep_object_tlv_header *tlv_header);
63static void pcep_lib_parse_rp(struct path *path, struct pcep_object_rp *rp);
64static void pcep_lib_parse_srp(struct path *path, struct pcep_object_srp *srp);
65static void pcep_lib_parse_lsp(struct path *path, struct pcep_object_lsp *lsp);
66static void pcep_lib_parse_lspa(struct path *path,
67 struct pcep_object_lspa *lspa);
56634922
JG
68static void pcep_lib_parse_lsp_symbolic_name(
69 struct path *path, struct pcep_object_tlv_symbolic_path_name *tlv);
efba0985
SM
70static void pcep_lib_parse_metric(struct path *path,
71 struct pcep_object_metric *obj);
56634922
JG
72static void
73pcep_lib_parse_endpoints_ipv4(struct path *path,
74 struct pcep_object_endpoints_ipv4 *obj);
75static void
76pcep_lib_parse_endpoints_ipv6(struct path *path,
77 struct pcep_object_endpoints_ipv6 *obj);
78static void pcep_lib_parse_vendor_info(struct path *path,
79 struct pcep_object_vendor_info *obj);
efba0985
SM
80static void pcep_lib_parse_ero(struct path *path, struct pcep_object_ro *ero);
81static struct path_hop *pcep_lib_parse_ero_sr(struct path_hop *next,
82 struct pcep_ro_subobj_sr *sr);
83static struct counters_group *copy_counter_group(struct counters_group *from);
84static struct counters_subgroup *
85copy_counter_subgroup(struct counters_subgroup *from);
86static struct counter *copy_counter(struct counter *from);
87static void free_counter_group(struct counters_group *group);
88static void free_counter_subgroup(struct counters_subgroup *subgroup);
89static void free_counter(struct counter *counter);
90
91struct pcep_lib_pthread_passthrough_data {
92 void *(*start_routine)(void *data);
93 void *data;
94};
95
96/* ------------ API Functions ------------ */
97
98int pcep_lib_initialize(struct frr_pthread *fpt)
99{
100 PCEP_DEBUG("Initializing pceplib");
101
102 /* Register pceplib logging callback */
103 register_logger(pceplib_logging_cb);
104
105 /* Its ok that this object goes out of scope, as it
106 * wont be stored, and its values will be copied */
107 struct pceplib_infra_config infra = {
108 /* Memory infrastructure */
109 .pceplib_infra_mt = MTYPE_PCEPLIB_INFRA,
110 .pceplib_messages_mt = MTYPE_PCEPLIB_MESSAGES,
111 .malloc_func = (pceplib_malloc_func)qmalloc,
112 .calloc_func = (pceplib_calloc_func)qcalloc,
113 .realloc_func = (pceplib_realloc_func)qrealloc,
114 .strdup_func = (pceplib_strdup_func)qstrdup,
115 .free_func = (pceplib_free_func)qfree,
116 /* Timers infrastructure */
117 .external_infra_data = fpt,
118 .socket_read_func = pcep_lib_pceplib_socket_read_cb,
119 .socket_write_func = pcep_lib_pceplib_socket_write_cb,
120 /* PCEP events */
121 .pcep_event_func = pcep_lib_pceplib_event_cb,
122 /* PCEPlib pthread creation callback */
123 .pthread_create_func = pcep_lib_pthread_create_cb};
124 if (!initialize_pcc_infra(&infra)) {
125 flog_err(EC_PATH_PCEP_PCC_INIT, "failed to initialize pceplib");
126 return 1;
127 }
128
129 return 0;
130}
131
132void pcep_lib_finalize(void)
133{
134 PCEP_DEBUG("Finalizing pceplib");
135 if (!destroy_pcc()) {
136 flog_err(EC_PATH_PCEP_PCC_FINI, "failed to finalize pceplib");
137 }
138}
139
140
141pcep_session *
142pcep_lib_connect(struct ipaddr *src_addr, int src_port, struct ipaddr *dst_addr,
143 int dst_port, short msd,
144 const struct pcep_config_group_opts *pcep_options)
145{
146 pcep_configuration *config;
147 pcep_session *sess;
148
149 config = create_default_pcep_configuration();
150 config->dst_pcep_port = dst_port;
151 config->src_pcep_port = src_port;
152 if (IS_IPADDR_V6(src_addr)) {
153 config->is_src_ipv6 = true;
154 memcpy(&config->src_ip.src_ipv6, &src_addr->ipaddr_v6,
155 sizeof(struct in6_addr));
156 } else {
157 config->is_src_ipv6 = false;
158 config->src_ip.src_ipv4 = src_addr->ipaddr_v4;
159 }
160
161 config->support_stateful_pce_lsp_update = true;
56634922 162 config->support_pce_lsp_instantiation = pcep_options->pce_initiated;
efba0985
SM
163 config->support_include_db_version = false;
164 config->support_lsp_triggered_resync = false;
165 config->support_lsp_delta_sync = false;
166 config->support_pce_triggered_initial_sync = false;
167 config->support_sr_te_pst = true;
168 config->pcc_can_resolve_nai_to_sid = false;
169
170 config->max_sid_depth = msd;
171 config->pcep_msg_versioning->draft_ietf_pce_segment_routing_07 =
172 pcep_options->draft07;
173 config->keep_alive_seconds = pcep_options->keep_alive_seconds;
174 config->min_keep_alive_seconds = pcep_options->min_keep_alive_seconds;
175 config->max_keep_alive_seconds = pcep_options->max_keep_alive_seconds;
176 config->dead_timer_seconds = pcep_options->dead_timer_seconds;
177 config->min_dead_timer_seconds = pcep_options->min_dead_timer_seconds;
178 config->max_dead_timer_seconds = pcep_options->max_dead_timer_seconds;
179 config->request_time_seconds = pcep_options->pcep_request_time_seconds;
180 /* TODO when available in the pceplib, set it here
181 pcep_options->state_timeout_inteval_seconds;*/
182
74971473 183 if (pcep_options->tcp_md5_auth[0] != '\0') {
efba0985 184 config->is_tcp_auth_md5 = true;
74971473
JG
185 strlcpy(config->tcp_authentication_str,
186 pcep_options->tcp_md5_auth,
187 sizeof(config->tcp_authentication_str));
efba0985
SM
188 } else {
189 config->is_tcp_auth_md5 = false;
190 }
191
192 if (IS_IPADDR_V6(dst_addr)) {
193 sess = connect_pce_ipv6(config, &dst_addr->ipaddr_v6);
194 } else {
195 sess = connect_pce(config, &dst_addr->ipaddr_v4);
196 }
197 destroy_pcep_configuration(config);
198 return sess;
199}
200
201void pcep_lib_disconnect(pcep_session *sess)
202{
203 assert(sess != NULL);
204 disconnect_pce(sess);
205}
206
207/* Callback passed to pceplib to write to a socket.
208 * When the socket is ready to be written to,
209 * pcep_lib_socket_write_ready() will be called */
210
211int pcep_lib_pceplib_socket_write_cb(void *fpt, void **thread, int fd,
212 void *payload)
213{
214 return pcep_thread_socket_write(fpt, thread, fd, payload,
215 pcep_lib_socket_write_ready);
216}
217
218/* Callback passed to pceplib to read from a socket.
219 * When the socket is ready to be read from,
220 * pcep_lib_socket_read_ready() will be called */
221
222int pcep_lib_pceplib_socket_read_cb(void *fpt, void **thread, int fd,
223 void *payload)
224{
225 return pcep_thread_socket_read(fpt, thread, fd, payload,
226 pcep_lib_socket_read_ready);
227}
228
229/* Callbacks called by path_pcep_controller when a socket is ready to read/write
230 */
231
cc9f21da 232void pcep_lib_socket_write_ready(struct thread *thread)
efba0985
SM
233{
234 struct pcep_ctrl_socket_data *data = THREAD_ARG(thread);
235 assert(data != NULL);
236
cc9f21da 237 pceplib_external_socket_write(data->fd, data->payload);
efba0985 238 XFREE(MTYPE_PCEP, data);
efba0985
SM
239}
240
cc9f21da 241void pcep_lib_socket_read_ready(struct thread *thread)
efba0985
SM
242{
243 struct pcep_ctrl_socket_data *data = THREAD_ARG(thread);
244 assert(data != NULL);
245
cc9f21da 246 pceplib_external_socket_read(data->fd, data->payload);
efba0985 247 XFREE(MTYPE_PCEP, data);
efba0985
SM
248}
249
250/* Callback passed to pceplib when a pcep_event is ready */
251void pcep_lib_pceplib_event_cb(void *fpt, pcep_event *event)
252{
253 pcep_thread_send_ctrl_event(fpt, event, pcep_thread_pcep_event);
254}
255
256/* Wrapper function around the actual pceplib thread start function */
257void *pcep_lib_pthread_start_passthrough(void *data)
258{
259 struct frr_pthread *fpt = data;
260 struct pcep_lib_pthread_passthrough_data *passthrough_data = fpt->data;
261 void *start_routine_data = passthrough_data->data;
262 void *(*start_routine)(void *) = passthrough_data->start_routine;
263 XFREE(MTYPE_PCEP, passthrough_data);
264
265 if (start_routine != NULL) {
266 return start_routine(start_routine_data);
267 }
268
269 return NULL;
270}
271
272int pcep_lib_pthread_create_cb(pthread_t *thread_id, const pthread_attr_t *attr,
273 void *(*start_routine)(void *), void *data,
274 const char *thread_name)
275{
276 /* Since FRR calls the start_routine with a struct frr_pthread,
277 * we have to store the real data and callback in a passthrough
278 * and pass the actual data the start_routine needs */
279 struct pcep_lib_pthread_passthrough_data *passthrough_data = XMALLOC(
280 MTYPE_PCEP, sizeof(struct pcep_lib_pthread_passthrough_data));
281 passthrough_data->data = data;
282 passthrough_data->start_routine = start_routine;
283
284 struct frr_pthread_attr fpt_attr = {
285 .start = pcep_lib_pthread_start_passthrough,
286 .stop = pcep_lib_pthread_stop_cb};
287 struct frr_pthread *fpt =
5ffdc11e 288 frr_pthread_new(&fpt_attr, thread_name, "pcep_lib");
efba0985
SM
289 if (fpt == NULL) {
290 return 1;
291 }
292
293 fpt->data = passthrough_data;
294 int retval = frr_pthread_run(fpt, attr);
295 if (retval) {
296 return retval;
297 }
298
299 *thread_id = fpt->thread;
300
301 return 0;
302}
303
304int pcep_lib_pthread_stop_cb(struct frr_pthread *fpt, void **res)
305{
306 pcep_lib_finalize();
307 frr_pthread_destroy(fpt);
308
309 return 0;
310}
311
312struct pcep_message *pcep_lib_format_report(struct pcep_caps *caps,
313 struct path *path)
314{
315 double_linked_list *objs = pcep_lib_format_path(caps, path);
316 return pcep_msg_create_report(objs);
317}
318
319static struct pcep_object_rp *create_rp(uint32_t reqid)
320{
321 double_linked_list *rp_tlvs;
322 struct pcep_object_tlv_path_setup_type *setup_type_tlv;
323 struct pcep_object_rp *rp;
324
325 rp_tlvs = dll_initialize();
326 setup_type_tlv = pcep_tlv_create_path_setup_type(SR_TE_PST);
327 dll_append(rp_tlvs, setup_type_tlv);
328
329 rp = pcep_obj_create_rp(0, false, false, false, true, reqid, rp_tlvs);
330
331 return rp;
332}
333
334struct pcep_message *pcep_lib_format_request(struct pcep_caps *caps,
335 struct path *path)
336{
337 struct ipaddr *src = &path->pcc_addr;
338 struct ipaddr *dst = &path->nbkey.endpoint;
339 double_linked_list *objs;
340 struct pcep_object_rp *rp;
341 struct pcep_object_endpoints_ipv4 *endpoints_ipv4;
342 struct pcep_object_endpoints_ipv6 *endpoints_ipv6;
343 struct pcep_object_objective_function *of = NULL;
344 enum objfun_type objfun = OBJFUN_UNDEFINED;
345
346 assert(src->ipa_type == dst->ipa_type);
347
348 objs = dll_initialize();
349 rp = create_rp(path->req_id);
350 rp->header.flag_p = true;
351
352 pcep_lib_format_constraints(path, objs);
353
354 /* Objective Function */
355 if (path->has_pcc_objfun) {
356 objfun = path->pcc_objfun;
357 }
358
359 if (objfun != OBJFUN_UNDEFINED) {
360 of = pcep_obj_create_objective_function(objfun, NULL);
361 assert(of != NULL);
362 of->header.flag_p = path->enforce_pcc_objfun;
363 dll_append(objs, of);
364 }
365
366 if (IS_IPADDR_V6(src)) {
367 endpoints_ipv6 = pcep_obj_create_endpoint_ipv6(&src->ipaddr_v6,
368 &dst->ipaddr_v6);
369 endpoints_ipv6->header.flag_p = true;
370 return pcep_msg_create_request_ipv6(rp, endpoints_ipv6, objs);
371 } else {
372 endpoints_ipv4 = pcep_obj_create_endpoint_ipv4(&src->ipaddr_v4,
373 &dst->ipaddr_v4);
374 endpoints_ipv4->header.flag_p = true;
375 return pcep_msg_create_request(rp, endpoints_ipv4, objs);
376 }
377}
378
56634922
JG
379struct pcep_message *pcep_lib_format_error(int error_type, int error_value,
380 struct path *path)
efba0985 381{
56634922
JG
382 double_linked_list *objs, *srp_tlvs;
383 struct pcep_object_srp *srp;
384 struct pcep_object_tlv_header *tlv;
385
386 if ((path == NULL) || (path->srp_id == 0))
387 return pcep_msg_create_error(error_type, error_value);
388
389 objs = dll_initialize();
390 srp_tlvs = dll_initialize();
391 tlv = (struct pcep_object_tlv_header *)pcep_tlv_create_path_setup_type(
392 SR_TE_PST);
393 dll_append(srp_tlvs, tlv);
394 srp = pcep_obj_create_srp(path->do_remove, path->srp_id, srp_tlvs);
395 dll_append(objs, srp);
396 return pcep_msg_create_error_with_objects(error_type, error_value,
397 objs);
efba0985
SM
398}
399
400struct pcep_message *pcep_lib_format_request_cancelled(uint32_t reqid)
401{
402 struct pcep_object_notify *notify;
403 double_linked_list *objs;
404 struct pcep_object_rp *rp;
405
406 notify = pcep_obj_create_notify(
407 PCEP_NOTIFY_TYPE_PENDING_REQUEST_CANCELLED,
408 PCEP_NOTIFY_VALUE_PCC_CANCELLED_REQUEST);
409 objs = dll_initialize();
410 rp = create_rp(reqid);
411 dll_append(objs, rp);
412
413 return pcep_msg_create_notify(notify, objs);
414}
415
416struct path *pcep_lib_parse_path(struct pcep_message *msg)
417{
418 struct path *path;
419 double_linked_list *objs = msg->obj_list;
420 double_linked_list_node *node;
421
422 struct pcep_object_header *obj;
423 struct pcep_object_rp *rp = NULL;
424 struct pcep_object_srp *srp = NULL;
425 struct pcep_object_lsp *lsp = NULL;
426 struct pcep_object_lspa *lspa = NULL;
427 struct pcep_object_ro *ero = NULL;
428 struct pcep_object_metric *metric = NULL;
429 struct pcep_object_bandwidth *bandwidth = NULL;
430 struct pcep_object_objective_function *of = NULL;
56634922
JG
431 struct pcep_object_endpoints_ipv4 *epv4 = NULL;
432 struct pcep_object_endpoints_ipv6 *epv6 = NULL;
433 struct pcep_object_vendor_info *vendor_info = NULL;
efba0985
SM
434
435 path = pcep_new_path();
436
437 for (node = objs->head; node != NULL; node = node->next_node) {
438 obj = (struct pcep_object_header *)node->data;
439 switch (CLASS_TYPE(obj->object_class, obj->object_type)) {
440 case CLASS_TYPE(PCEP_OBJ_CLASS_RP, PCEP_OBJ_TYPE_RP):
441 assert(rp == NULL);
442 rp = (struct pcep_object_rp *)obj;
443 pcep_lib_parse_rp(path, rp);
444 break;
445 case CLASS_TYPE(PCEP_OBJ_CLASS_SRP, PCEP_OBJ_TYPE_SRP):
446 assert(srp == NULL);
447 srp = (struct pcep_object_srp *)obj;
448 pcep_lib_parse_srp(path, srp);
449 break;
450 case CLASS_TYPE(PCEP_OBJ_CLASS_LSP, PCEP_OBJ_TYPE_LSP):
451 /* Only support single LSP per message */
452 assert(lsp == NULL);
453 lsp = (struct pcep_object_lsp *)obj;
454 pcep_lib_parse_lsp(path, lsp);
455 break;
456 case CLASS_TYPE(PCEP_OBJ_CLASS_LSPA, PCEP_OBJ_TYPE_LSPA):
457 assert(lspa == NULL);
458 lspa = (struct pcep_object_lspa *)obj;
459 pcep_lib_parse_lspa(path, lspa);
460 break;
461 case CLASS_TYPE(PCEP_OBJ_CLASS_ERO, PCEP_OBJ_TYPE_ERO):
462 /* Only support single ERO per message */
463 assert(ero == NULL);
464 ero = (struct pcep_object_ro *)obj;
465 pcep_lib_parse_ero(path, ero);
466 break;
467 case CLASS_TYPE(PCEP_OBJ_CLASS_METRIC, PCEP_OBJ_TYPE_METRIC):
468 metric = (struct pcep_object_metric *)obj;
469 pcep_lib_parse_metric(path, metric);
470 break;
471 case CLASS_TYPE(PCEP_OBJ_CLASS_BANDWIDTH,
472 PCEP_OBJ_TYPE_BANDWIDTH_REQ):
473 case CLASS_TYPE(PCEP_OBJ_CLASS_BANDWIDTH,
474 PCEP_OBJ_TYPE_BANDWIDTH_CISCO):
475 bandwidth = (struct pcep_object_bandwidth *)obj;
476 path->has_bandwidth = true;
477 path->bandwidth = bandwidth->bandwidth;
478 break;
479 case CLASS_TYPE(PCEP_OBJ_CLASS_NOPATH, PCEP_OBJ_TYPE_NOPATH):
480 path->no_path = true;
481 break;
482 case CLASS_TYPE(PCEP_OBJ_CLASS_OF, PCEP_OBJ_TYPE_OF):
483 of = (struct pcep_object_objective_function *)obj;
484 path->has_pce_objfun = true;
485 path->pce_objfun = of->of_code;
486 break;
56634922
JG
487 case CLASS_TYPE(PCEP_OBJ_CLASS_ENDPOINTS,
488 PCEP_OBJ_TYPE_ENDPOINT_IPV4):
489 epv4 = (struct pcep_object_endpoints_ipv4 *)obj;
490 pcep_lib_parse_endpoints_ipv4(path, epv4);
491 break;
492 case CLASS_TYPE(PCEP_OBJ_CLASS_ENDPOINTS,
493 PCEP_OBJ_TYPE_ENDPOINT_IPV6):
494 epv6 = (struct pcep_object_endpoints_ipv6 *)obj;
495 pcep_lib_parse_endpoints_ipv6(path, epv6);
496 break;
497 case CLASS_TYPE(PCEP_OBJ_CLASS_VENDOR_INFO,
498 PCEP_OBJ_TYPE_VENDOR_INFO):
499 vendor_info = (struct pcep_object_vendor_info *)obj;
500 pcep_lib_parse_vendor_info(path, vendor_info);
501 break;
efba0985
SM
502 default:
503 flog_warn(EC_PATH_PCEP_UNEXPECTED_PCEP_OBJECT,
504 "Unexpected PCEP object %s (%u) / %s (%u)",
505 pcep_object_class_name(obj->object_class),
506 obj->object_class,
507 pcep_object_type_name(obj->object_class,
508 obj->object_type),
509 obj->object_type);
510 break;
511 }
512 }
513
514 return path;
515}
516
517void pcep_lib_parse_capabilities(struct pcep_message *msg,
518 struct pcep_caps *caps)
519{
520 double_linked_list *objs = msg->obj_list;
521 double_linked_list_node *node;
522
523 struct pcep_object_header *obj;
524 struct pcep_object_open *open = NULL;
525
526 for (node = objs->head; node != NULL; node = node->next_node) {
527 obj = (struct pcep_object_header *)node->data;
528 switch (CLASS_TYPE(obj->object_class, obj->object_type)) {
529 case CLASS_TYPE(PCEP_OBJ_CLASS_OPEN, PCEP_OBJ_TYPE_OPEN):
530 assert(open == NULL);
531 open = (struct pcep_object_open *)obj;
532 pcep_lib_parse_open(caps, open);
533 break;
534 default:
535 flog_warn(EC_PATH_PCEP_UNEXPECTED_PCEP_OBJECT,
536 "Unexpected PCEP object %s (%u) / %s (%u)",
537 pcep_object_class_name(obj->object_class),
538 obj->object_class,
539 pcep_object_type_name(obj->object_class,
540 obj->object_type),
541 obj->object_type);
542 break;
543 }
544 }
545}
546
547struct counters_group *pcep_lib_copy_counters(pcep_session *sess)
548{
549 if (!sess || !sess->pcep_session_counters) {
550 return NULL;
551 }
552
553 return copy_counter_group(sess->pcep_session_counters);
554}
555
556void pcep_lib_free_counters(struct counters_group *counters)
557{
558 free_counter_group(counters);
559}
560
561pcep_session *pcep_lib_copy_pcep_session(pcep_session *sess)
562{
563 if (!sess) {
564 return NULL;
565 }
566
567 pcep_session *copy;
568 copy = XCALLOC(MTYPE_PCEP, sizeof(*copy));
569 memcpy(copy, sess, sizeof(*copy));
570 /* These fields should not be accessed */
571 copy->num_unknown_messages_time_queue = NULL;
572 copy->socket_comm_session = NULL;
573 copy->pcep_session_counters = NULL;
574
575 return copy;
576}
577
578/* ------------ pceplib logging callback ------------ */
579
580int pceplib_logging_cb(int priority, const char *fmt, va_list args)
581{
582 char buffer[1024];
583 vsnprintf(buffer, sizeof(buffer), fmt, args);
584 PCEP_DEBUG_PCEPLIB(priority, "pceplib: %s", buffer);
585 return 0;
586}
587
588/* ------------ Internal Functions ------------ */
589
590double_linked_list *pcep_lib_format_path(struct pcep_caps *caps,
591 struct path *path)
592{
593 struct in_addr addr_null;
594 double_linked_list *objs, *srp_tlvs, *lsp_tlvs, *ero_objs;
595 struct pcep_object_tlv_header *tlv;
596 struct pcep_object_ro_subobj *ero_obj;
597 struct pcep_object_srp *srp;
598 struct pcep_object_lsp *lsp;
599 struct pcep_object_ro *ero;
600 uint32_t encoded_binding_sid;
601 char binding_sid_lsp_tlv_data[6];
602
603 memset(&addr_null, 0, sizeof(addr_null));
604
605 objs = dll_initialize();
606
607 if (path->plsp_id != 0) {
608 /* SRP object */
609 srp_tlvs = dll_initialize();
610 tlv = (struct pcep_object_tlv_header *)
611 pcep_tlv_create_path_setup_type(SR_TE_PST);
612 assert(tlv != NULL);
613 dll_append(srp_tlvs, tlv);
614 srp = pcep_obj_create_srp(path->do_remove, path->srp_id,
615 srp_tlvs);
616 assert(srp != NULL);
617 srp->header.flag_p = true;
618 dll_append(objs, srp);
619 }
620
621 /* LSP object */
622 lsp_tlvs = dll_initialize();
623
624 if (path->plsp_id == 0 || IS_IPADDR_NONE(&path->nbkey.endpoint)
625 || IS_IPADDR_NONE(&path->pcc_addr)) {
626 tlv = (struct pcep_object_tlv_header *)
627 pcep_tlv_create_ipv4_lsp_identifiers(
628 &addr_null, &addr_null, 0, 0, &addr_null);
629 } else {
630 assert(path->pcc_addr.ipa_type
631 == path->nbkey.endpoint.ipa_type);
632 if (IS_IPADDR_V4(&path->pcc_addr)) {
633 tlv = (struct pcep_object_tlv_header *)
634 pcep_tlv_create_ipv4_lsp_identifiers(
635 &path->pcc_addr.ipaddr_v4,
636 &path->nbkey.endpoint.ipaddr_v4, 0, 0,
637 &path->pcc_addr.ipaddr_v4);
638 } else {
639 tlv = (struct pcep_object_tlv_header *)
640 pcep_tlv_create_ipv6_lsp_identifiers(
641 &path->pcc_addr.ipaddr_v6,
642 &path->nbkey.endpoint.ipaddr_v6, 0, 0,
643 &path->pcc_addr.ipaddr_v6);
644 }
645 }
646 assert(tlv != NULL);
647 dll_append(lsp_tlvs, tlv);
648 if (path->name != NULL) {
649 tlv = (struct pcep_object_tlv_header *)
650 /*FIXME: Remove the typecasty when pceplib is changed
651 to take a const char* */
652 pcep_tlv_create_symbolic_path_name((char *)path->name,
653 strlen(path->name));
654 assert(tlv != NULL);
655 dll_append(lsp_tlvs, tlv);
656 }
657 if ((path->plsp_id != 0) && (path->binding_sid != MPLS_LABEL_NONE)) {
658 memset(binding_sid_lsp_tlv_data, 0, 2);
659 encoded_binding_sid = htonl(path->binding_sid << 12);
660 memcpy(binding_sid_lsp_tlv_data + 2, &encoded_binding_sid, 4);
661 tlv = (struct pcep_object_tlv_header *)
662 pcep_tlv_create_tlv_arbitrary(
663 binding_sid_lsp_tlv_data,
56634922
JG
664 sizeof(binding_sid_lsp_tlv_data),
665 PCEP_OBJ_TYPE_CISCO_BSID);
efba0985
SM
666 assert(tlv != NULL);
667 dll_append(lsp_tlvs, tlv);
668 }
669 lsp = pcep_obj_create_lsp(
670 path->plsp_id, path->status, path->was_created /* C Flag */,
671 path->go_active /* A Flag */, path->was_removed /* R Flag */,
672 path->is_synching /* S Flag */, path->is_delegated /* D Flag */,
673 lsp_tlvs);
674 assert(lsp != NULL);
675 lsp->header.flag_p = true;
676 dll_append(objs, lsp);
677 /* ERO object */
678 ero_objs = dll_initialize();
679 for (struct path_hop *hop = path->first_hop; hop != NULL;
680 hop = hop->next) {
681 uint32_t sid;
682
683 /* Only supporting MPLS hops with both sid and nai */
684 assert(hop->is_mpls);
685 assert(hop->has_sid);
686
687 if (hop->has_attribs) {
688 sid = ENCODE_SR_ERO_SID(hop->sid.mpls.label,
689 hop->sid.mpls.traffic_class,
690 hop->sid.mpls.is_bottom,
691 hop->sid.mpls.ttl);
692 } else {
693 sid = ENCODE_SR_ERO_SID(hop->sid.mpls.label, 0, 0, 0);
694 }
695
696 ero_obj = NULL;
697 if (hop->has_nai) {
698 assert(hop->nai.type != PCEP_SR_SUBOBJ_NAI_ABSENT);
699 assert(hop->nai.type
700 != PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY);
701 assert(hop->nai.type != PCEP_SR_SUBOBJ_NAI_UNKNOWN);
702 switch (hop->nai.type) {
703 case PCEP_SR_SUBOBJ_NAI_IPV4_NODE:
704 ero_obj = (struct pcep_object_ro_subobj *)
705 pcep_obj_create_ro_subobj_sr_ipv4_node(
706 hop->is_loose, !hop->has_sid,
707 hop->has_attribs, /* C Flag */
708 hop->is_mpls, /* M Flag */
709 sid,
710 &hop->nai.local_addr.ipaddr_v4);
711 break;
712 case PCEP_SR_SUBOBJ_NAI_IPV6_NODE:
713 ero_obj = (struct pcep_object_ro_subobj *)
714 pcep_obj_create_ro_subobj_sr_ipv6_node(
715 hop->is_loose, !hop->has_sid,
716 hop->has_attribs, /* C Flag */
717 hop->is_mpls, /* M Flag */
718 sid,
719 &hop->nai.local_addr.ipaddr_v6);
720 break;
721 case PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY:
722 ero_obj = (struct pcep_object_ro_subobj *)
723 pcep_obj_create_ro_subobj_sr_ipv4_adj(
724 hop->is_loose, !hop->has_sid,
725 hop->has_attribs, /* C Flag */
726 hop->is_mpls, /* M Flag */
727 sid,
728 &hop->nai.local_addr.ipaddr_v4,
729 &hop->nai.remote_addr
730 .ipaddr_v4);
731 break;
732 case PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY:
733 ero_obj = (struct pcep_object_ro_subobj *)
734 pcep_obj_create_ro_subobj_sr_ipv6_adj(
735 hop->is_loose, !hop->has_sid,
736 hop->has_attribs, /* C Flag */
737 hop->is_mpls, /* M Flag */
738 sid,
739 &hop->nai.local_addr.ipaddr_v6,
740 &hop->nai.remote_addr
741 .ipaddr_v6);
742 break;
743 case PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY:
744 ero_obj = (struct pcep_object_ro_subobj *)
745 pcep_obj_create_ro_subobj_sr_unnumbered_ipv4_adj(
746 hop->is_loose, !hop->has_sid,
747 hop->has_attribs, /* C Flag */
748 hop->is_mpls, /* M Flag */
749 sid,
750 hop->nai.local_addr.ipaddr_v4
751 .s_addr,
752 hop->nai.local_iface,
753 hop->nai.remote_addr.ipaddr_v4
754 .s_addr,
755 hop->nai.remote_iface);
756 break;
d5dea350
DS
757 case PCEP_SR_SUBOBJ_NAI_ABSENT:
758 case PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY:
759 case PCEP_SR_SUBOBJ_NAI_UNKNOWN:
efba0985
SM
760 break;
761 }
762 }
763 if (ero_obj == NULL) {
764 ero_obj = (struct pcep_object_ro_subobj *)
765 pcep_obj_create_ro_subobj_sr_nonai(
766 hop->is_loose, sid,
767 hop->has_attribs, /* C Flag */
768 hop->is_mpls); /* M Flag */
769 }
770 dll_append(ero_objs, ero_obj);
771 }
772 ero = pcep_obj_create_ero(ero_objs);
773 assert(ero != NULL);
774 ero->header.flag_p = true;
775 dll_append(objs, ero);
776
777 if (path->plsp_id == 0) {
778 return objs;
779 }
780
781 pcep_lib_format_constraints(path, objs);
782
783 return objs;
784}
785
786void pcep_lib_format_constraints(struct path *path, double_linked_list *objs)
787{
788 struct pcep_object_metric *metric;
789 struct pcep_object_bandwidth *bandwidth;
790 struct pcep_object_lspa *lspa;
791
792 /* LSPA object */
793 if (path->has_affinity_filters) {
794 lspa = pcep_obj_create_lspa(
795 path->affinity_filters[AFFINITY_FILTER_EXCLUDE_ANY - 1],
796 path->affinity_filters[AFFINITY_FILTER_INCLUDE_ANY - 1],
797 path->affinity_filters[AFFINITY_FILTER_INCLUDE_ALL - 1],
798 DEFAULT_LSAP_SETUP_PRIO, DEFAULT_LSAP_HOLDING_PRIO,
799 DEFAULT_LSAP_LOCAL_PRETECTION);
800 assert(lspa != NULL);
801 lspa->header.flag_p = true;
802 dll_append(objs, lspa);
803 }
804
805 /* Bandwidth Objects */
806 if (path->has_bandwidth) {
807 /* Requested Bandwidth */
808 bandwidth = pcep_obj_create_bandwidth(path->bandwidth);
809 assert(bandwidth != NULL);
810 bandwidth->header.flag_p = path->enforce_bandwidth;
811 dll_append(objs, bandwidth);
812 }
813
814 /* Metric Objects */
815 for (struct path_metric *m = path->first_metric; m != NULL;
816 m = m->next) {
817 metric = pcep_obj_create_metric(m->type, m->is_bound,
818 m->is_computed, m->value);
819 assert(metric != NULL);
820 metric->header.flag_p = m->enforce;
821 dll_append(objs, metric);
822 }
823}
824
825void pcep_lib_parse_open(struct pcep_caps *caps, struct pcep_object_open *open)
826{
827 double_linked_list *tlvs = open->header.tlv_list;
828 double_linked_list_node *node;
829 struct pcep_object_tlv_header *tlv_header;
830
831 caps->is_stateful = false;
832 caps->supported_ofs_are_known = false;
833 caps->supported_ofs = 0;
834
835 for (node = tlvs->head; node != NULL; node = node->next_node) {
836 tlv_header = (struct pcep_object_tlv_header *)node->data;
837 switch (tlv_header->type) {
838 case PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY:
839 pcep_lib_parse_open_pce_capability(caps, tlv_header);
840 break;
841 case PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY:
842 break;
843 case PCEP_OBJ_TLV_TYPE_OBJECTIVE_FUNCTION_LIST:
844 pcep_lib_parse_open_objfun_list(caps, tlv_header);
845 break;
d5dea350
DS
846 case PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR:
847 case PCEP_OBJ_TLV_TYPE_VENDOR_INFO:
848 case PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS:
849 case PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS:
850 case PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE:
851 case PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC:
852 case PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION:
853 case PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID:
854 case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE:
855 case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY:
856 case PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID:
857 case PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME:
858 case PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID:
859 case PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE:
860 case PCEP_OBJ_TLV_TYPE_UNKNOWN:
861 case PCEP_OBJ_TLV_TYPE_ARBITRARY:
862 case PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME:
863 case PCEP_OBJ_TYPE_CISCO_BSID:
efba0985
SM
864 flog_warn(EC_PATH_PCEP_UNEXPECTED_PCEP_TLV,
865 "Unexpected OPEN's TLV %s (%u)",
866 pcep_tlv_type_name(tlv_header->type),
867 tlv_header->type);
868 break;
869 }
870 }
871}
872
873void pcep_lib_parse_open_pce_capability(
874 struct pcep_caps *caps, struct pcep_object_tlv_header *tlv_header)
875{
876 struct pcep_object_tlv_stateful_pce_capability *tlv;
877 tlv = (struct pcep_object_tlv_stateful_pce_capability *)tlv_header;
878 caps->is_stateful = tlv->flag_u_lsp_update_capability;
879}
880
881void pcep_lib_parse_open_objfun_list(struct pcep_caps *caps,
882 struct pcep_object_tlv_header *tlv_header)
883{
884 double_linked_list_node *node;
885 struct pcep_object_tlv_of_list *tlv;
886 tlv = (struct pcep_object_tlv_of_list *)tlv_header;
887 uint16_t of_code;
888 caps->supported_ofs_are_known = true;
889 for (node = tlv->of_list->head; node != NULL; node = node->next_node) {
890 of_code = *(uint16_t *)node->data;
891 if (of_code >= 32) {
892 zlog_warn(
893 "Ignoring unexpected objective function with code %u",
894 of_code);
895 continue;
896 }
897 SET_FLAG(caps->supported_ofs, of_code);
898 }
899}
900
901void pcep_lib_parse_rp(struct path *path, struct pcep_object_rp *rp)
902{
903 double_linked_list *tlvs = rp->header.tlv_list;
904 double_linked_list_node *node;
905 struct pcep_object_tlv_header *tlv;
906
120e524f
JG
907 if (tlvs == NULL) {
908 flog_warn(EC_PATH_PCEP_UNEXPECTED_PCEP_TLV,
909 "Unexpected Empty RP's TLV plsp-id:(%d)",
910 path ? (int32_t)path->plsp_id : -1);
911 return;
912 }
efba0985
SM
913 /* We ignore the other flags and priority for now */
914 path->req_id = rp->request_id;
915 path->has_pce_objfun = false;
916 path->pce_objfun = OBJFUN_UNDEFINED;
917
918 for (node = tlvs->head; node != NULL; node = node->next_node) {
919 tlv = (struct pcep_object_tlv_header *)node->data;
920 switch (tlv->type) {
921 case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE:
922 // TODO: enforce the path setup type is SR_TE_PST
923 break;
d5dea350
DS
924 case PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR:
925 case PCEP_OBJ_TLV_TYPE_OBJECTIVE_FUNCTION_LIST:
926 case PCEP_OBJ_TLV_TYPE_VENDOR_INFO:
927 case PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS:
928 case PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS:
929 case PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE:
930 case PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC:
931 case PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION:
932 case PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID:
933 case PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY:
934 case PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID:
935 case PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME:
936 case PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID:
937 case PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE:
938 case PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY:
939 case PCEP_OBJ_TLV_TYPE_UNKNOWN:
940 case PCEP_OBJ_TLV_TYPE_ARBITRARY:
941 case PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME:
942 case PCEP_OBJ_TYPE_CISCO_BSID:
943 case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY:
efba0985
SM
944 flog_warn(EC_PATH_PCEP_UNEXPECTED_PCEP_TLV,
945 "Unexpected RP's TLV %s (%u)",
946 pcep_tlv_type_name(tlv->type), tlv->type);
947 break;
948 }
949 }
950}
951
952void pcep_lib_parse_srp(struct path *path, struct pcep_object_srp *srp)
953{
954 double_linked_list *tlvs = srp->header.tlv_list;
955 double_linked_list_node *node;
956 struct pcep_object_tlv_header *tlv;
957
958 path->do_remove = srp->flag_lsp_remove;
959 path->srp_id = srp->srp_id_number;
960
120e524f
JG
961 if (tlvs == NULL) {
962 flog_warn(EC_PATH_PCEP_UNEXPECTED_PCEP_TLV,
963 "Unexpected Empty SRP's TLV plsp-id:(%d)",
964 path ? (int32_t)path->plsp_id : -1);
965 return;
966 }
efba0985
SM
967 for (node = tlvs->head; node != NULL; node = node->next_node) {
968 tlv = (struct pcep_object_tlv_header *)node->data;
969 switch (tlv->type) {
970 case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE:
971 // TODO: enforce the path setup type is SR_TE_PST
972 break;
d5dea350
DS
973 case PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR:
974 case PCEP_OBJ_TLV_TYPE_OBJECTIVE_FUNCTION_LIST:
975 case PCEP_OBJ_TLV_TYPE_VENDOR_INFO:
976 case PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY:
977 case PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME:
978 case PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS:
979 case PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS:
980 case PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE:
981 case PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC:
982 case PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION:
983 case PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID:
984 case PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY:
985 case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY:
986 case PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID:
987 case PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME:
988 case PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID:
989 case PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE:
990 case PCEP_OBJ_TLV_TYPE_UNKNOWN:
991 case PCEP_OBJ_TYPE_CISCO_BSID:
992 case PCEP_OBJ_TLV_TYPE_ARBITRARY:
efba0985
SM
993 flog_warn(EC_PATH_PCEP_UNEXPECTED_PCEP_TLV,
994 "Unexpected SRP's TLV %s (%u)",
995 pcep_tlv_type_name(tlv->type), tlv->type);
996 break;
997 }
998 }
999}
1000
1001void pcep_lib_parse_lsp(struct path *path, struct pcep_object_lsp *lsp)
1002{
1003 double_linked_list *tlvs = lsp->header.tlv_list;
1004 double_linked_list_node *node;
1005 struct pcep_object_tlv_header *tlv;
56634922
JG
1006 struct pcep_object_tlv_symbolic_path_name *name;
1007 struct pcep_object_tlv_arbitrary *arb_tlv;
efba0985
SM
1008
1009 path->plsp_id = lsp->plsp_id;
1010 path->status = lsp->operational_status;
1011 path->go_active = lsp->flag_a;
1012 path->was_created = lsp->flag_c;
1013 path->was_removed = lsp->flag_r;
1014 path->is_synching = lsp->flag_s;
1015 path->is_delegated = lsp->flag_d;
1016
120e524f
JG
1017 if (tlvs == NULL) {
1018 flog_warn(EC_PATH_PCEP_UNEXPECTED_PCEP_TLV,
1019 "Unexpected Empty LSP's TLV plsp-id:(%d)",
1020 path ? (int32_t)path->plsp_id : -1);
efba0985 1021 return;
120e524f 1022 }
efba0985
SM
1023
1024 for (node = tlvs->head; node != NULL; node = node->next_node) {
1025 tlv = (struct pcep_object_tlv_header *)node->data;
1026 switch (tlv->type) {
56634922
JG
1027 case PCEP_OBJ_TLV_TYPE_SYMBOLIC_PATH_NAME:
1028 name = (struct pcep_object_tlv_symbolic_path_name *)tlv;
1029 pcep_lib_parse_lsp_symbolic_name(path, name);
1030 break;
1031 case PCEP_OBJ_TYPE_CISCO_BSID:
1032 arb_tlv = (struct pcep_object_tlv_arbitrary *)tlv;
1033 memcpy(&path->binding_sid, arb_tlv->data + 2,
1034 sizeof(path->binding_sid));
1035 path->binding_sid = ntohl(path->binding_sid);
1036 path->binding_sid = (path->binding_sid >> 12);
1037 break;
d5dea350
DS
1038 case PCEP_OBJ_TLV_TYPE_NO_PATH_VECTOR:
1039 case PCEP_OBJ_TLV_TYPE_OBJECTIVE_FUNCTION_LIST:
1040 case PCEP_OBJ_TLV_TYPE_VENDOR_INFO:
1041 case PCEP_OBJ_TLV_TYPE_IPV4_LSP_IDENTIFIERS:
1042 case PCEP_OBJ_TLV_TYPE_IPV6_LSP_IDENTIFIERS:
1043 case PCEP_OBJ_TLV_TYPE_LSP_ERROR_CODE:
1044 case PCEP_OBJ_TLV_TYPE_RSVP_ERROR_SPEC:
1045 case PCEP_OBJ_TLV_TYPE_LSP_DB_VERSION:
1046 case PCEP_OBJ_TLV_TYPE_SPEAKER_ENTITY_ID:
1047 case PCEP_OBJ_TLV_TYPE_SR_PCE_CAPABILITY:
1048 case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE:
1049 case PCEP_OBJ_TLV_TYPE_PATH_SETUP_TYPE_CAPABILITY:
1050 case PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_ID:
1051 case PCEP_OBJ_TLV_TYPE_SRPOLICY_POL_NAME:
1052 case PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_ID:
1053 case PCEP_OBJ_TLV_TYPE_SRPOLICY_CPATH_PREFERENCE:
1054 case PCEP_OBJ_TLV_TYPE_STATEFUL_PCE_CAPABILITY:
1055 case PCEP_OBJ_TLV_TYPE_UNKNOWN:
1056 case PCEP_OBJ_TLV_TYPE_ARBITRARY:
efba0985
SM
1057 flog_warn(EC_PATH_PCEP_UNEXPECTED_PCEP_TLV,
1058 "Unexpected LSP TLV %s (%u)",
1059 pcep_tlv_type_name(tlv->type), tlv->type);
1060 break;
1061 }
1062 }
1063}
1064
56634922
JG
1065void pcep_lib_parse_lsp_symbolic_name(
1066 struct path *path, struct pcep_object_tlv_symbolic_path_name *tlv)
1067{
1068 uint16_t size = tlv->symbolic_path_name_length;
1069 assert(path->name == NULL);
1070 size = size > MAX_PATH_NAME_SIZE ? MAX_PATH_NAME_SIZE : size;
1071 path->name = XCALLOC(MTYPE_PCEP, size);
1072 strlcpy((char *)path->name, tlv->symbolic_path_name, size + 1);
1073}
1074
efba0985
SM
1075void pcep_lib_parse_lspa(struct path *path, struct pcep_object_lspa *lspa)
1076{
1077 path->has_affinity_filters = true;
1078 path->affinity_filters[AFFINITY_FILTER_EXCLUDE_ANY - 1] =
1079 lspa->lspa_exclude_any;
1080 path->affinity_filters[AFFINITY_FILTER_INCLUDE_ANY - 1] =
1081 lspa->lspa_include_any;
1082 path->affinity_filters[AFFINITY_FILTER_INCLUDE_ALL - 1] =
1083 lspa->lspa_include_all;
1084}
1085
1086void pcep_lib_parse_metric(struct path *path, struct pcep_object_metric *obj)
1087{
1088 struct path_metric *metric;
1089
1090 metric = pcep_new_metric();
1091 metric->type = obj->type;
1092 metric->is_bound = obj->flag_b;
1093 metric->is_computed = obj->flag_c;
1094 metric->value = obj->value;
1095 metric->next = path->first_metric;
1096 path->first_metric = metric;
1097}
1098
56634922
JG
1099void pcep_lib_parse_endpoints_ipv4(struct path *path,
1100 struct pcep_object_endpoints_ipv4 *obj)
1101{
1102 SET_IPADDR_V4(&path->pcc_addr);
1103 path->pcc_addr.ipaddr_v4 = obj->src_ipv4;
1104 SET_IPADDR_V4(&path->nbkey.endpoint);
1105 path->nbkey.endpoint.ipaddr_v4 = obj->dst_ipv4;
1106}
1107
1108void pcep_lib_parse_endpoints_ipv6(struct path *path,
1109 struct pcep_object_endpoints_ipv6 *obj)
1110{
1111 SET_IPADDR_V6(&path->pcc_addr);
1112 path->pcc_addr.ipaddr_v6 = obj->src_ipv6;
1113 SET_IPADDR_V6(&path->nbkey.endpoint);
1114 path->nbkey.endpoint.ipaddr_v6 = obj->dst_ipv6;
1115}
1116
1117void pcep_lib_parse_vendor_info(struct path *path,
1118 struct pcep_object_vendor_info *obj)
1119{
1120 if (obj->enterprise_number == ENTERPRISE_NUMBER_CISCO
1121 && obj->enterprise_specific_info == ENTERPRISE_COLOR_CISCO)
1122 path->nbkey.color = obj->enterprise_specific_info1;
1123 else
1124 path->nbkey.color = 0;
1125}
1126
efba0985
SM
1127void pcep_lib_parse_ero(struct path *path, struct pcep_object_ro *ero)
1128{
1129 struct path_hop *hop = NULL;
1130 double_linked_list *objs = ero->sub_objects;
1131 double_linked_list_node *node;
1132 struct pcep_object_ro_subobj *obj;
1133
120e524f
JG
1134 if (objs == NULL) {
1135 flog_warn(EC_PATH_PCEP_UNEXPECTED_PCEP_TLV,
1136 "Unexpected Empty ERO's sub_obj plsp-id:(%d)",
1137 path ? (int32_t)path->plsp_id : -1);
1138 return;
1139 }
efba0985
SM
1140 for (node = objs->tail; node != NULL; node = node->prev_node) {
1141 obj = (struct pcep_object_ro_subobj *)node->data;
1142 switch (obj->ro_subobj_type) {
1143 case RO_SUBOBJ_TYPE_SR:
1144 hop = pcep_lib_parse_ero_sr(
1145 hop, (struct pcep_ro_subobj_sr *)obj);
1146 break;
d5dea350
DS
1147 case RO_SUBOBJ_TYPE_IPV4:
1148 case RO_SUBOBJ_TYPE_IPV6:
1149 case RO_SUBOBJ_TYPE_LABEL:
1150 case RO_SUBOBJ_TYPE_UNNUM:
1151 case RO_SUBOBJ_TYPE_ASN:
1152 case RO_SUBOBJ_UNKNOWN:
efba0985
SM
1153 flog_warn(EC_PATH_PCEP_UNEXPECTED_PCEP_ERO_SUBOBJ,
1154 "Unexpected ERO sub-object %s (%u)",
1155 pcep_ro_type_name(obj->ro_subobj_type),
1156 obj->ro_subobj_type);
1157 break;
1158 }
1159 }
1160
1161 path->first_hop = hop;
1162}
1163
1164struct path_hop *pcep_lib_parse_ero_sr(struct path_hop *next,
1165 struct pcep_ro_subobj_sr *sr)
1166{
1167 struct path_hop *hop = NULL;
1168 union sid sid;
1169
1170 /* Only support IPv4 node with SID */
1171 assert(!sr->flag_s);
1172
1173 if (sr->flag_m) {
1174 sid.mpls = (struct sid_mpls){
1175 .label = GET_SR_ERO_SID_LABEL(sr->sid),
1176 .traffic_class = GET_SR_ERO_SID_TC(sr->sid),
1177 .is_bottom = GET_SR_ERO_SID_S(sr->sid),
1178 .ttl = GET_SR_ERO_SID_TTL(sr->sid)};
1179 } else {
1180 sid.value = sr->sid;
1181 }
1182
1183 hop = pcep_new_hop();
1184 *hop = (struct path_hop){.next = next,
1185 .is_loose =
1186 sr->ro_subobj.flag_subobj_loose_hop,
1187 .has_sid = !sr->flag_s,
1188 .is_mpls = sr->flag_m,
1189 .has_attribs = sr->flag_c,
1190 .sid = sid,
1191 .has_nai = !sr->flag_f,
1192 .nai = {.type = sr->nai_type}};
1193
1194 if (!sr->flag_f) {
1195 assert(sr->nai_list != NULL);
1196 double_linked_list_node *n = sr->nai_list->head;
1197 assert(n != NULL);
1198 assert(n->data != NULL);
1199 switch (sr->nai_type) {
1200 case PCEP_SR_SUBOBJ_NAI_IPV4_NODE:
1201 hop->nai.local_addr.ipa_type = IPADDR_V4;
1202 memcpy(&hop->nai.local_addr.ipaddr_v4, n->data,
1203 sizeof(struct in_addr));
1204 break;
1205 case PCEP_SR_SUBOBJ_NAI_IPV6_NODE:
1206 hop->nai.local_addr.ipa_type = IPADDR_V6;
1207 memcpy(&hop->nai.local_addr.ipaddr_v6, n->data,
1208 sizeof(struct in6_addr));
1209 break;
1210 case PCEP_SR_SUBOBJ_NAI_IPV4_ADJACENCY:
1211 hop->nai.local_addr.ipa_type = IPADDR_V4;
1212 memcpy(&hop->nai.local_addr.ipaddr_v4, n->data,
1213 sizeof(struct in_addr));
1214 n = n->next_node;
1215 assert(n != NULL);
1216 assert(n->data != NULL);
1217 hop->nai.remote_addr.ipa_type = IPADDR_V4;
1218 memcpy(&hop->nai.remote_addr.ipaddr_v4, n->data,
1219 sizeof(struct in_addr));
1220 break;
1221 case PCEP_SR_SUBOBJ_NAI_IPV6_ADJACENCY:
1222 hop->nai.local_addr.ipa_type = IPADDR_V6;
1223 memcpy(&hop->nai.local_addr.ipaddr_v6, n->data,
1224 sizeof(struct in6_addr));
1225 n = n->next_node;
1226 assert(n != NULL);
1227 assert(n->data != NULL);
1228 hop->nai.remote_addr.ipa_type = IPADDR_V6;
1229 memcpy(&hop->nai.remote_addr.ipaddr_v6, n->data,
1230 sizeof(struct in6_addr));
1231 break;
1232 case PCEP_SR_SUBOBJ_NAI_UNNUMBERED_IPV4_ADJACENCY:
1233 hop->nai.local_addr.ipa_type = IPADDR_V4;
1234 memcpy(&hop->nai.local_addr.ipaddr_v4, n->data,
1235 sizeof(struct in_addr));
1236 n = n->next_node;
1237 assert(n != NULL);
1238 assert(n->data != NULL);
1239 hop->nai.local_iface = *(uint32_t *)n->data;
1240 n = n->next_node;
1241 assert(n != NULL);
1242 assert(n->data != NULL);
1243 hop->nai.remote_addr.ipa_type = IPADDR_V4;
1244 memcpy(&hop->nai.remote_addr.ipaddr_v4, n->data,
1245 sizeof(struct in_addr));
1246 n = n->next_node;
1247 assert(n != NULL);
1248 assert(n->data != NULL);
1249 hop->nai.remote_iface = *(uint32_t *)n->data;
1250 break;
d5dea350
DS
1251 case PCEP_SR_SUBOBJ_NAI_ABSENT:
1252 case PCEP_SR_SUBOBJ_NAI_LINK_LOCAL_IPV6_ADJACENCY:
1253 case PCEP_SR_SUBOBJ_NAI_UNKNOWN:
efba0985
SM
1254 hop->has_nai = false;
1255 flog_warn(EC_PATH_PCEP_UNEXPECTED_SR_NAI,
1256 "Unexpected SR segment NAI type %s (%u)",
1257 pcep_nai_type_name(sr->nai_type),
1258 sr->nai_type);
1259 break;
1260 }
1261 }
1262
1263 return hop;
1264}
1265
1266struct counters_group *copy_counter_group(struct counters_group *from)
1267{
1268 int size, i;
1269 struct counters_group *result;
1270 if (from == NULL)
1271 return NULL;
1272 assert(from->max_subgroups >= from->num_subgroups);
1273 result = XCALLOC(MTYPE_PCEP, sizeof(*result));
1274 memcpy(result, from, sizeof(*result));
1275 size = sizeof(struct counters_subgroup *) * (from->max_subgroups + 1);
1276 result->subgroups = XCALLOC(MTYPE_PCEP, size);
1277 for (i = 0; i <= from->max_subgroups; i++)
1278 result->subgroups[i] =
1279 copy_counter_subgroup(from->subgroups[i]);
1280 return result;
1281}
1282
1283struct counters_subgroup *copy_counter_subgroup(struct counters_subgroup *from)
1284{
1285 int size, i;
1286 struct counters_subgroup *result;
1287 if (from == NULL)
1288 return NULL;
1289 assert(from->max_counters >= from->num_counters);
1290 result = XCALLOC(MTYPE_PCEP, sizeof(*result));
1291 memcpy(result, from, sizeof(*result));
1292 size = sizeof(struct counter *) * (from->max_counters + 1);
1293 result->counters = XCALLOC(MTYPE_PCEP, size);
1294 for (i = 0; i <= from->max_counters; i++)
1295 result->counters[i] = copy_counter(from->counters[i]);
1296 return result;
1297}
1298
1299struct counter *copy_counter(struct counter *from)
1300{
1301 struct counter *result;
1302 if (from == NULL)
1303 return NULL;
1304 result = XCALLOC(MTYPE_PCEP, sizeof(*result));
1305 memcpy(result, from, sizeof(*result));
1306 return result;
1307}
1308
1309void free_counter_group(struct counters_group *group)
1310{
1311 int i;
1312 if (group == NULL)
1313 return;
1314 for (i = 0; i <= group->max_subgroups; i++)
1315 free_counter_subgroup(group->subgroups[i]);
1316 XFREE(MTYPE_PCEP, group->subgroups);
1317 XFREE(MTYPE_PCEP, group);
1318}
1319
1320void free_counter_subgroup(struct counters_subgroup *subgroup)
1321{
1322 int i;
1323 if (subgroup == NULL)
1324 return;
1325 for (i = 0; i <= subgroup->max_counters; i++)
1326 free_counter(subgroup->counters[i]);
1327 XFREE(MTYPE_PCEP, subgroup->counters);
1328 XFREE(MTYPE_PCEP, subgroup);
1329}
1330
1331void free_counter(struct counter *counter)
1332{
1333 if (counter == NULL)
1334 return;
1335 XFREE(MTYPE_PCEP, counter);
1336}