diff mbox

[1/2] patch libpcap for odp

Message ID 1397824028-22186-1-git-send-email-maxim.uvarov@linaro.org
State Accepted
Headers show

Commit Message

Maxim Uvarov April 18, 2014, 12:27 p.m. UTC
From: Vincent Hsu <vincent.hsu@linaro.org>

Signed-off-by: Vincent Hsu <vincent.hsu@linaro.org>
---

 ODP Libpcap example was moved to new git repo:
  https://git.linaro.org/lng/odp-apps.git

 I think it's reasonable to have this patch revied in mailing list also,
 so sending it now.

 Best regards,
 Maxim.



 Makefile.in  |  15 ++-
 config.h.in  |   3 +
 configure    |  90 ++++++++++++++
 configure.in |  63 ++++++++++
 inet.c       |  10 ++
 pcap-int.h   |  22 ++++
 pcap-linux.c | 374 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 pcap.c       |  83 ++++++++++++-
 8 files changed, 652 insertions(+), 8 deletions(-)
diff mbox

Patch

diff --git a/Makefile.in b/Makefile.in
index 47f5a06..ec2acd8 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -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))
diff --git a/config.h.in b/config.h.in
index c6bc68e..be3175d 100644
--- a/config.h.in
+++ b/config.h.in
@@ -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
 
diff --git a/configure b/configure
index 07c2d33..34c2d84 100755
--- a/configure
+++ b/configure
@@ -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.
diff --git a/configure.in b/configure.in
index 42cbe9b..96e8331 100644
--- a/configure.in
+++ b/configure.in
@@ -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@:>@]),
diff --git a/inet.c b/inet.c
index c699658..beacc4e 100644
--- a/inet.c
+++ b/inet.c
@@ -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
diff --git a/pcap-int.h b/pcap-int.h
index 6d6febe..ca86c8d 100644
--- a/pcap-int.h
+++ b/pcap-int.h
@@ -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
diff --git a/pcap-linux.c b/pcap-linux.c
index a15a8b1..be0ef20 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -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 */
diff --git a/pcap.c b/pcap.c
index b2b5da6..242cb6a 100644
--- a/pcap.c
+++ b/pcap.c
@@ -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)