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