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