]> git.proxmox.com Git - mirror_frr.git/blame - pbrd/pbr_vty.c
pbrd: use spaces in show pbr map vty output
[mirror_frr.git] / pbrd / pbr_vty.c
CommitLineData
e5c83d9b
DS
1/*
2 * PBR - vty code
3 * Copyright (C) 2018 Cumulus Networks, Inc.
4 * Donald Sharp
5 *
6 * FRR is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
9 * later version.
10 *
11 * FRR is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20#include <zebra.h>
21
22#include "vty.h"
23#include "command.h"
24#include "prefix.h"
25#include "vrf.h"
26#include "nexthop.h"
27#include "nexthop_group.h"
50d89650 28#include "nexthop_group_private.h"
e5c83d9b 29#include "log.h"
e5c83d9b 30#include "debug.h"
8c28c034 31#include "pbr.h"
e5c83d9b
DS
32
33#include "pbrd/pbr_nht.h"
34#include "pbrd/pbr_map.h"
35#include "pbrd/pbr_zebra.h"
36#include "pbrd/pbr_vty.h"
e5c83d9b
DS
37#include "pbrd/pbr_debug.h"
38#ifndef VTYSH_EXTRACT_PL
39#include "pbrd/pbr_vty_clippy.c"
40#endif
41
17f8c652 42DEFUN_NOSH(pbr_map, pbr_map_cmd, "pbr-map PBRMAP seq (1-700)",
e5c83d9b
DS
43 "Create pbr-map or enter pbr-map command mode\n"
44 "The name of the PBR MAP\n"
45 "Sequence to insert in existing pbr-map entry\n"
46 "Sequence number\n")
47{
48 const char *pbrm_name = argv[1]->arg;
49 uint32_t seqno = atoi(argv[3]->arg);
50 struct pbr_map_sequence *pbrms;
51
52 pbrms = pbrms_get(pbrm_name, seqno);
53 VTY_PUSH_CONTEXT(PBRMAP_NODE, pbrms);
54
55 return CMD_SUCCESS;
56}
57
17f8c652 58DEFUN_NOSH(no_pbr_map, no_pbr_map_cmd, "no pbr-map PBRMAP [seq (1-700)]",
e5c83d9b
DS
59 NO_STR
60 "Delete pbr-map\n"
61 "The name of the PBR MAP\n"
62 "Sequence to delete from existing pbr-map entry\n"
63 "Sequence number\n")
64{
65 const char *pbrm_name = argv[2]->arg;
66 uint32_t seqno = 0;
67 struct pbr_map *pbrm = pbrm_find(pbrm_name);
e5c83d9b
DS
68 struct pbr_map_sequence *pbrms;
69 struct listnode *node, *next_node;
70
71 if (argc > 3)
72 seqno = atoi(argv[4]->arg);
73
74 if (!pbrm) {
75 vty_out(vty, "pbr-map %s not found\n", pbrm_name);
76 return CMD_SUCCESS;
77 }
78
b13e5ad6
DS
79 for (ALL_LIST_ELEMENTS(pbrm->seqnumbers, node, next_node, pbrms)) {
80 if (seqno && pbrms->seqno != seqno)
81 continue;
e5c83d9b 82
b13e5ad6
DS
83 pbr_map_delete(pbrms);
84 }
e5c83d9b
DS
85
86 return CMD_SUCCESS;
87}
88
7bec514c
QY
89DEFPY(pbr_set_table_range,
90 pbr_set_table_range_cmd,
91 "[no] pbr table range (10000-4294966272)$lb (10000-4294966272)$ub",
92 NO_STR
93 PBR_STR
94 "Set table ID range\n"
95 "Set table ID range\n"
96 "Lower bound for table ID range\n"
97 "Upper bound for table ID range\n")
98{
99 /* upper bound is 2^32 - 2^10 */
100 int ret = CMD_WARNING;
a4044dc1 101 const int minrange = 1000;
7bec514c
QY
102
103 /* validate given bounds */
104 if (lb > ub)
105 vty_out(vty, "%% Lower bound must be less than upper bound\n");
a4044dc1
QY
106 else if (ub - lb < minrange)
107 vty_out(vty, "%% Range breadth must be at least %d\n", minrange);
7bec514c
QY
108 else {
109 ret = CMD_SUCCESS;
110 pbr_nht_set_tableid_range((uint32_t) lb, (uint32_t) ub);
111 }
112
113 return ret;
114}
115
116
e5c83d9b
DS
117DEFPY(pbr_map_match_src, pbr_map_match_src_cmd,
118 "[no] match src-ip <A.B.C.D/M|X:X::X:X/M>$prefix",
119 NO_STR
120 "Match the rest of the command\n"
121 "Choose the src ip or ipv6 prefix to use\n"
122 "v4 Prefix\n"
123 "v6 Prefix\n")
124{
125 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
e5c83d9b 126
49027ce8
DS
127 pbrms->family = prefix->family;
128
e5c83d9b 129 if (!no) {
5d0e49c4
SW
130 if (pbrms->src) {
131 if (prefix_same(pbrms->src, prefix))
132 return CMD_SUCCESS;
133
0dcff6f4
SW
134 vty_out(vty,
135 "A `match src-ip XX` command already exists, please remove that first\n");
136 return CMD_WARNING_CONFIG_FAILED;
5d0e49c4
SW
137 }
138
139 pbrms->src = prefix_new();
e5c83d9b 140 prefix_copy(pbrms->src, prefix);
63265b5c
DS
141 } else
142 prefix_free(&pbrms->src);
e5c83d9b 143
b13e5ad6 144 pbr_map_check(pbrms);
e5c83d9b
DS
145
146 return CMD_SUCCESS;
147}
148
149DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd,
150 "[no] match dst-ip <A.B.C.D/M|X:X::X:X/M>$prefix",
151 NO_STR
152 "Match the rest of the command\n"
6c4c9a6c 153 "Choose the dst ip or ipv6 prefix to use\n"
e5c83d9b
DS
154 "v4 Prefix\n"
155 "v6 Prefix\n")
156{
157 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
e5c83d9b 158
49027ce8
DS
159 pbrms->family = prefix->family;
160
e5c83d9b 161 if (!no) {
5d0e49c4
SW
162 if (pbrms->dst) {
163 if (prefix_same(pbrms->dst, prefix))
164 return CMD_SUCCESS;
165
0dcff6f4
SW
166 vty_out(vty,
167 "A `match dst-ip XX` command already exists, please remove that first\n");
168 return CMD_WARNING_CONFIG_FAILED;
5d0e49c4
SW
169 }
170
171 pbrms->dst = prefix_new();
e5c83d9b 172 prefix_copy(pbrms->dst, prefix);
63265b5c
DS
173 } else
174 prefix_free(&pbrms->dst);
e5c83d9b 175
b13e5ad6 176 pbr_map_check(pbrms);
e5c83d9b
DS
177
178 return CMD_SUCCESS;
179}
180
95a9fe02
MM
181DEFPY(pbr_map_match_mark, pbr_map_match_mark_cmd,
182 "[no] match mark (1-4294967295)$mark",
183 NO_STR
184 "Match the rest of the command\n"
185 "Choose the mark value to use\n"
186 "mark\n")
187{
188 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
189
190#ifndef GNU_LINUX
191 vty_out(vty, "pbr marks are not supported on this platform");
192 return CMD_WARNING_CONFIG_FAILED;
193#endif
194
195 if (!no) {
5d0e49c4
SW
196 if (pbrms->mark) {
197 if (pbrms->mark == (uint32_t)mark)
198 return CMD_SUCCESS;
199
46b03820
SW
200 vty_out(vty,
201 "A `match mark XX` command already exists, please remove that first\n");
202 return CMD_WARNING_CONFIG_FAILED;
5d0e49c4
SW
203 }
204
205 pbrms->mark = (uint32_t)mark;
206 } else
95a9fe02 207 pbrms->mark = 0;
95a9fe02
MM
208
209 pbr_map_check(pbrms);
210
211 return CMD_SUCCESS;
be3b67b5
SW
212}
213
214#define SET_VRF_EXISTS_STR \
215 "A `set vrf XX` command already exists, please remove that first\n"
95a9fe02 216
e5c83d9b 217DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
be3b67b5
SW
218 "[no] set nexthop-group NHGNAME$name",
219 NO_STR
220 "Set for the PBR-MAP\n"
221 "nexthop-group to use\n"
222 "The name of the nexthop-group\n")
e5c83d9b
DS
223{
224 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
225 struct nexthop_group_cmd *nhgc;
e5c83d9b 226
e042a421
DS
227 if (pbrms->nhg) {
228 vty_out(vty,
229 "A `set nexthop XX` command already exists, please remove that first\n");
3a9210c2 230 return CMD_WARNING_CONFIG_FAILED;
e042a421
DS
231 }
232
be3b67b5
SW
233 if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
234 vty_out(vty, SET_VRF_EXISTS_STR);
235 return CMD_WARNING_CONFIG_FAILED;
236 }
237
e5c83d9b
DS
238 nhgc = nhgc_find(name);
239 if (!nhgc) {
240 vty_out(vty, "Specified nexthop-group %s does not exist\n",
241 name);
be3b67b5
SW
242 vty_out(vty,
243 "PBR-MAP will not be applied until it is created\n");
e5c83d9b
DS
244 }
245
246 if (no) {
247 if (pbrms->nhgrp_name && strcmp(name, pbrms->nhgrp_name) == 0)
be3b67b5 248 pbr_map_delete_nexthops(pbrms);
e5c83d9b
DS
249 else {
250 vty_out(vty,
47f94d17 251 "Nexthop Group specified: %s does not exist to remove\n",
e5c83d9b 252 name);
3a9210c2 253 return CMD_WARNING_CONFIG_FAILED;
e5c83d9b
DS
254 }
255 } else {
256 if (pbrms->nhgrp_name) {
257 if (strcmp(name, pbrms->nhgrp_name) != 0) {
258 vty_out(vty,
47f94d17 259 "Please delete current nexthop group before modifying current one\n");
3a9210c2 260 return CMD_WARNING_CONFIG_FAILED;
e5c83d9b
DS
261 }
262
263 return CMD_SUCCESS;
264 }
265 pbrms->nhgrp_name = XSTRDUP(MTYPE_TMP, name);
b13e5ad6 266 pbr_map_check(pbrms);
e5c83d9b
DS
267 }
268
e5c83d9b
DS
269 return CMD_SUCCESS;
270}
271
272DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
9c0fd853
RW
273 "[no] set nexthop\
274 <\
275 <A.B.C.D|X:X::X:X>$addr [INTERFACE$intf]\
276 |INTERFACE$intf\
277 >\
e429a2a0 278 [nexthop-vrf NAME$vrf_name]",
e5c83d9b
DS
279 NO_STR
280 "Set for the PBR-MAP\n"
281 "Specify one of the nexthops in this map\n"
282 "v4 Address\n"
283 "v6 Address\n"
284 "Interface to use\n"
9c0fd853 285 "Interface to use\n"
e5c83d9b
DS
286 "If the nexthop is in a different vrf tell us\n"
287 "The nexthop-vrf Name\n")
288{
289 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
290 struct vrf *vrf;
291 struct nexthop nhop;
292 struct nexthop *nh;
e5c83d9b
DS
293
294 if (pbrms->nhgrp_name) {
295 vty_out(vty,
47f94d17 296 "Please unconfigure the nexthop group before adding an individual nexthop\n");
3a9210c2 297 return CMD_WARNING_CONFIG_FAILED;
e5c83d9b
DS
298 }
299
be3b67b5
SW
300 if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
301 vty_out(vty, SET_VRF_EXISTS_STR);
302 return CMD_WARNING_CONFIG_FAILED;
303 }
304
e429a2a0
IR
305 if (vrf_name)
306 vrf = vrf_lookup_by_name(vrf_name);
e5c83d9b
DS
307 else
308 vrf = vrf_lookup_by_id(VRF_DEFAULT);
309
310 if (!vrf) {
e429a2a0 311 vty_out(vty, "Specified: %s is non-existent\n", vrf_name);
3a9210c2 312 return CMD_WARNING_CONFIG_FAILED;
e5c83d9b
DS
313 }
314
315 memset(&nhop, 0, sizeof(nhop));
316 nhop.vrf_id = vrf->vrf_id;
317
9c0fd853
RW
318 if (intf) {
319 nhop.ifindex = ifname2ifindex(intf, vrf->vrf_id);
320 if (nhop.ifindex == IFINDEX_INTERNAL) {
321 vty_out(vty,
322 "Specified Intf %s does not exist in vrf: %s\n",
323 intf, vrf->name);
324 return CMD_WARNING_CONFIG_FAILED;
325 }
326 }
327
328 if (addr) {
329 if (addr->sa.sa_family == AF_INET) {
330 nhop.gate.ipv4.s_addr = addr->sin.sin_addr.s_addr;
331 if (intf)
332 nhop.type = NEXTHOP_TYPE_IPV4_IFINDEX;
333 else
334 nhop.type = NEXTHOP_TYPE_IPV4;
cafec8da 335 } else {
9c0fd853
RW
336 nhop.gate.ipv6 = addr->sin6.sin6_addr;
337 if (intf)
338 nhop.type = NEXTHOP_TYPE_IPV6_IFINDEX;
339 else {
340 if (IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6)) {
341 vty_out(vty,
342 "Specified a v6 LL with no interface, rejecting\n");
343 return CMD_WARNING_CONFIG_FAILED;
344 }
345 nhop.type = NEXTHOP_TYPE_IPV6;
cafec8da 346 }
cafec8da 347 }
9c0fd853
RW
348 } else
349 nhop.type = NEXTHOP_TYPE_IFINDEX;
e5c83d9b
DS
350
351 if (pbrms->nhg)
352 nh = nexthop_exists(pbrms->nhg, &nhop);
353 else {
06210d1f 354 char buf[PBR_NHC_NAMELEN];
e5c83d9b
DS
355
356 if (no) {
220c5830 357 vty_out(vty, "No nexthops to delete\n");
3a9210c2 358 return CMD_WARNING_CONFIG_FAILED;
e5c83d9b
DS
359 }
360
361 pbrms->nhg = nexthop_group_new();
362 pbrms->internal_nhg_name =
363 XSTRDUP(MTYPE_TMP,
364 pbr_nht_nexthop_make_name(pbrms->parent->name,
06210d1f 365 PBR_NHC_NAMELEN,
e5c83d9b
DS
366 pbrms->seqno,
367 buf));
368 nh = NULL;
369 }
370
371 if (no) {
b13e5ad6
DS
372 if (nh)
373 pbr_nht_delete_individual_nexthop(pbrms);
e5c83d9b
DS
374 } else if (!nh) {
375
376 if (pbrms->nhg->nexthop) {
377 vty_out(vty,
47f94d17 378 "If you would like more than one nexthop please use nexthop-groups\n");
3a9210c2 379 return CMD_WARNING_CONFIG_FAILED;
e5c83d9b
DS
380 }
381
382 /* must be adding new nexthop since !no and !nexthop_exists */
383 nh = nexthop_new();
384
385 memcpy(nh, &nhop, sizeof(nhop));
50d89650 386 _nexthop_add(&pbrms->nhg->nexthop, nh);
e5c83d9b 387
b13e5ad6
DS
388 pbr_nht_add_individual_nexthop(pbrms);
389 pbr_map_check(pbrms);
e5c83d9b
DS
390 }
391
cb254f41
SW
392 if (nhop.type == NEXTHOP_TYPE_IFINDEX
393 || (nhop.type == NEXTHOP_TYPE_IPV6_IFINDEX
394 && IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6))) {
9c0fd853
RW
395 struct interface *ifp;
396
397 ifp = if_lookup_by_index(nhop.ifindex, nhop.vrf_id);
398 if (ifp)
399 pbr_nht_nexthop_interface_update(ifp);
400 }
401
e5c83d9b
DS
402 return CMD_SUCCESS;
403}
404
be3b67b5
SW
405DEFPY(pbr_map_vrf, pbr_map_vrf_cmd,
406 "[no] set vrf <NAME$vrf_name|unchanged>",
407 NO_STR
408 "Set for the PBR-MAP\n"
409 "Specify the VRF for this map\n"
410 "The VRF Name\n"
411 "Use the interface's VRF for lookup\n")
412{
413 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
414 int ret = CMD_SUCCESS;
415
416 if (no) {
417 pbr_map_delete_vrf(pbrms);
418
419 /* Reset all data */
420 pbrms->nhs_installed = false;
421 pbrms->vrf_name[0] = '\0';
422 pbrms->vrf_lookup = false;
423 pbrms->vrf_unchanged = false;
424
425 goto done;
426 }
427
428 if (pbrms->nhgrp_name || pbrms->nhg) {
429 vty_out(vty,
430 "A `set nexthop/nexthop-group XX` command already exits, please remove that first\n");
431 ret = CMD_WARNING_CONFIG_FAILED;
432 goto done;
433 }
434
435 if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
436 vty_out(vty, SET_VRF_EXISTS_STR);
437 ret = CMD_WARNING_CONFIG_FAILED;
438 goto done;
439 }
440
441 if (vrf_name) {
442 if (!pbr_vrf_lookup_by_name(vrf_name)) {
443 vty_out(vty, "Specified: %s is non-existent\n",
444 vrf_name);
445 ret = CMD_WARNING_CONFIG_FAILED;
446 goto done;
447 }
448
449 pbrms->vrf_lookup = true;
450 strlcpy(pbrms->vrf_name, vrf_name, sizeof(pbrms->vrf_name));
451 } else
452 pbrms->vrf_unchanged = true;
453
454 pbr_map_check(pbrms);
455
456done:
457 return ret;
458}
459
e5c83d9b
DS
460DEFPY (pbr_policy,
461 pbr_policy_cmd,
17f8c652 462 "[no] pbr-policy PBRMAP$mapname",
e5c83d9b
DS
463 NO_STR
464 "Policy to use\n"
465 "Name of the pbr-map to apply\n")
466{
467 VTY_DECLVAR_CONTEXT(interface, ifp);
468 struct pbr_map *pbrm, *old_pbrm;
469 struct pbr_interface *pbr_ifp = ifp->info;
470
6eb499b0 471 old_pbrm = NULL;
e5c83d9b
DS
472 pbrm = pbrm_find(mapname);
473
b13e5ad6 474 if (!pbr_ifp) {
d6416967
QY
475 /* we don't want one and we don't have one, so... */
476 if (no)
477 return CMD_SUCCESS;
478
479 /* Some one could have fat fingered the interface name */
b13e5ad6
DS
480 pbr_ifp = pbr_if_new(ifp);
481 }
482
e5c83d9b
DS
483 if (no) {
484 if (strcmp(pbr_ifp->mapname, mapname) == 0) {
5f504f14 485 pbr_ifp->mapname[0] = '\0';
e5c83d9b
DS
486 if (pbrm)
487 pbr_map_interface_delete(pbrm, ifp);
488 }
489 } else {
5f504f14
QY
490 if (strcmp(pbr_ifp->mapname, "") != 0) {
491 old_pbrm = pbrm_find(pbr_ifp->mapname);
6eb499b0
DS
492
493 /*
494 * So if we have an old pbrm we should only
495 * delete it if we are actually deleting and
496 * moving to a new pbrm
497 */
498 if (old_pbrm && old_pbrm != pbrm)
5f504f14 499 pbr_map_interface_delete(old_pbrm, ifp);
e5c83d9b 500 }
5f504f14
QY
501 snprintf(pbr_ifp->mapname, sizeof(pbr_ifp->mapname),
502 "%s", mapname);
6eb499b0
DS
503
504 /*
505 * So only reinstall if the old_pbrm and this pbrm are
506 * different.
507 */
508 if (pbrm && pbrm != old_pbrm)
5f504f14 509 pbr_map_add_interface(pbrm, ifp);
e5c83d9b
DS
510 }
511
512 return CMD_SUCCESS;
513}
514
515DEFPY (show_pbr,
516 show_pbr_cmd,
ef18ed6e 517 "show pbr",
e5c83d9b 518 SHOW_STR
24a21176 519 PBR_STR)
e5c83d9b
DS
520{
521 pbr_nht_write_table_range(vty);
522 pbr_nht_write_rule_range(vty);
523
524 return CMD_SUCCESS;
525}
526
1eaa8361
SW
527static void vty_show_pbrms(struct vty *vty,
528 const struct pbr_map_sequence *pbrms, bool detail)
529{
530 char buf[PREFIX_STRLEN];
531 char rbuf[64];
532
533 if (pbrms->reason)
534 pbr_map_reason_string(pbrms->reason, rbuf, sizeof(rbuf));
3259cde6
SW
535
536 vty_out(vty, " Seq: %u rule: %u\n", pbrms->seqno, pbrms->ruleno);
537
538 if (detail)
b740126d 539 vty_out(vty, " Installed: %" PRIu64 "(%u) Reason: %s\n",
3259cde6
SW
540 pbrms->installed, pbrms->unique,
541 pbrms->reason ? rbuf : "Valid");
542 else
b740126d 543 vty_out(vty, " Installed: %s Reason: %s\n",
3259cde6
SW
544 pbrms->installed ? "yes" : "no",
545 pbrms->reason ? rbuf : "Valid");
1eaa8361
SW
546
547 if (pbrms->src)
b740126d 548 vty_out(vty, " SRC Match: %s\n",
1eaa8361
SW
549 prefix2str(pbrms->src, buf, sizeof(buf)));
550 if (pbrms->dst)
b740126d 551 vty_out(vty, " DST Match: %s\n",
1eaa8361
SW
552 prefix2str(pbrms->dst, buf, sizeof(buf)));
553 if (pbrms->mark)
b740126d 554 vty_out(vty, " MARK Match: %u\n", pbrms->mark);
1eaa8361
SW
555
556 if (pbrms->nhgrp_name) {
b740126d 557 vty_out(vty, " Nexthop-Group: %s\n", pbrms->nhgrp_name);
add5e0a4 558
3259cde6 559 if (detail)
b740126d
SW
560 vty_out(vty,
561 " Installed: %u(%d) Tableid: %d\n",
3259cde6 562 pbrms->nhs_installed,
add5e0a4
SW
563 pbr_nht_get_installed(pbrms->nhgrp_name),
564 pbr_nht_get_table(pbrms->nhgrp_name));
3259cde6 565 else
b740126d 566 vty_out(vty, " Installed: %s Tableid: %d\n",
add5e0a4
SW
567 pbr_nht_get_installed(pbrms->nhgrp_name) ? "yes"
568 : "no",
569 pbr_nht_get_table(pbrms->nhgrp_name));
570
1eaa8361 571 } else if (pbrms->nhg) {
b740126d 572 vty_out(vty, " ");
1eaa8361 573 nexthop_group_write_nexthop(vty, pbrms->nhg->nexthop);
3259cde6 574 if (detail)
b740126d
SW
575 vty_out(vty,
576 " Installed: %u(%d) Tableid: %d\n",
3259cde6
SW
577 pbrms->nhs_installed,
578 pbr_nht_get_installed(pbrms->internal_nhg_name),
579 pbr_nht_get_table(pbrms->internal_nhg_name));
580 else
b740126d 581 vty_out(vty, " Installed: %s Tableid: %d\n",
3259cde6
SW
582 pbr_nht_get_installed(pbrms->internal_nhg_name)
583 ? "yes"
584 : "no",
585 pbr_nht_get_table(pbrms->internal_nhg_name));
586
1eaa8361 587 } else if (pbrms->vrf_unchanged) {
b740126d 588 vty_out(vty, " VRF Unchanged (use interface vrf)\n");
1eaa8361 589 } else if (pbrms->vrf_lookup) {
b740126d 590 vty_out(vty, " VRF Lookup: %s\n", pbrms->vrf_name);
1eaa8361 591 } else {
b740126d 592 vty_out(vty, " Nexthop-Group: Unknown Installed: no\n");
1eaa8361
SW
593 }
594}
595
596static void vty_show_pbr_map(struct vty *vty, const struct pbr_map *pbrm,
597 bool detail)
598{
599 struct pbr_map_sequence *pbrms;
600 struct listnode *node;
601
602 vty_out(vty, " pbr-map %s valid: %d\n", pbrm->name, pbrm->valid);
603
604 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
605 vty_show_pbrms(vty, pbrms, detail);
606}
607
e5c83d9b
DS
608DEFPY (show_pbr_map,
609 show_pbr_map_cmd,
ef18ed6e 610 "show pbr map [NAME$name] [detail$detail]",
e5c83d9b 611 SHOW_STR
24a21176 612 PBR_STR
e5c83d9b
DS
613 "PBR Map\n"
614 "PBR Map Name\n"
ef18ed6e 615 "Detailed information\n")
e5c83d9b 616{
e5c83d9b 617 struct pbr_map *pbrm;
e5c83d9b
DS
618
619 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
620 if (name && strcmp(name, pbrm->name) != 0)
621 continue;
622
1eaa8361 623 vty_show_pbr_map(vty, pbrm, detail);
e5c83d9b
DS
624 }
625 return CMD_SUCCESS;
626}
627
628DEFPY(show_pbr_nexthop_group,
629 show_pbr_nexthop_group_cmd,
630 "show pbr nexthop-groups [WORD$word]",
631 SHOW_STR
24a21176 632 PBR_STR
e5c83d9b
DS
633 "Nexthop Groups\n"
634 "Optional Name of the nexthop group\n")
635{
636 pbr_nht_show_nexthop_group(vty, word);
637
638 return CMD_SUCCESS;
639}
640
641DEFPY (show_pbr_interface,
642 show_pbr_interface_cmd,
ef18ed6e 643 "show pbr interface [NAME$name]",
e5c83d9b 644 SHOW_STR
24a21176 645 PBR_STR
e5c83d9b 646 "PBR Interface\n"
ef18ed6e 647 "PBR Interface Name\n")
e5c83d9b 648{
d3765386 649 struct interface *ifp;
e5c83d9b
DS
650 struct vrf *vrf;
651 struct pbr_interface *pbr_ifp;
652
653 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
654 FOR_ALL_INTERFACES(vrf, ifp) {
655 struct pbr_map *pbrm;
656
1c33fb1d
DS
657 if (!ifp->info)
658 continue;
659
e5c83d9b
DS
660 if (name && strcmp(ifp->name, name) != 0)
661 continue;
662
663 pbr_ifp = ifp->info;
664
665 if (strcmp(pbr_ifp->mapname, "") == 0)
666 continue;
667
668 pbrm = pbrm_find(pbr_ifp->mapname);
669 vty_out(vty, " %s(%d) with pbr-policy %s", ifp->name,
670 ifp->ifindex, pbr_ifp->mapname);
671 if (!pbrm)
672 vty_out(vty, " (map doesn't exist)");
673 vty_out(vty, "\n");
674 }
675 }
676
677 return CMD_SUCCESS;
678}
679
e14f43cc 680/* PBR debugging CLI ------------------------------------------------------- */
e14f43cc
QY
681
682static struct cmd_node debug_node = {DEBUG_NODE, "", 1};
683
684DEFPY(debug_pbr,
685 debug_pbr_cmd,
686 "[no] debug pbr [{map$map|zebra$zebra|nht$nht|events$events}]",
687 NO_STR
688 DEBUG_STR
24a21176 689 PBR_STR
e14f43cc
QY
690 "Policy maps\n"
691 "PBRD <-> Zebra communications\n"
692 "Nexthop tracking\n"
693 "Events\n")
694{
695 uint32_t mode = DEBUG_NODE2MODE(vty->node);
696
697 if (map)
698 DEBUG_MODE_SET(&pbr_dbg_map, mode, !no);
699 if (zebra)
700 DEBUG_MODE_SET(&pbr_dbg_zebra, mode, !no);
701 if (nht)
702 DEBUG_MODE_SET(&pbr_dbg_nht, mode, !no);
703 if (events)
704 DEBUG_MODE_SET(&pbr_dbg_event, mode, !no);
705
706 /* no specific debug --> act on all of them */
707 if (strmatch(argv[argc - 1]->text, "pbr"))
708 pbr_debug_set_all(mode, !no);
709
710 return CMD_SUCCESS;
711}
712
713DEFUN_NOSH(show_debugging_pbr,
714 show_debugging_pbr_cmd,
715 "show debugging [pbr]",
716 SHOW_STR
717 DEBUG_STR
24a21176 718 PBR_STR)
e14f43cc
QY
719{
720 vty_out(vty, "PBR debugging status:\n");
721
722 pbr_debug_config_write_helper(vty, false);
723
724 return CMD_SUCCESS;
725}
726
e14f43cc
QY
727/* ------------------------------------------------------------------------- */
728
729
e5c83d9b
DS
730static struct cmd_node interface_node = {
731 INTERFACE_NODE, "%s(config-if)# ", 1 /* vtysh ? yes */
732};
733
734static int pbr_interface_config_write(struct vty *vty)
735{
736 struct interface *ifp;
737 struct vrf *vrf;
738
739 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
740 FOR_ALL_INTERFACES (vrf, ifp) {
741 if (vrf->vrf_id == VRF_DEFAULT)
742 vty_frame(vty, "interface %s\n", ifp->name);
743 else
744 vty_frame(vty, "interface %s vrf %s\n",
745 ifp->name, vrf->name);
746
91e5b43a
RW
747 if (ifp->desc)
748 vty_out(vty, " description %s\n", ifp->desc);
749
e5c83d9b
DS
750 pbr_map_write_interfaces(vty, ifp);
751
752 vty_endframe(vty, "!\n");
753 }
754 }
755
756 return 1;
757}
758
759/* PBR map node structure. */
760static struct cmd_node pbr_map_node = {PBRMAP_NODE, "%s(config-pbr-map)# ", 1};
761
762static int pbr_vty_map_config_write_sequence(struct vty *vty,
763 struct pbr_map *pbrm,
764 struct pbr_map_sequence *pbrms)
765{
766 char buff[PREFIX_STRLEN];
767
5e44f18f 768 vty_out(vty, "pbr-map %s seq %u\n", pbrm->name, pbrms->seqno);
e5c83d9b
DS
769
770 if (pbrms->src)
7dce96f0 771 vty_out(vty, " match src-ip %s\n",
d3765386 772 prefix2str(pbrms->src, buff, sizeof(buff)));
e5c83d9b
DS
773
774 if (pbrms->dst)
7dce96f0 775 vty_out(vty, " match dst-ip %s\n",
d3765386 776 prefix2str(pbrms->dst, buff, sizeof(buff)));
e5c83d9b 777
95a9fe02
MM
778 if (pbrms->mark)
779 vty_out(vty, " match mark %u\n", pbrms->mark);
780
be3b67b5
SW
781 if (pbrms->vrf_unchanged)
782 vty_out(vty, " set vrf unchanged\n");
783
784 if (pbrms->vrf_lookup)
785 vty_out(vty, " set vrf %s\n", pbrms->vrf_name);
786
e5c83d9b 787 if (pbrms->nhgrp_name)
7dce96f0 788 vty_out(vty, " set nexthop-group %s\n", pbrms->nhgrp_name);
e5c83d9b
DS
789
790 if (pbrms->nhg) {
7dce96f0 791 vty_out(vty, " set ");
e5c83d9b
DS
792 nexthop_group_write_nexthop(vty, pbrms->nhg->nexthop);
793 }
794
5e44f18f 795 vty_out(vty, "!\n");
e5c83d9b
DS
796 return 1;
797}
798
799static int pbr_vty_map_config_write(struct vty *vty)
800{
801 struct pbr_map *pbrm;
802
803 pbr_nht_write_table_range(vty);
804 pbr_nht_write_rule_range(vty);
805
806 RB_FOREACH(pbrm, pbr_map_entry_head, &pbr_maps) {
807 struct pbr_map_sequence *pbrms;
808 struct listnode *node;
809
d3765386 810 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
e5c83d9b 811 pbr_vty_map_config_write_sequence(vty, pbrm, pbrms);
e5c83d9b
DS
812 }
813
814 return 1;
815}
816
17f8c652
DS
817static void pbr_map_completer(vector comps, struct cmd_token *token)
818{
819 struct pbr_map *pbrm;
820
821 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps)
822 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, pbrm->name));
823}
824
825static const struct cmd_variable_handler pbr_map_name[] = {
826 {
827 .tokenname = "PBRMAP", .completions = pbr_map_completer,
828 },
829 {
830 .completions = NULL
831 }
832};
833
e5c83d9b
DS
834void pbr_vty_init(void)
835{
17f8c652
DS
836 cmd_variable_handler_register(pbr_map_name);
837
e5c83d9b
DS
838 install_node(&interface_node,
839 pbr_interface_config_write);
840 if_cmd_init();
841
842 install_node(&pbr_map_node,
843 pbr_vty_map_config_write);
844
e14f43cc
QY
845 /* debug */
846 install_node(&debug_node, pbr_debug_config_write);
847 install_element(VIEW_NODE, &debug_pbr_cmd);
848 install_element(CONFIG_NODE, &debug_pbr_cmd);
849 install_element(VIEW_NODE, &show_debugging_pbr_cmd);
850
e5c83d9b
DS
851 install_default(PBRMAP_NODE);
852
853 install_element(CONFIG_NODE, &pbr_map_cmd);
854 install_element(CONFIG_NODE, &no_pbr_map_cmd);
7bec514c 855 install_element(CONFIG_NODE, &pbr_set_table_range_cmd);
e5c83d9b 856 install_element(INTERFACE_NODE, &pbr_policy_cmd);
e5c83d9b
DS
857 install_element(PBRMAP_NODE, &pbr_map_match_src_cmd);
858 install_element(PBRMAP_NODE, &pbr_map_match_dst_cmd);
95a9fe02 859 install_element(PBRMAP_NODE, &pbr_map_match_mark_cmd);
e5c83d9b
DS
860 install_element(PBRMAP_NODE, &pbr_map_nexthop_group_cmd);
861 install_element(PBRMAP_NODE, &pbr_map_nexthop_cmd);
be3b67b5 862 install_element(PBRMAP_NODE, &pbr_map_vrf_cmd);
e5c83d9b
DS
863 install_element(VIEW_NODE, &show_pbr_cmd);
864 install_element(VIEW_NODE, &show_pbr_map_cmd);
865 install_element(VIEW_NODE, &show_pbr_interface_cmd);
866 install_element(VIEW_NODE, &show_pbr_nexthop_group_cmd);
e5c83d9b 867}