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 vty_out(vty
, "Chunks:\n");
176 for (ALL_LIST_ELEMENTS_RO((struct list
*)locator
->chunks
, node
,
178 prefix2str(&chunk
->prefix
, str
, sizeof(str
));
179 vty_out(vty
, "- prefix: %s, owner: %s\n", str
,
180 zebra_route_string(chunk
->proto
));
188 DEFUN_NOSH (segment_routing
,
193 vty
->node
= SEGMENT_ROUTING_NODE
;
200 "Segment Routing SRv6\n")
202 vty
->node
= SRV6_NODE
;
210 "Segment Routing SRv6\n")
212 struct zebra_srv6
*srv6
= zebra_srv6_get_default();
213 struct srv6_locator
*locator
;
214 struct listnode
*node
, *nnode
;
216 for (ALL_LIST_ELEMENTS(srv6
->locators
, node
, nnode
, locator
))
217 zebra_srv6_locator_delete(locator
);
221 DEFUN_NOSH (srv6_locators
,
224 "Segment Routing SRv6 locators\n")
226 vty
->node
= SRV6_LOCS_NODE
;
230 DEFUN_NOSH (srv6_locator
,
233 "Segment Routing SRv6 locator\n"
234 "Specify locator-name\n")
236 struct srv6_locator
*locator
= NULL
;
238 locator
= zebra_srv6_locator_lookup(argv
[1]->arg
);
240 VTY_PUSH_CONTEXT(SRV6_LOC_NODE
, locator
);
241 locator
->status_up
= true;
245 locator
= srv6_locator_alloc(argv
[1]->arg
);
247 vty_out(vty
, "%% Alloc failed\n");
248 return CMD_WARNING_CONFIG_FAILED
;
250 locator
->status_up
= true;
252 VTY_PUSH_CONTEXT(SRV6_LOC_NODE
, locator
);
253 vty
->node
= SRV6_LOC_NODE
;
257 DEFUN (no_srv6_locator
,
261 "Segment Routing SRv6 locator\n"
262 "Specify locator-name\n")
264 struct srv6_locator
*locator
= zebra_srv6_locator_lookup(argv
[2]->arg
);
266 vty_out(vty
, "%% Can't find SRv6 locator\n");
267 return CMD_WARNING_CONFIG_FAILED
;
270 zebra_srv6_locator_delete(locator
);
274 DEFPY (locator_prefix
,
276 "prefix X:X::X:X/M$prefix [func-bits (0-64)$func_bit_len] \
277 [block-len (16-64)$block_bit_len] [node-len (16-64)$node_bit_len]",
278 "Configure SRv6 locator prefix\n"
279 "Specify SRv6 locator prefix\n"
280 "Configure SRv6 locator function length in bits\n"
281 "Specify SRv6 locator function length in bits\n"
282 "Configure SRv6 locator block length in bits\n"
283 "Specify SRv6 locator block length in bits\n"
284 "Configure SRv6 locator node length in bits\n"
285 "Specify SRv6 locator node length in bits\n")
287 VTY_DECLVAR_CONTEXT(srv6_locator
, locator
);
288 struct srv6_locator_chunk
*chunk
= NULL
;
289 struct listnode
*node
= NULL
;
291 locator
->prefix
= *prefix
;
292 func_bit_len
= func_bit_len
?: ZEBRA_SRV6_FUNCTION_LENGTH
;
294 /* Resolve optional arguments */
295 if (block_bit_len
== 0 && node_bit_len
== 0) {
297 prefix
->prefixlen
- ZEBRA_SRV6_LOCATOR_NODE_LENGTH
;
298 node_bit_len
= ZEBRA_SRV6_LOCATOR_NODE_LENGTH
;
299 } else if (block_bit_len
== 0) {
300 block_bit_len
= prefix
->prefixlen
- node_bit_len
;
301 } else if (node_bit_len
== 0) {
302 node_bit_len
= prefix
->prefixlen
- block_bit_len
;
304 if (block_bit_len
+ node_bit_len
!= prefix
->prefixlen
) {
306 "%% block-len + node-len must be equal to the selected prefix length %d\n",
308 return CMD_WARNING_CONFIG_FAILED
;
312 if (prefix
->prefixlen
+ func_bit_len
+ 0 > 128) {
314 "%% prefix-len + function-len + arg-len (%ld) cannot be greater than 128\n",
315 prefix
->prefixlen
+ func_bit_len
+ 0);
316 return CMD_WARNING_CONFIG_FAILED
;
320 * Currently, the SID transposition algorithm implemented in bgpd
321 * handles incorrectly the SRv6 locators with function length greater
322 * than 20 bits. To prevent issues, we currently limit the function
324 * This limit will be removed when the bgpd SID transposition is fixed.
326 if (func_bit_len
> 20) {
328 "%% currently func_bit_len > 20 is not supported\n");
329 return CMD_WARNING_CONFIG_FAILED
;
332 locator
->block_bits_length
= block_bit_len
;
333 locator
->node_bits_length
= node_bit_len
;
334 locator
->function_bits_length
= func_bit_len
;
335 locator
->argument_bits_length
= 0;
337 if (list_isempty(locator
->chunks
)) {
338 chunk
= srv6_locator_chunk_alloc();
339 chunk
->prefix
= *prefix
;
341 listnode_add(locator
->chunks
, chunk
);
343 for (ALL_LIST_ELEMENTS_RO(locator
->chunks
, node
, chunk
)) {
344 uint8_t zero
[16] = {0};
346 if (memcmp(&chunk
->prefix
.prefix
, zero
, 16) == 0) {
347 struct zserv
*client
;
348 struct listnode
*client_node
;
350 chunk
->prefix
= *prefix
;
351 for (ALL_LIST_ELEMENTS_RO(zrouter
.client_list
,
354 struct srv6_locator
*tmp
;
356 if (client
->proto
!= chunk
->proto
)
359 srv6_manager_get_locator_chunk_call(
368 zebra_srv6_locator_add(locator
);
372 static int zebra_sr_config(struct vty
*vty
)
374 struct zebra_srv6
*srv6
= zebra_srv6_get_default();
375 struct listnode
*node
;
376 struct srv6_locator
*locator
;
380 if (zebra_srv6_is_enable()) {
381 vty_out(vty
, "segment-routing\n");
382 vty_out(vty
, " srv6\n");
383 vty_out(vty
, " locators\n");
384 for (ALL_LIST_ELEMENTS_RO(srv6
->locators
, node
, locator
)) {
385 inet_ntop(AF_INET6
, &locator
->prefix
.prefix
,
387 vty_out(vty
, " locator %s\n", locator
->name
);
388 vty_out(vty
, " prefix %s/%u", str
,
389 locator
->prefix
.prefixlen
);
390 if (locator
->block_bits_length
)
391 vty_out(vty
, " block-len %u",
392 locator
->block_bits_length
);
393 if (locator
->node_bits_length
)
394 vty_out(vty
, " node-len %u",
395 locator
->node_bits_length
);
396 if (locator
->function_bits_length
)
397 vty_out(vty
, " func-bits %u",
398 locator
->function_bits_length
);
399 if (locator
->argument_bits_length
)
400 vty_out(vty
, " arg-len %u",
401 locator
->argument_bits_length
);
403 vty_out(vty
, " exit\n");
404 vty_out(vty
, " !\n");
406 vty_out(vty
, " exit\n");
407 vty_out(vty
, " !\n");
408 vty_out(vty
, " exit\n");
409 vty_out(vty
, " !\n");
410 vty_out(vty
, "exit\n");
416 void zebra_srv6_vty_init(void)
418 /* Install nodes and its default commands */
419 install_node(&sr_node
);
420 install_node(&srv6_node
);
421 install_node(&srv6_locs_node
);
422 install_node(&srv6_loc_node
);
423 install_default(SEGMENT_ROUTING_NODE
);
424 install_default(SRV6_NODE
);
425 install_default(SRV6_LOCS_NODE
);
426 install_default(SRV6_LOC_NODE
);
428 /* Command for change node */
429 install_element(CONFIG_NODE
, &segment_routing_cmd
);
430 install_element(SEGMENT_ROUTING_NODE
, &srv6_cmd
);
431 install_element(SEGMENT_ROUTING_NODE
, &no_srv6_cmd
);
432 install_element(SRV6_NODE
, &srv6_locators_cmd
);
433 install_element(SRV6_LOCS_NODE
, &srv6_locator_cmd
);
434 install_element(SRV6_LOCS_NODE
, &no_srv6_locator_cmd
);
436 /* Command for configuration */
437 install_element(SRV6_LOC_NODE
, &locator_prefix_cmd
);
439 /* Command for operation */
440 install_element(VIEW_NODE
, &show_srv6_locator_cmd
);
441 install_element(VIEW_NODE
, &show_srv6_locator_detail_cmd
);