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