summaryrefslogtreecommitdiffstats
path: root/pbrd/pbr_debug.c
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2018-01-23 19:11:36 +0100
committerDonald Sharp <sharpd@cumulusnetworks.com>2018-04-06 19:22:43 +0200
commite5c83d9b314cb513e78707de5d29ec655dbdca7e (patch)
tree0ede3af459164c589f9892e7f6c93e82f08ad208 /pbrd/pbr_debug.c
parentMerge pull request #2029 from cdwertmann/patch-1 (diff)
downloadfrr-e5c83d9b314cb513e78707de5d29ec655dbdca7e.tar.xz
frr-e5c83d9b314cb513e78707de5d29ec655dbdca7e.zip
pbrd: Add PBR to FRR
This is an implementation of PBR for FRR. This implemenation uses a combination of rules and tables to determine how packets will flow. PBR introduces a new concept of 'nexthop-groups' to specify a group of nexthops that will be used for ecmp. Nexthop-groups are specified on the cli via: nexthop-group DONNA nexthop 192.168.208.1 nexthop 192.168.209.1 nexthop 192.168.210.1 ! PBR sees the nexthop-group and installs these as a default route with these nexthops starting at table 10000 robot# show pbr nexthop-groups Nexthop-Group: DONNA Table: 10001 Valid: 1 Installed: 1 Valid: 1 nexthop 192.168.209.1 Valid: 1 nexthop 192.168.210.1 Valid: 1 nexthop 192.168.208.1 I have also introduced the ability to specify a table in a 'show ip route table XXX' to see the specified tables. robot# show ip route table 10001 Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF, I - IS-IS, B - BGP, P - PIM, E - EIGRP, N - NHRP, T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP, F - PBR, > - selected route, * - FIB route F>* 0.0.0.0/0 [0/0] via 192.168.208.1, enp0s8, 00:14:25 * via 192.168.209.1, enp0s9, 00:14:25 * via 192.168.210.1, enp0s10, 00:14:25 PBR tracks PBR-MAPS via the pbr-map command: ! pbr-map EVA seq 10 match src-ip 4.3.4.0/24 set nexthop-group DONNA ! pbr-map EVA seq 20 match dst-ip 4.3.5.0/24 set nexthop-group DONNA ! pbr-maps can have 'match src-ip <prefix>' and 'match dst-ip <prefix>' to affect decisions about incoming packets. Additionally if you only have one nexthop to use for a pbr-map you do not need to setup a nexthop-group and can specify 'set nexthop XXXX'. To apply the pbr-map to an incoming interface you do this: interface enp0s10 pbr-policy EVA ! When a pbr-map is applied to interfaces it can be installed into the kernel as a rule: [sharpd@robot frr1]$ ip rule show 0: from all lookup local 309: from 4.3.4.0/24 iif enp0s10 lookup 10001 319: from all to 4.3.5.0/24 iif enp0s10 lookup 10001 1000: from all lookup [l3mdev-table] 32766: from all lookup main 32767: from all lookup default [sharpd@robot frr1]$ ip route show table 10001 default proto pbr metric 20 nexthop via 192.168.208.1 dev enp0s8 weight 1 nexthop via 192.168.209.1 dev enp0s9 weight 1 nexthop via 192.168.210.1 dev enp0s10 weight 1 The linux kernel now will use the rules and tables to properly apply these policies. Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com> Signed-off-by: Don Slice <dslice@cumulusnetworks.com> Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
Diffstat (limited to 'pbrd/pbr_debug.c')
-rw-r--r--pbrd/pbr_debug.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/pbrd/pbr_debug.c b/pbrd/pbr_debug.c
new file mode 100644
index 000000000..163459512
--- /dev/null
+++ b/pbrd/pbr_debug.c
@@ -0,0 +1,171 @@
+/*
+ * PBR - debugging
+ * Copyright (C) 2018 Cumulus Networks, Inc.
+ * Quentin Young
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <zebra.h>
+
+#include "debug.h"
+#include "command.h"
+#include "vector.h"
+
+#ifndef VTYSH_EXTRACT_PL
+#include "pbrd/pbr_debug_clippy.c"
+#endif
+#include "pbrd/pbr_debug.h"
+
+struct debug pbr_dbg_map = {0, "PBR map"};
+struct debug pbr_dbg_zebra = {0, "PBR Zebra communications"};
+struct debug pbr_dbg_nht = {0, "PBR nexthop tracking"};
+struct debug pbr_dbg_event = {0, "PBR events"};
+
+struct debug *pbr_debugs[] = {&pbr_dbg_map, &pbr_dbg_zebra, &pbr_dbg_nht,
+ &pbr_dbg_event};
+
+const char *pbr_debugs_conflines[] = {
+ "debug pbr map",
+ "debug pbr zebra",
+ "debug pbr nht",
+ "debug pbr events",
+};
+
+/*
+ * Set or unset flags on all debugs for pbrd.
+ *
+ * flags
+ * The flags to set
+ *
+ * set
+ * Whether to set or unset the specified flags
+ */
+static void pbr_debug_set_all(uint32_t flags, bool set)
+{
+ for (unsigned int i = 0; i < array_size(pbr_debugs); i++) {
+ DEBUG_FLAGS_SET(pbr_debugs[i], flags, set);
+
+ /* if all modes have been turned off, don't preserve options */
+ if (!DEBUG_MODE_CHECK(pbr_debugs[i], DEBUG_MODE_ALL))
+ DEBUG_CLEAR(pbr_debugs[i]);
+ }
+}
+
+/*
+ * Check flags on all debugs for pbrd.
+ *
+ * flags
+ * The flags to set
+ *
+ * Returns:
+ * The subset of the given flags that were set in all pbrd debugs
+ */
+static uint32_t pbr_debug_check_all(uint32_t flags)
+{
+ uint32_t mode = DEBUG_MODE_ALL;
+ for (unsigned int i = 0; i < array_size(pbr_debugs); i++)
+ mode &= DEBUG_MODE_CHECK(pbr_debugs[i], flags);
+ return mode;
+}
+
+static int pbr_debug_config_write_helper(struct vty *vty, bool config)
+{
+ uint32_t mode = DEBUG_MODE_ALL;
+
+ if (config)
+ mode = DEBUG_MODE_CONF;
+
+ if (pbr_debug_check_all(DEBUG_MODE_CONF) == mode) {
+ vty_out(vty, "debug pbr\n");
+ return 0;
+ }
+
+ for (unsigned int i = 0; i < array_size(pbr_debugs); i++)
+ if (DEBUG_MODE_CHECK(pbr_debugs[i], mode))
+ vty_out(vty, "%s\n", pbr_debugs_conflines[i]);
+ return 0;
+}
+
+int pbr_debug_config_write(struct vty *vty)
+{
+ return pbr_debug_config_write_helper(vty, true);
+}
+
+/* PBR debugging CLI ------------------------------------------------------- */
+/* clang-format off */
+
+DEFPY(debug_pbr,
+ debug_pbr_cmd,
+ "[no] debug pbr [{map$map|zebra$zebra|nht$nht|events$events}]",
+ NO_STR
+ DEBUG_STR
+ "Policy Based Routing\n"
+ "Policy maps\n"
+ "PBRD <-> Zebra communications\n"
+ "Nexthop tracking\n"
+ "Events\n")
+{
+ uint32_t mode = DEBUG_NODE2MODE(vty->node);
+ if (map)
+ DEBUG_MODE_SET(&pbr_dbg_map, mode, !no);
+ if (zebra)
+ DEBUG_MODE_SET(&pbr_dbg_zebra, mode, !no);
+ if (nht)
+ DEBUG_MODE_SET(&pbr_dbg_nht, mode, !no);
+ if (events)
+ DEBUG_MODE_SET(&pbr_dbg_event, mode, !no);
+
+ /* no specific debug --> act on all of them */
+ if (strmatch(argv[argc - 1]->text, "pbr"))
+ pbr_debug_set_all(mode, !no);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_NOSH(show_debugging_pbr,
+ show_debugging_pbr_cmd,
+ "show debugging [pbr]",
+ SHOW_STR
+ DEBUG_STR
+ "Policy Based Routing\n")
+{
+ vty_out(vty, "PBR debugging status:\n");
+
+ pbr_debug_config_write_helper(vty, false);
+
+ return CMD_SUCCESS;
+}
+
+/* clang-format on */
+/* ------------------------------------------------------------------------- */
+
+static struct cmd_node debug_node = {DEBUG_NODE, "", 1};
+
+struct debug_callbacks pbr_dbg_cbs = {.debug_set_all = pbr_debug_set_all};
+
+void pbr_debug_init(void)
+{
+ debug_init(&pbr_dbg_cbs);
+}
+
+void pbr_debug_init_vty(void)
+{
+ install_node(&debug_node, pbr_debug_config_write);
+
+ install_element(VIEW_NODE, &debug_pbr_cmd);
+ install_element(CONFIG_NODE, &debug_pbr_cmd);
+
+ install_element(VIEW_NODE, &show_debugging_pbr_cmd);
+}