From c454e8993d18670f76b03dca780213860c2e19a2 Mon Sep 17 00:00:00 2001
From: Sivaprasad Tummala <Sivaprasad.Tummala@intel.com>
Date: Sat, 22 Jan 2022 03:09:18 +0530
Subject: snort: feature support on interface output

support snort plugin on interface output via ip4-output fa

Type: feature

Signed-off-by: Sivaprasad Tummala <Sivaprasad.Tummala@intel.com>
Change-Id: I2d5e7d0719c03f88806b12debfe596675dbd66c1
---
 src/plugins/snort/cli.c     | 15 ++++++++++++---
 src/plugins/snort/enqueue.c | 13 ++++++++++---
 src/plugins/snort/main.c    | 38 +++++++++++++++++++++++++++++++++-----
 src/plugins/snort/snort.h   | 10 +++++++++-
 4 files changed, 64 insertions(+), 12 deletions(-)

(limited to 'src')

diff --git a/src/plugins/snort/cli.c b/src/plugins/snort/cli.c
index cbb33c7abe8..08740f41b37 100644
--- a/src/plugins/snort/cli.c
+++ b/src/plugins/snort/cli.c
@@ -85,6 +85,7 @@ snort_attach_command_fn (vlib_main_t *vm, unformat_input_t *input,
   clib_error_t *err = 0;
   u8 *name = 0;
   u32 sw_if_index = ~0;
+  snort_attach_dir_t dir = SNORT_INOUT;
 
   /* Get a line of input. */
   if (!unformat_user (input, unformat_line_input, line_input))
@@ -97,6 +98,12 @@ snort_attach_command_fn (vlib_main_t *vm, unformat_input_t *input,
 	;
       else if (unformat (line_input, "instance %s", &name))
 	;
+      else if (unformat (line_input, "input"))
+	dir = SNORT_INPUT;
+      else if (unformat (line_input, "output"))
+	dir = SNORT_OUTPUT;
+      else if (unformat (line_input, "inout"))
+	dir = SNORT_INOUT;
       else
 	{
 	  err = clib_error_return (0, "unknown input `%U'",
@@ -117,7 +124,8 @@ snort_attach_command_fn (vlib_main_t *vm, unformat_input_t *input,
       goto done;
     }
 
-  err = snort_interface_enable_disable (vm, (char *) name, sw_if_index, 1);
+  err =
+    snort_interface_enable_disable (vm, (char *) name, sw_if_index, 1, dir);
 
 done:
   vec_free (name);
@@ -127,7 +135,8 @@ done:
 
 VLIB_CLI_COMMAND (snort_attach_command, static) = {
   .path = "snort attach",
-  .short_help = "snort attach instance <name> interface <if-name>",
+  .short_help = "snort attach instance <name> interface <if-name> "
+		"[input|ouput|inout]",
   .function = snort_attach_command_fn,
 };
 
@@ -163,7 +172,7 @@ snort_detach_command_fn (vlib_main_t *vm, unformat_input_t *input,
       goto done;
     }
 
-  err = snort_interface_enable_disable (vm, 0, sw_if_index, 0);
+  err = snort_interface_enable_disable (vm, 0, sw_if_index, 0, SNORT_INOUT);
 
 done:
   unformat_free (line_input);
diff --git a/src/plugins/snort/enqueue.c b/src/plugins/snort/enqueue.c
index 3f44e8013fd..147d3a4a67b 100644
--- a/src/plugins/snort/enqueue.c
+++ b/src/plugins/snort/enqueue.c
@@ -75,9 +75,16 @@ snort_enq_node_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
 
   while (n_left)
     {
+      u64 fa_data;
       u32 instance_index, next_index, n;
-      instance_index =
-	*(u32 *) vnet_feature_next_with_data (&next_index, b[0], sizeof (u32));
+      u32 l3_offset;
+
+      fa_data =
+	*(u64 *) vnet_feature_next_with_data (&next_index, b[0], sizeof (u64));
+
+      instance_index = (u32) (fa_data & 0xffffffff);
+      l3_offset =
+	(fa_data >> 32) ? vnet_buffer (b[0])->ip.save_rewrite_length : 0;
       si = vec_elt_at_index (sm->instances, instance_index);
 
       /* if client isn't connected skip enqueue and take default action */
@@ -108,7 +115,7 @@ snort_enq_node_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
 	  /* fill descriptor */
 	  d->buffer_pool = b[0]->buffer_pool_index;
 	  d->length = b[0]->current_length;
-	  d->offset = (u8 *) b[0]->data + b[0]->current_data -
+	  d->offset = (u8 *) b[0]->data + b[0]->current_data + l3_offset -
 		      sm->buffer_pool_base_addrs[d->buffer_pool];
 	  d->address_space_id = vnet_buffer (b[0])->sw_if_index[VLIB_RX];
 	}
diff --git a/src/plugins/snort/main.c b/src/plugins/snort/main.c
index 6b7e49a23ad..39c13a8f237 100644
--- a/src/plugins/snort/main.c
+++ b/src/plugins/snort/main.c
@@ -409,12 +409,14 @@ done:
 
 clib_error_t *
 snort_interface_enable_disable (vlib_main_t *vm, char *instance_name,
-				u32 sw_if_index, int is_enable)
+				u32 sw_if_index, int is_enable,
+				snort_attach_dir_t snort_dir)
 {
   snort_main_t *sm = &snort_main;
   vnet_main_t *vnm = vnet_get_main ();
   snort_instance_t *si;
   clib_error_t *err = 0;
+  u64 fa_data;
   u32 index;
 
   if (is_enable)
@@ -440,8 +442,18 @@ snort_interface_enable_disable (vlib_main_t *vm, char *instance_name,
 	}
 
       index = sm->instance_by_sw_if_index[sw_if_index] = si->index;
-      vnet_feature_enable_disable ("ip4-unicast", "snort-enq", sw_if_index, 1,
-				   &index, sizeof (index));
+      if (snort_dir & SNORT_INPUT)
+	{
+	  fa_data = (u64) index;
+	  vnet_feature_enable_disable ("ip4-unicast", "snort-enq", sw_if_index,
+				       1, &fa_data, sizeof (fa_data));
+	}
+      if (snort_dir & SNORT_OUTPUT)
+	{
+	  fa_data = (1LL << 32 | index);
+	  vnet_feature_enable_disable ("ip4-output", "snort-enq", sw_if_index,
+				       1, &fa_data, sizeof (fa_data));
+	}
     }
   else
     {
@@ -459,8 +471,18 @@ snort_interface_enable_disable (vlib_main_t *vm, char *instance_name,
       si = vec_elt_at_index (sm->instances, index);
 
       sm->instance_by_sw_if_index[sw_if_index] = ~0;
-      vnet_feature_enable_disable ("ip4-unicast", "snort-enq", sw_if_index, 0,
-				   &index, sizeof (index));
+      if (snort_dir & SNORT_INPUT)
+	{
+	  fa_data = (u64) index;
+	  vnet_feature_enable_disable ("ip4-unicast", "snort-enq", sw_if_index,
+				       0, &fa_data, sizeof (fa_data));
+	}
+      if (snort_dir & SNORT_OUTPUT)
+	{
+	  fa_data = (1LL << 32 | index);
+	  vnet_feature_enable_disable ("ip4-output", "snort-enq", sw_if_index,
+				       0, &fa_data, sizeof (fa_data));
+	}
     }
 
 done:
@@ -527,3 +549,9 @@ VNET_FEATURE_INIT (snort_enq, static) = {
   .node_name = "snort-enq",
   .runs_before = VNET_FEATURES ("ip4-lookup"),
 };
+
+VNET_FEATURE_INIT (snort_enq_out, static) = {
+  .arc_name = "ip4-output",
+  .node_name = "snort-enq",
+  .runs_before = VNET_FEATURES ("interface-output"),
+};
diff --git a/src/plugins/snort/snort.h b/src/plugins/snort/snort.h
index d069fa01661..79299aa6d91 100644
--- a/src/plugins/snort/snort.h
+++ b/src/plugins/snort/snort.h
@@ -90,6 +90,13 @@ typedef enum
   SNORT_ENQ_N_NEXT_NODES,
 } snort_enq_next_t;
 
+typedef enum
+{
+  SNORT_INPUT = 1,
+  SNORT_OUTPUT = 2,
+  SNORT_INOUT = 3
+} snort_attach_dir_t;
+
 #define SNORT_ENQ_NEXT_NODES                                                  \
   {                                                                           \
     [SNORT_ENQ_NEXT_DROP] = "error-drop",                                     \
@@ -100,7 +107,8 @@ clib_error_t *snort_instance_create (vlib_main_t *vm, char *name,
 				     u8 log2_queue_sz, u8 drop_on_disconnect);
 clib_error_t *snort_interface_enable_disable (vlib_main_t *vm,
 					      char *instance_name,
-					      u32 sw_if_index, int is_enable);
+					      u32 sw_if_index, int is_enable,
+					      snort_attach_dir_t dir);
 clib_error_t *snort_set_node_mode (vlib_main_t *vm, u32 mode);
 
 always_inline void
-- 
cgit