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