@@ -48,8 +48,11 @@ AR = @AR@
LN_S = @LN_S@
MKDEP = @MKDEP@
CCOPT = @V_CCOPT@
-INCLS = -I. @V_INCLS@
+INCLS = -I. @V_INCLS@ @ODP_INCLS@
DEFS = @DEFS@ @V_DEFS@
+ifeq ($(ODP_HAVE_NETMAP),yes)
+DEFS += -DODP_HAVE_NETMAP
+endif
ADDLOBJS = @ADDLOBJS@
ADDLARCHIVEOBJS = @ADDLARCHIVEOBJS@
LIBS = @LIBS@
@@ -359,8 +362,11 @@ all: libpcap.a shared pcap-config
libpcap.a: $(OBJ)
@rm -f $@
- $(AR) rc $@ $(OBJ) $(ADDLARCHIVEOBJS)
- $(RANLIB) $@
+ if [ -n "@ODP_LIB@" ] ; then $(AR) x @ODP_LIB@ ; fi
+ ODP_OBJS=`$(AR) t @ODP_LIB@`; \
+ $(AR) rc $@ $(OBJ) $(ADDLARCHIVEOBJS) $$ODP_OBJS; \
+ $(RANLIB) $@; \
+ if [ -n "@ODP_LIB@" ] ; then rm $$ODP_OBJS ; fi
shared: libpcap.$(DYEXT)
@@ -369,7 +375,7 @@ libpcap.so: $(OBJ)
VER=`cat $(srcdir)/VERSION`; \
MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
@V_SHLIB_CMD@ @V_SHLIB_OPT@ @V_SONAME_OPT@$@.$$MAJOR_VER $(LDFLAGS) \
- -o $@.$$VER $(OBJ) $(ADDLOBJS) $(LIBS)
+ -o $@.$$VER $(OBJ) $(ADDLOBJS) $(LIBS) @ODP_LIB@
#
# The following rule succeeds, but the result is untested.
@@ -624,6 +630,7 @@ install-shared-so: libpcap.so
$(INSTALL_PROGRAM) libpcap.so.$$VER $(DESTDIR)$(libdir)/libpcap.so.$$VER; \
ln -sf libpcap.so.$$VER $(DESTDIR)$(libdir)/libpcap.so.$$MAJOR_VER; \
ln -sf libpcap.so.$$MAJOR_VER $(DESTDIR)$(libdir)/libpcap.so
+ ln -sf libpcap.so $(DESTDIR)$(libdir)/libpcap.so.0.8
install-shared-dylib: libpcap.dylib
[ -d $(DESTDIR)$(libdir) ] || \
(mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
@@ -253,6 +253,9 @@
/* /dev/dlpi directory */
#undef PCAP_DEV_PREFIX
+/* target host supports odp */
+#undef PCAP_SUPPORT_ODP
+
/* target host supports Bluetooth sniffing */
#undef PCAP_SUPPORT_BT
@@ -658,6 +658,9 @@ AR
RANLIB
V_YACC
V_LEX
+PCAP_SUPPORT_ODP
+ODP_LIB
+ODP_INCLS
HAVE_LINUX_TPACKET_AUXDATA
LIBOBJS
EGREP
@@ -733,6 +736,9 @@ with_libnl
enable_ipv6
enable_optimizer_dbg
enable_yydebug
+with_odp
+with_odp_includes
+with_odp_libraries
with_dag
with_dag_includes
with_dag_libraries
@@ -1396,6 +1402,11 @@ Optional Packages:
--with-pcap=TYPE use packet capture TYPE
--without-libnl disable libnl support [default=yes, on Linux, if
present]
+ --with-odp[=DIR] include ODP support ["yes", "no" or DIR;
+ default="yes" on Linux if present]
+ --with-odp-includes=DIR ODP include directory
+ --with-odp-libraries=DIR
+ ODP library directory
--with-dag[=DIR] include Endace DAG support ["yes", "no" or DIR;
default="yes" on BSD and Linux if present]
--with-dag-includes=DIR Endace DAG include directory
@@ -6079,6 +6090,85 @@ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_yydebug-no}" >&5
$as_echo "${enable_yydebug-no}" >&6; }
+# Check for ODP support.
+
+# Check whether --with-odp was given.
+if test "${with_odp+set}" = set; then :
+ withval=$with_odp;
+ if test "$withval" = no
+ then
+ # User doesn't want ODP support.
+ want_odp=no
+ elif test "$withval" = yes
+ then
+ # User wants ODP support but hasn't specified a directory.
+ want_odp=yes
+ ODP_ROOT=../../..
+ else
+ # User wants ODP support and has specified a directory, so use the provided value.
+ want_odp=yes
+ ODP_ROOT=$withval
+ fi
+
+else
+
+ #
+ # Use ODP API if present, otherwise don't
+ #
+ want_odp=ifpresent
+
+fi
+
+
+
+# Check whether --with-odp-includes was given.
+if test "${with_odp_includes+set}" = set; then :
+ withval=$with_odp_includes;
+ # User wants odp support and has specified a header directory, so use the provided value.
+ want_odp=yes
+ ODP_INCLS=$withval
+
+fi
+
+
+
+# Check whether --with-odp-libraries was given.
+if test "${with_odp_libraries+set}" = set; then :
+ withval=$with_odp_libraries;
+ # User wants odp support and has specified a library directory, so use the provided value.
+ want_odp=yes
+ ODP_LIB=$withval
+
+fi
+
+
+if test "$want_odp" = yes; then
+
+$as_echo "#define PCAP_SUPPORT_ODP 1" >>confdefs.h
+
+
+ # If necessary, set default paths for ODP API headers and libraries.
+ if test -z "$ODP_ROOT"; then
+ ODP_ROOT="../../.."
+ fi
+
+ if test -z "$ODP_INCLS"; then
+ ODP_INCLS="-I$ODP_ROOT/build/include"
+ fi
+
+ if test -z "$ODP_LIB"; then
+ ODP_LIB="$ODP_ROOT/build/lib/libodp.a"
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: ODP is supported" >&5
+$as_echo "$as_me: ODP is supported" >&6;}
+
+
+
+
+
+fi
+
# Check for Endace DAG card support.
# Check whether --with-dag was given.
@@ -697,6 +697,69 @@ if test "$enable_yydebug" = "yes"; then
fi
AC_MSG_RESULT(${enable_yydebug-no})
+# Check for ODP support.
+AC_ARG_WITH([odp],
+AC_HELP_STRING([--with-odp@<:@=DIR@:>@],[include ODP support @<:@"yes", "no" or DIR; default="yes" on Linux if present@:>@]),
+[
+ if test "$withval" = no
+ then
+ # User doesn't want ODP support.
+ want_odp=no
+ elif test "$withval" = yes
+ then
+ # User wants ODP support but hasn't specified a directory.
+ want_odp=yes
+ ODP_ROOT=../../..
+ else
+ # User wants ODP support and has specified a directory, so use the provided value.
+ want_odp=yes
+ ODP_ROOT=$withval
+ fi
+],[
+ #
+ # Use ODP API if present, otherwise don't
+ #
+ want_odp=ifpresent
+])
+
+AC_ARG_WITH([odp-includes],
+AC_HELP_STRING([--with-odp-includes=DIR],[ODP include directory]),
+[
+ # User wants odp support and has specified a header directory, so use the provided value.
+ want_odp=yes
+ ODP_INCLS=$withval
+],[])
+
+AC_ARG_WITH([odp-libraries],
+AC_HELP_STRING([--with-odp-libraries=DIR],[ODP library directory]),
+[
+ # User wants odp support and has specified a library directory, so use the provided value.
+ want_odp=yes
+ ODP_LIB=$withval
+],[])
+
+if test "$want_odp" = yes; then
+ AC_DEFINE(PCAP_SUPPORT_ODP, 1, [target host supports odp])
+
+ # If necessary, set default paths for ODP API headers and libraries.
+ if test -z "$ODP_ROOT"; then
+ ODP_ROOT="../../.."
+ fi
+
+ if test -z "$ODP_INCLS"; then
+ ODP_INCLS="-I$ODP_ROOT/build/include"
+ fi
+
+ if test -z "$ODP_LIB"; then
+ ODP_LIB="$ODP_ROOT/build/lib/libodp.a"
+ fi
+
+ AC_MSG_NOTICE(ODP is supported)
+ AC_SUBST(ODP_INCLS)
+ AC_SUBST(ODP_LIB)
+ AC_SUBST(PCAP_SUPPORT_ODP)
+fi
+
# Check for Endace DAG card support.
AC_ARG_WITH([dag],
AC_HELP_STRING([--with-dag@<:@=DIR@:>@],[include Endace DAG support @<:@"yes", "no" or DIR; default="yes" on BSD and Linux if present@:>@]),
@@ -865,12 +865,22 @@ pcap_lookupnet(device, netp, maskp, errbuf)
register struct sockaddr_in *sin4;
struct ifreq ifr;
+#ifdef PCAP_SUPPORT_ODP
+ if (!strncmp(device, "odp:", 4))
+ device += 4;
+ else if (!strncmp(device, "netmap:", 7))
+ device += 7;
+#endif /* PCAP_SUPPORT_ODP */
+
/*
* The pseudo-device "any" listens on all interfaces and therefore
* has the network address and -mask "0.0.0.0" therefore catching
* all traffic. Using NULL for the interface is the same as "any".
*/
if (!device || strcmp(device, "any") == 0
+#ifdef PCAP_SUPPORT_ODP
+ || !strncmp(device, "vale", 4)
+#endif /* PCAP_SUPPORT_ODP */
#ifdef HAVE_DAG_API
|| strstr(device, "dag") != NULL
#endif
@@ -40,6 +40,13 @@
extern "C" {
#endif
+#ifdef PCAP_SUPPORT_ODP
+#include <odp.h>
+#include <helper/odp_linux.h>
+#include <helper/odp_eth.h>
+#include <helper/odp_ip.h>
+#endif /* PCAP_SUPPORT_ODP */
+
#ifdef WIN32
#include <Packet32.h>
extern CRITICAL_SECTION g_PcapCompileCriticalSection;
@@ -83,6 +90,9 @@ extern CRITICAL_SECTION g_PcapCompileCriticalSection;
#endif /* _MSC_VER */
struct pcap_opt {
+#ifdef PCAP_SUPPORT_ODP
+ char *destination;
+#endif
char *source;
int timeout; /* timeout for buffering */
int buffer_size;
@@ -223,6 +233,13 @@ struct pcap {
getadapter_op_t getadapter_op;
#endif
cleanup_op_t cleanup_op;
+
+#ifdef PCAP_SUPPORT_ODP
+ odp_pktio_t pktio;
+ odp_pktio_t pktio_second;
+ bool is_bridge;
+ bool is_netmap;
+#endif /* PCAP_SUPPORT_ODP */
};
/*
@@ -423,6 +440,11 @@ int install_bpf_program(pcap_t *, struct bpf_program *);
int pcap_strcasecmp(const char *, const char *);
+#ifdef PCAP_SUPPORT_ODP
+pcap_t* odp_create(const char *, char *, int *);
+pcap_t *pcap_create_bridge(const char *, char *, size_t);
+#endif
+
#ifdef __cplusplus
}
#endif
@@ -138,6 +138,17 @@
#include <poll.h>
#include <dirent.h>
+#ifdef PCAP_SUPPORT_ODP
+#include <sys/time.h>
+#define SHM_PKT_POOL_SIZE (512*2048)
+#define SHM_PKT_POOL_BUF_SIZE 1856
+#endif /* PCAP_SUPPORT_ODP */
+
+#ifdef ODP_HAVE_NETMAP
+#include <helper/odp_linux.h>
+#include <odp_pktio_types.h>
+#endif
+
#include "pcap-int.h"
#include "pcap/sll.h"
#include "pcap/vlan.h"
@@ -333,6 +344,12 @@ static int pcap_setfilter_linux(pcap_t *, struct bpf_program *);
static int pcap_setdirection_linux(pcap_t *, pcap_direction_t);
static int pcap_set_datalink_linux(pcap_t *, int);
static void pcap_cleanup_linux(pcap_t *);
+#ifdef PCAP_SUPPORT_ODP
+static void pcap_odp_init(pcap_t *);
+static int pcap_activate_odp(pcap_t *);
+static int pcap_read_odp(pcap_t *, int, pcap_handler, u_char *);
+static void pcap_cleanup_odp(pcap_t *);
+#endif
union thdr {
struct tpacket_hdr *h1;
@@ -1050,7 +1067,6 @@ linux_if_drops(const char * if_name)
return dropped_pkts;
}
-
/*
* With older kernels promiscuous mode is kind of interesting because we
* have to reset the interface before exiting. The problem can't really
@@ -1375,7 +1391,7 @@ pcap_activate_linux(pcap_t *handle)
* "handle->fd" is a socket, so "select()" and "poll()"
* should work on it.
*/
- handle->selectable_fd = handle->fd;
+ handle->selectable_fd = -1;
return status;
@@ -2399,6 +2415,11 @@ pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter,
}
}
+#ifdef PCAP_SUPPORT_ODP
+ /* ODP not yet support filtering_in_kernel */
+ can_filter_in_kernel = 0;
+#endif
+
/*
* NOTE: at this point, we've set both the "len" and "filter"
* fields of "fcode". As of the 2.6.32.4 kernel, at least,
@@ -6056,3 +6077,352 @@ reset_kernel_filter(pcap_t *handle)
&dummy, sizeof(dummy));
}
#endif
+
+#ifdef PCAP_SUPPORT_ODP
+pcap_t *
+odp_create(const char *device, char *ebuf, int *is_ours)
+{
+ pcap_t *handle;
+
+ *is_ours = (!strncmp(device, "odp:", 4)
+ || !strncmp(device, "b:", 2)
+ || !strncmp(device, "netmapb:", 8)
+ || !strncmp(device, "netmap:", 7)
+ || !strncmp(device, "vale", 4));
+ if (! *is_ours)
+ return NULL;
+ if (!strncmp(device, "odp:", 4)) {
+ handle = pcap_create_common((device + 4), ebuf, sizeof(struct pcap_linux));
+ handle->is_bridge = false;
+ handle->is_netmap = false;
+ } else if (!strncmp(device, "b:", 2)) {
+ handle = pcap_create_common((device + 2), ebuf, sizeof(struct pcap_linux));
+ handle->is_bridge = true;
+ handle->is_netmap = false;
+ printf("bridge src: %s, dest: %s\n",
+ handle->opt.source, handle->opt.destination);
+#ifdef ODP_HAVE_NETMAP
+ } else if (!strncmp(device, "netmap:", 7)) {
+ handle = pcap_create_common((device + 7), ebuf, sizeof(struct pcap_linux));
+ handle->is_bridge = false;
+ handle->is_netmap = true;
+ } else if (!strncmp(device, "netmapb:", 8)) {
+ handle = pcap_create_common((device + 8), ebuf, sizeof(struct pcap_linux));
+ handle->is_bridge = true;
+ handle->is_netmap = true;
+ printf("bridge src: %s, dest: %s\n",
+ handle->opt.source, handle->opt.destination);
+#endif
+ } else {
+ handle = pcap_create_common(device, ebuf, sizeof(struct pcap_linux));
+ handle->is_bridge = false;
+ handle->is_netmap = false;
+ }
+ if (handle == NULL)
+ return NULL;
+
+ handle->activate_op = pcap_activate_odp;
+ return (handle);
+}
+
+static void
+pcap_odp_init(pcap_t *handle)
+{
+ int thr_id;
+ odp_buffer_pool_t pool;
+ odp_pktio_t pktio;
+ void *pool_base;
+ char inq_name[ODP_QUEUE_NAME_LEN];
+ odp_queue_t inq_def;
+ odp_queue_param_t qparam;
+ int fd;
+ int ret;
+
+ /* Init ODP before calling anything else */
+ if (odp_init_global()) {
+ fprintf(stderr, "Error: ODP global init failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* Create thread structure for ODP */
+ thr_id = odp_thread_create(0);
+ odp_init_local(thr_id);
+
+ /* Is pool have been created in another theard ? */
+ pool = odp_buffer_pool_lookup("packet_pool");
+ if (pool == ODP_BUFFER_POOL_INVALID) {
+ /* Create packet pool */
+ pool_base = odp_shm_reserve("shm_packet_pool",
+ SHM_PKT_POOL_SIZE, ODP_CACHE_LINE_SIZE);
+ if (pool_base == NULL) {
+ fprintf(stderr,
+ "Error: packet pool mem alloc failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ 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) {
+ fprintf(stderr, "Error: packet pool create failed.\n");
+ exit(EXIT_FAILURE);
+ }
+ odp_buffer_pool_print(pool);
+ } else {
+ fprintf(stdout, "packet pool have been created.\n");
+ }
+
+ /* Open a packet IO instance for this thread */
+ /* if any device, need ODP support */
+
+ /* for netmap */
+ odp_pktio_params_t pparams;
+#ifdef ODP_HAVE_NETMAP
+ if (handle->is_netmap) {
+ memset(&pparams.nm_params, 0, sizeof(pparams.nm_params));
+ pparams.nm_params.type = ODP_PKTIO_TYPE_NETMAP;
+ pparams.nm_params.netmap_mode = ODP_NETMAP_MODE_HW;
+ pparams.nm_params.ringid = 0;
+ printf(" pktio type: netmap\n");
+ } else {
+#endif
+ memset(&pparams.sock_params, 0, sizeof(pparams.sock_params));
+ pparams.sock_params.type = ODP_PKTIO_TYPE_SOCKET;
+ printf(" pktio type: socket\n");
+#ifdef ODP_HAVE_NETMAP
+ }
+#endif
+ handle->pktio = odp_pktio_open(handle->opt.source, pool, &pparams);
+
+ if (handle->pktio == ODP_QUEUE_INVALID) {
+ fprintf(stderr, " Error: pktio create failed %s\n", handle->opt.source);
+ return;
+ }
+
+ /*
+ * 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_NONE;
+ qparam.sched.group = ODP_SCHED_GROUP_DEFAULT;
+ snprintf(inq_name, sizeof(inq_name), "%i-pktio_inq_def",
+ (int)handle->pktio);
+ inq_name[ODP_QUEUE_NAME_LEN - 1] = '\0';
+
+ inq_def = odp_queue_create(inq_name, ODP_QUEUE_TYPE_PKTIN, &qparam);
+ if (inq_def == ODP_QUEUE_INVALID) {
+ fprintf(stderr, " Error: pktio queue creation failed\n");
+ return;
+ }
+
+ ret = odp_pktio_inq_setdef(handle->pktio, inq_def);
+ if (ret != 0) {
+ fprintf(stderr, " Error: default input-Q setup\n");
+ return;
+ }
+
+ printf(" created pktio:%02i, queue mode\n"
+ " default pktio%02i-INPUT queue:%u\n",
+ handle->pktio, handle->pktio, inq_def);
+
+ /* for bridge */
+ if (handle->is_bridge) {
+ handle->pktio_second = odp_pktio_open(handle->opt.destination, pool, &pparams);
+ snprintf(inq_name, sizeof(inq_name), "%i-pktio_inq_def", (int)handle->pktio_second);
+ inq_name[ODP_QUEUE_NAME_LEN - 1] = '\0';
+
+ inq_def = odp_queue_create(inq_name, ODP_QUEUE_TYPE_PKTIN, &qparam);
+ if (inq_def == ODP_QUEUE_INVALID) {
+ fprintf(stderr, " Error: pktio queue creation failed\n");
+ return;
+ }
+
+ ret = odp_pktio_inq_setdef(handle->pktio_second, inq_def);
+ if (ret != 0) {
+ fprintf(stderr, " Error: default input-Q setup\n");
+ return;
+ }
+
+ printf(" created pktio:%02i, queue mode\n"
+ " default pktio%02i-INPUT queue:%u\n",
+ handle->pktio_second, handle->pktio_second, inq_def);
+ }
+}
+
+static int
+pcap_activate_odp(pcap_t *handle)
+{
+ struct pcap_linux *handlep = handle->priv;
+ const char *device;
+ int status = 0;
+ int arptype;
+ struct ifreq ifr;
+
+ /* initial ODP stuff */
+ pcap_odp_init(handle);
+
+ device = handle->opt.source;
+
+ handle->inject_op = pcap_inject_linux;
+ handle->setdirection_op = pcap_setdirection_linux;
+ handle->set_datalink_op = pcap_set_datalink_linux;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->cleanup_op = pcap_cleanup_odp;
+ handle->read_op = pcap_read_odp;
+ handle->setfilter_op = pcap_setfilter_linux;
+ handle->stats_op = pcap_stats_linux;
+
+ /*
+ * The "any" device is a special device which causes us not
+ * to bind to a particular device and thus to look at all
+ * devices.
+ */
+ if (strcmp(device, "any") == 0) {
+ if (handle->opt.promisc) {
+ handle->opt.promisc = 0;
+ /* Just a warning. */
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Promiscuous mode not supported on the \"any\" device");
+ status = PCAP_WARNING_PROMISC_NOTSUP;
+ }
+ }
+
+ handlep->device = strdup(device);
+ if (handlep->device == NULL) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+ pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
+
+ /* copy timeout value */
+ handlep->timeout = handle->opt.timeout;
+
+ /*
+ * If we're in promiscuous mode, then we probably want
+ * to see when the interface drops packets too, so get an
+ * initial count from /proc/net/dev
+ */
+ if (handle->opt.promisc)
+ handlep->proc_dropped = linux_if_drops(handlep->device);
+
+ /* + activate_new */
+ /* Will create a sock_fd just for setting */
+ status = activate_new(handle);
+ if (status < 0)
+ goto fail;
+
+ /* Allocate the buffer */
+ status = 0;
+ if (handle->opt.buffer_size != 0) {
+ /*
+ * Set the socket buffer size to the specified value.
+ */
+ if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
+ &handle->opt.buffer_size,
+ sizeof(handle->opt.buffer_size)) == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "SO_RCVBUF: %s", pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto fail;
+ }
+ }
+
+ handle->buffer = malloc(handle->bufsize + handle->offset);
+ if (!handle->buffer) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto fail;
+ }
+
+ handle->selectable_fd = handle->fd;
+ /* - activate_new */
+
+ return status;
+
+fail:
+ pcap_cleanup_linux(handle);
+ return status;
+}
+
+static int
+pcap_read_odp(pcap_t *handle, int max_packets, pcap_handler callback,
+ u_char *userdata)
+{
+ odp_packet_t pkt;
+ odp_buffer_t buf;
+ u_char *bp;
+ struct pcap_linux *handlep = handle->priv;
+ struct pcap_pkthdr pcap_header;
+ struct timeval ts;
+ long n = 1;
+
+ for (n = 1; (n <= max_packets) || (max_packets < 0); n++) {
+ /* Use schedule to get buf from any input queue */
+ buf = odp_schedule(NULL);
+ /* fill out pcap_header */
+ gettimeofday(&ts, NULL);
+ pcap_header.ts = ts;
+
+ pkt = odp_packet_from_buffer(buf);
+ bp = odp_packet_l2(pkt);
+ pcap_header.len = odp_packet_get_len(pkt);
+ pcap_header.caplen = pcap_header.len;
+
+ /* ODP not yet support filtering_in_kernel */
+ if (handlep->filter_in_userland && handle->fcode.bf_insns) {
+ if (bpf_filter(handle->fcode.bf_insns, bp,
+ pcap_header.len,
+ pcap_header.caplen) == 0) {
+ /* rejected by filter */
+ n--;
+ goto clean_buf;
+ }
+ }
+
+ callback(userdata, &pcap_header, bp);
+
+ /* for bridge */
+ if (handle->is_bridge) {
+ odp_pktio_t pktio_tmp;
+ odp_queue_t outq;
+ pktio_tmp = odp_pktio_get_input(pkt);
+ printf("ODP: from pktio %d\n", pktio_tmp);
+ if (pktio_tmp == handle->pktio) {
+ printf("ODP: to pktio %d\n", handle->pktio_second);
+ outq = odp_pktio_outq_getdef(handle->pktio_second);
+ } else if (pktio_tmp == handle->pktio_second) {
+ printf("ODP: to pktio %d\n", handle->pktio);
+ outq = odp_pktio_outq_getdef(handle->pktio);
+ } else {
+ printf("ODP: Unknown pktio\n");
+ goto clean_buf;
+ }
+ odp_queue_enq(outq, buf);
+ }
+clean_buf:
+ handlep->packets_read++;
+ odp_buffer_free(buf);
+
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ }
+
+ return max_packets;
+}
+
+static void
+pcap_cleanup_odp(pcap_t *handle)
+{
+ odp_pktio_close(handle->pktio);
+ if (handle->is_bridge)
+ odp_pktio_close(handle->pktio_second);
+ pcap_cleanup_linux(handle);
+}
+#endif /* PCAP_SUPPORT_ODP */
@@ -307,6 +307,9 @@ struct capture_source_type {
int (*findalldevs_op)(pcap_if_t **, char *);
pcap_t *(*create_op)(const char *, char *, int *);
} capture_source_types[] = {
+#ifdef PCAP_SUPPORT_ODP
+ { NULL, odp_create },
+#endif
#ifdef HAVE_DAG_API
{ dag_findalldevs, dag_create },
#endif
@@ -527,9 +530,84 @@ pcap_create_common(const char *source, char *ebuf, size_t size)
if (p == NULL)
return (NULL);
- p->opt.source = strdup(source);
+#ifdef PCAP_SUPPORT_ODP
+ if (strstr(source, ",")) {
+ char *delim = ",";
+ p = pcap_alloc_pcap_t(ebuf, size);
+ if (p == NULL)
+ return (NULL);
+
+ p->opt.source = strdup(strtok((char *) source, delim));
+ if (p->opt.source == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ free(p);
+ return (NULL);
+ }
+ p->opt.destination = strdup(strtok(NULL, delim));
+ if (p->opt.destination == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ free(p);
+ return (NULL);
+ }
+ } else {
+#endif
+ p->opt.source = strdup(source);
+ if (p->opt.source == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ free(p);
+ return (NULL);
+ }
+#ifdef PCAP_SUPPORT_ODP
+ }
+#endif
+
+ /*
+ * Default to "can't set rfmon mode"; if it's supported by
+ * a platform, the create routine that called us can set
+ * the op to its routine to check whether a particular
+ * device supports it.
+ */
+ p->can_set_rfmon_op = pcap_cant_set_rfmon;
+
+ initialize_ops(p);
+
+ /* put in some defaults*/
+ pcap_set_snaplen(p, 65535); /* max packet size */
+ p->opt.timeout = 0; /* no timeout specified */
+ p->opt.buffer_size = 0; /* use the platform's default */
+ p->opt.promisc = 0;
+ p->opt.rfmon = 0;
+ p->opt.immediate = 0;
+ p->opt.tstamp_type = -1; /* default to not setting time stamp type */
+ p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
+ return (p);
+}
+
+#ifdef PCAP_SUPPORT_ODP
+pcap_t *
+pcap_create_bridge(const char *device, char *ebuf, size_t size)
+{
+ pcap_t *p;
+ char *delim = ",";
+
+ p = pcap_alloc_pcap_t(ebuf, size);
+ if (p == NULL)
+ return (NULL);
+
+ p->opt.source = strdup(strtok((char *) device, delim));
if (p->opt.source == NULL) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ free(p);
+ return (NULL);
+ }
+
+ p->opt.destination = strdup(strtok(NULL, delim));
+ if (p->opt.destination == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
free(p);
return (NULL);
@@ -541,7 +619,7 @@ pcap_create_common(const char *source, char *ebuf, size_t size)
* the op to its routine to check whether a particular
* device supports it.
*/
- p->can_set_rfmon_op = pcap_cant_set_rfmon;
+ p->can_set_rfmon_op = 0;
initialize_ops(p);
@@ -556,6 +634,7 @@ pcap_create_common(const char *source, char *ebuf, size_t size)
p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
return (p);
}
+#endif /* PCAP_SUPPORT_ODP */
int
pcap_check_activated(pcap_t *p)