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