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