]> git.proxmox.com Git - mirror_frr.git/blob - pathd/path_pcep_cli.c
Merge pull request #9455 from LabNConsulting/chopps/fix-zebtest-fixed-sleep
[mirror_frr.git] / pathd / path_pcep_cli.c
1 /*
2 * Copyright (C) 2020 Volta Networks, Inc
3 * Brady Johnson
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include <zebra.h>
21 #include "pceplib/pcep_utils_counters.h"
22 #include "pceplib/pcep_session_logic.h"
23
24 #include "log.h"
25 #include "command.h"
26 #include "libfrr.h"
27 #include "printfrr.h"
28 #include "lib/version.h"
29 #include "northbound.h"
30 #include "frr_pthread.h"
31 #include "jhash.h"
32 #include "termtable.h"
33
34 #include "pathd/pathd.h"
35 #include "pathd/path_errors.h"
36 #include "pathd/path_pcep.h"
37 #include "pathd/path_pcep_cli.h"
38 #include "pathd/path_pcep_controller.h"
39 #include "pathd/path_pcep_debug.h"
40 #include "pathd/path_pcep_lib.h"
41 #include "pathd/path_pcep_pcc.h"
42
43 #ifndef VTYSH_EXTRACT_PL
44 #include "pathd/path_pcep_cli_clippy.c"
45 #endif
46
47 #define DEFAULT_PCE_PRECEDENCE 255
48 #define DEFAULT_PCC_MSD 4
49 #define DEFAULT_SR_DRAFT07 false
50 #define DEFAULT_PCE_INITIATED false
51 #define DEFAULT_TIMER_KEEP_ALIVE 30
52 #define DEFAULT_TIMER_KEEP_ALIVE_MIN 1
53 #define DEFAULT_TIMER_KEEP_ALIVE_MAX 255
54 #define DEFAULT_TIMER_DEADTIMER 120
55 #define DEFAULT_TIMER_DEADTIMER_MIN 4
56 #define DEFAULT_TIMER_DEADTIMER_MAX 255
57 #define DEFAULT_TIMER_PCEP_REQUEST 30
58 #define DEFAULT_TIMER_SESSION_TIMEOUT_INTERVAL 30
59 #define DEFAULT_DELEGATION_TIMEOUT_INTERVAL 10
60
61 /* CLI Function declarations */
62 static int pcep_cli_debug_config_write(struct vty *vty);
63 static int pcep_cli_debug_set_all(uint32_t flags, bool set);
64 static int pcep_cli_pcep_config_write(struct vty *vty);
65 static int pcep_cli_pcc_config_write(struct vty *vty);
66 static int pcep_cli_pce_config_write(struct vty *vty);
67 static int pcep_cli_pcep_pce_config_write(struct vty *vty);
68
69 /* Internal Util Function declarations */
70 static struct pce_opts_cli *pcep_cli_find_pce(const char *pce_name);
71 static bool pcep_cli_add_pce(struct pce_opts_cli *pce_opts_cli);
72 static struct pce_opts_cli *pcep_cli_create_pce_opts();
73 static void pcep_cli_delete_pce(const char *pce_name);
74 static void
75 pcep_cli_merge_pcep_pce_config_options(struct pce_opts_cli *pce_opts_cli);
76 static struct pcep_config_group_opts *
77 pcep_cli_find_pcep_pce_config(const char *group_name);
78 static bool
79 pcep_cli_add_pcep_pce_config(struct pcep_config_group_opts *config_group_opts);
80 static struct pcep_config_group_opts *
81 pcep_cli_create_pcep_pce_config(const char *group_name);
82 static bool pcep_cli_is_pcep_pce_config_used(const char *group_name);
83 static void pcep_cli_delete_pcep_pce_config(const char *group_name);
84 static int pcep_cli_print_pce_config(struct pcep_config_group_opts *group_opts,
85 char *buf, size_t buf_len);
86 static void print_pcep_capabilities(char *buf, size_t buf_len,
87 pcep_configuration *config);
88 static void print_pcep_session(struct vty *vty, struct pce_opts *pce_opts,
89 struct pcep_pcc_info *pcc_info);
90 static bool pcep_cli_pcc_has_pce(const char *pce_name);
91 static void pcep_cli_add_pce_connection(struct pce_opts *pce_opts);
92 static void pcep_cli_remove_pce_connection(struct pce_opts *pce_opts);
93 static int path_pcep_cli_pcc_pcc_peer_delete(struct vty *vty,
94 const char *peer_name,
95 const char *precedence_str,
96 long precedence);
97
98 /*
99 * Globals.
100 */
101
102 static const char PCEP_VTYSH_ARG_ADDRESS[] = "address";
103 static const char PCEP_VTYSH_ARG_SOURCE_ADDRESS[] = "source-address";
104 static const char PCEP_VTYSH_ARG_IP[] = "ip";
105 static const char PCEP_VTYSH_ARG_IPV6[] = "ipv6";
106 static const char PCEP_VTYSH_ARG_PORT[] = "port";
107 static const char PCEP_VTYSH_ARG_PRECEDENCE[] = "precedence";
108 static const char PCEP_VTYSH_ARG_MSD[] = "msd";
109 static const char PCEP_VTYSH_ARG_KEEP_ALIVE[] = "keep-alive";
110 static const char PCEP_VTYSH_ARG_TIMER[] = "timer";
111 static const char PCEP_VTYSH_ARG_KEEP_ALIVE_MIN[] = "min-peer-keep-alive";
112 static const char PCEP_VTYSH_ARG_KEEP_ALIVE_MAX[] = "max-peer-keep-alive";
113 static const char PCEP_VTYSH_ARG_DEAD_TIMER[] = "dead-timer";
114 static const char PCEP_VTYSH_ARG_DEAD_TIMER_MIN[] = "min-peer-dead-timer";
115 static const char PCEP_VTYSH_ARG_DEAD_TIMER_MAX[] = "max-peer-dead-timer";
116 static const char PCEP_VTYSH_ARG_PCEP_REQUEST[] = "pcep-request";
117 static const char PCEP_VTYSH_ARG_SESSION_TIMEOUT[] = "session-timeout-interval";
118 static const char PCEP_VTYSH_ARG_DELEGATION_TIMEOUT[] = "delegation-timeout";
119 static const char PCEP_VTYSH_ARG_SR_DRAFT07[] = "sr-draft07";
120 static const char PCEP_VTYSH_ARG_PCE_INIT[] = "pce-initiated";
121 static const char PCEP_VTYSH_ARG_TCP_MD5[] = "tcp-md5-auth";
122 static const char PCEP_VTYSH_ARG_BASIC[] = "basic";
123 static const char PCEP_VTYSH_ARG_PATH[] = "path";
124 static const char PCEP_VTYSH_ARG_MESSAGE[] = "message";
125 static const char PCEP_VTYSH_ARG_PCEPLIB[] = "pceplib";
126 static const char PCEP_CLI_CAP_STATEFUL[] = " [Stateful PCE]";
127 static const char PCEP_CLI_CAP_INCL_DB_VER[] = " [Include DB version]";
128 static const char PCEP_CLI_CAP_LSP_TRIGGERED[] = " [LSP Triggered Resync]";
129 static const char PCEP_CLI_CAP_LSP_DELTA[] = " [LSP Delta Sync]";
130 static const char PCEP_CLI_CAP_PCE_TRIGGERED[] =
131 " [PCE triggered Initial Sync]";
132 static const char PCEP_CLI_CAP_SR_TE_PST[] = " [SR TE PST]";
133 static const char PCEP_CLI_CAP_PCC_RESOLVE_NAI[] =
134 " [PCC can resolve NAI to SID]";
135 static const char PCEP_CLI_CAP_PCC_INITIATED[] = " [PCC Initiated LSPs]";
136 static const char PCEP_CLI_CAP_PCC_PCE_INITIATED[] =
137 " [PCC and PCE Initiated LSPs]";
138
139 struct pce_connections {
140 int num_connections;
141 struct pce_opts *connections[MAX_PCC];
142 };
143
144 struct pce_connections pce_connections_g = {.num_connections = 0};
145
146 /* Default PCE group that all PCE-Groups and PCEs will inherit from */
147 struct pcep_config_group_opts default_pcep_config_group_opts_g = {
148 .name = "default",
149 .tcp_md5_auth = "\0",
150 .draft07 = DEFAULT_SR_DRAFT07,
151 .pce_initiated = DEFAULT_PCE_INITIATED,
152 .keep_alive_seconds = DEFAULT_TIMER_KEEP_ALIVE,
153 .min_keep_alive_seconds = DEFAULT_TIMER_KEEP_ALIVE_MIN,
154 .max_keep_alive_seconds = DEFAULT_TIMER_KEEP_ALIVE_MAX,
155 .dead_timer_seconds = DEFAULT_TIMER_DEADTIMER,
156 .min_dead_timer_seconds = DEFAULT_TIMER_DEADTIMER_MIN,
157 .max_dead_timer_seconds = DEFAULT_TIMER_DEADTIMER_MAX,
158 .pcep_request_time_seconds = DEFAULT_TIMER_PCEP_REQUEST,
159 .session_timeout_inteval_seconds =
160 DEFAULT_TIMER_SESSION_TIMEOUT_INTERVAL,
161 .delegation_timeout_seconds = DEFAULT_DELEGATION_TIMEOUT_INTERVAL,
162 .source_port = DEFAULT_PCEP_TCP_PORT,
163 .source_ip.ipa_type = IPADDR_NONE,
164 };
165
166 /* Used by PCEP_PCE_CONFIG_NODE sub-commands to operate on the current pce group
167 */
168 struct pcep_config_group_opts *current_pcep_config_group_opts_g = NULL;
169 /* Used by PCEP_PCE_NODE sub-commands to operate on the current pce opts */
170 struct pce_opts_cli *current_pce_opts_g = NULL;
171 short pcc_msd_g = DEFAULT_PCC_MSD;
172 bool pcc_msd_configured_g = false;
173
174 static struct cmd_node pcep_node = {
175 .name = "srte pcep",
176 .node = PCEP_NODE,
177 .parent_node = SR_TRAFFIC_ENG_NODE,
178 .config_write = pcep_cli_pcep_config_write,
179 .prompt = "%s(config-sr-te-pcep)# "
180 };
181
182 static struct cmd_node pcep_pcc_node = {
183 .name = "srte pcep pcc",
184 .node = PCEP_PCC_NODE,
185 .parent_node = PCEP_NODE,
186 .config_write = pcep_cli_pcc_config_write,
187 .prompt = "%s(config-sr-te-pcep-pcc)# "
188 };
189
190 static struct cmd_node pcep_pce_node = {
191 .name = "srte pcep pce",
192 .node = PCEP_PCE_NODE,
193 .parent_node = PCEP_NODE,
194 .config_write = pcep_cli_pce_config_write,
195 .prompt = "%s(config-sr-te-pcep-pce)# "
196 };
197
198 static struct cmd_node pcep_pce_config_node = {
199 .name = "srte pcep pce-config",
200 .node = PCEP_PCE_CONFIG_NODE,
201 .parent_node = PCEP_NODE,
202 .config_write = pcep_cli_pcep_pce_config_write,
203 .prompt = "%s(pce-sr-te-pcep-pce-config)# "
204 };
205
206 /* Common code used in VTYSH processing for int values */
207 #define PCEP_VTYSH_INT_ARG_CHECK(arg_str, arg_val, arg_store, min_value, \
208 max_value) \
209 if (arg_str != NULL) { \
210 if (arg_val <= min_value || arg_val >= max_value) { \
211 vty_out(vty, \
212 "%% Invalid value %ld in range [%d - %d]", \
213 arg_val, min_value, max_value); \
214 return CMD_WARNING; \
215 } \
216 arg_store = arg_val; \
217 }
218
219 #define MERGE_COMPARE_CONFIG_GROUP_VALUE(config_param, not_set_value) \
220 pce_opts_cli->pce_opts.config_opts.config_param = \
221 pce_opts_cli->pce_config_group_opts.config_param; \
222 if (pce_opts_cli->pce_config_group_opts.config_param \
223 == not_set_value) { \
224 pce_opts_cli->pce_opts.config_opts.config_param = \
225 ((pce_config != NULL \
226 && pce_config->config_param != not_set_value) \
227 ? pce_config->config_param \
228 : default_pcep_config_group_opts_g \
229 .config_param); \
230 }
231
232 /*
233 * Internal Util functions
234 */
235
236 /* Check if a pce_opts_cli already exists based on its name and return it,
237 * return NULL otherwise */
238 static struct pce_opts_cli *pcep_cli_find_pce(const char *pce_name)
239 {
240 for (int i = 0; i < MAX_PCE; i++) {
241 struct pce_opts_cli *pce_rhs_cli = pcep_g->pce_opts_cli[i];
242 if (pce_rhs_cli != NULL) {
243 if (strcmp(pce_name, pce_rhs_cli->pce_opts.pce_name)
244 == 0) {
245 return pce_rhs_cli;
246 }
247 }
248 }
249
250 return NULL;
251 }
252
253 /* Add a new pce_opts_cli to pcep_g, return false if MAX_PCES, true otherwise */
254 static bool pcep_cli_add_pce(struct pce_opts_cli *pce_opts_cli)
255 {
256 for (int i = 0; i < MAX_PCE; i++) {
257 if (pcep_g->pce_opts_cli[i] == NULL) {
258 pcep_g->pce_opts_cli[i] = pce_opts_cli;
259 pcep_g->num_pce_opts_cli++;
260 return true;
261 }
262 }
263
264 return false;
265 }
266
267 /* Create a new pce opts_cli */
268 static struct pce_opts_cli *pcep_cli_create_pce_opts(const char *name)
269 {
270 struct pce_opts_cli *pce_opts_cli =
271 XCALLOC(MTYPE_PCEP, sizeof(struct pce_opts_cli));
272 strlcpy(pce_opts_cli->pce_opts.pce_name, name,
273 sizeof(pce_opts_cli->pce_opts.pce_name));
274 pce_opts_cli->pce_opts.port = PCEP_DEFAULT_PORT;
275
276 return pce_opts_cli;
277 }
278
279 static void pcep_cli_delete_pce(const char *pce_name)
280 {
281 for (int i = 0; i < MAX_PCE; i++) {
282 if (pcep_g->pce_opts_cli[i] != NULL) {
283 if (strcmp(pcep_g->pce_opts_cli[i]->pce_opts.pce_name,
284 pce_name)
285 == 0) {
286 XFREE(MTYPE_PCEP, pcep_g->pce_opts_cli[i]);
287 pcep_g->pce_opts_cli[i] = NULL;
288 pcep_g->num_pce_opts_cli--;
289 return;
290 }
291 }
292 }
293 }
294
295 static void
296 pcep_cli_merge_pcep_pce_config_options(struct pce_opts_cli *pce_opts_cli)
297 {
298 if (pce_opts_cli->merged == true) {
299 return;
300 }
301
302 struct pcep_config_group_opts *pce_config =
303 pcep_cli_find_pcep_pce_config(pce_opts_cli->config_group_name);
304
305 /* Configuration priorities:
306 * 1) pce_opts->config_opts, if present, overwrite pce_config
307 * config_opts 2) pce_config config_opts, if present, overwrite
308 * default config_opts 3) If neither pce_opts->config_opts nor
309 * pce_config config_opts are set, then the default config_opts value
310 * will be used.
311 */
312
313 const char *tcp_md5_auth_str =
314 pce_opts_cli->pce_config_group_opts.tcp_md5_auth;
315 if (pce_opts_cli->pce_config_group_opts.tcp_md5_auth[0] == '\0') {
316 if (pce_config != NULL && pce_config->tcp_md5_auth[0] != '\0') {
317 tcp_md5_auth_str = pce_config->tcp_md5_auth;
318 } else {
319 tcp_md5_auth_str =
320 default_pcep_config_group_opts_g.tcp_md5_auth;
321 }
322 }
323 strlcpy(pce_opts_cli->pce_opts.config_opts.tcp_md5_auth,
324 tcp_md5_auth_str,
325 sizeof(pce_opts_cli->pce_opts.config_opts.tcp_md5_auth));
326
327 struct ipaddr *source_ip =
328 &pce_opts_cli->pce_config_group_opts.source_ip;
329 if (pce_opts_cli->pce_config_group_opts.source_ip.ipa_type
330 == IPADDR_NONE) {
331 if (pce_config != NULL
332 && pce_config->source_ip.ipa_type != IPADDR_NONE) {
333 source_ip = &pce_config->source_ip;
334 } else {
335 source_ip = &default_pcep_config_group_opts_g.source_ip;
336 }
337 }
338 memcpy(&pce_opts_cli->pce_opts.config_opts.source_ip, source_ip,
339 sizeof(struct ipaddr));
340
341 MERGE_COMPARE_CONFIG_GROUP_VALUE(draft07, false);
342 MERGE_COMPARE_CONFIG_GROUP_VALUE(pce_initiated, false);
343 MERGE_COMPARE_CONFIG_GROUP_VALUE(keep_alive_seconds, 0);
344 MERGE_COMPARE_CONFIG_GROUP_VALUE(min_keep_alive_seconds, 0);
345 MERGE_COMPARE_CONFIG_GROUP_VALUE(max_keep_alive_seconds, 0);
346 MERGE_COMPARE_CONFIG_GROUP_VALUE(dead_timer_seconds, 0);
347 MERGE_COMPARE_CONFIG_GROUP_VALUE(min_dead_timer_seconds, 0);
348 MERGE_COMPARE_CONFIG_GROUP_VALUE(max_dead_timer_seconds, 0);
349 MERGE_COMPARE_CONFIG_GROUP_VALUE(pcep_request_time_seconds, 0);
350 MERGE_COMPARE_CONFIG_GROUP_VALUE(session_timeout_inteval_seconds, 0);
351 MERGE_COMPARE_CONFIG_GROUP_VALUE(delegation_timeout_seconds, 0);
352 MERGE_COMPARE_CONFIG_GROUP_VALUE(source_port, 0);
353
354 pce_opts_cli->merged = true;
355 }
356
357 /* Check if a pcep_config_group_opts already exists based on its name and return
358 * it, return NULL otherwise */
359 static struct pcep_config_group_opts *
360 pcep_cli_find_pcep_pce_config(const char *group_name)
361 {
362 for (int i = 0; i < MAX_PCE; i++) {
363 struct pcep_config_group_opts *pcep_pce_config_rhs =
364 pcep_g->config_group_opts[i];
365 if (pcep_pce_config_rhs != NULL) {
366 if (strcmp(group_name, pcep_pce_config_rhs->name)
367 == 0) {
368 return pcep_pce_config_rhs;
369 }
370 }
371 }
372
373 return NULL;
374 }
375
376 /* Add a new pcep_config_group_opts to pcep_g, return false if MAX_PCE,
377 * true otherwise */
378 static bool pcep_cli_add_pcep_pce_config(
379 struct pcep_config_group_opts *pcep_config_group_opts)
380 {
381 for (int i = 0; i < MAX_PCE; i++) {
382 if (pcep_g->config_group_opts[i] == NULL) {
383 pcep_g->config_group_opts[i] = pcep_config_group_opts;
384 pcep_g->num_config_group_opts++;
385 return true;
386 }
387 }
388
389 return false;
390 }
391
392 /* Create a new pce group, inheriting its values from the default pce group */
393 static struct pcep_config_group_opts *
394 pcep_cli_create_pcep_pce_config(const char *group_name)
395 {
396 struct pcep_config_group_opts *pcep_config_group_opts =
397 XCALLOC(MTYPE_PCEP, sizeof(struct pcep_config_group_opts));
398 strlcpy(pcep_config_group_opts->name, group_name,
399 sizeof(pcep_config_group_opts->name));
400
401 return pcep_config_group_opts;
402 }
403
404 /* Iterate the pce_opts and return true if the pce-group-name is referenced,
405 * false otherwise. */
406 static bool pcep_cli_is_pcep_pce_config_used(const char *group_name)
407 {
408 for (int i = 0; i < MAX_PCE; i++) {
409 if (pcep_g->pce_opts_cli[i] != NULL) {
410 if (strcmp(pcep_g->pce_opts_cli[i]->config_group_name,
411 group_name)
412 == 0) {
413 return true;
414 }
415 }
416 }
417
418 return false;
419 }
420
421 static void pcep_cli_delete_pcep_pce_config(const char *group_name)
422 {
423 for (int i = 0; i < MAX_PCE; i++) {
424 if (pcep_g->config_group_opts[i] != NULL) {
425 if (strcmp(pcep_g->config_group_opts[i]->name,
426 group_name)
427 == 0) {
428 XFREE(MTYPE_PCEP, pcep_g->config_group_opts[i]);
429 pcep_g->config_group_opts[i] = NULL;
430 pcep_g->num_config_group_opts--;
431 return;
432 }
433 }
434 }
435 }
436
437 static bool pcep_cli_pcc_has_pce(const char *pce_name)
438 {
439 for (int i = 0; i < MAX_PCC; i++) {
440 struct pce_opts *pce_opts = pce_connections_g.connections[i];
441 if (pce_opts == NULL) {
442 continue;
443 }
444
445 if (strcmp(pce_opts->pce_name, pce_name) == 0) {
446 return true;
447 }
448 }
449
450 return false;
451 }
452
453 static void pcep_cli_add_pce_connection(struct pce_opts *pce_opts)
454 {
455 for (int i = 0; i < MAX_PCC; i++) {
456 if (pce_connections_g.connections[i] == NULL) {
457 pce_connections_g.num_connections++;
458 pce_connections_g.connections[i] = pce_opts;
459 return;
460 }
461 }
462 }
463
464 static void pcep_cli_remove_pce_connection(struct pce_opts *pce_opts)
465 {
466 for (int i = 0; i < MAX_PCC; i++) {
467 if (pce_connections_g.connections[i] == pce_opts) {
468 pce_connections_g.num_connections--;
469 pce_connections_g.connections[i] = NULL;
470 return;
471 }
472 }
473 }
474
475 /*
476 * VTY command implementations
477 */
478
479 static int path_pcep_cli_debug(struct vty *vty, const char *no_str,
480 const char *basic_str, const char *path_str,
481 const char *message_str, const char *pceplib_str)
482 {
483 uint32_t mode = DEBUG_NODE2MODE(vty->node);
484 bool no = (no_str != NULL);
485
486 DEBUG_MODE_SET(&pcep_g->dbg, mode, !no);
487
488 if (basic_str != NULL) {
489 DEBUG_FLAGS_SET(&pcep_g->dbg, PCEP_DEBUG_MODE_BASIC, !no);
490 }
491 if (path_str != NULL) {
492 DEBUG_FLAGS_SET(&pcep_g->dbg, PCEP_DEBUG_MODE_PATH, !no);
493 }
494 if (message_str != NULL) {
495 DEBUG_FLAGS_SET(&pcep_g->dbg, PCEP_DEBUG_MODE_PCEP, !no);
496 }
497 if (pceplib_str != NULL) {
498 DEBUG_FLAGS_SET(&pcep_g->dbg, PCEP_DEBUG_MODE_PCEPLIB, !no);
499 }
500
501 return CMD_SUCCESS;
502 }
503
504 static int path_pcep_cli_show_srte_pcep_counters(struct vty *vty)
505 {
506 int i, j, row;
507 time_t diff_time;
508 struct tm tm_info;
509 char tm_buffer[26];
510 struct counters_group *group;
511 struct counters_subgroup *subgroup;
512 struct counter *counter;
513 const char *group_name, *empty_string = "";
514 struct ttable *tt;
515 char *table;
516
517 group = pcep_ctrl_get_counters(pcep_g->fpt, 1);
518
519 if (group == NULL) {
520 vty_out(vty, "No counters to display.\n\n");
521 return CMD_SUCCESS;
522 }
523
524 diff_time = time(NULL) - group->start_time;
525 localtime_r(&group->start_time, &tm_info);
526 strftime(tm_buffer, sizeof(tm_buffer), "%Y-%m-%d %H:%M:%S", &tm_info);
527
528 vty_out(vty, "PCEP counters since %s (%uh %um %us):\n", tm_buffer,
529 (uint32_t)(diff_time / 3600), (uint32_t)((diff_time / 60) % 60),
530 (uint32_t)(diff_time % 60));
531
532 /* Prepare table. */
533 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
534 ttable_add_row(tt, "Group|Name|Value");
535 tt->style.cell.rpad = 2;
536 tt->style.corner = '+';
537 ttable_restyle(tt);
538 ttable_rowseps(tt, 0, BOTTOM, true, '-');
539
540 for (row = 0, i = 0; i <= group->num_subgroups; i++) {
541 subgroup = group->subgroups[i];
542 if (subgroup != NULL) {
543 group_name = subgroup->counters_subgroup_name;
544 for (j = 0; j <= subgroup->num_counters; j++) {
545 counter = subgroup->counters[j];
546 if (counter != NULL) {
547 ttable_add_row(tt, "%s|%s|%u",
548 group_name,
549 counter->counter_name,
550 counter->counter_value);
551 row++;
552 group_name = empty_string;
553 }
554 }
555 ttable_rowseps(tt, row, BOTTOM, true, '-');
556 }
557 }
558
559 /* Dump the generated table. */
560 table = ttable_dump(tt, "\n");
561 vty_out(vty, "%s\n", table);
562 XFREE(MTYPE_TMP, table);
563
564 ttable_del(tt);
565
566 pcep_lib_free_counters(group);
567
568 return CMD_SUCCESS;
569 }
570
571 static int path_pcep_cli_pcep_pce_config(struct vty *vty,
572 const char *pcep_pce_config)
573 {
574 struct pcep_config_group_opts *pce_config =
575 pcep_cli_find_pcep_pce_config(pcep_pce_config);
576 if (pce_config == NULL) {
577 pce_config = pcep_cli_create_pcep_pce_config(pcep_pce_config);
578 if (pcep_cli_add_pcep_pce_config(pce_config) == false) {
579 vty_out(vty,
580 "%% Cannot create pce-config, as the Maximum limit of %d pce-config has been reached.\n",
581 MAX_PCE);
582 XFREE(MTYPE_PCEP, pce_config);
583 return CMD_WARNING;
584 }
585 } else {
586 vty_out(vty,
587 "Notice: changes to this pce-config will not affect PCEs already configured with this group\n");
588 }
589
590 current_pcep_config_group_opts_g = pce_config;
591 vty->node = PCEP_PCE_CONFIG_NODE;
592
593 return CMD_SUCCESS;
594 }
595
596 static int path_pcep_cli_pcep_pce_config_delete(struct vty *vty,
597 const char *pcep_pce_config)
598 {
599 struct pcep_config_group_opts *pce_config =
600 pcep_cli_find_pcep_pce_config(pcep_pce_config);
601 if (pce_config == NULL) {
602 vty_out(vty,
603 "%% Cannot delete pce-config, since it does not exist.\n");
604 return CMD_WARNING;
605 }
606
607 if (pcep_cli_is_pcep_pce_config_used(pce_config->name)) {
608 vty_out(vty,
609 "%% Cannot delete pce-config, since it is in use by a peer.\n");
610 return CMD_WARNING;
611 }
612
613 pcep_cli_delete_pcep_pce_config(pce_config->name);
614
615 return CMD_SUCCESS;
616 }
617
618 static int path_pcep_cli_show_srte_pcep_pce_config(struct vty *vty,
619 const char *pcep_pce_config)
620 {
621 char buf[1024] = "";
622
623 /* Only show 1 Peer config group */
624 struct pcep_config_group_opts *group_opts;
625 if (pcep_pce_config != NULL) {
626 if (strcmp(pcep_pce_config, "default") == 0) {
627 group_opts = &default_pcep_config_group_opts_g;
628 } else {
629 group_opts =
630 pcep_cli_find_pcep_pce_config(pcep_pce_config);
631 }
632 if (group_opts == NULL) {
633 vty_out(vty, "%% pce-config [%s] does not exist.\n",
634 pcep_pce_config);
635 return CMD_WARNING;
636 }
637
638 vty_out(vty, "pce-config: %s\n", group_opts->name);
639 pcep_cli_print_pce_config(group_opts, buf, sizeof(buf));
640 vty_out(vty, "%s", buf);
641 return CMD_SUCCESS;
642 }
643
644 /* Show all Peer config groups */
645 for (int i = 0; i < MAX_PCE; i++) {
646 group_opts = pcep_g->config_group_opts[i];
647 if (group_opts == NULL) {
648 continue;
649 }
650
651 vty_out(vty, "pce-config: %s\n", group_opts->name);
652 pcep_cli_print_pce_config(group_opts, buf, sizeof(buf));
653 vty_out(vty, "%s", buf);
654 buf[0] = 0;
655 }
656
657 return CMD_SUCCESS;
658 }
659
660 static int path_pcep_cli_pce(struct vty *vty, const char *pce_peer_name)
661 {
662 /* If it already exists, it will be updated in the sub-commands */
663 struct pce_opts_cli *pce_opts_cli = pcep_cli_find_pce(pce_peer_name);
664 if (pce_opts_cli == NULL) {
665 pce_opts_cli = pcep_cli_create_pce_opts(pce_peer_name);
666
667 if (!pcep_cli_add_pce(pce_opts_cli)) {
668 vty_out(vty,
669 "%% Cannot create PCE, as the Maximum limit of %d PCEs has been reached.\n",
670 MAX_PCE);
671 XFREE(MTYPE_PCEP, pce_opts_cli);
672 return CMD_WARNING;
673 }
674 }
675
676 current_pce_opts_g = pce_opts_cli;
677 vty->node = PCEP_PCE_NODE;
678
679 return CMD_SUCCESS;
680 }
681
682 static int path_pcep_cli_pce_delete(struct vty *vty, const char *pce_peer_name)
683 {
684 struct pce_opts_cli *pce_opts_cli = pcep_cli_find_pce(pce_peer_name);
685 if (pce_opts_cli == NULL) {
686 vty_out(vty, "%% PCC peer does not exist.\n");
687 return CMD_WARNING;
688 }
689
690 /* To better work with frr-reload, go ahead and delete it if its in use
691 */
692 if (pcep_cli_pcc_has_pce(pce_peer_name)) {
693 vty_out(vty,
694 "%% Notice: the pce is in use by a PCC, also disconnecting.\n");
695 path_pcep_cli_pcc_pcc_peer_delete(vty, pce_peer_name, NULL, 0);
696 }
697
698 pcep_cli_delete_pce(pce_peer_name);
699
700 return CMD_SUCCESS;
701 }
702
703 /* Internal Util func to show an individual PCE,
704 * only used by path_pcep_cli_show_srte_pcep_pce() */
705 static void show_pce_peer(struct vty *vty, struct pce_opts_cli *pce_opts_cli)
706 {
707 struct pce_opts *pce_opts = &pce_opts_cli->pce_opts;
708 vty_out(vty, "PCE: %s\n", pce_opts->pce_name);
709
710 /* Remote PCE IP address */
711 if (IS_IPADDR_V6(&pce_opts->addr)) {
712 vty_out(vty, " %s %s %pI6 %s %d\n", PCEP_VTYSH_ARG_ADDRESS,
713 PCEP_VTYSH_ARG_IPV6, &pce_opts->addr.ipaddr_v6,
714 PCEP_VTYSH_ARG_PORT, pce_opts->port);
715 } else {
716 vty_out(vty, " %s %s %pI4 %s %d\n", PCEP_VTYSH_ARG_ADDRESS,
717 PCEP_VTYSH_ARG_IP, &pce_opts->addr.ipaddr_v4,
718 PCEP_VTYSH_ARG_PORT, pce_opts->port);
719 }
720
721 if (pce_opts_cli->config_group_name[0] != '\0') {
722 vty_out(vty, " pce-config: %s\n",
723 pce_opts_cli->config_group_name);
724 }
725
726 char buf[1024] = "";
727 pcep_cli_print_pce_config(&pce_opts->config_opts, buf, sizeof(buf));
728 vty_out(vty, "%s", buf);
729 }
730
731 static int path_pcep_cli_show_srte_pcep_pce(struct vty *vty,
732 const char *pce_peer)
733 {
734 /* Only show 1 PCE */
735 struct pce_opts_cli *pce_opts_cli;
736 if (pce_peer != NULL) {
737 pce_opts_cli = pcep_cli_find_pce(pce_peer);
738 if (pce_opts_cli == NULL) {
739 vty_out(vty, "%% PCE [%s] does not exist.\n", pce_peer);
740 return CMD_WARNING;
741 }
742
743 pcep_cli_merge_pcep_pce_config_options(pce_opts_cli);
744 show_pce_peer(vty, pce_opts_cli);
745
746 return CMD_SUCCESS;
747 }
748
749 /* Show all PCEs */
750 for (int i = 0; i < MAX_PCE; i++) {
751 pce_opts_cli = pcep_g->pce_opts_cli[i];
752 if (pce_opts_cli == NULL) {
753 continue;
754 }
755
756 pcep_cli_merge_pcep_pce_config_options(pce_opts_cli);
757 show_pce_peer(vty, pce_opts_cli);
758 }
759
760 return CMD_SUCCESS;
761 }
762
763 static int path_pcep_cli_peer_sr_draft07(struct vty *vty)
764 {
765 struct pcep_config_group_opts *pce_config = NULL;
766
767 if (vty->node == PCEP_PCE_NODE) {
768 /* TODO need to see if the pce is in use, and reset the
769 * connection */
770 pce_config = &current_pce_opts_g->pce_config_group_opts;
771 current_pce_opts_g->merged = false;
772 } else if (vty->node == PCEP_PCE_CONFIG_NODE) {
773 pce_config = current_pcep_config_group_opts_g;
774 } else {
775 return CMD_ERR_NO_MATCH;
776 }
777
778 pce_config->draft07 = true;
779
780 return CMD_SUCCESS;
781 }
782
783 static int path_pcep_cli_peer_pce_initiated(struct vty *vty)
784 {
785 struct pcep_config_group_opts *pce_config = NULL;
786
787 if (vty->node == PCEP_PCE_NODE) {
788 /* TODO need to see if the pce is in use, and reset the
789 * connection */
790 pce_config = &current_pce_opts_g->pce_config_group_opts;
791 current_pce_opts_g->merged = false;
792 } else if (vty->node == PCEP_PCE_CONFIG_NODE) {
793 pce_config = current_pcep_config_group_opts_g;
794 } else {
795 return CMD_ERR_NO_MATCH;
796 }
797
798 pce_config->pce_initiated = true;
799
800 return CMD_SUCCESS;
801 }
802
803 static int path_pcep_cli_peer_tcp_md5_auth(struct vty *vty,
804 const char *tcp_md5_auth)
805 {
806 struct pcep_config_group_opts *pce_config = NULL;
807
808 if (vty->node == PCEP_PCE_NODE) {
809 /* TODO need to see if the pce is in use, and reset the
810 * connection */
811 pce_config = &current_pce_opts_g->pce_config_group_opts;
812 current_pce_opts_g->merged = false;
813 } else if (vty->node == PCEP_PCE_CONFIG_NODE) {
814 pce_config = current_pcep_config_group_opts_g;
815 } else {
816 return CMD_ERR_NO_MATCH;
817 }
818
819 strlcpy(pce_config->tcp_md5_auth, tcp_md5_auth,
820 sizeof(pce_config->tcp_md5_auth));
821
822 return CMD_SUCCESS;
823 }
824
825 static int path_pcep_cli_peer_address(struct vty *vty, const char *ip_str,
826 struct in_addr *ip, const char *ipv6_str,
827 struct in6_addr *ipv6,
828 const char *port_str, long port)
829 {
830 struct pce_opts *pce_opts = NULL;
831 if (vty->node == PCEP_PCE_NODE) {
832 /* TODO need to see if the pce is in use, and reset the
833 * connection */
834 pce_opts = &current_pce_opts_g->pce_opts;
835 current_pce_opts_g->merged = false;
836 } else {
837 return CMD_ERR_NO_MATCH;
838 }
839
840 if (ipv6_str != NULL) {
841 pce_opts->addr.ipa_type = IPADDR_V6;
842 memcpy(&pce_opts->addr.ipaddr_v6, ipv6,
843 sizeof(struct in6_addr));
844 } else if (ip_str != NULL) {
845 pce_opts->addr.ipa_type = IPADDR_V4;
846 memcpy(&pce_opts->addr.ipaddr_v4, ip, sizeof(struct in_addr));
847 } else {
848 return CMD_ERR_NO_MATCH;
849 }
850
851 /* Handle the optional port */
852 pce_opts->port = PCEP_DEFAULT_PORT;
853 PCEP_VTYSH_INT_ARG_CHECK(port_str, port, pce_opts->port, 0, 65535);
854
855 return CMD_SUCCESS;
856 }
857
858 static int path_pcep_cli_peer_source_address(struct vty *vty,
859 const char *ip_str,
860 struct in_addr *ip,
861 const char *ipv6_str,
862 struct in6_addr *ipv6,
863 const char *port_str, long port)
864 {
865 struct pcep_config_group_opts *pce_config = NULL;
866 if (vty->node == PCEP_PCE_NODE) {
867 /* TODO need to see if the pce is in use, and reset the
868 * connection */
869 pce_config = &current_pce_opts_g->pce_config_group_opts;
870 current_pce_opts_g->merged = false;
871 } else if (vty->node == PCEP_PCE_CONFIG_NODE) {
872 pce_config = current_pcep_config_group_opts_g;
873 } else {
874 return CMD_ERR_NO_MATCH;
875 }
876
877 /* Handle the optional source IP */
878 if (ipv6_str != NULL) {
879 pce_config->source_ip.ipa_type = IPADDR_V6;
880 memcpy(&pce_config->source_ip.ipaddr_v6, ipv6,
881 sizeof(struct in6_addr));
882 } else if (ip_str != NULL) {
883 pce_config->source_ip.ipa_type = IPADDR_V4;
884 memcpy(&pce_config->source_ip.ipaddr_v4, ip,
885 sizeof(struct in_addr));
886 }
887
888 /* Handle the optional port */
889 PCEP_VTYSH_INT_ARG_CHECK(port_str, port, pce_config->source_port, 0,
890 65535);
891
892 return CMD_SUCCESS;
893 }
894
895 static int path_pcep_cli_peer_pcep_pce_config_ref(struct vty *vty,
896 const char *config_group_name)
897 {
898 if (vty->node == PCEP_PCE_NODE) {
899 /* TODO need to see if the pce is in use, and reset the
900 * connection */
901 current_pce_opts_g->merged = false;
902 } else {
903 return CMD_ERR_NO_MATCH;
904 }
905
906 struct pcep_config_group_opts *pce_config =
907 pcep_cli_find_pcep_pce_config(config_group_name);
908 if (pce_config == NULL) {
909 vty_out(vty, "%% pce-config [%s] does not exist.\n",
910 config_group_name);
911 return CMD_WARNING;
912 }
913
914 strlcpy(current_pce_opts_g->config_group_name, config_group_name,
915 sizeof(current_pce_opts_g->config_group_name));
916
917 return CMD_SUCCESS;
918 }
919
920 static int path_pcep_cli_peer_timers(
921 struct vty *vty, const char *keep_alive_str, long keep_alive,
922 const char *min_peer_keep_alive_str, long min_peer_keep_alive,
923 const char *max_peer_keep_alive_str, long max_peer_keep_alive,
924 const char *dead_timer_str, long dead_timer,
925 const char *min_peer_dead_timer_str, long min_peer_dead_timer,
926 const char *max_peer_dead_timer_str, long max_peer_dead_timer,
927 const char *pcep_request_str, long pcep_request,
928 const char *session_timeout_interval_str, long session_timeout_interval,
929 const char *delegation_timeout_str, long delegation_timeout)
930 {
931 struct pcep_config_group_opts *pce_config = NULL;
932 if (vty->node == PCEP_PCE_NODE) {
933 /* TODO need to see if the pce is in use, and reset the
934 * connection */
935 pce_config = &current_pce_opts_g->pce_config_group_opts;
936 current_pce_opts_g->merged = false;
937 } else if (vty->node == PCEP_PCE_CONFIG_NODE) {
938 pce_config = current_pcep_config_group_opts_g;
939 } else {
940 return CMD_ERR_NO_MATCH;
941 }
942
943 if (min_peer_keep_alive && max_peer_keep_alive)
944 if (min_peer_keep_alive >= max_peer_keep_alive) {
945 return CMD_ERR_NO_MATCH;
946 }
947
948 if (min_peer_dead_timer && max_peer_dead_timer)
949 if (min_peer_dead_timer >= max_peer_dead_timer) {
950 return CMD_ERR_NO_MATCH;
951 }
952
953 /* Handle the arguments */
954 PCEP_VTYSH_INT_ARG_CHECK(keep_alive_str, keep_alive,
955 pce_config->keep_alive_seconds, 0, 64);
956 PCEP_VTYSH_INT_ARG_CHECK(min_peer_keep_alive_str, min_peer_keep_alive,
957 pce_config->min_keep_alive_seconds, 0, 256);
958 PCEP_VTYSH_INT_ARG_CHECK(max_peer_keep_alive_str, max_peer_keep_alive,
959 pce_config->max_keep_alive_seconds, 0, 256);
960 PCEP_VTYSH_INT_ARG_CHECK(dead_timer_str, dead_timer,
961 pce_config->dead_timer_seconds, 3, 256);
962 PCEP_VTYSH_INT_ARG_CHECK(min_peer_dead_timer_str, min_peer_dead_timer,
963 pce_config->min_dead_timer_seconds, 3, 256);
964 PCEP_VTYSH_INT_ARG_CHECK(max_peer_dead_timer_str, max_peer_dead_timer,
965 pce_config->max_dead_timer_seconds, 3, 256);
966 PCEP_VTYSH_INT_ARG_CHECK(pcep_request_str, pcep_request,
967 pce_config->pcep_request_time_seconds, 0, 121);
968 PCEP_VTYSH_INT_ARG_CHECK(
969 session_timeout_interval_str, session_timeout_interval,
970 pce_config->session_timeout_inteval_seconds, 0, 121);
971 PCEP_VTYSH_INT_ARG_CHECK(delegation_timeout_str, delegation_timeout,
972 pce_config->delegation_timeout_seconds, 0, 61);
973
974 return CMD_SUCCESS;
975 }
976
977 static int path_pcep_cli_pcc(struct vty *vty)
978 {
979 VTY_PUSH_CONTEXT_NULL(PCEP_PCC_NODE);
980
981 return CMD_SUCCESS;
982 }
983
984 static int path_pcep_cli_pcc_delete(struct vty *vty)
985 {
986 /* Clear the pce_connections */
987 memset(&pce_connections_g, 0, sizeof(pce_connections_g));
988 pcc_msd_configured_g = false;
989
990 pcep_ctrl_remove_pcc(pcep_g->fpt, NULL);
991
992 return CMD_SUCCESS;
993 }
994
995 static int path_pcep_cli_pcc_pcc_msd(struct vty *vty, const char *msd_str,
996 long msd)
997 {
998 pcc_msd_configured_g = true;
999 PCEP_VTYSH_INT_ARG_CHECK(msd_str, msd, pcc_msd_g, 0, 33);
1000
1001 return CMD_SUCCESS;
1002 }
1003
1004 static int path_pcep_cli_pcc_pcc_peer(struct vty *vty, const char *peer_name,
1005 const char *precedence_str,
1006 long precedence)
1007 {
1008 /* Check if the pcc-peer exists */
1009 struct pce_opts_cli *pce_opts_cli = pcep_cli_find_pce(peer_name);
1010 if (pce_opts_cli == NULL) {
1011 vty_out(vty, "%% PCE [%s] does not exist.\n", peer_name);
1012 return CMD_WARNING;
1013 }
1014 struct pce_opts *pce_opts = &pce_opts_cli->pce_opts;
1015
1016 /* Check if the pcc-peer is duplicated */
1017 if (pcep_cli_pcc_has_pce(peer_name)) {
1018 vty_out(vty, "%% The peer [%s] has already been configured.\n",
1019 peer_name);
1020 return CMD_WARNING;
1021 }
1022
1023 /* Get the optional precedence argument */
1024 pce_opts->precedence = DEFAULT_PCE_PRECEDENCE;
1025 PCEP_VTYSH_INT_ARG_CHECK(precedence_str, precedence,
1026 pce_opts->precedence, 0, 256);
1027
1028 /* Finalize the pce_opts config values */
1029 pcep_cli_merge_pcep_pce_config_options(pce_opts_cli);
1030 pcep_cli_add_pce_connection(&pce_opts_cli->pce_opts);
1031
1032 /* Verify the PCE has the IP set */
1033 struct in6_addr zero_v6_addr;
1034 memset(&zero_v6_addr, 0, sizeof(struct in6_addr));
1035 if (memcmp(&pce_opts->addr.ip, &zero_v6_addr, IPADDRSZ(&pce_opts->addr))
1036 == 0) {
1037 vty_out(vty,
1038 "%% The peer [%s] does not have an IP set and cannot be used until it does.\n",
1039 peer_name);
1040 return CMD_WARNING;
1041 }
1042
1043 /* Update the pcc_opts with the source ip, port, and msd */
1044 struct pcc_opts *pcc_opts_copy =
1045 XMALLOC(MTYPE_PCEP, sizeof(struct pcc_opts));
1046 memcpy(&pcc_opts_copy->addr,
1047 &pce_opts_cli->pce_opts.config_opts.source_ip,
1048 sizeof(pcc_opts_copy->addr));
1049 pcc_opts_copy->msd = pcc_msd_g;
1050 pcc_opts_copy->port = pce_opts_cli->pce_opts.config_opts.source_port;
1051 if (pcep_ctrl_update_pcc_options(pcep_g->fpt, pcc_opts_copy)) {
1052 return CMD_WARNING;
1053 }
1054
1055 /* Send a copy of the pce_opts, this one is only used for the CLI */
1056 struct pce_opts *pce_opts_copy =
1057 XMALLOC(MTYPE_PCEP, sizeof(struct pce_opts));
1058 memcpy(pce_opts_copy, pce_opts, sizeof(struct pce_opts));
1059 if (pcep_ctrl_update_pce_options(pcep_g->fpt, pce_opts_copy)) {
1060 return CMD_WARNING;
1061 }
1062
1063 return CMD_SUCCESS;
1064 }
1065
1066 static int path_pcep_cli_pcc_pcc_peer_delete(struct vty *vty,
1067 const char *peer_name,
1068 const char *precedence_str,
1069 long precedence)
1070 {
1071 /* Check if the pcc-peer is connected to the PCC */
1072 if (!pcep_cli_pcc_has_pce(peer_name)) {
1073 vty_out(vty,
1074 "%% WARN: The peer [%s] is not connected to the PCC.\n",
1075 peer_name);
1076 return CMD_WARNING;
1077 }
1078
1079 struct pce_opts_cli *pce_opts_cli = pcep_cli_find_pce(peer_name);
1080 pcep_cli_remove_pce_connection(&pce_opts_cli->pce_opts);
1081
1082 /* Send a copy of the pce_opts, this one is used for CLI only */
1083 struct pce_opts *pce_opts_copy =
1084 XMALLOC(MTYPE_PCEP, sizeof(struct pce_opts));
1085 memcpy(pce_opts_copy, &pce_opts_cli->pce_opts, sizeof(struct pce_opts));
1086 pcep_ctrl_remove_pcc(pcep_g->fpt, pce_opts_copy);
1087
1088 return CMD_SUCCESS;
1089 }
1090
1091 static int path_pcep_cli_show_srte_pcep_pcc(struct vty *vty)
1092 {
1093 vty_out(vty, "pcc msd %d\n", pcc_msd_g);
1094
1095 return CMD_SUCCESS;
1096 }
1097
1098 /* Internal util function to print pcep capabilities to a buffer */
1099 static void print_pcep_capabilities(char *buf, size_t buf_len,
1100 pcep_configuration *config)
1101 {
1102 if (config->support_stateful_pce_lsp_update) {
1103 csnprintfrr(buf, buf_len, "%s", PCEP_CLI_CAP_STATEFUL);
1104 }
1105 if (config->support_include_db_version) {
1106 csnprintfrr(buf, buf_len, "%s", PCEP_CLI_CAP_INCL_DB_VER);
1107 }
1108 if (config->support_lsp_triggered_resync) {
1109 csnprintfrr(buf, buf_len, "%s", PCEP_CLI_CAP_LSP_TRIGGERED);
1110 }
1111 if (config->support_lsp_delta_sync) {
1112 csnprintfrr(buf, buf_len, "%s", PCEP_CLI_CAP_LSP_DELTA);
1113 }
1114 if (config->support_pce_triggered_initial_sync) {
1115 csnprintfrr(buf, buf_len, "%s", PCEP_CLI_CAP_PCE_TRIGGERED);
1116 }
1117 if (config->support_sr_te_pst) {
1118 csnprintfrr(buf, buf_len, "%s", PCEP_CLI_CAP_SR_TE_PST);
1119 }
1120 if (config->pcc_can_resolve_nai_to_sid) {
1121 csnprintfrr(buf, buf_len, "%s", PCEP_CLI_CAP_PCC_RESOLVE_NAI);
1122 }
1123 }
1124
1125 /* Internal util function to print a pcep session */
1126 static void print_pcep_session(struct vty *vty, struct pce_opts *pce_opts,
1127 struct pcep_pcc_info *pcc_info)
1128 {
1129 char buf[1024];
1130 buf[0] = '\0';
1131
1132 vty_out(vty, "\nPCE %s\n", pce_opts->pce_name);
1133
1134 /* PCE IP */
1135 if (IS_IPADDR_V4(&pce_opts->addr)) {
1136 vty_out(vty, " PCE IP %pI4 port %d\n",
1137 &pce_opts->addr.ipaddr_v4, pce_opts->port);
1138 } else if (IS_IPADDR_V6(&pce_opts->addr)) {
1139 vty_out(vty, " PCE IPv6 %pI6 port %d\n",
1140 &pce_opts->addr.ipaddr_v6, pce_opts->port);
1141 }
1142
1143 /* PCC IP */
1144 if (IS_IPADDR_V4(&pcc_info->pcc_addr)) {
1145 vty_out(vty, " PCC IP %pI4 port %d\n",
1146 &pcc_info->pcc_addr.ipaddr_v4, pcc_info->pcc_port);
1147 } else if (IS_IPADDR_V6(&pcc_info->pcc_addr)) {
1148 vty_out(vty, " PCC IPv6 %pI6 port %d\n",
1149 &pcc_info->pcc_addr.ipaddr_v6, pcc_info->pcc_port);
1150 }
1151 vty_out(vty, " PCC MSD %d\n", pcc_info->msd);
1152
1153 if (pcc_info->status == PCEP_PCC_OPERATING) {
1154 vty_out(vty, " Session Status UP\n");
1155 } else {
1156 vty_out(vty, " Session Status %s\n",
1157 pcc_status_name(pcc_info->status));
1158 }
1159
1160 if (pcc_info->is_best_multi_pce) {
1161 vty_out(vty, " Precedence %d, best candidate\n",
1162 ((pcc_info->precedence > 0) ? pcc_info->precedence
1163 : DEFAULT_PCE_PRECEDENCE));
1164 } else {
1165 vty_out(vty, " Precedence %d\n",
1166 ((pcc_info->precedence > 0) ? pcc_info->precedence
1167 : DEFAULT_PCE_PRECEDENCE));
1168 }
1169 vty_out(vty, " Confidence %s\n",
1170 ((pcc_info->previous_best) ? "low"
1171 : "normal"));
1172
1173 /* PCEPlib pcep session values, get a thread safe copy of the counters
1174 */
1175 pcep_session *session =
1176 pcep_ctrl_get_pcep_session(pcep_g->fpt, pcc_info->pcc_id);
1177
1178 /* Config Options values */
1179 struct pcep_config_group_opts *config_opts = &pce_opts->config_opts;
1180 if (session != NULL) {
1181 vty_out(vty, " Timer: KeepAlive config %d, pce-negotiated %d\n",
1182 config_opts->keep_alive_seconds,
1183 session->pcc_config
1184 .keep_alive_pce_negotiated_timer_seconds);
1185 vty_out(vty, " Timer: DeadTimer config %d, pce-negotiated %d\n",
1186 config_opts->dead_timer_seconds,
1187 session->pcc_config.dead_timer_pce_negotiated_seconds);
1188 } else {
1189 vty_out(vty, " Timer: KeepAlive %d\n",
1190 config_opts->keep_alive_seconds);
1191 vty_out(vty, " Timer: DeadTimer %d\n",
1192 config_opts->dead_timer_seconds);
1193 }
1194 vty_out(vty, " Timer: PcRequest %d\n",
1195 config_opts->pcep_request_time_seconds);
1196 vty_out(vty, " Timer: SessionTimeout Interval %d\n",
1197 config_opts->session_timeout_inteval_seconds);
1198 vty_out(vty, " Timer: Delegation Timeout %d\n",
1199 config_opts->delegation_timeout_seconds);
1200 if (strlen(config_opts->tcp_md5_auth) > 0) {
1201 vty_out(vty, " TCP MD5 Auth Str: %s\n",
1202 config_opts->tcp_md5_auth);
1203 } else {
1204 vty_out(vty, " No TCP MD5 Auth\n");
1205 }
1206
1207 if (config_opts->draft07) {
1208 vty_out(vty, " PCE SR Version draft07\n");
1209 } else {
1210 vty_out(vty, " PCE SR Version draft16 and RFC8408\n");
1211 }
1212
1213 vty_out(vty, " Next PcReq ID %d\n", pcc_info->next_reqid);
1214 vty_out(vty, " Next PLSP ID %d\n", pcc_info->next_plspid);
1215
1216 if (session != NULL) {
1217 if (pcc_info->status == PCEP_PCC_SYNCHRONIZING
1218 || pcc_info->status == PCEP_PCC_OPERATING) {
1219 time_t current_time = time(NULL);
1220 struct tm lt = {0};
1221 /* Just for the timezone */
1222 localtime_r(&current_time, &lt);
1223 gmtime_r(&session->time_connected, &lt);
1224 vty_out(vty,
1225 " Connected for %u seconds, since %d-%02d-%02d %02d:%02d:%02d UTC\n",
1226 (uint32_t)(current_time
1227 - session->time_connected),
1228 lt.tm_year + 1900, lt.tm_mon + 1, lt.tm_mday,
1229 lt.tm_hour, lt.tm_min, lt.tm_sec);
1230 }
1231
1232 /* PCC capabilities */
1233 buf[0] = '\0';
1234 int index = 0;
1235 if (config_opts->pce_initiated) {
1236 index += csnprintfrr(buf, sizeof(buf), "%s",
1237 PCEP_CLI_CAP_PCC_PCE_INITIATED);
1238 } else {
1239 index += csnprintfrr(buf, sizeof(buf), "%s",
1240 PCEP_CLI_CAP_PCC_INITIATED);
1241 }
1242 print_pcep_capabilities(buf, sizeof(buf) - index,
1243 &session->pcc_config);
1244 vty_out(vty, " PCC Capabilities:%s\n", buf);
1245
1246 /* PCE capabilities */
1247 buf[0] = '\0';
1248 print_pcep_capabilities(buf, sizeof(buf), &session->pce_config);
1249 if (buf[0] != '\0') {
1250 vty_out(vty, " PCE Capabilities:%s\n", buf);
1251 }
1252 XFREE(MTYPE_PCEP, session);
1253 } else {
1254 vty_out(vty, " Detailed session information not available\n");
1255 }
1256
1257 /* Message Counters, get a thread safe copy of the counters */
1258 struct counters_group *group =
1259 pcep_ctrl_get_counters(pcep_g->fpt, pcc_info->pcc_id);
1260
1261 if (group != NULL) {
1262 struct counters_subgroup *rx_msgs =
1263 find_subgroup(group, COUNTER_SUBGROUP_ID_RX_MSG);
1264 struct counters_subgroup *tx_msgs =
1265 find_subgroup(group, COUNTER_SUBGROUP_ID_TX_MSG);
1266
1267 if (rx_msgs != NULL && tx_msgs != NULL) {
1268 vty_out(vty, " PCEP Message Statistics\n");
1269 vty_out(vty, " %27s %6s\n", "Sent", "Rcvd");
1270 for (int i = 0; i < rx_msgs->max_counters; i++) {
1271 struct counter *rx_counter =
1272 rx_msgs->counters[i];
1273 struct counter *tx_counter =
1274 tx_msgs->counters[i];
1275 if (rx_counter != NULL && tx_counter != NULL) {
1276 vty_out(vty, " %20s: %5d %5d\n",
1277 tx_counter->counter_name,
1278 tx_counter->counter_value,
1279 rx_counter->counter_value);
1280 }
1281 }
1282 vty_out(vty, " %20s: %5d %5d\n", "Total",
1283 subgroup_counters_total(tx_msgs),
1284 subgroup_counters_total(rx_msgs));
1285 }
1286 pcep_lib_free_counters(group);
1287 } else {
1288 vty_out(vty, " Counters not available\n");
1289 }
1290
1291 XFREE(MTYPE_PCEP, pcc_info);
1292 }
1293
1294 static int path_pcep_cli_show_srte_pcep_session(struct vty *vty,
1295 const char *pcc_peer)
1296 {
1297 struct pce_opts_cli *pce_opts_cli;
1298 struct pcep_pcc_info *pcc_info;
1299
1300 /* Only show 1 PCEP session */
1301 if (pcc_peer != NULL) {
1302 pce_opts_cli = pcep_cli_find_pce(pcc_peer);
1303 if (pce_opts_cli == NULL) {
1304 vty_out(vty, "%% PCE [%s] does not exist.\n", pcc_peer);
1305 return CMD_WARNING;
1306 }
1307
1308 if (!pcep_cli_pcc_has_pce(pcc_peer)) {
1309 vty_out(vty, "%% PCC is not connected to PCE [%s].\n",
1310 pcc_peer);
1311 return CMD_WARNING;
1312 }
1313
1314 pcc_info = pcep_ctrl_get_pcc_info(pcep_g->fpt, pcc_peer);
1315 if (pcc_info == NULL) {
1316 vty_out(vty,
1317 "%% Cannot retrieve PCEP session info for PCE [%s]\n",
1318 pcc_peer);
1319 return CMD_WARNING;
1320 }
1321
1322 print_pcep_session(vty, &pce_opts_cli->pce_opts, pcc_info);
1323
1324 return CMD_SUCCESS;
1325 }
1326
1327 /* Show all PCEP sessions */
1328 struct pce_opts *pce_opts;
1329 int num_pcep_sessions_conf = 0;
1330 int num_pcep_sessions_conn = 0;
1331 for (int i = 0; i < MAX_PCC; i++) {
1332 pce_opts = pce_connections_g.connections[i];
1333 if (pce_opts == NULL) {
1334 continue;
1335 }
1336
1337 pcc_info =
1338 pcep_ctrl_get_pcc_info(pcep_g->fpt, pce_opts->pce_name);
1339 if (pcc_info == NULL) {
1340 vty_out(vty,
1341 "%% Cannot retrieve PCEP session info for PCE [%s]\n",
1342 pce_opts->pce_name);
1343 continue;
1344 }
1345
1346 num_pcep_sessions_conn +=
1347 pcc_info->status == PCEP_PCC_OPERATING ? 1 : 0;
1348 num_pcep_sessions_conf++;
1349 print_pcep_session(vty, pce_opts, pcc_info);
1350 }
1351
1352 vty_out(vty, "PCEP Sessions => Configured %d ; Connected %d\n",
1353 num_pcep_sessions_conf, num_pcep_sessions_conn);
1354
1355 return CMD_SUCCESS;
1356 }
1357
1358 static int path_pcep_cli_clear_srte_pcep_session(struct vty *vty,
1359 const char *pcc_peer)
1360 {
1361 struct pce_opts_cli *pce_opts_cli;
1362
1363 /* Only clear 1 PCEP session */
1364 if (pcc_peer != NULL) {
1365 pce_opts_cli = pcep_cli_find_pce(pcc_peer);
1366 if (pce_opts_cli == NULL) {
1367 vty_out(vty, "%% PCE [%s] does not exist.\n", pcc_peer);
1368 return CMD_WARNING;
1369 }
1370
1371 if (!pcep_cli_pcc_has_pce(pcc_peer)) {
1372 vty_out(vty, "%% PCC is not connected to PCE [%s].\n",
1373 pcc_peer);
1374 return CMD_WARNING;
1375 }
1376
1377 pcep_ctrl_reset_pcc_session(pcep_g->fpt,
1378 pce_opts_cli->pce_opts.pce_name);
1379 vty_out(vty, "PCEP session cleared for peer %s\n", pcc_peer);
1380
1381 return CMD_SUCCESS;
1382 }
1383
1384 /* Clear all PCEP sessions */
1385 struct pce_opts *pce_opts;
1386 int num_pcep_sessions = 0;
1387 for (int i = 0; i < MAX_PCC; i++) {
1388 pce_opts = pce_connections_g.connections[i];
1389 if (pce_opts == NULL) {
1390 continue;
1391 }
1392
1393 num_pcep_sessions++;
1394 pcep_ctrl_reset_pcc_session(pcep_g->fpt, pce_opts->pce_name);
1395 vty_out(vty, "PCEP session cleared for peer %s\n",
1396 pce_opts->pce_name);
1397 }
1398
1399 vty_out(vty, "Cleared [%d] PCEP sessions\n", num_pcep_sessions);
1400
1401 return CMD_SUCCESS;
1402 }
1403
1404 /*
1405 * Config Write functions
1406 */
1407
1408 int pcep_cli_debug_config_write(struct vty *vty)
1409 {
1410 char buff[128] = "";
1411
1412 if (DEBUG_MODE_CHECK(&pcep_g->dbg, DEBUG_MODE_CONF)) {
1413 if (DEBUG_FLAGS_CHECK(&pcep_g->dbg, PCEP_DEBUG_MODE_BASIC))
1414 csnprintfrr(buff, sizeof(buff), " %s",
1415 PCEP_VTYSH_ARG_BASIC);
1416 if (DEBUG_FLAGS_CHECK(&pcep_g->dbg, PCEP_DEBUG_MODE_PATH))
1417 csnprintfrr(buff, sizeof(buff), " %s",
1418 PCEP_VTYSH_ARG_PATH);
1419 if (DEBUG_FLAGS_CHECK(&pcep_g->dbg, PCEP_DEBUG_MODE_PCEP))
1420 csnprintfrr(buff, sizeof(buff), " %s",
1421 PCEP_VTYSH_ARG_MESSAGE);
1422 if (DEBUG_FLAGS_CHECK(&pcep_g->dbg, PCEP_DEBUG_MODE_PCEPLIB))
1423 csnprintfrr(buff, sizeof(buff), " %s",
1424 PCEP_VTYSH_ARG_PCEPLIB);
1425 vty_out(vty, "debug pathd pcep%s\n", buff);
1426 buff[0] = 0;
1427 return 1;
1428 }
1429
1430 return 0;
1431 }
1432
1433 int pcep_cli_debug_set_all(uint32_t flags, bool set)
1434 {
1435 DEBUG_FLAGS_SET(&pcep_g->dbg, flags, set);
1436
1437 /* If all modes have been turned off, don't preserve options. */
1438 if (!DEBUG_MODE_CHECK(&pcep_g->dbg, DEBUG_MODE_ALL))
1439 DEBUG_CLEAR(&pcep_g->dbg);
1440
1441 return 0;
1442 }
1443
1444 int pcep_cli_pcep_config_write(struct vty *vty)
1445 {
1446 vty_out(vty, " pcep\n");
1447 return 1;
1448 }
1449
1450 int pcep_cli_pcc_config_write(struct vty *vty)
1451 {
1452 struct pce_opts *pce_opts;
1453 char buf[128] = "";
1454 int lines = 0;
1455
1456 /* The MSD, nor any PCE peers have been configured on the PCC */
1457 if (!pcc_msd_configured_g && pce_connections_g.num_connections == 0) {
1458 return lines;
1459 }
1460
1461 vty_out(vty, " pcc\n");
1462 lines++;
1463
1464 /* Prepare the MSD, if present */
1465 if (pcc_msd_configured_g) {
1466 vty_out(vty, " %s %d\n", PCEP_VTYSH_ARG_MSD, pcc_msd_g);
1467 lines++;
1468 }
1469
1470 if (pce_connections_g.num_connections == 0) {
1471 return lines;
1472 }
1473
1474 buf[0] = 0;
1475 for (int i = 0; i < MAX_PCC; i++) {
1476 pce_opts = pce_connections_g.connections[i];
1477 if (pce_opts == NULL) {
1478 continue;
1479 }
1480
1481 /* Only show the PCEs configured in the pcc sub-command */
1482 if (!pcep_cli_pcc_has_pce(pce_opts->pce_name)) {
1483 continue;
1484 }
1485
1486 csnprintfrr(buf, sizeof(buf), " peer %s",
1487 pce_opts->pce_name);
1488 if (pce_opts->precedence > 0
1489 && pce_opts->precedence != DEFAULT_PCE_PRECEDENCE) {
1490 csnprintfrr(buf, sizeof(buf), " %s %d",
1491 PCEP_VTYSH_ARG_PRECEDENCE,
1492 pce_opts->precedence);
1493 }
1494 vty_out(vty, "%s\n", buf);
1495 lines++;
1496 buf[0] = 0;
1497 }
1498
1499 return lines;
1500 }
1501
1502 /* Internal function used by pcep_cli_pce_config_write()
1503 * and pcep_cli_pcep_pce_config_write() */
1504 static int pcep_cli_print_pce_config(struct pcep_config_group_opts *group_opts,
1505 char *buf, size_t buf_len)
1506 {
1507 int lines = 0;
1508
1509 if (group_opts->source_ip.ipa_type != IPADDR_NONE
1510 || group_opts->source_port != 0) {
1511 csnprintfrr(buf, buf_len, " ");
1512 if (IS_IPADDR_V4(&group_opts->source_ip)) {
1513 csnprintfrr(buf, buf_len, " %s %s %pI4",
1514 PCEP_VTYSH_ARG_SOURCE_ADDRESS,
1515 PCEP_VTYSH_ARG_IP,
1516 &group_opts->source_ip.ipaddr_v4);
1517 } else if (IS_IPADDR_V6(&group_opts->source_ip)) {
1518 csnprintfrr(buf, buf_len, " %s %s %pI6",
1519 PCEP_VTYSH_ARG_SOURCE_ADDRESS,
1520 PCEP_VTYSH_ARG_IPV6,
1521 &group_opts->source_ip.ipaddr_v6);
1522 }
1523 if (group_opts->source_port > 0) {
1524 csnprintfrr(buf, buf_len, " %s %d", PCEP_VTYSH_ARG_PORT,
1525 group_opts->source_port);
1526 }
1527 csnprintfrr(buf, buf_len, "\n");
1528 lines++;
1529 }
1530 /* Group the keep-alive together for devman */
1531 if ((group_opts->keep_alive_seconds > 0)
1532 || (group_opts->min_keep_alive_seconds > 0)
1533 || (group_opts->max_keep_alive_seconds > 0)) {
1534 csnprintfrr(buf, buf_len, " %s", PCEP_VTYSH_ARG_TIMER);
1535
1536 if (group_opts->keep_alive_seconds > 0) {
1537 csnprintfrr(buf, buf_len, " %s %d",
1538 PCEP_VTYSH_ARG_KEEP_ALIVE,
1539 group_opts->keep_alive_seconds);
1540 }
1541 if (group_opts->min_keep_alive_seconds > 0) {
1542 csnprintfrr(buf, buf_len, " %s %d",
1543 PCEP_VTYSH_ARG_KEEP_ALIVE_MIN,
1544 group_opts->min_keep_alive_seconds);
1545 }
1546 if (group_opts->max_keep_alive_seconds > 0) {
1547 csnprintfrr(buf, buf_len, " %s %d",
1548 PCEP_VTYSH_ARG_KEEP_ALIVE_MAX,
1549 group_opts->max_keep_alive_seconds);
1550 }
1551 csnprintfrr(buf, buf_len, "\n");
1552 lines++;
1553 }
1554
1555 /* Group the dead-timer together for devman */
1556 if ((group_opts->dead_timer_seconds > 0)
1557 || (group_opts->min_dead_timer_seconds > 0)
1558 || (group_opts->max_dead_timer_seconds > 0)) {
1559 csnprintfrr(buf, buf_len, " %s", PCEP_VTYSH_ARG_TIMER);
1560
1561 if (group_opts->dead_timer_seconds > 0) {
1562 csnprintfrr(buf, buf_len, " %s %d",
1563 PCEP_VTYSH_ARG_DEAD_TIMER,
1564 group_opts->dead_timer_seconds);
1565 }
1566 if (group_opts->min_dead_timer_seconds > 0) {
1567 csnprintfrr(buf, buf_len, " %s %d",
1568 PCEP_VTYSH_ARG_DEAD_TIMER_MIN,
1569 group_opts->min_dead_timer_seconds);
1570 }
1571 if (group_opts->max_dead_timer_seconds > 0) {
1572 csnprintfrr(buf, buf_len, " %s %d",
1573 PCEP_VTYSH_ARG_DEAD_TIMER_MAX,
1574 group_opts->max_dead_timer_seconds);
1575 }
1576 csnprintfrr(buf, buf_len, "\n");
1577 lines++;
1578 }
1579
1580 if (group_opts->pcep_request_time_seconds > 0) {
1581 csnprintfrr(buf, buf_len, " %s %s %d\n",
1582 PCEP_VTYSH_ARG_TIMER, PCEP_VTYSH_ARG_PCEP_REQUEST,
1583 group_opts->pcep_request_time_seconds);
1584 lines++;
1585 }
1586 if (group_opts->delegation_timeout_seconds > 0) {
1587 csnprintfrr(buf, buf_len, " %s %s %d\n",
1588 PCEP_VTYSH_ARG_TIMER,
1589 PCEP_VTYSH_ARG_DELEGATION_TIMEOUT,
1590 group_opts->delegation_timeout_seconds);
1591 lines++;
1592 }
1593 if (group_opts->session_timeout_inteval_seconds > 0) {
1594 csnprintfrr(buf, buf_len, " %s %s %d\n",
1595 PCEP_VTYSH_ARG_TIMER,
1596 PCEP_VTYSH_ARG_SESSION_TIMEOUT,
1597 group_opts->session_timeout_inteval_seconds);
1598 lines++;
1599 }
1600 if (group_opts->tcp_md5_auth[0] != '\0') {
1601 csnprintfrr(buf, buf_len, " %s %s\n", PCEP_VTYSH_ARG_TCP_MD5,
1602 group_opts->tcp_md5_auth);
1603 lines++;
1604 }
1605 if (group_opts->draft07) {
1606 csnprintfrr(buf, buf_len, " %s\n",
1607 PCEP_VTYSH_ARG_SR_DRAFT07);
1608 lines++;
1609 }
1610 if (group_opts->pce_initiated) {
1611 csnprintfrr(buf, buf_len, " %s\n", PCEP_VTYSH_ARG_PCE_INIT);
1612 lines++;
1613 }
1614
1615 return lines;
1616 }
1617
1618 int pcep_cli_pce_config_write(struct vty *vty)
1619 {
1620 int lines = 0;
1621 char buf[1024] = "";
1622
1623 for (int i = 0; i < MAX_PCE; i++) {
1624 struct pce_opts_cli *pce_opts_cli = pcep_g->pce_opts_cli[i];
1625 if (pce_opts_cli == NULL) {
1626 continue;
1627 }
1628 struct pce_opts *pce_opts = &pce_opts_cli->pce_opts;
1629
1630 vty_out(vty, " pce %s\n", pce_opts->pce_name);
1631 if (IS_IPADDR_V6(&pce_opts->addr)) {
1632 vty_out(vty, " %s %s %pI6", PCEP_VTYSH_ARG_ADDRESS,
1633 PCEP_VTYSH_ARG_IPV6, &pce_opts->addr.ipaddr_v6);
1634 } else if (IS_IPADDR_V4(&pce_opts->addr)) {
1635 vty_out(vty, " address %s %pI4", PCEP_VTYSH_ARG_IP,
1636 &pce_opts->addr.ipaddr_v4);
1637 }
1638 if (pce_opts->port != PCEP_DEFAULT_PORT) {
1639 vty_out(vty, " %s %d", PCEP_VTYSH_ARG_PORT,
1640 pce_opts->port);
1641 }
1642 vty_out(vty, "%s\n", buf);
1643 lines += 2;
1644
1645 if (pce_opts_cli->config_group_name[0] != '\0') {
1646 vty_out(vty, " config %s\n",
1647 pce_opts_cli->config_group_name);
1648 lines++;
1649 }
1650
1651 /* Only display the values configured on the PCE, not the values
1652 * from its optional pce-config-group, nor the default values */
1653 lines += pcep_cli_print_pce_config(
1654 &pce_opts_cli->pce_config_group_opts, buf, sizeof(buf));
1655
1656 vty_out(vty, "%s", buf);
1657 buf[0] = '\0';
1658 }
1659
1660 return lines;
1661 }
1662
1663 int pcep_cli_pcep_pce_config_write(struct vty *vty)
1664 {
1665 int lines = 0;
1666 char buf[1024] = "";
1667
1668 for (int i = 0; i < MAX_PCE; i++) {
1669 struct pcep_config_group_opts *group_opts =
1670 pcep_g->config_group_opts[i];
1671 if (group_opts == NULL) {
1672 continue;
1673 }
1674
1675 vty_out(vty, " pce-config %s\n", group_opts->name);
1676 lines += 1;
1677
1678 lines +=
1679 pcep_cli_print_pce_config(group_opts, buf, sizeof(buf));
1680 vty_out(vty, "%s", buf);
1681 buf[0] = 0;
1682 }
1683
1684 return lines;
1685 }
1686
1687 /*
1688 * VTYSH command syntax definitions
1689 * The param names are taken from the path_pcep_cli_clippy.c generated file.
1690 */
1691
1692 DEFPY(show_debugging_pathd_pcep,
1693 show_debugging_pathd_pcep_cmd,
1694 "show debugging pathd-pcep",
1695 SHOW_STR
1696 "State of each debugging option\n"
1697 "pathd pcep module debugging\n")
1698 {
1699 vty_out(vty, "Pathd pcep debugging status:\n");
1700
1701 if (DEBUG_MODE_CHECK(&pcep_g->dbg, DEBUG_MODE_CONF)) {
1702 if (DEBUG_FLAGS_CHECK(&pcep_g->dbg, PCEP_DEBUG_MODE_BASIC))
1703 vty_out(vty, " Pathd pcep %s debugging is on\n",
1704 PCEP_VTYSH_ARG_BASIC);
1705 if (DEBUG_FLAGS_CHECK(&pcep_g->dbg, PCEP_DEBUG_MODE_PATH))
1706 vty_out(vty, " Pathd pcep %s debugging is on\n",
1707 PCEP_VTYSH_ARG_PATH);
1708 if (DEBUG_FLAGS_CHECK(&pcep_g->dbg, PCEP_DEBUG_MODE_PCEP))
1709 vty_out(vty, " Pathd pcep %s debugging is on\n",
1710 PCEP_VTYSH_ARG_MESSAGE);
1711 if (DEBUG_FLAGS_CHECK(&pcep_g->dbg, PCEP_DEBUG_MODE_PCEPLIB))
1712 vty_out(vty, " Pathd pcep %s debugging is on\n",
1713 PCEP_VTYSH_ARG_PCEPLIB);
1714 }
1715
1716 return CMD_SUCCESS;
1717 }
1718
1719 DEFPY(pcep_cli_debug,
1720 pcep_cli_debug_cmd,
1721 "[no] debug pathd pcep [basic]$basic_str [path]$path_str [message]$message_str [pceplib]$pceplib_str",
1722 NO_STR DEBUG_STR
1723 "pathd debugging\n"
1724 "pcep module debugging\n"
1725 "module basic debugging\n"
1726 "path structures debugging\n"
1727 "pcep message debugging\n"
1728 "pceplib debugging\n")
1729 {
1730 return path_pcep_cli_debug(vty, no, basic_str, path_str, message_str,
1731 pceplib_str);
1732 }
1733
1734 DEFPY(pcep_cli_show_srte_pcep_counters,
1735 pcep_cli_show_srte_pcep_counters_cmd,
1736 "show sr-te pcep counters",
1737 SHOW_STR
1738 "SR-TE info\n"
1739 "PCEP info\n"
1740 "PCEP counters\n")
1741 {
1742 return path_pcep_cli_show_srte_pcep_counters(vty);
1743 }
1744
1745 DEFPY_NOSH(
1746 pcep_cli_pcep,
1747 pcep_cli_pcep_cmd,
1748 "pcep",
1749 "PCEP configuration\n")
1750 {
1751 vty->node = PCEP_NODE;
1752 return CMD_SUCCESS;
1753 }
1754
1755 DEFPY_NOSH(
1756 pcep_cli_pcep_pce_config,
1757 pcep_cli_pcep_pce_config_cmd,
1758 "pce-config WORD$name",
1759 "Shared configuration\n"
1760 "Shared configuration name\n")
1761 {
1762 return path_pcep_cli_pcep_pce_config(vty, name);
1763 }
1764
1765 DEFPY(pcep_cli_pcep_no_pce_config,
1766 pcep_cli_pcep_no_pce_config_cmd,
1767 "no pce-config WORD$name",
1768 NO_STR
1769 "Shared configuration\n"
1770 "Shared configuration name\n")
1771 {
1772 return path_pcep_cli_pcep_pce_config_delete(vty, name);
1773 }
1774
1775 DEFPY(pcep_cli_show_srte_pcep_pce_config,
1776 pcep_cli_show_srte_pcep_pce_config_cmd,
1777 "show sr-te pcep pce-config [<default|WORD>$name]",
1778 SHOW_STR
1779 "SR-TE info\n"
1780 "PCEP info\n"
1781 "Show shared PCE configuration\n"
1782 "Show default hard-coded values\n"
1783 "Shared configuration name\n")
1784 {
1785 return path_pcep_cli_show_srte_pcep_pce_config(vty, name);
1786 }
1787
1788 DEFPY_NOSH(
1789 pcep_cli_pce,
1790 pcep_cli_pce_cmd,
1791 "pce WORD$name",
1792 "PCE configuration, address sub-config is mandatory\n"
1793 "PCE name\n")
1794 {
1795 return path_pcep_cli_pce(vty, name);
1796 }
1797
1798 DEFPY(pcep_cli_no_pce,
1799 pcep_cli_no_pce_cmd,
1800 "no pce WORD$name",
1801 NO_STR
1802 "PCE configuration, address sub-config is mandatory\n"
1803 "PCE name\n")
1804 {
1805 return path_pcep_cli_pce_delete(vty, name);
1806 }
1807
1808 DEFPY(pcep_cli_show_srte_pcep_pce,
1809 pcep_cli_show_srte_pcep_pce_cmd,
1810 "show sr-te pcep pce [WORD$name]",
1811 SHOW_STR
1812 "SR-TE info\n"
1813 "PCEP info\n"
1814 "Show detailed pce values\n"
1815 "pce name\n")
1816 {
1817 return path_pcep_cli_show_srte_pcep_pce(vty, name);
1818 }
1819
1820 DEFPY(pcep_cli_peer_sr_draft07,
1821 pcep_cli_peer_sr_draft07_cmd,
1822 "sr-draft07",
1823 "Configure PCC to send PCEP Open with SR draft07\n")
1824 {
1825 return path_pcep_cli_peer_sr_draft07(vty);
1826 }
1827
1828 DEFPY(pcep_cli_peer_pce_initiated,
1829 pcep_cli_peer_pce_initiated_cmd,
1830 "pce-initiated",
1831 "Configure PCC to accept PCE initiated LSPs\n")
1832 {
1833 return path_pcep_cli_peer_pce_initiated(vty);
1834 }
1835
1836 DEFPY(pcep_cli_peer_tcp_md5_auth,
1837 pcep_cli_peer_tcp_md5_auth_cmd,
1838 "tcp-md5-auth WORD",
1839 "Configure PCC TCP-MD5 RFC2385 Authentication\n"
1840 "TCP-MD5 Authentication string\n")
1841 {
1842 return path_pcep_cli_peer_tcp_md5_auth(vty, tcp_md5_auth);
1843 }
1844
1845 DEFPY(pcep_cli_peer_address,
1846 pcep_cli_peer_address_cmd,
1847 "address <ip A.B.C.D | ipv6 X:X::X:X> [port (1024-65535)]",
1848 "PCE IP Address configuration, mandatory configuration\n"
1849 "PCE IPv4 address\n"
1850 "Remote PCE server IPv4 address\n"
1851 "PCE IPv6 address\n"
1852 "Remote PCE server IPv6 address\n"
1853 "Remote PCE server port\n"
1854 "Remote PCE server port value\n")
1855 {
1856 return path_pcep_cli_peer_address(vty, ip_str, &ip, ipv6_str, &ipv6,
1857 port_str, port);
1858 }
1859
1860 DEFPY(pcep_cli_peer_source_address,
1861 pcep_cli_peer_source_address_cmd,
1862 "source-address [ip A.B.C.D | ipv6 X:X::X:X] [port (1024-65535)]",
1863 "PCE source IP Address configuration\n"
1864 "PCE source IPv4 address\n"
1865 "PCE source IPv4 address value\n"
1866 "PCE source IPv6 address\n"
1867 "PCE source IPv6 address value\n"
1868 "Source PCE server port\n"
1869 "Source PCE server port value\n")
1870 {
1871 return path_pcep_cli_peer_source_address(vty, ip_str, &ip, ipv6_str,
1872 &ipv6, port_str, port);
1873 }
1874
1875 DEFPY(pcep_cli_peer_pcep_pce_config_ref,
1876 pcep_cli_peer_pcep_pce_config_ref_cmd,
1877 "config WORD$name",
1878 "PCE shared configuration to use\n"
1879 "Shared configuration name\n")
1880 {
1881 return path_pcep_cli_peer_pcep_pce_config_ref(vty, name);
1882 }
1883
1884 DEFPY(pcep_cli_peer_timers,
1885 pcep_cli_peer_timers_cmd,
1886 "timer [keep-alive (1-63)] [min-peer-keep-alive (1-255)] [max-peer-keep-alive (1-255)] "
1887 "[dead-timer (4-255)] [min-peer-dead-timer (4-255)] [max-peer-dead-timer (4-255)] "
1888 "[pcep-request (1-120)] [session-timeout-interval (1-120)] [delegation-timeout (1-60)]",
1889 "PCE PCEP Session Timers configuration\n"
1890 "PCC Keep Alive Timer\n"
1891 "PCC Keep Alive Timer value in seconds\n"
1892 "Min Acceptable PCE Keep Alive Timer\n"
1893 "Min Acceptable PCE Keep Alive Timer value in seconds\n"
1894 "Max Acceptable PCE Keep Alive Timer\n"
1895 "Max Acceptable PCE Keep Alive Timer value in seconds\n"
1896 "PCC Dead Timer\n"
1897 "PCC Dead Timer value in seconds\n"
1898 "Min Acceptable PCE Dead Timer\n"
1899 "Min Acceptable PCE Dead Timer value in seconds\n"
1900 "Max Acceptable PCE Dead Timer\n"
1901 "Max Acceptable PCE Dead Timer value in seconds\n"
1902 "PCC PCEP Request Timer\n"
1903 "PCC PCEP Request Timer value in seconds\n"
1904 "PCC Session Timeout Interval\n"
1905 "PCC Session Timeout Interval value in seconds\n"
1906 "Multi-PCE delegation timeout\n"
1907 "Multi-PCE delegation timeout value in seconds\n")
1908 {
1909 return path_pcep_cli_peer_timers(
1910 vty, keep_alive_str, keep_alive, min_peer_keep_alive_str,
1911 min_peer_keep_alive, max_peer_keep_alive_str,
1912 max_peer_keep_alive, dead_timer_str, dead_timer,
1913 min_peer_dead_timer_str, min_peer_dead_timer,
1914 max_peer_dead_timer_str, max_peer_dead_timer, pcep_request_str,
1915 pcep_request, session_timeout_interval_str,
1916 session_timeout_interval, delegation_timeout_str,
1917 delegation_timeout);
1918 }
1919
1920 DEFPY_NOSH(
1921 pcep_cli_pcc,
1922 pcep_cli_pcc_cmd,
1923 "pcc",
1924 "PCC configuration\n")
1925 {
1926 return path_pcep_cli_pcc(vty);
1927 }
1928
1929 DEFPY(pcep_cli_no_pcc,
1930 pcep_cli_no_pcc_cmd,
1931 "no pcc",
1932 NO_STR
1933 "PCC configuration\n")
1934 {
1935 return path_pcep_cli_pcc_delete(vty);
1936 }
1937
1938 DEFPY(pcep_cli_pcc_pcc_msd,
1939 pcep_cli_pcc_pcc_msd_cmd,
1940 "msd (1-32)",
1941 "PCC maximum SID depth \n"
1942 "PCC maximum SID depth value\n")
1943 {
1944 return path_pcep_cli_pcc_pcc_msd(vty, msd_str, msd);
1945 }
1946
1947 DEFPY(pcep_cli_pcc_pcc_peer,
1948 pcep_cli_pcc_pcc_peer_cmd,
1949 "[no] peer WORD [precedence (1-255)]",
1950 NO_STR
1951 "PCC PCE peer\n"
1952 "PCC PCE name\n"
1953 "PCC Multi-PCE precedence\n"
1954 "PCE precedence\n")
1955 {
1956 if (no != NULL) {
1957 return path_pcep_cli_pcc_pcc_peer_delete(
1958 vty, peer, precedence_str, precedence);
1959 } else {
1960 return path_pcep_cli_pcc_pcc_peer(vty, peer, precedence_str,
1961 precedence);
1962 }
1963 }
1964
1965 DEFPY(pcep_cli_show_srte_pcc,
1966 pcep_cli_show_srte_pcc_cmd,
1967 "show sr-te pcep pcc",
1968 SHOW_STR
1969 "SR-TE info\n"
1970 "PCEP info\n"
1971 "Show current PCC configuration\n")
1972 {
1973 return path_pcep_cli_show_srte_pcep_pcc(vty);
1974 }
1975
1976 DEFPY(pcep_cli_show_srte_pcep_session,
1977 pcep_cli_show_srte_pcep_session_cmd,
1978 "show sr-te pcep session [WORD]$pce",
1979 SHOW_STR
1980 "SR-TE info\n"
1981 "PCEP info\n"
1982 "Show PCEP Session information\n"
1983 "PCE name\n")
1984 {
1985 return path_pcep_cli_show_srte_pcep_session(vty, pce);
1986 }
1987
1988 DEFPY(pcep_cli_clear_srte_pcep_session,
1989 pcep_cli_clear_srte_pcep_session_cmd,
1990 "clear sr-te pcep session [WORD]$pce",
1991 CLEAR_STR
1992 "SR-TE\n"
1993 "PCEP\n"
1994 "Reset PCEP connection\n"
1995 "PCE name\n")
1996 {
1997 return path_pcep_cli_clear_srte_pcep_session(vty, pce);
1998 }
1999
2000 void pcep_cli_init(void)
2001 {
2002 hook_register(nb_client_debug_config_write,
2003 pcep_cli_debug_config_write);
2004 hook_register(nb_client_debug_set_all, pcep_cli_debug_set_all);
2005
2006 memset(&pce_connections_g, 0, sizeof(pce_connections_g));
2007
2008 install_node(&pcep_node);
2009 install_node(&pcep_pcc_node);
2010 install_node(&pcep_pce_node);
2011 install_node(&pcep_pce_config_node);
2012
2013 install_default(PCEP_PCE_CONFIG_NODE);
2014 install_default(PCEP_PCE_NODE);
2015 install_default(PCEP_PCC_NODE);
2016 install_default(PCEP_NODE);
2017
2018 install_element(SR_TRAFFIC_ENG_NODE, &pcep_cli_pcep_cmd);
2019
2020 /* PCEP configuration group related configuration commands */
2021 install_element(PCEP_NODE, &pcep_cli_pcep_pce_config_cmd);
2022 install_element(PCEP_NODE, &pcep_cli_pcep_no_pce_config_cmd);
2023 install_element(PCEP_PCE_CONFIG_NODE,
2024 &pcep_cli_peer_source_address_cmd);
2025 install_element(PCEP_PCE_CONFIG_NODE, &pcep_cli_peer_timers_cmd);
2026 install_element(PCEP_PCE_CONFIG_NODE, &pcep_cli_peer_sr_draft07_cmd);
2027 install_element(PCEP_PCE_CONFIG_NODE, &pcep_cli_peer_pce_initiated_cmd);
2028 install_element(PCEP_PCE_CONFIG_NODE, &pcep_cli_peer_tcp_md5_auth_cmd);
2029
2030 /* PCE peer related configuration commands */
2031 install_element(PCEP_NODE, &pcep_cli_pce_cmd);
2032 install_element(PCEP_NODE, &pcep_cli_no_pce_cmd);
2033 install_element(PCEP_PCE_NODE, &pcep_cli_peer_address_cmd);
2034 install_element(PCEP_PCE_NODE, &pcep_cli_peer_source_address_cmd);
2035 install_element(PCEP_PCE_NODE, &pcep_cli_peer_pcep_pce_config_ref_cmd);
2036 install_element(PCEP_PCE_NODE, &pcep_cli_peer_timers_cmd);
2037 install_element(PCEP_PCE_NODE, &pcep_cli_peer_sr_draft07_cmd);
2038 install_element(PCEP_PCE_NODE, &pcep_cli_peer_pce_initiated_cmd);
2039 install_element(PCEP_PCE_NODE, &pcep_cli_peer_tcp_md5_auth_cmd);
2040
2041 /* PCC related configuration commands */
2042 install_element(ENABLE_NODE, &pcep_cli_show_srte_pcc_cmd);
2043 install_element(PCEP_NODE, &pcep_cli_pcc_cmd);
2044 install_element(PCEP_NODE, &pcep_cli_no_pcc_cmd);
2045 install_element(PCEP_PCC_NODE, &pcep_cli_pcc_pcc_peer_cmd);
2046 install_element(PCEP_PCC_NODE, &pcep_cli_pcc_pcc_msd_cmd);
2047
2048 /* Top commands */
2049 install_element(CONFIG_NODE, &pcep_cli_debug_cmd);
2050 install_element(ENABLE_NODE, &pcep_cli_debug_cmd);
2051 install_element(ENABLE_NODE, &show_debugging_pathd_pcep_cmd);
2052 install_element(ENABLE_NODE, &pcep_cli_show_srte_pcep_counters_cmd);
2053 install_element(ENABLE_NODE, &pcep_cli_show_srte_pcep_pce_config_cmd);
2054 install_element(ENABLE_NODE, &pcep_cli_show_srte_pcep_pce_cmd);
2055 install_element(ENABLE_NODE, &pcep_cli_show_srte_pcep_session_cmd);
2056 install_element(ENABLE_NODE, &pcep_cli_clear_srte_pcep_session_cmd);
2057 }