diff --git a/test/linux-generic/Makefile.am b/test/linux-generic/Makefile.am
index 4660cf0..998ee56 100644
--- a/test/linux-generic/Makefile.am
+++ b/test/linux-generic/Makefile.am
@@ -37,11 +37,15 @@ TESTS = validation/api/pktio/pktio_run.sh \
 
 SUBDIRS += validation/api/pktio\
 	   validation/api/shmem\
+	   mmap_vlan_ins\
 	   pktio_ipc\
 	   ring
 
 if HAVE_PCAP
 TESTS += validation/api/pktio/pktio_run_pcap.sh
+
+TESTS +=   mmap_vlan_ins/mmap_vlan_ins.sh
+SUBDIRS += mmap_vlan_ins
 endif
 if netmap_support
 TESTS += validation/api/pktio/pktio_run_netmap.sh
diff --git a/test/linux-generic/m4/configure.m4 b/test/linux-generic/m4/configure.m4
index 6b92201..8746dab 100644
--- a/test/linux-generic/m4/configure.m4
+++ b/test/linux-generic/m4/configure.m4
@@ -3,6 +3,7 @@ m4_include([test/linux-generic/m4/performance.m4])
 AC_CONFIG_FILES([test/linux-generic/Makefile
 		 test/linux-generic/validation/api/shmem/Makefile
 		 test/linux-generic/validation/api/pktio/Makefile
+		 test/linux-generic/mmap_vlan_ins/Makefile
 		 test/linux-generic/pktio_ipc/Makefile
 		 test/linux-generic/ring/Makefile
 		 test/linux-generic/performance/Makefile])
diff --git a/test/linux-generic/mmap_vlan_ins/.gitignore b/test/linux-generic/mmap_vlan_ins/.gitignore
new file mode 100644
index 0000000..755fa2e
--- /dev/null
+++ b/test/linux-generic/mmap_vlan_ins/.gitignore
@@ -0,0 +1,2 @@
+*.pcap
+plat_mmap_vlan_ins
diff --git a/test/linux-generic/mmap_vlan_ins/Makefile.am b/test/linux-generic/mmap_vlan_ins/Makefile.am
new file mode 100644
index 0000000..2641556
--- /dev/null
+++ b/test/linux-generic/mmap_vlan_ins/Makefile.am
@@ -0,0 +1,15 @@
+include $(top_srcdir)/test/Makefile.inc
+TESTS_ENVIRONMENT += TEST_DIR=${top_builddir}/test/validation
+
+dist_check_SCRIPTS = vlan.pcap \
+		     mmap_vlan_ins.sh \
+		     pktio_env
+
+test_SCRIPTS = $(dist_check_SCRIPTS)
+
+bin_PROGRAMS = plat_mmap_vlan_ins$(EXEEXT)
+plat_mmap_vlan_ins_LDFLAGS = $(AM_LDFLAGS) -static
+plat_mmap_vlan_ins_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/example
+
+# Clonned from example odp_l2fwd simple
+dist_plat_mmap_vlan_ins_SOURCES = mmap_vlan_ins.c
diff --git a/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c
new file mode 100644
index 0000000..0682d2d
--- /dev/null
+++ b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.c
@@ -0,0 +1,232 @@
+/* Copyright (c) 2016, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <signal.h>
+
+#include <odp_api.h>
+#include <odp/helper/linux.h>
+#include <odp/helper/eth.h>
+#include <odp/helper/ip.h>
+
+#define POOL_NUM_PKT 8192
+#define POOL_SEG_LEN 1856
+#define MAX_PKT_BURST 32
+#define MAX_WORKERS 1
+
+static int exit_thr;
+static int g_ret;
+
+struct {
+	odp_pktio_t if0, if1;
+	odp_pktin_queue_t if0in, if1in;
+	odp_pktout_queue_t if0out, if1out;
+	odph_ethaddr_t src, dst;
+} global;
+
+static void sig_handler(int signo ODP_UNUSED)
+{
+	printf("sig_handler!\n");
+	exit_thr = 1;
+}
+
+static odp_pktio_t create_pktio(const char *name, odp_pool_t pool,
+				odp_pktin_queue_t *pktin,
+				odp_pktout_queue_t *pktout)
+{
+	odp_pktio_param_t pktio_param;
+	odp_pktin_queue_param_t in_queue_param;
+	odp_pktout_queue_param_t out_queue_param;
+	odp_pktio_t pktio;
+
+	odp_pktio_param_init(&pktio_param);
+
+	pktio = odp_pktio_open(name, pool, &pktio_param);
+	if (pktio == ODP_PKTIO_INVALID) {
+		printf("Failed to open %s\n", name);
+		exit(1);
+	}
+
+	odp_pktin_queue_param_init(&in_queue_param);
+	odp_pktout_queue_param_init(&out_queue_param);
+
+	in_queue_param.op_mode = ODP_PKTIO_OP_MT_UNSAFE;
+
+	if (odp_pktin_queue_config(pktio, &in_queue_param)) {
+		printf("Failed to config input queue for %s\n", name);
+		exit(1);
+	}
+
+	out_queue_param.op_mode = ODP_PKTIO_OP_MT_UNSAFE;
+
+	if (odp_pktout_queue_config(pktio, &out_queue_param)) {
+		printf("Failed to config output queue for %s\n", name);
+		exit(1);
+	}
+
+	if (odp_pktin_queue(pktio, pktin, 1) != 1) {
+		printf("pktin queue query failed for %s\n", name);
+		exit(1);
+	}
+	if (odp_pktout_queue(pktio, pktout, 1) != 1) {
+		printf("pktout queue query failed for %s\n", name);
+		exit(1);
+	}
+	return pktio;
+}
+
+static int run_worker(void *arg ODP_UNUSED)
+{
+	odp_packet_t pkt_tbl[MAX_PKT_BURST];
+	int pkts, sent, tx_drops, i;
+	int total_pkts = 0;
+
+	if (odp_pktio_start(global.if0)) {
+		printf("unable to start input interface\n");
+		exit(1);
+	}
+	printf("started input interface\n");
+	if (odp_pktio_start(global.if1)) {
+		printf("unable to start output interface\n");
+		exit(1);
+	}
+	printf("started output interface\n");
+	printf("started all\n");
+
+	while (!exit_thr) {
+		pkts = odp_pktin_recv_tmo(global.if0in, pkt_tbl, MAX_PKT_BURST,
+					  ODP_PKTIN_NO_WAIT);
+
+		if (odp_unlikely(pkts <= 0))
+			continue;
+		for (i = 0; i < pkts; i++) {
+			odp_packet_t pkt = pkt_tbl[i];
+			odph_ethhdr_t *eth;
+
+			if (odp_unlikely(!odp_packet_has_eth(pkt))) {
+				printf("warning: packet has no eth header\n");
+				return 0;
+			}
+			eth = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
+			eth->src = global.src;
+			eth->dst = global.dst;
+		}
+		sent = odp_pktout_send(global.if1out, pkt_tbl, pkts);
+		if (sent < 0)
+			sent = 0;
+		total_pkts += sent;
+		tx_drops = pkts - sent;
+		if (odp_unlikely(tx_drops))
+			odp_packet_free_multi(&pkt_tbl[sent], tx_drops);
+	}
+
+	if (total_pkts < 10)
+		g_ret = -1;
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	odp_pool_t pool;
+	odp_pool_param_t params;
+	odp_cpumask_t cpumask;
+	odph_odpthread_t thd[MAX_WORKERS];
+	odp_instance_t instance;
+	odph_odpthread_params_t thr_params;
+	int opt;
+	int long_index;
+
+	static const struct option longopts[] = { {NULL, 0, NULL, 0} };
+	static const char *shortopts = "";
+
+	/* let helper collect its own arguments (e.g. --odph_proc) */
+	odph_parse_options(argc, argv, shortopts, longopts);
+
+	/*
+	 * parse own options: currentely none, but this will move optind
+	 * to the first non-option argument. (in case there where helprt args)
+	 */
+	opterr = 0; /* do not issue errors on helper options */
+	while (1) {
+		opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
+		if (-1 == opt)
+			break;  /* No more options */
+	}
+
+	if (argc != optind + 4 ||
+	    odph_eth_addr_parse(&global.dst, argv[optind + 2]) != 0 ||
+	    odph_eth_addr_parse(&global.src, argv[optind + 3]) != 0) {
+		printf("Usage: odp_l2fwd_simple eth0 eth1 01:02:03:04:05:06"
+		       " 07:08:09:0a:0b:0c\n");
+		printf("Where eth0 and eth1 are the used interfaces"
+		       " (must have 2 of them)\n");
+		printf("And the hexadecimal numbers are destination MAC address"
+		       " and source MAC address\n");
+		exit(1);
+	}
+
+	if (odp_init_global(&instance, NULL, NULL)) {
+		printf("Error: ODP global init failed.\n");
+		exit(1);
+	}
+
+	if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
+		printf("Error: ODP local init failed.\n");
+		exit(1);
+	}
+
+	/* Create packet pool */
+	odp_pool_param_init(&params);
+	params.pkt.seg_len = POOL_SEG_LEN;
+	params.pkt.len     = POOL_SEG_LEN;
+	params.pkt.num     = POOL_NUM_PKT;
+	params.type        = ODP_POOL_PACKET;
+
+	pool = odp_pool_create("packet pool", &params);
+
+	if (pool == ODP_POOL_INVALID) {
+		printf("Error: packet pool create failed.\n");
+		exit(1);
+	}
+
+	global.if0 = create_pktio(argv[optind], pool, &global.if0in,
+								&global.if0out);
+	global.if1 = create_pktio(argv[optind + 1], pool, &global.if1in,
+								&global.if1out);
+
+	odp_cpumask_default_worker(&cpumask, MAX_WORKERS);
+
+	memset(&thr_params, 0, sizeof(thr_params));
+	thr_params.start    = run_worker;
+	thr_params.arg      = NULL;
+	thr_params.thr_type = ODP_THREAD_WORKER;
+	thr_params.instance = instance;
+
+	signal(SIGINT, sig_handler);
+
+	odph_odpthreads_create(thd, &cpumask, &thr_params);
+	odph_odpthreads_join(thd);
+
+	if (odp_pool_destroy(pool)) {
+		printf("Error: pool destroy\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (odp_term_local()) {
+		printf("Error: term local\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (odp_term_global(instance)) {
+		printf("Error: term global\n");
+		exit(EXIT_FAILURE);
+	}
+
+	return g_ret;
+}
diff --git a/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.sh b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.sh
new file mode 100755
index 0000000..476ab9b
--- /dev/null
+++ b/test/linux-generic/mmap_vlan_ins/mmap_vlan_ins.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+#
+# Copyright (c) 2016, Linaro Limited
+# All rights reserved.
+#
+# SPDX-License-Identifier:	BSD-3-Clause
+#
+
+#
+# This test is intend to test pkt_mmap_vlan_insert() feature for
+# linux-generic packet mmap pktio.
+#
+#
+
+# directory where platform test sources are, including scripts
+TEST_SRC_DIR=$(dirname $0)
+
+# exit codes expected by automake for skipped tests
+TEST_SKIPPED=77
+
+# directories where binary can be found:
+# -in the validation dir when running make check (intree or out of tree)
+# -in the script directory, when running after 'make install', or
+# -in the validation when running standalone intree.
+# -in the current directory.
+# running stand alone out of tree requires setting PATH
+PATH=${TEST_DIR}/../mmap_vlan_ins:$PATH
+PATH=`pwd`/mmap_vlan_ins:$PATH
+PATH=$(dirname $0):$PATH
+PATH=.:$PATH
+
+bin_path=$(which plat_mmap_vlan_ins${EXEEXT})
+if [ -x "$bin_path" ] ; then
+	echo "running with plat_mmap_vlan_ins: $bin_path"
+else
+	echo "cannot find plat_mmap_vlan_ins: please set you PATH for it."
+	pwd
+	exit 1
+fi
+
+
+# Use installed pktio env or for make check take it from platform directory
+if [ -f "./pktio_env" ]; then
+	. ./pktio_env
+elif [ -f ${TEST_SRC_DIR}/pktio_env ]; then
+	. ${TEST_SRC_DIR}/pktio_env
+else
+	echo "BUG: unable to find pktio_env!"
+	echo "pktio_env has to be in current directory or"
+	echo " in platform/\$ODP_PLATFORM/test."
+	echo "ODP_PLATFORM=\"$ODP_PLATFORM\""
+	exit 1
+fi
+
+setup_pktio_env
+
+PCAP_IN=`find . ${TEST_DIR} $(dirname $0) -name vlan.pcap -print -quit`
+echo "using PCAP_IN = ${PCAP_IN}"
+PCAP_OUT=vlan_out.pcap
+
+# Listen on veth pipe and write to pcap Send pcap
+plat_mmap_vlan_ins${EXEEXT} pktiop0p1 pcap:out=${PCAP_OUT} \
+	00:02:03:04:05:06 00:08:09:0a:0b:0c &
+P1=$!
+# Send pcap file to veth interface
+plat_mmap_vlan_ins${EXEEXT} pcap:in=${PCAP_IN} pktiop0p1 \
+	01:02:03:04:05:06 01:08:09:0a:0b:0c &
+P2=$!
+
+sleep 1
+kill -s INT ${P1}
+kill -s INT ${P2}
+
+ret=$?
+rm -f ${PCAP_OUT}
+
+cleanup_pktio_env
+
+exit $ret
diff --git a/test/linux-generic/mmap_vlan_ins/pktio_env b/test/linux-generic/mmap_vlan_ins/pktio_env
new file mode 100644
index 0000000..345b5bd
--- /dev/null
+++ b/test/linux-generic/mmap_vlan_ins/pktio_env
@@ -0,0 +1,120 @@
+#!/bin/sh
+#
+# Copyright (c) 2015, Linaro Limited
+# All rights reserved.
+#
+# SPDX-License-Identifier:	BSD-3-Clause
+#
+# Test script wrapper for running ODP pktio apps on linux-generic.
+#
+# For linux-generic the default behavior is to create two pairs of
+# virtual Ethernet interfaces and provide the names of these via
+# environment variables to pktio apps, the interfaces will be removed
+# before the script exits.
+#
+# Note that the creation of virtual Ethernet devices depends on having
+# CONFIG_VETH enabled in the kernel, if not enabled the env setup will be skipped.
+#
+# Network set up
+# IF0 <---> IF1
+# IF2 <---> IF3
+IF0=pktiop0p1
+IF1=pktiop1p0
+IF2=pktiop2p3
+IF3=pktiop3p2
+
+if [ "$0" = "$BASH_SOURCE" ]; then
+	echo "Error: Platform specific env file has to be sourced."
+fi
+
+check_for_root()
+{
+	if [ "$(id -u)" != "0" ]; then
+		echo "check_for_root(): need to be root to setup VETH"
+		return 1
+	fi
+	return 0
+}
+
+# wait for a network interface's operational state to be "up"
+wait_for_iface_up()
+{
+	iface=$1
+	cnt=0
+
+	while [ $cnt -lt 50 ]; do
+		read operstate < /sys/class/net/$iface/operstate
+
+		if [ $? -ne 0 ]; then
+			break
+		elif [ "$operstate" = "up" ]; then
+			return 0
+		fi
+
+		sleep 0.1
+		cnt=`expr $cnt + 1`
+	done
+
+	return 1
+}
+
+setup_pktio_env()
+{
+	echo "pktio: setting up test interfaces $IF0, $IF1, $IF2, $IF3."
+
+	check_for_root
+	if [ $? -ne 0 ]; then
+		return 1
+	fi
+
+	for iface in $IF0 $IF1 $IF2 $IF3; do
+		ip link show $iface 2> /dev/null
+		if [ $? -eq 0 ]; then
+			echo "pktio: interface $iface already exist $?"
+			return 2
+		fi
+	done
+
+	if [ "$1" = "clean" ]; then
+		trap cleanup_pktio_env EXIT
+	fi
+
+	ip link add $IF0 type veth peer name $IF1
+	if [ $? -ne 0 ]; then
+		echo "pktio: error: unable to create veth pair"
+		return 3
+	fi
+	ip link add $IF2 type veth peer name $IF3
+	if [ $? -ne 0 ]; then
+		echo "pktio: error: unable to create veth pair"
+		return 4
+	fi
+
+	for iface in $IF0 $IF1 $IF2 $IF3; do
+		ip link set $iface mtu 9216 up
+		ifconfig $iface -arp
+	done
+
+	# check that the interface has come up before starting the test
+	for iface in $IF0 $IF1 $IF2 $IF3; do
+		wait_for_iface_up $iface
+		if [ $? -ne 0 ]; then
+			echo "pktio: interface $iface failed to come up"
+			return 5
+		fi
+	done
+}
+
+cleanup_pktio_env()
+{
+	echo "pktio: removing test interfaces $IF0, $IF1, $IF2, $IF3"
+	check_for_root
+	if [ $? -ne 0 ]; then
+		return 1
+	fi
+
+	for iface in $IF0 $IF1 $IF2 $IF3; do
+		ip link del $iface 2> /dev/null
+	done
+	return 0
+}
