]> git.proxmox.com Git - mirror_frr.git/blob - pathd/path_cli.c
pathd: use a define to store the the length of endpoint string
[mirror_frr.git] / pathd / path_cli.c
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
19 #include <zebra.h>
20
21 #include <float.h>
22 #include <math.h>
23 #include <zebra.h>
24
25 #include "memory.h"
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"
34 #include "pathd/path_cli_clippy.c"
35 #include "pathd/path_ted.h"
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
45 static int config_write_segment_routing(struct vty *vty);
46 static 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);
52 static 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);
58
59 DEFINE_MTYPE_STATIC(PATHD, PATH_CLI, "Client");
60
61 DEFINE_HOOK(pathd_srte_config_write, (struct vty *vty), (vty));
62
63 /* Vty node structures. */
64 static 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
72 static 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)# ",
77 };
78
79 static 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)# ",
84 };
85
86 static 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)# ",
91 };
92
93 static 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 */
104 DEFPY(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[ENDPOINT_STR_LENGTH];
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
154
155 /*
156 * Show detailed SR-TE info
157 */
158 DEFPY(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[ENDPOINT_STR_LENGTH];
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
227 DEFPY_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
237 DEFPY_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 */
250 DEFPY_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
283 DEFPY(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
299 void cli_show_srte_segment_list(struct vty *vty, const struct lyd_node *dnode,
300 bool show_defaults)
301 {
302 vty_out(vty, " segment-list %s\n",
303 yang_dnode_get_string(dnode, "./name"));
304 }
305
306 void cli_show_srte_segment_list_end(struct vty *vty,
307 const struct lyd_node *dnode)
308 {
309 vty_out(vty, " exit\n");
310 }
311
312 static 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;
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");
362 }
363
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 }
375 int 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;
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 }
475 /*
476 * XPath: /frr-pathd:pathd/srte/segment-list/segment
477 */
478 /* clang-format off */
479 DEFPY(srte_segment_list_segment, srte_segment_list_segment_cmd,
480 "index (0-4294967295)$index <[mpls$has_mpls_label label (16-1048575)$label] "
481 "|"
482 "[nai$has_nai <"
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 ">",
489 "Index\n"
490 "Index Value\n"
491 "MPLS or IP Label\n"
492 "Label\n"
493 "Label Value\n"
494 "Segment NAI\n"
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 */
508 {
509 char xpath[XPATH_MAXLEN];
510 int status = CMD_SUCCESS;
511
512
513 snprintf(xpath, sizeof(xpath), "./segment[index='%s']", index_str);
514 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
515
516 if (has_mpls_label != NULL) {
517 snprintf(xpath, sizeof(xpath),
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,
528 adj_src_ipv6_str, adj_dst_ipv6_str);
529 if (status != CMD_SUCCESS)
530 return status;
531 } else {
532 status = segment_list_has_prefix(
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;
538 }
539
540 return nb_cli_apply_changes(vty, NULL);
541 }
542
543 DEFPY(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
558 void cli_show_srte_segment_list_segment(struct vty *vty,
559 const struct lyd_node *dnode,
560 bool show_defaults)
561 {
562 vty_out(vty, " index %s", yang_dnode_get_string(dnode, "./index"));
563 if (yang_dnode_exists(dnode, "./sid-value")) {
564 vty_out(vty, " mpls label %s",
565 yang_dnode_get_string(dnode, "./sid-value"));
566 }
567 if (yang_dnode_exists(dnode, "./nai")) {
568 struct ipaddr addr;
569 struct ipaddr addr_rmt;
570
571 switch (yang_dnode_get_enum(dnode, "./nai/type")) {
572 case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE:
573 case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE:
574 case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM:
575 yang_dnode_get_ip(&addr, dnode, "./nai/local-address");
576 vty_out(vty, " nai prefix %pI4", &addr.ipaddr_v4);
577 break;
578 case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE:
579 case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE:
580 case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM:
581 yang_dnode_get_ip(&addr, dnode, "./nai/local-address");
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);
597 break;
598 default:
599 break;
600 }
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 }
616 }
617 vty_out(vty, "\n");
618 }
619
620 /*
621 * XPath: /frr-pathd:pathd/policy
622 */
623 DEFPY_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
649 DEFPY(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
670 void cli_show_srte_policy(struct vty *vty, const struct lyd_node *dnode,
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
678 void cli_show_srte_policy_end(struct vty *vty, const struct lyd_node *dnode)
679 {
680 vty_out(vty, " exit\n");
681 }
682
683 /*
684 * XPath: /frr-pathd:pathd/srte/policy/name
685 */
686 DEFPY(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
697 DEFPY(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
710 void cli_show_srte_policy_name(struct vty *vty, const struct lyd_node *dnode,
711 bool show_defaults)
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 */
719 DEFPY(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
730 DEFPY(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
742 void cli_show_srte_policy_binding_sid(struct vty *vty,
743 const struct lyd_node *dnode,
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 */
752 DEFPY(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
776 DEFPY_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 {
787 char xpath[XPATH_MAXLEN + XPATH_CANDIDATE_BASELEN];
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
807 DEFPY(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
821 DEFPY(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
834 DEFPY(srte_candidate_affinity_filter, srte_candidate_affinity_filter_cmd,
835 "affinity <exclude-any|include-any|include-all>$type BITPATTERN$value",
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
858 DEFPY(srte_candidate_no_affinity_filter, srte_candidate_no_affinity_filter_cmd,
859 "no affinity <exclude-any|include-any|include-all>$type [BITPATTERN$value]",
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
874 DEFPY(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
918 DEFPY(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
955 DEFPY(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
981 DEFPY(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
1016 DEFPY(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
1045 static 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
1087 DEFPY_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 {
1093
1094 vty_out(vty, "Path debugging status:\n");
1095
1096 cmd_show_lib_debugs(vty);
1097 /* nothing to do here */
1098 path_ted_show_debugging(vty);
1099 path_policy_show_debugging(vty);
1100 return CMD_SUCCESS;
1101 }
1102
1103 DEFPY(debug_path_policy, debug_path_policy_cmd, "[no] debug pathd policy",
1104 NO_STR DEBUG_STR
1105 "path debugging\n"
1106 "policy debugging\n")
1107 {
1108 uint32_t mode = DEBUG_NODE2MODE(vty->node);
1109 bool no_debug = no;
1110
1111 DEBUG_MODE_SET(&path_policy_debug, mode, !no);
1112 DEBUG_FLAGS_SET(&path_policy_debug, PATH_POLICY_DEBUG_BASIC, !no_debug);
1113 return CMD_SUCCESS;
1114 }
1115
1116 static const char *metric_type_name(enum srte_candidate_metric_type type)
1117 {
1118 switch (type) {
1119 case SRTE_CANDIDATE_METRIC_TYPE_IGP:
1120 return "igp";
1121 case SRTE_CANDIDATE_METRIC_TYPE_TE:
1122 return "te";
1123 case SRTE_CANDIDATE_METRIC_TYPE_HC:
1124 return "hc";
1125 case SRTE_CANDIDATE_METRIC_TYPE_ABC:
1126 return "abc";
1127 case SRTE_CANDIDATE_METRIC_TYPE_LMLL:
1128 return "lmll";
1129 case SRTE_CANDIDATE_METRIC_TYPE_CIGP:
1130 return "cigp";
1131 case SRTE_CANDIDATE_METRIC_TYPE_CTE:
1132 return "cte";
1133 case SRTE_CANDIDATE_METRIC_TYPE_PIGP:
1134 return "pigp";
1135 case SRTE_CANDIDATE_METRIC_TYPE_PTE:
1136 return "pte";
1137 case SRTE_CANDIDATE_METRIC_TYPE_PHC:
1138 return "phc";
1139 case SRTE_CANDIDATE_METRIC_TYPE_MSD:
1140 return "msd";
1141 case SRTE_CANDIDATE_METRIC_TYPE_PD:
1142 return "pd";
1143 case SRTE_CANDIDATE_METRIC_TYPE_PDV:
1144 return "pdv";
1145 case SRTE_CANDIDATE_METRIC_TYPE_PL:
1146 return "pl";
1147 case SRTE_CANDIDATE_METRIC_TYPE_PPD:
1148 return "ppd";
1149 case SRTE_CANDIDATE_METRIC_TYPE_PPDV:
1150 return "ppdv";
1151 case SRTE_CANDIDATE_METRIC_TYPE_PPL:
1152 return "ppl";
1153 case SRTE_CANDIDATE_METRIC_TYPE_NAP:
1154 return "nap";
1155 case SRTE_CANDIDATE_METRIC_TYPE_NLP:
1156 return "nlp";
1157 case SRTE_CANDIDATE_METRIC_TYPE_DC:
1158 return "dc";
1159 case SRTE_CANDIDATE_METRIC_TYPE_BNC:
1160 return "bnc";
1161 default:
1162 return NULL;
1163 }
1164 }
1165
1166 static void config_write_float(struct vty *vty, float value)
1167 {
1168 if (fabs(truncf(value) - value) < FLT_EPSILON) {
1169 vty_out(vty, " %d", (int)value);
1170 return;
1171 } else {
1172 vty_out(vty, " %f", value);
1173 }
1174 }
1175
1176 static void config_write_metric(struct vty *vty,
1177 enum srte_candidate_metric_type type,
1178 float value, bool required, bool is_bound)
1179 {
1180 const char *name = metric_type_name(type);
1181 if (name == NULL)
1182 return;
1183 vty_out(vty, " metric %s%s", is_bound ? "bound " : "",
1184 metric_type_name(type));
1185 config_write_float(vty, value);
1186 vty_out(vty, required ? " required" : "");
1187 vty_out(vty, "\n");
1188 }
1189
1190 static int config_write_metric_cb(const struct lyd_node *dnode, void *arg)
1191 {
1192 struct vty *vty = arg;
1193 enum srte_candidate_metric_type type;
1194 bool required, is_bound = false;
1195 float value;
1196
1197 type = yang_dnode_get_enum(dnode, "./type");
1198 value = (float)yang_dnode_get_dec64(dnode, "./value");
1199 required = yang_dnode_get_bool(dnode, "./required");
1200 if (yang_dnode_exists(dnode, "./is-bound"))
1201 is_bound = yang_dnode_get_bool(dnode, "./is-bound");
1202
1203 config_write_metric(vty, type, value, required, is_bound);
1204 return YANG_ITER_CONTINUE;
1205 }
1206
1207 void cli_show_srte_policy_candidate_path(struct vty *vty,
1208 const struct lyd_node *dnode,
1209 bool show_defaults)
1210 {
1211 float bandwidth;
1212 uint32_t affinity;
1213 bool required;
1214 enum objfun_type objfun_type;
1215 const char *type = yang_dnode_get_string(dnode, "./type");
1216
1217 vty_out(vty, " candidate-path preference %s name %s %s",
1218 yang_dnode_get_string(dnode, "./preference"),
1219 yang_dnode_get_string(dnode, "./name"), type);
1220 if (strmatch(type, "explicit"))
1221 vty_out(vty, " segment-list %s",
1222 yang_dnode_get_string(dnode, "./segment-list-name"));
1223 vty_out(vty, "\n");
1224
1225 if (strmatch(type, "dynamic")) {
1226 if (yang_dnode_exists(dnode, "./constraints/bandwidth")) {
1227 bandwidth = (float)yang_dnode_get_dec64(
1228 dnode, "./constraints/bandwidth/value");
1229 required = yang_dnode_get_bool(
1230 dnode, "./constraints/bandwidth/required");
1231 vty_out(vty, " bandwidth");
1232 config_write_float(vty, bandwidth);
1233 if (required)
1234 vty_out(vty, " required");
1235 vty_out(vty, "\n");
1236 }
1237 if (yang_dnode_exists(dnode,
1238 "./constraints/affinity/exclude-any")) {
1239 affinity = yang_dnode_get_uint32(
1240 dnode, "./constraints/affinity/exclude-any");
1241 vty_out(vty, " affinity exclude-any 0x%08x\n",
1242 affinity);
1243 }
1244 if (yang_dnode_exists(dnode,
1245 "./constraints/affinity/include-any")) {
1246 affinity = yang_dnode_get_uint32(
1247 dnode, "./constraints/affinity/include-any");
1248 vty_out(vty, " affinity include-any 0x%08x\n",
1249 affinity);
1250 }
1251 if (yang_dnode_exists(dnode,
1252 "./constraints/affinity/include-all")) {
1253 affinity = yang_dnode_get_uint32(
1254 dnode, "./constraints/affinity/include-all");
1255 vty_out(vty, " affinity include-all 0x%08x\n",
1256 affinity);
1257 }
1258 yang_dnode_iterate(config_write_metric_cb, vty, dnode,
1259 "./constraints/metrics");
1260 if (yang_dnode_exists(dnode,
1261 "./constraints/objective-function")) {
1262 objfun_type = yang_dnode_get_enum(dnode,
1263 "./constraints/objective-function/type");
1264 required = yang_dnode_get_bool(dnode,
1265 "./constraints/objective-function/required");
1266 vty_out(vty, " objective-function %s%s\n",
1267 objfun_type_name(objfun_type),
1268 required ? " required" : "");
1269 }
1270 }
1271 }
1272
1273 void cli_show_srte_policy_candidate_path_end(struct vty *vty,
1274 const struct lyd_node *dnode)
1275 {
1276 const char *type = yang_dnode_get_string(dnode, "./type");
1277
1278 if (strmatch(type, "dynamic"))
1279 vty_out(vty, " exit\n");
1280 }
1281
1282 static int config_write_dnode(const struct lyd_node *dnode, void *arg)
1283 {
1284 struct vty *vty = arg;
1285
1286 nb_cli_show_dnode_cmds(vty, dnode, false);
1287
1288 return YANG_ITER_CONTINUE;
1289 }
1290
1291 int config_write_segment_routing(struct vty *vty)
1292 {
1293 vty_out(vty, "segment-routing\n");
1294 vty_out(vty, " traffic-eng\n");
1295
1296 path_ted_config_write(vty);
1297
1298 yang_dnode_iterate(config_write_dnode, vty, running_config->dnode,
1299 "/frr-pathd:pathd/srte/segment-list");
1300 yang_dnode_iterate(config_write_dnode, vty, running_config->dnode,
1301 "/frr-pathd:pathd/srte/policy");
1302
1303 hook_call(pathd_srte_config_write, vty);
1304
1305 vty_out(vty, " exit\n");
1306 vty_out(vty, "exit\n");
1307
1308 return 1;
1309 }
1310
1311 static int path_policy_cli_debug_config_write(struct vty *vty)
1312 {
1313 if (DEBUG_MODE_CHECK(&path_policy_debug, DEBUG_MODE_CONF)) {
1314 if (DEBUG_FLAGS_CHECK(&path_policy_debug,
1315 PATH_POLICY_DEBUG_BASIC))
1316 vty_out(vty, "debug pathd policy\n");
1317 return 1;
1318 }
1319 return 0;
1320 }
1321
1322 static int path_policy_cli_debug_set_all(uint32_t flags, bool set)
1323 {
1324 DEBUG_FLAGS_SET(&path_policy_debug, flags, set);
1325
1326 /* If all modes have been turned off, don't preserve options. */
1327 if (!DEBUG_MODE_CHECK(&path_policy_debug, DEBUG_MODE_ALL))
1328 DEBUG_CLEAR(&path_policy_debug);
1329
1330 return 0;
1331 }
1332
1333 void path_cli_init(void)
1334 {
1335 hook_register(nb_client_debug_config_write,
1336 path_policy_cli_debug_config_write);
1337 hook_register(nb_client_debug_set_all, path_policy_cli_debug_set_all);
1338
1339 install_node(&segment_routing_node);
1340 install_node(&sr_traffic_eng_node);
1341 install_node(&srte_segment_list_node);
1342 install_node(&srte_policy_node);
1343 install_node(&srte_candidate_dyn_node);
1344 install_default(SEGMENT_ROUTING_NODE);
1345 install_default(SR_TRAFFIC_ENG_NODE);
1346 install_default(SR_SEGMENT_LIST_NODE);
1347 install_default(SR_POLICY_NODE);
1348 install_default(SR_CANDIDATE_DYN_NODE);
1349
1350 install_element(ENABLE_NODE, &show_debugging_pathd_cmd);
1351 install_element(ENABLE_NODE, &show_srte_policy_cmd);
1352 install_element(ENABLE_NODE, &show_srte_policy_detail_cmd);
1353
1354 install_element(ENABLE_NODE, &debug_path_policy_cmd);
1355 install_element(CONFIG_NODE, &debug_path_policy_cmd);
1356
1357 install_element(CONFIG_NODE, &segment_routing_cmd);
1358 install_element(SEGMENT_ROUTING_NODE, &sr_traffic_eng_cmd);
1359 install_element(SR_TRAFFIC_ENG_NODE, &srte_segment_list_cmd);
1360 install_element(SR_TRAFFIC_ENG_NODE, &srte_no_segment_list_cmd);
1361 install_element(SR_SEGMENT_LIST_NODE,
1362 &srte_segment_list_segment_cmd);
1363 install_element(SR_SEGMENT_LIST_NODE,
1364 &srte_segment_list_no_segment_cmd);
1365 install_element(SR_TRAFFIC_ENG_NODE, &srte_policy_cmd);
1366 install_element(SR_TRAFFIC_ENG_NODE, &srte_no_policy_cmd);
1367 install_element(SR_POLICY_NODE, &srte_policy_name_cmd);
1368 install_element(SR_POLICY_NODE, &srte_policy_no_name_cmd);
1369 install_element(SR_POLICY_NODE, &srte_policy_binding_sid_cmd);
1370 install_element(SR_POLICY_NODE, &srte_policy_no_binding_sid_cmd);
1371 install_element(SR_POLICY_NODE, &srte_policy_candidate_exp_cmd);
1372 install_element(SR_POLICY_NODE, &srte_policy_candidate_dyn_cmd);
1373 install_element(SR_POLICY_NODE, &srte_policy_no_candidate_cmd);
1374 install_element(SR_CANDIDATE_DYN_NODE,
1375 &srte_candidate_bandwidth_cmd);
1376 install_element(SR_CANDIDATE_DYN_NODE,
1377 &srte_candidate_no_bandwidth_cmd);
1378 install_element(SR_CANDIDATE_DYN_NODE,
1379 &srte_candidate_affinity_filter_cmd);
1380 install_element(SR_CANDIDATE_DYN_NODE,
1381 &srte_candidate_no_affinity_filter_cmd);
1382 install_element(SR_CANDIDATE_DYN_NODE,
1383 &srte_candidate_metric_cmd);
1384 install_element(SR_CANDIDATE_DYN_NODE,
1385 &srte_candidate_no_metric_cmd);
1386 install_element(SR_CANDIDATE_DYN_NODE,
1387 &srte_candidate_objfun_cmd);
1388 install_element(SR_CANDIDATE_DYN_NODE,
1389 &srte_candidate_no_objfun_cmd);
1390 }