]> git.proxmox.com Git - mirror_frr.git/blame - pathd/path_cli.c
build, vtysh: extract vtysh commands from .xref
[mirror_frr.git] / pathd / path_cli.c
CommitLineData
4d7b695d
SM
1/*
2 * Copyright (C) 2020 NetDEF, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; see the file COPYING; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
1f8031f7
DL
19#include <zebra.h>
20
4d7b695d
SM
21#include <float.h>
22#include <math.h>
23#include <zebra.h>
24
c7479286 25#include "memory.h"
4d7b695d
SM
26#include "log.h"
27#include "command.h"
28#include "mpls.h"
29#include "northbound_cli.h"
30#include "termtable.h"
31
32#include "pathd/pathd.h"
33#include "pathd/path_nb.h"
4d7b695d 34#include "pathd/path_cli_clippy.c"
f2b9485d 35#include "pathd/path_ted.h"
4d7b695d
SM
36
37#define XPATH_MAXATTRSIZE 64
38#define XPATH_MAXKEYSIZE 42
39#define XPATH_POLICY_BASELEN 100
40#define XPATH_POLICY_MAXLEN (XPATH_POLICY_BASELEN + XPATH_MAXATTRSIZE)
41#define XPATH_CANDIDATE_BASELEN (XPATH_POLICY_BASELEN + XPATH_MAXKEYSIZE)
42#define XPATH_CANDIDATE_MAXLEN (XPATH_CANDIDATE_BASELEN + XPATH_MAXATTRSIZE)
43
44
45static int config_write_segment_routing(struct vty *vty);
f2b9485d
JG
46static int segment_list_has_src_dst(
47 struct vty *vty, char *xpath, long index, const char *index_str,
48 struct in_addr adj_src_ipv4, struct in_addr adj_dst_ipv4,
49 struct in6_addr adj_src_ipv6, struct in6_addr adj_dst_ipv6,
50 const char *adj_src_ipv4_str, const char *adj_dst_ipv4_str,
51 const char *adj_src_ipv6_str, const char *adj_dst_ipv6_str);
52static int segment_list_has_prefix(
53 struct vty *vty, char *xpath, long index, const char *index_str,
54 const struct prefix_ipv4 *prefix_ipv4, const char *prefix_ipv4_str,
55 const struct prefix_ipv6 *prefix_ipv6, const char *prefix_ipv6_str,
56 const char *has_algo, long algo, const char *algo_str,
57 const char *has_iface_id, long iface_id, const char *iface_id_str);
4d7b695d 58
bf8d3d6a 59DEFINE_MTYPE_STATIC(PATHD, PATH_CLI, "Client");
4d7b695d 60
ac9103aa
IR
61DEFINE_HOOK(pathd_srte_config_write, (struct vty *vty), (vty));
62
4d7b695d
SM
63/* Vty node structures. */
64static struct cmd_node segment_routing_node = {
65 .name = "segment-routing",
66 .node = SEGMENT_ROUTING_NODE,
67 .parent_node = CONFIG_NODE,
68 .prompt = "%s(config-sr)# ",
69 .config_write = config_write_segment_routing,
70};
71
72static struct cmd_node sr_traffic_eng_node = {
73 .name = "sr traffic-eng",
74 .node = SR_TRAFFIC_ENG_NODE,
75 .parent_node = SEGMENT_ROUTING_NODE,
76 .prompt = "%s(config-sr-te)# ",
4d7b695d
SM
77};
78
79static struct cmd_node srte_segment_list_node = {
80 .name = "srte segment-list",
81 .node = SR_SEGMENT_LIST_NODE,
82 .parent_node = SR_TRAFFIC_ENG_NODE,
83 .prompt = "%s(config-sr-te-segment-list)# ",
4d7b695d
SM
84};
85
86static struct cmd_node srte_policy_node = {
87 .name = "srte policy",
88 .node = SR_POLICY_NODE,
89 .parent_node = SR_TRAFFIC_ENG_NODE,
90 .prompt = "%s(config-sr-te-policy)# ",
4d7b695d
SM
91};
92
93static struct cmd_node srte_candidate_dyn_node = {
94 .name = "srte candidate-dyn",
95 .node = SR_CANDIDATE_DYN_NODE,
96 .parent_node = SR_POLICY_NODE,
97 .prompt = "%s(config-sr-te-candidate)# ",
98};
99
100
101/*
102 * Show SR-TE info
103 */
104DEFPY(show_srte_policy,
105 show_srte_policy_cmd,
106 "show sr-te policy",
107 SHOW_STR
108 "SR-TE info\n"
109 "SR-TE Policy\n")
110{
111 struct ttable *tt;
112 struct srte_policy *policy;
113 char *table;
114
115 if (RB_EMPTY(srte_policy_head, &srte_policies)) {
116 vty_out(vty, "No SR Policies to display.\n\n");
117 return CMD_SUCCESS;
118 }
119
120 /* Prepare table. */
121 tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
122 ttable_add_row(tt, "Endpoint|Color|Name|BSID|Status");
123 tt->style.cell.rpad = 2;
124 tt->style.corner = '+';
125 ttable_restyle(tt);
126 ttable_rowseps(tt, 0, BOTTOM, true, '-');
127
128 RB_FOREACH (policy, srte_policy_head, &srte_policies) {
129 char endpoint[46];
130 char binding_sid[16] = "-";
131
132 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
133 if (policy->binding_sid != MPLS_LABEL_NONE)
134 snprintf(binding_sid, sizeof(binding_sid), "%u",
135 policy->binding_sid);
136
137 ttable_add_row(tt, "%s|%u|%s|%s|%s", endpoint, policy->color,
138 policy->name, binding_sid,
139 policy->status == SRTE_POLICY_STATUS_UP
140 ? "Active"
141 : "Inactive");
142 }
143
144 /* Dump the generated table. */
145 table = ttable_dump(tt, "\n");
146 vty_out(vty, "%s\n", table);
147 XFREE(MTYPE_TMP, table);
148
149 ttable_del(tt);
150
151 return CMD_SUCCESS;
152}
153
f2b9485d 154
4d7b695d
SM
155/*
156 * Show detailed SR-TE info
157 */
158DEFPY(show_srte_policy_detail,
159 show_srte_policy_detail_cmd,
160 "show sr-te policy detail",
161 SHOW_STR
162 "SR-TE info\n"
163 "SR-TE Policy\n"
164 "Show a detailed summary\n")
165{
166 struct srte_policy *policy;
167
168 if (RB_EMPTY(srte_policy_head, &srte_policies)) {
169 vty_out(vty, "No SR Policies to display.\n\n");
170 return CMD_SUCCESS;
171 }
172
173 vty_out(vty, "\n");
174 RB_FOREACH (policy, srte_policy_head, &srte_policies) {
175 struct srte_candidate *candidate;
176 char endpoint[46];
177 char binding_sid[16] = "-";
178 char *segment_list_info;
179 static char undefined_info[] = "(undefined)";
180 static char created_by_pce_info[] = "(created by PCE)";
181
182
183 ipaddr2str(&policy->endpoint, endpoint, sizeof(endpoint));
184 if (policy->binding_sid != MPLS_LABEL_NONE)
185 snprintf(binding_sid, sizeof(binding_sid), "%u",
186 policy->binding_sid);
187 vty_out(vty,
188 "Endpoint: %s Color: %u Name: %s BSID: %s Status: %s\n",
189 endpoint, policy->color, policy->name, binding_sid,
190 policy->status == SRTE_POLICY_STATUS_UP ? "Active"
191 : "Inactive");
192
193 RB_FOREACH (candidate, srte_candidate_head,
194 &policy->candidate_paths) {
195 struct srte_segment_list *segment_list;
196
197 segment_list = candidate->lsp->segment_list;
198 if (segment_list == NULL)
199 segment_list_info = undefined_info;
200 else if (segment_list->protocol_origin
201 == SRTE_ORIGIN_PCEP)
202 segment_list_info = created_by_pce_info;
203 else
204 segment_list_info =
205 candidate->lsp->segment_list->name;
206
207 vty_out(vty,
208 " %s Preference: %d Name: %s Type: %s Segment-List: %s Protocol-Origin: %s\n",
209 CHECK_FLAG(candidate->flags, F_CANDIDATE_BEST)
210 ? "*"
211 : " ",
212 candidate->preference, candidate->name,
213 candidate->type == SRTE_CANDIDATE_TYPE_EXPLICIT
214 ? "explicit"
215 : "dynamic",
216 segment_list_info,
217 srte_origin2str(
218 candidate->lsp->protocol_origin));
219 }
220
221 vty_out(vty, "\n");
222 }
223
224 return CMD_SUCCESS;
225}
226
227DEFPY_NOSH(
228 segment_routing_list,
229 segment_routing_cmd,
230 "segment-routing",
231 "Configure segment routing\n")
232{
233 VTY_PUSH_CONTEXT_NULL(SEGMENT_ROUTING_NODE);
234 return CMD_SUCCESS;
235}
236
237DEFPY_NOSH(
238 sr_traffic_eng_list,
239 sr_traffic_eng_cmd,
240 "traffic-eng",
241 "Configure SR traffic engineering\n")
242{
243 VTY_PUSH_CONTEXT_NULL(SR_TRAFFIC_ENG_NODE);
244 return CMD_SUCCESS;
245}
246
247/*
248 * XPath: /frr-pathd:pathd/srte/segment-list
249 */
250DEFPY_NOSH(
251 srte_segment_list,
252 srte_segment_list_cmd,
253 "segment-list WORD$name",
254 "Segment List\n"
255 "Segment List Name\n")
256{
257 char xpath[XPATH_MAXLEN];
258 int ret;
259
260 snprintf(xpath, sizeof(xpath),
261 "/frr-pathd:pathd/srte/segment-list[name='%s']", name);
262 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
263
264 snprintf(xpath, sizeof(xpath),
265 "/frr-pathd:pathd/srte/segment-list[name='%s']/protocol-origin",
266 name);
267 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "local");
268
269 snprintf(xpath, sizeof(xpath),
270 "/frr-pathd:pathd/srte/segment-list[name='%s']/originator", name);
271 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, "config");
272
273 ret = nb_cli_apply_changes(vty, NULL);
274 if (ret == CMD_SUCCESS) {
275 snprintf(xpath, sizeof(xpath),
276 "/frr-pathd:pathd/srte/segment-list[name='%s']", name);
277 VTY_PUSH_XPATH(SR_SEGMENT_LIST_NODE, xpath);
278 }
279
280 return ret;
281}
282
283DEFPY(srte_no_segment_list,
284 srte_no_segment_list_cmd,
285 "no segment-list WORD$name",
286 NO_STR
287 "Segment List\n"
288 "Segment List Name\n")
289{
290 char xpath[XPATH_MAXLEN];
291
292 snprintf(xpath, sizeof(xpath),
293 "/frr-pathd:pathd/srte/segment-list[name='%s']", name);
294 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
295
296 return nb_cli_apply_changes(vty, NULL);
297}
298
25605051 299void cli_show_srte_segment_list(struct vty *vty, const struct lyd_node *dnode,
4d7b695d
SM
300 bool show_defaults)
301{
302 vty_out(vty, " segment-list %s\n",
303 yang_dnode_get_string(dnode, "./name"));
304}
305
25605051
IR
306void cli_show_srte_segment_list_end(struct vty *vty,
307 const struct lyd_node *dnode)
07679ad9
IR
308{
309 vty_out(vty, " exit\n");
310}
311
f2b9485d
JG
312static int segment_list_has_src_dst(
313 struct vty *vty, char *xpath, long index, const char *index_str,
314 struct in_addr adj_src_ipv4, struct in_addr adj_dst_ipv4,
315 struct in6_addr adj_src_ipv6, struct in6_addr adj_dst_ipv6,
316 const char *adj_src_ipv4_str, const char *adj_dst_ipv4_str,
317 const char *adj_src_ipv6_str, const char *adj_dst_ipv6_str)
318{
319 const char *node_src_id;
320 uint32_t ted_sid = MPLS_LABEL_NONE;
321
322 struct ipaddr ip_src = {};
323 struct ipaddr ip_dst = {};
324 if (adj_src_ipv4_str != NULL) {
325 ip_src.ipa_type = IPADDR_V4;
326 ip_src.ip._v4_addr = adj_src_ipv4;
327 ip_dst.ipa_type = IPADDR_V4;
328 ip_dst.ip._v4_addr = adj_dst_ipv4;
329 } else if (adj_src_ipv6_str != NULL) {
330 ip_src.ipa_type = IPADDR_V6;
331 ip_src.ip._v6_addr = adj_src_ipv6;
332 ip_dst.ipa_type = IPADDR_V6;
333 ip_dst.ip._v6_addr = adj_dst_ipv6;
334 } else {
335 return CMD_ERR_NO_MATCH;
336 }
337 ted_sid = path_ted_query_type_f(&ip_src, &ip_dst);
338 if (ted_sid == MPLS_LABEL_NONE) {
339 zlog_warn(
340 "%s: [rcv ted] CLI NOT FOUND Continue query_type_f SRC (%pIA) DST (%pIA)!",
341 __func__, &ip_src, &ip_dst);
342 }
343 /* type */
344 snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/type",
345 index_str);
346 if (adj_src_ipv4_str != NULL) {
347 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
348 "ipv4_adjacency");
349 node_src_id = adj_src_ipv4_str;
350 } else if (adj_src_ipv6_str != NULL) {
351 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
352 "ipv6_adjacency");
353 node_src_id = adj_src_ipv6_str;
e81a74a6
DS
354 } else {
355 /*
356 * This is just to make the compiler happy about
357 * node_src_id not being initialized. This
358 * should never happen unless we change the cli
359 * function.
360 */
361 assert(!"We must have a adj_src_ipv4_str or a adj_src_ipv6_str");
f2b9485d 362 }
e81a74a6 363
f2b9485d
JG
364 /* addresses */
365 snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/local-address",
366 index_str);
367 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, node_src_id);
368 snprintf(xpath, XPATH_MAXLEN,
369 "./segment[index='%s']/nai/remote-address", index_str);
370 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
371 adj_dst_ipv4_str ? adj_dst_ipv4_str
372 : adj_dst_ipv6_str);
373 return CMD_SUCCESS;
374}
375int segment_list_has_prefix(
376 struct vty *vty, char *xpath, long index, const char *index_str,
377 const struct prefix_ipv4 *prefix_ipv4, const char *prefix_ipv4_str,
378 const struct prefix_ipv6 *prefix_ipv6, const char *prefix_ipv6_str,
379 const char *has_algo, long algo, const char *algo_str,
380 const char *has_iface_id, long iface_id, const char *iface_id_str)
381{
382 char buf_prefix[INET6_ADDRSTRLEN];
383
384 uint32_t ted_sid = MPLS_LABEL_NONE;
385 struct prefix prefix_cli = {};
386 struct ipaddr pre_ipaddr = {};
387 /* prefix with algorithm or local interface id */
388 /* Type */
389 snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/type",
390 index_str);
391 if (has_iface_id != NULL) {
392 if (prefix_ipv4_str != NULL) {
393 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
394 "ipv4_local_iface");
395 } else if (prefix_ipv6_str != NULL) {
396 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
397 "ipv6_local_iface");
398 } else {
399 return CMD_ERR_NO_MATCH;
400 }
401 } else {
402 if (prefix_ipv4_str != NULL) {
403 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
404 "ipv4_algo");
405 } else if (prefix_ipv6_str != NULL) {
406 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
407 "ipv6_algo");
408 } else {
409 return CMD_ERR_NO_MATCH;
410 }
411 }
412 /* Prefix */
413 if (prefix_ipv4_str != NULL) {
414 if (!str2prefix(prefix_ipv4_str, &prefix_cli)) {
415 vty_out(vty, "%% Malformed prefix\n");
416 return CMD_WARNING_CONFIG_FAILED;
417 }
418 inet_ntop(AF_INET, &prefix_cli.u.prefix4, buf_prefix,
419 sizeof(buf_prefix));
420 pre_ipaddr.ipa_type = IPADDR_V4;
421 pre_ipaddr.ip._v4_addr = prefix_cli.u.prefix4;
422 } else if (prefix_ipv6_str != NULL) {
423 if (!str2prefix(prefix_ipv6_str, &prefix_cli)) {
424 vty_out(vty, "%% Malformed prefix\n");
425 return CMD_WARNING_CONFIG_FAILED;
426 }
427 inet_ntop(AF_INET6, &prefix_cli.u.prefix6, buf_prefix,
428 sizeof(buf_prefix));
429 pre_ipaddr.ipa_type = IPADDR_V6;
430 pre_ipaddr.ip._v6_addr = prefix_cli.u.prefix6;
f2b9485d
JG
431 }
432 snprintf(xpath, XPATH_MAXLEN, "./segment[index='%s']/nai/local-address",
433 index_str);
434 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, buf_prefix);
435 snprintf(xpath, XPATH_MAXLEN,
436 "./segment[index='%s']/nai/local-prefix-len", index_str);
437 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
438 prefix_ipv4_str
439 ? strchr(prefix_ipv4_str, '/') + 1
440 : strchr(prefix_ipv6_str, '/') + 1);
441 /* Alg / Iface */
442 if (has_algo != NULL) {
443 snprintf(xpath, XPATH_MAXLEN,
444 "./segment[index='%s']/nai/algorithm", index_str);
445 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, algo_str);
446 } else {
447 if (has_iface_id != NULL) {
448 snprintf(xpath, XPATH_MAXLEN,
449 "./segment[index='%s']/nai/local-interface",
450 index_str);
451 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
452 iface_id_str);
453 }
454 }
455 if (has_algo != NULL) {
456 ted_sid = path_ted_query_type_c(&prefix_cli, algo);
457 if (ted_sid == MPLS_LABEL_NONE) {
458 zlog_err(
459 "%s: [rcv ted] CLI NOT FOUND Continue query_type_c PREFIX (%pIA/%d) ALGO (%ld) sid:(%d)!",
460 __func__, &pre_ipaddr, prefix_cli.prefixlen,
461 algo, ted_sid);
462 }
463 }
464 if (has_iface_id != NULL) {
465 ted_sid = path_ted_query_type_e(&prefix_cli, iface_id);
466 if (ted_sid == MPLS_LABEL_NONE) {
467 zlog_err(
468 "%s: [rcv ted] CLI NOT FOUND Continue query_type_e PREFIX (%pIA/%d) IFACE (%ld) sid:(%d)!",
469 __func__, &pre_ipaddr, prefix_cli.prefixlen,
470 iface_id, ted_sid);
471 }
472 }
473 return CMD_SUCCESS;
474}
4d7b695d
SM
475/*
476 * XPath: /frr-pathd:pathd/srte/segment-list/segment
477 */
f2b9485d
JG
478/* clang-format off */
479DEFPY(srte_segment_list_segment, srte_segment_list_segment_cmd,
480 "index (0-4294967295)$index <[mpls$has_mpls_label label (16-1048575)$label] "
481 "|"
4d7b695d 482 "[nai$has_nai <"
f2b9485d
JG
483 "prefix <A.B.C.D/M$prefix_ipv4|X:X::X:X/M$prefix_ipv6>"
484 "<algorithm$has_algo (0-1)$algo| iface$has_iface_id (0-4294967295)$iface_id>"
485 "| adjacency$has_adj "
486 "<A.B.C.D$adj_src_ipv4 A.B.C.D$adj_dst_ipv4|X:X::X:X$adj_src_ipv6 X:X::X:X$adj_dst_ipv6>"
487 ">]"
488 ">",
4d7b695d
SM
489 "Index\n"
490 "Index Value\n"
491 "MPLS or IP Label\n"
492 "Label\n"
493 "Label Value\n"
494 "Segment NAI\n"
f2b9485d
JG
495 "NAI prefix identifier\n"
496 "NAI IPv4 prefix identifier\n"
497 "NAI IPv6 prefix identifier\n"
498 "IGP Algorithm\n"
499 "Algorithm Value SPF or Strict-SPF\n"
500 "Interface Id\n"
501 "Interface Value\n"
502 "ADJ identifier\n"
503 "ADJ IPv4 src identifier\n"
504 "ADJ IPv4 dst identifier\n"
505 "ADJ IPv6 src identifier\n"
506 "ADJ IPv6 dst identifier\n")
507/* clang-format on */
4d7b695d
SM
508{
509 char xpath[XPATH_MAXLEN];
f2b9485d
JG
510 int status = CMD_SUCCESS;
511
4d7b695d
SM
512
513 snprintf(xpath, sizeof(xpath), "./segment[index='%s']", index_str);
514 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
515
f2b9485d 516 if (has_mpls_label != NULL) {
4d7b695d 517 snprintf(xpath, sizeof(xpath),
f2b9485d
JG
518 "./segment[index='%s']/sid-value", index_str);
519 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, label_str);
520 return nb_cli_apply_changes(vty, NULL);
521 }
522
523 if (has_adj != NULL) {
524 status = segment_list_has_src_dst(vty, xpath, index, index_str,
525 adj_src_ipv4, adj_dst_ipv4,
526 adj_src_ipv6, adj_dst_ipv6,
527 adj_src_ipv4_str, adj_dst_ipv4_str,
a38d5b7a 528 adj_src_ipv6_str, adj_dst_ipv6_str);
f2b9485d
JG
529 if (status != CMD_SUCCESS)
530 return status;
4d7b695d 531 } else {
ac57e2c9 532 status = segment_list_has_prefix(
f2b9485d
JG
533 vty, xpath, index, index_str, prefix_ipv4,
534 prefix_ipv4_str, prefix_ipv6, prefix_ipv6_str, has_algo,
535 algo, algo_str, has_iface_id, iface_id, iface_id_str);
536 if (status != CMD_SUCCESS)
537 return status;
4d7b695d
SM
538 }
539
540 return nb_cli_apply_changes(vty, NULL);
541}
542
543DEFPY(srte_segment_list_no_segment,
544 srte_segment_list_no_segment_cmd,
545 "no index (0-4294967295)$index",
546 NO_STR
547 "Index\n"
548 "Index Value\n")
549{
550 char xpath[XPATH_MAXLEN];
551
552 snprintf(xpath, sizeof(xpath), "./segment[index='%s']", index_str);
553 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
554
555 return nb_cli_apply_changes(vty, NULL);
556}
557
558void cli_show_srte_segment_list_segment(struct vty *vty,
25605051 559 const struct lyd_node *dnode,
4d7b695d
SM
560 bool show_defaults)
561{
882bae36 562 vty_out(vty, " index %s", yang_dnode_get_string(dnode, "./index"));
f2b9485d
JG
563 if (yang_dnode_exists(dnode, "./sid-value")) {
564 vty_out(vty, " mpls label %s",
565 yang_dnode_get_string(dnode, "./sid-value"));
566 }
4d7b695d
SM
567 if (yang_dnode_exists(dnode, "./nai")) {
568 struct ipaddr addr;
f2b9485d
JG
569 struct ipaddr addr_rmt;
570
4d7b695d
SM
571 switch (yang_dnode_get_enum(dnode, "./nai/type")) {
572 case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE:
f2b9485d
JG
573 case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE:
574 case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM:
4d7b695d 575 yang_dnode_get_ip(&addr, dnode, "./nai/local-address");
f2b9485d 576 vty_out(vty, " nai prefix %pI4", &addr.ipaddr_v4);
4d7b695d
SM
577 break;
578 case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE:
f2b9485d
JG
579 case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE:
580 case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM:
4d7b695d 581 yang_dnode_get_ip(&addr, dnode, "./nai/local-address");
f2b9485d
JG
582 vty_out(vty, " nai prefix %pI6", &addr.ipaddr_v6);
583 break;
584 case SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY:
585 yang_dnode_get_ip(&addr, dnode, "./nai/local-address");
586 yang_dnode_get_ip(&addr_rmt, dnode,
587 "./nai/remote-address");
588 vty_out(vty, " nai adjacency %pI4", &addr.ipaddr_v4);
589 vty_out(vty, " %pI4", &addr_rmt.ipaddr_v4);
590 break;
591 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY:
592 yang_dnode_get_ip(&addr, dnode, "./nai/local-address");
593 yang_dnode_get_ip(&addr_rmt, dnode,
594 "./nai/remote-address");
595 vty_out(vty, " nai adjacency %pI6", &addr.ipaddr_v6);
596 vty_out(vty, " %pI6", &addr_rmt.ipaddr_v6);
4d7b695d
SM
597 break;
598 default:
599 break;
600 }
f2b9485d
JG
601 if (yang_dnode_exists(dnode, "./nai/local-prefix-len")) {
602 vty_out(vty, "/%s",
603 yang_dnode_get_string(
604 dnode, "./nai/local-prefix-len"));
605 }
606 if (yang_dnode_exists(dnode, "./nai/local-interface")) {
607 vty_out(vty, " iface %s",
608 yang_dnode_get_string(dnode,
609 "./nai/local-interface"));
610 }
611 if (yang_dnode_exists(dnode, "./nai/algorithm")) {
612 vty_out(vty, " algorithm %s",
613 yang_dnode_get_string(dnode,
614 "./nai/algorithm"));
615 }
4d7b695d
SM
616 }
617 vty_out(vty, "\n");
618}
619
620/*
621 * XPath: /frr-pathd:pathd/policy
622 */
623DEFPY_NOSH(
624 srte_policy,
625 srte_policy_cmd,
626 "policy color (0-4294967295)$num endpoint <A.B.C.D|X:X::X:X>$endpoint",
627 "Segment Routing Policy\n"
628 "SR Policy color\n"
629 "SR Policy color value\n"
630 "SR Policy endpoint\n"
631 "SR Policy endpoint IPv4 address\n"
632 "SR Policy endpoint IPv6 address\n")
633{
634 char xpath[XPATH_POLICY_BASELEN];
635 int ret;
636
637 snprintf(xpath, sizeof(xpath),
638 "/frr-pathd:pathd/srte/policy[color='%s'][endpoint='%s']",
639 num_str, endpoint_str);
640 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
641
642 ret = nb_cli_apply_changes(vty, NULL);
643 if (ret == CMD_SUCCESS)
644 VTY_PUSH_XPATH(SR_POLICY_NODE, xpath);
645
646 return ret;
647}
648
649DEFPY(srte_no_policy,
650 srte_no_policy_cmd,
651 "no policy color (0-4294967295)$num endpoint <A.B.C.D|X:X::X:X>$endpoint",
652 NO_STR
653 "Segment Routing Policy\n"
654 "SR Policy color\n"
655 "SR Policy color value\n"
656 "SR Policy endpoint\n"
657 "SR Policy endpoint IPv4 address\n"
658 "SR Policy endpoint IPv6 address\n")
659{
660 char xpath[XPATH_POLICY_BASELEN];
661
662 snprintf(xpath, sizeof(xpath),
663 "/frr-pathd:pathd/srte/policy[color='%s'][endpoint='%s']",
664 num_str, endpoint_str);
665 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
666
667 return nb_cli_apply_changes(vty, NULL);
668}
669
25605051 670void cli_show_srte_policy(struct vty *vty, const struct lyd_node *dnode,
4d7b695d
SM
671 bool show_defaults)
672{
673 vty_out(vty, " policy color %s endpoint %s\n",
674 yang_dnode_get_string(dnode, "./color"),
675 yang_dnode_get_string(dnode, "./endpoint"));
676}
677
25605051 678void cli_show_srte_policy_end(struct vty *vty, const struct lyd_node *dnode)
07679ad9
IR
679{
680 vty_out(vty, " exit\n");
681}
682
4d7b695d
SM
683/*
684 * XPath: /frr-pathd:pathd/srte/policy/name
685 */
686DEFPY(srte_policy_name,
687 srte_policy_name_cmd,
688 "name WORD$name",
689 "Segment Routing Policy name\n"
690 "SR Policy name value\n")
691{
692 nb_cli_enqueue_change(vty, "./name", NB_OP_CREATE, name);
693
694 return nb_cli_apply_changes(vty, NULL);
695}
696
697DEFPY(srte_policy_no_name,
698 srte_policy_no_name_cmd,
699 "no name [WORD]",
700 NO_STR
701 "Segment Routing Policy name\n"
702 "SR Policy name value\n")
703{
704 nb_cli_enqueue_change(vty, "./name", NB_OP_DESTROY, NULL);
705
706 return nb_cli_apply_changes(vty, NULL);
707}
708
709
25605051
IR
710void cli_show_srte_policy_name(struct vty *vty, const struct lyd_node *dnode,
711 bool show_defaults)
4d7b695d
SM
712{
713 vty_out(vty, " name %s\n", yang_dnode_get_string(dnode, NULL));
714}
715
716/*
717 * XPath: /frr-pathd:pathd/srte/policy/binding-sid
718 */
719DEFPY(srte_policy_binding_sid,
720 srte_policy_binding_sid_cmd,
721 "binding-sid (16-1048575)$label",
722 "Segment Routing Policy Binding-SID\n"
723 "SR Policy Binding-SID label\n")
724{
725 nb_cli_enqueue_change(vty, "./binding-sid", NB_OP_CREATE, label_str);
726
727 return nb_cli_apply_changes(vty, NULL);
728}
729
730DEFPY(srte_policy_no_binding_sid,
731 srte_policy_no_binding_sid_cmd,
732 "no binding-sid [(16-1048575)]",
733 NO_STR
734 "Segment Routing Policy Binding-SID\n"
735 "SR Policy Binding-SID label\n")
736{
737 nb_cli_enqueue_change(vty, "./binding-sid", NB_OP_DESTROY, NULL);
738
739 return nb_cli_apply_changes(vty, NULL);
740}
741
742void cli_show_srte_policy_binding_sid(struct vty *vty,
25605051 743 const struct lyd_node *dnode,
4d7b695d
SM
744 bool show_defaults)
745{
746 vty_out(vty, " binding-sid %s\n", yang_dnode_get_string(dnode, NULL));
747}
748
749/*
750 * XPath: /frr-pathd:pathd/srte/policy/candidate-path
751 */
752DEFPY(srte_policy_candidate_exp,
753 srte_policy_candidate_exp_cmd,
754 "candidate-path preference (0-4294967295)$preference name WORD$name \
755 explicit segment-list WORD$list_name",
756 "Segment Routing Policy Candidate Path\n"
757 "Segment Routing Policy Candidate Path Preference\n"
758 "Administrative Preference\n"
759 "Segment Routing Policy Candidate Path Name\n"
760 "Symbolic Name\n"
761 "Explicit Path\n"
762 "List of SIDs\n"
763 "Name of the Segment List\n")
764{
765 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, preference_str);
766 nb_cli_enqueue_change(vty, "./name", NB_OP_MODIFY, name);
767 nb_cli_enqueue_change(vty, "./protocol-origin", NB_OP_MODIFY, "local");
768 nb_cli_enqueue_change(vty, "./originator", NB_OP_MODIFY, "config");
769 nb_cli_enqueue_change(vty, "./type", NB_OP_MODIFY, "explicit");
770 nb_cli_enqueue_change(vty, "./segment-list-name", NB_OP_MODIFY,
771 list_name);
772 return nb_cli_apply_changes(vty, "./candidate-path[preference='%s']",
773 preference_str);
774}
775
776DEFPY_NOSH(
777 srte_policy_candidate_dyn,
778 srte_policy_candidate_dyn_cmd,
779 "candidate-path preference (0-4294967295)$preference name WORD$name dynamic",
780 "Segment Routing Policy Candidate Path\n"
781 "Segment Routing Policy Candidate Path Preference\n"
782 "Administrative Preference\n"
783 "Segment Routing Policy Candidate Path Name\n"
784 "Symbolic Name\n"
785 "Dynamic Path\n")
786{
938b2b79 787 char xpath[XPATH_MAXLEN + XPATH_CANDIDATE_BASELEN];
4d7b695d
SM
788 int ret;
789
790 snprintf(xpath, sizeof(xpath), "%s/candidate-path[preference='%s']",
791 VTY_CURR_XPATH, preference_str);
792
793 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, preference_str);
794 nb_cli_enqueue_change(vty, "./name", NB_OP_MODIFY, name);
795 nb_cli_enqueue_change(vty, "./protocol-origin", NB_OP_MODIFY, "local");
796 nb_cli_enqueue_change(vty, "./originator", NB_OP_MODIFY, "config");
797 nb_cli_enqueue_change(vty, "./type", NB_OP_MODIFY, "dynamic");
798 ret = nb_cli_apply_changes(vty, "./candidate-path[preference='%s']",
799 preference_str);
800
801 if (ret == CMD_SUCCESS)
802 VTY_PUSH_XPATH(SR_CANDIDATE_DYN_NODE, xpath);
803
804 return ret;
805}
806
807DEFPY(srte_candidate_bandwidth,
808 srte_candidate_bandwidth_cmd,
809 "bandwidth BANDWIDTH$value [required$required]",
810 "Define a bandwidth constraint\n"
811 "Bandwidth value\n"
812 "Required constraint\n")
813{
814 nb_cli_enqueue_change(vty, "./constraints/bandwidth/required",
815 NB_OP_MODIFY, required ? "true" : "false");
816 nb_cli_enqueue_change(vty, "./constraints/bandwidth/value",
817 NB_OP_MODIFY, value);
818 return nb_cli_apply_changes(vty, NULL);
819}
820
821DEFPY(srte_candidate_no_bandwidth,
822 srte_candidate_no_bandwidth_cmd,
823 "no bandwidth [BANDWIDTH$value] [required$required]",
824 NO_STR
825 "Remove a bandwidth constraint\n"
826 "Bandwidth value\n"
827 "Required constraint\n")
828{
829 nb_cli_enqueue_change(vty, "./constraints/bandwidth", NB_OP_DESTROY,
830 NULL);
831 return nb_cli_apply_changes(vty, NULL);
832}
833
839e6ce5
JG
834DEFPY(srte_candidate_affinity_filter, srte_candidate_affinity_filter_cmd,
835 "affinity <exclude-any|include-any|include-all>$type BITPATTERN$value",
4d7b695d
SM
836 "Affinity constraint\n"
837 "Exclude any matching link\n"
838 "Include any matching link\n"
839 "Include all matching links\n"
840 "Attribute filter bit pattern as an hexadecimal value from 0x00000000 to 0xFFFFFFFF\n")
841{
842 uint32_t filter;
843 char xpath[XPATH_CANDIDATE_MAXLEN];
844 char decimal_value[11];
845
846 if (sscanf(value, "0x%x", &filter) != 1) {
847 vty_out(vty, "affinity type: fscanf: %s\n",
848 safe_strerror(errno));
849 return CMD_WARNING_CONFIG_FAILED;
850 }
851 snprintf(decimal_value, sizeof(decimal_value), "%u", filter);
852 snprintf(xpath, sizeof(xpath), "./constraints/affinity/%s", type);
853 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, decimal_value);
854
855 return nb_cli_apply_changes(vty, NULL);
856}
857
839e6ce5
JG
858DEFPY(srte_candidate_no_affinity_filter, srte_candidate_no_affinity_filter_cmd,
859 "no affinity <exclude-any|include-any|include-all>$type [BITPATTERN$value]",
4d7b695d
SM
860 NO_STR
861 "Affinity constraint\n"
862 "Exclude any matching link\n"
863 "Include any matching link\n"
864 "Include all matching links\n"
865 "Attribute filter bit pattern as an hexadecimal value from 0x00000000 to 0xFFFFFFFF\n")
866{
867 char xpath[XPATH_CANDIDATE_MAXLEN];
868
869 snprintf(xpath, sizeof(xpath), "./constraints/affinity/%s", type);
870 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
871 return nb_cli_apply_changes(vty, NULL);
872}
873
874DEFPY(srte_candidate_metric,
875 srte_candidate_metric_cmd,
876 "metric [bound$bound] <igp|te|hc|abc|lmll|cigp|cte|pigp|pte|phc|msd|pd|pdv|pl|ppd|ppdv|ppl|nap|nlp|dc|bnc>$type METRIC$value [required$required]",
877 "Define a metric constraint\n"
878 "If the metric is bounded\n"
879 "IGP metric\n"
880 "TE metric\n"
881 "Hop Counts\n"
882 "Aggregate bandwidth consumption\n"
883 "Load of the most loaded link\n"
884 "Cumulative IGP cost\n"
885 "Cumulative TE cost\n"
886 "P2MP IGP metric\n"
887 "P2MP TE metric\n"
888 "P2MP hop count metric\n"
889 "Segment-ID (SID) Depth.\n"
890 "Path Delay metric\n"
891 "Path Delay Variation metric\n"
892 "Path Loss metric\n"
893 "P2MP Path Delay metric\n"
894 "P2MP Path Delay variation metric\n"
895 "P2MP Path Loss metric\n"
896 "Number of adaptations on a path\n"
897 "Number of layers on a path\n"
898 "Domain Count metric\n"
899 "Border Node Count metric\n"
900 "Metric value\n"
901 "Required constraint\n")
902{
903 char xpath[XPATH_CANDIDATE_MAXLEN];
904 snprintf(xpath, sizeof(xpath), "./constraints/metrics[type='%s']/value",
905 type);
906 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, value);
907 snprintf(xpath, sizeof(xpath),
908 "./constraints/metrics[type='%s']/is-bound", type);
909 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
910 (bound != NULL) ? "true" : "false");
911 snprintf(xpath, sizeof(xpath),
912 "./constraints/metrics[type='%s']/required", type);
913 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
914 required ? "true" : "false");
915 return nb_cli_apply_changes(vty, NULL);
916}
917
918DEFPY(srte_candidate_no_metric,
919 srte_candidate_no_metric_cmd,
920 "no metric [bound] <igp|te|hc|abc|lmll|cigp|cte|pigp|pte|phc|msd|pd|pdv|pl|ppd|ppdv|ppl|nap|nlp|dc|bnc>$type [METRIC$value] [required$required]",
921 NO_STR
922 "Remove a metric constraint\n"
923 "If the metric is bounded\n"
924 "IGP metric\n"
925 "TE metric\n"
926 "Hop Counts\n"
927 "Aggregate bandwidth consumption\n"
928 "Load of the most loaded link\n"
929 "Cumulative IGP cost\n"
930 "Cumulative TE cost\n"
931 "P2MP IGP metric\n"
932 "P2MP TE metric\n"
933 "P2MP hop count metric\n"
934 "Segment-ID (SID) Depth.\n"
935 "Path Delay metric\n"
936 "Path Delay Variation metric\n"
937 "Path Loss metric\n"
938 "P2MP Path Delay metric\n"
939 "P2MP Path Delay variation metric\n"
940 "P2MP Path Loss metric\n"
941 "Number of adaptations on a path\n"
942 "Number of layers on a path\n"
943 "Domain Count metric\n"
944 "Border Node Count metric\n"
945 "Metric value\n"
946 "Required constraint\n")
947{
948 char xpath[XPATH_CANDIDATE_MAXLEN];
949 snprintf(xpath, sizeof(xpath), "./constraints/metrics[type='%s']",
950 type);
951 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
952 return nb_cli_apply_changes(vty, NULL);
953}
954
955DEFPY(srte_policy_no_candidate,
956 srte_policy_no_candidate_cmd,
957 "no candidate-path\
958 preference (0-4294967295)$preference\
959 [name WORD\
960 <\
961 explicit segment-list WORD\
962 |dynamic\
963 >]",
964 NO_STR
965 "Segment Routing Policy Candidate Path\n"
966 "Segment Routing Policy Candidate Path Preference\n"
967 "Administrative Preference\n"
968 "Segment Routing Policy Candidate Path Name\n"
969 "Symbolic Name\n"
970 "Explicit Path\n"
971 "List of SIDs\n"
972 "Name of the Segment List\n"
973 "Dynamic Path\n")
974{
975 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
976
977 return nb_cli_apply_changes(vty, "./candidate-path[preference='%s']",
978 preference_str);
979}
980
981DEFPY(srte_candidate_objfun,
982 srte_candidate_objfun_cmd,
983 "objective-function <mcp|mlp|mbp|mbc|mll|mcc|spt|mct|mplp|mup|mrup|mtd|mbn|mctd|msl|mss|msn>$type [required$required]",
984 "Define an objective function constraint\n"
985 "Minimum Cost Path\n"
986 "Minimum Load Path\n"
987 "Maximum residual Bandwidth Path\n"
988 "Minimize aggregate Bandwidth Consumption\n"
989 "Minimize the Load of the most loaded Link\n"
990 "Minimize the Cumulative Cost of a set of paths\n"
991 "Shortest Path Tree\n"
992 "Minimum Cost Tree\n"
993 "Minimum Packet Loss Path\n"
994 "Maximum Under-Utilized Path\n"
995 "Maximum Reserved Under-Utilized Path\n"
996 "Minimize the number of Transit Domains\n"
997 "Minimize the number of Border Nodes\n"
998 "Minimize the number of Common Transit Domains\n"
999 "Minimize the number of Shared Links\n"
1000 "Minimize the number of Shared SRLGs\n"
1001 "Minimize the number of Shared Nodes\n"
1002 "Required constraint\n")
1003{
1004 char xpath[XPATH_CANDIDATE_MAXLEN];
1005 nb_cli_enqueue_change(vty, "./constraints/objective-function",
1006 NB_OP_DESTROY, NULL);
1007 snprintf(xpath, sizeof(xpath),
1008 "./constraints/objective-function/required");
1009 nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY,
1010 required ? "true" : "false");
1011 nb_cli_enqueue_change(vty, "./constraints/objective-function/type",
1012 NB_OP_MODIFY, type);
1013 return nb_cli_apply_changes(vty, NULL);
1014}
1015
1016DEFPY(srte_candidate_no_objfun,
1017 srte_candidate_no_objfun_cmd,
1018 "no objective-function [<mcp|mlp|mbp|mbc|mll|mcc|spt|mct|mplp|mup|mrup|mtd|mbn|mctd|msl|mss|msn>] [required$required]",
1019 NO_STR
1020 "Remove an objective function constraint\n"
1021 "Minimum Cost Path\n"
1022 "Minimum Load Path\n"
1023 "Maximum residual Bandwidth Path\n"
1024 "Minimize aggregate Bandwidth Consumption\n"
1025 "Minimize the Load of the most loaded Link\n"
1026 "Minimize the Cumulative Cost of a set of paths\n"
1027 "Shortest Path Tree\n"
1028 "Minimum Cost Tree\n"
1029 "Minimum Packet Loss Path\n"
1030 "Maximum Under-Utilized Path\n"
1031 "Maximum Reserved Under-Utilized Path\n"
1032 "Minimize the number of Transit Domains\n"
1033 "Minimize the number of Border Nodes\n"
1034 "Minimize the number of Common Transit Domains\n"
1035 "Minimize the number of Shared Links\n"
1036 "Minimize the number of Shared SRLGs\n"
1037 "Minimize the number of Shared Nodes\n"
1038 "Required constraint\n")
1039{
1040 nb_cli_enqueue_change(vty, "./constraints/objective-function",
1041 NB_OP_DESTROY, NULL);
1042 return nb_cli_apply_changes(vty, NULL);
1043}
1044
1045static const char *objfun_type_name(enum objfun_type type)
1046{
1047 switch (type) {
1048 case OBJFUN_MCP:
1049 return "mcp";
1050 case OBJFUN_MLP:
1051 return "mlp";
1052 case OBJFUN_MBP:
1053 return "mbp";
1054 case OBJFUN_MBC:
1055 return "mbc";
1056 case OBJFUN_MLL:
1057 return "mll";
1058 case OBJFUN_MCC:
1059 return "mcc";
1060 case OBJFUN_SPT:
1061 return "spt";
1062 case OBJFUN_MCT:
1063 return "mct";
1064 case OBJFUN_MPLP:
1065 return "mplp";
1066 case OBJFUN_MUP:
1067 return "mup";
1068 case OBJFUN_MRUP:
1069 return "mrup";
1070 case OBJFUN_MTD:
1071 return "mtd";
1072 case OBJFUN_MBN:
1073 return "mbn";
1074 case OBJFUN_MCTD:
1075 return "mctd";
1076 case OBJFUN_MSL:
1077 return "msl";
1078 case OBJFUN_MSS:
1079 return "mss";
1080 case OBJFUN_MSN:
1081 return "msn";
1082 default:
1083 return NULL;
1084 }
1085}
1086
1087DEFPY_NOSH(show_debugging_pathd, show_debugging_pathd_cmd,
1088 "show debugging [pathd]",
1089 SHOW_STR
1090 "State of each debugging option\n"
1091 "pathd module debugging\n")
1092{
cf00164b
DS
1093
1094 cmd_show_lib_debugs(vty);
4d7b695d
SM
1095 /* nothing to do here */
1096 return CMD_SUCCESS;
1097}
1098
1099static const char *metric_type_name(enum srte_candidate_metric_type type)
1100{
1101 switch (type) {
1102 case SRTE_CANDIDATE_METRIC_TYPE_IGP:
1103 return "igp";
1104 case SRTE_CANDIDATE_METRIC_TYPE_TE:
1105 return "te";
1106 case SRTE_CANDIDATE_METRIC_TYPE_HC:
1107 return "hc";
1108 case SRTE_CANDIDATE_METRIC_TYPE_ABC:
1109 return "abc";
1110 case SRTE_CANDIDATE_METRIC_TYPE_LMLL:
1111 return "lmll";
1112 case SRTE_CANDIDATE_METRIC_TYPE_CIGP:
1113 return "cigp";
1114 case SRTE_CANDIDATE_METRIC_TYPE_CTE:
1115 return "cte";
1116 case SRTE_CANDIDATE_METRIC_TYPE_PIGP:
1117 return "pigp";
1118 case SRTE_CANDIDATE_METRIC_TYPE_PTE:
1119 return "pte";
1120 case SRTE_CANDIDATE_METRIC_TYPE_PHC:
1121 return "phc";
1122 case SRTE_CANDIDATE_METRIC_TYPE_MSD:
1123 return "msd";
1124 case SRTE_CANDIDATE_METRIC_TYPE_PD:
1125 return "pd";
1126 case SRTE_CANDIDATE_METRIC_TYPE_PDV:
1127 return "pdv";
1128 case SRTE_CANDIDATE_METRIC_TYPE_PL:
1129 return "pl";
1130 case SRTE_CANDIDATE_METRIC_TYPE_PPD:
1131 return "ppd";
1132 case SRTE_CANDIDATE_METRIC_TYPE_PPDV:
1133 return "ppdv";
1134 case SRTE_CANDIDATE_METRIC_TYPE_PPL:
1135 return "ppl";
1136 case SRTE_CANDIDATE_METRIC_TYPE_NAP:
1137 return "nap";
1138 case SRTE_CANDIDATE_METRIC_TYPE_NLP:
1139 return "nlp";
1140 case SRTE_CANDIDATE_METRIC_TYPE_DC:
1141 return "dc";
1142 case SRTE_CANDIDATE_METRIC_TYPE_BNC:
1143 return "bnc";
1144 default:
1145 return NULL;
1146 }
1147}
1148
1149static void config_write_float(struct vty *vty, float value)
1150{
1151 if (fabs(truncf(value) - value) < FLT_EPSILON) {
1152 vty_out(vty, " %d", (int)value);
1153 return;
1154 } else {
1155 vty_out(vty, " %f", value);
1156 }
1157}
1158
1159static void config_write_metric(struct vty *vty,
1160 enum srte_candidate_metric_type type,
1161 float value, bool required, bool is_bound)
1162{
1163 const char *name = metric_type_name(type);
1164 if (name == NULL)
1165 return;
1166 vty_out(vty, " metric %s%s", is_bound ? "bound " : "",
1167 metric_type_name(type));
1168 config_write_float(vty, value);
1169 vty_out(vty, required ? " required" : "");
1170 vty_out(vty, "\n");
1171}
1172
1173static int config_write_metric_cb(const struct lyd_node *dnode, void *arg)
1174{
1175 struct vty *vty = arg;
1176 enum srte_candidate_metric_type type;
1177 bool required, is_bound = false;
1178 float value;
1179
1180 type = yang_dnode_get_enum(dnode, "./type");
1181 value = (float)yang_dnode_get_dec64(dnode, "./value");
1182 required = yang_dnode_get_bool(dnode, "./required");
1183 if (yang_dnode_exists(dnode, "./is-bound"))
1184 is_bound = yang_dnode_get_bool(dnode, "./is-bound");
1185
1186 config_write_metric(vty, type, value, required, is_bound);
1187 return YANG_ITER_CONTINUE;
1188}
1189
1190void cli_show_srte_policy_candidate_path(struct vty *vty,
25605051 1191 const struct lyd_node *dnode,
4d7b695d
SM
1192 bool show_defaults)
1193{
1194 float bandwidth;
1195 uint32_t affinity;
1196 bool required;
1197 enum objfun_type objfun_type;
1198 const char *type = yang_dnode_get_string(dnode, "./type");
1199
1200 vty_out(vty, " candidate-path preference %s name %s %s",
1201 yang_dnode_get_string(dnode, "./preference"),
1202 yang_dnode_get_string(dnode, "./name"), type);
1203 if (strmatch(type, "explicit"))
1204 vty_out(vty, " segment-list %s",
1205 yang_dnode_get_string(dnode, "./segment-list-name"));
1206 vty_out(vty, "\n");
1207
1208 if (strmatch(type, "dynamic")) {
1209 if (yang_dnode_exists(dnode, "./constraints/bandwidth")) {
1210 bandwidth = (float)yang_dnode_get_dec64(
1211 dnode, "./constraints/bandwidth/value");
1212 required = yang_dnode_get_bool(
1213 dnode, "./constraints/bandwidth/required");
ec957bbc 1214 vty_out(vty, " bandwidth");
4d7b695d 1215 config_write_float(vty, bandwidth);
ec957bbc
EDP
1216 if (required)
1217 vty_out(vty, " required");
4d7b695d
SM
1218 vty_out(vty, "\n");
1219 }
1220 if (yang_dnode_exists(dnode,
1221 "./constraints/affinity/exclude-any")) {
1222 affinity = yang_dnode_get_uint32(
1223 dnode, "./constraints/affinity/exclude-any");
1224 vty_out(vty, " affinity exclude-any 0x%08x\n",
1225 affinity);
1226 }
1227 if (yang_dnode_exists(dnode,
1228 "./constraints/affinity/include-any")) {
1229 affinity = yang_dnode_get_uint32(
1230 dnode, "./constraints/affinity/include-any");
1231 vty_out(vty, " affinity include-any 0x%08x\n",
1232 affinity);
1233 }
1234 if (yang_dnode_exists(dnode,
1235 "./constraints/affinity/include-all")) {
1236 affinity = yang_dnode_get_uint32(
1237 dnode, "./constraints/affinity/include-all");
1238 vty_out(vty, " affinity include-all 0x%08x\n",
1239 affinity);
1240 }
1241 yang_dnode_iterate(config_write_metric_cb, vty, dnode,
1242 "./constraints/metrics");
1243 if (yang_dnode_exists(dnode,
1244 "./constraints/objective-function")) {
1245 objfun_type = yang_dnode_get_enum(dnode,
1246 "./constraints/objective-function/type");
1247 required = yang_dnode_get_bool(dnode,
1248 "./constraints/objective-function/required");
1249 vty_out(vty, " objective-function %s%s\n",
1250 objfun_type_name(objfun_type),
1251 required ? " required" : "");
1252 }
1253 }
1254}
1255
07679ad9 1256void cli_show_srte_policy_candidate_path_end(struct vty *vty,
25605051 1257 const struct lyd_node *dnode)
07679ad9
IR
1258{
1259 const char *type = yang_dnode_get_string(dnode, "./type");
1260
1261 if (strmatch(type, "dynamic"))
1262 vty_out(vty, " exit\n");
1263}
1264
4d7b695d
SM
1265static int config_write_dnode(const struct lyd_node *dnode, void *arg)
1266{
1267 struct vty *vty = arg;
1268
25605051 1269 nb_cli_show_dnode_cmds(vty, dnode, false);
4d7b695d
SM
1270
1271 return YANG_ITER_CONTINUE;
1272}
1273
1274int config_write_segment_routing(struct vty *vty)
1275{
1276 vty_out(vty, "segment-routing\n");
4d7b695d 1277 vty_out(vty, " traffic-eng\n");
ac9103aa 1278
f2b9485d 1279 path_ted_config_write(vty);
4d7b695d 1280
4d7b695d
SM
1281 yang_dnode_iterate(config_write_dnode, vty, running_config->dnode,
1282 "/frr-pathd:pathd/srte/segment-list");
4d7b695d
SM
1283 yang_dnode_iterate(config_write_dnode, vty, running_config->dnode,
1284 "/frr-pathd:pathd/srte/policy");
1285
ac9103aa
IR
1286 hook_call(pathd_srte_config_write, vty);
1287
07679ad9
IR
1288 vty_out(vty, " exit\n");
1289 vty_out(vty, "exit\n");
1290
4d7b695d
SM
1291 return 1;
1292}
1293
1294void path_cli_init(void)
1295{
1296 install_node(&segment_routing_node);
1297 install_node(&sr_traffic_eng_node);
1298 install_node(&srte_segment_list_node);
1299 install_node(&srte_policy_node);
1300 install_node(&srte_candidate_dyn_node);
1301 install_default(SEGMENT_ROUTING_NODE);
1302 install_default(SR_TRAFFIC_ENG_NODE);
1303 install_default(SR_SEGMENT_LIST_NODE);
1304 install_default(SR_POLICY_NODE);
1305 install_default(SR_CANDIDATE_DYN_NODE);
1306
1307 install_element(ENABLE_NODE, &show_debugging_pathd_cmd);
1308 install_element(ENABLE_NODE, &show_srte_policy_cmd);
1309 install_element(ENABLE_NODE, &show_srte_policy_detail_cmd);
1310
1311 install_element(CONFIG_NODE, &segment_routing_cmd);
1312 install_element(SEGMENT_ROUTING_NODE, &sr_traffic_eng_cmd);
1313 install_element(SR_TRAFFIC_ENG_NODE, &srte_segment_list_cmd);
1314 install_element(SR_TRAFFIC_ENG_NODE, &srte_no_segment_list_cmd);
1315 install_element(SR_SEGMENT_LIST_NODE,
1316 &srte_segment_list_segment_cmd);
1317 install_element(SR_SEGMENT_LIST_NODE,
1318 &srte_segment_list_no_segment_cmd);
1319 install_element(SR_TRAFFIC_ENG_NODE, &srte_policy_cmd);
1320 install_element(SR_TRAFFIC_ENG_NODE, &srte_no_policy_cmd);
1321 install_element(SR_POLICY_NODE, &srte_policy_name_cmd);
1322 install_element(SR_POLICY_NODE, &srte_policy_no_name_cmd);
1323 install_element(SR_POLICY_NODE, &srte_policy_binding_sid_cmd);
1324 install_element(SR_POLICY_NODE, &srte_policy_no_binding_sid_cmd);
1325 install_element(SR_POLICY_NODE, &srte_policy_candidate_exp_cmd);
1326 install_element(SR_POLICY_NODE, &srte_policy_candidate_dyn_cmd);
1327 install_element(SR_POLICY_NODE, &srte_policy_no_candidate_cmd);
1328 install_element(SR_CANDIDATE_DYN_NODE,
1329 &srte_candidate_bandwidth_cmd);
1330 install_element(SR_CANDIDATE_DYN_NODE,
1331 &srte_candidate_no_bandwidth_cmd);
1332 install_element(SR_CANDIDATE_DYN_NODE,
1333 &srte_candidate_affinity_filter_cmd);
1334 install_element(SR_CANDIDATE_DYN_NODE,
1335 &srte_candidate_no_affinity_filter_cmd);
1336 install_element(SR_CANDIDATE_DYN_NODE,
1337 &srte_candidate_metric_cmd);
1338 install_element(SR_CANDIDATE_DYN_NODE,
1339 &srte_candidate_no_metric_cmd);
1340 install_element(SR_CANDIDATE_DYN_NODE,
1341 &srte_candidate_objfun_cmd);
1342 install_element(SR_CANDIDATE_DYN_NODE,
1343 &srte_candidate_no_objfun_cmd);
1344}