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:
parent
5249b8a52d
commit
3e63a74514
63 changed files with 0 additions and 7267 deletions
|
@ -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
|
|
|
@ -1,3 +0,0 @@
|
||||||
subdir-ccflags-y +=-I${srctree}/net/yaip
|
|
||||||
|
|
||||||
obj-$(CONFIG_SLIP) = slip.o
|
|
|
@ -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);
|
|
|
@ -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
|
||||||
|
|
|
@ -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 = .;
|
||||||
|
|
|
@ -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 = .;
|
||||||
|
|
|
@ -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 */
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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 */
|
|
|
@ -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__ */
|
|
|
@ -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 */
|
|
|
@ -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__ */
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
147
net/yaip/Kconfig
147
net/yaip/Kconfig
|
@ -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"
|
|
|
@ -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
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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 */
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -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 */
|
|
|
@ -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.
|
|
|
@ -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
|
|
|
@ -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));
|
|
||||||
}
|
|
|
@ -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);
|
|
|
@ -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);
|
|
624
net/yaip/nbuf.c
624
net/yaip/nbuf.c
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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);
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 */
|
|
350
net/yaip/utils.c
350
net/yaip/utils.c
|
@ -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;
|
|
||||||
}
|
|
|
@ -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/
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
BOARD ?= qemu_x86
|
|
||||||
MDEF_FILE = prj.mdef
|
|
||||||
KERNEL_TYPE ?= nano
|
|
||||||
CONF_FILE = prj_$(ARCH).conf
|
|
||||||
|
|
||||||
include $(ZEPHYR_BASE)/Makefile.inc
|
|
|
@ -1,5 +0,0 @@
|
||||||
% Application : Network test
|
|
||||||
|
|
||||||
% TASK NAME PRIO ENTRY STACK GROUPS
|
|
||||||
% ===================================================
|
|
||||||
TASK MAIN 7 mainloop 2048 [EXE]
|
|
|
@ -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
|
|
|
@ -1,2 +0,0 @@
|
||||||
obj-y = main.o
|
|
||||||
ccflags-y += -I${srctree}/net/yaip
|
|
|
@ -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(ð_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 *)ð_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(ð_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 *)ð_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");
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
BOARD ?= qemu_x86
|
|
||||||
MDEF_FILE = prj.mdef
|
|
||||||
KERNEL_TYPE ?= nano
|
|
||||||
CONF_FILE = prj_$(ARCH).conf
|
|
||||||
|
|
||||||
include $(ZEPHYR_BASE)/Makefile.inc
|
|
|
@ -1,5 +0,0 @@
|
||||||
% Application : ICMPv6 test
|
|
||||||
|
|
||||||
% TASK NAME PRIO ENTRY STACK GROUPS
|
|
||||||
% ===================================================
|
|
||||||
TASK MAIN 7 main 2048 [EXE]
|
|
|
@ -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
|
|
|
@ -1,3 +0,0 @@
|
||||||
obj-y = main.o
|
|
||||||
|
|
||||||
ccflags-y += -I${srctree}/net/yaip
|
|
|
@ -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");
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
BOARD ?= qemu_x86
|
|
||||||
MDEF_FILE = prj.mdef
|
|
||||||
KERNEL_TYPE ?= nano
|
|
||||||
CONF_FILE = prj_$(ARCH).conf
|
|
||||||
|
|
||||||
include $(ZEPHYR_BASE)/Makefile.inc
|
|
|
@ -1,5 +0,0 @@
|
||||||
% Application : Network test
|
|
||||||
|
|
||||||
% TASK NAME PRIO ENTRY STACK GROUPS
|
|
||||||
% ===================================================
|
|
||||||
TASK MAIN 7 mainloop 2048 [EXE]
|
|
|
@ -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
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
obj-y = main.o
|
|
||||||
ccflags-y += -I${srctree}/net/yaip
|
|
|
@ -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");
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
BOARD ?= qemu_x86
|
|
||||||
MDEF_FILE = prj.mdef
|
|
||||||
KERNEL_TYPE ?= nano
|
|
||||||
CONF_FILE = prj_$(ARCH).conf
|
|
||||||
|
|
||||||
include $(ZEPHYR_BASE)/Makefile.inc
|
|
|
@ -1,5 +0,0 @@
|
||||||
% Application : Buffer test
|
|
||||||
|
|
||||||
% TASK NAME PRIO ENTRY STACK GROUPS
|
|
||||||
% ===================================================
|
|
||||||
TASK MAIN 7 mainloop 2048 [EXE]
|
|
|
@ -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
|
|
|
@ -1 +0,0 @@
|
||||||
obj-y = main.o
|
|
|
@ -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");
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
BOARD ?= qemu_x86
|
|
||||||
MDEF_FILE = prj.mdef
|
|
||||||
KERNEL_TYPE ?= nano
|
|
||||||
CONF_FILE = prj_$(ARCH).conf
|
|
||||||
|
|
||||||
include $(ZEPHYR_BASE)/Makefile.inc
|
|
|
@ -1,5 +0,0 @@
|
||||||
% Application : Network test
|
|
||||||
|
|
||||||
% TASK NAME PRIO ENTRY STACK GROUPS
|
|
||||||
% ===================================================
|
|
||||||
TASK MAIN 7 mainloop 2048 [EXE]
|
|
|
@ -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
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
obj-y = main.o
|
|
||||||
ccflags-y += -I${srctree}/net/yaip
|
|
|
@ -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");
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue