]> git.proxmox.com Git - mirror_frr.git/blob - sharpd/sharp_vty.c
Merge pull request #13464 from sri-mohan1/srib-ldpd
[mirror_frr.git] / sharpd / sharp_vty.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * SHARP - vty code
4 * Copyright (C) Cumulus Networks, Inc.
5 * Donald Sharp
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"
14 #include "vrf.h"
15 #include "zclient.h"
16 #include "nexthop_group.h"
17 #include "linklist.h"
18 #include "link_state.h"
19 #include "cspf.h"
20 #include "tc.h"
21
22 #include "sharpd/sharp_globals.h"
23 #include "sharpd/sharp_zebra.h"
24 #include "sharpd/sharp_nht.h"
25 #include "sharpd/sharp_vty.h"
26 #include "sharpd/sharp_vty_clippy.c"
27
28 DEFINE_MTYPE_STATIC(SHARPD, SRV6_LOCATOR, "SRv6 Locator");
29
30 DEFPY(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
57 DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
58 "sharp watch [vrf NAME$vrf_name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop> [connected$connected]",
59 "Sharp routing Protocol\n"
60 "Watch for changes\n"
61 "The vrf we would like to watch if non-default\n"
62 "The NAME of the vrf\n"
63 "Watch for nexthop changes\n"
64 "The v6 nexthop to signal for watching\n"
65 "Watch for import check changes\n"
66 "The v6 prefix to signal for watching\n"
67 "Should the route be connected\n")
68 {
69 struct vrf *vrf;
70 struct prefix p;
71 bool type_import;
72
73 if (!vrf_name)
74 vrf_name = VRF_DEFAULT_NAME;
75 vrf = vrf_lookup_by_name(vrf_name);
76 if (!vrf) {
77 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
78 vrf_name);
79 return CMD_WARNING;
80 }
81
82 memset(&p, 0, sizeof(p));
83
84 if (n) {
85 type_import = false;
86 p.prefixlen = IPV6_MAX_BITLEN;
87 memcpy(&p.u.prefix6, &nhop, IPV6_MAX_BYTELEN);
88 p.family = AF_INET6;
89 } else {
90 type_import = true;
91 prefix_copy(&p, inhop);
92 }
93
94 sharp_nh_tracker_get(&p);
95 sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
96 true, !!connected);
97
98 return CMD_SUCCESS;
99 }
100
101 DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
102 "sharp watch [vrf NAME$vrf_name] <nexthop$n A.B.C.D$nhop|import$import A.B.C.D/M$inhop> [connected$connected]",
103 "Sharp routing Protocol\n"
104 "Watch for changes\n"
105 "The vrf we would like to watch if non-default\n"
106 "The NAME of the vrf\n"
107 "Watch for nexthop changes\n"
108 "The v4 address to signal for watching\n"
109 "Watch for import check changes\n"
110 "The v4 prefix for import check to watch\n"
111 "Should the route be connected\n")
112 {
113 struct vrf *vrf;
114 struct prefix p;
115 bool type_import;
116
117 if (!vrf_name)
118 vrf_name = VRF_DEFAULT_NAME;
119 vrf = vrf_lookup_by_name(vrf_name);
120 if (!vrf) {
121 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
122 vrf_name);
123 return CMD_WARNING;
124 }
125
126 memset(&p, 0, sizeof(p));
127
128 if (n) {
129 type_import = false;
130 p.prefixlen = IPV4_MAX_BITLEN;
131 p.u.prefix4 = nhop;
132 p.family = AF_INET;
133 }
134 else {
135 type_import = true;
136 prefix_copy(&p, inhop);
137 }
138
139 sharp_nh_tracker_get(&p);
140 sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
141 true, !!connected);
142
143 return CMD_SUCCESS;
144 }
145
146 DEFPY(sharp_nht_data_dump,
147 sharp_nht_data_dump_cmd,
148 "sharp data nexthop",
149 "Sharp routing Protocol\n"
150 "Data about what is going on\n"
151 "Nexthop information\n")
152 {
153 sharp_nh_tracker_dump(vty);
154
155 return CMD_SUCCESS;
156 }
157
158 DEFPY (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 {
165 struct timeval r;
166
167 timersub(&sg.r.t_end, &sg.r.t_start, &r);
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);
171
172 return CMD_SUCCESS;
173 }
174
175 DEFPY (install_routes,
176 install_routes_cmd,
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>|\
180 nexthop-group NHGNAME$nexthop_group>\
181 [backup$backup <A.B.C.D$backup_nexthop4|X:X::X:X$backup_nexthop6>] \
182 (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt] [opaque WORD]",
183 "Sharp routing Protocol\n"
184 "install some routes\n"
185 "Routes to install\n"
186 "The vrf we would like to install into if non-default\n"
187 "The NAME of the vrf\n"
188 "v4 Address to start /32 generation at\n"
189 "v6 Address to start /32 generation at\n"
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"
193 "Nexthop-Group to use\n"
194 "The Name of the nexthop-group\n"
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"
198 "How many to create\n"
199 "Instance to use\n"
200 "Instance\n"
201 "Should we repeat this command\n"
202 "How many times to repeat this command\n"
203 "What opaque data to send down\n"
204 "The opaque data\n")
205 {
206 struct vrf *vrf;
207 struct prefix prefix;
208 uint32_t rts;
209 uint32_t nhgid = 0;
210
211 sg.r.total_routes = routes;
212 sg.r.installed_routes = 0;
213
214 if (rpt >= 2)
215 sg.r.repeat = rpt * 2;
216 else
217 sg.r.repeat = 0;
218
219 memset(&prefix, 0, sizeof(prefix));
220 memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
221 nexthop_del_srv6_seg6local(&sg.r.nhop);
222 nexthop_del_srv6_seg6(&sg.r.nhop);
223 memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
224 memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
225 memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
226 memset(&sg.r.backup_nhop_group, 0, sizeof(sg.r.nhop_group));
227
228 if (start4.s_addr != INADDR_ANY) {
229 prefix.family = AF_INET;
230 prefix.prefixlen = IPV4_MAX_BITLEN;
231 prefix.u.prefix4 = start4;
232 } else {
233 prefix.family = AF_INET6;
234 prefix.prefixlen = IPV6_MAX_BITLEN;
235 prefix.u.prefix6 = start6;
236 }
237 sg.r.orig_prefix = prefix;
238
239 if (!vrf_name)
240 vrf_name = VRF_DEFAULT_NAME;
241
242 vrf = vrf_lookup_by_name(vrf_name);
243 if (!vrf) {
244 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
245 vrf_name);
246 return CMD_WARNING;
247 }
248
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
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
264 nhgid = sharp_nhgroup_get_id(nexthop_group);
265 sg.r.nhgid = nhgid;
266 sg.r.nhop_group.nexthop = nhgc->nhg.nexthop;
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 }
283 } else {
284 if (nexthop4.s_addr != INADDR_ANY) {
285 sg.r.nhop.gate.ipv4 = nexthop4;
286 sg.r.nhop.type = NEXTHOP_TYPE_IPV4;
287 } else {
288 sg.r.nhop.gate.ipv6 = nexthop6;
289 sg.r.nhop.type = NEXTHOP_TYPE_IPV6;
290 }
291
292 sg.r.nhop.vrf_id = vrf->vrf_id;
293 sg.r.nhop_group.nexthop = &sg.r.nhop;
294 }
295
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);
300 sg.r.nhop.backup_num = 1;
301 sg.r.nhop.backup_idx[0] = 0;
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
315 if (opaque)
316 strlcpy(sg.r.opaque, opaque, ZAPI_MESSAGE_OPAQUE_LENGTH);
317 else
318 sg.r.opaque[0] = '\0';
319
320 sg.r.inst = instance;
321 sg.r.vrf_id = vrf->vrf_id;
322 rts = routes;
323 sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, nhgid,
324 &sg.r.nhop_group, &sg.r.backup_nhop_group,
325 rts, 0, sg.r.opaque);
326
327 return CMD_SUCCESS;
328 }
329
330 DEFPY (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));
365 nexthop_del_srv6_seg6local(&sg.r.nhop);
366 nexthop_del_srv6_seg6(&sg.r.nhop);
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;
376 prefix.prefixlen = IPV4_MAX_BITLEN;
377 prefix.u.prefix4 = start4;
378 } else {
379 prefix.family = AF_INET6;
380 prefix.prefixlen = IPV6_MAX_BITLEN;
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;
399 nexthop_add_srv6_seg6(&sg.r.nhop, &seg6_seg);
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
409 DEFPY (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|\
418 End_DT6$seg6l_enddt6 (1-4294967295)$seg6l_enddt6_table|\
419 End_DT4$seg6l_enddt4 (1-4294967295)$seg6l_enddt4_table|\
420 End_DT46$seg6l_enddt46 (1-4294967295)$seg6l_enddt46_table>\
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"
439 "SRv6 End.DT4 function to use\n"
440 "Redirect table id to use\n"
441 "SRv6 End.DT46 function to use\n"
442 "Redirect table id to use\n"
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));
461 nexthop_del_srv6_seg6local(&sg.r.nhop);
462 nexthop_del_srv6_seg6(&sg.r.nhop);
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;
495 } else if (seg6l_enddt4) {
496 action = ZEBRA_SEG6_LOCAL_ACTION_END_DT4;
497 ctx.table = seg6l_enddt4_table;
498 } else if (seg6l_enddt46) {
499 action = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
500 ctx.table = seg6l_enddt46_table;
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;
509 nexthop_add_srv6_seg6local(&sg.r.nhop, action, &ctx);
510
511 sg.r.vrf_id = vrf->vrf_id;
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);
516
517 return CMD_SUCCESS;
518 }
519
520 DEFPY(vrf_label, vrf_label_cmd,
521 "sharp label <ip$ipv4|ipv6$ipv6> vrf NAME$vrf_name label (0-100000)$label",
522 "Sharp Routing Protocol\n"
523 "Give a vrf a label\n"
524 "Pop and forward for IPv4\n"
525 "Pop and forward for IPv6\n"
526 VRF_CMD_HELP_STR
527 "The label to use, 0 specifies remove the label installed from previous\n"
528 "Specified range to use\n")
529 {
530 struct vrf *vrf;
531 afi_t afi = (ipv4) ? AFI_IP : AFI_IP6;
532
533 if (strcmp(vrf_name, "default") == 0)
534 vrf = vrf_lookup_by_id(VRF_DEFAULT);
535 else
536 vrf = vrf_lookup_by_name(vrf_name);
537
538 if (!vrf) {
539 vty_out(vty, "Unable to find vrf you silly head\n");
540 return CMD_WARNING_CONFIG_FAILED;
541 }
542
543 if (label == 0)
544 label = MPLS_LABEL_NONE;
545
546 vrf_label_add(vrf->vrf_id, afi, label);
547 return CMD_SUCCESS;
548 }
549
550 DEFPY (remove_routes,
551 remove_routes_cmd,
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]",
553 "Sharp Routing Protocol\n"
554 "Remove some routes\n"
555 "Routes to remove\n"
556 "The vrf we would like to remove from if non-default\n"
557 "The NAME of the vrf\n"
558 "v4 Starting spot\n"
559 "v6 Starting spot\n"
560 "Routes to uninstall\n"
561 "instance to use\n"
562 "Value of instance\n")
563 {
564 struct vrf *vrf;
565 struct prefix prefix;
566
567 sg.r.total_routes = routes;
568 sg.r.removed_routes = 0;
569 uint32_t rts;
570
571 memset(&prefix, 0, sizeof(prefix));
572
573 if (start4.s_addr != INADDR_ANY) {
574 prefix.family = AF_INET;
575 prefix.prefixlen = IPV4_MAX_BITLEN;
576 prefix.u.prefix4 = start4;
577 } else {
578 prefix.family = AF_INET6;
579 prefix.prefixlen = IPV6_MAX_BITLEN;
580 prefix.u.prefix6 = start6;
581 }
582
583 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
584 if (!vrf) {
585 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
586 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
587 return CMD_WARNING;
588 }
589
590 sg.r.inst = instance;
591 sg.r.vrf_id = vrf->vrf_id;
592 rts = routes;
593 sharp_remove_routes_helper(&prefix, sg.r.vrf_id,
594 sg.r.inst, rts);
595
596 return CMD_SUCCESS;
597 }
598
599 DEFUN_NOSH (show_debugging_sharpd,
600 show_debugging_sharpd_cmd,
601 "show debugging [sharp]",
602 SHOW_STR
603 DEBUG_STR
604 "Sharp Information\n")
605 {
606 vty_out(vty, "Sharp debugging status:\n");
607
608 cmd_show_lib_debugs(vty);
609
610 return CMD_SUCCESS;
611 }
612
613 DEFPY (sharp_lsp_prefix_v4, sharp_lsp_prefix_v4_cmd,
614 "sharp lsp [update]$update (0-100000)$inlabel\
615 nexthop-group NHGNAME$nhgname\
616 [prefix A.B.C.D/M$pfx\
617 " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
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")
629 {
630 struct nexthop_group_cmd *nhgc = NULL;
631 struct nexthop_group_cmd *backup_nhgc = NULL;
632 struct nexthop_group *backup_nhg = NULL;
633 struct prefix p = {};
634 int type = 0;
635 bool update_p;
636
637 update_p = (update != NULL);
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
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
681 if (sharp_install_lsps_helper(true /*install*/, update_p,
682 pfx->family > 0 ? &p : NULL,
683 type, instance, inlabel,
684 &(nhgc->nhg), backup_nhg) == 0)
685 return CMD_SUCCESS;
686 else {
687 vty_out(vty, "%% LSP install failed!\n");
688 return CMD_WARNING;
689 }
690 }
691
692 DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd,
693 "sharp remove lsp \
694 (0-100000)$inlabel\
695 [nexthop-group NHGNAME$nhgname] \
696 [prefix A.B.C.D/M$pfx\
697 " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
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"
706 FRR_IP_REDIST_HELP_STR_ZEBRA
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;
713 struct nexthop_group *nhg = NULL;
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
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 }
738
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);
745 }
746
747 if (sharp_install_lsps_helper(false /*!install*/, false,
748 pfx->family > 0 ? &p : NULL,
749 type, instance, inlabel, nhg, NULL) == 0)
750 return CMD_SUCCESS;
751 else {
752 vty_out(vty, "%% LSP remove failed!\n");
753 return CMD_WARNING;
754 }
755 }
756
757 DEFPY (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
773 DEFPY (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
789 DEFPY (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
801 DEFPY (send_opaque,
802 send_opaque_cmd,
803 "sharp send opaque type (1-255) (1-1000)$count",
804 SHARP_STR
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 {
811 sharp_opaque_send(type, 0, 0, 0, count);
812 return CMD_SUCCESS;
813 }
814
815 DEFPY (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
839 return CMD_SUCCESS;
840 }
841
842 DEFPY (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)",
847 SHARP_STR
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
868 DEFPY (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
885 if (dst4.s_addr != INADDR_ANY) {
886 prefix.family = AF_INET;
887 prefix.prefixlen = IPV4_MAX_BITLEN;
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
913 DEFPY (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
925 static void sharp_srv6_locator_chunk_free(struct prefix_ipv6 *chunk)
926 {
927 prefix_ipv6_free((struct prefix_ipv6 **)&chunk);
928 }
929
930 DEFPY (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();
953 loc->chunks->del =
954 (void (*)(void *))sharp_srv6_locator_chunk_free;
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
966 DEFUN (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 struct ls_edge_key ekey;
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 */
1039 ekey.family = AF_INET;
1040 IPV4_ADDR_COPY(&ekey.k.addr, &ip_addr);
1041 edge = ls_find_edge_by_key(sg.ted, ekey);
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 */
1064 subnet = ls_find_subnet(sg.ted, &pref);
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
1083 if (uj)
1084 vty_json(vty, json);
1085
1086 return CMD_SUCCESS;
1087 }
1088
1089 DEFPY (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);
1106 XFREE(MTYPE_SRV6_LOCATOR, loc);
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
1118 DEFPY (show_sharp_segment_routing_srv6,
1119 show_sharp_segment_routing_srv6_cmd,
1120 "show sharp segment-routing srv6 [json]",
1121 SHOW_STR
1122 SHARP_STR
1123 "Segment-Routing\n"
1124 "Segment-Routing IPv6\n"
1125 JSON_STR)
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;
1132 bool uj = use_json(argc, argv);
1133 json_object *jo_locs = NULL;
1134 json_object *jo_loc = NULL;
1135 json_object *jo_chunks = NULL;
1136
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
1152 vty_json(vty, jo_locs);
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");
1163 }
1164 }
1165
1166 return CMD_SUCCESS;
1167 }
1168
1169 DEFPY (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);
1250 cpath_del(path);
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");
1266 cpath_del(path);
1267 return CMD_SUCCESS;
1268 }
1269
1270 static 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
1284 DEFPY (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
1307 DEFPY (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
1331 DEFPY (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
1389 void sharp_vty_init(void)
1390 {
1391 install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
1392 install_element(ENABLE_NODE, &install_routes_cmd);
1393 install_element(ENABLE_NODE, &install_seg6_routes_cmd);
1394 install_element(ENABLE_NODE, &install_seg6local_routes_cmd);
1395 install_element(ENABLE_NODE, &remove_routes_cmd);
1396 install_element(ENABLE_NODE, &vrf_label_cmd);
1397 install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);
1398 install_element(ENABLE_NODE, &watch_redistribute_cmd);
1399 install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
1400 install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
1401 install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
1402 install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
1403 install_element(ENABLE_NODE, &logpump_cmd);
1404 install_element(ENABLE_NODE, &create_session_cmd);
1405 install_element(ENABLE_NODE, &remove_session_cmd);
1406 install_element(ENABLE_NODE, &send_opaque_cmd);
1407 install_element(ENABLE_NODE, &send_opaque_unicast_cmd);
1408 install_element(ENABLE_NODE, &send_opaque_reg_cmd);
1409 install_element(ENABLE_NODE, &neigh_discover_cmd);
1410 install_element(ENABLE_NODE, &import_te_cmd);
1411
1412 install_element(ENABLE_NODE, &show_debugging_sharpd_cmd);
1413 install_element(ENABLE_NODE, &show_sharp_ted_cmd);
1414 install_element(ENABLE_NODE, &show_sharp_cspf_cmd);
1415
1416 install_element(ENABLE_NODE, &sharp_srv6_manager_get_locator_chunk_cmd);
1417 install_element(ENABLE_NODE,
1418 &sharp_srv6_manager_release_locator_chunk_cmd);
1419 install_element(ENABLE_NODE, &show_sharp_segment_routing_srv6_cmd);
1420
1421 install_element(ENABLE_NODE, &sharp_interface_protodown_cmd);
1422 install_element(ENABLE_NODE, &no_sharp_interface_protodown_cmd);
1423
1424 install_element(ENABLE_NODE, &tc_filter_rate_cmd);
1425
1426 return;
1427 }