This patch adds a network driver for sandbox using tap.

Signed-off-by: Matthias Weisser <weiss...@arcor.de>
---
This patch adds support for networking to sandbox architecture using tap. A tap
device "tap0" has to be created e.g. using openvpn

$ openvpn --mktun --dev tap0

u-boot should then be able to detect the network device on startup. To test the
network related commands I used the following commands to create an ethernet
bridge to my local network connection

$ brctl addbr br0
$ ifconfig eth0 0.0.0.0 promisc
$ ifconfig tap0 0.0.0.0
$ brctl addif br0 eth0
$ brctl addif br0 tap0
$ ifconfig br0 up
$ pump -i br0

After this setup I was able to successfully execute the ping and tftp command.

To get timeouts working this patch also needs my timer patch for sandbox
http://patchwork.ozlabs.org/patch/128279/

Note:
As sandbox is build using the native compiler, which is in my case x86_64, ulong
is 64 bit in size. This caused non-working IP stuff as IPaddr_t is typedefed to
ulong. I changed this typedef to u32 which helped but is quite invasive to all
network related stuff. This is the main reason why this patched is marked as
RFC.

 arch/sandbox/cpu/cpu.c    |    9 +++
 arch/sandbox/cpu/os.c     |   39 ++++++++++++++
 arch/sandbox/lib/board.c  |    5 ++
 drivers/net/Makefile      |    1 +
 drivers/net/tap.c         |  125 +++++++++++++++++++++++++++++++++++++++++++++
 include/configs/sandbox.h |    9 ++--
 include/net.h             |    2 +-
 include/os.h              |    8 +++
 8 files changed, 193 insertions(+), 5 deletions(-)
 create mode 100644 drivers/net/tap.c

diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index d7684d3..53e58bd 100644
--- a/arch/sandbox/cpu/cpu.c
+++ b/arch/sandbox/cpu/cpu.c
@@ -60,3 +60,12 @@ void *map_physmem(phys_addr_t paddr, unsigned long len, 
unsigned long flags)
 void flush_dcache_range(unsigned long start, unsigned long stop)
 {
 }
+
+int cpu_eth_init(bd_t *bis)
+{
+#if defined(CONFIG_DRIVER_TAP)
+       return tap_initialize(bis);
+#else
+       return 0;
+#endif
+}
diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c
index 6d55b5c..9985b33 100644
--- a/arch/sandbox/cpu/os.c
+++ b/arch/sandbox/cpu/os.c
@@ -21,14 +21,20 @@
 
 #include <fcntl.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <termios.h>
 #include <unistd.h>
+#include <string.h>
 #include <time.h>
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
 #include <linux/types.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
 
 #include <os.h>
 
@@ -121,3 +127,36 @@ u64 os_get_nsec(void)
        return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000;
 #endif
 }
+
+int os_tap_open(char *dev)
+{
+       struct ifreq ifr;
+       int fd, err;
+
+       fd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
+       if (fd < 0) {
+               perror("could not open /dev/net/tun");
+               return -1;
+       }
+
+       memset(&ifr, 0, sizeof(ifr));
+
+       /* Flags: IFF_TUN   - TUN device (no Ethernet headers)
+        *        IFF_TAP   - TAP device
+        *
+        *        IFF_NO_PI - Do not provide packet information
+        */
+       ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+       if (*dev)
+               strncpy(ifr.ifr_name, dev, IFNAMSIZ);
+
+       err = ioctl(fd, TUNSETIFF, (void *)&ifr);
+       if (err < 0) {
+               perror("could not get tap device");
+               close(fd);
+               return err;
+       }
+
+       strcpy(dev, ifr.ifr_name);
+       return fd;
+}
diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c
index b7997e9..d02f6ca 100644
--- a/arch/sandbox/lib/board.c
+++ b/arch/sandbox/lib/board.c
@@ -257,6 +257,11 @@ void board_init_r(gd_t *id, ulong dest_addr)
        board_late_init();
 #endif
 
+#if defined(CONFIG_CMD_NET)
+       puts("Net:   ");
+       eth_initialize(gd->bd);
+#endif
+
 #ifdef CONFIG_POST
        post_run(NULL, POST_RAM | post_bootmode_get(0));
 #endif
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index d3df82e..1686405 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -69,6 +69,7 @@ COBJS-$(CONFIG_SH_ETHER) += sh_eth.o
 COBJS-$(CONFIG_SMC91111) += smc91111.o
 COBJS-$(CONFIG_SMC911X) += smc911x.o
 COBJS-$(CONFIG_DRIVER_TI_EMAC) += davinci_emac.o
+COBJS-$(CONFIG_DRIVER_TAP) += tap.o
 COBJS-$(CONFIG_TSEC_ENET) += tsec.o fsl_mdio.o
 COBJS-$(CONFIG_FMAN_ENET) += fsl_mdio.o
 COBJS-$(CONFIG_TSI108_ETH) += tsi108_eth.o
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
new file mode 100644
index 0000000..e6689bd
--- /dev/null
+++ b/drivers/net/tap.c
@@ -0,0 +1,125 @@
+/*
+ * tap.c - A tap ethernet driver for u-boot
+ *
+ * Copyright (c) 2011 Matthias Weißer <weiss...@arcor.de>
+ *
+ * Based on fec_mxc.c and tap.c from barebox:
+ * Copyright (c) 2007 Sascha Hauer <s.ha...@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <net.h>
+#include <os.h>
+
+struct tap_priv {
+       int fd; /* file descriptor */
+       char dev[128];
+};
+
+static int tap_init(struct eth_device *dev, bd_t* bd)
+{
+       /* Nothing to be done here */
+       return 0;
+}
+
+static void tap_halt(struct eth_device *dev)
+{
+       /* Nothing to be done here */
+}
+
+static int tap_send(struct eth_device *dev, void *packet, int length)
+{
+       struct tap_priv *priv = dev->priv;
+
+       os_write(priv->fd, (void *)packet, length);
+       return 0;
+}
+
+static int tap_recv(struct eth_device *dev)
+{
+       struct tap_priv *priv = dev->priv;
+       uchar buf[PKTSIZE];
+       int length;
+
+       length = os_read(priv->fd, buf, PKTSIZE);
+
+       if (length > 0)
+               NetReceive(buf, length);
+
+       return 0;
+}
+
+static int tap_set_hwaddr(struct eth_device *dev)
+{
+       /* Nothing to be done here */
+       return 0;
+}
+
+int tap_initialize(bd_t *bd)
+{
+       struct eth_device *edev;
+       struct tap_priv *tap;
+       int res = 0;
+
+       /* create and fill edev struct */
+       edev = (struct eth_device *)malloc(sizeof(struct eth_device));
+       if (!edev) {
+               puts("tap: not enough malloc memory for eth_device\n");
+               res = -ENOMEM;
+               goto err1;
+       }
+
+       tap = (struct tap_priv *)malloc(sizeof(struct tap_priv));
+       if (!tap) {
+               puts("tap: not enough malloc memory for tap_priv\n");
+               res = -ENOMEM;
+               goto err2;
+       }
+
+       memset(edev, 0, sizeof(*edev));
+       memset(tap, 0, sizeof(*tap));
+
+       strncpy(tap->dev, "tap0", sizeof(tap->dev));
+       tap->fd = os_tap_open(tap->dev);
+       if (tap->fd < 0) {
+               res = -EIO;
+               goto err3;
+       }
+
+       edev->priv = tap;
+       edev->init = tap_init;
+       edev->send = tap_send;
+       edev->recv = tap_recv;
+       edev->halt = tap_halt;
+       edev->write_hwaddr = tap_set_hwaddr;
+
+       sprintf(edev->name, "TAP");
+       eth_register(edev);
+
+       return res;
+
+err3:
+       free(tap);
+err2:
+       free(edev);
+err1:
+       return res;
+}
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 10565e6..1ca27e5 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -69,12 +69,13 @@
 
 #define CONFIG_SYS_NO_FLASH
 
+/* Network support */
+#define CONFIG_DRIVER_TAP
+
 /* include default commands */
 #include <config_cmd_default.h>
-
-/* We don't have networking support yet */
-#undef CONFIG_CMD_NET
-#undef CONFIG_CMD_NFS
+#define CONFIG_CMD_DHCP
+#define CONFIG_CMD_PING
 
 #define CONFIG_BOOTARGS ""
 
diff --git a/include/net.h b/include/net.h
index ad9afbf..9d878e5 100644
--- a/include/net.h
+++ b/include/net.h
@@ -33,7 +33,7 @@
 
 #define PKTALIGN       32
 
-typedef ulong          IPaddr_t;
+typedef u32            IPaddr_t;
 
 
 /**
diff --git a/include/os.h b/include/os.h
index f3af4f0..ba76419 100644
--- a/include/os.h
+++ b/include/os.h
@@ -98,3 +98,11 @@ void os_usleep(unsigned long usec);
  * \return A monotonic increasing time scaled in nano seconds
  */
 u64 os_get_nsec(void);
+
+/**
+ * Opens a TAP device for network emulation
+ *
+ * \param dev Device name to be opened
+ * \return File descriptor of the device
+ */
+int os_tap_open(char *dev);
-- 
1.7.5.4

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to