]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_srv6_vty.c
Merge pull request #12544 from mjstapp/fix_pathd_sa_pcep_config
[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 174
a3ff3dff
CS
175 if (CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID))
176 vty_out(vty, "Behavior: uSID\n");
177
4df9d859
HS
178 vty_out(vty, "Chunks:\n");
179 for (ALL_LIST_ELEMENTS_RO((struct list *)locator->chunks, node,
180 chunk)) {
181 prefix2str(&chunk->prefix, str, sizeof(str));
182 vty_out(vty, "- prefix: %s, owner: %s\n", str,
183 zebra_route_string(chunk->proto));
00978977 184 }
00978977
HS
185 }
186
4df9d859 187
00978977
HS
188 return CMD_SUCCESS;
189}
190
6c0a7c09
HS
191DEFUN_NOSH (segment_routing,
192 segment_routing_cmd,
193 "segment-routing",
194 "Segment Routing\n")
195{
196 vty->node = SEGMENT_ROUTING_NODE;
197 return CMD_SUCCESS;
198}
199
200DEFUN_NOSH (srv6,
201 srv6_cmd,
202 "srv6",
203 "Segment Routing SRv6\n")
204{
205 vty->node = SRV6_NODE;
206 return CMD_SUCCESS;
207}
208
0a735cd5
HS
209DEFUN (no_srv6,
210 no_srv6_cmd,
211 "no srv6",
212 NO_STR
213 "Segment Routing SRv6\n")
214{
215 struct zebra_srv6 *srv6 = zebra_srv6_get_default();
216 struct srv6_locator *locator;
217 struct listnode *node, *nnode;
218
219 for (ALL_LIST_ELEMENTS(srv6->locators, node, nnode, locator))
220 zebra_srv6_locator_delete(locator);
221 return CMD_SUCCESS;
222}
223
6c0a7c09
HS
224DEFUN_NOSH (srv6_locators,
225 srv6_locators_cmd,
226 "locators",
227 "Segment Routing SRv6 locators\n")
228{
229 vty->node = SRV6_LOCS_NODE;
230 return CMD_SUCCESS;
231}
232
233DEFUN_NOSH (srv6_locator,
234 srv6_locator_cmd,
235 "locator WORD",
236 "Segment Routing SRv6 locator\n"
237 "Specify locator-name\n")
238{
00978977
HS
239 struct srv6_locator *locator = NULL;
240
241 locator = zebra_srv6_locator_lookup(argv[1]->arg);
242 if (locator) {
243 VTY_PUSH_CONTEXT(SRV6_LOC_NODE, locator);
244 locator->status_up = true;
245 return CMD_SUCCESS;
246 }
247
248 locator = srv6_locator_alloc(argv[1]->arg);
249 if (!locator) {
250 vty_out(vty, "%% Alloc failed\n");
251 return CMD_WARNING_CONFIG_FAILED;
252 }
253 locator->status_up = true;
254
255 VTY_PUSH_CONTEXT(SRV6_LOC_NODE, locator);
6c0a7c09
HS
256 vty->node = SRV6_LOC_NODE;
257 return CMD_SUCCESS;
258}
259
0a735cd5
HS
260DEFUN (no_srv6_locator,
261 no_srv6_locator_cmd,
262 "no locator WORD",
263 NO_STR
264 "Segment Routing SRv6 locator\n"
265 "Specify locator-name\n")
266{
267 struct srv6_locator *locator = zebra_srv6_locator_lookup(argv[2]->arg);
268 if (!locator) {
269 vty_out(vty, "%% Can't find SRv6 locator\n");
270 return CMD_WARNING_CONFIG_FAILED;
271 }
272
273 zebra_srv6_locator_delete(locator);
274 return CMD_SUCCESS;
275}
276
daedb8b3 277DEFPY (locator_prefix,
00978977 278 locator_prefix_cmd,
3afb06d3
RS
279 "prefix X:X::X:X/M$prefix [block-len (16-64)$block_bit_len] \
280 [node-len (16-64)$node_bit_len] [func-bits (0-64)$func_bit_len]",
00978977
HS
281 "Configure SRv6 locator prefix\n"
282 "Specify SRv6 locator prefix\n"
5e04508c
CS
283 "Configure SRv6 locator block length in bits\n"
284 "Specify SRv6 locator block length in bits\n"
285 "Configure SRv6 locator node length in bits\n"
3afb06d3
RS
286 "Specify SRv6 locator node length in bits\n"
287 "Configure SRv6 locator function length in bits\n"
288 "Specify SRv6 locator function length in bits\n")
00978977
HS
289{
290 VTY_DECLVAR_CONTEXT(srv6_locator, locator);
00978977
HS
291 struct srv6_locator_chunk *chunk = NULL;
292 struct listnode *node = NULL;
00978977 293
daedb8b3 294 locator->prefix = *prefix;
85521aaa 295 func_bit_len = func_bit_len ?: ZEBRA_SRV6_FUNCTION_LENGTH;
ac6a9479 296
5e04508c
CS
297 /* Resolve optional arguments */
298 if (block_bit_len == 0 && node_bit_len == 0) {
299 block_bit_len =
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;
306 } else {
307 if (block_bit_len + node_bit_len != prefix->prefixlen) {
308 vty_out(vty,
309 "%% block-len + node-len must be equal to the selected prefix length %d\n",
310 prefix->prefixlen);
311 return CMD_WARNING_CONFIG_FAILED;
312 }
313 }
314
34e3711f
CS
315 if (prefix->prefixlen + func_bit_len + 0 > 128) {
316 vty_out(vty,
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;
320 }
321
537b8b13
CS
322 /*
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
326 * length to 20 bits.
327 * This limit will be removed when the bgpd SID transposition is fixed.
328 */
329 if (func_bit_len > 20) {
330 vty_out(vty,
331 "%% currently func_bit_len > 20 is not supported\n");
332 return CMD_WARNING_CONFIG_FAILED;
333 }
334
5e04508c
CS
335 locator->block_bits_length = block_bit_len;
336 locator->node_bits_length = node_bit_len;
daedb8b3 337 locator->function_bits_length = func_bit_len;
ac6a9479 338 locator->argument_bits_length = 0;
00978977
HS
339
340 if (list_isempty(locator->chunks)) {
341 chunk = srv6_locator_chunk_alloc();
daedb8b3 342 chunk->prefix = *prefix;
00978977
HS
343 chunk->proto = 0;
344 listnode_add(locator->chunks, chunk);
345 } else {
346 for (ALL_LIST_ELEMENTS_RO(locator->chunks, node, chunk)) {
347 uint8_t zero[16] = {0};
4df9d859 348
00978977
HS
349 if (memcmp(&chunk->prefix.prefix, zero, 16) == 0) {
350 struct zserv *client;
351 struct listnode *client_node;
4df9d859 352
daedb8b3 353 chunk->prefix = *prefix;
4df9d859
HS
354 for (ALL_LIST_ELEMENTS_RO(zrouter.client_list,
355 client_node,
356 client)) {
357 struct srv6_locator *tmp;
358
00978977
HS
359 if (client->proto != chunk->proto)
360 continue;
f29aed74 361
00978977 362 srv6_manager_get_locator_chunk_call(
4df9d859
HS
363 &tmp, client,
364 locator->name,
365 VRF_DEFAULT);
00978977
HS
366 }
367 }
368 }
369 }
370
371 zebra_srv6_locator_add(locator);
372 return CMD_SUCCESS;
373}
374
3a7e1f65
CS
375DEFPY (locator_behavior,
376 locator_behavior_cmd,
377 "[no] behavior usid",
378 NO_STR
379 "Configure SRv6 behavior\n"
380 "Specify SRv6 behavior uSID\n")
381{
382 VTY_DECLVAR_CONTEXT(srv6_locator, locator);
383
384 if (no && !CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID))
385 /* SRv6 locator uSID flag already unset, nothing to do */
386 return CMD_SUCCESS;
387
388 if (!no && CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID))
389 /* SRv6 locator uSID flag already set, nothing to do */
390 return CMD_SUCCESS;
391
392 /* Remove old locator from zclients */
393 zebra_notify_srv6_locator_delete(locator);
394
395 /* Set/Unset the SRV6_LOCATOR_USID */
396 if (no)
397 UNSET_FLAG(locator->flags, SRV6_LOCATOR_USID);
398 else
399 SET_FLAG(locator->flags, SRV6_LOCATOR_USID);
400
401 /* Notify the new locator to zclients */
402 zebra_notify_srv6_locator_add(locator);
403
404 return CMD_SUCCESS;
405}
406
6c0a7c09
HS
407static int zebra_sr_config(struct vty *vty)
408{
00978977
HS
409 struct zebra_srv6 *srv6 = zebra_srv6_get_default();
410 struct listnode *node;
411 struct srv6_locator *locator;
412 char str[256];
413
414 vty_out(vty, "!\n");
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,
421 str, sizeof(str));
422 vty_out(vty, " locator %s\n", locator->name);
fbd01eaa 423 vty_out(vty, " prefix %s/%u", str,
00978977 424 locator->prefix.prefixlen);
780c13eb
CS
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);
fbd01eaa
NM
431 if (locator->function_bits_length)
432 vty_out(vty, " func-bits %u",
433 locator->function_bits_length);
780c13eb
CS
434 if (locator->argument_bits_length)
435 vty_out(vty, " arg-len %u",
436 locator->argument_bits_length);
fbd01eaa 437 vty_out(vty, "\n");
dd8b193e
CS
438 if (CHECK_FLAG(locator->flags, SRV6_LOCATOR_USID))
439 vty_out(vty, " behavior usid\n");
07679ad9 440 vty_out(vty, " exit\n");
00978977
HS
441 vty_out(vty, " !\n");
442 }
07679ad9 443 vty_out(vty, " exit\n");
00978977 444 vty_out(vty, " !\n");
07679ad9 445 vty_out(vty, " exit\n");
00978977 446 vty_out(vty, " !\n");
07679ad9 447 vty_out(vty, "exit\n");
00978977
HS
448 vty_out(vty, "!\n");
449 }
6c0a7c09
HS
450 return 0;
451}
452
453void zebra_srv6_vty_init(void)
454{
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);
464
465 /* Command for change node */
466 install_element(CONFIG_NODE, &segment_routing_cmd);
467 install_element(SEGMENT_ROUTING_NODE, &srv6_cmd);
0a735cd5 468 install_element(SEGMENT_ROUTING_NODE, &no_srv6_cmd);
6c0a7c09
HS
469 install_element(SRV6_NODE, &srv6_locators_cmd);
470 install_element(SRV6_LOCS_NODE, &srv6_locator_cmd);
0a735cd5 471 install_element(SRV6_LOCS_NODE, &no_srv6_locator_cmd);
00978977
HS
472
473 /* Command for configuration */
474 install_element(SRV6_LOC_NODE, &locator_prefix_cmd);
3a7e1f65 475 install_element(SRV6_LOC_NODE, &locator_behavior_cmd);
00978977
HS
476
477 /* Command for operation */
478 install_element(VIEW_NODE, &show_srv6_locator_cmd);
479 install_element(VIEW_NODE, &show_srv6_locator_detail_cmd);
6c0a7c09 480}