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