summaryrefslogtreecommitdiffstats
path: root/src/dpi_cli.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dpi_cli.c')
-rw-r--r--src/dpi_cli.c357
1 files changed, 357 insertions, 0 deletions
diff --git a/src/dpi_cli.c b/src/dpi_cli.c
new file mode 100644
index 0000000..4fbc760
--- /dev/null
+++ b/src/dpi_cli.c
@@ -0,0 +1,357 @@
+/*
+ *------------------------------------------------------------------
+ * Copyright (c) 2018 Intel, Travelping and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *------------------------------------------------------------------
+ */
+
+#include <stdint.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <inttypes.h>
+
+#include <vlib/vlib.h>
+#include <vlib/unix/unix.h>
+#include <vnet/ethernet/ethernet.h>
+#include <vnet/plugin/plugin.h>
+#include <vnet/fib/fib_entry.h>
+#include <vnet/fib/fib_table.h>
+//#include <vpp/app/version.h>
+#include "dpi.h"
+
+
+extern dpi_main_t dpi_main;
+extern dpi_entry_t *dpi_dbs;
+
+static clib_error_t *
+dpi_flow_add_del_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd_arg)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ ip46_address_t src_ip = ip46_address_initializer;
+ ip46_address_t dst_ip = ip46_address_initializer;
+ u16 src_port = 0, dst_port = 0;
+ u8 is_add = 0;
+ u8 ipv4_set = 0;
+ u8 ipv6_set = 0;
+ u32 tmp;
+ int rv;
+ u8 protocol = 0;
+ u32 table_id;
+ u32 fib_index = 0;
+ u32 dpi_flow_id;
+
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "add"))
+ is_add = 1;
+ else if (unformat (line_input, "del"))
+ is_add = 0;
+ else if (unformat (line_input, "src-ip %U", unformat_ip46_address,
+ &src_ip, IP46_TYPE_ANY))
+ {
+ ip46_address_is_ip4 (&src_ip) ? (ipv4_set = 1) : (ipv6_set = 1);
+ }
+ else if (unformat (line_input, "dst-ip %U", unformat_ip46_address,
+ &dst_ip, IP46_TYPE_ANY))
+ {
+ ip46_address_is_ip4 (&dst_ip) ? (ipv4_set = 1) : (ipv6_set = 1);
+ }
+ else if (unformat (line_input, "src-port %d", &tmp))
+ src_port = (u16) tmp;
+ else if (unformat (line_input, "dst-port %d", &tmp))
+ dst_port = (u16) tmp;
+ else
+ if (unformat (line_input, "protocol %U", unformat_ip_protocol, &tmp))
+ protocol = (u8) tmp;
+ else if (unformat (line_input, "protocol %u", &tmp))
+ protocol = (u8) tmp;
+ else if (unformat (line_input, "vrf-id %d", &table_id))
+ {
+ fib_index = fib_table_find (fib_ip_proto (ipv6_set), table_id);
+ }
+ else
+ return clib_error_return (0, "parse error: '%U'",
+ format_unformat_error, line_input);
+ }
+
+ unformat_free (line_input);
+
+ if (ipv4_set && ipv6_set)
+ return clib_error_return (0, "both IPv4 and IPv6 addresses specified");
+
+ dpi_add_del_flow_args_t a = {.is_add = is_add,
+ .is_ipv6 = ipv6_set,
+#define _(x) .x = x,
+ foreach_copy_field
+#undef _
+ };
+
+ /* Add normal flow */
+ rv = dpi_flow_add_del (&a, &dpi_flow_id);
+ if (rv < 0)
+ return clib_error_return (0, "flow error: %d", rv);
+
+ /* Add reverse flow */
+ rv = dpi_reverse_flow_add_del (&a, dpi_flow_id);
+ if (rv < 0)
+ return clib_error_return (0, "reverse flow error: %d", rv);
+
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (dpi_flow_add_del_command, static) = {
+ .path = "dpi flow",
+ .short_help = "dpi flow [add | del] "
+ "[src-ip <ip-addr>] [dst-ip <ip-addr>] "
+ "[src-port <port>] [dst-port <port>] "
+ "[protocol <protocol>] [vrf-id <nn>]",
+ .function = dpi_flow_add_del_command_fn,
+};
+/* *INDENT-ON* */
+
+static clib_error_t *
+dpi_tcp_reass_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd_arg)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ u32 flow_id = ~0;
+ u8 reass_en = 0;
+ u8 reass_dir = 0;
+ int rv;
+
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "flow_id %d", &flow_id))
+ ;
+ else if (unformat (line_input, "enable"))
+ {
+ reass_en = 1;
+ }
+ else if (unformat (line_input, "disable"))
+ {
+ reass_en = 0;
+ }
+ else if (unformat (line_input, "client"))
+ {
+ reass_dir = REASS_C2S;
+ }
+ else if (unformat (line_input, "server"))
+ {
+ reass_dir = REASS_S2C;
+ }
+ else if (unformat (line_input, "both"))
+ {
+ reass_dir = REASS_BOTH;
+ }
+ else
+ return clib_error_return (0, "parse error: '%U'",
+ format_unformat_error, line_input);
+ }
+
+ unformat_free (line_input);
+
+ tcp_reass_args_t a = {.flow_id = flow_id,
+ .reass_en = reass_en,
+ .reass_dir = reass_dir,
+ };
+
+ rv = dpi_tcp_reass (&a);
+ if (rv < 0)
+ return clib_error_return (0, "flow error: %d", rv);
+
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (dpi_tcp_reass_command, static) = {
+ .path = "dpi tcp reass",
+ .short_help = "dpi tcp reass flow_id <nn> <enable|disable> "
+ "[ <client | server | both> ]",
+ .function = dpi_tcp_reass_command_fn,
+};
+/* *INDENT-ON* */
+
+static clib_error_t *
+dpi_flow_offload_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ dpi_main_t *dm = &dpi_main;
+ vnet_main_t *vnm = dm->vnet_main;
+ u32 rx_flow_id = ~0;
+ u32 hw_if_index = ~0;
+ int is_add = 1;
+ u32 is_ipv6 = 0;
+ dpi_flow_entry_t *flow;
+ vnet_hw_interface_t *hw_if;
+ u32 rx_fib_index = ~0;
+
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "hw %U", unformat_vnet_hw_interface, vnm,
+ &hw_if_index))
+ continue;
+ if (unformat (line_input, "rx %d", &rx_flow_id))
+ continue;
+ if (unformat (line_input, "del"))
+ {
+ is_add = 0;
+ continue;
+ }
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, line_input);
+ }
+
+ if (rx_flow_id == ~0)
+ return clib_error_return (0, "missing rx flow");
+ if (hw_if_index == ~0)
+ return clib_error_return (0, "missing hw interface");
+
+ flow = pool_elt_at_index (dm->dpi_flows, rx_flow_id);
+
+ hw_if = vnet_get_hw_interface (vnm, hw_if_index);
+
+ is_ipv6 = ip46_address_is_ip4 (&(flow->key.src_ip)) ? 0 : 1;
+
+ if (is_ipv6)
+ {
+ ip6_main_t *im6 = &ip6_main;
+ rx_fib_index =
+ vec_elt (im6->fib_index_by_sw_if_index, hw_if->sw_if_index);
+ }
+ else
+ {
+ ip4_main_t *im4 = &ip4_main;
+ rx_fib_index =
+ vec_elt (im4->fib_index_by_sw_if_index, hw_if->sw_if_index);
+ }
+
+ if (flow->key.fib_index != rx_fib_index)
+ return clib_error_return (0, "interface/flow fib mismatch");
+
+ if (dpi_add_del_rx_flow (hw_if_index, rx_flow_id, is_add, is_ipv6))
+ return clib_error_return (0, "error %s flow",
+ is_add ? "enabling" : "disabling");
+
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (dpi_flow_offload_command, static) = {
+ .path = "dpi set flow-offload",
+ .short_help =
+ "dpi set flow-offload hw <interface-name> rx <flow-id> [del]",
+ .function = dpi_flow_offload_command_fn,
+};
+/* *INDENT-ON* */
+
+static clib_error_t *
+dpi_set_flow_bypass (u32 is_ip6,
+ unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ vnet_main_t *vnm = vnet_get_main ();
+ clib_error_t *error = 0;
+ u32 sw_if_index, is_enable;
+
+ sw_if_index = ~0;
+ is_enable = 1;
+
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat_user (line_input, unformat_vnet_sw_interface, vnm,
+ &sw_if_index))
+ ;
+ else if (unformat (line_input, "del"))
+ is_enable = 0;
+ else
+ {
+ error = unformat_parse_error (line_input);
+ goto done;
+ }
+ }
+
+ if (~0 == sw_if_index)
+ {
+ error = clib_error_return (0, "unknown interface `%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
+
+ dpi_flow_bypass_mode (sw_if_index, is_ip6, is_enable);
+
+done:
+ unformat_free (line_input);
+
+ return error;
+}
+
+static clib_error_t *
+dpi_set_ip4_flow_bypass_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ return dpi_set_flow_bypass (0, input, cmd);
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (dpi_set_ip4_flow_bypass_command, static) =
+{
+ .path = "dpi set ip4 flow-bypass",
+ .short_help = "dpi set ip4 flow-bypass <interface> [del]",
+ .function = dpi_set_ip4_flow_bypass_command_fn,
+};
+/* *INDENT-ON* */
+
+static clib_error_t *
+dpi_set_ip6_flow_bypass_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ return dpi_set_flow_bypass (0, input, cmd);
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (dpi_set_ip6_flow_bypass_command, static) =
+{
+ .path = "dpi set ip6 flow-bypass",
+ .short_help = "dpi set ip6 flow-bypass <interface> [del]",
+ .function = dpi_set_ip6_flow_bypass_command_fn,
+};
+/* *INDENT-ON* */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */