| /* 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); |
| } |