diff --git a/MAINTAINERS b/MAINTAINERS
index b51c2d0..c48f1b5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -781,6 +781,14 @@ F: doc/guides/prog_guide/pdump_lib.rst
 F: app/pdump/
 F: doc/guides/tools/pdump.rst
 
+Port Representors
+M: Declan Doherty <declan.doherty@intel.com>
+M: Mohammad Abdul Awal <mohammad.abdul.awal@intel.com>
+M: Remy Horton <remy.horton@intel.com>
+F: lib/librte_representor
+F: doc/guides/prog_guide/representor_lib.rst
+
+
 Packet Framework
 ----------------
 M: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
@@ -794,7 +802,6 @@ F: doc/guides/sample_app_ug/test_pipeline.rst
 F: examples/ip_pipeline/
 F: doc/guides/sample_app_ug/ip_pipeline.rst
 
-
 Algorithms
 ----------
 
diff --git a/config/common_base b/config/common_base
index e74febe..7680397 100644
--- a/config/common_base
+++ b/config/common_base
@@ -793,6 +793,11 @@ CONFIG_RTE_LIBRTE_VHOST_NUMA=n
 CONFIG_RTE_LIBRTE_VHOST_DEBUG=n
 
 #
+# Compile port representor library
+#
+CONFIG_RTE_LIBRTE_REPRESENTOR=y
+
+#
 # Compile vhost PMD
 # To compile, CONFIG_RTE_LIBRTE_VHOST should be enabled.
 #
diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index 3492702..9954c5a 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -42,6 +42,7 @@ The public API headers are grouped by topics:
   [rte_flow]           (@ref rte_flow.h),
   [rte_tm]             (@ref rte_tm.h),
   [rte_mtr]            (@ref rte_mtr.h),
+  [Port Representor]   (@ref rte_port_representor.h),
   [cryptodev]          (@ref rte_cryptodev.h),
   [security]           (@ref rte_security.h),
   [eventdev]           (@ref rte_eventdev.h),
diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf
index b2cbe94..4d1b89f 100644
--- a/doc/api/doxy-api.conf
+++ b/doc/api/doxy-api.conf
@@ -70,6 +70,7 @@ INPUT                   = doc/api/doxy-api-index.md \
                           lib/librte_port \
                           lib/librte_power \
                           lib/librte_reorder \
+                          lib/librte_representor \
                           lib/librte_ring \
                           lib/librte_sched \
                           lib/librte_security \
diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst
index c4beb34..380d5c9 100644
--- a/doc/guides/prog_guide/index.rst
+++ b/doc/guides/prog_guide/index.rst
@@ -71,6 +71,7 @@ Programmer's Guide
     power_man
     packet_classif_access_ctrl
     packet_framework
+    representor_lib
     vhost_lib
     metrics_lib
     port_hotplug_framework
diff --git a/doc/guides/prog_guide/representor_lib.rst b/doc/guides/prog_guide/representor_lib.rst
new file mode 100644
index 0000000..dbf6acb
--- /dev/null
+++ b/doc/guides/prog_guide/representor_lib.rst
@@ -0,0 +1,62 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2017 Intel Corporation.
+
+.. _Representor_Library:
+
+Port Representor Library
+========================
+
+Port representors provide a logical presentation in DPDK of VF (virtual
+function) ports for the purposes of control and monitoring. Each port
+representor device represents a single VF and is associated with it's
+parent physical function (PF) PMD which provides the back-end hooks for
+the representor device ops and defines the control domain to which that
+port belongs. This allows to use existing DPDK APIs to monitor and control
+the port without the need to create and maintain VF specific APIs.
+
+Initialising the library
+------------------------
+
+Before port representors can be used, the port broker infrastructure
+has to be enabled within the EAL. This is done by passing the
+``--enable-representor`` EAL command-line parameter:
+
+.. code-block:: c
+
+    ./testpmd --enable-representor -- -i
+
+
+Registering a Port Representor
+------------------------------
+Before use, port representors have to be individually *registered*
+with the broker associated with the physical function. This requires
+the physical function's address in *DomBDF* (domain bus device function)
+format and the zero-based index of the virtual function. For instance, to
+create port representors for the first two virtual functions associated
+with physical function with device address ``0000:81:00.0`` on the PCI
+bus, the following code could be used:
+
+.. code-block:: c
+
+    uint16_t port_id_0;
+    uint16_t port_id_1;
+
+    rte_representor_port_register("pci_0000:81:00.0", 0, &port_id_0);
+    rte_representor_port_register("pci_0000:81:00.0", 1, &port_id_1);
+
+Upon successful registration, these functions return zero, and the
+passed-in pointer to integer is set to the ethdev port ID for the
+created port representor.
+
+Unregistering a Port Representor
+--------------------------------
+
+Unregistering a port representor that is no longer required uses the
+same parameters used to register it, namely the physical function address
+and virtual function index. There is no need for port representors to be
+unregistered in any particular order:
+
+.. code-block:: c
+
+    rte_representor_port_unregister("pci_0000:81:00.0", 0);
+    rte_representor_port_unregister("pci_0000:81:00.0", 1);
diff --git a/doc/guides/rel_notes/release_18_02.rst b/doc/guides/rel_notes/release_18_02.rst
index 24b67bb..5854d51 100644
--- a/doc/guides/rel_notes/release_18_02.rst
+++ b/doc/guides/rel_notes/release_18_02.rst
@@ -41,6 +41,15 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **Added Port Representor functionality.**
+
+  Port Representors provide a logical presentation in DPDK of VF (virtual
+  function) ports for the purposes of control and monitoring. Each port
+  representor device represents a single VF and is associated with it's
+  parent PF (physical function) PMD which provides the back-end hooks for
+  the representor device ops and defines the control domain to which that
+  port belongs.
+
 
 API Changes
 -----------
@@ -157,6 +166,7 @@ The libraries prepended with a plus sign were incremented in this version.
      librte_port.so.3
      librte_power.so.1
      librte_reorder.so.1
+   + librte_representor.so.1
      librte_ring.so.1
      librte_sched.so.1
      librte_security.so.1
diff --git a/lib/Makefile b/lib/Makefile
index 4202702..42932a9 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -73,6 +73,9 @@ DEPDIRS-librte_distributor := librte_eal librte_mbuf librte_ether
 DIRS-$(CONFIG_RTE_LIBRTE_PORT) += librte_port
 DEPDIRS-librte_port := librte_eal librte_mempool librte_mbuf librte_ether
 DEPDIRS-librte_port += librte_ip_frag librte_sched
+DIRS-$(CONFIG_RTE_LIBRTE_REPRESENTOR) += librte_representor
+DEPDIRS-librte_representor += librte_ether
+
 ifeq ($(CONFIG_RTE_LIBRTE_KNI),y)
 DEPDIRS-librte_port += librte_kni
 endif
diff --git a/lib/librte_eal/common/eal_common_log.c b/lib/librte_eal/common/eal_common_log.c
index 08b31e2..5549f50 100644
--- a/lib/librte_eal/common/eal_common_log.c
+++ b/lib/librte_eal/common/eal_common_log.c
@@ -210,6 +210,7 @@ static const struct logtype logtype_strings[] = {
 	{RTE_LOGTYPE_CRYPTODEV,  "cryptodev"},
 	{RTE_LOGTYPE_EFD,        "efd"},
 	{RTE_LOGTYPE_EVENTDEV,   "eventdev"},
+	{RTE_LOGTYPE_PORTREP,    "representor"},
 	{RTE_LOGTYPE_USER1,      "user1"},
 	{RTE_LOGTYPE_USER2,      "user2"},
 	{RTE_LOGTYPE_USER3,      "user3"},
diff --git a/lib/librte_eal/common/include/rte_log.h b/lib/librte_eal/common/include/rte_log.h
index 83faddf..bf79006 100644
--- a/lib/librte_eal/common/include/rte_log.h
+++ b/lib/librte_eal/common/include/rte_log.h
@@ -59,6 +59,7 @@ extern struct rte_logs rte_logs;
 #define RTE_LOGTYPE_EFD       18 /**< Log related to EFD. */
 #define RTE_LOGTYPE_EVENTDEV  19 /**< Log related to eventdev. */
 #define RTE_LOGTYPE_GSO       20 /**< Log related to GSO. */
+#define RTE_LOGTYPE_PORTREP   21 /**< Log related to port representors. */
 
 /* these log types can be used in an application */
 #define RTE_LOGTYPE_USER1     24 /**< User-defined log type 1. */
diff --git a/lib/librte_representor/Makefile b/lib/librte_representor/Makefile
new file mode 100644
index 0000000..9ccd5c9
--- /dev/null
+++ b/lib/librte_representor/Makefile
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2017 Intel Corporation.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+#
+# library name
+#
+LIB = librte_representor.a
+
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+EXPORT_MAP := rte_port_representor_version.map
+
+LIBABIVER := 1
+
+SRCS-$(CONFIG_RTE_LIBRTE_REPRESENTOR) += rte_port_representor.c
+
+#
+# Export include files
+#
+SYMLINK-$(CONFIG_RTE_LIBRTE_REPRESENTOR)-include += rte_port_representor.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_REPRESENTOR)-include += rte_port_representor_driver.h
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_representor/rte_port_representor.c b/lib/librte_representor/rte_port_representor.c
new file mode 100644
index 0000000..3b10701
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor.c
@@ -0,0 +1,345 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#include <rte_pci.h>
+#include <rte_port_representor.h>
+#include <rte_port_representor_driver.h>
+
+#include <rte_kvargs.h>
+
+TAILQ_HEAD(rte_broker_list, rte_representor_broker);
+
+struct rte_broker_list broker_list =
+	TAILQ_HEAD_INITIALIZER(broker_list);
+
+struct port_rep_parameters {
+	uint64_t vport_mask;
+	struct {
+		char bus[RTE_DEV_NAME_MAX_LEN];
+		char device[RTE_DEV_NAME_MAX_LEN];
+	} parent;
+};
+
+/* Macros to check for valid id */
+#define RTE_VERIFY_OR_ERR_RET(val, retval) do { \
+	if (!(val)) { \
+		RTE_LOG(DEBUG, PORTREP, "verify failed, ret= %d", (retval)); \
+		return retval; \
+	} \
+} while (0)
+
+#define RTE_VERIFY_OR_RET(val) do { \
+	if (!(val)) { \
+		RTE_LOG(DEBUG, PORTREP, "verify failed"); \
+		return; \
+	} \
+} while (0)
+
+int
+rte_representor_broker_init(struct rte_representor_broker *broker)
+{
+	RTE_VERIFY_OR_ERR_RET(broker, -ENODEV);
+
+	RTE_VERIFY_OR_ERR_RET(broker->bus && strlen(broker->bus), -ENXIO);
+	RTE_VERIFY_OR_ERR_RET(broker->device && strlen(broker->device), -ENXIO);
+
+	RTE_VERIFY_OR_ERR_RET(broker->nb_virtual_ports > 0, -EINVAL);
+
+	broker->vports = rte_malloc("rte_representor_ports",
+		sizeof(*(broker->vports)) * broker->nb_virtual_ports, 0);
+	if (broker->vports == NULL)
+		return -ENOMEM;
+
+	RTE_VERIFY_OR_ERR_RET(broker->ops, -EINVAL);
+
+	TAILQ_INSERT_TAIL(&broker_list, broker, next);
+	RTE_LOG(INFO, PORTREP, "Registered [%s_%s] broker.\n", broker->bus,
+		broker->device);
+
+	return 0;
+}
+
+int
+rte_representor_broker_uninit(struct rte_representor_broker *broker)
+{
+	int i;
+	struct rte_eth_dev *ethdev;
+	char name[RTE_DEV_NAME_MAX_LEN];
+
+	for (i = 0; i < broker->nb_virtual_ports; i++) {
+		if (broker->vports[i].state == RTE_REPRESENTOR_PORT_VALID) {
+			ethdev = broker->vports[i].ethdev;
+			rte_eth_dev_detach(ethdev->data->port_id,
+				name);
+		}
+	}
+
+	rte_free(broker->vports);
+
+	TAILQ_REMOVE(&broker_list, broker, next);
+	RTE_LOG(DEBUG, PORTREP, "Unregistered [%s_%s] broker.\n", broker->bus,
+		broker->device);
+
+	return 0;
+}
+
+struct rte_representor_broker *
+rte_representor_broker_find(const char *bus, const char *device)
+{
+	struct rte_representor_broker *broker = NULL;
+
+	TAILQ_FOREACH(broker, &broker_list, next) {
+		if ((strcmp(broker->bus, bus) == 0) &&
+				(strcmp(broker->device, device) == 0))
+			break;
+	}
+
+	return broker;
+}
+
+#define RTE_REPRESENTOR_PORT_VALID_ETHDEV_OR_RET_ERR(ethdev, retval) do { \
+	if (!strstr(ethdev->data->name, RTE_PORT_REPRESENTOR_DEVICE_NAME)) { \
+		RTE_LOG(DEBUG, PORTREP,	"port %d is not a representor port", \
+			ethdev->data->port_id); \
+		return retval; \
+	} \
+} while (0)
+
+#define RTE_REPRESENTOR_PORT_VALID_OR_RET_ERR(vport, retval) do { \
+	if (!(vport->state == RTE_REPRESENTOR_PORT_VALID)) { \
+		RTE_LOG(DEBUG, PORTREP, "Vport is not a representor port"); \
+		return retval; \
+	} \
+} while (0)
+
+static struct rte_representor_port *
+representor_port_find(struct rte_representor_broker *broker,
+		uint16_t vport_id)
+{
+	if (vport_id >= broker->nb_virtual_ports)
+		return NULL;
+
+	return &broker->vports[vport_id];
+}
+
+int
+rte_representor_port_register(char *pf_addr_str,
+		uint32_t vport_id, uint16_t *port_id)
+{
+	struct rte_eth_dev *rep_ethdev;
+	struct rte_representor_port *rep_port;
+	struct rte_representor_broker *broker;
+	char str_device_name[RTE_ETH_NAME_MAX_LEN];
+	int len_name;
+	int retval;
+	char *addr_delim;
+	int addr_len;
+	char addr_bus[RTE_ETH_NAME_MAX_LEN];
+	char addr_dev[RTE_ETH_NAME_MAX_LEN];
+	struct rte_pci_addr pci_addr;
+
+	RTE_LOG(INFO, PORTREP, "Creating representor for VF %i from %s\n",
+		vport_id, pf_addr_str);
+
+	/* the parent param has to be provided with type_name formatted */
+	memset(addr_bus, 0, sizeof(addr_bus));
+	memset(addr_dev, 0, sizeof(addr_dev));
+	addr_delim = strchr(pf_addr_str, '_');
+	if (addr_delim) {
+		addr_len = addr_delim - pf_addr_str;
+		strncpy(addr_bus, pf_addr_str, addr_len);
+		strncpy(addr_dev, addr_delim + 1,
+			strlen(pf_addr_str) - addr_len);
+		retval = eal_parse_pci_DomBDF(addr_dev, &pci_addr);
+		if (retval) {
+			RTE_LOG(ERR, PORTREP, "pf addr string '%s' "
+				"has invalid address format\n",
+				pf_addr_str);
+			return retval;
+		}
+	} else {
+		RTE_LOG(ERR, PORTREP, "pf addr string '%s' "
+			"has invalid address format\n",
+			pf_addr_str);
+		return -EINVAL;
+	}
+
+	/* Fetch broker for PF */
+	broker = rte_representor_broker_find(addr_bus, addr_dev);
+	if (broker == NULL) {
+		RTE_LOG(ERR, PORTREP, "Unable to find broker for %s on bus %s\n",
+			addr_dev, addr_bus);
+		return -EINVAL;
+	}
+	RTE_FUNC_PTR_OR_ERR_RET(broker->ops->port_init, -ENOTSUP);
+
+	/* Fetch representor slot for VF */
+	rep_port = representor_port_find(broker, vport_id);
+	if (rep_port == NULL) {
+		RTE_LOG(ERR, PORTREP, "vport_id %i exceeds number of VF ports %i",
+			vport_id, broker->nb_virtual_ports);
+		return -EINVAL;
+	}
+	if (rep_port->state == RTE_REPRESENTOR_PORT_VALID)
+		return -EEXIST;
+
+	/* Create representor ethdev */
+	len_name = snprintf(str_device_name, RTE_ETH_NAME_MAX_LEN, "%s.%s.%i",
+		RTE_PORT_REPRESENTOR_DEVICE_NAME, addr_dev, vport_id);
+	if (len_name == RTE_ETH_NAME_MAX_LEN) {
+		RTE_LOG(ERR, PORTREP, "Port Representor name"
+			" exceeds RTE_ETH_NAME_MAX_LEN\n");
+		return -EIO;
+	}
+	RTE_LOG(INFO, PORTREP, "Port Representor ethdev name: %s\n",
+		str_device_name);
+	rep_ethdev = rte_eth_dev_allocate(str_device_name);
+	if (rep_ethdev == NULL) {
+		RTE_LOG(ERR, PORTREP, "Unable to allocate Port Representor"
+			" ethdev\n");
+		return -ENOMEM;
+	}
+	rep_ethdev->data->mac_addrs = rte_malloc("representor_port_mac_addrs",
+			sizeof(struct ether_addr), 0);
+	if (rep_ethdev->data->mac_addrs == NULL) {
+		RTE_LOG(ERR, PORTREP, "Unable to allocate Port Representor"
+			" mac_addrs\n");
+		rte_eth_dev_release_port(rep_ethdev);
+		return -ENOMEM;
+	}
+
+	/* Allocate an rte_device & rte_driver for the ethdev. */
+	rep_port->rep_rtedev = rte_zmalloc_socket("rte_device",
+		sizeof(struct rte_device), 0, rte_socket_id());
+	if (rep_port->rep_rtedev == NULL) {
+		RTE_LOG(ERR, PORTREP, "Unable to allocate Port Representor"
+			" devive\n");
+		rte_free(rep_ethdev->data->mac_addrs);
+		rte_eth_dev_release_port(rep_ethdev);
+		return -ENOMEM;
+	}
+	rep_port->rep_rtedrv = rte_zmalloc_socket("rte_driver",
+		sizeof(struct rte_driver), 0, rte_socket_id());
+	if (rep_port->rep_rtedrv == NULL) {
+		RTE_LOG(ERR, PORTREP, "Unable to allocate Port Representor"
+			" driver\n");
+		rte_free(rep_port->rep_rtedev);
+		rte_free(rep_ethdev->data->mac_addrs);
+		rte_eth_dev_release_port(rep_ethdev);
+		return -ENOMEM;
+	}
+	rep_port->rep_rtedrv->name = RTE_PORT_REPRESENTOR_DEVICE_NAME;
+	rep_port->rep_rtedev->driver = rep_port->rep_rtedrv;
+	rep_ethdev->device = rep_port->rep_rtedev;
+
+	/* Register representor with broker */
+	RTE_REPRESENTOR_PORT_VALID_ETHDEV_OR_RET_ERR(rep_ethdev, -EINVAL);
+	rep_port->vport_id = vport_id;
+	rep_port->ethdev = rep_ethdev;
+	rep_port->broker = broker;
+	rep_port->state = RTE_REPRESENTOR_PORT_VALID;
+	rep_ethdev->data->dev_private = rep_port;
+
+	retval = broker->ops->port_init(broker, rep_ethdev);
+	if (retval) {
+		rte_free(rep_port->rep_rtedev);
+		rte_free(rep_port->rep_rtedrv);
+		rte_free(rep_ethdev->data->mac_addrs);
+		rte_eth_dev_release_port(rep_ethdev);
+		return retval;
+	}
+	RTE_LOG(INFO, PORTREP, "Registered port representor "
+			"<broker=%s_%s, vport_id=%u>\n",
+			broker->bus, broker->device, vport_id);
+
+	*port_id = rep_ethdev->data->port_id;
+
+	return 0;
+}
+
+int
+rte_representor_port_unregister(char *pf_addr_str, uint32_t vport_id)
+{
+	struct rte_representor_port *rep_port;
+	struct rte_representor_broker *broker;
+	char *addr_delim;
+	char addr_bus[RTE_ETH_NAME_MAX_LEN];
+	char addr_dev[RTE_ETH_NAME_MAX_LEN];
+	struct rte_pci_addr pci_addr;
+	int addr_len;
+	int retval;
+
+	RTE_LOG(INFO, PORTREP, "Deleting representor for VF %i from %s\n",
+		vport_id, pf_addr_str);
+
+	/* The parent param has to be provided with type_name formatted */
+	memset(addr_bus, 0, sizeof(addr_bus));
+	memset(addr_dev, 0, sizeof(addr_dev));
+	addr_delim = strchr(pf_addr_str, '_');
+	if (addr_delim) {
+		addr_len = addr_delim - pf_addr_str;
+		strncpy(addr_bus, pf_addr_str, addr_len);
+		strncpy(addr_dev, addr_delim + 1,
+			strlen(pf_addr_str) - addr_len);
+		retval = eal_parse_pci_DomBDF(addr_dev, &pci_addr);
+		if (retval) {
+			RTE_LOG(ERR, PORTREP, "pf addr string '%s' "
+				"has invalid address format\n",
+				pf_addr_str);
+			return retval;
+		}
+	} else {
+		RTE_LOG(ERR, PORTREP, "Parent address '%s' has invalid format\n",
+			pf_addr_str);
+		return -EINVAL;
+	}
+
+	/* Fetch broker for PF */
+	broker = rte_representor_broker_find(addr_bus, addr_dev);
+	if (broker == NULL) {
+		RTE_LOG(ERR, PORTREP, "Unable to find broker for %s on bus %s\n",
+			addr_dev, addr_bus);
+		return -EINVAL;
+	}
+	RTE_FUNC_PTR_OR_ERR_RET(broker->ops->port_uninit, -ENOTSUP);
+
+	/* Fetch representor slot for VF */
+	rep_port = representor_port_find(broker, vport_id);
+	if (rep_port == NULL) {
+		RTE_LOG(ERR, PORTREP, "Unable to fetch Port Representor handle\n");
+		return -EINVAL;
+	}
+	if (rep_port->state != RTE_REPRESENTOR_PORT_VALID) {
+		RTE_LOG(ERR, PORTREP, "Representor vport %i is not active\n",
+			vport_id);
+		return -EINVAL;
+	}
+
+	/* Free up representor */
+	rep_port->broker->ops->port_uninit(rep_port->broker, rep_port->ethdev);
+	rep_port->state = RTE_REPRESENTOR_PORT_INVALID;
+	rte_free(rep_port->ethdev->data->mac_addrs);
+	rte_eth_dev_release_port(rep_port->ethdev);
+
+	/* Cannot pass the pointers ethdev->device & ethdev->device->driver to
+	 * rte_free() so have to store the allocated pointers in separate
+	 * non-const variables.
+	 */
+	rte_free(rep_port->rep_rtedrv);
+	rte_free(rep_port->rep_rtedev);
+
+	return 0;
+}
+
+int
+rte_representor_port_get_vport_id(struct rte_eth_dev *ethdev)
+{
+	struct rte_representor_port *port;
+
+	RTE_REPRESENTOR_PORT_VALID_ETHDEV_OR_RET_ERR(ethdev, -EINVAL);
+
+	port = (struct rte_representor_port *)ethdev->data->dev_private;
+
+	return port->vport_id;
+}
diff --git a/lib/librte_representor/rte_port_representor.h b/lib/librte_representor/rte_port_representor.h
new file mode 100644
index 0000000..6582cb9
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#ifndef _RTE_PORT_REPRESENTOR_H_
+#define _RTE_PORT_REPRESENTOR_H_
+
+/**
+ * @file
+ * RTE Port Representor API
+ *
+ * Driver APIs for management and support of port representor
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_ethdev.h>
+#include <rte_malloc.h>
+#include <rte_flow.h>
+
+struct rte_representor_port;
+struct rte_representor_broker;
+
+/**
+ * Registers a representor ethdev with the broker, allocating a port representor
+ * context and calling the representor port initialization function.
+ *
+ * @param	pf_addr_str	Address of parent PF in Bus_DomBDF format
+ * @param	vport_id	Virtual port ID to register ethdev against
+ * @param	port_id         Pointer to integer that receives port_id
+ *
+ * @return
+ * - 0 on successful registration and initialization of representor port
+ * - errno on failure
+ */
+int
+rte_representor_port_register(char *pf_addr_str,
+		uint32_t vport_id, uint16_t *port_id);
+
+/**
+ * Unregister a representor port, called during destruction of representor
+ * ethdev context. Freeing any allocated memory for the representor port.
+ *
+ * @param	pf_addr_str	Address of parent PF in Bus_DomBDF format
+ * @param	vport_id	Virtual port ID to deregister
+ *
+ * @return
+ * - 0 on success
+ * - errno on failure
+ */
+int
+rte_representor_port_unregister(char *pf_addr_str, uint32_t vport_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_PORT_REPRESENTOR_H_ */
diff --git a/lib/librte_representor/rte_port_representor_driver.h b/lib/librte_representor/rte_port_representor_driver.h
new file mode 100644
index 0000000..57e527d
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_driver.h
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2017 Intel Corporation.
+ */
+
+#ifndef _RTE_PORT_REPRESENTOR_DRIVER_H_
+#define _RTE_PORT_REPRESENTOR_DRIVER_H_
+
+#include <rte_port_representor.h>
+
+/**
+ * @file
+ * RTE Port Representor Driver API
+ *
+ * Driver APIs for management and support of port representor
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RTE_PORT_REPRESENTOR_DEVICE_NAME "net_representor"
+
+enum rte_representor_port_state {
+	RTE_REPRESENTOR_PORT_INVALID,
+	/**< No ethdev instantiated for virtual port */
+	RTE_REPRESENTOR_PORT_VALID
+	/**< ethdev active for virtual port */
+};
+
+struct rte_representor_port;
+
+struct rte_representor_broker {
+	TAILQ_ENTRY(rte_representor_broker) next;
+	/**< Next broker object in linked list */
+
+	const char *bus;	/**< bus name */
+	const char *device;	/**< device name */
+
+	uint16_t nb_virtual_ports;
+	/**< number of virtual ports supported by device */
+
+	struct rte_representor_port *vports;
+	/**< Representor port contexts */
+
+	struct rte_representor_broker_port_ops *ops;
+	/**< broker port operations functions */
+	void *private_data;
+	/**< broker private data */
+};
+
+/** Port Representor */
+struct rte_representor_port {
+	uint16_t vport_id;
+	/**< Virtual Port Identifier */
+	struct rte_eth_dev *ethdev;
+	/**< ethdev handle of representor port */
+	struct rte_representor_broker *broker;
+	/**< Broker handle to allow reverse lookup */
+	enum rte_representor_port_state state;
+	/**< port state */
+	void *priv_data;
+	/**<  port private data */
+	/**< Representor ethdev device */
+	struct rte_device *rep_rtedev;
+	/**< Representor ethdev driver */
+	struct rte_driver *rep_rtedrv;
+};
+
+typedef int (*representor_broker_port_init_t)(
+		struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev);
+
+typedef int (*representor_broker_port_uninit_t)(
+		struct rte_representor_broker *broker,
+		struct rte_eth_dev *ethdev);
+
+struct rte_representor_broker_port_ops {
+	representor_broker_port_init_t port_init;
+	representor_broker_port_init_t port_uninit;
+};
+
+/**
+ * Initialize port representor broker
+ *
+ * This function is called by the PMDs initialization routine if the port
+ * representor is enabled by EAL command line argument.
+ *
+ * Verifies broker context parameters and initialises required resources.
+ *
+ * @param	broker		port representor broker context
+ *
+ * @return
+ * - 0 on success
+ * - errno on failure
+ */
+int
+rte_representor_broker_init(struct rte_representor_broker *broker);
+
+/**
+ * Un-initialize the port representor broker freeing all associated resources.
+ *
+ * @param	broker		port representor broker
+ *
+ * @return
+ * - 0 on success
+ * - errno on failure
+ */
+int
+rte_representor_broker_uninit(struct rte_representor_broker *broker);
+
+/**
+ * Fetch a port representor broker
+ *
+ * @param	bus		Bus parent PF is on
+ * @param	device		Address of PF
+ *
+ * @return
+ * - Pointer to port representor broker on success
+ * - NULL on failure
+ */
+struct rte_representor_broker *
+rte_representor_broker_find(const char *bus, const char *device);
+
+/**
+ * Get the  virtual port ID of given representor port ethdev context
+ *
+ * @param	ethdev		Port representor ethdev handle
+ *
+ * @return
+ * - Virtual port ID
+ * - errno on failure
+ */
+int
+rte_representor_port_get_vport_id(struct rte_eth_dev *ethdev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_PORT_REPRESENTOR_DRIVER_H_ */
diff --git a/lib/librte_representor/rte_port_representor_version.map b/lib/librte_representor/rte_port_representor_version.map
new file mode 100644
index 0000000..b26600c
--- /dev/null
+++ b/lib/librte_representor/rte_port_representor_version.map
@@ -0,0 +1,8 @@
+DPDK_18.02 {
+	global:
+
+	rte_representor_port_register;
+	rte_representor_port_unregister;
+
+	local: *;
+};
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index 6a6a745..67266bf 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -104,6 +104,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL)            += -lrte_eal
 _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE)        += -lrte_cmdline
 _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER)        += -lrte_reorder
 _LDLIBS-$(CONFIG_RTE_LIBRTE_SCHED)          += -lrte_sched
+_LDLIBS-$(CONFIG_RTE_LIBRTE_REPRESENTOR)    += -lrte_representor
 
 ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y)
 _LDLIBS-$(CONFIG_RTE_LIBRTE_KNI)            += -lrte_kni
