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