]> git.proxmox.com Git - mirror_frr.git/blame - sharpd/sharp_vty.c
Merge pull request #13214 from chiragshah6/fdev2
[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;
988 bool verbose = false;
989 bool uj = use_json(argc, argv);
990 json_object *json = NULL;
991
992 if (sg.ted == NULL) {
993 vty_out(vty, "MPLS-TE import is not enabled\n");
994 return CMD_WARNING;
995 }
996
997 if (uj)
998 json = json_object_new_object();
999
1000 if (argv[argc - 1]->arg && strmatch(argv[argc - 1]->text, "verbose"))
1001 verbose = true;
1002
1003 if (argv_find(argv, argc, "vertex", &idx)) {
1004 /* Show Vertex */
1005 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
1006 if (!inet_aton(argv[idx + 1]->arg, &ip_addr)) {
1007 vty_out(vty,
1008 "Specified Router ID %s is invalid\n",
1009 argv[idx + 1]->arg);
1010 return CMD_WARNING_CONFIG_FAILED;
1011 }
1012 /* Get the Vertex from the Link State Database */
1013 key = ((uint64_t)ip_addr.s_addr) & 0xffffffff;
1014 vertex = ls_find_vertex_by_key(sg.ted, key);
1015 if (!vertex) {
1016 vty_out(vty, "No vertex found for ID %pI4\n",
1017 &ip_addr);
1018 return CMD_WARNING;
1019 }
1020 } else
1021 vertex = NULL;
1022
1023 if (vertex)
1024 ls_show_vertex(vertex, vty, json, verbose);
1025 else
1026 ls_show_vertices(sg.ted, vty, json, verbose);
1027
1028 } else if (argv_find(argv, argc, "edge", &idx)) {
1029 /* Show Edge */
1030 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
1031 if (!inet_aton(argv[idx]->arg, &ip_addr)) {
1032 vty_out(vty,
1033 "Specified Edge ID %s is invalid\n",
1034 argv[idx]->arg);
1035 return CMD_WARNING_CONFIG_FAILED;
1036 }
1037 /* Get the Edge from the Link State Database */
1038 key = ((uint64_t)ip_addr.s_addr) & 0xffffffff;
1039 edge = ls_find_edge_by_key(sg.ted, key);
1040 if (!edge) {
1041 vty_out(vty, "No edge found for ID %pI4\n",
1042 &ip_addr);
1043 return CMD_WARNING;
1044 }
1045 } else
1046 edge = NULL;
1047
1048 if (edge)
1049 ls_show_edge(edge, vty, json, verbose);
1050 else
1051 ls_show_edges(sg.ted, vty, json, verbose);
1052
1053 } else if (argv_find(argv, argc, "subnet", &idx)) {
1054 /* Show Subnet */
1055 if (argv_find(argv, argc, "A.B.C.D/M", &idx)) {
1056 if (!str2prefix(argv[idx]->arg, &pref)) {
1057 vty_out(vty, "Invalid prefix format %s\n",
1058 argv[idx]->arg);
1059 return CMD_WARNING_CONFIG_FAILED;
1060 }
1061 /* Get the Subnet from the Link State Database */
1062 subnet = ls_find_subnet(sg.ted, pref);
1063 if (!subnet) {
1064 vty_out(vty, "No subnet found for ID %pFX\n",
1065 &pref);
1066 return CMD_WARNING;
1067 }
1068 } else
1069 subnet = NULL;
1070
1071 if (subnet)
1072 ls_show_subnet(subnet, vty, json, verbose);
1073 else
1074 ls_show_subnets(sg.ted, vty, json, verbose);
1075
1076 } else {
1077 /* Show the complete TED */
1078 ls_show_ted(sg.ted, vty, json, verbose);
1079 }
1080
c48349e3 1081 if (uj)
7297350e 1082 vty_json(vty, json);
ade3eebc
HS
1083
1084 return CMD_SUCCESS;
1085}
1086
1087DEFPY (sharp_srv6_manager_release_locator_chunk,
1088 sharp_srv6_manager_release_locator_chunk_cmd,
1089 "sharp srv6-manager release-locator-chunk NAME$locator_name",
1090 SHARP_STR
1091 "Segment-Routing IPv6\n"
1092 "Release SRv6 locator-chunk\n"
1093 "SRv6 Locator name\n")
1094{
1095 int ret;
1096 struct listnode *loc_node;
1097 struct sharp_srv6_locator *loc;
1098
1099 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, loc_node, loc)) {
1100 if (!strcmp(loc->name, locator_name)) {
1101 list_delete_all_node(loc->chunks);
1102 list_delete(&loc->chunks);
1103 listnode_delete(sg.srv6_locators, loc);
a0c47583 1104 XFREE(MTYPE_SRV6_LOCATOR, loc);
ade3eebc
HS
1105 break;
1106 }
1107 }
1108
1109 ret = sharp_zebra_srv6_manager_release_locator_chunk(locator_name);
1110 if (ret < 0)
1111 return CMD_WARNING_CONFIG_FAILED;
1112
1113 return CMD_SUCCESS;
1114}
1115
1116DEFPY (show_sharp_segment_routing_srv6,
1117 show_sharp_segment_routing_srv6_cmd,
a2df1e4f 1118 "show sharp segment-routing srv6 [json]",
ade3eebc
HS
1119 SHOW_STR
1120 SHARP_STR
1121 "Segment-Routing\n"
a2df1e4f
HS
1122 "Segment-Routing IPv6\n"
1123 JSON_STR)
ade3eebc
HS
1124{
1125 char str[256];
1126 struct listnode *loc_node;
1127 struct listnode *chunk_node;
1128 struct sharp_srv6_locator *loc;
1129 struct prefix_ipv6 *chunk;
a2df1e4f 1130 bool uj = use_json(argc, argv);
ade3eebc
HS
1131 json_object *jo_locs = NULL;
1132 json_object *jo_loc = NULL;
1133 json_object *jo_chunks = NULL;
1134
a2df1e4f
HS
1135 if (uj) {
1136 jo_locs = json_object_new_array();
1137 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, loc_node, loc)) {
1138 jo_loc = json_object_new_object();
1139 json_object_array_add(jo_locs, jo_loc);
1140 json_object_string_add(jo_loc, "name", loc->name);
1141 jo_chunks = json_object_new_array();
1142 json_object_object_add(jo_loc, "chunks", jo_chunks);
1143 for (ALL_LIST_ELEMENTS_RO(loc->chunks, chunk_node,
1144 chunk)) {
1145 prefix2str(chunk, str, sizeof(str));
1146 json_array_string_add(jo_chunks, str);
1147 }
1148 }
1149
7297350e 1150 vty_json(vty, jo_locs);
a2df1e4f
HS
1151 } else {
1152 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, loc_node, loc)) {
1153 vty_out(vty, "Locator %s has %d prefix chunks\n",
1154 loc->name, listcount(loc->chunks));
1155 for (ALL_LIST_ELEMENTS_RO(loc->chunks, chunk_node,
1156 chunk)) {
1157 prefix2str(chunk, str, sizeof(str));
1158 vty_out(vty, " %s\n", str);
1159 }
1160 vty_out(vty, "\n");
ade3eebc
HS
1161 }
1162 }
1163
1888e243
OD
1164 return CMD_SUCCESS;
1165}
1166
621fb5f3
OD
1167DEFPY (show_sharp_cspf,
1168 show_sharp_cspf_cmd,
1169 "show sharp cspf source <A.B.C.D$src4|X:X::X:X$src6> \
1170 destination <A.B.C.D$dst4|X:X::X:X$dst6> \
1171 <metric|te-metric|delay> (0-16777215)$cost \
1172 [rsv-bw (0-7)$cos BANDWIDTH$bw]",
1173 SHOW_STR
1174 SHARP_STR
1175 "Constraint Shortest Path First path computation\n"
1176 "Source of the path\n"
1177 "IPv4 Source address in dot decimal A.B.C.D\n"
1178 "IPv6 Source address as X:X:X:X\n"
1179 "Destination of the path\n"
1180 "IPv4 Destination address in dot decimal A.B.C.D\n"
1181 "IPv6 Destination address as X:X:X:X\n"
1182 "Maximum Metric\n"
1183 "Maximum TE Metric\n"
1184 "Maxim Delay\n"
1185 "Value of Maximum cost\n"
1186 "Reserved Bandwidth of this path\n"
1187 "Class of Service or Priority level\n"
1188 "Bytes/second (IEEE floating point format)\n")
1189{
1190
1191 struct cspf *algo;
1192 struct constraints csts;
1193 struct c_path *path;
1194 struct listnode *node;
1195 struct ls_edge *edge;
1196 int idx;
1197
1198 if (sg.ted == NULL) {
1199 vty_out(vty, "MPLS-TE import is not enabled\n");
1200 return CMD_WARNING;
1201 }
1202
1203 if ((src4.s_addr != INADDR_ANY && dst4.s_addr == INADDR_ANY) ||
1204 (src4.s_addr == INADDR_ANY && dst4.s_addr != INADDR_ANY)) {
1205 vty_out(vty, "Don't mix IPv4 and IPv6 addresses\n");
1206 return CMD_WARNING;
1207 }
1208
1209 idx = 6;
1210 memset(&csts, 0, sizeof(struct constraints));
1211 if (argv_find(argv, argc, "metric", &idx)) {
1212 csts.ctype = CSPF_METRIC;
1213 csts.cost = cost;
1214 }
1215 idx = 6;
1216 if (argv_find(argv, argc, "te-metric", &idx)) {
1217 csts.ctype = CSPF_TE_METRIC;
1218 csts.cost = cost;
1219 }
1220 idx = 6;
1221 if (argv_find(argv, argc, "delay", &idx)) {
1222 csts.ctype = CSPF_DELAY;
1223 csts.cost = cost;
1224 }
1225 if (argc > 9) {
1226 if (sscanf(bw, "%g", &csts.bw) != 1) {
1227 vty_out(vty, "Bandwidth constraints: fscanf: %s\n",
1228 safe_strerror(errno));
1229 return CMD_WARNING_CONFIG_FAILED;
1230 }
1231 csts.cos = cos;
1232 }
1233
1234 /* Initialize and call point-to-point Path computation */
1235 if (src4.s_addr != INADDR_ANY)
1236 algo = cspf_init_v4(NULL, sg.ted, src4, dst4, &csts);
1237 else
1238 algo = cspf_init_v6(NULL, sg.ted, src6, dst6, &csts);
1239 path = compute_p2p_path(algo, sg.ted);
1240 cspf_del(algo);
1241
1242 if (!path) {
1243 vty_out(vty, "Path computation failed without error\n");
1244 return CMD_SUCCESS;
1245 }
1246 if (path->status != SUCCESS) {
1247 vty_out(vty, "Path computation failed: %d\n", path->status);
5aa36ff7 1248 cpath_del(path);
621fb5f3
OD
1249 return CMD_SUCCESS;
1250 }
1251
1252 vty_out(vty, "Path computation success\n");
1253 vty_out(vty, "\tCost: %d\n", path->weight);
1254 vty_out(vty, "\tEdges:");
1255 for (ALL_LIST_ELEMENTS_RO(path->edges, node, edge)) {
1256 if (src4.s_addr != INADDR_ANY)
1257 vty_out(vty, " %pI4",
1258 &edge->attributes->standard.remote);
1259 else
1260 vty_out(vty, " %pI6",
1261 &edge->attributes->standard.remote6);
1262 }
1263 vty_out(vty, "\n");
5aa36ff7 1264 cpath_del(path);
621fb5f3
OD
1265 return CMD_SUCCESS;
1266}
1267
f9a1140c
SW
1268static struct interface *if_lookup_vrf_all(const char *ifname)
1269{
1270 struct interface *ifp;
1271 struct vrf *vrf;
1272
1273 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
1274 ifp = if_lookup_by_name(ifname, vrf->vrf_id);
1275 if (ifp)
1276 return ifp;
1277 }
1278
1279 return NULL;
1280}
1281
1282DEFPY (sharp_interface_protodown,
1283 sharp_interface_protodown_cmd,
1284 "sharp interface IFNAME$ifname protodown",
1285 SHARP_STR
1286 INTERFACE_STR
1287 IFNAME_STR
1288 "Set interface protodown\n")
1289{
1290 struct interface *ifp;
1291
1292 ifp = if_lookup_vrf_all(ifname);
1293
1294 if (!ifp) {
1295 vty_out(vty, "%% Can't find interface %s\n", ifname);
1296 return CMD_WARNING;
1297 }
1298
1299 if (sharp_zebra_send_interface_protodown(ifp, true) != 0)
1300 return CMD_WARNING;
1301
1302 return CMD_SUCCESS;
1303}
1304
1305DEFPY (no_sharp_interface_protodown,
1306 no_sharp_interface_protodown_cmd,
1307 "no sharp interface IFNAME$ifname protodown",
1308 NO_STR
1309 SHARP_STR
1310 INTERFACE_STR
1311 IFNAME_STR
1312 "Set interface protodown\n")
1313{
1314 struct interface *ifp;
1315
1316 ifp = if_lookup_vrf_all(ifname);
1317
1318 if (!ifp) {
1319 vty_out(vty, "%% Can't find interface %s\n", ifname);
1320 return CMD_WARNING;
1321 }
1322
1323 if (sharp_zebra_send_interface_protodown(ifp, false) != 0)
1324 return CMD_WARNING;
1325
1326 return CMD_SUCCESS;
1327}
1328
04bc334e
SY
1329DEFPY (tc_filter_rate,
1330 tc_filter_rate_cmd,
1331 "sharp tc dev IFNAME$ifname \
1332 source <A.B.C.D/M|X:X::X:X/M>$src \
1333 destination <A.B.C.D/M|X:X::X:X/M>$dst \
1334 ip-protocol <tcp|udp>$ip_proto \
1335 src-port (1-65535)$src_port \
1336 dst-port (1-65535)$dst_port \
1337 rate RATE$ratestr",
1338 SHARP_STR
1339 "Traffic control\n"
1340 "TC interface (for qdisc, class, filter)\n"
1341 "TC interface name\n"
1342 "TC filter source\n"
1343 "TC filter source IPv4 prefix\n"
1344 "TC filter source IPv6 prefix\n"
1345 "TC filter destination\n"
1346 "TC filter destination IPv4 prefix\n"
1347 "TC filter destination IPv6 prefix\n"
1348 "TC filter IP protocol\n"
1349 "TC filter IP protocol TCP\n"
1350 "TC filter IP protocol UDP\n"
1351 "TC filter source port\n"
1352 "TC filter source port\n"
1353 "TC filter destination port\n"
1354 "TC filter destination port\n"
1355 "TC rate\n"
1356 "TC rate number (bits/s) or rate string (suffixed with Bps or bit)\n")
1357{
1358 struct interface *ifp;
1359 struct protoent *p;
1360 uint64_t rate;
1361
1362 ifp = if_lookup_vrf_all(ifname);
1363
1364 if (!ifp) {
1365 vty_out(vty, "%% Can't find interface %s\n", ifname);
1366 return CMD_WARNING;
1367 }
1368
1369 p = getprotobyname(ip_proto);
1370 if (!p) {
1371 vty_out(vty, "Unable to convert %s to proto id\n", ip_proto);
1372 return CMD_WARNING;
1373 }
1374
1375 if (tc_getrate(ratestr, &rate) != 0) {
1376 vty_out(vty, "Unable to convert %s to rate\n", ratestr);
1377 return CMD_WARNING;
1378 }
1379
1380 if (sharp_zebra_send_tc_filter_rate(ifp, src, dst, p->p_proto, src_port,
1381 dst_port, rate) != 0)
1382 return CMD_WARNING;
1383
1384 return CMD_SUCCESS;
1385}
1386
8a71d93d
DS
1387void sharp_vty_init(void)
1388{
f59e6418 1389 install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
8a71d93d 1390 install_element(ENABLE_NODE, &install_routes_cmd);
1cb131ee
HS
1391 install_element(ENABLE_NODE, &install_seg6_routes_cmd);
1392 install_element(ENABLE_NODE, &install_seg6local_routes_cmd);
8a71d93d 1393 install_element(ENABLE_NODE, &remove_routes_cmd);
ab18a495 1394 install_element(ENABLE_NODE, &vrf_label_cmd);
86da53ab 1395 install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);
921af54d 1396 install_element(ENABLE_NODE, &watch_redistribute_cmd);
0ae8130d
DS
1397 install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
1398 install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
c9e5adba
MS
1399 install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
1400 install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
aef4a13f 1401 install_element(ENABLE_NODE, &logpump_cmd);
2be4d61a
MS
1402 install_element(ENABLE_NODE, &create_session_cmd);
1403 install_element(ENABLE_NODE, &remove_session_cmd);
2ac6c90d 1404 install_element(ENABLE_NODE, &send_opaque_cmd);
c8b27f2a 1405 install_element(ENABLE_NODE, &send_opaque_unicast_cmd);
939b2339 1406 install_element(ENABLE_NODE, &send_opaque_reg_cmd);
da187b77 1407 install_element(ENABLE_NODE, &neigh_discover_cmd);
1888e243 1408 install_element(ENABLE_NODE, &import_te_cmd);
aaf8c96f 1409
dd73744d 1410 install_element(ENABLE_NODE, &show_debugging_sharpd_cmd);
1888e243 1411 install_element(ENABLE_NODE, &show_sharp_ted_cmd);
621fb5f3 1412 install_element(ENABLE_NODE, &show_sharp_cspf_cmd);
aaf8c96f 1413
ade3eebc 1414 install_element(ENABLE_NODE, &sharp_srv6_manager_get_locator_chunk_cmd);
4df9d859
HS
1415 install_element(ENABLE_NODE,
1416 &sharp_srv6_manager_release_locator_chunk_cmd);
ade3eebc
HS
1417 install_element(ENABLE_NODE, &show_sharp_segment_routing_srv6_cmd);
1418
f9a1140c
SW
1419 install_element(ENABLE_NODE, &sharp_interface_protodown_cmd);
1420 install_element(ENABLE_NODE, &no_sharp_interface_protodown_cmd);
1421
04bc334e
SY
1422 install_element(ENABLE_NODE, &tc_filter_rate_cmd);
1423
8a71d93d
DS
1424 return;
1425}