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