Home page logo
/

snort logo Snort mailing list archives

Re: [PATCH] implement odp daq module
From: "Carter Waxman (cwaxman)" <cwaxman () cisco com>
Date: Fri, 18 Jul 2014 15:04:46 +0000

Thank you for your contribution. We are tracking this patch internally and
currently have it placed under review.

Thanks,
Carter

On 7/18/14, 10:17 AM, "Maxim Uvarov" <maxim.uvarov () linaro org> wrote:

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!



------------------------------------------------------------------------------
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