diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index 186b58d..f84b3fc 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -43,4 +43,7 @@ config NETDEVICES
 config DM_ETH
 	default y
 
+config ETH_SANDBOX_RAW
+	default y
+
 endmenu
diff --git a/arch/sandbox/cpu/Makefile b/arch/sandbox/cpu/Makefile
index 7d4410c..1b42fee 100644
--- a/arch/sandbox/cpu/Makefile
+++ b/arch/sandbox/cpu/Makefile
@@ -8,6 +8,7 @@
 #
 
 obj-y	:= cpu.o os.o start.o state.o
+obj-$(CONFIG_ETH_SANDBOX_RAW)	+= eth-raw-os.o
 obj-$(CONFIG_SANDBOX_SDL)	+= sdl.o
 
 # os.c is build in the system environment, so needs standard includes
@@ -20,3 +21,12 @@ $(obj)/os.o: $(src)/os.c FORCE
 	$(call if_changed_dep,cc_os.o)
 $(obj)/sdl.o: $(src)/sdl.c FORCE
 	$(call if_changed_dep,cc_os.o)
+
+# eth-raw-os.c is built in the system env, so needs standard includes
+# CFLAGS_REMOVE_eth-raw-os.o cannot be used to drop header include path
+quiet_cmd_cc_eth-raw-os.o = CC $(quiet_modtag)  $@
+cmd_cc_eth-raw-os.o = $(CC) $(filter-out -nostdinc, \
+	$(patsubst -I%,-idirafter%,$(c_flags))) -c -o $@ $<
+
+$(obj)/eth-raw-os.o: $(src)/eth-raw-os.c FORCE
+	$(call if_changed_dep,cc_eth-raw-os.o)
diff --git a/arch/sandbox/cpu/eth-raw-os.c b/arch/sandbox/cpu/eth-raw-os.c
new file mode 100644
index 0000000..601205a
--- /dev/null
+++ b/arch/sandbox/cpu/eth-raw-os.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <asm/eth-raw-os.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+
+int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+			    struct eth_sandbox_raw_priv *priv)
+{
+	struct sockaddr_ll *device;
+	struct packet_mreq mr;
+	int ret;
+	int flags;
+
+	/* Prepare device struct */
+	priv->device = malloc(sizeof(struct sockaddr_ll));
+	if (priv->device == NULL)
+		return -ENOMEM;
+	device = priv->device;
+	memset(device, 0, sizeof(struct sockaddr_ll));
+	device->sll_ifindex = if_nametoindex(ifname);
+	device->sll_family = AF_PACKET;
+	memcpy(device->sll_addr, ethmac, 6);
+	device->sll_halen = htons(6);
+
+	/* Open socket */
+	priv->sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+	if (priv->sd < 0) {
+		printf("Failed to open socket: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+	/* Bind to the specified interface */
+	ret = setsockopt(priv->sd, SOL_SOCKET, SO_BINDTODEVICE, ifname,
+		   strlen(ifname) + 1);
+	if (ret < 0) {
+		printf("Failed to bind to '%s': %d %s\n", ifname, errno,
+		       strerror(errno));
+		return -errno;
+	}
+
+	/* Make the socket non-blocking */
+	flags = fcntl(priv->sd, F_GETFL, 0);
+	fcntl(priv->sd, F_SETFL, flags | O_NONBLOCK);
+
+	/* Enable promiscuous mode to receive responses meant for us */
+	mr.mr_ifindex = device->sll_ifindex;
+	mr.mr_type = PACKET_MR_PROMISC;
+	ret = setsockopt(priv->sd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
+		   &mr, sizeof(mr));
+	if (ret < 0) {
+		struct ifreq ifr;
+
+		printf("Failed to set promiscuous mode: %d %s\n"
+		       "Falling back to the old \"flags\" way...\n",
+			errno, strerror(errno));
+		strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
+		if (ioctl(priv->sd, SIOCGIFFLAGS, &ifr) < 0) {
+			printf("Failed to read flags: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+		ifr.ifr_flags |= IFF_PROMISC;
+		if (ioctl(priv->sd, SIOCSIFFLAGS, &ifr) < 0) {
+			printf("Failed to write flags: %d %s\n", errno,
+			       strerror(errno));
+			return -errno;
+		}
+	}
+	return 0;
+}
+
+int sandbox_eth_raw_os_send(void *packet, int length,
+			    const struct eth_sandbox_raw_priv *priv)
+{
+	int retval;
+
+	if (!priv->sd || !priv->device)
+		return -EINVAL;
+
+	retval = sendto(priv->sd, packet, length, 0,
+			(struct sockaddr *)priv->device,
+			sizeof(struct sockaddr_ll));
+	if (retval < 0) {
+		printf("Failed to send packet: %d %s\n", errno,
+		       strerror(errno));
+		return -errno;
+	}
+	return retval;
+}
+
+int sandbox_eth_raw_os_recv(void *packet, int *length,
+			    const struct eth_sandbox_raw_priv *priv)
+{
+	int retval;
+	int saddr_size;
+
+	if (!priv->sd || !priv->device)
+		return -EINVAL;
+	saddr_size = sizeof(struct sockaddr);
+	retval = recvfrom(priv->sd, packet, 1536, 0,
+			  (struct sockaddr *)priv->device,
+			  (socklen_t *)&saddr_size);
+	*length = 0;
+	if (retval >= 0) {
+		*length = retval;
+		return 0;
+	}
+	/* The socket is non-blocking, so expect EAGAIN when there is no data */
+	if (errno == EAGAIN)
+		return 0;
+	return -errno;
+}
+
+void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv)
+{
+	free(priv->device);
+	priv->device = NULL;
+	close(priv->sd);
+	priv->sd = -1;
+}
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index c2a3304..8002196 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -186,4 +186,10 @@
 		reg = <0x10002000 0x1000>;
 		fake-host-hwaddr = [00 00 66 44 22 00];
 	};
+
+	eth@80000000 {
+		compatible = "sandbox,eth-raw";
+		reg = <0x80000000 0x1000>;
+		host-raw-interface = "eth0";
+	};
 };
diff --git a/arch/sandbox/include/asm/eth-raw-os.h b/arch/sandbox/include/asm/eth-raw-os.h
new file mode 100644
index 0000000..df60c4f
--- /dev/null
+++ b/arch/sandbox/include/asm/eth-raw-os.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#ifndef __ETH_RAW_OS_H
+#define __ETH_RAW_OS_H
+
+/**
+ * struct eth_sandbox_raw_priv - raw socket session
+ *
+ * sd: socket descriptor - the open socket during a session
+ * device: struct sockaddr_ll - the host interface packets move to/from
+ */
+struct eth_sandbox_raw_priv {
+	int sd;
+	void *device;
+};
+
+int sandbox_eth_raw_os_start(const char *ifname, unsigned char *ethmac,
+			    struct eth_sandbox_raw_priv *priv);
+int sandbox_eth_raw_os_send(void *packet, int length,
+			    const struct eth_sandbox_raw_priv *priv);
+int sandbox_eth_raw_os_recv(void *packet, int *length,
+			    const struct eth_sandbox_raw_priv *priv);
+void sandbox_eth_raw_os_stop(struct eth_sandbox_raw_priv *priv);
+
+#endif /* __ETH_RAW_OS_H */
diff --git a/board/sandbox/README.sandbox b/board/sandbox/README.sandbox
index c1f5f7e..aedf05a 100644
--- a/board/sandbox/README.sandbox
+++ b/board/sandbox/README.sandbox
@@ -190,6 +190,58 @@ Also sandbox uses generic board (CONFIG_SYS_GENERIC_BOARD) and supports
 driver model (CONFIG_DM) and associated commands.
 
 
+Linux RAW Networking Bridge
+---------------------------
+
+The sandbox_eth_raw driver bridges traffic between the bottom of the network
+stack and the RAW sockets API in Linux. This allows much of the u-boot network
+functionality to be tested in sandbox against real network traffic.
+
+For Ethernet network adapters, the bridge utilizes the RAW AF_PACKET API.  This
+is needed to get access to the lowest level of the network stack in Linux. This
+means that all of the Ethernet frame is included. This allows the u-boot network
+stack to be fully used. In other words, nothing about the Linux network stack is
+involved in forming the packets that end up on the wire. To receive the
+responses to packets sent from U-Boot the network interface has to be set to
+promiscuous mode so that the network card won't filter out packets not destined
+for its configured (on Linux) MAC address.
+
+The RAW sockets Ethernet API requires elevated privileges in Linux. You can
+either run as root, or you can add the capability needed like so:
+
+sudo /sbin/setcap "CAP_NET_RAW+ep" u-boot
+
+The default device tree for sandbox includes an entry for eth0 on the sandbox
+host machine whose alias is "eth1". The following are a few examples of network
+operations being tested on the eth0 interface.
+
+sudo u-boot -d u-boot.dtb
+
+DHCP
+....
+
+set autoload no
+set ethact eth1
+dhcp
+
+PING
+....
+
+set autoload no
+set ethact eth1
+dhcp
+ping $gatewayip
+
+TFTP
+....
+
+set autoload no
+set ethact eth1
+dhcp
+set serverip WWW.XXX.YYY.ZZZ
+tftpboot u-boot.bin
+
+
 SPI Emulation
 -------------
 
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index e46e57b..601366f 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -29,4 +29,14 @@ config ETH_SANDBOX
 
 	  This driver is particularly useful in the test/dm/eth.c tests
 
+config ETH_SANDBOX_RAW
+	depends on DM_ETH && SANDBOX
+	default y
+	bool "Sandbox: Bridge to Linux Raw Sockets"
+	help
+	  This driver is a bridge from the bottom of the network stack
+	  in u-boot to the RAW AF_PACKET API in Linux. This allows real
+	  network traffic to be tested from within sandbox. See
+	  board/sandbox/README.sandbox for more details.
+
 endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 15dc431..2659a8a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_PCNET) += pcnet.o
 obj-$(CONFIG_RTL8139) += rtl8139.o
 obj-$(CONFIG_RTL8169) += rtl8169.o
 obj-$(CONFIG_ETH_SANDBOX) += sandbox.o
+obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o
 obj-$(CONFIG_SH_ETHER) += sh_eth.o
 obj-$(CONFIG_SMC91111) += smc91111.o
 obj-$(CONFIG_SMC911X) += smc911x.o
diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c
new file mode 100644
index 0000000..435b874
--- /dev/null
+++ b/drivers/net/sandbox-raw.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015 National Instruments
+ *
+ * (C) Copyright 2015
+ * Joe Hershberger <joe.hershberger@ni.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0
+ */
+
+#include <asm/eth-raw-os.h>
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <net.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+
+static int sb_eth_raw_start(struct udevice *dev)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	const char *interface;
+
+	debug("eth_sandbox_raw: Start\n");
+
+	interface = fdt_getprop(gd->fdt_blob, dev->of_offset,
+					    "host-raw-interface", NULL);
+	if (interface == NULL)
+		return -EINVAL;
+
+	return sandbox_eth_raw_os_start(interface, pdata->enetaddr, priv);
+}
+
+static int sb_eth_raw_send(struct udevice *dev, void *packet, int length)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+
+	debug("eth_sandbox_raw: Send packet %d\n", length);
+
+	return sandbox_eth_raw_os_send(packet, length, priv);
+}
+
+static int sb_eth_raw_recv(struct udevice *dev, uchar **packetp)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+	int retval;
+	int length;
+
+	retval = sandbox_eth_raw_os_recv(net_rx_packets[0], &length, priv);
+
+	if (!retval && length) {
+		debug("eth_sandbox_raw: received packet %d\n",
+		      length);
+		*packetp = net_rx_packets[0];
+		return length;
+	}
+	return retval;
+}
+
+static void sb_eth_raw_stop(struct udevice *dev)
+{
+	struct eth_sandbox_raw_priv *priv = dev_get_priv(dev);
+
+	debug("eth_sandbox_raw: Stop\n");
+
+	sandbox_eth_raw_os_stop(priv);
+}
+
+static const struct eth_ops sb_eth_raw_ops = {
+	.start			= sb_eth_raw_start,
+	.send			= sb_eth_raw_send,
+	.recv			= sb_eth_raw_recv,
+	.stop			= sb_eth_raw_stop,
+};
+
+static int sb_eth_raw_ofdata_to_platdata(struct udevice *dev)
+{
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	pdata->iobase = dev_get_addr(dev);
+	return 0;
+}
+
+static const struct udevice_id sb_eth_raw_ids[] = {
+	{ .compatible = "sandbox,eth-raw" },
+	{ }
+};
+
+U_BOOT_DRIVER(eth_sandbox_raw) = {
+	.name	= "eth_sandbox_raw",
+	.id	= UCLASS_ETH,
+	.of_match = sb_eth_raw_ids,
+	.ofdata_to_platdata = sb_eth_raw_ofdata_to_platdata,
+	.ops	= &sb_eth_raw_ops,
+	.priv_auto_alloc_size = sizeof(struct eth_sandbox_raw_priv),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
