Home page logo
/

snort logo Snort mailing list archives

Re: [PATCH] implement odp daq module
From: Maxim Uvarov <maxim.uvarov () linaro org>
Date: Fri, 18 Jul 2014 18:17:57 +0400

Ping. There was no any feedback on that patch? Is it ok to be included?

Thank you,
Maxim.

On 07/15/2014 07:54 PM, Maxim Uvarov wrote:
OpenDataPlane (http://opendataplane.org, ODP) is open source (BSD-license)
framework to support networking on different platforms and architectures.
This patch implements daq module with odp functionality to listen for
traffic on hardware optimized NICs.

Signed-off-by: Maxim Uvarov <maxim.uvarov () linaro org>
---

  Please consider this patch for daq-2.0.2 to be included upstream.

  Thank you,
  Maxim.

  configure.ac               |   7 +
  os-daq-modules/Makefile.am |  12 ++
  os-daq-modules/daq_odp.c   | 394 +++++++++++++++++++++++++++++++++++++++++++++
  3 files changed, 413 insertions(+)
  create mode 100644 os-daq-modules/daq_odp.c

diff --git a/configure.ac b/configure.ac
index ae4f77f..5689dd3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -107,6 +107,12 @@ else
      DEFAULT_ENABLE=no
  fi
  
+# OpenDataPlane
+AC_ARG_ENABLE(odp-module,
+              AC_HELP_STRING([--disable-odp-module],[don't build the bundled OpenDataPlane module]),
+              [enable_odp_module="$enableval"], [enable_odp_module="$DEFAULT_ENABLE"])
+AM_CONDITIONAL([BUILD_ODP_MODULE], [test "$enable_odp_module" = yes])
+
  # AFPacket Module
  AC_ARG_ENABLE(afpacket-module,
                AC_HELP_STRING([--disable-afpacket-module],[don't build the bundled AFPacket module]),
@@ -276,4 +282,5 @@ echo "Build IPFW DAQ module...... : $enable_ipfw_module"
  echo "Build IPQ DAQ module....... : $enable_ipq_module"
  echo "Build NFQ DAQ module....... : $enable_nfq_module"
  echo "Build PCAP DAQ module...... : $enable_pcap_module"
+echo "Build ODP DAQ module......  : $enable_odp_module"
  echo
diff --git a/os-daq-modules/Makefile.am b/os-daq-modules/Makefile.am
index 37d6df3..cc61354 100644
--- a/os-daq-modules/Makefile.am
+++ b/os-daq-modules/Makefile.am
@@ -14,6 +14,18 @@ libdaq_static_modules_la_CFLAGS =
  libdaq_static_modules_la_LDFLAGS = -static -avoid-version
  libdaq_static_modules_la_LIBADD =
  
+if BUILD_ODP_MODULE
+if BUILD_SHARED_MODULES
+    pkglib_LTLIBRARIES += daq_odp.la
+    daq_odp_la_SOURCES = daq_odp.c
+    daq_odp_la_CFLAGS = -DBUILDING_SO
+    daq_odp_la_LDFLAGS = -module -export-dynamic -avoid-version -lrt -lodp -shared @XCCFLAGS@
+    daq_odp_la_LIBADD = $(top_builddir)/sfbpf/libsfbpf.la
+endif
+    libdaq_static_modules_la_SOURCES += daq_odp.c
+    libdaq_static_modules_la_CFLAGS += -DBUILD_ODP_MODULE
+endif
+
  if BUILD_AFPACKET_MODULE
  if BUILD_SHARED_MODULES
      pkglib_LTLIBRARIES += daq_afpacket.la
diff --git a/os-daq-modules/daq_odp.c b/os-daq-modules/daq_odp.c
new file mode 100644
index 0000000..c7983bc
--- /dev/null
+++ b/os-daq-modules/daq_odp.c
@@ -0,0 +1,394 @@
+/*
+ ** Copyright (c) 2014, Linaro Limited
+ ** All rights reserved.
+ **
+ ** SPDX-License-Identifier:      BSD-3-Clause
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "daq_api.h"
+#include "sfbpf.h"
+
+#include <odp.h>
+#include <helper/odp_linux.h>
+#include <helper/odp_packet_helper.h>
+#include <helper/odp_eth.h>
+#include <helper/odp_ip.h>
+
+#define MAX_WORKERS            1
+#define SHM_PKT_POOL_SIZE      (512*2048)
+#define SHM_PKT_POOL_BUF_SIZE  1856
+#define MAX_PKT_BURST          16
+#define ODP_DEBUG            1
+
+typedef struct _odp_context
+{
+     volatile int break_loop;
+     DAQ_Stats_t stats;
+     DAQ_State state;
+     odp_queue_t inq_def;
+     odp_pktio_t pktio;
+     int snaplen;
+     char *device;
+     char errbuf[256];
+} ODP_Context_t;
+
+static int odp_daq_initialize(const DAQ_Config_t *config, void **ctxt_ptr, char *errbuf, size_t errlen)
+{
+     ODP_Context_t *odpc;
+     int rval = DAQ_ERROR;
+     int thr_id;
+     odp_buffer_pool_t pool;
+     odp_pktio_params_t params;
+     socket_params_t *sock_params = &params.sock_params;
+     odp_queue_param_t qparam;
+     char inq_name[ODP_QUEUE_NAME_LEN];
+     int ret;
+     void *pool_base;
+
+     rval = DAQ_ERROR;
+
+     odpc = calloc(1, sizeof(ODP_Context_t));
+     if (!odpc)
+     {
+             snprintf(errbuf, errlen, "%s: Couldn't allocate memory for the new ODP context!", __FUNCTION__);
+             rval = DAQ_ERROR_NOMEM;
+             goto err;
+     }
+
+     odpc->device = strdup(config->name);
+     if (!odpc->device)
+     {
+             snprintf(errbuf, errlen, "%s: Couldn't allocate memory for the device string!", __FUNCTION__);
+             rval = DAQ_ERROR_NOMEM;
+             goto err;
+     }
+
+     *ctxt_ptr = odpc;
+
+     /* Init ODP before calling anything else */
+     if (odp_init_global()) {
+             ODP_ERR("Error: ODP global init failed.\n");
+             goto err;
+     }
+
+     /* Init this thread */
+     thr_id = odp_thread_create(0);
+     odp_init_local(thr_id);
+
+     /* Create packet pool */
+     pool_base = odp_shm_reserve("shm_packet_pool",
+                                 SHM_PKT_POOL_SIZE, ODP_CACHE_LINE_SIZE);
+     if (pool_base == NULL) {
+             ODP_ERR("Error: packet pool mem alloc failed.\n");
+             rval = DAQ_ERROR_NOMEM;
+             goto err;
+     }
+
+     pool = odp_buffer_pool_create("packet_pool", pool_base,
+                                   SHM_PKT_POOL_SIZE,
+                                   SHM_PKT_POOL_BUF_SIZE,
+                                   ODP_CACHE_LINE_SIZE,
+                                   ODP_BUFFER_TYPE_PACKET);
+     if (pool == ODP_BUFFER_POOL_INVALID) {
+             ODP_ERR("Error: packet pool create failed.\n");
+             rval = DAQ_ERROR;
+             goto err;
+     }
+     odpc->snaplen = SHM_PKT_POOL_BUF_SIZE;
+     odp_buffer_pool_print(pool);
+
+     /* Open a packet IO instance for this thread */
+     sock_params->type = ODP_PKTIO_TYPE_SOCKET_MMAP;
+     sock_params->fanout = 0;
+
+     odpc->pktio = odp_pktio_open(odpc->device, pool, &params);
+     if (odpc->pktio == ODP_PKTIO_INVALID) {
+             ODP_ERR("  [%02i] Error: pktio create failed\n", 1 /*thr*/);
+             rval = DAQ_ERROR_NODEV;
+             goto err;
+     }
+
+     /*
+      * Create and set the default INPUT queue associated with the 'pktio'
+      * resource
+      */
+     qparam.sched.prio  = ODP_SCHED_PRIO_DEFAULT;
+     qparam.sched.sync  = ODP_SCHED_SYNC_ATOMIC;
+     qparam.sched.group = ODP_SCHED_GROUP_DEFAULT;
+     snprintf(inq_name, sizeof(inq_name), "%i-pktio_inq_def", (int)odpc->pktio);
+     inq_name[ODP_QUEUE_NAME_LEN - 1] = '\0';
+
+     odpc->inq_def = odp_queue_create(inq_name, ODP_QUEUE_TYPE_PKTIN, &qparam);
+     if (odpc->inq_def == ODP_QUEUE_INVALID) {
+             ODP_ERR("  [%02i] Error: pktio queue creation failed\n", 1 /*thr*/);
+             goto err;
+     }
+
+     ret = odp_pktio_inq_setdef(odpc->pktio, odpc->inq_def);
+     if (ret != 0) {
+             ODP_ERR("  [%02i] Error: default input-Q setup\n", 1 /*thr*/);
+             goto err;
+     }
+
+        odpc->state = DAQ_STATE_INITIALIZED;
+
+     printf("%s() DAQ_SUCCESS.\n\n", __func__);
+     return DAQ_SUCCESS;
+err:
+
+     return rval;
+}
+
+static int odp_daq_set_filter(void *handle, const char *filter)
+{
+     /* not implemented yet */
+     return DAQ_SUCCESS;
+}
+
+static int odp_daq_start(void *handle)
+{
+     ODP_Context_t *odpc = (ODP_Context_t *) handle;
+     if (!odpc)
+             return DAQ_ERROR_NOCTX;
+
+     odpc->state = DAQ_STATE_STARTED;
+     return DAQ_SUCCESS;
+}
+
+static const DAQ_Verdict verdict_translation_table[MAX_DAQ_VERDICT] = {
+     DAQ_VERDICT_PASS,       /* DAQ_VERDICT_PASS */
+     DAQ_VERDICT_BLOCK,      /* DAQ_VERDICT_BLOCK */
+     DAQ_VERDICT_PASS,       /* DAQ_VERDICT_REPLACE */
+     DAQ_VERDICT_PASS,       /* DAQ_VERDICT_WHITELIST */
+     DAQ_VERDICT_BLOCK,      /* DAQ_VERDICT_BLACKLIST */
+     DAQ_VERDICT_PASS        /* DAQ_VERDICT_IGNORE */
+};
+
+static int odp_daq_acquire(void *handle, int cnt, DAQ_Analysis_Func_t callback, DAQ_Meta_Func_t metaback, void *user)
+{
+     ODP_Context_t *odpc;
+     DAQ_PktHdr_t daqhdr;
+     DAQ_Verdict verdict;
+     const uint8_t *data;
+     odp_packet_t pkt;
+     int i;
+     odp_packet_t pkt_tbl[MAX_PKT_BURST];
+     int pkts;
+
+     odpc = (ODP_Context_t *) handle;
+     if (!odpc)
+             return DAQ_ERROR;
+
+     if (odpc->state != DAQ_STATE_STARTED)
+             return DAQ_ERROR;
+
+     while (1)
+     {
+             /* Has breakloop() been called? */
+             if (odpc->break_loop)
+             {
+                     odpc->break_loop = 0;
+                     return 0;
+             }
+
+             pkts = odp_pktio_recv(odpc->pktio, pkt_tbl, MAX_PKT_BURST);
+             if (pkts <= 0) {
+                     return 0;
+             }
+
+             for (i = 0; i < pkts; ++i) {
+                     pkt = pkt_tbl[i];
+
+                     data = odp_packet_l2(pkt);
+                     if (!data) {
+                             //printf("no l2 offset, packet dropped\n");
+                             odpc->stats.packets_filtered++;
+                             odp_buffer_free(pkt);
+                             continue;
+                     }
+
+                     verdict = DAQ_VERDICT_PASS;
+
+                     gettimeofday(&daqhdr.ts, NULL);
+                     daqhdr.caplen = odp_buffer_size(pkt);
+
+                     daqhdr.pktlen = odp_packet_get_len(pkt);
+                     daqhdr.ingress_index = 0;
+                     daqhdr.egress_index =  DAQ_PKTHDR_UNKNOWN;
+                     daqhdr.ingress_group = DAQ_PKTHDR_UNKNOWN;
+                     daqhdr.egress_group = DAQ_PKTHDR_UNKNOWN;
+                     daqhdr.flags = 0;
+                     daqhdr.opaque = 0;
+                     daqhdr.priv_ptr = NULL;
+                     daqhdr.address_space_id = 0;
+
+                     if (callback)
+                     {
+                             verdict = callback(user, &daqhdr, data);
+                             if (verdict >= MAX_DAQ_VERDICT)
+                                     verdict = DAQ_VERDICT_PASS;
+                             odpc->stats.verdicts[verdict]++;
+                             verdict = verdict_translation_table[verdict];
+                     }
+
+                     odp_buffer_free(pkt);
+             }
+
+             if (pkts > 0) {
+                     odpc->stats.packets_received += pkts;
+                     break;
+             }
+     }
+     return 0;
+}
+
+static int odp_daq_inject(void *handle, const DAQ_PktHdr_t *hdr, const uint8_t *packet_data, uint32_t len, int 
reverse)
+{
+    return DAQ_SUCCESS;
+}
+
+static int odp_daq_breakloop(void *handle)
+{
+    ODP_Context_t *odpc = (ODP_Context_t *) handle;
+
+    odpc->break_loop = 1;
+    return DAQ_SUCCESS;
+}
+
+static int odp_daq_stop(void *handle)
+{
+     ODP_Context_t *odpc = (ODP_Context_t *) handle;
+
+     odpc->break_loop = 1;
+     odp_timer_disarm_all();
+     odpc->state = DAQ_STATE_STOPPED;
+
+     return DAQ_SUCCESS;
+}
+
+static void odp_daq_shutdown(void *handle)
+{
+     odp_timer_disarm_all();
+}
+
+static DAQ_State odp_daq_check_status(void *handle)
+{
+     ODP_Context_t *odpc = (ODP_Context_t *) handle;
+
+     if (!odpc) {
+             return DAQ_STATE_UNINITIALIZED;
+     }
+
+     return odpc->state;
+}
+
+static int odp_daq_get_stats(void *handle, DAQ_Stats_t *stats)
+{
+     ODP_Context_t *odpc = (ODP_Context_t *) handle;
+
+     memcpy(stats, &odpc->stats, sizeof(DAQ_Stats_t));
+     return DAQ_SUCCESS;
+}
+
+static void odp_daq_reset_stats(void *handle)
+{
+     ODP_Context_t *odpc = (ODP_Context_t *) handle;
+
+     memset(&odpc->stats, 0, sizeof(DAQ_Stats_t));
+}
+
+static int odp_daq_get_snaplen(void *handle)
+{
+     ODP_Context_t *odpc = (ODP_Context_t *) handle;
+
+     if (odpc)
+             return odpc->snaplen;
+
+     return 1500;
+}
+
+static uint32_t odp_daq_get_capabilities(void *handle)
+{
+     return DAQ_CAPA_BLOCK | DAQ_CAPA_REPLACE | DAQ_CAPA_BREAKLOOP | DAQ_CAPA_DEVICE_INDEX;
+}
+
+static int odp_daq_get_datalink_type(void *handle)
+{
+     return DLT_EN10MB;
+}
+
+static const char *odp_daq_get_errbuf(void *handle)
+{
+     ODP_Context_t *odpc = (ODP_Context_t *) handle;
+
+     return odpc->errbuf;
+}
+
+static void odp_daq_set_errbuf(void *handle, const char *string)
+{
+     ODP_Context_t *odpc = (ODP_Context_t *) handle;
+
+     if (!string)
+             return;
+
+     DPE(odpc->errbuf, "%s", string);
+     return;
+}
+
+static int odp_daq_get_device_index(void *handle, const char *string)
+{
+     return DAQ_ERROR_NOTSUP;
+}
+
+#ifdef BUILDING_SO
+DAQ_SO_PUBLIC const DAQ_Module_t DAQ_MODULE_DATA =
+#else
+const DAQ_Module_t afpacket_daq_module_data =
+#endif
+{
+     .api_version = DAQ_API_VERSION,
+     .module_version = 1,
+     .name = "odp",
+     .type = DAQ_TYPE_INTF_CAPABLE | DAQ_TYPE_INLINE_CAPABLE | DAQ_TYPE_MULTI_INSTANCE,
+     .initialize = odp_daq_initialize,
+     .set_filter = odp_daq_set_filter,
+     .start = odp_daq_start,
+     .acquire = odp_daq_acquire,
+     .inject = odp_daq_inject,
+     .breakloop = odp_daq_breakloop,
+     .stop = odp_daq_stop,
+     .shutdown = odp_daq_shutdown,
+     .check_status = odp_daq_check_status,
+     .get_stats = odp_daq_get_stats,
+     .reset_stats = odp_daq_reset_stats,
+     .get_snaplen = odp_daq_get_snaplen,
+     .get_capabilities = odp_daq_get_capabilities,
+     .get_datalink_type = odp_daq_get_datalink_type,
+     .get_errbuf = odp_daq_get_errbuf,
+     .set_errbuf = odp_daq_set_errbuf,
+     .get_device_index = odp_daq_get_device_index,
+     .modify_flow = NULL,
+     .hup_prep = NULL,
+     .hup_apply = NULL,
+     .hup_post = NULL,
+};


------------------------------------------------------------------------------
Want fast and easy access to all the code in your enterprise? Index and
search up to 200,000 lines of code with a free copy of Black Duck
Code Sight - the same software that powers the world's largest code
search on Ohloh, the Black Duck Open Hub! Try it now.
http://p.sf.net/sfu/bds
_______________________________________________
Snort-devel mailing list
Snort-devel () lists sourceforge net
https://lists.sourceforge.net/lists/listinfo/snort-devel
Archive:
http://sourceforge.net/mailarchive/forum.php?forum_name=snort-devel

Please visit http://blog.snort.org for the latest news about Snort!


  By Date           By Thread  

Current thread:
[ Nmap | Sec Tools | Mailing Lists | Site News | About/Contact | Advertising | Privacy ]
AlienVault