Merge "Merge net branch into master"

This commit is contained in:
Anas Nashif 2017-04-14 01:43:34 +00:00
commit d3af7f75c9
93 changed files with 4011 additions and 1541 deletions

View file

@ -36,18 +36,6 @@
^.*struct net_if __aligned\(32\)
^[- \t]*\^
#
# include/net/dns_client.h
#
^(?P<filename>[-._/\w]+/doc/api/networking.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
^[ \t]*
^[ \t]*\^
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]
^[ \t]*
^[ \t]*\^
^(?P=filename):(?P=lineno): WARNING: Invalid definition: Expected end of definition. \[error at [0-9]+]
^.*dns_context.address
^[- \t]*\^
#
# include/net/net_mgmt.h
#
^(?P<filename>[-._/\w]+/doc/api/networking.rst):(?P<lineno>[0-9]+): WARNING: Invalid definition: Expected identifier in nested name. \[error at [0-9]+]

View file

@ -58,9 +58,9 @@ MQTT 3.1.1
:project: Zephyr
:content-only:
DNS Client
==========
DNS Resolve
===========
.. doxygengroup:: dns_client
.. doxygengroup:: dns_resolve
:project: Zephyr
:content-only:

View file

@ -109,7 +109,7 @@ INPUT = \
../lib/libc/minimal/include/ \
../ext/lib/crypto/tinycrypt/include/ \
../include/net/zoap.h \
../include/net/dns_client.h \
../include/net/dns_resolve.h \
../tests/ztest/include/
INPUT_ENCODING = UTF-8
FILE_PATTERNS = "*.c" "*.h" "*.S"

View file

@ -30,3 +30,4 @@ obj-$(CONFIG_PINMUX) += pinmux/
obj-$(CONFIG_DMA) += dma/
obj-$(CONFIG_USB) += usb/
obj-$(CONFIG_CRYPTO) += crypto/
obj-y += crc/

1
drivers/crc/Makefile Normal file
View file

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

35
drivers/crc/crc16_sw.c Normal file
View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2017 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <crc16.h>
uint16_t crc16(const uint8_t *src, size_t len, uint16_t polynomial,
uint16_t initial_value)
{
uint16_t crc = initial_value;
size_t i, b;
/* src length + crc width of zeros appended */
for (i = 0; i < len + sizeof(crc); i++) {
for (b = 0; b < 8; b++) {
uint16_t divide = crc & 0x8000;
crc = (crc << 1);
/* choose input bytes or implicit trailing zeros */
if (i < len) {
crc |= !!(src[i] & (0x80 >> b));
}
if (divide) {
crc = crc ^ polynomial;
}
}
}
return crc;
}

View file

@ -448,7 +448,9 @@ static void eth_rx(struct device *iface)
irq_unlock(imask);
net_recv_data(context->iface, buf);
if (net_recv_data(context->iface, buf) < 0) {
net_nbuf_unref(buf);
}
}
static void eth_callback(ENET_Type *base, enet_handle_t *handle,

View file

@ -586,7 +586,9 @@ static void eth_rx(struct gmac_queue *queue)
while (rx_frame) {
SYS_LOG_DBG("ETH rx");
net_recv_data(dev_data->iface, rx_frame);
if (net_recv_data(dev_data->iface, rx_frame) < 0) {
net_nbuf_unref(rx_frame);
}
rx_frame = frame_get(queue);
}

View file

@ -541,7 +541,8 @@ static inline bool read_rxfifo_content(struct cc2520_spi *spi,
return true;
}
static inline bool verify_crc(struct cc2520_context *cc2520)
static inline bool verify_crc(struct cc2520_context *cc2520,
struct net_buf *buf)
{
cc2520->spi.cmd_buf[0] = CC2520_INS_RXBUF;
cc2520->spi.cmd_buf[1] = 0;
@ -558,6 +559,8 @@ static inline bool verify_crc(struct cc2520_context *cc2520)
return false;
}
net_nbuf_set_ieee802154_rssi(buf, cc2520->spi.cmd_buf[1]);
/**
* CC2520 does not provide an LQI but a correlation factor.
* See Section 20.6
@ -661,7 +664,7 @@ static void cc2520_rx(int arg)
goto flush;
}
if (!verify_crc(cc2520)) {
if (!verify_crc(cc2520, buf)) {
SYS_LOG_ERR("Bad packet CRC");
goto out;
}

66
include/crc16.h Normal file
View file

@ -0,0 +1,66 @@
/*
* Copyright (c) 2017 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
/** @file
* @brief CRC 16 computation function
*/
#ifndef __CRC16_H
#define __CRC16_H
#include <stdint.h>
#include <stddef.h>
/**
* @brief Generic function for computing CRC 16
*
* Compute CRC 16 by passing in the address of the input, the input length
* and polynomial used in addition to the initial value.
*
* @param src Input bytes for the computation
* @param len Length of the input in bytes
* @param polynomial The polynomial to use omitting the leading x^16
* coefficient
* @param initial_value Initial value for the CRC computation
*
* @return The computed CRC16 value
*/
uint16_t crc16(const uint8_t *src, size_t len, uint16_t polynomial,
uint16_t initial_value);
/**
* @brief Compute CCITT variant of CRC 16
*
* CCITT variant of CRC 16 is using 0x1021 as its polynomial with the initial
* value set to 0xffff.
*
* @param src Input bytes for the computation
* @param len Length of the input in bytes
*
* @return The computed CRC16 value
*/
static inline uint16_t crc16_ccitt(const uint8_t *src, size_t len)
{
return crc16(src, len, 0x1021, 0xffff);
}
/**
* @brief Compute ANSI variant of CRC 16
*
* ANSI variant of CRC 16 is using 0x8005 as its polynomial with the initial
* value set to 0xffff.
*
* @param src Input bytes for the computation
* @param len Length of the input in bytes
*
* @return The computed CRC16 value
*/
static inline uint16_t crc16_ansi(const uint8_t *src, size_t len)
{
return crc16(src, len, 0x8005, 0xffff);
}
#endif

View file

@ -1,107 +0,0 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _DNS_CLIENT_H_
#define _DNS_CLIENT_H_
#include <net/net_context.h>
#include <net/net_ip.h>
/**
* @brief DNS Client library
* @defgroup dns_client DNS Client Library
* @{
*/
/**
* DNS query type enum
*/
enum dns_query_type {
DNS_QUERY_TYPE_A = 1, /* IPv4 */
DNS_QUERY_TYPE_AAAA = 28 /* IPv6 */
};
/**
* DNS client context structure
*/
struct dns_context {
/* rx_sem and rx buffer, for internal use only */
struct k_sem rx_sem;
struct net_buf *rx_buf;
/** Previously initialized network context */
struct net_context *net_ctx;
/** An array of IPv4 or IPv6 address */
union {
struct in_addr *ipv4;
struct in6_addr *ipv6;
} address;
/** IP address and port number of the DNS server. */
struct sockaddr *dns_server;
/** RX/TX timeout.
* This timeout is also used when a buffer is
* required from the dns data internal pool.
*/
int32_t timeout;
/** C-string containing the Domain Name to resolve,
* i.e. 'example.com'.
*/
const char *name;
/** Query type: IPv4 or IPv6 */
uint16_t query_type;
/** Available positions in the 'address' array. */
uint8_t elements;
/** Number of IPv4 addresses stored in 'address'. */
uint8_t items;
};
/**
* DNS resolver initialization routine
*
* This routine must be called before any other dns routine.
*
* @param ctx DNS Client structure
* @retval 0, new versions may return error codes.
*/
int dns_init(struct dns_context *ctx);
/**
* Retrieves the IP addresses associated to the domain name 'client->name'.
*
* This routine obtains the IP addresses associated to the domain name
* 'client->name'. The DNS server is specified by the sockaddr structure
* inside 'client'. Depending on the DNS server used, one or more IP
* addresses may be recovered by this routine.
*
* NOTE: You can use an IPv6 DNS server to look-up for IPv4 addresses or
* an IPv4 server to look-up for IPv6 address. Domain name services are not
* tied to any specific routing or transport technology.
*
* @param ctx DNS Client structure
* @retval 0 on success. The number of returned addresses (client->items)
* may be less than the one reported by the DNS server. However, this situation
* is considered a success because we are 'resolving' the 'name'.
* Workaround: increase 'client->elements'.
* @retval -EIO on network error.
* @retval -EINVAL if an invalid parameter was passed as an argument to
* this routine. This value is also returned if the application received
* a malformed packet from the DNS server.
* @retval -ENOMEM if there are no buffers available.
*/
int dns_resolve(struct dns_context *ctx);
/**
* @}
*/
#endif

View file

@ -13,11 +13,15 @@
#ifndef _DNS_RESOLVE_H
#define _DNS_RESOLVE_H
#if defined(CONFIG_DNS_RESOLVER)
#include <net/net_ip.h>
#include <net/net_context.h>
/**
* @brief DNS resolving library
* @defgroup dns_resolve DNS Resolve Library
* @{
*/
/**
* DNS query type enum
*/
@ -30,6 +34,16 @@ enum dns_query_type {
#define DNS_MAX_NAME_SIZE 20
#endif
/* Make sure that we can compile things even if CONFIG_DNS_RESOLVER
* is not enabled.
*/
#if !defined(CONFIG_DNS_RESOLVER_MAX_SERVERS)
#define CONFIG_DNS_RESOLVER_MAX_SERVERS 1
#endif
#if !defined(CONFIG_DNS_NUM_CONCUR_QUERIES)
#define CONFIG_DNS_NUM_CONCUR_QUERIES 1
#endif
/**
* Address info struct is passed to callback that gets all the results.
*/
@ -153,7 +167,7 @@ struct dns_resolve_context {
* the stack, then the variable needs to be valid for the whole duration of
* the resolving. Caller does not need to fill the variable beforehand or
* edit the context afterwards.
* @param server_array DNS server addresses. The array is null terminated.
* @param dns_servers DNS server addresses. The array is null terminated.
* The port number can be given in the string.
* Syntax for the server addresses with or without port numbers:
* IPv4 : 10.0.9.1
@ -229,7 +243,7 @@ int dns_resolve_name(struct dns_resolve_context *ctx,
/**
* @brief Get default DNS context.
*
* @detail The system level DNS context uses DNS servers that are
* @details The system level DNS context uses DNS servers that are
* defined in project config file. If no DNS servers are defined by the
* user, then resolving DNS names using default DNS context will do nothing.
* The configuration options are described in subsys/net/lib/dns/Kconfig file.
@ -295,6 +309,11 @@ static inline int dns_cancel_addr_info(uint16_t dns_id)
return dns_resolve_cancel(dns_resolve_get_default(), dns_id);
}
/**
* @}
*/
#if defined(CONFIG_DNS_RESOLVER)
/**
* @brief Initialize DNS subsystem.
*/

View file

@ -50,6 +50,7 @@ struct ieee802154_context {
#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
struct ieee802154_security_ctx sec_ctx;
#endif
int16_t tx_power;
uint8_t sequence;
uint8_t ack_received : 1;
uint8_t ack_requested : 1;
@ -83,6 +84,8 @@ enum net_request_ieee802154_cmd {
NET_REQUEST_IEEE802154_CMD_GET_EXT_ADDR,
NET_REQUEST_IEEE802154_CMD_SET_SHORT_ADDR,
NET_REQUEST_IEEE802154_CMD_GET_SHORT_ADDR,
NET_REQUEST_IEEE802154_CMD_GET_TX_POWER,
NET_REQUEST_IEEE802154_CMD_SET_TX_POWER,
NET_REQUEST_IEEE802154_CMD_SET_SECURITY_SETTINGS,
NET_REQUEST_IEEE802154_CMD_GET_SECURITY_SETTINGS,
};
@ -163,6 +166,18 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_SHORT_ADDR);
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_SHORT_ADDR);
#define NET_REQUEST_IEEE802154_GET_TX_POWER \
(_NET_IEEE802154_BASE | \
NET_REQUEST_IEEE802154_CMD_GET_TX_POWER)
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_TX_POWER);
#define NET_REQUEST_IEEE802154_SET_TX_POWER \
(_NET_IEEE802154_BASE | \
NET_REQUEST_IEEE802154_CMD_SET_TX_POWER)
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_TX_POWER);
#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
#define NET_REQUEST_IEEE802154_SET_SECURITY_SETTINGS \

View file

@ -61,7 +61,31 @@ struct net_nbuf {
struct net_linkaddr lladdr_src;
struct net_linkaddr lladdr_dst;
#if defined(CONFIG_NET_IPV6_FRAGMENT)
/* Fragment id */
uint32_t ipv6_fragment_id;
/* Where is the start of the fragment header */
uint8_t *ipv6_frag_hdr_start;
/* What is the fragment offset of this IPv6 packet */
uint16_t ipv6_fragment_offset;
#endif
uint16_t appdatalen;
#if defined(CONFIG_NET_IPV6)
/* Where is the start of the last header before payload data
* in IPv6 packet. This is offset value from start of the IPv6
* packet. Note that this value should be updated by who ever
* adds IPv6 extension headers to the network packet.
*/
uint16_t ipv6_prev_hdr_start;
/* IPv6 hop limit for this network packet. */
uint8_t ipv6_hop_limit;
#endif
uint8_t ll_reserve; /* link layer header length */
uint8_t family; /* IPv4 vs IPv6 */
uint8_t ip_hdr_len; /* pre-filled in order to avoid func call */
@ -80,6 +104,10 @@ struct net_nbuf {
#if defined(CONFIG_NET_ROUTE)
bool forwarding; /* Are we forwarding this buf */
#endif
#if defined(CONFIG_NET_L2_IEEE802154)
uint8_t ieee802154_rssi;
#endif
/* @endcond */
};
@ -340,6 +368,86 @@ static inline void net_nbuf_copy_user_data(struct net_buf *new,
sizeof(struct net_nbuf));
}
#if defined(CONFIG_NET_IPV6)
static inline uint16_t net_nbuf_ipv6_hdr_prev(struct net_buf *buf)
{
return ((struct net_nbuf *)
net_buf_user_data(buf))->ipv6_prev_hdr_start;
}
static inline void net_nbuf_set_ipv6_hdr_prev(struct net_buf *buf,
uint16_t offset)
{
((struct net_nbuf *)
net_buf_user_data(buf))->ipv6_prev_hdr_start = offset;
}
static inline uint8_t net_nbuf_ipv6_hop_limit(struct net_buf *buf)
{
return ((struct net_nbuf *)
net_buf_user_data(buf))->ipv6_hop_limit;
}
static inline void net_nbuf_set_ipv6_hop_limit(struct net_buf *buf,
uint8_t hop_limit)
{
((struct net_nbuf *)
net_buf_user_data(buf))->ipv6_hop_limit = hop_limit;
}
#endif
#if defined(CONFIG_NET_IPV6_FRAGMENT)
static inline uint8_t *net_nbuf_ipv6_fragment_start(struct net_buf *buf)
{
return ((struct net_nbuf *)
net_buf_user_data(buf))->ipv6_frag_hdr_start;
}
static inline void net_nbuf_set_ipv6_fragment_start(struct net_buf *buf,
uint8_t *start)
{
((struct net_nbuf *)
net_buf_user_data(buf))->ipv6_frag_hdr_start = start;
}
static inline uint16_t net_nbuf_ipv6_fragment_offset(struct net_buf *buf)
{
return ((struct net_nbuf *)
net_buf_user_data(buf))->ipv6_fragment_offset;
}
static inline void net_nbuf_set_ipv6_fragment_offset(struct net_buf *buf,
uint16_t offset)
{
((struct net_nbuf *)
net_buf_user_data(buf))->ipv6_fragment_offset = offset;
}
static inline uint32_t net_nbuf_ipv6_fragment_id(struct net_buf *buf)
{
return ((struct net_nbuf *)net_buf_user_data(buf))->ipv6_fragment_id;
}
static inline void net_nbuf_set_ipv6_fragment_id(struct net_buf *buf,
uint32_t id)
{
((struct net_nbuf *)net_buf_user_data(buf))->ipv6_fragment_id = id;
}
#endif
#if defined(CONFIG_NET_L2_IEEE802154)
static inline uint8_t net_nbuf_ieee802154_rssi(struct net_buf *buf)
{
return ((struct net_nbuf *)net_buf_user_data(buf))->ieee802154_rssi;
}
static inline void net_nbuf_set_ieee802154_rssi(struct net_buf *buf,
uint8_t rssi)
{
((struct net_nbuf *)net_buf_user_data(buf))->ieee802154_rssi = rssi;
}
#endif
#define NET_IPV6_BUF(buf) ((struct net_ipv6_hdr *)net_nbuf_ip_data(buf))
#define NET_IPV4_BUF(buf) ((struct net_ipv4_hdr *)net_nbuf_ip_data(buf))
#define NET_ICMP_BUF(buf) ((struct net_icmp_hdr *)net_nbuf_icmp_data(buf))
@ -846,6 +954,28 @@ static inline bool net_nbuf_append_be32(struct net_buf *buf, uint32_t data)
K_FOREVER);
}
/**
* @brief Append uint32_t data to last fragment in fragment list
*
* @details Append data to last fragment. If there is not enough space in last
* fragment then new data fragment will be created and will be added to
* fragment list. Convert data to LE.
*
* @param buf Network buffer fragment list.
* @param data Data to be added
*
* @return True if all the data is placed at end of fragment list,
* False otherwise (In-case of false buf might contain input data
* in the process of placing into fragments).
*/
static inline bool net_nbuf_append_le32(struct net_buf *buf, uint32_t data)
{
uint32_t value = sys_cpu_to_le32(data);
return net_nbuf_append(buf, sizeof(uint32_t), (uint8_t *)&value,
K_FOREVER);
}
/**
* @brief Get data from buffer
*
@ -1112,6 +1242,35 @@ static inline bool net_nbuf_insert_be32(struct net_buf *buf,
(uint8_t *)&value, K_FOREVER);
}
/**
* @brief Split a fragment to two parts at arbitrary offset.
*
* @details This will generate two new fragments (fragA and fragB) from
* one (orig_frag). The original fragment is not modified but two new
* fragments are allocated and returned to the caller. The original fragment
* must be part of the chain pointed by the buf parameter. If the len parameter
* is larger than the amount of data in the orig fragment, then the fragA will
* contain all the data and fragB will be empty.
*
* @param buf Head of the network buffer fragment list.
* @param orig_frag Original network buffer fragment which is to be split.
* @param len Amount of data in the first returned fragment.
* @param fragA A fragment is returned. This will contain len bytes that
* are copied from start of orig_frag.
* @param fragB Another fragment is returned. This will contain remaining
* bytes (orig_frag->len - len) from the orig_frag or NULL if all the data
* was copied into fragA.
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then wait as long as
* necessary. Otherwise, wait up to the specified number of milliseconds before
* timing out.
*
* @return 0 on success, <0 otherwise.
*/
int net_nbuf_split(struct net_buf *buf, struct net_buf *orig_frag,
uint16_t len, struct net_buf **fragA,
struct net_buf **fragB, int32_t timeout);
/**
* @brief Get information about pre-defined RX, TX and DATA pools.
*

View file

@ -33,7 +33,7 @@ enum net_event_if_cmd {
/* IPv6 Events */
#define _NET_IPV6_LAYER NET_MGMT_LAYER_L3
#define _NET_IPV6_CORE_CODE 0x600
#define _NET_IPV6_CORE_CODE 0x060
#define _NET_EVENT_IPV6_BASE (NET_MGMT_EVENT_BIT | \
NET_MGMT_IFACE_BIT | \
NET_MGMT_LAYER(_NET_IPV6_LAYER) | \
@ -52,6 +52,8 @@ enum net_event_ipv6_cmd {
NET_EVENT_IPV6_CMD_ROUTER_DEL,
NET_EVENT_IPV6_CMD_ROUTE_ADD,
NET_EVENT_IPV6_CMD_ROUTE_DEL,
NET_EVENT_IPV6_CMD_DAD_SUCCEED,
NET_EVENT_IPV6_CMD_DAD_FAILED,
};
#define NET_EVENT_IPV6_ADDR_ADD \
@ -90,9 +92,15 @@ enum net_event_ipv6_cmd {
#define NET_EVENT_IPV6_ROUTE_DEL \
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTE_DEL)
#define NET_EVENT_IPV6_DAD_SUCCEED \
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DAD_SUCCEED)
#define NET_EVENT_IPV6_DAD_FAILED \
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DAD_FAILED)
/* IPv4 Events*/
#define _NET_IPV4_LAYER NET_MGMT_LAYER_L3
#define _NET_IPV4_CORE_CODE 0x400
#define _NET_IPV4_CORE_CODE 0x004
#define _NET_EVENT_IPV4_BASE (NET_MGMT_EVENT_BIT | \
NET_MGMT_IFACE_BIT | \
NET_MGMT_LAYER(_NET_IPV4_LAYER) | \

View file

@ -41,31 +41,32 @@ extern "C" {
* 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 k_delayed_work lifetime;
#if defined(CONFIG_NET_IPV6_DAD)
/** Duplicate address detection (DAD) timer */
struct k_delayed_work dad_timer;
#endif
/** 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;
#if defined(CONFIG_NET_IPV6_DAD)
/** How many times we have done DAD */
uint8_t dad_count;
#endif /* CONFIG_NET_IPV6_DAD */
#endif
/** Is the IP address valid forever */
bool is_infinite;
/** Is this IP address used or not */
bool is_used;
};
/**
@ -93,8 +94,8 @@ struct net_if_mcast_addr {
* Stores the multicast IP addresses assigned to this network interface.
*/
struct net_if_ipv6_prefix {
/** Is this prefix used or not */
bool is_used;
/** Prefix lifetime */
struct k_delayed_work lifetime;
/** IPv6 prefix */
struct in6_addr prefix;
@ -105,8 +106,8 @@ struct net_if_ipv6_prefix {
/** Is the IP prefix valid forever */
bool is_infinite;
/** Prefix lifetime */
struct k_delayed_work lifetime;
/** Is this prefix used or not */
bool is_used;
};
#endif /* CONFIG_NET_IPV6 */
@ -116,12 +117,15 @@ struct net_if_ipv6_prefix {
* Stores the router information.
*/
struct net_if_router {
/** Network interface the router is connected to */
struct net_if *iface;
/** Router lifetime */
struct k_delayed_work lifetime;
/** IP address */
struct net_addr address;
/** Network interface the router is connected to */
struct net_if *iface;
/** Is this router used or not */
bool is_used;
@ -130,9 +134,6 @@ struct net_if_router {
/** Is the router valid forever */
bool is_infinite;
/** Router lifetime */
struct k_delayed_work lifetime;
};
/*
@ -184,18 +185,21 @@ struct net_if {
/** The actually device driver instance the net_if is related to */
struct device *dev;
/* For internal use */
ATOMIC_DEFINE(flags, NET_IF_NUM_FLAGS);
/** Interface's L2 layer */
const struct net_l2 * const l2;
/** Interface's private L2 data pointer */
void *l2_data;
/* For internal use */
ATOMIC_DEFINE(flags, NET_IF_NUM_FLAGS);
/** The hardware link address */
struct net_linkaddr link_addr;
/** Queue for outgoing packets from apps */
struct k_fifo tx_queue;
/** The hardware MTU */
uint16_t mtu;
@ -208,9 +212,6 @@ struct net_if {
struct net_offload *offload;
#endif /* CONFIG_NET_OFFLOAD */
/** Queue for outgoing packets from apps */
struct k_fifo tx_queue;
#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
@ -224,30 +225,30 @@ struct net_if {
/** Prefixes */
struct net_if_ipv6_prefix prefix[NET_IF_MAX_IPV6_PREFIX];
} ipv6;
/** IPv6 hop limit */
uint8_t hop_limit;
/** Router solicitation timer */
struct k_delayed_work rs_timer;
/** Default reachable time (RFC 4861, page 52) */
uint32_t base_reachable_time;
/** Reachable time (RFC 4861, page 20) */
uint32_t reachable_time;
/** Retransmit timer (RFC 4861, page 52) */
uint32_t retrans_timer;
/** IPv6 hop limit */
uint8_t hop_limit;
#if defined(CONFIG_NET_IPV6_DAD)
/** IPv6 current duplicate address detection count */
uint8_t dad_count;
/** IPv6 current duplicate address detection count */
uint8_t dad_count;
#endif /* CONFIG_NET_IPV6_DAD */
/** Router solicitation timer */
struct k_delayed_work rs_timer;
/** RS count */
uint8_t rs_count;
/** Default reachable time (RFC 4861, page 52) */
uint32_t base_reachable_time;
/** Reachable time (RFC 4861, page 20) */
uint32_t reachable_time;
/** Retransmit timer (RFC 4861, page 52) */
uint32_t retrans_timer;
/** RS count */
uint8_t rs_count;
} ipv6;
#endif /* CONFIG_NET_IPV6 */
#if defined(CONFIG_NET_IPV4)
@ -265,10 +266,10 @@ struct net_if {
/** Netmask */
struct in_addr netmask;
} ipv4;
/** IPv4 time-to-live */
uint8_t ttl;
/** IPv4 time-to-live */
uint8_t ttl;
} ipv4;
#endif /* CONFIG_NET_IPV4 */
#if defined(CONFIG_NET_DHCPV4)
@ -290,15 +291,6 @@ struct net_if {
/** Requested IP addr */
struct in_addr requested_ip;
/**
* DHCPv4 client state in the process of network
* address allocation.
*/
enum net_dhcpv4_state state;
/** Number of attempts made for REQUEST and RENEWAL messages */
uint8_t attempts;
/** Timer for DHCPv4 Client requests (DISCOVER,
* REQUEST or RENEWAL)
*/
@ -309,8 +301,16 @@ struct net_if {
/** T2 (Rebinding) timer */
struct k_delayed_work t2_timer;
} dhcpv4;
/**
* DHCPv4 client state in the process of network
* address allocation.
*/
enum net_dhcpv4_state state;
/** Number of attempts made for REQUEST and RENEWAL messages */
uint8_t attempts;
} dhcpv4;
#endif
} __net_if_align;
@ -603,7 +603,7 @@ void net_if_ipv6_addr_update_lifetime(struct net_if_addr *ifaddr,
*
* @return True if successfully removed, false otherwise
*/
bool net_if_ipv6_addr_rm(struct net_if *iface, struct in6_addr *addr);
bool net_if_ipv6_addr_rm(struct net_if *iface, const struct in6_addr *addr);
/**
@ -814,7 +814,8 @@ struct net_if_router *net_if_ipv6_router_add(struct net_if *iface,
bool net_if_ipv6_router_rm(struct net_if_router *router);
/**
* @brief Get IPv6 hop limit specified for a given interface
* @brief Get IPv6 hop limit specified for a given interface. This is the
* default value but can be overridden by the user.
*
* @param iface Network interface
*
@ -822,11 +823,11 @@ bool net_if_ipv6_router_rm(struct net_if_router *router);
*/
static inline uint8_t net_if_ipv6_get_hop_limit(struct net_if *iface)
{
return iface->hop_limit;
return iface->ipv6.hop_limit;
}
/**
* @brief Set IPv6 hop limit of a given interface
* @brief Set the default IPv6 hop limit of a given interface.
*
* @param iface Network interface
* @param hop_limit New hop limit
@ -834,7 +835,7 @@ static inline uint8_t net_if_ipv6_get_hop_limit(struct net_if *iface)
static inline void net_ipv6_set_hop_limit(struct net_if *iface,
uint8_t hop_limit)
{
iface->hop_limit = hop_limit;
iface->ipv6.hop_limit = hop_limit;
}
/**
@ -846,7 +847,7 @@ static inline void net_ipv6_set_hop_limit(struct net_if *iface,
static inline void net_if_ipv6_set_base_reachable_time(struct net_if *iface,
uint32_t reachable_time)
{
iface->base_reachable_time = reachable_time;
iface->ipv6.base_reachable_time = reachable_time;
}
/**
@ -858,7 +859,7 @@ static inline void net_if_ipv6_set_base_reachable_time(struct net_if *iface,
*/
static inline uint32_t net_if_ipv6_get_reachable_time(struct net_if *iface)
{
return iface->reachable_time;
return iface->ipv6.reachable_time;
}
/**
@ -878,7 +879,7 @@ uint32_t net_if_ipv6_calc_reachable_time(struct net_if *iface);
*/
static inline void net_if_ipv6_set_reachable_time(struct net_if *iface)
{
iface->reachable_time = net_if_ipv6_calc_reachable_time(iface);
iface->ipv6.reachable_time = net_if_ipv6_calc_reachable_time(iface);
}
/**
@ -890,7 +891,7 @@ static inline void net_if_ipv6_set_reachable_time(struct net_if *iface)
static inline void net_if_ipv6_set_retrans_timer(struct net_if *iface,
uint32_t retrans_timer)
{
iface->retrans_timer = retrans_timer;
iface->ipv6.retrans_timer = retrans_timer;
}
/**
@ -902,7 +903,7 @@ static inline void net_if_ipv6_set_retrans_timer(struct net_if *iface,
*/
static inline uint32_t net_if_ipv6_get_retrans_timer(struct net_if *iface)
{
return iface->retrans_timer;
return iface->ipv6.retrans_timer;
}
/**
@ -943,6 +944,15 @@ struct in6_addr *net_if_ipv6_get_ll(struct net_if *iface,
struct in6_addr *net_if_ipv6_get_ll_addr(enum net_addr_state state,
struct net_if **iface);
/**
* @brief Stop IPv6 Duplicate Address Detection (DAD) procedure if
* we find out that our IPv6 address is already in use.
*
* @param iface Interface where the DAD was running.
* @param addr IPv6 address that failed DAD
*/
void net_if_ipv6_dad_failed(struct net_if *iface, const struct in6_addr *addr);
/**
* @brief Return global IPv6 address from the first interface that has
* a global IPv6 address either in TENTATIVE or PREFERRED state.
@ -968,7 +978,7 @@ struct in6_addr *net_if_ipv6_get_global_addr(struct net_if **iface);
*/
static inline uint8_t net_if_ipv4_get_ttl(struct net_if *iface)
{
return iface->ttl;
return iface->ipv4.ttl;
}
/**

View file

@ -244,6 +244,13 @@ struct net_ipv6_hdr {
struct in6_addr dst;
} __packed;
struct net_ipv6_frag_hdr {
uint8_t nexthdr;
uint8_t reserved;
uint16_t offset;
uint32_t id;
} __packed;
struct net_ipv4_hdr {
uint8_t vhl;
uint8_t tos;
@ -309,10 +316,10 @@ struct net_tcp_hdr {
*/
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;
return UNALIGNED_GET(&addr->s6_addr32[0]) == 0 &&
UNALIGNED_GET(&addr->s6_addr32[1]) == 0 &&
UNALIGNED_GET(&addr->s6_addr32[2]) == 0 &&
ntohl(UNALIGNED_GET(&addr->s6_addr32[3])) == 1;
}
/**
@ -501,8 +508,7 @@ static inline bool net_ipv6_addr_cmp(const struct in6_addr *addr1,
*/
static inline bool net_is_ipv6_ll_addr(const struct in6_addr *addr)
{
return ((addr->s6_addr[0]) == 0xFE) &&
((addr->s6_addr[1]) == 0x80);
return UNALIGNED_GET(&addr->s6_addr16[0]) == htons(0xFE80);
}
/**
@ -554,8 +560,10 @@ static inline bool net_ipv4_addr_mask_cmp(struct net_if *iface,
*/
static inline bool net_is_ipv6_addr_unspecified(const struct in6_addr *addr)
{
return addr->s6_addr32[0] == 0 && addr->s6_addr32[1] == 0 &&
addr->s6_addr32[2] == 0 && addr->s6_addr32[3] == 0;
return UNALIGNED_GET(&addr->s6_addr32[0]) == 0 &&
UNALIGNED_GET(&addr->s6_addr32[1]) == 0 &&
UNALIGNED_GET(&addr->s6_addr32[2]) == 0 &&
UNALIGNED_GET(&addr->s6_addr32[3]) == 0;
}
/**
@ -568,10 +576,11 @@ static inline bool net_is_ipv6_addr_unspecified(const struct in6_addr *addr)
*/
static inline bool net_is_ipv6_addr_solicited_node(const struct in6_addr *addr)
{
return addr->s6_addr32[0] == htonl(0xff020000) &&
addr->s6_addr32[1] == 0x00000000 &&
addr->s6_addr32[2] == htonl(0x00000001) &&
((addr->s6_addr32[3] & htonl(0xff000000)) == htonl(0xff000000));
return UNALIGNED_GET(&addr->s6_addr32[0]) == htonl(0xff020000) &&
UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00000000 &&
UNALIGNED_GET(&addr->s6_addr32[2]) == htonl(0x00000001) &&
((UNALIGNED_GET(&addr->s6_addr32[3]) & htonl(0xff000000)) ==
htonl(0xff000000));
}
/**
@ -594,20 +603,21 @@ static inline bool net_is_ipv6_addr_mcast_global(const struct in6_addr *addr)
* @param src IPv6 address.
* @param dst IPv6 address.
*/
static inline void net_ipv6_addr_create_solicited_node(struct in6_addr *src,
struct in6_addr *dst)
static inline
void net_ipv6_addr_create_solicited_node(const struct in6_addr *src,
struct in6_addr *dst)
{
dst->s6_addr[0] = 0xFF;
dst->s6_addr[1] = 0x02;
dst->s6_addr16[1] = 0;
dst->s6_addr16[2] = 0;
dst->s6_addr16[3] = 0;
dst->s6_addr16[4] = 0;
UNALIGNED_PUT(0, &dst->s6_addr16[1]);
UNALIGNED_PUT(0, &dst->s6_addr16[2]);
UNALIGNED_PUT(0, &dst->s6_addr16[3]);
UNALIGNED_PUT(0, &dst->s6_addr16[4]);
dst->s6_addr[10] = 0;
dst->s6_addr[11] = 0x01;
dst->s6_addr[12] = 0xFF;
dst->s6_addr[13] = src->s6_addr[13];
dst->s6_addr16[7] = src->s6_addr16[7];
UNALIGNED_PUT(UNALIGNED_GET(&src->s6_addr16[7]), &dst->s6_addr16[7]);
}
/** @brief Construct an IPv6 address from eight 16-bit words.
@ -628,14 +638,14 @@ static inline void net_ipv6_addr_create(struct in6_addr *addr,
uint16_t addr4, uint16_t addr5,
uint16_t addr6, uint16_t addr7)
{
addr->s6_addr16[0] = htons(addr0);
addr->s6_addr16[1] = htons(addr1);
addr->s6_addr16[2] = htons(addr2);
addr->s6_addr16[3] = htons(addr3);
addr->s6_addr16[4] = htons(addr4);
addr->s6_addr16[5] = htons(addr5);
addr->s6_addr16[6] = htons(addr6);
addr->s6_addr16[7] = htons(addr7);
UNALIGNED_PUT(htons(addr0), &addr->s6_addr16[0]);
UNALIGNED_PUT(htons(addr1), &addr->s6_addr16[1]);
UNALIGNED_PUT(htons(addr2), &addr->s6_addr16[2]);
UNALIGNED_PUT(htons(addr3), &addr->s6_addr16[3]);
UNALIGNED_PUT(htons(addr4), &addr->s6_addr16[4]);
UNALIGNED_PUT(htons(addr5), &addr->s6_addr16[5]);
UNALIGNED_PUT(htons(addr6), &addr->s6_addr16[6]);
UNALIGNED_PUT(htons(addr7), &addr->s6_addr16[7]);
}
/**
@ -659,8 +669,8 @@ static inline void net_ipv6_addr_create_iid(struct in6_addr *addr,
{
addr->s6_addr[0] = 0xfe;
addr->s6_addr[1] = 0x80;
addr->s6_addr16[1] = 0;
addr->s6_addr32[1] = 0;
UNALIGNED_PUT(0, &addr->s6_addr16[1]);
UNALIGNED_PUT(0, &addr->s6_addr32[1]);
switch (lladdr->len) {
case 2:
@ -668,7 +678,7 @@ static inline void net_ipv6_addr_create_iid(struct in6_addr *addr,
* Universal/Local bit. RFC 6282 ch 3.2.2
*/
if (lladdr->type == NET_LINK_IEEE802154) {
addr->s6_addr32[2] = 0;
UNALIGNED_PUT(0, &addr->s6_addr32[2]);
addr->s6_addr[11] = 0xff;
addr->s6_addr[12] = 0xfe;
addr->s6_addr[13] = 0;

View file

@ -0,0 +1,46 @@
CONFIG_SYS_LOG=y
CONFIG_NET_LOG=y
CONFIG_INIT_STACKS=y
CONFIG_MAIN_STACK_SIZE=1024
CONFIG_TEST_RANDOM_GENERATOR=y
# IP Stack Configuration
CONFIG_NETWORKING=y
CONFIG_NET_ARP=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_IPV4=n
CONFIG_NET_IPV6=y
CONFIG_NET_BUF=y
CONFIG_NET_IFACE_UNICAST_IPV4_ADDR_COUNT=3
# ENC28J60 Ethernet Device
CONFIG_ETH_ENC28J60=y
CONFIG_ETH_ENC28J60_0=y
CONFIG_ETH_ENC28J60_0_SPI_PORT_NAME="SPI_1"
CONFIG_ETH_ENC28J60_0_MAC3=0x2D
CONFIG_ETH_ENC28J60_0_MAC4=0x30
CONFIG_ETH_ENC28J60_0_MAC5=0x36
# Arduino 101
CONFIG_SPI=y
CONFIG_SYS_LOG_SHOW_COLOR=y
CONFIG_INIT_STACKS=y
CONFIG_PRINTK=y
CONFIG_NET_STATISTICS=y
CONFIG_NET_NBUF_RX_COUNT=14
CONFIG_NET_NBUF_TX_COUNT=14
CONFIG_NET_NBUF_RX_DATA_COUNT=30
CONFIG_NET_NBUF_TX_DATA_COUNT=30
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2
CONFIG_NET_MAX_CONTEXTS=10
CONFIG_ZOAP=y
CONFIG_MBEDTLS=y
CONFIG_MBEDTLS_BUILTIN=y
CONFIG_MBEDTLS_CFG_FILE="config-coap.h"
CONFIG_NET_APP_SETTINGS=y
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1"

View file

@ -18,6 +18,7 @@ int ieee802154_sample_setup(void)
{
uint16_t channel = CONFIG_NET_APP_IEEE802154_CHANNEL;
uint16_t pan_id = CONFIG_NET_APP_IEEE802154_PAN_ID;
int16_t tx_power = CONFIG_NET_APP_IEEE802154_RADIO_TX_POWER;
#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
struct ieee802154_security_params sec_params = {
@ -44,7 +45,9 @@ int ieee802154_sample_setup(void)
if (net_mgmt(NET_REQUEST_IEEE802154_SET_PAN_ID,
iface, &pan_id, sizeof(uint16_t)) ||
net_mgmt(NET_REQUEST_IEEE802154_SET_CHANNEL,
iface, &channel, sizeof(uint16_t))) {
iface, &channel, sizeof(uint16_t)) ||
net_mgmt(NET_REQUEST_IEEE802154_SET_TX_POWER,
iface, &tx_power, sizeof(int16_t))) {
return -EINVAL;
}

View file

@ -1,46 +0,0 @@
To exit from QEMU enter: 'CTRL+a, x'
[QEMU] CPU: qemu32
-------------------------------------------
[run_dns:142] name: not_a_real_domain_name
rc: -5
-------------------------------------------
[run_dns:142] name: zephyrproject.org
rc: -22
-------------------------------------------
[run_dns:142] name: linux.org
[run_dns:159] 192.243.104.10
-------------------------------------------
[run_dns:142] name: www.zephyrproject.org
[run_dns:159] 140.211.169.8
-------------------------------------------
[run_dns:142] name: kernel.org
[run_dns:159] 149.20.4.69
[run_dns:159] 199.204.44.194
[run_dns:159] 198.145.20.140
-------------------------------------------
[run_dns:142] name: gerrit.zephyrproject.org
[run_dns:159] 199.19.213.246
-------------------------------------------
[run_dns:142] name: linuxfoundation.org
[run_dns:159] 140.211.169.4
-------------------------------------------
[run_dns:142] name: jira.zephyrproject.org
[run_dns:159] 199.19.213.246
-------------------------------------------
[run_dns:142] name: www.wikipedia.org
[run_dns:159] 208.80.153.224
-------------------------------------------
[run_dns:142] name: collabprojects.linuxfoundation.org
[run_dns:159] 140.211.169.4

View file

@ -1,39 +0,0 @@
To exit from QEMU enter: 'CTRL+a, x'
[QEMU] CPU: qemu32
-------------------------------------------
[run_dns:142] name: not_a_real_domain_name
rc: -22
-------------------------------------------
[run_dns:142] name: zephyrproject.org
[run_dns:159] ff02::3
-------------------------------------------
[run_dns:142] name: www.zephyrproject.org
[run_dns:159] ff02::4
-------------------------------------------
[run_dns:142] name: gerrit.zephyrproject.org
[run_dns:159] ff02::5
-------------------------------------------
[run_dns:142] name: jira.zephyrproject.org
[run_dns:159] ff02::6
-------------------------------------------
[run_dns:142] name: jenkins.zephyrproject.org
[run_dns:159] ff02::7
-------------------------------------------
[run_dns:142] name: linuxfoundation.org
[run_dns:159] ff02::8
-------------------------------------------
[run_dns:142] name: www.linuxfoundation.org
[run_dns:159] ff02::9
-------------------------------------------
[run_dns:142] name: collabprojects.linuxfoundation.org
[run_dns:159] ff02::a

View file

@ -1,7 +0,0 @@
#
# Copyright (c) 2016 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
obj-y += main.o

View file

@ -1,38 +0,0 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _CONFIG_H_
#define _CONFIG_H_
#ifdef CONFIG_NET_APP_SETTINGS
#ifdef CONFIG_NET_IPV6
#define LOCAL_ADDR CONFIG_NET_APP_MY_IPV6_ADDR
#define REMOTE_ADDR CONFIG_NET_APP_PEER_IPV6_ADDR
#else
#define LOCAL_ADDR CONFIG_NET_APP_MY_IPV4_ADDR
#define REMOTE_ADDR CONFIG_NET_APP_PEER_IPV4_ADDR
#endif
#else
#ifdef CONFIG_NET_IPV6
#define LOCAL_ADDR "2001:db8::1"
#define REMOTE_ADDR "2001:db8::2"
#else
#define LOCAL_ADDR "192.168.1.101"
#define REMOTE_ADDR "192.168.1.10"
#endif
#endif
#define REMOTE_PORT 5353
#define APP_SLEEP_MSECS 400
/* The DNS server may return more than 1 IP address.
* This value controls the max number of IP addresses
* that the client will store per query.
*/
#define MAX_ADDRESSES 4
#endif

View file

@ -1,198 +0,0 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <net/dns_client.h>
#include <net/net_core.h>
#include <net/net_if.h>
#include <misc/printk.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#define STACK_SIZE 2048
uint8_t stack[STACK_SIZE];
#if CONFIG_NET_IPV6
static struct in6_addr addresses[MAX_ADDRESSES];
#else
static struct in_addr addresses[MAX_ADDRESSES];
#endif
static struct net_context *net_ctx;
static struct sockaddr remote_sock;
static char str[128];
static
char *domains[] = {"not_a_real_domain_name",
"zephyrproject.org",
"linux.org",
"www.zephyrproject.org",
"kernel.org",
"gerrit.zephyrproject.org",
"linuxfoundation.org",
"jira.zephyrproject.org",
"www.wikipedia.org",
"collabprojects.linuxfoundation.org",
"gcc.gnu.org",
"events.linuxfoundation.org",
"www.google.com",
NULL};
static
int set_addr(struct sockaddr *sock_addr, const char *addr, uint16_t port);
static
int set_local_addr(struct net_context **net_ctx, const char *local_addr);
void run_dns(void)
{
struct dns_context ctx;
int rc;
int d;
int i;
rc = set_local_addr(&net_ctx, LOCAL_ADDR);
if (rc) {
return;
}
rc = set_addr(&remote_sock, REMOTE_ADDR, REMOTE_PORT);
if (rc) {
goto lb_exit;
}
dns_init(&ctx);
ctx.net_ctx = net_ctx;
ctx.timeout = APP_SLEEP_MSECS;
ctx.dns_server = &remote_sock;
ctx.elements = MAX_ADDRESSES;
#ifdef CONFIG_NET_IPV6
ctx.query_type = DNS_QUERY_TYPE_AAAA;
ctx.address.ipv6 = addresses;
#else
ctx.query_type = DNS_QUERY_TYPE_A;
ctx.address.ipv4 = addresses;
#endif
for (d = 0; domains[d] != NULL; d++) {
printk("\n-------------------------------------------\n"
"[%s:%d] name: %s\n", __func__, __LINE__, domains[d]);
ctx.name = domains[d];
rc = dns_resolve(&ctx);
if (rc != 0) {
printk("rc: %d\n", rc);
continue;
}
for (i = 0; i < ctx.items; i++) {
#ifdef CONFIG_NET_IPV6
net_addr_ntop(AF_INET6, &addresses[i],
str, sizeof(str));
#else
net_addr_ntop(AF_INET, &addresses[i],
str, sizeof(str));
#endif
printk("[%s:%d] %s\n", __func__, __LINE__, str);
}
k_sleep(APP_SLEEP_MSECS);
}
lb_exit:
net_context_put(net_ctx);
printk("\nBye!\n");
}
void main(void)
{
k_thread_spawn(stack, STACK_SIZE, (k_thread_entry_t)run_dns,
NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0);
}
static
int set_addr(struct sockaddr *sock_addr, const char *addr, uint16_t port)
{
void *ptr;
int rc;
#ifdef CONFIG_NET_IPV6
net_sin6(sock_addr)->sin6_port = htons(port);
sock_addr->family = AF_INET6;
ptr = &(net_sin6(sock_addr)->sin6_addr);
rc = net_addr_pton(AF_INET6, addr, ptr);
#else
net_sin(sock_addr)->sin_port = htons(port);
sock_addr->family = AF_INET;
ptr = &(net_sin(sock_addr)->sin_addr);
rc = net_addr_pton(AF_INET, addr, ptr);
#endif
if (rc) {
printk("Invalid IP address: %s\n", addr);
}
return rc;
}
static
int set_local_addr(struct net_context **net_ctx, const char *local_addr)
{
#ifdef CONFIG_NET_IPV6
socklen_t addr_len = sizeof(struct sockaddr_in6);
sa_family_t family = AF_INET6;
#else
socklen_t addr_len = sizeof(struct sockaddr_in);
sa_family_t family = AF_INET;
#endif
struct sockaddr local_sock;
void *p;
int rc;
rc = set_addr(&local_sock, local_addr, 0);
if (rc) {
printk("set_addr (local) error\n");
return rc;
}
#ifdef CONFIG_NET_IPV6
p = net_if_ipv6_addr_add(net_if_get_default(),
&net_sin6(&local_sock)->sin6_addr,
NET_ADDR_MANUAL, 0);
#else
p = net_if_ipv4_addr_add(net_if_get_default(),
&net_sin(&local_sock)->sin_addr,
NET_ADDR_MANUAL, 0);
#endif
if (!p) {
return -EINVAL;
}
rc = net_context_get(family, SOCK_DGRAM, IPPROTO_UDP, net_ctx);
if (rc) {
printk("net_context_get error\n");
return rc;
}
rc = net_context_bind(*net_ctx, &local_sock, addr_len);
if (rc) {
printk("net_context_bind error\n");
goto lb_exit;
}
return 0;
lb_exit:
net_context_put(*net_ctx);
return rc;
}

View file

@ -1,4 +0,0 @@
[test]
tags = net dns
build_only = true
platform_whitelist = qemu_x86 arduino_101 frdm_k64f

View file

@ -1,14 +1,13 @@
.. _dns-client-sample:
.. _dns-resolve-sample:
DNS Client Application
######################
DNS Resolve Application
#######################
Overview
********
The DNS resolver or DNS client sample application implements a basic
DNS resolver according to RFC 1035. Supported DNS answers are:
IPv4/IPv6 addresses and CNAME.
The DNS resolver sample application implements a basic DNS resolver according
to RFC 1035. Supported DNS answers are IPv4/IPv6 addresses and CNAME.
If a CNAME is received, the DNS resolver will create another DNS query.
The number of additional queries is controlled by the
@ -16,20 +15,8 @@ DNS_RESOLVER_ADDITIONAL_QUERIES Kconfig variable.
For more information about DNS configuration variables, see:
:file:`subsys/net/lib/dns/Kconfig`. The DNS resolver API can be found at
:file:`include/net/dns_client.h`. The sample code can be found at:
:file:`samples/net/dns_client`.
The return codes used by this sample application are described by the following table.
======= ===== ================================================
Macro Value Description
------- ----- ------------------------------------------------
-EINVAL -22 if an invalid parameter was detected
-EIO -5 network error
-ENOMEM -12 memory error, perhaps related to network buffers
======= ===== ================================================
A return code of 0 must be interpreted as success.
:file:`include/net/dns_resolve.h`. The sample code can be found at:
:file:`samples/net/dns_resolve`.
Requirements
************
@ -47,6 +34,7 @@ Requirements
dnsmasq -v
Dnsmasq version 2.76 Copyright (c) 2000-2016 Simon Kelley
Wiring
******
@ -56,7 +44,7 @@ Arduino 101 board:
=========== ===================================
Arduino 101 ENC28J60 (pin numbers on the board)
----------- -----------------------------------
=========== ===================================
D13 SCK (1)
D12 SO (3)
D11 SI (2)
@ -75,18 +63,10 @@ Network Configuration
Open the project configuration file for your platform, for example:
:file:`prj_frdm_k64f.conf` is the configuration file for the
:ref:`frdm_k64f` board. For IPv4 networks, set the following variables:
:ref:`frdm_k64f` board.
.. code-block:: console
CONFIG_NET_IPV4=y
CONFIG_NET_IPV6=n
IPv6 is the preferred routing technology for this sample application,
if CONFIG_NET_IPV6=y is set, the value of CONFIG_NET_IPV4 is ignored.
In this sample application, only static IP addresses are supported,
those addresses are specified in the project configuration file,
In this sample application, both static or DHCPv4 IP addresses are supported.
Static IP addresses are specified in the project configuration file,
for example:
.. code-block:: console
@ -94,30 +74,28 @@ for example:
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
are the IPv6 addresses for the DNS client running Zephyr and the
DNS server, respectively.
Alternatively, the IP addresses may be specified in the
:file:`samples/net/dns_client/src/config.h` file.
Open the :file:`samples/net/dns_client/src/config.h` file and set the
server port to match the DNS server setup, for example:
.. code-block:: c
#define REMOTE_PORT 5353
assumes that the DNS server is listening at UDP port 5353.
are the IPv6 addresses for the DNS client running Zephyr and the DNS server,
respectively.
DNS server
==========
The dnsmasq tool may be used for testing purposes. Open a terminal
window and type:
The dnsmasq tool may be used for testing purposes. Sample dnsmasq start
script can be found in net-tools project.
The net-tools can be downloaded from
https://gerrit.zephyrproject.org/r/gitweb?p=net-tools.git;a=blob;f=README
Open a terminal window and type:
.. code-block:: console
$ dnsmasq -p 5353 -d
$ cd net-tools
$ ./dnsmasq.sh
NOTE: some systems may require root privileges to run dnsmaq, use sudo or su.
@ -127,12 +105,14 @@ If dnsmasq fails to start with an error like this:
dnsmasq: failed to create listening socket for port 5353: Address already in use
Open a terminal window and type:
.. code-block:: console
$ killall -s KILL dnsmasq
Try to launch the dnsmasq application again.
@ -150,18 +130,14 @@ Run 'loop_socat.sh' and 'loop-slip-tap.sh' as indicated at:
https://gerrit.zephyrproject.org/r/gitweb?p=net-tools.git;a=blob;f=README
Set the IPv4 ip address:
.. code-block:: console
$ ip addr add 192.0.2.2/24 dev tap0
Open a terminal where the project was build (i.e. :file:`samples/net/dns_client`) and type:
Open a terminal where the project was build (i.e. :file:`samples/net/dns_resolve`) and type:
.. code-block:: console
$ make run
FRDM K64F
=========
@ -203,6 +179,7 @@ Open a terminal window and type:
$ make BOARD=arduino_101
To load the binary in the development board follow the steps
in :ref:`arduino_101`.
@ -212,34 +189,7 @@ Open a terminal window and type:
$ screen /dev/ttyUSB0 115200
Use 'dmesg' to find the right USB device.
Once the binary is loaded into the Arduino 101 board, press the RESET button.
Sample Output
=============
IPv4 (CONFIG_NET_IPV6=n, CONFIG_NET_IPV4=y)
.. literalinclude:: sample_output_IPv4.txt
IPv6 (CONFIG_NET_IPV6=y, CONFIG_NET_IPV4=n)
.. literalinclude:: sample_output_IPv6.txt
Note: IPv6 addresses obtained via dnsmasq and :file:`/etc/hosts`.
Known Issues
============
- The above sample contains a rc: -22 (-EINVAL). This is the expected behavior
for that domain name.
- If a lot of rc: -5 (-EIO) errors are flooding the screen, increment
APP_SLEEP_MSECS to 500 or even 1000. See :file:`samples/net/dns_client/src/config.h`.
- IPv4: there is still an issue not yet isolated that causes the application
to fail during the first two queries. The issue lies between L2 (ARP) and
UDP and it only appears during application startup.

View file

@ -0,0 +1,45 @@
CONFIG_NETWORKING=y
CONFIG_NET_TCP=y
CONFIG_RANDOM_GENERATOR=y
CONFIG_NET_ARP=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_LOG=y
CONFIG_INIT_STACKS=y
CONFIG_NET_NBUF_RX_COUNT=16
CONFIG_NET_NBUF_TX_COUNT=16
CONFIG_NET_NBUF_RX_DATA_COUNT=16
CONFIG_NET_NBUF_TX_DATA_COUNT=16
CONFIG_NET_IPV6_RA_RDNSS=y
CONFIG_NET_IFACE_UNICAST_IPV4_ADDR_COUNT=3
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_HTTP_SERVER=y
CONFIG_HTTP_PARSER=y
# Enable IPv6 support
CONFIG_NET_IPV6=y
# Enable IPv4 support
CONFIG_NET_IPV4=n
CONFIG_NET_APP_SETTINGS=y
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_APP_MY_IPV4_ADDR="192.168.1.101"
CONFIG_NET_MAX_CONTEXTS=16
# ENC28J60 Ethernet Device
CONFIG_ETH_ENC28J60=y
CONFIG_ETH_ENC28J60_0=y
CONFIG_ETH_ENC28J60_0_SPI_PORT_NAME="SPI_1"
CONFIG_ETH_ENC28J60_0_MAC3=0x2D
CONFIG_ETH_ENC28J60_0_MAC4=0x30
CONFIG_ETH_ENC28J60_0_MAC5=0x36
# Arduino 101
CONFIG_SPI=y

View file

@ -0,0 +1,46 @@
CONFIG_NETWORKING=y
CONFIG_NET_TCP=y
CONFIG_RANDOM_GENERATOR=y
CONFIG_NET_ARP=y
CONFIG_NET_LOG=y
CONFIG_INIT_STACKS=y
CONFIG_NET_NBUF_RX_COUNT=16
CONFIG_NET_NBUF_TX_COUNT=16
CONFIG_NET_NBUF_RX_DATA_COUNT=16
CONFIG_NET_NBUF_TX_DATA_COUNT=16
CONFIG_NET_IPV6_RA_RDNSS=y
CONFIG_NET_IFACE_UNICAST_IPV4_ADDR_COUNT=3
CONFIG_STDOUT_CONSOLE=y
CONFIG_HTTP_SERVER=y
CONFIG_HTTP_PARSER=y
# Enable IPv6 support
CONFIG_NET_IPV6=y
# Enable IPv4 support
CONFIG_NET_IPV4=n
CONFIG_NET_APP_SETTINGS=y
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_APP_MY_IPV4_ADDR="192.168.1.101"
CONFIG_NET_MAX_CONTEXTS=16
CONFIG_BLUETOOTH=y
CONFIG_BLUETOOTH_DEBUG_LOG=y
CONFIG_BLUETOOTH_SMP=y
CONFIG_BLUETOOTH_PERIPHERAL=y
CONFIG_BLUETOOTH_L2CAP_DYNAMIC_CHANNEL=y
CONFIG_BLUETOOTH_DEVICE_NAME="Test Http_Server"
CONFIG_NET_UDP=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_L2_BLUETOOTH=y
CONFIG_NET_L2_BLUETOOTH_ZEP1656=y
CONFIG_NET_DEBUG_L2_BLUETOOTH=y
CONFIG_SYS_LOG_SHOW_COLOR=y
CONFIG_NET_STATISTICS=y
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2

View file

@ -12,4 +12,7 @@ ifdef CONFIG_MBEDTLS
obj-y += https_server.o ssl_utils.o
endif
ifeq ($(CONFIG_NET_L2_BLUETOOTH), y)
ccflags-y +=-I${ZEPHYR_BASE}/samples/bluetooth/
obj-y += ../../../bluetooth/gatt/ipss.o
endif

View file

@ -9,6 +9,11 @@
#include <misc/printk.h>
#if defined(CONFIG_NET_L2_BLUETOOTH)
#include <bluetooth/bluetooth.h>
#include <gatt/ipss.h>
#endif
#include "http_types.h"
#include "http_server.h"
#include "http_utils.h"
@ -26,6 +31,28 @@ int network_setup(struct net_context **net_ctx, net_tcp_accept_cb_t accept_cb,
void main(void)
{
#if defined(CONFIG_NET_L2_BLUETOOTH)
int err;
err = bt_enable(NULL);
if (err) {
printk("Bluetooth init failed (err %d)\n", err);
return;
}
printk("Bluetooth initialized\n");
ipss_init();
err = ipss_advertise();
if (err) {
printk("Advertising failed to start (err %d)\n", err);
return;
}
printk("Advertising successfully started\n");
#endif
struct net_context *net_ctx = NULL;
http_ctx_init();

View file

@ -1,4 +1,10 @@
[test]
tags = net http
build_only = true
platform_whitelist = frdm_k64f qemu_x86
platform_whitelist = frdm_k64f qemu_x86 arduino_101
[test_bt]
tags = net bluetooth
build_only = true
extra_args = CONF_FILE="prj_bt.conf"
platform_whitelist = arduino_101

View file

@ -1,6 +1,5 @@
CONFIG_INIT_STACKS=y
CONFIG_NET_LOG=y
CONFIG_NET_LOG_ENABLED=y
CONFIG_SYS_LOG_NET_LEVEL=2
CONFIG_NET_IPV4=y
@ -8,6 +7,7 @@ CONFIG_NET_DHCPV4=y
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=3
CONFIG_NET_IPV6=y
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NET_LOG=y
CONFIG_NET_MAX_CONTEXTS=10
CONFIG_NET_NBUF_RX_DATA_COUNT=30
CONFIG_NET_NBUF_TX_DATA_COUNT=30
@ -17,18 +17,30 @@ CONFIG_NET_SHELL=y
CONFIG_NET_STATISTICS=y
CONFIG_NET_TCP=y
CONFIG_NETWORKING=y
CONFIG_NET_MGMT_EVENT=y
CONFIG_NET_MGMT=y
CONFIG_DNS_RESOLVER=y
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=0
CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=1
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=2
CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=2
CONFIG_DNS_RESOLVER_MAX_SERVERS=1
CONFIG_DNS_SERVER_IP_ADDRESSES=y
CONFIG_DNS_NUM_CONCUR_QUERIES=2
# Google DNS IPv4 and IPv6 servers. IPv6 is the default server.
# For IPv4, uncomment the IPv4 specific setting and comment the
# IPv6 specific one.
CONFIG_DNS_SERVER1="2001:4860:4860::8888"
#CONFIG_DNS_SERVER1="8.8.8.8"
CONFIG_PRINTK=y
CONFIG_SYS_LOG_SHOW_COLOR=y
CONFIG_SYS_LOG_NET_LEVEL=4
CONFIG_NET_APP_SETTINGS=y
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
CONFIG_NET_APP_MY_IPV4_ADDR="192.168.0.1"
CONFIG_NET_APP_PEER_IPV4_ADDR="192.168.0.2"
CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1"
CONFIG_NET_APP_PEER_IPV4_ADDR="192.0.2.2"
CONFIG_NET_L2_ETHERNET=y

View file

@ -18,17 +18,29 @@ CONFIG_NET_SLIP_TAP=y
CONFIG_NET_STATISTICS=y
CONFIG_NET_TCP=y
CONFIG_NETWORKING=y
CONFIG_NET_MGMT_EVENT=y
CONFIG_NET_MGMT=y
CONFIG_DNS_RESOLVER=y
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=0
CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=1
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=2
CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=2
CONFIG_DNS_RESOLVER_MAX_SERVERS=1
CONFIG_DNS_SERVER_IP_ADDRESSES=y
CONFIG_DNS_NUM_CONCUR_QUERIES=2
# Google DNS IPv4 and IPv6 servers. IPv6 is the default server.
# For IPv4, uncomment the IPv4 specific setting and comment the
# IPv6 specific one.
CONFIG_DNS_SERVER1="2001:4860:4860::8888"
#CONFIG_DNS_SERVER1="8.8.8.8"
CONFIG_PRINTK=y
CONFIG_SYS_LOG_SHOW_COLOR=y
CONFIG_SYS_LOG_NET_LEVEL=4
CONFIG_NET_APP_SETTINGS=y
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
CONFIG_NET_APP_MY_IPV4_ADDR="192.168.0.1"
CONFIG_NET_APP_PEER_IPV4_ADDR="192.168.0.2"
CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1"
CONFIG_NET_APP_PEER_IPV4_ADDR="192.0.2.2"
CONFIG_TEST_RANDOM_GENERATOR=y

View file

@ -20,7 +20,9 @@
#include <net/net_if.h>
#include <stdio.h>
#include <zephyr.h>
#include <net/dns_client.h>
#include <net/dns_resolve.h>
#include <net/net_mgmt.h>
#include <net/net_event.h>
#if !defined(CONFIG_NET_IPV6) && !defined(CONFIG_NET_IPV4)
#error "CONFIG_NET_IPV6 or CONFIG_NET_IPV4 must be enabled for irc_bot"
@ -63,9 +65,6 @@ static bool fake_led;
#define ZIRC_PEER_IP_ADDR "2001:db8::2"
#endif /* CONFIG_NET_APP_PEER_IPV6_ADDR */
/* Google DNS server for IPv6 */
#define DNS_SERVER "2001:4860:4860::8888"
#else /* CONFIG_NET_IPV4 */
#define ZIRC_AF_INET AF_INET
@ -74,23 +73,19 @@ static bool fake_led;
#if defined(CONFIG_NET_APP_MY_IPV4_ADDR)
#define ZIRC_LOCAL_IP_ADDR CONFIG_NET_APP_MY_IPV4_ADDR
#else
#define ZIRC_LOCAL_IP_ADDR "192.168.0.1"
#define ZIRC_LOCAL_IP_ADDR "192.0.2.1"
#endif /* CONFIG_NET_APP_MY_IPV4_ADDR */
#if defined(CONFIG_NET_APP_PEER_IPV4_ADDR)
#define ZIRC_PEER_IP_ADDR CONFIG_NET_APP_PEER_IPV4_ADDR
#else
#define ZIRC_PEER_IP_ADDR "192.168.0.2"
#define ZIRC_PEER_IP_ADDR "192.0.2.2"
#endif /* CONFIG_NET_APP_PEER_IPV4_ADDR */
/* Google DNS server for IPv4 */
#define DNS_SERVER "8.8.8.8"
#endif
/* DNS API */
#define DNS_PORT 53
#define DNS_SLEEP_MSECS 400
#define DNS_QUERY_TIMEOUT K_SECONDS(4)
/* IRC API */
#define DEFAULT_SERVER "irc.freenode.net"
@ -103,6 +98,15 @@ typedef void (*on_privmsg_rcvd_cb_t)(void *data, struct zirc_chan *chan,
char *umask, char *msg);
struct zirc {
struct sockaddr local_addr;
struct sockaddr remote_addr;
#if defined(CONFIG_DNS_RESOLVER)
struct k_sem wait_dns;
#endif
struct k_sem wait_iface;
struct net_context *conn;
struct zirc_chan *chans;
@ -466,62 +470,68 @@ static int in_addr_set(sa_family_t family,
return rc;
}
static int
zirc_dns_lookup(const char *host,
struct sockaddr *src_addr,
struct sockaddr *dst_addr)
#if defined(CONFIG_DNS_RESOLVER)
static void resolve_cb(enum dns_resolve_status status,
struct dns_addrinfo *info,
void *user_data)
{
struct net_context *net_ctx;
struct dns_context dns_ctx;
struct sockaddr dns_addr = { 0 };
int ret;
struct zirc *irc = user_data;
/* query DNS for server IP */
dns_init(&dns_ctx);
/* Note that we cannot do any connection establishment in the DNS
* callback as the DNS query will timeout very soon. We inform the
* connect function via semaphore when it can continue.
*/
k_sem_give(&irc->wait_dns);
ret = net_context_get(ZIRC_AF_INET, SOCK_DGRAM, IPPROTO_UDP, &net_ctx);
if (ret < 0) {
NET_ERR("Cannot get network context for IP UDP: %d\n", -ret);
return ret;
if (status != DNS_EAI_INPROGRESS || !info) {
return;
}
ret = net_context_bind(net_ctx, src_addr,
sizeof(struct ZIRC_SOCKADDR_IN));
if (ret < 0) {
NET_ERR("Cannot bind: %d\n", -ret);
goto dns_exit;
}
in_addr_set(ZIRC_AF_INET, DNS_SERVER, DNS_PORT, &dns_addr);
dns_ctx.net_ctx = net_ctx;
dns_ctx.timeout = DNS_SLEEP_MSECS;
dns_ctx.dns_server = &dns_addr;
dns_ctx.elements = 1;
#ifdef CONFIG_NET_IPV6
dns_ctx.query_type = DNS_QUERY_TYPE_AAAA;
dns_ctx.address.ipv6 = &net_sin6(dst_addr)->sin6_addr;
#else
dns_ctx.query_type = DNS_QUERY_TYPE_A;
dns_ctx.address.ipv4 = &net_sin(dst_addr)->sin_addr;
#if defined(CONFIG_NET_IPV6)
if (info->ai_family == AF_INET6) {
net_ipaddr_copy(&net_sin6(&irc->remote_addr)->sin6_addr,
&net_sin6(&info->ai_addr)->sin6_addr);
net_sin6(&irc->remote_addr)->sin6_port = htons(DEFAULT_PORT);
net_sin6(&irc->remote_addr)->sin6_family = AF_INET6;
irc->remote_addr.family = AF_INET6;
} else
#endif
dns_ctx.name = DEFAULT_SERVER;
ret = dns_resolve(&dns_ctx);
if (ret != 0) {
NET_ERR("dns_resolve ERROR %d\n", -ret);
#if defined(CONFIG_NET_IPV4)
if (info->ai_family == AF_INET) {
net_ipaddr_copy(&net_sin(&irc->remote_addr)->sin_addr,
&net_sin(&info->ai_addr)->sin_addr);
net_sin(&irc->remote_addr)->sin_port = htons(DEFAULT_PORT);
net_sin(&irc->remote_addr)->sin_family = AF_INET;
irc->remote_addr.family = AF_INET;
} else
#endif
{
NET_ERR("Invalid IP address family %d", info->ai_family);
return;
}
dns_exit:
net_context_put(net_ctx);
return ret;
return;
}
static inline int zirc_dns_lookup(const char *host, void *user_data)
{
return dns_get_addr_info(host,
#ifdef CONFIG_NET_IPV6
DNS_QUERY_TYPE_AAAA,
#else
DNS_QUERY_TYPE_A,
#endif
NULL,
resolve_cb,
user_data,
DNS_QUERY_TIMEOUT);
}
#endif /* CONFIG_DNS_RESOLVER */
static int
zirc_connect(struct zirc *irc, const char *host, int port, void *data)
{
struct net_if *iface;
struct sockaddr dst_addr, src_addr;
struct zirc_chan *chan;
int ret;
char name_buf[32];
@ -531,62 +541,51 @@ zirc_connect(struct zirc *irc, const char *host, int port, void *data)
ret = net_context_get(ZIRC_AF_INET, SOCK_STREAM, IPPROTO_TCP,
&irc->conn);
if (ret < 0) {
NET_DBG("Could not get new context: %d", -ret);
NET_DBG("Could not get new context: %d", ret);
return ret;
}
iface = net_if_get_default();
if (!iface) {
NET_DBG("Could not get new context: %d", -ret);
NET_DBG("Could not get new context: %d", ret);
return -EIO;
}
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_DHCPV6)
/* TODO: IPV6 DHCP */
#elif defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_DHCPV4)
net_ipaddr_copy(&net_sin(&src_addr)->sin_addr,
&iface->dhcpv4.requested_ip);
ret = in_addr_set(ZIRC_AF_INET, NULL, 0, &src_addr);
#else
ret = in_addr_set(ZIRC_AF_INET, ZIRC_LOCAL_IP_ADDR,
0, &src_addr);
if (ret < 0) {
goto connect_exit;
}
#endif
#if defined(CONFIG_DNS_RESOLVER)
in_addr_set(ZIRC_AF_INET, NULL, port, &dst_addr);
irc->data = data;
/* set the IP address for the dst_addr via DNS */
ret = zirc_dns_lookup(host, &src_addr, &dst_addr);
ret = zirc_dns_lookup(host, irc);
if (ret < 0) {
NET_ERR("Could not peform DNS lookup on host %s: %d",
host, -ret);
host, ret);
goto connect_exit;
}
/* We continue the connection after the server name has been resolved.
*/
k_sem_take(&irc->wait_dns, K_FOREVER);
#else
ret = in_addr_set(ZIRC_AF_INET, ZIRC_PEER_IP_ADDR,
port, &dst_addr);
port, &irc->remote_addr);
if (ret < 0) {
goto connect_exit;
}
#endif
ret = net_context_bind(irc->conn, &src_addr,
ret = net_context_bind(irc->conn, &irc->local_addr,
sizeof(struct ZIRC_SOCKADDR_IN));
if (ret < 0) {
NET_DBG("Could not bind to local address: %d", -ret);
NET_DBG("Could not bind to local address: %d", ret);
goto connect_exit;
}
irc->data = data;
ret = net_context_connect(irc->conn, &dst_addr,
ret = net_context_connect(irc->conn, &irc->remote_addr,
sizeof(struct ZIRC_SOCKADDR_IN),
NULL, K_FOREVER, irc);
if (ret < 0) {
NET_DBG("Could not connect, errno %d", -ret);
NET_DBG("Could not connect, errno %d", ret);
goto connect_exit;
}
@ -845,12 +844,176 @@ on_msg_rcvd(void *data, struct zirc_chan *chan, char *umask, char *msg)
}
#undef CMD
#if defined(CONFIG_NET_DHCPV4) && !defined(CONFIG_NET_IPV6)
#define DHCPV4_TIMEOUT K_SECONDS(30)
static struct net_mgmt_event_callback mgmt4_cb;
static struct k_sem dhcpv4_ok = K_SEM_INITIALIZER(dhcpv4_ok, 0, UINT_MAX);
static void ipv4_addr_add_handler(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event,
struct net_if *iface)
{
char hr_addr[NET_IPV4_ADDR_LEN];
int i;
if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) {
return;
}
for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) {
struct net_if_addr *if_addr = &iface->ipv4.unicast[i];
if (if_addr->addr_type != NET_ADDR_DHCP || !if_addr->is_used) {
continue;
}
NET_INFO("IPv4 address: %s",
net_addr_ntop(AF_INET, &if_addr->address.in_addr,
hr_addr, NET_IPV4_ADDR_LEN));
NET_INFO("Lease time: %u seconds", iface->dhcpv4.lease_time);
NET_INFO("Subnet: %s",
net_addr_ntop(AF_INET, &iface->ipv4.netmask,
hr_addr, NET_IPV4_ADDR_LEN));
NET_INFO("Router: %s",
net_addr_ntop(AF_INET, &iface->ipv4.gw,
hr_addr, NET_IPV4_ADDR_LEN));
break;
}
k_sem_give(&dhcpv4_ok);
}
static void setup_dhcpv4(struct zirc *irc, struct net_if *iface)
{
NET_INFO("Running dhcpv4 client...");
net_mgmt_init_event_callback(&mgmt4_cb, ipv4_addr_add_handler,
NET_EVENT_IPV4_ADDR_ADD);
net_mgmt_add_event_callback(&mgmt4_cb);
net_dhcpv4_start(iface);
if (k_sem_take(&dhcpv4_ok, DHCPV4_TIMEOUT) < 0) {
panic("No IPv4 address.");
}
net_ipaddr_copy(&net_sin(&irc->local_addr)->sin_addr,
&iface->dhcpv4.requested_ip);
irc->local_addr.family = AF_INET;
net_sin(&irc->local_addr)->sin_family = AF_INET;
net_sin(&irc->local_addr)->sin_port = 0;
k_sem_give(&irc->wait_iface);
}
#else
#define setup_dhcpv4(...)
#endif /* CONFIG_NET_DHCPV4 */
#if defined(CONFIG_NET_IPV4) && !defined(CONFIG_NET_DHCPV4)
static void setup_ipv4(struct zirc *irc, struct net_if *iface)
{
char hr_addr[NET_IPV4_ADDR_LEN];
struct in_addr addr;
if (net_addr_pton(AF_INET, ZIRC_LOCAL_IP_ADDR, &addr)) {
NET_ERR("Invalid address: %s", ZIRC_LOCAL_IP_ADDR);
return;
}
net_if_ipv4_addr_add(iface, &addr, NET_ADDR_MANUAL, 0);
NET_INFO("IPv4 address: %s",
net_addr_ntop(AF_INET, &addr, hr_addr, NET_IPV4_ADDR_LEN));
if (in_addr_set(ZIRC_AF_INET, ZIRC_LOCAL_IP_ADDR, 0,
&irc->local_addr) < 0) {
NET_ERR("Invalid IP address: %s", ZIRC_LOCAL_IP_ADDR);
}
k_sem_give(&irc->wait_iface);
}
#else
#define setup_ipv4(...)
#endif /* CONFIG_NET_IPV4 && !CONFIG_NET_DHCPV4 */
#if defined(CONFIG_NET_IPV6)
#define DAD_TIMEOUT K_SECONDS(3)
static struct net_mgmt_event_callback mgmt6_cb;
static struct k_sem dad_ok = K_SEM_INITIALIZER(dad_ok, 0, UINT_MAX);
static struct in6_addr laddr;
static void ipv6_dad_ok_handler(struct net_mgmt_event_callback *cb,
uint32_t mgmt_event,
struct net_if *iface)
{
struct net_if_addr *ifaddr;
if (mgmt_event != NET_EVENT_IPV6_DAD_SUCCEED) {
return;
}
ifaddr = net_if_ipv6_addr_lookup(&laddr, &iface);
if (!ifaddr ||
!(net_ipv6_addr_cmp(&ifaddr->address.in6_addr, &laddr) &&
ifaddr->addr_state == NET_ADDR_PREFERRED)) {
/* Address is not yet properly setup */
return;
}
k_sem_give(&dad_ok);
}
static void setup_ipv6(struct zirc *irc, struct net_if *iface)
{
char hr_addr[NET_IPV6_ADDR_LEN];
if (net_addr_pton(AF_INET6, ZIRC_LOCAL_IP_ADDR, &laddr)) {
NET_ERR("Invalid address: %s", ZIRC_LOCAL_IP_ADDR);
return;
}
NET_INFO("IPv6 address: %s",
net_addr_ntop(AF_INET6, &laddr, hr_addr, NET_IPV6_ADDR_LEN));
net_mgmt_init_event_callback(&mgmt6_cb, ipv6_dad_ok_handler,
NET_EVENT_IPV6_DAD_SUCCEED);
net_mgmt_add_event_callback(&mgmt6_cb);
net_if_ipv6_addr_add(iface, &laddr, NET_ADDR_MANUAL, 0);
if (k_sem_take(&dad_ok, DAD_TIMEOUT) < 0) {
panic("IPv6 address setup failed.");
}
if (in_addr_set(ZIRC_AF_INET, ZIRC_LOCAL_IP_ADDR, 0,
&irc->local_addr) < 0) {
NET_ERR("Invalid IP address: %s", ZIRC_LOCAL_IP_ADDR);
}
k_sem_give(&irc->wait_iface);
}
#else
#define setup_ipv6(...)
#endif /* CONFIG_NET_IPV6 */
static void
initialize_network(void)
initialize_network(struct zirc *irc)
{
struct net_if *iface;
NET_INFO("Initializing network");
NET_INFO("Initializing network");
#if defined(CONFIG_DNS_RESOLVER)
k_sem_init(&irc->wait_dns, 0, UINT_MAX);
#endif
k_sem_init(&irc->wait_iface, 0, UINT_MAX);
iface = net_if_get_default();
if (!iface) {
@ -859,44 +1022,16 @@ initialize_network(void)
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_DHCPV6)
/* TODO: IPV6 DHCP */
#elif defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_DHCPV4)
net_dhcpv4_start(iface);
/* delay so DHCPv4 can assign IP */
/* TODO: add a timeout/retry */
NET_INFO("Waiting for DHCP ...");
do {
k_sleep(K_SECONDS(1));
} while (net_is_ipv4_addr_unspecified(&iface->dhcpv4.requested_ip));
NET_INFO("Done!");
/* TODO: add a timeout */
NET_INFO("Waiting for IP assginment ...");
do {
k_sleep(K_SECONDS(1));
} while (!net_is_my_ipv4_addr(&iface->dhcpv4.requested_ip));
NET_INFO("Done!");
#elif !defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_DHCPV4)
setup_dhcpv4(irc, iface);
#elif !defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4)
setup_ipv4(irc, iface);
#else
struct sockaddr addr;
if (in_addr_set(ZIRC_AF_INET, ZIRC_LOCAL_IP_ADDR, 0,
&addr) < 0) {
NET_ERR("Invalid IP address: %s",
ZIRC_LOCAL_IP_ADDR);
}
#if defined(CONFIG_NET_IPV6)
net_if_ipv6_addr_add(iface,
&net_sin6(&addr)->sin6_addr,
NET_ADDR_MANUAL, 0);
#else
net_if_ipv4_addr_add(iface,
&net_sin(&addr)->sin_addr,
NET_ADDR_MANUAL, 0);
setup_ipv6(irc, iface);
#endif
#endif /* CONFIG_NET_IPV6 && CONFIG_NET_DHCPV6 */
/* Wait until we are ready to continue */
k_sem_take(&irc->wait_iface, K_FOREVER);
}
static void
@ -914,15 +1049,21 @@ static void irc_bot(void)
{
struct zirc irc = { };
struct zirc_chan chan = { };
int ret;
NET_INFO("Zephyr IRC bot sample");
initialize_network();
initialize_network(&irc);
initialize_hardware();
if (zirc_connect(&irc, DEFAULT_SERVER, DEFAULT_PORT, &chan) < 0) {
ret = zirc_connect(&irc, DEFAULT_SERVER, DEFAULT_PORT, &chan);
if (ret < 0 && ret != -EINPROGRESS) {
panic("Could not connect");
}
for (;;) {
k_sleep(K_FOREVER);
}
}
void main(void)

View file

@ -115,12 +115,23 @@ struct net_buf *net_buf_alloc(struct net_buf_pool *pool, int32_t timeout)
uint32_t ref = k_uptime_get_32();
buf = k_lifo_get(&pool->free, K_NO_WAIT);
while (!buf) {
#if defined(CONFIG_NET_BUF_POOL_USAGE)
NET_BUF_WARN("%s():%d: Pool %s low on buffers.",
func, line, pool->name);
#else
NET_BUF_WARN("%s():%d: Pool %p low on buffers.",
func, line, pool);
#endif
buf = k_lifo_get(&pool->free, WARN_ALLOC_INTERVAL);
NET_BUF_WARN("%s():%d: blocked for %u secs",
func, line,
#if defined(CONFIG_NET_BUF_POOL_USAGE)
NET_BUF_WARN("%s():%d: Pool %s blocked for %u secs",
func, line, pool->name,
(k_uptime_get_32() - ref) / MSEC_PER_SEC);
#else
NET_BUF_WARN("%s():%d: Pool %p blocked for %u secs",
func, line, pool,
(k_uptime_get_32() - ref) / MSEC_PER_SEC);
#endif
}
} else {
buf = k_lifo_get(&pool->free, timeout);

View file

@ -53,45 +53,36 @@ static struct net_6lo_context ctx_6co[CONFIG_NET_MAX_6LO_CONTEXTS];
static inline bool net_6lo_ll_prefix_padded_with_zeros(struct in6_addr *addr)
{
return ((addr->s6_addr[2] == 0x00) &&
(addr->s6_addr[3] == 0x00) &&
(addr->s6_addr[4] == 0x00) &&
(addr->s6_addr[5] == 0x00) &&
(addr->s6_addr[6] == 0x00) &&
(addr->s6_addr[7] == 0x00));
return ((UNALIGNED_GET(&addr->s6_addr16[1]) == 0x00) &&
(UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00));
}
static inline bool net_6lo_addr_16_bit_compressible(struct in6_addr *addr)
{
return ((addr->s6_addr[8] == 0x00) &&
(addr->s6_addr[9] == 0x00) &&
(addr->s6_addr[10] == 0x00) &&
(addr->s6_addr[11] == 0xFF) &&
(addr->s6_addr[12] == 0xFE) &&
(addr->s6_addr[13] == 0x00));
return ((UNALIGNED_GET(&addr->s6_addr32[2]) == htonl(0xFF)) &&
(UNALIGNED_GET(&addr->s6_addr16[6]) == htons(0xFE00)));
}
static inline bool net_6lo_maddr_8_bit_compressible(struct in6_addr *addr)
{
return ((addr->s6_addr[1] == 0x02) &&
(addr->s6_addr16[1] == 0x00) &&
(addr->s6_addr32[1] == 0x00) &&
(addr->s6_addr32[2] == 0x00) &&
(UNALIGNED_GET(&addr->s6_addr16[1]) == 0x00) &&
(UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00) &&
(UNALIGNED_GET(&addr->s6_addr32[2]) == 0x00) &&
(addr->s6_addr[14] == 0x00));
}
static inline bool net_6lo_maddr_32_bit_compressible(struct in6_addr *addr)
{
return ((addr->s6_addr32[1] == 0x00) &&
(addr->s6_addr32[2] == 0x00) &&
return ((UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00) &&
(UNALIGNED_GET(&addr->s6_addr32[2]) == 0x00) &&
(addr->s6_addr[12] == 0x00));
}
static inline bool net_6lo_maddr_48_bit_compressible(struct in6_addr *addr)
{
return ((addr->s6_addr32[1] == 0x00) &&
(addr->s6_addr16[4] == 0x00) &&
return ((UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00) &&
(UNALIGNED_GET(&addr->s6_addr16[4]) == 0x00) &&
(addr->s6_addr[10] == 0x00));
}

View file

@ -69,6 +69,13 @@ config NET_APP_IEEE802154_CHANNEL
help
The channel to use by default in the sample application.
config NET_APP_IEEE802154_RADIO_TX_POWER
int "IEEE 802.15.4 TX power in dbm"
default 0
help
The tx power to use by defaulte in the sample application.
See NET_L2_IEEE802154_RADIO_DFLT_TX_POWER for more info.
config NET_APP_IEEE802154_SECURITY_KEY
string "IEEE 802.15.4 security key"
default "moooh!"

View file

@ -40,6 +40,38 @@ config NET_IPV6_MAX_NEIGHBORS
help
The value depends on your network needs.
config NET_IPV6_FRAGMENT
bool "Support IPv6 fragmentation"
default n
help
IPv6 fragmentation is disabled by default. This saves memory and
should not cause issues normally as we support anyway the minimum
length IPv6 packets (1280 bytes). If you enable fragmentation
support, please increase amount of RX data buffers so that larger
than 1280 byte packets can be received.
config NET_IPV6_FRAGMENT_MAX_COUNT
int "How many packets to reassemble at a time"
range 1 16
default 1
depends on NET_IPV6_FRAGMENT
help
How many fragmented IPv6 packets can be waiting reassembly
simultaneously. Each fragment count might use up to 1280 bytes
of memory so you need to plan this and increase the network buffer
count.
config NET_IPV6_FRAGMENT_TIMEOUT
int "How long to wait the fragments to receive"
range 1 60
default 60
depends on NET_IPV6_FRAGMENT
help
How long to wait for IPv6 fragment to arrive before the reassembly
will timeout. RFC 2460 chapter 4.5 tells to wait for 60 seconds but
this might be too long in memory constrained devices. This value
is in seconds.
config NET_IPV6_MLD
bool "Multicast Listener Discovery support"
default y

View file

@ -240,6 +240,13 @@ config NET_RPL_DIS_INTERVAL
This value decides how often DIS messages are sent. The
value is in seconds.
config NET_STATISTICS_RPL
bool "Collect RPL statistics"
depends on NET_STATISTICS
default n
help
Keep track of RPL related statistics
config NET_DEBUG_RPL
bool "Debug RPL"
default n

View file

@ -107,23 +107,23 @@ static inline uint16_t ipv6_to_hash(struct in6_addr *addr)
/* Use more bits from the lower part of address space */
return
/* Take 3 bits from higher values */
TAKE_BIT(addr->s6_addr32[0], 31, 11, 1) |
TAKE_BIT(addr->s6_addr32[0], 15, 11, 2) |
TAKE_BIT(addr->s6_addr32[0], 7, 11, 3) |
TAKE_BIT(UNALIGNED_GET(&addr->s6_addr32[0]), 31, 11, 1) |
TAKE_BIT(UNALIGNED_GET(&addr->s6_addr32[0]), 15, 11, 2) |
TAKE_BIT(UNALIGNED_GET(&addr->s6_addr32[0]), 7, 11, 3) |
/* Take 2 bits from higher middle values */
TAKE_BIT(addr->s6_addr32[1], 31, 11, 4) |
TAKE_BIT(addr->s6_addr32[1], 15, 11, 5) |
TAKE_BIT(UNALIGNED_GET(&addr->s6_addr32[1]), 31, 11, 4) |
TAKE_BIT(UNALIGNED_GET(&addr->s6_addr32[1]), 15, 11, 5) |
/* Take 2 bits from lower middle values */
TAKE_BIT(addr->s6_addr32[2], 31, 11, 6) |
TAKE_BIT(addr->s6_addr32[2], 15, 11, 7) |
TAKE_BIT(UNALIGNED_GET(&addr->s6_addr32[2]), 31, 11, 6) |
TAKE_BIT(UNALIGNED_GET(&addr->s6_addr32[2]), 15, 11, 7) |
/* Take 4 bits from lower values */
TAKE_BIT(addr->s6_addr32[3], 31, 11, 8) |
TAKE_BIT(addr->s6_addr32[3], 15, 11, 9) |
TAKE_BIT(addr->s6_addr32[3], 7, 11, 10) |
TAKE_BIT(addr->s6_addr32[3], 0, 11, 11);
TAKE_BIT(UNALIGNED_GET(&addr->s6_addr32[3]), 31, 11, 8) |
TAKE_BIT(UNALIGNED_GET(&addr->s6_addr32[3]), 15, 11, 9) |
TAKE_BIT(UNALIGNED_GET(&addr->s6_addr32[3]), 7, 11, 10) |
TAKE_BIT(UNALIGNED_GET(&addr->s6_addr32[3]), 0, 11, 11);
}
static inline uint16_t ipv4_to_hash(struct in_addr *addr)

File diff suppressed because it is too large Load diff

View file

@ -276,6 +276,9 @@ struct in6_addr *net_ipv6_nbr_lookup_by_index(struct net_if *iface,
/**
* @brief Add a neighbour to neighbor cache
*
* Add a neighbour to the cache after performing a lookup and in case
* there exists an entry in the cache update its state and lladdr.
*
* @param iface A valid pointer on a network interface
* @param addr Neighbor IPv6 address
* @param lladdr Neighbor link layer address
@ -365,6 +368,64 @@ static inline void net_ipv6_nbr_set_reachable_timer(struct net_if *iface,
}
#endif
#if defined(CONFIG_NET_IPV6_FRAGMENT)
/* We do not have to accept larger than 1500 byte IPv6 packet (RFC 2460 ch 5).
* This means that we should receive everything within first two fragments.
* The first one being 1280 bytes and the second one 220 bytes.
*/
#define NET_IPV6_FRAGMENTS_MAX_BUF 2
/** Store pending IPv6 fragment information that is needed for reassembly. */
struct net_ipv6_reassembly {
/** IPv6 source address of the fragment */
struct in6_addr src;
/** IPv6 destination address of the fragment */
struct in6_addr dst;
/**
* Timeout for cancelling the reassembly. The timer is used
* also to detect if this reassembly slot is used or not.
*/
struct k_delayed_work timer;
/** Pointers to pending fragments */
struct net_buf *buf[NET_IPV6_FRAGMENTS_MAX_BUF];
/** IPv6 fragment identification */
uint32_t id;
};
/**
* @typedef net_ipv6_frag_cb_t
* @brief Callback used while iterating over pending IPv6 fragments.
*
* @param reass IPv6 fragment reassembly struct
* @param user_data A valid pointer on some user data or NULL
*/
typedef void (*net_ipv6_frag_cb_t)(struct net_ipv6_reassembly *reass,
void *user_data);
/**
* @brief Go through all the currently pending IPv6 fragments.
*
* @param cb Callback to call for each pending IPv6 fragment.
* @param user_data User specified data or NULL.
*/
void net_ipv6_frag_foreach(net_ipv6_frag_cb_t cb, void *user_data);
#endif /* CONFIG_NET_IPV6_FRAGMENT */
/**
* @brief Find the last IPv6 extension header in the network packet.
*
* @param buf Network head buffer.
*
* @return Offset to the extension header within the first fragment of net_buf.
* Return <0 if the packet is malformed.
*/
int net_ipv6_find_last_ext_hdr(struct net_buf *buf);
#if defined(CONFIG_NET_IPV6)
void net_ipv6_init(void);
#else

View file

@ -4,7 +4,14 @@
# SPDX-License-Identifier: Apache-2.0
#
menu "IEEE 802.15.4 Radio protocol"
menu "IEEE 802.15.4 Radio"
config NET_L2_IEEE802154_RADIO_DFLT_TX_POWER
int "Default radio transmission power"
default 0
help
TX power in dbm. Valid setting are: -18, -7, -4, -2, 0, 1, 2, 3, 5
If wrongly set, it will silently fail.
config NET_L2_IEEE802154_RADIO_TX_RETRIES
int "Radio Transmission attempts"

View file

@ -334,5 +334,10 @@ void ieee802154_init(struct net_if *iface)
radio->set_ieee_addr(iface->dev, long_addr);
memcpy(ctx->ext_addr, long_addr, 8);
if (!radio->set_txpower(iface->dev,
CONFIG_NET_L2_IEEE802154_RADIO_DFLT_TX_POWER)) {
ctx->tx_power = CONFIG_NET_L2_IEEE802154_RADIO_DFLT_TX_POWER;
}
radio->start(iface->dev);
}

View file

@ -644,7 +644,7 @@ uint8_t *generate_aux_security_hdr(struct ieee802154_security_ctx *sec_ctx,
aux_sec->control.key_id_mode = sec_ctx->key_mode;
aux_sec->control.reserved = 0;
aux_sec->frame_counter = sec_ctx->frame_counter;
aux_sec->frame_counter = sys_cpu_to_le32(sec_ctx->frame_counter);
return p_buf + IEEE802154_SECURITY_CF_LENGTH +
IEEE802154_SECURITY_FRAME_COUNTER_LENGTH;
@ -920,7 +920,8 @@ bool ieee802154_decipher_data_frame(struct net_if *iface, struct net_buf *buf,
net_nbuf_ll_reserve(buf),
net_buf_frags_len(buf),
net_nbuf_ll_src(buf)->addr,
mpdu->mhr.aux_sec->frame_counter)) {
sys_le32_to_cpu(
mpdu->mhr.aux_sec->frame_counter))) {
NET_ERR("Could not decipher the frame");
return false;
}

View file

@ -419,6 +419,13 @@ static int ieee802154_set_parameters(uint32_t mgmt_request,
ctx->short_addr = value;
}
}
} else if (mgmt_request == NET_REQUEST_IEEE802154_SET_TX_POWER) {
if (ctx->tx_power != (int16_t)value) {
ret = radio->set_txpower(iface->dev, (int16_t)value);
if (!ret) {
ctx->tx_power = (int16_t)value;
}
}
}
return ret;
@ -436,6 +443,9 @@ NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_EXT_ADDR,
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_SHORT_ADDR,
ieee802154_set_parameters);
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_TX_POWER,
ieee802154_set_parameters);
static int ieee802154_get_parameters(uint32_t mgmt_request,
struct net_if *iface,
void *data, size_t len)
@ -460,8 +470,12 @@ static int ieee802154_get_parameters(uint32_t mgmt_request,
}
memcpy(data, ctx->ext_addr, IEEE802154_EXT_ADDR_LENGTH);
} else if (mgmt_request == NET_REQUEST_IEEE802154_SET_SHORT_ADDR) {
} else if (mgmt_request == NET_REQUEST_IEEE802154_GET_SHORT_ADDR) {
*value = ctx->short_addr;
} else if (mgmt_request == NET_REQUEST_IEEE802154_GET_TX_POWER) {
int16_t *s_value = (int16_t *)data;
*s_value = ctx->tx_power;
}
return 0;
@ -479,6 +493,9 @@ NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_EXT_ADDR,
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_SHORT_ADDR,
ieee802154_get_parameters);
NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_IEEE802154_GET_TX_POWER,
ieee802154_get_parameters);
#ifdef CONFIG_NET_L2_IEEE802154_SECURITY
static int ieee802154_set_security_settings(uint32_t mgmt_request,

View file

@ -347,6 +347,36 @@ static int shell_cmd_get_short_addr(int argc, char *argv[])
return 0;
}
static int shell_cmd_set_tx_power(int argc, char *argv[])
{
struct net_if *iface = net_if_get_default();
int16_t tx_power = (int16_t) atoi(argv[1]);
if (net_mgmt(NET_REQUEST_IEEE802154_SET_TX_POWER, iface,
&tx_power, sizeof(int16_t))) {
printk("Could not set TX power %d\n", tx_power);
} else {
printk("TX power %d set\n", tx_power);
}
return 0;
}
static int shell_cmd_get_tx_power(int argc, char *argv[])
{
struct net_if *iface = net_if_get_default();
int16_t tx_power;
if (net_mgmt(NET_REQUEST_IEEE802154_GET_SHORT_ADDR, iface,
&tx_power, sizeof(int16_t))) {
printk("Could not get TX power\n");
} else {
printk("TX power (in dbm) %d\n", tx_power);
}
return 0;
}
static struct shell_cmd ieee802154_commands[] = {
{ "ack", shell_cmd_ack,
"<set/1 | unset/0>" },
@ -373,6 +403,10 @@ static struct shell_cmd ieee802154_commands[] = {
"<short address>" },
{ "get_short_addr", shell_cmd_get_short_addr,
NULL },
{ "set_tx_power", shell_cmd_set_tx_power,
"<-18/-7/-4/-2/0/1/2/3/5>" },
{ "get_tx_power", shell_cmd_get_tx_power,
NULL },
{ NULL, NULL, NULL },
};

View file

@ -1516,6 +1516,59 @@ bool net_nbuf_insert(struct net_buf *buf, struct net_buf *frag,
return insert_data(buf, frag, temp, offset, len, data, timeout);
}
int net_nbuf_split(struct net_buf *buf, struct net_buf *orig_frag,
uint16_t len, struct net_buf **fragA,
struct net_buf **fragB, int32_t timeout)
{
if (!buf || !orig_frag || is_from_data_pool(buf)) {
return -EINVAL;
}
NET_ASSERT(fragA && fragB);
if (len == 0) {
*fragA = NULL;
*fragB = NULL;
return 0;
}
if (len > net_buf_tailroom(*fragA)) {
NET_DBG("Length %u is larger than fragment size %zd",
len, net_buf_tailroom(*fragA));
return -EINVAL;
}
if (len > orig_frag->len) {
*fragA = net_nbuf_get_frag(buf, timeout);
if (!*fragA) {
return -ENOMEM;
}
memcpy(net_buf_add(*fragA, orig_frag->len), orig_frag->data,
orig_frag->len);
*fragB = NULL;
return 0;
}
*fragA = net_nbuf_get_frag(buf, timeout);
if (!*fragA) {
return -ENOMEM;
}
*fragB = net_nbuf_get_frag(buf, timeout);
if (!*fragB) {
net_nbuf_unref(*fragA);
return -ENOMEM;
}
memcpy(net_buf_add(*fragA, len), orig_frag->data, len);
memcpy(net_buf_add(*fragB, orig_frag->len - len),
orig_frag->data + len, orig_frag->len - len);
return 0;
}
void net_nbuf_get_info(struct net_buf_pool **rx,
struct net_buf_pool **tx,
struct net_buf_pool **rx_data,

View file

@ -68,6 +68,17 @@ static inline enum net_verdict process_data(struct net_buf *buf,
bool is_loopback)
{
int ret;
bool locally_routed = false;
#if defined(CONFIG_NET_IPV6_FRAGMENT)
/* If the packet is routed back to us when we have reassembled
* an IPv6 packet, then do not pass it to L2 as the packet does
* not have link layer headers in it.
*/
if (net_nbuf_ipv6_fragment_start(buf)) {
locally_routed = true;
}
#endif
/* If there is no data, then drop the packet. Also if
* the buffer is wrong type, then also drop the packet.
@ -83,7 +94,7 @@ static inline enum net_verdict process_data(struct net_buf *buf,
return NET_DROP;
}
if (!is_loopback) {
if (!is_loopback && !locally_routed) {
ret = net_if_recv_data(net_nbuf_iface(buf), buf);
if (ret != NET_CONTINUE) {
if (ret == NET_DROP) {

View file

@ -397,6 +397,8 @@ static void dad_timeout(struct k_work *work)
*/
tmp = net_if_ipv6_addr_lookup(&ifaddr->address.in6_addr, &iface);
if (tmp == ifaddr) {
net_mgmt_event_notify(NET_EVENT_IPV6_DAD_SUCCEED, iface);
/* The address gets added to neighbor cache which is not needed
* in this case as the address is our own one.
*/
@ -444,6 +446,24 @@ void net_if_start_dad(struct net_if *iface)
net_sprint_ipv6_addr(&addr), iface);
}
}
void net_if_ipv6_dad_failed(struct net_if *iface, const struct in6_addr *addr)
{
struct net_if_addr *ifaddr;
ifaddr = net_if_ipv6_addr_lookup(addr, &iface);
if (!ifaddr) {
NET_ERR("Cannot find %s address in interface %p",
net_sprint_ipv6_addr(addr), iface);
return;
}
k_delayed_work_cancel(&ifaddr->dad_timer);
net_mgmt_event_notify(NET_EVENT_IPV6_DAD_FAILED, iface);
net_if_ipv6_addr_rm(iface, addr);
}
#else
static inline void net_if_ipv6_start_dad(struct net_if *iface,
struct net_if_addr *ifaddr)
@ -459,13 +479,13 @@ static inline void net_if_ipv6_start_dad(struct net_if *iface,
static void rs_timeout(struct k_work *work)
{
/* Did not receive RA yet. */
struct net_if *iface = CONTAINER_OF(work, struct net_if, rs_timer);
struct net_if *iface = CONTAINER_OF(work, struct net_if, ipv6.rs_timer);
iface->rs_count++;
iface->ipv6.rs_count++;
NET_DBG("RS no respond iface %p count %d", iface, iface->rs_count);
NET_DBG("RS no respond iface %p count %d", iface, iface->ipv6.rs_count);
if (iface->rs_count < RS_COUNT) {
if (iface->ipv6.rs_count < RS_COUNT) {
net_if_start_rs(iface);
}
}
@ -475,7 +495,7 @@ void net_if_start_rs(struct net_if *iface)
NET_DBG("Interface %p", iface);
if (!net_ipv6_start_rs(iface)) {
k_delayed_work_submit(&iface->rs_timer, RS_TIMEOUT);
k_delayed_work_submit(&iface->ipv6.rs_timer, RS_TIMEOUT);
}
}
#endif /* CONFIG_NET_IPV6_ND */
@ -617,7 +637,7 @@ struct net_if_addr *net_if_ipv6_addr_add(struct net_if *iface,
return NULL;
}
bool net_if_ipv6_addr_rm(struct net_if *iface, struct in6_addr *addr)
bool net_if_ipv6_addr_rm(struct net_if *iface, const struct in6_addr *addr)
{
int i;
@ -1287,10 +1307,10 @@ const struct in6_addr *net_if_ipv6_select_src_addr(struct net_if *dst_iface,
uint32_t net_if_ipv6_calc_reachable_time(struct net_if *iface)
{
return MIN_RANDOM_FACTOR * iface->base_reachable_time +
return MIN_RANDOM_FACTOR * iface->ipv6.base_reachable_time +
sys_rand32_get() %
(MAX_RANDOM_FACTOR * iface->base_reachable_time -
MIN_RANDOM_FACTOR * iface->base_reachable_time);
(MAX_RANDOM_FACTOR * iface->ipv6.base_reachable_time -
MIN_RANDOM_FACTOR * iface->ipv6.base_reachable_time);
}
#else /* CONFIG_NET_IPV6 */
@ -1394,7 +1414,7 @@ struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
continue;
}
if (addr->s4_addr32[0] ==
if (UNALIGNED_GET(&addr->s4_addr32[0]) ==
iface->ipv4.unicast[i].address.in_addr.s_addr[0]) {
if (ret) {
@ -1638,17 +1658,17 @@ void net_if_init(struct k_sem *startup_sync)
init_iface(iface);
#if defined(CONFIG_NET_IPV4)
iface->ttl = CONFIG_NET_INITIAL_TTL;
iface->ipv4.ttl = CONFIG_NET_INITIAL_TTL;
#endif
#if defined(CONFIG_NET_IPV6)
iface->hop_limit = CONFIG_NET_INITIAL_HOP_LIMIT;
iface->base_reachable_time = REACHABLE_TIME;
iface->ipv6.hop_limit = CONFIG_NET_INITIAL_HOP_LIMIT;
iface->ipv6.base_reachable_time = REACHABLE_TIME;
net_if_ipv6_set_reachable_time(iface);
#if defined(CONFIG_NET_IPV6_ND)
k_delayed_work_init(&iface->rs_timer, rs_timeout);
k_delayed_work_init(&iface->ipv6.rs_timer, rs_timeout);
#endif
#endif
}

View file

@ -23,6 +23,11 @@ enum net_verdict net_ipv4_process_pkt(struct net_buf *buf);
enum net_verdict net_ipv6_process_pkt(struct net_buf *buf);
extern void net_ipv6_init(void);
#if defined(CONFIG_NET_IPV6_FRAGMENT)
int net_ipv6_send_fragmented_pkt(struct net_if *iface, struct net_buf *buf,
uint16_t pkt_len);
#endif
extern const char *net_proto2str(enum net_ip_protocol proto);
extern char *net_byte_to_hex(char *ptr, uint8_t byte, char base, bool pad);
extern char *net_sprint_ll_addr_buf(const uint8_t *ll, uint8_t ll_len,

View file

@ -170,10 +170,11 @@ static void iface_cb(struct net_if *iface, void *user_data)
router->is_infinite ? " infinite" : "");
}
printk("IPv6 hop limit : %d\n", iface->hop_limit);
printk("IPv6 base reachable time : %d\n", iface->base_reachable_time);
printk("IPv6 reachable time : %d\n", iface->reachable_time);
printk("IPv6 retransmit timer : %d\n", iface->retrans_timer);
printk("IPv6 hop limit : %d\n", iface->ipv6.hop_limit);
printk("IPv6 base reachable time : %d\n",
iface->ipv6.base_reachable_time);
printk("IPv6 reachable time : %d\n", iface->ipv6.reachable_time);
printk("IPv6 retransmit timer : %d\n", iface->ipv6.retrans_timer);
#endif /* CONFIG_NET_IPV6 */
#if defined(CONFIG_NET_IPV4)
@ -310,7 +311,7 @@ static void route_mcast_cb(struct net_route_entry_mcast *entry,
printk("========================================================\n");
printk("IPv6 group : %s\n", net_sprint_ipv6_addr(&entry->group));
printk("Lifetime : %lu\n", entry->lifetime);
printk("Lifetime : %u\n", entry->lifetime);
}
static void iface_per_mcast_route_cb(struct net_if *iface, void *user_data)
@ -371,7 +372,7 @@ static inline void net_shell_print_statistics(void)
GET_STAT(udp.chkerr));
#endif
#if defined(CONFIG_NET_RPL_STATS)
#if defined(CONFIG_NET_STATISTICS_RPL)
printk("RPL DIS recv %d\tsent\t%d\tdrop\t%d\n",
GET_STAT(rpl.dis.recv),
GET_STAT(rpl.dis.sent),
@ -484,6 +485,27 @@ static void tcp_cb(struct net_tcp *tcp, void *user_data)
}
#endif
#if defined(CONFIG_NET_IPV6_FRAGMENT)
static void ipv6_frag_cb(struct net_ipv6_reassembly *reass,
void *user_data)
{
int *count = user_data;
char src[ADDR_LEN];
if (!*count) {
printk("\nIPv6 reassembly Id Remain Src\t\t\t\tDst\n");
}
snprintk(src, ADDR_LEN, "%s", net_sprint_ipv6_addr(&reass->src));
printk("%p 0x%08x %5d %s\t%s\n",
reass, reass->id, k_delayed_work_remaining_get(&reass->timer),
src, net_sprint_ipv6_addr(&reass->dst));
(*count)++;
}
#endif /* CONFIG_NET_IPV6_FRAGMENT */
#if defined(CONFIG_NET_DEBUG_NET_BUF)
static void allocs_cb(struct net_buf *buf,
const char *func_alloc,
@ -566,6 +588,14 @@ static int shell_cmd_conn(int argc, char *argv[])
}
#endif
#if defined(CONFIG_NET_IPV6_FRAGMENT)
count = 0;
net_ipv6_frag_foreach(ipv6_frag_cb, &count);
/* Do not print anything if no fragments are pending atm */
#endif
return 0;
}

View file

@ -80,7 +80,7 @@ void net_print_statistics(void)
GET_STAT(udp.chkerr));
#endif
#if defined(CONFIG_NET_STATISTICS_RPL_STATS)
#if defined(CONFIG_NET_STATISTICS_RPL)
NET_INFO("RPL DIS recv %d\tsent\t%d\tdrop\t%d",
GET_STAT(rpl.dis.recv),
GET_STAT(rpl.dis.sent),
@ -112,7 +112,7 @@ void net_print_statistics(void)
GET_STAT(rpl.loop_warnings));
NET_INFO("RPL r-repairs %d",
GET_STAT(rpl.root_repairs));
#endif
#endif /* CONFIG_NET_STATISTICS_RPL */
NET_INFO("Bytes received %u", GET_STAT(bytes.received));
NET_INFO("Bytes sent %u", GET_STAT(bytes.sent));

View file

@ -648,7 +648,7 @@ bool net_route_mcast_del(struct net_route_entry_mcast *route)
}
NET_ASSERT_INFO(route->is_used,
"Multicast route %d to %s was already removed", i,
"Multicast route %p to %s was already removed", route,
net_sprint_ipv6_addr(&route->group));
route->is_used = false;

View file

@ -304,7 +304,7 @@ static int net_rpl_mrhof_update_mc(struct net_rpl_instance *instance)
instance->mc.type = NET_RPL_MC_NONE;
return 0;
#else
rpl_path_metric_t path_metric;
uint16_t path_metric;
struct net_rpl_dag *dag;
#if defined(CONFIG_NET_RPL_MC_ENERGY)
@ -321,7 +321,7 @@ static int net_rpl_mrhof_update_mc(struct net_rpl_instance *instance)
dag = instance->current_dag;
if (!dag->joined) {
if (!net_rpl_dag_is_joined(dag)) {
NET_DBG("Cannot update the metric container when not joined.");
return -EINVAL;
}

View file

@ -113,6 +113,10 @@ static enum net_rpl_mode rpl_mode = NET_RPL_MODE_MESH;
static net_rpl_join_callback_t rpl_join_callback;
static uint8_t rpl_dao_sequence;
#if NET_RPL_MULTICAST
static void send_mcast_dao(struct net_rpl_instance *instance);
#endif
#if defined(CONFIG_NET_RPL_DIS_SEND)
/* DODAG Information Solicitation timer. */
struct k_delayed_work dis_timer;
@ -604,7 +608,7 @@ static void dio_timer(struct k_work *work)
net_rpl_dio_send(iface, instance, addr, NULL);
#if defined(CONFIG_NET_RPL_STATS)
#if defined(CONFIG_NET_STATISTICS_RPL)
instance->dio_send_pkt++;
#endif
} else {
@ -651,7 +655,7 @@ static void new_dio_interval(struct net_rpl_instance *instance)
*/
instance->dio_next_delay -= time;
#if defined(CONFIG_NET_RPL_STATS)
#if defined(CONFIG_NET_STATISTICS_RPL)
instance->dio_intervals++;
instance->dio_recv_pkt += instance->dio_counter;
@ -667,7 +671,7 @@ static void new_dio_interval(struct net_rpl_instance *instance)
instance->dio_interval_current,
instance->current_dag->rank == NET_RPL_ROOT_RANK(instance) ?
"ROOT" : "");
#endif /* CONFIG_NET_RPL_STATS */
#endif /* CONFIG_NET_STATISTICS_RPL */
instance->dio_counter = 0;
instance->dio_send = true;
@ -1021,7 +1025,9 @@ static inline void net_rpl_instance_init(struct net_rpl_instance *instance,
instance->is_used = true;
k_delayed_work_init(&instance->dio_timer, dio_timer);
#if defined(CONFIG_NET_RPL_PROBING)
k_delayed_work_init(&instance->probing_timer, rpl_probing_timer);
#endif
k_delayed_work_init(&instance->dao_lifetime_timer, dao_lifetime_timer);
k_delayed_work_init(&instance->dao_timer, dao_send_timer);
#if defined(CONFIG_NET_RPL_DAO_ACK)
@ -1130,12 +1136,10 @@ static void route_mcast_rm_cb(struct net_route_entry_mcast *route,
void *user_data)
{
struct net_rpl_dag *dag = user_data;
struct net_rpl_route_entry *extra;
extra = net_nbr_extra_data(net_route_get_nbr(entry));
struct net_rpl_route_entry *extra = route->data;
if (extra->dag == dag) {
net_route_mcast_del(route)
net_route_mcast_del(route);
}
}
#endif
@ -1145,7 +1149,7 @@ static void net_rpl_remove_routes(struct net_rpl_dag *dag)
net_route_foreach(route_rm_cb, dag);
#if NET_RPL_MULTICAST
net_route_mcast_foreach(route_mcast_rm_cb, dag);
net_route_mcast_foreach(route_mcast_rm_cb, NULL, dag);
#endif
}
@ -2126,28 +2130,27 @@ static void global_repair(struct net_if *iface,
} while (0)
#if NET_RPL_MULTICAST
static void send_mcast_dao(struct net_route_entry_mcast *route,
void *user_data)
static void send_mcast_dao_cb(struct net_route_entry_mcast *route,
void *user_data)
{
struct net_rpl_instance *instance = user_data;
/* Don't send if it's also our own address, done that already */
if (!net_route_mcast_lookup(&route->group)) {
net_rpl_dao_send(instance->current_dag->preferred_parent,
net_rpl_dao_send(instance->iface,
instance->current_dag->preferred_parent,
&route->group,
CONFIG_NET_RPL_MCAST_LIFETIME);
}
}
static inline void send_mcast_dao(struct net_rpl_instance *instance)
static void send_mcast_dao(struct net_rpl_instance *instance)
{
uip_mcast6_route_t *mcast_route;
struct in6_addr *addr = NULL;
uint8_t i;
/* Send a DAO for own multicast addresses */
for (i = 0; i < NET_IF_MAX_IPV6_MADDR; i++) {
struct in6_addr *addr;
addr = &instance->iface->ipv6.mcast[i].address.in6_addr;
if (instance->iface->ipv6.mcast[i].is_used &&
@ -2161,7 +2164,7 @@ static inline void send_mcast_dao(struct net_rpl_instance *instance)
}
/* Iterate over multicast routes and send DAOs */
net_route_mcast_foreach(send_mcast_dao, addr, instance);
net_route_mcast_foreach(send_mcast_dao_cb, addr, instance);
}
#endif
@ -3787,6 +3790,8 @@ static inline int add_rpl_opt(struct net_buf *buf, uint16_t offset)
bool ret;
/* next header */
net_nbuf_set_ipv6_hdr_prev(buf, offset);
ret = net_nbuf_insert_u8(buf, buf->frags, offset++,
NET_IPV6_BUF(buf)->nexthdr);
if (!ret) {
@ -3854,6 +3859,8 @@ static int net_rpl_update_header_empty(struct net_buf *buf)
NET_DBG("Verifying the presence of the RPL header option");
net_nbuf_set_ipv6_hdr_prev(buf, offset);
frag = net_nbuf_read_u8(frag, offset, &offset, &next_hdr);
frag = net_nbuf_read_u8(frag, offset, &offset, &len);
if (!frag) {
@ -4117,7 +4124,7 @@ void net_rpl_init(void)
CONFIG_NET_IPV6_MAX_NEIGHBORS,
sizeof(net_rpl_neighbor_pool));
#if defined(CONFIG_NET_RPL_STATS)
#if defined(CONFIG_NET_STATISTICS_RPL)
memset(&net_stats.rpl, 0, sizeof(net_stats.rpl));
#endif

View file

@ -463,7 +463,7 @@ struct net_rpl_instance {
*/
uint16_t lifetime_unit;
#if defined(CONFIG_NET_RPL_STATS)
#if defined(CONFIG_NET_STATISTICS_RPL)
/** Number of DIO intervals for this RPL instance. */
uint16_t dio_intervals;
@ -472,7 +472,7 @@ struct net_rpl_instance {
/** Number of DIOs received for this RPL instance. */
uint16_t dio_recv_pkt;
#endif /* CONFIG_NET_RPL_STATS */
#endif /* CONFIG_NET_STATISTICS_RPL */
/**
* This is the lifetime that is used as default for all RPL routes.
@ -639,10 +639,10 @@ struct net_rpl_route_entry {
*/
static inline bool net_rpl_is_ipv6_addr_mcast(const struct in6_addr *addr)
{
return addr->s6_addr32[0] == htonl(0xff020000) &&
addr->s6_addr32[1] == 0x00000000 &&
addr->s6_addr32[2] == 0x00000000 &&
addr->s6_addr32[3] == htonl(0x0000001a);
return UNALIGNED_GET(&addr->s6_addr32[0]) == htonl(0xff020000) &&
UNALIGNED_GET(&addr->s6_addr32[1]) == 0x00000000 &&
UNALIGNED_GET(&addr->s6_addr32[2]) == 0x00000000 &&
UNALIGNED_GET(&addr->s6_addr32[3]) == htonl(0x0000001a);
}
/**
@ -657,12 +657,12 @@ struct in6_addr *net_rpl_create_mcast_address(struct in6_addr *addr)
{
addr->s6_addr[0] = 0xFF;
addr->s6_addr[1] = 0x02;
addr->s6_addr16[1] = 0;
addr->s6_addr16[2] = 0;
addr->s6_addr16[3] = 0;
addr->s6_addr16[4] = 0;
addr->s6_addr16[5] = 0;
addr->s6_addr16[6] = 0;
UNALIGNED_PUT(0, &addr->s6_addr16[1]);
UNALIGNED_PUT(0, &addr->s6_addr16[2]);
UNALIGNED_PUT(0, &addr->s6_addr16[3]);
UNALIGNED_PUT(0, &addr->s6_addr16[4]);
UNALIGNED_PUT(0, &addr->s6_addr16[5]);
UNALIGNED_PUT(0, &addr->s6_addr16[6]);
addr->s6_addr[14] = 0;
addr->s6_addr[15] = 0x1a;

View file

@ -154,7 +154,9 @@ static void tcp_retry_expired(struct k_timer *timer)
struct net_buf, sent_list);
do_ref_if_needed(buf);
net_tcp_send_buf(buf);
if (net_tcp_send_buf(buf) < 0 && !is_6lo_technology(buf)) {
net_nbuf_unref(buf);
}
} else if (IS_ENABLED(CONFIG_NET_TCP_TIME_WAIT)) {
if (tcp->fin_sent && tcp->fin_rcvd) {
net_context_unref(tcp->context);
@ -521,8 +523,9 @@ static void net_tcp_set_syn_opt(struct net_tcp *tcp, uint8_t *options,
recv_mss = 0;
}
*((uint32_t *)(options + *optionlen)) =
htonl((uint32_t)(recv_mss | NET_TCP_MSS_HEADER));
UNALIGNED_PUT(htonl((uint32_t)recv_mss | NET_TCP_MSS_HEADER),
(uint32_t *)(options + *optionlen));
*optionlen += NET_TCP_MSS_SIZE;
}
@ -763,7 +766,10 @@ int net_tcp_send_data(struct net_context *context)
*/
SYS_SLIST_FOR_EACH_CONTAINER(&context->tcp->sent_list, buf, sent_list) {
if (!net_nbuf_buf_sent(buf)) {
net_tcp_send_buf(buf);
if (net_tcp_send_buf(buf) < 0 &&
!is_6lo_technology(buf)) {
net_nbuf_unref(buf);
}
}
}

View file

@ -141,7 +141,7 @@ char *net_addr_ntop(sa_family_t family, const void *src,
uint8_t j;
for (j = i; j < 8; j++) {
if (w[j] != 0) {
if (UNALIGNED_GET(&w[j]) != 0) {
break;
}
@ -208,7 +208,7 @@ char *net_addr_ntop(sa_family_t family, const void *src,
needcolon = false;
}
value = (uint32_t)sys_be16_to_cpu(w[i]);
value = (uint32_t)sys_be16_to_cpu(UNALIGNED_GET(&w[i]));
bh = value >> 8;
bl = value & 0xff;
@ -306,8 +306,8 @@ int net_addr_pton(sa_family_t family, const char *src,
if (*src != ':') {
/* Normal IPv6 16-bit piece */
addr->s6_addr16[i] = htons(strtol(src, NULL,
16));
UNALIGNED_PUT(htons(strtol(src, NULL, 16)),
&addr->s6_addr16[i]);
src = strchr(src, ':');
if (!src && i < expected_groups - 1) {
return -EINVAL;
@ -320,7 +320,7 @@ int net_addr_pton(sa_family_t family, const char *src,
/* Two colons in a row */
for (; i < expected_groups; i++) {
addr->s6_addr16[i] = 0;
UNALIGNED_PUT(0, &addr->s6_addr16[i]);
}
tmp = strrchr(src, ':');

View file

@ -1,5 +1,4 @@
ccflags-y += -I$(srctree)/subsys/net/lib/dns
obj-y := dns_pack.o
obj-$(CONFIG_DNS_RESOLVER) += dns_client.o
obj-$(CONFIG_DNS_RESOLVER) += resolve.o

View file

@ -1,18 +0,0 @@
DNS Client API for Zephyr
=========================
Known limitations:
- Synchronous queries
- Only IPv4 and IPv6 records can be handled
- Minimal protocol validation. If you do not trust your DNS server,
it is time to change it :)
Usage:
Before calling the resolver, it must be initialized via the 'dns_init'
routine.
See samples/net/dns_client/src/main.c.

View file

@ -1,362 +0,0 @@
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <net/dns_client.h>
#include "dns_pack.h"
#include <drivers/rand32.h>
#include <net/buf.h>
#include <net/nbuf.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
/* RFC 1035, 3.1. Name space definitions
* To simplify implementations, the total length of a domain name (i.e.,
* label octets and label length octets) is restricted to 255 octets or
* less.
*/
#define DNS_MAX_NAME_LEN 255
#define DNS_QUERY_MAX_SIZE (DNS_MSG_HEADER_SIZE + DNS_MAX_NAME_LEN + \
DNS_QTYPE_LEN + DNS_QCLASS_LEN)
/* This value is recommended by RFC 1035 */
#define DNS_RESOLVER_MAX_BUF_SIZE 512
#define DNS_RESOLVER_MIN_BUF 1
#define DNS_RESOLVER_BUF_CTR (DNS_RESOLVER_MIN_BUF + \
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR)
#define DNS_RESOLVER_QUERIES (1 + CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES)
/* Compressed RR uses a pointer to another RR. So, min size is 12 bytes without
* considering RR payload.
* See https://tools.ietf.org/html/rfc1035#section-4.1.4
*/
#define DNS_ANSWER_PTR_LEN 12
/* See dns_unpack_answer, and also see:
* https://tools.ietf.org/html/rfc1035#section-4.1.2
*/
#define DNS_QUERY_POS 0x0c
#define DNS_IPV4_LEN 4
#define DNS_IPV6_LEN 16
NET_BUF_POOL_DEFINE(dns_msg_pool, DNS_RESOLVER_BUF_CTR,
DNS_RESOLVER_MAX_BUF_SIZE, 0, NULL);
NET_BUF_POOL_DEFINE(dns_qname_pool, DNS_RESOLVER_BUF_CTR, DNS_MAX_NAME_LEN,
0, NULL);
int dns_init(struct dns_context *ctx)
{
k_sem_init(&ctx->rx_sem, 0, UINT_MAX);
return 0;
}
static int dns_write(struct dns_context *ctx, struct net_buf *dns_data,
uint16_t dns_id, struct net_buf *dns_qname);
static int dns_read(struct dns_context *ctx, struct net_buf *dns_data,
uint16_t dns_id, struct net_buf *cname);
/* net_context_recv callback */
static void cb_recv(struct net_context *net_ctx, struct net_buf *buf,
int status, void *data);
/*
* Note about the DNS transaction identifier:
* The transaction identifier is randomized according to:
* http://www.cisco.com/c/en/us/about/security-center/dns-best-practices.html#3
* Here we assume that even after the cast, dns_id = sys_rand32_get(), there is
* enough entropy :)
*/
int dns_resolve(struct dns_context *ctx)
{
struct net_buf *dns_data = NULL;
struct net_buf *dns_qname = NULL;
uint16_t dns_id;
int rc;
int i;
k_sem_reset(&ctx->rx_sem);
dns_id = sys_rand32_get();
net_context_recv(ctx->net_ctx, cb_recv, K_NO_WAIT, ctx);
dns_data = net_buf_alloc(&dns_msg_pool, ctx->timeout);
if (dns_data == NULL) {
rc = -ENOMEM;
goto exit_resolve;
}
dns_qname = net_buf_alloc(&dns_qname_pool, ctx->timeout);
if (dns_qname == NULL) {
rc = -ENOMEM;
goto exit_resolve;
}
rc = dns_msg_pack_qname(&dns_qname->len, dns_qname->data,
DNS_MAX_NAME_LEN, ctx->name);
if (rc != 0) {
rc = -EINVAL;
goto exit_resolve;
}
i = 0;
do {
rc = dns_write(ctx, dns_data, dns_id, dns_qname);
if (rc != 0) {
goto exit_resolve;
}
rc = dns_read(ctx, dns_data, dns_id, dns_qname);
if (rc != 0) {
goto exit_resolve;
}
/* Server response includes at least one IP address */
if (ctx->items > 0) {
break;
}
} while (++i < DNS_RESOLVER_QUERIES);
if (ctx->items > 0) {
rc = 0;
} else {
rc = -EINVAL;
}
exit_resolve:
/* dns_data may be NULL, however net_nbuf_unref supports that */
net_nbuf_unref(dns_data);
net_nbuf_unref(dns_qname);
/* uninstall the callback */
net_context_recv(ctx->net_ctx, NULL, 0, NULL);
return rc;
}
static int dns_write(struct dns_context *ctx, struct net_buf *dns_data,
uint16_t dns_id, struct net_buf *dns_qname)
{
struct net_buf *tx;
int server_addr_len;
int rc;
rc = dns_msg_pack_query(dns_data->data, &dns_data->len, dns_data->size,
dns_qname->data, dns_qname->len, dns_id,
(enum dns_rr_type)ctx->query_type);
if (rc != 0) {
rc = -EINVAL;
goto exit_write;
}
tx = net_nbuf_get_tx(ctx->net_ctx, K_FOREVER);
if (tx == NULL) {
rc = -ENOMEM;
goto exit_write;
}
rc = net_nbuf_append(tx, dns_data->len, dns_data->data, K_FOREVER);
if (rc != true) {
rc = -ENOMEM;
goto exit_write;
}
if (ctx->dns_server->family == AF_INET) {
server_addr_len = sizeof(struct sockaddr_in);
} else {
server_addr_len = sizeof(struct sockaddr_in6);
}
/* tx and dns_data buffers will be dereferenced after this call */
rc = net_context_sendto(tx, ctx->dns_server, server_addr_len, NULL,
ctx->timeout, NULL, NULL);
if (rc != 0) {
rc = -EIO;
goto exit_write;
}
rc = 0;
exit_write:
return rc;
}
static void cb_recv(struct net_context *net_ctx, struct net_buf *buf,
int status, void *data)
{
struct dns_context *ctx = (struct dns_context *)data;
ARG_UNUSED(net_ctx);
if (status != 0) {
return;
}
ctx->rx_buf = buf;
k_sem_give(&ctx->rx_sem);
}
static int dns_read(struct dns_context *ctx, struct net_buf *dns_data,
uint16_t dns_id, struct net_buf *cname)
{
/* helper struct to track the dns msg received from the server */
struct dns_msg_t dns_msg;
uint8_t *addresses;
/* RR ttl, so far it is not passed to caller */
uint32_t ttl;
uint8_t *src;
uint8_t *dst;
int address_size;
/* index that points to the current answer being analyzed */
int answer_ptr;
int data_len;
int offset;
int rc;
int i;
/* The cast is applied on address.ipv4, however we can also apply it on
* address.ipv6 and we will get the same result.
*/
addresses = (uint8_t *)ctx->address.ipv4;
if (ctx->elements <= 0) {
rc = -EINVAL;
goto exit_error;
}
ctx->rx_buf = NULL;
/* Block until timeout or data is received, see the 'cb_recv' routine */
k_sem_take(&ctx->rx_sem, ctx->timeout);
/* If data is received, rx_buf is set inside 'cb_recv'. Otherwise,
* k_sem_take will expire while ctx->rx_buf is still NULL
*/
if (!ctx->rx_buf) {
rc = -EIO;
goto exit_error;
}
data_len = min(net_nbuf_appdatalen(ctx->rx_buf),
DNS_RESOLVER_MAX_BUF_SIZE);
offset = net_buf_frags_len(ctx->rx_buf) - data_len;
rc = net_nbuf_linear_copy(dns_data, ctx->rx_buf, offset, data_len);
if (rc != 0) {
rc = -ENOMEM;
goto exit_error;
}
k_sem_give(&ctx->rx_sem);
dns_msg.msg = dns_data->data;
dns_msg.msg_size = data_len;
rc = dns_unpack_response_header(&dns_msg, dns_id);
if (rc != 0) {
rc = -EINVAL;
goto exit_error;
}
if (dns_header_qdcount(dns_msg.msg) != 1) {
rc = -EINVAL;
goto exit_error;
}
rc = dns_unpack_response_query(&dns_msg);
if (rc != 0) {
rc = -EINVAL;
goto exit_error;
}
if (ctx->query_type == DNS_QUERY_TYPE_A) {
address_size = DNS_IPV4_LEN;
} else {
address_size = DNS_IPV6_LEN;
}
/* while loop to traverse the response */
answer_ptr = DNS_QUERY_POS;
ctx->items = 0;
i = 0;
while (i < dns_header_ancount(dns_msg.msg)) {
rc = dns_unpack_answer(&dns_msg, answer_ptr, &ttl);
if (rc != 0) {
rc = -EINVAL;
goto exit_error;
}
switch (dns_msg.response_type) {
case DNS_RESPONSE_IP:
if (dns_msg.response_length < address_size) {
/* it seems this is a malformed message */
rc = -EINVAL;
goto exit_error;
}
src = dns_msg.msg + dns_msg.response_position;
dst = addresses + ctx->items * address_size;
memcpy(dst, src, address_size);
ctx->items += 1;
if (ctx->items >= ctx->elements) {
/* elements is always >= 1, so it is assumed
* that at least one address was returned.
*/
goto exit_ok;
}
break;
case DNS_RESPONSE_CNAME_NO_IP:
/* Instead of using the QNAME at DNS_QUERY_POS,
* we will use this CNAME
*/
answer_ptr = dns_msg.response_position;
break;
default:
rc = -EINVAL;
goto exit_error;
}
/* Update the answer offset to point to the next RR (answer) */
dns_msg.answer_offset += DNS_ANSWER_PTR_LEN;
dns_msg.answer_offset += dns_msg.response_length;
++i;
}
/* No IP addresses were found, so we take the last CNAME to generate
* another query. Number of additional queries is controlled via Kconfig
*/
if (ctx->items == 0) {
if (dns_msg.response_type == DNS_RESPONSE_CNAME_NO_IP) {
uint16_t pos = dns_msg.response_position;
rc = dns_copy_qname(cname->data, &cname->len,
cname->size, &dns_msg, pos);
if (rc != 0) {
goto exit_error;
}
}
}
exit_ok:
rc = 0;
exit_error:
net_nbuf_unref(ctx->rx_buf);
return rc;
}

View file

@ -142,6 +142,9 @@ int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[])
net_sin6(&ctx->servers[idx].dns_server)->sin6_port =
htons(port);
NET_DBG("[%d] IPv6 server %s port %d", idx, server,
port);
ctx->servers[idx++].dns_server.family = AF_INET6;
#endif /* CONFIG_NET_IPV6 */
@ -190,6 +193,9 @@ int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[])
net_sin(&ctx->servers[idx].dns_server)->sin_port =
htons(port);
NET_DBG("[%d] IPv4 server %s port %d", idx, server,
port);
ctx->servers[idx++].dns_server.family = AF_INET;
#endif /* CONFIG_NET_IPV4 */
@ -209,6 +215,9 @@ int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[])
net_sin(&ctx->servers[idx].dns_server)->sin_port =
htons(53);
NET_DBG("[%d] IPv4 server %s port %d", idx, servers[i],
53);
ctx->servers[idx++].dns_server.family = AF_INET;
} else if (ret == -EINVAL) {
@ -227,6 +236,9 @@ int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[])
net_sin6(&ctx->servers[idx].dns_server)->sin6_port =
htons(53);
NET_DBG("[%d] IPv6 server %s port %d", idx, servers[i],
53);
ctx->servers[idx++].dns_server.family = AF_INET6;
}
#endif
@ -243,6 +255,8 @@ int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[])
continue;
}
NET_DBG("[%d] IPv4 server %s port %d", idx, servers[i], 53);
net_sin(&ctx->servers[idx].dns_server)->sin_port = htons(53);
ctx->servers[idx++].dns_server.family = AF_INET;
#endif /* IPv4 && !IPv6 */
@ -258,6 +272,8 @@ int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[])
continue;
}
NET_DBG("[%d] IPv6 server %s port %d", idx, servers[i], 53);
net_sin6(&ctx->servers[idx].dns_server)->sin6_port = htons(53);
ctx->servers[idx++].dns_server.family = AF_INET6;
#endif /* IPv6 && !IPv4 */
@ -415,10 +431,14 @@ static int dns_read(struct dns_resolve_context *ctx,
address_size = DNS_IPV4_LEN;
addr = (uint8_t *)&net_sin(&info->ai_addr)->sin_addr;
info->ai_family = AF_INET;
info->ai_addr.family = AF_INET;
info->ai_addrlen = sizeof(struct sockaddr_in);
} else if (ctx->queries[query_idx].query_type == DNS_QUERY_TYPE_AAAA) {
address_size = DNS_IPV6_LEN;
addr = (uint8_t *)&net_sin6(&info->ai_addr)->sin6_addr;
info->ai_family = AF_INET6;
info->ai_addr.family = AF_INET6;
info->ai_addrlen = sizeof(struct sockaddr_in6);
} else {
ret = DNS_EAI_FAMILY;
goto quit;
@ -446,7 +466,6 @@ static int dns_read(struct dns_resolve_context *ctx,
src = dns_msg.msg + dns_msg.response_position;
memcpy(addr, src, address_size);
info->ai_addrlen = address_size;
ctx->queries[query_idx].cb(DNS_EAI_INPROGRESS, info,
ctx->queries[query_idx].user_data);
@ -566,7 +585,7 @@ static void cb_recv(struct net_context *net_ctx,
i = get_slot_by_id(ctx, dns_id);
if (i < 0) {
goto cancel;
goto free_buf;
}
for (j = 0; j < CONFIG_DNS_RESOLVER_MAX_SERVERS; j++) {
@ -598,7 +617,6 @@ quit:
goto free_buf;
}
cancel:
if (k_delayed_work_remaining_get(&ctx->queries[i].timer) > 0) {
k_delayed_work_cancel(&ctx->queries[i].timer);
}

4
tests/net/all/Makefile Normal file
View file

@ -0,0 +1,4 @@
BOARD ?= qemu_x86
CONF_FILE = prj.conf
include $(ZEPHYR_BASE)/Makefile.test

237
tests/net/all/prj.conf Normal file
View file

@ -0,0 +1,237 @@
# Activate all network Kconfig options in order to test that the result
# target compiles ok. Note that the different values in this file are
# just randomly selected, do not use the values in your real life
# applications.
# This test requires lot of memory so increase it here so that
# the compilation succeeds.
CONFIG_RAM_SIZE=300
# Generic options that are useful to be active
CONFIG_SYS_LOG_SHOW_COLOR=y
CONFIG_RANDOM_GENERATOR=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_ZTEST=y
# net_buf options
CONFIG_NET_BUF=y
CONFIG_NET_BUF_LOG=y
CONFIG_SYS_LOG_NET_BUF_LEVEL=4
CONFIG_NET_BUF_WARN_ALLOC_INTERVAL=2
CONFIG_NET_BUF_SIMPLE_LOG=y
CONFIG_NET_BUF_POOL_USAGE=y
# Core IP options
CONFIG_NETWORKING=y
CONFIG_NET_INIT_PRIO=98
CONFIG_NET_SHELL=y
CONFIG_NET_IP_ADDR_CHECK=y
# Statistics
CONFIG_NET_STATISTICS=y
CONFIG_NET_STATISTICS_USER_API=y
CONFIG_NET_STATISTICS_PERIODIC_OUTPUT=y
CONFIG_NET_STATISTICS_IPV4=y
CONFIG_NET_STATISTICS_IPV6=y
CONFIG_NET_STATISTICS_IPV6_ND=y
CONFIG_NET_STATISTICS_ICMP=y
CONFIG_NET_STATISTICS_UDP=y
CONFIG_NET_STATISTICS_TCP=y
CONFIG_NET_STATISTICS_RPL=y
CONFIG_NET_STATISTICS_MLD=y
# L2 drivers
CONFIG_NET_L2_IEEE802154_RADIO_TX_RETRIES=2
CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA=y
CONFIG_NET_L2_IEEE802154_RADIO_ALOHA=n
CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MAX_BO=4
CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MIN_BE=3
CONFIG_NET_L2_IEEE802154_RADIO_CSMA_CA_MAX_BE=5
CONFIG_NET_L2_IEEE802154=y
CONFIG_NET_L2_IEEE802154_MGMT=y
CONFIG_NET_L2_IEEE802154_ACK_REPLY=y
CONFIG_NET_L2_IEEE802154_RFD=y
CONFIG_NET_L2_IEEE802154_SHELL=y
CONFIG_NET_L2_IEEE802154_FRAGMENT=y
CONFIG_NET_L2_IEEE802154_FRAGMENT_REASS_CACHE_SIZE=2
CONFIG_NET_L2_IEEE802154_REASSEMBLY_TIMEOUT=10
CONFIG_NET_L2_IEEE802154_SECURITY=y
CONFIG_NET_L2_IEEE802154_SECURITY_CRYPTO_DEV_NAME="CRYPTO-DEV"
CONFIG_NET_L2_DUMMY=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_L2_BLUETOOTH=y
CONFIG_NET_L2_BLUETOOTH_ZEP1656=y
CONFIG_NET_L2_BLUETOOTH_SEC_LEVEL=4
CONFIG_NET_L2_BLUETOOTH_MGMT=y
CONFIG_NET_L2_BLUETOOTH_SHELL=y
CONFIG_NET_L2_RAW_CHANNEL=y
CONFIG_NET_DEBUG_L2_IEEE802154=y
CONFIG_NET_DEBUG_L2_IEEE802154_FRAGMENT=y
CONFIG_NET_DEBUG_L2_ETHERNET=y
CONFIG_NET_DEBUG_L2_BLUETOOTH=y
# IP offload support
CONFIG_NET_OFFLOAD=y
CONFIG_NET_DEBUG_NET_OFFLOAD=y
# RPL
CONFIG_NET_RPL=y
CONFIG_NET_RPL_MRHOF=y
CONFIG_NET_RPL_OF0=n
CONFIG_NET_RPL_MC_NONE=n
CONFIG_NET_RPL_MC_EXT=n
CONFIG_NET_RPL_MC_ENERGY=y
CONFIG_NET_RPL_MOP2=n
CONFIG_NET_RPL_MOP3=y
CONFIG_NET_RPL_DAO_MAX_RETRANSMISSIONS=2
CONFIG_NET_DEBUG_RPL=y
# Routing table
CONFIG_NET_MAX_ROUTERS=3
CONFIG_NET_ROUTE=y
CONFIG_NET_ROUTE_MCAST=y
# TCP
CONFIG_NET_TCP=y
CONFIG_NET_DEBUG_TCP=y
CONFIG_NET_TCP_TIME_WAIT=y
CONFIG_NET_TCP_2MSL_TIME=20
# UDP
CONFIG_NET_UDP=y
CONFIG_NET_DEBUG_UDP=y
# Network context
CONFIG_NET_MAX_CONN=10
CONFIG_NET_CONN_CACHE=y
CONFIG_NET_MAX_CONTEXTS=4
CONFIG_NET_CONTEXT_NBUF_POOL=y
CONFIG_NET_CONTEXT_SYNC_RECV=y
CONFIG_NET_CONTEXT_CHECK=y
# SLIP
CONFIG_NET_SLIP_TUN=n
CONFIG_NET_SLIP_TAP=y
# Trickle algo
CONFIG_NET_TRICKLE=y
CONFIG_NET_DEBUG_TRICKLE=y
# Network buffer
CONFIG_NET_NBUF_RX_COUNT=10
CONFIG_NET_NBUF_TX_COUNT=10
CONFIG_NET_NBUF_RX_DATA_COUNT=15
CONFIG_NET_NBUF_TX_DATA_COUNT=15
CONFIG_NET_NBUF_DATA_SIZE=128
CONFIG_NET_NBUF_USER_DATA_SIZE=10
# IPv6
CONFIG_NET_IPV6=y
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_IPV6_PREFIX_COUNT=3
CONFIG_NET_INITIAL_HOP_LIMIT=64
CONFIG_NET_IPV6_MAX_NEIGHBORS=5
CONFIG_NET_IPV6_FRAGMENT=y
CONFIG_NET_IPV6_FRAGMENT_MAX_COUNT=2
CONFIG_NET_IPV6_FRAGMENT_TIMEOUT=23
CONFIG_NET_IPV6_MLD=y
CONFIG_NET_IPV6_NBR_CACHE=y
CONFIG_NET_IPV6_ND=y
CONFIG_NET_IPV6_DAD=y
CONFIG_NET_IPV6_RA_RDNSS=y
CONFIG_NET_DEBUG_IPV6=y
CONFIG_NET_DEBUG_ICMPV6=y
CONFIG_NET_DEBUG_IPV6_NBR_CACHE=y
# 6lo
CONFIG_NET_6LO=y
CONFIG_NET_6LO_CONTEXT=y
CONFIG_NET_MAX_6LO_CONTEXTS=2
CONFIG_NET_DEBUG_6LO=y
# Sample application generic options
CONFIG_NET_APP_SETTINGS=y
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1"
CONFIG_NET_APP_PEER_IPV4_ADDR="192.0.2.2"
CONFIG_NET_APP_IEEE802154_DEV_NAME="FOO-BAR"
CONFIG_NET_APP_IEEE802154_PAN_ID=0x1234
CONFIG_NET_APP_IEEE802154_CHANNEL=15
CONFIG_NET_APP_IEEE802154_SECURITY_KEY="key"
CONFIG_NET_APP_IEEE802154_SECURITY_KEY_MODE=0
CONFIG_NET_APP_IEEE802154_SECURITY_LEVEL=0
# Network management
CONFIG_NET_MGMT=y
CONFIG_NET_MGMT_EVENT=y
CONFIG_NET_MGMT_EVENT_STACK_SIZE=800
CONFIG_NET_MGMT_EVENT_THREAD_PRIO=66
CONFIG_NET_MGMT_EVENT_QUEUE_SIZE=2
CONFIG_NET_DEBUG_MGMT_EVENT=y
CONFIG_NET_DEBUG_MGMT_EVENT_STACK=y
# IPv4
CONFIG_NET_IPV4=y
CONFIG_NET_INITIAL_TTL=42
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=2
CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT=2
CONFIG_NET_DHCPV4=y
CONFIG_NET_DEBUG_IPV4=y
CONFIG_NET_DEBUG_ICMPV4=y
CONFIG_NET_DEBUG_DHCPV4=y
# ARP
CONFIG_NET_ARP=y
CONFIG_NET_ARP_TABLE_SIZE=3
CONFIG_NET_DEBUG_ARP=y
# Logging
CONFIG_NET_LOG=y
CONFIG_SYS_LOG_NET_LEVEL=4
CONFIG_NET_LOG_GLOBAL=y
CONFIG_NET_DEBUG_CORE=y
CONFIG_NET_DEBUG_IF=y
CONFIG_NET_DEBUG_UTILS=y
CONFIG_NET_DEBUG_CONTEXT=y
CONFIG_NET_DEBUG_NET_BUF=y
CONFIG_NET_DEBUG_NET_BUF_EXTERNALS=4
CONFIG_NET_DEBUG_CONN=y
CONFIG_NET_DEBUG_ROUTE=y
# IP threads stack size
CONFIG_NET_TX_STACK_SIZE=1024
CONFIG_NET_RX_STACK_SIZE=1024
CONFIG_NET_RX_STACK_RPL=300
# DNS
CONFIG_DNS_RESOLVER=y
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=1
CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=2
CONFIG_DNS_RESOLVER_MAX_SERVERS=5
CONFIG_DNS_SERVER_IP_ADDRESSES=y
CONFIG_DNS_SERVER1="2001:db8::33:fe:2c:53"
CONFIG_DNS_SERVER2="[2001:db8::42]:5353"
CONFIG_DNS_SERVER3="192.0.2.42"
CONFIG_DNS_SERVER4="2001:db8::2"
CONFIG_DNS_SERVER5="192.0.2.11:1000"
CONFIG_DNS_NUM_CONCUR_QUERIES=2
CONFIG_NET_DEBUG_DNS_RESOLVE=y
# CoAP
CONFIG_ZOAP=y
# MQTT
CONFIG_MQTT_LIB=y
CONFIG_MQTT_MSG_MAX_SIZE=128
CONFIG_MQTT_ADDITIONAL_BUFFER_CTR=1
CONFIG_MQTT_SUBSCRIBE_MAX_TOPICS=2
# HTTP
CONFIG_HTTP=y
CONFIG_HTTP_SERVER=y
CONFIG_HTTP_HEADER_FIELD_ITEMS=2
CONFIG_HTTP_CLIENT=y
CONFIG_HTTP_PARSER=y
CONFIG_HTTP_PARSER_STRICT=y

View file

@ -0,0 +1,2 @@
obj-y = main.o
include $(ZEPHYR_BASE)/tests/Makefile.test

27
tests/net/all/src/main.c Normal file
View file

@ -0,0 +1,27 @@
/* main.c - Application main entry point */
/* We are just testing that this program compiles ok with all possible
* network related Kconfig options enabled.
*/
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
static void ok(void)
{
assert_true(true, "This test should never fail");
}
void test_main(void)
{
ztest_test_suite(net_compile_all_test,
ztest_unit_test(ok)
);
ztest_run_test_suite(net_compile_all_test);
}

View file

@ -0,0 +1,5 @@
[test]
tags = net
build_only = true
arch_whitelist = x86
platform_whitelist = qemu_x86

View file

@ -652,8 +652,6 @@ static bool run_tests(void)
break;
}
net_nbuf_unref(buf2);
/* Yielding so that network interface TX thread can proceed. */
k_yield();

View file

@ -0,0 +1,8 @@
BOARD ?= qemu_x86
CONF_FILE ?= prj_$(BOARD).conf
include $(ZEPHYR_BASE)/Makefile.test
ifeq ($(BOARD), qemu_x86)
include $(ZEPHYR_BASE)/samples/net/common/Makefile.ipstack
endif

View file

@ -1,30 +1,19 @@
CONFIG_NETWORKING=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_RANDOM_GENERATOR=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_ARP=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_LOG=y
CONFIG_INIT_STACKS=y
CONFIG_NET_NBUF_RX_COUNT=16
CONFIG_NET_NBUF_TX_COUNT=16
CONFIG_NET_NBUF_RX_DATA_COUNT=10
CONFIG_NET_NBUF_TX_DATA_COUNT=10
CONFIG_NET_NBUF_RX_DATA_COUNT=16
CONFIG_NET_NBUF_TX_DATA_COUNT=16
CONFIG_NET_IPV6_RA_RDNSS=y
CONFIG_NET_IFACE_UNICAST_IPV4_ADDR_COUNT=3
# ENC28J60 Ethernet Device
CONFIG_ETH_ENC28J60=y
CONFIG_ETH_ENC28J60_0=y
CONFIG_ETH_ENC28J60_0_SPI_PORT_NAME="SPI_1"
CONFIG_ETH_ENC28J60_0_MAC3=0x2D
CONFIG_ETH_ENC28J60_0_MAC4=0x30
CONFIG_ETH_ENC28J60_0_MAC5=0x32
# Arduino 101
CONFIG_SPI=y
CONFIG_PRINTK=y
#CONFIG_NET_DEBUG_NET_BUF=y
@ -32,15 +21,32 @@ CONFIG_NET_IPV4=y
# Enable IPv6 support
CONFIG_NET_IPV6=n
# Enable the DNS resolver
CONFIG_DNS_RESOLVER=y
# Enable additional buffers
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=0
# Enable additional queries
CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=1
# Enable the MQTT Lib
CONFIG_MQTT_LIB=y
CONFIG_NET_APP_SETTINGS=y
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
CONFIG_NET_APP_MY_IPV4_ADDR="192.168.1.101"
CONFIG_NET_APP_PEER_IPV4_ADDR="192.168.1.10"
CONFIG_MAIN_STACK_SIZE=2048
# For IPv6
CONFIG_NET_NBUF_DATA_SIZE=256
CONFIG_TEST_RANDOM_GENERATOR=y
# ENC28J60 Ethernet Device
CONFIG_ETH_ENC28J60=y
CONFIG_ETH_ENC28J60_0=y
CONFIG_ETH_ENC28J60_0_SPI_PORT_NAME="SPI_1"
CONFIG_ETH_ENC28J60_0_MAC3=0x2D
CONFIG_ETH_ENC28J60_0_MAC4=0x30
CONFIG_ETH_ENC28J60_0_MAC5=0x36
# Arduino 101
CONFIG_SPI=y
CONFIG_ZTEST=y

View file

@ -1,10 +1,11 @@
CONFIG_NETWORKING=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_RANDOM_GENERATOR=y
CONFIG_NET_ARP=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_LOG=y
CONFIG_INIT_STACKS=y
CONFIG_NET_NBUF_RX_COUNT=16
CONFIG_NET_NBUF_TX_COUNT=16
CONFIG_NET_NBUF_RX_DATA_COUNT=16
@ -20,15 +21,19 @@ CONFIG_NET_IPV4=y
# Enable IPv6 support
CONFIG_NET_IPV6=n
# Enable the DNS resolver
CONFIG_DNS_RESOLVER=y
# Enable additional buffers
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=0
# Enable additional queries
CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=1
# Enable the MQTT Lib
CONFIG_MQTT_LIB=y
CONFIG_NET_APP_SETTINGS=y
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
CONFIG_NET_APP_MY_IPV4_ADDR="192.168.1.101"
CONFIG_NET_APP_PEER_IPV4_ADDR="192.168.1.10"
CONFIG_MAIN_STACK_SIZE=2048
# For IPv6
CONFIG_NET_NBUF_DATA_SIZE=256
CONFIG_ZTEST=y

View file

@ -1,33 +1,40 @@
CONFIG_NETWORKING=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_RANDOM_GENERATOR=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_LOG=y
CONFIG_NET_SLIP_TAP=y
CONFIG_INIT_STACKS=y
CONFIG_NET_NBUF_RX_COUNT=16
CONFIG_NET_NBUF_TX_COUNT=16
CONFIG_NET_NBUF_RX_DATA_COUNT=16
CONFIG_NET_NBUF_TX_DATA_COUNT=16
CONFIG_NET_IPV6_RA_RDNSS=y
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2
CONFIG_PRINTK=y
#CONFIG_NET_DEBUG_NET_BUF=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_NET_IPV4=y
# Enable IPv6 support
CONFIG_NET_IPV6=n
# Enable IPv4 support
CONFIG_NET_IPV4=y
# Enable the DNS resolver
CONFIG_DNS_RESOLVER=y
# Enable additional buffers
CONFIG_DNS_RESOLVER_ADDITIONAL_BUF_CTR=0
# Enable additional queries
CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=1
# Enable the MQTT Lib
CONFIG_MQTT_LIB=y
CONFIG_NET_APP_SETTINGS=y
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1"
CONFIG_NET_APP_PEER_IPV4_ADDR="192.0.2.2"
CONFIG_MAIN_STACK_SIZE=2048
# For IPv6
CONFIG_NET_NBUF_DATA_SIZE=256
CONFIG_ZTEST=y

View file

@ -0,0 +1,3 @@
include $(ZEPHYR_BASE)/tests/Makefile.test
obj-y += main.o test_mqtt_publish.o

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __CONFIG_H__
#define __CONFIG_H__
#ifdef CONFIG_NET_APP_SETTINGS
#ifdef CONFIG_NET_IPV6
#define ZEPHYR_ADDR CONFIG_NET_APP_MY_IPV6_ADDR
#define SERVER_ADDR CONFIG_NET_APP_PEER_IPV6_ADDR
#else
#define ZEPHYR_ADDR CONFIG_NET_APP_MY_IPV4_ADDR
#define SERVER_ADDR CONFIG_NET_APP_PEER_IPV4_ADDR
#endif
#else
#ifdef CONFIG_NET_IPV6
#define ZEPHYR_ADDR "2001:db8::1"
#define SERVER_ADDR "2001:db8::2"
#else
#define ZEPHYR_ADDR "192.168.1.101"
#define SERVER_ADDR "192.168.1.10"
#endif
#endif
#define SERVER_PORT 1883
#define APP_SLEEP_MSECS 500
#define APP_TX_RX_TIMEOUT 300
#define APP_CONNECT_TRIES 10
#define APP_MAX_ITERATIONS 100
#define MQTT_CLIENTID "zephyr_publisher"
/* Set the following to 1 to enable the Bluemix topic format */
#define APP_BLUEMIX_TOPIC 0
#endif

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
extern void test_mqtt_init(void);
extern void test_mqtt_connect(void);
extern void test_mqtt_pingreq(void);
extern void test_mqtt_publish(void);
extern void test_mqtt_disconnect(void);
void test_main(void)
{
ztest_test_suite(mqtt_test,
ztest_unit_test(test_mqtt_init),
ztest_unit_test(test_mqtt_connect),
ztest_unit_test(test_mqtt_pingreq),
ztest_unit_test(test_mqtt_publish),
ztest_unit_test(test_mqtt_disconnect));
ztest_run_test_suite(mqtt_test);
}

View file

@ -0,0 +1,448 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <net/mqtt.h>
#include <ztest.h>
#include <net/net_context.h>
#include <net/nbuf.h>
#include <string.h>
#include <errno.h>
#include "config.h"
/* Container for some structures used by the MQTT publisher app. */
struct mqtt_client_ctx {
/**
* The connect message structure is only used during the connect
* stage. Developers must set some msg properties before calling the
* mqtt_tx_connect routine. See below.
*/
struct mqtt_connect_msg connect_msg;
/**
* This is the message that will be received by the server
* (MQTT broker).
*/
struct mqtt_publish_msg pub_msg;
/**
* This is the MQTT application context variable.
*/
struct mqtt_ctx mqtt_ctx;
/**
* This variable will be passed to the connect callback, declared inside
* the mqtt context struct. If not used, it could be set to NULL.
*/
void *connect_data;
/**
* This variable will be passed to the disconnect callback, declared
* inside the mqtt context struct. If not used, it could be set to NULL.
*/
void *disconnect_data;
/**
* This variable will be passed to the publish_tx callback, declared
* inside the mqtt context struct. If not used, it could be set to NULL.
*/
void *publish_data;
};
/* This is mqtt payload message. */
char payload[] = "DOORS:OPEN_QoSx";
/* This is the network context structure. */
static struct net_context *net_ctx;
/* The mqtt client struct */
static struct mqtt_client_ctx client_ctx;
/* This routine sets some basic properties for the network context variable */
static int network_setup(struct net_context **net_ctx, const char *local_addr,
const char *server_addr, uint16_t server_port);
/* The signature of this routine must match the connect callback declared at
* the mqtt.h header.
*/
static void connect_cb(struct mqtt_ctx *mqtt_ctx)
{
struct mqtt_client_ctx *client_ctx;
client_ctx = CONTAINER_OF(mqtt_ctx, struct mqtt_client_ctx, mqtt_ctx);
TC_PRINT("[%s:%d]", __func__, __LINE__);
if (client_ctx->connect_data) {
TC_PRINT(" user_data: %s",
(const char *)client_ctx->connect_data);
}
TC_PRINT("\n");
}
/* The signature of this routine must match the disconnect callback declared at
* the mqtt.h header.
*/
static void disconnect_cb(struct mqtt_ctx *mqtt_ctx)
{
struct mqtt_client_ctx *client_ctx;
client_ctx = CONTAINER_OF(mqtt_ctx, struct mqtt_client_ctx, mqtt_ctx);
TC_PRINT("[%s:%d]", __func__, __LINE__);
if (client_ctx->disconnect_data) {
TC_PRINT(" user_data: %s",
(const char *)client_ctx->disconnect_data);
}
TC_PRINT("\n");
}
/**
* The signature of this routine must match the publish_tx callback declared at
* the mqtt.h header.
*
* NOTE: we have two callbacks for MQTT Publish related stuff:
* - publish_tx, for publishers
* - publish_rx, for subscribers
*
* Applications must keep a "message database" with pkt_id's. So far, this is
* not implemented here. For example, if we receive a PUBREC message with an
* unknown pkt_id, this routine must return an error, for example -EINVAL or
* any negative value.
*/
static int publish_cb(struct mqtt_ctx *mqtt_ctx, uint16_t pkt_id,
enum mqtt_packet type)
{
struct mqtt_client_ctx *client_ctx;
const char *str;
int rc = 0;
client_ctx = CONTAINER_OF(mqtt_ctx, struct mqtt_client_ctx, mqtt_ctx);
switch (type) {
case MQTT_PUBACK:
str = "MQTT_PUBACK";
break;
case MQTT_PUBCOMP:
str = "MQTT_PUBCOMP";
break;
case MQTT_PUBREC:
str = "MQTT_PUBREC";
break;
default:
rc = -EINVAL;
str = "Invalid MQTT packet";
}
TC_PRINT("[%s:%d] <%s> packet id: %u", __func__, __LINE__, str, pkt_id);
if (client_ctx->publish_data) {
TC_PRINT(", user_data: %s",
(const char *)client_ctx->publish_data);
}
TC_PRINT("\n");
return rc;
}
/**
* The signature of this routine must match the malformed callback declared at
* the mqtt.h header.
*/
static void malformed_cb(struct mqtt_ctx *mqtt_ctx, uint16_t pkt_type)
{
TC_PRINT("[%s:%d] pkt_type: %u\n", __func__, __LINE__, pkt_type);
}
static char *get_mqtt_payload(enum mqtt_qos qos)
{
payload[strlen(payload) - 1] = '0' + qos;
return payload;
}
static char *get_mqtt_topic(void)
{
return "sensors";
}
static void prepare_mqtt_publish_msg(struct mqtt_publish_msg *pub_msg,
enum mqtt_qos qos)
{
/* MQTT message payload may be anything, we we use C strings */
pub_msg->msg = (uint8_t *)get_mqtt_payload(qos);
/* Payload's length */
pub_msg->msg_len = (uint16_t)strlen((char *)client_ctx.pub_msg.msg);
/* MQTT Quality of Service */
pub_msg->qos = qos;
/* Message's topic */
pub_msg->topic = get_mqtt_topic();
pub_msg->topic_len = strlen(client_ctx.pub_msg.topic);
/* Packet Identifier, always use different values */
pub_msg->pkt_id = sys_rand32_get();
}
#define RC_STR(rc) ((rc) == 0 ? "OK" : "ERROR")
#define PRINT_RESULT(func, rc) \
TC_PRINT("[%s:%d] %s: %d <%s>\n", __func__, __LINE__, \
(func), rc, RC_STR(rc))
/* In this routine we block until the connected variable is 1 */
static int try_to_connect(struct mqtt_client_ctx *client_ctx)
{
int i = 0;
while (i++ < APP_CONNECT_TRIES && !client_ctx->mqtt_ctx.connected) {
int rc;
rc = mqtt_tx_connect(&client_ctx->mqtt_ctx,
&client_ctx->connect_msg);
k_sleep(APP_SLEEP_MSECS);
if (rc != 0) {
continue;
}
}
if (client_ctx->mqtt_ctx.connected) {
return TC_PASS;
}
return TC_FAIL;
}
static int init_network(void)
{
int rc;
/* The net_ctx variable must be ready BEFORE passing it to the MQTT API.
*/
rc = network_setup(&net_ctx, ZEPHYR_ADDR, SERVER_ADDR, SERVER_PORT);
if (rc != 0) {
goto exit_app;
}
/* Set everything to 0 and later just assign the required fields. */
memset(&client_ctx, 0x00, sizeof(client_ctx));
/* The network context is the only field that must be set BEFORE
* calling the mqtt_init routine.
*/
client_ctx.mqtt_ctx.net_ctx = net_ctx;
/* connect, disconnect and malformed may be set to NULL */
client_ctx.mqtt_ctx.connect = connect_cb;
client_ctx.mqtt_ctx.disconnect = disconnect_cb;
client_ctx.mqtt_ctx.malformed = malformed_cb;
client_ctx.mqtt_ctx.net_timeout = APP_TX_RX_TIMEOUT;
/* Publisher apps TX the MQTT PUBLISH msg */
client_ctx.mqtt_ctx.publish_tx = publish_cb;
rc = mqtt_init(&client_ctx.mqtt_ctx, MQTT_APP_PUBLISHER);
if (rc != 0) {
goto exit_app;
}
/* The connect message will be sent to the MQTT server (broker).
* If clean_session here is 0, the mqtt_ctx clean_session variable
* will be set to 0 also. Please don't do that, set always to 1.
* Clean session = 0 is not yet supported.
*/
client_ctx.connect_msg.client_id = MQTT_CLIENTID;
client_ctx.connect_msg.client_id_len = strlen(MQTT_CLIENTID);
client_ctx.connect_msg.clean_session = 1;
client_ctx.connect_data = "CONNECTED";
client_ctx.disconnect_data = "DISCONNECTED";
client_ctx.publish_data = "PUBLISH";
return TC_PASS;
exit_app:
net_context_put(net_ctx);
return TC_FAIL;
}
static int test_connect(void)
{
int rc;
rc = try_to_connect(&client_ctx);
if (rc != 0) {
return TC_FAIL;
}
return TC_PASS;
}
static int test_pingreq(void)
{
int rc;
rc = mqtt_tx_pingreq(&client_ctx.mqtt_ctx);
k_sleep(APP_SLEEP_MSECS);
if (rc != 0) {
return TC_FAIL;
}
return TC_PASS;
}
static int test_publish(enum mqtt_qos qos)
{
int rc;
prepare_mqtt_publish_msg(&client_ctx.pub_msg, qos);
rc = mqtt_tx_publish(&client_ctx.mqtt_ctx, &client_ctx.pub_msg);
k_sleep(APP_SLEEP_MSECS);
if (rc != 0) {
return TC_FAIL;
}
return TC_PASS;
}
static int test_disconnect(void)
{
int rc;
rc = mqtt_tx_disconnect(&client_ctx.mqtt_ctx);
if (rc != 0) {
return TC_FAIL;
}
return TC_PASS;
}
static int set_addr(struct sockaddr *sock_addr, const char *addr, uint16_t port)
{
void *ptr;
int rc;
#ifdef CONFIG_NET_IPV6
net_sin6(sock_addr)->sin6_port = htons(port);
sock_addr->family = AF_INET6;
ptr = &(net_sin6(sock_addr)->sin6_addr);
rc = net_addr_pton(AF_INET6, addr, ptr);
#else
net_sin(sock_addr)->sin_port = htons(port);
sock_addr->family = AF_INET;
ptr = &(net_sin(sock_addr)->sin_addr);
rc = net_addr_pton(AF_INET, addr, ptr);
#endif
if (rc) {
TC_PRINT("Invalid IP address: %s\n", addr);
}
return rc;
}
static int network_setup(struct net_context **net_ctx, const char *local_addr,
const char *server_addr, uint16_t server_port)
{
#ifdef CONFIG_NET_IPV6
socklen_t addr_len = sizeof(struct sockaddr_in6);
sa_family_t family = AF_INET6;
#else
socklen_t addr_len = sizeof(struct sockaddr_in);
sa_family_t family = AF_INET;
#endif
struct sockaddr server_sock, local_sock;
void *p;
int rc;
rc = set_addr(&local_sock, local_addr, 0);
if (rc) {
TC_PRINT("set_addr (local) error\n");
return TC_FAIL;
}
#ifdef CONFIG_NET_IPV6
p = net_if_ipv6_addr_add(net_if_get_default(),
&net_sin6(&local_sock)->sin6_addr,
NET_ADDR_MANUAL, 0);
#else
p = net_if_ipv4_addr_add(net_if_get_default(),
&net_sin(&local_sock)->sin_addr,
NET_ADDR_MANUAL, 0);
#endif
if (!p) {
return TC_FAIL;
}
rc = net_context_get(family, SOCK_STREAM, IPPROTO_TCP, net_ctx);
if (rc) {
TC_PRINT("net_context_get error\n");
return TC_FAIL;
}
rc = net_context_bind(*net_ctx, &local_sock, addr_len);
if (rc) {
TC_PRINT("net_context_bind error\n");
goto lb_exit;
}
rc = set_addr(&server_sock, server_addr, server_port);
if (rc) {
TC_PRINT("set_addr (server) error\n");
goto lb_exit;
}
rc = net_context_connect(*net_ctx, &server_sock, addr_len, NULL,
APP_SLEEP_MSECS, NULL);
if (rc) {
TC_PRINT("net_context_connect error\n"
"Is the server (broker) up and running?\n");
goto lb_exit;
}
return TC_PASS;
lb_exit:
net_context_put(*net_ctx);
return TC_FAIL;
}
void test_mqtt_init(void)
{
assert_true(init_network() == TC_PASS, NULL);
}
void test_mqtt_connect(void)
{
assert_true(test_connect() == TC_PASS, NULL);
}
void test_mqtt_pingreq(void)
{
assert_true(test_pingreq() == TC_PASS, NULL);
}
void test_mqtt_publish(void)
{
assert_true(test_publish(MQTT_QoS0) == TC_PASS, NULL);
assert_true(test_publish(MQTT_QoS1) == TC_PASS, NULL);
assert_true(test_publish(MQTT_QoS2) == TC_PASS, NULL);
}
void test_mqtt_disconnect(void)
{
assert_true(test_disconnect() == TC_PASS, NULL);
}

View file

@ -0,0 +1,4 @@
[test]
tags = net mqtt
build_only = true
platform_whitelist = frdm_k64f qemu_x86

View file

@ -1,5 +1,5 @@
#
# Copyright (c) 2016 Intel Corporation
# Copyright (c) 2017 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
@ -7,7 +7,8 @@
BOARD ?= qemu_x86
CONF_FILE ?= prj_$(BOARD).conf
include $(ZEPHYR_BASE)/Makefile.inc
ifeq ($(BOARD), qemu_x86)
include $(ZEPHYR_BASE)/Makefile.test
ifeq ($(BOARD), qemu_x86)
include $(ZEPHYR_BASE)/samples/net/common/Makefile.ipstack
endif

View file

@ -0,0 +1,52 @@
CONFIG_NETWORKING=y
CONFIG_NET_TCP=y
CONFIG_RANDOM_GENERATOR=y
CONFIG_NET_ARP=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_LOG=y
CONFIG_INIT_STACKS=y
CONFIG_NET_NBUF_RX_COUNT=16
CONFIG_NET_NBUF_TX_COUNT=16
CONFIG_NET_NBUF_RX_DATA_COUNT=16
CONFIG_NET_NBUF_TX_DATA_COUNT=16
CONFIG_NET_IPV6_RA_RDNSS=y
CONFIG_NET_IFACE_UNICAST_IPV4_ADDR_COUNT=3
CONFIG_PRINTK=y
#CONFIG_NET_DEBUG_NET_BUF=y
CONFIG_NET_IPV4=y
# Enable IPv6 support
CONFIG_NET_IPV6=n
# Enable the MQTT Lib
CONFIG_MQTT_LIB=y
CONFIG_NET_APP_SETTINGS=y
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
CONFIG_NET_APP_MY_IPV4_ADDR="192.168.1.101"
CONFIG_NET_APP_PEER_IPV4_ADDR="192.168.1.10"
CONFIG_MAIN_STACK_SIZE=2048
# For IPv6
CONFIG_NET_NBUF_DATA_SIZE=256
CONFIG_TEST_RANDOM_GENERATOR=y
# ENC28J60 Ethernet Device
CONFIG_ETH_ENC28J60=y
CONFIG_ETH_ENC28J60_0=y
CONFIG_ETH_ENC28J60_0_SPI_PORT_NAME="SPI_1"
CONFIG_ETH_ENC28J60_0_MAC3=0x2D
CONFIG_ETH_ENC28J60_0_MAC4=0x30
CONFIG_ETH_ENC28J60_0_MAC5=0x36
# Arduino 101
CONFIG_SPI=y
CONFIG_ZTEST=y

View file

@ -0,0 +1,39 @@
CONFIG_NETWORKING=y
CONFIG_NET_TCP=y
CONFIG_RANDOM_GENERATOR=y
CONFIG_NET_ARP=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_LOG=y
CONFIG_INIT_STACKS=y
CONFIG_NET_NBUF_RX_COUNT=16
CONFIG_NET_NBUF_TX_COUNT=16
CONFIG_NET_NBUF_RX_DATA_COUNT=16
CONFIG_NET_NBUF_TX_DATA_COUNT=16
CONFIG_NET_IPV6_RA_RDNSS=y
CONFIG_NET_IFACE_UNICAST_IPV4_ADDR_COUNT=3
CONFIG_PRINTK=y
#CONFIG_NET_DEBUG_NET_BUF=y
CONFIG_NET_IPV4=y
# Enable IPv6 support
CONFIG_NET_IPV6=n
# Enable the MQTT Lib
CONFIG_MQTT_LIB=y
CONFIG_NET_APP_SETTINGS=y
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
CONFIG_NET_APP_MY_IPV4_ADDR="192.168.1.101"
CONFIG_NET_APP_PEER_IPV4_ADDR="192.168.1.10"
CONFIG_MAIN_STACK_SIZE=2048
# For IPv6
CONFIG_NET_NBUF_DATA_SIZE=256
CONFIG_ZTEST=y

View file

@ -0,0 +1,40 @@
CONFIG_NETWORKING=y
CONFIG_NET_TCP=y
CONFIG_RANDOM_GENERATOR=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_LOG=y
CONFIG_NET_SLIP_TAP=y
CONFIG_INIT_STACKS=y
CONFIG_NET_NBUF_RX_COUNT=16
CONFIG_NET_NBUF_TX_COUNT=16
CONFIG_NET_NBUF_RX_DATA_COUNT=16
CONFIG_NET_NBUF_TX_DATA_COUNT=16
CONFIG_NET_IPV6_RA_RDNSS=y
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2
CONFIG_STDOUT_CONSOLE=y
# Enable IPv6 support
CONFIG_NET_IPV6=n
# Enable IPv4 support
CONFIG_NET_IPV4=y
# Enable the MQTT Lib
CONFIG_MQTT_LIB=y
CONFIG_NET_APP_SETTINGS=y
CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_APP_PEER_IPV6_ADDR="2001:db8::2"
CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1"
CONFIG_NET_APP_PEER_IPV4_ADDR="192.0.2.2"
CONFIG_MAIN_STACK_SIZE=2048
# For IPv6
CONFIG_NET_NBUF_DATA_SIZE=256
CONFIG_ZTEST=y

View file

@ -0,0 +1,9 @@
#
# Copyright (c) 2017 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
#
include $(ZEPHYR_BASE)/tests/Makefile.test
obj-y += main.o test_mqtt_subscribe.o

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef __CONFIG_H__
#define __CONFIG_H__
#ifdef CONFIG_NET_APP_SETTINGS
#ifdef CONFIG_NET_IPV6
#define ZEPHYR_ADDR CONFIG_NET_APP_MY_IPV6_ADDR
#define SERVER_ADDR CONFIG_NET_APP_PEER_IPV6_ADDR
#else
#define ZEPHYR_ADDR CONFIG_NET_APP_MY_IPV4_ADDR
#define SERVER_ADDR CONFIG_NET_APP_PEER_IPV4_ADDR
#endif
#else
#ifdef CONFIG_NET_IPV6
#define ZEPHYR_ADDR "2001:db8::1"
#define SERVER_ADDR "2001:db8::2"
#else
#define ZEPHYR_ADDR "192.168.1.101"
#define SERVER_ADDR "192.168.1.10"
#endif
#endif
#define SERVER_PORT 1883
#define APP_SLEEP_MSECS 500
#define APP_TX_RX_TIMEOUT 300
#define APP_CONNECT_TRIES 10
#define APP_MAX_ITERATIONS 100
#define MQTT_CLIENTID "zephyr_publisher"
/* Set the following to 1 to enable the Bluemix topic format */
#define APP_BLUEMIX_TOPIC 0
#endif

View file

@ -0,0 +1,24 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
extern void test_mqtt_init(void);
extern void test_mqtt_connect(void);
extern void test_mqtt_subscribe(void);
extern void test_mqtt_unsubscribe(void);
extern void test_mqtt_disconnect(void);
void test_main(void)
{
ztest_test_suite(mqtt_test,
ztest_unit_test(test_mqtt_init),
ztest_unit_test(test_mqtt_connect),
ztest_unit_test(test_mqtt_subscribe),
ztest_unit_test(test_mqtt_unsubscribe),
ztest_unit_test(test_mqtt_disconnect));
ztest_run_test_suite(mqtt_test);
}

View file

@ -0,0 +1,483 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
#include <net/mqtt.h>
#include <net/net_context.h>
#include <net/nbuf.h>
#include <misc/printk.h>
#include <string.h>
#include <errno.h>
#include "config.h"
/* Container for some structures used by the MQTT subscriber app. */
struct mqtt_client_ctx {
/**
* The connect message structure is only used during the connect
* stage. Developers must set some msg properties before calling the
* mqtt_tx_connect routine. See below.
*/
struct mqtt_connect_msg connect_msg;
/**
* This is the message that will be received by the server
* (MQTT broker).
*/
struct mqtt_publish_msg pub_msg;
/**
* This is the MQTT application context variable.
*/
struct mqtt_ctx mqtt_ctx;
/**
* This variable will be passed to the connect callback, declared inside
* the mqtt context struct. If not used, it could be set to NULL.
*/
void *connect_data;
/**
* This variable will be passed to the disconnect callback, declared
* inside the mqtt context struct. If not used, it could be set to NULL.
*/
void *disconnect_data;
/**
* This variable will be passed to the subscribe_tx callback, declared
* inside the mqtt context struct. If not used, it could be set to NULL.
*/
void *subscribe_data;
/**
* This variable will be passed to the unsubscribe_tx callback, declared
* inside the mqtt context struct. If not used, it could be set to NULL.
*/
void *unsubscribe_data;
};
/* This is the network context structure. */
static struct net_context *net_ctx;
/* The mqtt client struct */
static struct mqtt_client_ctx client_ctx;
/* This routine sets some basic properties for the network context variable */
static int network_setup(struct net_context **net_ctx, const char *local_addr,
const char *server_addr, uint16_t server_port);
/* The signature of this routine must match the connect callback declared at
* the mqtt.h header.
*/
static void connect_cb(struct mqtt_ctx *mqtt_ctx)
{
struct mqtt_client_ctx *client_ctx;
client_ctx = CONTAINER_OF(mqtt_ctx, struct mqtt_client_ctx, mqtt_ctx);
printk("[%s:%d]", __func__, __LINE__);
if (client_ctx->connect_data) {
printk(" user_data: %s",
(const char *)client_ctx->connect_data);
}
printk("\n");
}
/* The signature of this routine must match the disconnect callback declared at
* the mqtt.h header.
*/
static void disconnect_cb(struct mqtt_ctx *mqtt_ctx)
{
struct mqtt_client_ctx *client_ctx;
client_ctx = CONTAINER_OF(mqtt_ctx, struct mqtt_client_ctx, mqtt_ctx);
printk("[%s:%d]", __func__, __LINE__);
if (client_ctx->disconnect_data) {
printk(" user_data: %s",
(const char *)client_ctx->disconnect_data);
}
printk("\n");
}
/**
* The signature of this routine must match the publish_rx callback declared at
* the mqtt.h header.
*
* NOTE: we have two callbacks for MQTT Publish related stuff:
* - publish_tx, for publishers
* - publish_rx, for subscribers
*
* Applications must keep a "message database" with pkt_id's. So far, this is
* not implemented here. For example, if we receive a PUBREC message with an
* unknown pkt_id, this routine must return an error, for example -EINVAL or
* any negative value.
*/
static int publish_rx_cb(struct mqtt_ctx *mqtt_ctx, struct mqtt_publish_msg
*msg, uint16_t pkt_id, enum mqtt_packet type)
{
struct mqtt_client_ctx *client_ctx;
const char *str;
int rc = 0;
client_ctx = CONTAINER_OF(mqtt_ctx, struct mqtt_client_ctx, mqtt_ctx);
switch (type) {
case MQTT_PUBLISH:
str = "MQTT_PUBLISH";
printk("[%s:%d] <%s> msg: %s", __func__, __LINE__,
str, msg->msg);
break;
case MQTT_PUBREL:
str = "MQTT_PUBREL";
printk("[%s:%d] <%s> packet id: %u", __func__, __LINE__,
str, pkt_id);
return 0;
default:
rc = -EINVAL;
str = "Invalid MQTT packet";
}
if (client_ctx->subscribe_data) {
printk(", user_data: %s",
(const char *)client_ctx->subscribe_data);
}
printk("\n");
return rc;
}
/**
* The signature of this routine must match the subscribe callback declared at
* the mqtt.h header.
*/
static int subscriber_cb(struct mqtt_ctx *mqtt_ctx, uint16_t pkt_id,
uint8_t items, enum mqtt_qos qos[])
{
struct mqtt_client_ctx *client_ctx;
client_ctx = CONTAINER_OF(mqtt_ctx, struct mqtt_client_ctx, mqtt_ctx);
printk("[%s:%d] items: %d packet id: %u", __func__, __LINE__,
items, pkt_id);
if (client_ctx->subscribe_data) {
printk(" user_data: %s",
(const char *)client_ctx->subscribe_data);
}
printk("\n");
return 0;
}
/**
* The signature of this routine must match the unsubscribe callback declared at
* the mqtt.h header.
*/
static int unsubscribe_cb(struct mqtt_ctx *mqtt_ctx, uint16_t pkt_id)
{
struct mqtt_client_ctx *client_ctx;
client_ctx = CONTAINER_OF(mqtt_ctx, struct mqtt_client_ctx, mqtt_ctx);
printk("[%s:%d] packet id: %u", __func__, __LINE__, pkt_id);
if (client_ctx->unsubscribe_data) {
printk(" user_data: %s",
(const char *)client_ctx->unsubscribe_data);
}
printk("\n");
return 0;
}
/**
* The signature of this routine must match the malformed callback declared at
* the mqtt.h header.
*/
static void malformed_cb(struct mqtt_ctx *mqtt_ctx, uint16_t pkt_type)
{
printk("[%s:%d] pkt_type: %u\n", __func__, __LINE__, pkt_type);
}
static char *get_mqtt_topic(void)
{
return "sensors";
}
#define RC_STR(rc) ((rc) == 0 ? "OK" : "ERROR")
#define PRINT_RESULT(func, rc) \
printk("[%s:%d] %s: %d <%s>\n", __func__, __LINE__, \
(func), rc, RC_STR(rc))
/* In this routine we block until the connected variable is 1 */
static int try_to_connect(struct mqtt_client_ctx *client_ctx)
{
int i = 0;
while (i++ < APP_CONNECT_TRIES && !client_ctx->mqtt_ctx.connected) {
int rc;
rc = mqtt_tx_connect(&client_ctx->mqtt_ctx,
&client_ctx->connect_msg);
k_sleep(APP_SLEEP_MSECS);
if (rc != 0) {
continue;
}
}
if (client_ctx->mqtt_ctx.connected) {
return TC_PASS;
}
return TC_FAIL;
}
static int init_network(void)
{
int rc;
/* The net_ctx variable must be ready BEFORE passing it to the MQTT API.
*/
rc = network_setup(&net_ctx, ZEPHYR_ADDR, SERVER_ADDR, SERVER_PORT);
if (rc != 0) {
goto exit_app;
}
/* Set everything to 0 and later just assign the required fields. */
memset(&client_ctx, 0x00, sizeof(client_ctx));
/* The network context is the only field that must be set BEFORE
* calling the mqtt_init routine.
*/
client_ctx.mqtt_ctx.net_ctx = net_ctx;
/* connect, disconnect and malformed may be set to NULL */
client_ctx.mqtt_ctx.connect = connect_cb;
client_ctx.mqtt_ctx.disconnect = disconnect_cb;
client_ctx.mqtt_ctx.malformed = malformed_cb;
client_ctx.mqtt_ctx.subscribe = subscriber_cb;
client_ctx.mqtt_ctx.unsubscribe = unsubscribe_cb;
client_ctx.mqtt_ctx.net_timeout = APP_TX_RX_TIMEOUT;
/* Publisher apps TX the MQTT PUBLISH msg */
client_ctx.mqtt_ctx.publish_rx = publish_rx_cb;
rc = mqtt_init(&client_ctx.mqtt_ctx, MQTT_APP_SUBSCRIBER);
if (rc != 0) {
goto exit_app;
}
/* The connect message will be sent to the MQTT server (broker).
* If clean_session here is 0, the mqtt_ctx clean_session variable
* will be set to 0 also. Please don't do that, set always to 1.
* Clean session = 0 is not yet supported.
*/
client_ctx.connect_msg.client_id = MQTT_CLIENTID;
client_ctx.connect_msg.client_id_len = strlen(MQTT_CLIENTID);
client_ctx.connect_msg.clean_session = 1;
client_ctx.connect_data = "CONNECTED";
client_ctx.disconnect_data = "DISCONNECTED";
client_ctx.subscribe_data = "SUBSCRIBE";
client_ctx.unsubscribe_data = "UNSUBSCRIBE";
return TC_PASS;
exit_app:
net_context_put(net_ctx);
return TC_FAIL;
}
static int test_connect(void)
{
int rc;
rc = try_to_connect(&client_ctx);
if (rc != 0) {
return TC_FAIL;
}
return TC_PASS;
}
static int test_subscribe(void)
{
int rc;
const char *topic_sub = get_mqtt_topic();
uint16_t pkt_id_sub = sys_rand32_get();
static enum mqtt_qos mqtt_qos_sub[1];
rc = mqtt_tx_subscribe(&client_ctx.mqtt_ctx, pkt_id_sub, 1,
&topic_sub, mqtt_qos_sub);
k_sleep(APP_SLEEP_MSECS);
if (rc != 0) {
return TC_FAIL;
}
return TC_PASS;
}
static int test_unsubscribe(void)
{
int rc;
const char *topic_sub = get_mqtt_topic();
uint16_t pkt_id_unsub = sys_rand32_get();
rc = mqtt_tx_unsubscribe(&client_ctx.mqtt_ctx, pkt_id_unsub,
1, &topic_sub);
k_sleep(APP_SLEEP_MSECS);
if (rc != 0) {
return TC_FAIL;
}
return TC_PASS;
}
static int test_disconnect(void)
{
int rc;
rc = mqtt_tx_disconnect(&client_ctx.mqtt_ctx);
if (rc != 0) {
return TC_FAIL;
}
return TC_PASS;
}
static int set_addr(struct sockaddr *sock_addr, const char *addr, uint16_t port)
{
void *ptr;
int rc;
#ifdef CONFIG_NET_IPV6
net_sin6(sock_addr)->sin6_port = htons(port);
sock_addr->family = AF_INET6;
ptr = &(net_sin6(sock_addr)->sin6_addr);
rc = net_addr_pton(AF_INET6, addr, ptr);
#else
net_sin(sock_addr)->sin_port = htons(port);
sock_addr->family = AF_INET;
ptr = &(net_sin(sock_addr)->sin_addr);
rc = net_addr_pton(AF_INET, addr, ptr);
#endif
if (rc) {
printk("Invalid IP address: %s\n", addr);
}
return rc;
}
static int network_setup(struct net_context **net_ctx, const char *local_addr,
const char *server_addr, uint16_t server_port)
{
#ifdef CONFIG_NET_IPV6
socklen_t addr_len = sizeof(struct sockaddr_in6);
sa_family_t family = AF_INET6;
#else
socklen_t addr_len = sizeof(struct sockaddr_in);
sa_family_t family = AF_INET;
#endif
struct sockaddr server_sock, local_sock;
void *p;
int rc;
rc = set_addr(&local_sock, local_addr, 0);
if (rc) {
printk("set_addr (local) error\n");
return rc;
}
#ifdef CONFIG_NET_IPV6
p = net_if_ipv6_addr_add(net_if_get_default(),
&net_sin6(&local_sock)->sin6_addr,
NET_ADDR_MANUAL, 0);
#else
p = net_if_ipv4_addr_add(net_if_get_default(),
&net_sin(&local_sock)->sin_addr,
NET_ADDR_MANUAL, 0);
#endif
if (!p) {
return -EINVAL;
}
rc = net_context_get(family, SOCK_STREAM, IPPROTO_TCP, net_ctx);
if (rc) {
printk("net_context_get error\n");
return rc;
}
rc = net_context_bind(*net_ctx, &local_sock, addr_len);
if (rc) {
printk("net_context_bind error\n");
goto lb_exit;
}
rc = set_addr(&server_sock, server_addr, server_port);
if (rc) {
printk("set_addr (server) error\n");
goto lb_exit;
}
rc = net_context_connect(*net_ctx, &server_sock, addr_len, NULL,
APP_SLEEP_MSECS, NULL);
if (rc) {
printk("net_context_connect error\n"
"Is the server (broker) up and running?\n");
goto lb_exit;
}
return 0;
lb_exit:
net_context_put(*net_ctx);
return rc;
}
void test_mqtt_init(void)
{
assert_true(init_network() == TC_PASS, NULL);
}
void test_mqtt_connect(void)
{
assert_true(test_connect() == TC_PASS, NULL);
}
void test_mqtt_subscribe(void)
{
assert_true(test_subscribe() == TC_PASS, NULL);
}
void test_mqtt_unsubscribe(void)
{
assert_true(test_unsubscribe() == TC_PASS, NULL);
}
void test_mqtt_disconnect(void)
{
assert_true(test_disconnect() == TC_PASS, NULL);
}

View file

@ -0,0 +1,4 @@
[test]
tags = net mqtt
build_only = true
platform_whitelist = frdm_k64f qemu_x86

View file

@ -1206,6 +1206,102 @@ static int test_fragment_compact(void)
return 0;
}
static const char frag_data[CONFIG_NET_NBUF_DATA_SIZE] = { 42 };
static int test_fragment_split(void)
{
#define TEST_FRAG_COUNT (FRAG_COUNT - 2)
#define FRAGA (FRAG_COUNT - 2)
#define FRAGB (FRAG_COUNT - 1)
struct net_buf *buf, *frags[FRAG_COUNT], *frag, *fragA, *fragB;
int i, total, splitA, splitB;
int ret;
buf = net_nbuf_get_reserve_rx(0, K_FOREVER);
frag = NULL;
for (i = 0, total = 0; i < TEST_FRAG_COUNT; i++) {
frags[i] = net_nbuf_get_reserve_rx_data(12, K_FOREVER);
if (frag) {
net_buf_frag_add(frag, frags[i]);
}
frag = frags[i];
/* Copy some test data in front of the fragment */
memcpy(net_buf_add(frags[i], sizeof(frag_data)),
frag_data, sizeof(frag_data));
total++;
}
if (total != TEST_FRAG_COUNT) {
printk("There should be %d fragments but was %d\n",
TEST_FRAG_COUNT, total);
return -1;
}
net_buf_frag_add(buf, frags[0]);
fragA = frags[FRAGA];
fragB = frags[FRAGB];
splitA = fragA->size * 2 / 3;
splitB = fragB->size - splitA;
/* Test some error cases first */
ret = net_nbuf_split(NULL, NULL, 1024, &fragA, &fragB, K_NO_WAIT);
if (!ret) {
printk("Invalid buf pointers\n");
return -1;
}
ret = net_nbuf_split(buf, buf->frags, 1024, &fragA, &fragB, K_NO_WAIT);
if (!ret) {
printk("Too long frag length %d\n", 1024);
return -1;
}
ret = net_nbuf_split(buf, buf->frags, CONFIG_NET_NBUF_DATA_SIZE + 1,
&fragA, &fragB, K_NO_WAIT);
if (!ret) {
printk("Too long frag size %d vs %d\n",
CONFIG_NET_NBUF_DATA_SIZE,
CONFIG_NET_NBUF_DATA_SIZE + 1);
return -1;
}
ret = net_nbuf_split(buf, buf->frags, splitA,
&fragA, &fragB, K_NO_WAIT);
if (ret < 0) {
printk("Cannot split into %d and %d parts\n", splitA, splitB);
return -1;
}
if (fragA->len != splitA) {
printk("Frag A len %d not %d\n", fragA->len, splitA);
return -1;
}
if (fragB->len != splitB) {
printk("Frag B len %d not %d\n", fragB->len, splitB);
return -1;
}
if (memcmp(buf->frags->data, fragA->data, splitA)) {
printk("Frag A data mismatch\n");
return -1;
}
if (memcmp(buf->frags->data + splitA, fragB->data, splitB)) {
printk("Frag B data mismatch\n");
return -1;
}
return 0;
}
void main(void)
{
if (test_ipv6_multi_frags() < 0) {
@ -1232,6 +1328,10 @@ void main(void)
goto fail;
}
if (test_fragment_split() < 0) {
goto fail;
}
printk("nbuf tests passed\n");
TC_END_REPORT(TC_PASS);

View file

@ -21,7 +21,7 @@ CONFIG_NET_RPL=y
CONFIG_NET_RPL_MAX_DAG_PER_INSTANCE=2
CONFIG_NET_RPL_MAX_INSTANCES=3
CONFIG_NET_RPL_PROBING=y
CONFIG_NET_RPL_STATS=y
CONFIG_NET_STATISTICS_RPL=y
CONFIG_SYS_LOG_NET_LEVEL=4
#CONFIG_NET_DEBUG_CONTEXT=y
#CONFIG_NET_DEBUG_CORE=y

View file

@ -228,7 +228,7 @@ static enum net_verdict test_ok(struct net_conn *conn,
if (!ud) {
fail = true;
DBG("Test %s failed.", ud->test);
DBG("Test failed.\n");
return NET_DROP;
}

View file

@ -0,0 +1,3 @@
INCLUDE += subsys
include $(ZEPHYR_BASE)/tests/unit/Makefile.unittest

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <ztest.h>
#include <drivers/crc/crc16_sw.c>
void test_crc16(void)
{
uint8_t test0[] = { };
uint8_t test1[] = { 'A' };
uint8_t test2[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9' };
assert(crc16_ccitt(test0, sizeof(test0)) == 0x1d0f, "pass", "fail");
assert(crc16_ccitt(test1, sizeof(test1)) == 0x9479, "pass", "fail");
assert(crc16_ccitt(test2, sizeof(test2)) == 0xe5cc, "pass", "fail");
}
void test_main(void *p1, void *p2, void *p3)
{
ztest_test_suite(test_crc16, ztest_unit_test(test_crc16));
ztest_run_test_suite(test_crc16);
}

View file

@ -0,0 +1,4 @@
[test]
type = unit
tags = net crc
timeout = 5