diff --git a/include/odp/api/nic.h b/include/odp/api/nic.h
index 0b13afd..3846608 100644
--- a/include/odp/api/nic.h
+++ b/include/odp/api/nic.h
@@ -20,6 +20,11 @@
 extern "C" {
 #endif
 
+/** @defgroup odp_drivers ODP DRIVERS
+ * Interface ODP-driver
+ *  @{
+ */
+
 /**
  * @typedef odp_nic_sgmt_pool_t
  * A nic segment pool.
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index a070cb3..c47bf52 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -34,6 +34,7 @@ odpinclude_HEADERS = \
 		  $(srcdir)/include/odp/hash.h \
 		  $(srcdir)/include/odp/hints.h \
 		  $(srcdir)/include/odp/init.h \
+		  $(srcdir)/include/odp/nic.h \
 		  $(srcdir)/include/odp/packet_flags.h \
 		  $(srcdir)/include/odp/packet.h \
 		  $(srcdir)/include/odp/packet_io.h \
@@ -71,6 +72,7 @@ odpplatinclude_HEADERS = \
 		  $(srcdir)/include/odp/plat/crypto_types.h \
 		  $(srcdir)/include/odp/plat/dma_types.h \
 		  $(srcdir)/include/odp/plat/event_types.h \
+		  $(srcdir)/include/odp/plat/nic_types.h \
 		  $(srcdir)/include/odp/plat/packet_types.h \
 		  $(srcdir)/include/odp/plat/packet_io_types.h \
 		  $(srcdir)/include/odp/plat/pci_types.h \
@@ -143,6 +145,7 @@ __LIB__libodp_la_SOURCES = \
 			   odp_init.c \
 			   odp_impl.c \
 			   odp_name_table.c \
+			   odp_nic.c \
 			   odp_packet.c \
 			   odp_packet_flags.c \
 			   odp_packet_io.c \
diff --git a/platform/linux-generic/include/odp/nic.h b/platform/linux-generic/include/odp/nic.h
new file mode 100644
index 0000000..b991bc3
--- /dev/null
+++ b/platform/linux-generic/include/odp/nic.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP nic driver interface
+ */
+
+#ifndef ODP_PLAT_NIC_H_
+#define ODP_PLAT_NIC_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/std_types.h>
+#include <odp/dma.h>
+#include <odp/shared_memory.h>
+#include <odp/plat/nic_types.h>
+
+/** @ingroup odp_nic
+ *  @{
+ */
+
+/**
+ * @}
+ */
+
+#include <odp/api/nic.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/plat/nic_types.h b/platform/linux-generic/include/odp/plat/nic_types.h
new file mode 100644
index 0000000..2cec1b4
--- /dev/null
+++ b/platform/linux-generic/include/odp/plat/nic_types.h
@@ -0,0 +1,46 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/**
+ * @file
+ *
+ * ODP NIC driver interface
+ */
+
+#ifndef ODP_NIC_TYPES_H_
+#define ODP_NIC_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <odp/std_types.h>
+#include <odp/plat/strong_types.h>
+#include <odp/plat/pool_types.h>
+
+/** @addtogroup odp_nic
+ *  @{
+ */
+
+/** Nic segment pool */
+typedef ODP_HANDLE_T(odp_nic_sgmt_pool_t);
+/** Invalid nic segment pool */
+#define ODP_NIC_SGMT_POOL_INVALID  _odp_cast_scalar(odp_nic_sgmt_pool_t, -1)
+
+/** Nic segment */
+typedef ODP_HANDLE_T(odp_nic_sgmt_t);
+/** Invalid nic segment */
+#define ODP_NIC_SGMT_INVALID _odp_cast_scalar(odp_nic_sgmt_t, -1)
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/platform/linux-generic/include/odp/plat/pool_types.h b/platform/linux-generic/include/odp/plat/pool_types.h
index 4b32c29..c77e6be 100644
--- a/platform/linux-generic/include/odp/plat/pool_types.h
+++ b/platform/linux-generic/include/odp/plat/pool_types.h
@@ -28,7 +28,8 @@ extern "C" {
 
 typedef ODP_HANDLE_T(odp_pool_t);
 
-#define ODP_POOL_INVALID _odp_cast_scalar(odp_pool_t, 0xffffffff)
+#define ODP_POOL_INVALID  _odp_cast_scalar(odp_pool_t, 0xffffffff)
+#define ODP_POOL_ALL_PKTS _odp_cast_scalar(odp_pool_t, 0xfffffffe)
 
 /**
  * Pool type
diff --git a/platform/linux-generic/odp_nic.c b/platform/linux-generic/odp_nic.c
new file mode 100644
index 0000000..0cd1c19
--- /dev/null
+++ b/platform/linux-generic/odp_nic.c
@@ -0,0 +1,163 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <odp/nic.h>
+#include <odp/pool.h>
+#include <odp_packet_io_internal.h>
+
+/* operations on NIC segments pools: */
+odp_nic_sgmt_pool_t odp_nic_sgmt_pool_create(odp_pool_t pool_hdl)
+{
+	odp_pool_info_t info;
+
+	if (pool_hdl == ODP_POOL_ALL_PKTS)
+		return (odp_nic_sgmt_pool_t)pool_hdl;
+
+	if (odp_pool_info(pool_hdl, &info) < 0)
+		return ODP_NIC_SGMT_POOL_INVALID;
+
+	if (info.params.type != ODP_POOL_PACKET)
+		return ODP_NIC_SGMT_POOL_INVALID;
+
+	/* in the linux implementation, segment pools maps packet pools: */
+	return (odp_nic_sgmt_pool_t)pool_hdl;
+}
+
+void odp_nic_sgmt_pool_destroy(odp_nic_sgmt_pool_t sgmt_pool_hdl ODP_UNUSED)
+{
+	/* nothing to do on this linux implementation */
+}
+
+int odp_nic_sgmt_pool_info(odp_nic_sgmt_pool_t pool,
+			   odp_nic_sgmt_pool_info_t *info)
+{
+	odp_pool_info_t pool_info;
+
+	if (!info)
+		return -1;
+
+	if ((odp_pool_t)pool == ODP_POOL_ALL_PKTS)
+		return -1;
+
+	if (odp_pool_info((odp_pool_t)pool, &pool_info) < 0)
+		return -1;
+
+	if (pool_info.params.type != ODP_POOL_PACKET)
+		return -1;
+
+	/*
+	 * in linux generic, the packet are not really fragmented:
+	 * one segment covers the whole packet.
+	 * therefore the size of the segment is the size of the packet
+	 * minus the default tail and headroom
+	 */
+	info->nic_max_seg_size = pool_info.params.pkt.len
+				       - ODP_CONFIG_PACKET_HEADROOM
+				       - ODP_CONFIG_PACKET_TAILROOM;
+	info->nic_max_pkt_size = info->nic_max_seg_size;
+
+	return 0;
+}
+
+odp_dma_map_t odp_nic_sgmt_pool_dma_map(odp_nic_sgmt_pool_t pool)
+{
+	odp_pool_info_t pool_info;
+
+	if ((odp_pool_t)pool == ODP_POOL_ALL_PKTS)
+		return _odp_pool_get_dma_map((odp_pool_t)pool);
+
+	if (odp_pool_info((odp_pool_t)pool, &pool_info) < 0)
+		return ODP_DMA_REGION_INVALID;
+
+	if (pool_info.params.type != ODP_POOL_PACKET)
+		return ODP_DMA_REGION_INVALID;
+
+	return _odp_pool_get_dma_map((odp_pool_t)pool);
+}
+
+/* operations on NIC segments: */
+odp_nic_sgmt_t odp_nic_sgmt_alloc(odp_nic_sgmt_pool_t pool)
+{
+	odp_packet_t packet;
+	odp_pool_t packet_pool;
+
+	/* in the linux implementation, nic segments 1:1 map to odp packets */
+	packet_pool = (odp_pool_t)pool;
+	packet = packet_alloc(packet_pool, 0, 1);
+	if (odp_likely(packet != ODP_PACKET_INVALID)) {
+		/* following call is empty on linux, but just as a reminder...*/
+		odp_nic_sgmt_set_next((odp_nic_sgmt_t)packet,
+				      ODP_NIC_SGMT_INVALID);
+		return (odp_nic_sgmt_t)packet;
+	} else {
+		return ODP_NIC_SGMT_INVALID;
+	}
+}
+
+void odp_nic_sgmt_free(odp_nic_sgmt_t sgmt)
+{
+	if (odp_likely(sgmt != ODP_NIC_SGMT_INVALID))
+		odp_packet_free((odp_packet_t)sgmt);
+}
+
+/** returns the virtual userland address for the segment */
+void *odp_nic_sgmt_get_addr(odp_nic_sgmt_t segmt)
+{
+	return odp_packet_data((odp_packet_t)segmt);
+}
+
+/** returns the dma address for the segment */
+odp_dma_addr_t odp_nic_sgmt_get_dma_addr(odp_nic_sgmt_t segmt)
+{
+	/*FIXME: using the virtual address as dma address will only work
+	  with iommu and a single process. */
+	return (odp_dma_addr_t)odp_packet_data((odp_packet_t)segmt);
+}
+
+/** returns the writable length for the segment */
+uint16_t odp_nic_sgmt_get_len(odp_nic_sgmt_t segmt)
+{
+	return odp_packet_buf_len((odp_packet_t)segmt) -
+	       odp_packet_headroom((odp_packet_t)segmt);
+}
+
+/** returns the data length (in bytes) for the segment */
+uint16_t odp_nic_sgmt_get_datalen(odp_nic_sgmt_t segmt)
+{
+	return odp_packet_len((odp_packet_t)segmt);
+}
+
+/**  set the data length (in bytes) for the segment */
+void odp_nic_sgmt_set_datalen(odp_nic_sgmt_t segmt, uint16_t len)
+{
+	odp_packet_pull_tail((odp_packet_t)segmt,
+			     odp_packet_len((odp_packet_t)segmt) - len);
+}
+
+/** get the next segment of a segment chain (or ODP_NIC_SGMT_INVALID) */
+odp_nic_sgmt_t odp_nic_sgmt_get_next(
+	__attribute__((__unused__)) odp_nic_sgmt_t segmt)
+{
+	/* not needed on linux generic as packet are contiguous */
+	return ODP_NIC_SGMT_INVALID;
+}
+
+/** set the next segment of a segment chain (may be ODP_NIC_SGMT_INVALID) */
+void odp_nic_sgmt_set_next(
+	__attribute__((__unused__)) odp_nic_sgmt_t segmt,
+	__attribute__((__unused__)) odp_nic_sgmt_t next)
+{
+	/* not needed on linux generic as packet are contiguous */
+}
+
+/**  set the segment as last segment of the packet. */
+void odp_nic_sgmt_set_last(odp_nic_sgmt_t segmt)
+{
+	odp_packet_hdr_t *pkt_hdr;
+
+	pkt_hdr = odp_packet_hdr((odp_packet_t)segmt);
+	packet_parse_l2(pkt_hdr);
+}
