]> git.proxmox.com Git - mirror_frr.git/blame - pbrd/pbr_vty.c
Merge pull request #5409 from qlyoung/bgpd-lcom-ecom-parse-fixes
[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) {
b8eb036f
DS
130 if (prefix_same(pbrms->src, prefix))
131 return CMD_SUCCESS;
132
e5c83d9b
DS
133 if (!pbrms->src)
134 pbrms->src = prefix_new();
135 prefix_copy(pbrms->src, prefix);
63265b5c
DS
136 } else
137 prefix_free(&pbrms->src);
e5c83d9b 138
b13e5ad6 139 pbr_map_check(pbrms);
e5c83d9b
DS
140
141 return CMD_SUCCESS;
142}
143
144DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd,
145 "[no] match dst-ip <A.B.C.D/M|X:X::X:X/M>$prefix",
146 NO_STR
147 "Match the rest of the command\n"
148 "Choose the src ip or ipv6 prefix to use\n"
149 "v4 Prefix\n"
150 "v6 Prefix\n")
151{
152 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
e5c83d9b 153
49027ce8
DS
154 pbrms->family = prefix->family;
155
e5c83d9b 156 if (!no) {
b8eb036f
DS
157 if (prefix_same(pbrms->dst, prefix))
158 return CMD_SUCCESS;
159
e5c83d9b
DS
160 if (!pbrms->dst)
161 pbrms->dst = prefix_new();
162 prefix_copy(pbrms->dst, prefix);
63265b5c
DS
163 } else
164 prefix_free(&pbrms->dst);
e5c83d9b 165
b13e5ad6 166 pbr_map_check(pbrms);
e5c83d9b
DS
167
168 return CMD_SUCCESS;
169}
170
95a9fe02
MM
171DEFPY(pbr_map_match_mark, pbr_map_match_mark_cmd,
172 "[no] match mark (1-4294967295)$mark",
173 NO_STR
174 "Match the rest of the command\n"
175 "Choose the mark value to use\n"
176 "mark\n")
177{
178 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
179
180#ifndef GNU_LINUX
181 vty_out(vty, "pbr marks are not supported on this platform");
182 return CMD_WARNING_CONFIG_FAILED;
183#endif
184
185 if (!no) {
186 if (pbrms->mark == (uint32_t) mark)
187 return CMD_SUCCESS;
188 pbrms->mark = (uint32_t) mark;
189 } else {
190 pbrms->mark = 0;
191 }
192
193 pbr_map_check(pbrms);
194
195 return CMD_SUCCESS;
be3b67b5
SW
196}
197
198#define SET_VRF_EXISTS_STR \
199 "A `set vrf XX` command already exists, please remove that first\n"
95a9fe02 200
e5c83d9b 201DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
be3b67b5
SW
202 "[no] set nexthop-group NHGNAME$name",
203 NO_STR
204 "Set for the PBR-MAP\n"
205 "nexthop-group to use\n"
206 "The name of the nexthop-group\n")
e5c83d9b
DS
207{
208 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
209 struct nexthop_group_cmd *nhgc;
e5c83d9b 210
e042a421
DS
211 if (pbrms->nhg) {
212 vty_out(vty,
213 "A `set nexthop XX` command already exists, please remove that first\n");
3a9210c2 214 return CMD_WARNING_CONFIG_FAILED;
e042a421
DS
215 }
216
be3b67b5
SW
217 if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
218 vty_out(vty, SET_VRF_EXISTS_STR);
219 return CMD_WARNING_CONFIG_FAILED;
220 }
221
e5c83d9b
DS
222 nhgc = nhgc_find(name);
223 if (!nhgc) {
224 vty_out(vty, "Specified nexthop-group %s does not exist\n",
225 name);
be3b67b5
SW
226 vty_out(vty,
227 "PBR-MAP will not be applied until it is created\n");
e5c83d9b
DS
228 }
229
230 if (no) {
231 if (pbrms->nhgrp_name && strcmp(name, pbrms->nhgrp_name) == 0)
be3b67b5 232 pbr_map_delete_nexthops(pbrms);
e5c83d9b
DS
233 else {
234 vty_out(vty,
235 "Nexthop Group specified: %s does not exist to remove",
236 name);
3a9210c2 237 return CMD_WARNING_CONFIG_FAILED;
e5c83d9b
DS
238 }
239 } else {
240 if (pbrms->nhgrp_name) {
241 if (strcmp(name, pbrms->nhgrp_name) != 0) {
242 vty_out(vty,
243 "Please delete current nexthop group before modifying current one");
3a9210c2 244 return CMD_WARNING_CONFIG_FAILED;
e5c83d9b
DS
245 }
246
247 return CMD_SUCCESS;
248 }
249 pbrms->nhgrp_name = XSTRDUP(MTYPE_TMP, name);
b13e5ad6 250 pbr_map_check(pbrms);
e5c83d9b
DS
251 }
252
e5c83d9b
DS
253 return CMD_SUCCESS;
254}
255
256DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
9c0fd853
RW
257 "[no] set nexthop\
258 <\
259 <A.B.C.D|X:X::X:X>$addr [INTERFACE$intf]\
260 |INTERFACE$intf\
261 >\
e429a2a0 262 [nexthop-vrf NAME$vrf_name]",
e5c83d9b
DS
263 NO_STR
264 "Set for the PBR-MAP\n"
265 "Specify one of the nexthops in this map\n"
266 "v4 Address\n"
267 "v6 Address\n"
268 "Interface to use\n"
9c0fd853 269 "Interface to use\n"
e5c83d9b
DS
270 "If the nexthop is in a different vrf tell us\n"
271 "The nexthop-vrf Name\n")
272{
273 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
274 struct vrf *vrf;
275 struct nexthop nhop;
276 struct nexthop *nh;
e5c83d9b
DS
277
278 if (pbrms->nhgrp_name) {
279 vty_out(vty,
280 "Please unconfigure the nexthop group before adding an individual nexthop");
3a9210c2 281 return CMD_WARNING_CONFIG_FAILED;
e5c83d9b
DS
282 }
283
be3b67b5
SW
284 if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
285 vty_out(vty, SET_VRF_EXISTS_STR);
286 return CMD_WARNING_CONFIG_FAILED;
287 }
288
e429a2a0
IR
289 if (vrf_name)
290 vrf = vrf_lookup_by_name(vrf_name);
e5c83d9b
DS
291 else
292 vrf = vrf_lookup_by_id(VRF_DEFAULT);
293
294 if (!vrf) {
e429a2a0 295 vty_out(vty, "Specified: %s is non-existent\n", vrf_name);
3a9210c2 296 return CMD_WARNING_CONFIG_FAILED;
e5c83d9b
DS
297 }
298
299 memset(&nhop, 0, sizeof(nhop));
300 nhop.vrf_id = vrf->vrf_id;
301
9c0fd853
RW
302 if (intf) {
303 nhop.ifindex = ifname2ifindex(intf, vrf->vrf_id);
304 if (nhop.ifindex == IFINDEX_INTERNAL) {
305 vty_out(vty,
306 "Specified Intf %s does not exist in vrf: %s\n",
307 intf, vrf->name);
308 return CMD_WARNING_CONFIG_FAILED;
309 }
310 }
311
312 if (addr) {
313 if (addr->sa.sa_family == AF_INET) {
314 nhop.gate.ipv4.s_addr = addr->sin.sin_addr.s_addr;
315 if (intf)
316 nhop.type = NEXTHOP_TYPE_IPV4_IFINDEX;
317 else
318 nhop.type = NEXTHOP_TYPE_IPV4;
cafec8da 319 } else {
9c0fd853
RW
320 nhop.gate.ipv6 = addr->sin6.sin6_addr;
321 if (intf)
322 nhop.type = NEXTHOP_TYPE_IPV6_IFINDEX;
323 else {
324 if (IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6)) {
325 vty_out(vty,
326 "Specified a v6 LL with no interface, rejecting\n");
327 return CMD_WARNING_CONFIG_FAILED;
328 }
329 nhop.type = NEXTHOP_TYPE_IPV6;
cafec8da 330 }
cafec8da 331 }
9c0fd853
RW
332 } else
333 nhop.type = NEXTHOP_TYPE_IFINDEX;
e5c83d9b
DS
334
335 if (pbrms->nhg)
336 nh = nexthop_exists(pbrms->nhg, &nhop);
337 else {
06210d1f 338 char buf[PBR_NHC_NAMELEN];
e5c83d9b
DS
339
340 if (no) {
220c5830 341 vty_out(vty, "No nexthops to delete\n");
3a9210c2 342 return CMD_WARNING_CONFIG_FAILED;
e5c83d9b
DS
343 }
344
345 pbrms->nhg = nexthop_group_new();
346 pbrms->internal_nhg_name =
347 XSTRDUP(MTYPE_TMP,
348 pbr_nht_nexthop_make_name(pbrms->parent->name,
06210d1f 349 PBR_NHC_NAMELEN,
e5c83d9b
DS
350 pbrms->seqno,
351 buf));
352 nh = NULL;
353 }
354
355 if (no) {
b13e5ad6
DS
356 if (nh)
357 pbr_nht_delete_individual_nexthop(pbrms);
e5c83d9b
DS
358 } else if (!nh) {
359
360 if (pbrms->nhg->nexthop) {
361 vty_out(vty,
362 "If you would like more than one nexthop please use nexthop-groups");
3a9210c2 363 return CMD_WARNING_CONFIG_FAILED;
e5c83d9b
DS
364 }
365
366 /* must be adding new nexthop since !no and !nexthop_exists */
367 nh = nexthop_new();
368
369 memcpy(nh, &nhop, sizeof(nhop));
50d89650 370 _nexthop_add(&pbrms->nhg->nexthop, nh);
e5c83d9b 371
b13e5ad6
DS
372 pbr_nht_add_individual_nexthop(pbrms);
373 pbr_map_check(pbrms);
e5c83d9b
DS
374 }
375
cb254f41
SW
376 if (nhop.type == NEXTHOP_TYPE_IFINDEX
377 || (nhop.type == NEXTHOP_TYPE_IPV6_IFINDEX
378 && IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6))) {
9c0fd853
RW
379 struct interface *ifp;
380
381 ifp = if_lookup_by_index(nhop.ifindex, nhop.vrf_id);
382 if (ifp)
383 pbr_nht_nexthop_interface_update(ifp);
384 }
385
e5c83d9b
DS
386 return CMD_SUCCESS;
387}
388
be3b67b5
SW
389DEFPY(pbr_map_vrf, pbr_map_vrf_cmd,
390 "[no] set vrf <NAME$vrf_name|unchanged>",
391 NO_STR
392 "Set for the PBR-MAP\n"
393 "Specify the VRF for this map\n"
394 "The VRF Name\n"
395 "Use the interface's VRF for lookup\n")
396{
397 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
398 int ret = CMD_SUCCESS;
399
400 if (no) {
401 pbr_map_delete_vrf(pbrms);
402
403 /* Reset all data */
404 pbrms->nhs_installed = false;
405 pbrms->vrf_name[0] = '\0';
406 pbrms->vrf_lookup = false;
407 pbrms->vrf_unchanged = false;
408
409 goto done;
410 }
411
412 if (pbrms->nhgrp_name || pbrms->nhg) {
413 vty_out(vty,
414 "A `set nexthop/nexthop-group XX` command already exits, please remove that first\n");
415 ret = CMD_WARNING_CONFIG_FAILED;
416 goto done;
417 }
418
419 if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
420 vty_out(vty, SET_VRF_EXISTS_STR);
421 ret = CMD_WARNING_CONFIG_FAILED;
422 goto done;
423 }
424
425 if (vrf_name) {
426 if (!pbr_vrf_lookup_by_name(vrf_name)) {
427 vty_out(vty, "Specified: %s is non-existent\n",
428 vrf_name);
429 ret = CMD_WARNING_CONFIG_FAILED;
430 goto done;
431 }
432
433 pbrms->vrf_lookup = true;
434 strlcpy(pbrms->vrf_name, vrf_name, sizeof(pbrms->vrf_name));
435 } else
436 pbrms->vrf_unchanged = true;
437
438 pbr_map_check(pbrms);
439
440done:
441 return ret;
442}
443
e5c83d9b
DS
444DEFPY (pbr_policy,
445 pbr_policy_cmd,
17f8c652 446 "[no] pbr-policy PBRMAP$mapname",
e5c83d9b
DS
447 NO_STR
448 "Policy to use\n"
449 "Name of the pbr-map to apply\n")
450{
451 VTY_DECLVAR_CONTEXT(interface, ifp);
452 struct pbr_map *pbrm, *old_pbrm;
453 struct pbr_interface *pbr_ifp = ifp->info;
454
6eb499b0 455 old_pbrm = NULL;
e5c83d9b
DS
456 pbrm = pbrm_find(mapname);
457
b13e5ad6 458 if (!pbr_ifp) {
d6416967
QY
459 /* we don't want one and we don't have one, so... */
460 if (no)
461 return CMD_SUCCESS;
462
463 /* Some one could have fat fingered the interface name */
b13e5ad6
DS
464 pbr_ifp = pbr_if_new(ifp);
465 }
466
e5c83d9b
DS
467 if (no) {
468 if (strcmp(pbr_ifp->mapname, mapname) == 0) {
5f504f14 469 pbr_ifp->mapname[0] = '\0';
e5c83d9b
DS
470 if (pbrm)
471 pbr_map_interface_delete(pbrm, ifp);
472 }
473 } else {
5f504f14
QY
474 if (strcmp(pbr_ifp->mapname, "") != 0) {
475 old_pbrm = pbrm_find(pbr_ifp->mapname);
6eb499b0
DS
476
477 /*
478 * So if we have an old pbrm we should only
479 * delete it if we are actually deleting and
480 * moving to a new pbrm
481 */
482 if (old_pbrm && old_pbrm != pbrm)
5f504f14 483 pbr_map_interface_delete(old_pbrm, ifp);
e5c83d9b 484 }
5f504f14
QY
485 snprintf(pbr_ifp->mapname, sizeof(pbr_ifp->mapname),
486 "%s", mapname);
6eb499b0
DS
487
488 /*
489 * So only reinstall if the old_pbrm and this pbrm are
490 * different.
491 */
492 if (pbrm && pbrm != old_pbrm)
5f504f14 493 pbr_map_add_interface(pbrm, ifp);
e5c83d9b
DS
494 }
495
496 return CMD_SUCCESS;
497}
498
499DEFPY (show_pbr,
500 show_pbr_cmd,
ef18ed6e 501 "show pbr",
e5c83d9b 502 SHOW_STR
24a21176 503 PBR_STR)
e5c83d9b
DS
504{
505 pbr_nht_write_table_range(vty);
506 pbr_nht_write_rule_range(vty);
507
508 return CMD_SUCCESS;
509}
510
511DEFPY (show_pbr_map,
512 show_pbr_map_cmd,
ef18ed6e 513 "show pbr map [NAME$name] [detail$detail]",
e5c83d9b 514 SHOW_STR
24a21176 515 PBR_STR
e5c83d9b
DS
516 "PBR Map\n"
517 "PBR Map Name\n"
ef18ed6e 518 "Detailed information\n")
e5c83d9b
DS
519{
520 struct pbr_map_sequence *pbrms;
521 struct pbr_map *pbrm;
522 struct listnode *node;
523 char buf[PREFIX_STRLEN];
524 char rbuf[64];
525
526 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
527 if (name && strcmp(name, pbrm->name) != 0)
528 continue;
529
530 vty_out(vty, " pbr-map %s valid: %d\n", pbrm->name,
531 pbrm->valid);
532
533 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
534 if (pbrms->reason)
535 pbr_map_reason_string(pbrms->reason, rbuf,
536 sizeof(rbuf));
537 vty_out(vty,
37c606ff 538 " Seq: %u rule: %u Installed: %" PRIu64 "(%u) Reason: %s\n",
e5c83d9b
DS
539 pbrms->seqno, pbrms->ruleno, pbrms->installed,
540 pbrms->unique, pbrms->reason ? rbuf : "Valid");
541
542 if (pbrms->src)
543 vty_out(vty, "\tSRC Match: %s\n",
544 prefix2str(pbrms->src, buf,
545 sizeof(buf)));
546 if (pbrms->dst)
547 vty_out(vty, "\tDST Match: %s\n",
548 prefix2str(pbrms->dst, buf,
549 sizeof(buf)));
95a9fe02
MM
550 if (pbrms->mark)
551 vty_out(vty, "\tMARK Match: %u\n", pbrms->mark);
e5c83d9b
DS
552
553 if (pbrms->nhgrp_name) {
554 vty_out(vty,
555 "\tNexthop-Group: %s(%u) Installed: %u(%d)\n",
556 pbrms->nhgrp_name,
557 pbr_nht_get_table(pbrms->nhgrp_name),
558 pbrms->nhs_installed,
559 pbr_nht_get_installed(
560 pbrms->nhgrp_name));
561 } else if (pbrms->nhg) {
562 vty_out(vty, " ");
563 nexthop_group_write_nexthop(
564 vty, pbrms->nhg->nexthop);
565 vty_out(vty,
566 "\tInstalled: %u(%d) Tableid: %d\n",
567 pbrms->nhs_installed,
568 pbr_nht_get_installed(
569 pbrms->internal_nhg_name),
570 pbr_nht_get_table(
571 pbrms->internal_nhg_name));
be3b67b5
SW
572 } else if (pbrms->vrf_unchanged) {
573 vty_out(vty,
574 "\tVRF Unchanged (use interface vrf)\n");
575 } else if (pbrms->vrf_lookup) {
576 vty_out(vty, "\tVRF Lookup: %s\n",
577 pbrms->vrf_name);
e5c83d9b
DS
578 } else {
579 vty_out(vty,
580 "\tNexthop-Group: Unknown Installed: 0(0)\n");
581 }
582 }
583 }
584 return CMD_SUCCESS;
585}
586
587DEFPY(show_pbr_nexthop_group,
588 show_pbr_nexthop_group_cmd,
589 "show pbr nexthop-groups [WORD$word]",
590 SHOW_STR
24a21176 591 PBR_STR
e5c83d9b
DS
592 "Nexthop Groups\n"
593 "Optional Name of the nexthop group\n")
594{
595 pbr_nht_show_nexthop_group(vty, word);
596
597 return CMD_SUCCESS;
598}
599
600DEFPY (show_pbr_interface,
601 show_pbr_interface_cmd,
ef18ed6e 602 "show pbr interface [NAME$name]",
e5c83d9b 603 SHOW_STR
24a21176 604 PBR_STR
e5c83d9b 605 "PBR Interface\n"
ef18ed6e 606 "PBR Interface Name\n")
e5c83d9b 607{
d3765386 608 struct interface *ifp;
e5c83d9b
DS
609 struct vrf *vrf;
610 struct pbr_interface *pbr_ifp;
611
612 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
613 FOR_ALL_INTERFACES(vrf, ifp) {
614 struct pbr_map *pbrm;
615
1c33fb1d
DS
616 if (!ifp->info)
617 continue;
618
e5c83d9b
DS
619 if (name && strcmp(ifp->name, name) != 0)
620 continue;
621
622 pbr_ifp = ifp->info;
623
624 if (strcmp(pbr_ifp->mapname, "") == 0)
625 continue;
626
627 pbrm = pbrm_find(pbr_ifp->mapname);
628 vty_out(vty, " %s(%d) with pbr-policy %s", ifp->name,
629 ifp->ifindex, pbr_ifp->mapname);
630 if (!pbrm)
631 vty_out(vty, " (map doesn't exist)");
632 vty_out(vty, "\n");
633 }
634 }
635
636 return CMD_SUCCESS;
637}
638
e14f43cc 639/* PBR debugging CLI ------------------------------------------------------- */
e14f43cc
QY
640
641static struct cmd_node debug_node = {DEBUG_NODE, "", 1};
642
643DEFPY(debug_pbr,
644 debug_pbr_cmd,
645 "[no] debug pbr [{map$map|zebra$zebra|nht$nht|events$events}]",
646 NO_STR
647 DEBUG_STR
24a21176 648 PBR_STR
e14f43cc
QY
649 "Policy maps\n"
650 "PBRD <-> Zebra communications\n"
651 "Nexthop tracking\n"
652 "Events\n")
653{
654 uint32_t mode = DEBUG_NODE2MODE(vty->node);
655
656 if (map)
657 DEBUG_MODE_SET(&pbr_dbg_map, mode, !no);
658 if (zebra)
659 DEBUG_MODE_SET(&pbr_dbg_zebra, mode, !no);
660 if (nht)
661 DEBUG_MODE_SET(&pbr_dbg_nht, mode, !no);
662 if (events)
663 DEBUG_MODE_SET(&pbr_dbg_event, mode, !no);
664
665 /* no specific debug --> act on all of them */
666 if (strmatch(argv[argc - 1]->text, "pbr"))
667 pbr_debug_set_all(mode, !no);
668
669 return CMD_SUCCESS;
670}
671
672DEFUN_NOSH(show_debugging_pbr,
673 show_debugging_pbr_cmd,
674 "show debugging [pbr]",
675 SHOW_STR
676 DEBUG_STR
24a21176 677 PBR_STR)
e14f43cc
QY
678{
679 vty_out(vty, "PBR debugging status:\n");
680
681 pbr_debug_config_write_helper(vty, false);
682
683 return CMD_SUCCESS;
684}
685
e14f43cc
QY
686/* ------------------------------------------------------------------------- */
687
688
e5c83d9b
DS
689static struct cmd_node interface_node = {
690 INTERFACE_NODE, "%s(config-if)# ", 1 /* vtysh ? yes */
691};
692
693static int pbr_interface_config_write(struct vty *vty)
694{
695 struct interface *ifp;
696 struct vrf *vrf;
697
698 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
699 FOR_ALL_INTERFACES (vrf, ifp) {
700 if (vrf->vrf_id == VRF_DEFAULT)
701 vty_frame(vty, "interface %s\n", ifp->name);
702 else
703 vty_frame(vty, "interface %s vrf %s\n",
704 ifp->name, vrf->name);
705
91e5b43a
RW
706 if (ifp->desc)
707 vty_out(vty, " description %s\n", ifp->desc);
708
e5c83d9b
DS
709 pbr_map_write_interfaces(vty, ifp);
710
711 vty_endframe(vty, "!\n");
712 }
713 }
714
715 return 1;
716}
717
718/* PBR map node structure. */
719static struct cmd_node pbr_map_node = {PBRMAP_NODE, "%s(config-pbr-map)# ", 1};
720
721static int pbr_vty_map_config_write_sequence(struct vty *vty,
722 struct pbr_map *pbrm,
723 struct pbr_map_sequence *pbrms)
724{
725 char buff[PREFIX_STRLEN];
726
5e44f18f 727 vty_out(vty, "pbr-map %s seq %u\n", pbrm->name, pbrms->seqno);
e5c83d9b
DS
728
729 if (pbrms->src)
7dce96f0 730 vty_out(vty, " match src-ip %s\n",
d3765386 731 prefix2str(pbrms->src, buff, sizeof(buff)));
e5c83d9b
DS
732
733 if (pbrms->dst)
7dce96f0 734 vty_out(vty, " match dst-ip %s\n",
d3765386 735 prefix2str(pbrms->dst, buff, sizeof(buff)));
e5c83d9b 736
95a9fe02
MM
737 if (pbrms->mark)
738 vty_out(vty, " match mark %u\n", pbrms->mark);
739
be3b67b5
SW
740 if (pbrms->vrf_unchanged)
741 vty_out(vty, " set vrf unchanged\n");
742
743 if (pbrms->vrf_lookup)
744 vty_out(vty, " set vrf %s\n", pbrms->vrf_name);
745
e5c83d9b 746 if (pbrms->nhgrp_name)
7dce96f0 747 vty_out(vty, " set nexthop-group %s\n", pbrms->nhgrp_name);
e5c83d9b
DS
748
749 if (pbrms->nhg) {
7dce96f0 750 vty_out(vty, " set ");
e5c83d9b
DS
751 nexthop_group_write_nexthop(vty, pbrms->nhg->nexthop);
752 }
753
5e44f18f 754 vty_out(vty, "!\n");
e5c83d9b
DS
755 return 1;
756}
757
758static int pbr_vty_map_config_write(struct vty *vty)
759{
760 struct pbr_map *pbrm;
761
762 pbr_nht_write_table_range(vty);
763 pbr_nht_write_rule_range(vty);
764
765 RB_FOREACH(pbrm, pbr_map_entry_head, &pbr_maps) {
766 struct pbr_map_sequence *pbrms;
767 struct listnode *node;
768
d3765386 769 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
e5c83d9b 770 pbr_vty_map_config_write_sequence(vty, pbrm, pbrms);
e5c83d9b
DS
771 }
772
773 return 1;
774}
775
17f8c652
DS
776static void pbr_map_completer(vector comps, struct cmd_token *token)
777{
778 struct pbr_map *pbrm;
779
780 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps)
781 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, pbrm->name));
782}
783
784static const struct cmd_variable_handler pbr_map_name[] = {
785 {
786 .tokenname = "PBRMAP", .completions = pbr_map_completer,
787 },
788 {
789 .completions = NULL
790 }
791};
792
e5c83d9b
DS
793void pbr_vty_init(void)
794{
17f8c652
DS
795 cmd_variable_handler_register(pbr_map_name);
796
e5c83d9b
DS
797 install_node(&interface_node,
798 pbr_interface_config_write);
799 if_cmd_init();
800
801 install_node(&pbr_map_node,
802 pbr_vty_map_config_write);
803
e14f43cc
QY
804 /* debug */
805 install_node(&debug_node, pbr_debug_config_write);
806 install_element(VIEW_NODE, &debug_pbr_cmd);
807 install_element(CONFIG_NODE, &debug_pbr_cmd);
808 install_element(VIEW_NODE, &show_debugging_pbr_cmd);
809
e5c83d9b
DS
810 install_default(PBRMAP_NODE);
811
812 install_element(CONFIG_NODE, &pbr_map_cmd);
813 install_element(CONFIG_NODE, &no_pbr_map_cmd);
7bec514c 814 install_element(CONFIG_NODE, &pbr_set_table_range_cmd);
e5c83d9b 815 install_element(INTERFACE_NODE, &pbr_policy_cmd);
e5c83d9b
DS
816 install_element(PBRMAP_NODE, &pbr_map_match_src_cmd);
817 install_element(PBRMAP_NODE, &pbr_map_match_dst_cmd);
95a9fe02 818 install_element(PBRMAP_NODE, &pbr_map_match_mark_cmd);
e5c83d9b
DS
819 install_element(PBRMAP_NODE, &pbr_map_nexthop_group_cmd);
820 install_element(PBRMAP_NODE, &pbr_map_nexthop_cmd);
be3b67b5 821 install_element(PBRMAP_NODE, &pbr_map_vrf_cmd);
e5c83d9b
DS
822 install_element(VIEW_NODE, &show_pbr_cmd);
823 install_element(VIEW_NODE, &show_pbr_map_cmd);
824 install_element(VIEW_NODE, &show_pbr_interface_cmd);
825 install_element(VIEW_NODE, &show_pbr_nexthop_group_cmd);
e5c83d9b 826}