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