blob: dbffcd74b3e59eb3942c847c4272b50c0dd88995 [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);
}