The Arrakis backport to Barrelfish.
authorSimon Peter <simpeter@cs.washington.edu>
Fri, 28 Feb 2014 08:54:25 +0000 (09:54 +0100)
committerGerd Zellweger <mail@gerdzellweger.com>
Fri, 28 Feb 2014 08:54:25 +0000 (09:54 +0100)
Here are the macro changes:
* Made lwIP an optional network stack
  * Moved lwIP headers out of the general include directory
  * Parallel hake
  * CPU-virtualized ("arrakis") applications
  * libarrakis is a new libOS that uses CPU features directly
  * arrakismon is a new monitor for Arrakis apps
  * QEMU Multiboot support instead of GRUB (enables KVM)
  * e10k virtual function driver
  * Software virtual->physical mapping (substitutes IOMMU)
  * To be replaced soon with an Intel IOMMU driver
  * Better GDB and stack tracing support
  * New POSIX support
     * pthreads, inet_*(), usleep(), syslimits.h, sigaction(), mman.h,
     * resource.h, sendmsg(), recvmsg(), mkfifo(), syslog.h, sysexits.h,
     * fcntl(), getegid(), getgid(), pipe(), rlimits
     * epoll support
     * Separate waitset for interrupts
  * Thread TLS key and ID support
  * Moved PCRE headers to include/, where they usually are
  * Intel performance counters support
  * Handle boot-time RAM overflow (for machines with >=64GB RAM)
  * Arranet network stack
  * Fix for build of lib/barrelfish/arch/x86_64/dispatch.c without -O2
  * New comandline options to pci daemon:
     * maxvfs=x, x is number of virtual functions to create for each
     * device supporting it
     * skb_bridge_program=x, x is SKB bridge programming script to use
     * bridge_bios is a script that uses the BIOS pre-set values, like Linux
   * Correctly build machine-optimized newlib parts
   * Library versions of e1000 and e10k drivers
   * Support for virtualization in e10k driver
   * e10k datacenter control plane daemon
   * Modified hellotest to be both a Barrelfish and an Arrakis application

I've decided not to include the lwIP 1.4.1 code, as the port is
not finished and who wants to use lwIP anyway with the Arrakis
network stack and mTCP being released soon. If you want this,
let me know (it's hugely superior to lwIP 1.3.1).

I've made the code backwards-compatible with Barrelfish. The
default should do what Barrelfish does. One can specify
commandline options to the PCI daemon and e10k driver to
configure I/O virtualization and the optional arrakismon allows
loading CPU-virtualized "arrakis" programs.

There are more pending changes, such as support for hardware
rate limiting and weighted round robin packet scheduling, but
I'd like these to go in first, before I push the rest.

268 files changed:
devices/Hakefile
devices/e10k.dev
devices/e10k_vf.dev [new file with mode: 0644]
devices/pci_hdr0.dev
devices/pci_hdr1.dev
devices/pci_sr_iov_cap.dev [new file with mode: 0644]
hake/ArchDefaults.hs
hake/Config.hs.template
hake/Main.hs
hake/RuleDefs.hs
hake/hake.sh
hake/menu.lst.x86_64
hake/symbolic_targets.mk
if/Hakefile
if/arrakis.if [new file with mode: 0644]
if/e10k_vf.if [copied from include/lwip/barrelfish.h with 58% similarity]
include/Hakefile
include/arch/x86/barrelfish_kpi/perfmon.h
include/arch/x86_64/barrelfish/syscall_arch.h
include/arch/x86_64/barrelfish_kpi/eflags_arch.h
include/arpa/inet.h
include/arranet.h [new file with mode: 0644]
include/arranet_debug.h [new file with mode: 0644]
include/arranet_impl.h [new file with mode: 0644]
include/barrelfish/core_state.h
include/barrelfish/debug.h
include/barrelfish/deferred.h
include/barrelfish/domain.h
include/barrelfish/inthandler.h
include/barrelfish/memobj.h
include/barrelfish/spawn_client.h
include/barrelfish/sys_debug.h
include/barrelfish/threads.h
include/barrelfish/waitset_chan.h
include/barrelfish_kpi/sys_debug.h
include/contmng/netbench.h
include/fcntl.h
include/limits.h
include/netdb.h
include/netinet/in.h
include/netinet6/in6.h [new file with mode: 0644]
include/pcre.h [moved from lib/pcre/pcre.h with 100% similarity]
include/pcreposix.h [moved from include/pcre/pcreposix.h with 100% similarity]
include/pthread.h [new file with mode: 0644]
include/signal.h
include/spawndomain/spawndomain.h
include/sys/_iovec.h
include/sys/_pthreadtypes.h [new file with mode: 0644]
include/sys/_sockaddr_storage.h [new file with mode: 0644]
include/sys/_types.h
include/sys/epoll.h [new file with mode: 0644]
include/sys/mman.h [new file with mode: 0644]
include/sys/resource.h [new file with mode: 0644]
include/sys/signal.h [new file with mode: 0644]
include/sys/socket.h
include/sys/stat.h
include/sys/syslog.h [new file with mode: 0644]
include/sys/types.h
include/sysexits.h [new file with mode: 0644]
include/syslog.h [new file with mode: 0644]
include/unistd.h
include/vfs/fdtab.h
kernel/arch/x86/perfmon.c
kernel/arch/x86/perfmon_intel.c
kernel/arch/x86_64/irq.c
kernel/arch/x86_64/startup_arch.c
kernel/arch/x86_64/syscall.c
kernel/arch/x86_64/vmkit.c
kernel/dispatch.c
kernel/include/arch/x86/perfmon_intel.h
kernel/include/arch/x86_64/vmkit.h
lib/arranet/Hakefile [new file with mode: 0644]
lib/arranet/arranet.c [new file with mode: 0644]
lib/arranet/inet_chksum.c [new file with mode: 0644]
lib/arranet/inet_chksum.h [copied from include/ipv4/lwip/inet_chksum.h with 50% similarity]
lib/arranet/ip_addr.c [new file with mode: 0644]
lib/barrelfish/Hakefile
lib/barrelfish/arch/x86_64/dispatch.c
lib/barrelfish/arch/x86_64/ldt.c
lib/barrelfish/arch/x86_64/sys_debug.c
lib/barrelfish/debug.c
lib/barrelfish/deferred.c
lib/barrelfish/dispatch.c
lib/barrelfish/domain.c
lib/barrelfish/include/threads_priv.h
lib/barrelfish/include/waitset_chan_priv.h
lib/barrelfish/init.c
lib/barrelfish/inthandler.c
lib/barrelfish/spawn_client.c
lib/barrelfish/threads.c
lib/barrelfish/vspace/memobj_anon.c
lib/barrelfish/waitset.c
lib/lwip/Hakefile
lib/lwip/src/api/sockets.c
lib/lwip/src/include/arch/sys_arch.h [moved from include/arch/sys_arch.h with 100% similarity]
lib/lwip/src/include/ipv4/lwip/autoip.h [moved from include/ipv4/lwip/autoip.h with 100% similarity]
lib/lwip/src/include/ipv4/lwip/icmp.h [moved from include/ipv4/lwip/icmp.h with 100% similarity]
lib/lwip/src/include/ipv4/lwip/igmp.h [moved from include/ipv4/lwip/igmp.h with 100% similarity]
lib/lwip/src/include/ipv4/lwip/inet.h [moved from include/ipv4/lwip/inet.h with 100% similarity]
lib/lwip/src/include/ipv4/lwip/inet_chksum.h [moved from include/ipv4/lwip/inet_chksum.h with 100% similarity]
lib/lwip/src/include/ipv4/lwip/ip.h [moved from include/ipv4/lwip/ip.h with 100% similarity]
lib/lwip/src/include/ipv4/lwip/ip_addr.h [moved from include/ipv4/lwip/ip_addr.h with 91% similarity]
lib/lwip/src/include/ipv4/lwip/ip_frag.h [moved from include/ipv4/lwip/ip_frag.h with 100% similarity]
lib/lwip/src/include/ipv6/lwip/icmp.h [moved from include/ipv6/lwip/icmp.h with 100% similarity]
lib/lwip/src/include/ipv6/lwip/inet.h [moved from include/ipv6/lwip/inet.h with 100% similarity]
lib/lwip/src/include/ipv6/lwip/ip.h [moved from include/ipv6/lwip/ip.h with 100% similarity]
lib/lwip/src/include/ipv6/lwip/ip_addr.h [moved from include/ipv6/lwip/ip_addr.h with 100% similarity]
lib/lwip/src/include/lwip/api.h [moved from include/lwip/api.h with 100% similarity]
lib/lwip/src/include/lwip/api_msg.h [moved from include/lwip/api_msg.h with 100% similarity]
lib/lwip/src/include/lwip/arch.h [moved from include/lwip/arch.h with 100% similarity]
lib/lwip/src/include/lwip/barrelfish.h [copied from include/lwip/barrelfish.h with 100% similarity]
lib/lwip/src/include/lwip/debug.h [moved from include/lwip/debug.h with 100% similarity]
lib/lwip/src/include/lwip/def.h [moved from include/lwip/def.h with 100% similarity]
lib/lwip/src/include/lwip/dhcp.h [moved from include/lwip/dhcp.h with 100% similarity]
lib/lwip/src/include/lwip/dns.h [moved from include/lwip/dns.h with 100% similarity]
lib/lwip/src/include/lwip/err.h [moved from include/lwip/err.h with 100% similarity]
lib/lwip/src/include/lwip/init.h [moved from include/lwip/init.h with 100% similarity]
lib/lwip/src/include/lwip/mem.h [moved from include/lwip/mem.h with 100% similarity]
lib/lwip/src/include/lwip/memp.h [moved from include/lwip/memp.h with 100% similarity]
lib/lwip/src/include/lwip/memp_std.h [moved from include/lwip/memp_std.h with 100% similarity]
lib/lwip/src/include/lwip/netbuf.h [moved from include/lwip/netbuf.h with 100% similarity]
lib/lwip/src/include/lwip/netdb.h [moved from include/lwip/netdb.h with 100% similarity]
lib/lwip/src/include/lwip/netif.h [moved from include/lwip/netif.h with 100% similarity]
lib/lwip/src/include/lwip/netifapi.h [moved from include/lwip/netifapi.h with 100% similarity]
lib/lwip/src/include/lwip/opt.h [moved from include/lwip/opt.h with 100% similarity]
lib/lwip/src/include/lwip/pbuf.h [moved from include/lwip/pbuf.h with 100% similarity]
lib/lwip/src/include/lwip/raw.h [moved from include/lwip/raw.h with 100% similarity]
lib/lwip/src/include/lwip/sio.h [moved from include/lwip/sio.h with 100% similarity]
lib/lwip/src/include/lwip/snmp.h [moved from include/lwip/snmp.h with 100% similarity]
lib/lwip/src/include/lwip/snmp_asn1.h [moved from include/lwip/snmp_asn1.h with 100% similarity]
lib/lwip/src/include/lwip/snmp_msg.h [moved from include/lwip/snmp_msg.h with 100% similarity]
lib/lwip/src/include/lwip/snmp_structs.h [moved from include/lwip/snmp_structs.h with 100% similarity]
lib/lwip/src/include/lwip/sock_chan_support.h [moved from include/lwip/sock_chan_support.h with 96% similarity]
lib/lwip/src/include/lwip/sock_serialise.h [moved from include/lwip/sock_serialise.h with 100% similarity]
lib/lwip/src/include/lwip/sockets.h [moved from include/lwip/sockets.h with 96% similarity]
lib/lwip/src/include/lwip/stats.h [moved from include/lwip/stats.h with 100% similarity]
lib/lwip/src/include/lwip/sys.h [moved from include/lwip/sys.h with 100% similarity]
lib/lwip/src/include/lwip/tcp.h [moved from include/lwip/tcp.h with 100% similarity]
lib/lwip/src/include/lwip/tcpip.h [moved from include/lwip/tcpip.h with 100% similarity]
lib/lwip/src/include/lwip/udp.h [moved from include/lwip/udp.h with 100% similarity]
lib/lwip/src/include/lwipopts.h [moved from include/lwipopts.h with 100% similarity]
lib/lwip/src/include/netif/bfeth.h [moved from include/netif/bfeth.h with 100% similarity]
lib/lwip/src/include/netif/e1000.h [new file with mode: 0644]
lib/lwip/src/include/netif/etharp.h [moved from include/netif/etharp.h with 100% similarity]
lib/lwip/src/include/netif/loopif.h [moved from include/netif/loopif.h with 100% similarity]
lib/lwip/src/include/netif/slipif.h [moved from include/netif/slipif.h with 100% similarity]
lib/newlib/newlib/libc/Hakefile
lib/newlib/newlib/libc/machine/Hakefile [new file with mode: 0644]
lib/newlib/newlib/libc/sys/barrelfish/syscalls.c
lib/oldc/src/fileno.c
lib/posixcompat/Hakefile
lib/posixcompat/alarm.c
lib/posixcompat/close.c
lib/posixcompat/epoll.c [new file with mode: 0644]
lib/posixcompat/fcntl.c
lib/posixcompat/getegid.c [deleted file]
lib/posixcompat/geteuid.c
lib/posixcompat/gettimeofday.c
lib/posixcompat/inet_ntop.c [new file with mode: 0644]
lib/posixcompat/inet_pton.c [new file with mode: 0644]
lib/posixcompat/mkfifo.c [new file with mode: 0644]
lib/posixcompat/pipe.c
lib/posixcompat/pthreads.c [new file with mode: 0644]
lib/posixcompat/read.c
lib/posixcompat/readv.c
lib/posixcompat/select.c
lib/posixcompat/setrlimit.c [new file with mode: 0644]
lib/posixcompat/signal.c
lib/posixcompat/sleep.c [new file with mode: 0644]
lib/posixcompat/sockets.c
lib/posixcompat/unixsock.h
lib/posixcompat/wait.c
lib/posixcompat/write.c
lib/skb/skb_functions.c
lib/spawndomain/arch/x86/spawn_arch.c
lib/spawndomain/spawn.c
lib/vfs/Hakefile
lib/vfs/vfs_fd.c
tools/debug.gdb
tools/debug.sh
tools/elver/elver.c
tools/harness/machines/uw.py [new file with mode: 0644]
tools/harness/machines/uw_machinedata.py [new file with mode: 0644]
tools/harness/siteconfig/__init__.py
tools/harness/siteconfig/uw.py [new file with mode: 0644]
usr/acpi/acpi_service.c
usr/arrakismon/Hakefile [new file with mode: 0644]
usr/arrakismon/apic.c [new file with mode: 0644]
usr/arrakismon/apic.h [new file with mode: 0644]
usr/arrakismon/console.c [new file with mode: 0644]
usr/arrakismon/console.h [new file with mode: 0644]
usr/arrakismon/guest.c [new file with mode: 0644]
usr/arrakismon/guest.h [new file with mode: 0644]
usr/arrakismon/hdd.c [new file with mode: 0644]
usr/arrakismon/hdd.h [new file with mode: 0644]
usr/arrakismon/keyboard.c [new file with mode: 0644]
usr/arrakismon/keyboard.h [new file with mode: 0644]
usr/arrakismon/lpc.c [new file with mode: 0644]
usr/arrakismon/lpc.h [new file with mode: 0644]
usr/arrakismon/pc16550d.c [new file with mode: 0644]
usr/arrakismon/pc16550d.h [new file with mode: 0644]
usr/arrakismon/pci.c [new file with mode: 0644]
usr/arrakismon/pci.h [new file with mode: 0644]
usr/arrakismon/pci_devices.h [copied from include/lwip/barrelfish.h with 60% similarity]
usr/arrakismon/pci_host.c [new file with mode: 0644]
usr/arrakismon/pci_host.h [moved from include/lwip/barrelfish.h with 60% similarity]
usr/arrakismon/pci_hostbridge.c [new file with mode: 0644]
usr/arrakismon/ps.c [new file with mode: 0644]
usr/arrakismon/ps.h [new file with mode: 0644]
usr/arrakismon/realmode.c [new file with mode: 0644]
usr/arrakismon/realmode.h [new file with mode: 0644]
usr/arrakismon/svm.h [new file with mode: 0644]
usr/arrakismon/vmkitmon.c [new file with mode: 0644]
usr/arrakismon/vmkitmon.h [new file with mode: 0644]
usr/arrakismon/x86.h [new file with mode: 0644]
usr/bench/ahci/Hakefile
usr/bench/net_latency/elb/Hakefile
usr/bench/udp_echo/Hakefile [new file with mode: 0644]
usr/bench/udp_echo/Makefile [new file with mode: 0644]
usr/bench/udp_echo/run_multiloop.sh [new file with mode: 0644]
usr/bench/udp_echo/udp_echo.c [new file with mode: 0644]
usr/bench/udp_echo/udp_openloop.c [new file with mode: 0644]
usr/drivers/e1000/Hakefile
usr/drivers/e1000/e1000n.c
usr/drivers/e1000/e1000n_debug.c [deleted file]
usr/drivers/e10k/Hakefile
usr/drivers/e10k/e10k.h
usr/drivers/e10k/e10k_cdriver.c
usr/drivers/e10k/e10k_qdriver.c
usr/drivers/e10k/e10k_queue.h
usr/drivers/e10k/e10k_vf.c [new file with mode: 0644]
usr/drivers/e10k/sleep.h
usr/fish/Hakefile
usr/kaluga/Hakefile
usr/net-test/Hakefile
usr/openssh/config.h
usr/pci/Hakefile
usr/pci/pci.c
usr/pci/pci.h
usr/pci/pcie.c
usr/pci/pcimain.c
usr/ramfsd/main.c
usr/skb/Hakefile
usr/skb/eclipse_kernel/src/config.h
usr/skb/icparc_solver/eregex.c
usr/skb/programs/bridge_bios.pl [new file with mode: 0644]
usr/skb/programs/bridge_fake_bigfish.pl [new file with mode: 0644]
usr/slideshow/Hakefile
usr/spawnd/Hakefile
usr/startd/Hakefile
usr/startd/internal.h
usr/startd/main.c
usr/startd/spawn.c
usr/tests/e10ktest/Hakefile [new file with mode: 0644]
usr/tests/e10ktest/e10k_ctrl.c [new file with mode: 0644]
usr/tests/e10ktest/e10ktest.c [new file with mode: 0644]
usr/tests/e10ktest/e10ktest_latencies.c [new file with mode: 0644]
usr/tests/filetests/Hakefile
usr/tests/hellotest/Hakefile
usr/tests/hellotest/hellotest.c
usr/tests/net_tests/nfs_throughput/Hakefile
usr/tests/perfmontest/Hakefile
usr/tests/perfmontest/spin.c [new file with mode: 0644]
usr/tests/posix/Hakefile [new file with mode: 0644]
usr/tests/posix/socket_pipe.c [new file with mode: 0644]
usr/tests/testdesc/Hakefile
usr/tests/testdesc/testdesc-child.c
usr/vmkitmon/Hakefile

index e8cc54f..b0d1aa5 100644 (file)
@@ -1,5 +1,5 @@
 --------------------------------------------------------------------------
--- Copyright (c) 2007-2012, ETH Zurich.
+-- Copyright (c) 2007-2013, ETH Zurich.
 -- All rights reserved.
 --
 -- This file is distributed under the terms in the attached LICENSE file.
@@ -27,6 +27,7 @@
            "audio_nbm",
            "e1000",
            "e10k",
+           "e10k_vf",
            "e10k_q",
            "ehci",
            "fat16_ebpb",
@@ -86,6 +87,7 @@
            "omap/omap44xx_sysctrl_padconf_core",
            "omap/omap44xx_sysctrl_padconf_wkup",
            "omap/omap44xx_usbconf",
+           "pci_sr_iov_cap",
            "omap/omap44xx_usbtllhs_config",
            "omap/omap44xx_uart3"
          ], arch <- allArchitectures
index d41ebb6..c7f8016 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, ETH Zurich. All rights reserved.
+ * Copyright (c) 2011, 2013, ETH Zurich. All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
  * If you do not find this file, copies can be found by writing to:
@@ -539,6 +539,9 @@ device e10k lsbfirst ( addr base ) "Intel 82599 10 GbE Controller" {
     _           27 rsvd;
   };
 
+  // Undocumented
+  register ciaa rw addr(base, 0x11088) "CIAA" type(uint32);
+  register ciad rw addr(base, 0x1108C) "CIAD" type(uint32);
 
   /************************************
    * 8.2.3.5 Interrupt Registers
@@ -707,7 +710,7 @@ device e10k lsbfirst ( addr base ) "Intel 82599 10 GbE Controller" {
     eimen       1 "EICS Immediate Interrupt Enable";
     ll_int      4 "Low latency Credits Increment Rate";
     rsc_delay   3 "RSC Delay";
-    vt_mode     2 "VT_Mode";
+    vtmode      2 type(vt_mode) "VT_Mode";
     _           14 rsvd;
     eiame       1 "Extended Interrupt Auto Mask Enable";
     pba_sup     1 "BA Support";
@@ -1445,6 +1448,14 @@ device e10k lsbfirst ( addr base ) "Intel 82599 10 GbE Controller" {
    * 8.2.3.12 - 8.2.3.18 TODO
    ***********************************/
 
+  // 8.2.3.12.4
+  register sectxminifg rw addr(base, 0x08810) "Security Tx Buffer Minimum IFG" {
+    minsecifg   4              "Minimum IFG between packets";
+    _          4;
+    sectxdcb   5       "If PFC enabled, set to 0x1f, else set to 0x10";
+    _          19;
+  };
+
   // 8.2.3.12.5
   register secrxctrl rw addr(base, 0x08d00) "Security Rx Control" {
     secrx_dis   1 "Rx Security Offload Disable Bit";
@@ -2256,67 +2267,119 @@ device e10k lsbfirst ( addr base ) "Intel 82599 10 GbE Controller" {
   register rlec rc addr(base, 0x04040) "Receive Length Error Count"
     type(uint32);
 
-  // 8.2.23.26
+  // 8.2.3.23.8
+  register ssvpc rc addr(base, 0x08780) "Switch Security Violation Packet Count"
+    type(uint32);
+
+  // 8.2.3.23.26
   register gprc ro addr(base, 0x04074) "Good packets recieved count"
     type(uint32);
 
+  // 8.2.3.23.27
+  register gorcl rc addr(base, 0x04088) "Good Octets Received Count Low"
+    type(uint32);
+
+  // 8.2.3.23.28
+  register gorch rc addr(base, 0x0408c) "Good Octets Received Count High"
+    type(uint32);
+
   // 8.2.3.23.29
   register rxnfgpc rc addr(base, 0x041B0) "Good Rx Non-Filtered Packet Counter"
     type(uint32);
 
-  // 8.2.23.32
+  // 8.2.3.23.32
   register rxdgpc rc addr(base, 0x02F50) "DMA Good Rx Packet Counter"
     type(uint32);
 
-  // 8.2.23.44
+  // 8.2.3.23.44
   register gptc rc addr(base, 0x04080) "Good packets trasmitted count"
     type(uint32);
 
-  // 8.2.23.47
+  // 8.2.3.23.45
+  register gotcl rc addr(base, 0x04090) "Good octets transmitted count low"
+    type(uint32);
+
+  // 8.2.3.23.46
+  register gotch rc addr(base, 0x04094) "Good octets transmitted count high"
+    type(uint32);
+
+  // 8.2.3.23.47
   register txdgpc rc addr(base, 0x087A0) "DMA Good Tx Packet Counter"
     type(uint32);
 
-  // 8.2.23.50
+  // 8.2.3.23.50
   register ruc rc addr(base, 0x040A4) "Receive Undersize Count"
     type(uint32);
 
-  // 8.2.23.51
+  // 8.2.3.23.51
   register rfc rc addr(base, 0x040A8) "Receive Fragment Count"
     type(uint32);
 
-  // 8.2.23.52
+  // 8.2.3.23.52
   register roc rc addr(base, 0x040AC) "Receive Oversize Count"
     type(uint32);
 
-  // 8.2.23.53
+  // 8.2.3.23.53
   register rjc rc addr(base, 0x040B0) "Receive Jabber Count"
     type(uint32);
 
-  // 8.2.23.54
+  // 8.2.3.23.54
   register mngprc rc addr(base, 0x040B4) "Management Packets Received Count"
     type(uint32);
 
-  // 8.2.23.55
+  // 8.2.3.23.55
   register mngpdc rc addr(base, 0x040B8) "Management Packets Dropped Count"
     type(uint32);
 
-  // 8.2.23.59
+  // 8.2.3.23.57
+  register torl rc addr(base, 0x040c0) "Total octets received low"
+    type(uint32);
+
+  // 8.2.3.23.58
+  register torh rc addr(base, 0x040c4) "Total octets received high"
+    type(uint32);
+
+  // 8.2.3.23.59
   register tpr rc addr(base, 0x040D0) "Total Packets Recieved"
     type(uint32);
 
-  // 8.2.23.60
+  // 8.2.3.23.60
   register tpt rc addr(base, 0x040D4) "Total Packets Transmitted"
     type(uint32);
 
-  // 8.2.23.69
+  // 8.2.3.23.69
   register mspdc rc addr(base, 0x04010) "MAC Short Packet Discard Count"
     type(uint32);
 
-  // 8.2.23.74
+  // 8.2.3.23.71
+  regarray rqsmr rw addr(base, 0x02300) [32; 0x4] "Receive Queue Statistics Mapping" {
+    q_map0      4  "Map to queue 4*n+0";
+    _           4;
+    q_map1      4  "Map to queue 4*n+1";
+    _           4;
+    q_map2      4  "Map to queue 4*n+2";
+    _           4;
+    q_map3      4  "Map to queue 4*n+3";
+    _           4;
+  };
+
+  // 8.2.3.23.73
+  regarray tqsm rw addr(base, 0x08600) [32; 0x4] "Transmit Queue Statistics Mapping" {
+    q_map0      4  "Map to queue 4*n+0";
+    _           4;
+    q_map1      4  "Map to queue 4*n+1";
+    _           4;
+    q_map2      4  "Map to queue 4*n+2";
+    _           4;
+    q_map3      4  "Map to queue 4*n+3";
+    _           4;
+  };
+
+  // 8.2.3.23.74
   regarray qprc rc addr(base, 0x01030) [16; 0x40] "Queue Packets Received Count"
     type(uint32);
 
-  // 8.2.23.75
+  // 8.2.3.23.75
   regarray qprdc rc addr(base, 0x01430) [16; 0x40] "Queue Packets Received Drop Count"
     type(uint32);
 
@@ -2413,6 +2476,18 @@ device e10k lsbfirst ( addr base ) "Intel 82599 10 GbE Controller" {
     _           1 rsvd;
   };
 
+  // 8.2.3.27.5
+  regarray pfvflre ro addr(base, 0x00600) [2] "PF VFLR Events Indication" type(uint32);
+
+  // 8.2.3.27.6
+  regarray pfvflrec rw1c addr(base, 0x00700) [2] "PF VFLR Events Clear" type(uint32);
+
+  // 8.2.3.27.7
+  regarray pfvfre rw addr(base, 0x051e0) [2] "PF VF Receive Enable" type(uint32);
+
+  // 8.2.3.27.8
+  regarray pfvfte rw addr(base, 0x08110) [2] "PF VF Transmit Enable" type(uint32);
+
   // 8.2.3.27.9
   register pfqde rw addr(base, 0x02F04) "PF PF Queue Drop Enable Register" {
     qde         1 "Enable drop of packets from Rx Queue queue_idx";
@@ -2424,6 +2499,30 @@ device e10k lsbfirst ( addr base ) "Intel 82599 10 GbE Controller" {
     _           14 rsvd;
   };
 
+  // 8.2.3.27.11
+  regarray pfvfspoof rw addr(base, 0x08200) [8] "PF VF Anti Spoof Control" {
+    macas  8        "MAC Address Anti-spoofing filter";
+    vlanas 8        "VLAN tag anti-spoofing filter";
+    _     16;
+  };
+
+  // 8.2.3.27.12
+  register pfdtxgswc rw addr(base, 0x08220) "PFDMA Tx General Switch Control" {
+    lbe           1         "Enables VMDQ loopback";
+    _     31;
+  };
+
+  // 8.2.3.27.14
+  regarray pfvml2flt rw addr(base, 0x0f000) [64] "PF VM L2 Control" {
+    _     24;
+    aupe   1   "Accept Untagged Packets Enable";
+    rompe  1   "Receive Overflow Multicast Packets";
+    rope   1   "Receive MAC Filters Overflow";
+    bam           1    "Broadcast accept";
+    mpe           1    "Multicast Promiscuous";
+    _     3;
+  };
+
   // 8.2.3.27.15
   regarray pfvlvf rw addr(base, 0x0F100) [64] "PF VM VLAN Pool Filter" {
     vlan_id     12 "VLAN tag for pool VLAN filter n";
diff --git a/devices/e10k_vf.dev b/devices/e10k_vf.dev
new file mode 100644 (file)
index 0000000..51a44d3
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 2011, 2013, ETH Zurich. All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+/*
+ * e10k_vf.dev
+ *
+ * DESCRIPTION: Intel 82599 10 GbE Controller Virtual Function
+ *
+ * Numbers in comments refer to the Intel 82599 10 GbE Controller Datasheet,
+ * Revison 2.76, September 2012
+ */
+
+device e10k_vf lsbfirst ( addr base ) "Intel 82599 10 GbE Controller Virtual Function" {
+
+  /************************************
+   * 8.3.5.1 General control registers--VF
+   ***********************************/
+
+  // 8.3.5.1.1
+  register vfctrl wo addr(base, 0x00000) "VF control" {
+    _           26 rsvd;
+    rst         1 "Device reset";
+    _           5 rsvd;
+  };
+
+  constants lanid "LAN ID" {
+    lan_0       = 0b00 "LAN 0";
+    lan_1       = 0b01 "LAN 1";
+    lan_not_u1  = 0b10 "LAN ID not used";
+    lan_not_u2  = 0b11 "LAN ID not used";
+  };
+
+  // 8.3.5.1.2
+  register vfstatus ro addr(base, 0x00008) "VF status" {
+    _           2;
+    lan_id      2 type(lanid) "LAN ID";
+    _           3;
+    link_up     1 "Linkup Status Indication";
+    _           2;
+    num_vfs     8 "Num VFs";
+    iov_active  1 "IOV Active";
+    pcie_mes    1 "PCIe Master Enable Status";
+    _           12;
+  };
+
+  // 8.3.5.1.3
+  constants mac_lnkmode "MAC link mode status" {
+    lms_1g      = 0b00 "1 GbE";
+    lms_10g_par = 0b01 "10 GbE parallel";
+    lms_10g_ser = 0b10 "10 GbE serial";
+    lms_aneg    = 0b11 "auto-negotiation";
+  };
+
+  constants link_speed "MAC link speed status" {
+    ls_100m     = 0b01 "100 Mb/s";
+    ls_1g       = 0b10 "1 GbE";
+    ls_10g      = 0b11 "10 GbE";
+  };
+
+  register vflinks ro addr(base, 0x00010) "VF Link Status Register" {
+    kxsig_det   1 "A signal is present";
+    fecsig_det  1 "FEC reports signal detected";
+    fecblk_lck  1 "FEC reached block lock";
+    krhberr     1 "10GbE serial KR_PCS high error rate";
+    krpcsbl     1 "10 GbE serial PCS block lock";
+    kxr_annprcv 1 "KX/KX4/KR AN Next Page Received";
+    kxr_anprcv  1 "KX/KX4/KR Backplane Auto Negotiation Page Received";
+    lnk_stat    1 "Link Up and there was no link down from last time read";
+    kx4sig_det  4 "Signal Detect of 10 GbE Parallel (KX4, CX4 or XAUI) (1bit per lane)";
+    krsig_det   1 "Signal Detect of 10 GbE serial (KR or SFI)";
+    l10g_syncst 4 "10G Parallel lane sync status (1bit per lane)";
+    l10g_algst  1 "10 GbE align_status";
+    l1g_syncst  1 "1G sync_status";
+    kxr_anrxid  1 "KX/KX4/KR Backplane Auto Negotiation Rx Idle";
+    l1g_anen    1 "PCS_1 GbE auto-negotiation is enabled";
+    l1g_lnken   1 "1 GbE PCS enabled for 1 GbE and SGMII operation";
+    l10g_lnken  1 "XGXS Enabled for 10 GbE operation";
+    fec_en      1 "Status of forwarderrorcorrection in 10 GbE serial link";
+    l10g_seren  1 "Status of 10 GbE serial PCS (KR PCS) for KR or SFI operation";
+    sgmii_en    1 "Status of SGMII operation";
+    mlink_mode  2 type (mac_lnkmode) "MAC link mode status";
+    lnk_speed   2 type (link_speed) "MAC link speed status";
+    lnk_up      1 "Link is up";
+    kxr_ancomp  1 "KX/KX4/KR backplane auto-negotiation has completed successfully";
+  };
+
+  // NYI:
+  // 8.3.5.1.4 VF Free Running Timer (VFFRTIMER)
+  // 8.3.5.1.5 VF Mailbox (VFMailbox)
+  // 8.3.5.1.6 VF Mailbox Memory (VFMBMEM)
+
+  // 8.3.5.1.7
+  register vfrxmemwrap ro addr(base, 0x03190) "VF Rx Packet Buffer Flush Detect" {
+    tc0_wrap    3 "Packet Buffer 0 Wrap Around Counter";
+    tc0_empty   1 "Packet Buffer 0 Empty";
+    tc1_wrap    3 "Packet Buffer 1 Wrap Around Counter";
+    tc1_empty   1 "Packet Buffer 1 Empty";
+    tc2_wrap    3 "Packet Buffer 2 Wrap Around Counter";
+    tc2_empty   1 "Packet Buffer 2 Empty";
+    tc3_wrap    3 "Packet Buffer 3 Wrap Around Counter";
+    tc3_empty   1 "Packet Buffer 3 Empty";
+    tc4_wrap    3 "Packet Buffer 4 Wrap Around Counter";
+    tc4_empty   1 "Packet Buffer 4 Empty";
+    tc5_wrap    3 "Packet Buffer 5 Wrap Around Counter";
+    tc5_empty   1 "Packet Buffer 5 Empty";
+    tc6_wrap    3 "Packet Buffer 6 Wrap Around Counter";
+    tc6_empty   1 "Packet Buffer 6 Empty";
+    tc7_wrap    3 "Packet Buffer 7 Wrap Around Counter";
+    tc7_empty   1 "Packet Buffer 7 Empty";
+  };
+
+  /************************************
+   * 8.3.5.2 Interrupt Registers--VF
+   ***********************************/
+
+  // 8.3.5.2.1
+  register vfeicr rw1c addr(base, 0x00100) "VF Extended Interrupt Cause" {
+    msix       3  "Indicates an interrupt cause mapped to MSI-X vectors 2:0";
+    _           29 rsvd;
+  };
+
+  // 8.3.5.2.2
+  register vfeics wo addr(base, 0x00104) "VF Extended Interrupt Cause Set" {
+    msix        3  "Sets to corresponding EICR bit of MSI-X vectors 2:0";
+    _           29 rsvd;
+  };
+
+  // 8.3.5.2.3
+  register vfeims rw addr(base, 0x00108) "VF Extended Interrupt Mask Set/Read" {
+    msix        3  "Set mask bit for the corresponding EICR bit of MSI-X vectors 2:0";
+    _           29 rsvd;
+  };
+
+  // 8.3.5.2.4
+  register vfeimc wo addr(base, 0x0010c) "VF Extended Interrupt Mask Clear" {
+    msix        3  "Clear mask bit for the corresponding EICR bit of MSI-X vectors 2:0";
+    _           29 rsvd;
+  };
+
+  // 8.3.5.2.5
+  register vfeiam rw addr(base, 0x00114) "VF Extended Interrupt Auto Mask Enable" {
+    msix        3  "Auto mask bit for the corresponding EICR bit of MSI-X vectors 2:0";
+    _           29 rsvd;
+  };
+
+  // 8.3.5.2.6
+/*
+  regtype vfeitrn "VF Extended Interrupt Throttle Register Type" {
+    _           3 rsvd;
+    itr_int     9 "Minimum inter-interrupt interval";
+    _           3 rsvd;
+    lli_mod     1 "LLI Moderation";
+    lli_credit  5 "LLI Credit";
+    itr_count   7 "ITR Counter";
+    _           3 rsvd;
+    cnt_wdis    1 "CNT_WDIS";
+  };
+*/
+  // XXX: Not sure if this is correct...
+  regarray vfeitr rw addr(base, 0x00820) [2]
+                "VF Extended Interrupt Mask Set/Read #0-#1"
+                type(uint32);
+
+  // 8.3.5.2.7
+  regarray vfivar rw addr(base, 0x00120) [4] "VF Interrupt Vector Allocation Registers" {
+    i_alloc0    1 "Defines the MSI-X vector (0 or 1) assigned to Rx queue 2*N for IVAR N register (N = 0..3)";
+    _           6 rsvd;
+    i_allocval0 1 "Interrupt allocation 0 valid";
+    i_alloc1    1 "The interrupt allocation for Tx queue 2n";
+    _           6 rsvd;
+    i_allocval1 1 "Interrupt allocation 1 valid";
+    i_alloc2    1 "The interrupt allocation for Rx queue 2n+1";
+    _           6 rsvd;
+    i_allocval2 1 "Interrupt allocation 2 valid";
+    i_alloc3    1 "The interrupt allocation for Tx queue 2n+1";
+    _           6 rsvd;
+    i_allocval3 1 "Interrupt allocation 3 valid";
+  };
+
+  // 8.3.5.2.8
+  register vfivar_misc rw addr(base, 0x00140) "VF Miscellaneous Interrupt Vector Allocation" {
+    i_alloc0    2 "MSI-X vector assigned to the mailbox interrupt";
+    _          5 rsvd;
+    i_allocval0 1 "Interrupt allocation 0 valid";
+    _           24 rsvd;
+  };
+
+  // 8.3.5.2.9
+  // XXX: Not sure if this is correct...
+  regarray vfrscint rw addr(base, 0x00180) [2] "VF RSC Enable Interrupt" type(uint32);
+
+  // 8.3.5.2.10
+  register vfpbacl rw1c addr(base, 0x00148) "VF MSI-X PBA Clear" {
+    penbit        3    "MSI-X Pending Bits Clear. Reading returns PBA vector.";
+    _             29   rsvd;
+  };
+
+  /************************************
+   * 8.3.5.3 Receive DMA Registers -- VF
+   ***********************************/
+
+  // 8.3.5.3.1
+  regarray vfrdbal rw addr(base, 0x01000) [8; 0x40]
+                "VF Receive Descriptor Base Address Low (#0-#7)"
+                type(uint32);
+
+  // 8.3.5.3.2
+  regarray vfrdbah rw addr(base, 0x01004) [8; 0x40]
+                "VF Receive Descriptor Base Address High (#0-#7)"
+                type(uint32);
+
+  // 8.3.5.3.3
+  regarray vfrdlen rw addr(base, 0x01008) [8; 0x40]
+                "VF Receive Descriptor Length (#0-#7)"
+                type(uint32);
+
+  // 8.3.5.3.4
+  regarray vfrdh rw addr(base, 0x01010) [8; 0x40]
+                "VF Receive Descriptor Head (#0-#7)"
+                type(uint32);
+
+  // 8.3.5.3.5
+  regarray vfrdt rw addr(base, 0x01018) [8; 0x40]
+                "VF Receive Descriptor Tail (#0-#7)"
+                type(uint32);
+
+  // 8.3.5.3.6
+  regtype rxdctl "Receive Descriptor Control" {
+    _           25 rsvd;
+    enable      1 "Receive Queue Enable";
+    _           4 rsvd;
+    vme         1 "VLAN Mode Enable";
+    _           1 rsvd;
+  };
+
+  regarray vfrxdctl rw addr(base, 0x01028) [8; 0x40]
+                "VF Receive Descriptor Control (#0-#7)"
+                type(rxdctl);
+
+  // 8.3.5.3.7
+  constants rx_desctype "RX Descriptor Type" {
+    legacy      = 0b000 "Legacy";
+    adv_1buf    = 0b001 "Advanced descriptor one buffer";
+    adv_hdrsp   = 0b010 "Advanced descriptor header splitting";
+    adv_usehb   = 0b101 "Advanced descriptor header splitting always use header buffer";
+  };
+
+  regtype srrctl "Split Receive Control Registers" {
+    bsz_pkt     5 "Receive Buffer Size for Packet Buffer";
+    _           3 mbz;
+    bsz_hdr     6 "Receive Buffer Size for Header Buffer";
+    _           8 rsvd;
+    rdmts       3 "Receive Descriptor Minimum Threshold Size";
+    desctype    3 type(rx_desctype) "Define the descriptor type";
+    drop_en     1 "Drop Enabled";
+    _           3 rsvd;
+  };
+
+  regarray vfsrrctl rw addr(base, 0x01014) [8; 0x40]
+                "VF Split Receive Control Registers (#0-#7)"
+                type(srrctl);
+
+  // 8.3.5.3.8
+  register vfpsrtype rw addr(base, 0x00300) "VF Replication Packet Split Receive Type" {
+    _           1 mbz;
+    split_nfs   1 "Split received NFS packets after NFS header";
+    _           2 mbz;
+    split_tcp   1 "Split received TCP packets after TCP header";
+    split_udp   1 "Split received UDP packets after UDP header";
+    _           2 mbz;
+    split_ip4   1 "Split received IPv4 packets after IPv4 header";
+    split_ip6   1 "Split received IPv6 packets after IPv6 header";
+    _           2 mbz;
+    split_l2    1 "Split received L2 packets after L2 header";
+    _           16 mbz;
+    rqpl        3 "Number of bits to use for RSS redirection";
+  };
+
+  // 8.3.5.3.9
+  constants rsc_maxdesc "Maximum descriptors per Large receive" {
+    max_1desc   = 0b00 "Maximum of 1 descriptor per large receive";
+    max_4desc   = 0b01 "Maximum of 4 descriptors per large receive";
+    max_8desc   = 0b10 "Maximum of 8 descriptors per large receive";
+    max_16desc  = 0b11 "Maximum of 16 descriptors per large receive";
+  };
+
+  regtype rscctl "RSC Control" {
+    rsc_en      1 "RSC Enable";
+    _           1 rsvd;
+    maxdesc     2 type(rsc_maxdesc) "Maximum descriptors per Large receive";
+    _           28 rsvd;
+  };
+
+  regarray vfrscctl rw addr(base, 0x0102c) [8; 0x40]
+                "RSC Control (#0-#7)"
+                type(rscctl);
+
+  /************************************
+   * 8.3.5.4 Transmit Registers -- VF
+   ***********************************/
+
+  // 8.3.5.4.1
+  regarray vftdbal rw addr(base, 0x02000) [4; 0x40]
+                "VF Transmit Descriptor Base Address Low"
+                type(uint32);
+
+  // 8.3.5.4.2
+  regarray vftdbah rw addr(base, 0x02004) [4; 0x40]
+                "VF Transmit Descriptor Base Address High"
+                type(uint32);
+
+  // 8.3.5.4.3
+  regarray vftdlen rw addr(base, 0x02008) [4; 0x40]
+                "VF Transmit Descriptor Length"
+                type(uint32);
+
+  // 8.3.5.4.4
+  // rw is only partially accurate here. This register must only be written
+  // directly after reset.
+  regarray vftdh rw addr(base, 0x02010) [4; 0x40]
+                "VF Transmit Descriptor Head"
+                type(uint32);
+
+  // 8.3.5.4.5
+  regarray vftdt rw addr(base, 0x02018) [4; 0x40]
+                "VF Transmit Descriptor Tail"
+                type(uint32);
+
+  // 8.3.5.4.6
+  regarray vftxdctl rw addr(base, 0x02028) [4; 0x40] "VF Transmit Descriptor Control" {
+    pthresh     7 "Pre-Fetch Threshold";
+    _           1 rsvd;
+    hthresh     7 "Host Threshold";
+    _           1 rsvd;
+    wthresh     7 "Write-Back Threshold";
+    _           2 rsvd;
+    enable      1 "Transmit Queue Enable";
+    swflsh      1 "Transmit Software Flush";
+    _           5 rsvd;
+  };
+
+  // 8.3.5.4.7
+  regarray vftdwbal rw addr(base, 0x02038) [4; 0x40] "VF Tx Descriptor Completion Write Back Address Low" {
+    headwb_en   1 "Head Write-Back Enable";
+    _           1 rsvd;
+    headwb_low  30 "Lowest 32 bits of the head write-back memory location";
+  };
+
+  // 8.3.5.4.8
+  regarray vftdwbah rw addr(base, 0x0203c) [4; 0x40] "VF Tx Descriptor Completion Write Back Address High" {
+    headwb_high 32 "Highest 32 bits of the head write-back memory location";
+  };
+
+  /************************************
+   * 8.3.5.5 DCA Registers -- VF
+   ***********************************/
+
+  // 8.3.5.5.1
+  regtype dca_rxctrl "Rx DCA Control Register" {
+    _           5 rsvd;
+    rxdca_desc  1 "Descriptor DCA EN";
+    rxdca_hdr   1 "Rx Header DCA EN";
+    rxdca_payl  1 "Payload DCA EN";
+    _           1 rsvd;
+    rxdesc_rdro 1 "Rx Descriptor Read Relax Order Enable";
+    _           1 rsvd;
+    rxdesc_wbro 1 mbz "Rx Descriptor Write Back Relax Order Enable";
+    _           1 rsvd;
+    rxdata_wrro 1 "Rx data Write Relax Order Enable";
+    _           1 rsvd;
+    rxhdr_ro    1 "Rx Split Header Relax Order Enable";
+    _           8 rsvd;
+    cpuid       8 "Physical ID";
+  };
+
+  regarray vfdca_rxctrl rw addr(base, 0x0100c) [8; 0x40]
+                "VF Rx DCA Control Register (#0-#7)"
+                type(dca_rxctrl);
+
+  // 8.3.5.5.2
+  regarray vfdca_txctrl rw addr(base, 0x0200c) [8; 0x40] "VF Tx DCA Control Registers" {
+    _           5 rsvd;
+    txdesc_dca  1 "Descriptor DCA Enable";
+    _           3 rsvd;
+    txdesc_rdro 1 "Tx Descriptor Read Relax Order Enable";
+    _           1 rsvd;
+    txdesc_wbro 1 "Relax Order Enable of Tx Descriptor well as head pointer write back";
+    _           1 rsvd;
+    txdata_rdro 1 "Tx Data Read Relax Order Enable";
+    _           10 rsvd;
+    cpuid       8 "Physical ID";
+  };
+
+  /************************************
+   * 8.3.5.6 Statistics -- VF
+   ***********************************/
+
+  // 8.3.5.6.1
+  register vfgprc ro addr(base, 0x0101c) "VF Good packets received count"
+    type(uint32);
+
+  // 8.3.5.6.2
+  register vfgptc ro addr(base, 0x0201c) "VF Good packets trasmitted count"
+    type(uint32);
+
+  // 8.3.5.6.3
+  register vfgorc_lsb ro addr(base, 0x01020) "VF Good Octets Received Count Low"
+    type(uint32);
+
+  // 8.3.5.6.4
+  register vfgorc_msb ro addr(base, 0x01024) "VF Good Octets Received Count High"
+    type(uint32);
+
+  // 8.3.5.6.5
+  register vfgotc_lsb ro addr(base, 0x02020) "VF Good Octets Transmitted Count Low"
+    type(uint32);
+  // 8.3.5.6.6
+  register vfgotc_msb ro addr(base, 0x02024) "VF Good Octets Transmitted Count High"
+    type(uint32);
+
+  // 8.3.5.6.7
+  register vfmprc ro addr(base, 0x01034) "VF Multicast Packets Received Count"
+    type(uint32);
+};
index 4ed06cc..c3794ef 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, ETH Zurich. All rights reserved.
+ * Copyright (c) 2008, 2013, ETH Zurich. All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
  * If you do not find this file, copies can be found by writing to:
@@ -167,7 +167,7 @@ device pci_hdr0 msbfirst ( pci base ) "PCI Type 0 Configuration" {
   register cap_ptr ro pci(base, 0x34) "Capabilities ptr" type(uint8);
 
   register int_line rw pci(base, 0x3c) "Interrupt line" type(uint8);
-  register int_pin ro pci(base, 0x3d) "Interrupt ping" type(uint8);
+  register int_pin ro pci(base, 0x3d) "Interrupt pin" type(uint8);
 
   register min_gnt ro pci(base, 0x3e) "Min Gnt" type(uint8);
   register max_lat ro pci(base, 0x3f) "Max Lat" type(uint8);
index 37fca9e..96c286a 100644 (file)
@@ -138,10 +138,12 @@ device pci_hdr1 msbfirst ( pci base ) "PCI Type 1 Configuration" {
   register bar0 pci ( base, 0x10 ) "Base address 0" type(uint32);
   register bar1 pci ( base, 0x14 ) "Base address 1" type(uint32);
 
-  register pri_bus pci (base, 0x18) "Primary bus number" type(uint8);
-  register sec_bus pci (base, 0x19) "Secondary bus number" type(uint8);
-  register sub_bus pci (base, 0x1a) "Subordinate bus number" type(uint8);
-  register sec_lat pci (base, 0x1b) "Secondary latency timer" type(uint8);
+  register bcfg pci (base, 0x18) "Bus configuration register" {
+    sec_lat    8   "Secondary latency timer";
+    sub_bus    8   "Subordinate bus number";
+    sec_bus    8   "Secondary bus number";
+    pri_bus    8   "Primary bus number";
+  };
 
   //
   // I/O base and limit registers
@@ -163,13 +165,11 @@ device pci_hdr1 msbfirst ( pci base ) "PCI Type 1 Configuration" {
   //
   // Memory-mapped I/O base and limit registers
   //
-  
-  regtype membl "Memory-mapped base and limit" {
-    addr       12 rw "Low bits of address";
-    _          4;
+
+  register membl pci (base, 0x20) "Memory base and limit" {
+    limit  16   "Limit";
+    base   16   "Base";
   };
-  register mem_base pci (base, 0x20) "Memory base" type(uint16);
-  register mem_limit pci (base, 0x22) "Memory limit" type(uint16);
 
   //
   // Prefetchable memory base and limit registers
@@ -206,7 +206,7 @@ device pci_hdr1 msbfirst ( pci base ) "PCI Type 1 Configuration" {
     pritm_dis  1 ro "Primary discard timeout";
     back2back   1 ro "Fast back-to-back enable";
     sec_reset   1 rw "Secondary bus reset";
-    mabort     1 ro "Master abort mode";
+    mabort     1 rw "Master abort mode";
     _          1;
     vga                1 rw "VGA enable";
     isa                1 rw "ISA enable";
diff --git a/devices/pci_sr_iov_cap.dev b/devices/pci_sr_iov_cap.dev
new file mode 100644 (file)
index 0000000..144044d
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013, ETH Zurich. All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+/*
+ * pci_sr_iov_cap.dev
+ *
+ * DESCRIPTION: PCI SR-IOV Extended Capability
+ * 
+ * Numbers in comments refer to the Single Root I/O Virtualization and
+ * Sharing Specification, Revision 1.1, January 20, 2010.
+ */
+
+device pci_sr_iov_cap lsbfirst ( addr base ) "PCI SR-IOV Extended Capability" {
+
+  // 3.3.1
+  register hdr ro addr( base, 0x00 ) "Extended Capabilities Header" {
+    id    16  "PCI Express Extended Capability ID";
+    ver           4   "Capability Version";
+    next   12  "Next Capability Offset";
+  };
+
+  // 3.3.2
+  register caps ro addr( base, 0x04 ) "SR-IOV Capabilities" {
+    vf_migration   1    "VF Migration Capable";
+    ari_preserved  1    "ARI Capable Hierarchy Preserved";
+    _             19;
+    vf_mig_int    11    "VF Migration Interrupt Message Number";
+  };
+
+  // 3.3.3
+  register ctrl rw addr( base, 0x08 ) "SR-IOV Control" {
+    vf_enable           1       "VF Enable";
+    vf_mig_enable       1       "VF Migration Enable";
+    vf_mig_int_enable   1       "VF Migration Interrupt Enable";
+    vf_mse              1       "VF MSE";
+    ari_capable                 1       "ARI Capable Hierarchy";
+    _                   11;
+  };
+
+  // 3.3.4
+  register status rw addr( base, 0x0a ) "SR-IOV Status" {
+    vf_migration     1    "VF Migration Status";
+    _               15 mbz;
+  };
+
+  // 3.3.5
+  register initialvfs ro addr( base, 0x0c ) "InitialVFs" type(uint16);
+  // 3.3.6
+  register totalvfs ro addr( base, 0x0e ) "TotalVFs" type(uint16);
+  // 3.3.7
+  register numvfs rw addr( base, 0x10 ) "NumVFs" type(uint16);
+  // 3.3.8
+  register fdl ro addr( base, 0x12 ) "Function Dependency Link" type(uint8);
+  // 3.3.9
+  register offset ro addr( base, 0x14 ) "First VF Offset" type(uint16);
+  // 3.3.10
+  register stride ro addr( base, 0x16 ) "VF Stride" type(uint16);
+  // 3.3.11
+  register devid ro addr( base, 0x1a ) "VF Device ID" type(uint16);
+
+  // 3.3.12
+  register sup_psize ro addr( base, 0x1c ) "Supported Page Sizes" type(uint32);
+  // 3.3.13
+  register sys_psize rw addr( base, 0x20 ) "System Page Size" type(uint32);
+
+  // 3.3.14
+  regarray vf_bar rw addr( base, 0x24 ) [6] "VF BAR" type(uint32);
+
+  // 3.3.15
+  register vf_mig_state ro addr( base, 0x3c ) "VF Migration State Array Offset" {
+    bir           3            "VF Migration State BIR";
+    offset 29          "VF Migration State Offset";
+  };
+
+};
index 93c0661..aaa502d 100644 (file)
@@ -60,7 +60,8 @@ cStdIncs arch archFamily =
       NoDep SrcTree "src" Config.libcInc,
       NoDep SrcTree "src" "/include/c",
       NoDep SrcTree "src" ("/include/target" ./. archFamily),
-      NoDep SrcTree "src" "/include/ipv4", -- XXX
+      NoDep SrcTree "src" Config.lwipxxxInc, -- XXX
+      NoDep SrcTree "src" Config.lwipInc,
       NoDep InstallTree arch "/include",
       NoDep InstallTree arch "/include/dev",
       NoDep SrcTree "src" ".",
index 438ec59..cf982a3 100644 (file)
@@ -1,5 +1,5 @@
 --------------------------------------------------------------------------
--- Copyright (c) 2007-2010, 2012, ETH Zurich.
+-- Copyright (c) 2007-2010, 2012, 2013, ETH Zurich.
 -- All rights reserved.
 --
 -- This file is distributed under the terms in the attached LICENSE file.
@@ -275,6 +275,12 @@ libcInc :: String
 libcInc = if libc == "oldc" then "/include/oldc"
           else "/lib/newlib/newlib/libc/include"
 
+-- Sets the include path for lwIP
+lwipInc :: String
+lwipInc = "/lib/lwip/src/include"
+lwipxxxInc :: String
+lwipxxxInc = "/lib/lwip/src/include/ipv4"
+
 -- some defines depend on the architecture/compile options
 arch_defines :: Options -> [RuleToken]
 arch_defines opts
index 21edf14..36eea1b 100755 (executable)
@@ -26,6 +26,7 @@ import Data.Dynamic
 import Data.Maybe
 import Data.List
 import Control.Monad
+import Control.Parallel.Strategies
 
 import RuleDefs
 import HakeTypes
@@ -211,7 +212,7 @@ resolveRelativePathName' d a f root =
 --
 makeDirectories :: [(String, HRule)] -> String
 makeDirectories r = 
-    let alldirs = makeDirs1 (Rules [ rl | (f,rl) <- r ])
+    let alldirs = makeDirs1 (Rules [ rl | (f,rl) <- r ]) `using` parListChunk 200 rdeepseq
         marker d = d ./. ".marker"
     in unlines ([ "# Directories follow" ] ++
                 [ "hake_dirs: " ++ (marker d) ++ "\n\n" ++
@@ -219,7 +220,7 @@ makeDirectories r =
                   "\tmkdir -p " ++ d ++ "\n" ++
                   "\ttouch " ++ (marker d) ++ "\n"
                 | d <- nub alldirs])
-       
+
 makeDirs1 :: HRule -> [String]
 makeDirs1 (Rules hrules) = concat [ makeDirs1 r | r <- hrules]
 makeDirs1 (Include tok) = 
@@ -265,7 +266,7 @@ allowedArchs = all (\a -> a `elem` (Config.architectures ++ specialArchitectures
 --
 makeMakefile :: [(String, HRule)] -> String
 makeMakefile r = 
-  unlines $ intersperse "" [makeMakefileSection f rl | (f,rl) <- r]
+  unlines $ intersperse "" ([makeMakefileSection f rl | (f,rl) <- r] `using` parList rdeepseq)
 
 makeMakefileSection :: String -> HRule -> String
 makeMakefileSection fname rules = 
index a25ed38..19cf0dc 100644 (file)
@@ -932,6 +932,60 @@ appBuildArch af tf args arch =
             )
 
 --
+-- Build an Arrakis application binary
+--
+
+arrakisapplication :: Args.Args
+arrakisapplication = Args.defaultArgs { Args.buildFunction = arrakisApplicationBuildFn }
+
+arrakisApplicationBuildFn :: [String] -> String -> Args.Args -> HRule
+arrakisApplicationBuildFn af tf args
+    | debugFlag && trace (Args.showArgs (tf ++ " Arrakis Application ") args) False
+        = undefined
+arrakisApplicationBuildFn af tf args =
+    Rules [ arrakisAppBuildArch af tf args arch | arch <- Args.architectures args ]
+
+arrakisAppGetOptionsForArch arch args =
+    (options arch) { extraIncludes =
+                         [ NoDep SrcTree "src" a | a <- Args.addIncludes args],
+                     optIncludes = (optIncludes $ options arch) \\
+                         [ NoDep SrcTree "src" i | i <- Args.omitIncludes args ],
+                     optFlags = ((optFlags $ options arch) ++ [ Str "-DARRAKIS" ]) \\
+                                [ Str f | f <- Args.omitCFlags args ],
+                     optCxxFlags = (optCxxFlags $ options arch) \\
+                                   [ Str f | f <- Args.omitCxxFlags args ],
+                     optSuffix = "_for_app_" ++ Args.target args,
+                     optLibs = [ In InstallTree arch "/lib/libarrakis.a" ] ++
+                               ((optLibs $ options arch) \\
+                                [ In InstallTree arch "/lib/libbarrelfish.a" ]),
+                     extraFlags = Args.addCFlags args ++ Args.addCxxFlags args,
+                     extraLdFlags = [ Str f | f <- Args.addLinkFlags args ],
+                     extraDependencies =
+                         [Dep BuildTree arch s | s <- Args.addGeneratedDependencies args]
+                   }
+
+arrakisAppBuildArch af tf args arch =
+    let -- Fiddle the options
+        opts = arrakisAppGetOptionsForArch arch args
+        csrcs = Args.cFiles args
+        cxxsrcs = Args.cxxFiles args
+        appname = Args.target args
+        -- XXX: Not sure if this is correct. Currently assuming that if the app
+        -- contains C++ files, we have to use the C++ linker.
+        mylink = if cxxsrcs == [] then link else linkCxx
+    in
+      Rules ( flounderRules opts args csrcs
+              ++
+              [ mackerelDependencies opts m csrcs | m <- Args.mackerelDevices args ]
+              ++
+              [ compileCFiles opts csrcs,
+                compileCxxFiles opts cxxsrcs,
+                assembleSFiles opts (Args.assemblyFiles args),
+                mylink opts (allObjectPaths opts args) (allLibraryPaths args) appname
+              ]
+            )
+
+--
 -- Build a static library
 --
 
@@ -985,13 +1039,13 @@ data LibDepTree = LibDep String | LibDeps [LibDepTree] deriving (Show,Eq)
 -- manually add dependencies for now (it would be better if each library
 -- defined each own dependencies locally, but that does not seem to be an
 -- easy thing to do currently
-libposixcompat_deps   = LibDeps [ LibDep "posixcompat", liblwip_deps,
+libposixcompat_deps   = LibDeps [ LibDep "posixcompat",
                                   libvfs_deps_all, LibDep "term_server" ]
 liblwip_deps          = LibDeps $ [ LibDep x | x <- deps ]
     where deps = ["lwip" ,"contmng" ,"net_if_raw" ,"timer" ,"hashtable"]
 libnetQmng_deps       = LibDeps $ [ LibDep x | x <- deps ]
     where deps = ["net_queue_manager", "contmng" ,"procon" , "net_if_raw", "bfdmuxvm"]
-libnfs_deps           = LibDeps $ [ LibDep "nfs", liblwip_deps ]
+libnfs_deps           = LibDeps $ [ LibDep "nfs" ]
 libssh_deps           = LibDeps [ libposixcompat_deps, libopenbsdcompat_deps,
                                   LibDep "zlib", LibDep "crypto", LibDep "ssh" ]
 libopenbsdcompat_deps = LibDeps [ libposixcompat_deps, LibDep "crypto",
@@ -1008,6 +1062,7 @@ vfsdeps (VFS_FAT:xs)        = [] ++ vfsdeps xs
 
 libvfs_deps_all        = LibDeps $ vfsdeps [VFS_NFS, VFS_RamFS, VFS_BlockdevFS,
                                             VFS_FAT]
+libvfs_deps_nonfs      = LibDeps $ vfsdeps [VFS_RamFS, VFS_BlockdevFS, VFS_FAT]
 libvfs_deps_nfs        = LibDeps $ vfsdeps [VFS_NFS]
 libvfs_deps_ramfs      = LibDeps $ vfsdeps [VFS_RamFS]
 libvfs_deps_blockdevfs = LibDeps $ vfsdeps [VFS_BlockdevFS]
@@ -1022,6 +1077,7 @@ flat ((LibDeps t):xs) = flat t ++ flat xs
 str2dep :: String -> LibDepTree
 str2dep  str
     | str == "vfs"           = libvfs_deps_all
+    | str == "vfs_nonfs"     = libvfs_deps_nonfs
     | str == "posixcompat"   = libposixcompat_deps
     | str == "lwip"          = liblwip_deps
     | str == "netQmng"       = libnetQmng_deps
@@ -1045,6 +1101,10 @@ libDeps xs = [x | (LibDep x) <- (sortBy xcmp) . nub . flat $ map str2dep xs ]
                   , "net_queue_manager"
                   , "bfdmuxvm"
                   , "lwip"
+                  , "arranet"
+                  , "e1000n"
+                  , "e10k"
+                  , "e10k_vf"
                   , "contmng"
                   , "procon"
                   , "net_if_raw"
index 91dba77..1d53fad 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/bash
 
 ##########################################################################
-# Copyright (c) 2009, 2011, ETH Zurich.
+# Copyright (c) 2009, 2011, 2013, ETH Zurich.
 # All rights reserved.
 #
 # This file is distributed under the terms in the attached LICENSE file.
@@ -132,16 +132,20 @@ ghc -O --make -XDeriveDataTypeable \
     -i$SRCDIR/hake \
     -ihake \
     -rtsopts=all \
+    -threaded \
     -with-rtsopts="-K32m" \
     $SRCDIR/hake/Main.hs $LDFLAGS || exit 1
 
+    # -eventlog \
+
 if [ "$RUN_HAKE" == "No" ] ; then
     echo "Not running hake as per your request."
     exit
 fi
 
 echo "Running hake..."
-./hake/hake --output-filename Makefile --source-dir "$SRCDIR" || exit
+#./hake/hake --output-filename Makefile --source-dir "$SRCDIR" +RTS -s -N -K64M -A64M -ls -lf || exit
+./hake/hake --output-filename Makefile --source-dir "$SRCDIR" +RTS -N -K64M -A64M || exit
 cat <<EOF
 
 OK - Hake has bootstrapped.  You should now have a Makefile in this
index 3cbdc01..9966ced 100644 (file)
@@ -36,10 +36,7 @@ module /x86_64/sbin/pci auto
 module /x86_64/sbin/ahcid auto
 
 ## For networking
-## For qemu, enable rtl8029
 module /x86_64/sbin/rtl8029 auto
-
-## For real hardware, enable e1000n
 module /x86_64/sbin/e1000n auto
 
 ## Other services needed for networking
index 7120851..85a23f1 100644 (file)
@@ -80,6 +80,15 @@ MODULES_GENERIC= \
 # this should shrink as targets are ported and move into the generic list above
 MODULES_x86_64= \
        sbin/cpu \
+       sbin/e1000test \
+       sbin/e10ktest \
+       sbin/e10ktest_vf \
+       sbin/e10k_ctrl \
+       sbin/udpecho_arranet_e1000 \
+       sbin/udpecho_arranet_e10k \
+       sbin/udpecho_arranet_e10kvf \
+       sbin/udpecho_arranet_e1000_recvfrom \
+       sbin/udpecho_arranet_e10k_recvfrom \
        sbin/mdbtest_range_query \
        sbin/mdbtest_addr_zero \
        sbin/mdb_bench \
@@ -135,6 +144,9 @@ MODULES_x86_64= \
        $(BIN_RCCE_LU) \
        sbin/rcce_pingpong \
        sbin/serial \
+       sbin/arrakismon \
+       sbin/arrakis_hellotest \
+       sbin/socketpipetest \
        sbin/shared_mem_clock_bench \
        sbin/sif \
        sbin/slideshow \
@@ -171,6 +183,7 @@ MODULES_x86_64= \
        sbin/angler \
        sbin/sshd \
        sbin/lshw \
+       sbin/spin \
 
 # the following are broken in the newidc system
 MODULES_x86_64_broken= \
@@ -295,8 +308,12 @@ CLEAN_HD=
 DISK=hd.img
 AHCI=-device ahci,id=ahci -device ide-drive,drive=disk,bus=ahci.0 -drive id=disk,file=$(DISK),if=none
 
+MENU_LST=-kernel $(shell sed -rne 's,^kernel[ \t]*/([^ ]*).*,\1,p' menu.lst) \
+       -append '$(shell sed -rne 's,^kernel[ \t]*[^ ]*[ \t]*(.*),\1,p' menu.lst)' \
+       -initrd '$(shell sed -rne 's,^module(nounzip)?[ \t]*/(.*),\2,p' menu.lst | awk '{ if(NR == 1) printf($$0); else printf("," $$0) } END { printf("\n") }')'
+
 ifeq ($(ARCH),x86_64)
-        QEMU_CMD=qemu-system-x86_64 -no-kvm -smp 2 -m 1024 -net nic,model=ne2k_pci -net user $(AHCI) -fda $(SRCDIR)/tools/grub-qemu.img -tftp $(PWD) -nographic
+        QEMU_CMD=qemu-system-x86_64 -smp 2 -m 1024 -net nic,model=e1000 -net user $(AHCI) -nographic $(MENU_LST)
        GDB=x86_64-pc-linux-gdb
        CLEAN_HD=qemu-img create $(DISK) 10M
 else ifeq ($(ARCH),x86_32)
index a67bd93..f4ff932 100644 (file)
@@ -68,6 +68,8 @@
                "unixsock",
               "bcache",
               "replay",
+               "arrakis",
+               "e10k_vf",
               "empty"],
              arch <- allArchitectures
 ] ++
diff --git a/if/arrakis.if b/if/arrakis.if
new file mode 100644 (file)
index 0000000..bf7fc01
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+interface arrakis "Interface to arrakismon" {
+    rpc spawn_arrakis_domain(in string path, in char argvbuf[argvbytes],
+       in char envbuf[envbytes], out errval err, out domainid domain_id);
+};
similarity index 58%
copy from include/lwip/barrelfish.h
copy to if/e10k_vf.if
index 4bd0c7a..f774eb7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, ETH Zurich.
+ * Copyright (c) 2007-2011, 2013, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -7,12 +7,7 @@
  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
  */
 
-#ifndef BARRELFISH_LWIP_H
-#define BARRELFISH_LWIP_H
-
-#include <errors/errno.h>
-#include <lwip/err.h>
-
-errval_t lwip_err_to_errval(err_t e);
-
-#endif
+interface e10k_vf "e10k VF/PF interface" {
+         rpc get_mac_address(in uint8 vfn, out uint64 mac);
+         rpc init_done(in uint8 vfn);
+};
index 7c4c218..b8c14c8 100644 (file)
@@ -14,7 +14,6 @@
       | f <- [ 
    "cpiobin.h",
    "dlfcn.h",
-   "lwipopts.h",
    "multicast.h",
    "utime.h",
    "values.h",
index 5de715e..90c3d3e 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2013, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
index 1452f09..1bfa695 100644 (file)
@@ -53,7 +53,8 @@
           "r" (a8), "r" (a9), "r" (a11), "r" (a12), "r" (syscall_num) \
         : "r11", "rcx");
 #else /* DEBUG */
-# define BF_SYSCALL_ASM(arg11, label) \
+# ifndef ARRAKIS
+#  define BF_SYSCALL_ASM(arg11, label) \
     __asm volatile("pushq %%rbp             \n\t"   \
                    "movq %%rcx, %%rbp       \n\t"   \
                    "syscall                 \n\t"   \
           "+r" (a3), "+r" (a4), "+r" (a5), "+r" (syscall_num)  \
         : "r" (a6), "r" (a7), "r" (a8), "r" (a9), "r" (a12) \
         : "r11");
+#else
+#  define BF_SYSCALL_ASM(arg11, label) \
+    __asm volatile("pushq %%rbp             \n\t"   \
+                   "movq %%rcx, %%rbp       \n\t"   \
+                   "vmmcall                 \n\t"   \
+                   label                            \
+                   "popq %%rbp              \n\t"   \
+        : "+a" (a10_ret1), "+c" (arg11), "+d" (a2_ret2), "+r" (a1), \
+          "+r" (a3), "+r" (a4), "+r" (a5), "+r" (syscall_num)  \
+        : "r" (a6), "r" (a7), "r" (a8), "r" (a9), "r" (a12) \
+        : "r11");
+#endif
 #endif
 
 /* NB: We use a10_ret (in the rax register) as both input and output
index 4fffc24..b694000 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2010, ETH Zurich.
+ * Copyright (c) 2010, 2013, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
 /**
  * State of EFLAGS when executing a user-space program: Enable interrupts
  */
-#define USER_CS                         0x23
-#define USER_SS                         0x1b
+#ifndef ARRAKIS
+// Unprivileged mode
+#       define USER_CS                         0x23
+#       define USER_SS                         0x1b
+#else
+// Privileged mode
+#       define USER_CS                         0x8
+#       define USER_SS                         0x10
+#endif
+
 #define USER_EFLAGS                     0x202
 
 #endif // ARCH_X86_64_BARRELFISH_KPI_EFLAGS_H
index c160458..a26795d 100644 (file)
@@ -3,4 +3,9 @@
 
 #include <lwip/sockets.h>
 
+const char *
+inet_ntop(int af, const void * __restrict src, char * __restrict dst,
+          socklen_t size);
+int inet_pton(int af, const char * __restrict src, void * __restrict dst);
+
 #endif
diff --git a/include/arranet.h b/include/arranet.h
new file mode 100644 (file)
index 0000000..b7178fc
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich. 
+ * Attn: Systems Group.
+ */
+
+#ifndef ARRAKIS_ARRANET_H
+#define ARRAKIS_ARRANET_H
+
+struct packet {
+    struct packet       *next;
+    uint8_t             *payload;
+    lpaddr_t            pa;
+    size_t              len;
+    uint64_t            flags;
+    struct socket       *sock;
+    void                *opaque;
+};
+
+typedef void (*arranet_tx_done_fn)(void *opaque);
+
+int recvfrom_arranet(int sockfd, void **buf, struct packet **p,
+                     struct sockaddr *src_addr, socklen_t *addrlen);
+void arranet_recv_free(struct packet *p);
+int sendmsg_arranet(int sockfd, const struct msghdr *msg);
+void arranet_register_tx_done_callback(arranet_tx_done_fn callback);
+
+#define SENDMSG_WITH_COPY
+
+#endif
diff --git a/include/arranet_debug.h b/include/arranet_debug.h
new file mode 100644 (file)
index 0000000..c56f09f
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2014, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich. 
+ * Attn: Systems Group.
+ */
+
+#ifndef ARRANET_DEBUG_H
+#define ARRANET_DEBUG_H
+
+//#define DEBUG_LATENCIES
+
+//#include <lwip/udp.h>
+#include <arranet_impl.h>
+#include <barrelfish/sys_debug.h>
+
+#define POSIX_TRANSA    1000
+
+#define MIN(a,b)        ((a) < (b) ? (a) : (b))
+
+#define        timersub(a, b, result)                                                \
+  do {                                                                       \
+    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;                            \
+    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;                         \
+    if ((result)->tv_usec < 0) {                                             \
+      --(result)->tv_sec;                                                    \
+      (result)->tv_usec += 1000000;                                          \
+    }                                                                        \
+  } while (0)
+
+    /**
+     * Definition of the header structure for a request packet.
+     * See section 2
+     */
+    typedef union {
+        struct {
+            uint8_t magic;
+            uint8_t opcode;
+            uint16_t keylen;
+            uint8_t extlen;
+            uint8_t datatype;
+            uint16_t reserved;
+            uint32_t bodylen;
+            uint32_t opaque;
+            uint64_t cas;
+        } request;
+        uint8_t bytes[24];
+    } protocol_binary_request_header;
+
+    /**
+     * Definition of the header structure for a response packet.
+     * See section 2
+     */
+    typedef union {
+        struct {
+            uint8_t magic;
+            uint8_t opcode;
+            uint16_t keylen;
+            uint8_t extlen;
+            uint8_t datatype;
+            uint16_t status;
+            uint32_t bodylen;
+            uint32_t opaque;
+            uint64_t cas;
+        } response;
+        uint8_t bytes[24];
+    } protocol_binary_response_header;
+
+    /**
+     * Definition of a request-packet containing no extras
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header)];
+    } protocol_binary_request_no_extras;
+
+    /**
+     * Definition of a response-packet containing no extras
+     */
+    typedef union {
+        struct {
+            protocol_binary_response_header header;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_response_header)];
+    } protocol_binary_response_no_extras;
+
+typedef struct {
+  uint16_t req_id;
+  uint16_t seq_id;
+  uint16_t n_data;
+  uint16_t extras;
+} memcached_udp_header;
+
+#define UDP_HEADLEN sizeof(memcached_udp_header)
+
+static inline int get_time(void)
+{
+    uint64_t now = rdtsc();
+    static uint64_t tscperms = 0;
+
+    if(tscperms == 0) {
+        errval_t err = sys_debug_get_tsc_per_ms(&tscperms);
+        assert(err_is_ok(err));
+        assert(tscperms >= 100000);
+    }
+
+    uint64_t tod_us = now / (tscperms / 100000);
+
+    return tod_us;
+}
+
+#endif
diff --git a/include/arranet_impl.h b/include/arranet_impl.h
new file mode 100644 (file)
index 0000000..9c36946
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2014, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich. 
+ * Attn: Systems Group.
+ */
+
+#ifndef ARRANET_IMPL_H
+#define ARRANET_IMPL_H
+
+#ifndef ETHARP_HWADDR_LEN
+#define ETHARP_HWADDR_LEN     6
+#endif
+
+PACK_STRUCT_BEGIN
+struct eth_addr {
+  PACK_STRUCT_FIELD(u8_t addr[ETHARP_HWADDR_LEN]);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+PACK_STRUCT_BEGIN
+/** Ethernet header */
+struct eth_hdr {
+#if ETH_PAD_SIZE
+  PACK_STRUCT_FIELD(u8_t padding[ETH_PAD_SIZE]);
+#endif
+  PACK_STRUCT_FIELD(struct eth_addr dest);
+  PACK_STRUCT_FIELD(struct eth_addr src);
+  PACK_STRUCT_FIELD(u16_t type);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+#define SIZEOF_ETH_HDR (14 + ETH_PAD_SIZE)
+
+PACK_STRUCT_BEGIN
+/** the ARP message, see RFC 826 ("Packet format") */
+struct etharp_hdr {
+  PACK_STRUCT_FIELD(u16_t hwtype);
+  PACK_STRUCT_FIELD(u16_t proto);
+  PACK_STRUCT_FIELD(u8_t  hwlen);
+  PACK_STRUCT_FIELD(u8_t  protolen);
+  PACK_STRUCT_FIELD(u16_t opcode);
+  PACK_STRUCT_FIELD(struct eth_addr shwaddr);
+  PACK_STRUCT_FIELD(struct ip_addr2 sipaddr);
+  PACK_STRUCT_FIELD(struct eth_addr dhwaddr);
+  PACK_STRUCT_FIELD(struct ip_addr2 dipaddr);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+#define SIZEOF_ETHARP_HDR 28
+#define SIZEOF_ETHARP_PACKET (SIZEOF_ETH_HDR + SIZEOF_ETHARP_HDR)
+
+#define ETHTYPE_ARP       0x0806U
+#define ETHTYPE_IP        0x0800U
+#define ETHTYPE_VLAN      0x8100U
+#define ETHTYPE_PPPOEDISC 0x8863U  /* PPP Over Ethernet Discovery Stage */
+#define ETHTYPE_PPPOE     0x8864U  /* PPP Over Ethernet Session Stage */
+
+#define ETH_PAD_SIZE          0
+
+/** ARP message types (opcodes) */
+#define ARP_REQUEST 1
+#define ARP_REPLY   2
+
+PACK_STRUCT_BEGIN
+struct ip_hdr {
+  /* version / header length */
+  PACK_STRUCT_FIELD(u8_t _v_hl);
+  /* type of service */
+  PACK_STRUCT_FIELD(u8_t _tos);
+  /* total length */
+  PACK_STRUCT_FIELD(u16_t _len);
+  /* identification */
+  PACK_STRUCT_FIELD(u16_t _id);
+  /* fragment offset field */
+  PACK_STRUCT_FIELD(u16_t _offset);
+#define IP_RF 0x8000U        /* reserved fragment flag */
+#define IP_DF 0x4000U        /* dont fragment flag */
+#define IP_MF 0x2000U        /* more fragments flag */
+#define IP_OFFMASK 0x1fffU   /* mask for fragmenting bits */
+  /* time to live */
+  PACK_STRUCT_FIELD(u8_t _ttl);
+  /* protocol*/
+  PACK_STRUCT_FIELD(u8_t _proto);
+  /* checksum */
+  PACK_STRUCT_FIELD(u16_t _chksum);
+  /* source and destination IP addresses */
+  PACK_STRUCT_FIELD(ip_addr_p_t src);
+  PACK_STRUCT_FIELD(ip_addr_p_t dest); 
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+#define IPH_V(hdr)  ((hdr)->_v_hl >> 4)
+#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f)
+#define IPH_TOS(hdr) ((hdr)->_tos)
+#define IPH_LEN(hdr) ((hdr)->_len)
+#define IPH_ID(hdr) ((hdr)->_id)
+#define IPH_OFFSET(hdr) ((hdr)->_offset)
+#define IPH_TTL(hdr) ((hdr)->_ttl)
+#define IPH_PROTO(hdr) ((hdr)->_proto)
+#define IPH_CHKSUM(hdr) ((hdr)->_chksum)
+
+#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (((v) << 4) | (hl))
+#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos)
+#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len)
+#define IPH_ID_SET(hdr, id) (hdr)->_id = (id)
+#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off)
+#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl)
+#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto)
+#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum)
+
+#define IP_HLEN 20
+
+#define IP_PROTO_ICMP    1
+#define IP_PROTO_IGMP    2
+#define IP_PROTO_UDP     17
+#define IP_PROTO_UDPLITE 136
+#define IP_PROTO_TCP     6
+
+PACK_STRUCT_BEGIN
+struct udp_hdr {
+  PACK_STRUCT_FIELD(u16_t src);
+  PACK_STRUCT_FIELD(u16_t dest);  /* src/dest UDP ports */
+  PACK_STRUCT_FIELD(u16_t len);
+  PACK_STRUCT_FIELD(u16_t chksum);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+PACK_STRUCT_BEGIN
+struct tcp_hdr {
+  PACK_STRUCT_FIELD(u16_t src);
+  PACK_STRUCT_FIELD(u16_t dest);
+  PACK_STRUCT_FIELD(u32_t seqno);
+  PACK_STRUCT_FIELD(u32_t ackno);
+  PACK_STRUCT_FIELD(u16_t _hdrlen_rsvd_flags);
+  PACK_STRUCT_FIELD(u16_t wnd);
+  PACK_STRUCT_FIELD(u16_t chksum);
+  PACK_STRUCT_FIELD(u16_t urgp);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+
+#define TCP_FIN 0x01U
+#define TCP_SYN 0x02U
+#define TCP_RST 0x04U
+#define TCP_PSH 0x08U
+#define TCP_ACK 0x10U
+#define TCP_URG 0x20U
+#define TCP_ECE 0x40U
+#define TCP_CWR 0x80U
+
+#define TCP_FLAGS 0x3fU
+
+/* Length of the TCP header, excluding options. */
+#define TCP_HLEN 20
+
+#define TCPH_HDRLEN(phdr) (ntohs((phdr)->_hdrlen_rsvd_flags) >> 12)
+#define TCPH_FLAGS(phdr)  (ntohs((phdr)->_hdrlen_rsvd_flags) & TCP_FLAGS)
+
+#define TCPH_HDRLEN_SET(phdr, len) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | TCPH_FLAGS(phdr))
+#define TCPH_FLAGS_SET(phdr, flags) (phdr)->_hdrlen_rsvd_flags = (((phdr)->_hdrlen_rsvd_flags & PP_HTONS((u16_t)(~(u16_t)(TCP_FLAGS)))) | htons(flags))
+#define TCPH_HDRLEN_FLAGS_SET(phdr, len, flags) (phdr)->_hdrlen_rsvd_flags = htons(((len) << 12) | (flags))
+
+#define TCPH_SET_FLAG(phdr, flags ) (phdr)->_hdrlen_rsvd_flags = ((phdr)->_hdrlen_rsvd_flags | htons(flags))
+#define TCPH_UNSET_FLAG(phdr, flags) (phdr)->_hdrlen_rsvd_flags = htons(ntohs((phdr)->_hdrlen_rsvd_flags) | (TCPH_FLAGS(phdr) & ~(flags)) )
+
+#define TCP_TCPLEN(seg) ((seg)->len + ((TCPH_FLAGS((seg)->tcphdr) & (TCP_FIN | TCP_SYN)) != 0))
+
+/** This returns a TCP header option for MSS in an u32_t */
+#define TCP_BUILD_MSS_OPTION(mss) htonl(0x02040000 | ((mss) & 0xFFFF))
+
+void lwip_mutex_lock(void);
+void lwip_mutex_unlock(void);
+
+// XXX: These assume a little-endian system!
+/* These macros should be calculated by the preprocessor and are used
+   with compile-time constants only (so that there is no little-endian
+   overhead at runtime). */
+#define PP_HTONS(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
+#define PP_NTOHS(x) PP_HTONS(x)
+#define PP_HTONL(x) ((((x) & 0xff) << 24) | \
+                     (((x) & 0xff00) << 8) | \
+                     (((x) & 0xff0000UL) >> 8) | \
+                     (((x) & 0xff000000UL) >> 24))
+#define PP_NTOHL(x) PP_HTONL(x)
+
+#define lwip_htons(x) LWIP_PLATFORM_HTONS(x)
+#define lwip_ntohs(x) LWIP_PLATFORM_HTONS(x)
+#define lwip_htonl(x) LWIP_PLATFORM_HTONL(x)
+#define lwip_ntohl(x) LWIP_PLATFORM_HTONL(x)
+
+#define ip_addr_isbroadcast(ipaddr, netif) ip4_addr_isbroadcast((ipaddr)->addr, (netif))
+u8_t ip4_addr_isbroadcast(u32_t addr, const struct netif *netif);
+
+#define ip_addr_netmask_valid(netmask) ip4_addr_netmask_valid((netmask)->addr)
+u8_t ip4_addr_netmask_valid(u32_t netmask);
+
+u32_t ipaddr_addr(const char *cp);
+int ipaddr_aton(const char *cp, ip_addr_t *addr);
+/** returns ptr to static buffer; not reentrant! */
+char *ipaddr_ntoa(const ip_addr_t *addr);
+char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen);
+
+#endif
index f216b37..adc7007 100644 (file)
@@ -41,11 +41,21 @@ struct captrack {
 };
 #endif // 0 DELETEME
 
+#define MAX_V2P_MAPPINGS        64
+
+struct v2pmap {
+    genvaddr_t  va;
+    genpaddr_t  pa;
+    size_t      size;
+};
+
 struct morecore_state {
     struct thread_mutex mutex;
     Header header_base;
     Header *header_freep;
     struct vspace_mmu_aware mmu_state;
+    struct v2pmap v2p_mappings[MAX_V2P_MAPPINGS];
+    int v2p_entries;
 #if 0 // DELETEME
     struct captrack track_frames[MAX_TRACK_FRAMES];
 #endif // 0 DELETEME
@@ -88,6 +98,7 @@ struct spawn_state;
 struct monitor_binding;
 struct mem_rpc_client;
 struct spawn_rpc_client;
+struct arrakis_rpc_client;
 
 struct core_state_generic {
     struct waitset default_waitset;
@@ -98,6 +109,7 @@ struct core_state_generic {
     struct ram_alloc_state ram_alloc_state;
     struct octopus_rpc_client *octopus_rpc_client;
     struct spawn_rpc_client *spawn_rpc_clients[MAX_CPUS];
+    struct arrakis_rpc_client *arrakis_rpc_clients[MAX_CPUS];
     struct terminal_state *terminal_state;
     struct domain_state *domain_state;
     struct spawn_state *spawn_state;
index 630622d..43b9356 100644 (file)
@@ -39,7 +39,7 @@ void debug_dump(arch_registers_state_t *state);
 void debug_call_chain(arch_registers_state_t *state);
 void debug_return_addresses(void);
 void debug_dump_mem_around_addr(lvaddr_t addr);
-void debug_dump_mem(lvaddr_t base, lvaddr_t limit);
+void debug_dump_mem(lvaddr_t base, lvaddr_t limit, lvaddr_t point);
 
 void debug_err(const char *file, const char *func, int line,
                errval_t err, const char *msg, ...);
index 9a512ff..ffa4e21 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2009, 2011, ETH Zurich.
+ * Copyright (c) 2009, 2011, 2013, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -33,6 +33,7 @@ errval_t deferred_event_register(struct deferred_event *event,
                                  struct waitset *ws, delayus_t delay,
                                  struct event_closure closure);
 errval_t deferred_event_cancel(struct deferred_event *event);
+errval_t barrelfish_usleep(delayus_t delay);
 
 struct periodic_event {
     struct deferred_event de;
index eb705be..68ff2d3 100644 (file)
@@ -28,6 +28,7 @@ struct monitor_binding;
 struct monitor_blocking_rpc_client;
 struct waitset;
 struct spawn_rpc_client;
+struct arrakis_rpc_client;
 
 struct waitset *get_default_waitset(void);
 void disp_set_core_id(coreid_t core_id);
@@ -48,7 +49,9 @@ struct ram_alloc_state *get_ram_alloc_state(void);
 void set_octopus_rpc_client(struct octopus_rpc_client *st);
 struct octopus_rpc_client *get_octopus_rpc_client(void);
 void set_spawn_rpc_client(coreid_t core, struct spawn_rpc_client *st);
+void set_arrakis_rpc_client(coreid_t core, struct arrakis_rpc_client *st);
 struct spawn_rpc_client *get_spawn_rpc_client(coreid_t core);
+struct arrakis_rpc_client *get_arrakis_rpc_client(coreid_t core);
 struct terminal_state *get_terminal_state(void);
 void set_terminal_state(struct terminal_state *st);
 struct domain_state *get_domain_state(void);
index c103a59..a999522 100644 (file)
@@ -21,6 +21,8 @@ errval_t inthandler_setup(interrupt_handler_fn handler, void *handler_arg,
 errval_t inthandler_setup_arm(interrupt_handler_fn handler, void *handler_arg,
         uint32_t irq);
 
+extern struct waitset *barrelfish_interrupt_waitset;
+
 __END_DECLS
 
 #endif
index fac10c5..80f40b0 100644 (file)
@@ -96,6 +96,7 @@ struct memobj_frame_list {
     genpaddr_t offset;              ///< Offset into the frame
     struct capref frame;            ///< Capability of the frame
     size_t size;                    ///< Size of the frame
+    genpaddr_t pa;                  ///< XXX: physical address of frame
     struct memobj_frame_list *next;
 };
 
index 48a2f7c..5fc7671 100644 (file)
@@ -35,6 +35,11 @@ errval_t spawn_program_with_caps(coreid_t coreid, const char *path,
                                  struct capref inheritcn_cap,
                                  struct capref argcn_cap, spawn_flags_t flags,
                                  domainid_t *ret_domainid);
+errval_t spawn_arrakis_program(coreid_t coreid, const char *path,
+                                 char *const argv[], char *const envp[],
+                                 struct capref inheritcn_cap,
+                                 struct capref argcn_cap, spawn_flags_t flags,
+                                 domainid_t *ret_domainid);
 errval_t spawn_program(coreid_t coreid, const char *path,
                        char *const argv[], char *const envp[],
                        spawn_flags_t flags, domainid_t *ret_domainid);
index 16c2482..94fc23d 100644 (file)
@@ -32,6 +32,7 @@ errval_t sys_debug_context_counter_reset(void);
 errval_t sys_debug_context_counter_read(uint64_t *ret);
 errval_t sys_debug_timeslice_counter_read(uint64_t *ret);
 errval_t sys_debug_get_tsc_per_ms(uint64_t *ret);
+errval_t sys_debug_get_apic_id(uint8_t *ret);
 errval_t sys_debug_get_apic_timer(uint32_t *ret);
 errval_t sys_debug_print_context_counter(void);
 errval_t sys_debug_print_timeslice(void);
index 2050cd8..d57e4b0 100644 (file)
@@ -66,6 +66,12 @@ void thread_sem_post(struct thread_sem *sem);
 void thread_set_tls(void *);
 void *thread_get_tls(void);
 
+void thread_set_tls_key(int, void *);
+void *thread_get_tls_key(int);
+
+uintptr_t thread_id(void);
+void thread_set_id(uintptr_t id);
+
 __END_DECLS
 
 #endif
index 8c60a42..3d04d69 100644 (file)
@@ -38,6 +38,9 @@ errval_t waitset_chan_register(struct waitset *ws, struct waitset_chanstate *cha
                                struct event_closure closure);
 void waitset_chan_migrate(struct waitset_chanstate *chan,
                           struct waitset *new_ws);
+errval_t waitset_chan_register_polled(struct waitset *ws,
+                                      struct waitset_chanstate *chan,
+                                      struct event_closure closure);
 
 __END_DECLS
 
index 13809fd..00a39e7 100644 (file)
@@ -29,7 +29,8 @@ enum debug_message {
     DEBUG_GET_TSC_PER_MS,
     DEBUG_GET_APIC_TIMER,
     DEBUG_GET_APIC_TICKS_PER_SEC,
-    DEBUG_FEIGN_FRAME_CAP
+    DEBUG_FEIGN_FRAME_CAP,
+    DEBUG_GET_APIC_ID
 };
 
 #endif //BARRELFISH_KPI_SYS_DEBUG_H
index 8eb0065..09c8854 100644 (file)
@@ -76,7 +76,12 @@ struct netbench_details {
     char name[NAME_SIZE];
 };
 
+// Utility functions
+uint64_t my_avg(uint64_t sum, uint64_t n);
 
+#ifndef LIBRARY
+
+float in_seconds(uint64_t cycles);
 void netbench_reset(struct netbench_details *nbp);
 struct netbench_details *netbench_alloc(char *name, uint32_t total_events);
 
@@ -91,9 +96,22 @@ void netbench_print_event_stat(struct netbench_details *nbp,
         uint8_t event_type, char *event_name, int type);
 void netbench_print_all_stats(struct netbench_details *nbp);
 
-// Utility functions
-uint64_t my_avg(uint64_t sum, uint64_t n);
-float in_seconds(uint64_t cycles);
+#else
+
+#define netbench_reset(a)
+#define netbench_alloc(a, b)
+#define netbench_record_event(a, b, c)
+#define netbench_record_event_no_ts(a, b)
+#define netbench_record_event_simple(a, b, c)   while(0) { (void)c; }
+#define netbench_print_event_stat(a, b, c, d)
+#define netbench_print_all_stats(a)
+
+static inline float in_seconds(uint64_t cycles)
+{
+    return cycles;
+}
+
+#endif
 
 __END_DECLS
 
index 1c02807..c662def 100644 (file)
@@ -88,7 +88,9 @@ typedef       __pid_t         pid_t;
 #define O_NOCTTY   00400
 #define O_TRUNC    01000       
 #define O_APPEND   02000
+#ifndef O_NONBLOCK
 #define O_NONBLOCK 04000
+#endif
 #define O_SYNC    010000
 #define O_FSYNC          O_SYNC
 #define O_ASYNC          020000
@@ -151,8 +153,10 @@ typedef    __pid_t         pid_t;
 #define        FFSYNC          O_FSYNC         /* kernel */
 #define        FNONBLOCK       O_NONBLOCK      /* kernel */
 #define        FNDELAY         O_NONBLOCK      /* compat */
+#ifndef O_NDELAY
 #define        O_NDELAY        O_NONBLOCK      /* compat */
 #endif
+#endif
 
 /*
  * We are out of bits in f_flag (which is a short).  However,
index fb09777..fd96534 100644 (file)
@@ -29,8 +29,8 @@
  * $FreeBSD: src/sys/sys/limits.h,v 1.10 2005/12/02 07:45:28 davidxu Exp $
  */
 
-#ifndef _SYS_LIMITS_H_
-#define        _SYS_LIMITS_H_
+#ifndef _LIMITS_H_
+#define        _LIMITS_H_
 
 #include <sys/cdefs.h>
 #include <machine/_limits.h>
 #undef ULONG_LONG_MAX
 #define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1ULL)
 
-// Barrelfish addition
-// I'm not sure where this belongs, but limits.h must provide it -AB
-#define PATH_MAX 1330
+#if __POSIX_VISIBLE
+#ifdef CONFIG_NEWLIB
+#include <sys/syslimits.h>
+#endif
+#endif
 
 #endif /* !_SYS_LIMITS_H_ */
index f71e30e..7f30116 100644 (file)
 __BEGIN_DECLS
 
 /*
+ * Error return codes from getaddrinfo()
+ */ 
+#define EAI_BADFLAGS     3      /* invalid value for ai_flags */
+#define EAI_SOCKTYPE    10      /* ai_socktype not supported */
+#define EAI_SYSTEM      11      /* system error returned in errno */
+#define EAI_BADHINTS    12      /* invalid value for hints */
+#define EAI_PROTOCOL    13      /* resolved protocol is unknown */
+#define EAI_OVERFLOW    14      /* argument buffer overflow */
+
+/*
  * Flag values for getaddrinfo()
  */
 #define AI_PASSIVE  0x00000001 /* get address to use bind() */
@@ -92,6 +102,24 @@ __BEGIN_DECLS
 /* special recommended flags for getipnodebyname */
 #define AI_DEFAULT  (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
 
+/*
+ * Constants for getnameinfo()
+ */
+#define NI_MAXHOST      1025
+#define NI_MAXSERV      32
+
+/*
+ * Flag values for getnameinfo()
+ */
+#define NI_NOFQDN       0x00000001
+#define NI_NUMERICHOST  0x00000002
+#define NI_NAMEREQD     0x00000004
+#define NI_NUMERICSERV  0x00000008
+#define NI_DGRAM        0x00000010
+#if 0 /* obsolete */
+#define NI_WITHSCOPEID  0x00000020
+#endif
+
 struct hostent *gethostbyname(const char *name);
 struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type);
 int getaddrinfo(const char *nodename,
index b564e5a..7b3864a 100644 (file)
 typedef int_least16_t in_port_t;
 typedef int_least32_t in_addr_t;
 
+#define IPPROTO_IPV6            41              /* IP6 header */
+#define INET_ADDRSTRLEN         16
+
 /*
  * Ports < IPPORT_RESERVED are reserved for
  * privileged processes (e.g. root).         (IP_PORTRANGE_LOW)
  */
 #define        IPPORT_RESERVED         1024
 
+/* INET6 stuff */
+#if __POSIX_VISIBLE >= 200112
+#define __KAME_NETINET_IN_H_INCLUDED_
+#include <netinet6/in6.h>
+#undef __KAME_NETINET_IN_H_INCLUDED_
+#endif
+
 #endif //_NETINET_IN_H_
diff --git a/include/netinet6/in6.h b/include/netinet6/in6.h
new file mode 100644 (file)
index 0000000..f0cf4f4
--- /dev/null
@@ -0,0 +1,716 @@
+/*-
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
+ *
+ *     $KAME: in6.h,v 1.89 2001/05/27 13:28:35 itojun Exp $
+ */
+
+/*-
+ * Copyright (c) 1982, 1986, 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)in.h        8.3 (Berkeley) 1/3/94
+ * $FreeBSD$
+ */
+
+#ifndef __KAME_NETINET_IN_H_INCLUDED_
+#error "do not include netinet6/in6.h directly, include netinet/in.h.  see RFC2553"
+#endif
+
+#ifndef _NETINET6_IN6_H_
+#define _NETINET6_IN6_H_
+
+/*
+ * Identification of the network protocol stack
+ * for *BSD-current/release: http://www.kame.net/dev/cvsweb.cgi/kame/COVERAGE
+ * has the table of implementation/integration differences.
+ */
+#define __KAME__
+#define __KAME_VERSION         "FreeBSD"
+
+/*
+ * IPv6 port allocation rules should mirror the IPv4 rules and are controlled
+ * by the net.inet.ip.portrange sysctl tree. The following defines exist
+ * for compatibility with userland applications that need them.
+ */
+#if __BSD_VISIBLE
+#define        IPV6PORT_RESERVED       1024
+#define        IPV6PORT_ANONMIN        49152
+#define        IPV6PORT_ANONMAX        65535
+#define        IPV6PORT_RESERVEDMIN    600
+#define        IPV6PORT_RESERVEDMAX    (IPV6PORT_RESERVED-1)
+#endif
+
+/*
+ * IPv6 address
+ */
+struct in6_addr {
+       union {
+               uint8_t         __u6_addr8[16];
+               uint16_t        __u6_addr16[8];
+               uint32_t        __u6_addr32[4];
+       } __u6_addr;                    /* 128-bit IP6 address */
+};
+
+#define s6_addr   __u6_addr.__u6_addr8
+#ifdef _KERNEL /* XXX nonstandard */
+#define s6_addr8  __u6_addr.__u6_addr8
+#define s6_addr16 __u6_addr.__u6_addr16
+#define s6_addr32 __u6_addr.__u6_addr32
+#endif
+
+#define INET6_ADDRSTRLEN       46
+
+/*
+ * XXX missing POSIX.1-2001 macro IPPROTO_IPV6.
+ */
+
+/*
+ * Socket address for IPv6
+ */
+#if __BSD_VISIBLE
+#define SIN6_LEN
+#endif
+
+struct sockaddr_in6 {
+       uint8_t         sin6_len;       /* length of this struct */
+       sa_family_t     sin6_family;    /* AF_INET6 */
+       in_port_t       sin6_port;      /* Transport layer port # */
+       uint32_t        sin6_flowinfo;  /* IP6 flow information */
+       struct in6_addr sin6_addr;      /* IP6 address */
+       uint32_t        sin6_scope_id;  /* scope zone index */
+};
+
+/*
+ * Local definition for masks
+ */
+#ifdef _KERNEL /* XXX nonstandard */
+#define IN6MASK0       {{{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}}
+#define IN6MASK32      {{{ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, \
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
+#define IN6MASK64      {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
+#define IN6MASK96      {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+                           0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }}}
+#define IN6MASK128     {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, \
+                           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}
+#endif
+
+#ifdef _KERNEL
+extern const struct sockaddr_in6 sa6_any;
+
+extern const struct in6_addr in6mask0;
+extern const struct in6_addr in6mask32;
+extern const struct in6_addr in6mask64;
+extern const struct in6_addr in6mask96;
+extern const struct in6_addr in6mask128;
+#endif /* _KERNEL */
+
+/*
+ * Macros started with IPV6_ADDR is KAME local
+ */
+#ifdef _KERNEL /* XXX nonstandard */
+#if _BYTE_ORDER == _BIG_ENDIAN
+#define IPV6_ADDR_INT32_ONE    1
+#define IPV6_ADDR_INT32_TWO    2
+#define IPV6_ADDR_INT32_MNL    0xff010000
+#define IPV6_ADDR_INT32_MLL    0xff020000
+#define IPV6_ADDR_INT32_SMP    0x0000ffff
+#define IPV6_ADDR_INT16_ULL    0xfe80
+#define IPV6_ADDR_INT16_USL    0xfec0
+#define IPV6_ADDR_INT16_MLL    0xff02
+#elif _BYTE_ORDER == _LITTLE_ENDIAN
+#define IPV6_ADDR_INT32_ONE    0x01000000
+#define IPV6_ADDR_INT32_TWO    0x02000000
+#define IPV6_ADDR_INT32_MNL    0x000001ff
+#define IPV6_ADDR_INT32_MLL    0x000002ff
+#define IPV6_ADDR_INT32_SMP    0xffff0000
+#define IPV6_ADDR_INT16_ULL    0x80fe
+#define IPV6_ADDR_INT16_USL    0xc0fe
+#define IPV6_ADDR_INT16_MLL    0x02ff
+#endif
+#endif
+
+/*
+ * Definition of some useful macros to handle IP6 addresses
+ */
+#if __BSD_VISIBLE
+#define IN6ADDR_ANY_INIT \
+       {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}
+#define IN6ADDR_LOOPBACK_INIT \
+       {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
+#define IN6ADDR_NODELOCAL_ALLNODES_INIT \
+       {{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
+#define IN6ADDR_INTFACELOCAL_ALLNODES_INIT \
+       {{{ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
+#define IN6ADDR_LINKLOCAL_ALLNODES_INIT \
+       {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}
+#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \
+       {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}}
+#define IN6ADDR_LINKLOCAL_ALLV2ROUTERS_INIT \
+       {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16 }}}
+#endif
+
+extern const struct in6_addr in6addr_any;
+extern const struct in6_addr in6addr_loopback;
+#if __BSD_VISIBLE
+extern const struct in6_addr in6addr_nodelocal_allnodes;
+extern const struct in6_addr in6addr_linklocal_allnodes;
+extern const struct in6_addr in6addr_linklocal_allrouters;
+extern const struct in6_addr in6addr_linklocal_allv2routers;
+#endif
+
+/*
+ * Equality
+ * NOTE: Some of kernel programming environment (for example, openbsd/sparc)
+ * does not supply memcmp().  For userland memcmp() is preferred as it is
+ * in ANSI standard.
+ */
+#ifdef _KERNEL
+#define IN6_ARE_ADDR_EQUAL(a, b)                       \
+    (bcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0)
+#else
+#if __BSD_VISIBLE
+#define IN6_ARE_ADDR_EQUAL(a, b)                       \
+    (memcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0)
+#endif
+#endif
+
+/*
+ * Unspecified
+ */
+#define IN6_IS_ADDR_UNSPECIFIED(a)     \
+       ((a)->__u6_addr.__u6_addr32[0] == 0 &&  \
+        (a)->__u6_addr.__u6_addr32[1] == 0 &&  \
+        (a)->__u6_addr.__u6_addr32[2] == 0 &&  \
+        (a)->__u6_addr.__u6_addr32[3] == 0)
+
+/*
+ * Loopback
+ */
+#define IN6_IS_ADDR_LOOPBACK(a)                \
+       ((a)->__u6_addr.__u6_addr32[0] == 0 &&  \
+        (a)->__u6_addr.__u6_addr32[1] == 0 &&  \
+        (a)->__u6_addr.__u6_addr32[2] == 0 &&  \
+        (a)->__u6_addr.__u6_addr32[3] == ntohl(1))
+
+/*
+ * IPv4 compatible
+ */
+#define IN6_IS_ADDR_V4COMPAT(a)                \
+       ((a)->__u6_addr.__u6_addr32[0] == 0 &&  \
+        (a)->__u6_addr.__u6_addr32[1] == 0 &&  \
+        (a)->__u6_addr.__u6_addr32[2] == 0 &&  \
+        (a)->__u6_addr.__u6_addr32[3] != 0 &&  \
+        (a)->__u6_addr.__u6_addr32[3] != ntohl(1))
+
+/*
+ * Mapped
+ */
+#define IN6_IS_ADDR_V4MAPPED(a)                      \
+       ((a)->__u6_addr.__u6_addr32[0] == 0 &&  \
+        (a)->__u6_addr.__u6_addr32[1] == 0 &&  \
+        (a)->__u6_addr.__u6_addr32[2] == ntohl(0x0000ffff))
+
+/*
+ * KAME Scope Values
+ */
+
+#ifdef _KERNEL /* XXX nonstandard */
+#define IPV6_ADDR_SCOPE_NODELOCAL      0x01
+#define IPV6_ADDR_SCOPE_INTFACELOCAL   0x01
+#define IPV6_ADDR_SCOPE_LINKLOCAL      0x02
+#define IPV6_ADDR_SCOPE_SITELOCAL      0x05
+#define IPV6_ADDR_SCOPE_ORGLOCAL       0x08    /* just used in this file */
+#define IPV6_ADDR_SCOPE_GLOBAL         0x0e
+#else
+#define __IPV6_ADDR_SCOPE_NODELOCAL    0x01
+#define __IPV6_ADDR_SCOPE_INTFACELOCAL 0x01
+#define __IPV6_ADDR_SCOPE_LINKLOCAL    0x02
+#define __IPV6_ADDR_SCOPE_SITELOCAL    0x05
+#define __IPV6_ADDR_SCOPE_ORGLOCAL     0x08    /* just used in this file */
+#define __IPV6_ADDR_SCOPE_GLOBAL       0x0e
+#endif
+
+/*
+ * Unicast Scope
+ * Note that we must check topmost 10 bits only, not 16 bits (see RFC2373).
+ */
+#define IN6_IS_ADDR_LINKLOCAL(a)       \
+       (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80))
+#define IN6_IS_ADDR_SITELOCAL(a)       \
+       (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
+
+/*
+ * Multicast
+ */
+#define IN6_IS_ADDR_MULTICAST(a)       ((a)->s6_addr[0] == 0xff)
+
+#ifdef _KERNEL /* XXX nonstandard */
+#define IPV6_ADDR_MC_SCOPE(a)          ((a)->s6_addr[1] & 0x0f)
+#else
+#define __IPV6_ADDR_MC_SCOPE(a)                ((a)->s6_addr[1] & 0x0f)
+#endif
+
+/*
+ * Multicast Scope
+ */
+#ifdef _KERNEL /* refers nonstandard items */
+#define IN6_IS_ADDR_MC_NODELOCAL(a)    \
+       (IN6_IS_ADDR_MULTICAST(a) &&    \
+        (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_NODELOCAL))
+#define IN6_IS_ADDR_MC_INTFACELOCAL(a) \
+       (IN6_IS_ADDR_MULTICAST(a) &&    \
+        (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_INTFACELOCAL))
+#define IN6_IS_ADDR_MC_LINKLOCAL(a)    \
+       (IN6_IS_ADDR_MULTICAST(a) &&    \
+        (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_LINKLOCAL))
+#define IN6_IS_ADDR_MC_SITELOCAL(a)    \
+       (IN6_IS_ADDR_MULTICAST(a) &&    \
+        (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_SITELOCAL))
+#define IN6_IS_ADDR_MC_ORGLOCAL(a)     \
+       (IN6_IS_ADDR_MULTICAST(a) &&    \
+        (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_ORGLOCAL))
+#define IN6_IS_ADDR_MC_GLOBAL(a)       \
+       (IN6_IS_ADDR_MULTICAST(a) &&    \
+        (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_GLOBAL))
+#else
+#define IN6_IS_ADDR_MC_NODELOCAL(a)    \
+       (IN6_IS_ADDR_MULTICAST(a) &&    \
+        (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_NODELOCAL))
+#define IN6_IS_ADDR_MC_LINKLOCAL(a)    \
+       (IN6_IS_ADDR_MULTICAST(a) &&    \
+        (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_LINKLOCAL))
+#define IN6_IS_ADDR_MC_SITELOCAL(a)    \
+       (IN6_IS_ADDR_MULTICAST(a) &&    \
+        (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_SITELOCAL))
+#define IN6_IS_ADDR_MC_ORGLOCAL(a)     \
+       (IN6_IS_ADDR_MULTICAST(a) &&    \
+        (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_ORGLOCAL))
+#define IN6_IS_ADDR_MC_GLOBAL(a)       \
+       (IN6_IS_ADDR_MULTICAST(a) &&    \
+        (__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_GLOBAL))
+#endif
+
+#ifdef _KERNEL /* nonstandard */
+/*
+ * KAME Scope
+ */
+#define IN6_IS_SCOPE_LINKLOCAL(a)      \
+       ((IN6_IS_ADDR_LINKLOCAL(a)) ||  \
+        (IN6_IS_ADDR_MC_LINKLOCAL(a)))
+#define        IN6_IS_SCOPE_EMBED(a)                   \
+       ((IN6_IS_ADDR_LINKLOCAL(a)) ||          \
+        (IN6_IS_ADDR_MC_LINKLOCAL(a)) ||       \
+        (IN6_IS_ADDR_MC_INTFACELOCAL(a)))
+
+#define IFA6_IS_DEPRECATED(a) \
+       ((a)->ia6_lifetime.ia6t_pltime != ND6_INFINITE_LIFETIME && \
+        (u_int32_t)((time_second - (a)->ia6_updatetime)) > \
+        (a)->ia6_lifetime.ia6t_pltime)
+#define IFA6_IS_INVALID(a) \
+       ((a)->ia6_lifetime.ia6t_vltime != ND6_INFINITE_LIFETIME && \
+        (u_int32_t)((time_second - (a)->ia6_updatetime)) > \
+        (a)->ia6_lifetime.ia6t_vltime)
+#endif /* _KERNEL */
+
+/*
+ * IP6 route structure
+ */
+#if __BSD_VISIBLE
+struct route_in6 {
+       struct  rtentry *ro_rt;
+       struct  llentry *ro_lle;
+       struct  in6_addr *ro_ia6;
+       int             ro_flags;
+       struct  sockaddr_in6 ro_dst;
+};
+#endif
+
+/*
+ * Options for use with [gs]etsockopt at the IPV6 level.
+ * First word of comment is data type; bool is stored in int.
+ */
+/* no hdrincl */
+#if 0 /* the followings are relic in IPv4 and hence are disabled */
+#define IPV6_OPTIONS           1  /* buf/ip6_opts; set/get IP6 options */
+#define IPV6_RECVOPTS          5  /* bool; receive all IP6 opts w/dgram */
+#define IPV6_RECVRETOPTS       6  /* bool; receive IP6 opts for response */
+#define IPV6_RECVDSTADDR       7  /* bool; receive IP6 dst addr w/dgram */
+#define IPV6_RETOPTS           8  /* ip6_opts; set/get IP6 options */
+#endif
+#define IPV6_SOCKOPT_RESERVED1 3  /* reserved for future use */
+#define IPV6_UNICAST_HOPS      4  /* int; IP6 hops */
+#define IPV6_MULTICAST_IF      9  /* u_int; set/get IP6 multicast i/f  */
+#define IPV6_MULTICAST_HOPS    10 /* int; set/get IP6 multicast hops */
+#define IPV6_MULTICAST_LOOP    11 /* u_int; set/get IP6 multicast loopback */
+#define IPV6_JOIN_GROUP                12 /* ipv6_mreq; join a group membership */
+#define IPV6_LEAVE_GROUP       13 /* ipv6_mreq; leave a group membership */
+#define IPV6_PORTRANGE         14 /* int; range to choose for unspec port */
+#define ICMP6_FILTER           18 /* icmp6_filter; icmp6 filter */
+/* RFC2292 options */
+#ifdef _KERNEL
+#define IPV6_2292PKTINFO       19 /* bool; send/recv if, src/dst addr */
+#define IPV6_2292HOPLIMIT      20 /* bool; hop limit */
+#define IPV6_2292NEXTHOP       21 /* bool; next hop addr */
+#define IPV6_2292HOPOPTS       22 /* bool; hop-by-hop option */
+#define IPV6_2292DSTOPTS       23 /* bool; destinaion option */
+#define IPV6_2292RTHDR         24 /* bool; routing header */
+#define IPV6_2292PKTOPTIONS    25 /* buf/cmsghdr; set/get IPv6 options */
+#endif
+
+#define IPV6_CHECKSUM          26 /* int; checksum offset for raw socket */
+#define IPV6_V6ONLY            27 /* bool; make AF_INET6 sockets v6 only */
+#ifndef _KERNEL
+#define IPV6_BINDV6ONLY                IPV6_V6ONLY
+#endif
+
+#if 1 /* IPSEC */
+#define IPV6_IPSEC_POLICY      28 /* struct; get/set security policy */
+#endif /* IPSEC */
+
+#define IPV6_FAITH             29 /* bool; accept FAITH'ed connections */
+
+#if 1 /* IPV6FIREWALL */
+#define IPV6_FW_ADD            30 /* add a firewall rule to chain */
+#define IPV6_FW_DEL            31 /* delete a firewall rule from chain */
+#define IPV6_FW_FLUSH          32 /* flush firewall rule chain */
+#define IPV6_FW_ZERO           33 /* clear single/all firewall counter(s) */
+#define IPV6_FW_GET            34 /* get entire firewall rule chain */
+#endif
+
+/* new socket options introduced in RFC3542 */
+#define IPV6_RTHDRDSTOPTS      35 /* ip6_dest; send dst option before rthdr */
+
+#define IPV6_RECVPKTINFO       36 /* bool; recv if, dst addr */
+#define IPV6_RECVHOPLIMIT      37 /* bool; recv hop limit */
+#define IPV6_RECVRTHDR         38 /* bool; recv routing header */
+#define IPV6_RECVHOPOPTS       39 /* bool; recv hop-by-hop option */
+#define IPV6_RECVDSTOPTS       40 /* bool; recv dst option after rthdr */
+#ifdef _KERNEL
+#define IPV6_RECVRTHDRDSTOPTS  41 /* bool; recv dst option before rthdr */
+#endif
+
+#define IPV6_USE_MIN_MTU       42 /* bool; send packets at the minimum MTU */
+#define IPV6_RECVPATHMTU       43 /* bool; notify an according MTU */
+
+#define IPV6_PATHMTU           44 /* mtuinfo; get the current path MTU (sopt),
+                                     4 bytes int; MTU notification (cmsg) */
+#if 0 /*obsoleted during 2292bis -> 3542*/
+#define IPV6_REACHCONF         45 /* no data; ND reachability confirm
+                                     (cmsg only/not in of RFC3542) */
+#endif
+
+/* more new socket options introduced in RFC3542 */
+#define IPV6_PKTINFO           46 /* in6_pktinfo; send if, src addr */
+#define IPV6_HOPLIMIT          47 /* int; send hop limit */
+#define IPV6_NEXTHOP           48 /* sockaddr; next hop addr */
+#define IPV6_HOPOPTS           49 /* ip6_hbh; send hop-by-hop option */
+#define IPV6_DSTOPTS           50 /* ip6_dest; send dst option befor rthdr */
+#define IPV6_RTHDR             51 /* ip6_rthdr; send routing header */
+#if 0
+#define IPV6_PKTOPTIONS                52 /* buf/cmsghdr; set/get IPv6 options */
+                                  /* obsoleted by RFC3542 */
+#endif
+
+#define IPV6_RECVTCLASS                57 /* bool; recv traffic class values */
+
+#define IPV6_AUTOFLOWLABEL     59 /* bool; attach flowlabel automagically */
+
+#define IPV6_TCLASS            61 /* int; send traffic class value */
+#define IPV6_DONTFRAG          62 /* bool; disable IPv6 fragmentation */
+
+#define IPV6_PREFER_TEMPADDR   63 /* int; prefer temporary addresses as
+                                   * the source address.
+                                   */
+
+#define        IPV6_BINDANY            64 /* bool: allow bind to any address */
+
+/*
+ * The following option is private; do not use it from user applications.
+ * It is deliberately defined to the same value as IP_MSFILTER.
+ */
+#define        IPV6_MSFILTER           74 /* struct __msfilterreq;
+                                   * set/get multicast source filter list.
+                                   */
+
+/* to define items, should talk with KAME guys first, for *BSD compatibility */
+
+#define IPV6_RTHDR_LOOSE     0 /* this hop need not be a neighbor. XXX old spec */
+#define IPV6_RTHDR_STRICT    1 /* this hop must be a neighbor. XXX old spec */
+#define IPV6_RTHDR_TYPE_0    0 /* IPv6 routing header type 0 */
+
+/*
+ * Defaults and limits for options
+ */
+#define IPV6_DEFAULT_MULTICAST_HOPS 1  /* normally limit m'casts to 1 hop */
+#define IPV6_DEFAULT_MULTICAST_LOOP 1  /* normally hear sends if a member */
+
+/*
+ * The im6o_membership vector for each socket is now dynamically allocated at
+ * run-time, bounded by USHRT_MAX, and is reallocated when needed, sized
+ * according to a power-of-two increment.
+ */
+#define        IPV6_MIN_MEMBERSHIPS    31
+#define        IPV6_MAX_MEMBERSHIPS    4095
+
+/*
+ * Default resource limits for IPv6 multicast source filtering.
+ * These may be modified by sysctl.
+ */
+#define        IPV6_MAX_GROUP_SRC_FILTER       512     /* sources per group */
+#define        IPV6_MAX_SOCK_SRC_FILTER        128     /* sources per socket/group */
+
+/*
+ * Argument structure for IPV6_JOIN_GROUP and IPV6_LEAVE_GROUP.
+ */
+struct ipv6_mreq {
+       struct in6_addr ipv6mr_multiaddr;
+       unsigned int    ipv6mr_interface;
+};
+
+/*
+ * IPV6_PKTINFO: Packet information(RFC2292 sec 5)
+ */
+struct in6_pktinfo {
+       struct in6_addr ipi6_addr;      /* src/dst IPv6 address */
+       unsigned int    ipi6_ifindex;   /* send/recv interface index */
+};
+
+/*
+ * Control structure for IPV6_RECVPATHMTU socket option.
+ */
+struct ip6_mtuinfo {
+       struct sockaddr_in6 ip6m_addr;  /* or sockaddr_storage? */
+       uint32_t ip6m_mtu;
+};
+
+/*
+ * Argument for IPV6_PORTRANGE:
+ * - which range to search when port is unspecified at bind() or connect()
+ */
+#define        IPV6_PORTRANGE_DEFAULT  0       /* default range */
+#define        IPV6_PORTRANGE_HIGH     1       /* "high" - request firewall bypass */
+#define        IPV6_PORTRANGE_LOW      2       /* "low" - vouchsafe security */
+
+#if __BSD_VISIBLE
+/*
+ * Definitions for inet6 sysctl operations.
+ *
+ * Third level is protocol number.
+ * Fourth level is desired variable within that protocol.
+ */
+#define IPV6PROTO_MAXID        (IPPROTO_PIM + 1)       /* don't list to IPV6PROTO_MAX */
+
+/*
+ * Names for IP sysctl objects
+ */
+#define IPV6CTL_FORWARDING     1       /* act as router */
+#define IPV6CTL_SENDREDIRECTS  2       /* may send redirects when forwarding*/
+#define IPV6CTL_DEFHLIM                3       /* default Hop-Limit */
+#ifdef notyet
+#define IPV6CTL_DEFMTU         4       /* default MTU */
+#endif
+#define IPV6CTL_FORWSRCRT      5       /* forward source-routed dgrams */
+#define IPV6CTL_STATS          6       /* stats */
+#define IPV6CTL_MRTSTATS       7       /* multicast forwarding stats */
+#define IPV6CTL_MRTPROTO       8       /* multicast routing protocol */
+#define IPV6CTL_MAXFRAGPACKETS 9       /* max packets reassembly queue */
+#define IPV6CTL_SOURCECHECK    10      /* verify source route and intf */
+#define IPV6CTL_SOURCECHECK_LOGINT 11  /* minimume logging interval */
+#define IPV6CTL_ACCEPT_RTADV   12
+#define IPV6CTL_KEEPFAITH      13
+#define IPV6CTL_LOG_INTERVAL   14
+#define IPV6CTL_HDRNESTLIMIT   15
+#define IPV6CTL_DAD_COUNT      16
+#define IPV6CTL_AUTO_FLOWLABEL 17
+#define IPV6CTL_DEFMCASTHLIM   18
+#define IPV6CTL_GIF_HLIM       19      /* default HLIM for gif encap packet */
+#define IPV6CTL_KAME_VERSION   20
+#define IPV6CTL_USE_DEPRECATED 21      /* use deprecated addr (RFC2462 5.5.4) */
+#define IPV6CTL_RR_PRUNE       22      /* walk timer for router renumbering */
+#if 0  /* obsolete */
+#define IPV6CTL_MAPPED_ADDR    23
+#endif
+#define IPV6CTL_V6ONLY         24
+#define IPV6CTL_RTEXPIRE       25      /* cloned route expiration time */
+#define IPV6CTL_RTMINEXPIRE    26      /* min value for expiration time */
+#define IPV6CTL_RTMAXCACHE     27      /* trigger level for dynamic expire */
+
+#define IPV6CTL_USETEMPADDR    32      /* use temporary addresses (RFC3041) */
+#define IPV6CTL_TEMPPLTIME     33      /* preferred lifetime for tmpaddrs */
+#define IPV6CTL_TEMPVLTIME     34      /* valid lifetime for tmpaddrs */
+#define IPV6CTL_AUTO_LINKLOCAL 35      /* automatic link-local addr assign */
+#define IPV6CTL_RIP6STATS      36      /* raw_ip6 stats */
+#define IPV6CTL_PREFER_TEMPADDR        37      /* prefer temporary addr as src */
+#define IPV6CTL_ADDRCTLPOLICY  38      /* get/set address selection policy */
+#define IPV6CTL_USE_DEFAULTZONE        39      /* use default scope zone */
+
+#define IPV6CTL_MAXFRAGS       41      /* max fragments */
+#if 0
+#define IPV6CTL_IFQ            42      /* ip6intrq node */
+#define IPV6CTL_ISATAPRTR      43      /* isatap router */
+#endif
+#define IPV6CTL_MCAST_PMTU     44      /* enable pMTU discovery for multicast? */
+
+/* New entries should be added here from current IPV6CTL_MAXID value. */
+/* to define items, should talk with KAME guys first, for *BSD compatibility */
+#define IPV6CTL_STEALTH                45
+
+#define        ICMPV6CTL_ND6_ONLINKNSRFC4861   47
+#define        IPV6CTL_NO_RADR         48      /* No defroute from RA */
+#define        IPV6CTL_NORBIT_RAIF     49      /* Disable R-bit in NA on RA
+                                        * receiving IF. */
+#define        IPV6CTL_RFC6204W3       50      /* Accept defroute even when forwarding
+                                          enabled */
+#define        IPV6CTL_MAXID           51
+#endif /* __BSD_VISIBLE */
+
+/*
+ * Redefinition of mbuf flags
+ */
+#define        M_AUTHIPHDR     M_PROTO2
+#define        M_DECRYPTED     M_PROTO3
+#define        M_LOOP          M_PROTO4
+#define        M_AUTHIPDGM     M_PROTO5
+#define        M_RTALERT_MLD   M_PROTO6
+
+#ifdef _KERNEL
+struct cmsghdr;
+
+int    in6_cksum __P((struct mbuf *, u_int8_t, u_int32_t, u_int32_t));
+int    in6_localaddr __P((struct in6_addr *));
+int    in6_localip(struct in6_addr *);
+int    in6_addrscope __P((struct in6_addr *));
+struct in6_ifaddr *in6_ifawithifp __P((struct ifnet *, struct in6_addr *));
+extern void in6_if_up __P((struct ifnet *));
+struct sockaddr;
+extern u_char  ip6_protox[];
+
+void   in6_sin6_2_sin __P((struct sockaddr_in *sin,
+                           struct sockaddr_in6 *sin6));
+void   in6_sin_2_v4mapsin6 __P((struct sockaddr_in *sin,
+                                struct sockaddr_in6 *sin6));
+void   in6_sin6_2_sin_in_sock __P((struct sockaddr *nam));
+void   in6_sin_2_v4mapsin6_in_sock __P((struct sockaddr **nam));
+extern void addrsel_policy_init __P((void));
+
+#define        satosin6(sa)    ((struct sockaddr_in6 *)(sa))
+#define        sin6tosa(sin6)  ((struct sockaddr *)(sin6))
+#define        ifatoia6(ifa)   ((struct in6_ifaddr *)(ifa))
+
+extern int     (*faithprefix_p)(struct in6_addr *);
+#endif /* _KERNEL */
+
+#ifndef _SIZE_T_DECLARED
+typedef        __size_t        size_t;
+#define        _SIZE_T_DECLARED
+#endif
+
+#ifndef _SOCKLEN_T_DECLARED
+typedef        __socklen_t     socklen_t;
+#define        _SOCKLEN_T_DECLARED
+#endif
+
+#if __BSD_VISIBLE
+
+__BEGIN_DECLS
+struct cmsghdr;
+
+extern int inet6_option_space __P((int));
+extern int inet6_option_init __P((void *, struct cmsghdr **, int));
+extern int inet6_option_append __P((struct cmsghdr *, const uint8_t *,
+       int, int));
+extern uint8_t *inet6_option_alloc __P((struct cmsghdr *, int, int, int));
+extern int inet6_option_next __P((const struct cmsghdr *, uint8_t **));
+extern int inet6_option_find __P((const struct cmsghdr *, uint8_t **, int));
+
+extern size_t inet6_rthdr_space __P((int, int));
+extern struct cmsghdr *inet6_rthdr_init __P((void *, int));
+extern int inet6_rthdr_add __P((struct cmsghdr *, const struct in6_addr *,
+       unsigned int));
+extern int inet6_rthdr_lasthop __P((struct cmsghdr *, unsigned int));
+#if 0 /* not implemented yet */
+extern int inet6_rthdr_reverse __P((const struct cmsghdr *, struct cmsghdr *));
+#endif
+extern int inet6_rthdr_segments __P((const struct cmsghdr *));
+extern struct in6_addr *inet6_rthdr_getaddr __P((struct cmsghdr *, int));
+extern int inet6_rthdr_getflags __P((const struct cmsghdr *, int));
+
+extern int inet6_opt_init __P((void *, socklen_t));
+extern int inet6_opt_append __P((void *, socklen_t, int, uint8_t, socklen_t,
+       uint8_t, void **));
+extern int inet6_opt_finish __P((void *, socklen_t, int));
+extern int inet6_opt_set_val __P((void *, int, void *, socklen_t));
+
+extern int inet6_opt_next __P((void *, socklen_t, int, uint8_t *, socklen_t *,
+       void **));
+extern int inet6_opt_find __P((void *, socklen_t, int, uint8_t, socklen_t *,
+       void **));
+extern int inet6_opt_get_val __P((void *, int, void *, socklen_t));
+extern socklen_t inet6_rth_space __P((int, int));
+extern void *inet6_rth_init __P((void *, socklen_t, int, int));
+extern int inet6_rth_add __P((void *, const struct in6_addr *));
+extern int inet6_rth_reverse __P((const void *, void *));
+extern int inet6_rth_segments __P((const void *));
+extern struct in6_addr *inet6_rth_getaddr __P((const void *, int));
+__END_DECLS
+
+#endif /* __BSD_VISIBLE */
+
+#endif /* !_NETINET6_IN6_H_ */
similarity index 100%
rename from lib/pcre/pcre.h
rename to include/pcre.h
similarity index 100%
rename from include/pcre/pcreposix.h
rename to include/pcreposix.h
diff --git a/include/pthread.h b/include/pthread.h
new file mode 100644 (file)
index 0000000..71e337b
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu
+ * Copyright (c) 1995-1998 by John Birrell <jb@cimlogic.com.au>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *  This product includes software developed by Chris Provenzano.
+ * 4. The name of Chris Provenzano may not be used to endorse or promote 
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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.
+ *
+ * $FreeBSD$
+ */
+#ifndef _PTHREAD_H_
+#define _PTHREAD_H_
+
+/*
+ * Header files.
+ */
+#include <sys/cdefs.h>
+#include <sys/_pthreadtypes.h>
+#include <machine/_limits.h>
+#include <sys/_types.h>
+#include <sys/_sigset.h>
+#include <sys/types.h>
+#include <sched.h>
+#include <time.h>
+
+/*
+ * Run-time invariant values:
+ */
+#define PTHREAD_DESTRUCTOR_ITERATIONS          4
+#define PTHREAD_KEYS_MAX                       256
+#define PTHREAD_STACK_MIN                      __MINSIGSTKSZ
+#define PTHREAD_THREADS_MAX                    __ULONG_MAX
+#define PTHREAD_BARRIER_SERIAL_THREAD          -1
+
+/*
+ * Flags for threads and thread attributes.
+ */
+#define PTHREAD_DETACHED            0x1
+#define PTHREAD_SCOPE_SYSTEM        0x2
+#define PTHREAD_INHERIT_SCHED       0x4
+#define PTHREAD_NOFLOAT             0x8
+
+#define PTHREAD_CREATE_DETACHED     PTHREAD_DETACHED
+#define PTHREAD_CREATE_JOINABLE     0
+#define PTHREAD_SCOPE_PROCESS       0
+#define PTHREAD_EXPLICIT_SCHED      0
+
+/*
+ * Flags for read/write lock attributes
+ */
+#define PTHREAD_PROCESS_PRIVATE     0
+#define PTHREAD_PROCESS_SHARED      1  
+
+/*
+ * Flags for cancelling threads
+ */
+#define PTHREAD_CANCEL_ENABLE          0
+#define PTHREAD_CANCEL_DISABLE         1
+#define PTHREAD_CANCEL_DEFERRED                0
+#define PTHREAD_CANCEL_ASYNCHRONOUS    2
+#define PTHREAD_CANCELED               ((void *) 1)
+
+/*
+ * Flags for once initialization.
+ */
+#define PTHREAD_NEEDS_INIT  0
+#define PTHREAD_DONE_INIT   1
+
+/*
+ * Static once initialization values. 
+ */
+#define PTHREAD_ONCE_INIT   { PTHREAD_NEEDS_INIT, NULL }
+
+/*
+ * Static initialization values. 
+ */
+#define PTHREAD_MUTEX_INITIALIZER      NULL
+#define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP  ((pthread_mutex_t)1)
+#define PTHREAD_COND_INITIALIZER       NULL
+#define PTHREAD_RWLOCK_INITIALIZER     NULL
+
+/*
+ * Default attribute arguments (draft 4, deprecated).
+ */
+#ifndef PTHREAD_KERNEL
+#define pthread_condattr_default    NULL
+#define pthread_mutexattr_default   NULL
+#define pthread_attr_default        NULL
+#endif
+
+#define PTHREAD_PRIO_NONE      0
+#define PTHREAD_PRIO_INHERIT   1
+#define PTHREAD_PRIO_PROTECT   2
+
+/*
+ * Mutex types (Single UNIX Specification, Version 2, 1997).
+ *
+ * Note that a mutex attribute with one of the following types:
+ *
+ *     PTHREAD_MUTEX_NORMAL
+ *     PTHREAD_MUTEX_RECURSIVE
+ *
+ * will deviate from POSIX specified semantics.
+ */
+enum pthread_mutextype {
+       PTHREAD_MUTEX_ERRORCHECK        = 1,    /* Default POSIX mutex */
+       PTHREAD_MUTEX_RECURSIVE         = 2,    /* Recursive mutex */
+       PTHREAD_MUTEX_NORMAL            = 3,    /* No error checking */
+       PTHREAD_MUTEX_ADAPTIVE_NP       = 4,    /* Adaptive mutex, spins briefly before blocking on lock */
+       PTHREAD_MUTEX_TYPE_MAX
+};
+
+#define PTHREAD_MUTEX_DEFAULT          PTHREAD_MUTEX_ERRORCHECK
+
+struct _pthread_cleanup_info {
+       __uintptr_t     pthread_cleanup_pad[8];
+};
+
+/*
+ * Thread function prototype definitions:
+ */
+__BEGIN_DECLS
+int            pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
+int            pthread_attr_destroy(pthread_attr_t *);
+int            pthread_attr_getstack(const pthread_attr_t * __restrict, 
+                       void ** __restrict, size_t * __restrict);
+int            pthread_attr_getstacksize(const pthread_attr_t *, size_t *);
+int            pthread_attr_getguardsize(const pthread_attr_t *, size_t *);
+int            pthread_attr_getstackaddr(const pthread_attr_t *, void **);
+int            pthread_attr_getdetachstate(const pthread_attr_t *, int *);
+int            pthread_attr_init(pthread_attr_t *);
+int            pthread_attr_setstacksize(pthread_attr_t *, size_t);
+int            pthread_attr_setguardsize(pthread_attr_t *, size_t);
+int            pthread_attr_setstack(pthread_attr_t *, void *, size_t);
+int            pthread_attr_setstackaddr(pthread_attr_t *, void *);
+int            pthread_attr_setdetachstate(pthread_attr_t *, int);
+int            pthread_barrier_destroy(pthread_barrier_t *);
+int            pthread_barrier_init(pthread_barrier_t *,
+                       const pthread_barrierattr_t *, unsigned);
+int            pthread_barrier_wait(pthread_barrier_t *);
+int            pthread_barrierattr_destroy(pthread_barrierattr_t *);
+int            pthread_barrierattr_getpshared(const pthread_barrierattr_t *,
+                       int *);
+int            pthread_barrierattr_init(pthread_barrierattr_t *);
+int            pthread_barrierattr_setpshared(pthread_barrierattr_t *, int);
+
+#define                pthread_cleanup_push(cleanup_routine, cleanup_arg)              \
+               {                                                               \
+                       struct _pthread_cleanup_info __cleanup_info__;          \
+                       __pthread_cleanup_push_imp(cleanup_routine, cleanup_arg,\
+                               &__cleanup_info__);                             \
+                       {
+
+#define                pthread_cleanup_pop(execute)                                    \
+                       }                                                       \
+                       __pthread_cleanup_pop_imp(execute);                     \
+               }
+
+int            pthread_condattr_destroy(pthread_condattr_t *);
+int            pthread_condattr_getclock(const pthread_condattr_t *,
+                       clockid_t *);
+int            pthread_condattr_getpshared(const pthread_condattr_t *, int *);
+int            pthread_condattr_init(pthread_condattr_t *);
+int            pthread_condattr_setclock(pthread_condattr_t *, clockid_t);
+int            pthread_condattr_setpshared(pthread_condattr_t *, int);
+int            pthread_cond_broadcast(pthread_cond_t *);
+int            pthread_cond_destroy(pthread_cond_t *);
+int            pthread_cond_init(pthread_cond_t *,
+                       const pthread_condattr_t *);
+int            pthread_cond_signal(pthread_cond_t *);
+int            pthread_cond_timedwait(pthread_cond_t *,
+                       pthread_mutex_t *, const struct timespec *);
+int            pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
+int            pthread_create(pthread_t *, const pthread_attr_t *,
+                       void *(*) (void *), void *);
+int            pthread_detach(pthread_t);
+int            pthread_equal(pthread_t, pthread_t);
+void           pthread_exit(void *) __dead2;
+void           *pthread_getspecific(pthread_key_t);
+int            pthread_getcpuclockid(pthread_t, clockid_t *);
+int            pthread_join(pthread_t, void **);
+int            pthread_key_create(pthread_key_t *,
+                       void (*) (void *));
+int            pthread_key_delete(pthread_key_t);
+int            pthread_mutexattr_init(pthread_mutexattr_t *);
+int            pthread_mutexattr_destroy(pthread_mutexattr_t *);
+int            pthread_mutexattr_getpshared(const pthread_mutexattr_t *,
+                       int *);
+int            pthread_mutexattr_gettype(pthread_mutexattr_t *, int *);
+int            pthread_mutexattr_settype(pthread_mutexattr_t *, int);
+int            pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
+int            pthread_mutex_destroy(pthread_mutex_t *);
+int            pthread_mutex_init(pthread_mutex_t *,
+                       const pthread_mutexattr_t *);
+int            pthread_mutex_lock(pthread_mutex_t *);
+int            pthread_mutex_trylock(pthread_mutex_t *);
+int            pthread_mutex_timedlock(pthread_mutex_t *,
+                       const struct timespec *);
+int            pthread_mutex_unlock(pthread_mutex_t *);
+int            pthread_once(pthread_once_t *, void (*) (void));
+int            pthread_rwlock_destroy(pthread_rwlock_t *);
+int            pthread_rwlock_init(pthread_rwlock_t *,
+                       const pthread_rwlockattr_t *);
+int            pthread_rwlock_rdlock(pthread_rwlock_t *);
+int            pthread_rwlock_timedrdlock(pthread_rwlock_t *,
+                       const struct timespec *);
+int            pthread_rwlock_timedwrlock(pthread_rwlock_t *,
+                       const struct timespec *);
+int            pthread_rwlock_tryrdlock(pthread_rwlock_t *);
+int            pthread_rwlock_trywrlock(pthread_rwlock_t *);
+int            pthread_rwlock_unlock(pthread_rwlock_t *);
+int            pthread_rwlock_wrlock(pthread_rwlock_t *);
+int            pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
+int            pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *,
+                       int *);
+int            pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *,
+                       int *);
+int            pthread_rwlockattr_init(pthread_rwlockattr_t *);
+int            pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *, int);
+int            pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
+pthread_t      pthread_self(void);
+int            pthread_setspecific(pthread_key_t, const void *);
+
+int            pthread_spin_init(pthread_spinlock_t *, int);
+int            pthread_spin_destroy(pthread_spinlock_t *);
+int            pthread_spin_lock(pthread_spinlock_t *);
+int            pthread_spin_trylock(pthread_spinlock_t *);
+int            pthread_spin_unlock(pthread_spinlock_t *);
+int            pthread_cancel(pthread_t);
+int            pthread_setcancelstate(int, int *);
+int            pthread_setcanceltype(int, int *);
+void           pthread_testcancel(void);
+
+#if __BSD_VISIBLE
+int            pthread_getprio(pthread_t);
+int            pthread_setprio(pthread_t, int);
+void           pthread_yield(void);
+#endif
+
+int            pthread_mutexattr_getprioceiling(pthread_mutexattr_t *,
+                       int *);
+int            pthread_mutexattr_setprioceiling(pthread_mutexattr_t *,
+                       int);
+int            pthread_mutex_getprioceiling(pthread_mutex_t *, int *);
+int            pthread_mutex_setprioceiling(pthread_mutex_t *, int, int *);
+
+int            pthread_mutexattr_getprotocol(pthread_mutexattr_t *, int *);
+int            pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int);
+
+int            pthread_attr_getinheritsched(const pthread_attr_t *, int *);
+int            pthread_attr_getschedparam(const pthread_attr_t *,
+                       struct sched_param *);
+int            pthread_attr_getschedpolicy(const pthread_attr_t *, int *);
+int            pthread_attr_getscope(const pthread_attr_t *, int *);
+int            pthread_attr_setinheritsched(pthread_attr_t *, int);
+int            pthread_attr_setschedparam(pthread_attr_t *,
+                       const struct sched_param *);
+int            pthread_attr_setschedpolicy(pthread_attr_t *, int);
+int            pthread_attr_setscope(pthread_attr_t *, int);
+int            pthread_getschedparam(pthread_t pthread, int *,
+                       struct sched_param *);
+int            pthread_setschedparam(pthread_t, int,
+                       const struct sched_param *);
+#if __XSI_VISIBLE
+int            pthread_getconcurrency(void);
+int            pthread_setconcurrency(int);
+#endif
+
+void           __pthread_cleanup_push_imp(void (*)(void *), void *,
+                       struct _pthread_cleanup_info *);
+void           __pthread_cleanup_pop_imp(int);
+__END_DECLS
+
+#endif
index e8df812..f6b6e95 100644 (file)
@@ -93,10 +93,31 @@ __BEGIN_DECLS
 
 #define NSIG            32      /* number of old signals (counting 0) */
 
-#define SIG_ERR ((void *) -1)
-#define SIG_DFL ((void *) 0)
-#define SIG_IGN ((void *) 1)
-#define SIG_HOLD ((void *)3)
+#if __POSIX_VISIBLE || __XSI_VISIBLE
+#define SA_NOCLDSTOP    0x0008  /* do not generate SIGCHLD on child stop */
+#endif /* __POSIX_VISIBLE || __XSI_VISIBLE */
+
+#if __XSI_VISIBLE
+#define SA_ONSTACK      0x0001  /* take signal on signal stack */
+#define SA_RESTART      0x0002  /* restart system call on signal return */
+#define SA_RESETHAND    0x0004  /* reset to SIG_DFL when taking signal */
+#define SA_NODEFER      0x0010  /* don't mask the signal we're delivering */
+#define SA_NOCLDWAIT    0x0020  /* don't keep zombies around */
+#define SA_SIGINFO      0x0040  /* signal handler with SA_SIGINFO args */
+#endif
+
+/* Adjusted to linux, has unused sa_restorer field and unsigned long
+   sa_flags; relatively unimportant though.  */
+/* Type of a signal handler.  */
+typedef void (*__sighandler_t)(int);
+
+/* The type used in newlib sources.  */
+typedef __sighandler_t _sig_func_ptr;
+
+#define SIG_ERR ((_sig_func_ptr) -1)
+#define SIG_DFL ((_sig_func_ptr) 0)
+#define SIG_IGN ((_sig_func_ptr) 1)
+#define SIG_HOLD ((_sig_func_ptr)3)
 
 #ifndef _PID_T_DECLARED
 typedef        __pid_t         pid_t;
@@ -110,6 +131,79 @@ typedef void (*signalhandler_t)(int);
 typedef __sigset_t      sigset_t;
 #endif
 
+union sigval {
+        /* Members as suggested by Annex C of POSIX 1003.1b. */
+        int     sival_int;
+        void    *sival_ptr;
+        /* 6.0 compatibility */
+        int     sigval_int;
+        void    *sigval_ptr;
+};
+
+typedef struct __siginfo {
+        int     si_signo;               /* signal number */
+        int     si_errno;               /* errno association */
+        /*
+         * Cause of signal, one of the SI_ macros or signal-specific
+         * values, i.e. one of the FPE_... values for SIGFPE.  This
+         * value is equivalent to the second argument to an old-style
+         * FreeBSD signal handler.
+         */
+        int     si_code;                /* signal code */
+        __pid_t si_pid;                 /* sending process */
+        __uid_t si_uid;                 /* sender's ruid */
+        int     si_status;              /* exit value */
+        void    *si_addr;               /* faulting instruction */
+        union sigval si_value;          /* signal value */
+        union   {
+                struct {
+                        int     _trapno;/* machine specific trap code */
+                } _fault;                                               
+                struct { 
+                        int     _timerid;
+                        int     _overrun;
+                } _timer;                
+                struct { 
+                        int     _mqd;
+                } _mesgq;            
+                struct { 
+                        long    _band;          /* band event for SIGPOLL */
+                } _poll;                        /* was this ever used ? */  
+                struct {                                                  
+                        long    __spare1__;
+                        int     __spare2__[7];
+                } __spare__;                  
+        } _reason;
+} siginfo_t;
+
+#define si_trapno       _reason._fault._trapno
+#define si_timerid      _reason._timer._timerid
+#define si_overrun      _reason._timer._overrun
+#define si_mqd          _reason._mesgq._mqd
+#define si_band         _reason._poll._band
+
+/* struct sigaction notes from POSIX:
+ *
+ *  (1) Routines stored in sa_handler should take a single int as
+ *      their argument although the POSIX standard does not require this.
+ *  (2) The fields sa_handler and sa_sigaction may overlap, and a conforming
+ *      application should not use both simultaneously.
+ */
+
+struct sigaction {
+  int         sa_flags;       /* Special flags to affect behavior of signal */
+  sigset_t    sa_mask;        /* Additional set of signals to be blocked */
+                              /*   during execution of signal-catching */
+                              /*   function. */
+  union {
+    _sig_func_ptr _handler;  /* SIG_DFL, SIG_IGN, or pointer to a function */
+    void      (*_sigaction)( int, siginfo_t *, void * );
+  } _signal_handlers;
+};
+
+#define sa_handler    _signal_handlers._handler
+#define sa_sigaction  _signal_handlers._sigaction
+
 /*
  * Flags for sigprocmask:
  */
@@ -126,7 +220,9 @@ int sigdelset(sigset_t *set, int signo);
 int sigemptyset(sigset_t *set);
 int sigfillset(sigset_t *set);
 int sigismember(const sigset_t *set, int signo);
-
+int sigaction(int signum, const struct sigaction *act,
+              struct sigaction *oldact);
+int raise(int sig);
 __END_DECLS
 
 #endif // BARRELFISH_SIGNAL_H_
index 1808a9e..8ebf9b9 100644 (file)
@@ -41,6 +41,9 @@ struct spawninfo {
 
     // vspace of spawned domain
     struct vspace *vspace;
+    struct vregion *vregion[16];
+    genvaddr_t base[16];
+    unsigned int vregions;
 
     dispatcher_handle_t handle;
     enum cpu_type cpu_type;
index af4d365..44d4049 100644 (file)
@@ -47,6 +47,7 @@ typedef       __size_t        size_t;
 struct iovec {
        void    *iov_base;      /* Base address. */
        size_t   iov_len;       /* Length. */
+        void    *iov_opaque;   /* XXX: Arranet extension. */
 };
 
 #endif /* !_SYS__IOVEC_H_ */
diff --git a/include/sys/_pthreadtypes.h b/include/sys/_pthreadtypes.h
new file mode 100644 (file)
index 0000000..76049ee
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu
+ * Copyright (c) 1995-1998 by John Birrell <jb@cimlogic.com.au>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *  This product includes software developed by Chris Provenzano.
+ * 4. The name of Chris Provenzano may not be used to endorse or promote 
+ *       products derived from this software without specific prior written
+ *       permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``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 CHRIS PROVENZANO 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS__PTHREADTYPES_H_
+#define _SYS__PTHREADTYPES_H_
+
+/*
+ * Forward structure definitions.
+ *
+ * These are mostly opaque to the user.
+ */
+struct pthread;
+struct pthread_attr;
+struct pthread_cond;
+struct pthread_cond_attr;
+struct pthread_mutex;
+struct pthread_mutex_attr;
+struct pthread_once;
+struct pthread_rwlock;
+struct pthread_rwlockattr;
+struct pthread_barrier;
+struct pthread_barrier_attr;
+struct pthread_spinlock;
+
+/*
+ * Primitive system data type definitions required by P1003.1c.
+ *
+ * Note that P1003.1c specifies that there are no defined comparison
+ * or assignment operators for the types pthread_attr_t, pthread_cond_t,
+ * pthread_condattr_t, pthread_mutex_t, pthread_mutexattr_t.
+ */
+#ifndef _PTHREAD_T_DECLARED
+typedef struct pthread                 *pthread_t;
+#define        _PTHREAD_T_DECLARED
+#endif
+typedef struct pthread_attr            *pthread_attr_t;
+typedef struct pthread_mutex           *pthread_mutex_t;
+typedef struct pthread_mutex_attr      *pthread_mutexattr_t;
+typedef struct pthread_cond            *pthread_cond_t;
+typedef struct pthread_cond_attr       *pthread_condattr_t;
+typedef int                            pthread_key_t;
+typedef struct pthread_once            pthread_once_t;
+typedef struct pthread_rwlock          *pthread_rwlock_t;
+typedef struct pthread_rwlockattr      *pthread_rwlockattr_t;
+typedef struct pthread_barrier         *pthread_barrier_t;
+typedef struct pthread_barrierattr     *pthread_barrierattr_t;
+typedef struct pthread_spinlock        *pthread_spinlock_t;
+
+/*
+ * Additional type definitions:
+ *
+ * Note that P1003.1c reserves the prefixes pthread_ and PTHREAD_ for
+ * use in header symbols.
+ */
+typedef void   *pthread_addr_t;
+typedef void   *(*pthread_startroutine_t)(void *);
+
+/*
+ * Once definitions.
+ */
+struct pthread_once {
+       int             state;
+       pthread_mutex_t mutex;
+};
+
+#endif /* ! _SYS__PTHREADTYPES_H_ */
diff --git a/include/sys/_sockaddr_storage.h b/include/sys/_sockaddr_storage.h
new file mode 100644 (file)
index 0000000..5c0048b
--- /dev/null
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1982, 1985, 1986, 1988, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)socket.h    8.4 (Berkeley) 2/21/94
+ * $FreeBSD$
+ */
+
+#ifndef _SYS__SOCKADDR_STORAGE_H_
+#define        _SYS__SOCKADDR_STORAGE_H_
+
+/*
+ * RFC 2553: protocol-independent placeholder for socket addresses
+ */
+#define        _SS_MAXSIZE     128U
+#define        _SS_ALIGNSIZE   (sizeof(__int64_t))
+#define        _SS_PAD1SIZE    (_SS_ALIGNSIZE - sizeof(unsigned char) - \
+                           sizeof(sa_family_t))
+#define        _SS_PAD2SIZE    (_SS_MAXSIZE - sizeof(unsigned char) - \
+                           sizeof(sa_family_t) - _SS_PAD1SIZE - _SS_ALIGNSIZE)
+
+struct sockaddr_storage {
+       unsigned char   ss_len;         /* address length */
+       sa_family_t     ss_family;      /* address family */
+       char            __ss_pad1[_SS_PAD1SIZE];
+       __int64_t       __ss_align;     /* force desired struct alignment */
+       char            __ss_pad2[_SS_PAD2SIZE];
+};
+
+#endif /* !_SYS__SOCKADDR_STORAGE_H_ */
index e42f433..ce651ef 100644 (file)
@@ -42,6 +42,7 @@ typedef int8_t          __int8_t;
 typedef int16_t         __int16_t;
 typedef int32_t         __int32_t;
 typedef int64_t         __int64_t;
+typedef uintptr_t       __uintptr_t;
 
 typedef __uint8_t       u_int8_t;       /* unsigned integrals (deprecated) */
 typedef __uint16_t      u_int16_t;
@@ -49,6 +50,7 @@ typedef __uint32_t      u_int32_t;
 typedef __uint64_t      u_int64_t;
 
 typedef __uint8_t       __sa_family_t;
+typedef __uint32_t     __socklen_t;
 
 typedef va_list         __va_list;
 typedef size_t          __size_t;
@@ -56,6 +58,7 @@ typedef size_t          __size_t;
 typedef __uint32_t     __gid_t;
 typedef __uint32_t     __uid_t;
 typedef __int32_t      __clock_t;
+typedef __int32_t       __clockid_t;    /* clock_gettime()... */
 
 typedef int             __ct_rune_t;    /* arg type for ctype funcs */
 typedef __ct_rune_t     __rune_t;       /* rune_t (see above) */
@@ -65,6 +68,9 @@ typedef __ct_rune_t     __wint_t;       /* wint_t (see above) */
 typedef __uint16_t      __mode_t;       /* permissions */
 typedef __int64_t       __off_t;        /* file offset */
 typedef __int32_t       __pid_t;        /* process [group] */
+typedef __int64_t       __rlim_t;       /* resource limit - intentionally */
+                                        /* signed, because of legacy code */
+                                        /* that uses -1 for RLIM_INFINITY */
 #define _HAVE_SYSTYPES
 typedef long            __key_t;        /* IPC key (for Sys V IPC) */
 
diff --git a/include/sys/epoll.h b/include/sys/epoll.h
new file mode 100644 (file)
index 0000000..952bf06
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * 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.
+ *
+ * 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.
+ */
+#ifndef _SYS_EPOLL_H_
+#define _SYS_EPOLL_H_
+
+#include <stdint.h>
+
+#define EPOLL_CLOEXEC    02000000
+#define EPOLL_NONBLOCK   04000
+
+#define EPOLLIN          0x00000001
+#define EPOLLPRI         0x00000002
+#define EPOLLOUT         0x00000004
+#define EPOLLERR         0x00000008
+#define EPOLLHUP         0x00000010
+#define EPOLLRDNORM      0x00000040
+#define EPOLLRDBAND      0x00000080
+#define EPOLLWRNORM      0x00000100
+#define EPOLLWRBAND      0x00000200
+#define EPOLLMSG         0x00000400
+#define EPOLLRDHUP       0x00002000
+#define EPOLLWAKEUP      0x20000000
+#define EPOLLONESHOT     0x40000000
+#define EPOLLET          0x80000000
+
+#define EPOLL_CTL_ADD    1
+#define EPOLL_CTL_DEL    2
+#define EPOLL_CTL_MOD    3
+
+typedef union epoll_data
+{
+  void *ptr;
+  int fd;
+  uint32_t u32;
+  uint64_t u64;
+} epoll_data_t;
+
+struct epoll_event
+{
+  uint32_t events;     /* Epoll events */
+  epoll_data_t data;   /* User data variable */
+} __attribute__ ((__packed__));
+
+int epoll_create(int size);
+int epoll_create1(int flags);
+int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
+int epoll_wait(int epfd, struct epoll_event *events,
+               int max, int timeout);
+int epoll_pwait(int epfd, struct epoll_event *events,
+                int max, int timeout, const sigset_t *sigmask);
+
+#endif
diff --git a/include/sys/mman.h b/include/sys/mman.h
new file mode 100644 (file)
index 0000000..a178d7c
--- /dev/null
@@ -0,0 +1,251 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)mman.h      8.2 (Berkeley) 1/9/95
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_MMAN_H_
+#define _SYS_MMAN_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+#if __BSD_VISIBLE
+/*
+ * Inheritance for minherit()
+ */
+#define INHERIT_SHARE  0
+#define INHERIT_COPY   1
+#define INHERIT_NONE   2
+#endif
+
+/*
+ * Protections are chosen from these bits, or-ed together
+ */
+#define        PROT_NONE       0x00    /* no permissions */
+#define        PROT_READ       0x01    /* pages can be read */
+#define        PROT_WRITE      0x02    /* pages can be written */
+#define        PROT_EXEC       0x04    /* pages can be executed */
+
+/*
+ * Flags contain sharing type and options.
+ * Sharing types; choose one.
+ */
+#define        MAP_SHARED      0x0001          /* share changes */
+#define        MAP_PRIVATE     0x0002          /* changes are private */
+#if __BSD_VISIBLE
+#define        MAP_COPY        MAP_PRIVATE     /* Obsolete */
+#endif
+
+/*
+ * Other flags
+ */
+#define        MAP_FIXED        0x0010 /* map addr must be exactly as requested */
+
+#if __BSD_VISIBLE
+#define        MAP_RENAME       0x0020 /* Sun: rename private pages to file */
+#define        MAP_NORESERVE    0x0040 /* Sun: don't reserve needed swap area */
+#define        MAP_RESERVED0080 0x0080 /* previously misimplemented MAP_INHERIT */
+#define        MAP_RESERVED0100 0x0100 /* previously unimplemented MAP_NOEXTEND */
+#define        MAP_HASSEMAPHORE 0x0200 /* region may contain semaphores */
+#define        MAP_STACK        0x0400 /* region grows down, like a stack */
+#define        MAP_NOSYNC       0x0800 /* page to but do not sync underlying file */
+
+/*
+ * Mapping type
+ */
+#define        MAP_FILE         0x0000 /* map from file (default) */
+#define        MAP_ANON         0x1000 /* allocated from memory, swap space */
+#ifndef _KERNEL
+#define        MAP_ANONYMOUS    MAP_ANON /* For compatibility. */
+#endif /* !_KERNEL */
+
+/*
+ * Extended flags
+ */
+#define        MAP_NOCORE       0x00020000 /* dont include these pages in a coredump */
+#define        MAP_PREFAULT_READ 0x00040000 /* prefault mapping for reading */
+#endif /* __BSD_VISIBLE */
+
+#if __POSIX_VISIBLE >= 199309
+/*
+ * Process memory locking
+ */
+#define MCL_CURRENT    0x0001  /* Lock only current memory */
+#define MCL_FUTURE     0x0002  /* Lock all future memory as well */
+#endif
+
+/*
+ * Error return from mmap()
+ */
+#define MAP_FAILED     ((void *)-1)
+
+/*
+ * msync() flags
+ */
+#define        MS_SYNC         0x0000  /* msync synchronously */
+#define MS_ASYNC       0x0001  /* return immediately */
+#define MS_INVALIDATE  0x0002  /* invalidate all cached data */
+
+/*
+ * Advice to madvise
+ */
+#define        _MADV_NORMAL    0       /* no further special treatment */
+#define        _MADV_RANDOM    1       /* expect random page references */
+#define        _MADV_SEQUENTIAL 2      /* expect sequential page references */
+#define        _MADV_WILLNEED  3       /* will need these pages */
+#define        _MADV_DONTNEED  4       /* dont need these pages */
+
+#if __BSD_VISIBLE
+#define        MADV_NORMAL     _MADV_NORMAL
+#define        MADV_RANDOM     _MADV_RANDOM
+#define        MADV_SEQUENTIAL _MADV_SEQUENTIAL
+#define        MADV_WILLNEED   _MADV_WILLNEED
+#define        MADV_DONTNEED   _MADV_DONTNEED
+#define        MADV_FREE       5       /* dont need these pages, and junk contents */
+#define        MADV_NOSYNC     6       /* try to avoid flushes to physical media */
+#define        MADV_AUTOSYNC   7       /* revert to default flushing strategy */
+#define        MADV_NOCORE     8       /* do not include these pages in a core file */
+#define        MADV_CORE       9       /* revert to including pages in a core file */
+#define        MADV_PROTECT    10      /* protect process from pageout kill */
+
+/*
+ * Return bits from mincore
+ */
+#define        MINCORE_INCORE           0x1 /* Page is incore */
+#define        MINCORE_REFERENCED       0x2 /* Page has been referenced by us */
+#define        MINCORE_MODIFIED         0x4 /* Page has been modified by us */
+#define        MINCORE_REFERENCED_OTHER 0x8 /* Page has been referenced */
+#define        MINCORE_MODIFIED_OTHER  0x10 /* Page has been modified */
+#define        MINCORE_SUPER           0x20 /* Page is a "super" page */
+
+/*
+ * Anonymous object constant for shm_open().
+ */
+#define        SHM_ANON                ((char *)1)
+#endif /* __BSD_VISIBLE */
+
+/*
+ * XXX missing POSIX_TYPED_MEM_* macros and
+ * posix_typed_mem_info structure.
+ */
+#if __POSIX_VISIBLE >= 200112
+#define        POSIX_MADV_NORMAL       _MADV_NORMAL
+#define        POSIX_MADV_RANDOM       _MADV_RANDOM
+#define        POSIX_MADV_SEQUENTIAL   _MADV_SEQUENTIAL
+#define        POSIX_MADV_WILLNEED     _MADV_WILLNEED
+#define        POSIX_MADV_DONTNEED     _MADV_DONTNEED
+#endif
+
+#ifndef _MODE_T_DECLARED
+typedef        __mode_t        mode_t;
+#define        _MODE_T_DECLARED
+#endif
+
+#ifndef _OFF_T_DECLARED
+typedef        __off_t         off_t;
+#define        _OFF_T_DECLARED
+#endif
+
+#ifndef _SIZE_T_DECLARED
+typedef        __size_t        size_t;
+#define        _SIZE_T_DECLARED
+#endif
+
+#if defined(_KERNEL) || defined(_WANT_FILE)
+#include <vm/vm.h>
+
+struct file;
+
+struct shmfd {
+       size_t          shm_size;
+       vm_object_t     shm_object;
+       int             shm_refs;
+       uid_t           shm_uid;
+       gid_t           shm_gid;
+       mode_t          shm_mode;
+       int             shm_kmappings;
+
+       /*
+        * Values maintained solely to make this a better-behaved file
+        * descriptor for fstat() to run on.
+        */
+       struct timespec shm_atime;
+       struct timespec shm_mtime;
+       struct timespec shm_ctime;
+       struct timespec shm_birthtime;
+
+       struct label    *shm_label;             /* MAC label */
+       const char      *shm_path;
+};
+#endif
+
+#ifdef _KERNEL
+int    shm_mmap(struct shmfd *shmfd, vm_size_t objsize, vm_ooffset_t foff,
+           vm_object_t *obj);
+int    shm_map(struct file *fp, size_t size, off_t offset, void **memp);
+int    shm_unmap(struct file *fp, void *mem, size_t size);
+void   shm_path(struct shmfd *shmfd, char *path, size_t size);
+
+#else /* !_KERNEL */
+
+__BEGIN_DECLS
+/*
+ * XXX not yet implemented: posix_mem_offset(), posix_typed_mem_get_info(),
+ * posix_typed_mem_open().
+ */
+#if __BSD_VISIBLE
+int    getpagesizes(size_t *, int);
+int    madvise(void *, size_t, int);
+int    mincore(const void *, size_t, char *);
+int    minherit(void *, size_t, int);
+#endif
+int    mlock(const void *, size_t);
+#ifndef _MMAP_DECLARED
+#define        _MMAP_DECLARED
+void * mmap(void *, size_t, int, int, int, off_t);
+#endif
+int    mprotect(const void *, size_t, int);
+int    msync(void *, size_t, int);
+int    munlock(const void *, size_t);
+int    munmap(void *, size_t);
+#if __POSIX_VISIBLE >= 200112
+int    posix_madvise(void *, size_t, int);
+#endif
+#if __POSIX_VISIBLE >= 199309
+int    mlockall(int);
+int    munlockall(void);
+int    shm_open(const char *, int, mode_t);
+int    shm_unlink(const char *);
+#endif
+__END_DECLS
+
+#endif /* !_KERNEL */
+
+#endif /* !_SYS_MMAN_H_ */
diff --git a/include/sys/resource.h b/include/sys/resource.h
new file mode 100644 (file)
index 0000000..0d604f2
--- /dev/null
@@ -0,0 +1,176 @@
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)resource.h  8.4 (Berkeley) 1/9/95
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_RESOURCE_H_
+#define        _SYS_RESOURCE_H_
+
+#include <sys/cdefs.h>
+#include <sys/time.h>
+#include <sys/_types.h>
+
+/*
+ * Process priority specifications to get/setpriority.
+ */
+#define        PRIO_MIN        -20
+#define        PRIO_MAX        20
+
+#define        PRIO_PROCESS    0
+#define        PRIO_PGRP       1
+#define        PRIO_USER       2
+
+/*
+ * Resource utilization information.
+ *
+ * All fields are only modified by curthread and
+ * no locks are required to read.
+ */
+
+#define        RUSAGE_SELF     0
+#define        RUSAGE_CHILDREN -1
+#define        RUSAGE_THREAD   1
+
+struct rusage {
+       struct timeval ru_utime;        /* user time used */
+       struct timeval ru_stime;        /* system time used */
+       long    ru_maxrss;              /* max resident set size */
+#define        ru_first        ru_ixrss
+       long    ru_ixrss;               /* integral shared memory size */
+       long    ru_idrss;               /* integral unshared data " */
+       long    ru_isrss;               /* integral unshared stack " */
+       long    ru_minflt;              /* page reclaims */
+       long    ru_majflt;              /* page faults */
+       long    ru_nswap;               /* swaps */
+       long    ru_inblock;             /* block input operations */
+       long    ru_oublock;             /* block output operations */
+       long    ru_msgsnd;              /* messages sent */
+       long    ru_msgrcv;              /* messages received */
+       long    ru_nsignals;            /* signals received */
+       long    ru_nvcsw;               /* voluntary context switches */
+       long    ru_nivcsw;              /* involuntary " */
+#define        ru_last         ru_nivcsw
+};
+
+/*
+ * Resource limits
+ */
+#define        RLIMIT_CPU      0               /* maximum cpu time in seconds */
+#define        RLIMIT_FSIZE    1               /* maximum file size */
+#define        RLIMIT_DATA     2               /* data size */
+#define        RLIMIT_STACK    3               /* stack size */
+#define        RLIMIT_CORE     4               /* core file size */
+#define        RLIMIT_RSS      5               /* resident set size */
+#define        RLIMIT_MEMLOCK  6               /* locked-in-memory address space */
+#define        RLIMIT_NPROC    7               /* number of processes */
+#define        RLIMIT_NOFILE   8               /* number of open files */
+#define        RLIMIT_SBSIZE   9               /* maximum size of all socket buffers */
+#define        RLIMIT_VMEM     10              /* virtual process size (incl. mmap) */
+#define        RLIMIT_AS       RLIMIT_VMEM     /* standard name for RLIMIT_VMEM */
+#define        RLIMIT_NPTS     11              /* pseudo-terminals */
+#define        RLIMIT_SWAP     12              /* swap used */
+
+#define        RLIM_NLIMITS    13              /* number of resource limits */
+
+#define        RLIM_INFINITY   ((rlim_t)(((uint64_t)1 << 63) - 1))
+/* XXX Missing: RLIM_SAVED_MAX, RLIM_SAVED_CUR */
+
+
+/*
+ * Resource limit string identifiers
+ */
+
+#ifdef _RLIMIT_IDENT
+static const char *rlimit_ident[RLIM_NLIMITS] = {
+       "cpu",
+       "fsize",
+       "data",
+       "stack",
+       "core",
+       "rss",
+       "memlock",
+       "nproc",
+       "nofile",
+       "sbsize",
+       "vmem",
+       "npts",
+       "swap",
+};
+#endif
+
+#ifndef _RLIM_T_DECLARED
+typedef        __rlim_t        rlim_t;
+#define        _RLIM_T_DECLARED
+#endif
+
+struct rlimit {
+       rlim_t  rlim_cur;               /* current (soft) limit */
+       rlim_t  rlim_max;               /* maximum value for rlim_cur */
+};
+
+#if __BSD_VISIBLE
+
+struct orlimit {
+       __int32_t       rlim_cur;       /* current (soft) limit */
+       __int32_t       rlim_max;       /* maximum value for rlim_cur */
+};
+
+struct loadavg {
+       __fixpt_t       ldavg[3];
+       long            fscale;
+};
+
+#define        CP_USER         0
+#define        CP_NICE         1
+#define        CP_SYS          2
+#define        CP_INTR         3
+#define        CP_IDLE         4
+#define        CPUSTATES       5
+
+#endif /* __BSD_VISIBLE */
+
+#ifdef _KERNEL
+
+extern struct loadavg averunnable;
+void   read_cpu_time(long *cp_time);   /* Writes array of CPUSTATES */
+
+#else
+
+__BEGIN_DECLS
+/* XXX 2nd arg to [gs]etpriority() should be an id_t */
+int    getpriority(int, int);
+int    getrlimit(int, struct rlimit *);
+int    getrusage(int, struct rusage *);
+int    setpriority(int, int, int);
+int    setrlimit(int, const struct rlimit *);
+__END_DECLS
+
+#endif /* _KERNEL */
+#endif /* !_SYS_RESOURCE_H_ */
diff --git a/include/sys/signal.h b/include/sys/signal.h
new file mode 100644 (file)
index 0000000..2e602da
--- /dev/null
@@ -0,0 +1 @@
+#include <signal.h>
index dad3207..8051208 100644 (file)
 
 #include <sys/cdefs.h>
 #include <lwip/sockets.h>
+#include <sys/_iovec.h>
+
+/*
+ * Message header for recvmsg and sendmsg calls.
+ * Used value-result for recvmsg, value only for sendmsg.
+ */
+struct msghdr {
+        void            *msg_name;              /* optional address */
+        socklen_t        msg_namelen;           /* size of address */
+        struct iovec    *msg_iov;               /* scatter/gather array */
+        int              msg_iovlen;            /* # elements in msg_iov */
+        void            *msg_control;           /* ancillary data, see below */
+        socklen_t        msg_controllen;        /* ancillary data buffer len */
+        int              msg_flags;             /* flags on received message */
+};
 
 #if __BSD_VISIBLE
 #define AF_LOCAL        AF_UNIX         /* local to host (pipes, portals) */
 #endif
 #define AF_UNIX         1               /* standardized name for AF_LOCAL */
+#define AF_INET6        28              /* IPv6 */
 #if __BSD_VISIBLE
 #define AF_MAX          38
 #endif
 
+#if __BSD_VISIBLE
+/*
+ * Protocol families, same as address families for now.
+ */
+#define PF_UNSPEC       AF_UNSPEC
+#define PF_LOCAL        AF_LOCAL
+#define PF_UNIX         PF_LOCAL        /* backward compatibility */
+#define PF_INET         AF_INET
+#define PF_IMPLINK      AF_IMPLINK
+#define PF_PUP          AF_PUP
+#define PF_CHAOS        AF_CHAOS
+#define PF_NETBIOS      AF_NETBIOS
+#define PF_ISO          AF_ISO
+#define PF_OSI          AF_ISO
+#define PF_ECMA         AF_ECMA
+#define PF_DATAKIT      AF_DATAKIT
+#define PF_CCITT        AF_CCITT
+#define PF_SNA          AF_SNA
+#define PF_DECnet       AF_DECnet
+#define PF_DLI          AF_DLI
+#define PF_LAT          AF_LAT
+#define PF_HYLINK       AF_HYLINK
+#define PF_APPLETALK    AF_APPLETALK
+#define PF_ROUTE        AF_ROUTE
+#define PF_LINK         AF_LINK
+#define PF_XTP          pseudo_AF_XTP   /* really just proto family, no AF */
+#define PF_COIP         AF_COIP
+#define PF_CNT          AF_CNT
+#define PF_SIP          AF_SIP
+#define PF_IPX          AF_IPX
+#define PF_RTIP         pseudo_AF_RTIP  /* same format as AF_INET */
+#define PF_PIP          pseudo_AF_PIP
+#define PF_ISDN         AF_ISDN
+#define PF_KEY          pseudo_AF_KEY
+#define PF_INET6        AF_INET6
+#define PF_NATM         AF_NATM
+#define PF_ATM          AF_ATM
+#define PF_NETGRAPH     AF_NETGRAPH
+#define PF_SLOW         AF_SLOW
+#define PF_SCLUSTER     AF_SCLUSTER
+#define PF_ARP          AF_ARP
+#define PF_BLUETOOTH    AF_BLUETOOTH
+#define PF_IEEE80211    AF_IEEE80211
+#define PF_INET_SDP     AF_INET_SDP
+#define PF_INET6_SDP    AF_INET6_SDP
+
+#define PF_MAX          AF_MAX
+#endif
+
 #ifndef _SA_FAMILY_T_DECLARED
 typedef __sa_family_t  sa_family_t;
 #define _SA_FAMILY_T_DECLARED
 #endif
 
+#include <sys/_sockaddr_storage.h>
+
 __BEGIN_DECLS
 ssize_t recv(int sockfd, void *buf, size_t len, int flags);
 ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                  struct sockaddr *src_addr, socklen_t *addrlen);
+ssize_t recvmsg(int, struct msghdr *, int);
 ssize_t send(int sockfd, const void *buf, size_t len, int flags);
 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                const struct sockaddr *dest_addr, socklen_t addrlen);
+ssize_t sendmsg(int, const struct msghdr *, int);
 int socket(int domain, int type, int protocol);
 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
 int listen(int sockfd, int backlog);
index b645182..0693e42 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2008, 2009, 2011, 2012, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2011, 2012, 2013, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -69,6 +69,7 @@ __BEGIN_DECLS
 mode_t umask(mode_t mask);
 int chmod(const char *path, mode_t mode);
 int mkdir(const char *pathname, int mode);
+int mkfifo(const char *pathname, mode_t mode);
 int stat(const char *pathname, struct stat *buf);
 int fstat(int fd, struct stat*buf);
 int lstat(const char *path, struct stat *buf);
diff --git a/include/sys/syslog.h b/include/sys/syslog.h
new file mode 100644 (file)
index 0000000..6f12831
--- /dev/null
@@ -0,0 +1,203 @@
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)syslog.h    8.1 (Berkeley) 6/2/93
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_SYSLOG_H_
+#define _SYS_SYSLOG_H_
+
+#define        _PATH_LOG       "/var/run/log"
+#define        _PATH_LOG_PRIV  "/var/run/logpriv"
+#define        _PATH_OLDLOG    "/dev/log"      /* backward compatibility */
+
+/*
+ * priorities/facilities are encoded into a single 32-bit quantity, where the
+ * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility
+ * (0-big number).  Both the priorities and the facilities map roughly
+ * one-to-one to strings in the syslogd(8) source code.  This mapping is
+ * included in this file.
+ *
+ * priorities (these are ordered)
+ */
+#define        LOG_EMERG       0       /* system is unusable */
+#define        LOG_ALERT       1       /* action must be taken immediately */
+#define        LOG_CRIT        2       /* critical conditions */
+#define        LOG_ERR         3       /* error conditions */
+#define        LOG_WARNING     4       /* warning conditions */
+#define        LOG_NOTICE      5       /* normal but significant condition */
+#define        LOG_INFO        6       /* informational */
+#define        LOG_DEBUG       7       /* debug-level messages */
+
+#define        LOG_PRIMASK     0x07    /* mask to extract priority part (internal) */
+                               /* extract priority */
+#define        LOG_PRI(p)      ((p) & LOG_PRIMASK)
+#define        LOG_MAKEPRI(fac, pri)   ((fac) | (pri))
+
+#ifdef SYSLOG_NAMES
+#define        INTERNAL_NOPRI  0x10    /* the "no priority" priority */
+                               /* mark "facility" */
+#define        INTERNAL_MARK   LOG_MAKEPRI((LOG_NFACILITIES<<3), 0)
+typedef struct _code {
+       const char      *c_name;
+       int             c_val;
+} CODE;
+
+CODE prioritynames[] = {
+       { "alert",      LOG_ALERT,      },
+       { "crit",       LOG_CRIT,       },
+       { "debug",      LOG_DEBUG,      },
+       { "emerg",      LOG_EMERG,      },
+       { "err",        LOG_ERR,        },
+       { "error",      LOG_ERR,        },      /* DEPRECATED */
+       { "info",       LOG_INFO,       },
+       { "none",       INTERNAL_NOPRI, },      /* INTERNAL */
+       { "notice",     LOG_NOTICE,     },
+       { "panic",      LOG_EMERG,      },      /* DEPRECATED */
+       { "warn",       LOG_WARNING,    },      /* DEPRECATED */
+       { "warning",    LOG_WARNING,    },
+       { NULL,         -1,             }
+};
+#endif
+
+/* facility codes */
+#define        LOG_KERN        (0<<3)  /* kernel messages */
+#define        LOG_USER        (1<<3)  /* random user-level messages */
+#define        LOG_MAIL        (2<<3)  /* mail system */
+#define        LOG_DAEMON      (3<<3)  /* system daemons */
+#define        LOG_AUTH        (4<<3)  /* authorization messages */
+#define        LOG_SYSLOG      (5<<3)  /* messages generated internally by syslogd */
+#define        LOG_LPR         (6<<3)  /* line printer subsystem */
+#define        LOG_NEWS        (7<<3)  /* network news subsystem */
+#define        LOG_UUCP        (8<<3)  /* UUCP subsystem */
+#define        LOG_CRON        (9<<3)  /* clock daemon */
+#define        LOG_AUTHPRIV    (10<<3) /* authorization messages (private) */
+                               /* Facility #10 clashes in DEC UNIX, where */
+                               /* it's defined as LOG_MEGASAFE for AdvFS  */
+                               /* event logging.                          */
+#define        LOG_FTP         (11<<3) /* ftp daemon */
+#define        LOG_NTP         (12<<3) /* NTP subsystem */
+#define        LOG_SECURITY    (13<<3) /* security subsystems (firewalling, etc.) */
+#define        LOG_CONSOLE     (14<<3) /* /dev/console output */
+
+       /* other codes through 15 reserved for system use */
+#define        LOG_LOCAL0      (16<<3) /* reserved for local use */
+#define        LOG_LOCAL1      (17<<3) /* reserved for local use */
+#define        LOG_LOCAL2      (18<<3) /* reserved for local use */
+#define        LOG_LOCAL3      (19<<3) /* reserved for local use */
+#define        LOG_LOCAL4      (20<<3) /* reserved for local use */
+#define        LOG_LOCAL5      (21<<3) /* reserved for local use */
+#define        LOG_LOCAL6      (22<<3) /* reserved for local use */
+#define        LOG_LOCAL7      (23<<3) /* reserved for local use */
+
+#define        LOG_NFACILITIES 24      /* current number of facilities */
+#define        LOG_FACMASK     0x03f8  /* mask to extract facility part */
+                               /* facility of pri */
+#define        LOG_FAC(p)      (((p) & LOG_FACMASK) >> 3)
+
+#ifdef SYSLOG_NAMES
+CODE facilitynames[] = {
+       { "auth",       LOG_AUTH,       },
+       { "authpriv",   LOG_AUTHPRIV,   },
+       { "console",    LOG_CONSOLE,    },
+       { "cron",       LOG_CRON,       },
+       { "daemon",     LOG_DAEMON,     },
+       { "ftp",        LOG_FTP,        },
+       { "kern",       LOG_KERN,       },
+       { "lpr",        LOG_LPR,        },
+       { "mail",       LOG_MAIL,       },
+       { "mark",       INTERNAL_MARK,  },      /* INTERNAL */
+       { "news",       LOG_NEWS,       },
+       { "ntp",        LOG_NTP,        },
+       { "security",   LOG_SECURITY,   },
+       { "syslog",     LOG_SYSLOG,     },
+       { "user",       LOG_USER,       },
+       { "uucp",       LOG_UUCP,       },
+       { "local0",     LOG_LOCAL0,     },
+       { "local1",     LOG_LOCAL1,     },
+       { "local2",     LOG_LOCAL2,     },
+       { "local3",     LOG_LOCAL3,     },
+       { "local4",     LOG_LOCAL4,     },
+       { "local5",     LOG_LOCAL5,     },
+       { "local6",     LOG_LOCAL6,     },
+       { "local7",     LOG_LOCAL7,     },
+       { NULL,         -1,             }
+};
+#endif
+
+#ifdef _KERNEL
+#define        LOG_PRINTF      -1      /* pseudo-priority to indicate use of printf */
+#endif
+
+/*
+ * arguments to setlogmask.
+ */
+#define        LOG_MASK(pri)   (1 << (pri))            /* mask for one priority */
+#define        LOG_UPTO(pri)   ((1 << ((pri)+1)) - 1)  /* all priorities through pri */
+
+/*
+ * Option flags for openlog.
+ *
+ * LOG_ODELAY no longer does anything.
+ * LOG_NDELAY is the inverse of what it used to be.
+ */
+#define        LOG_PID         0x01    /* log the pid with each message */
+#define        LOG_CONS        0x02    /* log on the console if errors in sending */
+#define        LOG_ODELAY      0x04    /* delay open until first syslog() (default) */
+#define        LOG_NDELAY      0x08    /* don't delay open */
+#define        LOG_NOWAIT      0x10    /* don't wait for console forks: DEPRECATED */
+#define        LOG_PERROR      0x20    /* log to stderr as well */
+
+#ifdef _KERNEL
+
+#else /* not _KERNEL */
+
+/*
+ * Don't use va_list in the vsyslog() prototype.   Va_list is typedef'd in two
+ * places (<machine/varargs.h> and <machine/stdarg.h>), so if we include one
+ * of them here we may collide with the utility's includes.  It's unreasonable
+ * for utilities to have to include one of them to include syslog.h, so we get
+ * __va_list from <sys/_types.h> and use it.
+ */
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+__BEGIN_DECLS
+void   closelog(void);
+void   openlog(const char *, int, int);
+int    setlogmask(int);
+void   syslog(int, const char *, ...) __printflike(2, 3);
+#if __BSD_VISIBLE
+void   vsyslog(int, const char *, __va_list) __printflike(2, 0);
+#endif
+__END_DECLS
+
+#endif /* !_KERNEL */
+
+#endif
index 93c82b8..d5edefd 100644 (file)
@@ -67,6 +67,9 @@ typedef unsigned int    uint;           /* Sys V compatibility */
 #endif
 #endif
 
+typedef char *          caddr_t;        /* core address */
+typedef const char *    c_caddr_t;      /* core address, pointer to const */
+
 //typedef int fd_set;
 typedef long ino_t;
 typedef long dev_t;
@@ -91,11 +94,21 @@ typedef __clock_t clock_t;
 #define _CLOCK_T_DECLARED
 #endif
 
+#ifndef _CLOCKID_T_DECLARED
+typedef __clockid_t     clockid_t;
+#define _CLOCKID_T_DECLARED
+#endif
+
 #ifndef _TIME_T_DECLARED
 typedef __time_t  time_t;
 #define _TIME_T_DECLARED
 #endif
 
+struct timespec {
+    time_t  tv_sec;         /* seconds */
+    long    tv_nsec;        /* and nanoseconds */
+};
+
 #ifndef _UID_T_DECLARED
 typedef __uid_t   uid_t;
 #define _UID_T_DECLARED
@@ -106,6 +119,11 @@ typedef __gid_t gid_t;
 #define _GID_T_DECLARED
 #endif
 
+#ifndef _SA_FAMILY_T_DECLARED
+typedef __sa_family_t  sa_family_t;
+#define _SA_FAMILY_T_DECLARED
+#endif
+
 typedef unsigned long useconds_t;
 typedef long suseconds_t;
 
diff --git a/include/sysexits.h b/include/sysexits.h
new file mode 100644 (file)
index 0000000..e52bb5b
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1987, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *     @(#)sysexits.h  8.1 (Berkeley) 6/2/93
+ *
+ * $FreeBSD$
+ */
+
+#ifndef        _SYSEXITS_H_
+#define        _SYSEXITS_H_
+
+/*
+ *  SYSEXITS.H -- Exit status codes for system programs.
+ *
+ *     This include file attempts to categorize possible error
+ *     exit statuses for system programs, notably delivermail
+ *     and the Berkeley network.
+ *
+ *     Error numbers begin at EX__BASE to reduce the possibility of
+ *     clashing with other exit statuses that random programs may
+ *     already return.  The meaning of the codes is approximately
+ *     as follows:
+ *
+ *     EX_USAGE -- The command was used incorrectly, e.g., with
+ *             the wrong number of arguments, a bad flag, a bad
+ *             syntax in a parameter, or whatever.
+ *     EX_DATAERR -- The input data was incorrect in some way.
+ *             This should only be used for user's data & not
+ *             system files.
+ *     EX_NOINPUT -- An input file (not a system file) did not
+ *             exist or was not readable.  This could also include
+ *             errors like "No message" to a mailer (if it cared
+ *             to catch it).
+ *     EX_NOUSER -- The user specified did not exist.  This might
+ *             be used for mail addresses or remote logins.
+ *     EX_NOHOST -- The host specified did not exist.  This is used
+ *             in mail addresses or network requests.
+ *     EX_UNAVAILABLE -- A service is unavailable.  This can occur
+ *             if a support program or file does not exist.  This
+ *             can also be used as a catchall message when something
+ *             you wanted to do doesn't work, but you don't know
+ *             why.
+ *     EX_SOFTWARE -- An internal software error has been detected.
+ *             This should be limited to non-operating system related
+ *             errors as possible.
+ *     EX_OSERR -- An operating system error has been detected.
+ *             This is intended to be used for such things as "cannot
+ *             fork", "cannot create pipe", or the like.  It includes
+ *             things like getuid returning a user that does not
+ *             exist in the passwd file.
+ *     EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
+ *             etc.) does not exist, cannot be opened, or has some
+ *             sort of error (e.g., syntax error).
+ *     EX_CANTCREAT -- A (user specified) output file cannot be
+ *             created.
+ *     EX_IOERR -- An error occurred while doing I/O on some file.
+ *     EX_TEMPFAIL -- temporary failure, indicating something that
+ *             is not really an error.  In sendmail, this means
+ *             that a mailer (e.g.) could not create a connection,
+ *             and the request should be reattempted later.
+ *     EX_PROTOCOL -- the remote system returned something that
+ *             was "not possible" during a protocol exchange.
+ *     EX_NOPERM -- You did not have sufficient permission to
+ *             perform the operation.  This is not intended for
+ *             file system problems, which should use NOINPUT or
+ *             CANTCREAT, but rather for higher level permissions.
+ */
+
+#define EX_OK          0       /* successful termination */
+
+#define EX__BASE       64      /* base value for error messages */
+
+#define EX_USAGE       64      /* command line usage error */
+#define EX_DATAERR     65      /* data format error */
+#define EX_NOINPUT     66      /* cannot open input */
+#define EX_NOUSER      67      /* addressee unknown */
+#define EX_NOHOST      68      /* host name unknown */
+#define EX_UNAVAILABLE 69      /* service unavailable */
+#define EX_SOFTWARE    70      /* internal software error */
+#define EX_OSERR       71      /* system error (e.g., can't fork) */
+#define EX_OSFILE      72      /* critical OS file missing */
+#define EX_CANTCREAT   73      /* can't create (user) output file */
+#define EX_IOERR       74      /* input/output error */
+#define EX_TEMPFAIL    75      /* temp failure; user is invited to retry */
+#define EX_PROTOCOL    76      /* remote error in protocol */
+#define EX_NOPERM      77      /* permission denied */
+#define EX_CONFIG      78      /* configuration error */
+
+#define EX__MAX        78      /* maximum listed value */
+
+#endif /* !_SYSEXITS_H_ */
diff --git a/include/syslog.h b/include/syslog.h
new file mode 100644 (file)
index 0000000..830b492
--- /dev/null
@@ -0,0 +1 @@
+#include <sys/syslog.h>
index ab92fa5..1a7a77e 100644 (file)
@@ -49,6 +49,8 @@
 #include <pwd.h>
 #include <fcntl.h> // for pid_t
 #include <sys/socket.h>
+#include <sys/select.h>
+#include <getopt.h>
 
 #define        R_OK 4
 #define        W_OK 2
@@ -253,6 +255,8 @@ long         sysconf(int name);
 char        *ttyname(int fd);
 int          unlink(const char*pathname);
 int          write(int fd, const void *buf, size_t len);
+int          usleep(useconds_t usec);
+unsigned int sleep(unsigned int seconds);
 __END_DECLS
 
 #endif // __BF_UNISTD_H
index aca427d..feda23b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2008, 2009, 2011, 2012, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2011, 2013, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -16,7 +16,8 @@
 __BEGIN_DECLS
 
 #define MIN_FD  0
-#define MAX_FD  132
+//#define MAX_FD  132
+#define MAX_FD  4096
 
 enum fdtab_type {
     FDTAB_TYPE_AVAILABLE,
@@ -26,10 +27,20 @@ enum fdtab_type {
     FDTAB_TYPE_STDOUT,
     FDTAB_TYPE_STDERR,
     FDTAB_TYPE_LWIP_SOCKET,
+    FDTAB_TYPE_EPOLL_INSTANCE,
     FDTAB_TYPE_PTM,         ///< master side of pseudo-terminal
     FDTAB_TYPE_PTS,         ///< slave side of pseudo-terminal
 };
 
+#include <signal.h>
+#include <sys/epoll.h>
+
+struct _epoll_events_list {
+    struct _epoll_events_list *prev, *next;
+    struct epoll_event event;
+    int fd;
+};
+
 struct fdtab_entry {
     enum fdtab_type     type;
 //    union {
@@ -37,6 +48,8 @@ struct fdtab_entry {
         int             fd;
         int             inherited;
 //    };
+    int epoll_fd;
+    struct _epoll_events_list epoll_events;
 };
 
 int fdtab_alloc(struct fdtab_entry *h);
index 3cc5b1b..1edfa99 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2013, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
 #include <arch/x86/perfmon.h>
 #include <arch/x86/apic.h>
 
-static bool perfmon_amd = false;
-static bool perfmon_intel = false;
+static bool perfmon_amd = false, perfmon_intel = false;
 /* static bool perfmon_measurement_running = false; */
 /* static bool perfmon_apic_activated = false; */
 static uint64_t perfmon_cntr_init = 0;
-struct capability perfmon_callback_ep;
-
+struct capability perfmon_callback_ep = {
+    .type = ObjType_Null,
+};
 
 void perfmon_init(void) 
 {
@@ -75,13 +75,18 @@ void perfmon_measure_start(uint8_t event, uint8_t umask,
         }
     }
 
-    // Activate performance measurement for Intel
     if(perfmon_amd) {
-        
         perfmon_amd_measure_write(ctr*-1, 0);
         perfmon_amd_measure_start(event, umask, kernel, counter_id, ctr!=0);
-        perfmon_cntr_init = ctr;
     }
+
+    // Activate performance measurement for Intel
+    if(perfmon_intel) {
+        perfmon_intel_measure_write(ctr*-1);
+        perfmon_intel_measure_start(event, umask, kernel, counter_id, ctr!=0);
+    }
+
+    perfmon_cntr_init = ctr;
 }
 
 /*
@@ -93,8 +98,11 @@ void perfmon_measure_reset(void)
     if(perfmon_amd) {
         perfmon_amd_measure_write(perfmon_cntr_init*-1, 0);
     }
+    if(perfmon_intel) {
+        perfmon_intel_reset();
+        perfmon_intel_measure_write(perfmon_cntr_init*-1);
+    }
 }
-    
 
 uint64_t perfmon_measure_read(void)
 {
@@ -130,8 +138,6 @@ void perfmon_measure_stop(void)
 {
     if(perfmon_amd) {
         perfmon_amd_measure_stop(0);
-    } else if(perfmon_intel) {
-        panic("Intel performance monitoring not supported yet.");
     }
 
     // Mask out performance counter overflow interrupts on APIC
index 25ce071..b421b8b 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2013, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -36,30 +36,46 @@ errval_t perfmon_intel_init(void)
 
     cpuid_apm_gen_t apmgen = cpuid_apm_gen_rd(&mycpuid);
 
-    printf("Architectural Performance Monitoring version %d, # counters %d, "
-           "# events %d\n", apmgen.version, apmgen.num_counters,
+    printf("Architectural Performance Monitoring version %d, # counters %d "
+           "(%d bits wide), # events %d\n",
+           apmgen.version, apmgen.num_counters, apmgen.width,
            apmgen.vec_length);
 
-    if(apmgen.version == 2) {
+    if(apmgen.version >= 2) {
         cpuid_apm_fixed_t apmfixed = cpuid_apm_fixed_rd(&mycpuid);
-
-        printf("# fixed function counters %d\n", apmfixed.num);
+        printf("# fixed function counters %d (%d bits wide)\n",
+               apmfixed.num, apmfixed.width);
     }
 
     char str[256];
     cpuid_apm_feat_pr(str, 256, &mycpuid);
     printf("Supported events:\n%s\n", str);
 
+    uint32_t apmfeat = cpuid_apm_feat_rd_raw(&mycpuid);
+    printf("Supported events: %x\n", apmfeat);
+
+    uint32_t status = ia32_perf_global_ctrl_rd(&ia32);
+    printf("Enabling counter %d, old val %x\n", 0, status);
+    ia32_perf_global_ctrl_pmc0_wrf(&ia32, 1);
+
     return SYS_ERR_OK;
 }
 
-void perfmon_intel_measure_start(uint8_t event, uint8_t umask)
+void perfmon_intel_reset(void)
+{
+    uint32_t status = ia32_perf_global_status_rd(&ia32);
+    ia32_perf_global_over_wr(&ia32, status);
+}
+
+void perfmon_intel_measure_start(uint8_t event, uint8_t umask, bool os, 
+                                 uint8_t idx, bool intr)
 {
     ia32_perfevtsel_t sel0 = ia32_perfevtsel_default;
     sel0 = ia32_perfevtsel_evsel_insert(sel0, event);
     sel0 = ia32_perfevtsel_umask_insert(sel0, umask);
-    sel0 = ia32_perfevtsel_usr_insert  (sel0, 1);
-    sel0 = ia32_perfevtsel_os_insert   (sel0, 0);
+    sel0 = ia32_perfevtsel_usr_insert(sel0, 1);
+    sel0 = ia32_perfevtsel_os_insert(sel0, os ? 1 : 0);
+    sel0 = ia32_perfevtsel_intr_insert(sel0, intr ? 1 : 0);
     sel0 = ia32_perfevtsel_en_insert   (sel0, 1);
     ia32_perfevtsel0_wr(&ia32, sel0);
 }
index 8b1b75c..fd6a3b5 100644 (file)
@@ -426,8 +426,8 @@ static void send_user_interrupt(int irq)
         if (err_no(err) == SYS_ERR_LMP_BUF_OVERFLOW) {
             struct dispatcher_shared_generic *disp =
                 get_dispatcher_shared_generic(cap->u.endpoint.listener->disp);
-            printk(LOG_DEBUG, "%.*s: IRQ message buffer overflow\n",
-                   DISP_NAME_LEN, disp->name);
+            printk(LOG_DEBUG, "%.*s: IRQ message buffer overflow on IRQ %d\n",
+                   DISP_NAME_LEN, disp->name, irq);
         } else {
             printk(LOG_ERR, "Unexpected error delivering IRQ\n");
         }
@@ -818,10 +818,10 @@ static __attribute__ ((used)) void handle_irq(int vector)
     // APIC timer interrupt: handle in kernel and reschedule
     if (vector == APIC_TIMER_INTERRUPT_VECTOR) {
         apic_eoi();
-        assert(kernel_ticks_enabled);
-        update_kernel_now();
-        trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_TIMER, kernel_now);
-        wakeup_check(kernel_now);
+       assert(kernel_ticks_enabled);
+       update_kernel_now();
+       trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_TIMER, kernel_now);
+       wakeup_check(kernel_now);
     } else if (vector == APIC_PERFORMANCE_INTERRUPT_VECTOR) {
         // Handle performance counter overflow
         // Reset counters
@@ -840,19 +840,19 @@ static __attribute__ ((used)) void handle_irq(int vector)
             };
             strncpy(data.name, disp->name, PERFMON_DISP_NAME_LEN);
 
-            // Call overflow handler represented by endpoint
+                // Call overflow handler represented by endpoint
             extern struct capability perfmon_callback_ep;
-            errval_t err;
-            size_t payload_len = sizeof(struct perfmon_overflow_data)/
-                sizeof(uintptr_t)+1;
-            err = lmp_deliver_payload(&perfmon_callback_ep,
-                                      NULL,
-                                      (uintptr_t*) &data,
-                                      payload_len,
-                                      false);
-
-            // Make sure delivery was okay. SYS_ERR_LMP_BUF_OVERFLOW is okay for now
-            assert(err_is_ok(err) || err_no(err)==SYS_ERR_LMP_BUF_OVERFLOW);
+           errval_t err;
+           size_t payload_len = sizeof(struct perfmon_overflow_data)/
+             sizeof(uintptr_t)+1;
+           err = lmp_deliver_payload(&perfmon_callback_ep,
+                                     NULL,
+                                     (uintptr_t*) &data,
+                                     payload_len,
+                                     false);
+
+                // Make sure delivery was okay. SYS_ERR_LMP_BUF_OVERFLOW is okay for now
+                assert(err_is_ok(err) || err_no(err)==SYS_ERR_LMP_BUF_OVERFLOW);
         } else {
             // This should never happen, as interrupts are disabled in kernel
             printf("Performance counter overflow interrupt from "
@@ -917,7 +917,7 @@ static __attribute__ ((used)) void handle_irq(int vector)
  * \param cpu_save_area  Pointer to save area for registers stacked by CPU
  * \param disp_save_area Pointer to save area in dispatcher
  */
-static __attribute__ ((used)) void
+static __attribute__ ((used, noreturn)) void
 generic_handle_irq(int vector,
                    uintptr_t * NONNULL COUNT(X86_SAVE_AREA_SIZE) cpu_save_area,
                    struct registers_x86_64 *disp_save_area)
@@ -942,6 +942,7 @@ generic_handle_irq(int vector,
     }
 
     handle_irq(vector);
+    resume(disp_save_area);
 }
 
 /* Utility function for code below; initialises a gate_descriptor */
index 0d268e6..b363976 100644 (file)
@@ -418,7 +418,10 @@ static void create_phys_caps(lpaddr_t init_alloc_addr)
                 debug(SUBSYS_STARTUP, "RAM %lx--%lx\n", base_addr, end_addr);
                 err = create_caps_to_cnode(base_addr, end_addr - base_addr,
                                            RegionType_Empty, &spawn_state, bootinfo);
-                assert(err_is_ok(err));
+                if(err_is_fail(err)) {
+                   printk(LOG_WARN, "Skipping RAM %lx--%lx...\n", base_addr, end_addr);
+                }
+                /* assert(err_is_ok(err)); */
             }
         } else if (mmap->base_addr > local_phys_to_gen_phys(init_alloc_addr)) {
             /* XXX: The multiboot spec just says that mapping types other than
index 88fcb68..dcfe04b 100644 (file)
@@ -33,6 +33,7 @@
 #include <arch/x86/timing.h>
 #include <fpu.h>
 #include <arch/x86/ipi_notify.h>
+#include <amd_vmcb_dev.h>
 
 #define MIN(a,b)        ((a) < (b) ? (a) : (b))
 
@@ -900,6 +901,11 @@ struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
                     save_area = &disp->enabled_save_area;
                 }
 
+               // Should be enabled. Else, how do we do an invocation??
+               if(dcb_current->disabled) {
+                 panic("Dispatcher needs to be enabled for this invocation");
+               }
+
                 // save calling dispatcher's registers, so that when the dispatcher
                 // next runs, it has a valid state in the relevant save area.
                 // Save RIP, RFLAGS, RSP and set RAX (return value) for later resume
@@ -908,17 +914,25 @@ struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
                 save_area->eflags = rflags;
                 save_area->rsp = user_stack_save;
 
-                /* save and zero FS/GS selectors (they're unmodified by the syscall path) */
-                __asm ("mov     %%fs, %[fs]     \n\t"
-                       "mov     %%gs, %[gs]     \n\t"
-                       "mov     %[zero], %%fs   \n\t"
-                       "mov     %[zero], %%gs   \n\t"
-                       : /* No output */
-                       :
-                       [fs] "m" (save_area->fs),
-                       [gs] "m" (save_area->gs),
-                       [zero] "r" (0)
-                       );
+               if(!dcb_current->is_vm_guest) {
+                 /* save and zero FS/GS selectors (they're unmodified by the syscall path) */
+                 __asm ("mov     %%fs, %[fs]     \n\t"
+                        "mov     %%gs, %[gs]     \n\t"
+                        "mov     %[zero], %%fs   \n\t"
+                        "mov     %[zero], %%gs   \n\t"
+                        : /* No output */
+                        :
+                        [fs] "m" (save_area->fs),
+                        [gs] "m" (save_area->gs),
+                        [zero] "r" (0)
+                        );
+               } else {
+                 lpaddr_t lpaddr = gen_phys_to_local_phys(dcb_current->guest_desc.vmcb.cap.u.frame.base);
+                 amd_vmcb_t vmcb;
+                 amd_vmcb_initialize(&vmcb, (void *)local_phys_to_mem(lpaddr));
+                 save_area->fs = amd_vmcb_fs_selector_rd(&vmcb);
+                 save_area->gs = amd_vmcb_gs_selector_rd(&vmcb);
+               }
 
                 dispatch(to->u.endpoint.listener);
                 panic("dispatch returned");
@@ -1007,6 +1021,10 @@ struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
             retval.value = timing_get_apic_ticks_per_sec();
             break;
 
+        case DEBUG_GET_APIC_ID:
+            retval.value = apic_get_id();
+            break;
+
         default:
             printk(LOG_ERR, "invalid sys_debug msg type\n");
         }
index e9a7310..878f910 100644 (file)
@@ -20,6 +20,7 @@
 #include <dispatch.h>
 #include <exec.h>
 #include <barrelfish_kpi/vmkit.h>
+#include <barrelfish_kpi/syscalls.h>
 
 #include <amd_vmcb_dev.h>
 
@@ -214,6 +215,33 @@ vmkit_switch_from (struct dcb *dcb)
 }
 
 void __attribute__ ((noreturn))
+vmkit_vmexec (struct dcb *dcb, lvaddr_t entry)
+{
+  dispatcher_handle_t handle = dcb->disp;
+  struct dispatcher_shared_generic *disp = get_dispatcher_shared_generic(handle);
+  lpaddr_t lpaddr = gen_phys_to_local_phys(dcb->guest_desc.ctrl.cap.u.frame.base);
+  struct guest_control *ctrl = (void *)local_phys_to_mem(lpaddr);
+  lpaddr = gen_phys_to_local_phys(dcb->guest_desc.vmcb.cap.u.frame.base);
+  amd_vmcb_t vmcb;
+  amd_vmcb_initialize(&vmcb, (void *)local_phys_to_mem(lpaddr));
+
+  memset(&ctrl->regs, 0, sizeof(struct registers_x86_64));
+  ctrl->regs.rdi = disp->udisp;
+  amd_vmcb_rip_wr(&vmcb, disp->dispatcher_run);
+  amd_vmcb_rsp_wr(&vmcb, 0);
+  amd_vmcb_rax_wr(&vmcb, 0);
+  amd_vmcb_rflags_wr_raw(&vmcb, USER_RFLAGS);
+  amd_vmcb_fs_selector_wr(&vmcb, 0);
+  amd_vmcb_gs_selector_wr(&vmcb, 0);
+  vmkit_vmenter(dcb);
+}
+
+struct sysret sys_syscall(uint64_t syscall, uint64_t arg0, uint64_t arg1,
+                          uint64_t *args, uint64_t rflags, uint64_t rip);
+
+extern uint64_t user_stack_save;
+
+void __attribute__ ((noreturn))
 vmkit_vmenter (struct dcb *dcb)
 {
     lpaddr_t lpaddr = gen_phys_to_local_phys(dcb->guest_desc.ctrl.cap.u.frame.base);
@@ -237,28 +265,88 @@ vmkit_vmenter (struct dcb *dcb)
         amd_vmcb_cr3_wr(&vmcb, dcb->vspace);
     }
 
+ vmenter_loop:
+
+    /* printf("vmenter IN\n"); */
+
     // Enter the guest
     vmkit_switch_to(dcb);
     vm_exec(dcb);
     vmkit_switch_from(dcb);
 
+    /* printf("vmenter OUT\n"); */
+
     // Here we exited the guest due to some intercept triggered a vm exit
     // our state is automatically restored by SVM
 
     uint64_t ec = amd_vmcb_exitcode_rd(&vmcb);
     /* We treat exits due to pysical interrupts (INTR, NMI, SMI) specially since
      * they need to be processed by the kernel interrupt service routines */
-    if (ec == VMEXIT_INTR || ec == VMEXIT_NMI || ec == VMEXIT_SMI) {
+    switch(ec) {
+    case VMEXIT_INTR:
+    case VMEXIT_NMI:
+    case VMEXIT_SMI:
+      {
+       arch_registers_state_t *area = NULL;
+
+       /* printf("INT at %" PRIx64 "\n", amd_vmcb_rip_rd(&vmcb)); */
 
         ctrl->num_vm_exits_without_monitor_invocation++;
+
+       // Store user state into corresponding save area
+       if(dispatcher_is_disabled_ip(dcb->disp, amd_vmcb_rip_rd(&vmcb))) {
+         area = dispatcher_get_disabled_save_area(dcb->disp);
+         dcb->disabled = true;
+       } else {
+         area = dispatcher_get_enabled_save_area(dcb->disp);
+         dcb->disabled = false;
+       }
+       memcpy(area, &ctrl->regs, sizeof(arch_registers_state_t));
+       area->rax = amd_vmcb_rax_rd(&vmcb);
+       area->rip = amd_vmcb_rip_rd(&vmcb);
+       area->rsp = amd_vmcb_rsp_rd(&vmcb);
+       area->eflags = amd_vmcb_rflags_rd_raw(&vmcb);
+       area->fs = amd_vmcb_fs_selector_rd(&vmcb);
+       area->gs = amd_vmcb_gs_selector_rd(&vmcb);
+
         // wait for interrupt will enable interrupts and therefore trigger their
         // corresponding handlers (which may be the monitor)
         wait_for_interrupt();
-    } else {
+      }
+      break;
+
+    case VMEXIT_VMMCALL:
+      {
+       // Translate this to a SYSCALL
+       struct registers_x86_64 *regs = &ctrl->regs;
+       uint64_t args[10] = {
+         regs->r10, regs->r8, regs->r9, regs->r12, regs->r13, regs->r14,
+         regs->r15, amd_vmcb_rax_rd(&vmcb), regs->rbp, regs->rbx
+       };
+
+       /* printf("VMMCALL\n"); */
+
+       // Advance guest RIP to next instruction
+       amd_vmcb_rip_wr(&vmcb, amd_vmcb_rip_rd(&vmcb) + 3);
+       user_stack_save = amd_vmcb_rsp_rd(&vmcb);
+
+       struct sysret ret =
+         sys_syscall(regs->rdi, regs->rsi, regs->rdx, args,
+                     amd_vmcb_rflags_rd_raw(&vmcb),
+                     amd_vmcb_rip_rd(&vmcb));
+
+       amd_vmcb_rax_wr(&vmcb, ret.error);
+       regs->rdx = ret.value;
+      }
+      goto vmenter_loop;
+
+    default:
         ctrl->num_vm_exits_with_monitor_invocation++;
         /* the guest exited not due to an interrupt but some condition the
          * monitor has to handle, therefore notify the monitor */
 
+       /* printf("OTHER\n"); */
+
         assert(dcb->is_vm_guest);
 
         // disable the domain
@@ -267,10 +355,11 @@ vmkit_vmenter (struct dcb *dcb)
         // call the monitor
         errval_t err = lmp_deliver_notification(&dcb->guest_desc.monitor_ep.cap);
         if (err_is_fail(err)) {
-            printk(LOG_ERR, "Unexpected error delivering VMM call");
+            printk(LOG_ERR, "Unexpected error delivering VMEXIT");
         }
 
         // run the monitor
         dispatch(dcb->guest_desc.monitor_ep.cap.u.endpoint.listener);
+       break;
     }
 }
index 2c8cdc5..779f8db 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2009, 2010, 2011, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2013, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -230,12 +230,6 @@ void __attribute__ ((noreturn)) dispatch(struct dcb *dcb)
     }
 
     assert(dcb != NULL);
-#ifdef __x86_64__
-    if (dcb->is_vm_guest) {
-        vmkit_vmenter(dcb);
-        panic("vmkit_vmenter unexpectedly returned");
-    }
-#endif
 
     dispatcher_handle_t handle = dcb->disp;
     struct dispatcher_shared_generic *disp =
@@ -250,12 +244,24 @@ void __attribute__ ((noreturn)) dispatch(struct dcb *dcb)
               disp->name, (uint64_t)registers_get_ip(disabled_area));
         assert(dispatcher_is_disabled_ip(handle,
                                          registers_get_ip(disabled_area)));
-        resume(disabled_area);
+       if(!dcb->is_vm_guest) {
+         resume(disabled_area);
+#ifdef __x86_64__
+       } else {
+         vmkit_vmenter(dcb);
+#endif
+       }
     } else {
         debug(SUBSYS_DISPATCH, "dispatch %.*s\n", DISP_NAME_LEN, disp->name);
         assert(disp->dispatcher_run != 0);
         disp->disabled = 1;
-        execute(disp->dispatcher_run);
+       if(!dcb->is_vm_guest) {
+         execute(disp->dispatcher_run);
+#ifdef __x86_64__
+       } else {
+         vmkit_vmexec(dcb, disp->dispatcher_run);
+#endif
+       }
     }
 } // end function: dispatch
 
index a464a49..0297a84 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2007, 2008, 2009, 2010, ETH Zurich.
+ * Copyright (c) 2007, 2008, 2009, 2010, 2013, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
 
 errval_t perfmon_intel_init(void);
 
-void perfmon_intel_measure_start(uint8_t event, uint8_t umask);
+void perfmon_intel_measure_start(uint8_t event, uint8_t umask, bool os, 
+                                 uint8_t idx, bool intr);
 uint64_t perfmon_intel_measure_read(void);
 void perfmon_intel_measure_write(uint64_t val);
+void perfmon_intel_reset(void);
 
 #endif
index 97b4037..aeb9279 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 /*
- * Copyright (c) 2009, ETH Zurich.
+ * Copyright (c) 2009, 2013, ETH Zurich.
  * All rights reserved.
  *
  * This file is distributed under the terms in the attached LICENSE file.
@@ -21,5 +21,6 @@
 errval_t vmkit_enable_virtualization (void);
 int vmkit_disable_virtualization (void);
 void __attribute__ ((noreturn)) vmkit_vmenter (struct dcb *dcb);
+void __attribute__ ((noreturn)) vmkit_vmexec (struct dcb *dcb, lvaddr_t entry);
 
 #endif // _VMKIT_H
diff --git a/lib/arranet/Hakefile b/lib/arranet/Hakefile
new file mode 100644 (file)
index 0000000..82c0329
--- /dev/null
@@ -0,0 +1,17 @@
+--------------------------------------------------------------------------
+-- Copyright (c) 2007-2009, 2011, 2012, 2013, ETH Zurich.
+-- All rights reserved.
+--
+-- This file is distributed under the terms in the attached LICENSE file.
+-- If you do not find this file, copies can be found by writing to:
+-- ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+--
+-- Hakefile for lib/arranet
+-- 
+--------------------------------------------------------------------------
+
+[ build library { target = "arranet",
+                  cFiles = [ "arranet.c", "inet_chksum.c", "ip_addr.c" ],
+                  flounderDefs = [ "net_queue_manager" ]
+                }
+]
diff --git a/lib/arranet/arranet.c b/lib/arranet/arranet.c
new file mode 100644 (file)
index 0000000..fa06720
--- /dev/null
@@ -0,0 +1,2740 @@
+/*
+ * Copyright (c) 2014, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich. 
+ * Attn: Systems Group.
+ */
+
+/**
+ * \file
+ * \brief Arranet library code
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/inthandler.h>
+#include <sys/socket.h>
+#include <netif/e1000.h>
+#include <limits.h>
+#include <barrelfish/waitset.h>
+#include <barrelfish/waitset_chan.h>
+#include <lwip/sock_chan_support.h>
+#include <netdb.h>
+#include <arranet.h>
+#include <arranet_impl.h>
+
+#include "inet_chksum.h"
+
+#include <arranet_debug.h>
+
+static ether_terminate_queue ether_terminate_queue_ptr = NULL;
+static ether_get_mac_address_t ether_get_mac_address_ptr = NULL;
+static ether_transmit_pbuf_list_t ether_transmit_pbuf_list_ptr = NULL;
+static ether_get_tx_free_slots tx_free_slots_fn_ptr = NULL;
+static ether_handle_free_TX_slot handle_free_tx_slot_fn_ptr = NULL;
+static ether_rx_register_buffer rx_register_buffer_fn_ptr = NULL;
+static ether_rx_get_free_slots rx_get_free_slots_fn_ptr = NULL;
+
+uint64_t interrupt_counter = 0;
+uint64_t total_rx_p_count = 0;
+uint64_t total_rx_datasize = 0;
+struct client_closure *g_cl = NULL;
+
+//#define MAX_PACKETS     1024
+#define MAX_PACKETS     2000
+#define PACKET_SIZE     2048
+
+#define MAX_PEERS       256
+
+struct peer {
+    uint32_t ip;
+    struct eth_addr mac;
+};
+
+// Configure static ARP entries here
+// IP addresses are in network byte order!
+static struct peer peers[MAX_PEERS] = {
+    {
+        .ip = 0x0102000a,       // 10.0.2.1
+        .mac.addr = "\x86\x86\x0b\xda\x22\xd7",
+    },
+    {
+        .ip = 0xaf06d080,       // 128.208.6.175 - swingout2
+        .mac.addr = "\x90\xe2\xba\x3a\x2e\xdd",
+    },
+    {
+        .ip = 0xec06d080,       // 128.208.6.236 - swingout3
+        .mac.addr = "\xa0\x36\x9f\x0f\xfb\xe2",
+    },
+    {
+        .ip = 0x8106d080,       // 128.208.6.129 - swingout4
+        .mac.addr = "\xa0\x36\x9f\x10\x01\x6e",
+    },
+    {
+        .ip = 0x8206d080,       // 128.208.6.130 - swingout5
+        .mac.addr = "\xa0\x36\x9f\x10\x00\xa2",
+    },
+    {
+        .ip = 0xc506d080,       // 128.208.6.197 - swingout6
+        .mac.addr = "\xa0\x36\x9f\x10\x03\x52",
+    },
+};
+static int peers_alloc = 6;             // Set number of static ARP here!
+
+#ifdef DEBUG_LATENCIES
+static int rx_packets_available = MAX_PACKETS;
+#endif
+
+struct socket {
+    struct socket *prev, *next;
+    int fd;
+    bool passive, nonblocking, connected, hangup, shutdown;
+    struct sockaddr_in bound_addr;
+    struct sockaddr_in peer_addr;
+    uint32_t my_seq, peer_seq, next_ack;
+};
+
+struct pkt_udp_headers {
+    struct eth_hdr eth;
+    struct ip_hdr ip;
+    struct udp_hdr udp;
+} __attribute__ ((packed));
+
+struct pkt_tcp_headers {
+    struct eth_hdr eth;
+    struct ip_hdr ip;
+    struct tcp_hdr tcp;
+} __attribute__ ((packed));
+
+// All known connections and those in progress
+static struct socket *connections = NULL;
+
+static struct socket sockets[MAX_FD];
+static struct packet rx_packets[MAX_PACKETS];
+
+// XXX: Needs to be per socket later on
+static struct waitset_chanstate recv_chanstate;
+static struct waitset_chanstate send_chanstate;
+
+static struct packet *inpkt = NULL;
+
+#ifdef DEBUG_LATENCIES
+static size_t memcache_packets_received = 0;
+static size_t output_pipeline_stalled = 0;
+static size_t port_cnt[65536];
+static int lwip_send_time[POSIX_TRANSA];       // Time until packet was delivered to network interface
+static size_t lwip_send_transactions = 0;
+int posix_recv_time[POSIX_TRANSA];       // Time until packet at exit of recvfrom
+size_t posix_recv_transactions = 0;
+static int posix_send_time[POSIX_TRANSA];       // Time until packet at entry to sendto
+static size_t posix_send_transactions = 0;
+
+int memcache_times[20][POSIX_TRANSA];       // Time until packet was delivered to network interface
+size_t memcache_transactions[20];
+
+size_t hash_option1 = 0;
+size_t hash_option2 = 0;
+size_t hash_option3 = 0;
+size_t hash_length = 0;
+size_t hash_calls = 0;
+size_t hash_aligned = 0;
+size_t hash_unaligned = 0;
+#endif
+
+static bool arranet_udp_accepted = false;
+static bool arranet_tcp_accepted = false;
+
+//#define TCP_LOCAL_PORT_RANGE_START        0xc000
+#define TCP_LOCAL_PORT_RANGE_START        8081
+#define TCP_LOCAL_PORT_RANGE_END          0xffff
+
+static uint16_t free_tcp_ports[TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START + 1];
+static uint16_t free_tcp_tail = TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START,
+    free_tcp_free = TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START + 1;
+
+#ifdef SENDMSG_WITH_COPY
+static uint16_t free_tcp_head = 0;
+
+// In network byte order
+static uint16_t tcp_new_port(void)
+{
+  if(free_tcp_free > 0) {
+      free_tcp_free--;
+      u16_t new_port = free_tcp_ports[free_tcp_head];
+      free_tcp_head = (free_tcp_head + 1) % (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START + 1);
+      /* printf("Allocating port %d\n", new_port); */
+      return new_port;
+  } else {
+      printf("No more free ports!\n");
+      return 0;
+  }
+}
+#endif
+
+static void tcp_free_port(uint16_t port)
+{
+    /* if(pcb->local_port == 8080) { */
+    /*     return; */
+    /* } */
+    /* if(pcb->local_port == 8080) { */
+    /*     printf("Freeing 8080 from %p %p %p\n", */
+    /*            __builtin_return_address(0), */
+    /*            __builtin_return_address(1), */
+    /*            __builtin_return_address(2)); */
+    /* } */
+    /* assert(pcb->local_port != 8080); */
+    assert(free_tcp_free < TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START + 1);
+
+    /* printf("Freeing port %d\n", pcb->local_port); */
+
+    /* for(int i = 0; i < free_tcp_free; i++) { */
+    /*     u16_t entry = free_tcp_ports[(i + free_tcp_head) % (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START + 1)]; */
+    /*     assert(entry != pcb->local_port); */
+    /* } */
+
+    free_tcp_free++;
+    free_tcp_tail = (free_tcp_tail + 1) % (TCP_LOCAL_PORT_RANGE_END - TCP_LOCAL_PORT_RANGE_START + 1);
+    free_tcp_ports[free_tcp_tail] = port;
+}
+
+static struct socket *free_sockets_queue[MAX_FD];
+static int free_sockets_head = 0, free_sockets_tail = MAX_FD - 1,
+    free_sockets = MAX_FD;
+
+static struct socket *alloc_socket(void)
+{
+    if(free_sockets == 0) {
+        return NULL;
+    }
+
+    free_sockets--;
+    struct socket *new_socket = free_sockets_queue[free_sockets_head];
+    // Reset all fields except FD
+    int fd_save = new_socket->fd;
+    uint32_t seq_save = new_socket->my_seq;
+    memset(new_socket, 0, sizeof(struct socket));
+    new_socket->fd = fd_save;
+    new_socket->my_seq = seq_save + 1000;
+    free_sockets_head = (free_sockets_head + 1) % MAX_FD;
+    /* printf("alloc_socket: returned %p\n", new_socket); */
+    return new_socket;
+}
+
+static void free_socket(struct socket *sock)
+{
+    /* printf("free_socket: %p\n", sock); */
+    assert(sock != NULL);
+    assert(free_sockets < MAX_FD);
+    free_sockets++;
+    free_sockets_tail = (free_sockets_tail + 1) % MAX_FD;
+    free_sockets_queue[free_sockets_tail] = sock;
+}
+
+/******** IP config *********/
+
+struct mac2ip {
+    uint8_t mac[ETHARP_HWADDR_LEN];
+    uint32_t ip;
+};
+
+static struct mac2ip ip_config[] = {
+    {   // QEMU
+        .mac = "\x52\x54\x00\x12\x34\x56",
+        .ip = 0x0a00020f,       // 10.0.2.15
+    },
+    {
+        // QEMU2
+        .mac = "\x52\x54\x00\x12\x34\x57",
+        .ip = 0xc0a80102,       // 192.168.1.2
+    },
+    {   // swingout1 (and swingout1-vf0)
+        .mac = "\xa0\x36\x9f\x10\x00\xa6",
+        .ip = 0x80d00643,       // 128.208.6.67
+    },
+    {   // swingout1-vf1
+        .mac = "\x22\xc9\xfc\x96\x83\xfc",
+        .ip = 0x80d00644,       // 128.208.6.68
+    },
+    {   // swingout1-vf2
+        .mac = "\xce\x43\x5b\xf7\x3e\x60",
+        .ip = 0x80d00602,       // 128.208.6.2
+    },
+    {   // swingout1-vf3
+        .mac = "\x6a\xb0\x62\xf6\xa7\x21",
+        .ip = 0x80d00603,       // 128.208.6.3
+    },
+    {   // swingout1-vf4
+        .mac = "\xb2\xdf\xf9\x39\xc6\x10",
+        .ip = 0x80d00604,       // 128.208.6.4
+    },
+    {   // swingout1-vf5
+        .mac = "\x92\x77\xe7\x3f\x80\x30",
+        .ip = 0x80d0060c,       // 128.208.6.12
+    },
+    {   // swingout5
+        .mac = "\xa0\x36\x9f\x10\x00\xa2",
+        .ip = 0x80d00682,       // 128.208.6.130
+    },
+};
+
+static uint8_t arranet_mymac[ETHARP_HWADDR_LEN];
+static uint32_t arranet_myip = 0;
+
+/******** NYI *********/
+
+struct thread_mutex *lwip_mutex = NULL;
+struct waitset *lwip_waitset = NULL;
+
+void lwip_mutex_lock(void)
+{
+}
+
+void lwip_mutex_unlock(void)
+{
+}
+
+int lwip_read(int s, void *mem, size_t len)
+{
+    assert(!"NYI");
+}
+
+int lwip_write(int s, const void *data, size_t size)
+{
+    assert(!"NYI");
+}
+
+int lwip_fcntl(int s, int cmd, int val)
+{
+    struct socket *sock = &sockets[s];
+    int retval = 0;
+
+    switch(cmd) {
+    case F_GETFL:
+        retval = sock->nonblocking ? O_NONBLOCK : 0;
+        break;
+
+    case F_SETFL:
+        sock->nonblocking = val & O_NONBLOCK ? true : false;
+        break;
+
+    default:
+        assert(!"NYI");
+        retval = -1;
+        break;
+    }
+
+    return retval;
+}
+
+int lwip_listen(int s, int backlog)
+{
+    struct socket *sock = &sockets[s];
+    sock->passive = true;
+    return 0;
+}
+
+int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
+{
+    int retval = 0;
+
+    switch(level) {
+    case SOL_SOCKET:
+        switch(optname) {
+        case SO_SNDBUF:
+            {
+                assert(*optlen >= sizeof(int));
+                int *ret = optval;
+                *ret = PACKET_SIZE;
+                *optlen = sizeof(int);
+            }
+            break;
+
+        case SO_ERROR:
+            {
+                assert(*optlen >= sizeof(int));
+                int *ret = optval;
+                struct socket *sock = &sockets[s];
+                assert(sock != NULL);
+                *ret = sock->connected ? 0 : EINPROGRESS;
+                *optlen = sizeof(int);
+            }
+            break;
+
+        default:
+            assert(!"NYI");
+            retval = -1;
+            break;
+        }
+        break;
+
+    default:
+        assert(!"NYI");
+        retval = -1;
+        break;
+    }
+
+    return retval;
+}
+
+int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
+{
+    int retval = 0;
+
+    switch(level) {
+    case SOL_SOCKET:
+        switch(optname) {
+        case SO_REUSEADDR:
+        case SO_REUSEPORT:
+            // No-op
+            break;
+
+        case SO_SNDBUF:
+            {
+                int len = *(const int *)optval;
+                if(len > PACKET_SIZE) {
+                    retval = -1;
+                }
+            }
+            break;
+
+        default:
+            printf("%d, %d\n", level, optname);
+            assert(!"NYI");
+            retval = -1;
+            break;
+        }
+        break;
+
+    case IPPROTO_TCP:
+        switch(optname) {
+        case TCP_NODELAY:
+            // XXX: No-op. We don't support Nagling anyway.
+            break;
+        }
+        break;
+
+    default:
+        assert(!"NYI");
+        retval = -1;
+        break;
+    }
+
+    return retval;
+}
+
+int lwip_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
+{
+    struct socket *sock = &sockets[s];
+    assert(sock != NULL);
+    assert(*namelen >= sizeof(struct sockaddr_in));
+
+    memcpy(name, &sock->bound_addr, sizeof(struct sockaddr_in));
+    *namelen = sizeof(struct sockaddr_in);
+
+    return 0;
+}
+
+struct hostent *lwip_gethostbyname(const char *name)
+{
+    assert(!"NYI");
+}
+
+int lwip_getaddrinfo(const char *nodename, const char *servname,
+                     const struct addrinfo *hints, struct addrinfo **res)
+{
+    struct addrinfo *r = calloc(1, sizeof(struct addrinfo));
+    struct sockaddr_in *sa = calloc(1, sizeof(struct sockaddr_in));
+
+    assert(hints != NULL);
+
+    sa->sin_family = AF_INET;
+    sa->sin_port = htons(atoi(servname));
+    sa->sin_addr.s_addr = INADDR_ANY;
+
+    // Return dummy UDP socket address
+    r->ai_flags = AI_PASSIVE;
+    r->ai_family = AF_INET;
+    r->ai_socktype = SOCK_DGRAM;
+    r->ai_protocol = hints->ai_protocol;
+    r->ai_addrlen = sizeof(struct sockaddr_in);
+    r->ai_addr = (struct sockaddr *)sa;
+    r->ai_canonname = NULL;
+    r->ai_next = NULL;
+
+    *res = r;
+    return 0;
+}
+
+void lwip_freeaddrinfo(struct addrinfo *ai)
+{
+    for(struct addrinfo *i = ai; i != NULL;) {
+        struct addrinfo *oldi = i;
+        free(i->ai_addr);
+        i = i->ai_next;
+        free(oldi);
+    }
+}
+
+int lwip_getpeername (int s, struct sockaddr *name, socklen_t *namelen)
+{
+    assert(!"NYI");
+}
+
+/* The following 2 are #defined in lwIP 1.4.1, but not in 1.3.1, duplicating them here */
+
+int inet_aton(const char *cp, struct in_addr *addr)
+{
+    return ipaddr_aton(cp, (ip_addr_t *)addr);
+}
+
+u32_t inet_addr(const char *cp)
+{
+    return ipaddr_addr(cp);
+}
+
+/***** lwIP-compatibility functions, so that NFS and RPC code compiles *****/
+
+u8_t pbuf_free_tagged(struct pbuf *p, const char *func_name, int line_no)
+{
+    assert(!"NYI");
+}
+
+u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
+{
+    assert(!"NYI");
+}
+
+struct udp_pcb;
+
+err_t udp_send(struct udp_pcb *pcb, struct pbuf *p);
+err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
+{
+    assert(!"NYI");
+}
+
+struct udp_pcb *udp_new(void);
+struct udp_pcb *udp_new(void)
+{
+    assert(!"NYI");
+}
+
+void udp_recv(struct udp_pcb *pcb,
+              void (*recvfn) (void *arg, struct udp_pcb * upcb,
+                            struct pbuf * p,
+                            struct ip_addr * addr,
+                            u16_t port), void *recv_arg);
+void udp_recv(struct udp_pcb *pcb,
+              void (*recvfn) (void *arg, struct udp_pcb * upcb,
+                            struct pbuf * p,
+                            struct ip_addr * addr,
+                            u16_t port), void *recv_arg)
+{
+    assert(!"NYI");
+}
+
+void udp_remove(struct udp_pcb *pcb);
+void udp_remove(struct udp_pcb *pcb)
+{
+    assert(!"NYI");
+}
+
+err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port);
+err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
+{
+    assert(!"NYI");
+}
+
+struct pbuf *pbuf_alloc_tagged(pbuf_layer layer, u16_t length, pbuf_type type, const char *func_name, int line_no)
+{
+    assert(!"NYI");
+}
+
+void lwip_record_event_simple(uint8_t event_type, uint64_t ts);
+void lwip_record_event_simple(uint8_t event_type, uint64_t ts)
+{
+    assert(!"NYI");
+}
+
+uint64_t wrapper_perform_lwip_work(void);
+uint64_t wrapper_perform_lwip_work(void)
+{
+    assert(!"NYI");
+}
+
+bool lwip_init_auto(void);
+bool lwip_init_auto(void)
+{
+    assert(!"NYI");
+}
+
+/******** NYI END *********/
+
+void ethernetif_backend_init(char *service_name, uint64_t queueid,
+                             ether_get_mac_address_t get_mac_ptr,
+                             ether_terminate_queue terminate_queue_ptr,
+                             ether_transmit_pbuf_list_t transmit_ptr,
+                             ether_get_tx_free_slots tx_free_slots_ptr,
+                             ether_handle_free_TX_slot handle_free_tx_slot_ptr,
+                             size_t rx_bufsz,
+                             ether_rx_register_buffer rx_register_buffer_ptr,
+                             ether_rx_get_free_slots rx_get_free_slots_ptr)
+{
+    ether_terminate_queue_ptr = terminate_queue_ptr;
+    ether_get_mac_address_ptr = get_mac_ptr;
+    ether_transmit_pbuf_list_ptr = transmit_ptr;
+    tx_free_slots_fn_ptr = tx_free_slots_ptr;
+    handle_free_tx_slot_fn_ptr = handle_free_tx_slot_ptr;
+    rx_register_buffer_fn_ptr = rx_register_buffer_ptr;
+    rx_get_free_slots_fn_ptr = rx_get_free_slots_ptr;
+    /* printf("PBUF_POOL_BUFSIZE = %u, rx buffer size = %zu\n", PBUF_POOL_BUFSIZE, */
+    /*        rx_bufsz); */
+}
+
+#define MAX_DRIVER_BUFS         16
+
+static genpaddr_t rx_pbase = 0;
+static genvaddr_t rx_vbase = 0;
+
+static struct packet tx_packets[MAX_PACKETS];
+static uint8_t tx_bufs[MAX_PACKETS][PACKET_SIZE];
+static unsigned int tx_idx = 0;
+/* static ssize_t tx_packets_available = MAX_PACKETS; */
+
+static void packet_output(struct packet *p)
+{
+    struct driver_buffer bufs[MAX_DRIVER_BUFS];
+    int n = 0;
+
+#ifdef DEBUG_LATENCIES
+    if(memcache_transactions[6] < POSIX_TRANSA) {
+        if(p->next == NULL) {
+            assert(p->next == NULL && p->len >= sizeof(protocol_binary_request_no_extras));
+            protocol_binary_request_no_extras *mypayload = (void *)p->payload + SIZEOF_ETH_HDR + 20 + sizeof(struct udp_hdr) + UDP_HEADLEN;
+            memcache_times[6][memcache_transactions[6]] = get_time() - mypayload->message.header.request.opaque;
+            memcache_transactions[6]++;
+        } else {
+            protocol_binary_request_no_extras *mypayload = (void *)p->next->payload + UDP_HEADLEN;
+            memcache_times[6][memcache_transactions[6]] = get_time() - mypayload->message.header.request.opaque;
+            memcache_transactions[6]++;
+        }
+    }
+#endif
+
+    for (struct packet *q = p; q != NULL; q = q->next) {
+        struct driver_buffer *buf = &bufs[n];
+
+        /* if(q->payload < &tx_bufs[0][0] || q->payload >= &tx_bufs[MAX_PACKETS][PACKET_SIZE]) { */
+        /*     printf("Called from %p %p\n", */
+        /*            __builtin_return_address(0), */
+        /*            __builtin_return_address(1)); */
+        /*     assert(q->payload >= &tx_bufs[0][0] && q->payload < &tx_bufs[MAX_PACKETS][PACKET_SIZE]); */
+        /* } */
+
+        /* Send the data from the pbuf to the interface, one pbuf at a
+           time. The size of the data in each pbuf is kept in the ->len
+           variable. */
+        assert(q->len > 0);
+
+        // Check if it's from the RX region
+        if(((genvaddr_t)q->payload) >= rx_vbase &&
+           ((genvaddr_t)q->payload) < rx_vbase + (MAX_PACKETS * PACKET_SIZE + 4096)) {
+            buf->pa = rx_pbase + ((genvaddr_t)q->payload - rx_vbase);
+        } else {
+            // Check if it's in morecore's region
+            struct morecore_state *mc_state = get_morecore_state();
+            struct vspace_mmu_aware *mmu_state = &mc_state->mmu_state;
+            genvaddr_t base = vregion_get_base_addr(&mmu_state->vregion);
+            struct memobj_frame_list *i;
+
+            // Walk frame list
+            for(i = mmu_state->memobj.frame_list; i != NULL; i = i->next) {
+                // If address is completely within frame, we can resolve
+                // XXX: Everything else would be easier with an IOMMU
+                if(base + i->offset <= (genvaddr_t)q->payload &&
+                   ((genvaddr_t)q->payload) + q->len < base + i->offset + i->size) {
+                    assert(i->pa != 0);
+
+                    /* buf->pa = id.base + ((genvaddr_t)q->payload - base - i->offset); */
+                    buf->pa = i->pa + ((genvaddr_t)q->payload - base - i->offset);
+                    break;
+                }
+            }
+
+            if(i == NULL) {
+                // Check if it's in text/data region
+                int entry;
+                for(entry = 0; entry < mc_state->v2p_entries; entry++) {
+                    struct v2pmap *pmap = &mc_state->v2p_mappings[entry];
+
+                    if(pmap->va <= (genvaddr_t)q->payload &&
+                       ((genvaddr_t)q->payload) + q->len < pmap->va + pmap->size) {
+                        buf->pa = pmap->pa + ((genvaddr_t)q->payload - pmap->va);
+                        break;
+                    }
+                }
+
+                if(entry == mc_state->v2p_entries) {
+                    printf("Called from %p %p\n",
+                           __builtin_return_address(0),
+                           __builtin_return_address(1));
+
+                    USER_PANIC("Invalid pbuf! payload = %p, pa = %p\n", q->payload, buf->pa);
+                }
+            }
+        }
+
+        /* printf("Sending: '%s'\n", (char *)q->payload); */
+
+        buf->va = q->payload;
+        buf->len = q->len;
+#ifndef SENDMSG_WITH_COPY
+        buf->opaque = q->opaque;
+#else
+        buf->opaque = q;
+#endif
+        buf->flags = q->flags;
+
+        n++;
+    }
+
+#ifdef DEBUG_LATENCIES
+    if(lwip_send_transactions < POSIX_TRANSA) {
+        struct ip_hdr *iphdr = (struct ip_hdr *)(p->payload + SIZEOF_ETH_HDR);
+
+        if(IPH_PROTO(iphdr) == IP_PROTO_UDP) {
+            struct udp_hdr *udphdr = (struct udp_hdr *)(p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4));
+            if(htons(udphdr->src) == 11212 || htons(udphdr->src) == 11211) {
+                protocol_binary_response_no_extras *mypayload;
+                if(p->next != NULL) {
+                    mypayload = (void *)p->next->next->payload;
+                } else {
+                    mypayload = (void *)p->payload + sizeof(struct pkt_udp_headers) + UDP_HEADLEN;
+                }
+                lwip_send_time[lwip_send_transactions] = get_time() - mypayload->message.header.response.opaque;
+                lwip_send_transactions++;
+            } else if (htons(udphdr->src) == 1234) {
+                protocol_binary_request_no_extras *mypayload;
+                if(p->next == NULL) {
+                    mypayload = (void *)p->payload + sizeof(struct pkt_udp_headers) + UDP_HEADLEN;
+                } else {
+                    mypayload = (void *)p->next->payload + UDP_HEADLEN;
+                }
+                lwip_send_time[lwip_send_transactions] = get_time() - mypayload->message.header.request.opaque;
+                lwip_send_transactions++;
+            }
+        }
+    }
+#endif
+
+    errval_t err = ether_transmit_pbuf_list_ptr(bufs, n);
+    assert(err_is_ok(err));
+}
+
+void arranet_recv_free(struct packet *p)
+{
+    assert(p >= rx_packets && p < &rx_packets[MAX_PACKETS]);
+
+#ifdef DEBUG_LATENCIES
+    rx_packets_available++;
+#endif
+    errval_t err = rx_register_buffer_fn_ptr(p->pa, p->payload, p);
+    assert(err_is_ok(err));
+}
+
+struct recv_udp_args {
+    void *buf;
+    size_t len;
+    int recv_len;
+    struct sockaddr *src_addr;
+    socklen_t *addrlen;
+    struct packet **inpkt;
+};
+
+struct recv_tcp_args {
+    void *buf;
+    size_t len;
+    int recv_len;
+    struct sockaddr *src_addr;
+    socklen_t *addrlen;
+    struct packet **inpkt;
+    bool syn, for_me;
+    uint32_t in_seqno;
+    struct socket *sock;
+};
+
+#define MIN(a,b)        ((a) < (b) ? (a) : (b))
+
+static void sock_recved_udp_packet(void *arg)
+{
+    struct recv_udp_args *args = arg;
+    assert(inpkt != NULL);
+    assert(inpkt->next == NULL);
+
+    // Process headers
+    struct ip_hdr *iphdr = (struct ip_hdr *)(inpkt->payload + SIZEOF_ETH_HDR);
+
+    assert(IPH_PROTO(iphdr) == IP_PROTO_UDP);
+
+    struct udp_hdr *udphdr = (struct udp_hdr *)(inpkt->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4));
+    size_t hdr_len = SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4) + sizeof(struct udp_hdr);
+    uint8_t *payload = inpkt->payload + hdr_len;
+    uint16_t pkt_len = htons(udphdr->len) - sizeof(struct udp_hdr);
+    assert(args->buf != NULL);      // No accept() allowed
+
+    // Fill in src_addr if provided
+    if(args->src_addr != NULL) {
+        struct sockaddr_in *addr = (struct sockaddr_in *)args->src_addr;
+
+        assert(*args->addrlen >= sizeof(struct sockaddr_in));
+        memset(addr, 0, sizeof(struct sockaddr_in));
+        addr->sin_len = sizeof(struct sockaddr_in);
+        addr->sin_family = AF_INET;
+        addr->sin_port = udphdr->src;
+        addr->sin_addr.s_addr = iphdr->src.addr;
+        *args->addrlen = sizeof(struct sockaddr_in);
+    }
+
+    // It's a recvfrom!
+    if(args->len != 0) {
+#ifdef DEBUG_LATENCIES
+    if(memcache_transactions[0] < POSIX_TRANSA) {
+        protocol_binary_request_no_extras *mypayload = (void *)payload + UDP_HEADLEN;
+        memcache_times[0][memcache_transactions[0]] = get_time() - mypayload->message.header.request.opaque;
+        memcache_transactions[0]++;
+    }
+#endif
+
+        args->recv_len = MIN(args->len, pkt_len);
+        memcpy(args->buf, payload, args->recv_len);
+
+#ifdef DEBUG_LATENCIES
+    if(memcache_transactions[1] < POSIX_TRANSA) {
+        protocol_binary_request_no_extras *mypayload = (void *)payload + UDP_HEADLEN;
+        memcache_times[1][memcache_transactions[1]] = get_time() - mypayload->message.header.request.opaque;
+        memcache_transactions[1]++;
+    }
+#endif
+
+#ifdef DEBUG_LATENCIES
+        rx_packets_available++;
+#endif
+        errval_t err = rx_register_buffer_fn_ptr(inpkt->pa, inpkt->payload, inpkt);
+        assert(err_is_ok(err));
+    } else {
+        args->recv_len = pkt_len;
+        *((void **)args->buf) = payload;
+        *args->inpkt = inpkt;
+    }
+
+    // Input packet is consumed in stack
+    inpkt = NULL;
+}
+
+static void sock_recved_tcp_packet(void *arg)
+{
+    struct recv_tcp_args *args = arg;
+
+    // Received only a FIN?
+    if(inpkt == NULL) {
+        args->recv_len = 0;
+        args->for_me = true;
+        return;
+    }
+    assert(inpkt != NULL);
+    assert(inpkt->next == NULL);
+
+    // Process headers
+    struct ip_hdr *iphdr = (struct ip_hdr *)(inpkt->payload + SIZEOF_ETH_HDR);
+    assert(IPH_PROTO(iphdr) == IP_PROTO_TCP);
+    struct tcp_hdr *tcphdr = (struct tcp_hdr *)(inpkt->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4));
+    size_t hdr_len = SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4) + (TCPH_HDRLEN(tcphdr) * 4);
+    uint8_t *payload = inpkt->payload + hdr_len;
+    uint16_t pkt_len = htons(IPH_LEN(iphdr)) - (TCPH_HDRLEN(tcphdr) * 4) - (IPH_HL(iphdr) * 4);
+
+    args->in_seqno = tcphdr->seqno;
+    args->for_me = true;
+
+    // Is this from an accept() call?
+    if(args->buf == NULL) {
+        if(TCPH_FLAGS(tcphdr) & TCP_SYN) {
+            args->syn = true;
+        } else {
+            // Don't consume packet
+            args->for_me = false;
+            return;
+        }
+    } else {    // From a recv() call
+        if(TCPH_FLAGS(tcphdr) & TCP_SYN) {
+            // Don't consume packet
+            args->syn = true;
+            args->for_me = false;
+            return;
+        } else {
+            assert(args->sock != NULL);
+            // Is this for the socket that's calling?
+            if(tcphdr->dest != args->sock->bound_addr.sin_port ||
+               tcphdr->src != args->sock->peer_addr.sin_port) {
+                // Don't consume packet
+                args->for_me = false;
+                return;
+            }
+
+            if(args->len != 0) {
+                assert(args->len >= pkt_len);
+                args->recv_len = MIN(args->len, pkt_len);
+                memcpy(args->buf, payload, args->recv_len);
+            } else {
+                assert(!"NYI");
+                args->recv_len = pkt_len;
+                *((void **)args->buf) = payload;
+                *args->inpkt = inpkt;
+            }
+        }
+    }
+
+    // Fill in src_addr if provided
+    if(args->src_addr != NULL) {
+        struct sockaddr_in *addr = (struct sockaddr_in *)args->src_addr;
+
+        assert(*args->addrlen >= sizeof(struct sockaddr_in));
+        memset(addr, 0, sizeof(struct sockaddr_in));
+        addr->sin_len = sizeof(struct sockaddr_in);
+        addr->sin_family = AF_INET;
+        addr->sin_port = tcphdr->src;
+        addr->sin_addr.s_addr = iphdr->src.addr;
+        *args->addrlen = sizeof(struct sockaddr_in);
+    }
+
+#ifdef DEBUG_LATENCIES
+    rx_packets_available++;
+#endif
+    errval_t err = rx_register_buffer_fn_ptr(inpkt->pa, inpkt->payload, inpkt);
+    assert(err_is_ok(err));
+
+    // Input packet is consumed in stack
+    inpkt = NULL;
+}
+
+int lwip_recv(int s, void *mem, size_t len, int flags)
+{
+    /* printf("lwip_recv(%d)\n", s); */
+    assert(arranet_tcp_accepted);
+    struct socket *sock = &sockets[s];
+    struct recv_tcp_args args = {
+        .buf = mem,
+        .len = len,
+        .src_addr = NULL,
+        .syn = false,
+        .sock = sock,
+    };
+    struct waitset ws;
+    waitset_init(&ws);
+
+    errval_t err = waitset_chan_register_polled(&ws, &recv_chanstate,
+                                                MKCLOSURE(sock_recved_tcp_packet, &args));
+    assert(err_is_ok(err));
+
+    /* if socket is ready, trigger event right away */
+    if (lwip_sock_ready_read(s)) {
+        err = waitset_chan_trigger(&recv_chanstate);
+        assert(err_is_ok(err));
+    }
+
+    if(sock->nonblocking) {
+        err = event_dispatch_non_block(&ws);
+        if(err_no(err) == LIB_ERR_NO_EVENT || !args.for_me) {
+            err = waitset_chan_deregister(&recv_chanstate);
+            assert(err_is_ok(err) ||
+                   (err_no(err) == LIB_ERR_CHAN_NOT_REGISTERED && !args.for_me));
+            errno = EAGAIN;
+            args.recv_len = -1;
+        } else {
+            errno = 0;
+            assert(err_is_ok(err));
+        }
+    } else {
+        err = event_dispatch(&ws);
+        assert(err_is_ok(err));
+        if(args.syn) {
+            assert(!"Will block forever");
+        }
+        errno = 0;
+    }
+
+    if(errno != EAGAIN) {
+        sock->peer_seq = htonl(args.in_seqno);
+        sock->next_ack = sock->peer_seq + args.recv_len;
+        /* printf("lwip_recv: Assigning %p, %x\n", sock, sock->next_ack); */
+    } else {
+        // Did it shutdown?
+        if(sock->hangup) {
+            errno = 0;
+            args.recv_len = 0;
+        }
+    }
+
+#ifdef DEBUG_LATENCIES
+    if(posix_recv_transactions < POSIX_TRANSA) {
+        protocol_binary_request_no_extras *mypayload = mem + UDP_HEADLEN;
+        posix_recv_time[posix_recv_transactions] = get_time() - mypayload->message.header.request.opaque;
+        posix_recv_transactions++;
+    }
+#endif
+
+    // Packet is now in buffer
+    /* printf("lwip_recv returned %d\n", args.recv_len); */
+    return args.recv_len;
+}
+
+int lwip_sendto(int s, const void *data, size_t size, int flags,
+                const struct sockaddr *to, socklen_t tolen)
+{
+    struct iovec io = {
+        .iov_base = (void *)data,
+        .iov_len = size,
+    };
+
+    struct msghdr msg = {
+        .msg_name = (void *)to,
+        .msg_namelen = tolen,
+        .msg_iov = &io,
+        .msg_iovlen = 1,
+        .msg_flags = 0,
+    };
+
+    return lwip_sendmsg(s, &msg, flags);
+}
+
+int lwip_socket(int domain, int type, int protocol)
+{
+    // XXX: Accept UDP or TCP, based on created sockets
+    switch(type) {
+    case SOCK_STREAM:
+        assert(!arranet_udp_accepted);
+        arranet_tcp_accepted = true;
+        break;
+
+    case SOCK_DGRAM:
+        assert(!arranet_tcp_accepted);
+        arranet_udp_accepted = true;
+        break;
+    }
+
+    struct socket *sock = alloc_socket();
+    assert(sock != NULL);
+    /* printf("lwip_socket() = %d\n", sock->fd); */
+    return sock->fd;
+}
+
+int lwip_bind(int s, const struct sockaddr *name, socklen_t namelen)
+{
+    struct socket *sock = &sockets[s];
+    assert(name->sa_family == AF_INET);
+    assert(namelen >= sizeof(struct sockaddr_in));
+    sock->bound_addr = *(struct sockaddr_in *)name;
+    return 0;
+}
+
+int lwip_recvfrom(int sockfd, void *buf, size_t len, int flags,
+                  struct sockaddr *src_addr, socklen_t *addrlen)
+{
+    assert(arranet_udp_accepted);
+    struct socket *sock = &sockets[sockfd];
+    struct recv_udp_args args = {
+        .buf = buf,
+        .len = len,
+        .src_addr = src_addr,
+        .addrlen = addrlen,
+    };
+    struct waitset ws;
+    waitset_init(&ws);
+
+    errval_t err = waitset_chan_register_polled(&ws, &recv_chanstate,
+                                                MKCLOSURE(sock_recved_udp_packet, &args));
+    assert(err_is_ok(err));
+
+    /* if socket is ready, trigger event right away */
+    if (lwip_sock_ready_read(sockfd)) {
+        err = waitset_chan_trigger(&recv_chanstate);
+        assert(err_is_ok(err));
+    }
+
+    if(sock->nonblocking) {
+        err = event_dispatch_non_block(&ws);
+        if(err_no(err) == LIB_ERR_NO_EVENT) {
+            err = waitset_chan_deregister(&recv_chanstate);
+            assert(err_is_ok(err));
+            errno = EAGAIN;
+            args.recv_len = -1;
+        } else {
+            assert(err_is_ok(err));
+        }
+    } else {
+        err = event_dispatch(&ws);
+        assert(err_is_ok(err));
+    }
+
+/* #ifdef DEBUG_LATENCIES */
+/*     if(posix_recv_transactions < POSIX_TRANSA) { */
+/*         protocol_binary_request_no_extras *mypayload = buf + UDP_HEADLEN; */
+/*         posix_recv_time[posix_recv_transactions] = get_time() - mypayload->message.header.request.opaque; */
+/*         posix_recv_transactions++; */
+/*     } */
+/* #endif */
+
+    // Packet is now in buffer
+    return args.recv_len;
+}
+
+int recvfrom_arranet(int sockfd, void **buf, struct packet **p,
+                     struct sockaddr *src_addr, socklen_t *addrlen)
+{
+    assert(arranet_udp_accepted);
+    struct fdtab_entry *e = fdtab_get(sockfd);
+    struct socket *sock = &sockets[e->fd];
+    struct recv_udp_args args = {
+        .buf = buf,
+        .len = 0,
+        .src_addr = src_addr,
+        .addrlen = addrlen,
+        .inpkt = p,
+        .recv_len = 0,
+    };
+    struct waitset ws;
+    waitset_init(&ws);
+
+    errval_t err = waitset_chan_register_polled(&ws, &recv_chanstate,
+                                                MKCLOSURE(sock_recved_udp_packet, &args));
+    assert(err_is_ok(err));
+
+    /* if socket is ready, trigger event right away */
+    if (lwip_sock_ready_read(e->fd)) {
+        err = waitset_chan_trigger(&recv_chanstate);
+        assert(err_is_ok(err));
+    }
+
+    if(sock->nonblocking) {
+        err = event_dispatch_non_block(&ws);
+        if(err_no(err) == LIB_ERR_NO_EVENT) {
+            err = waitset_chan_deregister(&recv_chanstate);
+            assert(err_is_ok(err));
+            errno = EAGAIN;
+            args.recv_len = -1;
+        } else {
+            assert(err_is_ok(err));
+        }
+    } else {
+        err = event_dispatch(&ws);
+        assert(err_is_ok(err));
+    }
+
+/* #ifdef DEBUG_LATENCIES */
+/*     if(posix_recv_transactions < POSIX_TRANSA) { */
+/*         protocol_binary_request_no_extras *mypayload = (*buf) + UDP_HEADLEN; */
+/*         posix_recv_time[posix_recv_transactions] = get_time() - mypayload->message.header.request.opaque; */
+/*         posix_recv_transactions++; */
+/*     } */
+/* #endif */
+
+    // XXX: Assert dword alignment
+    assert(((long)*buf) % 8 == 0);
+
+    // Packet is now in buffer
+    return args.recv_len;
+}
+
+static struct pkt_udp_headers packet_udp_header;
+static struct pkt_tcp_headers packet_tcp_header;
+
+static struct peer *peers_get_from_ip(uint32_t ip)
+{
+    for(int i = 0; i < MAX_PEERS; i++) {
+        if(ip == peers[i].ip) {
+            return &peers[i];
+        }
+    }
+
+    /* printf("NOT FOUND: %x\n", ip); */
+
+    return NULL;
+}
+
+static struct peer *peers_get_next_free(void)
+{
+    if(peers_alloc < MAX_PEERS) {
+        return &peers[peers_alloc++];
+    } else {
+        return NULL;
+    }
+}
+
+#define MAX_SENDMSG     16
+
+int sendmsg_arranet(int sockfd, const struct msghdr *msg)
+{
+    assert(arranet_udp_accepted);
+    struct fdtab_entry *e = fdtab_get(sockfd);
+    struct socket *sock = &sockets[e->fd];
+    ssize_t short_size = 0;
+    struct packet packets[MAX_SENDMSG];
+    struct packet hdrpkt;
+    struct packet *oldp = NULL;
+
+#ifdef DEBUG_LATENCIES
+    if(posix_send_transactions < POSIX_TRANSA) {
+        if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) {
+            protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base;
+            posix_send_time[posix_send_transactions] = get_time() - mypayload->message.header.response.opaque;
+            posix_send_transactions++;
+        } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) {
+            protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base;
+            posix_send_time[posix_send_transactions] = get_time() - mypayload->message.header.request.opaque;
+            posix_send_transactions++;
+        }
+    }
+#endif
+
+    assert(msg->msg_iovlen < MAX_SENDMSG);
+
+    for(int i = 0; i < msg->msg_iovlen; i++) {
+        struct packet *newp = &packets[i];
+
+        newp->payload = (uint8_t *)msg->msg_iov[i].iov_base;
+        newp->len = msg->msg_iov[i].iov_len;
+        newp->next = NULL;
+        newp->flags = 0;
+        if(oldp != NULL) {
+            oldp->next = newp;
+        }
+        short_size += msg->msg_iov[i].iov_len;
+        oldp = newp;
+    }
+
+    // Slap UDP/IP/Ethernet headers in front
+    struct pkt_udp_headers myhdr = packet_udp_header;
+    hdrpkt.payload = (uint8_t *)&myhdr;
+    struct pkt_udp_headers *p = (struct pkt_udp_headers *)hdrpkt.payload;
+    hdrpkt.len = sizeof(struct pkt_udp_headers);
+    hdrpkt.next = packets;
+
+    // Fine-tune headers
+    assert(msg->msg_name != NULL);
+    struct sockaddr_in *saddr = msg->msg_name;
+    assert(saddr->sin_family == AF_INET);
+    p->ip.dest.addr = saddr->sin_addr.s_addr;
+    p->udp.dest = saddr->sin_port;
+    struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+    p->eth.dest = peer->mac;
+    assert(sock->bound_addr.sin_port != 0);
+    p->udp.src = sock->bound_addr.sin_port;
+    p->udp.len = htons(short_size + sizeof(struct udp_hdr));
+    p->ip._len = htons(short_size + sizeof(struct udp_hdr) + IP_HLEN);
+#ifdef CONFIG_QEMU_NETWORK
+    p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+    hdrpkt.flags = 0;
+#else
+    // Hardware IP header checksumming on
+    p->ip._chksum = 0;
+    hdrpkt.flags = NETIF_TXFLAG_IPCHECKSUM;
+#endif
+
+    packet_output(&hdrpkt);
+
+    return short_size;
+}
+
+static struct packet *get_tx_packet(void)
+{
+    struct packet *p = &tx_packets[tx_idx];
+
+    // Busy-wait until packet not in flight
+    while(p->len != 0) {
+#ifdef DEBUG_LATENCIES
+        output_pipeline_stalled++;
+#endif
+        /* printf("Pipeline stalled! tx_packets_available = %zd\n", tx_packets_available); */
+        handle_free_tx_slot_fn_ptr();
+        /* if(!handle_free_tx_slot_fn_ptr()) { */
+        /*     printf("No packets could be freed!\n"); */
+        /* } */
+    }
+
+    /* tx_packets_available--; */
+
+    tx_idx = (tx_idx + 1) % MAX_PACKETS;
+    return p;
+}
+
+int lwip_shutdown(int s, int how)
+{
+    assert(arranet_tcp_accepted);
+    struct socket *sock = &sockets[s];
+    assert(sock->nonblocking);
+
+    /* printf("lwip_shutdown(%d)\n", s); */
+
+    if(how == SHUT_RD || sock->shutdown) {
+        return 0;
+    }
+
+    sock->shutdown = true;
+
+#ifdef SENDMSG_WITH_COPY
+    // Get new TX packet and send FIN-ACK
+    struct packet *newp = get_tx_packet();
+    newp->len = sizeof(struct pkt_tcp_headers);
+    newp->next = NULL;
+
+    // Slap TCP/IP/Ethernet headers in front
+    memcpy(newp->payload, &packet_tcp_header, sizeof(struct pkt_tcp_headers));
+
+    // Fine-tune headers
+    struct pkt_tcp_headers *p = (struct pkt_tcp_headers *)newp->payload;
+    p->ip.dest.addr = sock->peer_addr.sin_addr.s_addr;
+    p->tcp.dest = sock->peer_addr.sin_port;
+    struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+    p->eth.dest = peer->mac;
+    assert(sock->bound_addr.sin_port != 0);
+    p->tcp.src = sock->bound_addr.sin_port;
+    p->ip._len = htons(sizeof(struct tcp_hdr) + IP_HLEN);
+    p->tcp.seqno = htonl(sock->my_seq++);
+    p->tcp.ackno = htonl(sock->next_ack);
+    /* printf("lwip_shutdown: Sending %p, seq %x, ack %x\n", sock, sock->my_seq - 1, sock->next_ack); */
+    TCPH_FLAGS_SET(&p->tcp, TCP_FIN | TCP_ACK); // Set FIN-ACK
+    TCPH_HDRLEN_SET(&p->tcp, 5);   // 20 / 4
+    p->tcp.wnd = htons(11680);
+#ifdef CONFIG_QEMU_NETWORK
+    p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+    p->tcp.chksum = 0;
+    newp->payload = (uint8_t *)&p->tcp;
+    newp->len -= (uint8_t *)&p->tcp - (uint8_t *)p;
+    p->tcp.chksum = inet_chksum_pseudo(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+                                       IP_PROTO_TCP, TCP_HLEN);
+    newp->payload = (uint8_t *)p;
+    newp->len = sizeof(struct pkt_tcp_headers);
+    newp->flags = 0;
+#else
+    // Hardware IP/TCP header checksumming on
+    p->ip._chksum = 0;
+    p->tcp.chksum =
+        (~inet_chksum_pseudo_partial(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+                                     IP_PROTO_TCP, TCP_HLEN, 0)) & 0xffff;
+    newp->flags = (NETIF_TXFLAG_IPCHECKSUM | NETIF_TXFLAG_TCPCHECKSUM) |
+        (TCPH_HDRLEN(&p->tcp) << NETIF_TXFLAG_TCPHDRLEN_SHIFT);
+#endif
+
+    packet_output(newp);
+
+    return 0;
+#else
+    assert(!"NYI");
+#endif
+}
+
+int lwip_close(int s)
+{
+    assert(arranet_tcp_accepted);
+    struct socket *sock = &sockets[s];
+
+    lwip_shutdown(s, SHUT_RDWR);
+
+    // Might need to return port if it was bound
+    if(sock->bound_addr.sin_port != 0 && htons(sock->bound_addr.sin_port) != 8080) {
+        tcp_free_port(sock->bound_addr.sin_port);
+    }
+
+    // Remove from active connections
+    if(sock->prev != NULL) {
+        sock->prev->next = sock->next;
+    }
+    if(sock->next != NULL) {
+        sock->next->prev = sock->prev;
+    }
+    if(connections == sock) {
+        connections = sock->next;
+    }
+    sock->next = sock->prev = NULL;
+
+    free_socket(sock);
+    return 0;
+}
+
+int lwip_send(int s, const void *data, size_t size, int flags)
+{
+    assert(arranet_tcp_accepted);
+    struct socket *sock = &sockets[s];
+    assert(sock->nonblocking);
+    assert(size + sizeof(struct pkt_tcp_headers) <= 1500);
+
+    /* printf("lwip_send(%d, , %zu)\n", s, size); */
+
+#ifdef SENDMSG_WITH_COPY
+    // Get new TX packet and copy data into it
+    struct packet *newp = get_tx_packet();
+    newp->len = sizeof(struct pkt_tcp_headers) + size;
+    newp->next = NULL;
+    uint8_t *buf = newp->payload + sizeof(struct pkt_tcp_headers);
+    memcpy(buf, data, size);
+
+    // Slap TCP/IP/Ethernet headers in front
+    memcpy(newp->payload, &packet_tcp_header, sizeof(struct pkt_tcp_headers));
+
+    // Fine-tune headers
+    struct pkt_tcp_headers *p = (struct pkt_tcp_headers *)newp->payload;
+    p->ip.dest.addr = sock->peer_addr.sin_addr.s_addr;
+    p->tcp.dest = sock->peer_addr.sin_port;
+    struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+    assert(peer != NULL);
+    p->eth.dest = peer->mac;
+    assert(sock->bound_addr.sin_port != 0);
+    p->tcp.src = sock->bound_addr.sin_port;
+    p->ip._len = htons(sizeof(struct tcp_hdr) + IP_HLEN + size);
+    p->tcp.seqno = htonl(sock->my_seq);
+    sock->my_seq += size;
+    /* printf("lwip_send: Assigning %p, seq %x\n", sock, sock->my_seq); */
+    p->tcp.ackno = htonl(sock->next_ack);
+    /* printf("lwip_send: Sending %p, %x\n", sock, sock->next_ack); */
+    TCPH_FLAGS_SET(&p->tcp, TCP_ACK | TCP_PSH);
+    TCPH_HDRLEN_SET(&p->tcp, 5);   // 20 / 4
+    p->tcp.wnd = htons(11680);
+#ifdef CONFIG_QEMU_NETWORK
+    p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+    p->tcp.chksum = 0;
+    newp->payload = (uint8_t *)&p->tcp;
+    newp->len -= (uint8_t *)&p->tcp - (uint8_t *)p;
+    p->tcp.chksum = inet_chksum_pseudo(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+                                       IP_PROTO_TCP, TCP_HLEN + size);
+    newp->payload = (uint8_t *)p;
+    newp->len = sizeof(struct pkt_tcp_headers) + size;
+    newp->flags = 0;
+#else
+    // Hardware IP/TCP header checksumming on
+    p->ip._chksum = 0;
+    p->tcp.chksum =
+        (~inet_chksum_pseudo_partial(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+                                     IP_PROTO_TCP, TCP_HLEN + size, 0)) & 0xffff;
+    newp->flags = (NETIF_TXFLAG_IPCHECKSUM | NETIF_TXFLAG_TCPCHECKSUM) |
+        (TCPH_HDRLEN(&p->tcp) << NETIF_TXFLAG_TCPHDRLEN_SHIFT);
+#endif
+
+    packet_output(newp);
+
+    return size;
+#else
+    assert(!"NYI");
+#endif
+}
+
+int lwip_connect(int s, const struct sockaddr *name, socklen_t namelen)
+{
+    /* printf("lwip_connect(%d)\n", s); */
+    assert(arranet_tcp_accepted);
+    struct socket *sock = &sockets[s];
+    assert(sock->nonblocking);
+    assert(namelen == sizeof(struct sockaddr_in));
+    struct sockaddr_in *sa = (struct sockaddr_in *)name;
+    assert(sa->sin_family == AF_INET);
+
+    // Store peer address on socket
+    sock->peer_addr = *sa;
+
+#ifdef SENDMSG_WITH_COPY
+    // Get new TX packet and send SYN
+    struct packet *newp = get_tx_packet();
+    newp->len = sizeof(struct pkt_tcp_headers) + 6;
+    newp->next = NULL;
+
+    // Slap TCP/IP/Ethernet headers in front
+    memcpy(newp->payload, &packet_tcp_header, sizeof(struct pkt_tcp_headers));
+
+    // Fine-tune headers
+    struct pkt_tcp_headers *p = (struct pkt_tcp_headers *)newp->payload;
+    uint32_t *payload = (void *)p + sizeof(struct pkt_tcp_headers);
+    memset(payload, 0, 6);
+    p->ip.dest.addr = sa->sin_addr.s_addr;
+    p->tcp.dest = sa->sin_port;
+    struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+    assert(peer != NULL);
+    p->eth.dest = peer->mac;
+    assert(sock->bound_addr.sin_port == 0);
+    sock->bound_addr.sin_port = tcp_new_port();
+    p->tcp.src = sock->bound_addr.sin_port;
+    p->ip._len = htons(sizeof(struct tcp_hdr) + IP_HLEN + 4);
+    p->tcp.seqno = htonl(++sock->my_seq); sock->my_seq++;
+    /* printf("lwip_connect: Assigning %p seq %x\n", sock, sock->my_seq); */
+    p->tcp.ackno = 0;
+    TCPH_FLAGS_SET(&p->tcp, TCP_SYN);
+    TCPH_HDRLEN_SET(&p->tcp, 6);   // 24 / 4
+    p->tcp.wnd = htons(11680);
+    *payload = TCP_BUILD_MSS_OPTION(1460);
+#ifdef CONFIG_QEMU_NETWORK
+    p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+    p->tcp.chksum = 0;
+    newp->payload = (uint8_t *)&p->tcp;
+    newp->len -= (uint8_t *)&p->tcp - (uint8_t *)p;
+    p->tcp.chksum = inet_chksum_pseudo(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+                                       IP_PROTO_TCP, TCP_HLEN + 4);
+    newp->payload = (uint8_t *)p;
+    newp->len = sizeof(struct pkt_tcp_headers) + 6;
+    newp->flags = 0;
+#else
+    // Hardware IP/TCP header checksumming on
+    p->ip._chksum = 0;
+    p->tcp.chksum = 0;
+    p->tcp.chksum =
+        (~inet_chksum_pseudo_partial(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+                                     IP_PROTO_TCP, TCP_HLEN + 4, 0)) & 0xffff;
+    newp->flags = (NETIF_TXFLAG_IPCHECKSUM | NETIF_TXFLAG_TCPCHECKSUM) |
+        (TCPH_HDRLEN(&p->tcp) << NETIF_TXFLAG_TCPHDRLEN_SHIFT);
+#endif
+
+    packet_output(newp);
+
+    assert(sock->prev == NULL && sock->next == NULL);
+    sock->next = connections;
+    if(connections != NULL) {
+        assert(connections->prev == NULL);
+        connections->prev = sock;
+    }
+    sock->prev = NULL;
+    connections = sock;
+
+    errno = EINPROGRESS;
+    return -1;
+#else
+    assert(!"NYI");
+#endif
+}
+
+#ifdef SENDMSG_WITH_COPY
+
+int lwip_sendmsg(int sockfd, const struct msghdr *msg, int flags)
+{
+    assert(arranet_udp_accepted);
+    struct socket *sock = &sockets[sockfd];
+
+#ifdef DEBUG_LATENCIES
+    if(posix_send_transactions < POSIX_TRANSA) {
+        if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) {
+            protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base;
+            posix_send_time[posix_send_transactions] = get_time() - mypayload->message.header.response.opaque;
+            posix_send_transactions++;
+        } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) {
+            protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN;
+            posix_send_time[posix_send_transactions] = get_time() - mypayload->message.header.request.opaque;
+            posix_send_transactions++;
+        }
+    }
+#endif
+
+    assert(msg->msg_iovlen < MAX_SENDMSG);
+
+    // Determine length of sendmsg vector
+    ssize_t short_size = 0;
+    for(int i = 0; i < msg->msg_iovlen; i++) {
+        short_size += msg->msg_iov[i].iov_len;
+    }
+    assert(short_size <= PACKET_SIZE);
+
+/* #ifdef DEBUG_LATENCIES */
+/*     if(memcache_transactions[0] < POSIX_TRANSA) { */
+/*         if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) { */
+/*             protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base; */
+/*             memcache_times[0][memcache_transactions[0]] = get_time() - mypayload->message.header.response.opaque; */
+/*             memcache_transactions[0]++; */
+/*         } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) { */
+/*             protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN; */
+/*             memcache_times[0][memcache_transactions[0]] = get_time() - mypayload->message.header.request.opaque; */
+/*             memcache_transactions[0]++; */
+/*         } */
+/*     } */
+/* #endif */
+
+    // Get new TX packet and copy data into it
+    struct packet *newp = get_tx_packet();
+    uint8_t *buf = newp->payload;
+    size_t pos = sizeof(struct pkt_udp_headers);
+
+/* #ifdef DEBUG_LATENCIES */
+/*     if(memcache_transactions[1] < POSIX_TRANSA) { */
+/*         if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) { */
+/*             protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base; */
+/*             memcache_times[1][memcache_transactions[1]] = get_time() - mypayload->message.header.response.opaque; */
+/*             memcache_transactions[1]++; */
+/*         } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) { */
+/*             protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN; */
+/*             memcache_times[1][memcache_transactions[1]] = get_time() - mypayload->message.header.request.opaque; */
+/*             memcache_transactions[1]++; */
+/*         } */
+/*     } */
+
+/*     uint64_t last = rdpmc(0); */
+/* #endif */
+
+    //    assert(msg->msg_iovlen == 1);
+    for(int i = 0; i < msg->msg_iovlen; i++) {
+        /* assert((uintptr_t)(&buf[pos]) % 8 == 0); */
+        //        assert((uintptr_t)msg->msg_iov[i].iov_base % 8 == 0);
+        memcpy(&buf[pos], msg->msg_iov[i].iov_base, msg->msg_iov[i].iov_len);
+        pos += msg->msg_iov[i].iov_len;
+    }
+
+#ifdef DEBUG_LATENCIES
+    /* uint64_t now = rdpmc(0); */
+
+    /* if(memcache_transactions[19] < POSIX_TRANSA) {   // ZZZ 19 */
+    /*     memcache_times[19][memcache_transactions[19]] = now - last; */
+    /*     memcache_transactions[19]++; */
+    /* } */
+
+    if(memcache_transactions[2] < POSIX_TRANSA) {
+        if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) {
+            protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base;
+            memcache_times[2][memcache_transactions[2]] = get_time() - mypayload->message.header.response.opaque;
+            memcache_transactions[2]++;
+        } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) {
+            protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN;
+            memcache_times[2][memcache_transactions[2]] = get_time() - mypayload->message.header.request.opaque;
+            memcache_transactions[2]++;
+        }
+    }
+#endif
+
+    newp->len = short_size + sizeof(struct pkt_udp_headers);
+    newp->next = NULL;
+
+    // Slap UDP/IP/Ethernet headers in front
+    memcpy(buf, &packet_udp_header, sizeof(struct pkt_udp_headers));
+
+/* #ifdef DEBUG_LATENCIES */
+/*     if(memcache_transactions[3] < POSIX_TRANSA) { */
+/*         if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) { */
+/*             protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base; */
+/*             memcache_times[3][memcache_transactions[3]] = get_time() - mypayload->message.header.response.opaque; */
+/*             memcache_transactions[3]++; */
+/*         } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) { */
+/*             protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN; */
+/*             memcache_times[3][memcache_transactions[3]] = get_time() - mypayload->message.header.request.opaque; */
+/*             memcache_transactions[3]++; */
+/*         } */
+/*     } */
+/* #endif */
+
+    // Fine-tune headers
+    struct pkt_udp_headers *p = (struct pkt_udp_headers *)buf;
+    assert(msg->msg_name != NULL);
+    struct sockaddr_in *saddr = msg->msg_name;
+    assert(saddr->sin_family == AF_INET);
+    p->ip.dest.addr = saddr->sin_addr.s_addr;
+    p->udp.dest = saddr->sin_port;
+    struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+    p->eth.dest = peer->mac;
+    assert(sock->bound_addr.sin_port != 0);
+    p->udp.src = sock->bound_addr.sin_port;
+    p->udp.len = htons(short_size + sizeof(struct udp_hdr));
+    p->ip._len = htons(short_size + sizeof(struct udp_hdr) + IP_HLEN);
+#ifdef CONFIG_QEMU_NETWORK
+    p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+    newp->flags = 0;
+#else
+    // Hardware IP header checksumming on
+    p->ip._chksum = 0;
+    newp->flags = NETIF_TXFLAG_IPCHECKSUM;
+#endif
+
+/* #ifdef DEBUG_LATENCIES */
+/*     if(memcache_transactions[4] < POSIX_TRANSA) { */
+/*         if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) { */
+/*             protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base; */
+/*             memcache_times[4][memcache_transactions[4]] = get_time() - mypayload->message.header.response.opaque; */
+/*             memcache_transactions[4]++; */
+/*         } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) { */
+/*             protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN; */
+/*             memcache_times[4][memcache_transactions[4]] = get_time() - mypayload->message.header.request.opaque; */
+/*             memcache_transactions[4]++; */
+/*         } */
+/*     } */
+/* #endif */
+
+    packet_output(newp);
+
+/* #ifdef DEBUG_LATENCIES */
+/*     if(memcache_transactions[5] < POSIX_TRANSA) { */
+/*         if(msg->msg_iovlen > 1 && msg->msg_iov[1].iov_len == sizeof(protocol_binary_response_no_extras)) { */
+/*             protocol_binary_response_no_extras *mypayload = msg->msg_iov[1].iov_base; */
+/*             memcache_times[5][memcache_transactions[5]] = get_time() - mypayload->message.header.response.opaque; */
+/*             memcache_transactions[5]++; */
+/*         } else if(msg->msg_iov[0].iov_len >= sizeof(protocol_binary_request_no_extras)) { */
+/*             protocol_binary_request_no_extras *mypayload = msg->msg_iov[0].iov_base + UDP_HEADLEN; */
+/*             memcache_times[5][memcache_transactions[5]] = get_time() - mypayload->message.header.request.opaque; */
+/*             memcache_transactions[5]++; */
+/*         } */
+/*     } */
+/* #endif */
+
+    return short_size;
+}
+
+#else
+
+int lwip_sendmsg(int sockfd, const struct msghdr *msg, int flags)
+{
+    struct socket *sock = &sockets[sockfd];
+    ssize_t short_size = 0;
+    struct packet packets[MAX_SENDMSG];
+    struct packet *oldp = NULL;
+
+    assert(msg->msg_iovlen < MAX_SENDMSG);
+
+    for(int i = 0; i < msg->msg_iovlen; i++) {
+        struct packet *newp = &packets[i];
+
+        newp->payload = (uint8_t *)msg->msg_iov[i].iov_base;
+        newp->len = msg->msg_iov[i].iov_len;
+        newp->next = NULL;
+        newp->flags = 0;
+        newp->opaque = msg->msg_iov[i].iov_opaque;
+        if(oldp != NULL) {
+            oldp->next = newp;
+        }
+        short_size += msg->msg_iov[i].iov_len;
+        oldp = newp;
+    }
+
+    // Slap UDP/IP/Ethernet headers in front
+    struct packet *hdrpkt = get_tx_packet();
+    memcpy(hdrpkt->payload, &packet_udp_header, sizeof(struct pkt_udp_headers));
+    struct pkt_udp_headers *p = (struct pkt_udp_headers *)hdrpkt->payload;
+    hdrpkt->len = sizeof(struct pkt_udp_headers);
+    hdrpkt->next = packets;
+    hdrpkt->opaque = hdrpkt;
+
+    // Fine-tune headers
+    assert(msg->msg_name != NULL);
+    struct sockaddr_in *saddr = msg->msg_name;
+    assert(saddr->sin_family == AF_INET);
+    p->ip.dest.addr = saddr->sin_addr.s_addr;
+    p->udp.dest = saddr->sin_port;
+    struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+    p->eth.dest = peer->mac;
+    assert(sock->bound_addr.sin_port != 0);
+    p->udp.src = sock->bound_addr.sin_port;
+    p->udp.len = htons(short_size + sizeof(struct udp_hdr));
+    p->ip._len = htons(short_size + sizeof(struct udp_hdr) + IP_HLEN);
+#ifdef CONFIG_QEMU_NETWORK
+    p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+    hdrpkt->flags = 0;
+#else
+    // Hardware IP header checksumming on
+    p->ip._chksum = 0;
+    hdrpkt->flags = NETIF_TXFLAG_IPCHECKSUM;
+#endif
+
+    packet_output(hdrpkt);
+
+    // If we sent the data directly, we need to wait here until everything is out.
+    // Else, data might be overwritten by application before card can send it.
+    /* while(!e1000n_queue_empty()) thread_yield(); */
+
+    return short_size;
+}
+
+#endif
+
+int lwip_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
+{
+    assert(arranet_tcp_accepted);
+    struct socket *sock = &sockets[s];
+    assert(sock->passive);
+    struct socket *newsock = alloc_socket();
+    newsock->nonblocking = sock->nonblocking;
+    newsock->bound_addr = sock->bound_addr;
+    socklen_t adlen = sizeof(struct sockaddr_in);
+    struct recv_tcp_args args = {
+        .buf = NULL,
+        .len = 0,
+        .src_addr = (struct sockaddr *)&newsock->peer_addr,
+        .addrlen = &adlen,
+        .syn = false,
+        .sock = newsock,
+    };
+    struct waitset ws;
+    waitset_init(&ws);
+
+    errval_t err = waitset_chan_register_polled(&ws, &recv_chanstate,
+                                                MKCLOSURE(sock_recved_tcp_packet, &args));
+    assert(err_is_ok(err));
+
+    /* if socket is ready, trigger event right away */
+    if (lwip_sock_ready_read(s)) {
+        err = waitset_chan_trigger(&recv_chanstate);
+        assert(err_is_ok(err));
+    }
+
+    if(sock->nonblocking) {
+        err = event_dispatch_non_block(&ws);
+        if(err_no(err) == LIB_ERR_NO_EVENT) {   // Deregister if it didn't fire
+            err = waitset_chan_deregister(&recv_chanstate);
+            assert(err_is_ok(err));
+        }
+
+        if(err_no(err) == LIB_ERR_NO_EVENT || !args.syn) {
+            free_socket(newsock);
+            errno = EAGAIN;
+            return -1;
+        } else {
+            assert(err_is_ok(err));
+        }
+
+        if(!args.syn) {
+            free_socket(newsock);
+            errno = EAGAIN;
+            return -1;
+        }
+    } else {
+        err = event_dispatch(&ws);
+        assert(err_is_ok(err));
+
+        if(!args.syn) {
+            assert(!"Will block forever");
+        }
+    }
+
+    assert(adlen == sizeof(struct sockaddr_in));
+    assert(*addrlen >= sizeof(struct sockaddr_in));
+    // Set caller's addr buffers
+    if(addr != NULL) {
+        memcpy(addr, &newsock->peer_addr, sizeof(struct sockaddr_in));
+        *addrlen = adlen;
+    }
+
+    /* newsock->my_seq = 0; */
+    newsock->peer_seq = htonl(args.in_seqno);
+    /* printf("lwip_accept: Assigning %p seq %x\n", newsock, newsock->my_seq); */
+
+#ifdef SENDMSG_WITH_COPY
+    // Get new TX packet and send SYN-ACK
+    struct packet *newp = get_tx_packet();
+    newp->len = sizeof(struct pkt_tcp_headers) + 4;
+    newp->next = NULL;
+
+    // Slap TCP/IP/Ethernet headers in front
+    memcpy(newp->payload, &packet_tcp_header, sizeof(struct pkt_tcp_headers));
+
+    // Fine-tune headers
+    struct pkt_tcp_headers *p = (struct pkt_tcp_headers *)newp->payload;
+    uint32_t *payload = (void *)p + sizeof(struct pkt_tcp_headers);
+    memset(payload, 0, 4);
+    p->ip.dest.addr = newsock->peer_addr.sin_addr.s_addr;
+    p->tcp.dest = newsock->peer_addr.sin_port;
+    struct peer *peer = peers_get_from_ip(p->ip.dest.addr);
+    p->eth.dest = peer->mac;
+    assert(sock->bound_addr.sin_port != 0);
+    p->tcp.src = sock->bound_addr.sin_port;
+    p->ip._len = htons(sizeof(struct tcp_hdr) + IP_HLEN + 4);
+    p->tcp.seqno = htonl(++newsock->my_seq); newsock->my_seq++;
+    /* printf("lwip_accept: Assigning %p seq %x\n", newsock, newsock->my_seq); */
+    newsock->next_ack = newsock->peer_seq + 1;
+    /* printf("lwip_accept: Assigning %p, %x\n", newsock, newsock->next_ack); */
+    p->tcp.ackno = htonl(newsock->next_ack);
+    /* printf("lwip_accept: Sending %p, %x\n", newsock, newsock->next_ack); */
+    TCPH_FLAGS_SET(&p->tcp, TCP_SYN | TCP_ACK); // Set SYN-ACK
+    TCPH_HDRLEN_SET(&p->tcp, 6);   // 24 / 4
+    p->tcp.wnd = htons(11680);
+    *payload = TCP_BUILD_MSS_OPTION(1460);
+#ifdef CONFIG_QEMU_NETWORK
+    p->ip._chksum = inet_chksum(&p->ip, IP_HLEN);
+    p->tcp.chksum = 0;
+    newp->payload = (uint8_t *)&p->tcp;
+    newp->len -= (uint8_t *)&p->tcp - (uint8_t *)p;
+    p->tcp.chksum = inet_chksum_pseudo(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+                                       IP_PROTO_TCP, TCP_HLEN + 4);
+    newp->payload = (uint8_t *)p;
+    newp->len = sizeof(struct pkt_tcp_headers) + 4;
+    newp->flags = 0;
+#else
+    // Hardware IP/TCP header checksumming on
+    p->ip._chksum = 0;
+    p->tcp.chksum =
+        (~inet_chksum_pseudo_partial(newp, (ip_addr_t *)&p->ip.src, (ip_addr_t *)&p->ip.dest,
+                                     IP_PROTO_TCP, TCP_HLEN + 4, 0)) & 0xffff;
+    newp->flags = (NETIF_TXFLAG_IPCHECKSUM | NETIF_TXFLAG_TCPCHECKSUM) |
+        (6 << NETIF_TXFLAG_TCPHDRLEN_SHIFT);
+#endif
+
+    packet_output(newp);
+#else
+    assert(!"NYI");
+#endif
+
+    /* printf("Returned %d\n", newsock->fd); */
+    newsock->connected = true;
+    assert(newsock->prev == NULL && newsock->next == NULL);
+    newsock->next = connections;
+    if(connections != NULL) {
+        assert(connections->prev == NULL);
+        connections->prev = newsock;
+    }
+    newsock->prev = NULL;
+    connections = newsock;
+
+    /* printf("lwip_accept(%d) = %d\n", s, newsock->fd); */
+    return newsock->fd;
+}
+
+void process_received_packet(struct driver_rx_buffer *buffer, size_t count,
+                             uint64_t flags)
+{
+    struct packet *p = buffer->opaque;
+    assert(p != NULL);
+    assert(count == 1);
+    p->len = buffer->len;
+
+    /* printf("Got %p from driver\n", p); */
+
+    assert(p >= rx_packets && p < &rx_packets[MAX_PACKETS]);
+
+#ifdef DEBUG_LATENCIES
+    rx_packets_available--;
+    if(rx_packets_available < 10) {
+        printf("Too many RX packets in flight!\n");
+    }
+#endif
+
+    // Drop packets with invalid checksums
+    if(flags & NETIF_RXFLAG_IPCHECKSUM) {
+        if(!(flags & NETIF_RXFLAG_IPCHECKSUM_GOOD)) {
+            goto out;
+        }
+    }
+
+    if(flags & NETIF_RXFLAG_L4CHECKSUM) {
+        if(!(flags & NETIF_RXFLAG_L4CHECKSUM_GOOD)) {
+            goto out;
+        }
+    }
+
+    struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
+    switch (htons(ethhdr->type)) {
+    case ETHTYPE_ARP:
+        {
+            struct etharp_hdr *arphdr = (struct etharp_hdr *)(p->payload + SIZEOF_ETH_HDR);
+            uint32_t dipaddr = (arphdr->dipaddr.addrw[1] << 16) | arphdr->dipaddr.addrw[0];
+
+            /* printf("%d: ARP request, dip = %x\n", disp_get_core_id(), dipaddr); */
+
+            if(htons(arphdr->opcode) == ARP_REQUEST &&
+               dipaddr == arranet_myip) {
+                // Send reply
+                struct packet outp;
+                uint8_t payload[PACKET_SIZE];
+                struct eth_hdr *myeth = (struct eth_hdr *)payload;
+                struct etharp_hdr *myarp = (struct etharp_hdr *)(payload + SIZEOF_ETH_HDR);
+
+                /* printf("%d: ARP request for us!\n", disp_get_core_id()); */
+
+                // ETH header
+                memcpy(&myeth->dest, &arphdr->shwaddr, ETHARP_HWADDR_LEN);
+                memcpy(&myeth->src, arranet_mymac, ETHARP_HWADDR_LEN);
+                myeth->type = htons(ETHTYPE_ARP);
+
+                // ARP header
+                myarp->hwtype = htons(1);
+                myarp->proto = htons(ETHTYPE_IP);
+                myarp->hwlen = 6;
+                myarp->protolen = 4;
+                myarp->opcode = htons(ARP_REPLY);
+                memcpy(&myarp->shwaddr, arranet_mymac, ETHARP_HWADDR_LEN);
+                memcpy(&myarp->sipaddr, &arphdr->dipaddr, sizeof(myarp->sipaddr));
+                memcpy(&myarp->dhwaddr, &arphdr->shwaddr, ETHARP_HWADDR_LEN);
+                memcpy(&myarp->dipaddr, &arphdr->sipaddr, sizeof(myarp->dipaddr));
+
+                outp.payload = payload;
+                outp.len = p->len;
+                outp.next = NULL;
+                outp.flags = 0;
+                outp.opaque = NULL;
+                packet_output(&outp);
+                while(!e1000n_queue_empty()) thread_yield();
+            }
+        }
+        break;
+
+    case ETHTYPE_IP:
+        {
+            struct ip_hdr *iphdr = (struct ip_hdr *)(p->payload + SIZEOF_ETH_HDR);
+
+            /* printf("%d: Is an IP packet, type %x\n", disp_get_core_id(), IPH_PROTO(iphdr)); */
+
+#ifdef DEBUG_LATENCIES
+            if(IPH_PROTO(iphdr) == IP_PROTO_ICMP) {
+                static uint64_t cache_misses = 0;
+                uint64_t new_cache_misses = rdpmc(0);
+                printf("Cache misses = %" PRIu64 "\n", new_cache_misses - cache_misses);
+                cache_misses = new_cache_misses;
+
+                printf("hash_option1 = %zd, hash_option2 = %zd, hash_option3 = %zd\n",
+                       hash_option1, hash_option2, hash_option3);
+                printf("hash_calls = %zd, hash_length = %zd\n",
+                       hash_calls, hash_length);
+
+                printf("output pipeline stalled = %zd\n", output_pipeline_stalled);
+                output_pipeline_stalled = 0;
+
+                printf("memcache packets received = %zd\n", memcache_packets_received);
+                memcache_packets_received = 0;
+                for(int i = 0; i < 65536; i++) {
+                    if(port_cnt[i] != 0) {
+                        printf("port %d = %zu\n", i, port_cnt[i]);
+                        port_cnt[i] = 0;
+                    }
+                }
+
+                printf("recv_transa = %zu, send_transa = %zu\n",
+                       posix_recv_transactions, posix_send_transactions);
+                printf("posix_recv_transactions:\n");
+                for(int i = 0; i < posix_recv_transactions; i++) {
+                    printf("%u us\n", posix_recv_time[i]);
+                }
+                printf("posix_send_transactions:\n");
+                for(int i = 0; i < posix_send_transactions; i++) {
+                    printf("%u us\n", posix_send_time[i]);
+                }
+                posix_recv_transactions = posix_send_transactions = 0;
+
+                printf("lwip_send_transa = %zu\n", lwip_send_transactions);
+                printf("lwip_send_transactions:\n");
+                for(int i = 0; i < lwip_send_transactions; i++) {
+                    printf("%u us\n", lwip_send_time[i]);
+                }
+                lwip_send_transactions = 0;
+
+                for(int j = 0; j < 20; j++) {
+                    printf("memcache_transa[%d] = %zu:\n", j, memcache_transactions[j]);
+                    for(int i = 0; i < memcache_transactions[j]; i++) {
+                        printf("%u us\n", memcache_times[j][i]);
+                    }
+                    memcache_transactions[j] = 0;
+                }
+            }
+#endif
+
+            // Has to be UDP or TCP
+            if(IPH_PROTO(iphdr) != IP_PROTO_UDP && IPH_PROTO(iphdr) != IP_PROTO_TCP) {
+                goto out;
+            }
+
+            // XXX: Filter for our IP
+            if(iphdr->dest.addr != arranet_myip) {
+                goto out;
+            }
+
+            if(IPH_PROTO(iphdr) == IP_PROTO_UDP) {
+                struct udp_hdr *udphdr = (struct udp_hdr *)(p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4));
+                /* uint8_t *payload = p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4) + sizeof(struct udp_hdr); */
+
+                // Are we accepting UDP packets?
+                if(!arranet_udp_accepted) {
+                    goto out;
+                }
+
+                /* printf("Got UDP packet, dest IP %x, dest port %u\n", */
+                /*        htonl(iphdr->dest.addr), htons(udphdr->dest)); */
+
+                // XXX: Filter for UDP ports 1234, 11211, 11212
+                // TODO: Done in hardware soon
+                if(htons(udphdr->dest) != 1234 &&
+                   htons(udphdr->dest) != 11211 &&
+                   htons(udphdr->dest) != 11212) {
+                    goto out;
+                }
+
+#ifdef DEBUG_LATENCIES
+                {
+                    memcache_packets_received++;
+                    port_cnt[htons(udphdr->src)]++;
+                    protocol_binary_request_no_extras *mypayload = (void *)p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4) + sizeof(struct udp_hdr) + UDP_HEADLEN;
+                    mypayload->message.header.request.opaque = get_time();
+                }
+#endif
+            }
+
+            if(IPH_PROTO(iphdr) == IP_PROTO_TCP) {
+                struct tcp_hdr *tcphdr = (struct tcp_hdr *)(p->payload + SIZEOF_ETH_HDR + (IPH_HL(iphdr) * 4));
+
+                // Are we accepting TCP packets?
+                if(!arranet_tcp_accepted) {
+                    goto out;
+                }
+
+                /* printf("Got TCP packet, dest IP %x, src IP %x, dest port %u, src %u\n", */
+                /*        htonl(iphdr->dest.addr), htonl(iphdr->src.addr), */
+                /*        htons(tcphdr->dest), htons(tcphdr->src)); */
+
+                // XXX: Filter for TCP port 8080 and everything that we know
+                // TODO: Done in hardware soon
+                struct socket *sock = NULL;
+                for(sock = connections; sock != NULL; sock = sock->next) {
+                    if(sock->bound_addr.sin_port == tcphdr->dest &&
+                       sock->peer_addr.sin_port == tcphdr->src &&
+                       sock->peer_addr.sin_addr.s_addr == iphdr->src.addr) {
+                        break;
+                    }
+                }
+
+                p->sock = sock;
+
+                // Handle SYN-ACKs for connections we created and