aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board-qemu/Makefile3
-rw-r--r--board-qemu/slof/Makefile8
-rw-r--r--board-qemu/slof/vio-veth.fs35
-rw-r--r--clients/net-snk/kernel/modules.c1
-rw-r--r--include/netdriver.h24
-rw-r--r--lib/Makefile3
-rw-r--r--lib/libveth/Makefile50
-rw-r--r--lib/libveth/veth.c273
-rw-r--r--lib/libveth/veth.code61
-rw-r--r--lib/libveth/veth.h24
-rw-r--r--lib/libveth/veth.in20
11 files changed, 492 insertions, 10 deletions
diff --git a/board-qemu/Makefile b/board-qemu/Makefile
index 9826557..81d3b33 100644
--- a/board-qemu/Makefile
+++ b/board-qemu/Makefile
@@ -14,7 +14,8 @@ BOARD_TARGETS = tools_build romfs_build clients_build netdrivers stage1 subdirs
SUBDIRS = slof veth virtio-net
-COMMON_LIBS = libc libbootmsg libbases libnvram libelf libhvcall libvirtio libusb
+COMMON_LIBS = libc libbootmsg libbases libnvram libelf libhvcall libvirtio libusb \
+ libveth
all: $(BOARD_TARGETS)
$(MAKE) boot_rom.bin
diff --git a/board-qemu/slof/Makefile b/board-qemu/slof/Makefile
index fc905a6..d5be39c 100644
--- a/board-qemu/slof/Makefile
+++ b/board-qemu/slof/Makefile
@@ -21,14 +21,15 @@ all: Makefile.dep OF.ffs paflof $(SLOFCMNDIR)/xvect.bin
CPPFLAGS = -I$(LIBCMNDIR)/libbootmsg -I$(LIBCMNDIR)/libhvcall \
-I$(LIBCMNDIR)/libvirtio -I$(LIBCMNDIR)/libnvram \
- -I$(LIBCMNDIR)/libusb
+ -I$(LIBCMNDIR)/libusb -I$(LIBCMNDIR)/libveth
SLOF_LIBS = \
$(LIBCMNDIR)/libbootmsg.a \
$(LIBCMNDIR)/libelf.a \
$(LIBCMNDIR)/libhvcall.a \
$(LIBCMNDIR)/libvirtio.a \
$(LIBCMNDIR)/libusb.a \
- $(LIBCMNDIR)/libnvram.a
+ $(LIBCMNDIR)/libnvram.a \
+ $(LIBCMNDIR)/libveth.a
BOARD_SLOF_IN = \
$(LIBCMNDIR)/libhvcall/hvcall.in \
$(LIBCMNDIR)/libvirtio/virtio.in \
@@ -36,7 +37,8 @@ BOARD_SLOF_IN = \
$(LIBCMNDIR)/libbootmsg/bootmsg.in \
$(LIBCMNDIR)/libelf/libelf.in \
$(LIBCMNDIR)/libnvram/libnvram.in \
- $(LIBCMNDIR)/libbases/libbases.in
+ $(LIBCMNDIR)/libbases/libbases.in \
+ $(LIBCMNDIR)/libveth/veth.in
BOARD_SLOF_CODE = $(BOARD_SLOF_IN:%.in=%.code)
include $(SLOFCMNDIR)/Makefile.inc
diff --git a/board-qemu/slof/vio-veth.fs b/board-qemu/slof/vio-veth.fs
index a23ba1c..f6d1684 100644
--- a/board-qemu/slof/vio-veth.fs
+++ b/board-qemu/slof/vio-veth.fs
@@ -15,14 +15,41 @@
" network" device-type
INSTANCE VARIABLE obp-tftp-package
+0 VALUE veth-priv
+0 VALUE open-count
+
: open ( -- okay? )
- my-unit 1 rtas-set-tce-bypass
- my-args s" obp-tftp" $open-package obp-tftp-package ! true
+ open-count 0= IF
+ my-unit 1 rtas-set-tce-bypass
+ my-args s" obp-tftp" $open-package obp-tftp-package !
+ s" local-mac-address" get-node get-property not
+ s" reg" get-node get-property not 3 pick and IF
+ >r nip r>
+ libveth-open dup not IF ." libveth-open failed" EXIT THEN
+ drop TO veth-priv
+ THEN
+ THEN
+ open-count 1 + to open-count
+ true
;
: close ( -- )
- s" close" obp-tftp-package @ $call-method
- my-unit 0 rtas-set-tce-bypass
+ open-count 0> IF
+ open-count 1 - dup to open-count
+ 0= IF
+ s" close" obp-tftp-package @ $call-method
+ veth-priv libveth-close
+ my-unit 0 rtas-set-tce-bypass
+ THEN
+ THEN
+;
+
+: read ( buf len -- actual )
+ veth-priv libveth-read
+;
+
+: write ( buf len -- actual )
+ veth-priv libveth-write
;
: load ( addr -- len )
diff --git a/clients/net-snk/kernel/modules.c b/clients/net-snk/kernel/modules.c
index e7f8cbb..4484bc3 100644
--- a/clients/net-snk/kernel/modules.c
+++ b/clients/net-snk/kernel/modules.c
@@ -38,7 +38,6 @@ typedef struct {
static const mod_descriptor_t modules[] = {
{ "net_e1000", MOD_TYPE_NETWORK },
{ "net_bcm", MOD_TYPE_NETWORK },
- { "net_veth", MOD_TYPE_NETWORK },
{ "net_virtio", MOD_TYPE_NETWORK },
{ NULL, 0 }
};
diff --git a/include/netdriver.h b/include/netdriver.h
new file mode 100644
index 0000000..d81134e
--- /dev/null
+++ b/include/netdriver.h
@@ -0,0 +1,24 @@
+/******************************************************************************
+ * Copyright (c) 2013 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ ******************************************************************************/
+
+#ifndef _NETDRIVER_H
+#define _NETDRIVER_H
+
+#include <stdint.h>
+
+typedef struct net_driver {
+ uint8_t mac_addr[6];
+ uint32_t reg;
+ int running;
+} net_driver_t;
+
+#endif
diff --git a/lib/Makefile b/lib/Makefile
index fb1562f..b96f8e6 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -10,7 +10,8 @@
# * IBM Corporation - initial implementation
# ****************************************************************************/
-SUBDIRS = libc libipmi libbootmsg libbases libnvram libelf libhvcall libvirtio libusb
+SUBDIRS = libc libipmi libbootmsg libbases libnvram libelf libhvcall libvirtio \
+ libusb libveth
all: subdirs
diff --git a/lib/libveth/Makefile b/lib/libveth/Makefile
new file mode 100644
index 0000000..4556110
--- /dev/null
+++ b/lib/libveth/Makefile
@@ -0,0 +1,50 @@
+# *****************************************************************************
+# * Copyright (c) 2004, 2008 IBM Corporation
+# * All rights reserved.
+# * This program and the accompanying materials
+# * are made available under the terms of the BSD License
+# * which accompanies this distribution, and is available at
+# * http://www.opensource.org/licenses/bsd-license.php
+# *
+# * Contributors:
+# * IBM Corporation - initial implementation
+# ****************************************************************************/
+
+TOPCMNDIR ?= ../..
+
+CPPFLAGS = -I../libc/include $(CPUARCHDEF) -I$(INCLBRDDIR) \
+ -I$(INCLCMNDIR) -I$(INCLCMNDIR)/$(CPUARCH)
+CPPFLAGS += -I../libhvcall
+
+LDFLAGS = -nostdlib
+
+TARGET = ../libveth.a
+
+
+all: $(TARGET)
+
+SRCS = veth.c
+
+OBJS = $(SRCS:%.c=%.o)
+
+$(TARGET): $(OBJS)
+ $(AR) -rc $@ $(OBJS)
+ $(RANLIB) $@
+
+clean:
+ $(RM) $(TARGET) $(OBJS)
+
+distclean: clean
+ $(RM) Makefile.dep
+
+
+# Rules for creating the dependency file:
+depend:
+ $(RM) Makefile.dep
+ $(MAKE) Makefile.dep
+
+Makefile.dep: Makefile
+ $(CC) -M $(CPPFLAGS) $(CFLAGS) $(SRCS) $(SRCSS) > Makefile.dep
+
+# Include dependency file if available:
+-include Makefile.dep
diff --git a/lib/libveth/veth.c b/lib/libveth/veth.c
new file mode 100644
index 0000000..928a0f7
--- /dev/null
+++ b/lib/libveth/veth.c
@@ -0,0 +1,273 @@
+/******************************************************************************
+ * Copyright (c) 2011, 2013 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <helpers.h>
+#include "veth.h"
+#include "libhvcall.h"
+
+#undef VETH_DEBUG
+//#define VETH_DEBUG
+#ifdef VETH_DEBUG
+#define dprintf(_x ...) printf(_x)
+#else
+#define dprintf(_x ...)
+#endif
+
+/* *** WARNING: We pass our addresses as-is as DMA addresses,
+ * we -do- rely on the forth code to have enabled TCE bypass
+ * on our device !
+ */
+#define vaddr_to_dma(vaddr) ((uint64_t)vaddr)
+
+struct ibmveth_buf_desc_fields {
+ uint32_t flags_len;
+#define IBMVETH_BUF_VALID 0x80000000
+#define IBMVETH_BUF_TOGGLE 0x40000000
+#define IBMVETH_BUF_NO_CSUM 0x02000000
+#define IBMVETH_BUF_CSUM_GOOD 0x01000000
+#define IBMVETH_BUF_LEN_MASK 0x00FFFFFF
+ uint32_t address;
+};
+
+union ibmveth_buf_desc {
+ uint64_t desc;
+ struct ibmveth_buf_desc_fields fields;
+};
+
+struct ibmveth_rx_q_entry {
+ uint32_t flags_off;
+#define IBMVETH_RXQ_TOGGLE 0x80000000
+#define IBMVETH_RXQ_TOGGLE_SHIFT 31
+#define IBMVETH_RXQ_VALID 0x40000000
+#define IBMVETH_RXQ_NO_CSUM 0x02000000
+#define IBMVETH_RXQ_CSUM_GOOD 0x01000000
+#define IBMVETH_RXQ_OFF_MASK 0x0000FFFF
+
+ uint32_t length;
+ uint64_t correlator;
+};
+
+static void *buffer_list;
+static void *filter_list;
+static uint64_t *rx_bufs;
+static uint64_t *rx_bufs_aligned;
+static uint32_t cur_rx_toggle;
+static uint32_t cur_rx_index;
+
+#define RX_QUEUE_SIZE 16
+#define RX_BUF_SIZE 2048
+#define RX_BUF_MULT (RX_BUF_SIZE >> 3)
+
+static struct ibmveth_rx_q_entry *rx_queue;
+
+static inline uint64_t *veth_get_rx_buf(unsigned int i)
+{
+ return &rx_bufs_aligned[i * RX_BUF_MULT];
+}
+
+static int veth_init(net_driver_t *driver)
+{
+ char *mac_addr;
+ union ibmveth_buf_desc rxq_desc;
+ unsigned long rx_queue_len = sizeof(struct ibmveth_rx_q_entry) *
+ RX_QUEUE_SIZE;
+ unsigned int i;
+ long rc;
+
+ if (!driver)
+ return -1;
+
+ dprintf("veth_init(%02x:%02x:%02x:%02x:%02x:%02x)\n",
+ mac_addr[0], mac_addr[1], mac_addr[2],
+ mac_addr[3], mac_addr[4], mac_addr[5]);
+
+ if (driver->running != 0)
+ return 0;
+
+ mac_addr = (char *)driver->mac_addr;
+ cur_rx_toggle = IBMVETH_RXQ_TOGGLE;
+ cur_rx_index = 0;
+ buffer_list = SLOF_alloc_mem_aligned(8192, 4096);
+ filter_list = buffer_list + 4096;
+ rx_queue = SLOF_alloc_mem_aligned(rx_queue_len, 16);
+ rx_bufs = SLOF_alloc_mem(2048 * RX_QUEUE_SIZE + 4);
+ if (!buffer_list || !filter_list || !rx_queue || !rx_bufs) {
+ printf("veth: Failed to allocate memory !\n");
+ goto fail;
+ }
+ rx_bufs_aligned = (uint64_t *)(((uint64_t)rx_bufs | 3) + 1);
+ rxq_desc.fields.address = vaddr_to_dma(rx_queue);
+ rxq_desc.fields.flags_len = IBMVETH_BUF_VALID | rx_queue_len;
+
+ rc = h_register_logical_lan(driver->reg,
+ vaddr_to_dma(buffer_list),
+ rxq_desc.desc,
+ vaddr_to_dma(filter_list),
+ (*(uint64_t *)mac_addr) >> 16);
+ if (rc != H_SUCCESS) {
+ printf("veth: Error %ld registering interface !\n", rc);
+ goto fail;
+ }
+ for (i = 0; i < RX_QUEUE_SIZE; i++) {
+ uint64_t *buf = veth_get_rx_buf(i);
+ union ibmveth_buf_desc desc;
+ *buf = (uint64_t)buf;
+ desc.fields.address = vaddr_to_dma(buf);
+ desc.fields.flags_len = IBMVETH_BUF_VALID | RX_BUF_SIZE;
+ h_add_logical_lan_buffer(driver->reg, desc.desc);
+ }
+
+ driver->running = 1;
+
+ return 0;
+ fail:
+ if (buffer_list)
+ SLOF_free_mem(buffer_list, 8192);
+ if (rx_queue)
+ SLOF_free_mem(rx_queue, rx_queue_len);
+ if (rx_bufs)
+ SLOF_free_mem(rx_bufs, 2048 * RX_QUEUE_SIZE + 4);
+ return -1;
+}
+
+static int veth_term(net_driver_t *driver)
+{
+ dprintf("veth_term()\n");
+
+ if (driver->running == 0)
+ return 0;
+
+ h_free_logical_lan(driver->reg);
+
+ if (buffer_list)
+ SLOF_free_mem(buffer_list, 8192);
+ if (rx_queue)
+ SLOF_free_mem(rx_queue, sizeof(struct ibmveth_rx_q_entry) * RX_QUEUE_SIZE);
+ if (rx_bufs)
+ SLOF_free_mem(rx_bufs, 2048 * RX_QUEUE_SIZE + 4);
+
+ driver->running = 0;
+
+ return 0;
+}
+
+static int veth_receive(char *f_buffer_pc, int f_len_i, net_driver_t *driver)
+{
+ int packet = 0;
+
+ dprintf("veth_receive()\n");
+
+ while(!packet) {
+ struct ibmveth_rx_q_entry *desc = &rx_queue[cur_rx_index];
+ union ibmveth_buf_desc bdesc;
+ void *buf;
+
+ buf = (void *)desc->correlator;
+
+ if ((desc->flags_off & IBMVETH_RXQ_TOGGLE) != cur_rx_toggle)
+ break;
+
+ if (!(desc->flags_off & IBMVETH_RXQ_VALID))
+ goto recycle;
+ if (desc->length > f_len_i) {
+ printf("veth: Dropping too big packet [%d bytes]\n",
+ desc->length);
+ goto recycle;
+ }
+
+ packet = desc->length;
+ memcpy(f_buffer_pc,
+ buf + (desc->flags_off & IBMVETH_RXQ_OFF_MASK), packet);
+ recycle:
+ bdesc.fields.address = vaddr_to_dma(buf);
+ bdesc.fields.flags_len = IBMVETH_BUF_VALID | RX_BUF_SIZE;
+ h_add_logical_lan_buffer(driver->reg, bdesc.desc);
+
+ cur_rx_index = (cur_rx_index + 1) % RX_QUEUE_SIZE;
+ if (cur_rx_index == 0)
+ cur_rx_toggle ^= IBMVETH_RXQ_TOGGLE;
+ }
+
+ return packet;
+}
+
+static int veth_xmit(char *f_buffer_pc, int f_len_i, net_driver_t *driver)
+{
+ union ibmveth_buf_desc tx_desc;
+ long rc;
+
+ dprintf("veth_xmit(packet at %p, %d bytes)\n", f_buffer_pc, f_len_i);
+
+ tx_desc.fields.address = vaddr_to_dma(f_buffer_pc);
+ tx_desc.fields.flags_len = IBMVETH_BUF_VALID | f_len_i;
+
+ rc = hv_send_logical_lan(driver->reg, tx_desc.desc, 0, 0, 0, 0, 0);
+ if (rc != H_SUCCESS) {
+ printf("veth: Error %ld sending packet !\n", rc);
+ return -1;
+ }
+
+ return f_len_i;
+}
+
+net_driver_t *libveth_open(char *mac_addr, int mac_len, char *reg, int reg_len)
+{
+ net_driver_t *driver;
+
+ driver = SLOF_alloc_mem(sizeof(*driver));
+ if (!driver) {
+ printf("Unable to allocate veth driver\n");
+ return NULL;
+ }
+
+ /* veth uses a 8-byte wide property instead of 6-byte wide MACs */
+ if ((mac_len == 8) && (mac_addr[0] == 0) && mac_addr[1] == 0)
+ mac_addr += 2;
+ memcpy(driver->mac_addr, mac_addr, 6);
+ driver->reg = *(uint32_t *)reg;
+ driver->running = 0;
+
+ if (veth_init(driver)) {
+ SLOF_free_mem(driver, sizeof(*driver));
+ return NULL;
+ }
+
+ return driver;
+}
+
+void libveth_close(net_driver_t *driver)
+{
+ if (driver) {
+ veth_term(driver);
+ SLOF_free_mem(driver, sizeof(*driver));
+ }
+}
+
+int libveth_read(char *buf, int len, net_driver_t *driver)
+{
+ if (buf)
+ return veth_receive(buf, len, driver);
+
+ return -1;
+}
+
+int libveth_write(char *buf, int len, net_driver_t *driver)
+{
+ if (buf)
+ return veth_xmit(buf, len, driver);
+
+ return -1;
+}
diff --git a/lib/libveth/veth.code b/lib/libveth/veth.code
new file mode 100644
index 0000000..76d14a9
--- /dev/null
+++ b/lib/libveth/veth.code
@@ -0,0 +1,61 @@
+/******************************************************************************
+ * Copyright (c) 2013 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+/*
+ * libveth Forth wrapper
+ */
+
+#include <veth.h>
+
+// : libveth-open ( mac-addr-str len reg-str len -- false | [ driver true ] )
+PRIM(LIBVETH_X2d_OPEN)
+{
+ int reg_len = TOS.u; POP;
+ char *reg = TOS.a; POP;
+ int len = TOS.u; POP;
+ char *mac_addr = TOS.a;
+
+ net_driver_t *net_driver = libveth_open(mac_addr, len, reg, reg_len);
+ if (net_driver) {
+ TOS.u = (unsigned long)net_driver; PUSH;
+ TOS.n = -1;
+ } else
+ TOS.n = 0;
+}
+MIRP
+
+// : libveth-close ( driver -- )
+PRIM(LIBVETH_X2d_CLOSE)
+{
+ net_driver_t *driver = TOS.a; POP;
+ libveth_close(driver);
+}
+MIRP
+
+
+// : libveth-read ( addr len driver -- actual )
+PRIM(LIBVETH_X2d_READ)
+{
+ net_driver_t *driver = TOS.a; POP;
+ int len = TOS.u; POP;
+ TOS.n = libveth_read(TOS.a, len, driver);
+}
+MIRP
+
+// : libveth-write ( addr len driver -- actual )
+PRIM(LIBVETH_X2d_WRITE)
+{
+ net_driver_t *driver = TOS.a; POP;
+ int len = TOS.u; POP;
+ TOS.n = libveth_write(TOS.a, len, driver);
+}
+MIRP
diff --git a/lib/libveth/veth.h b/lib/libveth/veth.h
new file mode 100644
index 0000000..23af0ea
--- /dev/null
+++ b/lib/libveth/veth.h
@@ -0,0 +1,24 @@
+/******************************************************************************
+ * Copyright (c) 2013 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ ******************************************************************************/
+
+#ifndef _VETH_H
+#define _VETH_H
+
+#include <stdint.h>
+#include <netdriver.h>
+
+extern net_driver_t *libveth_open(char *mac_addr, int mac_len, char *reg, int reg_len);
+extern void libveth_close(net_driver_t *driver);
+extern int libveth_read(char *buf, int len, net_driver_t *driver);
+extern int libveth_write(char *buf, int len, net_driver_t *driver);
+
+#endif
diff --git a/lib/libveth/veth.in b/lib/libveth/veth.in
new file mode 100644
index 0000000..dc684fe
--- /dev/null
+++ b/lib/libveth/veth.in
@@ -0,0 +1,20 @@
+/******************************************************************************
+ * Copyright (c) 2013 IBM Corporation
+ * All rights reserved.
+ * This program and the accompanying materials
+ * are made available under the terms of the BSD License
+ * which accompanies this distribution, and is available at
+ * http://www.opensource.org/licenses/bsd-license.php
+ *
+ * Contributors:
+ * IBM Corporation - initial implementation
+ *****************************************************************************/
+
+/*
+ * libveth bindings for Forth - definitions
+ */
+
+cod(LIBVETH-OPEN)
+cod(LIBVETH-CLOSE)
+cod(LIBVETH-READ)
+cod(LIBVETH-WRITE)