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