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_dst_ipv6_str
, adj_src_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")
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
);