net/yaip: revert merge

Follow up to TSC decission for further discussion in the networking
WIG.

Change-Id: I148b484dfe308661573e47ed3e60cceed673bddf
Signed-off-by: Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
This commit is contained in:
Inaky Perez-Gonzalez 2016-07-21 16:49:17 -07:00
commit 3e63a74514
63 changed files with 0 additions and 7267 deletions

View file

@ -1,81 +0,0 @@
# Kconfig - SLIP driver configuration options
#
# Copyright (c) 2016 Intel Corporation
#
# 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.
#
# 3) Neither the name of Intel Corporation nor the names of its contributors
# may be used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
#
#
# SLIP options
#
menuconfig SLIP
bool
prompt "SLIP driver"
depends on NET_SLIP
select UART_PIPE
select UART_INTERRUPT_DRIVEN
if SLIP
config SLIP_DRV_NAME
string "SLIP Driver name"
default "slip"
help
This option sets the driver name
config SLIP_MTU
int "SLIP MTU"
default 1500
range 80 1500
help
This option sets the MTU for the SLIP connection.
The value is only used when fragmenting the network
data into net_buf's. The actual SLIP connection
does not use this value.
config SLIP_DEBUG
bool "SLIP driver debug"
default n
help
This option enables debug support for SLIP driver.
config SLIP_STATISTICS
bool "SLIP network connection statistics"
default n
help
This option enables statistics support for SLIP driver.
config SLIP_TAP
bool "Use TAP interface to host"
default n
select NET_L2_ETHERNET
help
By default TUN is used. In TAP the Ethernet frames
are transferred over SLIP.
endif

View file

@ -1,3 +0,0 @@
subdir-ccflags-y +=-I${srctree}/net/yaip
obj-$(CONFIG_SLIP) = slip.o

View file

@ -1,405 +0,0 @@
/* slip.c - SLIP driver using uart_pipe. This is meant for
* network connectivity between host and qemu. The host will
* need to run tunslip process.
*/
/*
* Copyright (c) 2016 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.
*/
#if defined(CONFIG_SLIP_DEBUG)
#define SYS_LOG_DOMAIN "slip"
#define SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
#include <misc/sys_log.h>
#include <stdio.h>
#endif
#include <nanokernel.h>
#include <stdbool.h>
#include <errno.h>
#include <stddef.h>
#include <misc/util.h>
#include <net/buf.h>
#include <net/nbuf.h>
#include <net/net_if.h>
#include <net/arp.h>
#include <net/net_core.h>
#include <console/uart_pipe.h>
#define SLIP_END 0300
#define SLIP_ESC 0333
#define SLIP_ESC_END 0334
#define SLIP_ESC_ESC 0335
enum slip_state {
STATE_MULTI_PACKETS,
STATE_GARBAGE,
STATE_OK,
STATE_ESC,
};
struct slip_context {
uint8_t buf[1]; /* SLIP data is read into this buf */
struct net_buf *rx; /* and then placed into this net_buf */
struct net_buf *last; /* Pointer to last fragment in the list */
uint8_t *ptr; /* Where in net_buf to add data */
uint8_t state;
uint16_t ll_reserve; /* Reserve any space for link layer headers */
uint8_t mac_addr[6];
struct net_linkaddr ll_addr;
#if defined(CONFIG_SLIP_STATISTICS)
#define SLIP_STATS(statement)
#else
uint16_t garbage;
uint16_t multi_packets;
uint16_t overflows;
uint16_t ip_drop;
#define SLIP_STATS(statement) statement
#endif
};
#if defined(CONFIG_SLIP_DEBUG)
static void hexdump(const char *str, const uint8_t *packet, size_t length)
{
int n = 0;
if (!length) {
SYS_LOG_DBG("%s zero-length packet", str);
return;
}
while (length--) {
if (n % 16 == 0) {
printf("%s %08X ", str, n);
}
printf("%02X ", *packet++);
n++;
if (n % 8 == 0) {
if (n % 16 == 0) {
printf("\n");
} else {
printf(" ");
}
}
}
if (n % 16) {
printf("\n");
}
}
#else
#define hexdump(str, packet, length)
#endif
static inline void slip_writeb(unsigned char c)
{
uint8_t buf[1] = { c };
uart_pipe_send(&buf[0], 1);
}
static int slip_send(struct net_if *iface, struct net_buf *buf)
{
struct slip_context *slip = iface->dev->driver_data;
uint16_t i;
uint8_t *ptr;
uint8_t c;
if (!buf->frags) {
/* No data? */
return -ENODATA;
}
slip_writeb(SLIP_END);
while (buf->frags) {
struct net_buf *frag = buf->frags;
#if defined(CONFIG_SLIP_DEBUG)
int frag_count = 0;
#endif
ptr = frag->data - slip->ll_reserve;
for (i = 0; i < frag->len + slip->ll_reserve; ++i) {
c = *ptr++;
if (c == SLIP_END) {
slip_writeb(SLIP_ESC);
c = SLIP_ESC_END;
} else if (c == SLIP_ESC) {
slip_writeb(SLIP_ESC);
c = SLIP_ESC_ESC;
}
slip_writeb(c);
}
#if defined(CONFIG_SLIP_DEBUG)
SYS_LOG_DBG("[%p] sent data %d bytes", slip,
frag->len + slip->ll_reserve);
if (frag->len + slip->ll_reserve) {
char msg[7 + 1];
snprintf(msg, sizeof(msg), "slip %d", frag_count++);
msg[7] = '\0';
hexdump(msg, frag->data - slip->ll_reserve,
frag->len + slip->ll_reserve);
}
#endif
net_buf_frag_del(buf, frag);
net_buf_unref(frag);
}
net_buf_unref(buf);
slip_writeb(SLIP_END);
return 0;
}
static struct net_buf *slip_poll_handler(struct slip_context *slip)
{
if (slip->last && slip->last->len) {
if (slip->state == STATE_MULTI_PACKETS) {
/* Assume no bytes where lost */
slip->state = STATE_OK;
}
return slip->rx;
}
return NULL;
}
static void process_msg(struct slip_context *slip)
{
struct net_buf *buf;
buf = slip_poll_handler(slip);
if (!buf) {
return;
}
if (buf->frags) {
if (net_recv_data(net_if_get_by_link_addr(&slip->ll_addr),
buf) < 0) {
net_nbuf_unref(buf);
}
slip->rx = slip->last = NULL;
}
}
static inline int slip_input_byte(struct slip_context *slip,
unsigned char c)
{
switch (slip->state) {
case STATE_GARBAGE:
if (c == SLIP_END) {
slip->state = STATE_OK;
}
return 0;
case STATE_MULTI_PACKETS:
return 0;
case STATE_ESC:
if (c == SLIP_ESC_END) {
c = SLIP_END;
} else if (c == SLIP_ESC_ESC) {
c = SLIP_ESC;
} else {
slip->state = STATE_GARBAGE;
SLIP_STATS(slip->garbage++);
return 0;
}
slip->state = STATE_OK;
break;
case STATE_OK:
if (c == SLIP_ESC) {
slip->state = STATE_ESC;
return 0;
} else if (c == SLIP_END) {
if (slip->last->len) {
slip->state = STATE_MULTI_PACKETS;
SLIP_STATS(slip->multi_packets++);
return 1;
}
return 0;
}
break;
}
if (!slip->rx) {
slip->rx = net_nbuf_get_reserve_rx(0);
if (!slip->rx) {
return 0;
}
slip->last = net_nbuf_get_reserve_data(slip->ll_reserve);
if (!slip->last) {
net_nbuf_unref(slip->rx);
slip->rx = NULL;
return 0;
}
net_buf_frag_add(slip->rx, slip->last);
net_nbuf_ll_reserve(slip->rx) = slip->ll_reserve;
slip->ptr = net_nbuf_ip_data(slip->rx) - slip->ll_reserve;
}
if (!net_buf_tailroom(slip->last)) {
/* We need to allocate a new fragment */
struct net_buf *frag;
frag = net_nbuf_get_reserve_data(slip->ll_reserve);
if (!frag) {
SYS_LOG_ERR("[%p] cannot allocate data fragment",
slip);
net_nbuf_unref(frag);
net_nbuf_unref(slip->rx);
slip->rx = NULL;
slip->last = NULL;
return 0;
}
net_buf_frag_insert(slip->last, frag);
slip->last = frag;
slip->ptr = slip->last->data - slip->ll_reserve;
}
/* The net_buf_add_u8() cannot add data to ll header so we need
* a way to do it.
*/
if (slip->ptr < slip->last->data) {
*slip->ptr = c;
} else {
slip->ptr = net_buf_add_u8(slip->last, c);
}
slip->ptr++;
return 0;
}
static uint8_t *recv_cb(uint8_t *buf, size_t *off)
{
struct slip_context *slip =
CONTAINER_OF(buf, struct slip_context, buf);
int i;
for (i = 0; i < *off; i++) {
if (slip_input_byte(slip, buf[i])) {
#if defined(CONFIG_SLIP_DEBUG)
struct net_buf *frag = slip->rx->frags;
int count = 0;
int bytes = net_buf_frags_len(slip->rx->frags);
while (bytes && frag) {
char msg[7 + 1];
snprintf(msg, sizeof(msg), "slip %d", count);
msg[7] = '\0';
hexdump(msg, frag->data - slip->ll_reserve,
frag->len + slip->ll_reserve);
frag = frag->frags;
count++;
}
SYS_LOG_DBG("[%p] received data %d bytes", slip,
bytes + count * slip->ll_reserve);
#endif
process_msg(slip);
break;
}
}
*off = 0;
return buf;
}
static int slip_init(struct device *dev)
{
struct slip_context *slip = dev->driver_data;
SYS_LOG_DBG("[%p] dev %p", slip, dev);
dev->driver_api = NULL;
slip->state = STATE_OK;
slip->rx = NULL;
#if defined(CONFIG_SLIP_TAP)
slip->ll_reserve = sizeof(struct net_eth_hdr);
#else
slip->ll_reserve = 0;
#endif
NET_DBG("%sll reserve %d",
#if defined(CONFIG_SLIP_TAP) && defined(CONFIG_NET_IPV4)
"ARP enabled, ",
#else
"",
#endif
slip->ll_reserve);
uart_pipe_register(slip->buf, sizeof(slip->buf), recv_cb);
return 0;
}
static inline struct net_linkaddr *slip_get_mac(struct device *dev)
{
struct slip_context *slip = dev->driver_data;
if (slip->mac_addr[0] == 0x00) {
/* 10-00-00-00-00 to 10-00-00-00-FF Documentation RFC7042 */
slip->mac_addr[0] = 0x10;
slip->mac_addr[1] = 0x00;
slip->mac_addr[2] = 0x00;
slip->mac_addr[3] = 0x00;
slip->mac_addr[4] = 0x00;
slip->mac_addr[5] = sys_rand32_get();
}
slip->ll_addr.addr = slip->mac_addr;
slip->ll_addr.len = sizeof(slip->mac_addr);
return &slip->ll_addr;
}
static void slip_iface_init(struct net_if *iface)
{
struct net_linkaddr *ll_addr = slip_get_mac(net_if_get_device(iface));
net_if_set_link_addr(iface, ll_addr->addr, ll_addr->len);
}
static struct net_if_api slip_if_api = {
.init = slip_iface_init,
.send = slip_send,
};
static struct slip_context slip_context_data;
#if defined(CONFIG_SLIP_TAP) && defined(CONFIG_NET_L2_ETHERNET)
#define _SLIP_L2_LAYER ETHERNET_L2
#else
#define _SLIP_L2_LAYER DUMMY_L2
#endif
NET_DEVICE_INIT(slip, CONFIG_SLIP_DRV_NAME, slip_init, &slip_context_data,
NULL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &slip_if_api,
_SLIP_L2_LAYER, 127);

View file

@ -274,16 +274,6 @@ SECTION_PROLOGUE (_k_task_list, (OPTIONAL),)
__bss_end = ALIGN(4); __bss_end = ALIGN(4);
} GROUP_LINK_IN(RAMABLE_REGION) } GROUP_LINK_IN(RAMABLE_REGION)
#ifdef CONFIG_NET_YAIP
SECTION_PROLOGUE(net_if, (OPTIONAL),)
{
__net_if_start = .;
*(".net_if.*")
KEEP(*(SORT_BY_NAME(".net_if*")))
__net_if_end = .;
} GROUP_LINK_IN(RAMABLE_REGION)
#endif
SECTION_PROLOGUE(_NOINIT_SECTION_NAME,(NOLOAD),) { SECTION_PROLOGUE(_NOINIT_SECTION_NAME,(NOLOAD),) {
/* /*
* This section is used for non-initialized objects that * This section is used for non-initialized objects that

View file

@ -229,16 +229,6 @@ SECTIONS
DEVICE_INIT_SECTIONS() DEVICE_INIT_SECTIONS()
} GROUP_LINK_IN(RAMABLE_REGION) } GROUP_LINK_IN(RAMABLE_REGION)
#ifdef CONFIG_NET_YAIP
SECTION_PROLOGUE(net_if, (OPTIONAL),)
{
__net_if_start = .;
*(".net_if.*")
KEEP(*(SORT_BY_NAME(".net_if*")))
__net_if_end = .;
} GROUP_LINK_IN(RAMABLE_REGION)
#endif
SECTION_PROLOGUE (_k_task_list, (OPTIONAL),) SECTION_PROLOGUE (_k_task_list, (OPTIONAL),)
{ {
_k_task_list_start = .; _k_task_list_start = .;

View file

@ -204,16 +204,6 @@ SECTIONS
KEXEC_PGALIGN_PAD(MMU_PAGE_SIZE) KEXEC_PGALIGN_PAD(MMU_PAGE_SIZE)
} GROUP_LINK_IN(RAM) } GROUP_LINK_IN(RAM)
#ifdef CONFIG_NET_YAIP
SECTION_PROLOGUE(net_if, (OPTIONAL),)
{
__net_if_start = .;
*(".net_if.*")
KEEP(*(SORT_BY_NAME(".net_if*")))
__net_if_end = .;
} GROUP_LINK_IN(RAM)
#endif
SECTION_PROLOGUE(_k_task_list, ALIGN(4), ALIGN(4)) SECTION_PROLOGUE(_k_task_list, ALIGN(4), ALIGN(4))
{ {
_k_task_list_start = .; _k_task_list_start = .;

View file

@ -20,131 +20,3 @@
* limitations under the License. * limitations under the License.
*/ */
#if defined(CONFIG_NET_YAIP)
#ifndef __NET_CONTEXT_H
#define __NET_CONTEXT_H
#include <nanokernel.h>
#include <net/net_ip.h>
#include <net/net_if.h>
#ifdef __cplusplus
extern "C" {
#endif
struct net_context {
/* Connection tuple identifies the connection */
struct net_tuple tuple;
/* Application receives data via this fifo */
struct nano_fifo rx_queue;
/* Network interface assigned to this context */
struct net_if *iface;
};
/**
* @brief Get network context.
*
* @details Network context is used to define the connection
* 5-tuple (protocol, remote address, remote port, source
* address and source port).
*
* @param ip_proto Protocol to use. Currently only UDP is supported.
* @param remote_addr Remote IPv6/IPv4 address.
* @param remote_port Remote UDP/TCP port.
* @param local_addr Local IPv6/IPv4 address. If the local address is
* set to be anyaddr (all zeros), the IP stack will use the link
* local address defined for the system.
* @param local_port Local UDP/TCP port. If the local port is 0,
* then a random port will be allocated.
*
* @return Network context if successful, NULL otherwise.
*/
struct net_context *net_context_get(enum ip_protocol ip_proto,
const struct net_addr *remote_addr,
uint16_t remote_port,
struct net_addr *local_addr,
uint16_t local_port);
/**
* @brief Release network context.
*
* @details Free the resources allocated for the context.
* All network listeners tied to this context are removed.
*
* @param context Network context.
*
*/
void net_context_put(struct net_context *context);
/**
* @brief Get network tuple for this context.
*
* @details This function returns the used connection tuple.
*
* @param context Network context.
*
* @return Network tuple if successful, NULL otherwise.
*/
static inline
struct net_tuple *net_context_get_tuple(struct net_context *context)
{
return &context->tuple;
}
/**
* @brief Get network queue for this context.
*
* @details This function returns the used network queue.
*
* @param context Network context.
*
* @return Context RX queue if successful, NULL otherwise.
*/
static inline
struct nano_fifo *net_context_get_queue(struct net_context *context)
{
return &context->rx_queue;
}
/**
* @brief Get network interface for this context.
*
* @details This function returns the used network interface.
*
* @param context Network context.
*
* @return Context network interface if context is bind to interface,
* NULL otherwise.
*/
static inline
struct net_if *net_context_get_iface(struct net_context *context)
{
return context->iface;
}
/**
* @brief Set network interface for this context.
*
* @details This function binds network interface to this context.
*
* @param context Network context.
* @param iface Network interface.
*/
static inline void net_context_set_iface(struct net_context *context,
struct net_if *iface)
{
context->iface = iface;
}
#ifdef __cplusplus
}
#endif
#endif /* __NET_CONTEXT_H */
#endif /* CONFIG_NET_YAIP */

View file

@ -14,8 +14,4 @@
* limitations under the License. * limitations under the License.
*/ */
#if defined(CONFIG_NET_YAIP)
#include <net/yaip/net_core.h>
#else
#include <net/uip/net_core.h> #include <net/uip/net_core.h>
#endif

View file

@ -16,6 +16,4 @@
#if defined(CONFIG_NET_UIP) #if defined(CONFIG_NET_UIP)
#include <net/uip/net_if.h> #include <net/uip/net_if.h>
#elif defined(CONFIG_NET_YAIP)
#include <net/yaip/net_if.h>
#endif #endif

View file

@ -14,8 +14,4 @@
* limitations under the License. * limitations under the License.
*/ */
#if defined(CONFIG_NET_YAIP)
#include <net/yaip/net_ip.h>
#else
#include <net/uip/net_ip.h> #include <net/uip/net_ip.h>
#endif

View file

@ -13,7 +13,3 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#ifdef CONFIG_NET_YAIP
#include <net/yaip/net_l2.h>
#endif

View file

@ -14,8 +14,4 @@
* limitations under the License. * limitations under the License.
*/ */
#if defined(CONFIG_NET_YAIP)
#include <net/yaip/net_socket.h>
#else
#include <net/uip/net_socket.h> #include <net/uip/net_socket.h>
#endif

View file

@ -1,156 +0,0 @@
/** @file
* @brief Network core definitions
*
* Definitions for networking support.
*/
/*
* 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.
*/
#ifndef __NET_CORE_H
#define __NET_CORE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Network subsystem logging helpers */
#if defined(CONFIG_NET_LOG)
#if !defined(SYS_LOG_DOMAIN)
#define SYS_LOG_DOMAIN "net"
#endif /* !SYS_LOG_DOMAIN */
#if NET_DEBUG > 0
#undef SYS_LOG_LEVEL
#define SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
#endif /* NET_DEBUG */
#define NET_DBG(fmt, ...) SYS_LOG_DBG("(%p): " fmt, sys_thread_self_get(), \
##__VA_ARGS__)
#define NET_ERR(fmt, ...) SYS_LOG_ERR(fmt, ##__VA_ARGS__)
#define NET_WARN(fmt, ...) SYS_LOG_WRN(fmt, ##__VA_ARGS__)
#define NET_INFO(fmt, ...) SYS_LOG_INF(fmt, ##__VA_ARGS__)
#define NET_ASSERT(cond) do { \
if (!(cond)) { \
NET_ERR("{assert: '" #cond "' failed}"); \
} } while (0)
#define NET_ASSERT_INFO(cond, fmt, ...) do { \
if (!(cond)) { \
NET_ERR("{assert: '" #cond "' failed} " fmt, \
##__VA_ARGS__); \
} } while (0)
#else /* CONFIG_NET_LOG */
#define NET_DBG(...)
#define NET_ERR(...)
#define NET_INFO(...)
#define NET_WARN(...)
#define NET_ASSERT(...)
#define NET_ASSERT_INFO(...)
#endif /* CONFIG_NET_LOG */
#include <nanokernel.h>
struct net_buf;
struct net_context;
struct net_if;
#include <misc/sys_log.h>
#include <string.h>
enum net_verdict {
NET_OK, /** Packet has been taken care of */
NET_CONTINUE, /** Packet has not been touched,
other part should decide about its fate */
NET_DROP, /** Packet must be dropped */
};
/* Called by lower network stack when a network packet has been received */
int net_recv_data(struct net_if *iface, struct net_buf *buf);
/**
* @brief Send data to network.
*
* @details Send data to network. This should not be used normally by
* applications as it requires that the buffer and fragments are properly
* constructed.
*
* @param buf Network buffer.
*
* @return 0 if ok, <0 if error.
*/
int net_send_data(struct net_buf *buf);
/** @cond ignore */
#if defined(CONFIG_INIT_STACKS) && defined(CONFIG_PRINTK)
#include <offsets.h>
#include <misc/printk.h>
static inline void net_analyze_stack(const char *name,
unsigned char *stack,
size_t size)
{
unsigned i, stack_offset, pcnt, unused = 0;
/* The TCS is always placed on a 4-byte aligned boundary - if
* the stack beginning doesn't match that there will be some
* unused bytes in the beginning.
*/
stack_offset = __tTCS_SIZEOF + ((4 - ((unsigned)stack % 4)) % 4);
/* TODO
* Currently all supported platforms have stack growth down and there is no
* Kconfig option to configure it so this always build "else" branch.
* When support for platform with stack direction up (or configurable direction)
* is added this check should be confirmed that correct Kconfig option is used.
*/
#if defined(CONFIG_STACK_GROWS_UP)
for (i = size - 1; i >= stack_offset; i--) {
if ((unsigned char)stack[i] == 0xaa) {
unused++;
} else {
break;
}
}
#else
for (i = stack_offset; i < size; i++) {
if ((unsigned char)stack[i] == 0xaa) {
unused++;
} else {
break;
}
}
#endif
/* Calculate the real size reserved for the stack */
size -= stack_offset;
pcnt = ((size - unused) * 100) / size;
printk("net (%p): %s stack real size %u "
"unused %u usage %u/%u (%u %%)\n",
sys_thread_self_get(), name,
size + stack_offset, unused, size - unused, size, pcnt);
}
#else
#define net_analyze_stack(...)
#endif
/* @endcond */
#ifdef __cplusplus
}
#endif
#endif /* __NET_CORE_H */

View file

@ -1,437 +0,0 @@
/*
* Copyright (c) 2016 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.
*/
/**
* @file
* @brief Public API for network interface
*/
#ifndef __NET_IF_H__
#define __NET_IF_H__
#include <device.h>
#include <net/net_core.h>
#include <net/buf.h>
#include <net/net_linkaddr.h>
#include <net/net_ip.h>
#include <net/net_l2.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Network Interface unicast IP addresses
*
* Stores the unicast IP addresses assigned to this network interface.
*
*/
struct net_if_addr {
/** Is this IP address used or not */
bool is_used;
/** IP address */
struct net_addr address;
/** How the IP address was set */
enum net_addr_type addr_type;
/** What is the current state of the address */
enum net_addr_state addr_state;
/** Is the IP address valid forever */
bool is_infinite;
/** Timer that triggers renewal */
struct nano_timer lifetime;
#if defined(CONFIG_NET_IPV6)
/** Duplicate address detection (DAD) timer */
struct nano_timer dad_timer;
/** How many times we have done DAD */
uint8_t dad_count;
#endif /* CONFIG_NET_IPV6 */
};
/**
* @brief Network Interface multicast IP addresses
*
* Stores the multicast IP addresses assigned to this network interface.
*
*/
struct net_if_mcast_addr {
/** Is this multicast IP address used or not */
bool is_used;
/** IP address */
struct net_addr address;
};
#if defined(CONFIG_NET_IPV6)
/**
* @brief Network Interface IPv6 prefixes
*
* Stores the multicast IP addresses assigned to this network interface.
*
*/
struct net_if_ipv6_prefix {
/** Is this prefix used or not */
bool is_used;
/** IPv6 prefix */
struct in6_addr prefix;
/** Prefix length */
uint8_t len;
/** Is the IP prefix valid forever */
bool is_infinite;
/** Prefix lifetime */
struct nano_timer lifetime;
};
#endif /* CONFIG_NET_IPV6 */
/**
* @brief Network Interface structure
*
* Used to handle a network interface on top of a device driver instance.
* There can be many net_if instance against the same device.
*
* Such interface is mainly to be used by the link layer, but is also tight
* to a network context: it then makes the relation with a network context
* and the network device.
*
* Because of the strong relationship between a device driver and such
* network interface, each net_if should be instanciated by
*/
struct net_if {
/** The actualy device driver instance the net_if is related to */
struct device *dev;
/** Interface's L2 layer */
const struct net_l2 const *l2;
/** The hardware link address */
struct net_linkaddr link_addr;
/** The hardware MTU */
uint16_t mtu;
/** Queue for outgoing packets from apps */
struct nano_fifo tx_queue;
/** Stack for the TX fiber tied to this interface */
#ifndef CONFIG_NET_TX_STACK_SIZE
#define CONFIG_NET_TX_STACK_SIZE 1024
#endif
char tx_fiber_stack[CONFIG_NET_TX_STACK_SIZE];
#if defined(CONFIG_NET_IPV6)
#define NET_IF_MAX_IPV6_ADDR CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT
#define NET_IF_MAX_IPV6_MADDR CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT
#define NET_IF_MAX_IPV6_PREFIX CONFIG_NET_IF_IPV6_PREFIX_COUNT
struct {
/** Unicast IP addresses */
struct net_if_addr unicast[NET_IF_MAX_IPV6_ADDR];
/** Multicast IP addresses */
struct net_if_mcast_addr mcast[NET_IF_MAX_IPV6_MADDR];
/** Prefixes */
struct net_if_ipv6_prefix prefix[NET_IF_MAX_IPV6_PREFIX];
} ipv6;
uint8_t hop_limit;
#endif /* CONFIG_NET_IPV6 */
#if defined(CONFIG_NET_IPV4)
#define NET_IF_MAX_IPV4_ADDR CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT
#define NET_IF_MAX_IPV4_MADDR CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT
struct {
/** Unicast IP addresses */
struct net_if_addr unicast[NET_IF_MAX_IPV4_ADDR];
/** Multicast IP addresses */
struct net_if_mcast_addr mcast[NET_IF_MAX_IPV4_MADDR];
/** Gateway */
struct in_addr gw;
/** Netmask */
struct in_addr netmask;
} ipv4;
#endif /* CONFIG_NET_IPV4 */
};
/**
* @brief Send a buffer through a net iface
* @param iface Pointer to a network interface structure
* @param buf Pointer on a net buffer to send
*/
static inline enum net_verdict net_if_send_data(struct net_if *iface,
struct net_buf *buf)
{
return iface->l2->send(iface, buf);
}
/**
* @brief Input a buffer through a net iface
* @param iface Pointer to a network interface structure
* @param buf Pointer on a net buffer to input
*/
static inline enum net_verdict net_if_recv_data(struct net_if *iface,
struct net_buf *buf)
{
return iface->l2->recv(iface, buf);
}
/**
* @brief Get an network interface's device
* @param iface Pointer to a network interface structure
* @return a pointer on the device driver instance
*/
static inline struct device *net_if_get_device(struct net_if *iface)
{
return iface->dev;
}
/**
* @brief Queue a packet into net if's TX queue
* @param iface Pointer to a network interface structure
* @param buf Pointer on a net buffer to queue
*/
static inline void net_if_queue_tx(struct net_if *iface, struct net_buf *buf)
{
nano_fifo_put(&iface->tx_queue, buf);
}
/**
* @brief Get an network interface's link address
* @param iface Pointer to a network interface structure
* @return a pointer on the network link address
*/
static inline struct net_linkaddr *net_if_get_link_addr(struct net_if *iface)
{
return &iface->link_addr;
}
/**
* @brief Set a network interfac's link address
* @param iface Pointer to a network interface structure
* @param addr a pointer on a uint8_t buffer representing the address
* @param len length of the address buffer
*/
static inline void net_if_set_link_addr(struct net_if *iface,
uint8_t *addr, uint8_t len)
{
iface->link_addr.addr = addr;
iface->link_addr.len = len;
}
/**
* @brief Get an network interface's MTU
* @param iface Pointer to a network interface structure
* @return the MTU
*/
static inline uint16_t net_if_get_mtu(struct net_if *iface)
{
return iface->mtu;
}
/**
* @brief Get an interface according to link layer address.
* @param ll_addr Link layer address.
* @return Network interface or NULL if not found.
*/
struct net_if *net_if_get_by_link_addr(struct net_linkaddr *ll_addr);
/**
* @brief Check if this IPv6 address belongs to one of the interfaces.
* @param addr IPv6 address
* @return Pointer to interface address, NULL if not found.
*/
struct net_if_addr *net_if_ipv6_addr_lookup(struct in6_addr *addr);
/**
* @brief Add a IPv6 address to an interface
* @param iface Network interface
* @param addr IPv6 address
* @param addr_type IPv6 address type
* @param vlifetime Validity time for this address
* @return Pointer to interface address, NULL if cannot be added
*/
struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
struct in6_addr *addr,
enum net_addr_type addr_type,
uint32_t vlifetime);
/**
* @brief Add a IPv6 multicast address to an interface
* @param iface Network interface
* @param addr IPv6 multicast address
* @return Pointer to interface multicast address, NULL if cannot be added
*/
struct net_if_mcast_addr *net_if_ipv6_maddr_add(struct net_if *iface,
struct in6_addr *addr);
/**
* @brief Check if this IPv6 multicast address belongs to one of the interfaces.
* @param addr IPv6 address
* @return Pointer to interface multicast address, NULL if not found.
*/
struct net_if_mcast_addr *net_if_ipv6_maddr_lookup(struct in6_addr *addr);
/**
* @brief Check if this IPv4 address belongs to one of the interfaces.
* @param addr IPv4 address
* @return Pointer to interface address, NULL if not found.
*/
struct net_if_addr *net_if_ipv4_addr_lookup(struct in_addr *addr);
/**
* @brief Add a IPv4 address to an interface
* @param iface Network interface
* @param addr IPv4 address
* @param addr_type IPv4 address type
* @param vlifetime Validity time for this address
* @return Pointer to interface address, NULL if cannot be added
*/
struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface,
struct in_addr *addr,
enum net_addr_type addr_type,
uint32_t vlifetime);
/**
* @brief Get IPv6 hop limit specified for a given interface
* @param iface Network interface
* @return Hop limit
*/
static inline uint8_t net_if_ipv6_get_hop_limit(struct net_if *iface)
{
#if defined(CONFIG_NET_IPV6)
return iface->hop_limit;
#else
return 0;
#endif
}
/**
* @brief Get a IPv6 source address that should be used when sending
* network data to destination.
* @param iface Interface that was used when packet was received.
* If the interface is not known, then NULL can be given.
* @param dst IPv6 destination address
* @return Pointer to IPv6 address to use, NULL if no IPv6 address
* could be found.
*/
struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *iface,
struct in6_addr *dst);
/**
* @brief Return IPv6 any address (all zeros, ::)
* @return IPv6 any address with all bits set to zero.
*/
struct in6_addr *net_if_ipv6_unspecified_addr(void);
/**
* @brief Return IPv4 broadcast address (all bits ones)
* @return IPv4 broadcast address with all bits set to one.
*/
const struct in_addr *net_if_ipv4_broadcast_addr(void);
/**
* @brief Get a IPv6 link local address in a given state.
* @param iface Interface to use. Must be a valid pointer to an interface.
* @param addr_state IPv6 address state (preferred, tentative, deprecated)
* @return Pointer to link local IPv6 address, NULL if no proper IPv6 address
* could be found.
*/
struct in6_addr *net_if_ipv6_get_ll(struct net_if *iface,
enum net_addr_state addr_state);
/**
* @brief Get the default network interface.
* @return Default interface or NULL if no interfaces are configured.
*/
struct net_if *net_if_get_default(void);
/**
* @brief Check if the given IPv4 address belongs to local subnet.
* @param iface Interface to use. Must be a valid pointer to an interface.
* @param addr IPv4 address
* @return True if address is part of local subnet, false otherwise.
*/
bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
struct in_addr *addr);
/**
* @brief Set IPv4 netmask for an interface.
* @param iface Interface to use.
* @param netmask IPv4 netmask
*/
static inline void net_if_set_netmask(struct net_if *iface,
struct in_addr *netmask)
{
#if defined(CONFIG_NET_IPV4)
net_ipaddr_copy(&iface->ipv4.netmask, netmask);
#endif
}
/**
* @brief Set IPv4 gateway for an interface.
* @param iface Interface to use.
* @param gw IPv4 address of an gateway
*/
static inline void net_if_set_gw(struct net_if *iface,
struct in_addr *gw)
{
#if defined(CONFIG_NET_IPV4)
net_ipaddr_copy(&iface->ipv4.gw, gw);
#endif
}
struct net_if_api {
void (*init)(struct net_if *iface);
int (*send)(struct net_if *iface, struct net_buf *buf);
};
#define NET_IF_GET_NAME(dev_name, sfx) (__net_if_##dev_name_##sfx)
#define NET_IF_GET(dev_name, sfx) (&NET_IF_GET_NAME(dev_name, sfx))
#define NET_IF_INIT(dev_name, sfx, _l2, _mtu) \
static struct net_if (NET_IF_GET_NAME(dev_name, sfx)) __used \
__attribute__((__section__(".net_if.data"))) = { \
.dev = &(__device_##dev_name), \
.l2 = &(NET_L2_GET_NAME(_l2)), \
.mtu = _mtu, \
}
/* Network device intialization macro */
#define NET_DEVICE_INIT(dev_name, drv_name, init_fn, \
data, cfg_info, prio, api, l2, mtu) \
DEVICE_AND_API_INIT(dev_name, drv_name, init_fn, data, \
cfg_info, NANOKERNEL, prio, api); \
NET_IF_INIT(dev_name, 0, l2, mtu)
#ifdef __cplusplus
}
#endif
#endif /* __NET_IF_H__ */

View file

@ -1,381 +0,0 @@
/** @file
* @brief IPv6 and IPv4 definitions
*
* Generic IPv6 and IPv4 address definitions.
*/
/*
* Copyright (c) 2016 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.
*/
#ifndef __NET_IP_H
#define __NET_IP_H
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <misc/byteorder.h>
#include <toolchain.h>
#ifdef __cplusplus
extern "C" {
#endif
/** Protocol families */
#define PF_UNSPEC 0 /* Unspecified. */
#define PF_INET 2 /* IP protocol family. */
#define PF_INET6 10 /* IP version 6. */
/** Address families. */
#define AF_UNSPEC PF_UNSPEC
#define AF_INET PF_INET
#define AF_INET6 PF_INET6
/** Protocol numbers from IANA */
enum ip_protocol {
IPPROTO_ICMP = 1,
IPPROTO_TCP = 6,
IPPROTO_UDP = 17,
IPPROTO_ICMPV6 = 58,
};
#define ntohs(x) sys_be16_to_cpu(x)
#define ntohl(x) sys_be32_to_cpu(x)
#define htons(x) sys_cpu_to_be16(x)
#define htonl(x) sys_cpu_to_be32(x)
/** IPv6 address structure */
struct in6_addr {
union {
uint8_t u6_addr8[16];
uint16_t u6_addr16[8]; /* In big endian */
uint32_t u6_addr32[4]; /* In big endian */
} in6_u;
#define s6_addr in6_u.u6_addr8
#define s6_addr16 in6_u.u6_addr16
#define s6_addr32 in6_u.u6_addr32
};
/** IPv4 address */
struct in_addr {
union {
uint8_t u4_addr8[4];
uint16_t u4_addr16[2]; /* In big endian */
uint32_t u4_addr32[1]; /* In big endian */
} in4_u;
#define s4_addr in4_u.u4_addr8
#define s4_addr16 in4_u.u4_addr16
#define s4_addr32 in4_u.u4_addr32
#define s_addr s4_addr32
};
typedef unsigned short int sa_family_t;
struct net_addr {
sa_family_t family;
union {
#if defined(CONFIG_NET_IPV6)
struct in6_addr in6_addr;
#endif
#if defined(CONFIG_NET_IPV4)
struct in_addr in_addr;
#endif
};
};
#define IN6ADDR_ANY_INIT { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0 } } }
#define IN6ADDR_LOOPBACK_INIT { { { 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 1 } } }
#define INET6_ADDRSTRLEN 46
#define INADDR_ANY 0
/** IPv6/IPv4 network connection tuple */
struct net_tuple {
/** IPv6/IPv4 remote address */
struct net_addr *remote_addr;
/** IPv6/IPv4 local address */
struct net_addr *local_addr;
/** UDP/TCP remote port */
uint16_t remote_port;
/** UDP/TCP local port */
uint16_t local_port;
/** IP protocol */
enum ip_protocol ip_proto;
};
/** How the network address is assigned to network interface */
enum net_addr_type {
NET_ADDR_ANY = 0,
NET_ADDR_AUTOCONF,
NET_ADDR_DHCP,
NET_ADDR_MANUAL,
};
#if NET_DEBUG > 0
static inline char *net_addr_type2str(enum net_addr_type type)
{
switch (type) {
case NET_ADDR_AUTOCONF:
return "AUTO";
case NET_ADDR_DHCP:
return "DHCP";
case NET_ADDR_MANUAL:
return "MANUAL";
case NET_ADDR_ANY:
default:
break;
}
return "<unknown>";
}
#else
static inline char *net_addr_type2str(enum net_addr_type type)
{
return NULL;
}
#endif
/** What is the current state of the network address */
enum net_addr_state {
NET_ADDR_ANY_STATE = -1,
NET_ADDR_TENTATIVE = 0,
NET_ADDR_PREFERRED,
NET_ADDR_DEPRECATED,
};
struct net_ipv6_hdr {
uint8_t vtc;
uint8_t tcflow;
uint16_t flow;
uint8_t len[2];
uint8_t nexthdr;
uint8_t hop_limit;
struct in6_addr src;
struct in6_addr dst;
} __packed;
struct net_ipv4_hdr {
uint8_t vhl;
uint8_t tos;
uint8_t len[2];
uint8_t id[2];
uint8_t offset[2];
uint8_t ttl;
uint8_t proto;
uint16_t chksum;
struct in_addr src;
struct in_addr dst;
} __packed;
struct net_icmp_hdr {
uint8_t type;
uint8_t code;
uint16_t chksum;
} __packed;
struct net_udp_hdr {
uint16_t src_port;
uint16_t dst_port;
uint16_t len;
uint16_t chksum;
} __packed;
#define NET_UDPH_LEN 8 /* Size of UDP header */
#define NET_TCPH_LEN 20 /* Size of TCP header */
#define NET_ICMPH_LEN 4 /* Size of ICMP header */
#define NET_IPV6H_LEN 40 /* Size of IPv6 header */
#define NET_ICMPV6H_LEN NET_ICMPH_LEN /* Size of ICMPv6 header */
#define NET_IPV6UDPH_LEN (NET_UDPH_LEN + NET_IPV6H_LEN) /* IPv6 + UDP */
#define NET_IPV6TCPH_LEN (NET_TCPH_LEN + NET_IPV6H_LEN) /* IPv6 + TCP */
#define NET_IPV6ICMPH_LEN (NET_IPV6H_LEN + NET_ICMPH_LEN) /* ICMPv6 + IPv6 */
#define NET_IPV6_FRAGH_LEN 8
#define NET_IPV4H_LEN 20 /* Size of IPv4 header */
#define NET_ICMPV4H_LEN NET_ICMPH_LEN /* Size of ICMPv4 header */
#define NET_IPV4UDPH_LEN (NET_UDPH_LEN + NET_IPV4H_LEN) /* IPv4 + UDP */
#define NET_IPV4TCPH_LEN (NET_TCPH_LEN + NET_IPV4H_LEN) /* IPv4 + TCP */
#define NET_IPV4ICMPH_LEN (NET_IPV4H_LEN + NET_ICMPH_LEN) /* ICMPv4 + IPv4 */
/** @brief Check if the IPv6 address is a loopback address (::1).
*
* @param addr IPv6 address
*
* @return True if address is a loopback address, False otherwise.
*/
static inline bool net_is_ipv6_addr_loopback(struct in6_addr *addr)
{
return addr->s6_addr32[0] == 0 &&
addr->s6_addr32[1] == 0 &&
addr->s6_addr32[2] == 0 &&
ntohl(addr->s6_addr32[3]) == 1;
}
/** @brief Check if the IPv6 address is a multicast address.
*
* @param addr IPv6 address
*
* @return True if address is multicast address, False otherwise.
*/
static inline bool net_is_ipv6_addr_mcast(struct in6_addr *addr)
{
return addr->s6_addr[0] == 0xFF;
}
extern struct net_if_addr *net_if_ipv6_addr_lookup(struct in6_addr *addr);
/** @brief Check if IPv6 address is found in one of the network interfaces.
*
* @param addr IPv6 address
*
* @return True if address was found, False otherwise.
*/
static inline bool net_is_my_ipv6_addr(struct in6_addr *addr)
{
return net_if_ipv6_addr_lookup(addr) != NULL;
}
extern struct net_if_mcast_addr *net_if_ipv6_maddr_lookup(struct in6_addr *addr);
/** @brief Check if IPv6 multicast address is found in one of the
* network interfaces.
*
* @param maddr Multicast IPv6 address
*
* @return True if address was found, False otherwise.
*/
static inline bool net_is_my_ipv6_maddr(struct in6_addr *maddr)
{
return net_if_ipv6_maddr_lookup(maddr) != NULL;
}
/** @brief Check if two IPv6 addresses are same when compared after prefix mask.
*
* @param addr1 First IPv6 address.
* @param addr2 Second IPv6 address.
* @param length Prefix length (max length is 128).
*
* @return True if addresses are the same, False otherwise.
*/
static inline bool net_is_ipv6_prefix(uint8_t *addr1, uint8_t *addr2,
uint8_t length)
{
uint8_t bits = 128 - length;
uint8_t bytes = bits / 8;
uint8_t remain = bits % 8;
if (length > 128) {
return false;
}
if (memcmp(addr1, addr2, 16 - bytes)) {
return false;
}
return ((addr1[16 - bytes] & ((8 - remain) << 8))
==
(addr2[16 - bytes] & ((8 - remain) << 8)));
}
extern struct net_if_addr *net_if_ipv4_addr_lookup(struct in_addr *addr);
/** @brief Check if the IPv4 address is assigned to any network interface
* in the system.
*
* @return True if IPv4 address is found in one of the network interfaces,
* False otherwise.
*/
static inline bool net_is_my_ipv4_addr(struct in_addr *addr)
{
return net_if_ipv4_addr_lookup(addr) != NULL;
}
/** @def net_ipaddr_copy
* @brief Copy an IPv4 or IPv6 address
*
* @param dest Destination IP address.
* @param src Source IP address.
*
* @return Destination address.
*/
#define net_ipaddr_copy(dest, src) (*(dest) = *(src))
/** @def net_ipv4_addr_cmp
* @brief Compare two IPv4 addresses
*
* @param addr1 Pointer to IPv4 address.
* @param addr2 Pointer to IPv4 address.
*
* @return True if the addresses are the same, false otherwise.
*/
#define net_ipv4_addr_cmp(addr1, addr2) \
((addr1)->s_addr[0] == (addr2)->s_addr[0])
/** @brief Check if the given IPv6 address is a link local address.
*
* @return True if it is, false otherwise.
*/
static inline bool net_is_ipv6_ll_addr(struct in6_addr *addr)
{
return ((addr->s6_addr[0]) == 0xFE) &&
((addr->s6_addr[1]) == 0x80);
}
struct in6_addr *net_if_ipv6_unspecified_addr(void);
/** @brief Return pointer to any (all bits zeros) IPv6 address.
*
* @return Any IPv6 address.
*/
static inline struct in6_addr *net_ipv6_unspecified_address(void)
{
return net_if_ipv6_unspecified_addr();
}
extern const struct in_addr *net_if_ipv4_broadcast_addr(void);
/** @brief Return pointer to broadcast (all bits ones) IPv4 address.
*
* @return Broadcast IPv4 address.
*/
static inline const struct in_addr *net_ipv4_broadcast_address(void)
{
return net_if_ipv4_broadcast_addr();
}
struct net_if;
extern bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
struct in_addr *addr);
/** @brief Check if the given address belongs to same subnet that
* has been configured for the interface.
*
* @return True if address is in same subnet, false otherwise.
*/
static inline bool net_ipv4_addr_mask_cmp(struct net_if *iface,
struct in_addr *addr)
{
return net_if_ipv4_addr_mask_cmp(iface, addr);
}
#ifdef __cplusplus
}
#endif
#endif /* __NET_IP_H */

View file

@ -1,67 +0,0 @@
/*
* Copyright (c) 2016 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.
*/
/**
* @file
* @brief Public API for network L2 interface
*/
#ifndef __NET_L2_H__
#define __NET_L2_H__
#include <net/buf.h>
#ifdef __cplusplus
extern "C" {
#endif
struct net_if;
struct net_l2 {
enum net_verdict (*recv)(struct net_if *iface, struct net_buf *buf);
enum net_verdict (*send)(struct net_if *iface, struct net_buf *buf);
};
#define NET_L2_GET_NAME(_name) (__net_l2_##_name)
#define NET_L2_DECLARE_PUBLIC(_name) \
extern const struct net_l2 const NET_L2_GET_NAME(_name)
extern struct net_l2 __net_l2_start[];
#ifdef CONFIG_NET_L2_DUMMY
#define DUMMY_L2 dummy
NET_L2_DECLARE_PUBLIC(DUMMY_L2);
#endif /* CONFIG_NET_L2_DUMMY */
#ifdef CONFIG_NET_L2_ETHERNET
#define ETHERNET_L2 ethernet
NET_L2_DECLARE_PUBLIC(ETHERNET_L2);
#endif /* CONFIG_NET_L2_ETHERNET */
extern struct net_l2 __net_l2_end[];
#define NET_L2_INIT(_name, _recv_fn, _send_fn) \
const struct net_l2 const (NET_L2_GET_NAME(_name)) __used \
__attribute__((__section__(".net_l2.init"))) = { \
.recv = (_recv_fn), \
.send = (_send_fn), \
}
#ifdef __cplusplus
}
#endif
#endif /* __NET_L2_H__ */

View file

@ -1,7 +1,3 @@
obj-$(CONFIG_BLUETOOTH) += bluetooth/ obj-$(CONFIG_BLUETOOTH) += bluetooth/
obj-$(CONFIG_NET_BUF) += buf.o obj-$(CONFIG_NET_BUF) += buf.o
ifeq ($(CONFIG_NET_YAIP),y)
obj-y += yaip/
else
obj-$(CONFIG_NETWORKING) += ip/ obj-$(CONFIG_NETWORKING) += ip/
endif

View file

@ -41,10 +41,6 @@ config NET_UIP
bool "uIP" bool "uIP"
help help
Choose this if unsure. Choose this if unsure.
config NET_YAIP
bool "New IP stack [EXPERIMENTAL]"
help
New IP stack.
endchoice endchoice
if NETWORKING && NET_UIP if NETWORKING && NET_UIP
@ -590,10 +586,6 @@ endif
if NETWORKING if NETWORKING
if NET_YAIP
source "net/yaip/Kconfig"
endif
source "net/ip/Kconfig.debug" source "net/ip/Kconfig.debug"
endif endif

View file

@ -16,17 +16,6 @@
# limitations under the License. # limitations under the License.
# #
if NET_YAIP
menuconfig NET_LOG
bool "Enable network stack logging"
select STDOUT_CONSOLE
select SYS_LOG
default n
help
Enable logging in various parts of the network stack.
endif
if !NET_YAIP
menuconfig NETWORKING_WITH_LOGGING menuconfig NETWORKING_WITH_LOGGING
bool "Enable network stack logging" bool "Enable network stack logging"
select STDOUT_CONSOLE select STDOUT_CONSOLE
@ -48,31 +37,9 @@ config NETWORK_IP_STACK_DEBUG_ANNOTATE
config NETWORK_IP_STACK_DEBUG_FULL config NETWORK_IP_STACK_DEBUG_FULL
bool "Print both messages and annotations" bool "Print both messages and annotations"
endchoice endchoice
endif
if NETWORKING_WITH_LOGGING || NET_LOG if NETWORKING_WITH_LOGGING || NET_LOG
config NETWORK_IP_STACK_DEBUG_CORE
bool "Debug core IP stack"
depends on NET_YAIP
default n
help
Enables core network stack code part to output debug messages
config NETWORK_IP_STACK_DEBUG_UTILS
bool "Debug utility functions in IP stack"
depends on NET_YAIP
default n
help
Enables utility functions to output debug messages
config NETWORK_IP_STACK_DEBUG_IF
bool "Debug network interface code"
depends on NET_YAIP
default n
help
Enables network interface code part to output debug messages
config NETWORK_IP_STACK_DEBUG_CONTEXT config NETWORK_IP_STACK_DEBUG_CONTEXT
bool "Debug network context allocation" bool "Debug network context allocation"
default n default n

View file

@ -1,147 +0,0 @@
# Kconfig.yaip - Yet another IP stack config
#
# Copyright (c) 2016 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.
#
config NET_INIT_PRIO
int
default 10
help
Network initialization priority level. This number tells how
early in the boot the network stack is initialized.
config NET_IPV6
bool "Enable IPv6"
default y
help
Enable IPv6 support. This should be selected by default as there is
limited set of network bearers provided that support IPv4.
config NET_IF_UNICAST_IPV6_ADDR_COUNT
int "Max number of unicast IPv6 addresses per network interface"
depends on NET_IPV6
default 1
config NET_IF_MCAST_IPV6_ADDR_COUNT
int "Max number of multicast IPv6 addresses per network interface"
depends on NET_IPV6
default 1
config NET_IF_IPV6_PREFIX_COUNT
int "Max number of IPv6 prefixes per network interface"
depends on NET_IPV6
default 2
config NET_INITIAL_HOP_LIMIT
int "Initial hop limit for a connection"
depends on NET_IPV6
default 64
help
The value should be > 0
config NET_IPV4
bool "Enable IPv4"
default n
help
Enable IPv4 support. If this is enabled then the device is
able to send and receive IPv4 network packets.
config NET_IF_UNICAST_IPV4_ADDR_COUNT
int "Max number of unicast IPv4 addresses per network interface"
depends on NET_IPV4
default 1
config NET_IF_MCAST_IPV4_ADDR_COUNT
int "Max number of multicast IPv4 addresses per network interface"
depends on NET_IPV4
default 1
config NET_TX_STACK_SIZE
int "TX fiber stack size"
default 1024
help
Set the TX fiber stack size in bytes. The TX fiber is waiting
data from application. Each network interface will start one
TX fiber for sending network packets destined to it.
config NET_RX_STACK_SIZE
int "RX fiber stack size"
default 1024
help
Set the RX fiber stack size in bytes. The RX fiber is waiting
data from network. There is one RX fiber in the system.
config NET_NBUF_RX_COUNT
int "How many network receives can be pending at the same time"
default 2
help
Each RX buffer will occupy smallish amount of memory.
See include/net/nbuf.h and the sizeof(struct nbuf)
config NET_NBUF_TX_COUNT
int "How many network sends can be pending at the same time"
default 2
help
Each TX buffer will occupy smallish amount of memory.
See include/net/nbuf.h and the sizeof(struct nbuf)
config NET_NBUF_DATA_COUNT
int "How many network data buffers are allocated"
default 16
help
Each data buffer will occupy CONFIG_NBUF_DATA_SIZE + smallish
header (sizeof(struct net_buf)) amount of data.
config NET_NBUF_DATA_SIZE
int "Size of each network data fragment"
default 128
help
This value tells what is the size of the data fragment that is
received from the network.
Example: For IEEE 802.15.4, the network packet is 127 bytes long,
which leaves in worst case 81 bytes for user data (MTU).
In order to be able to receive at least full IPv6 packet which
has a size of 1280 bytes, the one should allocate 16 fragments here.
config CONFIG_NET_MAX_CONTEXTS
int "Number of network contexts to allocate"
default 6
help
Each network context is used to describe a network 5-tuple that
is used when listening or sending network traffic.
config NET_SLIP
bool "Use SLIP connectivity with Qemu"
default n
select SLIP
select UART_PIPE
select UART_INTERRUPT_DRIVEN
help
The SLIP support is only used when the application is
run inside Qemu and the network peer is run in your
host. The host needs to have tunslip running in order
to receive and send network packets via the SLIP driver.
The SLIP driver Kconfig options can be tweaked in drivers
section.
config NET_STATISTICS
bool "Print network statistics"
default n
help
Print network send/receive statistics to console.
This takes memory so say 'n' if unsure.
source "net/yaip/l2/Kconfig"

View file

@ -1,11 +0,0 @@
ccflags-y += -I${srctree}/net/ip
obj-y = net_core.o \
net_if.o \
net_context.o \
nbuf.o \
utils.o
obj-y += l2/
obj-$(CONFIG_NET_IPV6) += icmpv6.o
obj-$(CONFIG_NET_IPV4) += icmpv4.o

View file

@ -1,87 +0,0 @@
/** @file
* @brief ICMPv4 related functions
*/
/*
* Copyright (c) 2016 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.
*/
#ifdef CONFIG_NETWORK_IP_STACK_DEBUG_ICMPV4
#define SYS_LOG_DOMAIN "net/icmpv4"
#define NET_DEBUG 1
#endif
#include <errno.h>
#include <misc/slist.h>
#include <net/net_core.h>
#include <net/nbuf.h>
#include <net/net_if.h>
#include <net/net_stats.h>
#include "net_private.h"
#include "icmpv4.h"
static inline enum net_verdict handle_echo_request(struct net_buf *buf)
{
/* Note that we send the same data buffers back and just swap
* the addresses etc.
*/
struct in_addr addr;
#if NET_DEBUG > 0
char out[sizeof("xxx.xxx.xxx.xxx")];
snprintf(out, sizeof(out),
net_sprint_ipv4_addr(&NET_IPV4_BUF(buf)->dst));
NET_DBG("Received Echo Request from %s to %s",
net_sprint_ipv4_addr(&NET_IPV4_BUF(buf)->src), out);
#endif /* NET_DEBUG > 0 */
net_ipaddr_copy(&addr, &NET_IPV4_BUF(buf)->src);
net_ipaddr_copy(&NET_IPV4_BUF(buf)->src,
&NET_IPV4_BUF(buf)->dst);
net_ipaddr_copy(&NET_IPV4_BUF(buf)->dst, &addr);
NET_ICMP_BUF(buf)->type = NET_ICMPV4_ECHO_REPLY;
NET_ICMP_BUF(buf)->code = 0;
NET_ICMP_BUF(buf)->chksum = 0;
NET_ICMP_BUF(buf)->chksum = ~net_calc_chksum_icmpv4(buf);
#if NET_DEBUG > 0
snprintf(out, sizeof(out),
net_sprint_ipv4_addr(&NET_IPV4_BUF(buf)->dst));
NET_DBG("Sending Echo Reply from %s to %s",
net_sprint_ipv4_addr(&NET_IPV4_BUF(buf)->src), out);
#endif /* NET_DEBUG > 0 */
if (net_send_data(buf) < 0) {
NET_STATS(++net_stats.icmp.drop);
return NET_DROP;
}
NET_STATS(++net_stats.icmp.sent);
return NET_OK;
}
enum net_verdict net_icmpv4_input(struct net_buf *buf, uint16_t len,
uint8_t type, uint8_t code)
{
switch (type) {
case NET_ICMPV4_ECHO_REQUEST:
return handle_echo_request(buf);
}
return NET_DROP;
}

View file

@ -1,37 +0,0 @@
/** @file
@brief ICMPv4 handler
This is not to be included by the application.
*/
/*
* Copyright (c) 2016 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.
*/
#ifndef __ICMPV4_H
#define __ICMPV4_H
#include <stdint.h>
#include <net/net_ip.h>
#include <net/nbuf.h>
#define NET_ICMPV4_ECHO_REQUEST 8
#define NET_ICMPV4_ECHO_REPLY 0
enum net_verdict net_icmpv4_input(struct net_buf *buf, uint16_t len,
uint8_t type, uint8_t code);
#endif /* __ICMPV4_H */

View file

@ -1,136 +0,0 @@
/** @file
* @brief ICMPv6 related functions
*/
/*
* Copyright (c) 2016 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.
*/
#ifdef CONFIG_NETWORK_IP_STACK_DEBUG_ICMPV6
#define SYS_LOG_DOMAIN "net/icmpv6"
#define NET_DEBUG 1
#endif
#include <errno.h>
#include <misc/slist.h>
#include <net/net_core.h>
#include <net/nbuf.h>
#include <net/net_if.h>
#include <net/net_stats.h>
#include "net_private.h"
#include "icmpv6.h"
static sys_slist_t handlers;
void net_icmpv6_register_handler(struct net_icmpv6_handler *handler)
{
sys_slist_prepend(&handlers, &handler->node);
}
static enum net_verdict handle_echo_request(struct net_buf *buf)
{
/* Note that we send the same data buffers back and just swap
* the addresses etc.
*/
#if NET_DEBUG > 0
char out[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
snprintf(out, sizeof(out),
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->dst));
NET_DBG("Received Echo Request from %s to %s",
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->src), out);
#endif /* NET_DEBUG > 0 */
if (net_is_ipv6_addr_mcast(&NET_IPV6_BUF(buf)->dst)) {
net_ipaddr_copy(&NET_IPV6_BUF(buf)->dst,
&NET_IPV6_BUF(buf)->src);
net_ipaddr_copy(&NET_IPV6_BUF(buf)->src,
net_if_ipv6_select_src_addr(net_nbuf_iface(buf),
&NET_IPV6_BUF(buf)->dst));
} else {
struct in6_addr addr;
net_ipaddr_copy(&addr, &NET_IPV6_BUF(buf)->src);
net_ipaddr_copy(&NET_IPV6_BUF(buf)->src,
&NET_IPV6_BUF(buf)->dst);
net_ipaddr_copy(&NET_IPV6_BUF(buf)->dst, &addr);
}
NET_IPV6_BUF(buf)->hop_limit =
net_if_ipv6_get_hop_limit(net_nbuf_iface(buf));
NET_ICMP_BUF(buf)->type = NET_ICMPV6_ECHO_REPLY;
NET_ICMP_BUF(buf)->code = 0;
NET_ICMP_BUF(buf)->chksum = 0;
NET_ICMP_BUF(buf)->chksum = ~net_calc_chksum_icmpv6(buf);
#if NET_DEBUG > 0
snprintf(out, sizeof(out),
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->dst));
NET_DBG("Sending Echo Reply from %s to %s",
net_sprint_ipv6_addr(&NET_IPV6_BUF(buf)->src), out);
#endif /* NET_DEBUG > 0 */
if (net_send_data(buf) < 0) {
NET_STATS(++net_stats.icmp.drop);
return NET_DROP;
}
NET_STATS(++net_stats.icmp.sent);
return NET_OK;
}
enum net_verdict net_icmpv6_input(struct net_buf *buf, uint16_t len,
uint8_t type, uint8_t code)
{
sys_snode_t *node;
struct net_icmpv6_handler *cb;
SYS_SLIST_FOR_EACH_NODE(&handlers, node) {
cb = (struct net_icmpv6_handler *)node;
if (!cb) {
continue;
}
if (cb->type == type && (cb->code == code || cb->code == 0)) {
NET_STATS(++net_stats.icmp.recv);
return cb->handler(buf);
}
}
return NET_DROP;
}
static struct net_icmpv6_handler echo_request_handler = {
.type = NET_ICMPV6_ECHO_REQUEST,
.code = 0,
.handler = handle_echo_request,
};
void net_icmpv6_init(void)
{
static bool is_initialized;
if (is_initialized) {
return;
}
net_icmpv6_register_handler(&echo_request_handler);
is_initialized = true;
}

View file

@ -1,49 +0,0 @@
/** @file
@brief ICMPv6 handler
This is not to be included by the application.
*/
/*
* Copyright (c) 2016 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.
*/
#ifndef __ICMPV6_H
#define __ICMPV6_H
#include <misc/slist.h>
#include <stdint.h>
#include <net/net_ip.h>
#include <net/nbuf.h>
#define NET_ICMPV6_ECHO_REQUEST 128
#define NET_ICMPV6_ECHO_REPLY 129
typedef enum net_verdict (*icmpv6_callback_handler_t)(struct net_buf *buf);
struct net_icmpv6_handler {
sys_snode_t node;
uint8_t type;
uint8_t code;
icmpv6_callback_handler_t handler;
};
void net_icmpv6_register_handler(struct net_icmpv6_handler *handler);
enum net_verdict net_icmpv6_input(struct net_buf *buf, uint16_t len,
uint8_t type, uint8_t code);
void net_icmpv6_init(void);
#endif /* __ICMPV6_H */

View file

@ -1,46 +0,0 @@
#
# Copyright (c) 2016 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.
#
config NET_L2_DUMMY
bool "Enable dummy l2 layer"
default n
default y if !NET_L2_ETHERNET && NET_SLIP
help
Add a dummy L2 layer driver, usually in case you need SLIP in
TUN mode.
config NET_L2_ETHERNET
bool "Enable ethernet support"
default n
help
Add suport for Ethernet, enabling selecting relevant hardware drivers.
If NET_SLIP and SLIP_TAP are selected, NET_L2_ETHERNET will enable to
fully simulate ethernet through SLIP.
config NET_ARP
bool "Enable ARP"
default y
depends on NET_IPV4 && NET_L2_ETHERNET
help
Enable ARP support. This is necessary on hardware that requires it to
get IPv4 working (like Ethernet devices).
config NET_ARP_TABLE_SIZE
int "Number of entries in ARP table."
depends on NET_ARP
default 2
help
Each entry in the ARP table consumes 22 bytes of memory.

View file

@ -1,6 +0,0 @@
ccflags-y += -I${srctree}/net/yaip
obj-$(CONFIG_NET_L2_DUMMY) += dummy.o
obj-${CONFIG_NET_L2_ETHERNET} += ethernet.o
obj-${CONFIG_NET_ARP} += arp.o

View file

@ -1,455 +0,0 @@
/** @file
* @brief ARP related functions
*/
/*
* Copyright (c) 2016 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.
*/
#ifdef CONFIG_NETWORK_IP_STACK_DEBUG_IPV4_ARP
#define SYS_LOG_DOMAIN "net/arp"
#define NET_DEBUG 1
#endif
#include <errno.h>
#include <net/net_core.h>
#include <net/nbuf.h>
#include <net/net_if.h>
#include <net/net_stats.h>
#include <net/arp.h>
#include "net_private.h"
struct arp_entry {
uint32_t time; /* FIXME - implement timeout functionality */
struct net_if *iface;
struct net_buf *pending;
struct in_addr ip;
struct net_eth_addr eth;
};
static struct arp_entry arp_table[CONFIG_NET_ARP_TABLE_SIZE];
static const struct net_eth_addr broadcast_eth_addr = {
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
static inline struct arp_entry *find_entry(struct net_if *iface,
struct in_addr *dst,
struct arp_entry **free_entry,
struct arp_entry **non_pending)
{
int i;
NET_DBG("dst %s", net_sprint_ipv4_addr(dst));
for (i = 0; i < CONFIG_NET_ARP_TABLE_SIZE; i++) {
NET_DBG("[%d] iface %p dst %s pending %p", i, iface,
net_sprint_ipv4_addr(&arp_table[i].ip),
arp_table[i].pending);
if (arp_table[i].iface == iface &&
net_ipv4_addr_cmp(&arp_table[i].ip, dst)) {
/* Is there already pending operation for this
* IP address.
*/
if (arp_table[i].pending) {
NET_DBG("ARP already pending to %s",
net_sprint_ipv4_addr(dst));
*free_entry = NULL;
*non_pending = NULL;
return NULL;
}
return &arp_table[i];
}
/* We return also the first free entry */
if (!*free_entry && !arp_table[i].pending &&
!arp_table[i].iface) {
*free_entry = &arp_table[i];
}
/* And also first non pending entry */
if (!*non_pending && !arp_table[i].pending) {
*non_pending = &arp_table[i];
}
}
return NULL;
}
static inline struct in_addr *if_get_addr(struct net_if *iface)
{
int i;
for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
if (iface->ipv4.unicast[i].is_used &&
iface->ipv4.unicast[i].address.family == AF_INET &&
iface->ipv4.unicast[i].addr_state == NET_ADDR_PREFERRED) {
return &iface->ipv4.unicast[i].address.in_addr;
}
}
return NULL;
}
static inline struct net_buf *prepare_arp(struct net_if *iface,
struct arp_entry *entry,
struct net_buf *pending)
{
struct net_buf *buf, *frag;
struct net_arp_hdr *hdr;
struct in_addr *my_addr;
buf = net_nbuf_get_reserve_tx(0);
if (!buf) {
goto fail;
}
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr));
if (!frag) {
goto fail;
}
net_buf_frag_add(buf, frag);
net_nbuf_iface(buf) = iface;
net_nbuf_ll_reserve(buf) = sizeof(struct net_eth_hdr);
hdr = NET_ARP_BUF(buf);
entry->pending = net_buf_ref(pending);
entry->iface = net_nbuf_iface(buf);
net_ipaddr_copy(&entry->ip, &NET_IPV4_BUF(pending)->dst);
hdr->eth_hdr.type = htons(NET_ETH_PTYPE_ARP);
memset(&hdr->eth_hdr.dst.addr, 0xff, sizeof(struct net_eth_addr));
memcpy(&hdr->eth_hdr.src.addr,
net_if_get_link_addr(entry->iface)->addr,
sizeof(struct net_eth_addr));
hdr->hwtype = htons(NET_ARP_HTYPE_ETH);
hdr->protocol = htons(NET_ETH_PTYPE_IP);
hdr->hwlen = sizeof(struct net_eth_addr);
hdr->protolen = sizeof(struct in_addr);
hdr->opcode = htons(NET_ARP_REQUEST);
memset(&hdr->dst_hwaddr.addr, 0x00, sizeof(struct net_eth_addr));
/* Is the destination in local network */
if (!net_if_ipv4_addr_mask_cmp(iface, &NET_IPV4_BUF(pending)->dst)) {
net_ipaddr_copy(&hdr->dst_ipaddr, &iface->ipv4.gw);
} else {
net_ipaddr_copy(&hdr->dst_ipaddr, &NET_IPV4_BUF(pending)->dst);
}
memcpy(hdr->src_hwaddr.addr, hdr->eth_hdr.src.addr,
sizeof(struct net_eth_addr));
my_addr = if_get_addr(entry->iface);
if (my_addr) {
net_ipaddr_copy(&hdr->src_ipaddr, my_addr);
} else {
memset(&hdr->src_ipaddr, 0, sizeof(struct in_addr));
}
net_buf_add(frag, sizeof(struct net_arp_hdr));
return buf;
fail:
net_nbuf_unref(buf);
net_nbuf_unref(pending);
return NULL;
}
struct net_buf *net_arp_prepare(struct net_buf *buf)
{
struct net_buf *frag;
struct arp_entry *entry, *free_entry = NULL, *non_pending = NULL;
struct net_linkaddr *ll;
struct net_eth_hdr *hdr;
if (!buf || !buf->frags) {
return NULL;
}
/* If the destination address is already known, we do not need
* to send any ARP packet.
*/
if (net_nbuf_ll_reserve(buf) != sizeof(struct net_eth_hdr)) {
NET_DBG("Ethernet header missing from buf %p, len %d min %d",
buf, net_nbuf_ll_reserve(buf),
sizeof(struct net_eth_hdr));
return NULL;
}
hdr = (struct net_eth_hdr *)net_nbuf_ll(buf);
if (ntohs(hdr->type) == NET_ETH_PTYPE_ARP) {
NET_DBG("Buf %p is already an ARP msg", buf);
return buf;
}
if (net_ipv4_addr_cmp(&NET_IPV4_BUF(buf)->dst,
net_ipv4_broadcast_address())) {
/* Broadcast address */
memcpy(&hdr->dst.addr,
&broadcast_eth_addr.addr, sizeof(struct net_eth_addr));
return buf;
} else if (NET_IPV4_BUF(buf)->dst.s4_addr[0] == 224) {
/* Multicast address */
hdr->dst.addr[0] = 0x01;
hdr->dst.addr[1] = 0x00;
hdr->dst.addr[2] = 0x5e;
hdr->dst.addr[3] = NET_IPV4_BUF(buf)->dst.s4_addr[1];
hdr->dst.addr[4] = NET_IPV4_BUF(buf)->dst.s4_addr[2];
hdr->dst.addr[5] = NET_IPV4_BUF(buf)->dst.s4_addr[3];
return buf;
}
entry = find_entry(net_nbuf_iface(buf),
&NET_IPV4_BUF(buf)->dst,
&free_entry, &non_pending);
if (!entry) {
if (!free_entry) {
/* So all the slots are occupied, use the first
* that can be taken.
*/
if (!non_pending) {
/* We cannot send the packet, the ARP
* cache is full or there is already a
* pending query to this IP address,
* so this packet must be discarded.
*/
return NULL;
}
free_entry = non_pending;
}
return prepare_arp(net_nbuf_iface(buf), free_entry, buf);
}
ll = net_if_get_link_addr(entry->iface);
NET_DBG("ARP using ll %s for IP %s",
net_sprint_ll_addr(ll->addr, sizeof(struct net_eth_addr)),
net_sprint_ipv4_addr(&NET_IPV4_BUF(buf)->src));
frag = buf->frags;
while (frag) {
/* If there is no room for link layer header, then
* just send the packet as is.
*/
if (!net_buf_headroom(frag)) {
frag = frag->frags;
continue;
}
hdr = (struct net_eth_hdr *)(frag->data -
net_nbuf_ll_reserve(buf));
hdr->type = htons(NET_ETH_PTYPE_IP);
memcpy(&hdr->src.addr, ll->addr,
sizeof(struct net_eth_addr));
memcpy(&hdr->dst.addr, &entry->eth.addr,
sizeof(struct net_eth_addr));
frag = frag->frags;
}
return buf;
}
static inline void send_pending(struct net_if *iface, struct net_buf **buf)
{
struct net_buf *pending = *buf;
NET_DBG("dst %s pending %p",
net_sprint_ipv4_addr(&NET_IPV4_BUF(pending)->dst), pending);
*buf = NULL;
if (net_if_send_data(iface, pending) < 0) {
/* This is to unref the original ref */
net_nbuf_unref(pending);
}
/* The pending buf was referenced when
* it was added to cache so we need to
* unref it now when it is removed from
* the cache.
*/
net_nbuf_unref(pending);
}
static inline void arp_update(struct net_if *iface,
struct in_addr *src,
struct net_eth_addr *hwaddr)
{
int i;
NET_DBG("src %s", net_sprint_ipv4_addr(src));
for (i = 0; i < CONFIG_NET_ARP_TABLE_SIZE; i++) {
NET_DBG("[%d] iface %p dst %s pending %p", i, iface,
net_sprint_ipv4_addr(&arp_table[i].ip),
arp_table[i].pending);
if (arp_table[i].iface == iface &&
net_ipv4_addr_cmp(&arp_table[i].ip, src)) {
if (arp_table[i].pending) {
/* We only update the ARP cache if we were
* initiating a request.
*/
memcpy(&arp_table[i].eth, hwaddr,
sizeof(struct net_eth_addr));
send_pending(iface, &arp_table[i].pending);
}
return;
}
}
}
static inline struct net_buf *prepare_arp_reply(struct net_if *iface,
struct net_buf *req)
{
struct net_buf *buf, *frag;
struct net_arp_hdr *hdr, *query;
buf = net_nbuf_get_reserve_tx(0);
if (!buf) {
goto fail;
}
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr));
if (!frag) {
goto fail;
}
net_buf_frag_add(buf, frag);
net_nbuf_iface(buf) = iface;
net_nbuf_ll_reserve(buf) = sizeof(struct net_eth_hdr);
hdr = NET_ARP_BUF(buf);
query = NET_ARP_BUF(req);
hdr->eth_hdr.type = htons(NET_ETH_PTYPE_ARP);
memcpy(&hdr->eth_hdr.dst.addr, &query->eth_hdr.src.addr,
sizeof(struct net_eth_addr));
memcpy(&hdr->eth_hdr.src.addr, net_if_get_link_addr(iface)->addr,
sizeof(struct net_eth_addr));
hdr->hwtype = htons(NET_ARP_HTYPE_ETH);
hdr->protocol = htons(NET_ETH_PTYPE_IP);
hdr->hwlen = sizeof(struct net_eth_addr);
hdr->protolen = sizeof(struct in_addr);
hdr->opcode = htons(NET_ARP_REPLY);
memcpy(&hdr->dst_hwaddr.addr, &query->eth_hdr.src.addr,
sizeof(struct net_eth_addr));
memcpy(&hdr->src_hwaddr.addr, &hdr->eth_hdr.src.addr,
sizeof(struct net_eth_addr));
net_ipaddr_copy(&hdr->dst_ipaddr, &query->src_ipaddr);
net_ipaddr_copy(&hdr->src_ipaddr, &query->dst_ipaddr);
net_buf_add(frag, sizeof(struct net_arp_hdr));
return buf;
fail:
net_nbuf_unref(buf);
return NULL;
}
enum net_verdict net_arp_input(struct net_buf *buf)
{
struct net_arp_hdr *arp_hdr;
struct net_buf *reply;
if (net_buf_frags_len(buf) < (sizeof(struct net_arp_hdr) -
net_nbuf_ll_reserve(buf))) {
NET_DBG("Invalid ARP header (len %d, min %d bytes)",
net_buf_frags_len(buf),
sizeof(struct net_arp_hdr) - net_nbuf_ll_reserve(buf));
return NET_DROP;
}
arp_hdr = NET_ARP_BUF(buf);
switch (ntohs(arp_hdr->opcode)) {
case NET_ARP_REQUEST:
/* Someone wants to know our ll address */
if (!net_ipv4_addr_cmp(&arp_hdr->dst_ipaddr,
if_get_addr(net_nbuf_iface(buf)))) {
/* Not for us so drop the packet silently */
return NET_DROP;
}
#if NET_DEBUG > 0
do {
char out[sizeof("xxx.xxx.xxx.xxx")];
snprintf(out, sizeof(out),
net_sprint_ipv4_addr(&arp_hdr->src_ipaddr));
NET_DBG("ARP request from %s [%s] for %s",
out,
net_sprint_ll_addr(
(uint8_t *)&arp_hdr->src_hwaddr,
arp_hdr->hwlen),
net_sprint_ipv4_addr(&arp_hdr->dst_ipaddr));
} while (0);
#endif
/* Send reply */
reply = prepare_arp_reply(net_nbuf_iface(buf), buf);
if (reply) {
if (net_send_data(reply) < 0) {
net_nbuf_unref(reply);
}
}
break;
case NET_ARP_REPLY:
if (net_is_my_ipv4_addr(&arp_hdr->dst_ipaddr)) {
arp_update(net_nbuf_iface(buf), &arp_hdr->src_ipaddr,
&arp_hdr->src_hwaddr);
}
break;
}
return NET_DROP;
}
void net_arp_init(void)
{
static bool is_initialized;
if (is_initialized) {
return;
}
is_initialized = true;
memset(&arp_table, 0, sizeof(arp_table));
}

View file

@ -1,35 +0,0 @@
/*
* Copyright (c) 2016 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 <net/net_core.h>
#include <net/net_l2.h>
#include <net/net_if.h>
static inline enum net_verdict dummy_recv(struct net_if *iface,
struct net_buf *buf)
{
return NET_CONTINUE;
}
static inline enum net_verdict dummy_send(struct net_if *iface,
struct net_buf *buf)
{
net_if_queue_tx(iface, buf);
return NET_OK;
}
NET_L2_INIT(DUMMY_L2, dummy_recv, dummy_send);

View file

@ -1,60 +0,0 @@
/*
* Copyright (c) 2016 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 <net/net_core.h>
#include <net/net_l2.h>
#include <net/net_if.h>
#include <net/arp.h>
static enum net_verdict ethernet_recv(struct net_if *iface,
struct net_buf *buf)
{
#ifdef CONFIG_NET_ARP
if ((net_nbuf_ll_reserve(buf) == sizeof(struct net_eth_hdr))) {
struct net_eth_hdr *eth_hdr =
(struct net_eth_hdr *) net_nbuf_ll(buf);
if (ntohs(eth_hdr->type) == NET_ETH_PTYPE_ARP) {
NET_DBG("ARP packet from %s received",
net_sprint_ll_addr(
(uint8_t *)eth_hdr->src.addr,
sizeof(struct net_eth_addr)));
return net_arp_input(buf);
}
}
#endif
return NET_CONTINUE;
}
static enum net_verdict ethernet_send(struct net_if *iface,
struct net_buf *buf)
{
#ifdef CONFIG_NET_ARP
struct net_buf *arp_buf = net_arp_prepare(buf);
if (!arp_buf) {
return NET_DROP;
}
buf = arp_buf;
#endif
net_if_queue_tx(iface, buf);
return NET_OK;
}
NET_L2_INIT(ETHERNET_L2, ethernet_recv, ethernet_send);

View file

@ -1,624 +0,0 @@
/** @file
@brief Network buffers for IP stack
Network data is passed between components using nbuf.
*/
/*
* Copyright (c) 2016 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.
*/
#if defined(CONFIG_NETWORK_IP_STACK_DEBUG_NET_BUF)
#define SYS_LOG_DOMAIN "net/nbuf"
#define SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
#endif
#include <nanokernel.h>
#include <toolchain.h>
#include <string.h>
#include <stdint.h>
#include <net/net_ip.h>
#include <net/buf.h>
#include <net/nbuf.h>
#include <net/net_core.h>
#if !defined(NET_DEBUG_NBUFS)
#undef NET_DBG
#define NET_DBG(...)
#endif
#include "net_private.h"
/* Available (free) buffers queue */
#if !defined(NBUF_RX_COUNT)
#if CONFIG_NET_NBUF_RX_COUNT > 0
#define NBUF_RX_COUNT CONFIG_NET_NBUF_RX_COUNT
#else
#define NBUF_RX_COUNT 1
#endif
#endif
#if !defined(NBUF_TX_COUNT)
#if CONFIG_NET_NBUF_TX_COUNT > 0
#define NBUF_TX_COUNT CONFIG_NET_NBUF_TX_COUNT
#else
#define NBUF_TX_COUNT 1
#endif
#endif
#if !defined(NBUF_DATA_COUNT)
#if CONFIG_NET_NBUF_DATA_COUNT > 0
#define NBUF_DATA_COUNT CONFIG_NET_NBUF_DATA_COUNT
#else
#define NBUF_DATA_COUNT 13
#endif
#endif
#if !defined(NBUF_DATA_LEN)
#if CONFIG_NET_NBUF_DATA_SIZE > 0
#define NBUF_DATA_LEN CONFIG_NET_NBUF_DATA_SIZE
#else
#define NBUF_DATA_LEN 128
#endif
#endif
#if defined(CONFIG_NET_TCP)
#define APP_PROTO_LEN NET_TCPH_LEN
#else
#if defined(CONFIG_NET_UDP)
#define APP_PROTO_LEN NET_UDPH_LEN
#else
#define APP_PROTO_LEN 0
#endif /* UDP */
#endif /* TCP */
#if defined(CONFIG_NET_IPV6)
#define IP_PROTO_LEN NET_IPV6H_LEN
#else
#if defined(CONFIG_NET_IPV4)
#define IP_PROTO_LEN NET_IPV4H_LEN
#endif /* IPv4 */
#endif /* IPv6 */
#define EXTRA_PROTO_LEN NET_ICMPH_LEN
/* Make sure that IP + TCP/UDP header fit into one
* fragment. This makes possible to cast a protocol header
* struct into memory area.
*/
#if NBUF_DATA_LEN < (IP_PROTO_LEN + APP_PROTO_LEN)
#if defined(STRING2)
#undef STRING2
#endif
#if defined(STRING)
#undef STRING
#endif
#define STRING2(x) #x
#define STRING(x) STRING2(x)
#pragma message "Data len " STRING(NBUF_DATA_LEN)
#pragma message "Minimum len " STRING(IP_PROTO_LEN + APP_PROTO_LEN)
#error "Too small net_buf fragment size"
#endif
#if defined(NET_DEBUG_NBUFS)
static int num_free_rx_bufs = NBUF_RX_COUNT;
static int num_free_tx_bufs = NBUF_TX_COUNT;
static int num_free_data_bufs = NBUF_DATA_COUNT;
static inline void dec_free_rx_bufs(struct net_buf *buf)
{
if (!buf) {
return;
}
num_free_rx_bufs--;
if (num_free_rx_bufs < 0) {
NET_DBG("*** ERROR *** Invalid RX buffer count.");
num_free_rx_bufs = 0;
}
}
static inline void inc_free_rx_bufs(struct net_buf *buf)
{
if (!buf) {
return;
}
if (num_free_rx_bufs > NBUF_RX_COUNT) {
num_free_rx_bufs = NBUF_RX_COUNT;
} else {
num_free_rx_bufs++;
}
}
static inline void dec_free_tx_bufs(struct net_buf *buf)
{
if (!buf) {
return;
}
num_free_tx_bufs--;
if (num_free_tx_bufs < 0) {
NET_DBG("*** ERROR *** Invalid TX buffer count.");
num_free_tx_bufs = 0;
}
}
static inline void inc_free_tx_bufs(struct net_buf *buf)
{
if (!buf) {
return;
}
if (num_free_tx_bufs > NBUF_TX_COUNT) {
num_free_tx_bufs = NBUF_TX_COUNT;
} else {
num_free_tx_bufs++;
}
}
static inline void dec_free_data_bufs(struct net_buf *buf)
{
if (!buf) {
return;
}
num_free_data_bufs--;
if (num_free_data_bufs < 0) {
NET_DBG("*** ERROR *** Invalid data buffer count.");
num_free_data_bufs = 0;
}
}
static inline void inc_free_data_bufs(struct net_buf *buf)
{
if (!buf) {
return;
}
if (num_free_data_bufs > NBUF_DATA_COUNT) {
num_free_data_bufs = NBUF_DATA_COUNT;
} else {
num_free_data_bufs++;
}
}
static inline int get_frees(enum net_nbuf_type type)
{
switch (type) {
case NET_NBUF_RX:
return num_free_rx_bufs;
case NET_NBUF_TX:
return num_free_tx_bufs;
case NET_NBUF_DATA:
return num_free_data_bufs;
}
return 0xffffffff;
}
#define inc_free_rx_bufs_func inc_free_rx_bufs
#define inc_free_tx_bufs_func inc_free_tx_bufs
#define inc_free_data_bufs_func inc_free_data_bufs
#else /* NET_DEBUG_NBUFS */
#define dec_free_rx_bufs(...)
#define inc_free_rx_bufs(...)
#define dec_free_tx_bufs(...)
#define inc_free_tx_bufs(...)
#define dec_free_data_bufs(...)
#define inc_free_data_bufs(...)
#define inc_free_rx_bufs_func(...)
#define inc_free_tx_bufs_func(...)
#define inc_free_data_bufs_func(...)
#endif /* NET_DEBUG_NBUFS */
static struct nano_fifo free_rx_bufs;
static struct nano_fifo free_tx_bufs;
static struct nano_fifo free_data_bufs;
static inline void free_rx_bufs_func(struct net_buf *buf)
{
inc_free_rx_bufs_func(buf);
nano_fifo_put(buf->free, buf);
}
static inline void free_tx_bufs_func(struct net_buf *buf)
{
inc_free_tx_bufs_func(buf);
nano_fifo_put(buf->free, buf);
}
static inline void free_data_bufs_func(struct net_buf *buf)
{
inc_free_data_bufs_func(buf);
nano_fifo_put(buf->free, buf);
}
/* The RX and TX pools do not store any data. Only bearer / protocol
* related data is stored here.
*/
static NET_BUF_POOL(rx_buffers, NBUF_RX_COUNT, 0, \
&free_rx_bufs, free_rx_bufs_func, \
sizeof(struct net_nbuf));
static NET_BUF_POOL(tx_buffers, NBUF_TX_COUNT, 0, \
&free_tx_bufs, free_tx_bufs_func, \
sizeof(struct net_nbuf));
/* The data fragment pool is for storing network data.
* This pool does not need any user data because the rx/tx pool already
* contains all the protocol/bearer specific information.
*/
static NET_BUF_POOL(data_buffers, NBUF_DATA_COUNT, \
NBUF_DATA_LEN, &free_data_bufs, \
free_data_bufs_func, 0);
static inline const char *type2str(enum net_nbuf_type type)
{
switch (type) {
case NET_NBUF_RX:
return "RX";
case NET_NBUF_TX:
return "TX";
case NET_NBUF_DATA:
return "DATA";
}
return NULL;
}
#ifdef NET_DEBUG_NBUFS
static struct net_buf *net_nbuf_get_reserve_debug(enum net_nbuf_type type,
uint16_t reserve_head,
const char *caller,
int line)
#else
static struct net_buf *net_nbuf_get_reserve(enum net_nbuf_type type,
uint16_t reserve_head)
#endif
{
struct net_buf *buf = NULL;
/*
* The reserve_head variable in the function will tell
* the size of the link layer headers if there are any.
*/
switch (type) {
case NET_NBUF_RX:
buf = net_buf_get(&free_rx_bufs, 0);
dec_free_rx_bufs(buf);
net_nbuf_type(buf) = type;
break;
case NET_NBUF_TX:
buf = net_buf_get(&free_tx_bufs, 0);
dec_free_tx_bufs(buf);
net_nbuf_type(buf) = type;
break;
case NET_NBUF_DATA:
buf = net_buf_get(&free_data_bufs, reserve_head);
dec_free_data_bufs(buf);
break;
default:
NET_ERR("Invalid type %d for net_buf", type);
return NULL;
}
if (!buf) {
#if defined(CONFIG_NETWORK_IP_STACK_DEBUG_NET_BUF)
#define PRINT_CYCLE (30 * sys_clock_ticks_per_sec)
static uint32_t next_print;
uint32_t curr = sys_tick_get_32();
if (!next_print || (next_print < curr &&
(!((curr - next_print) > PRINT_CYCLE)))) {
uint32_t new_print;
#ifdef NET_DEBUG_NBUFS
NET_ERR("Failed to get free %s buffer (%s():%d)",
type2str(type), caller, line);
#else
NET_ERR("Failed to get free %s buffer",
type2str(type));
#endif /* NET_DEBUG_NBUFS */
new_print = curr + PRINT_CYCLE;
if (new_print > curr) {
next_print = new_print;
} else {
/* Overflow */
next_print = PRINT_CYCLE -
(0xffffffff - curr);
}
}
#endif
return NULL;
}
NET_BUF_CHECK_IF_NOT_IN_USE(buf, buf->ref + 1);
#ifdef NET_DEBUG_NBUFS
NET_DBG("%s [%d] buf %p reserve %u ref %d (%s():%d)",
type2str(type), get_frees(type),
buf, reserve_head, buf->ref, caller, line);
#else
NET_DBG("%s buf %p reserve %u ref %d",
type2str(type), buf, reserve_head, buf->ref);
#endif
return buf;
}
#ifdef NET_DEBUG_NBUFS
struct net_buf *net_nbuf_get_reserve_rx_debug(uint16_t reserve_head,
const char *caller, int line)
#else
struct net_buf *net_nbuf_get_reserve_rx(uint16_t reserve_head)
#endif
{
#ifdef NET_DEBUG_NBUFS
return net_nbuf_get_reserve_debug(NET_NBUF_RX, reserve_head,
caller, line);
#else
return net_nbuf_get_reserve(NET_NBUF_RX, reserve_head);
#endif
}
#ifdef NET_DEBUG_NBUFS
struct net_buf *net_nbuf_get_reserve_tx_debug(uint16_t reserve_head,
const char *caller, int line)
#else
struct net_buf *net_nbuf_get_reserve_tx(uint16_t reserve_head)
#endif
{
#ifdef NET_DEBUG_NBUFS
return net_nbuf_get_reserve_debug(NET_NBUF_TX, reserve_head,
caller, line);
#else
return net_nbuf_get_reserve(NET_NBUF_TX, reserve_head);
#endif
}
#ifdef NET_DEBUG_NBUFS
struct net_buf *net_nbuf_get_reserve_data_debug(uint16_t reserve_head,
const char *caller, int line)
#else
struct net_buf *net_nbuf_get_reserve_data(uint16_t reserve_head)
#endif
{
#ifdef NET_DEBUG_NBUFS
return net_nbuf_get_reserve_debug(NET_NBUF_DATA, reserve_head,
caller, line);
#else
return net_nbuf_get_reserve(NET_NBUF_DATA, reserve_head);
#endif
}
#ifdef NET_DEBUG_NBUFS
static struct net_buf *net_nbuf_get_debug(enum net_nbuf_type type,
struct net_context *context,
const char *caller, int line)
#else
static struct net_buf *net_nbuf_get(enum net_nbuf_type type,
struct net_context *context)
#endif
{
struct net_buf *buf;
int16_t reserve = 0;
if (type == NET_NBUF_DATA) {
reserve = NBUF_DATA_LEN -
net_if_get_mtu(net_context_get_iface(context));
if (reserve < 0) {
NET_ERR("MTU %d bigger than fragment size %d",
net_if_get_mtu(net_context_get_iface(context)),
NBUF_DATA_LEN);
return NULL;
}
}
#ifdef NET_DEBUG_NBUFS
buf = net_nbuf_get_reserve_debug(type, (uint16_t)reserve, caller, line);
#else
buf = net_nbuf_get_reserve(type, (uint16_t)reserve);
#endif
if (!buf) {
return buf;
}
if (type != NET_NBUF_DATA) {
net_nbuf_context(buf) = context;
net_nbuf_ll_reserve(buf) = (uint16_t)reserve;
}
return buf;
}
#ifdef NET_DEBUG_NBUFS
struct net_buf *net_nbuf_get_rx_debug(struct net_context *context,
const char *caller, int line)
#else
struct net_buf *net_nbuf_get_rx(struct net_context *context)
#endif
{
#ifdef NET_DEBUG_NBUFS
return net_nbuf_get_debug(NET_NBUF_RX, context, caller, line);
#else
return net_nbuf_get(NET_NBUF_RX, context);
#endif
}
#ifdef NET_DEBUG_NBUFS
struct net_buf *net_nbuf_get_tx_debug(struct net_context *context,
const char *caller, int line)
#else
struct net_buf *net_nbuf_get_tx(struct net_context *context)
#endif
{
#ifdef NET_DEBUG_NBUFS
return net_nbuf_get_debug(NET_NBUF_TX, context, caller, line);
#else
return net_nbuf_get(NET_NBUF_TX, context);
#endif
}
#ifdef NET_DEBUG_NBUFS
struct net_buf *net_nbuf_get_data_debug(struct net_context *context,
const char *caller, int line)
#else
struct net_buf *net_nbuf_get_data(struct net_context *context)
#endif
{
#ifdef NET_DEBUG_NBUFS
return net_nbuf_get_debug(NET_NBUF_DATA, context, caller, line);
#else
return net_nbuf_get(NET_NBUF_DATA, context);
#endif
}
#ifdef NET_DEBUG_NBUFS
void net_nbuf_unref_debug(struct net_buf *buf, const char *caller, int line)
#else
void net_nbuf_unref(struct net_buf *buf)
#endif
{
struct net_buf *frag;
if (!buf) {
#ifdef NET_DEBUG_NBUFS
NET_DBG("*** ERROR *** buf %p (%s():%d)", buf, caller, line);
#else
NET_DBG("*** ERROR *** buf %p", buf);
#endif
return;
}
if (!buf->ref) {
#ifdef NET_DEBUG_NBUFS
NET_DBG("*** ERROR *** buf %p is freed already (%s():%d)",
buf, caller, line);
#else
NET_DBG("*** ERROR *** buf %p is freed already", buf);
#endif
return;
}
if (buf->user_data_size) {
#ifdef NET_DEBUG_NBUFS
NET_DBG("%s [%d] buf %p ref %d frags %p (%s():%d)",
type2str(net_nbuf_type(buf)),
get_frees(net_nbuf_type(buf)),
buf, buf->ref - 1, buf->frags, caller, line);
#else
NET_DBG("%s buf %p ref %d frags %p",
type2str(net_nbuf_type(buf)), buf, buf->ref - 1,
buf->frags);
#endif
} else {
#ifdef NET_DEBUG_NBUFS
NET_DBG("%s [%d] buf %p ref %d frags %p (%s():%d)",
type2str(NET_NBUF_DATA),
get_frees(NET_NBUF_DATA),
buf, buf->ref - 1, buf->frags, caller, line);
#else
NET_DBG("%s buf %p ref %d frags %p",
type2str(NET_NBUF_DATA), buf, buf->ref - 1,
buf->frags);
#endif
}
/* Remove the fragment list elements first, otherwise we
* have a memory leak. But only if we are to be remove the
* buffer.
*/
frag = buf->frags;
while (!(buf->ref - 1) && frag) {
struct net_buf *next = frag->frags;
net_buf_frag_del(buf, frag);
#ifdef NET_DEBUG_NBUFS
NET_DBG("%s [%d] buf %p ref %d frags %p (%s():%d)",
type2str(NET_NBUF_DATA),
get_frees(NET_NBUF_DATA),
frag, frag->ref - 1, frag->frags, caller, line);
#else
NET_DBG("%s buf %p ref %d frags %p",
type2str(NET_NBUF_DATA), frag, frag->ref - 1,
frag->frags);
#endif
net_buf_unref(frag);
frag = next;
}
net_buf_unref(buf);
}
#ifdef NET_DEBUG_NBUFS
struct net_buf *net_nbuf_ref_debug(struct net_buf *buf, const char *caller,
int line)
#else
struct net_buf *net_nbuf_ref(struct net_buf *buf)
#endif
{
if (!buf) {
#ifdef NET_DEBUG_NBUFS
NET_DBG("*** ERROR *** buf %p (%s():%d)", buf, caller, line);
#else
NET_DBG("*** ERROR *** buf %p", buf);
#endif
return NULL;
}
if (buf->user_data_size) {
#ifdef NET_DEBUG_NBUFS
NET_DBG("%s [%d] buf %p ref %d (%s():%d)",
type2str(net_nbuf_type(buf)),
get_frees(net_nbuf_type(buf)),
buf, buf->ref + 1, caller, line);
#else
NET_DBG("%s buf %p ref %d",
type2str(net_nbuf_type(buf)), buf, buf->ref + 1);
#endif
} else {
#ifdef NET_DEBUG_NBUFS
NET_DBG("%s buf %p ref %d (%s():%d)",
type2str(NET_NBUF_DATA),
buf, buf->ref + 1, caller, line);
#else
NET_DBG("%s buf %p ref %d",
type2str(NET_NBUF_DATA), buf, buf->ref + 1);
#endif
}
return net_buf_ref(buf);
}
void net_nbuf_init(void)
{
NET_DBG("Allocating %d RX (%d bytes), %d TX (%d bytes) "
"and %d data (%d bytes) buffers",
NBUF_RX_COUNT, sizeof(rx_buffers),
NBUF_TX_COUNT, sizeof(tx_buffers),
NBUF_DATA_COUNT, sizeof(data_buffers));
net_buf_pool_init(rx_buffers);
net_buf_pool_init(tx_buffers);
net_buf_pool_init(data_buffers);
}

View file

@ -1,148 +0,0 @@
/** @file
@brief Network context API
An API for applications to define a network connection.
*/
/*
* Copyright (c) 2016 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 <nanokernel.h>
#include <string.h>
#include <errno.h>
#include <stdbool.h>
#include <net/net_ip.h>
#include <net/net_context.h>
/* Override this in makefile if needed */
#if defined(CONFIG_NET_MAX_CONTEXTS)
#define NET_MAX_CONTEXT CONFIG_NET_MAX_CONTEXTS
#else
#define NET_MAX_CONTEXT 6
#endif
static struct net_context contexts[NET_MAX_CONTEXT];
static struct nano_sem contexts_lock;
static int context_port_used(enum ip_protocol ip_proto, uint16_t local_port,
const struct net_addr *local_addr)
{
int i;
for (i = 0; i < NET_MAX_CONTEXT; i++) {
if (contexts[i].tuple.ip_proto == ip_proto &&
contexts[i].tuple.local_port == local_port &&
!memcmp(&contexts[i].tuple.local_addr, local_addr,
sizeof(struct net_addr))) {
return -EEXIST;
}
}
return 0;
}
struct net_context *net_context_get(enum ip_protocol ip_proto,
const struct net_addr *remote_addr,
uint16_t remote_port,
struct net_addr *local_addr,
uint16_t local_port)
{
#ifdef CONFIG_NET_IPV6
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
#endif
int i;
struct net_context *context = NULL;
/* User must provide storage for the local address. */
if (!local_addr) {
return NULL;
}
#if defined(CONFIG_NET_IPV6)
if (memcmp(&local_addr->in6_addr, &in6addr_any,
sizeof(in6addr_any)) == 0) {
/* FIXME */
}
#endif
#if defined(CONFIG_NET_IPV4)
if (local_addr->in_addr.s_addr == INADDR_ANY) {
/* FIXME */
}
#endif
nano_sem_take(&contexts_lock, TICKS_UNLIMITED);
if (local_port) {
if (context_port_used(ip_proto, local_port, local_addr) < 0) {
return NULL;
}
} else {
do {
local_port = sys_rand32_get() | 0x8000;
} while (context_port_used(ip_proto, local_port,
local_addr) == -EEXIST);
}
for (i = 0; i < NET_MAX_CONTEXT; i++) {
if (!contexts[i].tuple.ip_proto) {
contexts[i].tuple.ip_proto = ip_proto;
contexts[i].tuple.remote_addr = (struct net_addr *)remote_addr;
contexts[i].tuple.remote_port = remote_port;
contexts[i].tuple.local_addr = (struct net_addr *)local_addr;
contexts[i].tuple.local_port = local_port;
context = &contexts[i];
break;
}
}
nano_sem_give(&contexts_lock);
return context;
}
void net_context_put(struct net_context *context)
{
if (!context) {
return;
}
nano_sem_take(&contexts_lock, TICKS_UNLIMITED);
if (context->tuple.ip_proto == IPPROTO_UDP) {
/* FIXME */
}
memset(&context->tuple, 0, sizeof(context->tuple));
nano_sem_give(&contexts_lock);
}
void net_context_init(void)
{
int i;
nano_sem_init(&contexts_lock);
memset(contexts, 0, sizeof(contexts));
for (i = 0; i < NET_MAX_CONTEXT; i++) {
nano_fifo_init(&contexts[i].rx_queue);
}
nano_sem_give(&contexts_lock);
}

View file

@ -1,440 +0,0 @@
/** @file
* @brief Network initialization
*
* Initialize the network IP stack. Create two fibers, one for reading data
* from applications (Tx fiber) and one for reading data from IP stack
* and passing that data to applications (Rx fiber).
*/
/*
* Copyright (c) 2016 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.
*/
#if defined(CONFIG_NETWORK_IP_STACK_DEBUG_CORE)
#define SYS_LOG_DOMAIN "net/core"
#define NET_DEBUG 1
#endif
#include <init.h>
#include <nanokernel.h>
#include <toolchain.h>
#include <sections.h>
#include <string.h>
#include <errno.h>
#include <net/net_if.h>
#include <net/arp.h>
#include <net/nbuf.h>
#include <net/net_core.h>
#include <net/net_stats.h>
#include "net_private.h"
#if defined(CONFIG_NET_IPV6)
#include "icmpv6.h"
#endif
#if defined(CONFIG_NET_IPV4)
#include "icmpv4.h"
#endif
/* Stack for the rx fiber.
*/
#if !defined(CONFIG_NET_RX_STACK_SIZE)
#define CONFIG_NET_RX_STACK_SIZE 1024
#endif
static char __noinit __stack rx_fiber_stack[CONFIG_NET_RX_STACK_SIZE];
static struct nano_fifo rx_queue;
static nano_thread_id_t rx_fiber_id;
#if defined(CONFIG_NET_STATISTICS)
#define PRINT_STAT(fmt, ...) printk(fmt, ##__VA_ARGS__)
struct net_stats net_stats;
#define GET_STAT(s) net_stats.s
#define PRINT_STATISTICS_INTERVAL (30 * sys_clock_ticks_per_sec)
#define net_print_statistics stats /* to make the debug print line shorter */
static inline void stats(void)
{
static uint32_t next_print;
uint32_t curr = sys_tick_get_32();
if (!next_print || (next_print < curr &&
(!((curr - next_print) > PRINT_STATISTICS_INTERVAL)))) {
uint32_t new_print;
#if defined(CONFIG_NET_IPV6)
PRINT_STAT("IPv6 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n",
GET_STAT(ipv6.recv),
GET_STAT(ipv6.sent),
GET_STAT(ipv6.drop),
GET_STAT(ipv6.forwarded));
#endif /* CONFIG_NET_IPV6 */
#if defined(CONFIG_NET_IPV4)
PRINT_STAT("IPv4 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n",
GET_STAT(ipv4.recv),
GET_STAT(ipv4.sent),
GET_STAT(ipv4.drop),
GET_STAT(ipv4.forwarded));
#endif /* CONFIG_NET_IPV4 */
PRINT_STAT("IP vhlerr %d\thblener\t%d\tlblener\t%d\n",
GET_STAT(ip_errors.vhlerr),
GET_STAT(ip_errors.hblenerr),
GET_STAT(ip_errors.lblenerr));
PRINT_STAT("IP fragerr %d\tchkerr\t%d\tprotoer\t%d\n",
GET_STAT(ip_errors.fragerr),
GET_STAT(ip_errors.chkerr),
GET_STAT(ip_errors.protoerr));
PRINT_STAT("ICMP recv %d\tsent\t%d\tdrop\t%d\n",
GET_STAT(icmp.recv),
GET_STAT(icmp.sent),
GET_STAT(icmp.drop));
PRINT_STAT("ICMP typeer %d\tchkerr\t%d\n",
GET_STAT(icmp.typeerr),
GET_STAT(icmp.chkerr));
#if defined(CONFIG_NET_UDP)
PRINT_STAT("UDP recv %d\tsent\t%d\tdrop\t%d\n",
GET_STAT(udp.recv),
GET_STAT(udp.sent),
GET_STAT(udp.drop));
PRINT_STAT("UDP chkerr %d\n",
GET_STAT(icmp.chkerr));
#endif
PRINT_STAT("Processing err %d\n", GET_STAT(processing_error));
new_print = curr + PRINT_STATISTICS_INTERVAL;
if (new_print > curr) {
next_print = new_print;
} else {
/* Overflow */
next_print = PRINT_STATISTICS_INTERVAL -
(0xffffffff - curr);
}
}
}
#else /* CONFIG_NET_STATISTICS */
#define net_print_statistics()
#endif /* CONFIG_NET_STATISTICS */
static inline enum net_verdict process_icmpv6_pkt(struct net_buf *buf,
struct net_ipv6_hdr *ipv6)
{
struct net_icmp_hdr *hdr = NET_ICMP_BUF(buf);
uint16_t len = (ipv6->len[0] << 8) + ipv6->len[1];
NET_DBG("ICMPv6 packet received length %d type %d code %d",
len, hdr->type, hdr->code);
return net_icmpv6_input(buf, len, hdr->type, hdr->code);
}
#if defined(CONFIG_NET_IPV6)
static inline enum net_verdict process_ipv6_pkt(struct net_buf *buf)
{
struct net_ipv6_hdr *hdr = NET_IPV6_BUF(buf);
int real_len = net_buf_frags_len(buf);
int pkt_len = (hdr->len[0] << 8) + hdr->len[1] + sizeof(*hdr);
if (real_len > pkt_len) {
NET_DBG("IPv6 adjust pkt len to %d (was %d)",
pkt_len, real_len);
net_buf_frag_last(buf)->len -= real_len - pkt_len;
real_len -= pkt_len;
} else if (real_len < pkt_len) {
NET_DBG("IPv6 packet size %d buf len %d", pkt_len, real_len);
NET_STATS(++net_stats.ipv6.drop);
goto drop;
}
#if NET_DEBUG > 0
do {
char out[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
snprintf(out, sizeof(out), net_sprint_ipv6_addr(&hdr->dst));
NET_DBG("IPv6 packet len %d received from %s to %s",
real_len, net_sprint_ipv6_addr(&hdr->src), out);
} while (0);
#endif /* NET_DEBUG > 0 */
if (net_is_ipv6_addr_mcast(&hdr->src)) {
NET_STATS(++net_stats.ipv6.drop);
NET_DBG("Dropping src multicast packet");
goto drop;
}
if (!net_is_my_ipv6_addr(&hdr->dst) &&
!net_is_my_ipv6_maddr(&hdr->dst) &&
!net_is_ipv6_addr_mcast(&hdr->dst) &&
!net_is_ipv6_addr_loopback(&hdr->dst)) {
NET_DBG("IPv6 packet in buf %p not for me", buf);
NET_STATS(++net_stats.ipv6.drop);
goto drop;
}
/* Check extension headers */
net_nbuf_next_hdr(buf) = &hdr->nexthdr;
net_nbuf_ext_len(buf) = 0;
net_nbuf_ext_bitmap(buf) = 0;
while (1) {
switch (*(net_nbuf_next_hdr(buf))) {
case IPPROTO_ICMPV6:
net_nbuf_ip_hdr_len(buf) = sizeof(struct net_ipv6_hdr);
return process_icmpv6_pkt(buf, hdr);
default:
goto bad_header;
}
}
bad_header:
drop:
return NET_DROP;
}
#endif /* CONFIG_NET_IPV6 */
#if defined(CONFIG_NET_IPV4)
static inline enum net_verdict process_icmpv4_pkt(struct net_buf *buf,
struct net_ipv4_hdr *ipv4)
{
struct net_icmp_hdr *hdr = NET_ICMP_BUF(buf);
uint16_t len = (ipv4->len[0] << 8) + ipv4->len[1];
NET_DBG("ICMPv4 packet received length %d type %d code %d",
len, hdr->type, hdr->code);
return net_icmpv4_input(buf, len, hdr->type, hdr->code);
}
#endif /* CONFIG_NET_IPV4 */
#if defined(CONFIG_NET_IPV4)
static inline enum net_verdict process_ipv4_pkt(struct net_buf *buf)
{
struct net_ipv4_hdr *hdr = NET_IPV4_BUF(buf);
int real_len = net_buf_frags_len(buf);
int pkt_len = (hdr->len[0] << 8) + hdr->len[1];
if (real_len > pkt_len) {
NET_DBG("IPv4 adjust pkt len to %d (was %d)",
pkt_len, real_len);
net_buf_frag_last(buf)->len -= real_len - pkt_len;
real_len -= pkt_len;
} else if (real_len < pkt_len) {
NET_DBG("IPv4 packet size %d buf len %d", pkt_len, real_len);
NET_STATS(++net_stats.ipv4.drop);
return NET_DROP;
}
#if NET_DEBUG > 0
do {
char out[sizeof("xxx.xxx.xxx.xxx")];
snprintf(out, sizeof(out), net_sprint_ipv4_addr(&hdr->dst));
NET_DBG("IPv4 packet received from %s to %s",
net_sprint_ipv4_addr(&hdr->src), out);
} while (0);
#endif /* NET_DEBUG > 0 */
if (!net_is_my_ipv4_addr(&hdr->dst)) {
NET_DBG("IPv4 packet in buf %p not for me", buf);
NET_STATS(++net_stats.ipv4.drop);
goto drop;
}
switch (hdr->proto) {
case IPPROTO_ICMP:
net_nbuf_ip_hdr_len(buf) = sizeof(struct net_ipv4_hdr);
return process_icmpv4_pkt(buf, hdr);
}
drop:
return NET_DROP;
}
#endif /* CONFIG_NET_IPV4 */
static inline enum net_verdict process_data(struct net_buf *buf)
{
int ret;
/* If there is no data, then drop the packet. Also if
* the buffer is wrong type, then also drop the packet.
* The first buffer needs to have user data part that
* contains user data. The rest of the fragments should
* be data fragments without user data.
*/
if (!buf->frags || !buf->user_data_size) {
NET_STATS(++net_stats.processing_error);
return NET_DROP;
}
ret = net_if_recv_data(net_nbuf_iface(buf), buf);
if (ret != NET_CONTINUE) {
if (ret == NET_DROP) {
NET_STATS(++net_stats.processing_error);
}
return ret;
}
/* IP version and header length. */
switch (NET_IPV6_BUF(buf)->vtc & 0xf0) {
#if defined(CONFIG_NET_IPV6)
case 0x60:
NET_STATS(++net_stats.ipv6.recv);
net_nbuf_family(buf) = PF_INET6;
return process_ipv6_pkt(buf);
#endif
#if defined(CONFIG_NET_IPV4)
case 0x40:
NET_STATS(++net_stats.ipv4.recv);
net_nbuf_family(buf) = PF_INET;
return process_ipv4_pkt(buf);
#endif
}
NET_STATS(++net_stats.ip_errors.protoerr);
NET_STATS(++net_stats.ip_errors.vhlerr);
return NET_DROP;
}
static void net_rx_fiber(void)
{
struct net_buf *buf;
NET_DBG("Starting RX fiber (stack %d bytes)",
sizeof(rx_fiber_stack));
/* Starting TX side. The ordering is important here and the TX
* can only be started when RX side is ready to receive packets.
*/
net_if_init();
while (1) {
buf = nano_fifo_get(&rx_queue, TICKS_UNLIMITED);
net_analyze_stack("RX fiber", rx_fiber_stack,
sizeof(rx_fiber_stack));
NET_DBG("Received buf %p len %d", buf,
net_buf_frags_len(buf));
switch (process_data(buf)) {
case NET_OK:
NET_DBG("Consumed buf %p", buf);
break;
case NET_DROP:
default:
NET_DBG("Dropping buf %p", buf);
net_nbuf_unref(buf);
break;
}
net_print_statistics();
}
}
static void init_rx_queue(void)
{
nano_fifo_init(&rx_queue);
rx_fiber_id = fiber_start(rx_fiber_stack, sizeof(rx_fiber_stack),
(nano_fiber_entry_t)net_rx_fiber,
0, 0, 8, 0);
}
/* Called when data needs to be sent to network */
int net_send_data(struct net_buf *buf)
{
if (!buf || !buf->frags) {
return -ENODATA;
}
if (!net_nbuf_iface(buf)) {
return -EINVAL;
}
#if defined(CONFIG_NET_STATISTICS)
switch (net_nbuf_family(buf)) {
case AF_INET:
NET_STATS(++net_stats.ipv4.sent);
break;
case AF_INET6:
NET_STATS(++net_stats.ipv6.sent);
break;
}
#endif
return net_if_send_data(net_nbuf_iface(buf), buf);
}
/* Called by driver when an IP packet has been received */
int net_recv_data(struct net_if *iface, struct net_buf *buf)
{
if (!buf->frags) {
return -ENODATA;
}
NET_DBG("fifo %p iface %p buf %p len %d", &rx_queue, iface, buf,
net_buf_frags_len(buf));
net_nbuf_iface(buf) = iface;
nano_fifo_put(&rx_queue, buf);
fiber_wakeup(rx_fiber_id);
return 0;
}
static int network_initialization(void)
{
#if defined(CONFIG_NET_IPV6)
net_icmpv6_init();
#endif
NET_DBG("Network L3 layer init done");
return 0;
}
static int net_init(struct device *unused)
{
static bool is_initialized;
if (is_initialized)
return -EALREADY;
is_initialized = true;
NET_DBG("Priority %d", CONFIG_NET_INIT_PRIO);
net_nbuf_init();
net_context_init();
#ifdef CONFIG_NET_ARP
net_arp_init();
#endif
network_initialization();
init_rx_queue();
return 0;
}
SYS_INIT(net_init, NANOKERNEL, CONFIG_NET_INIT_PRIO);

View file

@ -1,475 +0,0 @@
/*
* Copyright (c) 2016 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.
*/
#if defined(CONFIG_NETWORK_IP_STACK_DEBUG_IF)
#define SYS_LOG_DOMAIN "net/if"
#define NET_DEBUG 1
#endif
#include <init.h>
#include <nanokernel.h>
#include <sections.h>
#include <string.h>
#include <net/net_core.h>
#include <net/nbuf.h>
#include <net/net_if.h>
#include <net/arp.h>
#include "net_private.h"
/* net_if dedicated section limiters */
extern struct net_if __net_if_start[];
extern struct net_if __net_if_end[];
static void net_if_tx_fiber(struct net_if *iface)
{
struct net_if_api *api = (struct net_if_api *)iface->dev->driver_api;
api = (struct net_if_api *) iface->dev->driver_api;
NET_ASSERT(api && api->init && api->send);
NET_DBG("Starting TX fiber (stack %d bytes) for driver %p queue %p",
sizeof(iface->tx_fiber_stack), api, &iface->tx_queue);
api->init(iface);
while (1) {
struct net_buf *buf;
/* Get next packet from application - wait if necessary */
buf = nano_fifo_get(&iface->tx_queue, TICKS_UNLIMITED);
NET_DBG("Processing (buf %p, data len %u) network packet",
buf, net_buf_frags_len(buf->frags));
if (api->send(iface, buf) < 0) {
net_nbuf_unref(buf);
}
net_analyze_stack("TX fiber", iface->tx_fiber_stack,
sizeof(iface->tx_fiber_stack));
}
}
static inline void init_tx_queue(struct net_if *iface)
{
nano_fifo_init(&iface->tx_queue);
fiber_start(iface->tx_fiber_stack, sizeof(iface->tx_fiber_stack),
(nano_fiber_entry_t)net_if_tx_fiber, (int)iface, 0, 7, 0);
}
struct net_if *net_if_get_by_link_addr(struct net_linkaddr *ll_addr)
{
struct net_if *iface;
for (iface = __net_if_start; iface != __net_if_end; iface++) {
if (!memcmp(iface->link_addr.addr, ll_addr->addr,
ll_addr->len)) {
return iface;
}
}
return NULL;
}
struct net_if_addr *net_if_ipv6_addr_lookup(struct in6_addr *addr)
{
#if defined(CONFIG_NET_IPV6)
struct net_if *iface;
for (iface = __net_if_start; iface != __net_if_end; iface++) {
int i;
for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
if (!iface->ipv6.unicast[i].is_used ||
iface->ipv6.unicast[i].address.family != AF_INET6) {
continue;
}
if (net_is_ipv6_prefix(addr->s6_addr,
iface->ipv6.unicast[i].address.in6_addr.s6_addr,
128)) {
return &iface->ipv6.unicast[i];
}
}
}
#endif
return NULL;
}
struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
struct in6_addr *addr,
enum net_addr_type addr_type,
uint32_t vlifetime)
{
#if defined(CONFIG_NET_IPV6)
int i;
for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
if (iface->ipv6.unicast[i].is_used) {
continue;
}
iface->ipv6.unicast[i].is_used = true;
iface->ipv6.unicast[i].address.family = AF_INET6;
iface->ipv6.unicast[i].addr_type = addr_type;
memcpy(&iface->ipv6.unicast[i].address.in6_addr, addr, 16);
/* FIXME - set the mcast addr for this node */
if (vlifetime) {
iface->ipv6.unicast[i].is_infinite = false;
/* FIXME - set the timer */
} else {
iface->ipv6.unicast[i].is_infinite = true;
}
NET_DBG("[%d] interface %p address %s type %s added", i, iface,
net_sprint_ipv6_addr(addr),
net_addr_type2str(addr_type));
return &iface->ipv6.unicast[i];
}
#endif
return NULL;
}
struct net_if_mcast_addr *net_if_ipv6_maddr_add(struct net_if *iface,
struct in6_addr *addr)
{
#if defined(CONFIG_NET_IPV6)
int i;
if (!net_is_ipv6_addr_mcast(addr)) {
NET_DBG("Address %s is not a multicast address.",
net_sprint_ipv6_addr(addr));
return NULL;
}
for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
if (iface->ipv6.mcast[i].is_used) {
continue;
}
iface->ipv6.mcast[i].is_used = true;
memcpy(&iface->ipv6.mcast[i].address.in6_addr, addr, 16);
NET_DBG("[%d] interface %p address %s added", i, iface,
net_sprint_ipv6_addr(addr));
return &iface->ipv6.mcast[i];
}
#endif
return NULL;
}
struct net_if_mcast_addr *net_if_ipv6_maddr_lookup(struct in6_addr *maddr)
{
#if defined(CONFIG_NET_IPV6)
struct net_if *iface;
for (iface = __net_if_start; iface != __net_if_end; iface++) {
int i;
for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
if (!iface->ipv6.mcast[i].is_used ||
iface->ipv6.mcast[i].address.family != AF_INET6) {
continue;
}
if (net_is_ipv6_prefix(maddr->s6_addr,
iface->ipv6.mcast[i].address.in6_addr.s6_addr,
128)) {
return &iface->ipv6.mcast[i];
}
}
}
#endif
return NULL;
}
struct in6_addr *net_if_ipv6_unspecified_addr(void)
{
#if defined(CONFIG_NET_IPV6)
static struct in6_addr addr = IN6ADDR_ANY_INIT;
return &addr;
#else
return NULL;
#endif
}
const struct in_addr *net_if_ipv4_broadcast_addr(void)
{
#if defined(CONFIG_NET_IPV4)
static const struct in_addr addr = { { { 255, 255, 255, 255 } } };
return &addr;
#else
return NULL;
#endif
}
bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
struct in_addr *addr)
{
#if defined(CONFIG_NET_IPV4)
uint32_t subnet = ntohl(addr->s_addr[0]) &
ntohl(iface->ipv4.netmask.s_addr[0]);
int i;
for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
if (!iface->ipv4.unicast[i].is_used ||
iface->ipv4.unicast[i].address.family != AF_INET) {
continue;
}
if ((ntohl(iface->ipv4.unicast[i].address.in_addr.s_addr[0]) &
ntohl(iface->ipv4.netmask.s_addr[0])) == subnet) {
return true;
}
}
#endif
return false;
}
struct in6_addr *net_if_ipv6_get_ll(struct net_if *iface,
enum net_addr_state addr_state)
{
int i;
for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
if (!iface->ipv6.unicast[i].is_used ||
(addr_state != NET_ADDR_ANY_STATE &&
iface->ipv6.unicast[i].addr_state != addr_state) ||
iface->ipv6.unicast[i].address.family != AF_INET6) {
continue;
}
if (net_is_ipv6_ll_addr(&iface->ipv6.unicast[i].address.in6_addr)) {
return &iface->ipv6.unicast[i].address.in6_addr;
}
}
return NULL;
}
static inline uint8_t get_length(struct in6_addr *src, struct in6_addr *dst)
{
uint8_t j, k, xor;
uint8_t len = 0;
for (j = 0; j < 16; j++) {
if (src->s6_addr[j] == dst->s6_addr[j]) {
len += 8;
} else {
xor = src->s6_addr[j] ^ dst->s6_addr[j];
for (k = 0; k < 8; k++) {
if (!(xor & 0x80)) {
len++;
xor <<= 1;
} else {
break;
}
}
break;
}
}
return len;
}
static inline bool is_proper_ipv6_address(struct net_if_addr *addr)
{
if (addr->is_used && addr->addr_state == NET_ADDR_PREFERRED &&
addr->address.family == AF_INET6 &&
!net_is_ipv6_ll_addr(&addr->address.in6_addr)) {
return true;
}
return false;
}
static inline struct in6_addr *net_if_ipv6_get_best_match(struct net_if *iface,
struct in6_addr *dst,
uint8_t *best_so_far)
{
#if defined(CONFIG_NET_IPV6)
struct in6_addr *src = NULL;
uint8_t i, len;
for (i = 0; i < NET_IF_MAX_IPV6_ADDR; i++) {
if (!is_proper_ipv6_address(&iface->ipv6.unicast[i])) {
continue;
}
len = get_length(dst,
&iface->ipv6.unicast[i].address.in6_addr);
if (len >= *best_so_far) {
*best_so_far = len;
src = &iface->ipv6.unicast[i].address.in6_addr;
}
}
return src;
#else
return NULL;
#endif
}
struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface,
struct in6_addr *dst)
{
#if defined(CONFIG_NET_IPV6)
struct in6_addr *src = NULL;
uint8_t best_match = 0;
struct net_if *iface;
if (!net_is_ipv6_ll_addr(dst) && !net_is_ipv6_addr_mcast(dst)) {
for (iface = __net_if_start;
!dst_iface && iface != __net_if_end;
iface++) {
struct in6_addr *addr;
addr = net_if_ipv6_get_best_match(iface, dst,
&best_match);
if (addr) {
src = addr;
}
}
/* If caller has supplied interface, then use that */
if (dst_iface) {
src = net_if_ipv6_get_best_match(dst_iface, dst,
&best_match);
}
} else {
for (iface = __net_if_start;
!dst_iface && iface != __net_if_end;
iface++) {
struct in6_addr *addr;
addr = net_if_ipv6_get_ll(iface, NET_ADDR_PREFERRED);
if (addr) {
src = addr;
break;
}
}
if (dst_iface) {
src = net_if_ipv6_get_ll(dst_iface, NET_ADDR_PREFERRED);
}
}
if (!src) {
return net_if_ipv6_unspecified_addr();
}
return src;
#else
return NULL;
#endif
}
struct net_if_addr *net_if_ipv4_addr_lookup(struct in_addr *addr)
{
#if defined(CONFIG_NET_IPV4)
struct net_if *iface;
for (iface = __net_if_start; iface != __net_if_end; iface++) {
int i;
for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
if (!iface->ipv4.unicast[i].is_used ||
iface->ipv4.unicast[i].address.family != AF_INET) {
continue;
}
if (addr->s4_addr32[0] ==
iface->ipv4.unicast[i].address.in_addr.s_addr[0]) {
return &iface->ipv4.unicast[i];
}
}
}
#endif
return NULL;
}
struct net_if_addr *net_if_ipv4_addr_add(struct net_if *iface,
struct in_addr *addr,
enum net_addr_type addr_type,
uint32_t vlifetime)
{
#if defined(CONFIG_NET_IPV4)
int i;
for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
if (iface->ipv4.unicast[i].is_used) {
continue;
}
iface->ipv4.unicast[i].is_used = true;
iface->ipv4.unicast[i].address.family = AF_INET;
iface->ipv4.unicast[i].address.in_addr.s4_addr32[0] =
addr->s4_addr32[0];
iface->ipv4.unicast[i].addr_type = addr_type;
if (vlifetime) {
iface->ipv4.unicast[i].is_infinite = false;
/* FIXME - set the timer */
} else {
iface->ipv4.unicast[i].is_infinite = true;
iface->ipv4.unicast[i].addr_state = NET_ADDR_PREFERRED;
}
NET_DBG("[%d] interface %p address %s type %s added", i, iface,
net_sprint_ipv4_addr(addr),
net_addr_type2str(addr_type));
return &iface->ipv4.unicast[i];
}
#endif
return NULL;
}
struct net_if *net_if_get_default(void)
{
return __net_if_start;
}
void net_if_init(void)
{
struct net_if *iface;
for (iface = __net_if_start; iface != __net_if_end; iface++) {
init_tx_queue(iface);
#if defined(CONFIG_NET_IPV6)
iface->hop_limit = CONFIG_NET_INITIAL_HOP_LIMIT;
#endif
}
}

View file

@ -1,161 +0,0 @@
/** @file
@brief Network stack private header
This is not to be included by the application.
*/
/*
* Copyright (c) 2016 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 <errno.h>
extern void net_nbuf_init(void);
extern void net_if_init(void);
extern void net_context_init(void);
extern char *net_byte_to_hex(uint8_t *ptr, uint8_t byte, char base, bool pad);
extern char *net_sprint_ll_addr_buf(uint8_t *ll, uint8_t ll_len,
char *buf, int buflen);
extern char *net_sprint_ip_addr_buf(uint8_t *ip, int ip_len,
char *buf, int buflen);
extern uint16_t net_calc_chksum(struct net_buf *buf, uint8_t proto);
static inline uint16_t net_calc_chksum_icmpv6(struct net_buf *buf)
{
return net_calc_chksum(buf, IPPROTO_ICMPV6);
}
static inline uint16_t net_calc_chksum_icmpv4(struct net_buf *buf)
{
return net_calc_chksum(buf, IPPROTO_ICMP);
}
#if NET_DEBUG > 0
static inline char *net_sprint_ll_addr(uint8_t *ll, uint8_t ll_len)
{
static char buf[sizeof("xx:xx:xx:xx:xx:xx:xx:xx")];
return net_sprint_ll_addr_buf(ll, ll_len, (char *)buf, sizeof(buf));
}
static inline char *net_sprint_ip_addr_ptr(uint8_t *ptr, uint8_t len)
{
static char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")];
return net_sprint_ip_addr_buf(ptr, len, (char *)buf, sizeof(buf));
}
static inline char *net_sprint_ipv6_addr(struct in6_addr *addr)
{
#if defined(CONFIG_NET_IPV6)
return net_sprint_ip_addr_ptr(addr->s6_addr, 16);
#else
return NULL;
#endif
}
static inline char *net_sprint_ipv4_addr(struct in_addr *addr)
{
#if defined(CONFIG_NET_IPV4)
return net_sprint_ip_addr_ptr(addr->s4_addr, 4);
#else
return NULL;
#endif
}
static inline char *net_sprint_ip_addr(struct net_addr *addr)
{
switch (addr->family) {
case AF_INET6:
#if defined(CONFIG_NET_IPV6)
return net_sprint_ipv6_addr(&addr->in6_addr);
#else
break;
#endif
case AF_INET:
#if defined(CONFIG_NET_IPV4)
return net_sprint_ipv4_addr(&addr->in_addr);
#else
break;
#endif
default:
break;
}
return NULL;
}
static inline void net_hexdump(const char *str, const uint8_t *packet, size_t length)
{
int n = 0;
if (!length) {
SYS_LOG_DBG("%s zero-length packet", str);
return;
}
while (length--) {
if (n % 16 == 0) {
printf("%s %08X ", str, n);
}
printf("%02X ", *packet++);
n++;
if (n % 8 == 0) {
if (n % 16 == 0) {
printf("\n");
} else {
printf(" ");
}
}
}
if (n % 16) {
printf("\n");
}
}
#else /* NET_DEBUG */
static inline char *net_sprint_ll_addr(uint8_t *ll, uint8_t ll_len)
{
return NULL;
}
static inline char *net_sprint_ip_addr_ptr(uint8_t *ptr, uint8_t len)
{
return NULL;
}
static inline char *net_sprint_ipv6_addr(struct in6_addr *addr)
{
return NULL;
}
static inline char *net_sprint_ipv4_addr(struct in_addr *addr)
{
return NULL;
}
static inline char *net_sprint_ip_addr(struct net_addr *addr)
{
return NULL;
}
#define net_hexdump(str, packet, length)
#endif /* NET_DEBUG */

View file

@ -1,350 +0,0 @@
/** @file
* @brief Misc network utility functions
*
*/
/*
* Copyright (c) 2016 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.
*/
#if defined(CONFIG_NETWORK_IP_STACK_DEBUG_UTILS)
#define SYS_LOG_DOMAIN "net/utils"
#define NET_DEBUG 1
#endif
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <misc/byteorder.h>
#include <net/net_ip.h>
#include <net/nbuf.h>
#include <net/net_core.h>
char *net_byte_to_hex(uint8_t *ptr, uint8_t byte, char base, bool pad)
{
int i, val;
for (i = 0, val = (byte & 0xf0) >> 4; i < 2; i++, val = byte & 0x0f) {
if (i == 0 && !pad && !val) {
continue;
}
if (val < 10) {
*ptr++ = (char) (val + '0');
} else {
*ptr++ = (char) (val - 10 + base);
}
}
*ptr = '\0';
return ptr;
}
char *net_sprint_ll_addr_buf(uint8_t *ll, uint8_t ll_len,
char *buf, int buflen)
{
uint8_t i, len, blen;
char *ptr = buf;
switch (ll_len) {
case 8:
len = 8;
break;
case 6:
len = 6;
break;
default:
len = 6;
break;
}
for (i = 0, blen = buflen; i < len && blen > 0; i++) {
ptr = net_byte_to_hex(ptr, ll[i], 'A', true);
*ptr++ = ':';
blen -= 3;
}
if (!(ptr - buf)) {
return NULL;
}
*(ptr - 1) = '\0';
return buf;
}
static int net_value_to_udec(char *buf, uint32_t value, int precision)
{
uint32_t divisor;
int i;
int temp;
char *start = buf;
divisor = 1000000000;
if (precision < 0)
precision = 1;
for (i = 9; i >= 0; i--, divisor /= 10) {
temp = value / divisor;
value = value % divisor;
if ((precision > i) || (temp != 0)) {
precision = i;
*buf++ = (char) (temp + '0');
}
}
*buf = 0;
return buf - start;
}
char *net_sprint_ip_addr_buf(uint8_t *ip, int ip_len, char *buf, int buflen)
{
uint16_t *w = (uint16_t *)ip;
uint8_t i, bl, bh, longest = 1;
int8_t pos = -1;
char delim = ':';
unsigned char zeros[8] = { 0 };
char *ptr = buf;
int len = -1;
uint16_t value;
bool needcolon = false;
switch (ip_len) {
case 16:
len = 8;
for (i = 0; i < 8; i++) {
uint8_t j;
for (j = i; j < 8; j++) {
if (w[j] != 0) {
break;
}
zeros[i]++;
}
}
for (i = 0; i < 8; i++) {
if (zeros[i] > longest) {
longest = zeros[i];
pos = i;
}
}
if (longest == 1) {
pos = -1;
}
break;
case 4:
len = 4;
delim = '.';
break;
default:
break;
}
/* Invalid len, bail out */
if (len < 0) {
return NULL;
}
for (i = 0; i < len; i++) {
/* IPv4 address a.b.c.d */
if (len == 4) {
uint8_t l;
value = (uint32_t)ip[i];
/* net_byte_to_udec() eats 0 */
if (value == 0) {
*ptr++ = '0';
*ptr++ = delim;
continue;
}
l = net_value_to_udec(ptr, value, 0);
ptr += l;
*ptr++ = delim;
continue;
}
/* IPv6 address */
if (i == pos) {
if (needcolon || i == 0) {
*ptr++ = ':';
}
*ptr++ = ':';
needcolon = false;
i += longest - 1;
continue;
}
if (needcolon) {
*ptr++ = ':';
needcolon = false;
}
value = (uint32_t)sys_be16_to_cpu(w[i]);
bh = value >> 8;
bl = value & 0xff;
if (bh) {
if (bh > 0x0f) {
ptr = net_byte_to_hex(ptr, bh, 'a', false);
} else {
if (bh < 10) {
*ptr++ = (char)(bh + '0');
} else {
*ptr++ = (char) (bh - 10 + 'a');
}
}
ptr = net_byte_to_hex(ptr, bl, 'a', true);
} else if (bl > 0x0f) {
ptr = net_byte_to_hex(ptr, bl, 'a', false);
} else {
if (bl < 10) {
*ptr++ = (char)(bl + '0');
} else {
*ptr++ = (char) (bl - 10 + 'a');
}
}
needcolon = true;
}
if (!(ptr - buf)) {
return NULL;
}
if (ip_len == 4) {
*(ptr - 1) = '\0';
} else {
*ptr = '\0';
}
return buf;
}
static uint16_t calc_chksum(uint16_t sum, const uint8_t *ptr, uint16_t len)
{
uint16_t tmp;
const uint8_t *end;
end = ptr + len - 1;
while (ptr < end) {
tmp = (ptr[0] << 8) + ptr[1];
sum += tmp;
if (sum < tmp) {
sum++;
}
ptr += 2;
}
if (ptr == end) {
tmp = ptr[0] << 8;
sum += tmp;
if (sum < tmp) {
sum++;
}
}
return sum;
}
static inline uint16_t calc_chksum_buf(uint16_t sum, struct net_buf *buf,
uint16_t upper_layer_len)
{
struct net_buf *frag = buf->frags;
uint16_t proto_len = net_nbuf_ip_hdr_len(buf) + net_nbuf_ext_len(buf);
int16_t len = frag->len - proto_len;
uint8_t *ptr = frag->data + proto_len;
if (len < 0) {
NET_DBG("1st fragment len %u < IP header len %u",
frag->len, proto_len);
return 0;
}
while (frag) {
sum = calc_chksum(sum, ptr, len);
frag = frag->frags;
if (!frag) {
break;
}
ptr = frag->data;
/* Do we need to take first byte from next fragment */
if (len % 2) {
uint16_t tmp = *ptr;
sum += tmp;
if (sum < tmp) {
sum++;
}
len = frag->len - 1;
ptr++;
} else {
len = frag->len;
}
}
return sum;
}
uint16_t net_calc_chksum(struct net_buf *buf, uint8_t proto)
{
uint16_t upper_layer_len;
uint16_t sum;
switch (net_nbuf_family(buf)) {
#if defined(CONFIG_NET_IPV4)
case AF_INET:
upper_layer_len = (NET_IPV4_BUF(buf)->len[0] << 8) +
NET_IPV4_BUF(buf)->len[1] -
net_nbuf_ext_len(buf) -
net_nbuf_ip_hdr_len(buf);
if (proto == IPPROTO_ICMP) {
return htons(calc_chksum(0, net_nbuf_ip_data(buf) +
net_nbuf_ip_hdr_len(buf),
upper_layer_len));
} else {
sum = calc_chksum(upper_layer_len + proto,
(uint8_t *)&NET_IPV4_BUF(buf)->src,
2 * sizeof(struct in_addr));
}
break;
#endif
#if defined(CONFIG_NET_IPV6)
case AF_INET6:
upper_layer_len = (NET_IPV6_BUF(buf)->len[0] << 8) +
NET_IPV6_BUF(buf)->len[1] - net_nbuf_ext_len(buf);
sum = calc_chksum(upper_layer_len + proto,
(uint8_t *)&NET_IPV6_BUF(buf)->src,
2 * sizeof(struct in6_addr));
break;
#endif
default:
NET_DBG("Unknown protocol family %d", net_nbuf_family(buf));
return 0;
}
sum = calc_chksum_buf(sum, buf, upper_layer_len);
sum = (sum == 0) ? 0xffff : htons(sum);
return sum;
}

View file

@ -1,14 +1,10 @@
ccflags-y +=-I${ZEPHYR_BASE}/net/ip ccflags-y +=-I${ZEPHYR_BASE}/net/ip
ccflags-y +=-I${ZEPHYR_BASE}/samples/bluetooth/ ccflags-y +=-I${ZEPHYR_BASE}/samples/bluetooth/
ifeq ($(CONFIG_NET_YAIP), y)
obj-y = echo-server-yaip.o
else
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os/lib ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os/lib
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os
obj-y = echo-server.o obj-y = echo-server.o
endif
ifeq ($(CONFIG_NET_TESTING), y) ifeq ($(CONFIG_NET_TESTING), y)
ccflags-y +=-I${ZEPHYR_BASE}/samples/net/common/ ccflags-y +=-I${ZEPHYR_BASE}/samples/net/common/

View file

@ -1,258 +0,0 @@
/* echo.c - Networking echo server */
/*
* 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.
*/
#if defined(CONFIG_STDOUT_CONSOLE)
#include <stdio.h>
#define PRINT printf
#else
#include <misc/printk.h>
#define PRINT printk
#endif
#include <zephyr.h>
#include <sections.h>
#include <errno.h>
#include <net/net_if.h>
#include <net/net_core.h>
#if defined(CONFIG_NETWORKING_WITH_BT)
#include <bluetooth/bluetooth.h>
#include <gatt/ipss.h>
#endif
#if defined(CONFIG_NET_TESTING)
#include <net_testing.h>
#else
#endif /* CONFIG_NET_TESTING */
#if defined(CONFIG_NET_IPV6)
/* admin-local, dynamically allocated multicast address */
#define MCAST_IP6ADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0x2 } } }
/* Define my IP address where to expect messages */
#if !defined(CONFIG_NET_TESTING)
#define MY_IP6ADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0x1 } } }
#define MY_PREFIX_LEN 64
#endif
#if defined(CONFIG_NET_TESTING)
static const struct in6_addr in6addr_my = IN6ADDR_ANY_INIT;
#else
static const struct in6_addr in6addr_my = MY_IP6ADDR;
#endif
#endif /* IPv6 */
#if defined(CONFIG_NET_IPV4)
/* Organization-local 239.192.0.0/14 */
#define MCAST_IP4ADDR { { { 239, 192, 0, 2 } } }
/* The 192.0.2.0/24 is the private address space for documentation RFC 5737 */
#define MY_IP4ADDR { { { 192, 0, 2, 1 } } }
#endif /* IPv4 */
#define MY_PORT 4242
struct in6_addr addr6 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
static struct in_addr in4addr_my = MY_IP4ADDR;
static inline void init_app(void)
{
PRINT("%s: run echo server\n", __func__);
#if defined(CONFIG_NET_TESTING)
net_testing_setup();
#endif
#if defined(CONFIG_NET_IPV6)
net_if_ipv6_addr_add(net_if_get_default(), &addr6, NET_ADDR_MANUAL, 0);
#endif
#if defined(CONFIG_NET_IPV4)
net_if_ipv4_addr_add(net_if_get_default(), &in4addr_my, NET_ADDR_MANUAL, 0);
#endif
}
/* How many tics to wait for a network packet */
#if 1
#define WAIT_TIME 0
#define WAIT_TICKS (WAIT_TIME * sys_clock_ticks_per_sec / 10)
#else
#define WAIT_TICKS TICKS_UNLIMITED
#endif
static inline bool get_context(struct net_context **udp_recv4,
struct net_context **udp_recv6,
struct net_context **tcp_recv4,
struct net_context **tcp_recv6,
struct net_context **mcast_recv4,
struct net_context **mcast_recv6)
{
#if defined(CONFIG_NET_IPV6)
static struct net_addr mcast_addr6;
static struct net_addr any_addr6;
static struct net_addr my_addr6;
static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
static const struct in6_addr in6addr_mcast = MCAST_IP6ADDR;
#endif
#if defined(CONFIG_NET_IPV4)
static struct net_addr mcast_addr4;
static struct net_addr any_addr4;
static struct net_addr my_addr4;
static const struct in_addr in4addr_any = { { { 0 } } };
static struct in_addr in4addr_mcast = MCAST_IP4ADDR;
#endif
#if defined(CONFIG_NET_IPV6)
mcast_addr6.in6_addr = in6addr_mcast;
mcast_addr6.family = AF_INET6;
any_addr6.in6_addr = in6addr_any;
any_addr6.family = AF_INET6;
my_addr6.in6_addr = in6addr_my;
my_addr6.family = AF_INET6;
#endif
#if defined(CONFIG_NET_IPV4)
mcast_addr4.in_addr = in4addr_mcast;
mcast_addr4.family = AF_INET;
any_addr4.in_addr = in4addr_any;
any_addr4.family = AF_INET;
my_addr4.in_addr = in4addr_my;
my_addr4.family = AF_INET;
#endif
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_UDP)
*udp_recv6 = net_context_get(IPPROTO_UDP,
&any_addr6, 0,
&my_addr6, MY_PORT);
if (!*udp_recv6) {
PRINT("%s: Cannot get network context\n", __func__);
return NULL;
}
*mcast_recv5 = net_context_get(IPPROTO_UDP,
&any_addr6, 0,
&mcast_addr6, MY_PORT);
if (!*mcast_recv6) {
PRINT("%s: Cannot get receiving mcast network context\n",
__func__);
return false;
}
#endif
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP)
*udp_recv4 = net_context_get(IPPROTO_UDP,
&any_addr4, 0,
&my_addr4, MY_PORT);
if (!*udp_recv4) {
PRINT("%s: Cannot get network context\n", __func__);
return NULL;
}
*mcast_recv4 = net_context_get(IPPROTO_UDP,
&any_addr4, 0,
&mcast_addr4, MY_PORT);
if (!*mcast_recv4) {
PRINT("%s: Cannot get receiving mcast network context\n",
__func__);
return false;
}
#endif
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_TCP)
if (tcp_recv6) {
*tcp_recv6 = net_context_get(IPPROTO_TCP,
&any_addr6, 0,
&my_addr6, MY_PORT);
if (!*tcp_recv6) {
PRINT("%s: Cannot get network context\n", __func__);
return NULL;
}
}
#endif
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_TCP)
if (tcp_recv4) {
*tcp_recv4 = net_context_get(IPPROTO_TCP,
&any_addr4, 0,
&my_addr4, MY_PORT);
if (!*tcp_recv4) {
PRINT("%s: Cannot get network context\n", __func__);
return NULL;
}
}
#endif
return true;
}
#if defined(CONFIG_NANOKERNEL)
#define STACKSIZE 2000
char __noinit __stack fiberStack[STACKSIZE];
#endif
void receive(void)
{
static struct net_context *udp_recv4, *udp_recv6,
*tcp_recv4, *tcp_recv6;
static struct net_context *mcast_recv4, *mcast_recv6;
if (!get_context(&udp_recv4, &udp_recv6,
&tcp_recv4, &tcp_recv6,
&mcast_recv4, &mcast_recv6)) {
PRINT("%s: Cannot get network contexts\n", __func__);
return;
}
while (1) {
/* FIXME - Implementation is missing */
fiber_sleep(100);
}
}
void main(void)
{
init_app();
#if defined(CONFIG_NETWORKING_WITH_BT)
if (bt_enable(NULL)) {
PRINT("Bluetooth init failed\n");
return;
}
ipss_init();
ipss_advertise();
#endif
#if defined(CONFIG_MICROKERNEL)
receive();
#else
task_fiber_start(&fiberStack[0], STACKSIZE,
(nano_fiber_entry_t)receive, 0, 0, 7, 0);
#endif
}

View file

@ -1,6 +0,0 @@
BOARD ?= qemu_x86
MDEF_FILE = prj.mdef
KERNEL_TYPE ?= nano
CONF_FILE = prj_$(ARCH).conf
include $(ZEPHYR_BASE)/Makefile.inc

View file

@ -1,5 +0,0 @@
% Application : Network test
% TASK NAME PRIO ENTRY STACK GROUPS
% ===================================================
TASK MAIN 7 mainloop 2048 [EXE]

View file

@ -1,15 +0,0 @@
CONFIG_NETWORKING=y
CONFIG_NET_IPV4=y
CONFIG_NET_YAIP=y
CONFIG_NET_BUF=y
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_NET_NBUF_RX_COUNT=3
CONFIG_NET_NBUF_TX_COUNT=4
CONFIG_NET_NBUF_DATA_COUNT=7
CONFIG_NET_LOG=y
CONFIG_SYS_LOG_SHOW_COLOR=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_IFACE_UNICAST_IPV4_ADDR_COUNT=3
CONFIG_NETWORK_IP_STACK_DEBUG_IPV4_ARP=y
CONFIG_NETWORK_IP_STACK_DEBUG_IF=y
CONFIG_NETWORK_IP_STACK_DEBUG_CORE=y

View file

@ -1,2 +0,0 @@
obj-y = main.o
ccflags-y += -I${srctree}/net/yaip

View file

@ -1,752 +0,0 @@
/* main.c - Application main entry point */
/*
* Copyright (c) 2016 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 <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <device.h>
#include <init.h>
#include <misc/printk.h>
#include <net/net_core.h>
#include <net/nbuf.h>
#include <net/net_ip.h>
#include <net/arp.h>
#define NET_DEBUG 1
#include "net_private.h"
/* Sample ARP request (60 bytes) */
static const unsigned char pkt1[60] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x98, 0x4f, /* .......O */
0xee, 0x05, 0x4e, 0x5d, 0x08, 0x06, 0x00, 0x01, /* ..N].... */
0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x98, 0x4f, /* .......O */
0xee, 0x05, 0x4e, 0x5d, 0xc0, 0xa8, 0x00, 0x02, /* ..N].... */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, /* ........ */
0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x00, 0x00 /* .... */
};
static bool req_test;
static char *app_data = "0123456789";
static const struct net_eth_addr broadcast_eth_addr = {
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
static const struct net_eth_addr multicast_eth_addr = {
{ 0x01, 0x00, 0x5e, 0x01, 0x02, 0x03 } };
struct net_arp_context {
uint8_t mac_addr[sizeof(struct net_eth_addr)];
struct net_linkaddr ll_addr;
};
int net_arp_dev_init(struct device *dev)
{
struct net_arp_context *net_arp_context = dev->driver_data;
dev->driver_api = NULL;
net_arp_context = net_arp_context;
return 0;
}
static uint8_t *net_arp_get_mac(struct device *dev)
{
struct net_arp_context *context = dev->driver_data;
if (context->mac_addr[0] == 0x00) {
/* 10-00-00-00-00 to 10-00-00-00-FF Documentation RFC7042 */
context->mac_addr[0] = 0x10;
context->mac_addr[1] = 0x00;
context->mac_addr[2] = 0x00;
context->mac_addr[3] = 0x00;
context->mac_addr[4] = 0x00;
context->mac_addr[5] = sys_rand32_get();
}
return context->mac_addr;
}
static void net_arp_iface_init(struct net_if *iface)
{
uint8_t *mac = net_arp_get_mac(net_if_get_device(iface));
net_if_set_link_addr(iface, mac, 8);
}
static uint32_t net_arp_iface_cap(struct net_if *iface)
{
return NET_CAP_ARP;
}
static struct net_buf *pending_buf;
static struct net_eth_addr hwaddr = { { 0x42, 0x11, 0x69, 0xde, 0xfa, 0xec } };
static int send_status = -EINVAL;
#define NET_ARP_BUF(buf) ((struct net_arp_hdr *)net_nbuf_ll(buf))
static int tester_send(struct net_if *iface, struct net_buf *buf)
{
struct net_eth_hdr *hdr;
if (!buf->frags) {
printk("No data to send!");
return -ENODATA;
}
if (net_nbuf_ll_reserve(buf) != sizeof(struct net_eth_hdr)) {
printk("No ethernet header in buf %p", buf);
send_status = -EINVAL;
return send_status;
}
hdr = (struct net_eth_hdr *)net_nbuf_ll(buf);
if (ntohs(hdr->type) == NET_ETH_PTYPE_ARP) {
struct net_arp_hdr *arp_hdr =
(struct net_arp_hdr *)net_nbuf_ll(buf);
if (ntohs(arp_hdr->opcode) == NET_ARP_REPLY) {
if (!req_test && buf != pending_buf) {
printk("Pending data but to be sent is wrong, "
"expecting %p but got %p\n",
pending_buf, buf);
return -EINVAL;
}
if (!req_test && memcmp(&hdr->dst, &hwaddr,
sizeof(struct net_eth_addr))) {
char out[sizeof("xx:xx:xx:xx:xx:xx")];
snprintf(out, sizeof(out),
net_sprint_ll_addr(
(uint8_t *)&hdr->dst,
sizeof(struct net_eth_addr)));
printk("Invalid hwaddr %s, should be %s\n",
out,
net_sprint_ll_addr(
(uint8_t *)&hwaddr,
sizeof(struct net_eth_addr)));
send_status = -EINVAL;
return send_status;
}
} else if (ntohs(arp_hdr->opcode) == NET_ARP_REQUEST) {
if (memcmp(&hdr->src, &hwaddr,
sizeof(struct net_eth_addr))) {
char out[sizeof("xx:xx:xx:xx:xx:xx")];
snprintf(out, sizeof(out),
net_sprint_ll_addr(
(uint8_t *)&hdr->src,
sizeof(struct net_eth_addr)));
printk("Invalid hwaddr %s, should be %s\n",
out,
net_sprint_ll_addr(
(uint8_t *)&hwaddr,
sizeof(struct net_eth_addr)));
send_status = -EINVAL;
return send_status;
}
}
}
printk("Data was sent successfully\n");
net_nbuf_unref(buf);
send_status = 0;
return 0;
}
static inline struct in_addr *if_get_addr(struct net_if *iface)
{
int i;
for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
if (iface->ipv4.unicast[i].is_used &&
iface->ipv4.unicast[i].address.family == AF_INET &&
iface->ipv4.unicast[i].addr_state == NET_ADDR_PREFERRED) {
return &iface->ipv4.unicast[i].address.in_addr;
}
}
return NULL;
}
static inline struct net_buf *prepare_arp_reply(struct net_if *iface,
struct net_buf *req,
struct net_eth_addr *addr)
{
struct net_buf *buf, *frag;
struct net_arp_hdr *hdr;
buf = net_nbuf_get_reserve_tx(0);
if (!buf) {
goto fail;
}
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr));
if (!frag) {
goto fail;
}
net_buf_frag_add(buf, frag);
net_nbuf_iface(buf) = iface;
net_nbuf_ll_reserve(buf) = net_buf_headroom(frag);
hdr = (struct net_arp_hdr *)net_nbuf_ll(buf);
hdr->eth_hdr.type = htons(NET_ETH_PTYPE_ARP);
memset(&hdr->eth_hdr.dst.addr, 0xff, sizeof(struct net_eth_addr));
memcpy(&hdr->eth_hdr.src.addr, net_if_get_link_addr(iface)->addr,
sizeof(struct net_eth_addr));
hdr->hwtype = htons(NET_ARP_HTYPE_ETH);
hdr->protocol = htons(NET_ETH_PTYPE_IP);
hdr->hwlen = sizeof(struct net_eth_addr);
hdr->protolen = sizeof(struct in_addr);
hdr->opcode = htons(NET_ARP_REPLY);
memcpy(&hdr->dst_hwaddr.addr, &hdr->eth_hdr.src.addr,
sizeof(struct net_eth_addr));
memcpy(&hdr->src_hwaddr.addr, addr,
sizeof(struct net_eth_addr));
net_ipaddr_copy(&hdr->dst_ipaddr, &NET_ARP_BUF(req)->src_ipaddr);
net_ipaddr_copy(&hdr->src_ipaddr, &NET_ARP_BUF(req)->dst_ipaddr);
net_buf_add(frag, sizeof(struct net_arp_hdr) - net_buf_headroom(frag));
return buf;
fail:
net_nbuf_unref(buf);
return NULL;
}
static inline struct net_buf *prepare_arp_request(struct net_if *iface,
struct net_buf *req,
struct net_eth_addr *addr)
{
struct net_buf *buf, *frag;
struct net_arp_hdr *hdr, *req_hdr;
buf = net_nbuf_get_reserve_rx(0);
if (!buf) {
goto fail;
}
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr));
if (!frag) {
goto fail;
}
net_buf_frag_add(buf, frag);
net_nbuf_iface(buf) = iface;
net_nbuf_ll_reserve(buf) = sizeof(struct net_eth_hdr);
hdr = (struct net_arp_hdr *)net_nbuf_ll(buf);
req_hdr = (struct net_arp_hdr *)net_nbuf_ll(req);
hdr->eth_hdr.type = htons(NET_ETH_PTYPE_ARP);
memset(&hdr->eth_hdr.dst.addr, 0xff, sizeof(struct net_eth_addr));
memcpy(&hdr->eth_hdr.src.addr, addr, sizeof(struct net_eth_addr));
hdr->hwtype = htons(NET_ARP_HTYPE_ETH);
hdr->protocol = htons(NET_ETH_PTYPE_IP);
hdr->hwlen = sizeof(struct net_eth_addr);
hdr->protolen = sizeof(struct in_addr);
hdr->opcode = htons(NET_ARP_REQUEST);
memset(&hdr->dst_hwaddr.addr, 0x00, sizeof(struct net_eth_addr));
memcpy(&hdr->src_hwaddr.addr, addr, sizeof(struct net_eth_addr));
net_ipaddr_copy(&hdr->src_ipaddr, &req_hdr->src_ipaddr);
net_ipaddr_copy(&hdr->dst_ipaddr, &req_hdr->dst_ipaddr);
net_buf_add(frag, sizeof(struct net_arp_hdr) - net_buf_headroom(frag));
return buf;
fail:
net_nbuf_unref(buf);
return NULL;
}
static void setup_eth_header(struct net_if *iface, struct net_buf *buf,
struct net_eth_addr *hwaddr, uint16_t type)
{
struct net_eth_hdr *hdr = (struct net_eth_hdr *)net_nbuf_ll(buf);
memcpy(&hdr->dst.addr, hwaddr, sizeof(struct net_eth_addr));
memcpy(&hdr->src.addr, net_if_get_link_addr(iface)->addr,
sizeof(struct net_eth_addr));
hdr->type = htons(type);
}
struct net_arp_context net_arp_context_data;
static struct net_if_api net_arp_if_api = {
.init = net_arp_iface_init,
.capabilities = net_arp_iface_cap,
.send = tester_send,
};
NET_DEVICE_INIT(net_arp_test, "net_arp_test",
net_arp_dev_init, &net_arp_context_data, NULL,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&net_arp_if_api, 127);
#ifdef CONFIG_MICROKERNEL
void mainloop(void)
#else
void main(void)
#endif
{
struct net_buf *buf, *buf2;
struct net_buf *frag;
struct net_if *iface;
struct net_if_addr *ifaddr;
struct net_arp_hdr *arp_hdr;
struct net_ipv4_hdr *ipv4;
struct net_eth_hdr *eth_hdr;
int len;
struct in_addr dst = { { { 192, 168, 0, 2 } } };
struct in_addr dst_far = { { { 10, 11, 12, 13 } } };
struct in_addr dst_far2 = { { { 172, 16, 14, 186 } } };
struct in_addr src = { { { 192, 168, 0, 1 } } };
struct in_addr mcast = { { { 224, 1, 2, 3 } } };
struct in_addr netmask = { { { 255, 255, 255, 0 } } };
struct in_addr gw = { { { 192, 168, 0, 42 } } };
net_arp_init();
iface = net_if_get_default();
net_if_set_gw(iface, &gw);
net_if_set_netmask(iface, &netmask);
/* Broadcast and multicast tests */
buf = net_nbuf_get_reserve_tx(0);
if (!buf) {
printk("Out of mem TX xcast\n");
return;
}
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr));
if (!frag) {
printk("Out of mem DATA xcast\n");
return;
}
net_buf_frag_add(buf, frag);
net_nbuf_ll_reserve(buf) = net_buf_headroom(frag);
net_nbuf_iface(buf) = iface;
ipv4 = (struct net_ipv4_hdr *)net_buf_add(frag,
sizeof(struct net_ipv4_hdr));
net_ipaddr_copy(&ipv4->src, &src);
net_ipaddr_copy(&ipv4->dst, net_ipv4_broadcast_address());
buf2 = net_arp_prepare(buf);
if (buf2 != buf) {
printk("ARP broadcast buffer different\n");
return;
}
eth_hdr = (struct net_eth_hdr *)net_nbuf_ll(buf);
if (memcmp(&eth_hdr->dst.addr, &broadcast_eth_addr,
sizeof(struct net_eth_addr))) {
char out[sizeof("xx:xx:xx:xx:xx:xx")];
snprintf(out, sizeof(out),
net_sprint_ll_addr((uint8_t *)&eth_hdr->dst.addr,
sizeof(struct net_eth_addr)));
printk("ETH addr dest invalid %s, should be %s", out,
net_sprint_ll_addr((uint8_t *)&broadcast_eth_addr,
sizeof(broadcast_eth_addr)));
return;
}
net_ipaddr_copy(&ipv4->dst, &mcast);
buf2 = net_arp_prepare(buf);
if (buf2 != buf) {
printk("ARP multicast buffer different\n");
return;
}
if (memcmp(&eth_hdr->dst.addr, &multicast_eth_addr,
sizeof(struct net_eth_addr))) {
char out[sizeof("xx:xx:xx:xx:xx:xx")];
snprintf(out, sizeof(out),
net_sprint_ll_addr((uint8_t *)&eth_hdr->dst.addr,
sizeof(struct net_eth_addr)));
printk("ETH maddr dest invalid %s, should be %s", out,
net_sprint_ll_addr((uint8_t *)&multicast_eth_addr,
sizeof(broadcast_eth_addr)));
return;
}
net_nbuf_unref(buf);
/* Then the unicast test */
ifaddr = net_if_ipv4_addr_add(iface,
&src,
NET_ADDR_MANUAL,
0);
ifaddr->addr_state = NET_ADDR_PREFERRED;
/* Application data for testing */
buf = net_nbuf_get_reserve_tx(0);
if (!buf) {
printk("Out of mem TX\n");
return;
}
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr));
if (!frag) {
printk("Out of mem DATA\n");
return;
}
net_buf_frag_add(buf, frag);
net_nbuf_ll_reserve(buf) = net_buf_headroom(frag);
net_nbuf_iface(buf) = iface;
setup_eth_header(iface, buf, &hwaddr, NET_ETH_PTYPE_IP);
len = strlen(app_data);
if (net_nbuf_ll_reserve(buf) != sizeof(struct net_eth_hdr)) {
printk("LL reserve invalid, should be %d was %d\n",
sizeof(struct net_eth_hdr),
net_nbuf_ll_reserve(buf));
return;
}
ipv4 = (struct net_ipv4_hdr *)net_buf_add(frag,
sizeof(struct net_ipv4_hdr));
net_ipaddr_copy(&ipv4->src, &src);
net_ipaddr_copy(&ipv4->dst, &dst);
memcpy(net_buf_add(frag, len), app_data, len);
buf2 = net_arp_prepare(buf);
/* buf2 is the ARP buffer and buf is the IPv4 buffer and it was
* stored in ARP table.
*/
if (buf2 == buf) {
/* The buffers cannot be the same as the ARP cache has
* still room for the buf.
*/
printk("ARP cache should still have free space\n");
return;
}
if (!buf2) {
printk("ARP buf is empty\n");
return;
}
/* The ARP cache should now have a link to pending net_buf
* that is to be sent after we have got an ARP reply.
*/
if (!buf->frags) {
printk("Pending buf fragment is NULL\n");
return;
}
pending_buf = buf;
/* buf2 should contain the arp header, verify it */
if (memcmp(net_nbuf_ll(buf2), &broadcast_eth_addr,
sizeof(struct net_eth_addr))) {
printk("ARP ETH dest address invalid\n");
net_hexdump("ETH dest correct", net_nbuf_ll(buf2),
sizeof(struct net_eth_addr));
net_hexdump("ETH dest wrong ", (uint8_t *)&broadcast_eth_addr,
sizeof(struct net_eth_addr));
return;
}
if (memcmp(net_nbuf_ll(buf2) + sizeof(struct net_eth_addr),
iface->link_addr.addr,
sizeof(struct net_eth_addr))) {
printk("ARP ETH source address invalid\n");
net_hexdump("ETH src correct",
iface->link_addr.addr,
sizeof(struct net_eth_addr));
net_hexdump("ETH src wrong ",
net_nbuf_ll(buf2) + sizeof(struct net_eth_addr),
sizeof(struct net_eth_addr));
return;
}
arp_hdr = (struct net_arp_hdr *)net_nbuf_ll(buf2);
if (arp_hdr->eth_hdr.type != htons(NET_ETH_PTYPE_ARP)) {
printk("ETH type 0x%x, should be 0x%x\n",
arp_hdr->eth_hdr.type, htons(NET_ETH_PTYPE_ARP));
return;
}
if (arp_hdr->hwtype != htons(NET_ARP_HTYPE_ETH)) {
printk("ARP hwtype 0x%x, should be 0x%x\n",
arp_hdr->hwtype, htons(NET_ARP_HTYPE_ETH));
return;
}
if (arp_hdr->protocol != htons(NET_ETH_PTYPE_IP)) {
printk("ARP protocol 0x%x, should be 0x%x\n",
arp_hdr->protocol, htons(NET_ETH_PTYPE_IP));
return;
}
if (arp_hdr->hwlen != sizeof(struct net_eth_addr)) {
printk("ARP hwlen 0x%x, should be 0x%x\n",
arp_hdr->hwlen, sizeof(struct net_eth_addr));
return;
}
if (arp_hdr->protolen != sizeof(struct in_addr)) {
printk("ARP IP addr len 0x%x, should be 0x%x\n",
arp_hdr->protolen, sizeof(struct in_addr));
return;
}
if (arp_hdr->opcode != htons(NET_ARP_REQUEST)) {
printk("ARP opcode 0x%x, should be 0x%x\n",
arp_hdr->opcode, htons(NET_ARP_REQUEST));
return;
}
if (!net_ipv4_addr_cmp(&arp_hdr->dst_ipaddr,
&NET_IPV4_BUF(buf)->dst)) {
char out[sizeof("xxx.xxx.xxx.xxx")];
snprintf(out, sizeof(out),
net_sprint_ipv4_addr(&arp_hdr->dst_ipaddr));
printk("ARP IP dest invalid %s, should be %s", out,
net_sprint_ipv4_addr(&NET_IPV4_BUF(buf)->dst));
return;
}
if (!net_ipv4_addr_cmp(&arp_hdr->src_ipaddr,
&NET_IPV4_BUF(buf)->src)) {
char out[sizeof("xxx.xxx.xxx.xxx")];
snprintf(out, sizeof(out),
net_sprint_ipv4_addr(&arp_hdr->src_ipaddr));
printk("ARP IP src invalid %s, should be %s", out,
net_sprint_ipv4_addr(&NET_IPV4_BUF(buf)->src));
return;
}
if (buf->ref != 2) {
printk("ARP cache should own the original buffer\n");
return;
}
/* Then a case where target is not in the same subnet */
net_ipaddr_copy(&ipv4->dst, &dst_far);
buf2 = net_arp_prepare(buf);
if (buf2 == buf) {
printk("ARP cache should not find anything\n");
return;
}
if (!buf2) {
printk("ARP buf2 is empty\n");
return;
}
arp_hdr = (struct net_arp_hdr *)net_nbuf_ll(buf2);
if (!net_ipv4_addr_cmp(&arp_hdr->dst_ipaddr, &iface->ipv4.gw)) {
char out[sizeof("xxx.xxx.xxx.xxx")];
snprintf(out, sizeof(out),
net_sprint_ipv4_addr(&arp_hdr->dst_ipaddr));
printk("ARP IP dst invalid %s, should be %s\n", out,
net_sprint_ipv4_addr(&iface->ipv4.gw));
return;
}
net_nbuf_unref(buf2);
/* Try to find the same destination again, this should fail as there
* is a pending request in ARP cache.
*/
net_ipaddr_copy(&ipv4->dst, &dst_far);
/* Make sure prepare will not free the buf because it will be
* needed in the later test case.
*/
net_buf_ref(buf);
buf2 = net_arp_prepare(buf);
if (buf2) {
printk("ARP cache should fail now\n");
return;
}
/* Try to find the different destination, this should fail too
* as the cache table should be full.
*/
net_ipaddr_copy(&ipv4->dst, &dst_far2);
/* Make sure prepare will not free the buf because it will be
* needed in the next test case.
*/
net_buf_ref(buf);
buf2 = net_arp_prepare(buf);
if (buf2) {
printk("ARP cache should fail again\n");
return;
}
/* Restore the original address so that following test case can
* work properly.
*/
net_ipaddr_copy(&ipv4->dst, &dst);
/* The arp request packet is now verified, create an arp reply.
* The previous value of buf is stored in arp table and is not lost.
*/
buf = net_nbuf_get_reserve_rx(0);
if (!buf) {
printk("Out of mem RX reply\n");
return;
}
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr));
if (!frag) {
printk("Out of mem DATA reply\n");
return;
}
net_buf_frag_add(buf, frag);
net_nbuf_ll_reserve(buf) = net_buf_headroom(frag);
net_nbuf_iface(buf) = iface;
arp_hdr = (struct net_arp_hdr *)net_nbuf_ll(buf);
net_buf_add(buf, sizeof(struct net_arp_hdr));
net_ipaddr_copy(&arp_hdr->dst_ipaddr, &dst);
net_ipaddr_copy(&arp_hdr->src_ipaddr, &src);
buf2 = prepare_arp_reply(iface, buf, &hwaddr);
if (!buf2) {
printk("ARP reply generation failed.");
return;
}
switch (net_arp_input(buf2)) {
case NET_OK:
break;
case NET_DROP:
break;
}
/* Yielding so that network interface TX fiber can proceed. */
fiber_yield();
if (send_status < 0) {
printk("ARP reply was not sent\n");
return;
}
if (buf->ref != 1) {
printk("ARP cache should no longer own the original buffer\n");
return;
}
net_nbuf_unref(buf);
/* Then feed in ARP request */
buf = net_nbuf_get_reserve_rx(0);
if (!buf) {
printk("Out of mem RX request\n");
return;
}
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr));
if (!frag) {
printk("Out of mem DATA request\n");
return;
}
net_buf_frag_add(buf, frag);
net_nbuf_ll_reserve(buf) = sizeof(struct net_eth_hdr);
net_nbuf_iface(buf) = iface;
send_status = -EINVAL;
arp_hdr = (struct net_arp_hdr *)net_nbuf_ll(buf);
net_buf_add(frag, sizeof(struct net_arp_hdr) -
net_nbuf_ll_reserve(buf));
net_ipaddr_copy(&arp_hdr->dst_ipaddr, &src);
net_ipaddr_copy(&arp_hdr->src_ipaddr, &dst);
setup_eth_header(iface, buf, &hwaddr, NET_ETH_PTYPE_ARP);
buf2 = prepare_arp_request(iface, buf, &hwaddr);
if (!buf2) {
printk("ARP request generation failed.");
return;
}
req_test = true;
switch (net_arp_input(buf2)) {
case NET_OK:
break;
case NET_DROP:
break;
}
net_nbuf_unref(buf2);
/* Yielding so that network interface TX fiber can proceed. */
fiber_yield();
if (send_status < 0) {
printk("ARP req was not sent\n");
return;
}
net_nbuf_unref(buf);
printk("Network ARP checks passed\n");
}

View file

@ -1,6 +0,0 @@
BOARD ?= qemu_x86
MDEF_FILE = prj.mdef
KERNEL_TYPE ?= nano
CONF_FILE = prj_$(ARCH).conf
include $(ZEPHYR_BASE)/Makefile.inc

View file

@ -1,5 +0,0 @@
% Application : ICMPv6 test
% TASK NAME PRIO ENTRY STACK GROUPS
% ===================================================
TASK MAIN 7 main 2048 [EXE]

View file

@ -1,11 +0,0 @@
CONFIG_NETWORKING=y
CONFIG_NET_IPV6=y
CONFIG_NET_IPV4=y
CONFIG_NET_YAIP=y
CONFIG_NET_BUF=y
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_NET_NBUF_RX_COUNT=2
CONFIG_NET_NBUF_TX_COUNT=2
CONFIG_NET_NBUF_DATA_COUNT=5
CONFIG_NET_LOG=y
CONFIG_SYS_LOG_SHOW_COLOR=y

View file

@ -1,3 +0,0 @@
obj-y = main.o
ccflags-y += -I${srctree}/net/yaip

View file

@ -1,123 +0,0 @@
/* main.c - Application main entry point */
/*
* Copyright (c) 2016 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 <errno.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <misc/printk.h>
#include <net/buf.h>
#include "icmpv6.h"
static int handler_called;
struct header {
int status;
};
#define buf_status(buf) (((struct header *)net_buf_user_data((buf)))->status)
#define TEST_MSG "foobar devnull"
static struct nano_fifo bufs_fifo;
static struct nano_fifo data_fifo;
static NET_BUF_POOL(bufs_pool, 2, 0, &bufs_fifo, NULL, sizeof(struct header));
static NET_BUF_POOL(data_pool, 2, 128, &data_fifo, NULL, 0);
static enum net_verdict handle_test_msg(struct net_buf *buf)
{
struct net_buf *last = net_buf_frag_last(buf);
if (last->len != (strlen(TEST_MSG) + 1)) {
buf_status(buf) = -EINVAL;
} else {
buf_status(buf) = 0;
}
handler_called++;
return 0;
}
static struct net_icmpv6_handler test_handler1 = {
.type = NET_ICMPV6_ECHO_REPLY,
.code = 0,
.handler = handle_test_msg,
};
static struct net_icmpv6_handler test_handler2 = {
.type = NET_ICMPV6_ECHO_REQUEST,
.code = 0,
.handler = handle_test_msg,
};
void main(void)
{
struct net_buf *buf, *frag;
int ret;
net_buf_pool_init(bufs_pool);
net_buf_pool_init(data_pool);
net_icmpv6_register_handler(&test_handler1);
net_icmpv6_register_handler(&test_handler2);
buf = net_buf_get(&bufs_fifo, 0);
frag = net_buf_get(&data_fifo, 0);
net_buf_frag_add(buf, frag);
memcpy(net_buf_add(frag, sizeof(TEST_MSG)),
TEST_MSG, sizeof(TEST_MSG));
ret = net_icmpv6_input(buf, net_buf_frags_len(buf->frags), 0, 0);
if (!ret) {
printk("%d: Callback not called properly\n", __LINE__);
return;
}
ret = net_icmpv6_input(buf, net_buf_frags_len(buf->frags),
NET_ICMPV6_ECHO_REPLY, 0);
if (ret < 0 || buf_status(buf) != 0) {
printk("%d: Callback not called properly\n", __LINE__);
return;
}
ret = net_icmpv6_input(buf, net_buf_frags_len(buf->frags), 1, 0);
if (!ret) {
printk("%d: Callback not called properly\n", __LINE__);
return;
}
ret = net_icmpv6_input(buf, net_buf_frags_len(buf->frags),
NET_ICMPV6_ECHO_REQUEST, 0);
if (ret < 0 || buf_status(buf) != 0) {
printk("%d: Callback not called properly\n", __LINE__);
return;
}
if (handler_called != 2) {
printk("%d: Callbacks not called properly\n", __LINE__);
return;
}
printk("ICMPv6 tests passed\n");
}

View file

@ -1,6 +0,0 @@
BOARD ?= qemu_x86
MDEF_FILE = prj.mdef
KERNEL_TYPE ?= nano
CONF_FILE = prj_$(ARCH).conf
include $(ZEPHYR_BASE)/Makefile.inc

View file

@ -1,5 +0,0 @@
% Application : Network test
% TASK NAME PRIO ENTRY STACK GROUPS
% ===================================================
TASK MAIN 7 mainloop 2048 [EXE]

View file

@ -1,14 +0,0 @@
CONFIG_NETWORKING=y
CONFIG_NET_IPV6=y
CONFIG_NET_IPV4=y
CONFIG_NET_YAIP=y
CONFIG_NET_BUF=y
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_NET_NBUF_RX_COUNT=2
CONFIG_NET_NBUF_TX_COUNT=2
CONFIG_NET_NBUF_DATA_COUNT=5
CONFIG_NET_LOG=y
CONFIG_SYS_LOG_SHOW_COLOR=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_IFACE_UNICAST_IPV6_ADDR_COUNT=3

View file

@ -1,2 +0,0 @@
obj-y = main.o
ccflags-y += -I${srctree}/net/yaip

View file

@ -1,433 +0,0 @@
/* main.c - Application main entry point */
/*
* Copyright (c) 2016 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 <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <device.h>
#include <init.h>
#include <misc/printk.h>
#include <net/net_core.h>
#include <net/nbuf.h>
#include <net/net_ip.h>
#define NET_DEBUG 1
#include "net_private.h"
#define TEST_BYTE_1(value, expected) \
do { \
char out[3]; \
net_byte_to_hex(out, value, 'A', true); \
if (strcmp(out, expected)) { \
printk("Test 0x%s failed.\n", expected); \
return; \
} \
} while (0)
#define TEST_BYTE_2(value, expected) \
do { \
char out[3]; \
net_byte_to_hex(out, value, 'a', true); \
if (strcmp(out, expected)) { \
printk("Test 0x%s failed.\n", expected); \
return; \
} \
} while (0)
#define TEST_LL_6(a, b, c, d, e, f, expected) \
do { \
uint8_t ll[] = { a, b, c, d, e, f }; \
if (strcmp(net_sprint_ll_addr(ll, sizeof(ll)), \
expected)) { \
printk("Test %s failed.\n", expected); \
return; \
} \
} while (0)
#define TEST_LL_8(a, b, c, d, e, f, g, h, expected) \
do { \
uint8_t ll[] = { a, b, c, d, e, f, g, h }; \
if (strcmp(net_sprint_ll_addr(ll, sizeof(ll)), \
expected)) { \
printk("Test %s failed.\n", expected); \
return; \
} \
} while (0)
#define TEST_LL_6_TWO(a, b, c, d, e, f, expected) \
do { \
uint8_t ll1[] = { a, b, c, d, e, f }; \
uint8_t ll2[] = { f, e, d, c, b, a }; \
char out[2 * sizeof("xx:xx:xx:xx:xx:xx") + 1 + 1]; \
sprintf(out, "%s ", \
net_sprint_ll_addr(ll1, sizeof(ll1))); \
sprintf(out + sizeof("xx:xx:xx:xx:xx:xx"), "%s", \
net_sprint_ll_addr(ll2, sizeof(ll2))); \
if (strcmp(out, expected)) { \
printk("Test %s failed, got %s\n", expected, out); \
return; \
} \
} while (0)
#define TEST_IPV6(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, expected) \
do { \
struct in6_addr addr = { { { a, b, c, d, e, f, g, h, \
i, j, k, l, m, n, o, p } } }; \
char *ptr = net_sprint_ipv6_addr(&addr); \
if (strcmp(ptr, expected)) { \
printk("Test %s failed, got %s\n", expected, ptr); \
return; \
} \
} while (0)
#define TEST_IPV4(a, b, c, d, expected) \
do { \
struct in_addr addr = { { { a, b, c, d } } }; \
char *ptr = net_sprint_ipv4_addr(&addr); \
if (strcmp(ptr, expected)) { \
printk("Test %s failed, got %s\n", expected, ptr); \
return; \
} \
} while (0)
struct net_test_context {
uint8_t mac_addr[6];
struct net_linkaddr ll_addr;
};
int net_test_init(struct device *dev)
{
struct net_test_context *net_test_context = dev->driver_data;
dev->driver_api = NULL;
net_test_context = net_test_context;
return 0;
}
static uint8_t *net_test_get_mac(struct device *dev)
{
struct net_test_context *context = dev->driver_data;
if (context->mac_addr[0] == 0x00) {
/* 10-00-00-00-00 to 10-00-00-00-FF Documentation RFC7042 */
context->mac_addr[0] = 0x10;
context->mac_addr[1] = 0x00;
context->mac_addr[2] = 0x00;
context->mac_addr[3] = 0x00;
context->mac_addr[4] = 0x00;
context->mac_addr[5] = sys_rand32_get();
}
return context->mac_addr;
}
static void net_test_iface_init(struct net_if *iface)
{
uint8_t *mac = net_test_get_mac(net_if_get_device(iface));
net_if_set_link_addr(iface, mac, 8);
}
struct net_test_context net_test_context_data;
static struct net_if_api net_test_if_api = {
.init = net_test_iface_init
};
NET_DEVICE_INIT(net_addr_test, "net_addr_test",
net_test_init, &net_test_context_data, NULL,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&net_test_if_api, 127);
#ifdef CONFIG_MICROKERNEL
void mainloop(void)
#else
void main(void)
#endif
{
struct in6_addr loopback = IN6ADDR_LOOPBACK_INIT;
struct in6_addr any = IN6ADDR_ANY_INIT;
struct in6_addr mcast = { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x2 } } };
struct in6_addr addr6 = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
struct in6_addr addr6_pref1 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x1 } } };
struct in6_addr addr6_pref2 = { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0x2 } } };
struct in6_addr addr6_pref3 = { { { 0x20, 0x01, 0x0d, 0xb8, 0x64, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0x2 } } };
struct in6_addr *tmp;
struct net_if_addr *ifaddr1, *ifaddr2;
struct net_if_mcast_addr *ifmaddr1;
struct in_addr addr4 = { { { 192, 168, 0, 1 } } };
struct in_addr match_addr = { { { 192, 168, 0, 2 } } };
struct in_addr fail_addr = { { { 10, 1, 0, 2 } } };
struct in_addr netmask = { { { 255, 255, 255, 0 } } };
struct in_addr gw = { { { 192, 168, 0, 42 } } };
struct in_addr loopback4 = { { { 127, 0, 0, 1 } } };
struct net_if *iface;
int i;
TEST_BYTE_1(0xde, "DE");
TEST_BYTE_1(0x09, "09");
TEST_BYTE_2(0xa9, "a9");
TEST_BYTE_2(0x80, "80");
TEST_LL_6(0x12, 0x9f, 0xe3, 0x01, 0x7f, 0x00, "12:9F:E3:01:7F:00");
TEST_LL_8(0x12, 0x9f, 0xe3, 0x01, 0x7f, 0x00, 0xff, 0x0f, \
"12:9F:E3:01:7F:00:FF:0F");
TEST_LL_6_TWO(0x12, 0x9f, 0xe3, 0x01, 0x7f, 0x00, \
"12:9F:E3:01:7F:00 00:7F:01:E3:9F:12");
TEST_IPV6(0x20, 1, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, \
"2001:db8::1");
TEST_IPV6(0x20, 0x01, 0x0d, 0xb8, 0x12, 0x34, 0x56, 0x78, \
0x9a, 0xbc, 0xde, 0xf0, 0x01, 0x02, 0x03, 0x04, \
"2001:db8:1234:5678:9abc:def0:102:304");
TEST_IPV6(0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x0c, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, \
"fe80::cb8:0:0:2");
TEST_IPV6(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, \
"::1");
TEST_IPV6(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
"::");
TEST_IPV4(192, 168, 0, 1, "192.168.0.1");
TEST_IPV4(0, 0, 0, 0, "0.0.0.0");
TEST_IPV4(127, 0, 0, 1, "127.0.0.1");
printk("IP address print tests passed\n");
if (!net_is_ipv6_addr_loopback(&loopback)) {
printk("IPv6 loopback address check failed.\n");
return;
}
if (!net_is_ipv6_addr_mcast(&mcast)) {
printk("IPv6 multicast address check failed.\n");
return;
}
ifaddr1 = net_if_ipv6_addr_add(net_if_get_default(),
&addr6,
NET_ADDR_MANUAL,
0);
if (!ifaddr1) {
printk("IPv6 interface address add failed\n");
return;
}
ifaddr2 = net_if_ipv6_addr_lookup(&addr6);
if (ifaddr1 != ifaddr2) {
printk("IPv6 interface address mismatch\n");
return;
}
if (net_is_my_ipv6_addr(&loopback)) {
printk("My IPv6 loopback address check failed\n");
return;
}
if (!net_is_my_ipv6_addr(&addr6)) {
printk("My IPv6 address check failed\n");
return;
}
if (!net_is_ipv6_prefix((uint8_t *)&addr6_pref1,
(uint8_t *)&addr6_pref2,
64)) {
printk("Same IPv6 prefix test failed\n");
return;
}
if (net_is_ipv6_prefix((uint8_t *)&addr6_pref1,
(uint8_t *)&addr6_pref3,
64)) {
printk("Different IPv6 prefix test failed\n");
return;
}
if (net_is_ipv6_prefix((uint8_t *)&addr6_pref1,
(uint8_t *)&addr6_pref2,
128)) {
printk("Different full IPv6 prefix test failed\n");
return;
}
if (net_is_ipv6_prefix((uint8_t *)&addr6_pref1,
(uint8_t *)&addr6_pref3,
255)) {
printk("Too long prefix test failed\n");
return;
}
ifmaddr1 = net_if_ipv6_maddr_add(net_if_get_default(), &mcast);
if (!ifmaddr1) {
printk("IPv6 multicast address add failed\n");
return;
}
ifmaddr1 = net_if_ipv6_maddr_add(net_if_get_default(), &addr6);
if (ifmaddr1) {
printk("IPv6 multicast address could be added failed\n");
return;
}
ifaddr1 = net_if_ipv4_addr_add(net_if_get_default(),
&addr4,
NET_ADDR_MANUAL,
0);
if (!ifaddr1) {
printk("IPv4 interface address add failed\n");
return;
}
if (!net_is_my_ipv4_addr(&addr4)) {
printk("My IPv4 address check failed\n");
return;
}
if (net_is_my_ipv4_addr(&loopback4)) {
printk("My IPv4 loopback address check failed\n");
return;
}
if (memcmp(net_if_ipv6_unspecified_addr(), &any, sizeof(any))) {
printk("My IPv6 unspecified address check failed\n");
return;
}
ifaddr2 = net_if_ipv6_addr_add(net_if_get_default(),
&addr6,
NET_ADDR_AUTOCONF,
0);
if (!ifaddr2) {
printk("IPv6 ll address autoconf add failed\n");
return;
}
ifaddr2->addr_state = NET_ADDR_PREFERRED;
tmp = net_if_ipv6_get_ll(net_if_get_default(), NET_ADDR_PREFERRED);
if (memcmp(tmp, &addr6.s6_addr, sizeof(struct in6_addr))) {
printk("IPv6 ll address fetch failed\n");
return;
}
ifaddr2->addr_state = NET_ADDR_DEPRECATED;
tmp = net_if_ipv6_get_ll(net_if_get_default(), NET_ADDR_PREFERRED);
if (tmp || !memcmp(tmp, &any, sizeof(struct in6_addr))) {
printk("IPv6 preferred ll address fetch failed\n");
return;
}
ifaddr1 = net_if_ipv6_addr_add(net_if_get_default(),
&addr6_pref2,
NET_ADDR_AUTOCONF,
0);
if (!ifaddr1) {
printk("IPv6 global address autoconf add failed\n");
return;
}
ifaddr1->addr_state = NET_ADDR_PREFERRED;
/* Two tests, first with interface given, then when iface is NULL */
for (i = 0, iface = net_if_get_default(); i < 2; i++, iface = NULL) {
ifaddr2->addr_state = NET_ADDR_DEPRECATED;
tmp = net_if_ipv6_select_src_addr(iface, &addr6_pref1);
if (!tmp) {
printk("IPv6 src addr selection failed, iface %p\n",
iface);
return;
}
printk("Selected IPv6 address %s, iface %p\n",
net_sprint_ipv6_addr(tmp), iface);
if (memcmp(tmp->s6_addr, &addr6_pref2.s6_addr,
sizeof(struct in6_addr))) {
printk("IPv6 wrong src address selected, iface %p\n",
iface);
return;
}
/* Now we should get :: address */
tmp = net_if_ipv6_select_src_addr(iface, &addr6);
if (!tmp) {
printk("IPv6 src any addr selection failed, "
"iface %p\n", iface);
return;
}
printk("Selected IPv6 address %s, iface %p\n",
net_sprint_ipv6_addr(tmp), iface);
if (memcmp(tmp->s6_addr, &any.s6_addr,
sizeof(struct in6_addr))) {
printk("IPv6 wrong src any address selected, "
"iface %p\n", iface);
return;
}
ifaddr2->addr_state = NET_ADDR_PREFERRED;
/* Now we should get ll address */
tmp = net_if_ipv6_select_src_addr(iface, &addr6);
if (!tmp) {
printk("IPv6 src ll addr selection failed, iface %p\n",
iface);
return;
}
printk("Selected IPv6 address %s, iface %p\n",
net_sprint_ipv6_addr(tmp), iface);
if (memcmp(tmp->s6_addr, &addr6.s6_addr,
sizeof(struct in6_addr))) {
printk("IPv6 wrong src ll address selected, "
"iface %p\n", iface);
return;
}
}
iface = net_if_get_default();
net_if_set_gw(iface, &gw);
net_if_set_netmask(iface, &netmask);
if (net_ipv4_addr_mask_cmp(iface, &fail_addr)) {
printk("IPv4 wrong match failed\n");
return;
}
if (!net_ipv4_addr_mask_cmp(iface, &match_addr)) {
printk("IPv4 match failed\n");
return;
}
printk("IP address checks passed\n");
}

View file

@ -1,6 +0,0 @@
BOARD ?= qemu_x86
MDEF_FILE = prj.mdef
KERNEL_TYPE ?= nano
CONF_FILE = prj_$(ARCH).conf
include $(ZEPHYR_BASE)/Makefile.inc

View file

@ -1,5 +0,0 @@
% Application : Buffer test
% TASK NAME PRIO ENTRY STACK GROUPS
% ===================================================
TASK MAIN 7 mainloop 2048 [EXE]

View file

@ -1,12 +0,0 @@
CONFIG_NETWORKING=y
CONFIG_NET_IPV6=y
CONFIG_NET_YAIP=y
CONFIG_NET_BUF=y
CONFIG_NET_BUF_DEBUG=y
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_NET_NBUF_RX_COUNT=2
CONFIG_NET_NBUF_TX_COUNT=2
CONFIG_NET_NBUF_DATA_COUNT=5
CONFIG_NET_LOG=y
CONFIG_SYS_LOG_SHOW_COLOR=y
CONFIG_NETWORK_IP_STACK_DEBUG_NET_BUF=y

View file

@ -1 +0,0 @@
obj-y = main.o

View file

@ -1,170 +0,0 @@
/* main.c - Application main entry point */
/*
* Copyright (c) 2016 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 <stdint.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <misc/printk.h>
#include <net/nbuf.h>
#include <net/net_ip.h>
#define LL_RESERVE 28
struct ipv6_hdr {
uint8_t vtc;
uint8_t tcflow;
uint16_t flow;
uint8_t len[2];
uint8_t nexthdr;
uint8_t hop_limit;
struct in6_addr src;
struct in6_addr dst;
} __attribute__((__packed__));
struct udp_hdr {
uint16_t src_port;
uint16_t dst_port;
uint16_t len;
uint16_t chksum;
} __attribute__((__packed__));
static const char example_data[] =
"0123456789abcdefghijklmnopqrstuvxyz!#¤%&/()=?"
"0123456789abcdefghijklmnopqrstuvxyz!#¤%&/()=?"
"0123456789abcdefghijklmnopqrstuvxyz!#¤%&/()=?"
"0123456789abcdefghijklmnopqrstuvxyz!#¤%&/()=?"
"0123456789abcdefghijklmnopqrstuvxyz!#¤%&/()=?"
"0123456789abcdefghijklmnopqrstuvxyz!#¤%&/()=?";
static int test_ipv6_multi_frags(void)
{
struct net_buf *buf, *frag;
struct ipv6_hdr *ipv6;
struct udp_hdr *udp;
int bytes, remaining = strlen(example_data), pos = 0;
/* Example of multi fragment scenario with IPv6 */
buf = net_nbuf_get_reserve_rx(0);
frag = net_nbuf_get_reserve_data(LL_RESERVE);
/* Place the IP + UDP header in the first fragment */
if (!net_buf_tailroom(frag)) {
ipv6 = (struct ipv6_hdr *)(frag->data);
udp = (struct udp_hdr *)((void *)ipv6 + sizeof(*ipv6));
if (net_buf_tailroom(frag) < sizeof(ipv6)) {
printk("Not enough space for IPv6 header, "
"needed %d bytes, has %d bytes\n",
sizeof(ipv6), net_buf_tailroom(frag));
return -EINVAL;
}
net_buf_add(frag, sizeof(ipv6));
if (net_buf_tailroom(frag) < sizeof(udp)) {
printk("Not enough space for UDP header, "
"needed %d bytes, has %d bytes\n",
sizeof(udp), net_buf_tailroom(frag));
return -EINVAL;
}
net_nbuf_appdata(buf) = (void *)udp + sizeof(*udp);
net_nbuf_appdatalen(buf) = 0;
}
net_buf_frag_add(buf, frag);
/* Put some data to rest of the fragments */
frag = net_nbuf_get_reserve_data(LL_RESERVE);
if (net_buf_tailroom(frag) -
(CONFIG_NET_NBUF_DATA_SIZE - LL_RESERVE)) {
printk("Invalid number of bytes available in the buf, "
"should be 0 but was %d - %d\n",
net_buf_tailroom(frag),
CONFIG_NET_NBUF_DATA_SIZE - LL_RESERVE);
return -EINVAL;
}
if (((int)net_buf_tailroom(frag) - remaining) > 0) {
printk("We should have been out of space now, "
"tailroom %d user data len %d\n",
net_buf_tailroom(frag),
strlen(example_data));
return -EINVAL;
}
while (remaining > 0) {
int copy;
bytes = net_buf_tailroom(frag);
copy = remaining > bytes ? bytes : remaining;
memcpy(net_buf_add(frag, copy), &example_data[pos], copy);
printk("Remaining %d left %d copy %d\n", remaining, bytes,
copy);
pos += bytes;
remaining -= bytes;
if (net_buf_tailroom(frag) - (bytes - copy)) {
printk("There should have not been any tailroom left, "
"tailroom %d\n",
net_buf_tailroom(frag) - (bytes - copy));
return -EINVAL;
}
net_buf_frag_add(buf, frag);
if (remaining > 0) {
frag = net_nbuf_get_reserve_data(LL_RESERVE);
}
}
bytes = net_buf_frags_len(buf->frags);
if (bytes != strlen(example_data)) {
printk("Invalid number of bytes in message, %d vs %d\n",
strlen(example_data), bytes);
return -EINVAL;
}
/* Normally one should not unref the fragment list like this
* because it will leave the buf->frags pointing to already
* freed fragment.
*/
net_nbuf_unref(buf->frags);
if (!buf->frags) {
printk("Fragment list should not be empty.\n");
return -EINVAL;
}
buf->frags = NULL; /* to prevent double free */
net_nbuf_unref(buf);
return 0;
}
#ifdef CONFIG_MICROKERNEL
void mainloop(void)
#else
void main(void)
#endif
{
if (test_ipv6_multi_frags() < 0) {
return;
}
printk("nbuf tests passed\n");
}

View file

@ -1,6 +0,0 @@
BOARD ?= qemu_x86
MDEF_FILE = prj.mdef
KERNEL_TYPE ?= nano
CONF_FILE = prj_$(ARCH).conf
include $(ZEPHYR_BASE)/Makefile.inc

View file

@ -1,5 +0,0 @@
% Application : Network test
% TASK NAME PRIO ENTRY STACK GROUPS
% ===================================================
TASK MAIN 7 mainloop 2048 [EXE]

View file

@ -1,15 +0,0 @@
CONFIG_NETWORKING=y
CONFIG_NET_IPV6=y
CONFIG_NET_IPV4=y
CONFIG_NET_YAIP=y
CONFIG_NET_BUF=y
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_NET_NBUF_RX_COUNT=2
CONFIG_NET_NBUF_TX_COUNT=2
CONFIG_NET_NBUF_DATA_COUNT=7
CONFIG_NET_LOG=y
CONFIG_SYS_LOG_SHOW_COLOR=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_IFACE_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NETWORK_IP_STACK_DEBUG_UTILS=y

View file

@ -1,2 +0,0 @@
obj-y = main.o
ccflags-y += -I${srctree}/net/yaip

View file

@ -1,377 +0,0 @@
/* main.c - Application main entry point */
/*
* Copyright (c) 2016 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 <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <device.h>
#include <init.h>
#include <misc/printk.h>
#include <net/net_core.h>
#include <net/nbuf.h>
#include <net/net_ip.h>
#include <net/arp.h>
#define NET_DEBUG 1
#include "net_private.h"
/* ICMPv6 frame (104 bytes) */
static const unsigned char pkt1[104] = {
/* IPv6 header starts here */
0x60, 0x0c, 0x21, 0x63, 0x00, 0x40, 0x3a, 0x40, /* `.!c.@:@ */
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, /* ....... */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, /* ........ */
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, /* ....... */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* ........ */
/* ICMPv6 header starts here */
0x80, 0x00, 0x65, 0x6a, 0x68, 0x47, 0x00, 0x01, /* ..ejhG.. */
0x95, 0x5f, 0x3c, 0x57, 0x00, 0x00, 0x00, 0x00, /* ._<W.... */
0xbc, 0xd3, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, /* ........ */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* ........ */
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* ........ */
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* !"#$%&' */
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* ()*+,-./ */
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37 /* 01234567 */
};
/* ICMPv6 Frame (176 bytes) */
static const unsigned char pkt2[176] = {
/* IPv6 header starts here */
0x60, 0x0c, 0x21, 0x63, 0x00, 0x88, 0x3a, 0x40, /* `.!c..:@ */
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, /* ....... */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, /* ........ */
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, /* ....... */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* ........ */
/* ICMPv6 header starts here */
0x80, 0x00, 0x38, 0xbf, 0x32, 0x8d, 0x00, 0x01, /* ..8.2... */
0x78, 0x78, 0x3c, 0x57, 0x00, 0x00, 0x00, 0x00, /* xx<W.... */
0x63, 0xdb, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, /* c....... */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* ........ */
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* ........ */
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* !"#$%&' */
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* ()*+,-./ */
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 89:;<=>? */
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* HIJKLMNO */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* PQRSTUVW */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* XYZ[\]^_ */
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* `abcdefg */
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* hijklmno */
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* pqrstuvw */
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f /* xyz{|}~. */
};
/* Frame (199 bytes) */
static const unsigned char pkt3[199] = {
/* IPv6 header starts here */
0x60, 0x0c, 0x21, 0x63, 0x00, 0x9f, 0x3a, 0x40, /* `.!c..:@ */
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, /* ....... */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, /* ........ */
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, /* ....... */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* ........ */
/* ICMPv6 header starts here */
0x80, 0x00, 0x57, 0xac, 0x32, 0xeb, 0x00, 0x01, /* ..W.2... */
0x8f, 0x79, 0x3c, 0x57, 0x00, 0x00, 0x00, 0x00, /* .y<W.... */
0xa8, 0x78, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, /* .x...... */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* ........ */
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* ........ */
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* !"#$%&' */
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* ()*+,-./ */
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 01234567 */
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 89:;<=>? */
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* HIJKLMNO */
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* PQRSTUVW */
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* XYZ[\]^_ */
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* `abcdefg */
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* hijklmno */
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* pqrstuvw */
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* xyz{|}~. */
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, /* ........ */
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* ........ */
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96 /* ....... */
};
/* ICMP reply (98 bytes) */
static const unsigned char pkt4[98] = {
/* Ethernet header starts here */
0x1a, 0xc9, 0xb7, 0xb6, 0x46, 0x70, 0x10, 0x00, /* ....Fp.. */
0x00, 0x00, 0x00, 0x68, 0x08, 0x00,
/* IPv4 header starts here */
0x45, 0x00, /* ...h..E. */
0x00, 0x54, 0x33, 0x35, 0x40, 0x00, 0x40, 0x01, /* .T35@.@. */
0xf6, 0xf5, 0xc0, 0x00, 0x02, 0x01, 0x0a, 0xed, /* ........ */
0x43, 0x90,
/* ICMP header starts here */
0x00, 0x00, 0x14, 0xe2, 0x59, 0xe2, /* C.....Y. */
0x00, 0x01, 0x68, 0x4b, 0x44, 0x57, 0x00, 0x00, /* ..hKDW.. */
0x00, 0x00, 0x1a, 0xc5, 0x0b, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, /* ........ */
0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, /* ........ */
0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, /* .. !"#$% */
0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, /* &'()*+,- */
0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, /* ./012345 */
0x36, 0x37 /* 67 */
};
/* ICMP request (98 bytes) */
static const unsigned char pkt5[98] = {
/* Ethernet header starts here */
0x10, 0x00, 0x00, 0x00, 0x00, 0x68, 0x1a, 0xc9, /* .....h.. */
0xb7, 0xb6, 0x46, 0x70, 0x08, 0x00,
/* IPv4 header starts here */
0x45, 0x00, /* ..Fp..E. */
0x00, 0x54, 0x33, 0x35, 0x40, 0x00, 0x40, 0x01, /* .T35@.@. */
0xf6, 0xf5, 0x0a, 0xed, 0x43, 0x90, 0xc0, 0x00, /* ....C... */
0x02, 0x01,
/* ICMP header starts here */
0x08, 0x00, 0x0c, 0xe2, 0x59, 0xe2, /* ......Y. */
0x00, 0x01, 0x68, 0x4b, 0x44, 0x57, 0x00, 0x00, /* ..hKDW.. */
0x00, 0x00, 0x1a, 0xc5, 0x0b, 0x00, 0x00, 0x00, /* ........ */
0x00, 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, /* ........ */
0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, /* ........ */
0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, /* .. !"#$% */
0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, /* &'()*+,- */
0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, /* ./012345 */
0x36, 0x37 /* 67 */
};
#ifdef CONFIG_MICROKERNEL
void mainloop(void)
#else
void main(void)
#endif
{
struct net_buf *frag, *buf;
uint16_t chksum, orig_chksum;
int hdr_len, i, chunk, datalen, total = 0;
/* Packet fits to one fragment */
buf = net_nbuf_get_reserve_rx(0);
frag = net_nbuf_get_reserve_data(10);
net_buf_frag_add(buf, frag);
memcpy(net_buf_add(frag, sizeof(pkt1)), pkt1, sizeof(pkt1));
if (frag->len != sizeof(pkt1)) {
printk("Fragment len %d invalid, should be %d\n",
frag->len, sizeof(pkt1));
return;
}
net_nbuf_ip_hdr_len(buf) = sizeof(struct net_ipv6_hdr);
net_nbuf_family(buf) = AF_INET6;
net_nbuf_ext_len(buf) = 0;
/* We need to zero the ICMP checksum */
hdr_len = net_nbuf_ip_hdr_len(buf);
orig_chksum = (frag->data[hdr_len + 2] << 8) + frag->data[hdr_len + 3];
frag->data[hdr_len + 2] = 0;
frag->data[hdr_len + 3] = 0;
chksum = ntohs(~net_calc_chksum(buf, IPPROTO_ICMPV6));
if (chksum != orig_chksum) {
printk("Invalid chksum 0x%x in pkt1, should be 0x%x\n",
chksum, orig_chksum);
return;
}
net_nbuf_unref(buf);
/* Then a case where there will be two fragments */
buf = net_nbuf_get_reserve_rx(0);
frag = net_nbuf_get_reserve_data(10);
net_buf_frag_add(buf, frag);
memcpy(net_buf_add(frag, sizeof(pkt2) / 2), pkt2, sizeof(pkt2) / 2);
net_nbuf_ip_hdr_len(buf) = sizeof(struct net_ipv6_hdr);
net_nbuf_family(buf) = AF_INET6;
net_nbuf_ext_len(buf) = 0;
hdr_len = net_nbuf_ip_hdr_len(buf);
orig_chksum = (frag->data[hdr_len + 2] << 8) + frag->data[hdr_len + 3];
frag->data[hdr_len + 2] = 0;
frag->data[hdr_len + 3] = 0;
frag = net_nbuf_get_reserve_data(10);
net_buf_frag_add(buf, frag);
memcpy(net_buf_add(frag, sizeof(pkt2) - sizeof(pkt2) / 2),
pkt2 + sizeof(pkt2) / 2, sizeof(pkt2) - sizeof(pkt2) / 2);
chksum = ntohs(~net_calc_chksum(buf, IPPROTO_ICMPV6));
if (chksum != orig_chksum) {
printk("Invalid chksum 0x%x in pkt2, should be 0x%x\n",
chksum, orig_chksum);
return;
}
net_nbuf_unref(buf);
/* Then a case where there will be two fragments but odd data size */
buf = net_nbuf_get_reserve_rx(0);
frag = net_nbuf_get_reserve_data(10);
net_buf_frag_add(buf, frag);
memcpy(net_buf_add(frag, sizeof(pkt3) / 2), pkt3, sizeof(pkt3) / 2);
printk("First fragment will have %d bytes\n", sizeof(pkt3) / 2);
net_nbuf_ip_hdr_len(buf) = sizeof(struct net_ipv6_hdr);
net_nbuf_family(buf) = AF_INET6;
net_nbuf_ext_len(buf) = 0;
hdr_len = net_nbuf_ip_hdr_len(buf);
orig_chksum = (frag->data[hdr_len + 2] << 8) + frag->data[hdr_len + 3];
frag->data[hdr_len + 2] = 0;
frag->data[hdr_len + 3] = 0;
frag = net_nbuf_get_reserve_data(10);
net_buf_frag_add(buf, frag);
memcpy(net_buf_add(frag, sizeof(pkt3) - sizeof(pkt3) / 2),
pkt3 + sizeof(pkt3) / 2, sizeof(pkt3) - sizeof(pkt3) / 2);
printk("Second fragment will have %d bytes\n",
sizeof(pkt3) - sizeof(pkt3) / 2);
chksum = ntohs(~net_calc_chksum(buf, IPPROTO_ICMPV6));
if (chksum != orig_chksum) {
printk("Invalid chksum 0x%x in pkt3, should be 0x%x\n",
chksum, orig_chksum);
return;
}
net_nbuf_unref(buf);
/* Then a case where there will be several fragments */
buf = net_nbuf_get_reserve_rx(0);
frag = net_nbuf_get_reserve_data(10);
net_buf_frag_add(buf, frag);
memcpy(net_buf_add(frag, sizeof(struct net_ipv6_hdr)), pkt3,
sizeof(struct net_ipv6_hdr));
printk("[0] IPv6 fragment will have %d bytes\n", frag->len);
net_nbuf_ip_hdr_len(buf) = sizeof(struct net_ipv6_hdr);
net_nbuf_family(buf) = AF_INET6;
net_nbuf_ext_len(buf) = 0;
chunk = 29;
datalen = sizeof(pkt3) - sizeof(struct net_ipv6_hdr);
for (i = 0; i < datalen/chunk; i++) {
/* Next fragments will contain the data in odd sizes */
frag = net_nbuf_get_reserve_data(10);
net_buf_frag_add(buf, frag);
memcpy(net_buf_add(frag, chunk),
pkt3 + sizeof(struct net_ipv6_hdr) + i * chunk, chunk);
total += chunk;
printk("[%d] fragment will have %d bytes, icmp data %d\n",
i + 1, frag->len, total);
if (i == 0) {
/* First fragment will contain the ICMP header
* and we must clear the checksum field.
*/
orig_chksum = (frag->data[2] << 8) +
frag->data[3];
frag->data[2] = 0;
frag->data[3] = 0;
}
}
if ((datalen - total) > 0) {
frag = net_nbuf_get_reserve_data(10);
net_buf_frag_add(buf, frag);
memcpy(net_buf_add(frag, datalen - total),
pkt3 + sizeof(struct net_ipv6_hdr) + i * chunk,
datalen - total);
total += datalen - total;
printk("[%d] last fragment will have %d bytes, icmp data %d\n",
i + 1, frag->len, total);
}
if ((total + sizeof(struct net_ipv6_hdr)) != sizeof(pkt3) ||
(total + sizeof(struct net_ipv6_hdr)) !=
net_buf_frags_len(buf->frags)) {
printk("pkt3 size differs from fragment sizes, "
"pkt3 size %d frags size %d calc total %d\n",
sizeof(pkt3), net_buf_frags_len(buf->frags),
total + sizeof(struct net_ipv6_hdr));
return;
}
chksum = ntohs(~net_calc_chksum(buf, IPPROTO_ICMPV6));
if (chksum != orig_chksum) {
printk("Invalid chksum 0x%x in pkt3, should be 0x%x\n",
chksum, orig_chksum);
return;
}
net_nbuf_unref(buf);
/* Another packet that fits to one fragment.
* This one has ethernet header before IPv4 data.
*/
buf = net_nbuf_get_reserve_rx(0);
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr));
net_buf_frag_add(buf, frag);
net_nbuf_ll_reserve(buf) = sizeof(struct net_eth_hdr);
memcpy(net_nbuf_ll(buf), pkt4, sizeof(pkt4));
net_buf_add(frag, sizeof(pkt4) - sizeof(struct net_eth_hdr));
net_nbuf_ip_hdr_len(buf) = sizeof(struct net_ipv4_hdr);
net_nbuf_family(buf) = AF_INET;
net_nbuf_ext_len(buf) = 0;
hdr_len = net_nbuf_ip_hdr_len(buf);
orig_chksum = (frag->data[hdr_len + 2] << 8) + frag->data[hdr_len + 3];
frag->data[hdr_len + 2] = 0;
frag->data[hdr_len + 3] = 0;
chksum = ntohs(~net_calc_chksum(buf, IPPROTO_ICMP));
if (chksum != orig_chksum) {
printk("Invalid chksum 0x%x in pkt4, should be 0x%x\n",
chksum, orig_chksum);
return;
}
net_nbuf_unref(buf);
/* Another packet that fits to one fragment and which has correct
* checksum. This one has ethernet header before IPv4 data.
*/
buf = net_nbuf_get_reserve_rx(0);
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr));
net_buf_frag_add(buf, frag);
net_nbuf_ll_reserve(buf) = sizeof(struct net_eth_hdr);
memcpy(net_nbuf_ll(buf), pkt5, sizeof(pkt5));
net_buf_add(frag, sizeof(pkt5) - sizeof(struct net_eth_hdr));
net_nbuf_ip_hdr_len(buf) = sizeof(struct net_ipv4_hdr);
net_nbuf_family(buf) = AF_INET;
net_nbuf_ext_len(buf) = 0;
hdr_len = net_nbuf_ip_hdr_len(buf);
orig_chksum = (frag->data[hdr_len + 2] << 8) + frag->data[hdr_len + 3];
frag->data[hdr_len + 2] = 0;
frag->data[hdr_len + 3] = 0;
chksum = ntohs(~net_calc_chksum(buf, IPPROTO_ICMP));
if (chksum != orig_chksum) {
printk("Invalid chksum 0x%x in pkt5, should be 0x%x\n",
chksum, orig_chksum);
return;
}
net_nbuf_unref(buf);
printk("Network utils checks passed\n");
}