]> git.proxmox.com Git - mirror_frr.git/blame - sharpd/sharp_vty.c
zebra: fill_seg6ipt_encap func with boundary check
[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"
1888e243 32#include "link_state.h"
8a71d93d 33
547dc642 34#include "sharpd/sharp_globals.h"
8a71d93d 35#include "sharpd/sharp_zebra.h"
86da53ab 36#include "sharpd/sharp_nht.h"
8a71d93d 37#include "sharpd/sharp_vty.h"
2e4c2296 38#ifndef VTYSH_EXTRACT_PL
8a71d93d 39#include "sharpd/sharp_vty_clippy.c"
2e4c2296 40#endif
8a71d93d 41
ade3eebc
HS
42DEFINE_MTYPE_STATIC(SHARPD, SRV6_LOCATOR, "SRv6 Locator");
43
921af54d
DS
44DEFPY(watch_redistribute, watch_redistribute_cmd,
45 "sharp watch [vrf NAME$vrf_name] redistribute " FRR_REDIST_STR_SHARPD,
46 "Sharp routing Protocol\n"
47 "Watch for changes\n"
48 "The vrf we would like to watch if non-default\n"
49 "The NAME of the vrf\n"
50 "Redistribute into Sharp\n"
51 FRR_REDIST_HELP_STR_SHARPD)
52{
53 struct vrf *vrf;
54 int source;
55
56 if (!vrf_name)
57 vrf_name = VRF_DEFAULT_NAME;
58 vrf = vrf_lookup_by_name(vrf_name);
59 if (!vrf) {
60 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
61 vrf_name);
62 return CMD_WARNING;
63 }
64
65 source = proto_redistnum(AFI_IP, argv[argc-1]->text);
66 sharp_redistribute_vrf(vrf, source);
67
68 return CMD_SUCCESS;
69}
70
0ae8130d 71DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
e429a2a0 72 "sharp watch [vrf NAME$vrf_name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop> [connected$connected]",
0ae8130d
DS
73 "Sharp routing Protocol\n"
74 "Watch for changes\n"
a3b6aa82
DS
75 "The vrf we would like to watch if non-default\n"
76 "The NAME of the vrf\n"
0ae8130d 77 "Watch for nexthop changes\n"
a60ffbc9 78 "The v6 nexthop to signal for watching\n"
1be0815d
DS
79 "Watch for import check changes\n"
80 "The v6 prefix to signal for watching\n"
a60ffbc9 81 "Should the route be connected\n")
0ae8130d 82{
a3b6aa82 83 struct vrf *vrf;
0ae8130d 84 struct prefix p;
80d5ff33
DS
85 bool type_import;
86
e429a2a0
IR
87 if (!vrf_name)
88 vrf_name = VRF_DEFAULT_NAME;
89 vrf = vrf_lookup_by_name(vrf_name);
a3b6aa82
DS
90 if (!vrf) {
91 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
e429a2a0 92 vrf_name);
a3b6aa82
DS
93 return CMD_WARNING;
94 }
80d5ff33 95
0ae8130d
DS
96 memset(&p, 0, sizeof(p));
97
1be0815d
DS
98 if (n) {
99 type_import = false;
100 p.prefixlen = 128;
101 memcpy(&p.u.prefix6, &nhop, 16);
102 p.family = AF_INET6;
103 } else {
104 type_import = true;
105 p = *(const struct prefix *)inhop;
106 }
0ae8130d 107
86da53ab 108 sharp_nh_tracker_get(&p);
a3b6aa82 109 sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
91529dc8 110 true, !!connected);
0ae8130d
DS
111
112 return CMD_SUCCESS;
113}
114
115DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
e429a2a0 116 "sharp watch [vrf NAME$vrf_name] <nexthop$n A.B.C.D$nhop|import$import A.B.C.D/M$inhop> [connected$connected]",
0ae8130d
DS
117 "Sharp routing Protocol\n"
118 "Watch for changes\n"
a3b6aa82
DS
119 "The vrf we would like to watch if non-default\n"
120 "The NAME of the vrf\n"
0ae8130d 121 "Watch for nexthop changes\n"
1be0815d 122 "The v4 address to signal for watching\n"
80d5ff33 123 "Watch for import check changes\n"
1be0815d 124 "The v4 prefix for import check to watch\n"
a60ffbc9 125 "Should the route be connected\n")
0ae8130d 126{
a3b6aa82 127 struct vrf *vrf;
0ae8130d 128 struct prefix p;
80d5ff33 129 bool type_import;
0ae8130d 130
e429a2a0
IR
131 if (!vrf_name)
132 vrf_name = VRF_DEFAULT_NAME;
133 vrf = vrf_lookup_by_name(vrf_name);
a3b6aa82
DS
134 if (!vrf) {
135 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
e429a2a0 136 vrf_name);
a3b6aa82
DS
137 return CMD_WARNING;
138 }
139
0ae8130d
DS
140 memset(&p, 0, sizeof(p));
141
1be0815d 142 if (n) {
80d5ff33 143 type_import = false;
1be0815d
DS
144 p.prefixlen = 32;
145 p.u.prefix4 = nhop;
146 p.family = AF_INET;
147 }
148 else {
80d5ff33 149 type_import = true;
1be0815d
DS
150 p = *(const struct prefix *)inhop;
151 }
0ae8130d 152
86da53ab 153 sharp_nh_tracker_get(&p);
a3b6aa82 154 sharp_zebra_nexthop_watch(&p, vrf->vrf_id, type_import,
91529dc8 155 true, !!connected);
0ae8130d
DS
156
157 return CMD_SUCCESS;
158}
159
86da53ab
DS
160DEFPY(sharp_nht_data_dump,
161 sharp_nht_data_dump_cmd,
162 "sharp data nexthop",
163 "Sharp routing Protocol\n"
bcc519dc
DS
164 "Data about what is going on\n"
165 "Nexthop information\n")
86da53ab
DS
166{
167 sharp_nh_tracker_dump(vty);
168
169 return CMD_SUCCESS;
170}
171
f59e6418
DS
172DEFPY (install_routes_data_dump,
173 install_routes_data_dump_cmd,
174 "sharp data route",
175 "Sharp routing Protocol\n"
176 "Data about what is going on\n"
177 "Route Install/Removal Information\n")
178{
f59e6418
DS
179 struct timeval r;
180
181 timersub(&sg.r.t_end, &sg.r.t_start, &r);
2dbe669b
DA
182 vty_out(vty, "Prefix: %pFX Total: %u %u %u Time: %jd.%ld\n",
183 &sg.r.orig_prefix, sg.r.total_routes, sg.r.installed_routes,
184 sg.r.removed_routes, (intmax_t)r.tv_sec, (long)r.tv_usec);
f59e6418
DS
185
186 return CMD_SUCCESS;
187}
188
8a71d93d
DS
189DEFPY (install_routes,
190 install_routes_cmd,
1df3b1dc
MS
191 "sharp install routes [vrf NAME$vrf_name]\
192 <A.B.C.D$start4|X:X::X:X$start6>\
193 <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|\
dc3883cf
HS
194 nexthop-group NHGNAME$nexthop_group|\
195 nexthop-seg6local NAME$seg6l_oif\
196 <End$seg6l_end|\
197 End_X$seg6l_endx X:X::X:X$seg6l_endx_nh6|\
198 End_T$seg6l_endt (1-4294967295)$seg6l_endt_table|\
199 End_DX4$seg6l_enddx4 A.B.C.D$seg6l_enddx4_nh4|\
af31f6c0
HS
200 End_DT6$seg6l_enddt6 (1-4294967295)$seg6l_enddt6_table>|\
201 nexthop-seg6$nh_seg6 X:X::X:X$seg6_nh6 encap X:X::X:X$seg6_seg>\
1df3b1dc 202 [backup$backup <A.B.C.D$backup_nexthop4|X:X::X:X$backup_nexthop6>] \
cfa2a35d 203 (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt] [opaque WORD]",
75239f4f 204 "Sharp routing Protocol\n"
8a71d93d
DS
205 "install some routes\n"
206 "Routes to install\n"
4a7d4737
DS
207 "The vrf we would like to install into if non-default\n"
208 "The NAME of the vrf\n"
dbc1bf46
DS
209 "v4 Address to start /32 generation at\n"
210 "v6 Address to start /32 generation at\n"
ba041bea
DS
211 "Nexthop to use(Can be an IPv4 or IPv6 address)\n"
212 "V4 Nexthop address to use\n"
213 "V6 Nexthop address to use\n"
d4101c0a
DS
214 "Nexthop-Group to use\n"
215 "The Name of the nexthop-group\n"
dc3883cf
HS
216 "Nexthop-seg6local to use\n"
217 "Output device to use\n"
218 "SRv6 End function to use\n"
219 "SRv6 End.X function to use\n"
220 "V6 Nexthop address to use\n"
221 "SRv6 End.T function to use\n"
222 "Redirect table id to use\n"
223 "SRv6 End.DX4 function to use\n"
224 "V4 Nexthop address to use\n"
225 "SRv6 End.DT6 function to use\n"
226 "Redirect table id to use\n"
af31f6c0
HS
227 "Nexthop-seg6 to use\n"
228 "V6 Nexthop address to use\n"
229 "Encap mode\n"
230 "Segment List to use\n"
1df3b1dc
MS
231 "Backup nexthop to use(Can be an IPv4 or IPv6 address)\n"
232 "Backup V4 Nexthop address to use\n"
233 "Backup V6 Nexthop address to use\n"
ae252c02
DS
234 "How many to create\n"
235 "Instance to use\n"
b939f6ff
DS
236 "Instance\n"
237 "Should we repeat this command\n"
cfa2a35d
DS
238 "How many times to repeat this command\n"
239 "What opaque data to send down\n"
240 "The opaque data\n")
8a71d93d 241{
4a7d4737 242 struct vrf *vrf;
547dc642
DS
243 struct prefix prefix;
244 uint32_t rts;
569e87c0 245 uint32_t nhgid = 0;
c27b47d7 246 uint32_t route_flags = 0;
547dc642
DS
247
248 sg.r.total_routes = routes;
249 sg.r.installed_routes = 0;
8a71d93d 250
b939f6ff 251 if (rpt >= 2)
547dc642 252 sg.r.repeat = rpt * 2;
b939f6ff 253 else
547dc642 254 sg.r.repeat = 0;
b939f6ff
DS
255
256 memset(&prefix, 0, sizeof(prefix));
547dc642
DS
257 memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
258 memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
259 memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
1df3b1dc
MS
260 memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
261 memset(&sg.r.backup_nhop_group, 0, sizeof(sg.r.nhop_group));
8a71d93d 262
3a6290bd 263 if (start4.s_addr != INADDR_ANY) {
dbc1bf46
DS
264 prefix.family = AF_INET;
265 prefix.prefixlen = 32;
266 prefix.u.prefix4 = start4;
267 } else {
268 prefix.family = AF_INET6;
269 prefix.prefixlen = 128;
270 prefix.u.prefix6 = start6;
271 }
547dc642 272 sg.r.orig_prefix = prefix;
8a71d93d 273
e429a2a0
IR
274 if (!vrf_name)
275 vrf_name = VRF_DEFAULT_NAME;
a3b6aa82 276
e429a2a0 277 vrf = vrf_lookup_by_name(vrf_name);
4a7d4737
DS
278 if (!vrf) {
279 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
e429a2a0 280 vrf_name);
4a7d4737
DS
281 return CMD_WARNING;
282 }
283
1df3b1dc
MS
284 /* Explicit backup not available with named nexthop-group */
285 if (backup && nexthop_group) {
286 vty_out(vty, "%% Invalid: cannot specify both nexthop-group and backup\n");
287 return CMD_WARNING;
288 }
289
d4101c0a
DS
290 if (nexthop_group) {
291 struct nexthop_group_cmd *nhgc = nhgc_find(nexthop_group);
292 if (!nhgc) {
293 vty_out(vty,
294 "Specified Nexthop Group: %s does not exist\n",
295 nexthop_group);
296 return CMD_WARNING;
297 }
298
569e87c0
DS
299 nhgid = sharp_nhgroup_get_id(nexthop_group);
300 sg.r.nhgid = nhgid;
547dc642 301 sg.r.nhop_group.nexthop = nhgc->nhg.nexthop;
1df3b1dc
MS
302
303 /* Use group's backup nexthop info if present */
304 if (nhgc->backup_list_name[0]) {
305 struct nexthop_group_cmd *bnhgc =
306 nhgc_find(nhgc->backup_list_name);
307
308 if (!bnhgc) {
309 vty_out(vty, "%% Backup group %s not found for group %s\n",
310 nhgc->backup_list_name,
311 nhgc->name);
312 return CMD_WARNING;
313 }
314
315 sg.r.backup_nhop.vrf_id = vrf->vrf_id;
316 sg.r.backup_nhop_group.nexthop = bnhgc->nhg.nexthop;
317 }
dc3883cf 318 } else if (seg6l_oif) {
1bda3e62 319 struct seg6local_context ctx = {};
dc3883cf 320 enum seg6local_action_t action;
4df9d859 321
dc3883cf
HS
322 if (seg6l_enddx4) {
323 action = ZEBRA_SEG6_LOCAL_ACTION_END_DX4;
324 ctx.nh4 = seg6l_enddx4_nh4;
325 } else if (seg6l_endx) {
326 action = ZEBRA_SEG6_LOCAL_ACTION_END_X;
327 ctx.nh6 = seg6l_endx_nh6;
328 } else if (seg6l_endt) {
329 action = ZEBRA_SEG6_LOCAL_ACTION_END_T;
330 ctx.table = seg6l_endt_table;
331 } else if (seg6l_enddt6) {
332 action = ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
333 ctx.table = seg6l_enddt6_table;
334 } else {
335 action = ZEBRA_SEG6_LOCAL_ACTION_END;
336 }
337
338 sg.r.nhop.type = NEXTHOP_TYPE_IFINDEX;
339 sg.r.nhop.ifindex = ifname2ifindex(seg6l_oif, vrf->vrf_id);
340 sg.r.nhop.vrf_id = vrf->vrf_id;
341 sg.r.nhop_group.nexthop = &sg.r.nhop;
342 nexthop_add_seg6local(&sg.r.nhop, action, &ctx);
343 SET_FLAG(route_flags, ZEBRA_FLAG_SEG6LOCAL_ROUTE);
af31f6c0
HS
344 } else if (nh_seg6) {
345 sg.r.nhop.type = NEXTHOP_TYPE_IPV6;
346 sg.r.nhop.gate.ipv6 = seg6_nh6;
347 sg.r.nhop.vrf_id = vrf->vrf_id;
348 sg.r.nhop_group.nexthop = &sg.r.nhop;
349
350 nexthop_add_seg6(&sg.r.nhop, &seg6_seg);
351 SET_FLAG(route_flags, ZEBRA_FLAG_SEG6_ROUTE);
ba041bea 352 } else {
d4101c0a 353 if (nexthop4.s_addr != INADDR_ANY) {
547dc642
DS
354 sg.r.nhop.gate.ipv4 = nexthop4;
355 sg.r.nhop.type = NEXTHOP_TYPE_IPV4;
d4101c0a 356 } else {
547dc642
DS
357 sg.r.nhop.gate.ipv6 = nexthop6;
358 sg.r.nhop.type = NEXTHOP_TYPE_IPV6;
d4101c0a
DS
359 }
360
4a7d4737 361 sg.r.nhop.vrf_id = vrf->vrf_id;
547dc642 362 sg.r.nhop_group.nexthop = &sg.r.nhop;
ba041bea 363 }
8a71d93d 364
1df3b1dc
MS
365 /* Use single backup nexthop if specified */
366 if (backup) {
367 /* Set flag and index in primary nexthop */
368 SET_FLAG(sg.r.nhop.flags, NEXTHOP_FLAG_HAS_BACKUP);
474aebd9
MS
369 sg.r.nhop.backup_num = 1;
370 sg.r.nhop.backup_idx[0] = 0;
1df3b1dc
MS
371
372 if (backup_nexthop4.s_addr != INADDR_ANY) {
373 sg.r.backup_nhop.gate.ipv4 = backup_nexthop4;
374 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV4;
375 } else {
376 sg.r.backup_nhop.gate.ipv6 = backup_nexthop6;
377 sg.r.backup_nhop.type = NEXTHOP_TYPE_IPV6;
378 }
379
380 sg.r.backup_nhop.vrf_id = vrf->vrf_id;
381 sg.r.backup_nhop_group.nexthop = &sg.r.backup_nhop;
382 }
383
cfa2a35d
DS
384 if (opaque)
385 strlcpy(sg.r.opaque, opaque, ZAPI_MESSAGE_OPAQUE_LENGTH);
386 else
387 sg.r.opaque[0] = '\0';
388
547dc642 389 sg.r.inst = instance;
4a7d4737 390 sg.r.vrf_id = vrf->vrf_id;
b939f6ff 391 rts = routes;
ff9aca4f
SW
392 sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, nhgid,
393 &sg.r.nhop_group, &sg.r.backup_nhop_group,
c27b47d7 394 rts, route_flags, sg.r.opaque);
8a71d93d
DS
395
396 return CMD_SUCCESS;
397}
398
42567e00 399DEFPY(vrf_label, vrf_label_cmd,
e429a2a0 400 "sharp label <ip$ipv4|ipv6$ipv6> vrf NAME$vrf_name label (0-100000)$label",
75239f4f 401 "Sharp Routing Protocol\n"
ab18a495 402 "Give a vrf a label\n"
7d061b3c
DS
403 "Pop and forward for IPv4\n"
404 "Pop and forward for IPv6\n"
ab18a495 405 VRF_CMD_HELP_STR
42567e00 406 "The label to use, 0 specifies remove the label installed from previous\n"
ab18a495
DS
407 "Specified range to use\n")
408{
409 struct vrf *vrf;
7d061b3c 410 afi_t afi = (ipv4) ? AFI_IP : AFI_IP6;
ab18a495 411
e429a2a0 412 if (strcmp(vrf_name, "default") == 0)
ab18a495
DS
413 vrf = vrf_lookup_by_id(VRF_DEFAULT);
414 else
e429a2a0 415 vrf = vrf_lookup_by_name(vrf_name);
ab18a495
DS
416
417 if (!vrf) {
418 vty_out(vty, "Unable to find vrf you silly head");
419 return CMD_WARNING_CONFIG_FAILED;
420 }
421
42567e00
DS
422 if (label == 0)
423 label = MPLS_LABEL_NONE;
424
7d061b3c 425 vrf_label_add(vrf->vrf_id, afi, label);
ab18a495
DS
426 return CMD_SUCCESS;
427}
428
8a71d93d
DS
429DEFPY (remove_routes,
430 remove_routes_cmd,
e429a2a0 431 "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 432 "Sharp Routing Protocol\n"
8a71d93d
DS
433 "Remove some routes\n"
434 "Routes to remove\n"
4a7d4737
DS
435 "The vrf we would like to remove from if non-default\n"
436 "The NAME of the vrf\n"
e310fc19
DS
437 "v4 Starting spot\n"
438 "v6 Starting spot\n"
439 "Routes to uninstall\n"
ae252c02
DS
440 "instance to use\n"
441 "Value of instance\n")
8a71d93d 442{
4a7d4737 443 struct vrf *vrf;
547dc642
DS
444 struct prefix prefix;
445
446 sg.r.total_routes = routes;
447 sg.r.removed_routes = 0;
448 uint32_t rts;
8a71d93d 449
b939f6ff 450 memset(&prefix, 0, sizeof(prefix));
8a71d93d 451
3a6290bd 452 if (start4.s_addr != INADDR_ANY) {
dbc1bf46
DS
453 prefix.family = AF_INET;
454 prefix.prefixlen = 32;
455 prefix.u.prefix4 = start4;
456 } else {
457 prefix.family = AF_INET6;
458 prefix.prefixlen = 128;
459 prefix.u.prefix6 = start6;
460 }
8a71d93d 461
e429a2a0 462 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
4a7d4737
DS
463 if (!vrf) {
464 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
e429a2a0 465 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
4a7d4737
DS
466 return CMD_WARNING;
467 }
468
547dc642 469 sg.r.inst = instance;
4a7d4737 470 sg.r.vrf_id = vrf->vrf_id;
b939f6ff 471 rts = routes;
0cf08685
DS
472 sharp_remove_routes_helper(&prefix, sg.r.vrf_id,
473 sg.r.inst, rts);
8a71d93d
DS
474
475 return CMD_SUCCESS;
476}
477
aaf8c96f
DS
478DEFUN_NOSH (show_debugging_sharpd,
479 show_debugging_sharpd_cmd,
480 "show debugging [sharp]",
481 SHOW_STR
482 DEBUG_STR
483 "Sharp Information\n")
484{
c9e5adba 485 vty_out(vty, "Sharp debugging status:\n");
aaf8c96f
DS
486
487 return CMD_SUCCESS;
488}
489
faa75dfa
MS
490DEFPY (sharp_lsp_prefix_v4, sharp_lsp_prefix_v4_cmd,
491 "sharp lsp [update]$update (0-100000)$inlabel\
c9e5adba
MS
492 nexthop-group NHGNAME$nhgname\
493 [prefix A.B.C.D/M$pfx\
4b0f6237 494 " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
faa75dfa
MS
495 "Sharp Routing Protocol\n"
496 "Add an LSP\n"
497 "Update an LSP\n"
498 "The ingress label to use\n"
499 "Use nexthops from a nexthop-group\n"
500 "The nexthop-group name\n"
501 "Label a prefix\n"
502 "The v4 prefix to label\n"
503 FRR_IP_REDIST_HELP_STR_ZEBRA
504 "Instance to use\n"
505 "Instance\n")
c9e5adba
MS
506{
507 struct nexthop_group_cmd *nhgc = NULL;
665edffd
MS
508 struct nexthop_group_cmd *backup_nhgc = NULL;
509 struct nexthop_group *backup_nhg = NULL;
c9e5adba
MS
510 struct prefix p = {};
511 int type = 0;
faa75dfa
MS
512 bool update_p;
513
514 update_p = (update != NULL);
c9e5adba
MS
515
516 /* We're offered a v4 prefix */
517 if (pfx->family > 0 && type_str) {
518 p.family = pfx->family;
519 p.prefixlen = pfx->prefixlen;
520 p.u.prefix4 = pfx->prefix;
521
522 type = proto_redistnum(AFI_IP, type_str);
523 if (type < 0) {
524 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
525 return CMD_WARNING;
526 }
527 } else if (pfx->family > 0 || type_str) {
528 vty_out(vty, "%% Must supply both prefix and type\n");
529 return CMD_WARNING;
530 }
531
532 nhgc = nhgc_find(nhgname);
533 if (!nhgc) {
534 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
535 nhgname);
536 return CMD_WARNING;
537 }
538
539 if (nhgc->nhg.nexthop == NULL) {
540 vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname);
541 return CMD_WARNING;
542 }
543
665edffd
MS
544 /* Use group's backup nexthop info if present */
545 if (nhgc->backup_list_name[0]) {
546 backup_nhgc = nhgc_find(nhgc->backup_list_name);
547
548 if (!backup_nhgc) {
549 vty_out(vty,
550 "%% Backup group %s not found for group %s\n",
551 nhgc->backup_list_name,
552 nhgname);
553 return CMD_WARNING;
554 }
555 backup_nhg = &(backup_nhgc->nhg);
556 }
557
faa75dfa
MS
558 if (sharp_install_lsps_helper(true /*install*/, update_p,
559 pfx->family > 0 ? &p : NULL,
c9e5adba 560 type, instance, inlabel,
665edffd 561 &(nhgc->nhg), backup_nhg) == 0)
c9e5adba
MS
562 return CMD_SUCCESS;
563 else {
564 vty_out(vty, "%% LSP install failed!\n");
565 return CMD_WARNING;
566 }
567}
568
569DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd,
570 "sharp remove lsp \
571 (0-100000)$inlabel\
665edffd 572 [nexthop-group NHGNAME$nhgname] \
c9e5adba 573 [prefix A.B.C.D/M$pfx\
20c9e649 574 " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
c9e5adba
MS
575 "Sharp Routing Protocol\n"
576 "Remove data\n"
577 "Remove an LSP\n"
578 "The ingress label\n"
579 "Use nexthops from a nexthop-group\n"
580 "The nexthop-group name\n"
581 "Specify a v4 prefix\n"
582 "The v4 prefix to label\n"
20c9e649 583 FRR_IP_REDIST_HELP_STR_ZEBRA
c9e5adba
MS
584 "Routing instance\n"
585 "Instance to use\n")
586{
587 struct nexthop_group_cmd *nhgc = NULL;
588 struct prefix p = {};
589 int type = 0;
665edffd 590 struct nexthop_group *nhg = NULL;
c9e5adba
MS
591
592 /* We're offered a v4 prefix */
593 if (pfx->family > 0 && type_str) {
594 p.family = pfx->family;
595 p.prefixlen = pfx->prefixlen;
596 p.u.prefix4 = pfx->prefix;
597
598 type = proto_redistnum(AFI_IP, type_str);
599 if (type < 0) {
600 vty_out(vty, "%% Unknown route type '%s'\n", type_str);
601 return CMD_WARNING;
602 }
603 } else if (pfx->family > 0 || type_str) {
604 vty_out(vty, "%% Must supply both prefix and type\n");
605 return CMD_WARNING;
606 }
607
665edffd
MS
608 if (nhgname) {
609 nhgc = nhgc_find(nhgname);
610 if (!nhgc) {
611 vty_out(vty, "%% Nexthop-group '%s' does not exist\n",
612 nhgname);
613 return CMD_WARNING;
614 }
c9e5adba 615
665edffd
MS
616 if (nhgc->nhg.nexthop == NULL) {
617 vty_out(vty, "%% Nexthop-group '%s' is empty\n",
618 nhgname);
619 return CMD_WARNING;
620 }
621 nhg = &(nhgc->nhg);
c9e5adba
MS
622 }
623
faa75dfa
MS
624 if (sharp_install_lsps_helper(false /*!install*/, false,
625 pfx->family > 0 ? &p : NULL,
665edffd 626 type, instance, inlabel, nhg, NULL) == 0)
c9e5adba
MS
627 return CMD_SUCCESS;
628 else {
629 vty_out(vty, "%% LSP remove failed!\n");
630 return CMD_WARNING;
631 }
632}
633
aef4a13f
DL
634DEFPY (logpump,
635 logpump_cmd,
636 "sharp logpump duration (1-60) frequency (1-1000000) burst (1-1000)",
637 "Sharp Routing Protocol\n"
638 "Generate bulk log messages for testing\n"
639 "Duration of run (s)\n"
640 "Duration of run (s)\n"
641 "Frequency of bursts (s^-1)\n"
642 "Frequency of bursts (s^-1)\n"
643 "Number of log messages per each burst\n"
644 "Number of log messages per each burst\n")
645{
646 sharp_logpump_run(vty, duration, frequency, burst);
647 return CMD_SUCCESS;
648}
649
2be4d61a
MS
650DEFPY (create_session,
651 create_session_cmd,
652 "sharp create session (1-1024)",
653 "Sharp Routing Protocol\n"
654 "Create data\n"
655 "Create a test session\n"
656 "Session ID\n")
657{
658 if (sharp_zclient_create(session) != 0) {
659 vty_out(vty, "%% Client session error\n");
660 return CMD_WARNING;
661 }
662
663 return CMD_SUCCESS;
664}
665
666DEFPY (remove_session,
667 remove_session_cmd,
668 "sharp remove session (1-1024)",
669 "Sharp Routing Protocol\n"
670 "Remove data\n"
671 "Remove a test session\n"
672 "Session ID\n")
673{
674 sharp_zclient_delete(session);
675 return CMD_SUCCESS;
676}
677
2ac6c90d
MS
678DEFPY (send_opaque,
679 send_opaque_cmd,
680 "sharp send opaque type (1-255) (1-1000)$count",
478ff17b 681 SHARP_STR
2ac6c90d
MS
682 "Send messages for testing\n"
683 "Send opaque messages\n"
684 "Type code to send\n"
685 "Type code to send\n"
686 "Number of messages to send\n")
687{
c8b27f2a
MS
688 sharp_opaque_send(type, 0, 0, 0, count);
689 return CMD_SUCCESS;
690}
691
692DEFPY (send_opaque_unicast,
693 send_opaque_unicast_cmd,
694 "sharp send opaque unicast type (1-255) \
695 " FRR_IP_REDIST_STR_ZEBRA "$proto_str \
696 [{instance (0-1000) | session (1-1000)}] (1-1000)$count",
697 SHARP_STR
698 "Send messages for testing\n"
699 "Send opaque messages\n"
700 "Send unicast messages\n"
701 "Type code to send\n"
702 "Type code to send\n"
703 FRR_IP_REDIST_HELP_STR_ZEBRA
704 "Daemon instance\n"
705 "Daemon instance\n"
706 "Session ID\n"
707 "Session ID\n"
708 "Number of messages to send\n")
709{
710 uint32_t proto;
711
712 proto = proto_redistnum(AFI_IP, proto_str);
713
714 sharp_opaque_send(type, proto, instance, session, count);
715
2ac6c90d
MS
716 return CMD_SUCCESS;
717}
718
939b2339
MS
719DEFPY (send_opaque_reg,
720 send_opaque_reg_cmd,
721 "sharp send opaque <reg$reg | unreg> \
722 " FRR_IP_REDIST_STR_ZEBRA "$proto_str \
723 [{instance (0-1000) | session (1-1000)}] type (1-1000)",
478ff17b 724 SHARP_STR
939b2339
MS
725 "Send messages for testing\n"
726 "Send opaque messages\n"
727 "Send opaque registration\n"
728 "Send opaque unregistration\n"
729 FRR_IP_REDIST_HELP_STR_ZEBRA
730 "Daemon instance\n"
731 "Daemon instance\n"
732 "Session ID\n"
733 "Session ID\n"
734 "Opaque sub-type code\n"
735 "Opaque sub-type code\n")
736{
737 int proto;
738
739 proto = proto_redistnum(AFI_IP, proto_str);
740
741 sharp_opaque_reg_send((reg != NULL), proto, instance, session, type);
742 return CMD_SUCCESS;
743}
744
da187b77
JU
745DEFPY (neigh_discover,
746 neigh_discover_cmd,
747 "sharp neigh discover [vrf NAME$vrf_name] <A.B.C.D$dst4|X:X::X:X$dst6> IFNAME$ifname",
748 SHARP_STR
749 "Discover neighbours\n"
750 "Send an ARP/NDP request\n"
751 VRF_CMD_HELP_STR
752 "v4 Destination address\n"
753 "v6 Destination address\n"
754 "Interface name\n")
755{
756 struct vrf *vrf;
757 struct interface *ifp;
758 struct prefix prefix;
759
760 memset(&prefix, 0, sizeof(prefix));
761
3a6290bd 762 if (dst4.s_addr != INADDR_ANY) {
da187b77
JU
763 prefix.family = AF_INET;
764 prefix.prefixlen = 32;
765 prefix.u.prefix4 = dst4;
766 } else {
767 prefix.family = AF_INET6;
768 prefix.prefixlen = 128;
769 prefix.u.prefix6 = dst6;
770 }
771
772 vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME);
773 if (!vrf) {
774 vty_out(vty, "The vrf NAME specified: %s does not exist\n",
775 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
776 return CMD_WARNING;
777 }
778
779 ifp = if_lookup_by_name_vrf(ifname, vrf);
780 if (ifp == NULL) {
781 vty_out(vty, "%% Can't find interface %s\n", ifname);
782 return CMD_WARNING;
783 }
784
785 sharp_zebra_send_arp(ifp, &prefix);
786
787 return CMD_SUCCESS;
788}
789
1888e243
OD
790DEFPY (import_te,
791 import_te_cmd,
792 "sharp import-te",
793 SHARP_STR
794 "Import Traffic Engineering\n")
795{
796 sg.ted = ls_ted_new(1, "Sharp", 0);
797 sharp_zebra_register_te();
798
799 return CMD_SUCCESS;
800}
801
ade3eebc
HS
802DEFPY (sharp_srv6_manager_get_locator_chunk,
803 sharp_srv6_manager_get_locator_chunk_cmd,
804 "sharp srv6-manager get-locator-chunk NAME$locator_name",
805 SHARP_STR
806 "Segment-Routing IPv6\n"
807 "Get SRv6 locator-chunk\n"
808 "SRv6 Locator name\n")
809{
810 int ret;
811 struct listnode *node;
812 struct sharp_srv6_locator *loc;
813 struct sharp_srv6_locator *loc_found = NULL;
814
815 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, node, loc)) {
816 if (strcmp(loc->name, locator_name))
817 continue;
818 loc_found = loc;
819 break;
820 }
821 if (!loc_found) {
822 loc = XCALLOC(MTYPE_SRV6_LOCATOR,
823 sizeof(struct sharp_srv6_locator));
824 loc->chunks = list_new();
825 snprintf(loc->name, SRV6_LOCNAME_SIZE, "%s", locator_name);
826 listnode_add(sg.srv6_locators, loc);
827 }
828
829 ret = sharp_zebra_srv6_manager_get_locator_chunk(locator_name);
830 if (ret < 0)
831 return CMD_WARNING_CONFIG_FAILED;
832
833 return CMD_SUCCESS;
834}
835
1888e243
OD
836DEFUN (show_sharp_ted,
837 show_sharp_ted_cmd,
838 "show sharp ted [<vertex [A.B.C.D]|edge [A.B.C.D]|subnet [A.B.C.D/M]>] [verbose|json]",
839 SHOW_STR
840 SHARP_STR
841 "Traffic Engineering Database\n"
842 "MPLS-TE Vertex\n"
843 "MPLS-TE router ID (as an IP address)\n"
844 "MPLS-TE Edge\n"
845 "MPLS-TE Edge ID (as an IP address)\n"
846 "MPLS-TE Subnet\n"
847 "MPLS-TE Subnet ID (as an IP prefix)\n"
848 "Verbose output\n"
849 JSON_STR)
850{
851 int idx = 0;
852 struct in_addr ip_addr;
853 struct prefix pref;
854 struct ls_vertex *vertex;
855 struct ls_edge *edge;
856 struct ls_subnet *subnet;
857 uint64_t key;
858 bool verbose = false;
859 bool uj = use_json(argc, argv);
860 json_object *json = NULL;
861
862 if (sg.ted == NULL) {
863 vty_out(vty, "MPLS-TE import is not enabled\n");
864 return CMD_WARNING;
865 }
866
867 if (uj)
868 json = json_object_new_object();
869
870 if (argv[argc - 1]->arg && strmatch(argv[argc - 1]->text, "verbose"))
871 verbose = true;
872
873 if (argv_find(argv, argc, "vertex", &idx)) {
874 /* Show Vertex */
875 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
876 if (!inet_aton(argv[idx + 1]->arg, &ip_addr)) {
877 vty_out(vty,
878 "Specified Router ID %s is invalid\n",
879 argv[idx + 1]->arg);
880 return CMD_WARNING_CONFIG_FAILED;
881 }
882 /* Get the Vertex from the Link State Database */
883 key = ((uint64_t)ip_addr.s_addr) & 0xffffffff;
884 vertex = ls_find_vertex_by_key(sg.ted, key);
885 if (!vertex) {
886 vty_out(vty, "No vertex found for ID %pI4\n",
887 &ip_addr);
888 return CMD_WARNING;
889 }
890 } else
891 vertex = NULL;
892
893 if (vertex)
894 ls_show_vertex(vertex, vty, json, verbose);
895 else
896 ls_show_vertices(sg.ted, vty, json, verbose);
897
898 } else if (argv_find(argv, argc, "edge", &idx)) {
899 /* Show Edge */
900 if (argv_find(argv, argc, "A.B.C.D", &idx)) {
901 if (!inet_aton(argv[idx]->arg, &ip_addr)) {
902 vty_out(vty,
903 "Specified Edge ID %s is invalid\n",
904 argv[idx]->arg);
905 return CMD_WARNING_CONFIG_FAILED;
906 }
907 /* Get the Edge from the Link State Database */
908 key = ((uint64_t)ip_addr.s_addr) & 0xffffffff;
909 edge = ls_find_edge_by_key(sg.ted, key);
910 if (!edge) {
911 vty_out(vty, "No edge found for ID %pI4\n",
912 &ip_addr);
913 return CMD_WARNING;
914 }
915 } else
916 edge = NULL;
917
918 if (edge)
919 ls_show_edge(edge, vty, json, verbose);
920 else
921 ls_show_edges(sg.ted, vty, json, verbose);
922
923 } else if (argv_find(argv, argc, "subnet", &idx)) {
924 /* Show Subnet */
925 if (argv_find(argv, argc, "A.B.C.D/M", &idx)) {
926 if (!str2prefix(argv[idx]->arg, &pref)) {
927 vty_out(vty, "Invalid prefix format %s\n",
928 argv[idx]->arg);
929 return CMD_WARNING_CONFIG_FAILED;
930 }
931 /* Get the Subnet from the Link State Database */
932 subnet = ls_find_subnet(sg.ted, pref);
933 if (!subnet) {
934 vty_out(vty, "No subnet found for ID %pFX\n",
935 &pref);
936 return CMD_WARNING;
937 }
938 } else
939 subnet = NULL;
940
941 if (subnet)
942 ls_show_subnet(subnet, vty, json, verbose);
943 else
944 ls_show_subnets(sg.ted, vty, json, verbose);
945
946 } else {
947 /* Show the complete TED */
948 ls_show_ted(sg.ted, vty, json, verbose);
949 }
950
951 if (uj) {
952 vty_out(vty, "%s\n",
953 json_object_to_json_string_ext(
954 json, JSON_C_TO_STRING_PRETTY));
955 json_object_free(json);
956 }
ade3eebc
HS
957
958 return CMD_SUCCESS;
959}
960
961DEFPY (sharp_srv6_manager_release_locator_chunk,
962 sharp_srv6_manager_release_locator_chunk_cmd,
963 "sharp srv6-manager release-locator-chunk NAME$locator_name",
964 SHARP_STR
965 "Segment-Routing IPv6\n"
966 "Release SRv6 locator-chunk\n"
967 "SRv6 Locator name\n")
968{
969 int ret;
970 struct listnode *loc_node;
971 struct sharp_srv6_locator *loc;
972
973 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, loc_node, loc)) {
974 if (!strcmp(loc->name, locator_name)) {
975 list_delete_all_node(loc->chunks);
976 list_delete(&loc->chunks);
977 listnode_delete(sg.srv6_locators, loc);
978 break;
979 }
980 }
981
982 ret = sharp_zebra_srv6_manager_release_locator_chunk(locator_name);
983 if (ret < 0)
984 return CMD_WARNING_CONFIG_FAILED;
985
986 return CMD_SUCCESS;
987}
988
989DEFPY (show_sharp_segment_routing_srv6,
990 show_sharp_segment_routing_srv6_cmd,
a2df1e4f 991 "show sharp segment-routing srv6 [json]",
ade3eebc
HS
992 SHOW_STR
993 SHARP_STR
994 "Segment-Routing\n"
a2df1e4f
HS
995 "Segment-Routing IPv6\n"
996 JSON_STR)
ade3eebc
HS
997{
998 char str[256];
999 struct listnode *loc_node;
1000 struct listnode *chunk_node;
1001 struct sharp_srv6_locator *loc;
1002 struct prefix_ipv6 *chunk;
a2df1e4f 1003 bool uj = use_json(argc, argv);
ade3eebc
HS
1004 json_object *jo_locs = NULL;
1005 json_object *jo_loc = NULL;
1006 json_object *jo_chunks = NULL;
1007
a2df1e4f
HS
1008 if (uj) {
1009 jo_locs = json_object_new_array();
1010 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, loc_node, loc)) {
1011 jo_loc = json_object_new_object();
1012 json_object_array_add(jo_locs, jo_loc);
1013 json_object_string_add(jo_loc, "name", loc->name);
1014 jo_chunks = json_object_new_array();
1015 json_object_object_add(jo_loc, "chunks", jo_chunks);
1016 for (ALL_LIST_ELEMENTS_RO(loc->chunks, chunk_node,
1017 chunk)) {
1018 prefix2str(chunk, str, sizeof(str));
1019 json_array_string_add(jo_chunks, str);
1020 }
1021 }
1022
1023 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1024 jo_locs, JSON_C_TO_STRING_PRETTY));
1025 json_object_free(jo_locs);
1026 } else {
1027 for (ALL_LIST_ELEMENTS_RO(sg.srv6_locators, loc_node, loc)) {
1028 vty_out(vty, "Locator %s has %d prefix chunks\n",
1029 loc->name, listcount(loc->chunks));
1030 for (ALL_LIST_ELEMENTS_RO(loc->chunks, chunk_node,
1031 chunk)) {
1032 prefix2str(chunk, str, sizeof(str));
1033 vty_out(vty, " %s\n", str);
1034 }
1035 vty_out(vty, "\n");
ade3eebc
HS
1036 }
1037 }
1038
1888e243
OD
1039 return CMD_SUCCESS;
1040}
1041
8a71d93d
DS
1042void sharp_vty_init(void)
1043{
f59e6418 1044 install_element(ENABLE_NODE, &install_routes_data_dump_cmd);
8a71d93d
DS
1045 install_element(ENABLE_NODE, &install_routes_cmd);
1046 install_element(ENABLE_NODE, &remove_routes_cmd);
ab18a495 1047 install_element(ENABLE_NODE, &vrf_label_cmd);
86da53ab 1048 install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);
921af54d 1049 install_element(ENABLE_NODE, &watch_redistribute_cmd);
0ae8130d
DS
1050 install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
1051 install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
c9e5adba
MS
1052 install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
1053 install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd);
aef4a13f 1054 install_element(ENABLE_NODE, &logpump_cmd);
2be4d61a
MS
1055 install_element(ENABLE_NODE, &create_session_cmd);
1056 install_element(ENABLE_NODE, &remove_session_cmd);
2ac6c90d 1057 install_element(ENABLE_NODE, &send_opaque_cmd);
c8b27f2a 1058 install_element(ENABLE_NODE, &send_opaque_unicast_cmd);
939b2339 1059 install_element(ENABLE_NODE, &send_opaque_reg_cmd);
da187b77 1060 install_element(ENABLE_NODE, &neigh_discover_cmd);
1888e243 1061 install_element(ENABLE_NODE, &import_te_cmd);
aaf8c96f 1062
dd73744d 1063 install_element(ENABLE_NODE, &show_debugging_sharpd_cmd);
1888e243 1064 install_element(ENABLE_NODE, &show_sharp_ted_cmd);
aaf8c96f 1065
ade3eebc 1066 install_element(ENABLE_NODE, &sharp_srv6_manager_get_locator_chunk_cmd);
4df9d859
HS
1067 install_element(ENABLE_NODE,
1068 &sharp_srv6_manager_release_locator_chunk_cmd);
ade3eebc
HS
1069 install_element(ENABLE_NODE, &show_sharp_segment_routing_srv6_cmd);
1070
8a71d93d
DS
1071 return;
1072}