Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 2 additions & 0 deletions .reuse/dep5
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ Files:
examples/gpu/fb_img.jpeg
examples/echo_server/docs/echo_server.svg
docs/i2c/i2cdriver.drawio.png
docs/network/imgs/metadata.svg
docs/network/imgs/network_arch.png
Copyright: UNSW
License: CC-BY-SA-4.0

Expand Down
1 change: 1 addition & 0 deletions docs/network/imgs/metadata.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/network/imgs/network_arch.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
641 changes: 635 additions & 6 deletions docs/network/network.md

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion examples/echo_server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,9 @@ configurations will report utilisation numbers as 0, and no PMU data will be
printed.

Assuming you have ipbench setup, you can use the following script to run the
benchmark:
benchmark. Note that the machine which runs this script will become the ipbench
[controller](#benchmarking) of all the benchmarks, and the script assumes that
the ipbench daemon of the clients are already running.
```sh
python3 scripts/benchmark.py [target machine ip] --clients [ip addr(s) of ipbenchd systems]
```
Expand Down
68 changes: 2 additions & 66 deletions examples/echo_server/echo.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ net_queue_handle_t net_tx_handle;

#define LWIP_TICK_MS 100

struct pbuf *head;
struct pbuf *tail;

/**
* Netif status callback function that output's client's name and
* obtained IP address.
Expand All @@ -59,65 +56,6 @@ void set_timeout(void)
sddf_timer_set_timeout(timer_config.driver_id, LWIP_TICK_MS * NS_IN_MS);
}

/**
* Stores a pbuf to be transmitted upon available transmit buffers.
*
* @param p pbuf to be stored.
*/
net_sddf_err_t enqueue_pbufs(struct pbuf *p)
{
/* Indicate to the tx virt that we wish to be notified about free tx buffers */
net_request_signal_free(&net_tx_handle);

if (head == NULL) {
head = p;
} else {
tail->next_chain = p;
}
tail = p;

/* Increment reference count to ensure this pbuf is not freed by lwip */
pbuf_ref(p);

return SDDF_LWIP_ERR_OK;
}

void transmit(void)
{
bool reprocess = true;
while (reprocess) {
while (head != NULL && !net_queue_empty_free(&net_tx_handle)) {
net_sddf_err_t err = sddf_lwip_transmit_pbuf(head);
if (err == SDDF_LWIP_ERR_LARGE_PBUF) {
sddf_dprintf("LWIP|ERROR: attempted to send a packet of size %u > BUFFER SIZE %u\n", head->tot_len,
NET_BUFFER_SIZE);
} else if (err != SDDF_LWIP_ERR_OK) {
sddf_dprintf("LWIP|ERROR: unkown error when trying to send pbuf %p\n", head);
}

struct pbuf *temp = head;
head = temp->next_chain;
if (head == NULL) {
tail = NULL;
}
pbuf_free(temp);
}

/* Only request a signal if there are more pending pbufs to send */
if (head == NULL || !net_queue_empty_free(&net_tx_handle)) {
net_cancel_signal_free(&net_tx_handle);
} else {
net_request_signal_free(&net_tx_handle);
}
reprocess = false;

if (head != NULL && !net_queue_empty_free(&net_tx_handle)) {
net_cancel_signal_free(&net_tx_handle);
reprocess = true;
}
}
}

void init(void)
{
serial_queue_init(&serial_tx_queue_handle, serial_config.tx.queue.vaddr, serial_config.tx.data.size,
Expand All @@ -131,7 +69,7 @@ void init(void)
net_buffers_init(&net_tx_handle, 0);

sddf_lwip_init(&lib_sddf_lwip_config, &net_config, &timer_config, net_rx_handle, net_tx_handle, NULL, NULL,
netif_status_callback, enqueue_pbufs, NULL, NULL);
netif_status_callback, NULL, NULL, NULL);
set_timeout();

setup_udp_socket();
Expand All @@ -145,12 +83,10 @@ void notified(sddf_channel ch)
{
if (ch == net_config.rx.id) {
sddf_lwip_process_rx();
} else if (ch == net_config.tx.id) {
transmit();
} else if (ch == timer_config.driver_id) {
sddf_lwip_process_timeout();
set_timeout();
} else if (ch == serial_config.tx.id) {
} else if (ch == serial_config.tx.id || ch == net_config.tx.id) {
// Nothing to do
} else {
sddf_dprintf("LWIP|LOG: received notification on unexpected channel: %u\n", ch);
Expand Down
2 changes: 0 additions & 2 deletions examples/echo_server/echo.mk
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ LWIPDIR := network/ipstacks/lwip/src
BENCHMARK := $(SDDF)/benchmark
UTIL := $(SDDF)/util
ETHERNET_DRIVER := $(SDDF)/drivers/network/$(NET_DRIV_DIR)
ETHERNET_CONFIG_INCLUDE := ${ECHO_SERVER}/include/ethernet_config
Comment thread
Courtney3141 marked this conversation as resolved.
SERIAL_COMPONENTS := $(SDDF)/serial/components
UART_DRIVER := $(SDDF)/drivers/serial/$(UART_DRIV_DIR)
TIMER_DRIVER := $(SDDF)/drivers/timer/$(TIMER_DRIV_DIR)
Expand All @@ -51,7 +50,6 @@ CFLAGS += \
-I$(SDDF)/include/microkit \
-I$(SDDF)/include \
-I${ECHO_INCLUDE}/lwip \
-I${ETHERNET_CONFIG_INCLUDE} \
-I$(LWIPDIR)/include \
-I$(LWIPDIR)/include/ipv4 \
-I $(ECHO_SERVER)/include \
Expand Down
6 changes: 3 additions & 3 deletions include/sddf/network/lib_sddf_lwip.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ typedef net_sddf_err_t (*sddf_lwip_tx_handle_intercept_fn)(struct pbuf *p);
*
* @return true if pbuf pool is empty, false otherwise.
*/
bool pbuf_pool_empty(void);
bool sddf_lwip_pbuf_pool_empty(void);

/**
* Allocate a pbuf from lib sDDF lwIP static pbuf pool.
*
* @return pointer to allocated pbuf or NULL if out of memory.
*/
pbuf_custom_offset_t *pbuf_pool_alloc(void);
pbuf_custom_offset_t *sddf_lwip_pbuf_pool_alloc(void);

/**
* Free a pbuf allocated from lib sDDF lwIP static pbuf pool. WARNING: This
Expand All @@ -100,7 +100,7 @@ pbuf_custom_offset_t *pbuf_pool_alloc(void);
* @return SDDF_LWIP_ERR_INVALID_PBUF pbuf is not part of lib sDDF lwIP static
* pbuf pool.
*/
net_sddf_err_t pbuf_pool_free(pbuf_custom_offset_t *pbuf);
net_sddf_err_t sddf_lwip_pbuf_pool_free(pbuf_custom_offset_t *pbuf);

/**
* Checks lwIP system timeouts. Should be invoked after every lwIP tick.
Expand Down
37 changes: 26 additions & 11 deletions network/lib_sddf_lwip/lib_sddf_lwip.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,14 @@ static void pbuf_pool_init(void *mem, size_t mem_size, size_t pbuf_count)
pbuf_pool.pbufs[pbuf_count - 1].next_free = SIZE_MAX;
}

inline bool pbuf_pool_empty(void)
inline bool sddf_lwip_pbuf_pool_empty(void)
{
return pbuf_pool.first_free == SIZE_MAX;
}

pbuf_custom_offset_t *pbuf_pool_alloc(void)
pbuf_custom_offset_t *sddf_lwip_pbuf_pool_alloc(void)
{
if (pbuf_pool_empty()) {
if (sddf_lwip_pbuf_pool_empty()) {
return NULL;
}

Expand All @@ -116,7 +116,7 @@ pbuf_custom_offset_t *pbuf_pool_alloc(void)
return &pbuf_pool.pbufs[first_free].pbuf;
}

net_sddf_err_t pbuf_pool_free(pbuf_custom_offset_t *pbuf)
net_sddf_err_t sddf_lwip_pbuf_pool_free(pbuf_custom_offset_t *pbuf)
{
if (pbuf == NULL || pbuf < (pbuf_custom_offset_t *)pbuf_pool.pbufs
|| pbuf > (pbuf_custom_offset_t *)&pbuf_pool.pbufs[pbuf_pool.capacity]
Expand Down Expand Up @@ -190,16 +190,24 @@ static void netif_status_callback_default(char *ip_addr)
}

/**
* Default handling function to be called during transmission if tx free
* queue is empty.
* Default handling function to be called during transmission of a pbuf if the
* Tx free queue is empty. We signal the Tx virtualiser as it is likely that
* there has been a delay in processing active buffers, possibly due to the Tx
* virtualiser not being scheduled.
*
* @param p pbuf that could not be sent due to queue being empty.
*
* @return Simply returns the sddf error indicating nothing was done.
* @return sddf error indicating that there were no buffers available.
*/
static inline net_sddf_err_t handle_empty_tx_free_default(struct pbuf *p)
{
return SDDF_LWIP_ERR_UNHANDLED;
if (sddf_state.tx_queue.capacity && sddf_state.notify_tx && net_require_signal_active(&sddf_state.tx_queue)) {
net_cancel_signal_active(&sddf_state.tx_queue);
sddf_state.notify_tx = false;
sddf_notify(sddf_state.tx_ch);
}

return SDDF_LWIP_ERR_NO_BUF;
}

/**
Expand Down Expand Up @@ -260,7 +268,7 @@ static void interface_free_buffer(struct pbuf *p)
int err = net_enqueue_free(&(sddf_state.rx_queue), buffer);
assert(!err);
sddf_state.notify_rx = true;
pbuf_pool_free(custom_pbuf_offset);
sddf_lwip_pbuf_pool_free(custom_pbuf_offset);
SYS_ARCH_UNPROTECT(old_level);
}

Expand All @@ -280,7 +288,7 @@ static struct pbuf *create_interface_buffer(uint64_t offset, size_t length)
return NULL;
}

pbuf_custom_offset_t *custom_pbuf_offset = pbuf_pool_alloc();
pbuf_custom_offset_t *custom_pbuf_offset = sddf_lwip_pbuf_pool_alloc();
if (!custom_pbuf_offset) {
return NULL;
}
Expand Down Expand Up @@ -361,7 +369,7 @@ void sddf_lwip_process_rx(void)

bool reprocess = true;
while (reprocess) {
while (!net_queue_empty_active(&sddf_state.rx_queue) && !pbuf_pool_empty()) {
while (!net_queue_empty_active(&sddf_state.rx_queue) && !sddf_lwip_pbuf_pool_empty()) {
net_buff_desc_t buffer;
int err = net_dequeue_active(&sddf_state.rx_queue, &buffer);
assert(!err);
Expand Down Expand Up @@ -446,6 +454,13 @@ void sddf_lwip_init(lib_sddf_lwip_config_t *lib_sddf_lwip_config, net_client_con
}
lib_config = *lib_sddf_lwip_config;

/**
* This library assumes that we will never run out of pbufs to input Rx
* buffers into the lwIP stack. This means that the number of pbufs must
* exceed the capacity of the Rx queue.
*/
assert(lib_config.num_pbufs >= sddf_state.rx_queue.capacity);

/* Initialise sddf state */
sddf_state.rx_queue = rx_queue;
sddf_state.tx_queue = tx_queue;
Expand Down