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