diff --git a/MAINTAINERS b/MAINTAINERS
index f071138..6c87f33 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -89,6 +89,7 @@ F: lib/librte_eal/common/include/generic/
 F: doc/guides/prog_guide/env_abstraction_layer.rst
 F: app/test/test_alarm.c
 F: app/test/test_atomic.c
+F: app/test/test_bus.c
 F: app/test/test_byteorder.c
 F: app/test/test_common.c
 F: app/test/test_cpuflags.c
diff --git a/app/test/Makefile b/app/test/Makefile
index 9de301f..48235ad 100644
--- a/app/test/Makefile
+++ b/app/test/Makefile
@@ -94,7 +94,7 @@ SRCS-y += test_cycles.c
 SRCS-y += test_spinlock.c
 SRCS-y += test_memory.c
 SRCS-y += test_memzone.c
-
+SRCS-y += test_bus.c
 SRCS-y += test_ring.c
 SRCS-y += test_ring_perf.c
 SRCS-y += test_pmd_perf.c
diff --git a/app/test/autotest_data.py b/app/test/autotest_data.py
index 0cd598b..ab08a64 100644
--- a/app/test/autotest_data.py
+++ b/app/test/autotest_data.py
@@ -204,6 +204,12 @@ def per_sockets(num):
         "Tests":
         [
             {
+                "Name":    "Bus autotest",
+                "Command": "bus_autotest",
+                "Func":    default_autotest,
+                "Report":  None,
+            },
+            {
                 "Name":    "PCI autotest",
                 "Command": "pci_autotest",
                 "Func":    default_autotest,
diff --git a/app/test/test.h b/app/test/test.h
index 82831f4..9be88a7 100644
--- a/app/test/test.h
+++ b/app/test/test.h
@@ -233,6 +233,7 @@ extern const char *prgname;
 
 int commands_init(void);
 
+int test_bus(void);
 int test_pci(void);
 int test_pci_run;
 
diff --git a/app/test/test_bus.c b/app/test/test_bus.c
new file mode 100644
index 0000000..e2a58fa
--- /dev/null
+++ b/app/test/test_bus.c
@@ -0,0 +1,355 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2016 NXP.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of NXP nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+#include <rte_bus.h>
+#include <rte_pci.h>
+#include <rte_devargs.h>
+
+#include "test.h"
+#include "resource.h"
+
+/* Visualizing following bus-device-driver model for test
+ *
+ *  ===.===========.===========.=========,= busA
+ *     |           |           .         |
+ *   devA1       devA2         .         '____CPU_
+ *    `-----------`-------> driverA      |
+ *                                       '
+ *  ===.===========.===========.=========|= busB
+ *     |           |           .
+ *   devB1       devB2         .
+ *    `-----------`-------> driverB
+ *
+ */
+
+#define MAX_DEVICES_ON_BUS	10
+#define MAX_DRIVERS_ON_BUS	10
+
+struct dummy_driver;
+struct dummy_device;
+struct dummy_bus;
+
+TAILQ_HEAD(dummy_device_list, dummy_device); /**< List of dummy devices */
+TAILQ_HEAD(dummy_driver_list, dummy_driver); /**< List of dummy drivers */
+
+/* A structure representing a ethernet/crypto device, embedding
+ * the rte_device.
+ */
+struct dummy_device {
+	TAILQ_ENTRY(dummy_device) next;
+	const char *name;
+	struct rte_device dev;
+};
+
+/* A structure representing a PMD driver of a particular type,
+ * for e.g. PCI.
+ */
+struct dummy_driver {
+	TAILQ_ENTRY(dummy_driver) next;
+	const char *name;
+	struct rte_driver drv;
+};
+
+struct dummy_bus {
+	TAILQ_ENTRY(dummy_bus) next;
+	const char *name;
+	struct rte_bus bus;
+	struct dummy_driver_list driver_list;
+	struct dummy_device_list device_list;
+};
+
+/* Structure representing a Bus with devices attached to it, and drivers
+ * for those devices
+ */
+struct dummy_bus_map {
+	const char *name;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddrivers[MAX_DRIVERS_ON_BUS];
+	struct dummy_device *ddevices[MAX_DEVICES_ON_BUS];
+};
+
+struct rte_bus_list orig_bus_list =
+	TAILQ_HEAD_INITIALIZER(orig_bus_list);
+
+struct dummy_bus busA = {
+	.name = "busA_impl", /* busA */
+	.bus = {
+		.name = "busA",
+	},
+};
+
+struct dummy_bus busB = {
+	.name = "busB_impl", /* busB */
+	.bus = {
+		.name = "busB",
+	},
+};
+
+struct dummy_driver driverA = {
+	.name = "driverA_impl",
+	.drv = {
+		.name = "driverA",
+	},
+};
+
+struct dummy_device devA1 = {
+	.name = "devA1",
+	.dev = {
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devA2 = {
+	.name = "devA2",
+	.dev = {
+		.driver = NULL,
+	}
+};
+
+struct dummy_driver driverB = {
+	.name = "driverB_impl",
+	.drv = {
+		.name = "driverB",
+	},
+};
+
+struct dummy_device devB1 = {
+	.name = "devB1",
+	.dev = {
+		.driver = NULL,
+	}
+};
+
+struct dummy_device devB2 = {
+	.name = "devB2",
+	.dev = {
+		.driver = NULL,
+	}
+};
+
+struct dummy_bus_map bus_map[] = {
+	{
+		.name = "busA",
+		.dbus = &busA,
+		.ddrivers = {&driverA, NULL},
+		.ddevices = {&devA1, &devA2, NULL},
+	},
+	{
+		.name = "busB",
+		.dbus = &busB,
+		.ddrivers = {&driverB, NULL},
+		.ddevices = {&devB1, &devB2, NULL},
+	},
+	{NULL, NULL, {NULL,}, {NULL,}, },
+};
+
+/* @internal
+ * Dump the device tree
+ */
+static void
+dump_device_tree(void)
+{
+	int i;
+	struct dummy_bus_map *db;
+	struct rte_bus *bus;
+	struct dummy_bus *dbus;
+	struct dummy_driver *ddriver;
+	struct dummy_device *ddevice;
+
+	printf("------>8-------\n");
+	printf("Device Tree:\n");
+	for (i = 0; bus_map[i].name; i++) {
+		db = &bus_map[i];
+
+		bus = &db->dbus->bus;
+		if (!bus)
+			return;
+
+		dbus = container_of(bus, struct dummy_bus, bus);
+		printf(" Bus: %s (Implementation name: %s)\n",
+		       bus->name, dbus->name);
+
+		printf("  Drivers on bus:\n");
+		TAILQ_FOREACH(ddriver, &dbus->driver_list, next) {
+			printf("    %s\n", ddriver->name);
+		}
+
+		printf("  Devices on bus:\n");
+		TAILQ_FOREACH(ddevice, &dbus->device_list, next) {
+			printf("    Addr: %p\n", ddevice);
+			if (ddevice->dev.driver)
+				printf("    Driver = %s\n",
+				       ddevice->dev.driver->name);
+			else
+				printf("    Driver = None\n");
+		}
+	}
+	printf("------>8-------\n");
+}
+
+static int
+test_bus_setup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Preserve the original bus list before executing test */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&orig_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_cleanup(void)
+{
+	struct rte_bus *bus_p = NULL;
+
+	/* Cleanup rte_bus_list before restoring entries */
+	while (!TAILQ_EMPTY(&rte_bus_list)) {
+		bus_p = TAILQ_FIRST(&rte_bus_list);
+		rte_bus_unregister(bus_p);
+		TAILQ_REMOVE(&rte_bus_list, bus_p, next);
+	}
+
+	bus_p = NULL;
+	/* Restore original entries */
+	while (!TAILQ_EMPTY(&orig_bus_list)) {
+		bus_p = TAILQ_FIRST(&orig_bus_list);
+		TAILQ_REMOVE(&orig_bus_list, bus_p, next);
+		TAILQ_INSERT_TAIL(&rte_bus_list, bus_p, next);
+	}
+
+	return 0;
+}
+
+static int
+test_bus_registration(void)
+{
+	int i;
+	int ret;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		rte_bus_register(bus);
+		printf("Registered Bus %s\n", bus_map[i].name);
+	}
+
+	/* Verify that all buses have been successfully registered */
+	i = 0;
+	TAILQ_FOREACH(bus, &rte_bus_list, next) {
+		/* Or, if the name of the bus is NULL */
+		if (!bus->name) {
+			/* Incorrect entry in list */
+			printf("Incorrect bus registered.\n");
+			return -1;
+		}
+
+		/* Or, if the bus name doesn't match that of bus_map */
+		ret = strcmp(bus->name, bus_map[i].name);
+		if (ret) {
+			/* Bus name doesn't match */
+			printf("Unable to correctly register bus (%s).\n",
+			       bus_map[i].name);
+			return -1;
+		}
+		i++;
+	}
+
+	/* Current value of bus_map[i] should be the NULL entry */
+	if (bus_map[i].name != NULL) {
+		printf("Not all buses were registered. For e.g. (%s)\n",
+		       bus_map[i].name);
+		return -1;
+	}
+
+	printf("Buses registered are:\n");
+	rte_bus_dump(stdout);
+
+	return 0;
+}
+
+static int
+test_bus_unregistration(void)
+{
+	int i;
+	struct rte_bus *bus = NULL;
+
+	for (i = 0; bus_map[i].name != NULL; i++) {
+		bus = &(bus_map[i].dbus->bus);
+		if (bus) {
+			printf("Unregistering bus: '%s'\n", bus->name);
+			rte_bus_unregister(bus);
+		}
+	}
+
+	if (!TAILQ_EMPTY(&rte_bus_list)) {
+		/* Unable to unregister all dummy buses */
+		printf("Unable to unregister all buses\n");
+		return -1;
+	}
+
+	printf("All buses have been unregistered.\n");
+	dump_device_tree();
+	return 0;
+}
+
+int
+test_bus(void)
+{
+	/* Make necessary arrangements before starting test */
+	if (test_bus_setup())
+		return -1;
+
+	if (test_bus_registration())
+		return -1;
+
+	if (test_bus_unregistration())
+		return -1;
+
+	/* Restore the original environment/settings */
+	if (test_bus_cleanup())
+		return -1;
+
+	return 0;
+}
+
+REGISTER_TEST_COMMAND(bus_autotest, test_bus);
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index 2cf1ac8..a3d9fac 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -178,6 +178,7 @@ DPDK_16.11 {
 DPDK_17.02 {
 	global:
 
+	rte_bus_list;
 	rte_bus_dump;
 	rte_bus_probe;
 	rte_bus_register;
diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h
index 7c36969..19954f4 100644
--- a/lib/librte_eal/common/include/rte_bus.h
+++ b/lib/librte_eal/common/include/rte_bus.h
@@ -56,6 +56,9 @@ extern "C" {
 /** Double linked list of buses */
 TAILQ_HEAD(rte_bus_list, rte_bus);
 
+/* Bus list exposed */
+extern struct rte_bus_list rte_bus_list;
+
 /**
  * Bus specific scan for devices attached on the bus.
  * For each bus object, the scan would be reponsible for finding devices and
diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
index 3c68ff5..69e0e7b 100644
--- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map
@@ -182,6 +182,7 @@ DPDK_16.11 {
 DPDK_17.02 {
 	global:
 
+	rte_bus_list;
 	rte_bus_dump;
 	rte_bus_probe;
 	rte_bus_register;
