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