]> git.proxmox.com Git - mirror_frr.git/blame - sharpd/sharp_vty.c
build, vtysh: extract vtysh commands from .xref
[mirror_frr.git] / sharpd / sharp_vty.c
CommitLineData
8a71d93d
DS
1/*
2 * SHARP - vty code
3 * Copyright (C) Cumulus Networks, Inc.
4 * Donald Sharp
5 *
6 * This file is part of FRR.
7 *
8 * FRR is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2, or (at your option) any
11 * later version.
12 *
13 * FRR is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; see the file COPYING; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22#include <zebra.h>
23
24#include "vty.h"
25#include "command.h"
26#include "prefix.h"
27#include "nexthop.h"
28#include "log.h"
ab18a495
DS
29#include "vrf.h"
30#include "zclient.h"
694b242f 31#include "nexthop_group.h"
621fb5f3 32#include "linklist.h"
1888e243 33#include "link_state.h"
621fb5f3 34#include "cspf.h"
8a71d93d 35
547dc642 36#include "sharpd/sharp_globals.h"
8a71d93d 37#include "sharpd/sharp_zebra.h"
86da53ab 38#include "sharpd/sharp_nht.h"
8a71d93d
DS
39#include "sharpd/sharp_vty.h"
40#include "sharpd/sharp_vty_clippy.c"
41
ade3eebc
HS
42DEFINE_MTYPE_STATIC(SHARPD, SRV6_LOCATOR, "SRv6 Locator");
43
921af54d
DS
44DEFPY(watch_redistribute, watch_redistribute_cmd,
45 "sharp watch [vrf NAME$vrf_name] redistribute " FRR_REDIST_STR_SHARPD,
46 "Sharp routing Protocol\n"
47 "Watch for changes\n"
48 "The vrf we would like to watch if non-default\n"
49 "The NAME of the vrf\n"
50 "Redistribute into Sharp\n"
51 FRR_REDIST_HELP_STR_SHARPD)
52{
53 struct vrf *vrf;
54 int source;
55
56 if (!vrf_name)
57 vrf_name = VRF_DEFAULT_NAME;
58 vrf = vrf_lookup_by_name(vrf_name);
59 if (!vrf) {
60 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
61 vrf_name);
62 return CMD_WARNING;
63 }
64
65 source = proto_redistnum(AFI_IP, argv[argc-1]->text);
66 sharp_redistribute_vrf(vrf, source);
67
68 return CMD_SUCCESS;
69}
70
0ae8130d 71DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
e429a2a0 72 "sharp watch [vrf NAME$vrf_name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop> [connected$connected]",
0ae8130d
DS
73 "Sharp routing Protocol\n"
74 "Watch for changes\n"
a3b6aa82
DS
75 "The vrf we would like to watch if non-default\n"
76 "The NAME of the vrf\n"
0ae8130d 77 "Watch for nexthop changes\n"
a60ffbc9 78 "The v6 nexthop to signal for watching\n"
1be0815d
DS
79 "Watch for import check changes\n"
80 "The v6 prefix to signal for watching\n"
a60ffbc9 81 "Should the route be connected\n")
0ae8130d 82{
a3b6aa82 83 struct vrf *vrf;
0ae8130d 84 struct prefix p;
80d5ff33
DS
85 bool type_import;
86
e429a2a0
IR
87 if (!vrf_name)
88 vrf_name = VRF_DEFAULT_NAME;
89 vrf = vrf_lookup_by_name(vrf_name);
a3b6aa82
DS
90 if (!vrf) {
91 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
e429a2a0 92 vrf_name);
a3b6aa82
DS
93 return CMD_WARNING;
94 }
80d5ff33 95
0ae8130d
DS
96 memset(&p, 0, sizeof(p));
97
1be0815d
DS
98 if (n) {
99 type_import = false;
13ccce6e 100 p.prefixlen = IPV6_MAX_BITLEN;
8643c2e5 101 memcpy(&p.u.prefix6, &nhop, IPV6_MAX_BYTELEN);
1be0815d
DS
102 p.family = AF_INET6;
103 } else {
104 type_import = true;
5c7a6fb3 105 prefix_copy(&p, inhop);
1be0815d 106 }
0ae8130d 107
86da53ab 108 sharp_nh_tracker_get(&p);
a3b6aa82 109 sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
91529dc8 110 true, !!connected);
0ae8130d
DS
111
112 return CMD_SUCCESS;
113}
114
115DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
e429a2a0 116 "sharp watch [vrf NAME$vrf_name] <nexthop$n A.B.C.D$nhop|import$import A.B.C.D/M$inhop> [connected$connected]",
0ae8130d
DS
117 "Sharp routing Protocol\n"
118 "Watch for changes\n"
a3b6aa82
DS
119 "The vrf we would like to watch if non-default\n"
120 "The NAME of the vrf\n"
0ae8130d 121 "Watch for nexthop changes\n"
1be0815d 122 "The v4 address to signal for watching\n"
80d5ff33 123 "Watch for import check changes\n"
1be0815d 124 "The v4 prefix for import check to watch\n"
a60ffbc9 125 "Should the route be connected\n")
0ae8130d 126{
a3b6aa82 127 struct vrf *vrf;
0ae8130d 128 struct prefix p;
80d5ff33 129 bool type_import;
0ae8130d 130
e429a2a0
IR
131 if (!vrf_name)
132 vrf_name = VRF_DEFAULT_NAME;
133 vrf = vrf_lookup_by_name(vrf_name);
a3b6aa82
DS
134 if (!vrf) {
135 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
e429a2a0 136 vrf_name);
a3b6aa82
DS
137 return CMD_WARNING;
138 }
139
0ae8130d
DS
140 memset(&p, 0, sizeof(p));
141
1be0815d 142 if (n) {
80d5ff33 143 type_import = false;
12256b84 144 p.prefixlen = IPV4_MAX_BITLEN;
1be0815d
DS
145 p.u.prefix4 = nhop;
146 p.family = AF_INET;
147 }
148 else {
80d5ff33 149 type_import = true;
5c7a6fb3 150 prefix_copy(&p, inhop);
1be0815d 151 }
0ae8130d 152
86da53ab 153 sharp_nh_tracker_get(&p);
a3b6aa82 154 sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
91529dc8 155 true, !!connected);
0ae8130d
DS
156
157 return CMD_SUCCESS;
158}
159
86da53ab
DS
160DEFPY(sharp_nht_data_dump,
161 sharp_nht_data_dump_cmd,
162 "sharp data nexthop",
163 "Sharp routing Protocol\n"
bcc519dc
DS
164 "Data about what is going on\n"
165 "Nexthop information\n")
86da53ab
DS
166{
167 sharp_nh_tracker_dump(vty);
168
169 return CMD_SUCCESS;
170}
171
f59e6418
DS
172DEFPY (install_routes_data_dump,
173 install_routes_data_dump_cmd,
174 "sharp data route",
175 "Sharp routing Protocol\n"
176 "Data about what is going on\n"
177 "Route Install/Removal Information\n")
178{
f59e6418
DS
179 struct timeval r;
180
181 timersub(&sg.r.t_end, &sg.r.t_start, &r);
2dbe669b
DA
182 vty_out(vty, "Prefix: %pFX Total: %u %u %u Time: %jd.%ld\n",
183 &sg.r.orig_prefix, sg.r.total_routes, sg.r.installed_routes,
184 sg.r.removed_routes, (intmax_t)r.tv_sec, (long)r.tv_usec);
f59e6418
DS
185
186 return CMD_SUCCESS;
187}
188
8a71d93d
DS
189DEFPY (install_routes,
190 install_routes_cmd,
1df3b1dc
MS
191 "sharp install routes [vrf NAME$vrf_name]\
192 <A.B.C.D$start4|X:X::X:X$start6>\
193 <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|\
1cb131ee 194 nexthop-group NHGNAME$nexthop_group>\
1df3b1dc 195 [backup$backup <A.B.C.D$backup_nexthop4|X:X::X:X$backup_nexthop6>] \
cfa2a35d 196 (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt] [opaque WORD]",
75239f4f 197 "Sharp routing Protocol\n"
8a71d93d
DS
198 "install some routes\n"
199 "Routes to install\n"
4a7d4737
DS
200 "The vrf we would like to install into if non-default\n"
201 "The NAME of the vrf\n"
dbc1bf46
DS
202 "v4 Address to start /32 generation at\n"
203 "v6 Address to start /32 generation at\n"
ba041bea
DS
204 "Nexthop to use(Can be an IPv4 or IPv6 address)\n"
205 "V4 Nexthop address to use\n"
206 "V6 Nexthop address to use\n"
d4101c0a
DS
207 "Nexthop-Group to use\n"
208 "The Name of the nexthop-group\n"
1df3b1dc
MS
209 "Backup nexthop to use(Can be an IPv4 or IPv6 address)\n"
210 "Backup V4 Nexthop address to use\n"
211 "Backup V6 Nexthop address to use\n"
ae252c02
DS
212 "How many to create\n"
213 "Instance to use\n"
b939f6ff
DS
214 "Instance\n"
215 "Should we repeat this command\n"
cfa2a35d
DS
216 "How many times to repeat this command\n"
217 "What opaque data to send down\n"
218 "The opaque data\n")
8a71d93d 219{
4a7d4737 220 struct vrf *vrf;
547dc642
DS
221 struct prefix prefix;
222 uint32_t rts;
569e87c0 223 uint32_t nhgid = 0;
547dc642
DS
224
225 sg.r.total_routes = routes;
226 sg.r.installed_routes = 0;
8a71d93d 227
b939f6ff 228 if (rpt >= 2)
547dc642 229 sg.r.repeat = rpt * 2;
b939f6ff 230 else
547dc642 231 sg.r.repeat = 0;
b939f6ff
DS
232
233 memset(&prefix, 0, sizeof(prefix));
547dc642 234 memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
877682e3
CS
235 nexthop_del_srv6_seg6local(&sg.r.nhop);
236 nexthop_del_srv6_seg6(&sg.r.nhop);
547dc642
DS
237 memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
238 memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
1df3b1dc
MS
239 memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
240 memset(&sg.r.backup_nhop_group, 0, sizeof(sg.r.nhop_group));
8a71d93d 241
3a6290bd 242 if (start4.s_addr != INADDR_ANY) {
dbc1bf46 243 prefix.family = AF_INET;
12256b84 244 prefix.prefixlen = IPV4_MAX_BITLEN;
dbc1bf46
DS
245 prefix.u.prefix4 = start4;
246 } else {
247 prefix.family = AF_INET6;
13ccce6e 248 prefix.prefixlen = IPV6_MAX_BITLEN;
dbc1bf46
DS
249 prefix.u.prefix6 = start6;
250 }
547dc642 251 sg.r.orig_prefix = prefix;
8a71d93d 252
e429a2a0
IR
253 if (!vrf_name)
254 vrf_name = VRF_DEFAULT_NAME;
a3b6aa82 255
e429a2a0 256 vrf = vrf_lookup_by_name(vrf_name);
4a7d4737
DS
257 if (!vrf) {
258 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
e429a2a0 259 vrf_name);
4a7d4737
DS
260 return CMD_WARNING;
261 }
262
1df3b1dc
MS
263 /* Explicit backup not available with named nexthop-group */
264 if (backup && nexthop_group) {
265 vty_out(vty, "%% Invalid: cannot specify both nexthop-group and backup\n");
266 return CMD_WARNING;
267 }
268
d4101c0a
DS
269 if (nexthop_group) {
270 struct nexthop_group_cmd *nhgc = nhgc_find(nexthop_group);
271 if (!nhgc) {
272 vty_out(vty,
273 "Specified Nexthop Group: %s does not exist\n",
274 nexthop_group);
275 return CMD_WARNING;
276 }
277
569e87c0
DS
278 nhgid = sharp_nhgroup_get_id(nexthop_group);
279 sg.r.nhgid = nhgid;
547dc642 280 sg.r.nhop_group.nexthop = nhgc->nhg.nexthop;
1df3b1dc
MS
281
282 /* Use group's backup nexthop info if present */
283 if (nhgc->backup_list_name[0]) {
284 struct nexthop_group_cmd *bnhgc =
285 nhgc_find(nhgc->backup_list_name);
286
287 if (!bnhgc) {
288 vty_out(vty, "%% Backup group %s not found for group %s\n",
289 nhgc->backup_list_name,
290 nhgc->name);
291 return CMD_WARNING;
292 }
293
294 sg.r.backup_nhop.vrf_id = vrf->vrf_id;
295 sg.r.backup_nhop_group.nexthop = bnhgc->nhg.nexthop;
296 }
ba041bea 297 } else {
d4101c0a 298 if (nexthop4.s_addr != INADDR_ANY) {
547dc642
DS
299 sg.r.nhop.gate.ipv4 = nexthop4;
300 sg.r.nhop.type = NEXTHOP_TYPE_IPV4;
d4101c0a 301 } else {
547dc642
DS
302 sg.r.nhop.gate.ipv6 = nexthop6;
303 sg.r.nhop.type = NEXTHOP_TYPE_IPV6;
d4101c0a
DS
304 }
305
4a7d4737 306 sg.r.nhop.vrf_id = vrf->vrf_id;
547dc642 307 sg.r.nhop_group.nexthop = &sg.r.nhop;
ba041bea 308 }
8a71d93d 309
1df3b1dc
MS
310 /* Use single backup nexthop if specified */
311 if (backup) {
312 /* Set flag and index in primary nexthop */
313 SET_FLAG(sg.r.nhop.flags, NEXTHOP_FLAG_HAS_BACKUP);
474aebd9
MS
314 sg.r.nhop.backup_num = 1;
315 sg.r.nhop.backup_idx[0] = 0;
1df3b1dc
MS
316
317 if (backup_nexthop4.s_addr != INADDR_ANY) {
318 sg.r.backup_nhop.gate.ipv4 = backup_nexthop4;
319 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV4;
320 } else {
321 sg.r.backup_nhop.gate.ipv6 = backup_nexthop6;
322 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV6;
323 }
324
325 sg.r.backup_nhop.vrf_id = vrf->vrf_id;
326 sg.r.backup_nhop_group.nexthop = &sg.r.backup_nhop;
327 }
328
cfa2a35d
DS
329 if (opaque)
330 strlcpy(sg.r.opaque, opaque, ZAPI_MESSAGE_OPAQUE_LENGTH);
331 else
332 sg.r.opaque[0] = '\0';
333
547dc642 334 sg.r.inst = instance;
4a7d4737 335 sg.r.vrf_id = vrf->vrf_id;
b939f6ff 336 rts = routes;
ff9aca4f
SW
337 sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, nhgid,
338 &sg.r.nhop_group, &sg.r.backup_nhop_group,
1cb131ee
HS
339 rts, 0, sg.r.opaque);
340
341 return CMD_SUCCESS;
342}
343
344DEFPY (install_seg6_routes,
345 install_seg6_routes_cmd,
346 "sharp install seg6-routes [vrf NAME$vrf_name]\
347 <A.B.C.D$start4|X:X::X:X$start6>\
348 nexthop-seg6 X:X::X:X$seg6_nh6 encap X:X::X:X$seg6_seg\
349 (1-1000000)$routes [repeat (2-1000)$rpt]",
350 "Sharp routing Protocol\n"
351 "install some routes\n"
352 "Routes to install\n"
353 "The vrf we would like to install into if non-default\n"
354 "The NAME of the vrf\n"
355 "v4 Address to start /32 generation at\n"
356 "v6 Address to start /32 generation at\n"
357 "Nexthop-seg6 to use\n"
358 "V6 Nexthop address to use\n"
359 "Encap mode\n"
360 "Segment List to use\n"
361 "How many to create\n"
362 "Should we repeat this command\n"
363 "How many times to repeat this command\n")
364{
365 struct vrf *vrf;
366 struct prefix prefix;
367 uint32_t route_flags = 0;
368
369 sg.r.total_routes = routes;
370 sg.r.installed_routes = 0;
371
372 if (rpt >= 2)
373 sg.r.repeat = rpt * 2;
374 else
375 sg.r.repeat = 0;
376
377 memset(&prefix, 0, sizeof(prefix));
378 memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
877682e3
CS
379 nexthop_del_srv6_seg6local(&sg.r.nhop);
380 nexthop_del_srv6_seg6(&sg.r.nhop);
1cb131ee
HS
381 memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
382 memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
383 memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
384 memset(&sg.r.backup_nhop_group, 0, sizeof(sg.r.nhop_group));
385 sg.r.opaque[0] = '\0';
386 sg.r.inst = 0;
387
388 if (start4.s_addr != INADDR_ANY) {
389 prefix.family = AF_INET;
12256b84 390 prefix.prefixlen = IPV4_MAX_BITLEN;
1cb131ee
HS
391 prefix.u.prefix4 = start4;
392 } else {
393 prefix.family = AF_INET6;
13ccce6e 394 prefix.prefixlen = IPV6_MAX_BITLEN;
1cb131ee
HS
395 prefix.u.prefix6 = start6;
396 }
397 sg.r.orig_prefix = prefix;
398
399 if (!vrf_name)
400 vrf_name = VRF_DEFAULT_NAME;
401
402 vrf = vrf_lookup_by_name(vrf_name);
403 if (!vrf) {
404 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
405 vrf_name);
406 return CMD_WARNING;
407 }
408
409 sg.r.nhop.type = NEXTHOP_TYPE_IPV6;
410 sg.r.nhop.gate.ipv6 = seg6_nh6;
411 sg.r.nhop.vrf_id = vrf->vrf_id;
412 sg.r.nhop_group.nexthop = &sg.r.nhop;
eab0f8f0 413 nexthop_add_srv6_seg6(&sg.r.nhop, &seg6_seg);
1cb131ee
HS
414
415 sg.r.vrf_id = vrf->vrf_id;
416 sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, 0,
417 &sg.r.nhop_group, &sg.r.backup_nhop_group,
418 routes, route_flags, sg.r.opaque);
419
420 return CMD_SUCCESS;
421}
422
423DEFPY (install_seg6local_routes,
424 install_seg6local_routes_cmd,
425 "sharp install seg6local-routes [vrf NAME$vrf_name]\
426 X:X::X:X$start6\
427 nexthop-seg6local NAME$seg6l_oif\
428 <End$seg6l_end|\
429 End_X$seg6l_endx X:X::X:X$seg6l_endx_nh6|\
430 End_T$seg6l_endt (1-4294967295)$seg6l_endt_table|\
431 End_DX4$seg6l_enddx4 A.B.C.D$seg6l_enddx4_nh4|\
478d592e 432 End_DT6$seg6l_enddt6 (1-4294967295)$seg6l_enddt6_table|\
6c2e67be
CS
433 End_DT4$seg6l_enddt4 (1-4294967295)$seg6l_enddt4_table|\
434 End_DT46$seg6l_enddt46 (1-4294967295)$seg6l_enddt46_table>\
1cb131ee
HS
435 (1-1000000)$routes [repeat (2-1000)$rpt]",
436 "Sharp routing Protocol\n"
437 "install some routes\n"
438 "Routes to install\n"
439 "The vrf we would like to install into if non-default\n"
440 "The NAME of the vrf\n"
441 "v6 Address to start /32 generation at\n"
442 "Nexthop-seg6local to use\n"
443 "Output device to use\n"
444 "SRv6 End function to use\n"
445 "SRv6 End.X function to use\n"
446 "V6 Nexthop address to use\n"
447 "SRv6 End.T function to use\n"
448 "Redirect table id to use\n"
449 "SRv6 End.DX4 function to use\n"
450 "V4 Nexthop address to use\n"
451 "SRv6 End.DT6 function to use\n"
452 "Redirect table id to use\n"
478d592e
RS
453 "SRv6 End.DT4 function to use\n"
454 "Redirect table id to use\n"
6c2e67be
CS
455 "SRv6 End.DT46 function to use\n"
456 "Redirect table id to use\n"
1cb131ee
HS
457 "How many to create\n"
458 "Should we repeat this command\n"
459 "How many times to repeat this command\n")
460{
461 struct vrf *vrf;
462 uint32_t route_flags = 0;
463 struct seg6local_context ctx = {};
464 enum seg6local_action_t action;
465
466 sg.r.total_routes = routes;
467 sg.r.installed_routes = 0;
468
469 if (rpt >= 2)
470 sg.r.repeat = rpt * 2;
471 else
472 sg.r.repeat = 0;
473
474 memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
877682e3
CS
475 nexthop_del_srv6_seg6local(&sg.r.nhop);
476 nexthop_del_srv6_seg6(&sg.r.nhop);
1cb131ee
HS
477 memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
478 memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
479 memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
480 memset(&sg.r.backup_nhop_group, 0, sizeof(sg.r.nhop_group));
481 sg.r.opaque[0] = '\0';
482 sg.r.inst = 0;
483 sg.r.orig_prefix.family = AF_INET6;
484 sg.r.orig_prefix.prefixlen = 128;
485 sg.r.orig_prefix.u.prefix6 = start6;
486
487 if (!vrf_name)
488 vrf_name = VRF_DEFAULT_NAME;
489
490 vrf = vrf_lookup_by_name(vrf_name);
491 if (!vrf) {
492 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
493 vrf_name);
494 return CMD_WARNING;
495 }
496
497 if (seg6l_enddx4) {
498 action = ZEBRA_SEG6_LOCAL_ACTION_END_DX4;
499 ctx.nh4 = seg6l_enddx4_nh4;
500 } else if (seg6l_endx) {
501 action = ZEBRA_SEG6_LOCAL_ACTION_END_X;
502 ctx.nh6 = seg6l_endx_nh6;
503 } else if (seg6l_endt) {
504 action = ZEBRA_SEG6_LOCAL_ACTION_END_T;
505 ctx.table = seg6l_endt_table;
506 } else if (seg6l_enddt6) {
507 action = ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
508 ctx.table = seg6l_enddt6_table;
478d592e
RS
509 } else if (seg6l_enddt4) {
510 action = ZEBRA_SEG6_LOCAL_ACTION_END_DT4;
511 ctx.table = seg6l_enddt4_table;
6c2e67be
CS
512 } else if (seg6l_enddt46) {
513 action = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
514 ctx.table = seg6l_enddt46_table;
1cb131ee
HS
515 } else {
516 action = ZEBRA_SEG6_LOCAL_ACTION_END;
517 }
518
519 sg.r.nhop.type = NEXTHOP_TYPE_IFINDEX;
520 sg.r.nhop.ifindex = ifname2ifindex(seg6l_oif, vrf->vrf_id);
521 sg.r.nhop.vrf_id = vrf->vrf_id;
522 sg.r.nhop_group.nexthop = &sg.r.nhop;
eab0f8f0 523 nexthop_add_srv6_seg6local(&sg.r.nhop, action, &ctx);
1cb131ee
HS
524
525 sg.r.vrf_id = vrf->vrf_id;
2ba6be5b
HS
526 sharp_install_routes_helper(&sg.r.orig_prefix, sg.r.vrf_id, sg.r.inst,
527 0, &sg.r.nhop_group,
528 &sg.r.backup_nhop_group, routes,
529 route_flags, sg.r.opaque);
8a71d93d
DS
530
531 return CMD_SUCCESS;
532}
533
42567e00 534DEFPY(vrf_label, vrf_label_cmd,
e429a2a0 535 "sharp label <ip$ipv4|ipv6$ipv6> vrf NAME$vrf_name label (0-100000)$label",
75239f4f 536 "Sharp Routing Protocol\n"
ab18a495 537 "Give a vrf a label\n"
7d061b3c
DS
538 "Pop and forward for IPv4\n"
539 "Pop and forward for IPv6\n"
ab18a495 540 VRF_CMD_HELP_STR
42567e00 541 "The label to use, 0 specifies remove the label installed from previous\n"
ab18a495
DS
542 "Specified range to use\n")
543{
544 struct vrf *vrf;
7d061b3c 545 afi_t afi = (ipv4) ? AFI_IP : AFI_IP6;
ab18a495 546
e429a2a0 547 if (strcmp(vrf_name, "default") == 0)
ab18a495
DS
548 vrf = vrf_lookup_by_id(VRF_DEFAULT);
549 else
e429a2a0 550 vrf = vrf_lookup_by_name(vrf_name);
ab18a495
DS
551
552 if (!vrf) {
4d4c404b 553 vty_out(vty, "Unable to find vrf you silly head\n");
ab18a495
DS
554 return CMD_WARNING_CONFIG_FAILED;
555 }
556
42567e00
DS
557 if (label == 0)
558 label = MPLS_LABEL_NONE;
559
7d061b3c 560 vrf_label_add(vrf->vrf_id, afi, label);
ab18a495
DS
561 return CMD_SUCCESS;
562}
563
8a71d93d
DS
564DEFPY (remove_routes,
565 remove_routes_cmd,
e429a2a0 566 "sharp remove routes [vrf NAME$vrf_name] <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]",
75239f4f 567 "Sharp Routing Protocol\n"
8a71d93d
DS
568 "Remove some routes\n"
569 "Routes to remove\n"
4a7d4737
DS
570 "The vrf we would like to remove from if non-default\n"
571 "The NAME of the vrf\n"
e310fc19
DS
572 "v4 Starting spot\n"
573 "v6 Starting spot\n"
574 "Routes to uninstall\n"
ae252c02
DS
575 "instance to use\n"
576 "Value of instance\n")
8a71d93d 577{
4a7d4737 578 struct vrf *vrf;
547dc642
DS
579 struct prefix prefix;
580
581 sg.r.total_routes = routes;
582 sg.r.removed_routes = 0;
583 uint32_t rts;
8a71d93d 584
b939f6ff 585 memset(&prefix, 0, sizeof(prefix));
8a71d93d 586
3a6290bd 587 if (start4.s_addr != INADDR_ANY) {
dbc1bf46 588 prefix.family = AF_INET;
12256b84 589 prefix.prefixlen = IPV4_MAX_BITLEN;
dbc1bf46
DS
590 prefix.u.prefix4 = start4;
591 } else {
592 prefix.family = AF_INET6;
13ccce6e 593 prefix.prefixlen = IPV6_MAX_BITLEN;
dbc1bf46
DS
594 prefix.u.prefix6 = start6;
595 }
8a71d93d 596
e429a2a0 597 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
4a7d4737
DS
598 if (!vrf) {
599 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
e429a2a0 600 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
4a7d4737
DS
601 return CMD_WARNING;
602 }
603
547dc642 604 sg.r.inst = instance;
4a7d4737 605 sg.r.vrf_id = vrf->vrf_id;
b939f6ff 606 rts = routes;
0cf08685
DS
607 sharp_remove_routes_helper(&prefix, sg.r.vrf_id,
608 sg.r.inst, rts);
8a71d93d
DS
609
610 return CMD_SUCCESS;
611}
612
aaf8c96f
DS
613DEFUN_NOSH (show_debugging_sharpd,
614 show_debugging_sharpd_cmd,
615 "show debugging [sharp]",
616 SHOW_STR
617 DEBUG_STR
618 "Sharp Information\n")
619{
c9e5adba 620 vty_out(vty, "Sharp debugging status:\n");
aaf8c96f 621
cf00164b
DS
622 cmd_show_lib_debugs(vty);
623
aaf8c96f
DS
624 return CMD_SUCCESS;
625}
626
faa75dfa
MS
627DEFPY (sharp_lsp_prefix_v4, sharp_lsp_prefix_v4_cmd,
628 "sharp lsp [update]$update (0-100000)$inlabel\
c9e5adba
MS
629 nexthop-group NHGNAME$nhgname\
630 [prefix A.B.C.D/M$pfx\
4b0f6237 631 " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
faa75dfa
MS
632 "Sharp Routing Protocol\n"
633 "Add an LSP\n"
634 "Update an LSP\n"
635 "The ingress label to use\n"
636 "Use nexthops from a nexthop-group\n"
637 "The nexthop-group name\n"
638 "Label a prefix\n"
639 "The v4 prefix to label\n"
640 FRR_IP_REDIST_HELP_STR_ZEBRA
641 "Instance to use\n"
642 "Instance\n")
c9e5adba
MS
643{
644 struct nexthop_group_cmd *nhgc = NULL;
665edffd
MS
645 struct nexthop_group_cmd *backup_nhgc = NULL;
646 struct nexthop_group *backup_nhg = NULL;
c9e5adba
MS
647 struct prefix p = {};
648 int type = 0;
faa75dfa
MS
649 bool update_p;
650
651 update_p = (update != NULL);
c9e5adba
MS
652
653 /* We're offered a v4 prefix */
654 if (pfx->family > 0 && type_str) {
655 p.family = pfx->family;
656 p.prefixlen = pfx->prefixlen;
657 p.u.prefix4 = pfx->prefix;
658
659 type = proto_redistnum(AFI_IP, type_str);
660 if (type < 0) {
661 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
662 return CMD_WARNING;
663 }
664 } else if (pfx->family > 0 || type_str) {
665 vty_out(vty, "%% Must supply both prefix and type\n");
666 return CMD_WARNING;
667 }
668
669 nhgc = nhgc_find(nhgname);
670 if (!nhgc) {
671 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
672 nhgname);
673 return CMD_WARNING;
674 }
675
676 if (nhgc->nhg.nexthop == NULL) {
677 vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname);
678 return CMD_WARNING;
679 }
680
665edffd
MS
681 /* Use group's backup nexthop info if present */
682 if (nhgc->backup_list_name[0]) {
683 backup_nhgc = nhgc_find(nhgc->backup_list_name);
684
685 if (!backup_nhgc) {
686 vty_out(vty,
687 "%% Backup group %s not found for group %s\n",
688 nhgc->backup_list_name,
689 nhgname);
690 return CMD_WARNING;
691 }
692 backup_nhg = &(backup_nhgc->nhg);
693 }
694
faa75dfa
MS
695 if (sharp_install_lsps_helper(true /*install*/, update_p,
696 pfx->family > 0 ? &p : NULL,
c9e5adba 697 type, instance, inlabel,
665edffd 698 &(nhgc->nhg), backup_nhg) == 0)
c9e5adba
MS
699 return CMD_SUCCESS;
700 else {
701 vty_out(vty, "%% LSP install failed!\n");
702 return CMD_WARNING;
703 }
704}
705
706DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd,
707 "sharp remove lsp \
708 (0-100000)$inlabel\
665edffd 709 [nexthop-group NHGNAME$nhgname] \
c9e5adba 710 [prefix A.B.C.D/M$pfx\
20c9e649 711 " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
c9e5adba
MS
712 "Sharp Routing Protocol\n"
713 "Remove data\n"
714 "Remove an LSP\n"
715 "The ingress label\n"
716 "Use nexthops from a nexthop-group\n"
717 "The nexthop-group name\n"
718 "Specify a v4 prefix\n"
719 "The v4 prefix to label\n"
20c9e649 720 FRR_IP_REDIST_HELP_STR_ZEBRA
c9e5adba
MS
721 "Routing instance\n"
722 "Instance to use\n")
723{
724 struct nexthop_group_cmd *nhgc = NULL;
725 struct prefix p = {};
726 int type = 0;
665edffd 727 struct nexthop_group *nhg = NULL;
c9e5adba
MS
728
729 /* We're offered a v4 prefix */
730 if (pfx->family > 0 && type_str) {
731 p.family = pfx->family;
732 p.prefixlen = pfx->prefixlen;
733 p.u.prefix4 = pfx->prefix;
734
735 type = proto_redistnum(AFI_IP, type_str);
736 if (type < 0) {
737 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
738 return CMD_WARNING;
739 }
740 } else if (pfx->family > 0 || type_str) {
741 vty_out(vty, "%% Must supply both prefix and type\n");
742 return CMD_WARNING;
743 }
744
665edffd
MS
745 if (nhgname) {
746 nhgc = nhgc_find(nhgname);
747 if (!nhgc) {
748 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
749 nhgname);
750 return CMD_WARNING;
751 }
c9e5adba 752
665edffd
MS
753 if (nhgc->nhg.nexthop == NULL) {
754 vty_out(vty, "%% Nexthop-group '%s' is empty\n",
755 nhgname);
756 return CMD_WARNING;
757 }
758 nhg = &(nhgc->nhg);
c9e5adba
MS
759 }
760
faa75dfa
MS
761 if (sharp_install_lsps_helper(false /*!install*/, false,
762 pfx->family > 0 ? &p : NULL,
665edffd 763 type, instance, inlabel, nhg, NULL) == 0)
c9e5adba
MS
764 return CMD_SUCCESS;
765 else {
766 vty_out(vty, "%% LSP remove failed!\n");
767 return CMD_WARNING;
768 }
769}
770
aef4a13f
DL
771DEFPY (logpump,
772 logpump_cmd,
773 "sharp logpump duration (1-60) frequency (1-1000000) burst (1-1000)",
774 "Sharp Routing Protocol\n"
775 "Generate bulk log messages for testing\n"
776 "Duration of run (s)\n"
777 "Duration of run (s)\n"
778 "Frequency of bursts (s^-1)\n"
779 "Frequency of bursts (s^-1)\n"
780 "Number of log messages per each burst\n"
781 "Number of log messages per each burst\n")
782{
783 sharp_logpump_run(vty, duration, frequency, burst);
784 return CMD_SUCCESS;
785}
786
2be4d61a
MS
787DEFPY (create_session,
788 create_session_cmd,
789 "sharp create session (1-1024)",
790 "Sharp Routing Protocol\n"
791 "Create data\n"
792 "Create a test session\n"
793 "Session ID\n")
794{
795 if (sharp_zclient_create(session) != 0) {
796 vty_out(vty, "%% Client session error\n");
797 return CMD_WARNING;
798 }
799
800 return CMD_SUCCESS;
801}
802
803DEFPY (remove_session,
804 remove_session_cmd,
805 "sharp remove session (1-1024)",
806 "Sharp Routing Protocol\n"
807 "Remove data\n"
808 "Remove a test session\n"
809 "Session ID\n")
810{
811 sharp_zclient_delete(session);
812 return CMD_SUCCESS;
813}
814
2ac6c90d
MS
815DEFPY (send_opaque,
816 send_opaque_cmd,
817 "sharp send opaque type (1-255) (1-1000)$count",
478ff17b 818 SHARP_STR
2ac6c90d
MS
819 "Send messages for testing\n"
820 "Send opaque messages\n"
821 "Type code to send\n"
822 "Type code to send\n"
823 "Number of messages to send\n")
824{
c8b27f2a
MS
825 sharp_opaque_send(type, 0, 0, 0, count);
826 return CMD_SUCCESS;
827}
828
829DEFPY (send_opaque_unicast,
830 send_opaque_unicast_cmd,
831 "sharp send opaque unicast type (1-255) \
832 " FRR_IP_REDIST_STR_ZEBRA "$proto_str \
833 [{instance (0-1000) | session (1-1000)}] (1-1000)$count",
834 SHARP_STR
835 "Send messages for testing\n"
836 "Send opaque messages\n"
837 "Send unicast messages\n"
838 "Type code to send\n"
839 "Type code to send\n"
840 FRR_IP_REDIST_HELP_STR_ZEBRA
841 "Daemon instance\n"
842 "Daemon instance\n"
843 "Session ID\n"
844 "Session ID\n"
845 "Number of messages to send\n")
846{
847 uint32_t proto;
848
849 proto = proto_redistnum(AFI_IP, proto_str);
850
851 sharp_opaque_send(type, proto, instance, session, count);
852
2ac6c90d
MS
853 return CMD_SUCCESS;
854}
855
939b2339
MS
856DEFPY (send_opaque_reg,
857 send_opaque_reg_cmd,
858 "sharp send opaque <reg$reg | unreg> \
859 " FRR_IP_REDIST_STR_ZEBRA "$proto_str \
860 [{instance (0-1000) | session (1-1000)}] type (1-1000)",
478ff17b 861 SHARP_STR
939b2339
MS
862 "Send messages for testing\n"
863 "Send opaque messages\n"
864 "Send opaque registration\n"
865 "Send opaque unregistration\n"
866 FRR_IP_REDIST_HELP_STR_ZEBRA
867 "Daemon instance\n"
868 "Daemon instance\n"
869 "Session ID\n"
870 "Session ID\n"
871 "Opaque sub-type code\n"
872 "Opaque sub-type code\n")
873{
874 int proto;
875
876 proto = proto_redistnum(AFI_IP, proto_str);
877
878 sharp_opaque_reg_send((reg != NULL), proto, instance, session, type);
879 return CMD_SUCCESS;
880}
881
da187b77
JU
882DEFPY (neigh_discover,
883 neigh_discover_cmd,
884 "sharp neigh discover [vrf NAME$vrf_name] <A.B.C.D$dst4|X:X::X:X$dst6> IFNAME$ifname",
885 SHARP_STR
886 "Discover neighbours\n"
887 "Send an ARP/NDP request\n"
888 VRF_CMD_HELP_STR
889 "v4 Destination address\n"
890 "v6 Destination address\n"
891 "Interface name\n")
892{
893 struct vrf *vrf;
894 struct interface *ifp;
895 struct prefix prefix;
896
897 memset(&prefix, 0, sizeof(prefix));
898
3a6290bd 899 if (dst4.s_addr != INADDR_ANY) {
da187b77 900 prefix.family = AF_INET;
12256b84 901 prefix.prefixlen = IPV4_MAX_BITLEN;
da187b77
JU
902 prefix.u.prefix4 = dst4;
903 } else {
904 prefix.family = AF_INET6;
905 prefix.prefixlen = 128;
906 prefix.u.prefix6 = dst6;
907 }
908
909 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
910 if (!vrf) {
911 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
912 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
913 return CMD_WARNING;
914 }
915
916 ifp = if_lookup_by_name_vrf(ifname, vrf);
917 if (ifp == NULL) {
918 vty_out(vty, "%% Can't find interface %s\n", ifname);
919 return CMD_WARNING;
920 }
921
922 sharp_zebra_send_arp(ifp, &prefix);
923
924 return CMD_SUCCESS;
925}
926
1888e243
OD
927DEFPY (import_te,
928 import_te_cmd,
929 "sharp import-te",
930 SHARP_STR
931 "Import Traffic Engineering\n")
932{
933 sg.ted = ls_ted_new(1, "Sharp", 0);
934 sharp_zebra_register_te();
935
936 return CMD_SUCCESS;
937}
938
6dece5ac
CS
939static void sharp_srv6_locator_chunk_free(struct prefix_ipv6 *chunk)
940{
941 prefix_ipv6_free((struct prefix_ipv6 **)&chunk);
942}
943
ade3eebc
HS
944DEFPY (sharp_srv6_manager_get_locator_chunk,
945 sharp_srv6_manager_get_locator_chunk_cmd,
946 "sharp srv6-manager get-locator-chunk NAME$locator_name",
947 SHARP_STR
948 "Segment-Routing IPv6\n"
949 "Get SRv6 locator-chunk\n"
950 "SRv6 Locator name\n")
951{
952 int ret;
953 struct listnode *node;
954 struct sharp_srv6_locator *loc;
955 struct sharp_srv6_locator *loc_found = NULL;
956
957 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, node, loc)) {
958 if (strcmp(loc->name, locator_name))
959 continue;
960 loc_found = loc;
961 break;
962 }
963 if (!loc_found) {
964 loc = XCALLOC(MTYPE_SRV6_LOCATOR,
965 sizeof(struct sharp_srv6_locator));
966 loc->chunks = list_new();
6dece5ac
CS
967 loc->chunks->del =
968 (void (*)(void *))sharp_srv6_locator_chunk_free;
ade3eebc
HS
969 snprintf(loc->name, SRV6_LOCNAME_SIZE, "%s", locator_name);
970 listnode_add(sg.srv6_locators, loc);
971 }
972
973 ret = sharp_zebra_srv6_manager_get_locator_chunk(locator_name);
974 if (ret < 0)
975 return CMD_WARNING_CONFIG_FAILED;
976
977 return CMD_SUCCESS;
978}
979
1888e243
OD
980DEFUN (show_sharp_ted,
981 show_sharp_ted_cmd,
982 "show sharp ted [<vertex [A.B.C.D]|edge [A.B.C.D]|subnet [A.B.C.D/M]>] [verbose|json]",
983 SHOW_STR
984 SHARP_STR
985 "Traffic Engineering Database\n"
986 "MPLS-TE Vertex\n"
987 "MPLS-TE router ID (as an IP address)\n"
988 "MPLS-TE Edge\n"
989 "MPLS-TE Edge ID (as an IP address)\n"
990 "MPLS-TE Subnet\n"
991 "MPLS-TE Subnet ID (as an IP prefix)\n"
992 "Verbose output\n"
993 JSON_STR)
994{
995 int idx = 0;
996 struct in_addr ip_addr;
997 struct prefix pref;
998 struct ls_vertex *vertex;
999 struct ls_edge *edge;
1000 struct ls_subnet *subnet;
1001 uint64_t key;
1002 bool verbose = false;
1003 bool uj = use_json(argc, argv);
1004 json_object *json = NULL;
1005
1006 if (sg.ted == NULL) {
1007 vty_out(vty, "MPLS-TE import is not enabled\n");
1008 return CMD_WARNING;
1009 }
1010
1011 if (uj)
1012 json = json_object_new_object();
1013
1014 if (argv[argc - 1]->arg && strmatch(argv[argc - 1]->text, "verbose"))
1015 verbose = true;
1016
1017 if (argv_find(argv, argc, "vertex", &idx)) {
1018 /* Show Vertex */
1019 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
1020 if (!inet_aton(argv[idx + 1]->arg, &ip_addr)) {
1021 vty_out(vty,
1022 "Specified Router ID %s is invalid\n",
1023 argv[idx + 1]->arg);
1024 return CMD_WARNING_CONFIG_FAILED;
1025 }
1026 /* Get the Vertex from the Link State Database */
1027 key = ((uint64_t)ip_addr.s_addr) & 0xffffffff;
1028 vertex = ls_find_vertex_by_key(sg.ted, key);
1029 if (!vertex) {
1030 vty_out(vty, "No vertex found for ID %pI4\n",
1031 &ip_addr);
1032 return CMD_WARNING;
1033 }
1034 } else
1035 vertex = NULL;
1036
1037 if (vertex)
1038 ls_show_vertex(vertex, vty, json, verbose);
1039 else
1040 ls_show_vertices(sg.ted, vty, json, verbose);
1041
1042 } else if (argv_find(argv, argc, "edge", &idx)) {
1043 /* Show Edge */
1044 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
1045 if (!inet_aton(argv[idx]->arg, &ip_addr)) {
1046 vty_out(vty,
1047 "Specified Edge ID %s is invalid\n",
1048 argv[idx]->arg);
1049 return CMD_WARNING_CONFIG_FAILED;
1050 }
1051 /* Get the Edge from the Link State Database */
1052 key = ((uint64_t)ip_addr.s_addr) & 0xffffffff;
1053 edge = ls_find_edge_by_key(sg.ted, key);
1054 if (!edge) {
1055 vty_out(vty, "No edge found for ID %pI4\n",
1056 &ip_addr);
1057 return CMD_WARNING;
1058 }
1059 } else
1060 edge = NULL;
1061
1062 if (edge)
1063 ls_show_edge(edge, vty, json, verbose);
1064 else
1065 ls_show_edges(sg.ted, vty, json, verbose);
1066
1067 } else if (argv_find(argv, argc, "subnet", &idx)) {
1068 /* Show Subnet */
1069 if (argv_find(argv, argc, "A.B.C.D/M", &idx)) {
1070 if (!str2prefix(argv[idx]->arg, &pref)) {
1071 vty_out(vty, "Invalid prefix format %s\n",
1072 argv[idx]->arg);
1073 return CMD_WARNING_CONFIG_FAILED;
1074 }
1075 /* Get the Subnet from the Link State Database */
1076 subnet = ls_find_subnet(sg.ted, pref);
1077 if (!subnet) {
1078 vty_out(vty, "No subnet found for ID %pFX\n",
1079 &pref);
1080 return CMD_WARNING;
1081 }
1082 } else
1083 subnet = NULL;
1084
1085 if (subnet)
1086 ls_show_subnet(subnet, vty, json, verbose);
1087 else
1088 ls_show_subnets(sg.ted, vty, json, verbose);
1089
1090 } else {
1091 /* Show the complete TED */
1092 ls_show_ted(sg.ted, vty, json, verbose);
1093 }
1094
c48349e3 1095 if (uj)
7297350e 1096 vty_json(vty, json);
ade3eebc
HS
1097
1098 return CMD_SUCCESS;
1099}
1100
1101DEFPY (sharp_srv6_manager_release_locator_chunk,
1102 sharp_srv6_manager_release_locator_chunk_cmd,
1103 "sharp srv6-manager release-locator-chunk NAME$locator_name",
1104 SHARP_STR
1105 "Segment-Routing IPv6\n"
1106 "Release SRv6 locator-chunk\n"
1107 "SRv6 Locator name\n")
1108{
1109 int ret;
1110 struct listnode *loc_node;
1111 struct sharp_srv6_locator *loc;
1112
1113 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, loc_node, loc)) {
1114 if (!strcmp(loc->name, locator_name)) {
1115 list_delete_all_node(loc->chunks);
1116 list_delete(&loc->chunks);
1117 listnode_delete(sg.srv6_locators, loc);
a0c47583 1118 XFREE(MTYPE_SRV6_LOCATOR, loc);
ade3eebc
HS
1119 break;
1120 }
1121 }
1122
1123 ret = sharp_zebra_srv6_manager_release_locator_chunk(locator_name);
1124 if (ret < 0)
1125 return CMD_WARNING_CONFIG_FAILED;
1126
1127 return CMD_SUCCESS;
1128}
1129
1130DEFPY (show_sharp_segment_routing_srv6,
1131 show_sharp_segment_routing_srv6_cmd,
a2df1e4f 1132 "show sharp segment-routing srv6 [json]",
ade3eebc
HS
1133 SHOW_STR
1134 SHARP_STR
1135 "Segment-Routing\n"
a2df1e4f
HS
1136 "Segment-Routing IPv6\n"
1137 JSON_STR)
ade3eebc
HS
1138{
1139 char str[256];
1140 struct listnode *loc_node;
1141 struct listnode *chunk_node;
1142 struct sharp_srv6_locator *loc;
1143 struct prefix_ipv6 *chunk;
a2df1e4f 1144 bool uj = use_json(argc, argv);
ade3eebc
HS
1145 json_object *jo_locs = NULL;
1146 json_object *jo_loc = NULL;
1147 json_object *jo_chunks = NULL;
1148
a2df1e4f
HS
1149 if (uj) {
1150 jo_locs = json_object_new_array();
1151 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, loc_node, loc)) {
1152 jo_loc = json_object_new_object();
1153 json_object_array_add(jo_locs, jo_loc);
1154 json_object_string_add(jo_loc, "name", loc->name);
1155 jo_chunks = json_object_new_array();
1156 json_object_object_add(jo_loc, "chunks", jo_chunks);
1157 for (ALL_LIST_ELEMENTS_RO(loc->chunks, chunk_node,
1158 chunk)) {
1159 prefix2str(chunk, str, sizeof(str));
1160 json_array_string_add(jo_chunks, str);
1161 }
1162 }
1163
7297350e 1164 vty_json(vty, jo_locs);
a2df1e4f
HS
1165 } else {
1166 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, loc_node, loc)) {
1167 vty_out(vty, "Locator %s has %d prefix chunks\n",
1168 loc->name, listcount(loc->chunks));
1169 for (ALL_LIST_ELEMENTS_RO(loc->chunks, chunk_node,
1170 chunk)) {
1171 prefix2str(chunk, str, sizeof(str));
1172 vty_out(vty, " %s\n", str);
1173 }
1174 vty_out(vty, "\n");
ade3eebc
HS
1175 }
1176 }
1177
1888e243
OD
1178 return CMD_SUCCESS;
1179}
1180
621fb5f3
OD
1181DEFPY (show_sharp_cspf,
1182 show_sharp_cspf_cmd,
1183 "show sharp cspf source <A.B.C.D$src4|X:X::X:X$src6> \
1184 destination <A.B.C.D$dst4|X:X::X:X$dst6> \
1185 <metric|te-metric|delay> (0-16777215)$cost \
1186 [rsv-bw (0-7)$cos BANDWIDTH$bw]",
1187 SHOW_STR
1188 SHARP_STR
1189 "Constraint Shortest Path First path computation\n"
1190 "Source of the path\n"
1191 "IPv4 Source address in dot decimal A.B.C.D\n"
1192 "IPv6 Source address as X:X:X:X\n"
1193 "Destination of the path\n"
1194 "IPv4 Destination address in dot decimal A.B.C.D\n"
1195 "IPv6 Destination address as X:X:X:X\n"
1196 "Maximum Metric\n"
1197 "Maximum TE Metric\n"
1198 "Maxim Delay\n"
1199 "Value of Maximum cost\n"
1200 "Reserved Bandwidth of this path\n"
1201 "Class of Service or Priority level\n"
1202 "Bytes/second (IEEE floating point format)\n")
1203{
1204
1205 struct cspf *algo;
1206 struct constraints csts;
1207 struct c_path *path;
1208 struct listnode *node;
1209 struct ls_edge *edge;
1210 int idx;
1211
1212 if (sg.ted == NULL) {
1213 vty_out(vty, "MPLS-TE import is not enabled\n");
1214 return CMD_WARNING;
1215 }
1216
1217 if ((src4.s_addr != INADDR_ANY && dst4.s_addr == INADDR_ANY) ||
1218 (src4.s_addr == INADDR_ANY && dst4.s_addr != INADDR_ANY)) {
1219 vty_out(vty, "Don't mix IPv4 and IPv6 addresses\n");
1220 return CMD_WARNING;
1221 }
1222
1223 idx = 6;
1224 memset(&csts, 0, sizeof(struct constraints));
1225 if (argv_find(argv, argc, "metric", &idx)) {
1226 csts.ctype = CSPF_METRIC;
1227 csts.cost = cost;
1228 }
1229 idx = 6;
1230 if (argv_find(argv, argc, "te-metric", &idx)) {
1231 csts.ctype = CSPF_TE_METRIC;
1232 csts.cost = cost;
1233 }
1234 idx = 6;
1235 if (argv_find(argv, argc, "delay", &idx)) {
1236 csts.ctype = CSPF_DELAY;
1237 csts.cost = cost;
1238 }
1239 if (argc > 9) {
1240 if (sscanf(bw, "%g", &csts.bw) != 1) {
1241 vty_out(vty, "Bandwidth constraints: fscanf: %s\n",
1242 safe_strerror(errno));
1243 return CMD_WARNING_CONFIG_FAILED;
1244 }
1245 csts.cos = cos;
1246 }
1247
1248 /* Initialize and call point-to-point Path computation */
1249 if (src4.s_addr != INADDR_ANY)
1250 algo = cspf_init_v4(NULL, sg.ted, src4, dst4, &csts);
1251 else
1252 algo = cspf_init_v6(NULL, sg.ted, src6, dst6, &csts);
1253 path = compute_p2p_path(algo, sg.ted);
1254 cspf_del(algo);
1255
1256 if (!path) {
1257 vty_out(vty, "Path computation failed without error\n");
1258 return CMD_SUCCESS;
1259 }
1260 if (path->status != SUCCESS) {
1261 vty_out(vty, "Path computation failed: %d\n", path->status);
1262 return CMD_SUCCESS;
1263 }
1264
1265 vty_out(vty, "Path computation success\n");
1266 vty_out(vty, "\tCost: %d\n", path->weight);
1267 vty_out(vty, "\tEdges:");
1268 for (ALL_LIST_ELEMENTS_RO(path->edges, node, edge)) {
1269 if (src4.s_addr != INADDR_ANY)
1270 vty_out(vty, " %pI4",
1271 &edge->attributes->standard.remote);
1272 else
1273 vty_out(vty, " %pI6",
1274 &edge->attributes->standard.remote6);
1275 }
1276 vty_out(vty, "\n");
1277
1278 return CMD_SUCCESS;
1279}
1280
f9a1140c
SW
1281static struct interface *if_lookup_vrf_all(const char *ifname)
1282{
1283 struct interface *ifp;
1284 struct vrf *vrf;
1285
1286 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
1287 ifp = if_lookup_by_name(ifname, vrf->vrf_id);
1288 if (ifp)
1289 return ifp;
1290 }
1291
1292 return NULL;
1293}
1294
1295DEFPY (sharp_interface_protodown,
1296 sharp_interface_protodown_cmd,
1297 "sharp interface IFNAME$ifname protodown",
1298 SHARP_STR
1299 INTERFACE_STR
1300 IFNAME_STR
1301 "Set interface protodown\n")
1302{
1303 struct interface *ifp;
1304
1305 ifp = if_lookup_vrf_all(ifname);
1306
1307 if (!ifp) {
1308 vty_out(vty, "%% Can't find interface %s\n", ifname);
1309 return CMD_WARNING;
1310 }
1311
1312 if (sharp_zebra_send_interface_protodown(ifp, true) != 0)
1313 return CMD_WARNING;
1314
1315 return CMD_SUCCESS;
1316}
1317
1318DEFPY (no_sharp_interface_protodown,
1319 no_sharp_interface_protodown_cmd,
1320 "no sharp interface IFNAME$ifname protodown",
1321 NO_STR
1322 SHARP_STR
1323 INTERFACE_STR
1324 IFNAME_STR
1325 "Set interface protodown\n")
1326{
1327 struct interface *ifp;
1328
1329 ifp = if_lookup_vrf_all(ifname);
1330
1331 if (!ifp) {
1332 vty_out(vty, "%% Can't find interface %s\n", ifname);
1333 return CMD_WARNING;
1334 }
1335
1336 if (sharp_zebra_send_interface_protodown(ifp, false) != 0)
1337 return CMD_WARNING;
1338
1339 return CMD_SUCCESS;
1340}
1341
8a71d93d
DS
1342void sharp_vty_init(void)
1343{
f59e6418 1344 install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
8a71d93d 1345 install_element(ENABLE_NODE, &install_routes_cmd);
1cb131ee
HS
1346 install_element(ENABLE_NODE, &install_seg6_routes_cmd);
1347 install_element(ENABLE_NODE, &install_seg6local_routes_cmd);
8a71d93d 1348 install_element(ENABLE_NODE, &remove_routes_cmd);
ab18a495 1349 install_element(ENABLE_NODE, &vrf_label_cmd);
86da53ab 1350 install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);
921af54d 1351 install_element(ENABLE_NODE, &watch_redistribute_cmd);
0ae8130d
DS
1352 install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
1353 install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
c9e5adba
MS
1354 install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
1355 install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
aef4a13f 1356 install_element(ENABLE_NODE, &logpump_cmd);
2be4d61a
MS
1357 install_element(ENABLE_NODE, &create_session_cmd);
1358 install_element(ENABLE_NODE, &remove_session_cmd);
2ac6c90d 1359 install_element(ENABLE_NODE, &send_opaque_cmd);
c8b27f2a 1360 install_element(ENABLE_NODE, &send_opaque_unicast_cmd);
939b2339 1361 install_element(ENABLE_NODE, &send_opaque_reg_cmd);
da187b77 1362 install_element(ENABLE_NODE, &neigh_discover_cmd);
1888e243 1363 install_element(ENABLE_NODE, &import_te_cmd);
aaf8c96f 1364
dd73744d 1365 install_element(ENABLE_NODE, &show_debugging_sharpd_cmd);
1888e243 1366 install_element(ENABLE_NODE, &show_sharp_ted_cmd);
621fb5f3 1367 install_element(ENABLE_NODE, &show_sharp_cspf_cmd);
aaf8c96f 1368
ade3eebc 1369 install_element(ENABLE_NODE, &sharp_srv6_manager_get_locator_chunk_cmd);
4df9d859
HS
1370 install_element(ENABLE_NODE,
1371 &sharp_srv6_manager_release_locator_chunk_cmd);
ade3eebc
HS
1372 install_element(ENABLE_NODE, &show_sharp_segment_routing_srv6_cmd);
1373
f9a1140c
SW
1374 install_element(ENABLE_NODE, &sharp_interface_protodown_cmd);
1375 install_element(ENABLE_NODE, &no_sharp_interface_protodown_cmd);
1376
8a71d93d
DS
1377 return;
1378}