diff --git a/repos/ealanos/include/mxip/arch/cc.h b/repos/ealanos/include/mxip/arch/cc.h
new file mode 100644
index 0000000000..50a5253c49
--- /dev/null
+++ b/repos/ealanos/include/mxip/arch/cc.h
@@ -0,0 +1,70 @@
+/*
+ * \brief Some size definitions and macros needed by LwIP.
+ * \author Stefan Kalkowski
+ * \author Emery Hemingway
+ * \date 2009-11-10
+ */
+
+/*
+ * Copyright (C) 2009-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef __LWIP__ARCH__CC_H__
+#define __LWIP__ARCH__CC_H__
+
+#ifdef LITTLE_ENDIAN
+#undef LITTLE_ENDIAN
+#endif
+
+#ifdef BIG_ENDIAN
+#undef BIG_ENDIAN
+#endif
+
+#include
+
+#ifndef LWIP_RAND
+genode_uint32_t genode_rand();
+#define LWIP_RAND() genode_rand()
+#endif
+
+#include
+#include
+#include
+
+#ifndef LWIP_PLATFORM_DIAG
+void lwip_printf(const char *format, ...);
+#define LWIP_PLATFORM_DIAG(x) do { lwip_printf x; } while(0)
+#endif /* LWIP_PLATFORM_DIAG */
+
+
+#ifdef GENODE_RELEASE
+#define LWIP_PLATFORM_ASSERT(x)
+#else /* GENODE_RELEASE */
+void lwip_platform_assert(char const* msg, char const *file, int line);
+#define LWIP_PLATFORM_ASSERT(x) \
+ do { \
+ lwip_platform_assert(x, __FILE__, __LINE__); \
+ } while (0)
+#endif /* GENODE_RELEASE */
+
+
+/*
+ * XXX: Should these be inlined?
+ */
+void genode_memcpy( void *dst, const void *src, size_t len);
+void *genode_memmove(void *dst, const void *src, size_t len);
+
+void genode_free(void *ptr);
+void *genode_malloc(unsigned long size);
+void *genode_calloc(unsigned long number, unsigned long size);
+
+#define mem_clib_free genode_free
+#define mem_clib_malloc genode_malloc
+#define mem_clib_calloc genode_calloc
+
+void genode_backtrace();
+
+#endif /* __LWIP__ARCH__CC_H__ */
diff --git a/repos/ealanos/include/mxip/arch/perf.h b/repos/ealanos/include/mxip/arch/perf.h
new file mode 100644
index 0000000000..eea977777f
--- /dev/null
+++ b/repos/ealanos/include/mxip/arch/perf.h
@@ -0,0 +1,20 @@
+/*
+ * \brief Header file with macros needed by LwIP.
+ * \author Stefan Kalkowski
+ * \date 2009-11-10
+ */
+
+/*
+ * Copyright (C) 2009-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef __LWIP__ARCH__PERF_H__
+#define __LWIP__ARCH__PERF_H__
+
+#define PERF_START
+#define PERF_STOP(x)
+
+#endif /* __LWIP__ARCH__PERF_H__ */
diff --git a/repos/ealanos/include/mxip/genode_init.h b/repos/ealanos/include/mxip/genode_init.h
new file mode 100644
index 0000000000..56bafb28a5
--- /dev/null
+++ b/repos/ealanos/include/mxip/genode_init.h
@@ -0,0 +1,24 @@
+/*
+ * \brief Genode native lwIP initalization
+ * \author Emery Hemingway
+ * \date 2017-08-21
+ */
+
+/*
+ * Copyright (C) 2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef _INCLUDE__MXIP__GENODE_INIT_H_
+#define _INCLUDE__MXIP__GENODE_INIT_H_
+
+#include
+#include
+
+namespace Mxip {
+ void mxip_init(Genode::Allocator &heap, ::Timer::Connection &timer);
+}
+
+#endif
diff --git a/repos/ealanos/include/mxip/lwipopts.h b/repos/ealanos/include/mxip/lwipopts.h
new file mode 100644
index 0000000000..8149942677
--- /dev/null
+++ b/repos/ealanos/include/mxip/lwipopts.h
@@ -0,0 +1,153 @@
+/*
+ * \brief Configuration file for LwIP, adapt it to your needs.
+ * \author Stefan Kalkowski
+ * \author Emery Hemingway
+ * \date 2009-11-10
+ *
+ * See lwip/src/include/lwip/opt.h for all options
+ */
+
+/*
+ * Copyright (C) 2009-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef __LWIP__LWIPOPTS_H__
+#define __LWIP__LWIPOPTS_H__
+
+/* Genode includes */
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Use lwIP without OS-awareness
+ */
+#define NO_SYS 1
+#define SYS_LIGHTWEIGHT_PROT 0
+
+#define LWIP_DNS 0 /* DNS support */
+#define LWIP_DHCP 1 /* DHCP support */
+#define LWIP_SOCKET 0 /* LwIP socket API */
+#define LWIP_NETIF_LOOPBACK 0 /* Looping back to same address? */
+#define LWIP_STATS 0 /* disable stating */
+#define LWIP_ICMP 0
+#define LWIP_SNMP 0
+#define LWIP_TCP_TIMESTAMPS 0
+#define TCP_LISTEN_BACKLOG 255
+#define TCP_MSS 1460
+#define TCP_WND (80 * TCP_MSS)
+#define TCP_SND_BUF (80 * TCP_MSS)
+#define LWIP_WND_SCALE 3
+#define TCP_RCV_SCALE 2
+#define TCP_SND_QUEUELEN ((512 * (TCP_SND_BUF) + (TCP_MSS - 1))/(TCP_MSS))
+
+#define LWIP_NETIF_STATUS_CALLBACK 1 /* callback function used for interface changes */
+#define LWIP_NETIF_LINK_CALLBACK 1 /* callback function used for link-state changes */
+#define LWIP_SUPPORT_CUSTOM_PBUF 1
+
+#define LWIP_SINGLE_NETIF 1
+
+#define TCP_QUEUE_OOSEQ 1
+/***********************************
+ ** Checksum calculation settings **
+ ***********************************/
+
+/* checksum calculation for outgoing packets can be disabled if the hardware supports it */
+#define LWIP_CHECKSUM_ON_COPY 1 /* calculate checksum during memcpy */
+
+/*********************
+ ** Memory settings **
+ *********************/
+
+#define MEM_LIBC_MALLOC 1
+#define MEMP_MEM_MALLOC 1
+
+/* MEM_ALIGNMENT > 4 e.g. for x86_64 are not supported, see Genode issue #817 */
+#define MEM_ALIGNMENT 4
+#define MEMP_NUM_TCP_SEG (2 * TCP_SND_QUEUELEN)
+
+#define DEFAULT_ACCEPTMBOX_SIZE 128
+#define TCPIP_MBOX_SIZE 128
+
+#define RECV_BUFSIZE_DEFAULT (512*1024)
+
+#define PBUF_POOL_SIZE 8192
+
+#define MEMP_NUM_SYS_TIMEOUT 16
+#define MEMP_NUM_TCP_PCB 512
+#define MEMP_NUM_PBUF (128*4096)
+
+#ifndef MEMCPY
+#define MEMCPY(dst,src,len) genode_memcpy(dst,src,len)
+#endif
+
+#ifndef MEMMOVE
+#define MEMMOVE(dst,src,len) genode_memmove(dst,src,len)
+#endif
+
+/********************
+ ** Debug settings **
+ ********************/
+#define LWIP_NOASSERT 1
+
+//#define LWIP_DEBUG
+/* #define DHCP_DEBUG LWIP_DBG_ON */
+/* #define ETHARP_DEBUG LWIP_DBG_ON */
+/* #define NETIF_DEBUG LWIP_DBG_ON */
+//#define PBUF_DEBUG LWIP_DBG_ON
+/* #define API_LIB_DEBUG LWIP_DBG_ON */
+/* #define API_MSG_DEBUG LWIP_DBG_ON */
+/* #define SOCKETS_DEBUG LWIP_DBG_ON */
+/* #define ICMP_DEBUG LWIP_DBG_ON */
+/* #define INET_DEBUG LWIP_DBG_ON */
+/* #define IP_DEBUG LWIP_DBG_ON */
+/* #define IP_REASS_DEBUG LWIP_DBG_ON */
+/* #define RAW_DEBUG LWIP_DBG_ON */
+/* #define MEM_DEBUG LWIP_DBG_ON */
+/* #define MEMP_DEBUG LWIP_DBG_ON */
+/* #define SYS_DEBUG LWIP_DBG_ON */
+//#define TCP_DEBUG LWIP_DBG_ON
+
+
+/*
+ ----------------------------------
+ ---------- DHCP options ----------
+ ----------------------------------
+*/
+
+#define LWIP_DHCP_CHECK_LINK_UP 1
+
+
+/*
+ ----------------------------------------------
+ ---------- Sequential layer options ----------
+ ----------------------------------------------
+*/
+/* no Netconn API */
+#define LWIP_NETCONN 0
+
+
+/*
+ ---------------------------------------
+ ---------- IPv6 options ---------------
+ ---------------------------------------
+*/
+
+#define LWIP_IPV6 0
+#define IPV6_FRAG_COPYHEADER 1
+
+#define LWIP_IPV4 1
+#define IPV4_FRAG_COPYHEADER 0
+#define IP_REASSEMBLY 0
+#define IP_FRAG 0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LWIP__LWIPOPTS_H__ */
diff --git a/repos/ealanos/include/mxip/mxnic_netif.h b/repos/ealanos/include/mxip/mxnic_netif.h
new file mode 100644
index 0000000000..651ca12dc9
--- /dev/null
+++ b/repos/ealanos/include/mxip/mxnic_netif.h
@@ -0,0 +1,599 @@
+/*
+ * \brief LwIP netif for the Nic session
+ * \author Emery Hemingway
+ * \date 2016-09-28
+ *
+ * If you want to use the lwIP API in a native Genode
+ * component then this is the Nic client to use.
+ */
+
+/*
+ * Copyright (C) 2016-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+/* TODO: Bugs
+ * tcp_out.c:1410 0x1033d4c - GPF
+ * tcp_in.c:1102 0x102c084 - GPF
+ * tcp_out.c:1335 - GPF
+ * OUT_OF_CAPS
+ * PAGE_FAULT and GPFs on task->execute
+ * GPF on task->next()
+*/
+
+#ifndef __LWIP__NIC_NETIF_H__
+#define __LWIP__NIC_NETIF_H__
+
+#include "base/allocator.h"
+#include "mx/memory/global_heap.h"
+#include
+#if ETH_PAD_SIZE
+#error ETH_PAD_SIZE defined but unsupported by lwip/nic_netif.h
+#endif
+
+#ifndef __cplusplus
+#error lwip/nic_netif.h is a C++ only header
+#endif
+
+/* Genode includes */
+#include
+#include
+#include
+
+/* MxTasking includes */
+#include
+#include
+
+/* EalanOS includes */
+#include
+
+namespace Lwip {
+
+extern "C" {
+/* LwIP includes */
+#include
+#include
+#if LWIP_IPV6
+#include
+#endif
+#include
+#include
+#include
+}
+} // namespace Lwip
+
+namespace Mxip
+{
+ class Receive_task;
+ class Tx_ready_task;
+ class Link_state_task;
+ class Finished_rx_task;
+ class Nic_netif;
+
+ using namespace Lwip;
+}
+
+namespace Lwip {
+
+ extern "C" {
+
+ static void nic_netif_pbuf_free(pbuf *p);
+ static err_t nic_netif_init(struct netif *netif);
+ static err_t nic_netif_linkoutput(struct netif *netif, struct pbuf *p);
+ static void nic_netif_status_callback(struct netif *netif);
+ }
+
+ /**
+ * Metadata for packet backed pbufs
+ */
+ struct Nic_netif_pbuf
+ {
+ struct pbuf_custom p { };
+ Mxip::Nic_netif &netif;
+ void *payload;
+
+ Nic_netif_pbuf(Mxip::Nic_netif &nic, void *pl)
+ : netif(nic), payload(pl)
+ {
+ p.custom_free_function = nic_netif_pbuf_free;
+ }
+ };
+}
+
+class Mxip::Nic_netif
+{
+ public:
+
+ friend class Mxip::Receive_task;
+ friend class Mxip::Tx_ready_task;
+ friend class Mxip::Link_state_task;
+
+ struct Wakeup_scheduler : Genode::Noncopyable, Genode::Interface
+ {
+ virtual void schedule_nic_server_wakeup() = 0;
+ };
+
+ enum { TASK_SIZE = 128, SB_SIZE = 2 * 2048 };
+
+ private:
+
+ Genode::Entrypoint _ep;
+
+ Wakeup_scheduler &_wakeup_scheduler;
+
+ bool _tx_saturated = false;
+
+ enum {
+ PACKET_SIZE = Nic::Packet_allocator::DEFAULT_PACKET_SIZE,
+ BUF_SIZE = 2048*PACKET_SIZE,
+ };
+
+ Genode::Tslab _pbuf_alloc;
+
+ public:
+ using Payload_allocator = Ealan::Memory::Hamstraaja;
+
+ private:
+ Ealan::Memory::Hamstraaja<128, 4 * 4096> *_task_alloc{nullptr};
+ Payload_allocator *_packet_alloc{nullptr};
+ Nic::Packet_allocator _nic_tx_alloc;
+ Nic::Connection _nic;
+
+ struct Lwip::netif _netif { };
+
+ Lwip::ip_addr_t ip { };
+ Lwip::ip_addr_t nm { };
+ Lwip::ip_addr_t gw { };
+
+ Genode::Io_signal_handler _link_state_handler;
+ Genode::Io_signal_handler _rx_packet_handler;
+ Genode::Io_signal_handler _tx_ready_handler;
+
+ bool _dhcp { false };
+
+ public:
+
+ void free_pbuf(Lwip::Nic_netif_pbuf &pbuf)
+ {
+ /*bool msg_once = true;
+ while (!_nic.rx()->ready_to_ack()) {
+ if (msg_once)
+ Genode::error("Nic rx acknowledgement queue congested, blocking to free pbuf");
+ msg_once = false;
+ _ep.wait_and_dispatch_one_io_signal();
+ }
+
+ _nic.rx()->try_ack_packet(pbuf.packet);
+ _wakeup_scheduler.schedule_nic_server_wakeup();*/
+ _packet_alloc->free(pbuf.payload);
+ _task_alloc->free(&pbuf);//destroy(_pbuf_alloc, &pbuf);
+ }
+
+ /*************************
+ ** Nic signal handlers **
+ *************************/
+
+ void handle_link_state();
+ void handle_rx_packets();
+
+ /**
+ * Handle tx ack_avail and ready_to_submit signals
+ */
+ void handle_tx_ready();
+
+ void configure(Genode::Xml_node const &config)
+ {
+ _dhcp = config.attribute_value("dhcp", false);
+
+ using Str = Genode::String;
+ Str ip_str = config.attribute_value("ip_addr", Str());
+
+ Genode::log("Static IP: ", ip_str);
+
+ if (_dhcp && ip_str != "") {
+ _dhcp = false;
+ Lwip::netif_set_down(&_netif);
+ Genode::error("refusing to configure lwIP interface with both DHCP and a static IPv4 address");
+ return;
+ }
+
+ Genode::log("Bringing up NIC");
+ Lwip::netif_set_up(&_netif);
+ Genode::log("Set NIC up");
+
+ if (ip_str != "") {
+ Lwip::ip_addr_t ipaddr;
+ if (!Lwip::ipaddr_aton(ip_str.string(), &ipaddr)) {
+ Genode::error("lwIP configured with invalid IP address '",ip_str,"'");
+ throw ip_str;
+ }
+
+ Genode::log("Setting IP for NIC");
+ netif_set_ipaddr(&_netif, ip_2_ip4(&ipaddr));
+
+ Genode::log("Set IP address for NIC");
+ if (config.has_attribute("netmask")) {
+ Str str = config.attribute_value("netmask", Str());
+ Lwip::ip_addr_t ip;
+ Lwip::ipaddr_aton(str.string(), &ip);
+ Lwip::netif_set_netmask(&_netif, ip_2_ip4(&ip));
+ }
+
+ if (config.has_attribute("gateway")) {
+ Str str = config.attribute_value("gateway", Str());
+ Lwip::ip_addr_t ip;
+ Lwip::ipaddr_aton(str.string(), &ip);
+ Lwip::netif_set_gw(&_netif, ip_2_ip4(&ip));
+ }
+
+ }
+
+ if (config.has_attribute("nameserver")) {
+ /*
+ * LwIP does not use DNS internally, but the application
+ * should expect "dns_getserver" to work regardless of
+ * how the netif configures itself.
+ */
+ Str str = config.attribute_value("nameserver", Str());
+ Lwip::ip_addr_t ip;
+ Lwip::ipaddr_aton(str.string(), &ip);
+ //dns_setserver(0, &ip);
+ }
+
+ Genode::log("Finished configuring NIC");
+ handle_link_state();
+ }
+
+ Nic_netif(Genode::Env &env, Genode::Allocator &alloc, Genode::Xml_node config,
+ Wakeup_scheduler &wakeup_scheduler,
+ Ealan::Memory::Hamstraaja<128, 4 * 4096> *task_alloc, Payload_allocator *palloc)
+ : _ep(env, 4*4096, "mxip_ep", env.cpu().affinity_space().location_of_index(0)), _wakeup_scheduler(wakeup_scheduler), _pbuf_alloc(alloc),
+ _task_alloc(task_alloc),
+ _packet_alloc(palloc),
+ _nic_tx_alloc(&alloc),
+ _nic(env, &_nic_tx_alloc,
+ BUF_SIZE, BUF_SIZE,
+ config.attribute_value("label", Genode::String<160>("mxip")).string()),
+ _link_state_handler(_ep, *this, &Nic_netif::handle_link_state),
+ _rx_packet_handler( _ep, *this, &Nic_netif::handle_rx_packets),
+ _tx_ready_handler(_ep, *this, &Nic_netif::handle_tx_ready)
+ {
+ Genode::memset(&_netif, 0x00, sizeof(_netif));
+
+ {
+ Lwip::ip4_addr_t v4dummy;
+ IP4_ADDR(&v4dummy, 0, 0, 0, 0);
+
+ netif* r = Lwip::netif_add(&_netif, &v4dummy, &v4dummy, &v4dummy,
+ this, nic_netif_init, ethernet_input);
+ if (r == NULL) {
+ Genode::error("failed to initialize Nic to lwIP interface");
+ throw r;
+ }
+ }
+
+ Lwip::netif_set_default(&_netif);
+ Lwip::netif_set_status_callback(
+ &_netif, nic_netif_status_callback);
+ Lwip::nic_netif_status_callback(&_netif);
+
+ configure(config);
+ }
+
+ virtual ~Nic_netif() { }
+
+ Lwip::netif& lwip_netif() { return _netif; }
+
+ bool tx_saturated() const { return _tx_saturated; }
+
+ /**
+ * Status callback to override in subclass
+ */
+ virtual void status_callback() { }
+
+ /**
+ * Callback issued by lwIP to initialize netif struct
+ *
+ * \noapi
+ */
+ err_t init()
+ {
+ /*
+ * XXX: hostname and MTU could probably be
+ * set in the Nic client constructor
+ */
+
+#if LWIP_NETIF_HOSTNAME
+ /* Initialize interface hostname */
+ _netif.hostname = "";
+#endif /* LWIP_NETIF_HOSTNAME */
+
+ _netif.name[0] = 'e';
+ _netif.name[1] = 'n';
+
+ _netif.output = etharp_output;
+#if LWIP_IPV6
+ _netif.output_ip6 = ethip6_output;
+#endif /* LWIP_IPV6 */
+
+ _netif.linkoutput = nic_netif_linkoutput;
+
+ /* Set physical MAC address */
+ Nic::Mac_address const mac = _nic.mac_address();
+ for(int i=0; i<6; ++i)
+ _netif.hwaddr[i] = mac.addr[i];
+
+ _netif.mtu = 1500; /* XXX: just a guess */
+ _netif.hwaddr_len = ETHARP_HWADDR_LEN;
+ _netif.flags = NETIF_FLAG_BROADCAST |
+ NETIF_FLAG_ETHARP |
+ NETIF_FLAG_LINK_UP;
+
+ /* set Nic session signal handlers */
+ _nic.link_state_sigh(_link_state_handler);
+ _nic.rx_channel()->sigh_packet_avail(_rx_packet_handler);
+ _nic.rx_channel()->sigh_ready_to_ack(_rx_packet_handler);
+ _nic.tx_channel()->sigh_ready_to_submit(_tx_ready_handler);
+ _nic.tx_channel()->sigh_ack_avail (_tx_ready_handler);
+
+ return ERR_OK;
+ }
+
+ /**
+ * Callback issued by lwIP to write a Nic packet
+ *
+ * \noapi
+ */
+ err_t linkoutput(struct pbuf *p)
+ {
+ auto &tx = *_nic.tx();
+
+ /* flush acknowledgements */
+ while (tx.ack_avail()) {
+ tx.release_packet(tx.try_get_acked_packet());
+ _tx_saturated = false;
+ }
+
+ if (!tx.ready_to_submit()) {
+ Genode::error("lwIP: Nic packet queue congested, cannot send packet");
+ _tx_saturated = true;
+ return ERR_WOULDBLOCK;
+ }
+
+ Nic::Packet_descriptor packet;
+ try { packet = tx.alloc_packet(p->tot_len); }
+ catch (...) {
+ Genode::error("lwIP: Nic packet allocation failed, cannot send packet");
+ _tx_saturated = true;
+ return ERR_WOULDBLOCK;
+ }
+
+ /*
+ * We iterate over the pbuf chain until we have read the entire
+ * pbuf into the packet.
+ */
+ char *dst = tx.packet_content(packet);
+ for (struct pbuf *q = p; q != nullptr; q = q->next) {
+ char const *src = (char const *)q->payload;
+ Genode::memcpy(dst, src, q->len);
+ dst += q->len;
+ }
+
+ tx.try_submit_packet(packet);
+ _wakeup_scheduler.schedule_nic_server_wakeup();
+ LINK_STATS_INC(link.xmit);
+ return ERR_OK;
+ }
+
+ bool ready()
+ {
+ return netif_is_up(&_netif) &&
+ !ip_addr_isany(&_netif.ip_addr);
+ }
+
+ /**
+ * Trigger submission of deferred packet-stream signals
+ */
+ void wakeup_nic_server()
+ {
+ _nic.rx()->wakeup();
+ _nic.tx()->wakeup();
+ }
+};
+
+/**************************
+ ** MxIP handler tasks **
+ **************************/
+
+class Mxip::Receive_task : public mx::tasking::TaskInterface
+{
+ public:
+
+ Receive_task(void *payload, size_t len, struct Lwip::netif &netif, Mxip::Nic_netif &net)
+ : _netif(netif), _payload(payload), _length(len), _net(net)
+ {
+ }
+
+ mx::tasking::TaskResult execute(std::uint16_t, std::uint16_t) override
+ {
+ Lwip::Nic_netif_pbuf *nic_pbuf = new (_net._task_alloc->alloc(sizeof(Lwip::Nic_netif_pbuf)))
+ Lwip::Nic_netif_pbuf(_net, _payload);
+
+ if (!nic_pbuf) {
+ Genode::warning("Could not allocate pbuf ");
+ _net._task_alloc->free(this);
+ return mx::tasking::TaskResult::make_null();
+ }
+ pbuf *p = pbuf_alloced_custom(PBUF_RAW, _length, PBUF_REF, &nic_pbuf->p, _payload,
+ _length);
+ LINK_STATS_INC(link.recv);
+
+ if (!p) {
+ Genode::warning("Initialization of pbuf failed.");
+ _net._task_alloc->free(this);
+ return mx::tasking::TaskResult::make_null();
+ }
+ err_t rc = _netif.input(p, &_netif);
+
+ if (rc != ERR_OK) {
+ Genode::error("error forwarding Nic packet to lwIP: error=",
+ static_cast(rc));
+ pbuf_free(p);
+ }
+
+ _net._task_alloc->free(this);
+ return mx::tasking::TaskResult::make_null();
+ //return mx::tasking::TaskResult::make_remove();
+ }
+
+ private:
+
+ struct Lwip::netif &_netif;
+ void *_payload;
+ std::size_t _length;
+ Mxip::Nic_netif &_net;
+
+};
+
+class Mxip::Tx_ready_task : public mx::tasking::TaskInterface
+{
+ public:
+
+ Tx_ready_task(Nic::Connection &nic, Mxip::Nic_netif &netif) : _nic(nic), _netif(netif) { }
+ mx::tasking::TaskResult execute(std::uint16_t, std::uint16_t) override
+ {
+ auto &tx = *_nic.tx();
+ bool progress = false;
+
+ while (tx.ack_avail()) {
+ tx.release_packet(tx.try_get_acked_packet());
+ _netif._tx_saturated = false;
+ progress = true;
+ }
+
+ _netif.status_callback();
+
+ if (progress) _netif._wakeup_scheduler.schedule_nic_server_wakeup();
+
+ _netif._task_alloc->free(this);
+ return mx::tasking::TaskResult::make_null();
+ //return mx::tasking::TaskResult::make_remove();
+ }
+
+ private:
+
+ Nic::Connection &_nic;
+ Mxip::Nic_netif &_netif;
+};
+
+class Mxip::Link_state_task : public mx::tasking::TaskInterface
+{
+ public:
+
+ Link_state_task(Nic::Connection &nic, Lwip::netif &netif, Mxip::Nic_netif &nic_netif,
+ bool dhcp)
+ : _nic(nic), _nic_netif(nic_netif), _netif(netif), _dhcp(dhcp)
+ {
+ }
+
+ mx::tasking::TaskResult execute(std::uint16_t, std::uint16_t) override
+ {
+ /*
+ * if the application wants to be informed of the
+ * link state then it should use 'set_link_callback'
+ */
+ if (_nic.link_state()) {
+ Lwip::netif_set_link_up(&_netif);
+ if (_dhcp) {
+ err_t err = dhcp_start(&_netif);
+ if (err != ERR_OK) {
+ Genode::error("failed to configure lwIP interface with DHCP, error ", -err);
+ }
+ } else {
+ Lwip::dhcp_inform(&_netif);
+ }
+ } else {
+ Lwip::netif_set_link_down(&_netif);
+ if (_dhcp) {
+ Lwip::dhcp_release_and_stop(&_netif);
+ }
+ }
+ _nic_netif._task_alloc->free(this);
+ return mx::tasking::TaskResult::make_null();
+ //return mx::tasking::TaskResult::make_remove();
+ }
+
+ private:
+
+ Nic::Connection &_nic;
+ Mxip::Nic_netif &_nic_netif;
+ Lwip::netif &_netif;
+ bool _dhcp;
+};
+
+/**************************
+ ** LwIP netif callbacks **
+ **************************/
+
+namespace Lwip {
+ extern "C" {
+
+/**
+ * Free a packet buffer backed pbuf
+ */
+static void nic_netif_pbuf_free(pbuf *p)
+{
+ Nic_netif_pbuf *nic_pbuf = reinterpret_cast(p);
+ nic_pbuf->netif.free_pbuf(*nic_pbuf);
+}
+
+
+/**
+ * Initialize the netif
+ */
+static err_t nic_netif_init(struct netif *netif)
+{
+ Mxip::Nic_netif *nic_netif = (Mxip::Nic_netif *)netif->state;
+ return nic_netif->init();
+}
+
+
+/**
+ * Send a raw packet to the Nic session
+ */
+static err_t nic_netif_linkoutput(struct netif *netif, struct pbuf *p)
+{
+ Mxip::Nic_netif *nic_netif = (Mxip::Nic_netif *)netif->state;
+ return nic_netif->linkoutput(p);
+}
+
+
+static void nic_netif_status_callback(struct netif *netif)
+{
+ Mxip::Nic_netif *nic_netif = (Mxip::Nic_netif *)netif->state;
+
+ if (netif_is_up(netif)) {
+ if (!ip4_addr_isany(netif_ip4_addr(netif))) {
+ using Str = Genode::String;
+ Str address((char const*)ip4addr_ntoa(netif_ip4_addr(netif)));
+ Str netmask((char const*)ip4addr_ntoa(netif_ip4_netmask(netif)));
+ Str gateway((char const*)ip4addr_ntoa(netif_ip4_gw(netif)));
+
+ Genode::log("MxIP Nic interface up"
+ " address=", address,
+ " netmask=", netmask,
+ " gateway=", gateway);
+ }
+ } else {
+ Genode::log("MxIP Nic interface down");
+ }
+
+ //nic_netif->status_callback();
+}
+
+ }
+}
+
+#endif /* __LWIP__NIC_NETIF_H__ */
diff --git a/repos/ealanos/lib/import/import-mxip.mk b/repos/ealanos/lib/import/import-mxip.mk
new file mode 100644
index 0000000000..c1eea5f246
--- /dev/null
+++ b/repos/ealanos/lib/import/import-mxip.mk
@@ -0,0 +1,2 @@
+INC_DIR += $(call select_from_ports,mxip)/include/lwip
+INC_DIR += $(call select_from_repositories,include/mxip)
diff --git a/repos/ealanos/lib/mk/mxip.mk b/repos/ealanos/lib/mk/mxip.mk
new file mode 100644
index 0000000000..5b304f3429
--- /dev/null
+++ b/repos/ealanos/lib/mk/mxip.mk
@@ -0,0 +1,54 @@
+#
+# lwIP TCP/IP library
+#
+# The library implements TCP and UDP as well as DNS and DHCP.
+#
+
+LWIP_PORT_DIR := $(call select_from_ports,mxip)
+LWIPDIR := $(LWIP_PORT_DIR)/src/lib/lwip/src
+
+MXTASKING := $(REP_DIR)/src/lib/
+
+-include $(LWIPDIR)/Filelists.mk
+
+# Genode platform files
+SRC_CC = printf.cc rand.cc sys_arch.cc mxnic_netif.cc
+
+# Core files
+SRC_C += $(notdir $(COREFILES))
+
+# IPv4 files
+SRC_C += $(notdir $(CORE4FILES))
+
+# IPv6 files
+SRC_C += $(notdir $(CORE6FILES))
+
+# Network interface files
+SRC_C += $(notdir $(NETIFFILES))
+
+INC_DIR += $(REP_DIR)/include/mxip \
+ $(LWIP_PORT_DIR)/include/lwip \
+ $(LWIPDIR)/include \
+ $(LWIPDIR)/include/ipv4 \
+ $(LWIPDIR)/include/api \
+ $(LWIPDIR)/include/netif \
+ $(MXTASKING) \
+
+vpath %.cc $(REP_DIR)/src/lib/mxip/platform
+vpath %.c $(sort $(dir \
+ $(COREFILES) $(CORE4FILES) $(CORE6FILES) $(NETIFFILES)))
+vpath %.h $(INC_DIR)
+
+GENODE_GCC_TOOLCHAIN_DIR ?= /usr/local/genode/tool/21.05
+
+CUSTOM_CXX = /usr/local/genode/tool/bin/clang++
+CUSTOM_CC = /usr/local/genode/tool/bin/clang
+
+CC_OPT := --target=x86_64-genode --sysroot=/does/not/exist --gcc-toolchain=$(GENODE_GCC_TOOLCHAIN_DIR) -DCLANG_CXX11_ATOMICS -Wno-error=all -Wno-error=conversion -Wno-error=effc++ -Wno-error=unknown-attributes -g -DNDEBUG -I$(MXINC_DIR) -std=c++20 -mssse3 #-D_GLIBCXX_ATOMIC_BUILTINS_8 -D__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
+CC_OPT += -Wno-deprecated-anon-enum-enum-conversion
+
+CC_OLEVEL = -O3
+
+LIBS += libm libc stdcxx mxtasking format
+EXT_OBJECTS += /usr/local/genode/tool/lib/clang/14.0.5/lib/linux/libclang_rt.builtins-x86_64.a /usr/local/genode/tool/lib/libatomic.a
+
diff --git a/repos/ealanos/ports/mxip.hash b/repos/ealanos/ports/mxip.hash
new file mode 100644
index 0000000000..edaa2b4e63
--- /dev/null
+++ b/repos/ealanos/ports/mxip.hash
@@ -0,0 +1 @@
+e310a8d13995d4b3110cb727a298d781b4f03504
diff --git a/repos/ealanos/ports/mxip.port b/repos/ealanos/ports/mxip.port
new file mode 100644
index 0000000000..461b4202af
--- /dev/null
+++ b/repos/ealanos/ports/mxip.port
@@ -0,0 +1,23 @@
+LICENSE := BSD
+VERSION := 2.1.2
+DOWNLOADS := lwip.archive
+
+URL(lwip) := http://git.savannah.nongnu.org/cgit/lwip.git/snapshot/lwip-STABLE-2_1_2_RELEASE.tar.gz
+SHA(lwip) := da6a3e07944505e6add328f6efafea4ad670700731f36b1ba54bd43d4f35243e
+DIR(lwip) := src/lib/lwip
+
+UNPACKED_DIR := src/lib/lwip
+
+PATCHES := $(wildcard $(REP_DIR)/src/lib/lwip/*.patch)
+PATCH_OPT := -p1 -d src/lib/lwip
+
+DIRS := \
+ include/lwip/lwip \
+ include/lwip/lwip/priv \
+ include/lwip/lwip/prot \
+ include/lwip/netif \
+
+DIR_CONTENT(include/lwip/lwip/priv) := $(UNPACKED_DIR)/src/include/lwip/priv/*.h
+DIR_CONTENT(include/lwip/lwip/prot) := $(UNPACKED_DIR)/src/include/lwip/prot/*.h
+DIR_CONTENT(include/lwip/lwip) := $(UNPACKED_DIR)/src/include/lwip/*.h
+DIR_CONTENT(include/lwip/netif) := $(UNPACKED_DIR)/src/include/netif/*.h
diff --git a/repos/ealanos/recipes/api/mxip/content.mk b/repos/ealanos/recipes/api/mxip/content.mk
new file mode 100644
index 0000000000..8c28bde149
--- /dev/null
+++ b/repos/ealanos/recipes/api/mxip/content.mk
@@ -0,0 +1,20 @@
+MIRROR_FROM_REP_DIR := \
+ $(shell cd $(REP_DIR); find include/mxip src/lib/mxip -type f) \
+ lib/import/import-mxip.mk \
+ lib/mk/mxip.mk \
+
+PORT_DIR := $(call port_dir,$(REP_DIR)/ports/mxip)
+
+MIRROR_FROM_PORT_DIR := $(shell cd $(PORT_DIR); find include src -type f)
+
+content: $(MIRROR_FROM_REP_DIR) $(MIRROR_FROM_PORT_DIR) LICENSE
+
+$(MIRROR_FROM_REP_DIR):
+ $(mirror_from_rep_dir)
+
+$(MIRROR_FROM_PORT_DIR):
+ mkdir -p $(dir $@)
+ cp -r $(PORT_DIR)/$@ $@
+
+LICENSE:
+ cp $(PORT_DIR)/src/lib/lwip/COPYING $@
diff --git a/repos/ealanos/recipes/api/mxip/used_api b/repos/ealanos/recipes/api/mxip/used_api
new file mode 100644
index 0000000000..7a5f1ab72b
--- /dev/null
+++ b/repos/ealanos/recipes/api/mxip/used_api
@@ -0,0 +1,5 @@
+base
+libm
+libc
+stdcxx
+mxtasking
\ No newline at end of file
diff --git a/repos/ealanos/src/lib/mxip/include/stdlib.h b/repos/ealanos/src/lib/mxip/include/stdlib.h
new file mode 100644
index 0000000000..2641481f45
--- /dev/null
+++ b/repos/ealanos/src/lib/mxip/include/stdlib.h
@@ -0,0 +1,15 @@
+#ifndef _LWIP__INCLUDE__STDLIB_H_
+#define _LWIP__INCLUDE__STDLIB_H_
+
+/**
+ * Simple atoi for LwIP purposes
+ */
+static inline int atoi(char const *s)
+{
+ int n = 0;
+ while ('0' <= *s && *s <= '9')
+ n = 10*n - (*s++ - '0');
+ return n;
+}
+
+#endif
diff --git a/repos/ealanos/src/lib/mxip/include/string.h b/repos/ealanos/src/lib/mxip/include/string.h
new file mode 100644
index 0000000000..0d4b83330f
--- /dev/null
+++ b/repos/ealanos/src/lib/mxip/include/string.h
@@ -0,0 +1,34 @@
+/*
+ * \brief Memory manipulation utilities
+ * \author Emery Hemingway
+ * \date 2017-08-21
+ */
+
+/*
+ * Copyright (C) 2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+#ifndef __LWIP__INCLUDE__STRING_H__
+#define __LWIP__INCLUDE__STRING_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void *memcpy(void *dst, const void *src, size_t len);
+void *memset(void *b, int c, size_t len);
+
+size_t strlen(const char *s);
+
+int memcmp(const void *b1, const void *b2, size_t len);
+int strcmp(const char *s1, const char *s2);
+int strncmp(const char *s1, const char *s2, size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __LWIP__INCLUDE__STRING_H__ */
\ No newline at end of file
diff --git a/repos/ealanos/src/lib/mxip/memmove.patch b/repos/ealanos/src/lib/mxip/memmove.patch
new file mode 100644
index 0000000000..681805f15d
--- /dev/null
+++ b/repos/ealanos/src/lib/mxip/memmove.patch
@@ -0,0 +1,12 @@
+diff --git a/src/core/def.c b/src/core/def.c
+index 9da36fee..58edce6f 100644
+--- a/src/core/def.c
++++ b/src/core/def.c
+@@ -235,6 +235,6 @@ lwip_itoa(char *result, size_t bufsize, int number)
+ return;
+ }
+ /* move from temporary buffer to output buffer (sign is not moved) */
+- memmove(res, tmp, (size_t)((result + bufsize) - tmp));
++ MEMMOVE(res, tmp, (size_t)((result + bufsize) - tmp));
+ }
+ #endif
diff --git a/repos/ealanos/src/lib/mxip/platform/mxnic_netif.cc b/repos/ealanos/src/lib/mxip/platform/mxnic_netif.cc
new file mode 100644
index 0000000000..28943eb52e
--- /dev/null
+++ b/repos/ealanos/src/lib/mxip/platform/mxnic_netif.cc
@@ -0,0 +1,86 @@
+#include "lwip/pbuf.h"
+#include
+#include
+#include
+#include
+#include
+
+void Mxip::Nic_netif::handle_rx_packets()
+{
+
+Nic::Session::Rx::Sink *rx = _nic.rx();
+
+bool progress = false;
+
+while (rx->packet_avail() && rx->ready_to_ack()) {
+
+ try
+ {
+ Nic::Packet_descriptor packet = rx->try_get_packet();
+ progress = true;
+
+ void *payload = _packet_alloc->alloc(sizeof(packet.size()));
+ memcpy(payload, rx->packet_content(packet), packet.size());
+
+ Mxip::Receive_task *task = new (_task_alloc->alloc(sizeof(Mxip::Receive_task))) Mxip::Receive_task(payload, packet.size(), _netif, *this);
+ if (task == nullptr)
+ {
+ Genode::warning("Could not allocate task object.");
+ return;
+ }
+ task->annotate(static_cast(0));
+ mx::tasking::runtime::spawn(*task);
+
+ if (progress) {
+
+ while (!_nic.rx()->ready_to_ack()) { _ep.wait_and_dispatch_one_io_signal(); }
+
+ rx->try_ack_packet(packet);
+ _wakeup_scheduler.schedule_nic_server_wakeup();
+ }
+ }
+ catch (Genode::Exception)
+ {
+ Genode::warning("Got signal without actual packet in queue");
+ }
+}
+}
+
+void Mxip::Nic_netif::handle_tx_ready()
+{
+/*Mxip::Tx_ready_task *task = new (_task_alloc->alloc(sizeof(Mxip::Tx_ready_task)))
+Mxip::Tx_ready_task(_nic, *this); if (task == nullptr)
+{
+ Genode::warning("Could not allocate tx_ready task object.");
+ return;
+}
+task->annotate(static_cast(0));
+mx::tasking::runtime::spawn(*task);*/
+
+
+ auto &tx = *_nic.tx();
+ bool progress = false;
+
+ while (tx.ack_avail()) {
+ tx.release_packet(tx.try_get_acked_packet());
+ _tx_saturated = false;
+ progress = true;
+ }
+
+ status_callback();
+
+ if (progress) _wakeup_scheduler.schedule_nic_server_wakeup();
+
+ //return mx::tasking::TaskResult::make_remove();
+}
+
+void Mxip::Nic_netif::handle_link_state()
+{
+Mxip::Link_state_task *task = new (_task_alloc->alloc(sizeof(Mxip::Link_state_task))) Mxip::Link_state_task(_nic, _netif, *this, _dhcp);
+if (task == nullptr) {
+ Genode::warning("Could not allocate link state task object.");
+ return;
+}
+task->annotate(static_cast(0));
+mx::tasking::runtime::spawn(*task);
+}
\ No newline at end of file
diff --git a/repos/ealanos/src/lib/mxip/platform/printf.cc b/repos/ealanos/src/lib/mxip/platform/printf.cc
new file mode 100644
index 0000000000..47beed01de
--- /dev/null
+++ b/repos/ealanos/src/lib/mxip/platform/printf.cc
@@ -0,0 +1,38 @@
+/*
+ * \brief Print function for debugging functionality of lwIP.
+ * \author Stefan Kalkowski
+ * \date 2009-10-26
+ */
+
+/*
+ * Copyright (C) 2009-2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+/* Genode includes */
+#include
+#include
+
+#include
+
+extern "C" {
+
+/* LwIP includes */
+#include
+
+ /* Simply map to Genode's printf implementation */
+ void lwip_printf(const char *format, ...)
+ {
+ va_list list;
+ va_start(list, format);
+
+ char buf[128] { };
+ Format::String_console(buf, sizeof(buf)).vprintf(format, list);
+ Genode::log(Genode::Cstring(buf));
+
+ va_end(list);
+ }
+
+}
diff --git a/repos/ealanos/src/lib/mxip/platform/rand.cc b/repos/ealanos/src/lib/mxip/platform/rand.cc
new file mode 100644
index 0000000000..0472c619cf
--- /dev/null
+++ b/repos/ealanos/src/lib/mxip/platform/rand.cc
@@ -0,0 +1,30 @@
+/*
+ * \brief Simple random number generator for lwIP
+ * \author Emery Hemingway
+ * \date 2016-07-30
+ */
+
+// *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
+// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
+
+/* Genode includes */
+#include
+#include
+
+extern "C"
+genode_uint32_t genode_rand()
+{
+ using namespace Genode;
+
+ static uint64_t const inc = Trace::timestamp()|1;
+ static uint64_t state = Trace::timestamp();
+ uint64_t oldstate = state;
+
+ // Advance internal state
+ state = oldstate * 6364136223846793005ULL + inc;
+
+ // Calculate output function (XSH RR), uses old state for max ILP
+ uint32_t xorshifted = (uint32_t)(((oldstate >> 18u) ^ oldstate) >> 27u);
+ uint32_t rot = (uint32_t)(oldstate >> 59u);
+ return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
+}
diff --git a/repos/ealanos/src/lib/mxip/platform/sys_arch.cc b/repos/ealanos/src/lib/mxip/platform/sys_arch.cc
new file mode 100644
index 0000000000..7db0048013
--- /dev/null
+++ b/repos/ealanos/src/lib/mxip/platform/sys_arch.cc
@@ -0,0 +1,161 @@
+/*
+ * \brief lwIP platform support
+ * \author Stefan Kalkowski
+ * \author Emery Hemingway
+ * \date 2016-12-01
+ */
+
+/*
+ * Copyright (C) 2017 Genode Labs GmbH
+ *
+ * This file is part of the Genode OS framework, which is distributed
+ * under the terms of the GNU Affero General Public License version 3.
+ */
+
+/* Genode includes */
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+
+extern "C" {
+/* LwIP includes */
+#include
+#include
+#include
+#include
+
+/* our abridged copy of string.h */
+#include
+}
+
+namespace Mxip {
+
+ static Genode::Allocator *_heap;
+
+ class Timeout_task : public mx::tasking::TaskInterface
+ {
+ public:
+
+ Timeout_task() { }
+
+ mx::tasking::TaskResult execute(std::uint16_t, std::uint16_t) override
+ {
+ //GENODE_LOG_TSC_NAMED(1, "sys_check_timeouts");
+ sys_check_timeouts();
+ //_heap->free(static_cast(this), 0);
+ return mx::tasking::TaskResult::make_remove();
+ }
+ };
+
+ struct Sys_timer
+ {
+ void check_timeouts(Genode::Duration)
+ {
+ Timeout_task *task = /*new (_heap->alloc(sizeof(Timeout_task)))
+ Timeout_task();*/ mx::tasking::runtime::new_task(0);
+ if (task == nullptr) {
+ Genode::error("Failed to allocate timeout task");
+ return;
+ }
+ task->annotate(static_cast(0));
+ mx::tasking::runtime::spawn(*task);
+ }
+
+ ::Timer::Connection &timer;
+
+ Timer::Periodic_timeout timeout {
+ timer, *this, &Sys_timer::check_timeouts,
+ Genode::Microseconds{250*1000} };
+
+ Sys_timer(::Timer::Connection &timer) : timer(timer) { }
+ };
+
+ static Sys_timer *sys_timer_ptr;
+
+ void mxip_init(Genode::Allocator &heap, ::Timer::Connection &timer)
+ {
+ LWIP_ASSERT("LwIP initialized with an allocator that does not track sizes",
+ !heap.need_size_for_free());
+
+ _heap = &heap;
+
+ static Sys_timer sys_timer(timer);
+ sys_timer_ptr = &sys_timer;
+
+ lwip_init();
+ }
+}
+
+
+extern "C" {
+
+ void lwip_platform_assert(char const* msg, char const *file, int line)
+ {
+ Genode::error("Assertion \"", msg, "\" ", file, ":", line);
+ Genode::backtrace();
+ Genode::sleep_forever();
+ }
+
+ void genode_free(void *ptr)
+ {
+ Mxip::_heap->free(ptr, 0);
+ }
+
+ void *genode_malloc(unsigned long size)
+ {
+ void *ptr = Mxip::_heap->try_alloc(size).convert(
+ [&](void *ptr) { return ptr; },
+ [&](Genode::Allocator::Alloc_error) -> void * { return nullptr; });
+ if (reinterpret_cast(ptr) >= (0x7FFF80000000UL)) {
+ Genode::error("Non-canonic address from heap: ", ptr);
+ Genode::sleep_forever();
+ }
+ return ptr;
+ }
+
+ void *genode_calloc(unsigned long number, unsigned long size)
+ {
+ size *= number;
+
+ void * const ptr = genode_malloc(size);
+ if (ptr)
+ Genode::memset(ptr, 0x00, size);
+
+ return ptr;
+ }
+
+ u32_t sys_now(void) {
+ return (u32_t)Mxip::sys_timer_ptr->timer.curr_time().trunc_to_plain_ms().value; }
+
+ void genode_memcpy(void *dst, const void *src, size_t len) {
+ Genode::memcpy(dst, src, len); }
+
+ void *genode_memmove(void *dst, const void *src, size_t len) {
+ return Genode::memmove(dst, src, len); }
+
+ int memcmp(const void *b1, const void *b2, ::size_t len) {
+ return Genode::memcmp(b1, b2, len); }
+
+ int strcmp(const char *s1, const char *s2)
+ {
+ size_t len = Genode::min(Genode::strlen(s1), Genode::strlen(s2));
+ return Genode::strcmp(s1, s2, len);
+ }
+
+ int strncmp(const char *s1, const char *s2, size_t len) {
+ return Genode::strcmp(s1, s2, len);
+ }
+
+ void genode_backtrace()
+ {
+ Genode::backtrace();
+ }
+
+}
diff --git a/repos/libports/lib/symbols/stdcxx b/repos/libports/lib/symbols/stdcxx
index e7a2643251..b16df76723 100644
--- a/repos/libports/lib/symbols/stdcxx
+++ b/repos/libports/lib/symbols/stdcxx
@@ -1858,3 +1858,10 @@ _ZTv0_n24_NSt7__cxx1119basic_ostringstreamIwSt11char_traitsIwESaIwEED1Ev W
_ZNSt17__timepunct_cacheIcE12_S_timezonesE D 112
_ZNSt17__timepunct_cacheIwE12_S_timezonesE D 112
+
+# symbols used by clang
+_ZNSt13basic_filebufIcSt11char_traitsIcEED2Ev W
+_ZNSt14basic_ifstreamIcSt11char_traitsIcEEC1ERKNSt7__cxx1112basic_stringIcS1_SaIcEEESt13_Ios_Openmode W
+_ZNSt14basic_ofstreamIcSt11char_traitsIcEEC1ERKNSt7__cxx1112basic_stringIcS1_SaIcEEESt13_Ios_Openmode W
+_ZNSo6sentryD2Ev W
+_ZNKRSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEE3strEv W
\ No newline at end of file