2 * Copyright (C) 2020 NetDEF, Inc.
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)
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
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
29 #include "northbound_cli.h"
30 #include "termtable.h"
32 #include "pathd/pathd.h"
33 #include "pathd/path_nb.h"
34 #ifndef VTYSH_EXTRACT_PL
35 #include "pathd/path_cli_clippy.c"
37 #include "pathd/path_ted.h"
39 #define XPATH_MAXATTRSIZE 64
40 #define XPATH_MAXKEYSIZE 42
41 #define XPATH_POLICY_BASELEN 100
42 #define XPATH_POLICY_MAXLEN (XPATH_POLICY_BASELEN + XPATH_MAXATTRSIZE)
43 #define XPATH_CANDIDATE_BASELEN (XPATH_POLICY_BASELEN + XPATH_MAXKEYSIZE)
44 #define XPATH_CANDIDATE_MAXLEN (XPATH_CANDIDATE_BASELEN + XPATH_MAXATTRSIZE)
47 static int config_write_segment_routing(struct vty
*vty
);
48 static int segment_list_has_src_dst(
49 struct vty
*vty
, char *xpath
, long index
, const char *index_str
,
50 struct in_addr adj_src_ipv4
, struct in_addr adj_dst_ipv4
,
51 struct in6_addr adj_src_ipv6
, struct in6_addr adj_dst_ipv6
,
52 const char *adj_src_ipv4_str
, const char *adj_dst_ipv4_str
,
53 const char *adj_src_ipv6_str
, const char *adj_dst_ipv6_str
);
54 static int segment_list_has_prefix(
55 struct vty
*vty
, char *xpath
, long index
, const char *index_str
,
56 const struct prefix_ipv4
*prefix_ipv4
, const char *prefix_ipv4_str
,
57 const struct prefix_ipv6
*prefix_ipv6
, const char *prefix_ipv6_str
,
58 const char *has_algo
, long algo
, const char *algo_str
,
59 const char *has_iface_id
, long iface_id
, const char *iface_id_str
);
61 DEFINE_MTYPE_STATIC(PATHD
, PATH_CLI
, "Client");
63 DEFINE_HOOK(pathd_srte_config_write
, (struct vty
*vty
), (vty
));
65 /* Vty node structures. */
66 static struct cmd_node segment_routing_node
= {
67 .name
= "segment-routing",
68 .node
= SEGMENT_ROUTING_NODE
,
69 .parent_node
= CONFIG_NODE
,
70 .prompt
= "%s(config-sr)# ",
71 .config_write
= config_write_segment_routing
,
74 static struct cmd_node sr_traffic_eng_node
= {
75 .name
= "sr traffic-eng",
76 .node
= SR_TRAFFIC_ENG_NODE
,
77 .parent_node
= SEGMENT_ROUTING_NODE
,
78 .prompt
= "%s(config-sr-te)# ",
81 static struct cmd_node srte_segment_list_node
= {
82 .name
= "srte segment-list",
83 .node
= SR_SEGMENT_LIST_NODE
,
84 .parent_node
= SR_TRAFFIC_ENG_NODE
,
85 .prompt
= "%s(config-sr-te-segment-list)# ",
88 static struct cmd_node srte_policy_node
= {
89 .name
= "srte policy",
90 .node
= SR_POLICY_NODE
,
91 .parent_node
= SR_TRAFFIC_ENG_NODE
,
92 .prompt
= "%s(config-sr-te-policy)# ",
95 static struct cmd_node srte_candidate_dyn_node
= {
96 .name
= "srte candidate-dyn",
97 .node
= SR_CANDIDATE_DYN_NODE
,
98 .parent_node
= SR_POLICY_NODE
,
99 .prompt
= "%s(config-sr-te-candidate)# ",
106 DEFPY(show_srte_policy
,
107 show_srte_policy_cmd
,
114 struct srte_policy
*policy
;
117 if (RB_EMPTY(srte_policy_head
, &srte_policies
)) {
118 vty_out(vty
, "No SR Policies to display.\n\n");
123 tt
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
124 ttable_add_row(tt
, "Endpoint|Color|Name|BSID|Status");
125 tt
->style
.cell
.rpad
= 2;
126 tt
->style
.corner
= '+';
128 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
130 RB_FOREACH (policy
, srte_policy_head
, &srte_policies
) {
132 char binding_sid
[16] = "-";
134 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
135 if (policy
->binding_sid
!= MPLS_LABEL_NONE
)
136 snprintf(binding_sid
, sizeof(binding_sid
), "%u",
137 policy
->binding_sid
);
139 ttable_add_row(tt
, "%s|%u|%s|%s|%s", endpoint
, policy
->color
,
140 policy
->name
, binding_sid
,
141 policy
->status
== SRTE_POLICY_STATUS_UP
146 /* Dump the generated table. */
147 table
= ttable_dump(tt
, "\n");
148 vty_out(vty
, "%s\n", table
);
149 XFREE(MTYPE_TMP
, table
);
158 * Show detailed SR-TE info
160 DEFPY(show_srte_policy_detail
,
161 show_srte_policy_detail_cmd
,
162 "show sr-te policy detail",
166 "Show a detailed summary\n")
168 struct srte_policy
*policy
;
170 if (RB_EMPTY(srte_policy_head
, &srte_policies
)) {
171 vty_out(vty
, "No SR Policies to display.\n\n");
176 RB_FOREACH (policy
, srte_policy_head
, &srte_policies
) {
177 struct srte_candidate
*candidate
;
179 char binding_sid
[16] = "-";
180 char *segment_list_info
;
181 static char undefined_info
[] = "(undefined)";
182 static char created_by_pce_info
[] = "(created by PCE)";
185 ipaddr2str(&policy
->endpoint
, endpoint
, sizeof(endpoint
));
186 if (policy
->binding_sid
!= MPLS_LABEL_NONE
)
187 snprintf(binding_sid
, sizeof(binding_sid
), "%u",
188 policy
->binding_sid
);
190 "Endpoint: %s Color: %u Name: %s BSID: %s Status: %s\n",
191 endpoint
, policy
->color
, policy
->name
, binding_sid
,
192 policy
->status
== SRTE_POLICY_STATUS_UP
? "Active"
195 RB_FOREACH (candidate
, srte_candidate_head
,
196 &policy
->candidate_paths
) {
197 struct srte_segment_list
*segment_list
;
199 segment_list
= candidate
->lsp
->segment_list
;
200 if (segment_list
== NULL
)
201 segment_list_info
= undefined_info
;
202 else if (segment_list
->protocol_origin
204 segment_list_info
= created_by_pce_info
;
207 candidate
->lsp
->segment_list
->name
;
210 " %s Preference: %d Name: %s Type: %s Segment-List: %s Protocol-Origin: %s\n",
211 CHECK_FLAG(candidate
->flags
, F_CANDIDATE_BEST
)
214 candidate
->preference
, candidate
->name
,
215 candidate
->type
== SRTE_CANDIDATE_TYPE_EXPLICIT
220 candidate
->lsp
->protocol_origin
));
230 segment_routing_list
,
233 "Configure segment routing\n")
235 VTY_PUSH_CONTEXT_NULL(SEGMENT_ROUTING_NODE
);
243 "Configure SR traffic engineering\n")
245 VTY_PUSH_CONTEXT_NULL(SR_TRAFFIC_ENG_NODE
);
250 * XPath: /frr-pathd:pathd/srte/segment-list
254 srte_segment_list_cmd
,
255 "segment-list WORD$name",
257 "Segment List Name\n")
259 char xpath
[XPATH_MAXLEN
];
262 snprintf(xpath
, sizeof(xpath
),
263 "/frr-pathd:pathd/srte/segment-list[name='%s']", name
);
264 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
266 snprintf(xpath
, sizeof(xpath
),
267 "/frr-pathd:pathd/srte/segment-list[name='%s']/protocol-origin",
269 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "local");
271 snprintf(xpath
, sizeof(xpath
),
272 "/frr-pathd:pathd/srte/segment-list[name='%s']/originator", name
);
273 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "config");
275 ret
= nb_cli_apply_changes(vty
, NULL
);
276 if (ret
== CMD_SUCCESS
) {
277 snprintf(xpath
, sizeof(xpath
),
278 "/frr-pathd:pathd/srte/segment-list[name='%s']", name
);
279 VTY_PUSH_XPATH(SR_SEGMENT_LIST_NODE
, xpath
);
285 DEFPY(srte_no_segment_list
,
286 srte_no_segment_list_cmd
,
287 "no segment-list WORD$name",
290 "Segment List Name\n")
292 char xpath
[XPATH_MAXLEN
];
294 snprintf(xpath
, sizeof(xpath
),
295 "/frr-pathd:pathd/srte/segment-list[name='%s']", name
);
296 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
298 return nb_cli_apply_changes(vty
, NULL
);
301 void cli_show_srte_segment_list(struct vty
*vty
, const struct lyd_node
*dnode
,
304 vty_out(vty
, " segment-list %s\n",
305 yang_dnode_get_string(dnode
, "./name"));
308 void cli_show_srte_segment_list_end(struct vty
*vty
,
309 const struct lyd_node
*dnode
)
311 vty_out(vty
, " exit\n");
314 static int segment_list_has_src_dst(
315 struct vty
*vty
, char *xpath
, long index
, const char *index_str
,
316 struct in_addr adj_src_ipv4
, struct in_addr adj_dst_ipv4
,
317 struct in6_addr adj_src_ipv6
, struct in6_addr adj_dst_ipv6
,
318 const char *adj_src_ipv4_str
, const char *adj_dst_ipv4_str
,
319 const char *adj_src_ipv6_str
, const char *adj_dst_ipv6_str
)
321 const char *node_src_id
;
322 uint32_t ted_sid
= MPLS_LABEL_NONE
;
324 struct ipaddr ip_src
= {};
325 struct ipaddr ip_dst
= {};
326 if (adj_src_ipv4_str
!= NULL
) {
327 ip_src
.ipa_type
= IPADDR_V4
;
328 ip_src
.ip
._v4_addr
= adj_src_ipv4
;
329 ip_dst
.ipa_type
= IPADDR_V4
;
330 ip_dst
.ip
._v4_addr
= adj_dst_ipv4
;
331 } else if (adj_src_ipv6_str
!= NULL
) {
332 ip_src
.ipa_type
= IPADDR_V6
;
333 ip_src
.ip
._v6_addr
= adj_src_ipv6
;
334 ip_dst
.ipa_type
= IPADDR_V6
;
335 ip_dst
.ip
._v6_addr
= adj_dst_ipv6
;
337 return CMD_ERR_NO_MATCH
;
339 ted_sid
= path_ted_query_type_f(&ip_src
, &ip_dst
);
340 if (ted_sid
== MPLS_LABEL_NONE
) {
342 "%s: [rcv ted] CLI NOT FOUND Continue query_type_f SRC (%pIA) DST (%pIA)!",
343 __func__
, &ip_src
, &ip_dst
);
346 snprintf(xpath
, XPATH_MAXLEN
, "./segment[index='%s']/nai/type",
348 if (adj_src_ipv4_str
!= NULL
) {
349 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
351 node_src_id
= adj_src_ipv4_str
;
352 } else if (adj_src_ipv6_str
!= NULL
) {
353 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
355 node_src_id
= adj_src_ipv6_str
;
358 * This is just to make the compiler happy about
359 * node_src_id not being initialized. This
360 * should never happen unless we change the cli
363 assert(!"We must have a adj_src_ipv4_str or a adj_src_ipv6_str");
367 snprintf(xpath
, XPATH_MAXLEN
, "./segment[index='%s']/nai/local-address",
369 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, node_src_id
);
370 snprintf(xpath
, XPATH_MAXLEN
,
371 "./segment[index='%s']/nai/remote-address", index_str
);
372 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
373 adj_dst_ipv4_str
? adj_dst_ipv4_str
377 int segment_list_has_prefix(
378 struct vty
*vty
, char *xpath
, long index
, const char *index_str
,
379 const struct prefix_ipv4
*prefix_ipv4
, const char *prefix_ipv4_str
,
380 const struct prefix_ipv6
*prefix_ipv6
, const char *prefix_ipv6_str
,
381 const char *has_algo
, long algo
, const char *algo_str
,
382 const char *has_iface_id
, long iface_id
, const char *iface_id_str
)
384 char buf_prefix
[INET6_ADDRSTRLEN
];
386 uint32_t ted_sid
= MPLS_LABEL_NONE
;
387 struct prefix prefix_cli
= {};
388 struct ipaddr pre_ipaddr
= {};
389 /* prefix with algorithm or local interface id */
391 snprintf(xpath
, XPATH_MAXLEN
, "./segment[index='%s']/nai/type",
393 if (has_iface_id
!= NULL
) {
394 if (prefix_ipv4_str
!= NULL
) {
395 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
397 } else if (prefix_ipv6_str
!= NULL
) {
398 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
401 return CMD_ERR_NO_MATCH
;
404 if (prefix_ipv4_str
!= NULL
) {
405 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
407 } else if (prefix_ipv6_str
!= NULL
) {
408 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
411 return CMD_ERR_NO_MATCH
;
415 if (prefix_ipv4_str
!= NULL
) {
416 if (!str2prefix(prefix_ipv4_str
, &prefix_cli
)) {
417 vty_out(vty
, "%% Malformed prefix\n");
418 return CMD_WARNING_CONFIG_FAILED
;
420 inet_ntop(AF_INET
, &prefix_cli
.u
.prefix4
, buf_prefix
,
422 pre_ipaddr
.ipa_type
= IPADDR_V4
;
423 pre_ipaddr
.ip
._v4_addr
= prefix_cli
.u
.prefix4
;
424 } else if (prefix_ipv6_str
!= NULL
) {
425 if (!str2prefix(prefix_ipv6_str
, &prefix_cli
)) {
426 vty_out(vty
, "%% Malformed prefix\n");
427 return CMD_WARNING_CONFIG_FAILED
;
429 inet_ntop(AF_INET6
, &prefix_cli
.u
.prefix6
, buf_prefix
,
431 pre_ipaddr
.ipa_type
= IPADDR_V6
;
432 pre_ipaddr
.ip
._v6_addr
= prefix_cli
.u
.prefix6
;
434 snprintf(xpath
, XPATH_MAXLEN
, "./segment[index='%s']/nai/local-address",
436 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, buf_prefix
);
437 snprintf(xpath
, XPATH_MAXLEN
,
438 "./segment[index='%s']/nai/local-prefix-len", index_str
);
439 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
441 ? strchr(prefix_ipv4_str
, '/') + 1
442 : strchr(prefix_ipv6_str
, '/') + 1);
444 if (has_algo
!= NULL
) {
445 snprintf(xpath
, XPATH_MAXLEN
,
446 "./segment[index='%s']/nai/algorithm", index_str
);
447 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, algo_str
);
449 if (has_iface_id
!= NULL
) {
450 snprintf(xpath
, XPATH_MAXLEN
,
451 "./segment[index='%s']/nai/local-interface",
453 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
457 if (has_algo
!= NULL
) {
458 ted_sid
= path_ted_query_type_c(&prefix_cli
, algo
);
459 if (ted_sid
== MPLS_LABEL_NONE
) {
461 "%s: [rcv ted] CLI NOT FOUND Continue query_type_c PREFIX (%pIA/%d) ALGO (%ld) sid:(%d)!",
462 __func__
, &pre_ipaddr
, prefix_cli
.prefixlen
,
466 if (has_iface_id
!= NULL
) {
467 ted_sid
= path_ted_query_type_e(&prefix_cli
, iface_id
);
468 if (ted_sid
== MPLS_LABEL_NONE
) {
470 "%s: [rcv ted] CLI NOT FOUND Continue query_type_e PREFIX (%pIA/%d) IFACE (%ld) sid:(%d)!",
471 __func__
, &pre_ipaddr
, prefix_cli
.prefixlen
,
478 * XPath: /frr-pathd:pathd/srte/segment-list/segment
480 /* clang-format off */
481 DEFPY(srte_segment_list_segment
, srte_segment_list_segment_cmd
,
482 "index (0-4294967295)$index <[mpls$has_mpls_label label (16-1048575)$label] "
485 "prefix <A.B.C.D/M$prefix_ipv4|X:X::X:X/M$prefix_ipv6>"
486 "<algorithm$has_algo (0-1)$algo| iface$has_iface_id (0-4294967295)$iface_id>"
487 "| adjacency$has_adj "
488 "<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>"
497 "NAI prefix identifier\n"
498 "NAI IPv4 prefix identifier\n"
499 "NAI IPv6 prefix identifier\n"
501 "Algorithm Value SPF or Strict-SPF\n"
505 "ADJ IPv4 src identifier\n"
506 "ADJ IPv4 dst identifier\n"
507 "ADJ IPv6 src identifier\n"
508 "ADJ IPv6 dst identifier\n")
509 /* clang-format on */
511 char xpath
[XPATH_MAXLEN
];
512 int status
= CMD_SUCCESS
;
515 snprintf(xpath
, sizeof(xpath
), "./segment[index='%s']", index_str
);
516 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
518 if (has_mpls_label
!= NULL
) {
519 snprintf(xpath
, sizeof(xpath
),
520 "./segment[index='%s']/sid-value", index_str
);
521 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, label_str
);
522 return nb_cli_apply_changes(vty
, NULL
);
525 if (has_adj
!= NULL
) {
526 status
= segment_list_has_src_dst(vty
, xpath
, index
, index_str
,
527 adj_src_ipv4
, adj_dst_ipv4
,
528 adj_src_ipv6
, adj_dst_ipv6
,
529 adj_src_ipv4_str
, adj_dst_ipv4_str
,
530 adj_src_ipv6_str
, adj_dst_ipv6_str
);
531 if (status
!= CMD_SUCCESS
)
534 status
= segment_list_has_prefix(
535 vty
, xpath
, index
, index_str
, prefix_ipv4
,
536 prefix_ipv4_str
, prefix_ipv6
, prefix_ipv6_str
, has_algo
,
537 algo
, algo_str
, has_iface_id
, iface_id
, iface_id_str
);
538 if (status
!= CMD_SUCCESS
)
542 return nb_cli_apply_changes(vty
, NULL
);
545 DEFPY(srte_segment_list_no_segment
,
546 srte_segment_list_no_segment_cmd
,
547 "no index (0-4294967295)$index",
552 char xpath
[XPATH_MAXLEN
];
554 snprintf(xpath
, sizeof(xpath
), "./segment[index='%s']", index_str
);
555 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
557 return nb_cli_apply_changes(vty
, NULL
);
560 void cli_show_srte_segment_list_segment(struct vty
*vty
,
561 const struct lyd_node
*dnode
,
564 vty_out(vty
, " index %s", yang_dnode_get_string(dnode
, "./index"));
565 if (yang_dnode_exists(dnode
, "./sid-value")) {
566 vty_out(vty
, " mpls label %s",
567 yang_dnode_get_string(dnode
, "./sid-value"));
569 if (yang_dnode_exists(dnode
, "./nai")) {
571 struct ipaddr addr_rmt
;
573 switch (yang_dnode_get_enum(dnode
, "./nai/type")) {
574 case SRTE_SEGMENT_NAI_TYPE_IPV4_NODE
:
575 case SRTE_SEGMENT_NAI_TYPE_IPV4_LOCAL_IFACE
:
576 case SRTE_SEGMENT_NAI_TYPE_IPV4_ALGORITHM
:
577 yang_dnode_get_ip(&addr
, dnode
, "./nai/local-address");
578 vty_out(vty
, " nai prefix %pI4", &addr
.ipaddr_v4
);
580 case SRTE_SEGMENT_NAI_TYPE_IPV6_NODE
:
581 case SRTE_SEGMENT_NAI_TYPE_IPV6_LOCAL_IFACE
:
582 case SRTE_SEGMENT_NAI_TYPE_IPV6_ALGORITHM
:
583 yang_dnode_get_ip(&addr
, dnode
, "./nai/local-address");
584 vty_out(vty
, " nai prefix %pI6", &addr
.ipaddr_v6
);
586 case SRTE_SEGMENT_NAI_TYPE_IPV4_ADJACENCY
:
587 yang_dnode_get_ip(&addr
, dnode
, "./nai/local-address");
588 yang_dnode_get_ip(&addr_rmt
, dnode
,
589 "./nai/remote-address");
590 vty_out(vty
, " nai adjacency %pI4", &addr
.ipaddr_v4
);
591 vty_out(vty
, " %pI4", &addr_rmt
.ipaddr_v4
);
593 case SRTE_SEGMENT_NAI_TYPE_IPV6_ADJACENCY
:
594 yang_dnode_get_ip(&addr
, dnode
, "./nai/local-address");
595 yang_dnode_get_ip(&addr_rmt
, dnode
,
596 "./nai/remote-address");
597 vty_out(vty
, " nai adjacency %pI6", &addr
.ipaddr_v6
);
598 vty_out(vty
, " %pI6", &addr_rmt
.ipaddr_v6
);
603 if (yang_dnode_exists(dnode
, "./nai/local-prefix-len")) {
605 yang_dnode_get_string(
606 dnode
, "./nai/local-prefix-len"));
608 if (yang_dnode_exists(dnode
, "./nai/local-interface")) {
609 vty_out(vty
, " iface %s",
610 yang_dnode_get_string(dnode
,
611 "./nai/local-interface"));
613 if (yang_dnode_exists(dnode
, "./nai/algorithm")) {
614 vty_out(vty
, " algorithm %s",
615 yang_dnode_get_string(dnode
,
623 * XPath: /frr-pathd:pathd/policy
628 "policy color (0-4294967295)$num endpoint <A.B.C.D|X:X::X:X>$endpoint",
629 "Segment Routing Policy\n"
631 "SR Policy color value\n"
632 "SR Policy endpoint\n"
633 "SR Policy endpoint IPv4 address\n"
634 "SR Policy endpoint IPv6 address\n")
636 char xpath
[XPATH_POLICY_BASELEN
];
639 snprintf(xpath
, sizeof(xpath
),
640 "/frr-pathd:pathd/srte/policy[color='%s'][endpoint='%s']",
641 num_str
, endpoint_str
);
642 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
644 ret
= nb_cli_apply_changes(vty
, NULL
);
645 if (ret
== CMD_SUCCESS
)
646 VTY_PUSH_XPATH(SR_POLICY_NODE
, xpath
);
651 DEFPY(srte_no_policy
,
653 "no policy color (0-4294967295)$num endpoint <A.B.C.D|X:X::X:X>$endpoint",
655 "Segment Routing Policy\n"
657 "SR Policy color value\n"
658 "SR Policy endpoint\n"
659 "SR Policy endpoint IPv4 address\n"
660 "SR Policy endpoint IPv6 address\n")
662 char xpath
[XPATH_POLICY_BASELEN
];
664 snprintf(xpath
, sizeof(xpath
),
665 "/frr-pathd:pathd/srte/policy[color='%s'][endpoint='%s']",
666 num_str
, endpoint_str
);
667 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
669 return nb_cli_apply_changes(vty
, NULL
);
672 void cli_show_srte_policy(struct vty
*vty
, const struct lyd_node
*dnode
,
675 vty_out(vty
, " policy color %s endpoint %s\n",
676 yang_dnode_get_string(dnode
, "./color"),
677 yang_dnode_get_string(dnode
, "./endpoint"));
680 void cli_show_srte_policy_end(struct vty
*vty
, const struct lyd_node
*dnode
)
682 vty_out(vty
, " exit\n");
686 * XPath: /frr-pathd:pathd/srte/policy/name
688 DEFPY(srte_policy_name
,
689 srte_policy_name_cmd
,
691 "Segment Routing Policy name\n"
692 "SR Policy name value\n")
694 nb_cli_enqueue_change(vty
, "./name", NB_OP_CREATE
, name
);
696 return nb_cli_apply_changes(vty
, NULL
);
699 DEFPY(srte_policy_no_name
,
700 srte_policy_no_name_cmd
,
703 "Segment Routing Policy name\n"
704 "SR Policy name value\n")
706 nb_cli_enqueue_change(vty
, "./name", NB_OP_DESTROY
, NULL
);
708 return nb_cli_apply_changes(vty
, NULL
);
712 void cli_show_srte_policy_name(struct vty
*vty
, const struct lyd_node
*dnode
,
715 vty_out(vty
, " name %s\n", yang_dnode_get_string(dnode
, NULL
));
719 * XPath: /frr-pathd:pathd/srte/policy/binding-sid
721 DEFPY(srte_policy_binding_sid
,
722 srte_policy_binding_sid_cmd
,
723 "binding-sid (16-1048575)$label",
724 "Segment Routing Policy Binding-SID\n"
725 "SR Policy Binding-SID label\n")
727 nb_cli_enqueue_change(vty
, "./binding-sid", NB_OP_CREATE
, label_str
);
729 return nb_cli_apply_changes(vty
, NULL
);
732 DEFPY(srte_policy_no_binding_sid
,
733 srte_policy_no_binding_sid_cmd
,
734 "no binding-sid [(16-1048575)]",
736 "Segment Routing Policy Binding-SID\n"
737 "SR Policy Binding-SID label\n")
739 nb_cli_enqueue_change(vty
, "./binding-sid", NB_OP_DESTROY
, NULL
);
741 return nb_cli_apply_changes(vty
, NULL
);
744 void cli_show_srte_policy_binding_sid(struct vty
*vty
,
745 const struct lyd_node
*dnode
,
748 vty_out(vty
, " binding-sid %s\n", yang_dnode_get_string(dnode
, NULL
));
752 * XPath: /frr-pathd:pathd/srte/policy/candidate-path
754 DEFPY(srte_policy_candidate_exp
,
755 srte_policy_candidate_exp_cmd
,
756 "candidate-path preference (0-4294967295)$preference name WORD$name \
757 explicit segment-list WORD$list_name",
758 "Segment Routing Policy Candidate Path\n"
759 "Segment Routing Policy Candidate Path Preference\n"
760 "Administrative Preference\n"
761 "Segment Routing Policy Candidate Path Name\n"
765 "Name of the Segment List\n")
767 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, preference_str
);
768 nb_cli_enqueue_change(vty
, "./name", NB_OP_MODIFY
, name
);
769 nb_cli_enqueue_change(vty
, "./protocol-origin", NB_OP_MODIFY
, "local");
770 nb_cli_enqueue_change(vty
, "./originator", NB_OP_MODIFY
, "config");
771 nb_cli_enqueue_change(vty
, "./type", NB_OP_MODIFY
, "explicit");
772 nb_cli_enqueue_change(vty
, "./segment-list-name", NB_OP_MODIFY
,
774 return nb_cli_apply_changes(vty
, "./candidate-path[preference='%s']",
779 srte_policy_candidate_dyn
,
780 srte_policy_candidate_dyn_cmd
,
781 "candidate-path preference (0-4294967295)$preference name WORD$name dynamic",
782 "Segment Routing Policy Candidate Path\n"
783 "Segment Routing Policy Candidate Path Preference\n"
784 "Administrative Preference\n"
785 "Segment Routing Policy Candidate Path Name\n"
789 char xpath
[XPATH_MAXLEN
+ XPATH_CANDIDATE_BASELEN
];
792 snprintf(xpath
, sizeof(xpath
), "%s/candidate-path[preference='%s']",
793 VTY_CURR_XPATH
, preference_str
);
795 nb_cli_enqueue_change(vty
, ".", NB_OP_CREATE
, preference_str
);
796 nb_cli_enqueue_change(vty
, "./name", NB_OP_MODIFY
, name
);
797 nb_cli_enqueue_change(vty
, "./protocol-origin", NB_OP_MODIFY
, "local");
798 nb_cli_enqueue_change(vty
, "./originator", NB_OP_MODIFY
, "config");
799 nb_cli_enqueue_change(vty
, "./type", NB_OP_MODIFY
, "dynamic");
800 ret
= nb_cli_apply_changes(vty
, "./candidate-path[preference='%s']",
803 if (ret
== CMD_SUCCESS
)
804 VTY_PUSH_XPATH(SR_CANDIDATE_DYN_NODE
, xpath
);
809 DEFPY(srte_candidate_bandwidth
,
810 srte_candidate_bandwidth_cmd
,
811 "bandwidth BANDWIDTH$value [required$required]",
812 "Define a bandwidth constraint\n"
814 "Required constraint\n")
816 nb_cli_enqueue_change(vty
, "./constraints/bandwidth/required",
817 NB_OP_MODIFY
, required
? "true" : "false");
818 nb_cli_enqueue_change(vty
, "./constraints/bandwidth/value",
819 NB_OP_MODIFY
, value
);
820 return nb_cli_apply_changes(vty
, NULL
);
823 DEFPY(srte_candidate_no_bandwidth
,
824 srte_candidate_no_bandwidth_cmd
,
825 "no bandwidth [BANDWIDTH$value] [required$required]",
827 "Remove a bandwidth constraint\n"
829 "Required constraint\n")
831 nb_cli_enqueue_change(vty
, "./constraints/bandwidth", NB_OP_DESTROY
,
833 return nb_cli_apply_changes(vty
, NULL
);
836 DEFPY(srte_candidate_affinity_filter
, srte_candidate_affinity_filter_cmd
,
837 "affinity <exclude-any|include-any|include-all>$type BITPATTERN$value",
838 "Affinity constraint\n"
839 "Exclude any matching link\n"
840 "Include any matching link\n"
841 "Include all matching links\n"
842 "Attribute filter bit pattern as an hexadecimal value from 0x00000000 to 0xFFFFFFFF\n")
845 char xpath
[XPATH_CANDIDATE_MAXLEN
];
846 char decimal_value
[11];
848 if (sscanf(value
, "0x%x", &filter
) != 1) {
849 vty_out(vty
, "affinity type: fscanf: %s\n",
850 safe_strerror(errno
));
851 return CMD_WARNING_CONFIG_FAILED
;
853 snprintf(decimal_value
, sizeof(decimal_value
), "%u", filter
);
854 snprintf(xpath
, sizeof(xpath
), "./constraints/affinity/%s", type
);
855 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, decimal_value
);
857 return nb_cli_apply_changes(vty
, NULL
);
860 DEFPY(srte_candidate_no_affinity_filter
, srte_candidate_no_affinity_filter_cmd
,
861 "no affinity <exclude-any|include-any|include-all>$type [BITPATTERN$value]",
863 "Affinity constraint\n"
864 "Exclude any matching link\n"
865 "Include any matching link\n"
866 "Include all matching links\n"
867 "Attribute filter bit pattern as an hexadecimal value from 0x00000000 to 0xFFFFFFFF\n")
869 char xpath
[XPATH_CANDIDATE_MAXLEN
];
871 snprintf(xpath
, sizeof(xpath
), "./constraints/affinity/%s", type
);
872 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
873 return nb_cli_apply_changes(vty
, NULL
);
876 DEFPY(srte_candidate_metric
,
877 srte_candidate_metric_cmd
,
878 "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]",
879 "Define a metric constraint\n"
880 "If the metric is bounded\n"
884 "Aggregate bandwidth consumption\n"
885 "Load of the most loaded link\n"
886 "Cumulative IGP cost\n"
887 "Cumulative TE cost\n"
890 "P2MP hop count metric\n"
891 "Segment-ID (SID) Depth.\n"
892 "Path Delay metric\n"
893 "Path Delay Variation metric\n"
895 "P2MP Path Delay metric\n"
896 "P2MP Path Delay variation metric\n"
897 "P2MP Path Loss metric\n"
898 "Number of adaptations on a path\n"
899 "Number of layers on a path\n"
900 "Domain Count metric\n"
901 "Border Node Count metric\n"
903 "Required constraint\n")
905 char xpath
[XPATH_CANDIDATE_MAXLEN
];
906 snprintf(xpath
, sizeof(xpath
), "./constraints/metrics[type='%s']/value",
908 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, value
);
909 snprintf(xpath
, sizeof(xpath
),
910 "./constraints/metrics[type='%s']/is-bound", type
);
911 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
912 (bound
!= NULL
) ? "true" : "false");
913 snprintf(xpath
, sizeof(xpath
),
914 "./constraints/metrics[type='%s']/required", type
);
915 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
916 required
? "true" : "false");
917 return nb_cli_apply_changes(vty
, NULL
);
920 DEFPY(srte_candidate_no_metric
,
921 srte_candidate_no_metric_cmd
,
922 "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]",
924 "Remove a metric constraint\n"
925 "If the metric is bounded\n"
929 "Aggregate bandwidth consumption\n"
930 "Load of the most loaded link\n"
931 "Cumulative IGP cost\n"
932 "Cumulative TE cost\n"
935 "P2MP hop count metric\n"
936 "Segment-ID (SID) Depth.\n"
937 "Path Delay metric\n"
938 "Path Delay Variation metric\n"
940 "P2MP Path Delay metric\n"
941 "P2MP Path Delay variation metric\n"
942 "P2MP Path Loss metric\n"
943 "Number of adaptations on a path\n"
944 "Number of layers on a path\n"
945 "Domain Count metric\n"
946 "Border Node Count metric\n"
948 "Required constraint\n")
950 char xpath
[XPATH_CANDIDATE_MAXLEN
];
951 snprintf(xpath
, sizeof(xpath
), "./constraints/metrics[type='%s']",
953 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
954 return nb_cli_apply_changes(vty
, NULL
);
957 DEFPY(srte_policy_no_candidate
,
958 srte_policy_no_candidate_cmd
,
960 preference (0-4294967295)$preference\
963 explicit segment-list WORD\
967 "Segment Routing Policy Candidate Path\n"
968 "Segment Routing Policy Candidate Path Preference\n"
969 "Administrative Preference\n"
970 "Segment Routing Policy Candidate Path Name\n"
974 "Name of the Segment List\n"
977 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
979 return nb_cli_apply_changes(vty
, "./candidate-path[preference='%s']",
983 DEFPY(srte_candidate_objfun
,
984 srte_candidate_objfun_cmd
,
985 "objective-function <mcp|mlp|mbp|mbc|mll|mcc|spt|mct|mplp|mup|mrup|mtd|mbn|mctd|msl|mss|msn>$type [required$required]",
986 "Define an objective function constraint\n"
987 "Minimum Cost Path\n"
988 "Minimum Load Path\n"
989 "Maximum residual Bandwidth Path\n"
990 "Minimize aggregate Bandwidth Consumption\n"
991 "Minimize the Load of the most loaded Link\n"
992 "Minimize the Cumulative Cost of a set of paths\n"
993 "Shortest Path Tree\n"
994 "Minimum Cost Tree\n"
995 "Minimum Packet Loss Path\n"
996 "Maximum Under-Utilized Path\n"
997 "Maximum Reserved Under-Utilized Path\n"
998 "Minimize the number of Transit Domains\n"
999 "Minimize the number of Border Nodes\n"
1000 "Minimize the number of Common Transit Domains\n"
1001 "Minimize the number of Shared Links\n"
1002 "Minimize the number of Shared SRLGs\n"
1003 "Minimize the number of Shared Nodes\n"
1004 "Required constraint\n")
1006 char xpath
[XPATH_CANDIDATE_MAXLEN
];
1007 nb_cli_enqueue_change(vty
, "./constraints/objective-function",
1008 NB_OP_DESTROY
, NULL
);
1009 snprintf(xpath
, sizeof(xpath
),
1010 "./constraints/objective-function/required");
1011 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
1012 required
? "true" : "false");
1013 nb_cli_enqueue_change(vty
, "./constraints/objective-function/type",
1014 NB_OP_MODIFY
, type
);
1015 return nb_cli_apply_changes(vty
, NULL
);
1018 DEFPY(srte_candidate_no_objfun
,
1019 srte_candidate_no_objfun_cmd
,
1020 "no objective-function [<mcp|mlp|mbp|mbc|mll|mcc|spt|mct|mplp|mup|mrup|mtd|mbn|mctd|msl|mss|msn>] [required$required]",
1022 "Remove an objective function constraint\n"
1023 "Minimum Cost Path\n"
1024 "Minimum Load Path\n"
1025 "Maximum residual Bandwidth Path\n"
1026 "Minimize aggregate Bandwidth Consumption\n"
1027 "Minimize the Load of the most loaded Link\n"
1028 "Minimize the Cumulative Cost of a set of paths\n"
1029 "Shortest Path Tree\n"
1030 "Minimum Cost Tree\n"
1031 "Minimum Packet Loss Path\n"
1032 "Maximum Under-Utilized Path\n"
1033 "Maximum Reserved Under-Utilized Path\n"
1034 "Minimize the number of Transit Domains\n"
1035 "Minimize the number of Border Nodes\n"
1036 "Minimize the number of Common Transit Domains\n"
1037 "Minimize the number of Shared Links\n"
1038 "Minimize the number of Shared SRLGs\n"
1039 "Minimize the number of Shared Nodes\n"
1040 "Required constraint\n")
1042 nb_cli_enqueue_change(vty
, "./constraints/objective-function",
1043 NB_OP_DESTROY
, NULL
);
1044 return nb_cli_apply_changes(vty
, NULL
);
1047 static const char *objfun_type_name(enum objfun_type type
)
1089 DEFPY_NOSH(show_debugging_pathd
, show_debugging_pathd_cmd
,
1090 "show debugging [pathd]",
1092 "State of each debugging option\n"
1093 "pathd module debugging\n")
1096 cmd_show_lib_debugs(vty
);
1097 /* nothing to do here */
1101 static const char *metric_type_name(enum srte_candidate_metric_type type
)
1104 case SRTE_CANDIDATE_METRIC_TYPE_IGP
:
1106 case SRTE_CANDIDATE_METRIC_TYPE_TE
:
1108 case SRTE_CANDIDATE_METRIC_TYPE_HC
:
1110 case SRTE_CANDIDATE_METRIC_TYPE_ABC
:
1112 case SRTE_CANDIDATE_METRIC_TYPE_LMLL
:
1114 case SRTE_CANDIDATE_METRIC_TYPE_CIGP
:
1116 case SRTE_CANDIDATE_METRIC_TYPE_CTE
:
1118 case SRTE_CANDIDATE_METRIC_TYPE_PIGP
:
1120 case SRTE_CANDIDATE_METRIC_TYPE_PTE
:
1122 case SRTE_CANDIDATE_METRIC_TYPE_PHC
:
1124 case SRTE_CANDIDATE_METRIC_TYPE_MSD
:
1126 case SRTE_CANDIDATE_METRIC_TYPE_PD
:
1128 case SRTE_CANDIDATE_METRIC_TYPE_PDV
:
1130 case SRTE_CANDIDATE_METRIC_TYPE_PL
:
1132 case SRTE_CANDIDATE_METRIC_TYPE_PPD
:
1134 case SRTE_CANDIDATE_METRIC_TYPE_PPDV
:
1136 case SRTE_CANDIDATE_METRIC_TYPE_PPL
:
1138 case SRTE_CANDIDATE_METRIC_TYPE_NAP
:
1140 case SRTE_CANDIDATE_METRIC_TYPE_NLP
:
1142 case SRTE_CANDIDATE_METRIC_TYPE_DC
:
1144 case SRTE_CANDIDATE_METRIC_TYPE_BNC
:
1151 static void config_write_float(struct vty
*vty
, float value
)
1153 if (fabs(truncf(value
) - value
) < FLT_EPSILON
) {
1154 vty_out(vty
, " %d", (int)value
);
1157 vty_out(vty
, " %f", value
);
1161 static void config_write_metric(struct vty
*vty
,
1162 enum srte_candidate_metric_type type
,
1163 float value
, bool required
, bool is_bound
)
1165 const char *name
= metric_type_name(type
);
1168 vty_out(vty
, " metric %s%s", is_bound
? "bound " : "",
1169 metric_type_name(type
));
1170 config_write_float(vty
, value
);
1171 vty_out(vty
, required
? " required" : "");
1175 static int config_write_metric_cb(const struct lyd_node
*dnode
, void *arg
)
1177 struct vty
*vty
= arg
;
1178 enum srte_candidate_metric_type type
;
1179 bool required
, is_bound
= false;
1182 type
= yang_dnode_get_enum(dnode
, "./type");
1183 value
= (float)yang_dnode_get_dec64(dnode
, "./value");
1184 required
= yang_dnode_get_bool(dnode
, "./required");
1185 if (yang_dnode_exists(dnode
, "./is-bound"))
1186 is_bound
= yang_dnode_get_bool(dnode
, "./is-bound");
1188 config_write_metric(vty
, type
, value
, required
, is_bound
);
1189 return YANG_ITER_CONTINUE
;
1192 void cli_show_srte_policy_candidate_path(struct vty
*vty
,
1193 const struct lyd_node
*dnode
,
1199 enum objfun_type objfun_type
;
1200 const char *type
= yang_dnode_get_string(dnode
, "./type");
1202 vty_out(vty
, " candidate-path preference %s name %s %s",
1203 yang_dnode_get_string(dnode
, "./preference"),
1204 yang_dnode_get_string(dnode
, "./name"), type
);
1205 if (strmatch(type
, "explicit"))
1206 vty_out(vty
, " segment-list %s",
1207 yang_dnode_get_string(dnode
, "./segment-list-name"));
1210 if (strmatch(type
, "dynamic")) {
1211 if (yang_dnode_exists(dnode
, "./constraints/bandwidth")) {
1212 bandwidth
= (float)yang_dnode_get_dec64(
1213 dnode
, "./constraints/bandwidth/value");
1214 required
= yang_dnode_get_bool(
1215 dnode
, "./constraints/bandwidth/required");
1216 vty_out(vty
, " bandwidth");
1217 config_write_float(vty
, bandwidth
);
1219 vty_out(vty
, " required");
1222 if (yang_dnode_exists(dnode
,
1223 "./constraints/affinity/exclude-any")) {
1224 affinity
= yang_dnode_get_uint32(
1225 dnode
, "./constraints/affinity/exclude-any");
1226 vty_out(vty
, " affinity exclude-any 0x%08x\n",
1229 if (yang_dnode_exists(dnode
,
1230 "./constraints/affinity/include-any")) {
1231 affinity
= yang_dnode_get_uint32(
1232 dnode
, "./constraints/affinity/include-any");
1233 vty_out(vty
, " affinity include-any 0x%08x\n",
1236 if (yang_dnode_exists(dnode
,
1237 "./constraints/affinity/include-all")) {
1238 affinity
= yang_dnode_get_uint32(
1239 dnode
, "./constraints/affinity/include-all");
1240 vty_out(vty
, " affinity include-all 0x%08x\n",
1243 yang_dnode_iterate(config_write_metric_cb
, vty
, dnode
,
1244 "./constraints/metrics");
1245 if (yang_dnode_exists(dnode
,
1246 "./constraints/objective-function")) {
1247 objfun_type
= yang_dnode_get_enum(dnode
,
1248 "./constraints/objective-function/type");
1249 required
= yang_dnode_get_bool(dnode
,
1250 "./constraints/objective-function/required");
1251 vty_out(vty
, " objective-function %s%s\n",
1252 objfun_type_name(objfun_type
),
1253 required
? " required" : "");
1258 void cli_show_srte_policy_candidate_path_end(struct vty
*vty
,
1259 const struct lyd_node
*dnode
)
1261 const char *type
= yang_dnode_get_string(dnode
, "./type");
1263 if (strmatch(type
, "dynamic"))
1264 vty_out(vty
, " exit\n");
1267 static int config_write_dnode(const struct lyd_node
*dnode
, void *arg
)
1269 struct vty
*vty
= arg
;
1271 nb_cli_show_dnode_cmds(vty
, dnode
, false);
1273 return YANG_ITER_CONTINUE
;
1276 int config_write_segment_routing(struct vty
*vty
)
1278 vty_out(vty
, "segment-routing\n");
1279 vty_out(vty
, " traffic-eng\n");
1281 path_ted_config_write(vty
);
1283 yang_dnode_iterate(config_write_dnode
, vty
, running_config
->dnode
,
1284 "/frr-pathd:pathd/srte/segment-list");
1285 yang_dnode_iterate(config_write_dnode
, vty
, running_config
->dnode
,
1286 "/frr-pathd:pathd/srte/policy");
1288 hook_call(pathd_srte_config_write
, vty
);
1290 vty_out(vty
, " exit\n");
1291 vty_out(vty
, "exit\n");
1296 void path_cli_init(void)
1298 install_node(&segment_routing_node
);
1299 install_node(&sr_traffic_eng_node
);
1300 install_node(&srte_segment_list_node
);
1301 install_node(&srte_policy_node
);
1302 install_node(&srte_candidate_dyn_node
);
1303 install_default(SEGMENT_ROUTING_NODE
);
1304 install_default(SR_TRAFFIC_ENG_NODE
);
1305 install_default(SR_SEGMENT_LIST_NODE
);
1306 install_default(SR_POLICY_NODE
);
1307 install_default(SR_CANDIDATE_DYN_NODE
);
1309 install_element(ENABLE_NODE
, &show_debugging_pathd_cmd
);
1310 install_element(ENABLE_NODE
, &show_srte_policy_cmd
);
1311 install_element(ENABLE_NODE
, &show_srte_policy_detail_cmd
);
1313 install_element(CONFIG_NODE
, &segment_routing_cmd
);
1314 install_element(SEGMENT_ROUTING_NODE
, &sr_traffic_eng_cmd
);
1315 install_element(SR_TRAFFIC_ENG_NODE
, &srte_segment_list_cmd
);
1316 install_element(SR_TRAFFIC_ENG_NODE
, &srte_no_segment_list_cmd
);
1317 install_element(SR_SEGMENT_LIST_NODE
,
1318 &srte_segment_list_segment_cmd
);
1319 install_element(SR_SEGMENT_LIST_NODE
,
1320 &srte_segment_list_no_segment_cmd
);
1321 install_element(SR_TRAFFIC_ENG_NODE
, &srte_policy_cmd
);
1322 install_element(SR_TRAFFIC_ENG_NODE
, &srte_no_policy_cmd
);
1323 install_element(SR_POLICY_NODE
, &srte_policy_name_cmd
);
1324 install_element(SR_POLICY_NODE
, &srte_policy_no_name_cmd
);
1325 install_element(SR_POLICY_NODE
, &srte_policy_binding_sid_cmd
);
1326 install_element(SR_POLICY_NODE
, &srte_policy_no_binding_sid_cmd
);
1327 install_element(SR_POLICY_NODE
, &srte_policy_candidate_exp_cmd
);
1328 install_element(SR_POLICY_NODE
, &srte_policy_candidate_dyn_cmd
);
1329 install_element(SR_POLICY_NODE
, &srte_policy_no_candidate_cmd
);
1330 install_element(SR_CANDIDATE_DYN_NODE
,
1331 &srte_candidate_bandwidth_cmd
);
1332 install_element(SR_CANDIDATE_DYN_NODE
,
1333 &srte_candidate_no_bandwidth_cmd
);
1334 install_element(SR_CANDIDATE_DYN_NODE
,
1335 &srte_candidate_affinity_filter_cmd
);
1336 install_element(SR_CANDIDATE_DYN_NODE
,
1337 &srte_candidate_no_affinity_filter_cmd
);
1338 install_element(SR_CANDIDATE_DYN_NODE
,
1339 &srte_candidate_metric_cmd
);
1340 install_element(SR_CANDIDATE_DYN_NODE
,
1341 &srte_candidate_no_metric_cmd
);
1342 install_element(SR_CANDIDATE_DYN_NODE
,
1343 &srte_candidate_objfun_cmd
);
1344 install_element(SR_CANDIDATE_DYN_NODE
,
1345 &srte_candidate_no_objfun_cmd
);