]> git.proxmox.com Git - mirror_frr.git/blob - pbrd/pbr_vty.c
pbrd: make vty nexthop/nexthop-group output consistent
[mirror_frr.git] / pbrd / pbr_vty.c
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 "nexthop_group_private.h"
29 #include "log.h"
30 #include "debug.h"
31 #include "pbr.h"
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"
37 #include "pbrd/pbr_debug.h"
38 #ifndef VTYSH_EXTRACT_PL
39 #include "pbrd/pbr_vty_clippy.c"
40 #endif
41
42 DEFUN_NOSH(pbr_map, pbr_map_cmd, "pbr-map PBRMAP seq (1-700)",
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
58 DEFUN_NOSH(no_pbr_map, no_pbr_map_cmd, "no pbr-map PBRMAP [seq (1-700)]",
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);
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
79 for (ALL_LIST_ELEMENTS(pbrm->seqnumbers, node, next_node, pbrms)) {
80 if (seqno && pbrms->seqno != seqno)
81 continue;
82
83 pbr_map_delete(pbrms);
84 }
85
86 return CMD_SUCCESS;
87 }
88
89 DEFPY(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;
101 const int minrange = 1000;
102
103 /* validate given bounds */
104 if (lb > ub)
105 vty_out(vty, "%% Lower bound must be less than upper bound\n");
106 else if (ub - lb < minrange)
107 vty_out(vty, "%% Range breadth must be at least %d\n", minrange);
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
117 DEFPY(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);
126
127 pbrms->family = prefix->family;
128
129 if (!no) {
130 if (pbrms->src) {
131 if (prefix_same(pbrms->src, prefix))
132 return CMD_SUCCESS;
133
134 vty_out(vty,
135 "A `match src-ip XX` command already exists, please remove that first\n");
136 return CMD_WARNING_CONFIG_FAILED;
137 }
138
139 pbrms->src = prefix_new();
140 prefix_copy(pbrms->src, prefix);
141 } else
142 prefix_free(&pbrms->src);
143
144 pbr_map_check(pbrms);
145
146 return CMD_SUCCESS;
147 }
148
149 DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd,
150 "[no] match dst-ip <A.B.C.D/M|X:X::X:X/M>$prefix",
151 NO_STR
152 "Match the rest of the command\n"
153 "Choose the dst ip or ipv6 prefix to use\n"
154 "v4 Prefix\n"
155 "v6 Prefix\n")
156 {
157 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
158
159 pbrms->family = prefix->family;
160
161 if (!no) {
162 if (pbrms->dst) {
163 if (prefix_same(pbrms->dst, prefix))
164 return CMD_SUCCESS;
165
166 vty_out(vty,
167 "A `match dst-ip XX` command already exists, please remove that first\n");
168 return CMD_WARNING_CONFIG_FAILED;
169 }
170
171 pbrms->dst = prefix_new();
172 prefix_copy(pbrms->dst, prefix);
173 } else
174 prefix_free(&pbrms->dst);
175
176 pbr_map_check(pbrms);
177
178 return CMD_SUCCESS;
179 }
180
181 DEFPY(pbr_map_match_mark, pbr_map_match_mark_cmd,
182 "[no] match mark (1-4294967295)$mark",
183 NO_STR
184 "Match the rest of the command\n"
185 "Choose the mark value to use\n"
186 "mark\n")
187 {
188 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
189
190 #ifndef GNU_LINUX
191 vty_out(vty, "pbr marks are not supported on this platform");
192 return CMD_WARNING_CONFIG_FAILED;
193 #endif
194
195 if (!no) {
196 if (pbrms->mark) {
197 if (pbrms->mark == (uint32_t)mark)
198 return CMD_SUCCESS;
199
200 vty_out(vty,
201 "A `match mark XX` command already exists, please remove that first\n");
202 return CMD_WARNING_CONFIG_FAILED;
203 }
204
205 pbrms->mark = (uint32_t)mark;
206 } else
207 pbrms->mark = 0;
208
209 pbr_map_check(pbrms);
210
211 return CMD_SUCCESS;
212 }
213
214 #define SET_VRF_EXISTS_STR \
215 "A `set vrf XX` command already exists, please remove that first\n"
216
217 DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
218 "[no] set nexthop-group NHGNAME$name",
219 NO_STR
220 "Set for the PBR-MAP\n"
221 "nexthop-group to use\n"
222 "The name of the nexthop-group\n")
223 {
224 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
225 struct nexthop_group_cmd *nhgc;
226
227 if (pbrms->nhg) {
228 vty_out(vty,
229 "A `set nexthop XX` command already exists, please remove that first\n");
230 return CMD_WARNING_CONFIG_FAILED;
231 }
232
233 if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
234 vty_out(vty, SET_VRF_EXISTS_STR);
235 return CMD_WARNING_CONFIG_FAILED;
236 }
237
238 nhgc = nhgc_find(name);
239 if (!nhgc) {
240 vty_out(vty, "Specified nexthop-group %s does not exist\n",
241 name);
242 vty_out(vty,
243 "PBR-MAP will not be applied until it is created\n");
244 }
245
246 if (no) {
247 if (pbrms->nhgrp_name && strcmp(name, pbrms->nhgrp_name) == 0)
248 pbr_map_delete_nexthops(pbrms);
249 else {
250 vty_out(vty,
251 "Nexthop Group specified: %s does not exist to remove\n",
252 name);
253 return CMD_WARNING_CONFIG_FAILED;
254 }
255 } else {
256 if (pbrms->nhgrp_name) {
257 if (strcmp(name, pbrms->nhgrp_name) != 0) {
258 vty_out(vty,
259 "Please delete current nexthop group before modifying current one\n");
260 return CMD_WARNING_CONFIG_FAILED;
261 }
262
263 return CMD_SUCCESS;
264 }
265 pbrms->nhgrp_name = XSTRDUP(MTYPE_TMP, name);
266 pbr_map_check(pbrms);
267 }
268
269 return CMD_SUCCESS;
270 }
271
272 DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
273 "[no] set nexthop\
274 <\
275 <A.B.C.D|X:X::X:X>$addr [INTERFACE$intf]\
276 |INTERFACE$intf\
277 >\
278 [nexthop-vrf NAME$vrf_name]",
279 NO_STR
280 "Set for the PBR-MAP\n"
281 "Specify one of the nexthops in this map\n"
282 "v4 Address\n"
283 "v6 Address\n"
284 "Interface to use\n"
285 "Interface to use\n"
286 "If the nexthop is in a different vrf tell us\n"
287 "The nexthop-vrf Name\n")
288 {
289 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
290 struct vrf *vrf;
291 struct nexthop nhop;
292 struct nexthop *nh;
293
294 if (pbrms->nhgrp_name) {
295 vty_out(vty,
296 "Please unconfigure the nexthop group before adding an individual nexthop\n");
297 return CMD_WARNING_CONFIG_FAILED;
298 }
299
300 if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
301 vty_out(vty, SET_VRF_EXISTS_STR);
302 return CMD_WARNING_CONFIG_FAILED;
303 }
304
305 if (vrf_name)
306 vrf = vrf_lookup_by_name(vrf_name);
307 else
308 vrf = vrf_lookup_by_id(VRF_DEFAULT);
309
310 if (!vrf) {
311 vty_out(vty, "Specified: %s is non-existent\n", vrf_name);
312 return CMD_WARNING_CONFIG_FAILED;
313 }
314
315 memset(&nhop, 0, sizeof(nhop));
316 nhop.vrf_id = vrf->vrf_id;
317
318 if (intf) {
319 nhop.ifindex = ifname2ifindex(intf, vrf->vrf_id);
320 if (nhop.ifindex == IFINDEX_INTERNAL) {
321 vty_out(vty,
322 "Specified Intf %s does not exist in vrf: %s\n",
323 intf, vrf->name);
324 return CMD_WARNING_CONFIG_FAILED;
325 }
326 }
327
328 if (addr) {
329 if (addr->sa.sa_family == AF_INET) {
330 nhop.gate.ipv4.s_addr = addr->sin.sin_addr.s_addr;
331 if (intf)
332 nhop.type = NEXTHOP_TYPE_IPV4_IFINDEX;
333 else
334 nhop.type = NEXTHOP_TYPE_IPV4;
335 } else {
336 nhop.gate.ipv6 = addr->sin6.sin6_addr;
337 if (intf)
338 nhop.type = NEXTHOP_TYPE_IPV6_IFINDEX;
339 else {
340 if (IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6)) {
341 vty_out(vty,
342 "Specified a v6 LL with no interface, rejecting\n");
343 return CMD_WARNING_CONFIG_FAILED;
344 }
345 nhop.type = NEXTHOP_TYPE_IPV6;
346 }
347 }
348 } else
349 nhop.type = NEXTHOP_TYPE_IFINDEX;
350
351 if (pbrms->nhg)
352 nh = nexthop_exists(pbrms->nhg, &nhop);
353 else {
354 char buf[PBR_NHC_NAMELEN];
355
356 if (no) {
357 vty_out(vty, "No nexthops to delete\n");
358 return CMD_WARNING_CONFIG_FAILED;
359 }
360
361 pbrms->nhg = nexthop_group_new();
362 pbrms->internal_nhg_name =
363 XSTRDUP(MTYPE_TMP,
364 pbr_nht_nexthop_make_name(pbrms->parent->name,
365 PBR_NHC_NAMELEN,
366 pbrms->seqno,
367 buf));
368 nh = NULL;
369 }
370
371 if (no) {
372 if (nh)
373 pbr_nht_delete_individual_nexthop(pbrms);
374 } else if (!nh) {
375
376 if (pbrms->nhg->nexthop) {
377 vty_out(vty,
378 "If you would like more than one nexthop please use nexthop-groups\n");
379 return CMD_WARNING_CONFIG_FAILED;
380 }
381
382 /* must be adding new nexthop since !no and !nexthop_exists */
383 nh = nexthop_new();
384
385 memcpy(nh, &nhop, sizeof(nhop));
386 _nexthop_add(&pbrms->nhg->nexthop, nh);
387
388 pbr_nht_add_individual_nexthop(pbrms);
389 pbr_map_check(pbrms);
390 }
391
392 if (nhop.type == NEXTHOP_TYPE_IFINDEX
393 || (nhop.type == NEXTHOP_TYPE_IPV6_IFINDEX
394 && IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6))) {
395 struct interface *ifp;
396
397 ifp = if_lookup_by_index(nhop.ifindex, nhop.vrf_id);
398 if (ifp)
399 pbr_nht_nexthop_interface_update(ifp);
400 }
401
402 return CMD_SUCCESS;
403 }
404
405 DEFPY(pbr_map_vrf, pbr_map_vrf_cmd,
406 "[no] set vrf <NAME$vrf_name|unchanged>",
407 NO_STR
408 "Set for the PBR-MAP\n"
409 "Specify the VRF for this map\n"
410 "The VRF Name\n"
411 "Use the interface's VRF for lookup\n")
412 {
413 struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
414 int ret = CMD_SUCCESS;
415
416 if (no) {
417 pbr_map_delete_vrf(pbrms);
418
419 /* Reset all data */
420 pbrms->nhs_installed = false;
421 pbrms->vrf_name[0] = '\0';
422 pbrms->vrf_lookup = false;
423 pbrms->vrf_unchanged = false;
424
425 goto done;
426 }
427
428 if (pbrms->nhgrp_name || pbrms->nhg) {
429 vty_out(vty,
430 "A `set nexthop/nexthop-group XX` command already exits, please remove that first\n");
431 ret = CMD_WARNING_CONFIG_FAILED;
432 goto done;
433 }
434
435 if (pbrms->vrf_lookup || pbrms->vrf_unchanged) {
436 vty_out(vty, SET_VRF_EXISTS_STR);
437 ret = CMD_WARNING_CONFIG_FAILED;
438 goto done;
439 }
440
441 if (vrf_name) {
442 if (!pbr_vrf_lookup_by_name(vrf_name)) {
443 vty_out(vty, "Specified: %s is non-existent\n",
444 vrf_name);
445 ret = CMD_WARNING_CONFIG_FAILED;
446 goto done;
447 }
448
449 pbrms->vrf_lookup = true;
450 strlcpy(pbrms->vrf_name, vrf_name, sizeof(pbrms->vrf_name));
451 } else
452 pbrms->vrf_unchanged = true;
453
454 pbr_map_check(pbrms);
455
456 done:
457 return ret;
458 }
459
460 DEFPY (pbr_policy,
461 pbr_policy_cmd,
462 "[no] pbr-policy PBRMAP$mapname",
463 NO_STR
464 "Policy to use\n"
465 "Name of the pbr-map to apply\n")
466 {
467 VTY_DECLVAR_CONTEXT(interface, ifp);
468 struct pbr_map *pbrm, *old_pbrm;
469 struct pbr_interface *pbr_ifp = ifp->info;
470
471 old_pbrm = NULL;
472 pbrm = pbrm_find(mapname);
473
474 if (!pbr_ifp) {
475 /* we don't want one and we don't have one, so... */
476 if (no)
477 return CMD_SUCCESS;
478
479 /* Some one could have fat fingered the interface name */
480 pbr_ifp = pbr_if_new(ifp);
481 }
482
483 if (no) {
484 if (strcmp(pbr_ifp->mapname, mapname) == 0) {
485 pbr_ifp->mapname[0] = '\0';
486 if (pbrm)
487 pbr_map_interface_delete(pbrm, ifp);
488 }
489 } else {
490 if (strcmp(pbr_ifp->mapname, "") != 0) {
491 old_pbrm = pbrm_find(pbr_ifp->mapname);
492
493 /*
494 * So if we have an old pbrm we should only
495 * delete it if we are actually deleting and
496 * moving to a new pbrm
497 */
498 if (old_pbrm && old_pbrm != pbrm)
499 pbr_map_interface_delete(old_pbrm, ifp);
500 }
501 snprintf(pbr_ifp->mapname, sizeof(pbr_ifp->mapname),
502 "%s", mapname);
503
504 /*
505 * So only reinstall if the old_pbrm and this pbrm are
506 * different.
507 */
508 if (pbrm && pbrm != old_pbrm)
509 pbr_map_add_interface(pbrm, ifp);
510 }
511
512 return CMD_SUCCESS;
513 }
514
515 DEFPY (show_pbr,
516 show_pbr_cmd,
517 "show pbr",
518 SHOW_STR
519 PBR_STR)
520 {
521 pbr_nht_write_table_range(vty);
522 pbr_nht_write_rule_range(vty);
523
524 return CMD_SUCCESS;
525 }
526
527 static void vty_show_pbrms(struct vty *vty,
528 const struct pbr_map_sequence *pbrms, bool detail)
529 {
530 char buf[PREFIX_STRLEN];
531 char rbuf[64];
532
533 if (pbrms->reason)
534 pbr_map_reason_string(pbrms->reason, rbuf, sizeof(rbuf));
535
536 vty_out(vty, " Seq: %u rule: %u\n", pbrms->seqno, pbrms->ruleno);
537
538 if (detail)
539 vty_out(vty, "\tInstalled: %" PRIu64 "(%u) Reason: %s\n",
540 pbrms->installed, pbrms->unique,
541 pbrms->reason ? rbuf : "Valid");
542 else
543 vty_out(vty, "\tInstalled: %s Reason: %s\n",
544 pbrms->installed ? "yes" : "no",
545 pbrms->reason ? rbuf : "Valid");
546
547 if (pbrms->src)
548 vty_out(vty, "\tSRC Match: %s\n",
549 prefix2str(pbrms->src, buf, sizeof(buf)));
550 if (pbrms->dst)
551 vty_out(vty, "\tDST Match: %s\n",
552 prefix2str(pbrms->dst, buf, sizeof(buf)));
553 if (pbrms->mark)
554 vty_out(vty, "\tMARK Match: %u\n", pbrms->mark);
555
556 if (pbrms->nhgrp_name) {
557 vty_out(vty, "\tNexthop-Group: %s\n", pbrms->nhgrp_name);
558
559 if (detail)
560 vty_out(vty, "\t\tInstalled: %u(%d) Tableid: %d\n",
561 pbrms->nhs_installed,
562 pbr_nht_get_installed(pbrms->nhgrp_name),
563 pbr_nht_get_table(pbrms->nhgrp_name));
564 else
565 vty_out(vty, "\t\tInstalled: %s Tableid: %d\n",
566 pbr_nht_get_installed(pbrms->nhgrp_name) ? "yes"
567 : "no",
568 pbr_nht_get_table(pbrms->nhgrp_name));
569
570 } else if (pbrms->nhg) {
571 vty_out(vty, "\t");
572 nexthop_group_write_nexthop(vty, pbrms->nhg->nexthop);
573 if (detail)
574 vty_out(vty, "\t\tInstalled: %u(%d) Tableid: %d\n",
575 pbrms->nhs_installed,
576 pbr_nht_get_installed(pbrms->internal_nhg_name),
577 pbr_nht_get_table(pbrms->internal_nhg_name));
578 else
579 vty_out(vty, "\t\tInstalled: %s Tableid: %d\n",
580 pbr_nht_get_installed(pbrms->internal_nhg_name)
581 ? "yes"
582 : "no",
583 pbr_nht_get_table(pbrms->internal_nhg_name));
584
585 } else if (pbrms->vrf_unchanged) {
586 vty_out(vty, "\tVRF Unchanged (use interface vrf)\n");
587 } else if (pbrms->vrf_lookup) {
588 vty_out(vty, "\tVRF Lookup: %s\n", pbrms->vrf_name);
589 } else {
590 vty_out(vty, "\tNexthop-Group: Unknown Installed: no\n");
591 }
592 }
593
594 static void vty_show_pbr_map(struct vty *vty, const struct pbr_map *pbrm,
595 bool detail)
596 {
597 struct pbr_map_sequence *pbrms;
598 struct listnode *node;
599
600 vty_out(vty, " pbr-map %s valid: %d\n", pbrm->name, pbrm->valid);
601
602 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
603 vty_show_pbrms(vty, pbrms, detail);
604 }
605
606 DEFPY (show_pbr_map,
607 show_pbr_map_cmd,
608 "show pbr map [NAME$name] [detail$detail]",
609 SHOW_STR
610 PBR_STR
611 "PBR Map\n"
612 "PBR Map Name\n"
613 "Detailed information\n")
614 {
615 struct pbr_map *pbrm;
616
617 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) {
618 if (name && strcmp(name, pbrm->name) != 0)
619 continue;
620
621 vty_show_pbr_map(vty, pbrm, detail);
622 }
623 return CMD_SUCCESS;
624 }
625
626 DEFPY(show_pbr_nexthop_group,
627 show_pbr_nexthop_group_cmd,
628 "show pbr nexthop-groups [WORD$word]",
629 SHOW_STR
630 PBR_STR
631 "Nexthop Groups\n"
632 "Optional Name of the nexthop group\n")
633 {
634 pbr_nht_show_nexthop_group(vty, word);
635
636 return CMD_SUCCESS;
637 }
638
639 DEFPY (show_pbr_interface,
640 show_pbr_interface_cmd,
641 "show pbr interface [NAME$name]",
642 SHOW_STR
643 PBR_STR
644 "PBR Interface\n"
645 "PBR Interface Name\n")
646 {
647 struct interface *ifp;
648 struct vrf *vrf;
649 struct pbr_interface *pbr_ifp;
650
651 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
652 FOR_ALL_INTERFACES(vrf, ifp) {
653 struct pbr_map *pbrm;
654
655 if (!ifp->info)
656 continue;
657
658 if (name && strcmp(ifp->name, name) != 0)
659 continue;
660
661 pbr_ifp = ifp->info;
662
663 if (strcmp(pbr_ifp->mapname, "") == 0)
664 continue;
665
666 pbrm = pbrm_find(pbr_ifp->mapname);
667 vty_out(vty, " %s(%d) with pbr-policy %s", ifp->name,
668 ifp->ifindex, pbr_ifp->mapname);
669 if (!pbrm)
670 vty_out(vty, " (map doesn't exist)");
671 vty_out(vty, "\n");
672 }
673 }
674
675 return CMD_SUCCESS;
676 }
677
678 /* PBR debugging CLI ------------------------------------------------------- */
679
680 static struct cmd_node debug_node = {DEBUG_NODE, "", 1};
681
682 DEFPY(debug_pbr,
683 debug_pbr_cmd,
684 "[no] debug pbr [{map$map|zebra$zebra|nht$nht|events$events}]",
685 NO_STR
686 DEBUG_STR
687 PBR_STR
688 "Policy maps\n"
689 "PBRD <-> Zebra communications\n"
690 "Nexthop tracking\n"
691 "Events\n")
692 {
693 uint32_t mode = DEBUG_NODE2MODE(vty->node);
694
695 if (map)
696 DEBUG_MODE_SET(&pbr_dbg_map, mode, !no);
697 if (zebra)
698 DEBUG_MODE_SET(&pbr_dbg_zebra, mode, !no);
699 if (nht)
700 DEBUG_MODE_SET(&pbr_dbg_nht, mode, !no);
701 if (events)
702 DEBUG_MODE_SET(&pbr_dbg_event, mode, !no);
703
704 /* no specific debug --> act on all of them */
705 if (strmatch(argv[argc - 1]->text, "pbr"))
706 pbr_debug_set_all(mode, !no);
707
708 return CMD_SUCCESS;
709 }
710
711 DEFUN_NOSH(show_debugging_pbr,
712 show_debugging_pbr_cmd,
713 "show debugging [pbr]",
714 SHOW_STR
715 DEBUG_STR
716 PBR_STR)
717 {
718 vty_out(vty, "PBR debugging status:\n");
719
720 pbr_debug_config_write_helper(vty, false);
721
722 return CMD_SUCCESS;
723 }
724
725 /* ------------------------------------------------------------------------- */
726
727
728 static struct cmd_node interface_node = {
729 INTERFACE_NODE, "%s(config-if)# ", 1 /* vtysh ? yes */
730 };
731
732 static int pbr_interface_config_write(struct vty *vty)
733 {
734 struct interface *ifp;
735 struct vrf *vrf;
736
737 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
738 FOR_ALL_INTERFACES (vrf, ifp) {
739 if (vrf->vrf_id == VRF_DEFAULT)
740 vty_frame(vty, "interface %s\n", ifp->name);
741 else
742 vty_frame(vty, "interface %s vrf %s\n",
743 ifp->name, vrf->name);
744
745 if (ifp->desc)
746 vty_out(vty, " description %s\n", ifp->desc);
747
748 pbr_map_write_interfaces(vty, ifp);
749
750 vty_endframe(vty, "!\n");
751 }
752 }
753
754 return 1;
755 }
756
757 /* PBR map node structure. */
758 static struct cmd_node pbr_map_node = {PBRMAP_NODE, "%s(config-pbr-map)# ", 1};
759
760 static int pbr_vty_map_config_write_sequence(struct vty *vty,
761 struct pbr_map *pbrm,
762 struct pbr_map_sequence *pbrms)
763 {
764 char buff[PREFIX_STRLEN];
765
766 vty_out(vty, "pbr-map %s seq %u\n", pbrm->name, pbrms->seqno);
767
768 if (pbrms->src)
769 vty_out(vty, " match src-ip %s\n",
770 prefix2str(pbrms->src, buff, sizeof(buff)));
771
772 if (pbrms->dst)
773 vty_out(vty, " match dst-ip %s\n",
774 prefix2str(pbrms->dst, buff, sizeof(buff)));
775
776 if (pbrms->mark)
777 vty_out(vty, " match mark %u\n", pbrms->mark);
778
779 if (pbrms->vrf_unchanged)
780 vty_out(vty, " set vrf unchanged\n");
781
782 if (pbrms->vrf_lookup)
783 vty_out(vty, " set vrf %s\n", pbrms->vrf_name);
784
785 if (pbrms->nhgrp_name)
786 vty_out(vty, " set nexthop-group %s\n", pbrms->nhgrp_name);
787
788 if (pbrms->nhg) {
789 vty_out(vty, " set ");
790 nexthop_group_write_nexthop(vty, pbrms->nhg->nexthop);
791 }
792
793 vty_out(vty, "!\n");
794 return 1;
795 }
796
797 static int pbr_vty_map_config_write(struct vty *vty)
798 {
799 struct pbr_map *pbrm;
800
801 pbr_nht_write_table_range(vty);
802 pbr_nht_write_rule_range(vty);
803
804 RB_FOREACH(pbrm, pbr_map_entry_head, &pbr_maps) {
805 struct pbr_map_sequence *pbrms;
806 struct listnode *node;
807
808 for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms))
809 pbr_vty_map_config_write_sequence(vty, pbrm, pbrms);
810 }
811
812 return 1;
813 }
814
815 static void pbr_map_completer(vector comps, struct cmd_token *token)
816 {
817 struct pbr_map *pbrm;
818
819 RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps)
820 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, pbrm->name));
821 }
822
823 static const struct cmd_variable_handler pbr_map_name[] = {
824 {
825 .tokenname = "PBRMAP", .completions = pbr_map_completer,
826 },
827 {
828 .completions = NULL
829 }
830 };
831
832 void pbr_vty_init(void)
833 {
834 cmd_variable_handler_register(pbr_map_name);
835
836 install_node(&interface_node,
837 pbr_interface_config_write);
838 if_cmd_init();
839
840 install_node(&pbr_map_node,
841 pbr_vty_map_config_write);
842
843 /* debug */
844 install_node(&debug_node, pbr_debug_config_write);
845 install_element(VIEW_NODE, &debug_pbr_cmd);
846 install_element(CONFIG_NODE, &debug_pbr_cmd);
847 install_element(VIEW_NODE, &show_debugging_pbr_cmd);
848
849 install_default(PBRMAP_NODE);
850
851 install_element(CONFIG_NODE, &pbr_map_cmd);
852 install_element(CONFIG_NODE, &no_pbr_map_cmd);
853 install_element(CONFIG_NODE, &pbr_set_table_range_cmd);
854 install_element(INTERFACE_NODE, &pbr_policy_cmd);
855 install_element(PBRMAP_NODE, &pbr_map_match_src_cmd);
856 install_element(PBRMAP_NODE, &pbr_map_match_dst_cmd);
857 install_element(PBRMAP_NODE, &pbr_map_match_mark_cmd);
858 install_element(PBRMAP_NODE, &pbr_map_nexthop_group_cmd);
859 install_element(PBRMAP_NODE, &pbr_map_nexthop_cmd);
860 install_element(PBRMAP_NODE, &pbr_map_vrf_cmd);
861 install_element(VIEW_NODE, &show_pbr_cmd);
862 install_element(VIEW_NODE, &show_pbr_map_cmd);
863 install_element(VIEW_NODE, &show_pbr_interface_cmd);
864 install_element(VIEW_NODE, &show_pbr_nexthop_group_cmd);
865 }