diff --git a/drivers/net/softnic/Makefile b/drivers/net/softnic/Makefile
index b211559..677a5b1 100644
--- a/drivers/net/softnic/Makefile
+++ b/drivers/net/softnic/Makefile
@@ -26,6 +26,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_mempool.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_swq.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_link.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tm.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_SOFTNIC) += rte_eth_softnic_tap.c
 
 #
 # Export include files
diff --git a/drivers/net/softnic/rte_eth_softnic.c b/drivers/net/softnic/rte_eth_softnic.c
index d3b659f..4cd5cb7 100644
--- a/drivers/net/softnic/rte_eth_softnic.c
+++ b/drivers/net/softnic/rte_eth_softnic.c
@@ -225,6 +225,7 @@ pmd_init(struct pmd_params *params)
 	softnic_mempool_init(p);
 	softnic_swq_init(p);
 	softnic_link_init(p);
+	softnic_tap_init(p);
 
 	return p;
 }
@@ -235,6 +236,7 @@ pmd_free(struct pmd_internals *p)
 	if (p == NULL)
 		return;
 
+	softnic_tap_free(p);
 	softnic_link_free(p);
 	softnic_swq_free(p);
 	softnic_mempool_free(p);
diff --git a/drivers/net/softnic/rte_eth_softnic_internals.h b/drivers/net/softnic/rte_eth_softnic_internals.h
index be56c4f..c7177d4 100644
--- a/drivers/net/softnic/rte_eth_softnic_internals.h
+++ b/drivers/net/softnic/rte_eth_softnic_internals.h
@@ -201,6 +201,17 @@ struct tm_internals {
 };
 
 /**
+ * TAP
+ */
+struct softnic_tap {
+	TAILQ_ENTRY(softnic_tap) node;
+	char name[NAME_SIZE];
+	int fd;
+};
+
+TAILQ_HEAD(softnic_tap_list, softnic_tap);
+
+/**
  * PMD Internals
  */
 struct pmd_internals {
@@ -215,6 +226,7 @@ struct pmd_internals {
 	struct softnic_mempool_list mempool_list;
 	struct softnic_swq_list swq_list;
 	struct softnic_link_list link_list;
+	struct softnic_tap_list tap_list;
 };
 
 /**
@@ -294,4 +306,21 @@ tm_used(struct rte_eth_dev *dev __rte_unused)
 	return 0;
 }
 
+/**
+ * TAP
+ */
+int
+softnic_tap_init(struct pmd_internals *p);
+
+void
+softnic_tap_free(struct pmd_internals *p);
+
+struct softnic_tap *
+softnic_tap_find(struct pmd_internals *p,
+	const char *name);
+
+struct softnic_tap *
+softnic_tap_create(struct pmd_internals *p,
+	const char *name);
+
 #endif /* __INCLUDE_RTE_ETH_SOFTNIC_INTERNALS_H__ */
diff --git a/drivers/net/softnic/rte_eth_softnic_tap.c b/drivers/net/softnic/rte_eth_softnic_tap.c
new file mode 100644
index 0000000..bcc23a9
--- /dev/null
+++ b/drivers/net/softnic/rte_eth_softnic_tap.c
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2018 Intel Corporation
+ */
+
+#include <netinet/in.h>
+#ifdef RTE_EXEC_ENV_LINUXAPP
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#endif
+#include <sys/ioctl.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rte_string_fns.h>
+
+#include "rte_eth_softnic_internals.h"
+
+#define TAP_DEV                                            "/dev/net/tun"
+
+int
+softnic_tap_init(struct pmd_internals *p)
+{
+	TAILQ_INIT(&p->tap_list);
+
+	return 0;
+}
+
+void
+softnic_tap_free(struct pmd_internals *p)
+{
+	for ( ; ; ) {
+		struct softnic_tap *tap;
+
+		tap = TAILQ_FIRST(&p->tap_list);
+		if (tap == NULL)
+			break;
+
+		TAILQ_REMOVE(&p->tap_list, tap, node);
+		free(tap);
+	}
+}
+
+struct softnic_tap *
+softnic_tap_find(struct pmd_internals *p,
+	const char *name)
+{
+	struct softnic_tap *tap;
+
+	if (name == NULL)
+		return NULL;
+
+	TAILQ_FOREACH(tap, &p->tap_list, node)
+		if (strcmp(tap->name, name) == 0)
+			return tap;
+
+	return NULL;
+}
+
+#ifndef RTE_EXEC_ENV_LINUXAPP
+
+struct softnic_tap *
+softnic_tap_create(struct pmd_internals *p __rte_unused,
+	const char *name __rte_unused)
+{
+	return NULL;
+}
+
+#else
+
+struct softnic_tap *
+softnic_tap_create(struct pmd_internals *p,
+	const char *name)
+{
+	struct softnic_tap *tap;
+	struct ifreq ifr;
+	int fd, status;
+
+	/* Check input params */
+	if (name == NULL ||
+		softnic_tap_find(p, name))
+		return NULL;
+
+	/* Resource create */
+	fd = open(TAP_DEV, O_RDWR | O_NONBLOCK);
+	if (fd < 0)
+		return NULL;
+
+	memset(&ifr, 0, sizeof(ifr));
+	ifr.ifr_flags = IFF_TAP | IFF_NO_PI; /* No packet information */
+	snprintf(ifr.ifr_name, IFNAMSIZ, "%s", name);
+
+	status = ioctl(fd, TUNSETIFF, (void *)&ifr);
+	if (status < 0) {
+		close(fd);
+		return NULL;
+	}
+
+	/* Node allocation */
+	tap = calloc(1, sizeof(struct softnic_tap));
+	if (tap == NULL) {
+		close(fd);
+		return NULL;
+	}
+	/* Node fill in */
+	strlcpy(tap->name, name, sizeof(tap->name));
+	tap->fd = fd;
+
+	/* Node add to list */
+	TAILQ_INSERT_TAIL(&p->tap_list, tap, node);
+
+	return tap;
+}
+
+#endif
