2 * Zebra SRv6 VTY functions
3 * Copyright (C) 2020 Hiroki Shirokura, LINE Corporation
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #include "zebra/zserv.h"
34 #include "zebra/zebra_router.h"
35 #include "zebra/zebra_vrf.h"
36 #include "zebra/zebra_srv6.h"
37 #include "zebra/zebra_srv6_vty.h"
38 #include "zebra/zebra_rnh.h"
39 #include "zebra/redistribute.h"
40 #include "zebra/zebra_routemap.h"
41 #include "zebra/zebra_dplane.h"
43 #include "zebra/zebra_srv6_vty_clippy.c"
45 static int zebra_sr_config(struct vty
*vty
);
47 static struct cmd_node sr_node
= {
49 .node
= SEGMENT_ROUTING_NODE
,
50 .parent_node
= CONFIG_NODE
,
51 .prompt
= "%s(config-sr)# ",
52 .config_write
= zebra_sr_config
,
55 static struct cmd_node srv6_node
= {
58 .parent_node
= SEGMENT_ROUTING_NODE
,
59 .prompt
= "%s(config-srv6)# ",
63 static struct cmd_node srv6_locs_node
= {
64 .name
= "srv6-locators",
65 .node
= SRV6_LOCS_NODE
,
66 .parent_node
= SRV6_NODE
,
67 .prompt
= "%s(config-srv6-locators)# ",
70 static struct cmd_node srv6_loc_node
= {
71 .name
= "srv6-locator",
72 .node
= SRV6_LOC_NODE
,
73 .parent_node
= SRV6_LOCS_NODE
,
74 .prompt
= "%s(config-srv6-locator)# "
77 DEFUN (show_srv6_locator
,
78 show_srv6_locator_cmd
,
79 "show segment-routing srv6 locator [json]",
82 "Segment Routing SRv6\n"
83 "Locator Information\n"
86 const bool uj
= use_json(argc
, argv
);
87 struct zebra_srv6
*srv6
= zebra_srv6_get_default();
88 struct srv6_locator
*locator
;
89 struct listnode
*node
;
92 json_object
*json
= NULL
;
93 json_object
*json_locators
= NULL
;
94 json_object
*json_locator
= NULL
;
97 json
= json_object_new_object();
98 json_locators
= json_object_new_array();
99 json_object_object_add(json
, "locators", json_locators
);
101 for (ALL_LIST_ELEMENTS_RO(srv6
->locators
, node
, locator
)) {
102 json_locator
= srv6_locator_json(locator
);
105 json_object_array_add(json_locators
, json_locator
);
111 vty_out(vty
, "Locator:\n");
112 vty_out(vty
, "Name ID Prefix Status\n");
113 vty_out(vty
, "-------------------- ------- ------------------------ -------\n");
116 for (ALL_LIST_ELEMENTS_RO(srv6
->locators
, node
, locator
)) {
117 prefix2str(&locator
->prefix
, str
, sizeof(str
));
118 vty_out(vty
, "%-20s %7d %-24s %s\n",
119 locator
->name
, id
, str
,
120 locator
->status_up
? "Up" : "Down");
129 DEFUN (show_srv6_locator_detail
,
130 show_srv6_locator_detail_cmd
,
131 "show segment-routing srv6 locator NAME detail [json]",
134 "Segment Routing SRv6\n"
135 "Locator Information\n"
137 "Detailed information\n"
140 const bool uj
= use_json(argc
, argv
);
141 struct zebra_srv6
*srv6
= zebra_srv6_get_default();
142 struct srv6_locator
*locator
;
143 struct listnode
*node
;
145 const char *locator_name
= argv
[4]->arg
;
146 json_object
*json_locator
= NULL
;
149 locator
= zebra_srv6_locator_lookup(locator_name
);
153 json_locator
= srv6_locator_detailed_json(locator
);
154 vty_json(vty
, json_locator
);
158 for (ALL_LIST_ELEMENTS_RO(srv6
->locators
, node
, locator
)) {
159 struct listnode
*node
;
160 struct srv6_locator_chunk
*chunk
;
162 if (strcmp(locator
->name
, locator_name
) != 0)
165 prefix2str(&locator
->prefix
, str
, sizeof(str
));
166 vty_out(vty
, "Name: %s\n", locator
->name
);
167 vty_out(vty
, "Prefix: %s\n", str
);
168 vty_out(vty
, "Block-Bit-Len: %u\n", locator
->block_bits_length
);
169 vty_out(vty
, "Node-Bit-Len: %u\n", locator
->node_bits_length
);
170 vty_out(vty
, "Function-Bit-Len: %u\n",
171 locator
->function_bits_length
);
172 vty_out(vty
, "Argument-Bit-Len: %u\n",
173 locator
->argument_bits_length
);
175 if (CHECK_FLAG(locator
->flags
, SRV6_LOCATOR_USID
))
176 vty_out(vty
, "Behavior: uSID\n");
178 vty_out(vty
, "Chunks:\n");
179 for (ALL_LIST_ELEMENTS_RO((struct list
*)locator
->chunks
, node
,
181 prefix2str(&chunk
->prefix
, str
, sizeof(str
));
182 vty_out(vty
, "- prefix: %s, owner: %s\n", str
,
183 zebra_route_string(chunk
->proto
));
191 DEFUN_NOSH (segment_routing
,
196 vty
->node
= SEGMENT_ROUTING_NODE
;
203 "Segment Routing SRv6\n")
205 vty
->node
= SRV6_NODE
;
213 "Segment Routing SRv6\n")
215 struct zebra_srv6
*srv6
= zebra_srv6_get_default();
216 struct srv6_locator
*locator
;
217 struct listnode
*node
, *nnode
;
219 for (ALL_LIST_ELEMENTS(srv6
->locators
, node
, nnode
, locator
))
220 zebra_srv6_locator_delete(locator
);
224 DEFUN_NOSH (srv6_locators
,
227 "Segment Routing SRv6 locators\n")
229 vty
->node
= SRV6_LOCS_NODE
;
233 DEFUN_NOSH (srv6_locator
,
236 "Segment Routing SRv6 locator\n"
237 "Specify locator-name\n")
239 struct srv6_locator
*locator
= NULL
;
241 locator
= zebra_srv6_locator_lookup(argv
[1]->arg
);
243 VTY_PUSH_CONTEXT(SRV6_LOC_NODE
, locator
);
244 locator
->status_up
= true;
248 locator
= srv6_locator_alloc(argv
[1]->arg
);
250 vty_out(vty
, "%% Alloc failed\n");
251 return CMD_WARNING_CONFIG_FAILED
;
253 locator
->status_up
= true;
255 VTY_PUSH_CONTEXT(SRV6_LOC_NODE
, locator
);
256 vty
->node
= SRV6_LOC_NODE
;
260 DEFUN (no_srv6_locator
,
264 "Segment Routing SRv6 locator\n"
265 "Specify locator-name\n")
267 struct srv6_locator
*locator
= zebra_srv6_locator_lookup(argv
[2]->arg
);
269 vty_out(vty
, "%% Can't find SRv6 locator\n");
270 return CMD_WARNING_CONFIG_FAILED
;
273 zebra_srv6_locator_delete(locator
);
277 DEFPY (locator_prefix
,
279 "prefix X:X::X:X/M$prefix [func-bits (0-64)$func_bit_len] \
280 [block-len (16-64)$block_bit_len] [node-len (16-64)$node_bit_len]",
281 "Configure SRv6 locator prefix\n"
282 "Specify SRv6 locator prefix\n"
283 "Configure SRv6 locator function length in bits\n"
284 "Specify SRv6 locator function length in bits\n"
285 "Configure SRv6 locator block length in bits\n"
286 "Specify SRv6 locator block length in bits\n"
287 "Configure SRv6 locator node length in bits\n"
288 "Specify SRv6 locator node length in bits\n")
290 VTY_DECLVAR_CONTEXT(srv6_locator
, locator
);
291 struct srv6_locator_chunk
*chunk
= NULL
;
292 struct listnode
*node
= NULL
;
294 locator
->prefix
= *prefix
;
295 func_bit_len
= func_bit_len
?: ZEBRA_SRV6_FUNCTION_LENGTH
;
297 /* Resolve optional arguments */
298 if (block_bit_len
== 0 && node_bit_len
== 0) {
300 prefix
->prefixlen
- ZEBRA_SRV6_LOCATOR_NODE_LENGTH
;
301 node_bit_len
= ZEBRA_SRV6_LOCATOR_NODE_LENGTH
;
302 } else if (block_bit_len
== 0) {
303 block_bit_len
= prefix
->prefixlen
- node_bit_len
;
304 } else if (node_bit_len
== 0) {
305 node_bit_len
= prefix
->prefixlen
- block_bit_len
;
307 if (block_bit_len
+ node_bit_len
!= prefix
->prefixlen
) {
309 "%% block-len + node-len must be equal to the selected prefix length %d\n",
311 return CMD_WARNING_CONFIG_FAILED
;
315 if (prefix
->prefixlen
+ func_bit_len
+ 0 > 128) {
317 "%% prefix-len + function-len + arg-len (%ld) cannot be greater than 128\n",
318 prefix
->prefixlen
+ func_bit_len
+ 0);
319 return CMD_WARNING_CONFIG_FAILED
;
323 * Currently, the SID transposition algorithm implemented in bgpd
324 * handles incorrectly the SRv6 locators with function length greater
325 * than 20 bits. To prevent issues, we currently limit the function
327 * This limit will be removed when the bgpd SID transposition is fixed.
329 if (func_bit_len
> 20) {
331 "%% currently func_bit_len > 20 is not supported\n");
332 return CMD_WARNING_CONFIG_FAILED
;
335 locator
->block_bits_length
= block_bit_len
;
336 locator
->node_bits_length
= node_bit_len
;
337 locator
->function_bits_length
= func_bit_len
;
338 locator
->argument_bits_length
= 0;
340 if (list_isempty(locator
->chunks
)) {
341 chunk
= srv6_locator_chunk_alloc();
342 chunk
->prefix
= *prefix
;
344 listnode_add(locator
->chunks
, chunk
);
346 for (ALL_LIST_ELEMENTS_RO(locator
->chunks
, node
, chunk
)) {
347 uint8_t zero
[16] = {0};
349 if (memcmp(&chunk
->prefix
.prefix
, zero
, 16) == 0) {
350 struct zserv
*client
;
351 struct listnode
*client_node
;
353 chunk
->prefix
= *prefix
;
354 for (ALL_LIST_ELEMENTS_RO(zrouter
.client_list
,
357 struct srv6_locator
*tmp
;
359 if (client
->proto
!= chunk
->proto
)
362 srv6_manager_get_locator_chunk_call(
371 zebra_srv6_locator_add(locator
);
375 DEFPY (locator_behavior
,
376 locator_behavior_cmd
,
377 "[no] behavior usid",
379 "Configure SRv6 behavior\n"
380 "Specify SRv6 behavior uSID\n")
382 VTY_DECLVAR_CONTEXT(srv6_locator
, locator
);
384 if (no
&& !CHECK_FLAG(locator
->flags
, SRV6_LOCATOR_USID
))
385 /* SRv6 locator uSID flag already unset, nothing to do */
388 if (!no
&& CHECK_FLAG(locator
->flags
, SRV6_LOCATOR_USID
))
389 /* SRv6 locator uSID flag already set, nothing to do */
392 /* Remove old locator from zclients */
393 zebra_notify_srv6_locator_delete(locator
);
395 /* Set/Unset the SRV6_LOCATOR_USID */
397 UNSET_FLAG(locator
->flags
, SRV6_LOCATOR_USID
);
399 SET_FLAG(locator
->flags
, SRV6_LOCATOR_USID
);
401 /* Notify the new locator to zclients */
402 zebra_notify_srv6_locator_add(locator
);
407 static int zebra_sr_config(struct vty
*vty
)
409 struct zebra_srv6
*srv6
= zebra_srv6_get_default();
410 struct listnode
*node
;
411 struct srv6_locator
*locator
;
415 if (zebra_srv6_is_enable()) {
416 vty_out(vty
, "segment-routing\n");
417 vty_out(vty
, " srv6\n");
418 vty_out(vty
, " locators\n");
419 for (ALL_LIST_ELEMENTS_RO(srv6
->locators
, node
, locator
)) {
420 inet_ntop(AF_INET6
, &locator
->prefix
.prefix
,
422 vty_out(vty
, " locator %s\n", locator
->name
);
423 vty_out(vty
, " prefix %s/%u", str
,
424 locator
->prefix
.prefixlen
);
425 if (locator
->block_bits_length
)
426 vty_out(vty
, " block-len %u",
427 locator
->block_bits_length
);
428 if (locator
->node_bits_length
)
429 vty_out(vty
, " node-len %u",
430 locator
->node_bits_length
);
431 if (locator
->function_bits_length
)
432 vty_out(vty
, " func-bits %u",
433 locator
->function_bits_length
);
434 if (locator
->argument_bits_length
)
435 vty_out(vty
, " arg-len %u",
436 locator
->argument_bits_length
);
437 if (CHECK_FLAG(locator
->flags
, SRV6_LOCATOR_USID
))
438 vty_out(vty
, " behavior usid");
440 vty_out(vty
, " exit\n");
441 vty_out(vty
, " !\n");
443 vty_out(vty
, " exit\n");
444 vty_out(vty
, " !\n");
445 vty_out(vty
, " exit\n");
446 vty_out(vty
, " !\n");
447 vty_out(vty
, "exit\n");
453 void zebra_srv6_vty_init(void)
455 /* Install nodes and its default commands */
456 install_node(&sr_node
);
457 install_node(&srv6_node
);
458 install_node(&srv6_locs_node
);
459 install_node(&srv6_loc_node
);
460 install_default(SEGMENT_ROUTING_NODE
);
461 install_default(SRV6_NODE
);
462 install_default(SRV6_LOCS_NODE
);
463 install_default(SRV6_LOC_NODE
);
465 /* Command for change node */
466 install_element(CONFIG_NODE
, &segment_routing_cmd
);
467 install_element(SEGMENT_ROUTING_NODE
, &srv6_cmd
);
468 install_element(SEGMENT_ROUTING_NODE
, &no_srv6_cmd
);
469 install_element(SRV6_NODE
, &srv6_locators_cmd
);
470 install_element(SRV6_LOCS_NODE
, &srv6_locator_cmd
);
471 install_element(SRV6_LOCS_NODE
, &no_srv6_locator_cmd
);
473 /* Command for configuration */
474 install_element(SRV6_LOC_NODE
, &locator_prefix_cmd
);
475 install_element(SRV6_LOC_NODE
, &locator_behavior_cmd
);
477 /* Command for operation */
478 install_element(VIEW_NODE
, &show_srv6_locator_cmd
);
479 install_element(VIEW_NODE
, &show_srv6_locator_detail_cmd
);