Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ridale/lwip #13

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions apps/lwip/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#
# Copyright 2019, Data61
# Commonwealth Scientific and Industrial Research Organisation (CSIRO)
# ABN 41 687 119 230.
#
# This software may be distributed and modified according to the terms of
# the BSD 2-Clause license. Note that NO WARRANTY is provided.
# See "LICENSE_BSD2.txt" for details.
#
# @TAG(DATA61_BSD)
Copy link
Member

@axel-h axel-h Mar 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is obsolete, please use:

Suggested change
# @TAG(DATA61_BSD)
# SPDX-License-Identifier: BSD-2-Clause

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case (because it is "ours") the rest of the header should be collapsed as well into just the copyright line and SPDX identifier like in the rest of the sources.

#

cmake_minimum_required(VERSION 3.8.2)

project(lwip C)

includeGlobalComponents()

set(LibLwip ON CACHE BOOL "" FORCE)
set(LibPicotcpBsd OFF CACHE BOOL "" FORCE)
set(LibEthdriverNumPreallocatedBuffers 32 CACHE STRING "" FORCE)

# For x86, we map DMA frames into the IOMMU to use as buffers for the
# Ethernet device. The VKA and VSpace libraries do not like pages that
# are not 4K in size.
set(CAmkESDMALargeFramePromotion OFF CACHE BOOL "" FORCE)

# The app has only been tested on hardware, and not on QEMU
set(SIMULATION OFF CACHE BOOL "" FORCE)
if("${KernelArch}" STREQUAL "x86")
# The IOMMU is required for the Ethdriver component on x86
set(KernelIOMMU ON CACHE BOOL "" FORCE)
endif()

set(CAmkESCPP ON CACHE BOOL "" FORCE)
if("${KernelArch}" STREQUAL "x86")
set(cpp_define -DKernelArchX86)
elseif("${KernelArch}" STREQUAL "arm")
set(cpp_define -DKernelArchArm)
endif()
ridale marked this conversation as resolved.
Show resolved Hide resolved

set(LWIPSERVER_IP_ADDR "" CACHE STRING "IP address for the LWIP server component")

DeclareCAmkESComponent(
Server
SOURCES
components/Server/src/main.c
components/Server/src/eth_interface.c
INCLUDES
components/include/
LIBS
sel4utils
lwip
ethdrivers
)

DeclareCAmkESRootserver(
lwip.camkes
CPP_FLAGS
${cpp_define}
-DLWIPSERVER_IP_ADDR=\"${LWIPSERVER_IP_ADDR}\"
)
3 changes: 3 additions & 0 deletions apps/lwip/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

LWIP echo server with any luck, based off the picoserver

219 changes: 219 additions & 0 deletions apps/lwip/components/Server/src/eth_interface.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
/*
* Copyright 2019, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(DATA61_GPL)
*/

#include <autoconf.h>

#include <string.h>
#include <camkes.h>

/* remove the camkes ERR_IF definition to not overlap with lwip */
#undef ERR_IF

#include <ethdrivers/raw.h>
#include <ethdrivers/lwip.h>

#include <sel4/sel4.h>
#include <sel4utils/sel4_zf_logif.h>

#include <lwip/lwipopts.h>

#include <lwip/init.h>
#include <lwip/netif.h>
#include <lwip/timers.h>
#include <lwip/udp.h>

#include <netif/etharp.h>

static lwip_iface_t lwip_driver = {0};

static void low_level_init(struct eth_driver *driver, uint8_t *mac, int *mtu)
{
// 1500 is the standard ethernet MTU at the network layer.
*mtu = 1500;
ethdriver_mac(&mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
}

extern void *ethdriver_buf;

static void raw_poll(struct eth_driver *driver)
{
int len;
int status;
status = ethdriver_rx(&len);
while (status != -1) {
void *buf;
void *cookie;
buf = (void *)driver->i_cb.allocate_rx_buf(driver->cb_cookie, len, &cookie);
if (buf) {
// Only proceed if we successfully got a buffer. If not, the packet will simply be dropped.
// UDP doesn't mind, and the packet will be resent for TCP due to us not sending an ACK.
// This prevents crashing in a DDOS attack or malicious packet that is too large.
memcpy(buf, (void *)ethdriver_buf, len);
driver->i_cb.rx_complete(driver->cb_cookie, 1, &cookie, (unsigned int *)&len);
}

if (status == 1) {
status = ethdriver_rx(&len);
} else {
/* if status is 0 we already saw the last packet */
assert(status == 0);
status = -1;
}
}
}

static int raw_tx(struct eth_driver *driver, unsigned int num, uintptr_t *phys, unsigned int *len, void *cookie)
{
unsigned int total_len = 0;
int i;
void *p = (void *)ethdriver_buf;
for (i = 0; i < num; i++) {
memcpy(p + total_len, (void *)phys[i], len[i]);
total_len += len[i];
}
ethdriver_tx(total_len);
return ETHIF_TX_COMPLETE;
}

static void handle_irq(struct eth_driver *driver, int irq)
{
raw_poll(driver);
}

void interface_tick() {
handle_irq(&lwip_driver.driver, 0);
}

static struct raw_iface_funcs iface_fns = {
.raw_handleIRQ = handle_irq,
.print_state = NULL,
.low_level_init = low_level_init,
.raw_tx = raw_tx,
.raw_poll = raw_poll
};

static int ethdriver_init(struct eth_driver *eth_driver, ps_io_ops_t io_ops, void *config)
{
eth_driver->eth_data = NULL;
eth_driver->dma_alignment = 1;
eth_driver->i_fn = iface_fns;
return 0;
}

static void *malloc_dma_alloc(void *cookie, size_t size, int align, int cached, ps_mem_flags_t flags)
{
assert(cached);
int error;
void *ret = malloc(size);
if (ret == NULL) {
ZF_LOGE("ERR: Failed to allocate %d\n", size);
return NULL;
}
return ret;
}

static void malloc_dma_free(void *cookie, void *addr, size_t size)
{
free(addr);
}

static uintptr_t malloc_dma_pin(void *cookie, void *addr, size_t size)
{
return (uintptr_t)addr;
}

static void malloc_dma_unpin(void *cookie, void *addr, size_t size)
{
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For empty functions, pleas add a comment in the body that they are empty on purpose. So it's clear the contain was not lonst somewhere during merging or rebasing or. The parameters should also be flagged as unused to silence compiler warnings.


static void malloc_dma_cache_op(void *cookie, void *addr, size_t size, dma_cache_op_t op)
{
}

void udp_recv_callback(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *ip, u16_t port) {
printf("Received udp packet of %d bytes from %s:%d\n", p->len, ipaddr_ntoa(ip), port);
char *data = malloc(p->len + 1);
strncpy(data, p->payload, p->len);
data[p->len] = '\0';

printf("Data: %s\n", data);
free(data);
/* send the data back */
udp_sendto(pcb, p, ip, port);
pbuf_free(p);
}

void netif_link_callback(struct netif *netif) {
if (netif_is_link_up(netif)) {
int err;
printf("Link is up\n");
printf("IPADDR is %s\n", ipaddr_ntoa(&netif->ip_addr));
struct udp_pcb *udp_conn = udp_new();
ZF_LOGF_IF(!udp_conn, "Failed to create udp connection");

err = udp_bind(udp_conn, IP_ADDR_ANY, 7);
ZF_LOGF_IF(err != ERR_OK, "Failed to bind port 7");
udp_recv(udp_conn, udp_recv_callback, NULL);
netif_set_up(netif);
}
}

static struct netif *init_interface(lwip_iface_t *lwip) {
assert(lwip->netif == NULL);
struct netif *netif = malloc(sizeof(*netif));
err_t err;
ip_addr_t addr, mask, gw;
IP4_ADDR(&mask, 255,255,255,0);
IP4_ADDR(&gw, 192,168,168,1);
IP4_ADDR(&addr, 192,168,168,2);

/* Initialise after configuration */
lwip->netif = netif_add(netif, &addr, &mask, &gw, lwip, ethif_get_ethif_init(lwip), ethernet_input);

assert(lwip->netif != NULL);
netif_set_default(lwip->netif);
netif_set_status_callback(lwip->netif, netif_link_callback);
netif_set_link_up(lwip->netif);
// err = dhcp_start(lwip->netif);
// ZF_LOGF_IF(err != ERR_OK, "Failed to start dhcp");

return netif;
}

static ps_io_ops_t io_ops;

void eth_init()
{
memset(&io_ops, 0, sizeof(io_ops));
io_ops.dma_manager = (ps_dma_man_t) {
.cookie = NULL,
.dma_alloc_fn = malloc_dma_alloc,
.dma_free_fn = malloc_dma_free,
.dma_pin_fn = malloc_dma_pin,
.dma_unpin_fn = malloc_dma_unpin,
.dma_cache_op_fn = malloc_dma_cache_op
};

/* Create a driver. This utilises preallocated buffers, backed up by malloc above */
if (NULL == ethif_new_lwip_driver_no_malloc(io_ops, NULL, ethdriver_init, NULL, &lwip_driver)) {
ZF_LOGF("Failed to create the lwip Driver");
}

/* Initialise LWIP stack */
lwip_init();

// lwip iface
struct netif *iface = init_interface(&lwip_driver);
if (iface == NULL) {
ZF_LOGF("Failed to create the lwip interface");
}
}
43 changes: 43 additions & 0 deletions apps/lwip/components/Server/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include <camkes.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a header with copyright infos (author, license).

#include <autoconf.h>
#include <stdio.h>
/* remove the camkes ERR_IF definition to not overlap with lwip */
#undef ERR_IF

#include <ethdrivers/lwip.h>
#include <lwip/timers.h>

#define LWIP_TICK_MS 100

static uint32_t counter_s = 0;

void eth_init();
void interface_tick();

u32_t sys_now(void) {
return counter_s/10;
}


void pre_init(void)
{
eth_init();
/* Start the timer for the TCP stack */
timer_periodic(0, NS_IN_MS * LWIP_TICK_MS);
}
/* Callback that gets called when the timer fires. */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add an empty line before the comment

void timer_complete_callback(void)
{
mut_lock();
counter_s +=1;
sys_check_timeouts();
interface_tick();
mut_unlock();
}


int run(void)
{
int retval = 0;
return retval;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add a a line break at the end of the file

Loading