]> git.proxmox.com Git - mirror_frr.git/blob - pathd/path_pcep.c
Merge pull request #8121 from opensourcerouting/macro-cleanup
[mirror_frr.git] / pathd / path_pcep.c
1 /*
2 * Copyright (C) 2020 NetDEF, Inc.
3 *
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)
7 * any later version.
8 *
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
12 * more details.
13 *
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
17 */
18
19 #include <zebra.h>
20 #include "pceplib/pcep_utils_counters.h"
21
22 #include "log.h"
23 #include "command.h"
24 #include "libfrr.h"
25 #include "printfrr.h"
26 #include "version.h"
27 #include "northbound.h"
28 #include "frr_pthread.h"
29 #include "jhash.h"
30 #include "termtable.h"
31
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"
40
41
42 /*
43 * Globals.
44 */
45 static struct pcep_glob pcep_glob_space = {.dbg = {0, "pathd module: pcep"}};
46 struct pcep_glob *pcep_g = &pcep_glob_space;
47
48 /* Main Thread Even Handler */
49 static int pcep_main_event_handler(enum pcep_main_event_type type, int pcc_id,
50 void *payload);
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,
55 bool force);
56
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);
61
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);
65
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);
70
71 /* ------------ Path Helper Functions ------------ */
72
73 struct path *pcep_new_path(void)
74 {
75 struct path *path;
76 path = XCALLOC(MTYPE_PCEP, sizeof(*path));
77 path->binding_sid = MPLS_LABEL_NONE;
78 path->enforce_bandwidth = true;
79 return path;
80 }
81
82 struct path_hop *pcep_new_hop(void)
83 {
84 struct path_hop *hop;
85 hop = XCALLOC(MTYPE_PCEP, sizeof(*hop));
86 return hop;
87 }
88
89 struct path_metric *pcep_new_metric(void)
90 {
91 struct path_metric *metric;
92 metric = XCALLOC(MTYPE_PCEP, sizeof(*metric));
93 return metric;
94 }
95
96 struct path_metric *pcep_copy_metrics(struct path_metric *metric)
97 {
98 if (metric == NULL)
99 return NULL;
100 struct path_metric *new_metric = pcep_new_metric();
101 *new_metric = *metric;
102 new_metric->next = pcep_copy_metrics(metric->next);
103 return new_metric;
104 }
105
106 struct path_hop *pcep_copy_hops(struct path_hop *hop)
107 {
108 if (hop == NULL)
109 return NULL;
110 struct path_hop *new_hop = pcep_new_hop();
111 *new_hop = *hop;
112 new_hop->next = pcep_copy_hops(hop->next);
113 return new_hop;
114 }
115
116 struct path *pcep_copy_path(struct path *path)
117 {
118 struct path *new_path = pcep_new_path();
119
120 *new_path = *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);
127 return new_path;
128 }
129
130 void pcep_free_path(struct path *path)
131 {
132 struct path_hop *hop;
133 struct path_metric *metric;
134 char *tmp;
135
136 metric = path->first_metric;
137 while (metric != NULL) {
138 struct path_metric *next = metric->next;
139 XFREE(MTYPE_PCEP, metric);
140 metric = next;
141 }
142 hop = path->first_hop;
143 while (hop != NULL) {
144 struct path_hop *next = hop->next;
145 XFREE(MTYPE_PCEP, hop);
146 hop = next;
147 }
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;
155 }
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);
162 path->name = NULL;
163 }
164 XFREE(MTYPE_PCEP, path);
165 }
166
167
168 /* ------------ Main Thread Even Handler ------------ */
169
170 int pcep_main_event_handler(enum pcep_main_event_type type, int pcc_id,
171 void *payload)
172 {
173 int ret = 0;
174
175 switch (type) {
176 case PCEP_MAIN_EVENT_START_SYNC:
177 ret = pcep_main_event_start_sync(pcc_id);
178 break;
179 case PCEP_MAIN_EVENT_UPDATE_CANDIDATE:
180 assert(payload != NULL);
181 ret = pcep_main_event_update_candidate((struct path *)payload);
182 break;
183 case PCEP_MAIN_EVENT_REMOVE_CANDIDATE_LSP:
184 ret = pcep_main_event_remove_candidate_segments(
185 (const char *)payload, true);
186 break;
187 default:
188 flog_warn(EC_PATH_PCEP_RECOVERABLE_INTERNAL_ERROR,
189 "Unexpected event received in the main thread: %u",
190 type);
191 break;
192 }
193
194 return ret;
195 }
196
197 int pcep_main_event_start_sync(int pcc_id)
198 {
199 path_pcep_config_list_path(pcep_main_event_start_sync_cb, &pcc_id);
200 pcep_ctrl_sync_done(pcep_g->fpt, pcc_id);
201 return 0;
202 }
203
204 int pcep_main_event_start_sync_cb(struct path *path, void *arg)
205 {
206 int *pcc_id = (int *)arg;
207 pcep_ctrl_sync_path(pcep_g->fpt, *pcc_id, path);
208 return 1;
209 }
210
211 int pcep_main_event_update_candidate(struct path *path)
212 {
213 struct path *resp = NULL;
214 int ret = 0;
215
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);
222 }
223 }
224 return ret;
225 }
226
227 int pcep_main_event_remove_candidate_segments(const char *originator,
228 bool force)
229 {
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);
234
235 srte_apply_changes();
236
237 return 0;
238 }
239
240 /* ------------ Hook Handlers Functions Called From Main Thread ------------ */
241
242 int pathd_candidate_created_handler(struct srte_candidate *candidate)
243 {
244 struct path *path = candidate_to_path(candidate);
245 int ret = pcep_ctrl_pathd_event(pcep_g->fpt, PCEP_PATH_CREATED, path);
246 return ret;
247 }
248
249 int pathd_candidate_updated_handler(struct srte_candidate *candidate)
250 {
251 struct path *path = candidate_to_path(candidate);
252 int ret = pcep_ctrl_pathd_event(pcep_g->fpt, PCEP_PATH_UPDATED, path);
253 return ret;
254 }
255
256 int pathd_candidate_removed_handler(struct srte_candidate *candidate)
257 {
258 struct path *path = candidate_to_path(candidate);
259 int ret = pcep_ctrl_pathd_event(pcep_g->fpt, PCEP_PATH_REMOVED, path);
260 return ret;
261 }
262
263
264 /* ------------ Module Functions ------------ */
265
266 int pcep_module_late_init(struct thread_master *tm)
267 {
268 assert(pcep_g->fpt == NULL);
269 assert(pcep_g->master == NULL);
270
271 struct frr_pthread *fpt;
272
273 if (pcep_ctrl_initialize(tm, &fpt, pcep_main_event_handler))
274 return 1;
275
276 if (pcep_lib_initialize(fpt))
277 return 1;
278
279 pcep_g->master = tm;
280 pcep_g->fpt = fpt;
281
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);
285
286 hook_register(frr_fini, pcep_module_finish);
287
288 pcep_cli_init();
289
290 return 0;
291 }
292
293 int pcep_module_finish(void)
294 {
295 pcep_ctrl_finalize(&pcep_g->fpt);
296 pcep_lib_finalize();
297
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]);
301
302 return 0;
303 }
304
305 int pcep_module_init(void)
306 {
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;
313
314 hook_register(frr_late_init, pcep_module_late_init);
315 return 0;
316 }
317
318 FRR_MODULE_SETUP(.name = "frr_pathd_pcep", .version = FRR_VERSION,
319 .description = "FRR pathd PCEP module",
320 .init = pcep_module_init,
321 );