From 5c0aa976d3d47f17471b609d19b749557716f2a0 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 12 Feb 2015 13:34:09 +0100 Subject: Add zerocopy sendto --- testsuite/zerocopy01/test_main.c | 243 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 testsuite/zerocopy01/test_main.c (limited to 'testsuite') diff --git a/testsuite/zerocopy01/test_main.c b/testsuite/zerocopy01/test_main.c new file mode 100644 index 00000000..d23c746f --- /dev/null +++ b/testsuite/zerocopy01/test_main.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2015 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define TEST_NAME "LIBBSD ZEROCOPY 1" + +#define BUFFER_COUNT 128 + +#define NOTIFY_THRESHOLD 64 + +#define DATA_SIZE (ETHERMTU - sizeof(struct ip) - sizeof(struct udphdr)) + +struct buffer { + SLIST_ENTRY(buffer) link; + u_int ref_cnt; + char *data; +}; + +struct buffer_control { + SLIST_HEAD(buffer_list, buffer) free_list; + rtems_interrupt_lock lock; + size_t free_buffers; + rtems_id waiting_task; + struct buffer buffers[BUFFER_COUNT]; + char data[DATA_SIZE][BUFFER_COUNT]; +}; + +static struct buffer_control buffer_control; + +static void +buffer_free(void *arg1, void *arg2) +{ + struct buffer_control *bc = arg1; + struct buffer *buf = arg2; + rtems_status_code sc; + rtems_interrupt_lock_context lock_context; + rtems_id waiting_task; + + buf->ref_cnt = 0; + + rtems_interrupt_lock_acquire(&bc->lock, &lock_context); + SLIST_INSERT_HEAD(&bc->free_list, buf, link); + waiting_task = bc->waiting_task; + ++bc->free_buffers; + if (bc->free_buffers < NOTIFY_THRESHOLD) { + waiting_task = 0; + } + rtems_interrupt_lock_release(&bc->lock, &lock_context); + + if (waiting_task != 0) { + sc = rtems_event_transient_send(waiting_task); + assert(sc == RTEMS_SUCCESSFUL); + } +} + +static struct mbuf * +buffer_get(struct buffer_control *bc) +{ + struct mbuf *m = rtems_bsd_m_gethdr(M_WAITOK, MT_DATA); + struct buffer *buf; + rtems_status_code sc; + rtems_interrupt_lock_context lock_context; + + do { + rtems_interrupt_lock_acquire(&bc->lock, &lock_context); + if (SLIST_EMPTY(&bc->free_list)) { + bc->waiting_task = rtems_task_self(); + rtems_interrupt_lock_release(&bc->lock, &lock_context); + + sc = rtems_event_transient_receive(RTEMS_WAIT, + RTEMS_NO_TIMEOUT); + assert(sc == RTEMS_SUCCESSFUL); + + buf = NULL; + } else { + buf = SLIST_FIRST(&bc->free_list); + SLIST_REMOVE_HEAD(&bc->free_list, link); + --bc->free_buffers; + rtems_interrupt_lock_release(&bc->lock, &lock_context); + } + } while (buf == NULL); + + m->m_len = DATA_SIZE; + m->m_pkthdr.len = DATA_SIZE; + rtems_bsd_m_extaddref(m, buf, DATA_SIZE, &buf->ref_cnt, buffer_free, + bc, buf); + + return (m); +} + +static void +network_flood_task(rtems_task_argument arg) +{ + int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + struct sockaddr_in addr = { + .sin_len = sizeof(addr), + .sin_family = AF_INET, + .sin_port = htons(13161), + .sin_addr = { + .s_addr = INADDR_ANY + } + }; + int rv = inet_aton(NET_CFG_PEER_IP, &addr.sin_addr); + struct buffer_control *bc = (struct buffer_control *)arg; + + assert(fd >= 0); + assert(rv != 0); + + while (true) { + struct mbuf *m = buffer_get(bc); + int error = rtems_bsd_sendto( + fd, + m, + 0, + (const struct sockaddr *) &addr + ); + + if (error != 0) { + printf("zerocopy sendto error: %s\n", strerror(error)); + sleep(1); + } + } +} + +static void +telnet_shell(char *name, void *arg) +{ + rtems_shell_env_t env; + + memset(&env, 0, sizeof(env)); + + env.devname = name; + env.taskname = "TLNT"; + env.login_check = NULL; + env.forever = false; + + rtems_shell_main_loop(&env); +} + +rtems_telnetd_config_table rtems_telnetd_config = { + .command = telnet_shell, + .arg = NULL, + .priority = 2, + .stack_size = 0, + .login_check = NULL, + .keep_stdio = false +}; + +static void +test_main(void) +{ + struct buffer_control *bc = &buffer_control; + rtems_status_code sc; + rtems_id id; + size_t i; + + sc = rtems_telnetd_initialize(); + assert(sc == RTEMS_SUCCESSFUL); + + SLIST_INIT(&bc->free_list); + + for (i = 0; i < BUFFER_COUNT; ++i) { + SLIST_INSERT_HEAD(&bc->free_list, &bc->buffers[i], link); + bc->buffers[i].data = &bc->data[i][0]; + } + + sc = rtems_task_create( + rtems_build_name('F', 'L', 'O', 'D'), + 3, + RTEMS_MINIMUM_STACK_SIZE, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &id + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start(id, network_flood_task, (rtems_task_argument) bc); + assert(sc == RTEMS_SUCCESSFUL); + + rtems_task_delete(RTEMS_SELF); + assert(0); +} + +#define DEFAULT_NETWORK_DHCPCD_ENABLE +#define DEFAULT_NETWORK_SHELL + +#define CONFIGURE_MAXIMUM_DRIVERS 32 + +#include -- cgit v1.2.3