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