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"
27 #include "northbound.h"
28 #include "frr_pthread.h"
30 #include "termtable.h"
32 #include "pathd/pathd.h"
33 #include "pathd/path_errors.h"
34 #include "pathd/path_pcep_memory.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"
45 static struct pcep_glob pcep_glob_space
= {.dbg
= {0, "pathd module: pcep"}};
46 struct pcep_glob
*pcep_g
= &pcep_glob_space
;
48 /* Main Thread Even Handler */
49 static int pcep_main_event_handler(enum pcep_main_event_type type
, int pcc_id
,
51 static int pcep_main_event_start_sync(int pcc_id
);
52 static int pcep_main_event_start_sync_cb(struct path
*path
, void *arg
);
53 static int pcep_main_event_update_candidate(struct path
*path
);
54 static int pcep_main_event_remove_candidate_segments(const char *originator
,
57 /* Hook Handlers called from the Main Thread */
58 static int pathd_candidate_created_handler(struct srte_candidate
*candidate
);
59 static int pathd_candidate_updated_handler(struct srte_candidate
*candidate
);
60 static int pathd_candidate_removed_handler(struct srte_candidate
*candidate
);
62 /* Path manipulation functions */
63 static struct path_metric
*pcep_copy_metrics(struct path_metric
*metric
);
64 static struct path_hop
*pcep_copy_hops(struct path_hop
*hop
);
66 /* Module Functions */
67 static int pcep_module_finish(void);
68 static int pcep_module_late_init(struct thread_master
*tm
);
69 static int pcep_module_init(void);
71 /* ------------ Path Helper Functions ------------ */
73 struct path
*pcep_new_path(void)
76 path
= XCALLOC(MTYPE_PCEP
, sizeof(*path
));
77 path
->binding_sid
= MPLS_LABEL_NONE
;
78 path
->enforce_bandwidth
= true;
82 struct path_hop
*pcep_new_hop(void)
85 hop
= XCALLOC(MTYPE_PCEP
, sizeof(*hop
));
89 struct path_metric
*pcep_new_metric(void)
91 struct path_metric
*metric
;
92 metric
= XCALLOC(MTYPE_PCEP
, sizeof(*metric
));
96 struct path_metric
*pcep_copy_metrics(struct path_metric
*metric
)
100 struct path_metric
*new_metric
= pcep_new_metric();
101 *new_metric
= *metric
;
102 new_metric
->next
= pcep_copy_metrics(metric
->next
);
106 struct path_hop
*pcep_copy_hops(struct path_hop
*hop
)
110 struct path_hop
*new_hop
= pcep_new_hop();
112 new_hop
->next
= pcep_copy_hops(hop
->next
);
116 struct path
*pcep_copy_path(struct path
*path
)
118 struct path
*new_path
= pcep_new_path();
121 new_path
->first_metric
= pcep_copy_metrics(path
->first_metric
);
122 new_path
->first_hop
= pcep_copy_hops(path
->first_hop
);
123 if (path
->name
!= NULL
)
124 new_path
->name
= XSTRDUP(MTYPE_PCEP
, path
->name
);
125 if (path
->originator
!= NULL
)
126 new_path
->originator
= XSTRDUP(MTYPE_PCEP
, path
->originator
);
130 void pcep_free_path(struct path
*path
)
132 struct path_hop
*hop
;
133 struct path_metric
*metric
;
136 metric
= path
->first_metric
;
137 while (metric
!= NULL
) {
138 struct path_metric
*next
= metric
->next
;
139 XFREE(MTYPE_PCEP
, metric
);
142 hop
= path
->first_hop
;
143 while (hop
!= NULL
) {
144 struct path_hop
*next
= hop
->next
;
145 XFREE(MTYPE_PCEP
, hop
);
148 if (path
->originator
!= NULL
) {
149 /* The path own the memory, it is const so it is clear it
150 shouldn't be modified. XFREE macro do not support type casting
151 so we need a temporary variable */
152 tmp
= (char *)path
->originator
;
153 XFREE(MTYPE_PCEP
, tmp
);
154 path
->originator
= NULL
;
156 if (path
->name
!= NULL
) {
157 /* The path own the memory, it is const so it is clear it
158 shouldn't be modified. XFREE macro do not support type casting
159 so we need a temporary variable */
160 tmp
= (char *)path
->name
;
161 XFREE(MTYPE_PCEP
, tmp
);
164 XFREE(MTYPE_PCEP
, path
);
168 /* ------------ Main Thread Even Handler ------------ */
170 int pcep_main_event_handler(enum pcep_main_event_type type
, int pcc_id
,
176 case PCEP_MAIN_EVENT_START_SYNC
:
177 ret
= pcep_main_event_start_sync(pcc_id
);
179 case PCEP_MAIN_EVENT_UPDATE_CANDIDATE
:
180 assert(payload
!= NULL
);
181 ret
= pcep_main_event_update_candidate((struct path
*)payload
);
183 case PCEP_MAIN_EVENT_REMOVE_CANDIDATE_LSP
:
184 ret
= pcep_main_event_remove_candidate_segments(
185 (const char *)payload
, true);
188 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR
,
189 "Unexpected event received in the main thread: %u",
197 int pcep_main_event_start_sync(int pcc_id
)
199 path_pcep_config_list_path(pcep_main_event_start_sync_cb
, &pcc_id
);
200 pcep_ctrl_sync_done(pcep_g
->fpt
, pcc_id
);
204 int pcep_main_event_start_sync_cb(struct path
*path
, void *arg
)
206 int *pcc_id
= (int *)arg
;
207 pcep_ctrl_sync_path(pcep_g
->fpt
, *pcc_id
, path
);
211 int pcep_main_event_update_candidate(struct path
*path
)
213 struct path
*resp
= NULL
;
216 ret
= path_pcep_config_update_path(path
);
217 if (ret
!= PATH_NB_ERR
&& path
->srp_id
!= 0) {
218 if ((resp
= path_pcep_config_get_path(&path
->nbkey
))) {
219 resp
->srp_id
= path
->srp_id
;
220 pcep_ctrl_send_report(pcep_g
->fpt
, path
->pcc_id
, resp
,
221 ret
== PATH_NB_NO_CHANGE
);
227 int pcep_main_event_remove_candidate_segments(const char *originator
,
230 srte_candidate_unset_segment_list(originator
, force
);
231 /* Avoid compiler warnings about const char* */
232 void *free_ptr
= (void *)originator
;
233 XFREE(MTYPE_PCEP
, free_ptr
);
235 srte_apply_changes();
240 /* ------------ Hook Handlers Functions Called From Main Thread ------------ */
242 int pathd_candidate_created_handler(struct srte_candidate
*candidate
)
244 struct path
*path
= candidate_to_path(candidate
);
245 int ret
= pcep_ctrl_pathd_event(pcep_g
->fpt
, PCEP_PATH_CREATED
, path
);
249 int pathd_candidate_updated_handler(struct srte_candidate
*candidate
)
251 struct path
*path
= candidate_to_path(candidate
);
252 int ret
= pcep_ctrl_pathd_event(pcep_g
->fpt
, PCEP_PATH_UPDATED
, path
);
256 int pathd_candidate_removed_handler(struct srte_candidate
*candidate
)
258 struct path
*path
= candidate_to_path(candidate
);
259 int ret
= pcep_ctrl_pathd_event(pcep_g
->fpt
, PCEP_PATH_REMOVED
, path
);
264 /* ------------ Module Functions ------------ */
266 int pcep_module_late_init(struct thread_master
*tm
)
268 assert(pcep_g
->fpt
== NULL
);
269 assert(pcep_g
->master
== NULL
);
271 struct frr_pthread
*fpt
;
273 if (pcep_ctrl_initialize(tm
, &fpt
, pcep_main_event_handler
))
276 if (pcep_lib_initialize(fpt
))
282 hook_register(pathd_candidate_created
, pathd_candidate_created_handler
);
283 hook_register(pathd_candidate_updated
, pathd_candidate_updated_handler
);
284 hook_register(pathd_candidate_removed
, pathd_candidate_removed_handler
);
286 hook_register(frr_fini
, pcep_module_finish
);
293 int pcep_module_finish(void)
295 pcep_ctrl_finalize(&pcep_g
->fpt
);
298 for (int i
= 0; i
< MAX_PCC
; i
++)
299 if (pcep_g
->pce_opts_cli
[i
] != NULL
)
300 XFREE(MTYPE_PCEP
, pcep_g
->pce_opts_cli
[i
]);
305 int pcep_module_init(void)
307 pcep_g
->num_pce_opts_cli
= 0;
308 for (int i
= 0; i
< MAX_PCE
; i
++)
309 pcep_g
->pce_opts_cli
[i
] = NULL
;
310 pcep_g
->num_config_group_opts
= 0;
311 for (int i
= 0; i
< MAX_PCE
; i
++)
312 pcep_g
->config_group_opts
[i
] = NULL
;
314 hook_register(frr_late_init
, pcep_module_late_init
);
318 FRR_MODULE_SETUP(.name
= "frr_pathd_pcep", .version
= FRR_VERSION
,
319 .description
= "FRR pathd PCEP module",
320 .init
= pcep_module_init
)