2 * Copyright (C) 2020 NetDEF, Inc.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along
15 * with this program; see the file COPYING; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "pceplib/pcep_utils_counters.h"
28 #include "northbound.h"
29 #include "frr_pthread.h"
31 #include "termtable.h"
33 #include "pathd/pathd.h"
34 #include "pathd/path_errors.h"
35 #include "pathd/path_pcep.h"
36 #include "pathd/path_pcep_cli.h"
37 #include "pathd/path_pcep_controller.h"
38 #include "pathd/path_pcep_lib.h"
39 #include "pathd/path_pcep_config.h"
41 DEFINE_MTYPE(PATHD
, PCEP
, "PCEP module");
46 static struct pcep_glob pcep_glob_space
= {.dbg
= {0, "pathd module: pcep"}};
47 struct pcep_glob
*pcep_g
= &pcep_glob_space
;
49 /* Main Thread Even Handler */
50 static int pcep_main_event_handler(enum pcep_main_event_type type
, int pcc_id
,
52 static int pcep_main_event_start_sync(int pcc_id
);
53 static int pcep_main_event_start_sync_cb(struct path
*path
, void *arg
);
54 static int pcep_main_event_update_candidate(struct path
*path
);
55 static int pcep_main_event_remove_candidate_segments(const char *originator
,
58 /* Hook Handlers called from the Main Thread */
59 static int pathd_candidate_created_handler(struct srte_candidate
*candidate
);
60 static int pathd_candidate_updated_handler(struct srte_candidate
*candidate
);
61 static int pathd_candidate_removed_handler(struct srte_candidate
*candidate
);
63 /* Path manipulation functions */
64 static struct path_metric
*pcep_copy_metrics(struct path_metric
*metric
);
65 static struct path_hop
*pcep_copy_hops(struct path_hop
*hop
);
67 /* Module Functions */
68 static int pcep_module_finish(void);
69 static int pcep_module_late_init(struct thread_master
*tm
);
70 static int pcep_module_init(void);
72 /* ------------ Path Helper Functions ------------ */
74 struct path
*pcep_new_path(void)
77 path
= XCALLOC(MTYPE_PCEP
, sizeof(*path
));
78 path
->binding_sid
= MPLS_LABEL_NONE
;
79 path
->enforce_bandwidth
= true;
83 struct path_hop
*pcep_new_hop(void)
86 hop
= XCALLOC(MTYPE_PCEP
, sizeof(*hop
));
90 struct path_metric
*pcep_new_metric(void)
92 struct path_metric
*metric
;
93 metric
= XCALLOC(MTYPE_PCEP
, sizeof(*metric
));
97 struct path_metric
*pcep_copy_metrics(struct path_metric
*metric
)
101 struct path_metric
*new_metric
= pcep_new_metric();
102 *new_metric
= *metric
;
103 new_metric
->next
= pcep_copy_metrics(metric
->next
);
107 struct path_hop
*pcep_copy_hops(struct path_hop
*hop
)
111 struct path_hop
*new_hop
= pcep_new_hop();
113 new_hop
->next
= pcep_copy_hops(hop
->next
);
117 struct path
*pcep_copy_path(struct path
*path
)
119 struct path
*new_path
= pcep_new_path();
122 new_path
->first_metric
= pcep_copy_metrics(path
->first_metric
);
123 new_path
->first_hop
= pcep_copy_hops(path
->first_hop
);
124 if (path
->name
!= NULL
)
125 new_path
->name
= XSTRDUP(MTYPE_PCEP
, path
->name
);
126 if (path
->originator
!= NULL
)
127 new_path
->originator
= XSTRDUP(MTYPE_PCEP
, path
->originator
);
131 void pcep_free_path(struct path
*path
)
133 struct path_hop
*hop
;
134 struct path_metric
*metric
;
137 metric
= path
->first_metric
;
138 while (metric
!= NULL
) {
139 struct path_metric
*next
= metric
->next
;
140 XFREE(MTYPE_PCEP
, metric
);
143 hop
= path
->first_hop
;
144 while (hop
!= NULL
) {
145 struct path_hop
*next
= hop
->next
;
146 XFREE(MTYPE_PCEP
, hop
);
149 if (path
->originator
!= NULL
) {
150 /* The path own the memory, it is const so it is clear it
151 shouldn't be modified. XFREE macro do not support type casting
152 so we need a temporary variable */
153 tmp
= (char *)path
->originator
;
154 XFREE(MTYPE_PCEP
, tmp
);
155 path
->originator
= NULL
;
157 if (path
->name
!= NULL
) {
158 /* The path own the memory, it is const so it is clear it
159 shouldn't be modified. XFREE macro do not support type casting
160 so we need a temporary variable */
161 tmp
= (char *)path
->name
;
162 XFREE(MTYPE_PCEP
, tmp
);
165 XFREE(MTYPE_PCEP
, path
);
169 /* ------------ Main Thread Even Handler ------------ */
171 int pcep_main_event_handler(enum pcep_main_event_type type
, int pcc_id
,
177 case PCEP_MAIN_EVENT_START_SYNC
:
178 ret
= pcep_main_event_start_sync(pcc_id
);
180 case PCEP_MAIN_EVENT_UPDATE_CANDIDATE
:
181 assert(payload
!= NULL
);
182 ret
= pcep_main_event_update_candidate((struct path
*)payload
);
184 case PCEP_MAIN_EVENT_REMOVE_CANDIDATE_LSP
:
185 ret
= pcep_main_event_remove_candidate_segments(
186 (const char *)payload
, true);
189 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR
,
190 "Unexpected event received in the main thread: %u",
198 int pcep_main_event_start_sync(int pcc_id
)
200 path_pcep_config_list_path(pcep_main_event_start_sync_cb
, &pcc_id
);
201 pcep_ctrl_sync_done(pcep_g
->fpt
, pcc_id
);
205 int pcep_main_event_start_sync_cb(struct path
*path
, void *arg
)
207 int *pcc_id
= (int *)arg
;
208 pcep_ctrl_sync_path(pcep_g
->fpt
, *pcc_id
, path
);
212 int pcep_main_event_update_candidate(struct path
*path
)
214 struct path
*resp
= NULL
;
217 ret
= path_pcep_config_update_path(path
);
218 if (ret
!= PATH_NB_ERR
&& path
->srp_id
!= 0) {
219 if ((resp
= path_pcep_config_get_path(&path
->nbkey
))) {
220 resp
->srp_id
= path
->srp_id
;
221 pcep_ctrl_send_report(pcep_g
->fpt
, path
->pcc_id
, resp
,
222 ret
== PATH_NB_NO_CHANGE
);
228 int pcep_main_event_remove_candidate_segments(const char *originator
,
231 srte_candidate_unset_segment_list(originator
, force
);
232 /* Avoid compiler warnings about const char* */
233 void *free_ptr
= (void *)originator
;
234 XFREE(MTYPE_PCEP
, free_ptr
);
236 srte_apply_changes();
241 /* ------------ Hook Handlers Functions Called From Main Thread ------------ */
243 int pathd_candidate_created_handler(struct srte_candidate
*candidate
)
245 struct path
*path
= candidate_to_path(candidate
);
246 int ret
= pcep_ctrl_pathd_event(pcep_g
->fpt
, PCEP_PATH_CREATED
, path
);
250 int pathd_candidate_updated_handler(struct srte_candidate
*candidate
)
252 struct path
*path
= candidate_to_path(candidate
);
253 int ret
= pcep_ctrl_pathd_event(pcep_g
->fpt
, PCEP_PATH_UPDATED
, path
);
257 int pathd_candidate_removed_handler(struct srte_candidate
*candidate
)
259 struct path
*path
= candidate_to_path(candidate
);
260 int ret
= pcep_ctrl_pathd_event(pcep_g
->fpt
, PCEP_PATH_REMOVED
, path
);
265 /* ------------ Module Functions ------------ */
267 int pcep_module_late_init(struct thread_master
*tm
)
269 assert(pcep_g
->fpt
== NULL
);
270 assert(pcep_g
->master
== NULL
);
272 struct frr_pthread
*fpt
;
274 if (pcep_ctrl_initialize(tm
, &fpt
, pcep_main_event_handler
))
277 if (pcep_lib_initialize(fpt
))
283 hook_register(pathd_candidate_created
, pathd_candidate_created_handler
);
284 hook_register(pathd_candidate_updated
, pathd_candidate_updated_handler
);
285 hook_register(pathd_candidate_removed
, pathd_candidate_removed_handler
);
287 hook_register(frr_fini
, pcep_module_finish
);
294 int pcep_module_finish(void)
296 pcep_ctrl_finalize(&pcep_g
->fpt
);
299 for (int i
= 0; i
< MAX_PCC
; i
++)
300 if (pcep_g
->pce_opts_cli
[i
] != NULL
)
301 XFREE(MTYPE_PCEP
, pcep_g
->pce_opts_cli
[i
]);
306 int pcep_module_init(void)
308 pcep_g
->num_pce_opts_cli
= 0;
309 for (int i
= 0; i
< MAX_PCE
; i
++)
310 pcep_g
->pce_opts_cli
[i
] = NULL
;
311 pcep_g
->num_config_group_opts
= 0;
312 for (int i
= 0; i
< MAX_PCE
; i
++)
313 pcep_g
->config_group_opts
[i
] = NULL
;
315 hook_register(frr_late_init
, pcep_module_late_init
);
319 FRR_MODULE_SETUP(.name
= "frr_pathd_pcep", .version
= FRR_VERSION
,
320 .description
= "FRR pathd PCEP module",
321 .init
= pcep_module_init
,