lxip: Port of the Linux TCP/IP stack

This commit is contained in:
Sebastian Sumpf 2013-08-26 13:58:58 +02:00 committed by Norman Feske
parent 864a047206
commit 5e17fef898
40 changed files with 6924 additions and 89 deletions

View File

@ -10,87 +10,8 @@ ECHO = @echo
PATCHES := $(shell find patches -name \*.patch) PATCHES := $(shell find patches -name \*.patch)
LINUX = linux-3.9 LINUX = linux-3.9
LINUX_TBZ2 = $(LINUX).tar.bz2 LINUX_TGZ = $(LINUX).tar.gz
LINUX_URL = http://www.kernel.org/pub/linux/kernel/v3.x/$(LINUX_TBZ2) LINUX_URL = http://www.kernel.org/pub/linux/kernel/v3.x/$(LINUX_TGZ)
# Linux utilities
CONTENT += include/linux/list.h
CONTENT += $(addprefix include/linux/,pci_ids.h usb.h hid.h hiddev.h input.h mod_devicetable.h)
CONTENT += include/linux/byteorder/generic.h
CONTENT += include/linux/swab.h
CONTENT += $(addprefix include/asm-generic/bitops/,__ffs.h non-atomic.h)
CONTENT_UAPI = byteorder/little_endian.h hid.h input.h pci_regs.h usb/ch11.h \
usb/ch9.h
CONTENT_USB = ch9.h phy.h
CONTENT += $(addprefix include/uapi/linux/,$(CONTENT_UAPI))
CONTENT += $(addprefix include/linux/usb/,$(CONTENT_USB))
CONTENT += include/uapi/asm-generic/ioctl.h
# USB core
CONTENT_CORE = buffer.c config.c devices.c driver.c endpoint.c file.c generic.c \
hcd.c hcd-pci.c hub.h hub.c message.c notify.c quirks.c port.c \
urb.c usb.c usb.h
CONTENT += $(addprefix drivers/usb/core/,$(CONTENT_CORE))
CONTENT += drivers/usb/usb-common.c
CONTENT_INCLUDE_USB := ehci_def.h hcd.h input.h otg.h quirks.h storage.h
CONTENT += $(addprefix include/linux/usb/,$(CONTENT_INCLUDE_USB))
# needed by usb/core/devio.c
CONTENT += include/asm-generic/ioctl.h
# USB host-controller driver
CONTENT_USB_HOST := ehci.h ehci-hcd.c ehci-hub.c ehci-dbg.c ehci-mem.c \
ehci-omap.c ehci-q.c ehci-pci.c ehci-s5p.c ehci-sched.c \
ehci-sysfs.c ehci-timer.c
CONTENT_USB_HOST += ohci.h ohci-hcd.c ohci-hub.c ohci-dbg.c ohci-mem.c \
ohci-q.c ohci-pci.c
CONTENT_USB_HOST += uhci-hcd.h uhci-hcd.c uhci-debug.c uhci-q.c uhci-hub.c \
uhci-pci.c
CONTENT_USB_HOST += xhci-dbg.c xhci-ext-caps.h xhci-hub.c xhci-mem.c \
xhci-plat.c xhci-ring.c xhci.h xhci.c
CONTENT_USB_HOST += pci-quirks.h pci-quirks.c
CONTENT += $(addprefix drivers/usb/host/,$(CONTENT_USB_HOST))
# USB storage driver
CONTENT += drivers/usb/storage/
CONTENT += include/linux/usb_usual.h
# SCSI support for storage
CONTENT += $(addprefix drivers/scsi/,scsi.h scsi.c constants.c scsi_priv.h scsi_logging.h)
CONTENT += $(addprefix include/scsi/,scsi.h scsi_host.h)
# USB hid driver
CONTENT += drivers/hid/hid-input.c drivers/hid/hid-generic.c drivers/hid/hid-core.c drivers/hid/hid-ids.h
CONTENT += drivers/hid/hid-cherry.c drivers/hid/usbhid
# needed by USB hid
CONTENT_INPUT := input.c evdev.c input-compat.h
CONTENT += $(addprefix drivers/input/,$(CONTENT_INPUT))
CONTENT += include/linux/input/mt.h
# usb network driver
CONTENT_NET = usbnet.c
# Panda board
CONTENT_NET += smsc95xx.c smsc95xx.h
# Arndale board
CONTENT_NET += asix_devices.c asix_common.c ax88172a.c ax88179_178a.c asix.h
CONTENT += $(addprefix drivers/net/usb/,$(CONTENT_NET))
CONTENT += include/linux/usb/usbnet.h include/linux/netdev_features.h
# DWC3 controller
CONTENT_DWC3 = core.c core.h dwc3-exynos.c host.c io.h
CONTENT += $(addprefix drivers/usb/dwc3/,$(CONTENT_DWC3))
CONTENT += include/linux/platform_data/dwc3-exynos.h
# OMAP
CONTENT += include/linux/platform_data/usb-omap.h
# Arndale
CONTENT += arch/arm/plat-samsung/include/plat/usb-phy.h
CONTENT += include/linux/platform_data/usb-ehci-s5p.h
# Raspberry Pi # Raspberry Pi
DWC_OTG_GIT_URL := https://github.com/nfeske/dwc_otg.git DWC_OTG_GIT_URL := https://github.com/nfeske/dwc_otg.git
@ -127,13 +48,13 @@ prepare_rpi: prepare
git reset --hard HEAD && git checkout $(DWC_OTG_GIT_BRANCH) git reset --hard HEAD && git checkout $(DWC_OTG_GIT_BRANCH)
$(CONTRIB_DIR)/.prepared: Makefile $(CONTRIB_DIR)/.prepared: Makefile
$(CONTRIB_DIR)/.prepared: $(DOWNLOAD_DIR)/$(LINUX_TBZ2) $(CONTRIB_DIR)/.prepared: $(DOWNLOAD_DIR)/$(LINUX_TGZ)
$(ECHO) "extracting source code to '$(CONTRIB_DIR)'" $(ECHO) "extracting source code to '$(CONTRIB_DIR)'"
$(VERBOSE)tar xfj $< --transform "s/$(LINUX)/$(CONTRIB_DIR)/" $(addprefix $(LINUX)/,$(CONTENT)) $(VERBOSE)tar xfz $< --transform "s{$(LINUX){$(CONTRIB_DIR){" --files-from files.list
$(VERBOSE)tar xfz $< --transform "s{$(LINUX){$(CONTRIB_DIR)/lxip{" --files-from lxip_header.list
$(VERBOSE)touch $@ $(VERBOSE)touch $@
$(ECHO) "applying patches to '$(CONTRIB_DIR)/'" $(ECHO) "applying patches to '$(CONTRIB_DIR)/'"
$(VERBOSE)for i in $(PATCHES); do patch -d $(CONTRIB_DIR) -p1 < $$i; done $(VERBOSE)for i in $(PATCHES); do patch -d $(CONTRIB_DIR) -p1 < $$i; done
$(VERBOSE)ln -sf ../../uapi/linux/usb/ch11.h $(CONTRIB_DIR)/include/linux/usb/ch11.h
$(VERBOSE)touch $(CONTRIB_DIR)/drivers/usb/dwc3/gadget.h $(VERBOSE)touch $(CONTRIB_DIR)/drivers/usb/dwc3/gadget.h
$(VERBOSE)touch $(CONTRIB_DIR)/drivers/usb/dwc3/debug.h $(VERBOSE)touch $(CONTRIB_DIR)/drivers/usb/dwc3/debug.h
@ -141,7 +62,7 @@ $(CONTRIB_DIR)/.prepared: $(DOWNLOAD_DIR)/$(LINUX_TBZ2)
$(DOWNLOAD_DIR): $(DOWNLOAD_DIR):
$(VERBOSE)mkdir -p $@ $(VERBOSE)mkdir -p $@
$(DOWNLOAD_DIR)/$(LINUX_TBZ2): $(DOWNLOAD_DIR) $(DOWNLOAD_DIR)/$(LINUX_TGZ): $(DOWNLOAD_DIR)
$(ECHO) "downloading source code to '$@'" $(ECHO) "downloading source code to '$@'"
$(VERBOSE)cd $(DOWNLOAD_DIR); wget -c $(LINUX_URL) $(VERBOSE)cd $(DOWNLOAD_DIR); wget -c $(LINUX_URL)
$(VERBOSE)touch $@ $(VERBOSE)touch $@

View File

@ -74,3 +74,11 @@ cannot be accessed via the host controller making it impossible to retrieve the
devices hardware address. If this is the case and no 'mac' attribute is given a devices hardware address. If this is the case and no 'mac' attribute is given a
fallback address will be assigned to the network device. Note that the fallback fallback address will be assigned to the network device. Note that the fallback
address will always be the same. address will always be the same.
LXIP
####
LXIP is a port of the Linux TCP/IP stack to Genode. It is build as a shared
library named 'lxip.lib.so'. The IP stack can be interfaced using Genode's
version of 'libc' by linking your application to 'lxip_libc' plugin in your
'target.mk' file.

228
dde_linux/files.list Normal file
View File

@ -0,0 +1,228 @@
linux-3.9/include/asm-generic/bitops/__ffs.h
linux-3.9/include/asm-generic/bitops/non-atomic.h
linux-3.9/include/asm-generic/ioctl.h
linux-3.9/include/linux/byteorder/generic.h
linux-3.9/include/linux/hiddev.h
linux-3.9/include/linux/hid.h
linux-3.9/include/linux/input.h
linux-3.9/include/linux/input/mt.h
linux-3.9/include/linux/list.h
linux-3.9/include/linux/mod_devicetable.h
linux-3.9/include/linux/netdev_features.h
linux-3.9/include/linux/pci_ids.h
linux-3.9/include/linux/platform_data/dwc3-exynos.h
linux-3.9/include/linux/platform_data/usb-ehci-s5p.h
linux-3.9/include/linux/platform_data/usb-omap.h
linux-3.9/include/linux/swab.h
linux-3.9/include/linux/usb/ch9.h
linux-3.9/include/linux/usb/ehci_def.h
linux-3.9/include/linux/usb.h
linux-3.9/include/linux/usb/hcd.h
linux-3.9/include/linux/usb/input.h
linux-3.9/include/linux/usb/otg.h
linux-3.9/include/linux/usb/phy.h
linux-3.9/include/linux/usb/quirks.h
linux-3.9/include/linux/usb/storage.h
linux-3.9/include/linux/usb/usbnet.h
linux-3.9/include/linux/usb_usual.h
linux-3.9/include/scsi/scsi.h
linux-3.9/include/scsi/scsi_host.h
linux-3.9/include/uapi/asm-generic/ioctl.h
linux-3.9/include/uapi/linux/byteorder/little_endian.h
linux-3.9/include/uapi/linux/hid.h
linux-3.9/include/uapi/linux/input.h
linux-3.9/include/uapi/linux/pci_regs.h
linux-3.9/include/uapi/linux/usb/ch11.h
linux-3.9/include/uapi/linux/usb/ch9.h
linux-3.9/arch/arm/plat-samsung/include/plat/usb-phy.h
linux-3.9/drivers/hid/hid-cherry.c
linux-3.9/drivers/hid/hid-core.c
linux-3.9/drivers/hid/hid-generic.c
linux-3.9/drivers/hid/hid-ids.h
linux-3.9/drivers/hid/hid-input.c
linux-3.9/drivers/hid/usbhid/hid-core.c
linux-3.9/drivers/hid/usbhid/hiddev.c
linux-3.9/drivers/hid/usbhid/hid-pidff.c
linux-3.9/drivers/hid/usbhid/hid-quirks.c
linux-3.9/drivers/hid/usbhid/Kconfig
linux-3.9/drivers/hid/usbhid/Makefile
linux-3.9/drivers/hid/usbhid/usbhid.h
linux-3.9/drivers/hid/usbhid/usbkbd.c
linux-3.9/drivers/hid/usbhid/usbmouse.c
linux-3.9/drivers/input/evdev.c
linux-3.9/drivers/input/input.c
linux-3.9/drivers/input/input-compat.h
linux-3.9/drivers/net/usb/asix_common.c
linux-3.9/drivers/net/usb/asix_devices.c
linux-3.9/drivers/net/usb/asix.h
linux-3.9/drivers/net/usb/ax88172a.c
linux-3.9/drivers/net/usb/ax88179_178a.c
linux-3.9/drivers/net/usb/smsc95xx.c
linux-3.9/drivers/net/usb/smsc95xx.h
linux-3.9/drivers/net/usb/usbnet.c
linux-3.9/drivers/scsi/constants.c
linux-3.9/drivers/scsi/scsi.c
linux-3.9/drivers/scsi/scsi.h
linux-3.9/drivers/scsi/scsi_logging.h
linux-3.9/drivers/scsi/scsi_priv.h
linux-3.9/drivers/usb/core/buffer.c
linux-3.9/drivers/usb/core/config.c
linux-3.9/drivers/usb/core/devices.c
linux-3.9/drivers/usb/core/driver.c
linux-3.9/drivers/usb/core/endpoint.c
linux-3.9/drivers/usb/core/file.c
linux-3.9/drivers/usb/core/generic.c
linux-3.9/drivers/usb/core/hcd.c
linux-3.9/drivers/usb/core/hcd-pci.c
linux-3.9/drivers/usb/core/hub.c
linux-3.9/drivers/usb/core/hub.h
linux-3.9/drivers/usb/core/message.c
linux-3.9/drivers/usb/core/notify.c
linux-3.9/drivers/usb/core/port.c
linux-3.9/drivers/usb/core/quirks.c
linux-3.9/drivers/usb/core/urb.c
linux-3.9/drivers/usb/core/usb.c
linux-3.9/drivers/usb/core/usb.h
linux-3.9/drivers/usb/dwc3/core.c
linux-3.9/drivers/usb/dwc3/core.h
linux-3.9/drivers/usb/dwc3/debug.h
linux-3.9/drivers/usb/dwc3/dwc3-exynos.c
linux-3.9/drivers/usb/dwc3/gadget.h
linux-3.9/drivers/usb/dwc3/host.c
linux-3.9/drivers/usb/dwc3/io.h
linux-3.9/drivers/usb/host/ehci-dbg.c
linux-3.9/drivers/usb/host/ehci.h
linux-3.9/drivers/usb/host/ehci-hcd.c
linux-3.9/drivers/usb/host/ehci-hub.c
linux-3.9/drivers/usb/host/ehci-mem.c
linux-3.9/drivers/usb/host/ehci-omap.c
linux-3.9/drivers/usb/host/ehci-pci.c
linux-3.9/drivers/usb/host/ehci-q.c
linux-3.9/drivers/usb/host/ehci-s5p.c
linux-3.9/drivers/usb/host/ehci-sched.c
linux-3.9/drivers/usb/host/ehci-sysfs.c
linux-3.9/drivers/usb/host/ehci-timer.c
linux-3.9/drivers/usb/host/ohci-dbg.c
linux-3.9/drivers/usb/host/ohci.h
linux-3.9/drivers/usb/host/ohci-hcd.c
linux-3.9/drivers/usb/host/ohci-hub.c
linux-3.9/drivers/usb/host/ohci-mem.c
linux-3.9/drivers/usb/host/ohci-pci.c
linux-3.9/drivers/usb/host/ohci-q.c
linux-3.9/drivers/usb/host/pci-quirks.c
linux-3.9/drivers/usb/host/pci-quirks.h
linux-3.9/drivers/usb/host/uhci-debug.c
linux-3.9/drivers/usb/host/uhci-hcd.c
linux-3.9/drivers/usb/host/uhci-hcd.h
linux-3.9/drivers/usb/host/uhci-hub.c
linux-3.9/drivers/usb/host/uhci-pci.c
linux-3.9/drivers/usb/host/uhci-q.c
linux-3.9/drivers/usb/host/xhci.c
linux-3.9/drivers/usb/host/xhci-dbg.c
linux-3.9/drivers/usb/host/xhci-ext-caps.h
linux-3.9/drivers/usb/host/xhci.h
linux-3.9/drivers/usb/host/xhci-hub.c
linux-3.9/drivers/usb/host/xhci-mem.c
linux-3.9/drivers/usb/host/xhci-plat.c
linux-3.9/drivers/usb/host/xhci-ring.c
linux-3.9/drivers/usb/storage/alauda.c
linux-3.9/drivers/usb/storage/cypress_atacb.c
linux-3.9/drivers/usb/storage/datafab.c
linux-3.9/drivers/usb/storage/debug.c
linux-3.9/drivers/usb/storage/debug.h
linux-3.9/drivers/usb/storage/ene_ub6250.c
linux-3.9/drivers/usb/storage/freecom.c
linux-3.9/drivers/usb/storage/initializers.c
linux-3.9/drivers/usb/storage/initializers.h
linux-3.9/drivers/usb/storage/isd200.c
linux-3.9/drivers/usb/storage/jumpshot.c
linux-3.9/drivers/usb/storage/karma.c
linux-3.9/drivers/usb/storage/Kconfig
linux-3.9/drivers/usb/storage/Makefile
linux-3.9/drivers/usb/storage/onetouch.c
linux-3.9/drivers/usb/storage/option_ms.c
linux-3.9/drivers/usb/storage/option_ms.h
linux-3.9/drivers/usb/storage/protocol.c
linux-3.9/drivers/usb/storage/protocol.h
linux-3.9/drivers/usb/storage/realtek_cr.c
linux-3.9/drivers/usb/storage/scsiglue.c
linux-3.9/drivers/usb/storage/scsiglue.h
linux-3.9/drivers/usb/storage/sddr09.c
linux-3.9/drivers/usb/storage/sddr55.c
linux-3.9/drivers/usb/storage/shuttle_usbat.c
linux-3.9/drivers/usb/storage/sierra_ms.c
linux-3.9/drivers/usb/storage/sierra_ms.h
linux-3.9/drivers/usb/storage/transport.c
linux-3.9/drivers/usb/storage/transport.h
linux-3.9/drivers/usb/storage/uas.c
linux-3.9/drivers/usb/storage/unusual_alauda.h
linux-3.9/drivers/usb/storage/unusual_cypress.h
linux-3.9/drivers/usb/storage/unusual_datafab.h
linux-3.9/drivers/usb/storage/unusual_devs.h
linux-3.9/drivers/usb/storage/unusual_ene_ub6250.h
linux-3.9/drivers/usb/storage/unusual_freecom.h
linux-3.9/drivers/usb/storage/unusual_isd200.h
linux-3.9/drivers/usb/storage/unusual_jumpshot.h
linux-3.9/drivers/usb/storage/unusual_karma.h
linux-3.9/drivers/usb/storage/unusual_onetouch.h
linux-3.9/drivers/usb/storage/unusual_realtek.h
linux-3.9/drivers/usb/storage/unusual_sddr09.h
linux-3.9/drivers/usb/storage/unusual_sddr55.h
linux-3.9/drivers/usb/storage/unusual_usbat.h
linux-3.9/drivers/usb/storage/usb.c
linux-3.9/drivers/usb/storage/usb.h
linux-3.9/drivers/usb/storage/usual-tables.c
linux-3.9/drivers/usb/usb-common.c
linux-3.9/lib/checksum.c
linux-3.9/net/802/p8023.c
linux-3.9/net/core/datagram.c
linux-3.9/net/core/dev.c
linux-3.9/net/core/dev_addr_lists.c
linux-3.9/net/core/dst.c
linux-3.9/net/core/ethtool.c
linux-3.9/net/core/iovec.c
linux-3.9/net/core/neighbour.c
linux-3.9/net/core/net-sysfs.h
linux-3.9/net/core/request_sock.c
linux-3.9/net/core/skbuff.c
linux-3.9/net/core/sock.c
linux-3.9/net/core/stream.c
linux-3.9/net/core/utils.c
linux-3.9/net/ethernet/eth.c
linux-3.9/net/ipv4/af_inet.c
linux-3.9/net/ipv4/arp.c
linux-3.9/net/ipv4/devinet.c
linux-3.9/net/ipv4/fib_frontend.c
linux-3.9/net/ipv4/fib_lookup.h
linux-3.9/net/ipv4/fib_semantics.c
linux-3.9/net/ipv4/fib_trie.c
linux-3.9/net/ipv4/icmp.c
linux-3.9/net/ipv4/inet_connection_sock.c
linux-3.9/net/ipv4/inet_fragment.c
linux-3.9/net/ipv4/inet_hashtables.c
linux-3.9/net/ipv4/inetpeer.c
linux-3.9/net/ipv4/ipconfig.c
linux-3.9/net/ipv4/ip_forward.c
linux-3.9/net/ipv4/ip_fragment.c
linux-3.9/net/ipv4/ip_input.c
linux-3.9/net/ipv4/ip_options.c
linux-3.9/net/ipv4/ip_output.c
linux-3.9/net/ipv4/ip_sockglue.c
linux-3.9/net/ipv4/ping.c
linux-3.9/net/ipv4/protocol.c
linux-3.9/net/ipv4/raw.c
linux-3.9/net/ipv4/route.c
linux-3.9/net/ipv4/tcp.c
linux-3.9/net/ipv4/tcp_cong.c
linux-3.9/net/ipv4/tcp_cubic.c
linux-3.9/net/ipv4/tcp_diag.c
linux-3.9/net/ipv4/tcp_input.c
linux-3.9/net/ipv4/tcp_ipv4.c
linux-3.9/net/ipv4/tcp_minisocks.c
linux-3.9/net/ipv4/tcp_output.c
linux-3.9/net/ipv4/tcp_timer.c
linux-3.9/net/ipv4/udp.c
linux-3.9/net/ipv4/udp_impl.h
linux-3.9/net/netlink/af_netlink.c
linux-3.9/net/sched/sch_generic.c

View File

@ -0,0 +1,97 @@
/*
* \brief Lxip: Linux TCP/IP as a library
* \author Christian Helmuth
* \author Sebastian Sumpf
* \date 2013-09-04
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE_LXIP_LXIP_H_
#define _INCLUDE_LXIP_LXIP_H_
#include <base/stdint.h>
namespace Lxip {
struct Handle
{
void *socket;
bool non_block;
Handle() : socket(0), non_block(false) { }
};
enum Type { TYPE_STREAM, TYPE_DGRAM };
class Socketcall;
Socketcall & init();
typedef Genode::uint8_t uint8_t;
typedef Genode::uint16_t uint16_t;
typedef Genode::uint32_t uint32_t;
typedef signed long ssize_t;
typedef Genode::size_t size_t;
enum Poll_mask {
POLLIN = 0x1,
POLLOUT = 0x2,
POLLEX = 0x4,
};
enum Message_flags {
LINUX_MSG_COMPAT = 0x0,
LINUX_MSG_OOB = 0x1,
LINUX_MSG_PEEK = 0x2,
LINUX_MSG_DONTROUTE = 0x4,
LINUX_MSG_CTRUNC = 0x8,
LINUX_MSG_TRUNC = 0x20,
LINUX_MSG_DONTWAIT = 0x40,
LINUX_MSG_EOR = 0x80,
LINUX_MSG_WAITALL = 0x100,
LINUX_MSG_EOF = 0x200,
LINUX_MSG_NOSIGNAL = 0x4000,
};
enum Socket_level {
LINUX_SOL_SOCKET = 1,
};
enum Ioctl_cmd {
LINUX_FIONREAD = 0x541b /* == SIOCINQ */
};
}
class Lxip::Socketcall
{
public:
virtual Handle accept(Handle h, void *addr, uint32_t *len) = 0;
virtual int bind(Handle h, uint16_t family, void *addr) = 0;
virtual void close(Handle h) = 0;
virtual int connect(Handle h, uint16_t family, void *addr) = 0;
virtual int getpeername(Handle h, void *addr, uint32_t *len) = 0;
virtual int getsockname(Handle h, void *addr, uint32_t *len) = 0;
virtual int getsockopt(Handle h, int level, int optname,
void *optval, int *optlen) = 0;
virtual int ioctl(Handle h, int request, char *arg) = 0;
virtual int listen(Handle h, int backlog) = 0;
virtual int poll(Handle h, bool block) = 0;
virtual ssize_t recv(Handle h, void *buf, size_t len, int flags,
uint16_t family, void *addr, uint32_t *addr_len) = 0;
virtual ssize_t send(Handle h, const void *buf, size_t len, int flags,
uint16_t family, void *addr) = 0;
virtual int setsockopt(Handle h, int level, int optname,
const void *optval, uint32_t optlen) = 0;
virtual int shutdown(Handle h, int how) = 0;
virtual Handle socket(Type) = 0;
};
#endif /* _INCLUDE_LXIP_LXIP_H_ */

View File

@ -0,0 +1,5 @@
SRC_CC = init.cc plugin.cc
vpath %.cc $(REP_DIR)/src/lib/libc_lxip
LIBS += lxip libc libc_resolv

94
dde_linux/lib/mk/lxip.mk Normal file
View File

@ -0,0 +1,94 @@
SHARED_LIB = yes
LIB_DIR = $(REP_DIR)/src/lib/lxip
LIB_INC_DIR = $(LIB_DIR)/include
LIBS += base cxx dde_kit
CONTRIB_DIR := $(REP_DIR)/contrib
NET_DIR := $(CONTRIB_DIR)/net
#
# The order of include-search directories is important, we need to look into
# 'contrib' before falling back to our custom 'lx_emul.h' header.
#
INC_DIR += $(LIB_INC_DIR)
INC_DIR += $(CONTRIB_DIR)/include $(CONTRIB_DIR)/include/uapi \
$(CONTRIB_DIR)/lxip/include $(CONTRIB_DIR)/lxip/include/uapi \
$(CONTRIB_DIR)
CC_OLEVEL = -O2
SETUP_SUFFIX =
CC_OPT += -DSETUP_SUFFIX=$(SETUP_SUFFIX)
CC_OPT += -U__linux__ -D__KERNEL__
CC_OPT += -DCONFIG_INET -DCONFIG_BASE_SMALL=0 -DCONFIG_DEBUG_LOCK_ALLOC \
-DCONFIG_IP_PNP_DHCP
CC_WARN = -Wall -Wno-unused-variable -Wno-uninitialized \
-Wno-unused-function -Wno-overflow -Wno-pointer-arith \
-Wno-sign-compare
CC_C_OPT += -Wno-implicit-function-declaration -Wno-unused-but-set-variable \
-Wno-pointer-sign
CC_C_OPT += -include $(LIB_INC_DIR)/lx_emul.h
CC_CXX_OPT = -fpermissive
SRC_CC = dummies.cc env.cc lxcc_emul.cc nic_handler.cc socket_handler.cc \
timer_handler.cc
SRC_C += driver.c init.c lxc_emul.c socket.c
SRC_C += net/802/p8023.c
SRC_C += $(addprefix net/core/,$(notdir $(wildcard $(NET_DIR)/core/*.c)))
SRC_C += $(addprefix net/ipv4/,$(notdir $(wildcard $(NET_DIR)/ipv4/*.c)))
SRC_C += net/ethernet/eth.c
SRC_C += net/netlink/af_netlink.c
SRC_C += net/sched/sch_generic.c
SRC_C += lib/checksum.c
# DHCP support
SRC_C += net/ipv4/ipconfig.c
#SRC_C = net/ipv4/inet_connection_sock.c
#
# Determine the header files included by the contrib code. For each
# of these header files we create a symlink to 'lx_emul.h'.
#
GEN_INCLUDES := $(shell grep -rh "^\#include .*\/" $(CONTRIB_DIR) |\
sed "s/^\#include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" | sort | uniq)
#
# Filter out original Linux headers that exist in the contrib directory
#
NO_GEN_INCLUDES := $(shell cd $(CONTRIB_DIR); find -name "*.h" | sed "s/.\///" | sed "s/.*include\///")
GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES))
#
# Put Linux headers in 'GEN_INC' dir, since some include use "../../" paths use
# three level include hierarchy
#
GEN_INC := $(shell pwd)/include/include/include
$(shell mkdir -p $(GEN_INC))
GEN_INCLUDES := $(addprefix $(GEN_INC)/,$(GEN_INCLUDES))
INC_DIR += $(GEN_INC)
#
# Make sure to create the header symlinks prior building
#
$(SRC_C:.c=.o) $(SRC_CC:.cc=.o): $(GEN_INCLUDES)
net/ethernet/eth.o: SETUP_SUFFIX="_eth"
$(GEN_INCLUDES):
$(VERBOSE)mkdir -p $(dir $@)
$(VERBOSE)ln -s $(LIB_INC_DIR)/lx_emul.h $@
vpath %.c $(CONTRIB_DIR)
vpath %.c $(LIB_DIR)
vpath %.cc $(LIB_DIR)

View File

@ -17,7 +17,7 @@ CC_OLEVEL = -O2
# 'contrib' before falling back to our custom 'lx_emul.h' header. # 'contrib' before falling back to our custom 'lx_emul.h' header.
# #
INC_DIR += $(LIB_INC_DIR) INC_DIR += $(LIB_INC_DIR)
INC_DIR += $(CONTRIB_DIR)/include $(CONTRIB_DIR) INC_DIR += $(CONTRIB_DIR)/include $(CONTRIB_DIR)/include/uapi $(CONTRIB_DIR)
CC_OPT += -U__linux__ -D__KERNEL__ CC_OPT += -U__linux__ -D__KERNEL__
CC_OPT += -DCONFIG_USB_DEVICEFS -DCONFIG_HOTPLUG -DDEBUG CC_OPT += -DCONFIG_USB_DEVICEFS -DCONFIG_HOTPLUG -DDEBUG
@ -28,6 +28,7 @@ CC_WARN = -Wall -Wno-unused-variable -Wno-uninitialized \
CC_C_OPT += -Wno-implicit-function-declaration -Wno-unused-but-set-variable \ CC_C_OPT += -Wno-implicit-function-declaration -Wno-unused-but-set-variable \
-Wno-pointer-sign -Wno-pointer-sign
CXX_OPT = -fpermissive
# #
# Suffix of global 'module_init' function # Suffix of global 'module_init' function
# #
@ -57,13 +58,13 @@ SRC_C += $(addprefix scsi/,scsi.c constants.c)
# Determine the header files included by the contrib code. For each # Determine the header files included by the contrib code. For each
# of these header files we create a symlink to 'lx_emul.h'. # of these header files we create a symlink to 'lx_emul.h'.
# #
GEN_INCLUDES := $(shell grep -Rh "^\#include .*\/" $(CONTRIB_DIR) |\ GEN_INCLUDES := $(shell grep -rh "^\#include .*\/" $(CONTRIB_DIR) |\
sed "s/^\#include *[<\"]\(.*\)[>\"].*/\1/" | sort | uniq) sed "s/^\#include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" | sort | uniq)
# #
# Filter out original Linux headers that exist in the contrib directory # Filter out original Linux headers that exist in the contrib directory
# #
NO_GEN_INCLUDES := $(shell cd $(CONTRIB_DIR); find -name "*.h" | sed "s/.\///" | sed "s/.*include\///") NO_GEN_INCLUDES := $(shell cd $(CONTRIB_DIR)/include; find -name "*.h" | sed "s/.\///" | sed "s/.*include\///")
GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES)) GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES))
# #

View File

@ -0,0 +1,85 @@
linux-3.9/include/linux/errqueue.h
linux-3.9/include/linux/etherdevice.h
linux-3.9/include/linux/ethtool.h
linux-3.9/include/linux/icmp.h
linux-3.9/include/linux/if_arp.h
linux-3.9/include/linux/if_ether.h
linux-3.9/include/linux/if_link.h
linux-3.9/include/linux/jhash.h
linux-3.9/include/linux/inetdevice.h
linux-3.9/include/linux/list_nulls.h
linux-3.9/include/linux/netdev_features.h
linux-3.9/include/linux/netdevice.h
linux-3.9/include/linux/net.h
linux-3.9/include/linux/netlink.h
linux-3.9/include/linux/skbuff.h
linux-3.9/include/linux/socket.h
linux-3.9/include/linux/tcp.h
linux-3.9/include/linux/udp.h
linux-3.9/include/net/arp.h
linux-3.9/include/net/datalink.h
linux-3.9/include/net/dst.h
linux-3.9/include/net/dst_ops.h
linux-3.9/include/net/dsfield.h
linux-3.9/include/net/flow.h
linux-3.9/include/net/icmp.h
linux-3.9/include/net/inet_connection_sock.h
linux-3.9/include/net/inet_frag.h
linux-3.9/include/net/inet_hashtables.h
linux-3.9/include/net/inetpeer.h
linux-3.9/include/net/inet_sock.h
linux-3.9/include/net/inet_timewait_sock.h
linux-3.9/include/net/ipconfig.h
linux-3.9/include/net/ip_fib.h
linux-3.9/include/net/ip.h
linux-3.9/include/net/neighbour.h
linux-3.9/include/net/netlink.h
linux-3.9/include/net/netns/ipv4.h
linux-3.9/include/net/netns/mib.h
linux-3.9/include/net/ping.h
linux-3.9/include/net/pkt_sched.h
linux-3.9/include/net/protocol.h
linux-3.9/include/net/raw.h
linux-3.9/include/net/request_sock.h
linux-3.9/include/net/route.h
linux-3.9/include/net/sch_generic.h
linux-3.9/include/net/snmp.h
linux-3.9/include/net/sock.h
linux-3.9/include/net/tcp.h
linux-3.9/include/net/tcp_states.h
linux-3.9/include/net/timewait_sock.h
linux-3.9/include/net/udp.h
linux-3.9/include/net/udplite.h
linux-3.9/include/uapi/asm-generic/socket.h
linux-3.9/include/uapi/linux/errqueue.h
linux-3.9/include/uapi/linux/ethtool.h
linux-3.9/include/uapi/linux/fib_rules.h
linux-3.9/include/uapi/linux/gen_stats.h
linux-3.9/include/uapi/linux/icmp.h
linux-3.9/include/uapi/linux/if_addr.h
linux-3.9/include/uapi/linux/if_arp.h
linux-3.9/include/uapi/linux/if_bridge.h
linux-3.9/include/uapi/linux/if_ether.h
linux-3.9/include/uapi/linux/if.h
linux-3.9/include/uapi/linux/if_link.h
linux-3.9/include/uapi/linux/if_packet.h
linux-3.9/include/uapi/linux/in6.h
linux-3.9/include/uapi/linux/inet_diag.h
linux-3.9/include/uapi/linux/in.h
linux-3.9/include/uapi/linux/in_route.h
linux-3.9/include/uapi/linux/ip.h
linux-3.9/include/uapi/linux/neighbour.h
linux-3.9/include/uapi/linux/netconf.h
linux-3.9/include/uapi/linux/netdevice.h
linux-3.9/include/uapi/linux/netfilter.h
linux-3.9/include/uapi/linux/net.h
linux-3.9/include/uapi/linux/netlink.h
linux-3.9/include/uapi/linux/pkt_sched.h
linux-3.9/include/uapi/linux/route.h
linux-3.9/include/uapi/linux/rtnetlink.h
linux-3.9/include/uapi/linux/snmp.h
linux-3.9/include/uapi/linux/socket.h
linux-3.9/include/uapi/linux/sockios.h
linux-3.9/include/uapi/linux/swab.h
linux-3.9/include/uapi/linux/tcp.h
linux-3.9/include/uapi/linux/udp.h

View File

@ -0,0 +1,12 @@
diff -r a4522abad72d net/ipv4/icmp.c
--- a/net/ipv4/icmp.c Tue Oct 15 12:18:08 2013 +0200
+++ b/net/ipv4/icmp.c Tue Oct 15 12:18:33 2013 +0200
@@ -787,7 +787,7 @@
if (!net->ipv4.sysctl_icmp_echo_ignore_all) {
struct icmp_bxm icmp_param;
- icmp_param.data.icmph = *icmp_hdr(skb);
+ memcpy(&icmp_param.data.icmph, icmp_hdr(skb), sizeof(struct icmphdr));
icmp_param.data.icmph.type = ICMP_ECHOREPLY;
icmp_param.skb = skb;
icmp_param.offset = 0;

View File

@ -0,0 +1,36 @@
diff -r d3a8e67b38cf net/ipv4/ipconfig.c
--- a/net/ipv4/ipconfig.c Fri Sep 20 12:18:22 2013 +0200
+++ b/net/ipv4/ipconfig.c Fri Sep 20 12:18:56 2013 +0200
@@ -1505,24 +1505,24 @@
*/
pr_info("IP-Config: Complete:\n");
- pr_info(" device=%s, hwaddr=%*phC, ipaddr=%pI4, mask=%pI4, gw=%pI4\n",
- ic_dev->name, ic_dev->addr_len, ic_dev->dev_addr,
- &ic_myaddr, &ic_netmask, &ic_gateway);
+ pr_info(" device=%s, len=%u hwaddr=" MAC_FMT ", ipaddr=" IP_FMT ", mask=" IP_FMT " , gw=" IP_FMT "\n",
+ ic_dev->name, ic_dev->addr_len, MAC_ARG(ic_dev->dev_addr),
+ IP_ARG(ic_myaddr), IP_ARG(ic_netmask), IP_ARG(ic_gateway));
pr_info(" host=%s, domain=%s, nis-domain=%s\n",
utsname()->nodename, ic_domain, utsname()->domainname);
- pr_info(" bootserver=%pI4, rootserver=%pI4, rootpath=%s",
- &ic_servaddr, &root_server_addr, root_server_path);
+ pr_info(" bootserver=" IP_FMT ", rootserver=" IP_FMT ", rootpath=%s\n",
+ IP_ARG(ic_servaddr), IP_ARG(root_server_addr), root_server_path);
if (ic_dev_mtu)
pr_cont(", mtu=%d", ic_dev_mtu);
for (i = 0; i < CONF_NAMESERVERS_MAX; i++)
if (ic_nameservers[i] != NONE) {
- pr_info(" nameserver%u=%pI4",
- i, &ic_nameservers[i]);
+ pr_info(" nameserver%u=" IP_FMT,
+ i, IP_ARG(ic_nameservers[i]));
break;
}
for (i++; i < CONF_NAMESERVERS_MAX; i++)
if (ic_nameservers[i] != NONE)
- pr_cont(", nameserver%u=%pI4", i, &ic_nameservers[i]);
+ pr_cont(", nameserver%u=" IP_FMT, i, IP_ARG(ic_nameservers[i]));
pr_cont("\n");
#endif /* !SILENT */

View File

@ -0,0 +1,30 @@
diff -r 6e1a0ab143a5 net/core/skbuff.c
--- a/net/core/skbuff.c Fri Oct 18 12:02:45 2013 +0200
+++ b/net/core/skbuff.c Fri Oct 18 12:04:07 2013 +0200
@@ -419,23 +419,9 @@
unsigned int fragsz = SKB_DATA_ALIGN(length + NET_SKB_PAD) +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
- if (fragsz <= PAGE_SIZE && !(gfp_mask & (__GFP_WAIT | GFP_DMA))) {
- void *data;
-
- if (sk_memalloc_socks())
- gfp_mask |= __GFP_MEMALLOC;
-
- data = __netdev_alloc_frag(fragsz, gfp_mask);
-
- if (likely(data)) {
- skb = build_skb(data, fragsz);
- if (unlikely(!skb))
- put_page(virt_to_head_page(data));
- }
- } else {
- skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask,
- SKB_ALLOC_RX, NUMA_NO_NODE);
- }
+ skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask,
+ SKB_ALLOC_RX, NUMA_NO_NODE);
+
if (likely(skb)) {
skb_reserve(skb, NET_SKB_PAD);
skb->dev = dev;

View File

@ -0,0 +1,32 @@
From 8b2f74f2258b62ca0e62656cdccbc9159aeab893 Mon Sep 17 00:00:00 2001
From: Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
Date: Tue, 6 Aug 2013 16:12:54 +0200
Subject: [PATCH] L4Linux: Increase TCP-window size
TCP window size is calculated by the amount of memory within L4Linux, use a
larger window size to allow acceptable performance even on smaller VMs.
---
net/ipv4/tcp.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index e220207..29613bf 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -3648,6 +3648,13 @@ void __init tcp_init(void)
tcp_init_mem(&init_net);
/* Set per-socket limits to no more than 1/128 the pressure threshold */
limit = nr_free_buffer_pages() << (PAGE_SHIFT - 7);
+
+ /*
+ * Adjust limit so it performs well on systems with little memory. If
+ * this causes errors increase L4Linux main memory
+ */
+ limit = limit < 1024U * 1024 ? 1024U * 1024 : limit;
+
max_wshare = min(4UL*1024*1024, limit);
max_rshare = min(6UL*1024*1024, limit);
--
1.8.4

View File

@ -0,0 +1,24 @@
/*
* \brief Lxip plugin creation
* \author Christian Helmuth
* \author Sebastian Sumpf
* \date 2013-09-04
*
*/
/*
* Copyright (C) 2010-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/printf.h>
extern void create_lxip_plugin();
void __attribute__((constructor)) init_libc_lxip(void)
{
PDBG("init_libc_lxip()\n");
create_lxip_plugin();
}

View File

@ -0,0 +1,657 @@
/*
* \brief Lxip plugin implementation
* \author Sebastian Sumpf
* \author Christian Helmuth
* \date 2013-09-04
*/
/*
* Copyright (C) 2010-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Libc includes */
#include <errno.h>
#include <netinet/in.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
/* Genode includes */
#include <base/env.h>
#include <base/printf.h>
/* Libc plugin includes */
#include <libc-plugin/fd_alloc.h>
#include <libc-plugin/plugin_registry.h>
/* Lxip includes */
#include <lxip/lxip.h>
/**************************
** Linux family numbers **
**************************/
enum {
LINUX_AF_INET = 2
};
/**********************
** Plugin interface **
**********************/
extern "C" void wait_for_continue();
namespace {
class Plugin_context : public Libc::Plugin_context
{
private:
Lxip::Handle _handle;
public:
/**
* Constructor
*/
Plugin_context(Lxip::Handle handle) : _handle(handle) { }
Lxip::Handle handle() const { return _handle; }
void non_block(bool nb) { _handle.non_block = nb; }
};
static inline Plugin_context * context(Libc::File_descriptor *fd)
{
return static_cast<Plugin_context *>(fd->context);
}
struct Plugin : Libc::Plugin
{
/**
* Interface to LXIP stack
*/
struct Lxip::Socketcall &socketcall;
/**
* Constructor
*/
Plugin();
bool supports_select(int nfds,
fd_set *readfds,
fd_set *writefds,
fd_set *exceptfds,
struct timeval *timeout);
bool supports_socket(int domain, int type, int protocol);
Libc::File_descriptor *accept(Libc::File_descriptor *sockfdo,
struct sockaddr *addr,
socklen_t *addrlen);
int bind(Libc::File_descriptor *sockfdo,
const struct sockaddr *addr,
socklen_t addrlen);
int close(Libc::File_descriptor *fdo);
int connect(Libc::File_descriptor *sockfdo,
const struct sockaddr *addr,
socklen_t addrlen);
int fcntl(Libc::File_descriptor *sockfdo, int cmd, long val);
int getpeername(Libc::File_descriptor *sockfdo,
struct sockaddr *addr,
socklen_t *addrlen);
int getsockname(Libc::File_descriptor *sockfdo,
struct sockaddr *addr,
socklen_t *addrlen);
int getsockopt(Libc::File_descriptor *sockfdo, int level,
int optname, void *optval,
socklen_t *optlen);
int ioctl(Libc::File_descriptor *sockfdo, int request, char *argp);
int listen(Libc::File_descriptor *sockfdo, int backlog);
ssize_t read(Libc::File_descriptor *fdo, void *buf, ::size_t count);
int shutdown(Libc::File_descriptor *fdo, int);
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
ssize_t send(Libc::File_descriptor *, const void *buf, ::size_t len, int flags);
ssize_t sendto(Libc::File_descriptor *, const void *buf,
::size_t len, int flags,
const struct sockaddr *dest_addr,
socklen_t addrlen);
ssize_t recv(Libc::File_descriptor *, void *buf, ::size_t len, int flags);
ssize_t recvfrom(Libc::File_descriptor *, void *buf, ::size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
int setsockopt(Libc::File_descriptor *sockfdo, int level,
int optname, const void *optval,
socklen_t optlen);
Libc::File_descriptor *socket(int domain, int type, int protocol);
ssize_t write(Libc::File_descriptor *fdo, const void *buf, ::size_t count);
int linux_family(const struct sockaddr *addr, socklen_t addrlen);
int bsd_family(struct sockaddr *addr);
int retrieve_and_clear_fds(int nfds, struct fd_set *fds, struct fd_set *in);
int translate_msg_flags(int bsd_flags);
int translate_ops_linux(int optname);
};
Plugin::Plugin() : socketcall(Lxip::init())
{
PDBG("using the lxip libc plugin");
}
/* TODO shameful copied from lwip... generalize this */
bool Plugin::supports_select(int nfds,
fd_set *readfds,
fd_set *writefds,
fd_set *exceptfds,
struct timeval *timeout)
{
/*
* Return true if any file descriptor which is marked set in one of
* the sets belongs to this plugin.
*/
Libc::File_descriptor *fdo;
for (int libc_fd = 0; libc_fd < nfds; libc_fd++) {
if (FD_ISSET(libc_fd, readfds)
|| FD_ISSET(libc_fd, writefds) || FD_ISSET(libc_fd, exceptfds)) {
fdo = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd);
if (fdo && (fdo->plugin == this)) {
return true;
}
}
}
return false;
}
bool Plugin::supports_socket(int domain, int type, int)
{
if (domain == AF_INET && (type == SOCK_STREAM || type == SOCK_DGRAM))
return true;
return false;
}
Libc::File_descriptor *Plugin::accept(Libc::File_descriptor *sockfdo,
struct sockaddr *addr, socklen_t *addrlen)
{
Lxip::Handle handle;
handle = socketcall.accept(context(sockfdo)->handle(), (void *)addr, addrlen);
if (!handle.socket)
return 0;
if (addr) {
addr->sa_family = bsd_family(addr);
addr->sa_len = *addrlen;
}
Plugin_context *context = new (Genode::env()->heap()) Plugin_context(handle);
Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->alloc(this, context);
return fd;
}
int Plugin::bind(Libc::File_descriptor *sockfdo, const struct sockaddr *addr,
socklen_t addrlen)
{
int family;
if (!(family = linux_family(addr, addrlen))) {
errno = ENOTSUP;
return -1;
}
errno = -socketcall.bind(context(sockfdo)->handle(), family, (void*)addr);
return errno > 0 ? -1 : 0;
}
int Plugin::close(Libc::File_descriptor *sockfdo)
{
socketcall.close(context(sockfdo)->handle());
if (context(sockfdo))
Genode::destroy(Genode::env()->heap(), context(sockfdo));
Libc::file_descriptor_allocator()->free(sockfdo);
return 0;
}
int Plugin::connect(Libc::File_descriptor *sockfdo,
const struct sockaddr *addr,
socklen_t addrlen)
{
int family;
if (!(family = linux_family(addr, addrlen))) {
errno = ENOTSUP;
return -1;
}
errno = -socketcall.connect(context(sockfdo)->handle(), family, (void *)addr);
return errno > 0 ? -1 : 0;
}
int Plugin::fcntl(Libc::File_descriptor *sockfdo, int cmd, long val)
{
switch (cmd) {
case F_GETFL:
return context(sockfdo)->handle().non_block ? O_NONBLOCK : 0;
case F_SETFL:
context(sockfdo)->non_block(!!(val & O_NONBLOCK));
return 0;
default:
PERR("unsupported fcntl() request: %d", cmd);
errno = ENOSYS;
return -1;
}
}
/* XXX freeaddrinfo / getaddrinfo from libc_resolv.conf */
int Plugin::getpeername(Libc::File_descriptor *sockfdo,
struct sockaddr *addr,
socklen_t *addrlen)
{
if (!addr) {
errno = EFAULT;
return -1;
}
errno = -socketcall.getpeername(context(sockfdo)->handle(), (void *)addr, addrlen);
addr->sa_family = bsd_family(addr);
addr->sa_len = *addrlen;
return errno > 0 ? -1 : 0;
}
int Plugin::getsockname(Libc::File_descriptor *sockfdo,
struct sockaddr *addr,
socklen_t *addrlen)
{
if (!addr) {
errno = EFAULT;
return -1;
}
errno = -socketcall.getsockname(context(sockfdo)->handle(), (void *)addr, addrlen);
addr->sa_family = bsd_family(addr);
addr->sa_len = *addrlen;
return errno > 0 ? -1 : 0;
}
int Plugin::getsockopt(Libc::File_descriptor *sockfdo, int level,
int optname, void *optval, socklen_t *optlen)
{
if (level != SOL_SOCKET) {
PERR("%s: Unsupported level %d, we only support SOL_SOCKET for now",
__func__, level);
errno = EBADF;
return -1;
}
optname = translate_ops_linux(optname);
if (optname < 0) {
errno = ENOPROTOOPT;
return -1;
}
return socketcall.getsockopt(context(sockfdo)->handle(), Lxip::LINUX_SOL_SOCKET,
optname, optval, (int *)optlen);
}
int Plugin::ioctl(Libc::File_descriptor *sockfdo, int request, char *argp)
{
switch (request) {
case FIONBIO:
context(sockfdo)->non_block(!!*argp);
return 0;
case FIONREAD:
errno = -socketcall.ioctl(context(sockfdo)->handle(), Lxip::LINUX_FIONREAD,
argp);
return errno > 0 ? -1 : 0;
default:
PERR("unsupported ioctl() request");
errno = ENOSYS;
return -1;
}
}
int Plugin::listen(Libc::File_descriptor *sockfdo, int backlog)
{
errno = -socketcall.listen(context(sockfdo)->handle(), backlog);
return errno > 0 ? -1 : 0;
}
int Plugin::shutdown(Libc::File_descriptor *sockfdo, int how)
{
errno = -socketcall.shutdown(context(sockfdo)->handle(), how);
return errno > 0 ? -1 : 0;
}
/* TODO: Support timeouts */
/* XXX: Check blocking and non-blocking semantics */
int Plugin::select(int nfds,
fd_set *readfds,
fd_set *writefds,
fd_set *exceptfds,
struct timeval *timeout)
{
Libc::File_descriptor *sockfdo;
struct fd_set fds[3];
int bits = 0;
if (nfds < 0) {
errno = EINVAL;
return -1;
}
for (int i = 0; i < 3; i++)
FD_ZERO(&fds[i]);
bool block = false;
for (int fd = 0; fd <= nfds; fd++) {
if (fd == nfds && !bits) {
fd = -1;
block = true;
continue;
}
int set = 0;
set |= FD_ISSET(fd, readfds);
set |= FD_ISSET(fd, writefds);
set |= FD_ISSET(fd, exceptfds);
if (!set)
continue;
sockfdo = Libc::file_descriptor_allocator()->find_by_libc_fd(fd);
/* handle only libc_fds that belong to this plugin */
if (!sockfdo || (sockfdo->plugin != this))
continue;
/* call IP stack blocking/non-blocking */
int mask = socketcall.poll(context(sockfdo)->handle(), block);
if (mask)
block = false;
if (readfds && (mask & Lxip::POLLIN) && FD_ISSET(fd, readfds) && ++bits)
FD_SET(fd, &fds[0]);
if (writefds && (mask & Lxip::POLLOUT) && FD_ISSET(fd, writefds) && ++bits)
FD_SET(fd, &fds[1]);
if (exceptfds && (mask & Lxip::POLLEX) && FD_ISSET(fd, exceptfds) && ++bits)
FD_SET(fd, &fds[2]);
}
if (readfds) *readfds = fds[0];
if (writefds) *writefds = fds[1];
if (exceptfds) *exceptfds = fds[2];
return bits;
}
ssize_t Plugin::read(Libc::File_descriptor *fdo, void *buf, ::size_t count)
{
return recv(fdo, buf, count, 0);
}
ssize_t Plugin::recv(Libc::File_descriptor *sockfdo, void *buf, ::size_t len, int flags)
{
return recvfrom(sockfdo, buf, len, flags, 0, 0);
}
ssize_t Plugin::recvfrom(Libc::File_descriptor *sockfdo, void *buf, ::size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
{
int family = 0;
if (src_addr && addrlen && !(family = linux_family(src_addr, *addrlen))) {
errno = ENOTSUP;
return -1;
}
int recv = socketcall.recv(context(sockfdo)->handle(), buf, len, translate_msg_flags(flags),
family, (void *)src_addr, addrlen);
if (recv < 0) {
errno = -recv;
return errno == EAGAIN ? 0 : -1;
}
if (src_addr) {
src_addr->sa_family = bsd_family(src_addr);
src_addr->sa_len = *addrlen;
}
return recv;
}
ssize_t Plugin::send(Libc::File_descriptor *sockfdo, const void *buf, ::size_t len, int flags)
{
return sendto(sockfdo, buf, len, flags, 0, 0);
}
ssize_t Plugin::sendto(Libc::File_descriptor *sockfdo, const void *buf,
::size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen)
{
int family = 0;
if (dest_addr && addrlen && !(family = linux_family(dest_addr, addrlen))) {
errno = ENOTSUP;
return -1;
}
int send = socketcall.send(context(sockfdo)->handle(), buf, len, translate_msg_flags(flags),
family, (void *)dest_addr);
if (send < 0)
errno = -send;
return send < 0 ? -1 : send;
}
int Plugin::setsockopt(Libc::File_descriptor *sockfdo, int level,
int optname, const void *optval,
socklen_t optlen)
{
if (level != SOL_SOCKET) {
PERR("%s: Unsupported level %d, we only support SOL_SOCKET for now",
__func__, level);
errno = EBADF;
return -1;
}
optname = translate_ops_linux(optname);
if (optname < 0) {
errno = ENOPROTOOPT;
return -1;
}
return socketcall.setsockopt(context(sockfdo)->handle(), Lxip::LINUX_SOL_SOCKET,
optname, optval, optlen);
}
Libc::File_descriptor *Plugin::socket(int domain, int type, int protocol)
{
using namespace Lxip;
Handle handle = socketcall.socket(type == SOCK_STREAM ? TYPE_STREAM : TYPE_DGRAM);
if (!handle.socket) {
errno = EBADF;
return 0;
}
Plugin_context *context = new (Genode::env()->heap()) Plugin_context(handle);
Libc::File_descriptor *fd = Libc::file_descriptor_allocator()->alloc(this, context);
return fd;
}
ssize_t Plugin::write(Libc::File_descriptor *fdo, const void *buf, ::size_t count)
{
return send(fdo, buf, count, 0);
}
int Plugin::linux_family(const struct sockaddr *addr, socklen_t addrlen)
{
switch (addr->sa_family)
{
case AF_INET:
return LINUX_AF_INET;
default:
PERR("Unsupported socket BSD-protocol %u\n", addr->sa_family);
return 0;
}
return 0;
}
int Plugin::bsd_family(struct sockaddr *addr)
{
/*
* Note: Since in Linux 'sa_family' is 16 bit while in BSD it is 8 bit (both
* little endian), 'sa_len' will contain the actual family (or lower order
* bits) of Linux
*/
addr->sa_family = addr->sa_len;
switch (addr->sa_family)
{
case LINUX_AF_INET: return AF_INET;
default:
PERR("Unsupported socket Linux-protocol %u\n", addr->sa_family);
return 0;
}
}
int Plugin::translate_msg_flags(int bsd_flags)
{
using namespace Lxip;
int f = 0;
if (bsd_flags & MSG_OOB) f |= LINUX_MSG_OOB;
if (bsd_flags & MSG_PEEK) f |= LINUX_MSG_PEEK;
if (bsd_flags & MSG_DONTROUTE) f |= LINUX_MSG_DONTROUTE;
if (bsd_flags & MSG_EOR) f |= LINUX_MSG_EOR;
if (bsd_flags & MSG_TRUNC) f |= LINUX_MSG_TRUNC;
if (bsd_flags & MSG_CTRUNC) f |= LINUX_MSG_CTRUNC;
if (bsd_flags & MSG_WAITALL) f |= LINUX_MSG_WAITALL;
if (bsd_flags & MSG_NOTIFICATION) PWRN("MSG_NOTIFICATION ignored");
if (bsd_flags & MSG_DONTWAIT) f |= LINUX_MSG_DONTWAIT;
if (bsd_flags & MSG_EOF) f |= LINUX_MSG_EOF;
if (bsd_flags & MSG_NBIO) PWRN("MSG_NBIO ignored");
if (bsd_flags & MSG_NOSIGNAL) f |= LINUX_MSG_NOSIGNAL;
if (bsd_flags & MSG_COMPAT) f |= LINUX_MSG_COMPAT;
return f;
}
/* index is Linux, value is BSD */
static int sockopts[]
{
0, /* 0 */
SO_DEBUG,
SO_REUSEADDR,
SO_TYPE,
SO_ERROR,
SO_DONTROUTE, /* 5 */
SO_BROADCAST,
SO_SNDBUF,
SO_RCVBUF,
SO_KEEPALIVE,
SO_OOBINLINE, /* 10 */
/* SO_NOCHECK */ 0,
/* SO_PRIORITY */ 0,
SO_LINGER,
/* SO_BSDCOMPAT */ 0,
SO_REUSEPORT, /* 15 */
/* SO_PASSCRED */ 0,
/* SO_PEERCRED */ 0,
SO_RCVLOWAT,
SO_SNDLOWAT,
SO_RCVTIMEO, /* 20 */
SO_SNDTIMEO,
0,
0,
0,
0, /* 25 */
0,
0,
SO_PEERLABEL,
SO_TIMESTAMP,
SO_ACCEPTCONN, /* 30 */
-1
};
int Plugin::translate_ops_linux(int optname)
{
for (int i = 0; sockopts[i] > -1; i++)
if (sockopts[i] == optname)
return i;
PERR("Unsupported sockopt %d\n", optname);
return -1;
}
} /* unnamed namespace */
void create_lxip_plugin()
{
static Plugin lxip_plugin;
}

View File

@ -0,0 +1,122 @@
/**
* \brief Back-end driver for IP stack
* \author Sebastian Sumpf
* \author Stefan Kalkowski
* \date 2013-09-04
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <lx_emul.h>
#include <nic.h>
static struct net_device *_dev;
static int driver_net_open(struct net_device *dev)
{
printk("%s called\n",__func__);
_dev = dev;
return 0;
}
int driver_net_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct net_device_stats *stats = (struct net_device_stats*) netdev_priv(dev);
int len = skb->len;
void* addr = skb->data;
/* transmit to nic-session */
while (net_tx(addr, len)) {
/* tx queue is full, could not enqueue packet */
printk("TX full\n");
}
dev_kfree_skb(skb);
/* save timestamp */
dev->trans_start = jiffies;
stats->tx_packets++;
stats->tx_bytes += len;
return NETDEV_TX_OK;
}
void net_driver_rx(void *addr, unsigned long size)
{
struct net_device_stats *stats;
if (!_dev)
return;
stats = (struct net_device_stats*) netdev_priv(_dev);
/* allocate skb */
struct sk_buff *skb = dev_alloc_skb(size + 4);
if (!skb) {
printk(KERN_NOTICE "genode_net_rx: low on mem - packet dropped!\n");
stats->rx_dropped++;
return;
}
/* copy packet */
memcpy(skb_put(skb, size), addr, size);
skb->dev = _dev;
skb->protocol = eth_type_trans(skb, _dev);
skb->ip_summed = CHECKSUM_NONE;
netif_receive_skb(skb);
stats->rx_packets++;
stats->rx_bytes += size;
}
static const struct net_device_ops driver_net_ops =
{
.ndo_open = driver_net_open,
.ndo_start_xmit = driver_net_xmit,
};
static int driver_init(void)
{
struct net_device *dev;
int err = -ENODEV;
dev = alloc_etherdev(0);
if (!(dev = alloc_etherdev(0)))
goto out;
dev->netdev_ops = &driver_net_ops;
/* set MAC */
net_mac(dev->dev_addr, ETH_ALEN);
if ((err = register_netdev(dev))) {
panic("driver: Could not register back-end %d\n", err);
goto out_free;
}
return 0;
out_free:
free_netdev(dev);
out:
return err;
}
module_init(driver_init);

View File

@ -0,0 +1,521 @@
/**
* \brief Dummy functions
* \author Sebastian Sumpf
* \date 2013-08-26
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/printf.h>
extern "C" {
typedef long DUMMY;
enum {
SHOW_DUMMY = 0,
SHOW_SKIP = 0,
SHOW_RET = 0,
};
#define DUMMY(retval, name) \
DUMMY name(void) { \
if (SHOW_DUMMY) \
PDBG( #name " called (from %p) not implemented", __builtin_return_address(0)); \
return retval; \
}
#define DUMMY_SKIP(retval, name) \
DUMMY name(void) { \
if (SHOW_SKIP) \
PLOG( #name " called (from %p) skipped", __builtin_return_address(0)); \
return retval; \
}
#define DUMMY_RET(retval, name) \
DUMMY name(void) { \
if (SHOW_RET) \
PWRN( #name " called (from %p) return %d", __builtin_return_address(0), retval); \
return retval; \
}
/*
* Changed return values
*/
DUMMY_RET(0, in_irq)
DUMMY_RET(0, inet_twsk_alloc)
DUMMY_RET(0, ipv6_only_sock)
DUMMY_RET(0, netpoll_receive_skb)
DUMMY_RET(0, netpoll_rx_disable)
DUMMY_RET(1, nf_hook)
DUMMY_RET(0, notifier_to_errno)
DUMMY_RET(0, net_hash_mix)
DUMMY_RET(0, netdev_kobject_init)
DUMMY_RET(0, netdev_register_kobject)
DUMMY_RET(0, netpoll_rx)
DUMMY_RET(0, nla_put)
DUMMY_RET(1, num_possible_cpus)
DUMMY_RET(0, read_seqretry)
DUMMY_RET(0, poll_does_not_wait)
DUMMY_RET(0, secpath_exists)
DUMMY_RET(0, security_inet_conn_request)
DUMMY_RET(0, security_sk_alloc)
DUMMY_RET(0, signal_pending)
DUMMY_RET(0, sk_filter)
DUMMY_RET(0, sock_tx_timestamp)
DUMMY_RET(0, sscanf)
DUMMY_RET(0, static_key_false)
DUMMY_RET(0, vlan_tx_nonzero_tag_present)
DUMMY_RET(0, vlan_tx_tag_present)
DUMMY_RET(1, xfrm4_policy_check)
DUMMY_RET(0, xfrm_sk_clone_policy)
DUMMY_RET(0, xfrm_decode_session_reverse)
/*
* Unnecessary to trace
*/
DUMMY_SKIP( 0, ASSERT_RTNL)
DUMMY_SKIP(-1, debug_check_no_locks_freed)
DUMMY_SKIP(-1, local_bh_disable)
DUMMY_SKIP(-1, local_bh_enable)
DUMMY_SKIP(-1, local_irq_disable)
DUMMY_SKIP(-1, local_irq_enable)
DUMMY_SKIP(-1, local_irq_restore)
DUMMY_SKIP(-1, local_irq_save)
DUMMY_SKIP(-1, lockdep_init_map)
DUMMY_SKIP(-1, lockdep_set_class_and_name)
DUMMY_SKIP(-1, kmemcheck_annotate_variable)
DUMMY_SKIP(-1, might_sleep)
DUMMY_SKIP(-1, mutex_acquire)
DUMMY_SKIP(-1, mutex_init)
DUMMY_SKIP(-1, mutex_release)
DUMMY_SKIP(-1, mutex_unlock)
DUMMY_SKIP(-1, prefetchw)
DUMMY_SKIP(-1, mutex_lock)
DUMMY_SKIP(-1, rcu_read_lock)
DUMMY_SKIP(-1, rcu_read_unlock)
DUMMY_SKIP(-1, rcu_read_lock_bh)
DUMMY_SKIP(-1, rcu_read_unlock_bh)
DUMMY_SKIP(-1, read_lock)
DUMMY_SKIP(-1, read_seqbegin)
DUMMY_SKIP(-1, read_unlock)
DUMMY_SKIP(-1, read_lock_bh)
DUMMY_SKIP(-1, read_unlock_bh)
DUMMY_SKIP(-1, rwlock_init)
DUMMY_SKIP(-1, seqlock_init)
DUMMY_SKIP(-1, smp_mb)
DUMMY_SKIP(-1, smp_rmb)
DUMMY_SKIP(-1, smp_wmb)
DUMMY_SKIP(-1, spin_lock_irqsave)
DUMMY_SKIP( 1, spin_trylock)
DUMMY_SKIP(-1, spin_unlock_irqrestore)
DUMMY_SKIP(-1, synchronize_rcu)
DUMMY_SKIP(-1, trace_kfree_skb)
DUMMY_SKIP(-1, trace_consume_skb)
DUMMY_SKIP(-1, trace_net_dev_xmit)
DUMMY_SKIP(-1, trace_netif_receive_skb)
DUMMY_SKIP(-1, write_lock)
DUMMY_SKIP(-1, write_lock_bh)
DUMMY_SKIP(-1, write_lock_irq)
DUMMY_SKIP(-1, write_seqlock)
DUMMY_SKIP(-1, write_seqlock_bh)
DUMMY_SKIP(-1, write_sequnlock)
DUMMY_SKIP(-1, write_sequnlock_bh)
DUMMY_SKIP(-1, write_unlock)
DUMMY_SKIP(-1, write_unlock_bh)
DUMMY_SKIP(-1, write_unlock_irq)
/* requires CONFIG_MEMCG_KMEM */
DUMMY_SKIP(-1, sock_release_memcg)
DUMMY_SKIP(-1, waitqueue_active)
DUMMY_SKIP(-1, wake_up)
/*
* Test
*/
DUMMY_SKIP(-1, rtmsg_ifinfo)
DUMMY_RET(0, rtnl_is_locked)
DUMMY_SKIP(-1, rtnl_lock)
DUMMY(-1, rtnl_notify)
DUMMY(-1, rtnl_set_sk_err)
DUMMY_SKIP(-1, rtnl_unlock)
DUMMY_RET(0, rtnetlink_put_metrics)
DUMMY(-1, rtnl_af_register)
DUMMY(-1, rtnl_put_cacheinfo)
DUMMY_SKIP(-1, rtnl_register)
DUMMY(-1, rtnl_unicast)
/*
* Dummies
*/
DUMMY(-1, access_ok)
DUMMY(-1, add_device_randomness)
DUMMY(-1, addrconf_finite_timeout)
DUMMY(-1, addrconf_timeout_fixup)
DUMMY(-1, add_wait_queue)
DUMMY(-1, add_wait_queue_exclusive)
DUMMY(-1, atomic_notifier_call_chain)
DUMMY(-1, atomic_notifier_chain_register)
DUMMY(-1, atomic_notifier_chain_unregister)
DUMMY(-1, audit_enabled)
DUMMY(-1, audit_get_loginuid)
DUMMY(-1, audit_get_sessionid)
DUMMY(-1, audit_log)
DUMMY(-1, autoremove_wake_function)
DUMMY(-1, blocking_notifier_chain_unregister)
DUMMY(-1, call_netevent_notifiers)
DUMMY(-1, cancel_delayed_work)
DUMMY(-1, cancel_delayed_work_sync)
DUMMY(-1, capable)
DUMMY(-1, cipso_v4_validate)
DUMMY(-1, __clear_bit)
DUMMY(-1, clamp)
DUMMY(-1, clear_bit)
DUMMY(-1, cond_resched)
DUMMY(-1, cond_resched_softirq)
DUMMY(-1, __copy_from_user_nocache)
DUMMY(-1, csum_block_sub)
DUMMY(-1, csum_replace2)
DUMMY(-1, csum_sub)
DUMMY(-1, csum_unfold)
DUMMY(-1, current)
DUMMY(-1, current_egid)
DUMMY(-1, current_text_addr)
DUMMY(-1, current_uid_gid)
DUMMY(-1, del_timer_sync)
DUMMY(-1, dev_driver_string)
DUMMY(-1, device_rename)
DUMMY(-1, dev_ioctl)
DUMMY(-1, dev_is_pci)
DUMMY(-1, dev_load)
DUMMY(-1, dev_name)
DUMMY(-1, dev_num_vf)
DUMMY(-1, dev_printk_emit)
DUMMY(-1, div64_u64)
DUMMY(-1, div_u64)
DUMMY(-1, do_softirq)
DUMMY(-1, dump_stack)
DUMMY(-1, ether_addr_equal_64bits)
DUMMY(-1, exit_fn)
DUMMY(-1, file_inode)
DUMMY(-1, finish_wait)
DUMMY(-1, __fls)
DUMMY(-1, fls64)
DUMMY(-1, free_pages)
DUMMY(-1, from_kgid)
DUMMY(-1, from_kgid_munged)
DUMMY(-1, from_kuid)
DUMMY(-1, from_kuid_munged)
DUMMY(-1, generic_pipe_buf_confirm)
DUMMY(-1, generic_pipe_buf_map)
DUMMY(-1, generic_pipe_buf_unmap)
DUMMY(-1, gen_kill_estimator)
DUMMY(-1, get_current_groups)
DUMMY(-1, get_ds)
DUMMY(-1, __get_free_pages)
DUMMY(-1, get_fs)
DUMMY(-1, get_net_ns_by_fd)
DUMMY(-1, get_net_ns_by_pid)
DUMMY(-1, getnstimeofday)
DUMMY(-1, get_nulls_value)
DUMMY(-1, get_options)
DUMMY(-1, get_page)
DUMMY(-1, get_random_bytes)
DUMMY(-1, gfp_pfmemalloc_allowed)
DUMMY(-1, gid_lte)
DUMMY(-1, hash32_ptr)
DUMMY(-1, hex_to_bin)
DUMMY(-1, hlist_add_after_rcu)
DUMMY(-1, hlist_add_before_rcu)
DUMMY(-1, hlist_nulls_del)
DUMMY(-1, hlist_nulls_empty)
DUMMY(-1, hotcpu_notifier)
DUMMY(-1, hweight32)
DUMMY(-1, hweight64)
DUMMY(-1, inet_ctl_sock_destroy)
DUMMY(-1, inet_diag_dump_icsk)
DUMMY(-1, inet_diag_dump_one_icsk)
DUMMY(-1, inet_diag_register)
DUMMY(-1, inet_diag_unregister)
DUMMY(-1, INET_ECN_dontxmit)
DUMMY(-1, INET_ECN_is_not_ect)
DUMMY(-1, INET_ECN_xmit)
DUMMY(-1, inet_twdr_hangman)
DUMMY(-1, inet_twdr_twcal_tick)
DUMMY(-1, inet_twdr_twkill_work)
DUMMY(-1, inet_twsk_bind_unhash)
DUMMY(-1, inet_twsk_deschedule)
DUMMY(-1, __inet_twsk_hashdance)
DUMMY(-1, inet_twsk_purge)
DUMMY(-1, inet_twsk_put)
DUMMY(-1, inet_twsk_schedule)
DUMMY(-1, inet_twsk_unhash)
DUMMY(-1, inet_v6_ipv6only)
DUMMY(-1, INIT_DEFERRABLE_WORK)
DUMMY(-1, INIT_HLIST_NULLS_HEAD)
DUMMY(-1, init_user_ns)
DUMMY(-1, init_waitqueue_head)
DUMMY(-1, INIT_WORK)
DUMMY(-1, in_softirq)
DUMMY(-1, ip4_datagram_connect)
DUMMY(-1, ip4_datagram_release_cb)
DUMMY(-1, ip_check_mc_rcu)
DUMMY(-1, ip_mc_destroy_dev)
DUMMY(-1, ip_mc_down)
DUMMY(-1, ip_mc_drop_socket)
DUMMY(-1, ip_mc_gsfget)
DUMMY(-1, ip_mc_init_dev)
DUMMY(-1, ip_mc_join_group)
DUMMY(-1, ip_mc_leave_group)
DUMMY(-1, ip_mc_msfget)
DUMMY(-1, ip_mc_msfilter)
DUMMY(-1, ip_mc_remap)
DUMMY(-1, ip_mc_sf_allow)
DUMMY(-1, ip_mc_source)
DUMMY(-1, ip_mc_unmap)
DUMMY(-1, ip_mc_up)
DUMMY(-1, ip_mroute_getsockopt)
DUMMY(-1, ip_mroute_opt)
DUMMY(-1, ip_mroute_setsockopt)
DUMMY(-1, ipv4_is_lbcast)
DUMMY(-1, ipv4_is_local_multicast)
DUMMY(-1, ipv4_is_zeronet)
DUMMY(-1, irqs_disabled)
DUMMY(-1, is_a_nulls)
DUMMY(-1, is_multicast_ether_addr)
DUMMY(-1, is_valid_ether_addr)
DUMMY(-1, is_vlan_dev)
DUMMY(-1, jiffies_delta_to_clock_t)
DUMMY(-1, jiffies_to_clock_t)
DUMMY(-1, jiffies_to_msecs)
DUMMY(-1, jiffies_to_usecs)
DUMMY(-1, kernel_sendmsg)
DUMMY(-1, kmem_cache_destroy)
DUMMY(-1, kobject_put)
DUMMY(-1, kobject_uevent)
DUMMY(-1, krealloc)
DUMMY(-1, kref_init)
DUMMY(-1, kref_put)
DUMMY(-1, kstrdup)
DUMMY(-1, kstrtoul)
DUMMY(-1, ktime_equal)
DUMMY(-1, ktime_to_timespec)
DUMMY(-1, ktime_to_timeval)
DUMMY(-1, ktime_us_delta)
DUMMY(-1, kunmap)
DUMMY(-1, kunmap_atomic)
DUMMY(-1, linkwatch_fire_event)
DUMMY(-1, linkwatch_forget_dev)
DUMMY(-1, linkwatch_init_dev)
DUMMY(-1, linkwatch_run_queue)
DUMMY(-1, list_del_rcu)
DUMMY(-1, list_replace_rcu)
DUMMY(-1, local_softirq_pending)
DUMMY(-1, lockdep_rtnl_is_held)
DUMMY(-1, min)
DUMMY(-1, mod_delayed_work)
DUMMY(-1, module_put)
DUMMY(-1, move_addr_to_kernel)
DUMMY(-1, mq_qdisc_ops)
DUMMY(-1, msecs_to_jiffies)
DUMMY(-1, msleep)
DUMMY(-1, mutex_is_locked)
DUMMY(-1, need_resched)
DUMMY(-1, netdev_queue_update_kobjects)
DUMMY(-1, netdev_unregister_kobject)
DUMMY(-1, net_dmaengine_get)
DUMMY(-1, net_dmaengine_put)
DUMMY(-1, net_eq)
DUMMY(-1, net_namespace_list)
DUMMY(-1, netpoll_poll_lock)
DUMMY(-1, netpoll_poll_unlock)
DUMMY(-1, netpoll_rx_enable)
DUMMY(-1, netpoll_rx_on)
DUMMY(-1, next_pseudo_random32)
DUMMY(-1, nf_bridge_pad)
DUMMY(-1, nf_ct_attach)
DUMMY(-1, nla_find)
DUMMY(-1, nla_memcpy)
DUMMY(-1, nla_parse)
DUMMY(-1, nla_reserve)
DUMMY(-1, nla_strcmp)
DUMMY(-1, nla_strlcpy)
DUMMY(-1, nla_validate)
DUMMY(-1, notifier_from_errno)
DUMMY(-1, ns_capable)
DUMMY(-1, num_online_cpus)
DUMMY(-1, on_each_cpu)
DUMMY(-1, open_softirq)
DUMMY(-1, PageHighMem)
DUMMY(-1, percpu_counter_destroy)
DUMMY(-1, percpu_counter_sum_positive)
DUMMY(-1, pid_vnr)
DUMMY(-1, pr_crit)
DUMMY(-1, pr_err_once)
DUMMY(-1, preempt_disable)
DUMMY(-1, preempt_enable)
DUMMY(-1, prefetch)
DUMMY(-1, pr_emerg)
DUMMY(-1, prepare_to_wait)
DUMMY(-1, prepare_to_wait_exclusive)
DUMMY(-1, pr_err)
DUMMY(-1, pr_info)
DUMMY(-1, pr_info_once)
DUMMY(-1, pr_warn)
DUMMY(-1, put_cmsg)
DUMMY(-1, put_cpu)
DUMMY(-1, put_cpu_var)
DUMMY(-1, put_cred)
DUMMY(-1, put_device)
DUMMY(-1, put_pid)
DUMMY(-1, put_unaligned_be32)
DUMMY(-1, __raise_softirq_irqoff)
DUMMY(-1, raise_softirq_irqoff)
DUMMY(-1, random32)
DUMMY(-1, __ratelimit)
DUMMY(-1, raw_notifier_chain_unregister)
DUMMY(-1, rcu_barrier)
DUMMY(-1, register_gifconf)
DUMMY(-1, release_net)
DUMMY(-1, remove_proc_entry)
DUMMY(-1, remove_wait_queue)
DUMMY(-1, request_module)
DUMMY(-1, round_jiffies)
DUMMY(-1, round_jiffies_relative)
DUMMY(-1, round_jiffies_up)
DUMMY(-1, roundup_pow_of_two)
DUMMY(-1, rt_genid_bump)
DUMMY(-1, rtnetlink_init)
DUMMY(-1, __rtnl_unlock)
DUMMY(-1, schedule)
DUMMY(-1, schedule_delayed_work)
DUMMY(-1, schedule_timeout_interruptible)
DUMMY(-1, schedule_work)
DUMMY(-1, scm_destroy)
DUMMY(-1, scm_recv)
DUMMY(-1, scm_send)
DUMMY(-1, scnprintf)
DUMMY(-1, secpath_reset)
DUMMY(-1, secure_ip_id)
DUMMY(-1, secure_ipv4_port_ephemeral)
DUMMY(-1, secure_ipv6_id)
DUMMY(-1, secure_tcp_sequence_number)
DUMMY(-1, security_inet_conn_established)
DUMMY(-1, security_inet_csk_clone)
DUMMY(-1, security_netlink_send)
DUMMY(-1, security_release_secctx)
DUMMY(-1, security_req_classify_flow)
DUMMY(-1, security_secid_to_secctx)
DUMMY(-1, security_skb_classify_flow)
DUMMY(-1, security_skb_owned_by)
DUMMY(-1, security_sk_classify_flow)
DUMMY(-1, security_sk_free)
DUMMY(-1, security_socket_getpeersec_dgram)
DUMMY(-1, security_socket_getpeersec_stream)
DUMMY(-1, security_sock_graft)
DUMMY(-1, send_sigurg)
DUMMY(-1, send_sig)
DUMMY(-1, __set_bit)
DUMMY(-1, set_bit)
DUMMY(-1, __set_current_state)
DUMMY(-1, set_current_state)
DUMMY(-1, set_fs)
DUMMY(-1, sg_mark_end)
DUMMY(-1, sg_set_buf)
DUMMY(-1, sg_set_page)
DUMMY(-1, sha_transform)
DUMMY(-1, si_meminfo)
DUMMY(-1, S_ISSOCK)
DUMMY(-1, sk_attach_filter)
DUMMY(-1, sk_detach_filter)
DUMMY(-1, sk_filter_len)
DUMMY(-1, sk_filter_release_rcu)
DUMMY(-1, sk_get_filter)
DUMMY(-1, smp_mb__after_clear_bit)
DUMMY(-1, smp_mb__before_atomic_dec)
DUMMY(-1, __sock_recv_timestamp)
DUMMY(-1, __sock_recv_ts_and_drops)
DUMMY(-1, __sock_recv_wifi_status)
DUMMY(-1, sock_release)
DUMMY(-1, sock_update_classid)
DUMMY(-1, sock_update_memcg)
DUMMY(-1, sock_update_netprioidx)
DUMMY(-1, sock_wake_async)
DUMMY(-1, splice_to_pipe)
DUMMY(-1, srandom32)
DUMMY(-1, ssleep)
DUMMY(-1, static_key_enabled)
DUMMY(-1, static_key_slow_dec)
DUMMY(-1, static_key_slow_inc)
DUMMY(-1, strcat)
DUMMY(-1, strncpy_from_user)
DUMMY(-1, synchronize_rcu_expedited)
DUMMY(-1, sysctl_igmp_max_msf)
DUMMY(-1, sysctl_tcp_fastopen)
DUMMY(-1, system_wq)
DUMMY(-1, tasklet_init)
DUMMY(-1, tasklet_schedule)
DUMMY(-1, task_pid_nr)
DUMMY(-1, task_tgid_vnr)
DUMMY(-1, tcp_fastopen_cache_get)
DUMMY(-1, tcp_fastopen_cache_set)
DUMMY(-1, tcp_fastopen_cookie_gen)
DUMMY(-1, tcp_fetch_timewait_stamp)
DUMMY(-1, tcp_hdrlen)
DUMMY(-1, tcp_init_metrics)
DUMMY(-1, tcp_metrics_init)
DUMMY(-1, tcp_peer_is_proven)
DUMMY(-1, tcp_remember_stamp)
DUMMY(-1, tcp_tw_remember_stamp)
DUMMY(-1, tcp_update_metrics)
DUMMY(-1, test_and_clear_bit)
DUMMY(-1, test_and_set_bit)
DUMMY(-1, test_bit)
DUMMY(-1, textsearch_find)
DUMMY(-1, __this_cpu_read)
DUMMY(-1, trace_napi_poll)
DUMMY(-1, trace_net_dev_queue)
DUMMY(-1, trace_netif_rx)
DUMMY(-1, trace_skb_copy_datagram_iovec)
DUMMY(-1, trace_sock_exceed_buf_limit)
DUMMY(-1, trace_sock_rcvqueue_full)
DUMMY(-1, trace_udp_fail_queue_rcv_skb)
DUMMY(-1, try_module_get)
DUMMY(-1, tsk_restore_flags)
DUMMY(-1, u64_stats_fetch_begin_bh)
DUMMY(-1, u64_stats_fetch_retry_bh)
DUMMY(-1, u64_stats_update_begin)
DUMMY(-1, u64_stats_update_end)
DUMMY(-1, udplite4_register)
DUMMY(-1, uid_eq)
DUMMY(-1, vfree)
DUMMY(-1, virt_to_page)
DUMMY(-1, vlan_do_receive)
DUMMY(-1, __vlan_put_tag)
DUMMY(-1, vlan_untag)
DUMMY(-1, vzalloc)
DUMMY(-1, wake_up_interruptible)
DUMMY(-1, wake_up_interruptible_all)
DUMMY(-1, wake_up_interruptible_poll)
DUMMY(-1, wake_up_interruptible_sync_poll)
DUMMY(-1, WARN_ONCE)
DUMMY(-1, write_seqcount_begin)
DUMMY(-1, write_seqcount_end)
DUMMY(-1, xchg)
DUMMY(-1, xfrm4_policy_check_reverse)
DUMMY(-1, xfrm4_route_forward)
DUMMY(-1, xfrm4_udp_encap_rcv)
DUMMY(-1, xfrm_sk_free_policy)
DUMMY(-1, xfrm_user_policy)
DUMMY(-1, yield)
} /* extern "C" */

View File

@ -0,0 +1,20 @@
/*
* \brief Global environment
* \author Stefan Kalkowski
* \date 2013-05-23
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include "env.h"
Genode::Signal_receiver* Net::Env::receiver()
{
static Genode::Signal_receiver receiver;
return &receiver;
}

View File

@ -0,0 +1,30 @@
/*
* \brief Proxy-ARP environment
* \author Stefan Kalkowski
* \date 2013-05-24
*
* A database containing all clients sorted by IP and MAC addresses.
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _SRC__SERVER__NIC_BRIDGE__ENV_H_
#define _SRC__SERVER__NIC_BRIDGE__ENV_H_
#include <base/signal.h>
namespace Net {
struct Env;
}
struct Net::Env
{
static Genode::Signal_receiver* receiver();
};
#endif /* _SRC__SERVER__NIC_BRIDGE__ENV_H_ */

View File

@ -0,0 +1,21 @@
/**
* \brief IP stack initialization
* \author Sebastian Sumpf
* \date 2013-09-26
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__INIT_H_
#define _INCLUDE__INIT_H_
#ifdef __cplusplus
extern "C"
#endif
int lxip_init(void);
#endif

View File

@ -0,0 +1,2 @@
#include <uapi/linux/in.h>
#include <uapi/linux/ip.h>

View File

@ -0,0 +1,2 @@
#include <linux/udp.h>
#include <net/inet_timewait_sock.h>

View File

@ -0,0 +1,3 @@
#ifndef pr_fmt
#define pr_fmt(fmt) fmt
#endif

View File

@ -0,0 +1 @@
#include <uapi/linux/netfilter.h>

View File

@ -0,0 +1 @@
#include <uapi/linux/netfilter.h>

View File

@ -0,0 +1,2 @@
#include <uapi/asm-generic/socket.h>
#include <uapi/linux/sockios.h>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
#include <uapi/linux/fib_rules.h>

View File

@ -0,0 +1 @@
#include <uapi/linux/gen_stats.h>

View File

@ -0,0 +1 @@
#include <net/inet_connection_sock.h>

View File

@ -0,0 +1,6 @@
#include <net/route.h>
#include <linux/tcp.h>
struct ipv6hdr;
#include <net/dsfield.h>

View File

@ -0,0 +1,27 @@
/**
* \brief C back-end
* \author Sebastian Sumpf
* \date 2013-09-09
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__NIC_H_
#define _INCLUDE__NIC_H_
#ifdef __cplusplus
extern "C" {
#endif
void net_mac(void* mac, unsigned long size);
int net_tx(void* addr, unsigned long len);
void net_driver_rx(void *addr, unsigned long size);
#ifdef __cplusplus
}
#endif
#endif /* _INCLUDE__NIC_H_ */

View File

@ -0,0 +1,73 @@
/*
* \brief Signal driven network handler
* \author Stefan Kalkowski
* \auhtor Sebastian Sumpf
* \date 2013-09-24
*/
/*
* Copyright (C) 2010-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _PACKET_HANDLER_H_
#define _PACKET_HANDLER_H_
/* Genode */
#include <nic_session/connection.h>
namespace Net {
class Packet_handler;
}
/**
* Generic packet handler used as base for NIC and client packet handlers.
*/
class Net::Packet_handler
{
private:
/**
* submit queue not empty anymore
*/
void _packet_avail(unsigned);
/**
* acknoledgement queue not full anymore
*/
void _ready_to_ack(unsigned);
/**
* acknoledgement queue not empty anymore
*/
void _ack_avail(unsigned);
/**
* submit queue not full anymore
*
* TODO: by now, we just drop packets that cannot be transferred
* to the other side, that's why we ignore this signal.
*/
void _ready_to_submit(unsigned) { }
protected:
Genode::Signal_dispatcher<Packet_handler> _sink_ack;
Genode::Signal_dispatcher<Packet_handler> _sink_submit;
Genode::Signal_dispatcher<Packet_handler> _source_ack;
Genode::Signal_dispatcher<Packet_handler> _source_submit;
public:
Packet_handler();
virtual Packet_stream_sink< ::Nic::Session::Policy> * sink() = 0;
virtual Packet_stream_source< ::Nic::Session::Policy> * source() = 0;
void packet_avail() { _packet_avail(1); }
};
#endif /* _PACKET_HANDLER_H_ */

View File

@ -0,0 +1,78 @@
/**
* \brief IP stack initialization
* \author Sebastian Sumpf
* \date 2013-08-26
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <dde_kit/timer.h>
#include <linux/inetdevice.h>
#include <net/tcp.h>
#include <init.h>
/*
* Header declarations and tuning
*/
struct net init_net;
unsigned long *sysctl_local_reserved_ports;
struct pernet_operations loopback_net_ops;
/**
* nr_free_buffer_pages - count number of pages beyond high watermark
*
* nr_free_buffer_pages() counts the number of pages which are beyond the
* high
* watermark within ZONE_DMA and ZONE_NORMAL.
*/
unsigned long nr_free_buffer_pages(void)
{
return 1000;
}
/**
* Initialize sub-systems
*/
int lxip_init()
{
/* init data */
INIT_LIST_HEAD(&init_net.dev_base_head);
/*start jiffies */
dde_kit_timer_init(0, 0);
/* call __setup stuff */
__ip_auto_config_setup("dhcp");
core_sock_init();
core_netlink_proto_init();
/* sub-systems */
subsys_net_dev_init();
fs_inet_init();
/* enable local accepts */
IPV4_DEVCONF_ALL(&init_net, ACCEPT_LOCAL) = 0x1;
/* congestion control */
module_cubictcp_register();
/* driver */
module_driver_init();
/* late */
late_tcp_congestion_default();
/* dhcp */
late_ip_auto_config();
return 1;
}

View File

@ -0,0 +1,393 @@
/**
* \brief Linux emulation code
* \author Sebastian Sumpf
* \date 2013-08-30
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <linux/netdevice.h>
#include <net/ip_fib.h>
#include <uapi/linux/rtnetlink.h>
#include <dde_kit/memory.h>
#include <net/route.h>
#include <net/tcp.h>
/********************
** linux/slab.h **
********************/
struct kmem_cache
{
const char *name; /* cache name */
unsigned size; /* object size */
};
struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align,
unsigned long falgs, void (*ctor)(void *))
{
dde_kit_log(DEBUG_SLAB, "\"%s\" obj_size=%zd", name, size);
struct kmem_cache *cache;
if (!name) {
pr_info("kmem_cache name required\n");
return 0;
}
cache = (struct kmem_cache *)kmalloc(sizeof(*cache), 0);
if (!cache) {
pr_crit("No memory for slab cache\n");
return 0;
}
cache->name = name;
cache->size = size;
return cache;
}
void *kmem_cache_alloc_node(struct kmem_cache *cache, gfp_t flags, int node)
{
dde_kit_log(DEBUG_SLAB, "\"%s\" alloc obj_size=%zd", cache->name,cache->size);
return kmalloc(cache->size, 0);
}
void *kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags)
{
dde_kit_log(DEBUG_SLAB, "\"%s\" alloc obj_size=%zd", cache->name,cache->size);
return kmalloc(cache->size, 0);
}
void kmem_cache_free(struct kmem_cache *cache, void *objp)
{
dde_kit_log(DEBUG_SLAB, "\"%s\" (%p)", cache->name, objp);
kfree(objp);
}
void *alloc_large_system_hash(const char *tablename,
unsigned long bucketsize,
unsigned long numentries,
int scale,
int flags,
unsigned int *_hash_shift,
unsigned int *_hash_mask,
unsigned long low_limit,
unsigned long high_limit)
{
unsigned long elements = numentries ? numentries : high_limit;
unsigned long nlog2 = ilog2(elements);
nlog2 <<= (1 << nlog2) < elements ? 1 : 0;
void *table = dde_kit_simple_malloc(elements * bucketsize);
if (_hash_mask)
*_hash_mask = (1 << nlog2) - 1;
if (_hash_shift)
*_hash_shift = nlog2;
return table;
}
/********************
** linux/bitmap.h **
********************/
void bitmap_fill(unsigned long *dst, int nbits)
{
int count = nbits / (8 * sizeof (long));
int i;
memset(dst, 0xff, count * sizeof(long));
dst += count;
count = nbits % (8 * sizeof(long));
for (i = 0; i < count; i++)
*dst |= (1 << i);
}
void bitmap_zero(unsigned long *dst, int nbits)
{
int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
memset(dst, 0, len);
}
/*****************
** linux/gfp.h **
*****************/
unsigned long get_zeroed_page(gfp_t gfp_mask)
{
return (unsigned long)kzalloc(PAGE_SIZE, 0);
}
/********************
** linux/percpu.h **
********************/
void *__alloc_percpu(size_t size, size_t align)
{
return kmalloc(size, 0);
}
/******************
** linux/hash.h **
******************/
u32 hash_32(u32 val, unsigned int bits)
{
enum { GOLDEN_RATIO_PRIME_32 = 0x9e370001UL };
u32 hash = val * GOLDEN_RATIO_PRIME_32;
hash = hash >> (32 - bits);
return hash;
}
/******************
** linux/dcache **
******************/
unsigned int full_name_hash(const unsigned char *name, unsigned int len)
{
unsigned hash = 0, i;
for (i = 0; i < len; i++)
hash += name[i];
return hash;
}
/******************************
* net/core/net/namespace.h **
******************************/
int register_pernet_subsys(struct pernet_operations *ops)
{
if (ops->init)
ops->init(&init_net);
return 0;
}
int register_pernet_device(struct pernet_operations *ops)
{
return register_pernet_subsys(ops);
}
/*************************
** net/net_namespace.h **
*************************/
int rt_genid(struct net *net)
{
int ret = atomic_read(&net->rt_genid);
return -1;
}
/**********************
** linx/rtnetlink.h **
**********************/
struct netdev_queue *dev_ingress_queue(struct net_device *dev)
{
return dev->ingress_queue;
}
/****************
** linux/ip.h **
****************/
struct iphdr *ip_hdr(const struct sk_buff *skb)
{
return (struct iphdr *)skb_network_header(skb);
}
/***********************
** linux/netdevice.h **
***********************/
struct netdev_queue *netdev_pick_tx(struct net_device *dev, struct sk_buff *skb)
{
return netdev_get_tx_queue(dev, 0);
}
/*******************************
** asm-generic/bitops/find.h **
*******************************/
unsigned long find_first_zero_bit(unsigned long const *addr, unsigned long size)
{
unsigned long i, j;
for (i = 0; i < (size / BITS_PER_LONG); i++)
if (addr[i] != ~0UL)
break;
if (i == size)
return size;
for (j = 0; j < BITS_PER_LONG; j++)
if ((~addr[i]) & (1 << j))
break;
return (i * BITS_PER_LONG) + j;
}
/****************************
** asm-generic/getorder.h **
****************************/
int get_order(unsigned long size)
{
int order;
size--;
size >>= PAGE_SHIFT;
order = __builtin_ctzl(size);
return order;
}
/*********************
** linux/jiffies.h **
*********************/
long time_after_eq(long a, long b) { return (a - b) >= 0; }
long time_after(long a, long b) { return (b - a) < 0; }
/*********************
** linux/utsname.h **
*********************/
struct uts_name init_uts_ns;
struct new_utsname *init_utsname(void) { return &init_uts_ns.name; }
struct new_utsname *utsname(void) { return init_utsname(); }
/**********************
** linux/notifier.h **
**********************/
int raw_notifier_chain_register(struct raw_notifier_head *nh,
struct notifier_block *n)
{
struct notifier_block *nl = nh->head;
struct notifier_block *pr = 0;
while (nl) {
if (n->priority > nl->priority)
break;
pr = nl;
nl = nl->next;
}
n->next = nl;
if (pr)
pr->next = n;
else
nh->head = n;
return 0;
}
int raw_notifier_call_chain(struct raw_notifier_head *nh,
unsigned long val, void *v)
{
int ret = NOTIFY_DONE;
struct notifier_block *nb = nh->head;
while (nb) {
ret = nb->notifier_call(nb, val, v);
if ((ret & NOTIFY_STOP_MASK) == NOTIFY_STOP_MASK)
break;
nb = nb->next;
}
return ret;
}
int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
struct notifier_block *n)
{
return raw_notifier_chain_register((struct raw_notifier_head *)nh, n);
}
int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
unsigned long val, void *v)
{
return raw_notifier_call_chain((struct raw_notifier_head *)nh, val, v);
}
/****************************
** asm-generic/checksum.h **
****************************/
__sum16 csum_fold(__wsum csum)
{
u32 sum = (u32)csum;
sum = (sum & 0xffff) + (sum >> 16);
sum = (sum & 0xffff) + (sum >> 16);
return (__sum16)~sum;
}
/*******************
** net/checksum.h **
********************/
__wsum csum_add(__wsum csum, __wsum addend)
{
u32 res = (u32)csum;
res += (u32)addend;
return (__wsum)(res + (res < (u32)addend));
}
__wsum csum_block_add(__wsum csum, __wsum csum2, int offset)
{
u32 sum = (u32)csum2;
if (offset&1)
sum = ((sum&0xFF00FF)<<8)+((sum>>8)&0xFF00FF);
return csum_add(csum, (__wsum)sum);
}
/**
* Misc
*/
void set_sock_wait(struct socket *sock, unsigned long ptr)
{
sock->sk->sk_wq = (struct socket_wq *)ptr;
}

View File

@ -0,0 +1,635 @@
/**
* \brief Linux emulation code
* \author Sebastian Sumpf
* \date 2013-08-28
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/allocator_avl.h>
#include <base/snprintf.h>
#include <dataspace/client.h>
#include <rm_session/connection.h>
#include <lx_emul.h>
#include <env.h>
extern "C" {
#include <dde_kit/memory.h>
}
/*
* VM-area to reserve for back-end allocator
*/
enum { VM_RESERVATION = 24 * 1024 * 1024 };
/*
* TODO: fine tune these
*/
unsigned long totalram_pages = VM_RESERVATION / PAGE_SIZE;
unsigned long num_physpages = totalram_pages;
namespace Genode {
template <unsigned VM_SIZE> class Slab_backend_alloc;
typedef Slab_backend_alloc<VM_RESERVATION> Backend_alloc;
class Slab_alloc;
}
/**
* Back-end allocator for Genode's slab allocator
*/
template <unsigned VM_SIZE>
class Genode::Slab_backend_alloc : public Genode::Allocator,
public Genode::Rm_connection
{
private:
enum {
BLOCK_SIZE = 1024 * 1024, /* 1 MB */
ELEMENTS = VM_SIZE / BLOCK_SIZE, /* MAX number of dataspaces in VM */
};
addr_t _base; /* virt. base address */
bool _cached; /* non-/cached RAM */
Ram_dataspace_capability _ds_cap[ELEMENTS]; /* dataspaces to put in VM */
addr_t _ds_phys[ELEMENTS]; /* physical bases of dataspaces */
int _index; /* current index in ds_cap */
Allocator_avl _range; /* manage allocations */
bool _alloc_block()
{
if (_index == ELEMENTS) {
PERR("Slab-backend exhausted!");
return false;
}
try {
_ds_cap[_index] = Genode::env()->ram_session()->alloc(BLOCK_SIZE, _cached);
/* attach at index * BLOCK_SIZE */
Rm_connection::attach_at(_ds_cap[_index], _index * BLOCK_SIZE, BLOCK_SIZE, 0);
/* lookup phys. address */
_ds_phys[_index] = Dataspace_client(_ds_cap[_index]).phys_addr();
} catch (...) { return false; }
/* return base + offset in VM area */
addr_t block_base = _base + (_index * BLOCK_SIZE);
++_index;
_range.add_range(block_base, BLOCK_SIZE);
return true;
}
public:
Slab_backend_alloc(bool cached)
: Rm_connection(0, VM_SIZE), _cached(cached), _index(0),
_range(env()->heap())
{
/* reserver attach us, anywere */
_base = env()->rm_session()->attach(dataspace());
}
/**
* Allocate
*/
bool alloc(size_t size, void **out_addr)
{
bool done = _range.alloc(size, out_addr);
if (done)
return done;
done = _alloc_block();
if (!done) {
PERR("Backend allocator exhausted\n");
return false;
}
return _range.alloc(size, out_addr);
}
void free(void *addr, size_t /* size */) { }
size_t overhead(size_t size) { return 0; }
/**
* Return phys address for given virtual addr.
*/
addr_t phys_addr(addr_t addr)
{
if (addr < _base || addr >= (_base + VM_SIZE))
return ~0UL;
int index = (addr - _base) / BLOCK_SIZE;
/* physical base of dataspace */
addr_t phys = _ds_phys[index];
if (!phys)
return ~0UL;
/* add offset */
phys += (addr - _base - (index * BLOCK_SIZE));
return phys;
}
addr_t start() const { return _base; }
addr_t end() const { return _base + VM_SIZE - 1; }
};
/**
* Slab allocator using our back-end allocator
*/
class Genode::Slab_alloc : public Genode::Slab
{
private:
size_t _calculate_block_size(size_t object_size)
{
size_t block_size = 8 * (object_size + sizeof(Slab_entry)) + sizeof(Slab_block);
return align_addr(block_size, 12);
}
public:
Slab_alloc(size_t object_size, Backend_alloc *allocator)
: Slab(object_size, _calculate_block_size(object_size), 0, allocator)
{ }
inline addr_t alloc()
{
addr_t result;
return (Slab::alloc(slab_size(), (void **)&result) ? result : 0);
}
};
/**
* Memory interface used used for Linux emulation
*/
class Malloc
{
private:
enum {
SLAB_START_LOG2 = 3, /* 8 B */
SLAB_STOP_LOG2 = 16, /* 64 KB */
NUM_SLABS = (SLAB_STOP_LOG2 - SLAB_START_LOG2) + 1,
};
typedef Genode::addr_t addr_t;
typedef Genode::Slab_alloc Slab_alloc;
typedef Genode::Slab_backend_alloc<VM_RESERVATION> Slab_backend_alloc;
Slab_backend_alloc *_back_allocator;
Slab_alloc *_allocator[NUM_SLABS];
bool _cached; /* cached or un-cached memory */
addr_t _start; /* VM region of this allocator */
addr_t _end;
/**
* Set 'value' at 'addr'
*/
void _set_at(addr_t addr, addr_t value) { *((addr_t *)addr) = value; }
/**
* Retrieve slab index belonging to given address
*/
unsigned _slab_index(Genode::addr_t **addr)
{
using namespace Genode;
/* get index */
addr_t index = *(*addr - 1);
/*
* If index large, we use aligned memory, retrieve beginning of slab entry
* and read index from there
*/
if (index > 32) {
*addr = (addr_t *)*(*addr - 1);
index = *(*addr - 1);
}
return index;
}
public:
Malloc(Slab_backend_alloc *alloc, bool cached)
: _back_allocator(alloc), _cached(cached), _start(alloc->start()),
_end(alloc->end())
{
/* init slab allocators */
for (unsigned i = SLAB_START_LOG2; i <= SLAB_STOP_LOG2; i++)
_allocator[i - SLAB_START_LOG2] = new (Genode::env()->heap())
Slab_alloc(1U << i, alloc);
}
/**
* Alloc in slabs
*/
void *alloc(Genode::size_t size, int align = 0, Genode::addr_t *phys = 0)
{
using namespace Genode;
/* += slab index + aligment size */
size += sizeof(addr_t) + (align > 2 ? (1 << align) : 0);
int msb = Genode::log2(size);
if (size > (1U << msb))
msb++;
if (size < (1U << SLAB_START_LOG2))
msb = SLAB_STOP_LOG2;
if (msb > SLAB_STOP_LOG2) {
PERR("Slab too large %u requested %zu cached %d", 1U << msb, size, _cached);
return 0;
}
addr_t addr = _allocator[msb - SLAB_START_LOG2]->alloc();
if (!addr) {
PERR("Failed to get slab for %u", 1 << msb);
return 0;
}
_set_at(addr, msb - SLAB_START_LOG2);
addr += sizeof(addr_t);
if (align > 2) {
/* save */
addr_t ptr = addr;
addr_t align_val = (1U << align);
addr_t align_mask = align_val - 1;
/* align */
addr = (addr + align_val) & ~align_mask;
/* write start address before aligned address */
_set_at(addr - sizeof(addr_t), ptr);
}
if (phys)
*phys = _back_allocator->phys_addr(addr);
return (addr_t *)addr;
}
void free(void const *a)
{
using namespace Genode;
addr_t *addr = (addr_t *)a;
unsigned nr = _slab_index(&addr);
_allocator[nr]->free((void *)(addr - 1));
}
size_t slab_size(void const *a)
{
using namespace Genode;
addr_t *addr =(addr_t *)a;
unsigned nr = _slab_index(&addr);
size_t size = 1 << (SLAB_START_LOG2 + nr);
size -= (addr_t)a - (addr_t)(addr - 1);
return size;
}
Genode::addr_t phys_addr(void *a)
{
return _back_allocator->phys_addr((addr_t)a);
}
/**
* Belongs given address to this allocator
*/
bool inside(addr_t const addr) const { return (addr > _start) && (addr <= _end); }
/**
* Cached memory allocator
*/
static Malloc *mem()
{
static Slab_backend_alloc _b(true);
static Malloc _m(&_b, true);
return &_m;
}
};
/*************************************
** Memory allocation, linux/slab.h **
*************************************/
void *kmalloc(size_t size, gfp_t flags)
{
void *addr = Malloc::mem()->alloc(size);
unsigned long a = (unsigned long)addr;
if (a & 0x3)
PERR("Unaligned kmalloc %lx", a);
// PDBG("Kmalloc: [%lx-%lx) from %p", a, a + size, __builtin_return_address(0));
return addr;
}
void *kzalloc(size_t size, gfp_t flags)
{
void *addr = kmalloc(size, flags);
if (addr)
Genode::memset(addr, 0, size);
//PDBG("Kmalloc: [%lx-%lx) from %p", (unsigned)addr, (unsigned)addr + size, __builtin_return_address(0));
return addr;
}
void *kcalloc(size_t n, size_t size, gfp_t flags)
{
if (size != 0 && n > ~0UL / size)
return 0;
return kzalloc(n * size, flags);
}
void kfree(const void *p)
{
if (Malloc::mem()->inside((Genode::addr_t)p))
Malloc::mem()->free(p);
else
PWRN("%p is not within our memory range called from %p",
p, __builtin_return_address(0));
}
void *kmalloc_node_track_caller(size_t size, gfp_t flags, int node)
{
return kmalloc(size, 0);
}
void *kzalloc_node(size_t size, gfp_t flags, int node)
{
return kzalloc(size, 0);
}
size_t ksize(const void *p)
{
if (!(Malloc::mem()->inside((Genode::addr_t)p))) {
PDBG("%p not in slab allocator", p);
return 0;
}
size_t size = Malloc::mem()->slab_size(p);
return size;
}
/********************
** linux/string.h **
********************/
char *strcpy(char *to, const char *from)
{
char *save = to;
for (; (*to = *from); ++from, ++to);
return(save);
}
char *strchr(const char *p, int ch)
{
char c;
c = ch;
for (;; ++p) {
if (*p == c)
return ((char *)p);
if (*p == '\0')
break;
}
return 0;
}
char *strnchr(const char *p, size_t count, int ch)
{
char c;
c = ch;
for (; count; ++p, count--) {
if (*p == c)
return ((char *)p);
if (*p == '\0')
break;
}
return 0;
}
size_t strnlen(const char *s, size_t maxlen)
{
size_t c;
for (c = 0; c < maxlen; c++)
if (!s[c])
return c;
return maxlen;
}
size_t strlen(const char *s) { return Genode::strlen(s); }
int strcmp(const char *s1, const char *s2) { return Genode::strcmp(s1, s2); }
int strncmp(const char *s1, const char *s2, size_t len) {
return Genode::strcmp(s1, s2, len); }
int memcmp(const void *p0, const void *p1, size_t size) {
return Genode::memcmp(p0, p1, size); }
int snprintf(char *str, size_t size, const char *format, ...)
{
va_list list;
va_start(list, format);
Genode::String_console sc(str, size);
sc.vprintf(format, list);
va_end(list);
return sc.len();
}
size_t strlcpy(char *dest, const char *src, size_t size)
{
size_t ret = strlen(src);
if (size) {
size_t len = (ret >= size) ? size - 1 : ret;
Genode::memcpy(dest, src, len);
dest[len] = '\0';
}
return ret;
}
void *kmemdup(const void *src, size_t len, gfp_t gfp)
{
void *ptr = kmalloc(len, gfp);
Genode::memcpy(ptr, src, len);
return ptr;
}
void *genode_memcpy(void *d, const void *s, size_t n)
{
return Genode::memcpy(d, s, n);
}
/******************
** linux/log2.h **
******************/
unsigned long ilog2(unsigned long n) { return Genode::log2<unsigned long>(n); }
/*******************
** linux/sched.h **
*******************/
extern "C" void __wait_event()
{
Genode::Signal s = Net::Env::receiver()->wait_for_signal();
static_cast<Genode::Signal_dispatcher_base *>(s.context())->dispatch(s.num());
}
long schedule_timeout_uninterruptible(signed long timeout)
{
return schedule_timeout(timeout);
}
signed long schedule_timeout(signed long timeout)
{
long start = jiffies;
__wait_event();
timeout -= jiffies - start;
return timeout < 0 ? 0 : timeout;
}
void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
{
__wait_event();
}
/******************
** linux/time.h **
******************/
unsigned long get_seconds(void)
{
return jiffies / HZ;
}
/*****************
** linux/gfp.h **
*****************/
class Avl_page : public Genode::Avl_node<Avl_page>
{
private:
Genode::addr_t _addr;
Genode::size_t _size;
struct page *_page;
public:
Avl_page(Genode::size_t size) : _size(size)
{
_addr =(Genode::addr_t)kmalloc(size, 0);
if (!_addr)
throw -1;
_page = (struct page *) kzalloc(sizeof(struct page), 0);
if (!_page) {
kfree((void *)_addr);
throw -2;
}
_page->addr = (void *)_addr;
atomic_set(&_page->_count, 1);
dde_kit_log(DEBUG_SLAB, "alloc page: %p addr: %lx-%lx", _page, _addr, _addr + size);
}
virtual ~Avl_page()
{
kfree((void *)_addr);
kfree((void *)_page);
}
struct page* page() { return _page; }
bool higher(Avl_page *c)
{
return c->_addr > _addr;
}
Avl_page *find_by_address(Genode::addr_t addr)
{
if (addr >= _addr && addr < _addr + _size)
return this;
bool side = addr > _addr;
Avl_page *c = Avl_node<Avl_page>::child(side);
return c ? c->find_by_address(addr) : 0;
}
};
static Genode::Avl_tree<Avl_page> tree;
struct page *alloc_pages(gfp_t gfp_mask, unsigned int order)
{
Avl_page *p;
try {
p = (Avl_page *)new (Genode::env()->heap()) Avl_page(PAGE_SIZE << order);
tree.insert(p);
} catch (...) { return 0; }
return p->page();
}
/****************
** linux/mm.h **
****************/
struct page *virt_to_head_page(const void *x)
{
Avl_page *p = tree.first()->find_by_address((Genode::addr_t)x);
dde_kit_log(DEBUG_SLAB, "virt_to_head_page: %p page %p\n", x,p ? p->page() : 0);
return p ? p->page() : 0;
}
void put_page(struct page *page)
{
if (!atomic_dec_and_test(&page->_count))
return;
dde_kit_log(DEBUG_SLAB, "put_page: %p", page);
Avl_page *p = tree.first()->find_by_address((Genode::addr_t)page->addr);
tree.remove(p);
destroy(Genode::env()->heap(), p);
}

View File

@ -0,0 +1,148 @@
#include <base/printf.h>
#include <nic/packet_allocator.h>
#include <nic_session/connection.h>
#include <env.h>
#include <nic.h>
#include <packet_handler.h>
enum {
MAC_LEN = 17,
ETH_ALEN = 6,
};
namespace Net {
class Nic;
}
class Net::Nic : public Net::Packet_handler
{
private:
enum {
PACKET_SIZE = ::Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
BUF_SIZE = ::Nic::Session::QUEUE_SIZE * PACKET_SIZE,
};
::Nic::Packet_allocator _tx_block_alloc;
::Nic::Connection _nic;
public:
Nic()
: _tx_block_alloc(Genode::env()->heap()),
_nic(&_tx_block_alloc, BUF_SIZE, BUF_SIZE)
{
_nic.rx_channel()->sigh_ready_to_ack(_sink_ack);
_nic.rx_channel()->sigh_packet_avail(_sink_submit);
_nic.tx_channel()->sigh_ack_avail(_source_ack);
_nic.tx_channel()->sigh_ready_to_submit(_source_submit);
}
/******************************
** Packet_handler interface **
******************************/
Packet_stream_sink< ::Nic::Session::Policy> * sink() {
return _nic.rx(); }
Packet_stream_source< ::Nic::Session::Policy> * source() {
return _nic.tx(); }
static Nic *nic()
{
static Nic _net_nic;
return &_net_nic;
}
static ::Nic::Connection *n()
{
return &nic()->_nic;
}
};
Net::Packet_handler::Packet_handler()
: _sink_ack(*Net::Env::receiver(), *this, &Packet_handler::_ready_to_ack),
_sink_submit(*Net::Env::receiver(), *this, &Packet_handler::_packet_avail),
_source_ack(*Net::Env::receiver(), *this, &Packet_handler::_ack_avail),
_source_submit(*Net::Env::receiver(), *this, &Packet_handler::_ready_to_submit)
{ }
void Net::Packet_handler::_ack_avail(unsigned)
{
while (source()->ack_avail())
source()->release_packet(source()->get_acked_packet());
}
void Net::Packet_handler::_ready_to_ack(unsigned num)
{
_packet_avail(num);
}
void Net::Packet_handler::_packet_avail(unsigned)
{
using namespace Net;
enum { MAX_PACKETS = 50 };
int count = 0;
while(Nic::n()->rx()->packet_avail() &&
Nic::n()->rx()->ready_to_ack() &&
++count < MAX_PACKETS) {
Packet_descriptor p = Nic::n()->rx()->get_packet();
net_driver_rx(Net::Nic::n()->rx()->packet_content(p), p.size());
Nic::n()->rx()->acknowledge_packet(p);
}
if (count == MAX_PACKETS)
_sink_submit.submit(1);
//Genode::Signal_transmitter(_sink_submit).submit();
}
static void snprint_mac(unsigned char *buf, unsigned char *mac)
{
for (int i = 0; i < ETH_ALEN; i++) {
Genode::snprintf((char *)&buf[i * 3], 3, "%02x", mac[i]);
if ((i * 3) < MAC_LEN)
buf[(i * 3) + 2] = ':';
}
buf[MAC_LEN] = 0;
}
void net_mac(void* mac, unsigned long size)
{
unsigned char str[MAC_LEN + 1];
using namespace Genode;
Nic::Mac_address m = Net::Nic::n()->mac_address();
Genode::memcpy(mac, &m.addr, min(sizeof(m.addr), (size_t)size));
snprint_mac(str, (unsigned char *)m.addr);
PINF("Received mac: %s", str);
}
int net_tx(void* addr, unsigned long len)
{
try {
Packet_descriptor packet = Net::Nic::n()->tx()->alloc_packet(len);
void* content = Net::Nic::n()->tx()->packet_content(packet);
Genode::memcpy((char *)content, addr, len);
Net::Nic::n()->tx()->submit_packet(packet);
return 0;
/* 'Packet_alloc_failed' */
} catch(...) {
return 1;
}
}

View File

@ -0,0 +1,115 @@
/**
* \brief BSD style socket helpers
* \author Sebastian Sumpf
* \date 2013-08-28
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <linux/net.h>
#include <net/sock.h>
#include <net/tcp_states.h>
#include <lx_emul.h>
static const struct net_proto_family *net_families[NPROTO];
int sock_register(const struct net_proto_family *ops)
{
if (ops->family >= NPROTO) {
printk("protocol %d >= NPROTO (%d)\n", ops->family, NPROTO);
return -ENOBUFS;
}
net_families[ops->family] = ops;
pr_info("NET: Registered protocol family %d\n", ops->family);
return 0;
}
struct socket *sock_alloc(void)
{
return (struct socket *)kmalloc(sizeof(struct socket), 0);
}
int sock_create_lite(int family, int type, int protocol, struct socket **res)
{
struct socket *sock = sock_alloc();
if (!sock)
return -ENOMEM;
sock->type = type;
*res = sock;
return 0;
}
int sock_create_kern(int family, int type, int proto,
struct socket **res)
{
struct socket *sock;
const struct net_proto_family *pf;
int err;
if (family < 0 || family > NPROTO)
return -EAFNOSUPPORT;
if (type < 0 || type > SOCK_MAX)
return -EINVAL;
pf = net_families[family];
if (!pf) {
printk("No protocol found for family %d\n", family);
return -ENOPROTOOPT;
}
if (!(sock = (struct socket *)kzalloc(sizeof(struct socket), 0))) {
printk("Could not allocate socket\n");
return -ENFILE;
}
sock->type = type;
err = pf->create(&init_net, sock, proto, 1);
if (err) {
kfree(sock);
return err;
}
*res = sock;
return 0;
}
int socket_check_state(struct socket *socket)
{
if (socket->sk->sk_state == TCP_CLOSE_WAIT)
return -EINTR;
return 0;
}
void log_sock(struct socket *socket)
{
printk("\nNEW socket %p sk %p fsk %x &sk %p &fsk %p\n\n",
socket, socket->sk, socket->flags, &socket->sk, &socket->flags);
}
static void sock_init(void)
{
skb_init();
}
core_initcall(sock_init);

View File

@ -0,0 +1,630 @@
/**
* \brief Front-end and glue to IP stack
* \author Sebastian Sumpf
* \date 2013-09-26
*/
/*
* Copyright (C) 2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/env.h>
#include <base/signal.h>
#include <base/printf.h>
#include <base/thread.h>
#include <lxip/lxip.h>
#include <env.h>
#include <init.h>
#include <nic.h>
extern "C" void wait_for_continue();
static const bool verbose = false;
namespace Linux {
extern "C" {
#include <lx_emul.h>
#include <linux/socket.h>
#include <uapi/linux/in.h>
extern int sock_setsockopt(struct socket *sock, int level,
int op, char __user *optval,
unsigned int optlen);
extern int sock_getsockopt(struct socket *sock, int level,
int op, char __user *optval,
int __user *optlen);
}
}
namespace Net
{
class Socketcall;
enum Opcode { OP_SOCKET = 0, OP_CLOSE = 1, OP_BIND = 2, OP_LISTEN = 3,
OP_ACCEPT = 4, OP_POLL = 5, OP_RECV = 6, OP_CONNECT = 7,
OP_SEND = 8, OP_SETOPT = 9, OP_GETOPT = 10, OP_GETNAME = 11,
OP_PEERNAME = 12, OP_IOCTL = 13, OP_SHUTDOWN = 14 };
struct Call
{
Opcode opcode;
Lxip::Handle handle;
union
{
struct
{
Lxip::Type type;
} socket;
struct
{
int backlog;
} listen;
struct
{
void *addr;
Lxip::uint32_t *len;
} accept;
struct
{
mutable void *buf;
Lxip::size_t len;
int flags;
void *addr;
Lxip::uint32_t *addr_len;
} msg;
struct
{
int level;
int optname;
const void *optval;
Lxip::uint32_t optlen;
int *optlen_ptr;
} sockopt;
struct {
bool block;
} poll;
struct {
int request;
unsigned long arg;
} ioctl;
struct {
int how;
} shutdown;
};
struct Linux::sockaddr_storage addr;
Lxip::uint32_t addr_len;
};
union Result
{
int err;
Lxip::ssize_t len;
};
};
class Net::Socketcall : public Genode::Signal_dispatcher_base,
public Genode::Signal_context_capability,
public Lxip::Socketcall,
public Genode::Thread<64 * 1024 * sizeof(Genode::addr_t)>
{
private:
Call _call;
Result _result;
Lxip::Handle _handle;
Genode::Signal_transmitter _signal;
Genode::Semaphore _block;
void _submit_and_block()
{
//_signal.submit(); /* global submit */
submit(1); /* local submit */
_block.down();
}
void _unblock() { _block.up(); }
struct Linux::socket * call_socket()
{
return static_cast<struct Linux::socket *>(_call.handle.socket);
}
Lxip::uint32_t _family_handler(Lxip::uint16_t family, void *addr)
{
using namespace Linux;
if (!addr)
return 0;
switch (family)
{
case AF_INET:
struct sockaddr_in *in = (struct sockaddr_in *)addr;
struct sockaddr_in *out = (struct sockaddr_in *)&_call.addr;
out->sin_family = family;
out->sin_port = in->sin_port;
out->sin_addr.s_addr = in->sin_addr.s_addr;
return sizeof(struct sockaddr_in);
}
return 0;
}
/******************************************
** Glue interface to Linux TCP/IP stack **
******************************************/
void _do_accept()
{
using namespace Linux;
struct socket *sock = call_socket();
struct socket *new_sock = (struct socket *)kzalloc(sizeof(struct socket), 0);
_handle.socket = 0;
if (!new_sock)
return;
new_sock->type = sock->type;
new_sock->ops = sock->ops;
if ((sock->ops->accept(sock, new_sock, 0)) < 0) {
kfree(new_sock);
return;
}
_handle.socket = static_cast<void *>(new_sock);
if (!_call.accept.addr)
return;
int len;
if ((new_sock->ops->getname(new_sock, (struct sockaddr *)&_call.addr,
&len, 2)) < 0)
return;
*_call.accept.len = min(*_call.accept.len, len);
Genode::memcpy(_call.accept.addr, &_call.addr, *_call.accept.len);
}
void _do_bind()
{
struct Linux::socket *sock = call_socket();
_result.err = sock->ops->bind(sock, (struct Linux::sockaddr *) &_call.addr,
_call.addr_len);
}
void _do_close()
{
using namespace Linux;
struct socket *s = call_socket();
if (s->ops)
s->ops->release(s);
kfree(s);
}
void _do_connect()
{
Linux::socket *sock = call_socket();
//XXX: have a look at the file flags
_result.err = sock->ops->connect(sock, (struct Linux::sockaddr *) &_call.addr,
_call.addr_len, 0);
}
void _do_getname(int peer)
{
int len = sizeof(Linux::sockaddr_storage);
_result.err = call_socket()->ops->getname(call_socket(),
(struct Linux::sockaddr *)&_call.addr,
&len, peer);
*_call.accept.len = Linux::min(*_call.accept.len, len);
Genode::memcpy(_call.accept.addr, &_call.addr, *_call.accept.len);
}
void _do_getopt()
{
_result.err = Linux::sock_getsockopt(call_socket(), _call.sockopt.level,
_call.sockopt.optname,
(char *)_call.sockopt.optval,
_call.sockopt.optlen_ptr);
}
void _do_ioctl()
{
_result.err = call_socket()->ops->ioctl(call_socket(),
_call.ioctl.request,
_call.ioctl.arg);
}
void _do_listen()
{
_result.err = call_socket()->ops->listen(call_socket(),
_call.listen.backlog);
}
void _do_poll()
{
using namespace Linux;
struct socket *sock = call_socket();
enum {
POLLIN_SET = (POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR),
POLLOUT_SET = (POLLWRBAND | POLLWRNORM | POLLOUT | POLLERR),
POLLEX_SET = (POLLPRI)
};
/*
* Set socket wait queue to one so we can block poll in 'tcp_poll -> poll_wait'
*/
set_sock_wait(sock, _call.poll.block ? 1 : 0);
int mask =sock->ops->poll(0, sock, 0);
set_sock_wait(sock, 0);
_result.err = 0;
if (mask & POLLIN_SET)
_result.err |= Lxip::POLLIN;
if (mask & POLLOUT_SET)
_result.err |= Lxip::POLLOUT;
if (mask & POLLEX_SET)
_result.err |= Lxip::POLLEX;
}
void _do_recv()
{
using namespace Linux;
struct msghdr msg;
struct iovec iov;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_iovlen = 1;
msg.msg_iov = &iov;
iov.iov_len = _call.msg.len;
iov.iov_base = _call.msg.buf;
msg.msg_name = _call.addr_len ? &_call.addr : 0;
msg.msg_namelen = _call.addr_len;
msg.msg_flags = 0;
if (_call.handle.non_block)
msg.msg_flags |= MSG_DONTWAIT;
//XXX: check for non-blocking flag
_result.err = call_socket()->ops->recvmsg(0, call_socket(), &msg,
_call.msg.len,
_call.msg.flags);
if (_call.msg.addr) {
*_call.msg.addr_len = min(*_call.msg.addr_len, msg.msg_namelen);
Genode::memcpy(_call.msg.addr, &_call.addr, *_call.msg.addr_len);
}
}
void _do_send()
{
using namespace Linux;
struct msghdr msg;
struct iovec iov;
_result.err = socket_check_state(call_socket());
if (_result.err < 0)
return;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_iovlen = 1;
msg.msg_iov = &iov;
iov.iov_len = _call.msg.len;
iov.iov_base = _call.msg.buf;
msg.msg_name = _call.addr_len ? &_call.addr : 0;
msg.msg_namelen = _call.addr_len;
msg.msg_flags = _call.msg.flags;
if (_call.handle.non_block)
msg.msg_flags |= MSG_DONTWAIT;
_result.err = call_socket()->ops->sendmsg(0, call_socket(), &msg,
_call.msg.len);
}
void _do_setopt()
{
_result.err = Linux::sock_setsockopt(call_socket(), _call.sockopt.level,
_call.sockopt.optname,
(char *)_call.sockopt.optval,
_call.sockopt.optlen);
}
void _do_shutdown()
{
_result.err = call_socket()->ops->shutdown(call_socket(),
_call.shutdown.how);
}
void _do_socket()
{
using namespace Linux;
int type = _call.socket.type == Lxip::TYPE_STREAM ? SOCK_STREAM :
SOCK_DGRAM;
struct socket *s = (struct socket *)kzalloc(sizeof(struct socket), 0);
if (!sock_create_kern(AF_INET, type, 0, &s)) {
_handle.socket = static_cast<void *>(s);
return;
}
_handle.socket = 0;
kfree(s);
}
public:
Socketcall()
: Thread("socketcall"),
_signal(Genode::Signal_context_capability(Env::receiver()->manage(this)))
{
start();
}
void entry()
{
while (true) {
Genode::Signal s = Net::Env::receiver()->wait_for_signal();
static_cast<Genode::Signal_dispatcher_base *>(s.context())->dispatch(s.num());
}
}
/***********************
** Signal dispatcher **
***********************/
void dispatch(unsigned num)
{
if (verbose)
PDBG("SOCKET dispatch %u", _call.opcode);
switch (_call.opcode) {
case OP_ACCEPT : _do_accept(); break;
case OP_BIND : _do_bind(); break;
case OP_CLOSE : _do_close(); break;
case OP_CONNECT : _do_connect(); break;
case OP_GETNAME : _do_getname(0); break;
case OP_GETOPT : _do_getopt(); break;
case OP_IOCTL : _do_ioctl(); break;
case OP_PEERNAME : _do_getname(1); break;
case OP_LISTEN : _do_listen(); break;
case OP_POLL : _do_poll(); break;
case OP_RECV : _do_recv(); break;
case OP_SEND : _do_send(); break;
case OP_SETOPT : _do_setopt(); break;
case OP_SHUTDOWN : _do_shutdown(); break;
case OP_SOCKET : _do_socket(); break;
default:
_handle.socket = 0;
PWRN("Unkown opcode: %u\n", _call.opcode);
}
_unblock();
}
/**************************
** Socketcall interface **
**************************/
Lxip::Handle accept(Lxip::Handle h, void *addr, Lxip::uint32_t *len)
{
_call.opcode = OP_ACCEPT;
_call.handle = h;
_call.accept.addr = addr;
_call.accept.len = len;
_submit_and_block();
return _handle;
}
int bind(Lxip::Handle h, Lxip::uint16_t family, void *addr)
{
_call.opcode = OP_BIND;
_call.handle = h;
_call.addr_len = _family_handler(family, addr);
_submit_and_block();
return _result.err;
}
void close(Lxip::Handle h)
{
_call.opcode = OP_CLOSE;
_call.handle = h;
_submit_and_block();
}
int connect(Lxip::Handle h, Lxip::uint16_t family, void *addr)
{
_call.opcode = OP_CONNECT;
_call.handle = h;
_call.addr_len = _family_handler(family, addr);
_submit_and_block();
return _result.err;
}
int getpeername(Lxip::Handle h, void *addr, Lxip::uint32_t *len)
{
_call.opcode = OP_PEERNAME;
_call.handle = h;
_call.accept.len = len;
_call.accept.addr = addr;
_submit_and_block();
return _result.err;
}
int getsockname(Lxip::Handle h, void *addr, Lxip::uint32_t *len)
{
_call.opcode = OP_GETNAME;
_call.handle = h;
_call.accept.len = len;
_call.accept.addr = addr;
_submit_and_block();
return _result.err;
}
int getsockopt(Lxip::Handle h, int level, int optname,
void *optval, int *optlen)
{
_call.opcode = OP_GETOPT;
_call.handle = h;
_call.sockopt.level = level;
_call.sockopt.optname = optname;
_call.sockopt.optval = optval;
_call.sockopt.optlen_ptr = optlen;
_submit_and_block();
return _result.err;
}
int ioctl(Lxip::Handle h, int request, char *arg)
{
_call.opcode = OP_IOCTL;
_call.handle = h;
_call.ioctl.request = request;
_call.ioctl.arg = (unsigned long)arg;
_submit_and_block();
return _result.err;
}
int listen(Lxip::Handle h, int backlog)
{
_call.opcode = OP_LISTEN;
_call.handle = h;
_call.listen.backlog = backlog;
_submit_and_block();
return _result.err;
}
int poll(Lxip::Handle h, bool block)
{
_call.opcode = OP_POLL;
_call.handle = h;
_call.poll.block = block;
_submit_and_block();
return _result.err;
}
Lxip::ssize_t recv(Lxip::Handle h, void *buf, Lxip::size_t len, int flags,
Lxip::uint16_t family, void *addr,
Lxip::uint32_t *addr_len)
{
_call.opcode = OP_RECV;
_call.handle = h;
_call.msg.buf = buf;
_call.msg.len = len;
_call.msg.addr = addr;
_call.msg.addr_len = addr_len;
_call.msg.flags = flags;
_call.addr_len = _family_handler(family, addr);
_submit_and_block();
return _result.len;
}
Lxip::ssize_t send(Lxip::Handle h, const void *buf, Lxip::size_t len, int flags,
Lxip::uint16_t family, void *addr)
{
_call.opcode = OP_SEND;
_call.handle = h;
_call.msg.buf = (void *)buf;
_call.msg.len = len;
_call.msg.flags = flags;
_call.addr_len = _family_handler(family, addr);
_submit_and_block();
return _result.len;
}
int setsockopt(Lxip::Handle h, int level, int optname,
const void *optval, Lxip::uint32_t optlen)
{
_call.opcode = OP_SETOPT,
_call.handle = h;
_call.sockopt.level = level;
_call.sockopt.optname = optname;
_call.sockopt.optval = optval;
_call.sockopt.optlen = optlen;
_submit_and_block();
return _result.err;
}
int shutdown(Lxip::Handle h, int how)
{
_call.opcode = OP_SHUTDOWN;
_call.handle = h;
_call.shutdown.how = how;
_submit_and_block();
return _result.err;
}
Lxip::Handle socket(Lxip::Type type)
{
_call.opcode = OP_SOCKET;
_call.socket.type = type;
_submit_and_block();
return _handle;
}
};
Lxip::Socketcall & Lxip::init()
{
static int init = lxip_init();
static Net::Socketcall socketcall;
return socketcall;
}

View File

@ -0,0 +1,145 @@
/*
* \brief Signal context for timer events
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
* \date 2012-05-23
*/
/*
* Copyright (C) 2012-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <base/env.h>
#include <base/printf.h>
#include <lx_emul.h>
#include <env.h>
extern "C" {
#include <dde_kit/timer.h>
}
static void handler(void *timer);
/**
* Signal context for time-outs
*/
class Timer_context
{
private:
timer_list *_timer; /* Linux timer */
dde_kit_timer *_dde_timer; /* DDE kit timer */
Genode::Signal_dispatcher<Timer_context> _dispatcher;
/* call timer function */
void _handle(unsigned) { _timer->function(_timer->data); }
public:
Timer_context(timer_list *timer)
: _timer(timer), _dde_timer(0),
_dispatcher(*Net::Env::receiver(), *this, &Timer_context::_handle) {}
/* schedule next timeout */
void schedule(unsigned long expires)
{
if (!_dde_timer)
_dde_timer = dde_kit_timer_add(handler, this, expires);
else
dde_kit_timer_schedule_absolute(_dde_timer, expires);
}
/**
* Return true if timer is pending
*/
bool pending() const
{
return _dde_timer ? dde_kit_timer_pending(_dde_timer) : false;
}
/**
* Return internal signal cap
*/
Genode::Signal_context_capability cap() const { return _dispatcher; }
void submit() { _dispatcher.submit(1); }
/**
* Convert 'timer_list' to 'Timer_conext'
*/
static Timer_context *to_ctx(timer_list const *timer) {
return static_cast<Timer_context *>(timer->timer); }
void remove()
{
if (_dde_timer)
dde_kit_timer_del(_dde_timer);
_dde_timer = 0;
}
};
/**
* C handler for DDE timer interface
*/
static void handler(void *timer)
{
Timer_context *t = static_cast<Timer_context *>(timer);
t->submit();
/* set context and submit
Genode::Signal_transmitter transmitter(t->cap());
transmitter.submit(); */
}
/*******************
** linux/timer.h **
*******************/
void init_timer(struct timer_list *timer) {
timer->timer = (void *) new (Genode::env()->heap()) Timer_context(timer); }
void add_timer(struct timer_list *timer)
{
BUG_ON(timer_pending(timer));
mod_timer(timer, timer->expires);
}
int mod_timer(struct timer_list *timer, unsigned long expires)
{
dde_kit_log(DEBUG_TIMER, "Timer: %p j: %lu ex: %lu func %p",
timer, jiffies, expires, timer->function);
Timer_context::to_ctx(timer)->schedule(expires);
return 0;
}
void setup_timer(struct timer_list *timer,void (*function)(unsigned long),
unsigned long data)
{
timer->function = function;
timer->data = data;
init_timer(timer);
}
int timer_pending(const struct timer_list * timer)
{
bool pending = Timer_context::to_ctx(timer)->pending();
dde_kit_log(DEBUG_TIMER, "Pending %p %u", timer, pending);
return pending;
}
int del_timer(struct timer_list *timer)
{
dde_kit_log(DEBUG_TIMER, "Delete timer %p", timer);
Timer_context::to_ctx(timer)->remove();
return 0;
}

View File

@ -55,6 +55,7 @@ lappend_if $use_platform_driver build_components drivers/platform
lappend_if $use_nic_bridge build_components server/nic_bridge lappend_if $use_nic_bridge build_components server/nic_bridge
lappend_if [have_spec acpi] build_components drivers/acpi lappend_if [have_spec acpi] build_components drivers/acpi
lappend_if [have_spec pci] build_components drivers/pci/device_pd lappend_if [have_spec pci] build_components drivers/pci/device_pd
lappend_if [have_spec gpio] build_components drivers/gpio
build $build_components build $build_components
@ -96,6 +97,13 @@ append_if $use_platform_driver config {
<provides><service name="Regulator"/></provides> <provides><service name="Regulator"/></provides>
</start>} </start>}
append_if [have_spec gpio] config {
<start name="gpio_drv">
<resource name="RAM" quantum="4M"/>
<provides><service name="Gpio"/></provides>
<config/>
</start>}
append_if $use_nic_bridge config { append_if $use_nic_bridge config {
<start name="nic_bridge"> <start name="nic_bridge">
<resource name="RAM" quantum="4M"/> <resource name="RAM" quantum="4M"/>
@ -196,6 +204,7 @@ lappend_if $use_nic_bridge boot_modules nic_bridge
lappend_if $use_platform_driver boot_modules platform_drv lappend_if $use_platform_driver boot_modules platform_drv
lappend_if [have_spec acpi] boot_modules acpi_drv lappend_if [have_spec acpi] boot_modules acpi_drv
lappend_if [have_spec pci] boot_modules pci_drv lappend_if [have_spec pci] boot_modules pci_drv
lappend_if [have_spec gpio] boot_modules gpio_drv
lappend_if $use_usb_driver boot_modules usb_drv lappend_if $use_usb_driver boot_modules usb_drv
lappend_if $use_nic_driver boot_modules nic_drv lappend_if $use_nic_driver boot_modules nic_drv
lappend_if [have_spec nova] boot_modules pci_device_pd lappend_if [have_spec nova] boot_modules pci_device_pd