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 #include "pathd/path_cli_clippy.c"
35 #include "pathd/path_ted.h"
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)
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
);
59 DEFINE_MTYPE_STATIC(PATHD
, PATH_CLI
, "Client");
61 DEFINE_HOOK(pathd_srte_config_write
, (struct vty
*vty
), (vty
));
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
,
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)# ",
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)# ",
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)# ",
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)# ",
104 DEFPY(show_srte_policy
,
105 show_srte_policy_cmd
,
112 struct srte_policy
*policy
;
115 if (RB_EMPTY(srte_policy_head
, &srte_policies
)) {
116 vty_out(vty
, "No SR Policies to display.\n\n");
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
= '+';
126 ttable_rowseps(tt
, 0, BOTTOM
, true, '-');
128 RB_FOREACH (policy
, srte_policy_head
, &srte_policies
) {
130 char binding_sid
[16] = "-";
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
);
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
144 /* Dump the generated table. */
145 table
= ttable_dump(tt
, "\n");
146 vty_out(vty
, "%s\n", table
);
147 XFREE(MTYPE_TMP
, table
);
156 * Show detailed SR-TE info
158 DEFPY(show_srte_policy_detail
,
159 show_srte_policy_detail_cmd
,
160 "show sr-te policy detail",
164 "Show a detailed summary\n")
166 struct srte_policy
*policy
;
168 if (RB_EMPTY(srte_policy_head
, &srte_policies
)) {
169 vty_out(vty
, "No SR Policies to display.\n\n");
174 RB_FOREACH (policy
, srte_policy_head
, &srte_policies
) {
175 struct srte_candidate
*candidate
;
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)";
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
);
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"
193 RB_FOREACH (candidate
, srte_candidate_head
,
194 &policy
->candidate_paths
) {
195 struct srte_segment_list
*segment_list
;
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
202 segment_list_info
= created_by_pce_info
;
205 candidate
->lsp
->segment_list
->name
;
208 " %s Preference: %d Name: %s Type: %s Segment-List: %s Protocol-Origin: %s\n",
209 CHECK_FLAG(candidate
->flags
, F_CANDIDATE_BEST
)
212 candidate
->preference
, candidate
->name
,
213 candidate
->type
== SRTE_CANDIDATE_TYPE_EXPLICIT
218 candidate
->lsp
->protocol_origin
));
228 segment_routing_list
,
231 "Configure segment routing\n")
233 VTY_PUSH_CONTEXT_NULL(SEGMENT_ROUTING_NODE
);
241 "Configure SR traffic engineering\n")
243 VTY_PUSH_CONTEXT_NULL(SR_TRAFFIC_ENG_NODE
);
248 * XPath: /frr-pathd:pathd/srte/segment-list
252 srte_segment_list_cmd
,
253 "segment-list WORD$name",
255 "Segment List Name\n")
257 char xpath
[XPATH_MAXLEN
];
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
);
264 snprintf(xpath
, sizeof(xpath
),
265 "/frr-pathd:pathd/srte/segment-list[name='%s']/protocol-origin",
267 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "local");
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");
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
);
283 DEFPY(srte_no_segment_list
,
284 srte_no_segment_list_cmd
,
285 "no segment-list WORD$name",
288 "Segment List Name\n")
290 char xpath
[XPATH_MAXLEN
];
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
);
296 return nb_cli_apply_changes(vty
, NULL
);
299 void cli_show_srte_segment_list(struct vty
*vty
, const struct lyd_node
*dnode
,
302 vty_out(vty
, " segment-list %s\n",
303 yang_dnode_get_string(dnode
, "./name"));
306 void cli_show_srte_segment_list_end(struct vty
*vty
,
307 const struct lyd_node
*dnode
)
309 vty_out(vty
, " exit\n");
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
)
319 const char *node_src_id
;
320 uint32_t ted_sid
= MPLS_LABEL_NONE
;
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
;
335 return CMD_ERR_NO_MATCH
;
337 ted_sid
= path_ted_query_type_f(&ip_src
, &ip_dst
);
338 if (ted_sid
== MPLS_LABEL_NONE
) {
340 "%s: [rcv ted] CLI NOT FOUND Continue query_type_f SRC (%pIA) DST (%pIA)!",
341 __func__
, &ip_src
, &ip_dst
);
344 snprintf(xpath
, XPATH_MAXLEN
, "./segment[index='%s']/nai/type",
346 if (adj_src_ipv4_str
!= NULL
) {
347 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
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
,
353 node_src_id
= adj_src_ipv6_str
;
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
361 assert(!"We must have a adj_src_ipv4_str or a adj_src_ipv6_str");
365 snprintf(xpath
, XPATH_MAXLEN
, "./segment[index='%s']/nai/local-address",
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
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
)
382 char buf_prefix
[INET6_ADDRSTRLEN
];
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 */
389 snprintf(xpath
, XPATH_MAXLEN
, "./segment[index='%s']/nai/type",
391 if (has_iface_id
!= NULL
) {
392 if (prefix_ipv4_str
!= NULL
) {
393 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
395 } else if (prefix_ipv6_str
!= NULL
) {
396 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
399 return CMD_ERR_NO_MATCH
;
402 if (prefix_ipv4_str
!= NULL
) {
403 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
405 } else if (prefix_ipv6_str
!= NULL
) {
406 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
409 return CMD_ERR_NO_MATCH
;
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
;
418 inet_ntop(AF_INET
, &prefix_cli
.u
.prefix4
, 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
;
427 inet_ntop(AF_INET6
, &prefix_cli
.u
.prefix6
, buf_prefix
,
429 pre_ipaddr
.ipa_type
= IPADDR_V6
;
430 pre_ipaddr
.ip
._v6_addr
= prefix_cli
.u
.prefix6
;
432 snprintf(xpath
, XPATH_MAXLEN
, "./segment[index='%s']/nai/local-address",
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
,
439 ? strchr(prefix_ipv4_str
, '/') + 1
440 : strchr(prefix_ipv6_str
, '/') + 1);
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
);
447 if (has_iface_id
!= NULL
) {
448 snprintf(xpath
, XPATH_MAXLEN
,
449 "./segment[index='%s']/nai/local-interface",
451 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
,
455 if (has_algo
!= NULL
) {
456 ted_sid
= path_ted_query_type_c(&prefix_cli
, algo
);
457 if (ted_sid
== MPLS_LABEL_NONE
) {
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
,
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
) {
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
,
476 * XPath: /frr-pathd:pathd/srte/segment-list/segment
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] "
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>"
495 "NAI prefix identifier\n"
496 "NAI IPv4 prefix identifier\n"
497 "NAI IPv6 prefix identifier\n"
499 "Algorithm Value SPF or Strict-SPF\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 */
509 char xpath
[XPATH_MAXLEN
];
510 int status
= CMD_SUCCESS
;
513 snprintf(xpath
, sizeof(xpath
), "./segment[index='%s']", index_str
);
514 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
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
);
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
)
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
)
540 return nb_cli_apply_changes(vty
, NULL
);
543 DEFPY(srte_segment_list_no_segment
,
544 srte_segment_list_no_segment_cmd
,
545 "no index (0-4294967295)$index",
550 char xpath
[XPATH_MAXLEN
];
552 snprintf(xpath
, sizeof(xpath
), "./segment[index='%s']", index_str
);
553 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
555 return nb_cli_apply_changes(vty
, NULL
);
558 void cli_show_srte_segment_list_segment(struct vty
*vty
,
559 const struct lyd_node
*dnode
,
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"));
567 if (yang_dnode_exists(dnode
, "./nai")) {
569 struct ipaddr addr_rmt
;
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
);
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
);
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
);
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
);
601 if (yang_dnode_exists(dnode
, "./nai/local-prefix-len")) {
603 yang_dnode_get_string(
604 dnode
, "./nai/local-prefix-len"));
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"));
611 if (yang_dnode_exists(dnode
, "./nai/algorithm")) {
612 vty_out(vty
, " algorithm %s",
613 yang_dnode_get_string(dnode
,
621 * XPath: /frr-pathd:pathd/policy
626 "policy color (0-4294967295)$num endpoint <A.B.C.D|X:X::X:X>$endpoint",
627 "Segment Routing Policy\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")
634 char xpath
[XPATH_POLICY_BASELEN
];
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
);
642 ret
= nb_cli_apply_changes(vty
, NULL
);
643 if (ret
== CMD_SUCCESS
)
644 VTY_PUSH_XPATH(SR_POLICY_NODE
, xpath
);
649 DEFPY(srte_no_policy
,
651 "no policy color (0-4294967295)$num endpoint <A.B.C.D|X:X::X:X>$endpoint",
653 "Segment Routing Policy\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")
660 char xpath
[XPATH_POLICY_BASELEN
];
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
);
667 return nb_cli_apply_changes(vty
, NULL
);
670 void cli_show_srte_policy(struct vty
*vty
, const struct lyd_node
*dnode
,
673 vty_out(vty
, " policy color %s endpoint %s\n",
674 yang_dnode_get_string(dnode
, "./color"),
675 yang_dnode_get_string(dnode
, "./endpoint"));
678 void cli_show_srte_policy_end(struct vty
*vty
, const struct lyd_node
*dnode
)
680 vty_out(vty
, " exit\n");
684 * XPath: /frr-pathd:pathd/srte/policy/name
686 DEFPY(srte_policy_name
,
687 srte_policy_name_cmd
,
689 "Segment Routing Policy name\n"
690 "SR Policy name value\n")
692 nb_cli_enqueue_change(vty
, "./name", NB_OP_CREATE
, name
);
694 return nb_cli_apply_changes(vty
, NULL
);
697 DEFPY(srte_policy_no_name
,
698 srte_policy_no_name_cmd
,
701 "Segment Routing Policy name\n"
702 "SR Policy name value\n")
704 nb_cli_enqueue_change(vty
, "./name", NB_OP_DESTROY
, NULL
);
706 return nb_cli_apply_changes(vty
, NULL
);
710 void cli_show_srte_policy_name(struct vty
*vty
, const struct lyd_node
*dnode
,
713 vty_out(vty
, " name %s\n", yang_dnode_get_string(dnode
, NULL
));
717 * XPath: /frr-pathd:pathd/srte/policy/binding-sid
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")
725 nb_cli_enqueue_change(vty
, "./binding-sid", NB_OP_CREATE
, label_str
);
727 return nb_cli_apply_changes(vty
, NULL
);
730 DEFPY(srte_policy_no_binding_sid
,
731 srte_policy_no_binding_sid_cmd
,
732 "no binding-sid [(16-1048575)]",
734 "Segment Routing Policy Binding-SID\n"
735 "SR Policy Binding-SID label\n")
737 nb_cli_enqueue_change(vty
, "./binding-sid", NB_OP_DESTROY
, NULL
);
739 return nb_cli_apply_changes(vty
, NULL
);
742 void cli_show_srte_policy_binding_sid(struct vty
*vty
,
743 const struct lyd_node
*dnode
,
746 vty_out(vty
, " binding-sid %s\n", yang_dnode_get_string(dnode
, NULL
));
750 * XPath: /frr-pathd:pathd/srte/policy/candidate-path
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"
763 "Name of the Segment List\n")
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
,
772 return nb_cli_apply_changes(vty
, "./candidate-path[preference='%s']",
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"
787 char xpath
[XPATH_MAXLEN
+ XPATH_CANDIDATE_BASELEN
];
790 snprintf(xpath
, sizeof(xpath
), "%s/candidate-path[preference='%s']",
791 VTY_CURR_XPATH
, preference_str
);
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']",
801 if (ret
== CMD_SUCCESS
)
802 VTY_PUSH_XPATH(SR_CANDIDATE_DYN_NODE
, xpath
);
807 DEFPY(srte_candidate_bandwidth
,
808 srte_candidate_bandwidth_cmd
,
809 "bandwidth BANDWIDTH$value [required$required]",
810 "Define a bandwidth constraint\n"
812 "Required constraint\n")
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
);
821 DEFPY(srte_candidate_no_bandwidth
,
822 srte_candidate_no_bandwidth_cmd
,
823 "no bandwidth [BANDWIDTH$value] [required$required]",
825 "Remove a bandwidth constraint\n"
827 "Required constraint\n")
829 nb_cli_enqueue_change(vty
, "./constraints/bandwidth", NB_OP_DESTROY
,
831 return nb_cli_apply_changes(vty
, NULL
);
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")
843 char xpath
[XPATH_CANDIDATE_MAXLEN
];
844 char decimal_value
[11];
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
;
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
);
855 return nb_cli_apply_changes(vty
, NULL
);
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]",
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")
867 char xpath
[XPATH_CANDIDATE_MAXLEN
];
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
);
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"
882 "Aggregate bandwidth consumption\n"
883 "Load of the most loaded link\n"
884 "Cumulative IGP cost\n"
885 "Cumulative TE cost\n"
888 "P2MP hop count metric\n"
889 "Segment-ID (SID) Depth.\n"
890 "Path Delay metric\n"
891 "Path Delay Variation 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"
901 "Required constraint\n")
903 char xpath
[XPATH_CANDIDATE_MAXLEN
];
904 snprintf(xpath
, sizeof(xpath
), "./constraints/metrics[type='%s']/value",
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
);
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]",
922 "Remove a metric constraint\n"
923 "If the metric is bounded\n"
927 "Aggregate bandwidth consumption\n"
928 "Load of the most loaded link\n"
929 "Cumulative IGP cost\n"
930 "Cumulative TE cost\n"
933 "P2MP hop count metric\n"
934 "Segment-ID (SID) Depth.\n"
935 "Path Delay metric\n"
936 "Path Delay Variation 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"
946 "Required constraint\n")
948 char xpath
[XPATH_CANDIDATE_MAXLEN
];
949 snprintf(xpath
, sizeof(xpath
), "./constraints/metrics[type='%s']",
951 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
952 return nb_cli_apply_changes(vty
, NULL
);
955 DEFPY(srte_policy_no_candidate
,
956 srte_policy_no_candidate_cmd
,
958 preference (0-4294967295)$preference\
961 explicit segment-list WORD\
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"
972 "Name of the Segment List\n"
975 nb_cli_enqueue_change(vty
, ".", NB_OP_DESTROY
, NULL
);
977 return nb_cli_apply_changes(vty
, "./candidate-path[preference='%s']",
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")
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
);
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]",
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")
1040 nb_cli_enqueue_change(vty
, "./constraints/objective-function",
1041 NB_OP_DESTROY
, NULL
);
1042 return nb_cli_apply_changes(vty
, NULL
);
1045 static const char *objfun_type_name(enum objfun_type type
)
1087 DEFPY_NOSH(show_debugging_pathd
, show_debugging_pathd_cmd
,
1088 "show debugging [pathd]",
1090 "State of each debugging option\n"
1091 "pathd module debugging\n")
1094 cmd_show_lib_debugs(vty
);
1095 /* nothing to do here */
1099 static const char *metric_type_name(enum srte_candidate_metric_type type
)
1102 case SRTE_CANDIDATE_METRIC_TYPE_IGP
:
1104 case SRTE_CANDIDATE_METRIC_TYPE_TE
:
1106 case SRTE_CANDIDATE_METRIC_TYPE_HC
:
1108 case SRTE_CANDIDATE_METRIC_TYPE_ABC
:
1110 case SRTE_CANDIDATE_METRIC_TYPE_LMLL
:
1112 case SRTE_CANDIDATE_METRIC_TYPE_CIGP
:
1114 case SRTE_CANDIDATE_METRIC_TYPE_CTE
:
1116 case SRTE_CANDIDATE_METRIC_TYPE_PIGP
:
1118 case SRTE_CANDIDATE_METRIC_TYPE_PTE
:
1120 case SRTE_CANDIDATE_METRIC_TYPE_PHC
:
1122 case SRTE_CANDIDATE_METRIC_TYPE_MSD
:
1124 case SRTE_CANDIDATE_METRIC_TYPE_PD
:
1126 case SRTE_CANDIDATE_METRIC_TYPE_PDV
:
1128 case SRTE_CANDIDATE_METRIC_TYPE_PL
:
1130 case SRTE_CANDIDATE_METRIC_TYPE_PPD
:
1132 case SRTE_CANDIDATE_METRIC_TYPE_PPDV
:
1134 case SRTE_CANDIDATE_METRIC_TYPE_PPL
:
1136 case SRTE_CANDIDATE_METRIC_TYPE_NAP
:
1138 case SRTE_CANDIDATE_METRIC_TYPE_NLP
:
1140 case SRTE_CANDIDATE_METRIC_TYPE_DC
:
1142 case SRTE_CANDIDATE_METRIC_TYPE_BNC
:
1149 static void config_write_float(struct vty
*vty
, float value
)
1151 if (fabs(truncf(value
) - value
) < FLT_EPSILON
) {
1152 vty_out(vty
, " %d", (int)value
);
1155 vty_out(vty
, " %f", value
);
1159 static void config_write_metric(struct vty
*vty
,
1160 enum srte_candidate_metric_type type
,
1161 float value
, bool required
, bool is_bound
)
1163 const char *name
= metric_type_name(type
);
1166 vty_out(vty
, " metric %s%s", is_bound
? "bound " : "",
1167 metric_type_name(type
));
1168 config_write_float(vty
, value
);
1169 vty_out(vty
, required
? " required" : "");
1173 static int config_write_metric_cb(const struct lyd_node
*dnode
, void *arg
)
1175 struct vty
*vty
= arg
;
1176 enum srte_candidate_metric_type type
;
1177 bool required
, is_bound
= false;
1180 type
= yang_dnode_get_enum(dnode
, "./type");
1181 value
= (float)yang_dnode_get_dec64(dnode
, "./value");
1182 required
= yang_dnode_get_bool(dnode
, "./required");
1183 if (yang_dnode_exists(dnode
, "./is-bound"))
1184 is_bound
= yang_dnode_get_bool(dnode
, "./is-bound");
1186 config_write_metric(vty
, type
, value
, required
, is_bound
);
1187 return YANG_ITER_CONTINUE
;
1190 void cli_show_srte_policy_candidate_path(struct vty
*vty
,
1191 const struct lyd_node
*dnode
,
1197 enum objfun_type objfun_type
;
1198 const char *type
= yang_dnode_get_string(dnode
, "./type");
1200 vty_out(vty
, " candidate-path preference %s name %s %s",
1201 yang_dnode_get_string(dnode
, "./preference"),
1202 yang_dnode_get_string(dnode
, "./name"), type
);
1203 if (strmatch(type
, "explicit"))
1204 vty_out(vty
, " segment-list %s",
1205 yang_dnode_get_string(dnode
, "./segment-list-name"));
1208 if (strmatch(type
, "dynamic")) {
1209 if (yang_dnode_exists(dnode
, "./constraints/bandwidth")) {
1210 bandwidth
= (float)yang_dnode_get_dec64(
1211 dnode
, "./constraints/bandwidth/value");
1212 required
= yang_dnode_get_bool(
1213 dnode
, "./constraints/bandwidth/required");
1214 vty_out(vty
, " bandwidth");
1215 config_write_float(vty
, bandwidth
);
1217 vty_out(vty
, " required");
1220 if (yang_dnode_exists(dnode
,
1221 "./constraints/affinity/exclude-any")) {
1222 affinity
= yang_dnode_get_uint32(
1223 dnode
, "./constraints/affinity/exclude-any");
1224 vty_out(vty
, " affinity exclude-any 0x%08x\n",
1227 if (yang_dnode_exists(dnode
,
1228 "./constraints/affinity/include-any")) {
1229 affinity
= yang_dnode_get_uint32(
1230 dnode
, "./constraints/affinity/include-any");
1231 vty_out(vty
, " affinity include-any 0x%08x\n",
1234 if (yang_dnode_exists(dnode
,
1235 "./constraints/affinity/include-all")) {
1236 affinity
= yang_dnode_get_uint32(
1237 dnode
, "./constraints/affinity/include-all");
1238 vty_out(vty
, " affinity include-all 0x%08x\n",
1241 yang_dnode_iterate(config_write_metric_cb
, vty
, dnode
,
1242 "./constraints/metrics");
1243 if (yang_dnode_exists(dnode
,
1244 "./constraints/objective-function")) {
1245 objfun_type
= yang_dnode_get_enum(dnode
,
1246 "./constraints/objective-function/type");
1247 required
= yang_dnode_get_bool(dnode
,
1248 "./constraints/objective-function/required");
1249 vty_out(vty
, " objective-function %s%s\n",
1250 objfun_type_name(objfun_type
),
1251 required
? " required" : "");
1256 void cli_show_srte_policy_candidate_path_end(struct vty
*vty
,
1257 const struct lyd_node
*dnode
)
1259 const char *type
= yang_dnode_get_string(dnode
, "./type");
1261 if (strmatch(type
, "dynamic"))
1262 vty_out(vty
, " exit\n");
1265 static int config_write_dnode(const struct lyd_node
*dnode
, void *arg
)
1267 struct vty
*vty
= arg
;
1269 nb_cli_show_dnode_cmds(vty
, dnode
, false);
1271 return YANG_ITER_CONTINUE
;
1274 int config_write_segment_routing(struct vty
*vty
)
1276 vty_out(vty
, "segment-routing\n");
1277 vty_out(vty
, " traffic-eng\n");
1279 path_ted_config_write(vty
);
1281 yang_dnode_iterate(config_write_dnode
, vty
, running_config
->dnode
,
1282 "/frr-pathd:pathd/srte/segment-list");
1283 yang_dnode_iterate(config_write_dnode
, vty
, running_config
->dnode
,
1284 "/frr-pathd:pathd/srte/policy");
1286 hook_call(pathd_srte_config_write
, vty
);
1288 vty_out(vty
, " exit\n");
1289 vty_out(vty
, "exit\n");
1294 void path_cli_init(void)
1296 install_node(&segment_routing_node
);
1297 install_node(&sr_traffic_eng_node
);
1298 install_node(&srte_segment_list_node
);
1299 install_node(&srte_policy_node
);
1300 install_node(&srte_candidate_dyn_node
);
1301 install_default(SEGMENT_ROUTING_NODE
);
1302 install_default(SR_TRAFFIC_ENG_NODE
);
1303 install_default(SR_SEGMENT_LIST_NODE
);
1304 install_default(SR_POLICY_NODE
);
1305 install_default(SR_CANDIDATE_DYN_NODE
);
1307 install_element(ENABLE_NODE
, &show_debugging_pathd_cmd
);
1308 install_element(ENABLE_NODE
, &show_srte_policy_cmd
);
1309 install_element(ENABLE_NODE
, &show_srte_policy_detail_cmd
);
1311 install_element(CONFIG_NODE
, &segment_routing_cmd
);
1312 install_element(SEGMENT_ROUTING_NODE
, &sr_traffic_eng_cmd
);
1313 install_element(SR_TRAFFIC_ENG_NODE
, &srte_segment_list_cmd
);
1314 install_element(SR_TRAFFIC_ENG_NODE
, &srte_no_segment_list_cmd
);
1315 install_element(SR_SEGMENT_LIST_NODE
,
1316 &srte_segment_list_segment_cmd
);
1317 install_element(SR_SEGMENT_LIST_NODE
,
1318 &srte_segment_list_no_segment_cmd
);
1319 install_element(SR_TRAFFIC_ENG_NODE
, &srte_policy_cmd
);
1320 install_element(SR_TRAFFIC_ENG_NODE
, &srte_no_policy_cmd
);
1321 install_element(SR_POLICY_NODE
, &srte_policy_name_cmd
);
1322 install_element(SR_POLICY_NODE
, &srte_policy_no_name_cmd
);
1323 install_element(SR_POLICY_NODE
, &srte_policy_binding_sid_cmd
);
1324 install_element(SR_POLICY_NODE
, &srte_policy_no_binding_sid_cmd
);
1325 install_element(SR_POLICY_NODE
, &srte_policy_candidate_exp_cmd
);
1326 install_element(SR_POLICY_NODE
, &srte_policy_candidate_dyn_cmd
);
1327 install_element(SR_POLICY_NODE
, &srte_policy_no_candidate_cmd
);
1328 install_element(SR_CANDIDATE_DYN_NODE
,
1329 &srte_candidate_bandwidth_cmd
);
1330 install_element(SR_CANDIDATE_DYN_NODE
,
1331 &srte_candidate_no_bandwidth_cmd
);
1332 install_element(SR_CANDIDATE_DYN_NODE
,
1333 &srte_candidate_affinity_filter_cmd
);
1334 install_element(SR_CANDIDATE_DYN_NODE
,
1335 &srte_candidate_no_affinity_filter_cmd
);
1336 install_element(SR_CANDIDATE_DYN_NODE
,
1337 &srte_candidate_metric_cmd
);
1338 install_element(SR_CANDIDATE_DYN_NODE
,
1339 &srte_candidate_no_metric_cmd
);
1340 install_element(SR_CANDIDATE_DYN_NODE
,
1341 &srte_candidate_objfun_cmd
);
1342 install_element(SR_CANDIDATE_DYN_NODE
,
1343 &srte_candidate_no_objfun_cmd
);