1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2020 NetDEF, Inc.
16 #include "northbound_cli.h"
17 #include "termtable.h"
19 #include "pathd/pathd.h"
20 #include "pathd/path_nb.h"
21 #include "pathd/path_cli_clippy.c"
22 #include "pathd/path_ted.h"
24 #define XPATH_MAXATTRSIZE 64
25 #define XPATH_MAXKEYSIZE 42
26 #define XPATH_POLICY_BASELEN 100
27 #define XPATH_POLICY_MAXLEN (XPATH_POLICY_BASELEN + XPATH_MAXATTRSIZE)
28 #define XPATH_CANDIDATE_BASELEN (XPATH_POLICY_BASELEN + XPATH_MAXKEYSIZE)
29 #define XPATH_CANDIDATE_MAXLEN (XPATH_CANDIDATE_BASELEN + XPATH_MAXATTRSIZE)
32 static int config_write_segment_routing(struct vty
*vty
);
33 static int segment_list_has_src_dst(
34 struct vty
*vty
, char *xpath
, long index
, const char *index_str
,
35 struct in_addr adj_src_ipv4
, struct in_addr adj_dst_ipv4
,
36 struct in6_addr adj_src_ipv6
, struct in6_addr adj_dst_ipv6
,
37 const char *adj_src_ipv4_str
, const char *adj_dst_ipv4_str
,
38 const char *adj_src_ipv6_str
, const char *adj_dst_ipv6_str
);
39 static int segment_list_has_prefix(
40 struct vty
*vty
, char *xpath
, long index
, const char *index_str
,
41 const struct prefix_ipv4
*prefix_ipv4
, const char *prefix_ipv4_str
,
42 const struct prefix_ipv6
*prefix_ipv6
, const char *prefix_ipv6_str
,
43 const char *has_algo
, long algo
, const char *algo_str
,
44 const char *has_iface_id
, long iface_id
, const char *iface_id_str
);
46 DEFINE_MTYPE_STATIC(PATHD
, PATH_CLI
, "Client");
48 DEFINE_HOOK(pathd_srte_config_write
, (struct vty
*vty
), (vty
));
50 /* Vty node structures. */
51 static struct cmd_node segment_routing_node
= {
52 .name
= "segment-routing",
53 .node
= SEGMENT_ROUTING_NODE
,
54 .parent_node
= CONFIG_NODE
,
55 .prompt
= "%s(config-sr)# ",
56 .config_write
= config_write_segment_routing
,
59 static struct cmd_node sr_traffic_eng_node
= {
60 .name
= "sr traffic-eng",
61 .node
= SR_TRAFFIC_ENG_NODE
,
62 .parent_node
= SEGMENT_ROUTING_NODE
,
63 .prompt
= "%s(config-sr-te)# ",
66 static struct cmd_node srte_segment_list_node
= {
67 .name
= "srte segment-list",
68 .node
= SR_SEGMENT_LIST_NODE
,
69 .parent_node
= SR_TRAFFIC_ENG_NODE
,
70 .prompt
= "%s(config-sr-te-segment-list)# ",
73 static struct cmd_node srte_policy_node
= {
74 .name
= "srte policy",
75 .node
= SR_POLICY_NODE
,
76 .parent_node
= SR_TRAFFIC_ENG_NODE
,
77 .prompt
= "%s(config-sr-te-policy)# ",
80 static struct cmd_node srte_candidate_dyn_node
= {
81 .name
= "srte candidate-dyn",
82 .node
= SR_CANDIDATE_DYN_NODE
,
83 .parent_node
= SR_POLICY_NODE
,
84 .prompt
= "%s(config-sr-te-candidate)# ",
91 DEFPY(show_srte_policy
,
99 struct srte_policy
*policy
;
102 if (RB_EMPTY(srte_policy_head
, &srte_policies
)) {
103 vty_out(vty
, "No SR Policies to display.\n\n");
108 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
109 ttable_add_row(tt
, "Endpoint|Color|Name|BSID|Status");
110 tt
->style
.cell
.rpad
= 2;
111 tt
->style
.corner
= '+';
113 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
115 RB_FOREACH (policy
, srte_policy_head
, &srte_policies
) {
116 char endpoint
[ENDPOINT_STR_LENGTH
];
117 char binding_sid
[16] = "-";
119 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
120 if (policy
->binding_sid
!= MPLS_LABEL_NONE
)
121 snprintf(binding_sid
, sizeof(binding_sid
), "%u",
122 policy
->binding_sid
);
124 ttable_add_row(tt
, "%s|%u|%s|%s|%s", endpoint
, policy
->color
,
125 policy
->name
, binding_sid
,
126 policy
->status
== SRTE_POLICY_STATUS_UP
131 /* Dump the generated table. */
132 table
= ttable_dump(tt
, "\n");
133 vty_out(vty
, "%s\n", table
);
134 XFREE(MTYPE_TMP
, table
);
143 * Show detailed SR-TE info
145 DEFPY(show_srte_policy_detail
,
146 show_srte_policy_detail_cmd
,
147 "show sr-te policy detail",
151 "Show a detailed summary\n")
153 struct srte_policy
*policy
;
155 if (RB_EMPTY(srte_policy_head
, &srte_policies
)) {
156 vty_out(vty
, "No SR Policies to display.\n\n");
161 RB_FOREACH (policy
, srte_policy_head
, &srte_policies
) {
162 struct srte_candidate
*candidate
;
163 char endpoint
[ENDPOINT_STR_LENGTH
];
164 char binding_sid
[16] = "-";
165 char *segment_list_info
;
166 static char undefined_info
[] = "(undefined)";
167 static char created_by_pce_info
[] = "(created by PCE)";
170 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
171 if (policy
->binding_sid
!= MPLS_LABEL_NONE
)
172 snprintf(binding_sid
, sizeof(binding_sid
), "%u",
173 policy
->binding_sid
);
175 "Endpoint: %s Color: %u Name: %s BSID: %s Status: %s\n",
176 endpoint
, policy
->color
, policy
->name
, binding_sid
,
177 policy
->status
== SRTE_POLICY_STATUS_UP
? "Active"
180 RB_FOREACH (candidate
, srte_candidate_head
,
181 &policy
->candidate_paths
) {
182 struct srte_segment_list
*segment_list
;
184 segment_list
= candidate
->lsp
->segment_list
;
185 if (segment_list
== NULL
)
186 segment_list_info
= undefined_info
;
187 else if (segment_list
->protocol_origin
189 segment_list_info
= created_by_pce_info
;
192 candidate
->lsp
->segment_list
->name
;
195 " %s Preference: %d Name: %s Type: %s Segment-List: %s Protocol-Origin: %s\n",
196 CHECK_FLAG(candidate
->flags
, F_CANDIDATE_BEST
)
199 candidate
->preference
, candidate
->name
,
200 candidate
->type
== SRTE_CANDIDATE_TYPE_EXPLICIT
205 candidate
->lsp
->protocol_origin
));
215 segment_routing_list
,
218 "Configure segment routing\n")
220 VTY_PUSH_CONTEXT_NULL(SEGMENT_ROUTING_NODE
);
228 "Configure SR traffic engineering\n")
230 VTY_PUSH_CONTEXT_NULL(SR_TRAFFIC_ENG_NODE
);
235 * XPath: /frr-pathd:pathd/srte/segment-list
239 srte_segment_list_cmd
,
240 "segment-list WORD$name",
242 "Segment List Name\n")
244 char xpath
[XPATH_MAXLEN
];
247 snprintf(xpath
, sizeof(xpath
),
248 "/frr-pathd:pathd/srte/segment-list[name='%s']", name
);
249 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
251 snprintf(xpath
, sizeof(xpath
),
252 "/frr-pathd:pathd/srte/segment-list[name='%s']/protocol-origin",
254 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "local");
256 snprintf(xpath
, sizeof(xpath
),
257 "/frr-pathd:pathd/srte/segment-list[name='%s']/originator", name
);
258 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "config");
260 ret
= nb_cli_apply_changes(vty
, NULL
);
261 if (ret
== CMD_SUCCESS
) {
262 snprintf(xpath
, sizeof(xpath
),
263 "/frr-pathd:pathd/srte/segment-list[name='%s']", name
);
264 VTY_PUSH_XPATH(SR_SEGMENT_LIST_NODE
, xpath
);
270 DEFPY(srte_no_segment_list
,
271 srte_no_segment_list_cmd
,
272 "no segment-list WORD$name",
275 "Segment List Name\n")
277 char xpath
[XPATH_MAXLEN
];
279 snprintf(xpath
, sizeof(xpath
),
280 "/frr-pathd:pathd/srte/segment-list[name='%s']", name
);
281 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
283 return nb_cli_apply_changes(vty
, NULL
);
286 void cli_show_srte_segment_list(struct vty
*vty
, const struct lyd_node
*dnode
,
289 vty_out(vty
, " segment-list %s\n",
290 yang_dnode_get_string(dnode
, "./name"));
293 void cli_show_srte_segment_list_end(struct vty
*vty
,
294 const struct lyd_node
*dnode
)
296 vty_out(vty
, " exit\n");
299 static int segment_list_has_src_dst(
300 struct vty
*vty
, char *xpath
, long index
, const char *index_str
,
301 struct in_addr adj_src_ipv4
, struct in_addr adj_dst_ipv4
,
302 struct in6_addr adj_src_ipv6
, struct in6_addr adj_dst_ipv6
,
303 const char *adj_src_ipv4_str
, const char *adj_dst_ipv4_str
,
304 const char *adj_src_ipv6_str
, const char *adj_dst_ipv6_str
)
306 const char *node_src_id
;
307 uint32_t ted_sid
= MPLS_LABEL_NONE
;
309 struct ipaddr ip_src
= {};
310 struct ipaddr ip_dst
= {};
311 if (adj_src_ipv4_str
!= NULL
) {
312 ip_src
.ipa_type
= IPADDR_V4
;
313 ip_src
.ip
._v4_addr
= adj_src_ipv4
;
314 ip_dst
.ipa_type
= IPADDR_V4
;
315 ip_dst
.ip
._v4_addr
= adj_dst_ipv4
;
316 } else if (adj_src_ipv6_str
!= NULL
) {
317 ip_src
.ipa_type
= IPADDR_V6
;
318 ip_src
.ip
._v6_addr
= adj_src_ipv6
;
319 ip_dst
.ipa_type
= IPADDR_V6
;
320 ip_dst
.ip
._v6_addr
= adj_dst_ipv6
;
322 return CMD_ERR_NO_MATCH
;
324 ted_sid
= path_ted_query_type_f(&ip_src
, &ip_dst
);
325 if (ted_sid
== MPLS_LABEL_NONE
) {
327 "%s: [rcv ted] CLI NOT FOUND Continue query_type_f SRC (%pIA) DST (%pIA)!",
328 __func__
, &ip_src
, &ip_dst
);
331 snprintf(xpath
, XPATH_MAXLEN
, "./segment[index='%s']/nai/type",
333 if (adj_src_ipv4_str
!= NULL
) {
334 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
336 node_src_id
= adj_src_ipv4_str
;
337 } else if (adj_src_ipv6_str
!= NULL
) {
338 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
340 node_src_id
= adj_src_ipv6_str
;
343 * This is just to make the compiler happy about
344 * node_src_id not being initialized. This
345 * should never happen unless we change the cli
348 assert(!"We must have a adj_src_ipv4_str or a adj_src_ipv6_str");
352 snprintf(xpath
, XPATH_MAXLEN
, "./segment[index='%s']/nai/local-address",
354 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, node_src_id
);
355 snprintf(xpath
, XPATH_MAXLEN
,
356 "./segment[index='%s']/nai/remote-address", index_str
);
357 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
358 adj_dst_ipv4_str
? adj_dst_ipv4_str
362 int segment_list_has_prefix(
363 struct vty
*vty
, char *xpath
, long index
, const char *index_str
,
364 const struct prefix_ipv4
*prefix_ipv4
, const char *prefix_ipv4_str
,
365 const struct prefix_ipv6
*prefix_ipv6
, const char *prefix_ipv6_str
,
366 const char *has_algo
, long algo
, const char *algo_str
,
367 const char *has_iface_id
, long iface_id
, const char *iface_id_str
)
369 char buf_prefix
[INET6_ADDRSTRLEN
];
371 uint32_t ted_sid
= MPLS_LABEL_NONE
;
372 struct prefix prefix_cli
= {};
373 struct ipaddr pre_ipaddr
= {};
374 /* prefix with algorithm or local interface id */
376 snprintf(xpath
, XPATH_MAXLEN
, "./segment[index='%s']/nai/type",
378 if (has_iface_id
!= NULL
) {
379 if (prefix_ipv4_str
!= NULL
) {
380 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
382 } else if (prefix_ipv6_str
!= NULL
) {
383 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
386 return CMD_ERR_NO_MATCH
;
389 if (prefix_ipv4_str
!= NULL
) {
390 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
392 } else if (prefix_ipv6_str
!= NULL
) {
393 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
396 return CMD_ERR_NO_MATCH
;
400 if (prefix_ipv4_str
!= NULL
) {
401 if (!str2prefix(prefix_ipv4_str
, &prefix_cli
)) {
402 vty_out(vty
, "%% Malformed prefix\n");
403 return CMD_WARNING_CONFIG_FAILED
;
405 inet_ntop(AF_INET
, &prefix_cli
.u
.prefix4
, buf_prefix
,
407 pre_ipaddr
.ipa_type
= IPADDR_V4
;
408 pre_ipaddr
.ip
._v4_addr
= prefix_cli
.u
.prefix4
;
409 } else if (prefix_ipv6_str
!= NULL
) {
410 if (!str2prefix(prefix_ipv6_str
, &prefix_cli
)) {
411 vty_out(vty
, "%% Malformed prefix\n");
412 return CMD_WARNING_CONFIG_FAILED
;
414 inet_ntop(AF_INET6
, &prefix_cli
.u
.prefix6
, buf_prefix
,
416 pre_ipaddr
.ipa_type
= IPADDR_V6
;
417 pre_ipaddr
.ip
._v6_addr
= prefix_cli
.u
.prefix6
;
419 snprintf(xpath
, XPATH_MAXLEN
, "./segment[index='%s']/nai/local-address",
421 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, buf_prefix
);
422 snprintf(xpath
, XPATH_MAXLEN
,
423 "./segment[index='%s']/nai/local-prefix-len", index_str
);
424 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
426 ? strchr(prefix_ipv4_str
, '/') + 1
427 : strchr(prefix_ipv6_str
, '/') + 1);
429 if (has_algo
!= NULL
) {
430 snprintf(xpath
, XPATH_MAXLEN
,
431 "./segment[index='%s']/nai/algorithm", index_str
);
432 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, algo_str
);
434 if (has_iface_id
!= NULL
) {
435 snprintf(xpath
, XPATH_MAXLEN
,
436 "./segment[index='%s']/nai/local-interface",
438 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
442 if (has_algo
!= NULL
) {
443 ted_sid
= path_ted_query_type_c(&prefix_cli
, algo
);
444 if (ted_sid
== MPLS_LABEL_NONE
) {
446 "%s: [rcv ted] CLI NOT FOUND Continue query_type_c PREFIX (%pIA/%d) ALGO (%ld) sid:(%d)!",
447 __func__
, &pre_ipaddr
, prefix_cli
.prefixlen
,
451 if (has_iface_id
!= NULL
) {
452 ted_sid
= path_ted_query_type_e(&prefix_cli
, iface_id
);
453 if (ted_sid
== MPLS_LABEL_NONE
) {
455 "%s: [rcv ted] CLI NOT FOUND Continue query_type_e PREFIX (%pIA/%d) IFACE (%ld) sid:(%d)!",
456 __func__
, &pre_ipaddr
, prefix_cli
.prefixlen
,
463 * XPath: /frr-pathd:pathd/srte/segment-list/segment
465 /* clang-format off */
466 DEFPY(srte_segment_list_segment
, srte_segment_list_segment_cmd
,
467 "index (0-4294967295)$index <[mpls$has_mpls_label label (16-1048575)$label] "
470 "prefix <A.B.C.D/M$prefix_ipv4|X:X::X:X/M$prefix_ipv6>"
471 "<algorithm$has_algo (0-1)$algo| iface$has_iface_id (0-4294967295)$iface_id>"
472 "| adjacency$has_adj "
473 "<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>"
482 "NAI prefix identifier\n"
483 "NAI IPv4 prefix identifier\n"
484 "NAI IPv6 prefix identifier\n"
486 "Algorithm Value SPF or Strict-SPF\n"
490 "ADJ IPv4 src identifier\n"
491 "ADJ IPv4 dst identifier\n"
492 "ADJ IPv6 src identifier\n"
493 "ADJ IPv6 dst identifier\n")
494 /* clang-format on */
496 char xpath
[XPATH_MAXLEN
];
497 int status
= CMD_SUCCESS
;
500 snprintf(xpath
, sizeof(xpath
), "./segment[index='%s']", index_str
);
501 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
503 if (has_mpls_label
!= NULL
) {
504 snprintf(xpath
, sizeof(xpath
),
505 "./segment[index='%s']/sid-value", index_str
);
506 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, label_str
);
507 return nb_cli_apply_changes(vty
, NULL
);
510 if (has_adj
!= NULL
) {
511 status
= segment_list_has_src_dst(vty
, xpath
, index
, index_str
,
512 adj_src_ipv4
, adj_dst_ipv4
,
513 adj_src_ipv6
, adj_dst_ipv6
,
514 adj_src_ipv4_str
, adj_dst_ipv4_str
,
515 adj_src_ipv6_str
, adj_dst_ipv6_str
);
516 if (status
!= CMD_SUCCESS
)
519 status
= segment_list_has_prefix(
520 vty
, xpath
, index
, index_str
, prefix_ipv4
,
521 prefix_ipv4_str
, prefix_ipv6
, prefix_ipv6_str
, has_algo
,
522 algo
, algo_str
, has_iface_id
, iface_id
, iface_id_str
);
523 if (status
!= CMD_SUCCESS
)
527 return nb_cli_apply_changes(vty
, NULL
);
530 DEFPY(srte_segment_list_no_segment
,
531 srte_segment_list_no_segment_cmd
,
532 "no index (0-4294967295)$index",
537 char xpath
[XPATH_MAXLEN
];
539 snprintf(xpath
, sizeof(xpath
), "./segment[index='%s']", index_str
);
540 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
542 return nb_cli_apply_changes(vty
, NULL
);
545 void cli_show_srte_segment_list_segment(struct vty
*vty
,
546 const struct lyd_node
*dnode
,
549 vty_out(vty
, " index %s", yang_dnode_get_string(dnode
, "./index"));
550 if (yang_dnode_exists(dnode
, "./sid-value")) {
551 vty_out(vty
, " mpls label %s",
552 yang_dnode_get_string(dnode
, "./sid-value"));
554 if (yang_dnode_exists(dnode
, "./nai")) {
556 struct ipaddr addr_rmt
;
558 switch (yang_dnode_get_enum(dnode
, "./nai/type")) {
559 case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE
:
560 case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE
:
561 case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM
:
562 yang_dnode_get_ip(&addr
, dnode
, "./nai/local-address");
563 vty_out(vty
, " nai prefix %pI4", &addr
.ipaddr_v4
);
565 case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE
:
566 case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE
:
567 case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM
:
568 yang_dnode_get_ip(&addr
, dnode
, "./nai/local-address");
569 vty_out(vty
, " nai prefix %pI6", &addr
.ipaddr_v6
);
571 case SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY
:
572 yang_dnode_get_ip(&addr
, dnode
, "./nai/local-address");
573 yang_dnode_get_ip(&addr_rmt
, dnode
,
574 "./nai/remote-address");
575 vty_out(vty
, " nai adjacency %pI4", &addr
.ipaddr_v4
);
576 vty_out(vty
, " %pI4", &addr_rmt
.ipaddr_v4
);
578 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY
:
579 yang_dnode_get_ip(&addr
, dnode
, "./nai/local-address");
580 yang_dnode_get_ip(&addr_rmt
, dnode
,
581 "./nai/remote-address");
582 vty_out(vty
, " nai adjacency %pI6", &addr
.ipaddr_v6
);
583 vty_out(vty
, " %pI6", &addr_rmt
.ipaddr_v6
);
588 if (yang_dnode_exists(dnode
, "./nai/local-prefix-len")) {
590 yang_dnode_get_string(
591 dnode
, "./nai/local-prefix-len"));
593 if (yang_dnode_exists(dnode
, "./nai/local-interface")) {
594 vty_out(vty
, " iface %s",
595 yang_dnode_get_string(dnode
,
596 "./nai/local-interface"));
598 if (yang_dnode_exists(dnode
, "./nai/algorithm")) {
599 vty_out(vty
, " algorithm %s",
600 yang_dnode_get_string(dnode
,
608 * XPath: /frr-pathd:pathd/policy
613 "policy color (0-4294967295)$num endpoint <A.B.C.D|X:X::X:X>$endpoint",
614 "Segment Routing Policy\n"
616 "SR Policy color value\n"
617 "SR Policy endpoint\n"
618 "SR Policy endpoint IPv4 address\n"
619 "SR Policy endpoint IPv6 address\n")
621 char xpath
[XPATH_POLICY_BASELEN
];
624 snprintf(xpath
, sizeof(xpath
),
625 "/frr-pathd:pathd/srte/policy[color='%s'][endpoint='%s']",
626 num_str
, endpoint_str
);
627 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
629 ret
= nb_cli_apply_changes(vty
, NULL
);
630 if (ret
== CMD_SUCCESS
)
631 VTY_PUSH_XPATH(SR_POLICY_NODE
, xpath
);
636 DEFPY(srte_no_policy
,
638 "no policy color (0-4294967295)$num endpoint <A.B.C.D|X:X::X:X>$endpoint",
640 "Segment Routing Policy\n"
642 "SR Policy color value\n"
643 "SR Policy endpoint\n"
644 "SR Policy endpoint IPv4 address\n"
645 "SR Policy endpoint IPv6 address\n")
647 char xpath
[XPATH_POLICY_BASELEN
];
649 snprintf(xpath
, sizeof(xpath
),
650 "/frr-pathd:pathd/srte/policy[color='%s'][endpoint='%s']",
651 num_str
, endpoint_str
);
652 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
654 return nb_cli_apply_changes(vty
, NULL
);
657 void cli_show_srte_policy(struct vty
*vty
, const struct lyd_node
*dnode
,
660 vty_out(vty
, " policy color %s endpoint %s\n",
661 yang_dnode_get_string(dnode
, "./color"),
662 yang_dnode_get_string(dnode
, "./endpoint"));
665 void cli_show_srte_policy_end(struct vty
*vty
, const struct lyd_node
*dnode
)
667 vty_out(vty
, " exit\n");
671 * XPath: /frr-pathd:pathd/srte/policy/name
673 DEFPY(srte_policy_name
,
674 srte_policy_name_cmd
,
676 "Segment Routing Policy name\n"
677 "SR Policy name value\n")
679 nb_cli_enqueue_change(vty
, "./name", NB_OP_CREATE
, name
);
681 return nb_cli_apply_changes(vty
, NULL
);
684 DEFPY(srte_policy_no_name
,
685 srte_policy_no_name_cmd
,
688 "Segment Routing Policy name\n"
689 "SR Policy name value\n")
691 nb_cli_enqueue_change(vty
, "./name", NB_OP_DESTROY
, NULL
);
693 return nb_cli_apply_changes(vty
, NULL
);
697 void cli_show_srte_policy_name(struct vty
*vty
, const struct lyd_node
*dnode
,
700 vty_out(vty
, " name %s\n", yang_dnode_get_string(dnode
, NULL
));
704 * XPath: /frr-pathd:pathd/srte/policy/binding-sid
706 DEFPY(srte_policy_binding_sid
,
707 srte_policy_binding_sid_cmd
,
708 "binding-sid (16-1048575)$label",
709 "Segment Routing Policy Binding-SID\n"
710 "SR Policy Binding-SID label\n")
712 nb_cli_enqueue_change(vty
, "./binding-sid", NB_OP_CREATE
, label_str
);
714 return nb_cli_apply_changes(vty
, NULL
);
717 DEFPY(srte_policy_no_binding_sid
,
718 srte_policy_no_binding_sid_cmd
,
719 "no binding-sid [(16-1048575)]",
721 "Segment Routing Policy Binding-SID\n"
722 "SR Policy Binding-SID label\n")
724 nb_cli_enqueue_change(vty
, "./binding-sid", NB_OP_DESTROY
, NULL
);
726 return nb_cli_apply_changes(vty
, NULL
);
729 void cli_show_srte_policy_binding_sid(struct vty
*vty
,
730 const struct lyd_node
*dnode
,
733 vty_out(vty
, " binding-sid %s\n", yang_dnode_get_string(dnode
, NULL
));
737 * XPath: /frr-pathd:pathd/srte/policy/candidate-path
739 DEFPY(srte_policy_candidate_exp
,
740 srte_policy_candidate_exp_cmd
,
741 "candidate-path preference (0-4294967295)$preference name WORD$name \
742 explicit segment-list WORD$list_name",
743 "Segment Routing Policy Candidate Path\n"
744 "Segment Routing Policy Candidate Path Preference\n"
745 "Administrative Preference\n"
746 "Segment Routing Policy Candidate Path Name\n"
750 "Name of the Segment List\n")
752 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, preference_str
);
753 nb_cli_enqueue_change(vty
, "./name", NB_OP_MODIFY
, name
);
754 nb_cli_enqueue_change(vty
, "./protocol-origin", NB_OP_MODIFY
, "local");
755 nb_cli_enqueue_change(vty
, "./originator", NB_OP_MODIFY
, "config");
756 nb_cli_enqueue_change(vty
, "./type", NB_OP_MODIFY
, "explicit");
757 nb_cli_enqueue_change(vty
, "./segment-list-name", NB_OP_MODIFY
,
759 return nb_cli_apply_changes(vty
, "./candidate-path[preference='%s']",
764 srte_policy_candidate_dyn
,
765 srte_policy_candidate_dyn_cmd
,
766 "candidate-path preference (0-4294967295)$preference name WORD$name dynamic",
767 "Segment Routing Policy Candidate Path\n"
768 "Segment Routing Policy Candidate Path Preference\n"
769 "Administrative Preference\n"
770 "Segment Routing Policy Candidate Path Name\n"
774 char xpath
[XPATH_MAXLEN
+ XPATH_CANDIDATE_BASELEN
];
777 snprintf(xpath
, sizeof(xpath
), "%s/candidate-path[preference='%s']",
778 VTY_CURR_XPATH
, preference_str
);
780 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, preference_str
);
781 nb_cli_enqueue_change(vty
, "./name", NB_OP_MODIFY
, name
);
782 nb_cli_enqueue_change(vty
, "./protocol-origin", NB_OP_MODIFY
, "local");
783 nb_cli_enqueue_change(vty
, "./originator", NB_OP_MODIFY
, "config");
784 nb_cli_enqueue_change(vty
, "./type", NB_OP_MODIFY
, "dynamic");
785 ret
= nb_cli_apply_changes(vty
, "./candidate-path[preference='%s']",
788 if (ret
== CMD_SUCCESS
)
789 VTY_PUSH_XPATH(SR_CANDIDATE_DYN_NODE
, xpath
);
794 DEFPY(srte_candidate_bandwidth
,
795 srte_candidate_bandwidth_cmd
,
796 "bandwidth BANDWIDTH$value [required$required]",
797 "Define a bandwidth constraint\n"
799 "Required constraint\n")
801 nb_cli_enqueue_change(vty
, "./constraints/bandwidth/required",
802 NB_OP_MODIFY
, required
? "true" : "false");
803 nb_cli_enqueue_change(vty
, "./constraints/bandwidth/value",
804 NB_OP_MODIFY
, value
);
805 return nb_cli_apply_changes(vty
, NULL
);
808 DEFPY(srte_candidate_no_bandwidth
,
809 srte_candidate_no_bandwidth_cmd
,
810 "no bandwidth [BANDWIDTH$value] [required$required]",
812 "Remove a bandwidth constraint\n"
814 "Required constraint\n")
816 nb_cli_enqueue_change(vty
, "./constraints/bandwidth", NB_OP_DESTROY
,
818 return nb_cli_apply_changes(vty
, NULL
);
821 DEFPY(srte_candidate_affinity_filter
, srte_candidate_affinity_filter_cmd
,
822 "affinity <exclude-any|include-any|include-all>$type BITPATTERN$value",
823 "Affinity constraint\n"
824 "Exclude any matching link\n"
825 "Include any matching link\n"
826 "Include all matching links\n"
827 "Attribute filter bit pattern as an hexadecimal value from 0x00000000 to 0xFFFFFFFF\n")
830 char xpath
[XPATH_CANDIDATE_MAXLEN
];
831 char decimal_value
[11];
833 if (sscanf(value
, "0x%x", &filter
) != 1) {
834 vty_out(vty
, "affinity type: fscanf: %s\n",
835 safe_strerror(errno
));
836 return CMD_WARNING_CONFIG_FAILED
;
838 snprintf(decimal_value
, sizeof(decimal_value
), "%u", filter
);
839 snprintf(xpath
, sizeof(xpath
), "./constraints/affinity/%s", type
);
840 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, decimal_value
);
842 return nb_cli_apply_changes(vty
, NULL
);
845 DEFPY(srte_candidate_no_affinity_filter
, srte_candidate_no_affinity_filter_cmd
,
846 "no affinity <exclude-any|include-any|include-all>$type [BITPATTERN$value]",
848 "Affinity constraint\n"
849 "Exclude any matching link\n"
850 "Include any matching link\n"
851 "Include all matching links\n"
852 "Attribute filter bit pattern as an hexadecimal value from 0x00000000 to 0xFFFFFFFF\n")
854 char xpath
[XPATH_CANDIDATE_MAXLEN
];
856 snprintf(xpath
, sizeof(xpath
), "./constraints/affinity/%s", type
);
857 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
858 return nb_cli_apply_changes(vty
, NULL
);
861 DEFPY(srte_candidate_metric
,
862 srte_candidate_metric_cmd
,
863 "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]",
864 "Define a metric constraint\n"
865 "If the metric is bounded\n"
869 "Aggregate bandwidth consumption\n"
870 "Load of the most loaded link\n"
871 "Cumulative IGP cost\n"
872 "Cumulative TE cost\n"
875 "P2MP hop count metric\n"
876 "Segment-ID (SID) Depth.\n"
877 "Path Delay metric\n"
878 "Path Delay Variation metric\n"
880 "P2MP Path Delay metric\n"
881 "P2MP Path Delay variation metric\n"
882 "P2MP Path Loss metric\n"
883 "Number of adaptations on a path\n"
884 "Number of layers on a path\n"
885 "Domain Count metric\n"
886 "Border Node Count metric\n"
888 "Required constraint\n")
890 char xpath
[XPATH_CANDIDATE_MAXLEN
];
891 snprintf(xpath
, sizeof(xpath
), "./constraints/metrics[type='%s']/value",
893 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, value
);
894 snprintf(xpath
, sizeof(xpath
),
895 "./constraints/metrics[type='%s']/is-bound", type
);
896 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
897 (bound
!= NULL
) ? "true" : "false");
898 snprintf(xpath
, sizeof(xpath
),
899 "./constraints/metrics[type='%s']/required", type
);
900 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
901 required
? "true" : "false");
902 return nb_cli_apply_changes(vty
, NULL
);
905 DEFPY(srte_candidate_no_metric
,
906 srte_candidate_no_metric_cmd
,
907 "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]",
909 "Remove a metric constraint\n"
910 "If the metric is bounded\n"
914 "Aggregate bandwidth consumption\n"
915 "Load of the most loaded link\n"
916 "Cumulative IGP cost\n"
917 "Cumulative TE cost\n"
920 "P2MP hop count metric\n"
921 "Segment-ID (SID) Depth.\n"
922 "Path Delay metric\n"
923 "Path Delay Variation metric\n"
925 "P2MP Path Delay metric\n"
926 "P2MP Path Delay variation metric\n"
927 "P2MP Path Loss metric\n"
928 "Number of adaptations on a path\n"
929 "Number of layers on a path\n"
930 "Domain Count metric\n"
931 "Border Node Count metric\n"
933 "Required constraint\n")
935 char xpath
[XPATH_CANDIDATE_MAXLEN
];
936 snprintf(xpath
, sizeof(xpath
), "./constraints/metrics[type='%s']",
938 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
939 return nb_cli_apply_changes(vty
, NULL
);
942 DEFPY(srte_policy_no_candidate
,
943 srte_policy_no_candidate_cmd
,
945 preference (0-4294967295)$preference\
948 explicit segment-list WORD\
952 "Segment Routing Policy Candidate Path\n"
953 "Segment Routing Policy Candidate Path Preference\n"
954 "Administrative Preference\n"
955 "Segment Routing Policy Candidate Path Name\n"
959 "Name of the Segment List\n"
962 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
964 return nb_cli_apply_changes(vty
, "./candidate-path[preference='%s']",
968 DEFPY(srte_candidate_objfun
,
969 srte_candidate_objfun_cmd
,
970 "objective-function <mcp|mlp|mbp|mbc|mll|mcc|spt|mct|mplp|mup|mrup|mtd|mbn|mctd|msl|mss|msn>$type [required$required]",
971 "Define an objective function constraint\n"
972 "Minimum Cost Path\n"
973 "Minimum Load Path\n"
974 "Maximum residual Bandwidth Path\n"
975 "Minimize aggregate Bandwidth Consumption\n"
976 "Minimize the Load of the most loaded Link\n"
977 "Minimize the Cumulative Cost of a set of paths\n"
978 "Shortest Path Tree\n"
979 "Minimum Cost Tree\n"
980 "Minimum Packet Loss Path\n"
981 "Maximum Under-Utilized Path\n"
982 "Maximum Reserved Under-Utilized Path\n"
983 "Minimize the number of Transit Domains\n"
984 "Minimize the number of Border Nodes\n"
985 "Minimize the number of Common Transit Domains\n"
986 "Minimize the number of Shared Links\n"
987 "Minimize the number of Shared SRLGs\n"
988 "Minimize the number of Shared Nodes\n"
989 "Required constraint\n")
991 char xpath
[XPATH_CANDIDATE_MAXLEN
];
992 nb_cli_enqueue_change(vty
, "./constraints/objective-function",
993 NB_OP_DESTROY
, NULL
);
994 snprintf(xpath
, sizeof(xpath
),
995 "./constraints/objective-function/required");
996 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
997 required
? "true" : "false");
998 nb_cli_enqueue_change(vty
, "./constraints/objective-function/type",
1000 return nb_cli_apply_changes(vty
, NULL
);
1003 DEFPY(srte_candidate_no_objfun
,
1004 srte_candidate_no_objfun_cmd
,
1005 "no objective-function [<mcp|mlp|mbp|mbc|mll|mcc|spt|mct|mplp|mup|mrup|mtd|mbn|mctd|msl|mss|msn>] [required$required]",
1007 "Remove an objective function constraint\n"
1008 "Minimum Cost Path\n"
1009 "Minimum Load Path\n"
1010 "Maximum residual Bandwidth Path\n"
1011 "Minimize aggregate Bandwidth Consumption\n"
1012 "Minimize the Load of the most loaded Link\n"
1013 "Minimize the Cumulative Cost of a set of paths\n"
1014 "Shortest Path Tree\n"
1015 "Minimum Cost Tree\n"
1016 "Minimum Packet Loss Path\n"
1017 "Maximum Under-Utilized Path\n"
1018 "Maximum Reserved Under-Utilized Path\n"
1019 "Minimize the number of Transit Domains\n"
1020 "Minimize the number of Border Nodes\n"
1021 "Minimize the number of Common Transit Domains\n"
1022 "Minimize the number of Shared Links\n"
1023 "Minimize the number of Shared SRLGs\n"
1024 "Minimize the number of Shared Nodes\n"
1025 "Required constraint\n")
1027 nb_cli_enqueue_change(vty
, "./constraints/objective-function",
1028 NB_OP_DESTROY
, NULL
);
1029 return nb_cli_apply_changes(vty
, NULL
);
1032 static const char *objfun_type_name(enum objfun_type type
)
1069 case OBJFUN_UNDEFINED
:
1073 assert(!"Reached end of function we should never hit");
1076 DEFPY_NOSH(show_debugging_pathd
, show_debugging_pathd_cmd
,
1077 "show debugging [pathd]",
1079 "State of each debugging option\n"
1080 "pathd module debugging\n")
1083 vty_out(vty
, "Path debugging status:\n");
1085 cmd_show_lib_debugs(vty
);
1086 /* nothing to do here */
1087 path_ted_show_debugging(vty
);
1088 path_policy_show_debugging(vty
);
1092 DEFPY(debug_path_policy
, debug_path_policy_cmd
, "[no] debug pathd policy",
1095 "policy debugging\n")
1097 uint32_t mode
= DEBUG_NODE2MODE(vty
->node
);
1100 DEBUG_MODE_SET(&path_policy_debug
, mode
, !no
);
1101 DEBUG_FLAGS_SET(&path_policy_debug
, PATH_POLICY_DEBUG_BASIC
, !no_debug
);
1105 static const char *metric_type_name(enum srte_candidate_metric_type type
)
1108 case SRTE_CANDIDATE_METRIC_TYPE_IGP
:
1110 case SRTE_CANDIDATE_METRIC_TYPE_TE
:
1112 case SRTE_CANDIDATE_METRIC_TYPE_HC
:
1114 case SRTE_CANDIDATE_METRIC_TYPE_ABC
:
1116 case SRTE_CANDIDATE_METRIC_TYPE_LMLL
:
1118 case SRTE_CANDIDATE_METRIC_TYPE_CIGP
:
1120 case SRTE_CANDIDATE_METRIC_TYPE_CTE
:
1122 case SRTE_CANDIDATE_METRIC_TYPE_PIGP
:
1124 case SRTE_CANDIDATE_METRIC_TYPE_PTE
:
1126 case SRTE_CANDIDATE_METRIC_TYPE_PHC
:
1128 case SRTE_CANDIDATE_METRIC_TYPE_MSD
:
1130 case SRTE_CANDIDATE_METRIC_TYPE_PD
:
1132 case SRTE_CANDIDATE_METRIC_TYPE_PDV
:
1134 case SRTE_CANDIDATE_METRIC_TYPE_PL
:
1136 case SRTE_CANDIDATE_METRIC_TYPE_PPD
:
1138 case SRTE_CANDIDATE_METRIC_TYPE_PPDV
:
1140 case SRTE_CANDIDATE_METRIC_TYPE_PPL
:
1142 case SRTE_CANDIDATE_METRIC_TYPE_NAP
:
1144 case SRTE_CANDIDATE_METRIC_TYPE_NLP
:
1146 case SRTE_CANDIDATE_METRIC_TYPE_DC
:
1148 case SRTE_CANDIDATE_METRIC_TYPE_BNC
:
1155 static void config_write_float(struct vty
*vty
, float value
)
1157 if (fabs(truncf(value
) - value
) < FLT_EPSILON
) {
1158 vty_out(vty
, " %d", (int)value
);
1161 vty_out(vty
, " %f", value
);
1165 static void config_write_metric(struct vty
*vty
,
1166 enum srte_candidate_metric_type type
,
1167 float value
, bool required
, bool is_bound
)
1169 const char *name
= metric_type_name(type
);
1172 vty_out(vty
, " metric %s%s", is_bound
? "bound " : "",
1173 metric_type_name(type
));
1174 config_write_float(vty
, value
);
1175 vty_out(vty
, required
? " required" : "");
1179 static int config_write_metric_cb(const struct lyd_node
*dnode
, void *arg
)
1181 struct vty
*vty
= arg
;
1182 enum srte_candidate_metric_type type
;
1183 bool required
, is_bound
= false;
1186 type
= yang_dnode_get_enum(dnode
, "./type");
1187 value
= (float)yang_dnode_get_dec64(dnode
, "./value");
1188 required
= yang_dnode_get_bool(dnode
, "./required");
1189 if (yang_dnode_exists(dnode
, "./is-bound"))
1190 is_bound
= yang_dnode_get_bool(dnode
, "./is-bound");
1192 config_write_metric(vty
, type
, value
, required
, is_bound
);
1193 return YANG_ITER_CONTINUE
;
1196 void cli_show_srte_policy_candidate_path(struct vty
*vty
,
1197 const struct lyd_node
*dnode
,
1203 enum objfun_type objfun_type
;
1204 const char *type
= yang_dnode_get_string(dnode
, "./type");
1206 vty_out(vty
, " candidate-path preference %s name %s %s",
1207 yang_dnode_get_string(dnode
, "./preference"),
1208 yang_dnode_get_string(dnode
, "./name"), type
);
1209 if (strmatch(type
, "explicit"))
1210 vty_out(vty
, " segment-list %s",
1211 yang_dnode_get_string(dnode
, "./segment-list-name"));
1214 if (strmatch(type
, "dynamic")) {
1215 if (yang_dnode_exists(dnode
, "./constraints/bandwidth")) {
1216 bandwidth
= (float)yang_dnode_get_dec64(
1217 dnode
, "./constraints/bandwidth/value");
1218 required
= yang_dnode_get_bool(
1219 dnode
, "./constraints/bandwidth/required");
1220 vty_out(vty
, " bandwidth");
1221 config_write_float(vty
, bandwidth
);
1223 vty_out(vty
, " required");
1226 if (yang_dnode_exists(dnode
,
1227 "./constraints/affinity/exclude-any")) {
1228 affinity
= yang_dnode_get_uint32(
1229 dnode
, "./constraints/affinity/exclude-any");
1230 vty_out(vty
, " affinity exclude-any 0x%08x\n",
1233 if (yang_dnode_exists(dnode
,
1234 "./constraints/affinity/include-any")) {
1235 affinity
= yang_dnode_get_uint32(
1236 dnode
, "./constraints/affinity/include-any");
1237 vty_out(vty
, " affinity include-any 0x%08x\n",
1240 if (yang_dnode_exists(dnode
,
1241 "./constraints/affinity/include-all")) {
1242 affinity
= yang_dnode_get_uint32(
1243 dnode
, "./constraints/affinity/include-all");
1244 vty_out(vty
, " affinity include-all 0x%08x\n",
1247 yang_dnode_iterate(config_write_metric_cb
, vty
, dnode
,
1248 "./constraints/metrics");
1249 if (yang_dnode_exists(dnode
,
1250 "./constraints/objective-function")) {
1251 objfun_type
= yang_dnode_get_enum(dnode
,
1252 "./constraints/objective-function/type");
1253 required
= yang_dnode_get_bool(dnode
,
1254 "./constraints/objective-function/required");
1255 vty_out(vty
, " objective-function %s%s\n",
1256 objfun_type_name(objfun_type
),
1257 required
? " required" : "");
1262 void cli_show_srte_policy_candidate_path_end(struct vty
*vty
,
1263 const struct lyd_node
*dnode
)
1265 const char *type
= yang_dnode_get_string(dnode
, "./type");
1267 if (strmatch(type
, "dynamic"))
1268 vty_out(vty
, " exit\n");
1271 static int config_write_dnode(const struct lyd_node
*dnode
, void *arg
)
1273 struct vty
*vty
= arg
;
1275 nb_cli_show_dnode_cmds(vty
, dnode
, false);
1277 return YANG_ITER_CONTINUE
;
1280 int config_write_segment_routing(struct vty
*vty
)
1282 vty_out(vty
, "segment-routing\n");
1283 vty_out(vty
, " traffic-eng\n");
1285 path_ted_config_write(vty
);
1287 yang_dnode_iterate(config_write_dnode
, vty
, running_config
->dnode
,
1288 "/frr-pathd:pathd/srte/segment-list");
1289 yang_dnode_iterate(config_write_dnode
, vty
, running_config
->dnode
,
1290 "/frr-pathd:pathd/srte/policy");
1292 hook_call(pathd_srte_config_write
, vty
);
1294 vty_out(vty
, " exit\n");
1295 vty_out(vty
, "exit\n");
1300 static int path_policy_cli_debug_config_write(struct vty
*vty
)
1302 if (DEBUG_MODE_CHECK(&path_policy_debug
, DEBUG_MODE_CONF
)) {
1303 if (DEBUG_FLAGS_CHECK(&path_policy_debug
,
1304 PATH_POLICY_DEBUG_BASIC
))
1305 vty_out(vty
, "debug pathd policy\n");
1311 static int path_policy_cli_debug_set_all(uint32_t flags
, bool set
)
1313 DEBUG_FLAGS_SET(&path_policy_debug
, flags
, set
);
1315 /* If all modes have been turned off, don't preserve options. */
1316 if (!DEBUG_MODE_CHECK(&path_policy_debug
, DEBUG_MODE_ALL
))
1317 DEBUG_CLEAR(&path_policy_debug
);
1322 void path_cli_init(void)
1324 hook_register(nb_client_debug_config_write
,
1325 path_policy_cli_debug_config_write
);
1326 hook_register(nb_client_debug_set_all
, path_policy_cli_debug_set_all
);
1328 install_node(&segment_routing_node
);
1329 install_node(&sr_traffic_eng_node
);
1330 install_node(&srte_segment_list_node
);
1331 install_node(&srte_policy_node
);
1332 install_node(&srte_candidate_dyn_node
);
1333 install_default(SEGMENT_ROUTING_NODE
);
1334 install_default(SR_TRAFFIC_ENG_NODE
);
1335 install_default(SR_SEGMENT_LIST_NODE
);
1336 install_default(SR_POLICY_NODE
);
1337 install_default(SR_CANDIDATE_DYN_NODE
);
1339 install_element(ENABLE_NODE
, &show_debugging_pathd_cmd
);
1340 install_element(ENABLE_NODE
, &show_srte_policy_cmd
);
1341 install_element(ENABLE_NODE
, &show_srte_policy_detail_cmd
);
1343 install_element(ENABLE_NODE
, &debug_path_policy_cmd
);
1344 install_element(CONFIG_NODE
, &debug_path_policy_cmd
);
1346 install_element(CONFIG_NODE
, &segment_routing_cmd
);
1347 install_element(SEGMENT_ROUTING_NODE
, &sr_traffic_eng_cmd
);
1348 install_element(SR_TRAFFIC_ENG_NODE
, &srte_segment_list_cmd
);
1349 install_element(SR_TRAFFIC_ENG_NODE
, &srte_no_segment_list_cmd
);
1350 install_element(SR_SEGMENT_LIST_NODE
,
1351 &srte_segment_list_segment_cmd
);
1352 install_element(SR_SEGMENT_LIST_NODE
,
1353 &srte_segment_list_no_segment_cmd
);
1354 install_element(SR_TRAFFIC_ENG_NODE
, &srte_policy_cmd
);
1355 install_element(SR_TRAFFIC_ENG_NODE
, &srte_no_policy_cmd
);
1356 install_element(SR_POLICY_NODE
, &srte_policy_name_cmd
);
1357 install_element(SR_POLICY_NODE
, &srte_policy_no_name_cmd
);
1358 install_element(SR_POLICY_NODE
, &srte_policy_binding_sid_cmd
);
1359 install_element(SR_POLICY_NODE
, &srte_policy_no_binding_sid_cmd
);
1360 install_element(SR_POLICY_NODE
, &srte_policy_candidate_exp_cmd
);
1361 install_element(SR_POLICY_NODE
, &srte_policy_candidate_dyn_cmd
);
1362 install_element(SR_POLICY_NODE
, &srte_policy_no_candidate_cmd
);
1363 install_element(SR_CANDIDATE_DYN_NODE
,
1364 &srte_candidate_bandwidth_cmd
);
1365 install_element(SR_CANDIDATE_DYN_NODE
,
1366 &srte_candidate_no_bandwidth_cmd
);
1367 install_element(SR_CANDIDATE_DYN_NODE
,
1368 &srte_candidate_affinity_filter_cmd
);
1369 install_element(SR_CANDIDATE_DYN_NODE
,
1370 &srte_candidate_no_affinity_filter_cmd
);
1371 install_element(SR_CANDIDATE_DYN_NODE
,
1372 &srte_candidate_metric_cmd
);
1373 install_element(SR_CANDIDATE_DYN_NODE
,
1374 &srte_candidate_no_metric_cmd
);
1375 install_element(SR_CANDIDATE_DYN_NODE
,
1376 &srte_candidate_objfun_cmd
);
1377 install_element(SR_CANDIDATE_DYN_NODE
,
1378 &srte_candidate_no_objfun_cmd
);