]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_srv6_vty.c
Merge pull request #13631 from donaldsharp/fix_some_ping_issues
[mirror_frr.git] / zebra / zebra_srv6_vty.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
6c0a7c09
HS
2/*
3 * Zebra SRv6 VTY functions
4 * Copyright (C) 2020 Hiroki Shirokura, LINE Corporation
6c0a7c09
HS
5 */
6
7#include <zebra.h>
8
9#include "memory.h"
10#include "if.h"
11#include "prefix.h"
12#include "command.h"
13#include "table.h"
14#include "rib.h"
15#include "nexthop.h"
16#include "vrf.h"
17#include "srv6.h"
18#include "lib/json.h"
19
20#include "zebra/zserv.h"
00978977 21#include "zebra/zebra_router.h"
6c0a7c09 22#include "zebra/zebra_vrf.h"
00978977 23#include "zebra/zebra_srv6.h"
6c0a7c09
HS
24#include "zebra/zebra_srv6_vty.h"
25#include "zebra/zebra_rnh.h"
26#include "zebra/redistribute.h"
27#include "zebra/zebra_routemap.h"
28#include "zebra/zebra_dplane.h"
29
daedb8b3 30#include "zebra/zebra_srv6_vty_clippy.c"
daedb8b3 31
6c0a7c09
HS
32static int zebra_sr_config(struct vty *vty);
33
34static struct cmd_node sr_node = {
35 .name = "sr",
36 .node = SEGMENT_ROUTING_NODE,
37 .parent_node = CONFIG_NODE,
38 .prompt = "%s(config-sr)# ",
39 .config_write = zebra_sr_config,
40};
41
42static struct cmd_node srv6_node = {
43 .name = "srv6",
44 .node = SRV6_NODE,
45 .parent_node = SEGMENT_ROUTING_NODE,
46 .prompt = "%s(config-srv6)# ",
47
48};
49
50static struct cmd_node srv6_locs_node = {
51 .name = "srv6-locators",
52 .node = SRV6_LOCS_NODE,
53 .parent_node = SRV6_NODE,
54 .prompt = "%s(config-srv6-locators)# ",
55};
56
57static struct cmd_node srv6_loc_node = {
58 .name = "srv6-locator",
59 .node = SRV6_LOC_NODE,
60 .parent_node = SRV6_LOCS_NODE,
61 .prompt = "%s(config-srv6-locator)# "
62};
63
00978977
HS
64DEFUN (show_srv6_locator,
65 show_srv6_locator_cmd,
66 "show segment-routing srv6 locator [json]",
67 SHOW_STR
68 "Segment Routing\n"
69 "Segment Routing SRv6\n"
70 "Locator Information\n"
71 JSON_STR)
72{
73 const bool uj = use_json(argc, argv);
74 struct zebra_srv6 *srv6 = zebra_srv6_get_default();
75 struct srv6_locator *locator;
76 struct listnode *node;
77 char str[256];
78 int id;
79 json_object *json = NULL;
80 json_object *json_locators = NULL;
81 json_object *json_locator = NULL;
82
83 if (uj) {
84 json = json_object_new_object();
85 json_locators = json_object_new_array();
86 json_object_object_add(json, "locators", json_locators);
87
88 for (ALL_LIST_ELEMENTS_RO(srv6->locators, node, locator)) {
89 json_locator = srv6_locator_json(locator);
90 if (!json_locator)
91 continue;
92 json_object_array_add(json_locators, json_locator);
93
94 }
95
962af8a8 96 vty_json(vty, json);
00978977
HS
97 } else {
98 vty_out(vty, "Locator:\n");
99 vty_out(vty, "Name ID Prefix Status\n");
100 vty_out(vty, "-------------------- ------- ------------------------ -------\n");
101
102 id = 1;
103 for (ALL_LIST_ELEMENTS_RO(srv6->locators, node, locator)) {
104 prefix2str(&locator->prefix, str, sizeof(str));
105 vty_out(vty, "%-20s %7d %-24s %s\n",
106 locator->name, id, str,
107 locator->status_up ? "Up" : "Down");
108 ++id;
109 }
110 vty_out(vty, "\n");
111 }
112
113 return CMD_SUCCESS;
114}
115
116DEFUN (show_srv6_locator_detail,
117 show_srv6_locator_detail_cmd,
118 "show segment-routing srv6 locator NAME detail [json]",
119 SHOW_STR
120 "Segment Routing\n"
121 "Segment Routing SRv6\n"
122 "Locator Information\n"
123 "Locator Name\n"
124 "Detailed information\n"
125 JSON_STR)
126{
127 const bool uj = use_json(argc, argv);
128 struct zebra_srv6 *srv6 = zebra_srv6_get_default();
129 struct srv6_locator *locator;
130 struct listnode *node;
131 char str[256];
132 const char *locator_name = argv[4]->arg;
559f4b2f 133 json_object *json_locator = NULL;
00978977
HS
134
135 if (uj) {
559f4b2f
YS
136 locator = zebra_srv6_locator_lookup(locator_name);
137 if (!locator)
138 return CMD_WARNING;
139
140 json_locator = srv6_locator_detailed_json(locator);
141 vty_json(vty, json_locator);
142 return CMD_SUCCESS;
4df9d859 143 }
00978977 144
4df9d859
HS
145 for (ALL_LIST_ELEMENTS_RO(srv6->locators, node, locator)) {
146 struct listnode *node;
147 struct srv6_locator_chunk *chunk;
148
149 if (strcmp(locator->name, locator_name) != 0)
150 continue;
151
152 prefix2str(&locator->prefix, str, sizeof(str));
153 vty_out(vty, "Name: %s\n", locator->name);
154 vty_out(vty, "Prefix: %s\n", str);
d9d31799
CS
155 vty_out(vty, "Block-Bit-Len: %u\n", locator->block_bits_length);
156 vty_out(vty, "Node-Bit-Len: %u\n", locator->node_bits_length);
4df9d859
HS
157 vty_out(vty, "Function-Bit-Len: %u\n",
158 locator->function_bits_length);
d9d31799
CS
159 vty_out(vty, "Argument-Bit-Len: %u\n",
160 locator->argument_bits_length);
4df9d859 161
a3ff3dff
CS
162 if (CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID))
163 vty_out(vty, "Behavior: uSID\n");
164
4df9d859
HS
165 vty_out(vty, "Chunks:\n");
166 for (ALL_LIST_ELEMENTS_RO((struct list *)locator->chunks, node,
167 chunk)) {
168 prefix2str(&chunk->prefix, str, sizeof(str));
169 vty_out(vty, "- prefix: %s, owner: %s\n", str,
170 zebra_route_string(chunk->proto));
00978977 171 }
00978977
HS
172 }
173
4df9d859 174
00978977
HS
175 return CMD_SUCCESS;
176}
177
6c0a7c09
HS
178DEFUN_NOSH (segment_routing,
179 segment_routing_cmd,
180 "segment-routing",
181 "Segment Routing\n")
182{
183 vty->node = SEGMENT_ROUTING_NODE;
184 return CMD_SUCCESS;
185}
186
187DEFUN_NOSH (srv6,
188 srv6_cmd,
189 "srv6",
190 "Segment Routing SRv6\n")
191{
192 vty->node = SRV6_NODE;
193 return CMD_SUCCESS;
194}
195
0a735cd5
HS
196DEFUN (no_srv6,
197 no_srv6_cmd,
198 "no srv6",
199 NO_STR
200 "Segment Routing SRv6\n")
201{
202 struct zebra_srv6 *srv6 = zebra_srv6_get_default();
203 struct srv6_locator *locator;
204 struct listnode *node, *nnode;
205
206 for (ALL_LIST_ELEMENTS(srv6->locators, node, nnode, locator))
207 zebra_srv6_locator_delete(locator);
208 return CMD_SUCCESS;
209}
210
6c0a7c09
HS
211DEFUN_NOSH (srv6_locators,
212 srv6_locators_cmd,
213 "locators",
214 "Segment Routing SRv6 locators\n")
215{
216 vty->node = SRV6_LOCS_NODE;
217 return CMD_SUCCESS;
218}
219
220DEFUN_NOSH (srv6_locator,
221 srv6_locator_cmd,
222 "locator WORD",
223 "Segment Routing SRv6 locator\n"
224 "Specify locator-name\n")
225{
00978977
HS
226 struct srv6_locator *locator = NULL;
227
228 locator = zebra_srv6_locator_lookup(argv[1]->arg);
229 if (locator) {
230 VTY_PUSH_CONTEXT(SRV6_LOC_NODE, locator);
231 locator->status_up = true;
232 return CMD_SUCCESS;
233 }
234
235 locator = srv6_locator_alloc(argv[1]->arg);
236 if (!locator) {
237 vty_out(vty, "%% Alloc failed\n");
238 return CMD_WARNING_CONFIG_FAILED;
239 }
240 locator->status_up = true;
241
242 VTY_PUSH_CONTEXT(SRV6_LOC_NODE, locator);
6c0a7c09
HS
243 vty->node = SRV6_LOC_NODE;
244 return CMD_SUCCESS;
245}
246
0a735cd5
HS
247DEFUN (no_srv6_locator,
248 no_srv6_locator_cmd,
249 "no locator WORD",
250 NO_STR
251 "Segment Routing SRv6 locator\n"
252 "Specify locator-name\n")
253{
254 struct srv6_locator *locator = zebra_srv6_locator_lookup(argv[2]->arg);
255 if (!locator) {
256 vty_out(vty, "%% Can't find SRv6 locator\n");
257 return CMD_WARNING_CONFIG_FAILED;
258 }
259
260 zebra_srv6_locator_delete(locator);
261 return CMD_SUCCESS;
262}
263
daedb8b3 264DEFPY (locator_prefix,
00978977 265 locator_prefix_cmd,
3afb06d3
RS
266 "prefix X:X::X:X/M$prefix [block-len (16-64)$block_bit_len] \
267 [node-len (16-64)$node_bit_len] [func-bits (0-64)$func_bit_len]",
00978977
HS
268 "Configure SRv6 locator prefix\n"
269 "Specify SRv6 locator prefix\n"
5e04508c
CS
270 "Configure SRv6 locator block length in bits\n"
271 "Specify SRv6 locator block length in bits\n"
272 "Configure SRv6 locator node length in bits\n"
3afb06d3
RS
273 "Specify SRv6 locator node length in bits\n"
274 "Configure SRv6 locator function length in bits\n"
275 "Specify SRv6 locator function length in bits\n")
00978977
HS
276{
277 VTY_DECLVAR_CONTEXT(srv6_locator, locator);
00978977
HS
278 struct srv6_locator_chunk *chunk = NULL;
279 struct listnode *node = NULL;
00978977 280
daedb8b3 281 locator->prefix = *prefix;
85521aaa 282 func_bit_len = func_bit_len ?: ZEBRA_SRV6_FUNCTION_LENGTH;
ac6a9479 283
5e04508c
CS
284 /* Resolve optional arguments */
285 if (block_bit_len == 0 && node_bit_len == 0) {
286 block_bit_len =
287 prefix->prefixlen - ZEBRA_SRV6_LOCATOR_NODE_LENGTH;
288 node_bit_len = ZEBRA_SRV6_LOCATOR_NODE_LENGTH;
289 } else if (block_bit_len == 0) {
290 block_bit_len = prefix->prefixlen - node_bit_len;
291 } else if (node_bit_len == 0) {
292 node_bit_len = prefix->prefixlen - block_bit_len;
293 } else {
294 if (block_bit_len + node_bit_len != prefix->prefixlen) {
295 vty_out(vty,
296 "%% block-len + node-len must be equal to the selected prefix length %d\n",
297 prefix->prefixlen);
298 return CMD_WARNING_CONFIG_FAILED;
299 }
300 }
301
34e3711f
CS
302 if (prefix->prefixlen + func_bit_len + 0 > 128) {
303 vty_out(vty,
304 "%% prefix-len + function-len + arg-len (%ld) cannot be greater than 128\n",
305 prefix->prefixlen + func_bit_len + 0);
306 return CMD_WARNING_CONFIG_FAILED;
307 }
308
537b8b13
CS
309 /*
310 * Currently, the SID transposition algorithm implemented in bgpd
311 * handles incorrectly the SRv6 locators with function length greater
312 * than 20 bits. To prevent issues, we currently limit the function
313 * length to 20 bits.
314 * This limit will be removed when the bgpd SID transposition is fixed.
315 */
316 if (func_bit_len > 20) {
317 vty_out(vty,
318 "%% currently func_bit_len > 20 is not supported\n");
319 return CMD_WARNING_CONFIG_FAILED;
320 }
321
5e04508c
CS
322 locator->block_bits_length = block_bit_len;
323 locator->node_bits_length = node_bit_len;
daedb8b3 324 locator->function_bits_length = func_bit_len;
ac6a9479 325 locator->argument_bits_length = 0;
00978977
HS
326
327 if (list_isempty(locator->chunks)) {
328 chunk = srv6_locator_chunk_alloc();
daedb8b3 329 chunk->prefix = *prefix;
00978977
HS
330 chunk->proto = 0;
331 listnode_add(locator->chunks, chunk);
332 } else {
333 for (ALL_LIST_ELEMENTS_RO(locator->chunks, node, chunk)) {
334 uint8_t zero[16] = {0};
4df9d859 335
00978977
HS
336 if (memcmp(&chunk->prefix.prefix, zero, 16) == 0) {
337 struct zserv *client;
338 struct listnode *client_node;
4df9d859 339
daedb8b3 340 chunk->prefix = *prefix;
4df9d859
HS
341 for (ALL_LIST_ELEMENTS_RO(zrouter.client_list,
342 client_node,
343 client)) {
344 struct srv6_locator *tmp;
345
00978977
HS
346 if (client->proto != chunk->proto)
347 continue;
f29aed74 348
00978977 349 srv6_manager_get_locator_chunk_call(
4df9d859
HS
350 &tmp, client,
351 locator->name,
352 VRF_DEFAULT);
00978977
HS
353 }
354 }
355 }
356 }
357
358 zebra_srv6_locator_add(locator);
359 return CMD_SUCCESS;
360}
361
3a7e1f65
CS
362DEFPY (locator_behavior,
363 locator_behavior_cmd,
364 "[no] behavior usid",
365 NO_STR
366 "Configure SRv6 behavior\n"
367 "Specify SRv6 behavior uSID\n")
368{
369 VTY_DECLVAR_CONTEXT(srv6_locator, locator);
370
371 if (no && !CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID))
372 /* SRv6 locator uSID flag already unset, nothing to do */
373 return CMD_SUCCESS;
374
375 if (!no && CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID))
376 /* SRv6 locator uSID flag already set, nothing to do */
377 return CMD_SUCCESS;
378
379 /* Remove old locator from zclients */
380 zebra_notify_srv6_locator_delete(locator);
381
382 /* Set/Unset the SRV6_LOCATOR_USID */
383 if (no)
384 UNSET_FLAG(locator->flags, SRV6_LOCATOR_USID);
385 else
386 SET_FLAG(locator->flags, SRV6_LOCATOR_USID);
387
388 /* Notify the new locator to zclients */
389 zebra_notify_srv6_locator_add(locator);
390
391 return CMD_SUCCESS;
392}
393
6c0a7c09
HS
394static int zebra_sr_config(struct vty *vty)
395{
00978977
HS
396 struct zebra_srv6 *srv6 = zebra_srv6_get_default();
397 struct listnode *node;
398 struct srv6_locator *locator;
399 char str[256];
400
401 vty_out(vty, "!\n");
402 if (zebra_srv6_is_enable()) {
403 vty_out(vty, "segment-routing\n");
404 vty_out(vty, " srv6\n");
405 vty_out(vty, " locators\n");
406 for (ALL_LIST_ELEMENTS_RO(srv6->locators, node, locator)) {
407 inet_ntop(AF_INET6, &locator->prefix.prefix,
408 str, sizeof(str));
409 vty_out(vty, " locator %s\n", locator->name);
fbd01eaa 410 vty_out(vty, " prefix %s/%u", str,
00978977 411 locator->prefix.prefixlen);
780c13eb
CS
412 if (locator->block_bits_length)
413 vty_out(vty, " block-len %u",
414 locator->block_bits_length);
415 if (locator->node_bits_length)
416 vty_out(vty, " node-len %u",
417 locator->node_bits_length);
fbd01eaa
NM
418 if (locator->function_bits_length)
419 vty_out(vty, " func-bits %u",
420 locator->function_bits_length);
780c13eb
CS
421 if (locator->argument_bits_length)
422 vty_out(vty, " arg-len %u",
423 locator->argument_bits_length);
fbd01eaa 424 vty_out(vty, "\n");
dd8b193e
CS
425 if (CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID))
426 vty_out(vty, " behavior usid\n");
07679ad9 427 vty_out(vty, " exit\n");
00978977
HS
428 vty_out(vty, " !\n");
429 }
07679ad9 430 vty_out(vty, " exit\n");
00978977 431 vty_out(vty, " !\n");
07679ad9 432 vty_out(vty, " exit\n");
00978977 433 vty_out(vty, " !\n");
07679ad9 434 vty_out(vty, "exit\n");
00978977
HS
435 vty_out(vty, "!\n");
436 }
6c0a7c09
HS
437 return 0;
438}
439
440void zebra_srv6_vty_init(void)
441{
442 /* Install nodes and its default commands */
443 install_node(&sr_node);
444 install_node(&srv6_node);
445 install_node(&srv6_locs_node);
446 install_node(&srv6_loc_node);
447 install_default(SEGMENT_ROUTING_NODE);
448 install_default(SRV6_NODE);
449 install_default(SRV6_LOCS_NODE);
450 install_default(SRV6_LOC_NODE);
451
452 /* Command for change node */
453 install_element(CONFIG_NODE, &segment_routing_cmd);
454 install_element(SEGMENT_ROUTING_NODE, &srv6_cmd);
0a735cd5 455 install_element(SEGMENT_ROUTING_NODE, &no_srv6_cmd);
6c0a7c09
HS
456 install_element(SRV6_NODE, &srv6_locators_cmd);
457 install_element(SRV6_LOCS_NODE, &srv6_locator_cmd);
0a735cd5 458 install_element(SRV6_LOCS_NODE, &no_srv6_locator_cmd);
00978977
HS
459
460 /* Command for configuration */
461 install_element(SRV6_LOC_NODE, &locator_prefix_cmd);
3a7e1f65 462 install_element(SRV6_LOC_NODE, &locator_behavior_cmd);
00978977
HS
463
464 /* Command for operation */
465 install_element(VIEW_NODE, &show_srv6_locator_cmd);
466 install_element(VIEW_NODE, &show_srv6_locator_detail_cmd);
6c0a7c09 467}