]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_srv6_vty.c
build, vtysh: extract vtysh commands from .xref
[mirror_frr.git] / zebra / zebra_srv6_vty.c
CommitLineData
6c0a7c09
HS
1/*
2 * Zebra SRv6 VTY functions
3 * Copyright (C) 2020 Hiroki Shirokura, LINE Corporation
4 *
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)
8 * any later version.
9 *
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
13 * more details.
14 *
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
18 */
19
20#include <zebra.h>
21
22#include "memory.h"
23#include "if.h"
24#include "prefix.h"
25#include "command.h"
26#include "table.h"
27#include "rib.h"
28#include "nexthop.h"
29#include "vrf.h"
30#include "srv6.h"
31#include "lib/json.h"
32
33#include "zebra/zserv.h"
00978977 34#include "zebra/zebra_router.h"
6c0a7c09 35#include "zebra/zebra_vrf.h"
00978977 36#include "zebra/zebra_srv6.h"
6c0a7c09
HS
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"
42
daedb8b3 43#include "zebra/zebra_srv6_vty_clippy.c"
daedb8b3 44
6c0a7c09
HS
45static int zebra_sr_config(struct vty *vty);
46
47static struct cmd_node sr_node = {
48 .name = "sr",
49 .node = SEGMENT_ROUTING_NODE,
50 .parent_node = CONFIG_NODE,
51 .prompt = "%s(config-sr)# ",
52 .config_write = zebra_sr_config,
53};
54
55static struct cmd_node srv6_node = {
56 .name = "srv6",
57 .node = SRV6_NODE,
58 .parent_node = SEGMENT_ROUTING_NODE,
59 .prompt = "%s(config-srv6)# ",
60
61};
62
63static 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)# ",
68};
69
70static 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)# "
75};
76
00978977
HS
77DEFUN (show_srv6_locator,
78 show_srv6_locator_cmd,
79 "show segment-routing srv6 locator [json]",
80 SHOW_STR
81 "Segment Routing\n"
82 "Segment Routing SRv6\n"
83 "Locator Information\n"
84 JSON_STR)
85{
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;
90 char str[256];
91 int id;
92 json_object *json = NULL;
93 json_object *json_locators = NULL;
94 json_object *json_locator = NULL;
95
96 if (uj) {
97 json = json_object_new_object();
98 json_locators = json_object_new_array();
99 json_object_object_add(json, "locators", json_locators);
100
101 for (ALL_LIST_ELEMENTS_RO(srv6->locators, node, locator)) {
102 json_locator = srv6_locator_json(locator);
103 if (!json_locator)
104 continue;
105 json_object_array_add(json_locators, json_locator);
106
107 }
108
962af8a8 109 vty_json(vty, json);
00978977
HS
110 } else {
111 vty_out(vty, "Locator:\n");
112 vty_out(vty, "Name ID Prefix Status\n");
113 vty_out(vty, "-------------------- ------- ------------------------ -------\n");
114
115 id = 1;
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");
121 ++id;
122 }
123 vty_out(vty, "\n");
124 }
125
126 return CMD_SUCCESS;
127}
128
129DEFUN (show_srv6_locator_detail,
130 show_srv6_locator_detail_cmd,
131 "show segment-routing srv6 locator NAME detail [json]",
132 SHOW_STR
133 "Segment Routing\n"
134 "Segment Routing SRv6\n"
135 "Locator Information\n"
136 "Locator Name\n"
137 "Detailed information\n"
138 JSON_STR)
139{
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;
144 char str[256];
145 const char *locator_name = argv[4]->arg;
559f4b2f 146 json_object *json_locator = NULL;
00978977
HS
147
148 if (uj) {
559f4b2f
YS
149 locator = zebra_srv6_locator_lookup(locator_name);
150 if (!locator)
151 return CMD_WARNING;
152
153 json_locator = srv6_locator_detailed_json(locator);
154 vty_json(vty, json_locator);
155 return CMD_SUCCESS;
4df9d859 156 }
00978977 157
4df9d859
HS
158 for (ALL_LIST_ELEMENTS_RO(srv6->locators, node, locator)) {
159 struct listnode *node;
160 struct srv6_locator_chunk *chunk;
161
162 if (strcmp(locator->name, locator_name) != 0)
163 continue;
164
165 prefix2str(&locator->prefix, str, sizeof(str));
166 vty_out(vty, "Name: %s\n", locator->name);
167 vty_out(vty, "Prefix: %s\n", str);
d9d31799
CS
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);
4df9d859
HS
170 vty_out(vty, "Function-Bit-Len: %u\n",
171 locator->function_bits_length);
d9d31799
CS
172 vty_out(vty, "Argument-Bit-Len: %u\n",
173 locator->argument_bits_length);
4df9d859
HS
174
175 vty_out(vty, "Chunks:\n");
176 for (ALL_LIST_ELEMENTS_RO((struct list *)locator->chunks, node,
177 chunk)) {
178 prefix2str(&chunk->prefix, str, sizeof(str));
179 vty_out(vty, "- prefix: %s, owner: %s\n", str,
180 zebra_route_string(chunk->proto));
00978977 181 }
00978977
HS
182 }
183
4df9d859 184
00978977
HS
185 return CMD_SUCCESS;
186}
187
6c0a7c09
HS
188DEFUN_NOSH (segment_routing,
189 segment_routing_cmd,
190 "segment-routing",
191 "Segment Routing\n")
192{
193 vty->node = SEGMENT_ROUTING_NODE;
194 return CMD_SUCCESS;
195}
196
197DEFUN_NOSH (srv6,
198 srv6_cmd,
199 "srv6",
200 "Segment Routing SRv6\n")
201{
202 vty->node = SRV6_NODE;
203 return CMD_SUCCESS;
204}
205
0a735cd5
HS
206DEFUN (no_srv6,
207 no_srv6_cmd,
208 "no srv6",
209 NO_STR
210 "Segment Routing SRv6\n")
211{
212 struct zebra_srv6 *srv6 = zebra_srv6_get_default();
213 struct srv6_locator *locator;
214 struct listnode *node, *nnode;
215
216 for (ALL_LIST_ELEMENTS(srv6->locators, node, nnode, locator))
217 zebra_srv6_locator_delete(locator);
218 return CMD_SUCCESS;
219}
220
6c0a7c09
HS
221DEFUN_NOSH (srv6_locators,
222 srv6_locators_cmd,
223 "locators",
224 "Segment Routing SRv6 locators\n")
225{
226 vty->node = SRV6_LOCS_NODE;
227 return CMD_SUCCESS;
228}
229
230DEFUN_NOSH (srv6_locator,
231 srv6_locator_cmd,
232 "locator WORD",
233 "Segment Routing SRv6 locator\n"
234 "Specify locator-name\n")
235{
00978977
HS
236 struct srv6_locator *locator = NULL;
237
238 locator = zebra_srv6_locator_lookup(argv[1]->arg);
239 if (locator) {
240 VTY_PUSH_CONTEXT(SRV6_LOC_NODE, locator);
241 locator->status_up = true;
242 return CMD_SUCCESS;
243 }
244
245 locator = srv6_locator_alloc(argv[1]->arg);
246 if (!locator) {
247 vty_out(vty, "%% Alloc failed\n");
248 return CMD_WARNING_CONFIG_FAILED;
249 }
250 locator->status_up = true;
251
252 VTY_PUSH_CONTEXT(SRV6_LOC_NODE, locator);
6c0a7c09
HS
253 vty->node = SRV6_LOC_NODE;
254 return CMD_SUCCESS;
255}
256
0a735cd5
HS
257DEFUN (no_srv6_locator,
258 no_srv6_locator_cmd,
259 "no locator WORD",
260 NO_STR
261 "Segment Routing SRv6 locator\n"
262 "Specify locator-name\n")
263{
264 struct srv6_locator *locator = zebra_srv6_locator_lookup(argv[2]->arg);
265 if (!locator) {
266 vty_out(vty, "%% Can't find SRv6 locator\n");
267 return CMD_WARNING_CONFIG_FAILED;
268 }
269
270 zebra_srv6_locator_delete(locator);
271 return CMD_SUCCESS;
272}
273
daedb8b3 274DEFPY (locator_prefix,
00978977 275 locator_prefix_cmd,
5e04508c
CS
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]",
00978977
HS
278 "Configure SRv6 locator prefix\n"
279 "Specify SRv6 locator prefix\n"
280 "Configure SRv6 locator function length in bits\n"
5e04508c
CS
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")
00978977
HS
286{
287 VTY_DECLVAR_CONTEXT(srv6_locator, locator);
00978977
HS
288 struct srv6_locator_chunk *chunk = NULL;
289 struct listnode *node = NULL;
00978977 290
daedb8b3 291 locator->prefix = *prefix;
85521aaa 292 func_bit_len = func_bit_len ?: ZEBRA_SRV6_FUNCTION_LENGTH;
ac6a9479 293
5e04508c
CS
294 /* Resolve optional arguments */
295 if (block_bit_len == 0 && node_bit_len == 0) {
296 block_bit_len =
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;
303 } else {
304 if (block_bit_len + node_bit_len != prefix->prefixlen) {
305 vty_out(vty,
306 "%% block-len + node-len must be equal to the selected prefix length %d\n",
307 prefix->prefixlen);
308 return CMD_WARNING_CONFIG_FAILED;
309 }
310 }
311
34e3711f
CS
312 if (prefix->prefixlen + func_bit_len + 0 > 128) {
313 vty_out(vty,
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;
317 }
318
537b8b13
CS
319 /*
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
323 * length to 20 bits.
324 * This limit will be removed when the bgpd SID transposition is fixed.
325 */
326 if (func_bit_len > 20) {
327 vty_out(vty,
328 "%% currently func_bit_len > 20 is not supported\n");
329 return CMD_WARNING_CONFIG_FAILED;
330 }
331
5e04508c
CS
332 locator->block_bits_length = block_bit_len;
333 locator->node_bits_length = node_bit_len;
daedb8b3 334 locator->function_bits_length = func_bit_len;
ac6a9479 335 locator->argument_bits_length = 0;
00978977
HS
336
337 if (list_isempty(locator->chunks)) {
338 chunk = srv6_locator_chunk_alloc();
daedb8b3 339 chunk->prefix = *prefix;
00978977
HS
340 chunk->proto = 0;
341 listnode_add(locator->chunks, chunk);
342 } else {
343 for (ALL_LIST_ELEMENTS_RO(locator->chunks, node, chunk)) {
344 uint8_t zero[16] = {0};
4df9d859 345
00978977
HS
346 if (memcmp(&chunk->prefix.prefix, zero, 16) == 0) {
347 struct zserv *client;
348 struct listnode *client_node;
4df9d859 349
daedb8b3 350 chunk->prefix = *prefix;
4df9d859
HS
351 for (ALL_LIST_ELEMENTS_RO(zrouter.client_list,
352 client_node,
353 client)) {
354 struct srv6_locator *tmp;
355
00978977
HS
356 if (client->proto != chunk->proto)
357 continue;
f29aed74 358
00978977 359 srv6_manager_get_locator_chunk_call(
4df9d859
HS
360 &tmp, client,
361 locator->name,
362 VRF_DEFAULT);
00978977
HS
363 }
364 }
365 }
366 }
367
368 zebra_srv6_locator_add(locator);
369 return CMD_SUCCESS;
370}
371
6c0a7c09
HS
372static int zebra_sr_config(struct vty *vty)
373{
00978977
HS
374 struct zebra_srv6 *srv6 = zebra_srv6_get_default();
375 struct listnode *node;
376 struct srv6_locator *locator;
377 char str[256];
378
379 vty_out(vty, "!\n");
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,
386 str, sizeof(str));
387 vty_out(vty, " locator %s\n", locator->name);
fbd01eaa 388 vty_out(vty, " prefix %s/%u", str,
00978977 389 locator->prefix.prefixlen);
780c13eb
CS
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);
fbd01eaa
NM
396 if (locator->function_bits_length)
397 vty_out(vty, " func-bits %u",
398 locator->function_bits_length);
780c13eb
CS
399 if (locator->argument_bits_length)
400 vty_out(vty, " arg-len %u",
401 locator->argument_bits_length);
fbd01eaa 402 vty_out(vty, "\n");
07679ad9 403 vty_out(vty, " exit\n");
00978977
HS
404 vty_out(vty, " !\n");
405 }
07679ad9 406 vty_out(vty, " exit\n");
00978977 407 vty_out(vty, " !\n");
07679ad9 408 vty_out(vty, " exit\n");
00978977 409 vty_out(vty, " !\n");
07679ad9 410 vty_out(vty, "exit\n");
00978977
HS
411 vty_out(vty, "!\n");
412 }
6c0a7c09
HS
413 return 0;
414}
415
416void zebra_srv6_vty_init(void)
417{
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);
427
428 /* Command for change node */
429 install_element(CONFIG_NODE, &segment_routing_cmd);
430 install_element(SEGMENT_ROUTING_NODE, &srv6_cmd);
0a735cd5 431 install_element(SEGMENT_ROUTING_NODE, &no_srv6_cmd);
6c0a7c09
HS
432 install_element(SRV6_NODE, &srv6_locators_cmd);
433 install_element(SRV6_LOCS_NODE, &srv6_locator_cmd);
0a735cd5 434 install_element(SRV6_LOCS_NODE, &no_srv6_locator_cmd);
00978977
HS
435
436 /* Command for configuration */
437 install_element(SRV6_LOC_NODE, &locator_prefix_cmd);
438
439 /* Command for operation */
440 install_element(VIEW_NODE, &show_srv6_locator_cmd);
441 install_element(VIEW_NODE, &show_srv6_locator_detail_cmd);
6c0a7c09 442}