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