Merge "Merge net branch into master"
This commit is contained in:
commit
d3af7f75c9
|
@ -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]+]
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
1
drivers/crc/Makefile
Normal file
|
@ -0,0 +1 @@
|
|||
obj-y += crc16_sw.o
|
35
drivers/crc/crc16_sw.c
Normal file
35
drivers/crc/crc16_sw.c
Normal 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;
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
66
include/crc16.h
Normal 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
|
|
@ -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
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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) | \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
46
samples/net/coaps_server/prj_arduino_101.conf
Normal file
46
samples/net/coaps_server/prj_arduino_101.conf
Normal 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"
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#
|
||||
# Copyright (c) 2016 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
obj-y += main.o
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
[test]
|
||||
tags = net dns
|
||||
build_only = true
|
||||
platform_whitelist = qemu_x86 arduino_101 frdm_k64f
|
|
@ -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.
|
45
samples/net/http_server/prj_arduino_101.conf
Normal file
45
samples/net/http_server/prj_arduino_101.conf
Normal 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
|
||||
|
46
samples/net/http_server/prj_bt.conf
Normal file
46
samples/net/http_server/prj_bt.conf
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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!"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
1176
subsys/net/ip/ipv6.c
1176
subsys/net/ip/ipv6.c
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 },
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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, ':');
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
|
@ -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
4
tests/net/all/Makefile
Normal 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
237
tests/net/all/prj.conf
Normal 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
|
2
tests/net/all/src/Makefile
Normal file
2
tests/net/all/src/Makefile
Normal file
|
@ -0,0 +1,2 @@
|
|||
obj-y = main.o
|
||||
include $(ZEPHYR_BASE)/tests/Makefile.test
|
27
tests/net/all/src/main.c
Normal file
27
tests/net/all/src/main.c
Normal 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);
|
||||
}
|
5
tests/net/all/testcase.ini
Normal file
5
tests/net/all/testcase.ini
Normal file
|
@ -0,0 +1,5 @@
|
|||
[test]
|
||||
tags = net
|
||||
build_only = true
|
||||
arch_whitelist = x86
|
||||
platform_whitelist = qemu_x86
|
|
@ -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();
|
||||
|
||||
|
|
8
tests/net/lib/mqtt_publisher/Makefile
Normal file
8
tests/net/lib/mqtt_publisher/Makefile
Normal 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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
3
tests/net/lib/mqtt_publisher/src/Makefile
Normal file
3
tests/net/lib/mqtt_publisher/src/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
include $(ZEPHYR_BASE)/tests/Makefile.test
|
||||
|
||||
obj-y += main.o test_mqtt_publish.o
|
42
tests/net/lib/mqtt_publisher/src/config.h
Normal file
42
tests/net/lib/mqtt_publisher/src/config.h
Normal 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
|
24
tests/net/lib/mqtt_publisher/src/main.c
Normal file
24
tests/net/lib/mqtt_publisher/src/main.c
Normal 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);
|
||||
}
|
448
tests/net/lib/mqtt_publisher/src/test_mqtt_publish.c
Normal file
448
tests/net/lib/mqtt_publisher/src/test_mqtt_publish.c
Normal 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);
|
||||
}
|
4
tests/net/lib/mqtt_publisher/testcase.ini
Normal file
4
tests/net/lib/mqtt_publisher/testcase.ini
Normal file
|
@ -0,0 +1,4 @@
|
|||
[test]
|
||||
tags = net mqtt
|
||||
build_only = true
|
||||
platform_whitelist = frdm_k64f qemu_x86
|
|
@ -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
|
52
tests/net/lib/mqtt_subscriber/prj_arduino_101.conf
Normal file
52
tests/net/lib/mqtt_subscriber/prj_arduino_101.conf
Normal 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
|
39
tests/net/lib/mqtt_subscriber/prj_frdm_k64f.conf
Normal file
39
tests/net/lib/mqtt_subscriber/prj_frdm_k64f.conf
Normal 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
|
40
tests/net/lib/mqtt_subscriber/prj_qemu_x86.conf
Normal file
40
tests/net/lib/mqtt_subscriber/prj_qemu_x86.conf
Normal 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
|
9
tests/net/lib/mqtt_subscriber/src/Makefile
Normal file
9
tests/net/lib/mqtt_subscriber/src/Makefile
Normal 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
|
||||
|
42
tests/net/lib/mqtt_subscriber/src/config.h
Normal file
42
tests/net/lib/mqtt_subscriber/src/config.h
Normal 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
|
24
tests/net/lib/mqtt_subscriber/src/main.c
Normal file
24
tests/net/lib/mqtt_subscriber/src/main.c
Normal 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);
|
||||
}
|
483
tests/net/lib/mqtt_subscriber/src/test_mqtt_subscribe.c
Normal file
483
tests/net/lib/mqtt_subscriber/src/test_mqtt_subscribe.c
Normal 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);
|
||||
}
|
4
tests/net/lib/mqtt_subscriber/testcase.ini
Normal file
4
tests/net/lib/mqtt_subscriber/testcase.ini
Normal file
|
@ -0,0 +1,4 @@
|
|||
[test]
|
||||
tags = net mqtt
|
||||
build_only = true
|
||||
platform_whitelist = frdm_k64f qemu_x86
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
3
tests/unit/drivers/crc/Makefile
Normal file
3
tests/unit/drivers/crc/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
INCLUDE += subsys
|
||||
|
||||
include $(ZEPHYR_BASE)/tests/unit/Makefile.unittest
|
26
tests/unit/drivers/crc/main.c
Normal file
26
tests/unit/drivers/crc/main.c
Normal 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);
|
||||
}
|
4
tests/unit/drivers/crc/testcase.ini
Normal file
4
tests/unit/drivers/crc/testcase.ini
Normal file
|
@ -0,0 +1,4 @@
|
|||
[test]
|
||||
type = unit
|
||||
tags = net crc
|
||||
timeout = 5
|
Loading…
Reference in a new issue