blob: fe6f44f94faa0e14e324b5a9351a952a26cdcd67 [file] [log] [blame]
/* network.c - Networking demo */
/*
* Copyright (c) 2015 Intel Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <zephyr.h>
#if defined(CONFIG_STDOUT_CONSOLE)
#include <stdio.h>
#define PRINT printf
#else
#include <misc/printk.h>
#define PRINT printk
#endif
#include <net/ip_buf.h>
#include <net/net_core.h>
#include <net/net_socket.h>
#include <net_driver_loopback.h>
/* Longer packet sending works only if fragmentation is supported
* by network stack.
*/
/* Generated by http://www.lipsum.com/
* 2 paragraphs, 185 words, 1231 bytes of Lorem Ipsum
* The main() will add one null byte at the end so the maximum
* length for the data to send is 1232 bytes.
*/
static const char *lorem_ipsum =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam congue non neque vel tempor. In id porta nibh, ut cursus tortor. Morbi eleifend tristique vehicula. Nunc vitae risus mauris. Praesent vel imperdiet dolor, et ultricies nibh. Aliquam erat volutpat. Maecenas pellentesque dolor vitae dictum tincidunt. Fusce vel nibh nec leo tristique auctor eu a massa. Nam et tellus ac tortor sollicitudin semper vitae nec tortor. Aliquam nec lacus velit. Maecenas ornare ullamcorper justo non auctor. Donec aliquam feugiat turpis, quis elementum sem rutrum ut. Sed eu ullamcorper libero, ut suscipit magna."
"\n"
"Donec vehicula magna ut varius aliquam. Ut vitae commodo nulla, quis ornare dolor. Nulla tortor sem, venenatis eu iaculis id, commodo ut massa. Sed est lorem, euismod vitae enim sed, hendrerit gravida felis. Donec eros lacus, auctor ut ultricies eget, lobortis quis nisl. Aliquam sit amet blandit eros. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque egestas nisl leo, sed consectetur leo ornare eu. Suspendisse vitae urna vel purus maximus finibus. Proin sed sollicitudin turpis. Mauris interdum neque eu tellus pellentesque, id fringilla nisi fermentum. Suspendisse gravida pharetra sodales orci aliquam.";
/* specify delay between greetings (in ms); compute equivalent in ticks */
#define SLEEPTIME 1000
#define SLEEPTICKS (SLEEPTIME * sys_clock_ticks_per_sec / 1000)
#define STACKSIZE 2000
static char fiberReceiverStack[STACKSIZE];
static char fiberSenderStack[STACKSIZE];
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; /* :: */
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; /* ::1 */
static struct net_addr any_addr;
static struct net_addr loopback_addr;
static int sent;
static int received;
static nano_thread_id_t sender_id;
static nano_thread_id_t receiver_id;
static bool failure;
static int appdatalen;
/* How many packets to send/receive */
#if defined(CONFIG_NETWORK_LOOPBACK_TEST_COUNT)
#define TEST_COUNT CONFIG_NETWORK_LOOPBACK_TEST_COUNT
#else
#define TEST_COUNT 0
#endif
static unsigned long count = TEST_COUNT;
void fiber_receiver(void)
{
struct nano_timer timer;
uint32_t data[2] = {0, 0};
struct net_context *ctx;
struct net_buf *buf;
ctx = net_context_get(IPPROTO_UDP,
&any_addr, 0,
&loopback_addr, 4242);
if (!ctx) {
PRINT("%s: Cannot get network context\n", __func__);
return;
}
nano_timer_init(&timer, data);
while (!failure) {
buf = net_receive(ctx, TICKS_UNLIMITED);
if (buf) {
PRINT("%d: %s: received %d bytes\n", received++,
__func__, ip_buf_appdatalen(buf));
if (appdatalen != ip_buf_appdatalen(buf)) {
failure = true;
PRINT("Received %d bytes but was sent "
"%d bytes\n",
ip_buf_appdatalen(buf), appdatalen);
} else if (memcmp(lorem_ipsum, ip_buf_appdata(buf),
appdatalen - 1)) {
failure = true;
PRINT("Sent and received data do not match.\n");
PRINT(" Sent: %.*s\n", appdatalen, lorem_ipsum);
PRINT("Received: %.*s\n", appdatalen, ip_buf_appdata(buf));
}
ip_buf_unref(buf);
}
if (count && (count < received)) {
break;
}
fiber_wakeup(sender_id);
fiber_sleep(SLEEPTICKS);
}
}
void fiber_sender(void)
{
struct nano_timer timer;
uint32_t data[2] = {0, 0};
struct net_context *ctx;
struct net_buf *buf;
int len;
int ipsum_len = strlen(lorem_ipsum);
ctx = net_context_get(IPPROTO_UDP,
&loopback_addr, 4242,
&any_addr, 0);
if (!ctx) {
PRINT("Cannot get network context\n");
return;
}
nano_timer_init(&timer, data);
while (!failure) {
buf = ip_buf_get_tx(ctx);
if (buf) {
uint8_t *ptr;
uint16_t sent_len;
len = sys_rand32_get() % ipsum_len;
ptr = net_buf_add(buf, 0);
memcpy(ptr, lorem_ipsum, len);
ptr = net_buf_add(buf, len);
ptr = net_buf_add(buf, 1); /* add \0 */
*ptr = '\0';
sent_len = buf->len;
appdatalen = 0;
if (net_send(buf) < 0) {
PRINT("%s: sending %d bytes failed\n",
__func__, len);
ip_buf_unref(buf);
} else {
appdatalen = sent_len - ip_buf_reserve(buf);
PRINT("%d: %s: sent %d bytes\n", sent++,
__func__, appdatalen);
}
}
fiber_wakeup(receiver_id);
fiber_sleep(SLEEPTICKS);
if (sent != received) {
failure = true;
}
if (count && (count < sent)) {
break;
}
}
if (failure) {
PRINT("ERROR TEST FAILED\n");
} else {
PRINT("TEST PASSED\n");
}
}
void main(void)
{
/* Pretend to be ethernet with 6 byte mac */
uint8_t mac[] = { 0x0a, 0xbe, 0xef, 0x15, 0xf0, 0x0d };
PRINT("%s: run network loopback test\n", __func__);
sys_rand32_init();
net_init();
net_driver_loopback_init();
any_addr.in6_addr = in6addr_any;
any_addr.family = AF_INET6;
loopback_addr.in6_addr = in6addr_loopback;
loopback_addr.family = AF_INET6;
net_set_mac(mac, sizeof(mac));
receiver_id = task_fiber_start(&fiberReceiverStack[0], STACKSIZE,
(nano_fiber_entry_t)fiber_receiver,
0, 0, 7, 0);
sender_id = task_fiber_start(&fiberSenderStack[0], STACKSIZE,
(nano_fiber_entry_t)fiber_sender,
0, 0, 7, 0);
}