]> git.proxmox.com Git - mirror_frr.git/blame - pbrd/pbr_vty.c
Merge pull request #5058 from mjstapp/fix_dplane_config_handler
[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
9c0fd853
RW
366 if (nhop.type == NEXTHOP_TYPE_IFINDEX) {
367 struct interface *ifp;
368
369 ifp = if_lookup_by_index(nhop.ifindex, nhop.vrf_id);
370 if (ifp)
371 pbr_nht_nexthop_interface_update(ifp);
372 }
373
e5c83d9b
DS
374 return CMD_SUCCESS;
375}
376
e5c83d9b
DS
377DEFPY (pbr_policy,
378 pbr_policy_cmd,
17f8c652 379 "[no] pbr-policy PBRMAP$mapname",
e5c83d9b
DS
380 NO_STR
381 "Policy to use\n"
382 "Name of the pbr-map to apply\n")
383{
384 VTY_DECLVAR_CONTEXT(interface, ifp);
385 struct pbr_map *pbrm, *old_pbrm;
386 struct pbr_interface *pbr_ifp = ifp->info;
387
6eb499b0 388 old_pbrm = NULL;
e5c83d9b
DS
389 pbrm = pbrm_find(mapname);
390
b13e5ad6 391 if (!pbr_ifp) {
d6416967
QY
392 /* we don't want one and we don't have one, so... */
393 if (no)
394 return CMD_SUCCESS;
395
396 /* Some one could have fat fingered the interface name */
b13e5ad6
DS
397 pbr_ifp = pbr_if_new(ifp);
398 }
399
e5c83d9b
DS
400 if (no) {
401 if (strcmp(pbr_ifp->mapname, mapname) == 0) {
5f504f14 402 pbr_ifp->mapname[0] = '\0';
e5c83d9b
DS
403 if (pbrm)
404 pbr_map_interface_delete(pbrm, ifp);
405 }
406 } else {
5f504f14
QY
407 if (strcmp(pbr_ifp->mapname, "") != 0) {
408 old_pbrm = pbrm_find(pbr_ifp->mapname);
6eb499b0
DS
409
410 /*
411 * So if we have an old pbrm we should only
412 * delete it if we are actually deleting and
413 * moving to a new pbrm
414 */
415 if (old_pbrm && old_pbrm != pbrm)
5f504f14 416 pbr_map_interface_delete(old_pbrm, ifp);
e5c83d9b 417 }
5f504f14
QY
418 snprintf(pbr_ifp->mapname, sizeof(pbr_ifp->mapname),
419 "%s", mapname);
6eb499b0
DS
420
421 /*
422 * So only reinstall if the old_pbrm and this pbrm are
423 * different.
424 */
425 if (pbrm && pbrm != old_pbrm)
5f504f14 426 pbr_map_add_interface(pbrm, ifp);
e5c83d9b
DS
427 }
428
429 return CMD_SUCCESS;
430}
431
432DEFPY (show_pbr,
433 show_pbr_cmd,
ef18ed6e 434 "show pbr",
e5c83d9b 435 SHOW_STR
24a21176 436 PBR_STR)
e5c83d9b
DS
437{
438 pbr_nht_write_table_range(vty);
439 pbr_nht_write_rule_range(vty);
440
441 return CMD_SUCCESS;
442}
443
444DEFPY (show_pbr_map,
445 show_pbr_map_cmd,
ef18ed6e 446 "show pbr map [NAME$name] [detail$detail]",
e5c83d9b 447 SHOW_STR
24a21176 448 PBR_STR
e5c83d9b
DS
449 "PBR Map\n"
450 "PBR Map Name\n"
ef18ed6e 451 "Detailed information\n")
e5c83d9b
DS
452{
453 struct pbr_map_sequence *pbrms;
454 struct pbr_map *pbrm;
455 struct listnode *node;
456 char buf[PREFIX_STRLEN];
457 char rbuf[64];
458
459 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
460 if (name && strcmp(name, pbrm->name) != 0)
461 continue;
462
463 vty_out(vty, " pbr-map %s valid: %d\n", pbrm->name,
464 pbrm->valid);
465
466 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) {
467 if (pbrms->reason)
468 pbr_map_reason_string(pbrms->reason, rbuf,
469 sizeof(rbuf));
470 vty_out(vty,
37c606ff 471 " Seq: %u rule: %u Installed: %" PRIu64 "(%u) Reason: %s\n",
e5c83d9b
DS
472 pbrms->seqno, pbrms->ruleno, pbrms->installed,
473 pbrms->unique, pbrms->reason ? rbuf : "Valid");
474
475 if (pbrms->src)
476 vty_out(vty, "\tSRC Match: %s\n",
477 prefix2str(pbrms->src, buf,
478 sizeof(buf)));
479 if (pbrms->dst)
480 vty_out(vty, "\tDST Match: %s\n",
481 prefix2str(pbrms->dst, buf,
482 sizeof(buf)));
95a9fe02
MM
483 if (pbrms->mark)
484 vty_out(vty, "\tMARK Match: %u\n", pbrms->mark);
e5c83d9b
DS
485
486 if (pbrms->nhgrp_name) {
487 vty_out(vty,
488 "\tNexthop-Group: %s(%u) Installed: %u(%d)\n",
489 pbrms->nhgrp_name,
490 pbr_nht_get_table(pbrms->nhgrp_name),
491 pbrms->nhs_installed,
492 pbr_nht_get_installed(
493 pbrms->nhgrp_name));
494 } else if (pbrms->nhg) {
495 vty_out(vty, " ");
496 nexthop_group_write_nexthop(
497 vty, pbrms->nhg->nexthop);
498 vty_out(vty,
499 "\tInstalled: %u(%d) Tableid: %d\n",
500 pbrms->nhs_installed,
501 pbr_nht_get_installed(
502 pbrms->internal_nhg_name),
503 pbr_nht_get_table(
504 pbrms->internal_nhg_name));
505 } else {
506 vty_out(vty,
507 "\tNexthop-Group: Unknown Installed: 0(0)\n");
508 }
509 }
510 }
511 return CMD_SUCCESS;
512}
513
514DEFPY(show_pbr_nexthop_group,
515 show_pbr_nexthop_group_cmd,
516 "show pbr nexthop-groups [WORD$word]",
517 SHOW_STR
24a21176 518 PBR_STR
e5c83d9b
DS
519 "Nexthop Groups\n"
520 "Optional Name of the nexthop group\n")
521{
522 pbr_nht_show_nexthop_group(vty, word);
523
524 return CMD_SUCCESS;
525}
526
527DEFPY (show_pbr_interface,
528 show_pbr_interface_cmd,
ef18ed6e 529 "show pbr interface [NAME$name]",
e5c83d9b 530 SHOW_STR
24a21176 531 PBR_STR
e5c83d9b 532 "PBR Interface\n"
ef18ed6e 533 "PBR Interface Name\n")
e5c83d9b 534{
d3765386 535 struct interface *ifp;
e5c83d9b
DS
536 struct vrf *vrf;
537 struct pbr_interface *pbr_ifp;
538
539 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
540 FOR_ALL_INTERFACES(vrf, ifp) {
541 struct pbr_map *pbrm;
542
1c33fb1d
DS
543 if (!ifp->info)
544 continue;
545
e5c83d9b
DS
546 if (name && strcmp(ifp->name, name) != 0)
547 continue;
548
549 pbr_ifp = ifp->info;
550
551 if (strcmp(pbr_ifp->mapname, "") == 0)
552 continue;
553
554 pbrm = pbrm_find(pbr_ifp->mapname);
555 vty_out(vty, " %s(%d) with pbr-policy %s", ifp->name,
556 ifp->ifindex, pbr_ifp->mapname);
557 if (!pbrm)
558 vty_out(vty, " (map doesn't exist)");
559 vty_out(vty, "\n");
560 }
561 }
562
563 return CMD_SUCCESS;
564}
565
e14f43cc 566/* PBR debugging CLI ------------------------------------------------------- */
e14f43cc
QY
567
568static struct cmd_node debug_node = {DEBUG_NODE, "", 1};
569
570DEFPY(debug_pbr,
571 debug_pbr_cmd,
572 "[no] debug pbr [{map$map|zebra$zebra|nht$nht|events$events}]",
573 NO_STR
574 DEBUG_STR
24a21176 575 PBR_STR
e14f43cc
QY
576 "Policy maps\n"
577 "PBRD <-> Zebra communications\n"
578 "Nexthop tracking\n"
579 "Events\n")
580{
581 uint32_t mode = DEBUG_NODE2MODE(vty->node);
582
583 if (map)
584 DEBUG_MODE_SET(&pbr_dbg_map, mode, !no);
585 if (zebra)
586 DEBUG_MODE_SET(&pbr_dbg_zebra, mode, !no);
587 if (nht)
588 DEBUG_MODE_SET(&pbr_dbg_nht, mode, !no);
589 if (events)
590 DEBUG_MODE_SET(&pbr_dbg_event, mode, !no);
591
592 /* no specific debug --> act on all of them */
593 if (strmatch(argv[argc - 1]->text, "pbr"))
594 pbr_debug_set_all(mode, !no);
595
596 return CMD_SUCCESS;
597}
598
599DEFUN_NOSH(show_debugging_pbr,
600 show_debugging_pbr_cmd,
601 "show debugging [pbr]",
602 SHOW_STR
603 DEBUG_STR
24a21176 604 PBR_STR)
e14f43cc
QY
605{
606 vty_out(vty, "PBR debugging status:\n");
607
608 pbr_debug_config_write_helper(vty, false);
609
610 return CMD_SUCCESS;
611}
612
e14f43cc
QY
613/* ------------------------------------------------------------------------- */
614
615
e5c83d9b
DS
616static struct cmd_node interface_node = {
617 INTERFACE_NODE, "%s(config-if)# ", 1 /* vtysh ? yes */
618};
619
620static int pbr_interface_config_write(struct vty *vty)
621{
622 struct interface *ifp;
623 struct vrf *vrf;
624
625 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
626 FOR_ALL_INTERFACES (vrf, ifp) {
627 if (vrf->vrf_id == VRF_DEFAULT)
628 vty_frame(vty, "interface %s\n", ifp->name);
629 else
630 vty_frame(vty, "interface %s vrf %s\n",
631 ifp->name, vrf->name);
632
91e5b43a
RW
633 if (ifp->desc)
634 vty_out(vty, " description %s\n", ifp->desc);
635
e5c83d9b
DS
636 pbr_map_write_interfaces(vty, ifp);
637
638 vty_endframe(vty, "!\n");
639 }
640 }
641
642 return 1;
643}
644
645/* PBR map node structure. */
646static struct cmd_node pbr_map_node = {PBRMAP_NODE, "%s(config-pbr-map)# ", 1};
647
648static int pbr_vty_map_config_write_sequence(struct vty *vty,
649 struct pbr_map *pbrm,
650 struct pbr_map_sequence *pbrms)
651{
652 char buff[PREFIX_STRLEN];
653
5e44f18f 654 vty_out(vty, "pbr-map %s seq %u\n", pbrm->name, pbrms->seqno);
e5c83d9b
DS
655
656 if (pbrms->src)
7dce96f0 657 vty_out(vty, " match src-ip %s\n",
d3765386 658 prefix2str(pbrms->src, buff, sizeof(buff)));
e5c83d9b
DS
659
660 if (pbrms->dst)
7dce96f0 661 vty_out(vty, " match dst-ip %s\n",
d3765386 662 prefix2str(pbrms->dst, buff, sizeof(buff)));
e5c83d9b 663
95a9fe02
MM
664 if (pbrms->mark)
665 vty_out(vty, " match mark %u\n", pbrms->mark);
666
e5c83d9b 667 if (pbrms->nhgrp_name)
7dce96f0 668 vty_out(vty, " set nexthop-group %s\n", pbrms->nhgrp_name);
e5c83d9b
DS
669
670 if (pbrms->nhg) {
7dce96f0 671 vty_out(vty, " set ");
e5c83d9b
DS
672 nexthop_group_write_nexthop(vty, pbrms->nhg->nexthop);
673 }
674
5e44f18f 675 vty_out(vty, "!\n");
e5c83d9b
DS
676 return 1;
677}
678
679static int pbr_vty_map_config_write(struct vty *vty)
680{
681 struct pbr_map *pbrm;
682
683 pbr_nht_write_table_range(vty);
684 pbr_nht_write_rule_range(vty);
685
686 RB_FOREACH(pbrm, pbr_map_entry_head, &pbr_maps) {
687 struct pbr_map_sequence *pbrms;
688 struct listnode *node;
689
d3765386 690 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
e5c83d9b 691 pbr_vty_map_config_write_sequence(vty, pbrm, pbrms);
e5c83d9b
DS
692 }
693
694 return 1;
695}
696
17f8c652
DS
697static void pbr_map_completer(vector comps, struct cmd_token *token)
698{
699 struct pbr_map *pbrm;
700
701 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps)
702 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, pbrm->name));
703}
704
705static const struct cmd_variable_handler pbr_map_name[] = {
706 {
707 .tokenname = "PBRMAP", .completions = pbr_map_completer,
708 },
709 {
710 .completions = NULL
711 }
712};
713
e5c83d9b
DS
714void pbr_vty_init(void)
715{
17f8c652
DS
716 cmd_variable_handler_register(pbr_map_name);
717
e5c83d9b
DS
718 install_node(&interface_node,
719 pbr_interface_config_write);
720 if_cmd_init();
721
722 install_node(&pbr_map_node,
723 pbr_vty_map_config_write);
724
e14f43cc
QY
725 /* debug */
726 install_node(&debug_node, pbr_debug_config_write);
727 install_element(VIEW_NODE, &debug_pbr_cmd);
728 install_element(CONFIG_NODE, &debug_pbr_cmd);
729 install_element(VIEW_NODE, &show_debugging_pbr_cmd);
730
e5c83d9b
DS
731 install_default(PBRMAP_NODE);
732
733 install_element(CONFIG_NODE, &pbr_map_cmd);
734 install_element(CONFIG_NODE, &no_pbr_map_cmd);
7bec514c 735 install_element(CONFIG_NODE, &pbr_set_table_range_cmd);
e5c83d9b 736 install_element(INTERFACE_NODE, &pbr_policy_cmd);
e5c83d9b
DS
737 install_element(PBRMAP_NODE, &pbr_map_match_src_cmd);
738 install_element(PBRMAP_NODE, &pbr_map_match_dst_cmd);
95a9fe02 739 install_element(PBRMAP_NODE, &pbr_map_match_mark_cmd);
e5c83d9b
DS
740 install_element(PBRMAP_NODE, &pbr_map_nexthop_group_cmd);
741 install_element(PBRMAP_NODE, &pbr_map_nexthop_cmd);
742 install_element(VIEW_NODE, &show_pbr_cmd);
743 install_element(VIEW_NODE, &show_pbr_map_cmd);
744 install_element(VIEW_NODE, &show_pbr_interface_cmd);
745 install_element(VIEW_NODE, &show_pbr_nexthop_group_cmd);
e5c83d9b 746}