net: Make native IP stack the default
As the native IP stack is now the default, there is no need for corresponding Kconfig option. Change-Id: I08e4992f540f928a2b7378e8803e634e38725348 Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
parent
3c28f9c211
commit
68ea9377e6
|
@ -16,11 +16,7 @@ obj-$(CONFIG_GPIO) += gpio/
|
|||
obj-$(CONFIG_I2C) += i2c/
|
||||
obj-$(CONFIG_PWM) += pwm/
|
||||
obj-$(CONFIG_ADC) += adc/
|
||||
ifeq ($(CONFIG_NET_YAIP), y)
|
||||
obj-$(CONFIG_NET_L2_ETHERNET) += ethernet/
|
||||
else
|
||||
obj-$(CONFIG_ETHERNET) += ethernet/
|
||||
endif
|
||||
obj-$(CONFIG_SLIP) += slip/
|
||||
obj-$(CONFIG_IEEE802154) += ieee802154/
|
||||
obj-$(CONFIG_WATCHDOG) += watchdog/
|
||||
|
|
|
@ -236,9 +236,7 @@ struct eth_enc28j60_config {
|
|||
};
|
||||
|
||||
struct eth_enc28j60_runtime {
|
||||
#ifdef CONFIG_NET_YAIP
|
||||
struct net_if *iface;
|
||||
#endif
|
||||
char __stack thread_stack[ENC28J60_THREAD_STACK_SIZE];
|
||||
struct device *gpio;
|
||||
struct device *spi;
|
||||
|
@ -249,9 +247,6 @@ struct eth_enc28j60_runtime {
|
|||
struct k_sem tx_rx_sem;
|
||||
struct k_sem int_sem;
|
||||
struct k_sem spi_sem;
|
||||
#ifndef CONFIG_NET_YAIP
|
||||
void (*receive_callback)(uint8_t *buffer, uint16_t len);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /*_ENC28J60_*/
|
||||
|
|
|
@ -37,7 +37,7 @@ menu "IEEE 802.15.4 drivers options"
|
|||
|
||||
config TI_CC2520
|
||||
bool "TI CC2520 Driver support"
|
||||
depends on NET_YAIP
|
||||
depends on NETWORKING
|
||||
select NET_L2_IEEE802154
|
||||
default n
|
||||
|
||||
|
@ -130,7 +130,7 @@ endif
|
|||
config UPIPE_15_4
|
||||
bool "UART PIPE fake radio driver support for QEMU"
|
||||
depends on BOARD_QEMU_X86
|
||||
select NET_YAIP
|
||||
select NETWORKING
|
||||
select UART_PIPE
|
||||
default n
|
||||
|
||||
|
|
|
@ -39,9 +39,7 @@ struct cc2520_spi {
|
|||
};
|
||||
|
||||
struct cc2520_context {
|
||||
#ifdef CONFIG_NET_YAIP
|
||||
struct net_if *iface;
|
||||
#endif
|
||||
/**************************/
|
||||
struct device **gpios;
|
||||
struct gpio_callback sfd_cb;
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
/** @file
|
||||
* @brief DHCPv4 Client Handler
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -14,6 +18,31 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_NET_YAIP)
|
||||
#include <net/yaip/dhcpv4.h>
|
||||
#endif
|
||||
#ifndef __DHCPV4_H
|
||||
#define __DHCPV4_H
|
||||
|
||||
#include <misc/slist.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** Current state of DHCPv4 client address negotiation */
|
||||
enum net_dhcpv4_state {
|
||||
NET_DHCPV4_INIT,
|
||||
NET_DHCPV4_DISCOVER,
|
||||
NET_DHCPV4_OFFER,
|
||||
NET_DHCPV4_REQUEST,
|
||||
NET_DHCPV4_RENEWAL,
|
||||
NET_DHCPV4_ACK,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Start DHCPv4 client
|
||||
*
|
||||
* @details Start DHCPv4 client on a given interface. DHCPv4 client
|
||||
* will start negotiation for IPv4 address. Once the negotiation is
|
||||
* success IPv4 address details will be added to interface.
|
||||
*
|
||||
* @param iface A valid pointer on an interface
|
||||
*/
|
||||
void net_dhcpv4_start(struct net_if *iface);
|
||||
|
||||
#endif /* __DHCPV4_H */
|
||||
|
|
|
@ -14,6 +14,50 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_YAIP
|
||||
#include <net/yaip/ieee802154.h>
|
||||
#endif
|
||||
/**
|
||||
* @file
|
||||
* @brief IEEE 802.15.4 L2 stack public header
|
||||
*/
|
||||
|
||||
#ifndef __IEEE802154_H__
|
||||
#define __IEEE802154_H__
|
||||
|
||||
#include <net/net_mgmt.h>
|
||||
|
||||
/* This not meant to be used by any code but 802.15.4 L2 stack */
|
||||
struct ieee802154_context {
|
||||
uint16_t pan_id;
|
||||
uint16_t channel;
|
||||
uint8_t sequence;
|
||||
struct k_sem ack_lock;
|
||||
uint8_t ack_received : 1;
|
||||
uint8_t ack_requested : 1;
|
||||
uint8_t _unused : 6;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Management part definitions */
|
||||
|
||||
#define _NET_IEEE802154_LAYER NET_MGMT_LAYER_L2
|
||||
#define _NET_IEEE802154_CODE 0x154
|
||||
#define _NET_IEEE802154_BASE (NET_MGMT_IFACE_BIT | \
|
||||
NET_MGMT_LAYER(_NET_IEEE802154_LAYER) |\
|
||||
NET_MGMT_LAYER_CODE(_NET_IEEE802154_CODE))
|
||||
|
||||
enum net_request_ieee802154_cmd {
|
||||
NET_REQUEST_IEEE802154_CMD_SET_ACK = 1,
|
||||
NET_REQUEST_IEEE802154_CMD_UNSET_ACK,
|
||||
};
|
||||
|
||||
|
||||
#define NET_REQUEST_IEEE802154_SET_ACK \
|
||||
(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_ACK)
|
||||
|
||||
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_ACK);
|
||||
|
||||
#define NET_REQUEST_IEEE802154_UNSET_ACK \
|
||||
(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_UNSET_ACK)
|
||||
|
||||
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_UNSET_ACK);
|
||||
|
||||
#endif /* __IEEE802154_H__ */
|
||||
|
|
|
@ -14,6 +14,89 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_YAIP
|
||||
#include <net/yaip/ieee802154_radio.h>
|
||||
#endif
|
||||
/**
|
||||
* @file
|
||||
* @brief Public IEEE 802.15.4 Radio API
|
||||
*/
|
||||
|
||||
#ifndef __IEEE802154_RADIO_H__
|
||||
#define __IEEE802154_RADIO_H__
|
||||
|
||||
#include <device.h>
|
||||
#include <net/net_if.h>
|
||||
|
||||
struct ieee802154_radio_api {
|
||||
/**
|
||||
* Mandatory to get in first position.
|
||||
* A network device should indeed provide a pointer on such
|
||||
* net_if_api structure. So we make current structure pointer
|
||||
* that can be casted to a net_if_api structure pointer.
|
||||
*/
|
||||
struct net_if_api iface_api;
|
||||
|
||||
/** Clear Channel Assesment - Check channel's activity */
|
||||
int (*cca)(struct device *dev);
|
||||
|
||||
/** Set current channel */
|
||||
int (*set_channel)(struct device *dev, uint16_t channel);
|
||||
|
||||
/** Set current PAN id */
|
||||
int (*set_pan_id)(struct device *dev, uint16_t pan_id);
|
||||
|
||||
/** Set current device's short address */
|
||||
int (*set_short_addr)(struct device *dev, uint16_t short_addr);
|
||||
|
||||
/** Set current devices's full length address */
|
||||
int (*set_ieee_addr)(struct device *dev, const uint8_t *ieee_addr);
|
||||
|
||||
/** Set TX power level in dbm */
|
||||
int (*set_txpower)(struct device *dev, int16_t dbm);
|
||||
|
||||
/** Transmit a buffer */
|
||||
int (*tx)(struct device *dev, struct net_buf *buf);
|
||||
|
||||
/** Start the device */
|
||||
int (*start)(struct device *dev);
|
||||
|
||||
/** Stop the device */
|
||||
int (*stop)(struct device *dev);
|
||||
|
||||
/** Get latest Link Quality Information */
|
||||
uint8_t (*get_lqi)(struct device *dev);
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* @brief Radio driver sending function that hw drivers should use
|
||||
*
|
||||
* @details This function should be used to fill in struct net_if's send pointer.
|
||||
*
|
||||
* @param iface A valid pointer on a network interface to send from
|
||||
* @param buf A valid pointer on a buffer to send
|
||||
*
|
||||
* @return 0 on success, negative value otherwise
|
||||
*/
|
||||
extern int ieee802154_radio_send(struct net_if *iface,
|
||||
struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* @brief Radio driver ACK handling function that hw drivers should use
|
||||
*
|
||||
* @details ACK handling requires fast handling and thus such function
|
||||
* helps to hook direcly the hw drivers to the radio driver.
|
||||
*
|
||||
* @param iface A valid pointer on a network interface that received the packet
|
||||
* @param buf A valid pointer on a buffer to check
|
||||
*
|
||||
* @return NET_OK if it was handled, NET_CONTINUE otherwise
|
||||
*/
|
||||
extern enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface,
|
||||
struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* @brief Initialize L2 stack for a given interface
|
||||
*
|
||||
* @param iface A valid pointer on a network interface
|
||||
*/
|
||||
void ieee802154_init(struct net_if *iface);
|
||||
|
||||
#endif /* __IEEE802154_RADIO_H__ */
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
/** @file
|
||||
* @brief Network buffer API
|
||||
*
|
||||
* Network data is passed between different parts of the stack via
|
||||
* net_buf struct.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
|
@ -14,6 +21,911 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_YAIP
|
||||
#include <net/yaip/nbuf.h>
|
||||
#endif /* CONFIG_NET_YAIP */
|
||||
/* Data buffer API - used for all data to/from net */
|
||||
|
||||
#ifndef __NBUF_H
|
||||
#define __NBUF_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <net/buf.h>
|
||||
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_linkaddr.h>
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/net_context.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct net_context;
|
||||
|
||||
/** @cond ignore */
|
||||
enum net_nbuf_type {
|
||||
NET_NBUF_RX = 0,
|
||||
NET_NBUF_TX = 1,
|
||||
NET_NBUF_DATA = 2,
|
||||
};
|
||||
/** @endcond */
|
||||
|
||||
struct net_nbuf {
|
||||
/** Network connection context */
|
||||
struct net_context *context;
|
||||
|
||||
/** Network context token that user can set. This is passed
|
||||
* to user callback when data has been sent.
|
||||
*/
|
||||
void *token;
|
||||
|
||||
/** Network interface */
|
||||
struct net_if *iface;
|
||||
|
||||
/** @cond ignore */
|
||||
uint8_t *appdata; /* application data starts here */
|
||||
uint8_t *next_hdr; /* where is the next header */
|
||||
|
||||
/* Filled by layer 2 when network packet is received. */
|
||||
struct net_linkaddr lladdr_src;
|
||||
struct net_linkaddr lladdr_dst;
|
||||
|
||||
enum net_nbuf_type type;
|
||||
|
||||
uint16_t appdatalen;
|
||||
uint16_t reserve; /* length of the protocol headers */
|
||||
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 */
|
||||
uint8_t ext_len; /* length of extension headers */
|
||||
uint8_t ext_bitmap;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
uint8_t ext_opt_len; /* IPv6 ND option length */
|
||||
#endif
|
||||
/* @endcond */
|
||||
};
|
||||
|
||||
/** @cond ignore */
|
||||
|
||||
|
||||
/* The interface real ll address */
|
||||
static inline struct net_linkaddr *net_nbuf_ll_if(struct net_buf *buf)
|
||||
{
|
||||
return net_if_get_link_addr(
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->iface);
|
||||
}
|
||||
|
||||
static inline struct net_context *net_nbuf_context(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->context;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_context(struct net_buf *buf,
|
||||
struct net_context *ctx)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->context = ctx;
|
||||
}
|
||||
|
||||
static inline void *net_nbuf_token(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->token;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_token(struct net_buf *buf, void *token)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->token = token;
|
||||
}
|
||||
|
||||
static inline struct net_if *net_nbuf_iface(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->iface;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_iface(struct net_buf *buf, struct net_if *iface)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->iface = iface;
|
||||
}
|
||||
|
||||
static inline enum net_nbuf_type net_nbuf_type(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->type;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_type(struct net_buf *buf, uint8_t type)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->type = type;
|
||||
}
|
||||
|
||||
static inline uint8_t net_nbuf_family(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->family;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_family(struct net_buf *buf, uint8_t family)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->family = family;
|
||||
}
|
||||
|
||||
static inline uint8_t net_nbuf_ip_hdr_len(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *) net_buf_user_data(buf))->ip_hdr_len;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_ip_hdr_len(struct net_buf *buf, uint8_t len)
|
||||
{
|
||||
((struct net_nbuf *) net_buf_user_data(buf))->ip_hdr_len = len;
|
||||
}
|
||||
|
||||
static inline uint8_t net_nbuf_ext_len(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->ext_len;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_ext_len(struct net_buf *buf, uint8_t len)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->ext_len = len;
|
||||
}
|
||||
|
||||
static inline uint8_t net_nbuf_ext_bitmap(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->ext_bitmap;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_ext_bitmap(struct net_buf *buf, uint8_t bm)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->ext_bitmap = bm;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_add_ext_bitmap(struct net_buf *buf, uint8_t bm)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->ext_bitmap |= bm;
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_next_hdr(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->next_hdr;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_next_hdr(struct net_buf *buf, uint8_t *hdr)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->next_hdr = hdr;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static inline uint8_t net_nbuf_ext_opt_len(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->ext_opt_len;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_ext_opt_len(struct net_buf *buf, uint8_t len)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->ext_opt_len = len;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline uint16_t net_nbuf_get_len(struct net_buf *buf)
|
||||
{
|
||||
return buf->len;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_len(struct net_buf *buf, uint16_t len)
|
||||
{
|
||||
buf->len = len;
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_ip_data(struct net_buf *buf)
|
||||
{
|
||||
return buf->frags->data;
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_udp_data(struct net_buf *buf)
|
||||
{
|
||||
return &buf->frags->data[net_nbuf_ip_hdr_len(buf) +
|
||||
net_nbuf_ext_len(buf)];
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_tcp_data(struct net_buf *buf)
|
||||
{
|
||||
return &buf->frags->data[net_nbuf_ip_hdr_len(buf) +
|
||||
net_nbuf_ext_len(buf)];
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_icmp_data(struct net_buf *buf)
|
||||
{
|
||||
return &buf->frags->data[net_nbuf_ip_hdr_len(buf) +
|
||||
net_nbuf_ext_len(buf)];
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_appdata(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->appdata;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_appdata(struct net_buf *buf, uint8_t *data)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->appdata = data;
|
||||
}
|
||||
|
||||
static inline uint16_t net_nbuf_appdatalen(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->appdatalen;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_appdatalen(struct net_buf *buf, uint16_t len)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->appdatalen = len;
|
||||
}
|
||||
|
||||
static inline uint16_t net_nbuf_reserve(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->reserve;
|
||||
}
|
||||
|
||||
static inline uint8_t net_nbuf_ll_reserve(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *) net_buf_user_data(buf))->ll_reserve;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_ll_reserve(struct net_buf *buf, uint8_t len)
|
||||
{
|
||||
((struct net_nbuf *) net_buf_user_data(buf))->ll_reserve = len;
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_ll(struct net_buf *buf)
|
||||
{
|
||||
return net_nbuf_ip_data(buf) - net_nbuf_ll_reserve(buf);
|
||||
}
|
||||
|
||||
static inline struct net_linkaddr *net_nbuf_ll_src(struct net_buf *buf)
|
||||
{
|
||||
return &((struct net_nbuf *)net_buf_user_data(buf))->lladdr_src;
|
||||
}
|
||||
|
||||
static inline struct net_linkaddr *net_nbuf_ll_dst(struct net_buf *buf)
|
||||
{
|
||||
return &((struct net_nbuf *)net_buf_user_data(buf))->lladdr_dst;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_ll_clear(struct net_buf *buf)
|
||||
{
|
||||
memset(net_nbuf_ll(buf), 0, net_nbuf_ll_reserve(buf));
|
||||
net_nbuf_ll_src(buf)->addr = NULL;
|
||||
net_nbuf_ll_src(buf)->len = 0;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_ll_swap(struct net_buf *buf)
|
||||
{
|
||||
uint8_t *addr = net_nbuf_ll_src(buf)->addr;
|
||||
|
||||
net_nbuf_ll_src(buf)->addr = net_nbuf_ll_dst(buf)->addr;
|
||||
net_nbuf_ll_dst(buf)->addr = addr;
|
||||
}
|
||||
|
||||
#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))
|
||||
#define NET_UDP_BUF(buf) ((struct net_udp_hdr *)(net_nbuf_udp_data(buf)))
|
||||
#define NET_TCP_BUF(buf) ((struct net_tcp_hdr *)(net_nbuf_tcp_data(buf)))
|
||||
|
||||
static inline void net_nbuf_set_src_ipv6_addr(struct net_buf *buf)
|
||||
{
|
||||
net_if_ipv6_select_src_addr(net_context_get_iface(
|
||||
net_nbuf_context(buf)),
|
||||
&NET_IPV6_BUF(buf)->src);
|
||||
}
|
||||
|
||||
/* @endcond */
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
|
||||
/* Debug versions of the nbuf functions that are used when tracking
|
||||
* buffer usage.
|
||||
*/
|
||||
|
||||
struct net_buf *net_nbuf_get_rx_debug(struct net_context *context,
|
||||
const char *caller, int line);
|
||||
#define net_nbuf_get_rx(context) \
|
||||
net_nbuf_get_rx_debug(context, __func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_get_tx_debug(struct net_context *context,
|
||||
const char *caller, int line);
|
||||
#define net_nbuf_get_tx(context) \
|
||||
net_nbuf_get_tx_debug(context, __func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_get_data_debug(struct net_context *context,
|
||||
const char *caller, int line);
|
||||
#define net_nbuf_get_data(context) \
|
||||
net_nbuf_get_data_debug(context, __func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_get_reserve_rx_debug(uint16_t reserve_head,
|
||||
const char *caller, int line);
|
||||
#define net_nbuf_get_reserve_rx(res) \
|
||||
net_nbuf_get_reserve_rx_debug(res, __func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_get_reserve_tx_debug(uint16_t reserve_head,
|
||||
const char *caller, int line);
|
||||
#define net_nbuf_get_reserve_tx(res) \
|
||||
net_nbuf_get_reserve_tx_debug(res, __func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_get_reserve_data_debug(uint16_t reserve_head,
|
||||
const char *caller, int line);
|
||||
#define net_nbuf_get_reserve_data(res) \
|
||||
net_nbuf_get_reserve_data_debug(res, __func__, __LINE__)
|
||||
|
||||
void net_nbuf_unref_debug(struct net_buf *buf, const char *caller, int line);
|
||||
#define net_nbuf_unref(buf) net_nbuf_unref_debug(buf, __func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_ref_debug(struct net_buf *buf, const char *caller,
|
||||
int line);
|
||||
#define net_nbuf_ref(buf) net_nbuf_ref_debug(buf, __func__, __LINE__)
|
||||
|
||||
/**
|
||||
* @brief Print fragment list and the fragment sizes
|
||||
*
|
||||
* @details Only available if debugging is activated.
|
||||
*
|
||||
* @param buf Network buffer fragment. This should be the first fragment (data)
|
||||
* in the fragment list.
|
||||
*/
|
||||
void net_nbuf_print_frags(struct net_buf *buf);
|
||||
|
||||
#else /* CONFIG_NET_DEBUG_NET_BUF */
|
||||
|
||||
#define net_nbuf_print_frags(...)
|
||||
|
||||
/**
|
||||
* @brief Get buffer from the RX buffers pool.
|
||||
*
|
||||
* @details Get network buffer from RX buffer pool. You must have
|
||||
* network context before able to use this function.
|
||||
*
|
||||
* @param context Network context that will be related to
|
||||
* this buffer.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_rx(struct net_context *context);
|
||||
|
||||
/**
|
||||
* @brief Get buffer from the TX buffers pool.
|
||||
*
|
||||
* @details Get network buffer from TX buffer pool. You must have
|
||||
* network context before able to use this function.
|
||||
*
|
||||
* @param context Network context that will be related to
|
||||
* this buffer.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_tx(struct net_context *context);
|
||||
|
||||
/**
|
||||
* @brief Get buffer from the DATA buffers pool.
|
||||
*
|
||||
* @details Get network buffer from DATA buffer pool. You must have
|
||||
* network context before able to use this function.
|
||||
*
|
||||
* @param context Network context that will be related to
|
||||
* this buffer.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_data(struct net_context *context);
|
||||
|
||||
/**
|
||||
* @brief Get RX buffer from pool but also reserve headroom for
|
||||
* potential headers.
|
||||
*
|
||||
* @details Normally this version is not useful for applications
|
||||
* but is mainly used by network fragmentation code.
|
||||
*
|
||||
* @param reserve_head How many bytes to reserve for headroom.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_reserve_rx(uint16_t reserve_head);
|
||||
|
||||
/**
|
||||
* @brief Get TX buffer from pool but also reserve headroom for
|
||||
* potential headers.
|
||||
*
|
||||
* @details Normally this version is not useful for applications
|
||||
* but is mainly used by network fragmentation code.
|
||||
*
|
||||
* @param reserve_head How many bytes to reserve for headroom.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_reserve_tx(uint16_t reserve_head);
|
||||
|
||||
/**
|
||||
* @brief Get DATA buffer from pool but also reserve headroom for
|
||||
* potential headers.
|
||||
*
|
||||
* @details Normally this version is not useful for applications
|
||||
* but is mainly used by network fragmentation code.
|
||||
*
|
||||
* @param reserve_head How many bytes to reserve for headroom.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_reserve_data(uint16_t reserve_head);
|
||||
|
||||
/**
|
||||
* @brief Place buffer back into the available buffers pool.
|
||||
*
|
||||
* @details Releases the buffer to other use. This needs to be
|
||||
* called by application after it has finished with
|
||||
* the buffer.
|
||||
*
|
||||
* @param buf Network buffer to release.
|
||||
*
|
||||
*/
|
||||
void net_nbuf_unref(struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* @brief Increase the ref count
|
||||
*
|
||||
* @details Mark the buffer to be used still.
|
||||
*
|
||||
* @param buf Network buffer to ref.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_ref(struct net_buf *buf);
|
||||
|
||||
#endif /* CONFIG_NET_DEBUG_NET_BUF */
|
||||
|
||||
/**
|
||||
* @brief Copy a buffer with fragments while reserving some extra space
|
||||
* in destination buffer before a copy.
|
||||
*
|
||||
* @details Note that the original buffer is not really usable after the copy
|
||||
* as the function will call net_buf_pull() internally and should be discarded.
|
||||
*
|
||||
* @param buf Network buffer fragment. This should be the first fragment (data)
|
||||
* in the fragment list.
|
||||
* @param amount Max amount of data to be copied.
|
||||
* @param reserve Amount of extra data (this is not link layer header) in the
|
||||
* first data fragment that is returned. The function will copy the original
|
||||
* buffer right after the reserved bytes in the first destination fragment.
|
||||
*
|
||||
* @return New fragment list if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_copy(struct net_buf *buf, size_t amount,
|
||||
size_t reserve);
|
||||
|
||||
/**
|
||||
* @brief Copy a buffer with fragments while reserving some extra space
|
||||
* in destination buffer before a copy.
|
||||
*
|
||||
* @param buf Network buffer fragment. This should be the first fragment (data)
|
||||
* in the fragment list.
|
||||
* @param reserve Amount of extra data (this is not link layer header) in the
|
||||
* first data fragment that is returned. The function will copy the original
|
||||
* buffer right after the reserved bytes in the first destination fragment.
|
||||
*
|
||||
* @return New fragment list if successful, NULL otherwise.
|
||||
*/
|
||||
static inline struct net_buf *net_nbuf_copy_all(struct net_buf *buf,
|
||||
size_t reserve)
|
||||
{
|
||||
return net_nbuf_copy(buf, net_buf_frags_len(buf), reserve);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compact the fragment list.
|
||||
*
|
||||
* @details After this there is no more any free space in individual fragments.
|
||||
* @param buf Network buffer fragment. This should be the first fragment (data)
|
||||
* in the fragment list.
|
||||
*
|
||||
* @return Pointer to the start of the fragment list if ok, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_compact(struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* @brief Check if the buffer chain is compact or not.
|
||||
*
|
||||
* @details The compact here means that is there any free space in the
|
||||
* fragments. Only the last fragment can have some free space if the fragment
|
||||
* list is compact.
|
||||
*
|
||||
* @param buf Network buffer.
|
||||
*
|
||||
* @return True if there is no free space in the fragment list,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool net_nbuf_is_compact(struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* @brief Create some more space in front of the fragment list.
|
||||
*
|
||||
* @details After this there is more space available before the first
|
||||
* fragment. The existing data needs to be moved "down" which will
|
||||
* cause a cascading effect on fragment list because fragments are fixed
|
||||
* size.
|
||||
*
|
||||
* @param parent Pointer to parent of the network buffer. If there is
|
||||
* no parent, then set this parameter NULL.
|
||||
* @param buf Network buffer
|
||||
* @param amount Amount of data that is needed in front of the fragment list.
|
||||
*
|
||||
* @return Pointer to the start of the fragment list if ok, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_push(struct net_buf *parent, struct net_buf *buf,
|
||||
size_t amount);
|
||||
|
||||
/**
|
||||
* @brief Remove given amount of data from the beginning of fragment list.
|
||||
* This is similar thing to do as in net_buf_pull() but this function changes
|
||||
* the fragment list instead of one fragment.
|
||||
*
|
||||
* @param buf Network buffer fragment list.
|
||||
* @param amount Max amount of data to be remove.
|
||||
*
|
||||
* @return Pointer to start of the fragment list if successful. NULL can be
|
||||
* returned if all fragments were removed from the list.
|
||||
*/
|
||||
struct net_buf *net_nbuf_pull(struct net_buf *buf, size_t amount);
|
||||
|
||||
/**
|
||||
* @brief Append 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. Caller has to take care of endianness if needed.
|
||||
*
|
||||
* @param buf Network buffer fragment list.
|
||||
* @param len Total length of input data
|
||||
* @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).
|
||||
*/
|
||||
bool net_nbuf_append(struct net_buf *buf, uint16_t len, uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief Append uint8_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. Caller has to take care of endianness if needed.
|
||||
*
|
||||
* @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_u8(struct net_buf *buf, uint8_t data)
|
||||
{
|
||||
return net_nbuf_append(buf, 1, &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Append uint16_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. Caller has to take care of endianness if needed.
|
||||
*
|
||||
* @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_be16(struct net_buf *buf, uint16_t data)
|
||||
{
|
||||
uint16_t value = sys_cpu_to_be16(data);
|
||||
|
||||
return net_nbuf_append(buf, sizeof(uint16_t), (uint8_t *)&value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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. Caller has to take care of endianness if needed.
|
||||
*
|
||||
* @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_be32(struct net_buf *buf, uint32_t data)
|
||||
{
|
||||
uint32_t value = sys_cpu_to_be32(data);
|
||||
|
||||
return net_nbuf_append(buf, sizeof(uint32_t), (uint8_t *)&value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get data from buffer
|
||||
*
|
||||
* @details Get N number of bytes starting from fragment's offset. If the total
|
||||
* length of data is placed in multiple framgents, this function will read from
|
||||
* all fragments until it reaches N number of bytes. Caller has to take care of
|
||||
* endianness if needed.
|
||||
*
|
||||
* @param buf Network buffer fragment.
|
||||
* @param offset Offset of input buffer.
|
||||
* @param pos Pointer to position of offset after reading n number of bytes,
|
||||
* this is with respect to return buffer(fragment).
|
||||
* @param len Total length of data to be read.
|
||||
* @param data Data will be copied here.
|
||||
*
|
||||
* @return Pointer to the fragment or
|
||||
* NULL and pos is 0 after successful read,
|
||||
* NULL and pos is 0xffff otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_read(struct net_buf *buf, uint16_t offset,
|
||||
uint16_t *pos, uint16_t len, uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief Skip N number of bytes while reading buffer
|
||||
*
|
||||
* @details Skip N number of bytes starting from fragment's offset. If the total
|
||||
* length of data is placed in multiple framgents, this function will skip from
|
||||
* all fragments until it reaches N number of bytes. This function is useful
|
||||
* when unwanted data (e.g. reserved or not supported data in message) is part
|
||||
* of fragment and want to skip it.
|
||||
*
|
||||
* @param buf Network buffer fragment.
|
||||
* @param offset Offset of input buffer.
|
||||
* @param pos Pointer to position of offset after reading n number of bytes,
|
||||
* this is with respect to return buffer(fragment).
|
||||
* @param len Total length of data to be read.
|
||||
*
|
||||
* @return Pointer to the fragment or
|
||||
* NULL and pos is 0 after successful skip,
|
||||
* NULL and pos is 0xffff otherwise.
|
||||
*/
|
||||
static inline struct net_buf *net_nbuf_skip(struct net_buf *buf,
|
||||
uint16_t offset,
|
||||
uint16_t *pos, uint16_t len)
|
||||
{
|
||||
return net_nbuf_read(buf, offset, pos, len, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a byte value from fragmented buffer
|
||||
*
|
||||
* @param buf Network buffer fragment.
|
||||
* @param offset Offset of input buffer.
|
||||
* @param pos Pointer to position of offset after reading 2 bytes,
|
||||
* this is with respect to return buffer(fragment).
|
||||
* @param value Value is returned
|
||||
*
|
||||
* @return Pointer to fragment after successful read,
|
||||
* NULL otherwise (if pos is 0, NULL is not a failure case).
|
||||
*/
|
||||
static inline struct net_buf *net_nbuf_read_u8(struct net_buf *buf,
|
||||
uint16_t offset,
|
||||
uint16_t *pos,
|
||||
uint8_t *value)
|
||||
{
|
||||
return net_nbuf_read(buf, offset, pos, 1, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get 16 bit big endian value from fragmented buffer
|
||||
*
|
||||
* @param buf Network buffer fragment.
|
||||
* @param offset Offset of input buffer.
|
||||
* @param pos Pointer to position of offset after reading 2 bytes,
|
||||
* this is with respect to return buffer(fragment).
|
||||
* @param value Value is returned
|
||||
*
|
||||
* @return Pointer to fragment after successful read,
|
||||
* NULL otherwise (if pos is 0, NULL is not a failure case).
|
||||
*/
|
||||
struct net_buf *net_nbuf_read_be16(struct net_buf *buf, uint16_t offset,
|
||||
uint16_t *pos, uint16_t *value);
|
||||
|
||||
/**
|
||||
* @brief Get 32 bit big endian value from fragmented buffer
|
||||
*
|
||||
* @param buf Network buffer fragment.
|
||||
* @param offset Offset of input buffer.
|
||||
* @param pos Pointer to position of offset after reading 4 bytes,
|
||||
* this is with respect to return buffer(fragment).
|
||||
* @param value Value is returned
|
||||
*
|
||||
* @return Pointer to fragment after successful read,
|
||||
* NULL otherwise (if pos is 0, NULL is not a failure case).
|
||||
*/
|
||||
struct net_buf *net_nbuf_read_be32(struct net_buf *buf, uint16_t offset,
|
||||
uint16_t *pos, uint32_t *value);
|
||||
|
||||
/**
|
||||
* @brief Write data to an arbitrary offset in a series of fragments.
|
||||
*
|
||||
* @details Write data to an arbitrary offset in a series of fragments.
|
||||
* Offset is based on fragment 'size' and calculates from input fragment
|
||||
* starting position.
|
||||
*
|
||||
* Size in this context refers the fragment full size without link layer header
|
||||
* part. The fragment might have user written data in it, the amount of such
|
||||
* data is stored in frag->len variable (the frag->len is always <= frag->size).
|
||||
* If using this API, the tailroom in the fragments will be taken into use.
|
||||
*
|
||||
* If offset is more than already allocated length in fragment, then empty space
|
||||
* or extra empty fragments is created to reach proper offset.
|
||||
* If there is any data present on input fragment offset, then it will be
|
||||
* 'overwritten'. Use net_nbuf_insert() api if you don't want to overwrite.
|
||||
*
|
||||
* Offset is calculated from starting point of data area in input fragment.
|
||||
* e.g. Buf(Tx/Rx) - Frag1 - Frag2 - Frag3 - Frag4
|
||||
* (Assume FRAG DATA SIZE is 100 bytes after link layer header)
|
||||
*
|
||||
* 1) net_nbuf_write(buf, frag2, 20, &pos, 20, data)
|
||||
* In this case write starts from "frag2->data + 20",
|
||||
* returns frag2, pos = 40
|
||||
*
|
||||
* 2) net_nbuf_write(buf, frag1, 150, &pos, 60, data)
|
||||
* In this case write starts from "frag2->data + 50"
|
||||
* returns frag3, pos = 10
|
||||
*
|
||||
* 3) net_nbuf_write(buf, frag1, 350, &pos, 30, data)
|
||||
* In this case write starts from "frag4->data + 50"
|
||||
* returns frag4, pos = 80
|
||||
*
|
||||
* 4) net_nbuf_write(buf, frag2, 110, &pos, 90, data)
|
||||
* In this case write starts from "frag3->data + 10"
|
||||
* returns frag4, pos = 0
|
||||
*
|
||||
* 5) net_nbuf_write(buf, frag4, 110, &pos, 20, data)
|
||||
* In this case write creates new data fragment and starts from
|
||||
* "frag5->data + 10"
|
||||
* returns frag5, pos = 30
|
||||
*
|
||||
* If input argument frag is NULL, it will create new data fragment
|
||||
* and append at the end of fragment list.
|
||||
*
|
||||
* @param buf Network buffer fragment list.
|
||||
* @param frag Network buffer fragment.
|
||||
* @param offset Offset
|
||||
* @param pos Position of offset after write completed (this will be
|
||||
* relative to return fragment)
|
||||
* @param len Length of the data to be written.
|
||||
* @param data Data to be written
|
||||
*
|
||||
* @return Pointer to the fragment and position (*pos) where write ended,
|
||||
* NULL and pos is 0xffff otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_write(struct net_buf *buf, struct net_buf *frag,
|
||||
uint16_t offset, uint16_t *pos, uint16_t len,
|
||||
uint8_t *data);
|
||||
|
||||
/* Write uint8_t data to an arbitrary offset in fragment. */
|
||||
static inline struct net_buf *net_nbuf_write_u8(struct net_buf *buf,
|
||||
struct net_buf *frag,
|
||||
uint16_t offset,
|
||||
uint16_t *pos,
|
||||
uint8_t data)
|
||||
{
|
||||
return net_nbuf_write(buf, frag, offset, pos, sizeof(uint8_t), &data);
|
||||
}
|
||||
|
||||
/* Write uint16_t big endian value to an arbitrary offset in fragment. */
|
||||
static inline struct net_buf *net_nbuf_write_be16(struct net_buf *buf,
|
||||
struct net_buf *frag,
|
||||
uint16_t offset,
|
||||
uint16_t *pos,
|
||||
uint16_t data)
|
||||
{
|
||||
uint16_t value = htons(data);
|
||||
|
||||
return net_nbuf_write(buf, frag, offset, pos, sizeof(uint16_t),
|
||||
(uint8_t *)&value);
|
||||
}
|
||||
|
||||
/* Write uint32_t big endian value to an arbitrary offset in fragment. */
|
||||
static inline struct net_buf *net_nbuf_write_be32(struct net_buf *buf,
|
||||
struct net_buf *frag,
|
||||
uint16_t offset,
|
||||
uint16_t *pos,
|
||||
uint32_t data)
|
||||
{
|
||||
uint32_t value = htonl(data);
|
||||
|
||||
return net_nbuf_write(buf, frag, offset, pos, sizeof(uint32_t),
|
||||
(uint8_t *)&value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert data at an arbitrary offset in a series of fragments.
|
||||
*
|
||||
* @details Insert data at an arbitrary offset in a series of fragments. Offset
|
||||
* is based on fragment length (only user written data length, any tailroom
|
||||
* in fragments does not come to consideration unlike net_nbuf_write()) and
|
||||
* calculates from input fragment starting position.
|
||||
*
|
||||
* Offset examples can be considered from net_nbuf_write() api.
|
||||
* If the offset is more than already allocated fragments length then it is an
|
||||
* error case.
|
||||
*
|
||||
* @param buf Network buffer fragment list.
|
||||
* @param frag Network buffer fragment.
|
||||
* @param offset Offset of fragment where insertion will start.
|
||||
* @param len Length of the data to be inserted.
|
||||
* @param data Data to be inserted
|
||||
*
|
||||
* @return True on success,
|
||||
* False otherwise.
|
||||
*/
|
||||
bool net_nbuf_insert(struct net_buf *buf, struct net_buf *frag,
|
||||
uint16_t offset, uint16_t len, uint8_t *data);
|
||||
|
||||
/* Insert uint8_t data at an arbitrary offset in a series of fragments. */
|
||||
static inline bool net_nbuf_insert_u8(struct net_buf *buf, struct net_buf *frag,
|
||||
uint16_t offset, uint8_t data)
|
||||
{
|
||||
return net_nbuf_insert(buf, frag, offset, sizeof(uint8_t), &data);
|
||||
}
|
||||
|
||||
/* Insert uint16_t big endian value at an arbitrary offset in a series of
|
||||
* fragments.
|
||||
*/
|
||||
static inline bool net_nbuf_insert_be16(struct net_buf *buf,
|
||||
struct net_buf *frag,
|
||||
uint16_t offset, uint16_t data)
|
||||
{
|
||||
uint16_t value = htons(data);
|
||||
|
||||
return net_nbuf_insert(buf, frag, offset, sizeof(uint16_t),
|
||||
(uint8_t *)&value);
|
||||
}
|
||||
|
||||
/* Insert uint32_t big endian value at an arbitrary offset in a series of
|
||||
* fragments.
|
||||
*/
|
||||
static inline bool net_nbuf_insert_be32(struct net_buf *buf,
|
||||
struct net_buf *frag,
|
||||
uint16_t offset, uint32_t data)
|
||||
{
|
||||
uint32_t value = htonl(data);
|
||||
|
||||
return net_nbuf_insert(buf, frag, offset, sizeof(uint32_t),
|
||||
(uint8_t *)&value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get information about available free buffer count in
|
||||
* various network buffer pools. The amount of free buffers is
|
||||
* only returned if network buffer debugging is enabled.
|
||||
*
|
||||
* @param tx_size Size of TX pool. Value is returned.
|
||||
* @param rx_size Size of RX pool. Value is returned.
|
||||
* @param data_size Size of DATA pool. Value is returned.
|
||||
* @param tx Amount of free buffers in TX pool. Value is returned.
|
||||
* @param rx Amount of free buffers in RX pool. Value is returned.
|
||||
* @param data Amount of free buffers in DATA pool. Value is returned.
|
||||
*/
|
||||
void net_nbuf_get_info(size_t *tx_size, size_t *rx_size, size_t *data_size,
|
||||
int *tx, int *rx, int *data);
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
/**
|
||||
* @brief Debug helper to print out the buffer allocations
|
||||
*/
|
||||
void net_nbuf_print(void);
|
||||
#else
|
||||
#define net_nbuf_print(...)
|
||||
#endif /* CONFIG_NET_DEBUG_NET_BUF */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NBUF_H */
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/** @file
|
||||
* @brief Network context definitions
|
||||
*
|
||||
* An API for applications to define a network connection.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
|
@ -14,6 +20,651 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_NET_YAIP)
|
||||
#include <net/yaip/net_context.h>
|
||||
#ifndef __NET_CONTEXT_H
|
||||
#define __NET_CONTEXT_H
|
||||
|
||||
#include <kernel.h>
|
||||
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/net_stats.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Is this context used or not */
|
||||
#define NET_CONTEXT_IN_USE BIT(0)
|
||||
|
||||
/** State of the context (bits 1 & 2 in the flags) */
|
||||
enum net_context_state {
|
||||
NET_CONTEXT_IDLE = 0,
|
||||
NET_CONTEXT_UNCONNECTED = 0,
|
||||
NET_CONTEXT_CONFIGURING = 1,
|
||||
NET_CONTEXT_CONNECTING = 1,
|
||||
NET_CONTEXT_READY = 2,
|
||||
NET_CONTEXT_CONNECTED = 2,
|
||||
NET_CONTEXT_LISTENING = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* The address family, connection type and IP protocol are
|
||||
* stored into a bit field to save space.
|
||||
*/
|
||||
/** Protocol family of this connection */
|
||||
#define NET_CONTEXT_FAMILY BIT(4)
|
||||
|
||||
/** Type of the connection (datagram / stream) */
|
||||
#define NET_CONTEXT_TYPE BIT(5)
|
||||
|
||||
/** IP protocol (like UDP or TCP) */
|
||||
#define NET_CONTEXT_PROTO BIT(6)
|
||||
|
||||
/** Remote address set */
|
||||
#define NET_CONTEXT_REMOTE_ADDR_SET BIT(7)
|
||||
|
||||
struct net_context;
|
||||
|
||||
/**
|
||||
* @brief Network data receive callback.
|
||||
*
|
||||
* @details The recv callback is called after a network data is
|
||||
* received.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param buf Network buffer that is received. If the buf is not NULL,
|
||||
* then the callback will own the buffer and it needs to to unref the buf
|
||||
* as soon as it has finished working with it.
|
||||
* @param status Value is set to 0 if some data is received, <0 if
|
||||
* there was an error receiving data, in this case the buf parameter is
|
||||
* set to NULL.
|
||||
* @param user_data The user data given in net_recv() call.
|
||||
*/
|
||||
typedef void (*net_context_recv_cb_t)(struct net_context *context,
|
||||
struct net_buf *buf,
|
||||
int status,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Network data send callback.
|
||||
*
|
||||
* @details The send callback is called after a network data is
|
||||
* sent.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param status Value is set to 0 if all data was sent ok, <0 if
|
||||
* there was an error sending data. >0 amount of data that was
|
||||
* sent when not all data was sent ok.
|
||||
* @param token User specified value specified in net_send() call.
|
||||
* @param user_data The user data given in net_send() call.
|
||||
*/
|
||||
typedef void (*net_context_send_cb_t)(struct net_context *context,
|
||||
int status,
|
||||
void *token,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Accept callback
|
||||
*
|
||||
* @details The accept callback is called after a successful
|
||||
* connection is being established or if there was an error
|
||||
* while we were waiting for a connection attempt.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param addr The peer address.
|
||||
* @param addrlen Length of the peer address.
|
||||
* @param status The status code, 0 on success, < 0 otherwise
|
||||
* @param user_data The user data given in net_context_accept() call.
|
||||
*/
|
||||
typedef void (*net_context_accept_cb_t)(struct net_context *new_context,
|
||||
struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
int status,
|
||||
void *user_data);
|
||||
|
||||
struct net_tcp;
|
||||
|
||||
struct net_conn_handle;
|
||||
|
||||
/**
|
||||
* Note that we do not store the actual source IP address in the context
|
||||
* because the address is already be set in the network interface struct.
|
||||
* If there is no such source address there, the packet cannot be sent
|
||||
* anyway. This saves 12 bytes / context in IPv6.
|
||||
*/
|
||||
struct net_context {
|
||||
/** Local IP address. Note that the values are in network byte order.
|
||||
*/
|
||||
struct sockaddr_ptr local;
|
||||
|
||||
/** Remote IP address. Note that the values are in network byte order.
|
||||
*/
|
||||
struct sockaddr remote;
|
||||
|
||||
/** Connection handle */
|
||||
struct net_conn_handle *conn_handler;
|
||||
|
||||
/** Receive callback to be called when desired packet
|
||||
* has been received.
|
||||
*/
|
||||
net_context_recv_cb_t recv_cb;
|
||||
|
||||
/** Send callback to be called when the packet has been sent
|
||||
* successfully.
|
||||
*/
|
||||
net_context_send_cb_t send_cb;
|
||||
|
||||
/** User data.
|
||||
*/
|
||||
void *user_data;
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
|
||||
/**
|
||||
* Mutex for synchronous recv API call.
|
||||
*/
|
||||
struct k_sem recv_data_wait;
|
||||
#endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
|
||||
|
||||
/** Network interface assigned to this context */
|
||||
uint8_t iface;
|
||||
|
||||
/** Flags for the context */
|
||||
uint8_t flags;
|
||||
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
/** TCP connection information */
|
||||
struct net_tcp *tcp;
|
||||
|
||||
/** Accept callback to be called when the connection has been
|
||||
* established.
|
||||
*/
|
||||
net_context_accept_cb_t accept_cb;
|
||||
#endif /* CONFIG_NET_TCP */
|
||||
};
|
||||
|
||||
static inline bool net_context_is_used(struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
return context->flags & NET_CONTEXT_IN_USE;
|
||||
}
|
||||
|
||||
#define NET_CONTEXT_STATE_SHIFT 1
|
||||
#define NET_CONTEXT_STATE_MASK 0x03
|
||||
|
||||
/**
|
||||
* @brief Get state for this network context.
|
||||
*
|
||||
* @details This function returns the state of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
*
|
||||
* @return Network state.
|
||||
*/
|
||||
static inline
|
||||
enum net_context_state net_context_get_state(struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
return (context->flags >> NET_CONTEXT_STATE_SHIFT) &
|
||||
NET_CONTEXT_STATE_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set state for this network context.
|
||||
*
|
||||
* @details This function sets the state of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
* @param state New network context state.
|
||||
*/
|
||||
static inline void net_context_set_state(struct net_context *context,
|
||||
enum net_context_state state)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
context->flags |= ((state & NET_CONTEXT_STATE_MASK) <<
|
||||
NET_CONTEXT_STATE_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get address family for this network context.
|
||||
*
|
||||
* @details This function returns the address family (IPv4 or IPv6)
|
||||
* of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
*
|
||||
* @return Network state.
|
||||
*/
|
||||
static inline sa_family_t net_context_get_family(struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
if (context->flags & NET_CONTEXT_FAMILY) {
|
||||
return AF_INET6;
|
||||
}
|
||||
|
||||
return AF_INET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set address family for this network context.
|
||||
*
|
||||
* @details This function sets the address family (IPv4 or IPv6)
|
||||
* of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
* @param family Address family (AF_INET or AF_INET6)
|
||||
*/
|
||||
static inline void net_context_set_family(struct net_context *context,
|
||||
sa_family_t family)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
if (family == AF_INET6) {
|
||||
context->flags |= NET_CONTEXT_FAMILY;
|
||||
return;
|
||||
}
|
||||
|
||||
context->flags &= ~NET_CONTEXT_FAMILY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get context type for this network context.
|
||||
*
|
||||
* @details This function returns the context type (stream or datagram)
|
||||
* of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
*
|
||||
* @return Network context type.
|
||||
*/
|
||||
static inline
|
||||
enum net_sock_type net_context_get_type(struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
if (context->flags & NET_CONTEXT_TYPE) {
|
||||
return SOCK_STREAM;
|
||||
}
|
||||
|
||||
return SOCK_DGRAM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set context type for this network context.
|
||||
*
|
||||
* @details This function sets the context type (stream or datagram)
|
||||
* of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
* @param type Context type (SOCK_STREAM or SOCK_DGRAM)
|
||||
*/
|
||||
static inline void net_context_set_type(struct net_context *context,
|
||||
enum net_sock_type type)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
if (type == SOCK_STREAM) {
|
||||
context->flags |= NET_CONTEXT_TYPE;
|
||||
return;
|
||||
}
|
||||
|
||||
context->flags &= ~NET_CONTEXT_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get context IP protocol for this network context.
|
||||
*
|
||||
* @details This function returns the context IP protocol (UDP / TCP)
|
||||
* of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
*
|
||||
* @return Network context IP protocol.
|
||||
*/
|
||||
static inline
|
||||
enum net_ip_protocol net_context_get_ip_proto(struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
if (context->flags & NET_CONTEXT_PROTO) {
|
||||
return IPPROTO_TCP;
|
||||
}
|
||||
|
||||
return IPPROTO_UDP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set context IP protocol for this network context.
|
||||
*
|
||||
* @details This function sets the context IP protocol (UDP / TCP)
|
||||
* of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
* @param ip_proto Context IP protocol (IPPROTO_UDP or IPPROTO_TCP)
|
||||
*/
|
||||
static inline void net_context_set_ip_proto(struct net_context *context,
|
||||
enum net_ip_protocol ip_proto)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
if (ip_proto == IPPROTO_TCP) {
|
||||
context->flags |= NET_CONTEXT_PROTO;
|
||||
return;
|
||||
}
|
||||
|
||||
context->flags &= ~NET_CONTEXT_PROTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get network interface for this context.
|
||||
*
|
||||
* @details This function returns the used network interface.
|
||||
*
|
||||
* @param context Network context.
|
||||
*
|
||||
* @return Context network interface if context is bind to interface,
|
||||
* NULL otherwise.
|
||||
*/
|
||||
static inline
|
||||
struct net_if *net_context_get_iface(struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
return net_if_get_by_index(context->iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set network interface for this context.
|
||||
*
|
||||
* @details This function binds network interface to this context.
|
||||
*
|
||||
* @param context Network context.
|
||||
* @param iface Network interface.
|
||||
*/
|
||||
static inline void net_context_set_iface(struct net_context *context,
|
||||
struct net_if *iface)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
|
||||
context->iface = net_if_get_by_iface(iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get network context.
|
||||
*
|
||||
* @details Network context is used to define the connection
|
||||
* 5-tuple (protocol, remote address, remote port, source
|
||||
* address and source port). This is similar as BSD socket()
|
||||
* function.
|
||||
*
|
||||
* @param family IP address family (AF_INET or AF_INET6)
|
||||
* @param type Type of the socket, SOCK_STREAM or SOCK_DGRAM
|
||||
* @param ip_proto IP protocol, IPPROTO_UDP or IPPROTO_TCP
|
||||
* @param context The allocated context is returned to the caller.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_get(sa_family_t family,
|
||||
enum net_sock_type type,
|
||||
enum net_ip_protocol ip_proto,
|
||||
struct net_context **context);
|
||||
|
||||
/**
|
||||
* @brief Free/close a network context.
|
||||
*
|
||||
* @details This releases the context. It is not possible to
|
||||
* send or receive data via this context after this call.
|
||||
* This is similar as BSD shutdown() function.
|
||||
*
|
||||
* @param context The context to be closed.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_put(struct net_context *context);
|
||||
|
||||
/**
|
||||
* @brief Assign a socket a local address.
|
||||
*
|
||||
* @details This is similar as BSD bind() function.
|
||||
*
|
||||
* @param context The context to be assigned.
|
||||
* @param addr Address to assigned.
|
||||
* @param addrlen Length of the address.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_bind(struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* @brief Mark the context as a listening one.
|
||||
*
|
||||
* @details This is similar as BSD listen() function.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param backlog The size of the pending connections backlog.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_listen(struct net_context *context,
|
||||
int backlog);
|
||||
|
||||
/**
|
||||
* @brief Connection callback.
|
||||
*
|
||||
* @details The connect callback is called after a connection is being
|
||||
* established.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param user_data The user data given in net_context_connect() call.
|
||||
*/
|
||||
typedef void (*net_context_connect_cb_t)(struct net_context *context,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Create a network connection.
|
||||
*
|
||||
* @details The net_context_connect function creates a network
|
||||
* connection to the host specified by addr. After the
|
||||
* connection is established, the user supplied callback (cb)
|
||||
* is executed. cb is called even if the timeout was set to
|
||||
* K_FOREVER. cb is not called if the timeout expires.
|
||||
* For datagram sockets (SOCK_DGRAM), this function only sets
|
||||
* the peer address.
|
||||
* This function is similar to the BSD connect() function.
|
||||
*
|
||||
* @param context The network context.
|
||||
* @param addr The peer address to connect to.
|
||||
* @param addrlen Peer address length.
|
||||
* @param cb Callback function. Set to NULL if not required.
|
||||
* @param timeout The timeout value for the connection. Possible values:
|
||||
* * K_NO_WAIT: this function will return immediately,
|
||||
* * K_FOREVER: this function will block until the
|
||||
* connection is established,
|
||||
* * >0: this function will wait the specified ms.
|
||||
* @param user_data Data passed to the callback function.
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return -EINVAL if an invalid parameter is passed as an argument.
|
||||
* @return -ENOTSUP if the operation is not supported or implemented.
|
||||
*/
|
||||
int net_context_connect(struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
net_context_connect_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Accept a network connection attempt.
|
||||
*
|
||||
* @details Accept a connection being established. This function
|
||||
* will return immediately if the timeout is set to K_NO_WAIT.
|
||||
* In this case the context will call the supplied callback when ever
|
||||
* there is a connection established to this context. This is "a register
|
||||
* handler and forget" type of call (async).
|
||||
* If the timeout is set to K_FOREVER, the function will wait
|
||||
* until the connection is established. Timeout value > 0, will wait as
|
||||
* many ms.
|
||||
* After the connection is established a caller supplied callback is called.
|
||||
* The callback is called even if timeout was set to K_FOREVER, the
|
||||
* callback is called before this function will return in this case.
|
||||
* The callback is not called if the timeout expires.
|
||||
* This is similar as BSD accept() function.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Timeout for the connection. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_accept(struct net_context *context,
|
||||
net_context_accept_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Send a network buffer to a peer.
|
||||
*
|
||||
* @details This function can be used to send network data to a peer
|
||||
* connection. This function will return immediately if the timeout
|
||||
* is set to K_NO_WAIT. If the timeout is set to K_FOREVER, the function
|
||||
* will wait until the network buffer is sent. Timeout value > 0 will
|
||||
* wait as many ms. After the network buffer is sent,
|
||||
* a caller supplied callback is called. The callback is called even
|
||||
* if timeout was set to K_FOREVER, the callback is called
|
||||
* before this function will return in this case. The callback is not
|
||||
* called if the timeout expires. For context of type SOCK_DGRAM,
|
||||
* the destination address must have been set by the call to
|
||||
* net_context_connect().
|
||||
* This is similar as BSD send() function.
|
||||
*
|
||||
* @param buf The network buffer to send.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Timeout for the connection. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param token Caller specified value that is passed as is to callback.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_send(struct net_buf *buf,
|
||||
net_context_send_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *token,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Send a network buffer to a peer specified by address.
|
||||
*
|
||||
* @details This function can be used to send network data to a peer
|
||||
* specified by address. This variant can only be used for datagram
|
||||
* connections of type SOCK_DGRAM. This function will return immediately
|
||||
* if the timeout is set to K_NO_WAIT. If the timeout is set to K_FOREVER,
|
||||
* the function will wait until the network buffer is sent. Timeout
|
||||
* value > 0 will wait as many ms. After the network buffer
|
||||
* is sent, a caller supplied callback is called. The callback is called
|
||||
* even if timeout was set to K_FOREVER, the callback is called
|
||||
* before this function will return. The callback is not called if the
|
||||
* timeout expires.
|
||||
* This is similar as BSD sendto() function.
|
||||
*
|
||||
* @param buf The network buffer to send.
|
||||
* @param dst_addr Destination address. This will override the address
|
||||
* already set in network buffer.
|
||||
* @param addrlen Length of the address.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Timeout for the connection. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param token Caller specified value that is passed as is to callback.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_sendto(struct net_buf *buf,
|
||||
const struct sockaddr *dst_addr,
|
||||
socklen_t addrlen,
|
||||
net_context_send_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *token,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Receive network data from a peer specified by context.
|
||||
*
|
||||
* @details This function can be used to register a callback function
|
||||
* that is called by the network stack when network data has been received
|
||||
* for this context. As this function registers a callback, then there
|
||||
* is no need to call this function multiple times if timeout is set to
|
||||
* K_NO_WAIT.
|
||||
* If callback function or user data changes, then the function can be called
|
||||
* multiple times to register new values.
|
||||
* This function will return immediately if the timeout is set to K_NO_WAIT.
|
||||
* If the timeout is set to K_FOREVER, the function will wait until the
|
||||
* network buffer is received. Timeout value > 0 will wait as many ms.
|
||||
* After the network buffer is received, a caller supplied callback is
|
||||
* called. The callback is called even if timeout was set to K_FOREVER,
|
||||
* the callback is called before this function will return in this case.
|
||||
* The callback is not called if the timeout expires. The timeout functionality
|
||||
* can be compiled out if synchronous behaviour is not needed. The sync call
|
||||
* logic requires some memory that can be saved if only async way of call is
|
||||
* used. If CONFIG_NET_CONTEXT_SYNC_RECV is not set, then the timeout parameter
|
||||
* value is ignored.
|
||||
* This is similar as BSD recv() function.
|
||||
*
|
||||
* @param context The network context to use.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Caller supplied timeout. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_recv(struct net_context *context,
|
||||
net_context_recv_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Internal function that is called when network packet is sent
|
||||
* successfully.
|
||||
*
|
||||
* @param context The network context to use.
|
||||
* @param token User supplied token tied to the net_buf that was sent.
|
||||
* @param err_code Error code
|
||||
*/
|
||||
static inline void net_context_send_cb(struct net_context *context,
|
||||
void *token,
|
||||
int err_code)
|
||||
{
|
||||
if (context->send_cb) {
|
||||
context->send_cb(context, err_code, token, context->user_data);
|
||||
}
|
||||
|
||||
if (net_context_get_ip_proto(context) == IPPROTO_UDP) {
|
||||
NET_STATS_UDP(++net_stats.udp.sent);
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*net_context_cb_t)(struct net_context *context, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Go through all the network connections and call callback
|
||||
* for each network context.
|
||||
*
|
||||
* @param cb User supplied callback function to call.
|
||||
* @param user_data User specified data.
|
||||
*/
|
||||
void net_context_foreach(net_context_cb_t cb, void *user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NET_CONTEXT_H */
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
/** @file
|
||||
* @brief Network core definitions
|
||||
*
|
||||
* Definitions for networking support.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -14,6 +20,193 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_NET_YAIP)
|
||||
#include <net/yaip/net_core.h>
|
||||
#ifndef __NET_CORE_H
|
||||
#define __NET_CORE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Network subsystem logging helpers */
|
||||
|
||||
#if defined(CONFIG_NET_LOG)
|
||||
#if NET_DEBUG > 0
|
||||
#if !defined(SYS_LOG_DOMAIN)
|
||||
#define SYS_LOG_DOMAIN "net"
|
||||
#endif /* !SYS_LOG_DOMAIN */
|
||||
|
||||
#undef SYS_LOG_LEVEL
|
||||
#define SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
|
||||
#endif /* NET_DEBUG */
|
||||
|
||||
#define NET_DBG(fmt, ...) SYS_LOG_DBG("(%p): " fmt, k_current_get(), \
|
||||
##__VA_ARGS__)
|
||||
#define NET_ERR(fmt, ...) SYS_LOG_ERR(fmt, ##__VA_ARGS__)
|
||||
#define NET_WARN(fmt, ...) SYS_LOG_WRN(fmt, ##__VA_ARGS__)
|
||||
#define NET_INFO(fmt, ...) SYS_LOG_INF(fmt, ##__VA_ARGS__)
|
||||
#define NET_ASSERT(cond) do { \
|
||||
if (!(cond)) { \
|
||||
NET_ERR("{assert: '" #cond "' failed}"); \
|
||||
} } while (0)
|
||||
#define NET_ASSERT_INFO(cond, fmt, ...) do { \
|
||||
if (!(cond)) { \
|
||||
NET_ERR("{assert: '" #cond "' failed} " fmt, \
|
||||
##__VA_ARGS__); \
|
||||
} } while (0)
|
||||
#else /* CONFIG_NET_LOG */
|
||||
#define NET_DBG(...)
|
||||
#define NET_ERR(...)
|
||||
#define NET_INFO(...)
|
||||
#define NET_WARN(...)
|
||||
#define NET_ASSERT(...)
|
||||
#define NET_ASSERT_INFO(...)
|
||||
#endif /* CONFIG_NET_LOG */
|
||||
|
||||
#include <kernel.h>
|
||||
|
||||
struct net_buf;
|
||||
struct net_context;
|
||||
struct net_if;
|
||||
|
||||
#include <misc/sys_log.h>
|
||||
#include <string.h>
|
||||
|
||||
enum net_verdict {
|
||||
NET_OK, /** Packet has been taken care of */
|
||||
NET_CONTINUE, /** Packet has not been touched,
|
||||
other part should decide about its fate */
|
||||
NET_DROP, /** Packet must be dropped */
|
||||
};
|
||||
|
||||
/* Called by lower network stack when a network packet has been received */
|
||||
int net_recv_data(struct net_if *iface, struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* @brief Send data to network.
|
||||
*
|
||||
* @details Send data to network. This should not be used normally by
|
||||
* applications as it requires that the buffer and fragments are properly
|
||||
* constructed.
|
||||
*
|
||||
* @param buf Network buffer.
|
||||
*
|
||||
* @return 0 if ok, <0 if error. If <0 is returned, then the caller needs
|
||||
* to unref the buf in order to avoid buffer leak.
|
||||
*/
|
||||
int net_send_data(struct net_buf *buf);
|
||||
|
||||
struct net_stack_info {
|
||||
unsigned char *stack;
|
||||
const char *pretty_name;
|
||||
const char *name;
|
||||
size_t orig_size;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_SHELL)
|
||||
#define NET_STACK_GET_NAME(name, sfx) (__net_stack_##name##_##sfx)
|
||||
|
||||
#define NET_STACK_INFO_ADDR(_pretty, _name, _orig, _size, _addr, sfx) \
|
||||
static struct net_stack_info \
|
||||
(NET_STACK_GET_NAME(_name, sfx)) __used \
|
||||
__attribute__((__section__(".net_stack.data"))) = { \
|
||||
.stack = _addr, \
|
||||
.size = _size, \
|
||||
.orig_size = _orig, \
|
||||
.name = #_name, \
|
||||
.pretty_name = _pretty, \
|
||||
}
|
||||
|
||||
#define NET_STACK_INFO(_pretty_name, _name, _orig, _size) \
|
||||
NET_STACK_INFO_ADDR(_pretty_name, _name, _orig, _size, _name, 0)
|
||||
|
||||
#define NET_STACK_DEFINE(pretty_name, name, orig, size) \
|
||||
static unsigned char __noinit __stack name[size]; \
|
||||
NET_STACK_INFO(pretty_name, name, orig, size)
|
||||
|
||||
#else /* CONFIG_NET_SHELL */
|
||||
|
||||
#define NET_STACK_INFO(...)
|
||||
#define NET_STACK_INFO_ADDR(...)
|
||||
|
||||
#define NET_STACK_DEFINE(pretty_name, name, orig, size) \
|
||||
static unsigned char __noinit __stack name[size]
|
||||
|
||||
#endif /* CONFIG_NET_SHELL */
|
||||
|
||||
#define NET_STACK_DEFINE_EMBEDDED(name, size) unsigned char name[size]
|
||||
|
||||
/** @cond ignore */
|
||||
#if defined(CONFIG_INIT_STACKS)
|
||||
#include <offsets.h>
|
||||
|
||||
static inline void net_analyze_stack_get_values(unsigned char *stack,
|
||||
size_t size,
|
||||
unsigned *stack_offset,
|
||||
unsigned *pcnt,
|
||||
unsigned *unused)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
*unused = 0;
|
||||
|
||||
/* The TCS is always placed on a 4-byte aligned boundary - if
|
||||
* the stack beginning doesn't match that there will be some
|
||||
* unused bytes in the beginning.
|
||||
*/
|
||||
*stack_offset = K_THREAD_SIZEOF + ((4 - ((unsigned)stack % 4)) % 4);
|
||||
|
||||
/* TODO
|
||||
* Currently all supported platforms have stack growth down and there is no
|
||||
* Kconfig option to configure it so this always build "else" branch.
|
||||
* When support for platform with stack direction up (or configurable direction)
|
||||
* is added this check should be confirmed that correct Kconfig option is used.
|
||||
*/
|
||||
#if defined(CONFIG_STACK_GROWS_UP)
|
||||
for (i = size - 1; i >= *stack_offset; i--) {
|
||||
if ((unsigned char)stack[i] == 0xaa) {
|
||||
(*unused)++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (i = *stack_offset; i < size; i++) {
|
||||
if ((unsigned char)stack[i] == 0xaa) {
|
||||
(*unused)++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Calculate the real size reserved for the stack */
|
||||
size -= *stack_offset;
|
||||
*pcnt = ((size - *unused) * 100) / size;
|
||||
}
|
||||
|
||||
static inline void net_analyze_stack(const char *name,
|
||||
unsigned char *stack,
|
||||
size_t size)
|
||||
{
|
||||
unsigned stack_offset, pcnt, unused;
|
||||
|
||||
net_analyze_stack_get_values(stack, size, &stack_offset,
|
||||
&pcnt, &unused);
|
||||
|
||||
NET_INFO("net (%p): %s stack real size %u "
|
||||
"unused %u usage %u/%u (%u %%)",
|
||||
k_current_get(), name,
|
||||
size + stack_offset, unused, size - unused, size, pcnt);
|
||||
}
|
||||
#else
|
||||
#define net_analyze_stack(...)
|
||||
#define net_analyze_stack_get_values(...)
|
||||
#endif
|
||||
/* @endcond */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NET_CORE_H */
|
||||
|
|
|
@ -14,6 +14,70 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_YAIP
|
||||
#include <net/yaip/net_event.h>
|
||||
#endif
|
||||
/**
|
||||
* @file
|
||||
* @brief Network Events code public header
|
||||
*/
|
||||
|
||||
#ifndef __NET_EVENT_H__
|
||||
#define __NET_EVENT_H__
|
||||
|
||||
/* IPv6 Events */
|
||||
#define _NET_IPV6_LAYER NET_MGMT_LAYER_L3
|
||||
#define _NET_IPV6_CORE_CODE 0x600
|
||||
#define _NET_EVENT_IPV6_BASE (NET_MGMT_EVENT_BIT | \
|
||||
NET_MGMT_IFACE_BIT | \
|
||||
NET_MGMT_LAYER(_NET_IPV6_LAYER) | \
|
||||
NET_MGMT_LAYER_CODE(_NET_IPV6_CORE_CODE))
|
||||
|
||||
enum net_event_ipv6_cmd {
|
||||
NET_EVENT_IPV6_CMD_ADDR_ADD = 0,
|
||||
NET_EVENT_IPV6_CMD_ADDR_DEL,
|
||||
NET_EVENT_IPV6_CMD_MADDR_ADD,
|
||||
NET_EVENT_IPV6_CMD_MADDR_DEL,
|
||||
NET_EVENT_IPV6_CMD_PREFIX_ADD,
|
||||
NET_EVENT_IPV6_CMD_PREFIX_DEL,
|
||||
};
|
||||
|
||||
#define NET_EVENT_IPV6_ADDR_ADD \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_ADD)
|
||||
|
||||
#define NET_EVENT_IPV6_ADDR_DEL \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_DEL)
|
||||
|
||||
#define NET_EVENT_IPV6_MADDR_ADD \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MADDR_ADD)
|
||||
|
||||
#define NET_EVENT_IPV6_MADDR_DEL \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MADDR_DEL)
|
||||
|
||||
#define NET_EVENT_IPV6_PREFIX_ADD \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PREFIX_ADD)
|
||||
|
||||
#define NET_EVENT_IPV6_PREFIX_DEL \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PREFIX_DEL)
|
||||
|
||||
#define _NET_IPV4_LAYER NET_MGMT_LAYER_L3
|
||||
#define _NET_IPV4_CORE_CODE 0x400
|
||||
#define _NET_EVENT_IPV4_BASE (NET_MGMT_EVENT_BIT | \
|
||||
NET_MGMT_IFACE_BIT | \
|
||||
NET_MGMT_LAYER(_NET_IPV4_LAYER) | \
|
||||
NET_MGMT_LAYER_CODE(_NET_IPV4_CORE_CODE))
|
||||
|
||||
/* IPv4 Events*/
|
||||
enum net_event_ipv4_cmd {
|
||||
NET_EVENT_IPV4_CMD_ADDR_ADD = 0,
|
||||
NET_EVENT_IPV4_CMD_ADDR_DEL,
|
||||
NET_EVENT_IPV4_CMD_ROUTER_ADD,
|
||||
};
|
||||
|
||||
#define NET_EVENT_IPV4_ADDR_ADD \
|
||||
(_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ADDR_ADD)
|
||||
|
||||
#define NET_EVENT_IPV4_ADDR_DEL \
|
||||
(_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ADDR_DEL)
|
||||
|
||||
#define NET_EVENT_IPV4_ROUTER_ADD \
|
||||
(_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ROUTER_ADD)
|
||||
|
||||
#endif /* __NET_EVENT_H__ */
|
||||
|
|
1128
include/net/net_if.h
1128
include/net/net_if.h
File diff suppressed because it is too large
Load diff
|
@ -1,3 +1,9 @@
|
|||
/** @file
|
||||
* @brief IPv6 and IPv4 definitions
|
||||
*
|
||||
* Generic IPv6 and IPv4 address definitions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
|
@ -14,4 +20,778 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <net/yaip/net_ip.h>
|
||||
#ifndef __NET_IP_H
|
||||
#define __NET_IP_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <misc/byteorder.h>
|
||||
#include <toolchain.h>
|
||||
|
||||
#include <net/net_linkaddr.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Protocol families */
|
||||
#define PF_UNSPEC 0 /* Unspecified. */
|
||||
#define PF_INET 2 /* IP protocol family. */
|
||||
#define PF_INET6 10 /* IP version 6. */
|
||||
|
||||
/** Address families. */
|
||||
#define AF_UNSPEC PF_UNSPEC
|
||||
#define AF_INET PF_INET
|
||||
#define AF_INET6 PF_INET6
|
||||
|
||||
/** Protocol numbers from IANA */
|
||||
enum net_ip_protocol {
|
||||
IPPROTO_ICMP = 1,
|
||||
IPPROTO_TCP = 6,
|
||||
IPPROTO_UDP = 17,
|
||||
IPPROTO_ICMPV6 = 58,
|
||||
};
|
||||
|
||||
/** Socket type */
|
||||
enum net_sock_type {
|
||||
SOCK_DGRAM = 1,
|
||||
SOCK_STREAM,
|
||||
};
|
||||
|
||||
#define ntohs(x) sys_be16_to_cpu(x)
|
||||
#define ntohl(x) sys_be32_to_cpu(x)
|
||||
#define htons(x) sys_cpu_to_be16(x)
|
||||
#define htonl(x) sys_cpu_to_be32(x)
|
||||
|
||||
/** IPv6 address structure */
|
||||
struct in6_addr {
|
||||
union {
|
||||
uint8_t u6_addr8[16];
|
||||
uint16_t u6_addr16[8]; /* In big endian */
|
||||
uint32_t u6_addr32[4]; /* In big endian */
|
||||
} in6_u;
|
||||
#define s6_addr in6_u.u6_addr8
|
||||
#define s6_addr16 in6_u.u6_addr16
|
||||
#define s6_addr32 in6_u.u6_addr32
|
||||
};
|
||||
|
||||
/** IPv4 address */
|
||||
struct in_addr {
|
||||
union {
|
||||
uint8_t u4_addr8[4];
|
||||
uint16_t u4_addr16[2]; /* In big endian */
|
||||
uint32_t u4_addr32[1]; /* In big endian */
|
||||
} in4_u;
|
||||
#define s4_addr in4_u.u4_addr8
|
||||
#define s4_addr16 in4_u.u4_addr16
|
||||
#define s4_addr32 in4_u.u4_addr32
|
||||
|
||||
#define s_addr s4_addr32
|
||||
};
|
||||
|
||||
typedef unsigned short int sa_family_t;
|
||||
typedef size_t socklen_t;
|
||||
|
||||
/**
|
||||
* Note that the sin_port and sin6_port are in network byte order
|
||||
* in various sockaddr* structs.
|
||||
*/
|
||||
struct sockaddr_in6 {
|
||||
sa_family_t sin6_family; /* AF_INET6 */
|
||||
uint16_t sin6_port; /* Port number */
|
||||
struct in6_addr sin6_addr; /* IPv6 address */
|
||||
uint8_t sin6_scope_id; /* interfaces for a scope */
|
||||
};
|
||||
|
||||
struct sockaddr_in6_ptr {
|
||||
sa_family_t sin6_family; /* AF_INET6 */
|
||||
uint16_t sin6_port; /* Port number */
|
||||
struct in6_addr *sin6_addr; /* IPv6 address */
|
||||
uint8_t sin6_scope_id; /* interfaces for a scope */
|
||||
};
|
||||
|
||||
struct sockaddr_in {
|
||||
sa_family_t sin_family; /* AF_INET */
|
||||
uint16_t sin_port; /* Port number */
|
||||
struct in_addr sin_addr; /* IPv4 address */
|
||||
};
|
||||
|
||||
struct sockaddr_in_ptr {
|
||||
sa_family_t sin_family; /* AF_INET */
|
||||
uint16_t sin_port; /* Port number */
|
||||
struct in_addr *sin_addr; /* IPv4 address */
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
#define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_in6))
|
||||
#define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_in6_ptr))
|
||||
#elif defined(CONFIG_NET_IPV4)
|
||||
#define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_in))
|
||||
#define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_in_ptr))
|
||||
#else
|
||||
#if !defined(CONFIG_NET_L2_RAW_CHANNEL)
|
||||
#error "Either IPv6 or IPv4 needs to be selected."
|
||||
#else
|
||||
#define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_in6))
|
||||
#define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_in6_ptr))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct sockaddr {
|
||||
sa_family_t family;
|
||||
char data[NET_SOCKADDR_MAX_SIZE - sizeof(sa_family_t)];
|
||||
};
|
||||
|
||||
struct sockaddr_ptr {
|
||||
sa_family_t family;
|
||||
char data[NET_SOCKADDR_PTR_MAX_SIZE - sizeof(sa_family_t)];
|
||||
};
|
||||
|
||||
struct net_addr {
|
||||
sa_family_t family;
|
||||
union {
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
struct in6_addr in6_addr;
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
struct in_addr in_addr;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
#define IN6ADDR_ANY_INIT { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0 } } }
|
||||
#define IN6ADDR_LOOPBACK_INIT { { { 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1 } } }
|
||||
|
||||
#define INET6_ADDRSTRLEN 46
|
||||
#define NET_IPV6_ADDR_LEN sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")
|
||||
#define NET_IPV4_ADDR_LEN sizeof("xxx.xxx.xxx.xxx")
|
||||
|
||||
#define INADDR_ANY 0
|
||||
|
||||
#define NET_IPV6_MTU 1280
|
||||
|
||||
/** IPv6 extension headers types */
|
||||
#define NET_IPV6_NEXTHDR_HBHO 0
|
||||
#define NET_IPV6_NEXTHDR_DESTO 60
|
||||
#define NET_IPV6_NEXTHDR_ROUTING 43
|
||||
#define NET_IPV6_NEXTHDR_FRAG 44
|
||||
#define NET_IPV6_NEXTHDR_NONE 59
|
||||
|
||||
/** IPv6/IPv4 network connection tuple */
|
||||
struct net_tuple {
|
||||
/** IPv6/IPv4 remote address */
|
||||
struct net_addr *remote_addr;
|
||||
/** IPv6/IPv4 local address */
|
||||
struct net_addr *local_addr;
|
||||
/** UDP/TCP remote port */
|
||||
uint16_t remote_port;
|
||||
/** UDP/TCP local port */
|
||||
uint16_t local_port;
|
||||
/** IP protocol */
|
||||
enum net_ip_protocol ip_proto;
|
||||
};
|
||||
|
||||
/** How the network address is assigned to network interface */
|
||||
enum net_addr_type {
|
||||
NET_ADDR_ANY = 0,
|
||||
NET_ADDR_AUTOCONF,
|
||||
NET_ADDR_DHCP,
|
||||
NET_ADDR_MANUAL,
|
||||
};
|
||||
|
||||
#if NET_DEBUG > 0
|
||||
static inline char *net_addr_type2str(enum net_addr_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case NET_ADDR_AUTOCONF:
|
||||
return "AUTO";
|
||||
case NET_ADDR_DHCP:
|
||||
return "DHCP";
|
||||
case NET_ADDR_MANUAL:
|
||||
return "MANUAL";
|
||||
case NET_ADDR_ANY:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "<unknown>";
|
||||
}
|
||||
#else
|
||||
static inline char *net_addr_type2str(enum net_addr_type type)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** What is the current state of the network address */
|
||||
enum net_addr_state {
|
||||
NET_ADDR_ANY_STATE = -1,
|
||||
NET_ADDR_TENTATIVE = 0,
|
||||
NET_ADDR_PREFERRED,
|
||||
NET_ADDR_DEPRECATED,
|
||||
};
|
||||
|
||||
struct net_ipv6_hdr {
|
||||
uint8_t vtc;
|
||||
uint8_t tcflow;
|
||||
uint16_t flow;
|
||||
uint8_t len[2];
|
||||
uint8_t nexthdr;
|
||||
uint8_t hop_limit;
|
||||
struct in6_addr src;
|
||||
struct in6_addr dst;
|
||||
} __packed;
|
||||
|
||||
struct net_ipv4_hdr {
|
||||
uint8_t vhl;
|
||||
uint8_t tos;
|
||||
uint8_t len[2];
|
||||
uint8_t id[2];
|
||||
uint8_t offset[2];
|
||||
uint8_t ttl;
|
||||
uint8_t proto;
|
||||
uint16_t chksum;
|
||||
struct in_addr src;
|
||||
struct in_addr dst;
|
||||
} __packed;
|
||||
|
||||
struct net_icmp_hdr {
|
||||
uint8_t type;
|
||||
uint8_t code;
|
||||
uint16_t chksum;
|
||||
} __packed;
|
||||
|
||||
struct net_udp_hdr {
|
||||
uint16_t src_port;
|
||||
uint16_t dst_port;
|
||||
uint16_t len;
|
||||
uint16_t chksum;
|
||||
} __packed;
|
||||
|
||||
struct net_tcp_hdr {
|
||||
uint16_t src_port;
|
||||
uint16_t dst_port;
|
||||
uint8_t seq[4];
|
||||
uint8_t ack[4];
|
||||
uint8_t offset;
|
||||
uint8_t flags;
|
||||
uint8_t wnd[2];
|
||||
uint16_t chksum;
|
||||
uint8_t urg[2];
|
||||
uint8_t optdata[0];
|
||||
} __packed;
|
||||
|
||||
#define NET_UDPH_LEN 8 /* Size of UDP header */
|
||||
#define NET_TCPH_LEN 20 /* Size of TCP header */
|
||||
#define NET_ICMPH_LEN 4 /* Size of ICMP header */
|
||||
|
||||
#define NET_IPV6H_LEN 40 /* Size of IPv6 header */
|
||||
#define NET_ICMPV6H_LEN NET_ICMPH_LEN /* Size of ICMPv6 header */
|
||||
#define NET_IPV6UDPH_LEN (NET_UDPH_LEN + NET_IPV6H_LEN) /* IPv6 + UDP */
|
||||
#define NET_IPV6TCPH_LEN (NET_TCPH_LEN + NET_IPV6H_LEN) /* IPv6 + TCP */
|
||||
#define NET_IPV6ICMPH_LEN (NET_IPV6H_LEN + NET_ICMPH_LEN) /* ICMPv6 + IPv6 */
|
||||
#define NET_IPV6_FRAGH_LEN 8
|
||||
|
||||
#define NET_IPV4H_LEN 20 /* Size of IPv4 header */
|
||||
#define NET_ICMPV4H_LEN NET_ICMPH_LEN /* Size of ICMPv4 header */
|
||||
#define NET_IPV4UDPH_LEN (NET_UDPH_LEN + NET_IPV4H_LEN) /* IPv4 + UDP */
|
||||
#define NET_IPV4TCPH_LEN (NET_TCPH_LEN + NET_IPV4H_LEN) /* IPv4 + TCP */
|
||||
#define NET_IPV4ICMPH_LEN (NET_IPV4H_LEN + NET_ICMPH_LEN) /* ICMPv4 + IPv4 */
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv6 address is a loopback address (::1).
|
||||
*
|
||||
* @param addr IPv6 address
|
||||
*
|
||||
* @return True if address is a loopback address, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv6_addr_loopback(struct in6_addr *addr)
|
||||
{
|
||||
return addr->s6_addr32[0] == 0 &&
|
||||
addr->s6_addr32[1] == 0 &&
|
||||
addr->s6_addr32[2] == 0 &&
|
||||
ntohl(addr->s6_addr32[3]) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv6 address is a multicast address.
|
||||
*
|
||||
* @param addr IPv6 address
|
||||
*
|
||||
* @return True if address is multicast address, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv6_addr_mcast(const struct in6_addr *addr)
|
||||
{
|
||||
return addr->s6_addr[0] == 0xFF;
|
||||
}
|
||||
|
||||
struct net_if;
|
||||
|
||||
extern struct net_if_addr *net_if_ipv6_addr_lookup(const struct in6_addr *addr,
|
||||
struct net_if **iface);
|
||||
|
||||
/**
|
||||
* @brief Check if IPv6 address is found in one of the network interfaces.
|
||||
*
|
||||
* @param addr IPv6 address
|
||||
*
|
||||
* @return True if address was found, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_my_ipv6_addr(struct in6_addr *addr)
|
||||
{
|
||||
return net_if_ipv6_addr_lookup(addr, NULL) != NULL;
|
||||
}
|
||||
|
||||
extern struct net_if_mcast_addr *net_if_ipv6_maddr_lookup(const struct in6_addr *addr,
|
||||
struct net_if **iface);
|
||||
|
||||
/**
|
||||
* @brief Check if IPv6 multicast address is found in one of the
|
||||
* network interfaces.
|
||||
*
|
||||
* @param maddr Multicast IPv6 address
|
||||
*
|
||||
* @return True if address was found, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_my_ipv6_maddr(struct in6_addr *maddr)
|
||||
{
|
||||
return net_if_ipv6_maddr_lookup(maddr, NULL) != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if two IPv6 addresses are same when compared after prefix mask.
|
||||
*
|
||||
* @param addr1 First IPv6 address.
|
||||
* @param addr2 Second IPv6 address.
|
||||
* @param length Prefix length (max length is 128).
|
||||
*
|
||||
* @return True if addresses are the same, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv6_prefix(const uint8_t *addr1,
|
||||
const uint8_t *addr2,
|
||||
uint8_t length)
|
||||
{
|
||||
uint8_t bits = 128 - length;
|
||||
uint8_t bytes = bits / 8;
|
||||
uint8_t remain = bits % 8;
|
||||
|
||||
if (length > 128) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(addr1, addr2, 16 - bytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((addr1[16 - bytes] & ((8 - remain) << 8))
|
||||
==
|
||||
(addr2[16 - bytes] & ((8 - remain) << 8)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv4 address is a loopback address (127.0.0.0/8).
|
||||
*
|
||||
* @param addr IPv4 address
|
||||
*
|
||||
* @return True if address is a loopback address, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv4_addr_loopback(struct in_addr *addr)
|
||||
{
|
||||
return addr->s4_addr[0] == 127;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv4 address is unspecified (all bits zero)
|
||||
*
|
||||
* @param addr IPv4 address.
|
||||
*
|
||||
* @return True if the address is unspecified, false otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv4_addr_unspecified(const struct in_addr *addr)
|
||||
{
|
||||
return addr->s_addr[0] == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv4 address is a multicast address.
|
||||
*
|
||||
* @param addr IPv4 address
|
||||
*
|
||||
* @return True if address is multicast address, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv4_addr_mcast(const struct in_addr *addr)
|
||||
{
|
||||
return (addr->s_addr[0] & 0xE0000000) == 0xE0000000;
|
||||
}
|
||||
|
||||
extern struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
|
||||
struct net_if **iface);
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv4 address is assigned to any network interface
|
||||
* in the system.
|
||||
*
|
||||
* @param addr A valid pointer on an IPv4 address
|
||||
*
|
||||
* @return True if IPv4 address is found in one of the network interfaces,
|
||||
* False otherwise.
|
||||
*/
|
||||
static inline bool net_is_my_ipv4_addr(const struct in_addr *addr)
|
||||
{
|
||||
return net_if_ipv4_addr_lookup(addr, NULL) != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @def net_ipaddr_copy
|
||||
* @brief Copy an IPv4 or IPv6 address
|
||||
*
|
||||
* @param dest Destination IP address.
|
||||
* @param src Source IP address.
|
||||
*
|
||||
* @return Destination address.
|
||||
*/
|
||||
#define net_ipaddr_copy(dest, src) \
|
||||
UNALIGNED_PUT(UNALIGNED_GET(src), dest)
|
||||
|
||||
/**
|
||||
* @brief Compare two IPv4 addresses
|
||||
*
|
||||
* @param addr1 Pointer to IPv4 address.
|
||||
* @param addr2 Pointer to IPv4 address.
|
||||
*
|
||||
* @return True if the addresses are the same, false otherwise.
|
||||
*/
|
||||
static inline bool net_ipv4_addr_cmp(const struct in_addr *addr1,
|
||||
const struct in_addr *addr2)
|
||||
{
|
||||
return addr1->s_addr[0] == addr2->s_addr[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare two IPv6 addresses
|
||||
*
|
||||
* @param addr1 Pointer to IPv6 address.
|
||||
* @param addr2 Pointer to IPv6 address.
|
||||
*
|
||||
* @return True if the addresses are the same, false otherwise.
|
||||
*/
|
||||
static inline bool net_ipv6_addr_cmp(const struct in6_addr *addr1,
|
||||
const struct in6_addr *addr2)
|
||||
{
|
||||
return !memcmp(addr1, addr2, sizeof(struct in6_addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the given IPv6 address is a link local address.
|
||||
*
|
||||
* @param addr A valid pointer on an IPv6 address
|
||||
*
|
||||
* @return True if it is, false otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv6_ll_addr(const struct in6_addr *addr)
|
||||
{
|
||||
return ((addr->s6_addr[0]) == 0xFE) &&
|
||||
((addr->s6_addr[1]) == 0x80);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return pointer to any (all bits zeros) IPv6 address.
|
||||
*
|
||||
* @return Any IPv6 address.
|
||||
*/
|
||||
const struct in6_addr *net_ipv6_unspecified_address(void);
|
||||
|
||||
/**
|
||||
* @brief Return pointer to any (all bits zeros) IPv4 address.
|
||||
*
|
||||
* @return Any IPv4 address.
|
||||
*/
|
||||
const struct in_addr *net_ipv4_unspecified_address(void);
|
||||
|
||||
/**
|
||||
* @brief Return pointer to broadcast (all bits ones) IPv4 address.
|
||||
*
|
||||
* @return Broadcast IPv4 address.
|
||||
*/
|
||||
const struct in_addr *net_ipv4_broadcast_address(void);
|
||||
|
||||
struct net_if;
|
||||
extern bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
|
||||
struct in_addr *addr);
|
||||
|
||||
/**
|
||||
* @brief Check if the given address belongs to same subnet that
|
||||
* has been configured for the interface.
|
||||
*
|
||||
* @param iface A valid pointer on an interface
|
||||
* @param addr pointer on an address
|
||||
*
|
||||
* @return True if address is in same subnet, false otherwise.
|
||||
*/
|
||||
static inline bool net_ipv4_addr_mask_cmp(struct net_if *iface,
|
||||
struct in_addr *addr)
|
||||
{
|
||||
return net_if_ipv4_addr_mask_cmp(iface, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv6 address is unspecified (all bits zero)
|
||||
*
|
||||
* @param addr IPv6 address.
|
||||
*
|
||||
* @return True if the address is unspecified, false otherwise.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv6 address is solicited node multicast address
|
||||
* FF02:0:0:0:0:1:FFXX:XXXX defined in RFC 3513
|
||||
*
|
||||
* @param addr IPv6 address.
|
||||
*
|
||||
* @return True if the address is solicited node address, false otherwise.
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv6 address is a global multicast address (FFxE::/16).
|
||||
*
|
||||
* @param addr IPv6 address.
|
||||
*
|
||||
* @return True if the address is global multicast address, false otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv6_addr_mcast_global(const struct in6_addr *addr)
|
||||
{
|
||||
return addr->s6_addr[0] == 0xff &&
|
||||
(addr->s6_addr[1] & 0x0e) == 0x0e;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create solicited node IPv6 multicast address
|
||||
* FF02:0:0:0:0:1:FFXX:XXXX defined in RFC 3513
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
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;
|
||||
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];
|
||||
}
|
||||
|
||||
/** @brief Construct an IPv6 address from eight 16-bit words.
|
||||
*
|
||||
* @param addr IPv6 address
|
||||
* @param addr0 16-bit word which is part of the address
|
||||
* @param addr1 16-bit word which is part of the address
|
||||
* @param addr2 16-bit word which is part of the address
|
||||
* @param addr3 16-bit word which is part of the address
|
||||
* @param addr4 16-bit word which is part of the address
|
||||
* @param addr5 16-bit word which is part of the address
|
||||
* @param addr6 16-bit word which is part of the address
|
||||
* @param addr7 16-bit word which is part of the address
|
||||
*/
|
||||
static inline void net_ipv6_addr_create(struct in6_addr *addr,
|
||||
uint16_t addr0, uint16_t addr1,
|
||||
uint16_t addr2, uint16_t addr3,
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create link local allnodes multicast IPv6 address
|
||||
*
|
||||
* @param addr IPv6 address
|
||||
*/
|
||||
static inline void net_ipv6_addr_create_ll_allnodes_mcast(struct in6_addr *addr)
|
||||
{
|
||||
net_ipv6_addr_create(addr, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create IPv6 address interface identifier
|
||||
*
|
||||
* @param addr IPv6 address
|
||||
* @param lladdr Link local address
|
||||
*/
|
||||
static inline void net_ipv6_addr_create_iid(struct in6_addr *addr,
|
||||
struct net_linkaddr *lladdr)
|
||||
{
|
||||
addr->s6_addr[0] = 0xfe;
|
||||
addr->s6_addr[1] = 0x80;
|
||||
addr->s6_addr16[1] = 0;
|
||||
addr->s6_addr32[1] = 0;
|
||||
|
||||
switch (lladdr->len) {
|
||||
case 2:
|
||||
addr->s6_addr32[2] = 0;
|
||||
addr->s6_addr[11] = 0xff;
|
||||
addr->s6_addr[12] = 0xfe;
|
||||
addr->s6_addr[13] = 0;
|
||||
addr->s6_addr[14] = lladdr->addr[0];
|
||||
addr->s6_addr[15] = lladdr->addr[1];
|
||||
addr->s6_addr[8] ^= 0x02;
|
||||
break;
|
||||
case 6:
|
||||
memcpy(&addr->s6_addr[8], lladdr->addr, 3);
|
||||
addr->s6_addr[11] = 0xff;
|
||||
addr->s6_addr[12] = 0xfe;
|
||||
memcpy(&addr->s6_addr[13], lladdr->addr + 3, 3);
|
||||
addr->s6_addr[8] ^= 0x02;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
memcpy(&addr->s6_addr[8], lladdr->addr, lladdr->len);
|
||||
addr->s6_addr[8] ^= 0x02;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if given address is based on link layer address
|
||||
*
|
||||
* @return True if it is, False otherwise
|
||||
*/
|
||||
static inline bool net_ipv6_addr_based_on_ll(const struct in6_addr *addr,
|
||||
const struct net_linkaddr *lladdr)
|
||||
{
|
||||
switch (lladdr->len) {
|
||||
case 2:
|
||||
if (!memcmp(&addr->s6_addr[14], lladdr->addr, lladdr->len) &&
|
||||
(addr->s6_addr[8] ^ 0x02) == lladdr->addr[0] &&
|
||||
addr->s6_addr[11] == 0xff &&
|
||||
addr->s6_addr[12] == 0xfe) {
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case 6:
|
||||
if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1], 2) &&
|
||||
!memcmp(&addr->s6_addr[13], &lladdr->addr[3], 3) &&
|
||||
addr->s6_addr[11] == 0xff &&
|
||||
addr->s6_addr[12] == 0xfe &&
|
||||
(addr->s6_addr[8] ^ 0x02) == lladdr->addr[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case 8:
|
||||
if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1],
|
||||
lladdr->len - 1) &&
|
||||
(addr->s6_addr[8] ^ 0x02) == lladdr->addr[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sockaddr_in6 from sockaddr. This is a helper so that
|
||||
* the code calling this function can be made shorter.
|
||||
*
|
||||
* @param addr Socket address
|
||||
*
|
||||
* @return Pointer to IPv6 socket address
|
||||
*/
|
||||
static inline struct sockaddr_in6 *net_sin6(const struct sockaddr *addr)
|
||||
{
|
||||
return (struct sockaddr_in6 *)addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sockaddr_in from sockaddr. This is a helper so that
|
||||
* the code calling this function can be made shorter.
|
||||
*
|
||||
* @param addr Socket address
|
||||
*
|
||||
* @return Pointer to IPv4 socket address
|
||||
*/
|
||||
static inline struct sockaddr_in *net_sin(const struct sockaddr *addr)
|
||||
{
|
||||
return (struct sockaddr_in *)addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sockaddr_in6_ptr from sockaddr_ptr. This is a helper so that
|
||||
* the code calling this function can be made shorter.
|
||||
*
|
||||
* @param addr Socket address
|
||||
*
|
||||
* @return Pointer to IPv6 socket address
|
||||
*/
|
||||
static inline
|
||||
struct sockaddr_in6_ptr *net_sin6_ptr(const struct sockaddr_ptr *addr)
|
||||
{
|
||||
return (struct sockaddr_in6_ptr *)addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sockaddr_in_ptr from sockaddr_ptr. This is a helper so that
|
||||
* the code calling this function can be made shorter.
|
||||
*
|
||||
* @param addr Socket address
|
||||
*
|
||||
* @return Pointer to IPv4 socket address
|
||||
*/
|
||||
static inline
|
||||
struct sockaddr_in_ptr *net_sin_ptr(const struct sockaddr_ptr *addr)
|
||||
{
|
||||
return (struct sockaddr_in_ptr *)addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a string to IP address.
|
||||
*
|
||||
* @param family IP address family (AF_INET or AF_INET6)
|
||||
* @param src IP address in a null terminated string
|
||||
* @param dst Pointer to struct in_addr if family is AF_INET or
|
||||
* pointer to struct in6_addr if family is AF_INET6
|
||||
*
|
||||
* @note This function doesn't do precise error checking,
|
||||
* do not use for untrusted strings.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_addr_pton(sa_family_t family, const char *src,
|
||||
struct sockaddr *dst);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NET_IP_H */
|
||||
|
|
|
@ -14,6 +14,106 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_YAIP
|
||||
#include <net/yaip/net_l2.h>
|
||||
/**
|
||||
* @file
|
||||
* @brief Public API for network L2 interface
|
||||
*/
|
||||
|
||||
#ifndef __NET_L2_H__
|
||||
#define __NET_L2_H__
|
||||
|
||||
#include <net/buf.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct net_if;
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
struct net_l2_offload_ip;
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
|
||||
struct net_l2 {
|
||||
/**
|
||||
* This function is used by net core to get iface's L2 layer parsing
|
||||
* what's relevant to itself.
|
||||
*/
|
||||
enum net_verdict (*recv)(struct net_if *iface, struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* This function is used by net core to push a buffer to lower layer
|
||||
* (interface's L2), which in turn might work on the buffer relevantly.
|
||||
* (adding proper header etc...)
|
||||
*/
|
||||
enum net_verdict (*send)(struct net_if *iface, struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* This function is used to get the amount of bytes the net core should
|
||||
* reserve as headroom in a net buffer. Such space is relevant to L2
|
||||
* layer only.
|
||||
*/
|
||||
uint16_t (*reserve)(struct net_if *iface, void *data);
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
struct net_l2_offload_ip *offload_ip;
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
};
|
||||
|
||||
#define NET_L2_GET_NAME(_name) (__net_l2_##_name)
|
||||
#define NET_L2_DECLARE_PUBLIC(_name) \
|
||||
extern const struct net_l2 const NET_L2_GET_NAME(_name)
|
||||
#define NET_L2_GET_CTX_TYPE(_name) _name##_CTX_TYPE
|
||||
|
||||
extern struct net_l2 __net_l2_start[];
|
||||
|
||||
#ifdef CONFIG_NET_L2_DUMMY
|
||||
#define DUMMY_L2 DUMMY
|
||||
#define DUMMY_L2_CTX_TYPE void*
|
||||
NET_L2_DECLARE_PUBLIC(DUMMY_L2);
|
||||
#endif /* CONFIG_NET_L2_DUMMY */
|
||||
|
||||
#ifdef CONFIG_NET_L2_ETHERNET
|
||||
#define ETHERNET_L2 ETHERNET
|
||||
#define ETHERNET_L2_CTX_TYPE void*
|
||||
NET_L2_DECLARE_PUBLIC(ETHERNET_L2);
|
||||
#endif /* CONFIG_NET_L2_ETHERNET */
|
||||
|
||||
#ifdef CONFIG_NET_L2_IEEE802154
|
||||
#include <net/ieee802154.h>
|
||||
#define IEEE802154_L2 IEEE802154
|
||||
#define IEEE802154_L2_CTX_TYPE struct ieee802154_context
|
||||
NET_L2_DECLARE_PUBLIC(IEEE802154_L2);
|
||||
#endif /* CONFIG_NET_L2_IEEE802154 */
|
||||
|
||||
#ifdef CONFIG_NET_L2_BLUETOOTH
|
||||
#define BLUETOOTH_L2 BLUETOOTH
|
||||
#define BLUETOOTH_L2_CTX_TYPE void*
|
||||
#endif /* CONFIG_NET_L2_BLUETOOTH */
|
||||
|
||||
#ifdef CONFIG_NET_L2_OFFLOAD_IP
|
||||
#define OFFLOAD_IP_L2 OFFLOAD_IP
|
||||
#define OFFLOAD_IP_L2_CTX_TYPE void*
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
|
||||
extern struct net_l2 __net_l2_end[];
|
||||
|
||||
#define NET_L2_INIT(_name, _recv_fn, _send_fn, _reserve_fn) \
|
||||
const struct net_l2 const (NET_L2_GET_NAME(_name)) __used \
|
||||
__attribute__((__section__(".net_l2.init"))) = { \
|
||||
.recv = (_recv_fn), \
|
||||
.send = (_send_fn), \
|
||||
.reserve = (_reserve_fn), \
|
||||
}
|
||||
|
||||
#define NET_L2_GET_DATA(name, sfx) (__net_l2_data_##name##sfx)
|
||||
|
||||
#define NET_L2_DATA_INIT(name, sfx, ctx_type) \
|
||||
static ctx_type NET_L2_GET_DATA(name, sfx) __used \
|
||||
__attribute__((__section__(".net_l2.data")));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NET_L2_H__ */
|
||||
|
|
|
@ -14,6 +14,169 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_YAIP
|
||||
#include <net/yaip/net_mgmt.h>
|
||||
#endif
|
||||
/**
|
||||
* @file
|
||||
* @brief Network Management API public header
|
||||
*/
|
||||
|
||||
#ifndef __NET_MGMT_H__
|
||||
#define __NET_MGMT_H__
|
||||
|
||||
#include <misc/__assert.h>
|
||||
#include <net/net_core.h>
|
||||
|
||||
struct net_if;
|
||||
|
||||
/**
|
||||
* @brief NET MGMT event mask basics, normalizing parts of bit fields
|
||||
*/
|
||||
#define NET_MGMT_EVENT_MASK 0x80000000
|
||||
#define NET_MGMT_ON_IFACE_MASK 0x40000000
|
||||
#define NET_MGMT_LAYER_MASK 0x30000000
|
||||
#define NET_MGMT_LAYER_CODE_MASK 0x0FFF0000
|
||||
#define NET_MGMT_COMMAND_MASK 0x0000FFFF
|
||||
|
||||
#define NET_MGMT_EVENT_BIT BIT(31)
|
||||
#define NET_MGMT_IFACE_BIT BIT(30)
|
||||
|
||||
#define NET_MGMT_LAYER(_layer) (_layer << 28)
|
||||
#define NET_MGMT_LAYER_CODE(_code) (_code << 16)
|
||||
|
||||
#define NET_MGMT_EVENT(mgmt_request) \
|
||||
(mgmt_request & NET_MGMT_EVENT_MASK)
|
||||
|
||||
#define NET_MGMT_ON_IFACE(mgmt_request) \
|
||||
(mgmt_request & NET_MGMT_ON_IFACE_MASK)
|
||||
|
||||
#define NET_MGMT_GET_LAYER(mgmt_request) \
|
||||
(mgmt_request & NET_MGMT_LAYER_MASK)
|
||||
|
||||
#define NET_MGMT_GET_LAYER_CODE(mgmt_request) \
|
||||
(mgmt_request & NET_MGMT_LAYER_CODE_MASK)
|
||||
|
||||
#define NET_MGMT_GET_COMMAND(mgmt_request) \
|
||||
(mgmt_request & NET_MGMT_COMMAND_MASK)
|
||||
|
||||
|
||||
/* Useful generic definitions */
|
||||
#define NET_MGMT_LAYER_L1 1
|
||||
#define NET_MGMT_LAYER_L2 2
|
||||
#define NET_MGMT_LAYER_L3 3
|
||||
|
||||
#include <net/net_event.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Signature which all Net MGMT request handler need to follow
|
||||
* @param mgmt_request The exact request value the handler is being called
|
||||
* through
|
||||
* @param iface A valid pointer on struct net_if if the request is meant
|
||||
* to be tight to a network interface. NULL otherwise.
|
||||
* @param data A valid pointer on a data understood by the handler.
|
||||
* NULL otherwise.
|
||||
* @param len Length in byte of the memory pointed by data.
|
||||
*/
|
||||
typedef int (*net_mgmt_request_handler_t)(uint32_t mgmt_request,
|
||||
struct net_if *iface,
|
||||
void *data, size_t len);
|
||||
|
||||
#define net_mgmt(_mgmt_request, _iface, _data, _len) \
|
||||
net_mgmt_##_mgmt_request(_mgmt_request, _iface, _data, _len)
|
||||
|
||||
#define NET_MGMT_DEFINE_REQUEST_HANDLER(_mgmt_request) \
|
||||
extern int net_mgmt_##_mgmt_request(uint32_t mgmt_request, \
|
||||
struct net_if *iface, \
|
||||
void *data, size_t len)
|
||||
|
||||
#define NET_MGMT_REGISTER_REQUEST_HANDLER(_mgmt_request, _func) \
|
||||
FUNC_ALIAS(_func, net_mgmt_##_mgmt_request, int)
|
||||
|
||||
struct net_mgmt_event_callback;
|
||||
|
||||
/**
|
||||
* @typedef net_mgmt_event_handler_t
|
||||
* @brief Define the user's callback handler function signature
|
||||
* @param "struct net_mgmt_event_callback *cb"
|
||||
* Original struct net_mgmt_event_callback owning this handler.
|
||||
* @param "uint32_t mgmt_event" The network event being notified.
|
||||
* @param "struct net_if *iface" A pointer on a struct net_if to which the
|
||||
* the event belongs to, if it's an event on an iface. NULL otherwise.
|
||||
*/
|
||||
typedef void (*net_mgmt_event_handler_t)(struct net_mgmt_event_callback *cb,
|
||||
uint32_t mgmt_event,
|
||||
struct net_if *iface);
|
||||
|
||||
/**
|
||||
* @brief Network Management event callback structure
|
||||
* Used to register a callback into the network management event part, in order
|
||||
* to let the owner of this struct to get network event notification based on
|
||||
* given event mask.
|
||||
*/
|
||||
struct net_mgmt_event_callback {
|
||||
/** Meant to be used internally, to insert the callback into a list.
|
||||
* So nobody should mess with it.
|
||||
*/
|
||||
sys_snode_t node;
|
||||
|
||||
/** Actual callback function being used to notify the owner
|
||||
*/
|
||||
net_mgmt_event_handler_t handler;
|
||||
|
||||
/** A mask of network events on which the above handler should be
|
||||
* called in case those events come. Such mask can be modified
|
||||
* whenever necessary by the owner, and thus will affect the handler
|
||||
* being called or not.
|
||||
*/
|
||||
uint32_t event_mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Helper to initialize a struct net_mgmt_event_callback properly
|
||||
* @param cb A valid application's callback structure pointer.
|
||||
* @param handler A valid handler function pointer.
|
||||
* @param mgmt_event_mask A mask of relevant events for the handler
|
||||
*/
|
||||
static inline
|
||||
void net_mgmt_init_event_callback(struct net_mgmt_event_callback *cb,
|
||||
net_mgmt_event_handler_t handler,
|
||||
uint32_t mgmt_event_mask)
|
||||
{
|
||||
__ASSERT(cb, "Callback pointer should not be NULL");
|
||||
__ASSERT(handler, "Handler pointer should not be NULL");
|
||||
|
||||
cb->handler = handler;
|
||||
cb->event_mask = mgmt_event_mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Add a user callback
|
||||
* @param cb A valid pointer on user's callback to add.
|
||||
*/
|
||||
void net_mgmt_add_event_callback(struct net_mgmt_event_callback *cb);
|
||||
|
||||
/**
|
||||
* @brief Delete a user callback
|
||||
* @param cb A valid pointer on user's callback to delete.
|
||||
*/
|
||||
void net_mgmt_del_event_callback(struct net_mgmt_event_callback *cb);
|
||||
|
||||
#ifdef CONFIG_NET_MGMT_EVENT
|
||||
/**
|
||||
* @brief Used by the system to notify an event.
|
||||
* @param mgmt_event The actual network event code to notify
|
||||
* @param iface a valid pointer on a struct net_if if only the event is
|
||||
* based on an iface. NULL otherwise.
|
||||
*/
|
||||
void net_mgmt_event_notify(uint32_t mgmt_event, struct net_if *iface);
|
||||
|
||||
/**
|
||||
* @brief Used by the core of the network stack to initialize the network
|
||||
* event processing.
|
||||
*/
|
||||
void net_mgmt_event_init(void);
|
||||
#else
|
||||
#define net_mgmt_event_notify(...)
|
||||
#define net_mgmt_event_init(...)
|
||||
#endif /* CONFIG_NET_MGMT_EVENT */
|
||||
|
||||
#endif /* __NET_MGMT_H__ */
|
||||
|
|
|
@ -14,6 +14,436 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_NET_YAIP)
|
||||
#include <net/yaip/offload_ip.h>
|
||||
/**
|
||||
* @file
|
||||
* @brief Public API for offloading IP stack
|
||||
*/
|
||||
|
||||
#ifndef __OFFLOAD_IP_H__
|
||||
#define __OFFLOAD_IP_H__
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
|
||||
#include <net/buf.h>
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_context.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** For return parameters and return values of the elements in this
|
||||
* struct, see similarly named functions in net_context.h
|
||||
*/
|
||||
struct net_l2_offload_ip {
|
||||
/**
|
||||
* This function is called when the socket is to be opened.
|
||||
*/
|
||||
int (*get)(sa_family_t family,
|
||||
enum net_sock_type type,
|
||||
enum net_ip_protocol ip_proto,
|
||||
struct net_context **context);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to bind to local IP address.
|
||||
*/
|
||||
int (*bind)(struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to mark the socket
|
||||
* to be a listening one.
|
||||
*/
|
||||
int (*listen)(struct net_context *context, int backlog);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to create a connection
|
||||
* to a peer host.
|
||||
*/
|
||||
int (*connect)(struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
net_context_connect_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to accept a connection
|
||||
* being established.
|
||||
*/
|
||||
int (*accept)(struct net_context *context,
|
||||
net_context_accept_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to send data to peer host.
|
||||
*/
|
||||
int (*send)(struct net_buf *buf,
|
||||
net_context_send_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *token,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to send data to peer host.
|
||||
*/
|
||||
int (*sendto)(struct net_buf *buf,
|
||||
const struct sockaddr *dst_addr,
|
||||
socklen_t addrlen,
|
||||
net_context_send_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *token,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to receive data from peer
|
||||
* host.
|
||||
*/
|
||||
int (*recv)(struct net_context *context,
|
||||
net_context_recv_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to close the socket.
|
||||
*/
|
||||
int (*put)(struct net_context *context);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get a network socket/context from the offloaded IP stack.
|
||||
*
|
||||
* @details Network socket is used to define the connection
|
||||
* 5-tuple (protocol, remote address, remote port, source
|
||||
* address and source port). This is similar as BSD socket()
|
||||
* function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param family IP address family (AF_INET or AF_INET6)
|
||||
* @param type Type of the socket, SOCK_STREAM or SOCK_DGRAM
|
||||
* @param ip_proto IP protocol, IPPROTO_UDP or IPPROTO_TCP
|
||||
* @param context The allocated context is returned to the caller.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_get(struct net_if *iface,
|
||||
sa_family_t family,
|
||||
enum net_sock_type type,
|
||||
enum net_ip_protocol ip_proto,
|
||||
struct net_context **context)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->get);
|
||||
|
||||
return iface->l2->offload_ip->get(family, type, ip_proto, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assign a socket a local address.
|
||||
*
|
||||
* @details This is similar as BSD bind() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param context The context to be assigned.
|
||||
* @param addr Address to assigned.
|
||||
* @param addrlen Length of the address.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_bind(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->bind);
|
||||
|
||||
return iface->l2->offload_ip->bind(context, addr, addrlen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Mark the context as a listening one.
|
||||
*
|
||||
* @details This is similar as BSD listen() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param context The context to use.
|
||||
* @param backlog The size of the pending connections backlog.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_listen(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
int backlog)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->listen);
|
||||
|
||||
return iface->l2->offload_ip->listen(context, backlog);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a network connection.
|
||||
*
|
||||
* @details The net_context_connect function creates a network
|
||||
* connection to the host specified by addr. After the
|
||||
* connection is established, the user supplied callback (cb)
|
||||
* is executed. cb is called even if the timeout was set to
|
||||
* K_FOREVER. cb is not called if the timeout expires.
|
||||
* For datagram sockets (SOCK_DGRAM), this function only sets
|
||||
* the peer address.
|
||||
* This function is similar to the BSD connect() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param context The network context.
|
||||
* @param addr The peer address to connect to.
|
||||
* @param addrlen Peer address length.
|
||||
* @param cb Callback function. Set to NULL if not required.
|
||||
* @param timeout The timeout value for the connection. Possible values:
|
||||
* * K_NO_WAIT: this function will return immediately,
|
||||
* * K_FOREVER: this function will block until the
|
||||
* connection is established,
|
||||
* * >0: this function will wait the specified ms.
|
||||
* @param user_data Data passed to the callback function.
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return -EINVAL if an invalid parameter is passed as an argument.
|
||||
* @return -ENOTSUP if the operation is not supported or implemented.
|
||||
*/
|
||||
static inline int net_l2_offload_ip_connect(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
net_context_connect_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->connect);
|
||||
|
||||
return iface->l2->offload_ip->connect(context, addr, addrlen, cb,
|
||||
timeout, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Accept a network connection attempt.
|
||||
*
|
||||
* @details Accept a connection being established. This function
|
||||
* will return immediately if the timeout is set to K_NO_WAIT.
|
||||
* In this case the context will call the supplied callback when ever
|
||||
* there is a connection established to this context. This is "a register
|
||||
* handler and forget" type of call (async).
|
||||
* If the timeout is set to K_FOREVER, the function will wait
|
||||
* until the connection is established. Timeout value > 0, will wait as
|
||||
* many ms.
|
||||
* After the connection is established a caller supplied callback is called.
|
||||
* The callback is called even if timeout was set to K_FOREVER, the
|
||||
* callback is called before this function will return in this case.
|
||||
* The callback is not called if the timeout expires.
|
||||
* This is similar as BSD accept() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param context The context to use.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Timeout for the connection. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_accept(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
net_context_accept_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->accept);
|
||||
|
||||
return iface->l2->offload_ip->accept(context, cb, timeout, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a network buffer to a peer.
|
||||
*
|
||||
* @details This function can be used to send network data to a peer
|
||||
* connection. This function will return immediately if the timeout
|
||||
* is set to K_NO_WAIT. If the timeout is set to K_FOREVER, the function
|
||||
* will wait until the network buffer is sent. Timeout value > 0 will
|
||||
* wait as many ms. After the network buffer is sent,
|
||||
* a caller supplied callback is called. The callback is called even
|
||||
* if timeout was set to K_FOREVER, the callback is called
|
||||
* before this function will return in this case. The callback is not
|
||||
* called if the timeout expires. For context of type SOCK_DGRAM,
|
||||
* the destination address must have been set by the call to
|
||||
* net_context_connect().
|
||||
* This is similar as BSD send() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param buf The network buffer to send.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Timeout for the connection. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param token Caller specified value that is passed as is to callback.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_send(struct net_if *iface,
|
||||
struct net_buf *buf,
|
||||
net_context_send_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *token,
|
||||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->send);
|
||||
|
||||
return iface->l2->offload_ip->send(buf, cb, timeout, token, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a network buffer to a peer specified by address.
|
||||
*
|
||||
* @details This function can be used to send network data to a peer
|
||||
* specified by address. This variant can only be used for datagram
|
||||
* connections of type SOCK_DGRAM. This function will return immediately
|
||||
* if the timeout is set to K_NO_WAIT. If the timeout is set to K_FOREVER,
|
||||
* the function will wait until the network buffer is sent. Timeout
|
||||
* value > 0 will wait as many ms. After the network buffer
|
||||
* is sent, a caller supplied callback is called. The callback is called
|
||||
* even if timeout was set to K_FOREVER, the callback is called
|
||||
* before this function will return. The callback is not called if the
|
||||
* timeout expires.
|
||||
* This is similar as BSD sendto() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param buf The network buffer to send.
|
||||
* @param dst_addr Destination address. This will override the address
|
||||
* already set in network buffer.
|
||||
* @param addrlen Length of the address.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Timeout for the connection. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param token Caller specified value that is passed as is to callback.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_sendto(struct net_if *iface,
|
||||
struct net_buf *buf,
|
||||
const struct sockaddr *dst_addr,
|
||||
socklen_t addrlen,
|
||||
net_context_send_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *token,
|
||||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->sendto);
|
||||
|
||||
return iface->l2->offload_ip->sendto(buf, dst_addr, addrlen, cb,
|
||||
timeout, token, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive network data from a peer specified by context.
|
||||
*
|
||||
* @details This function can be used to register a callback function
|
||||
* that is called by the network stack when network data has been received
|
||||
* for this context. As this function registers a callback, then there
|
||||
* is no need to call this function multiple times if timeout is set to
|
||||
* K_NO_WAIT.
|
||||
* If callback function or user data changes, then the function can be called
|
||||
* multiple times to register new values.
|
||||
* This function will return immediately if the timeout is set to K_NO_WAIT.
|
||||
* If the timeout is set to K_FOREVER, the function will wait until the
|
||||
* network buffer is received. Timeout value > 0 will wait as many ms.
|
||||
* After the network buffer is received, a caller supplied callback is
|
||||
* called. The callback is called even if timeout was set to K_FOREVER,
|
||||
* the callback is called before this function will return in this case.
|
||||
* The callback is not called if the timeout expires. The timeout functionality
|
||||
* can be compiled out if synchronous behaviour is not needed. The sync call
|
||||
* logic requires some memory that can be saved if only async way of call is
|
||||
* used. If CONFIG_NET_CONTEXT_SYNC_RECV is not set, then the timeout parameter
|
||||
* value is ignored.
|
||||
* This is similar as BSD recv() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param context The network context to use.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Caller supplied timeout. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_recv(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
net_context_recv_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->recv);
|
||||
|
||||
return iface->l2->offload_ip->recv(context, cb, timeout, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free/close a network context.
|
||||
*
|
||||
* @details This releases the context. It is not possible to
|
||||
* send or receive data via this context after this call.
|
||||
* This is similar as BSD shutdown() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param context The context to be closed.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_put(struct net_if *iface,
|
||||
struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->put);
|
||||
|
||||
return iface->l2->offload_ip->put(context);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
|
||||
#endif /* __OFFLOAD_IP_H__ */
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/** @file
|
||||
* @brief Trickle timer library
|
||||
*
|
||||
* This implements Trickle timer as specified in RFC 6206
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
|
@ -14,6 +20,117 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_NET_YAIP)
|
||||
#include <net/yaip/trickle.h>
|
||||
#ifndef __TRICKLE_H
|
||||
#define __TRICKLE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <kernel.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct net_trickle;
|
||||
|
||||
typedef void (*net_trickle_cb_t)(struct net_trickle *trickle,
|
||||
bool do_suppress, void *user_data);
|
||||
|
||||
/*
|
||||
* The variable names are taken directly from RFC when applicable.
|
||||
* Note that the struct members should not be accessed directly but
|
||||
* only via the Trickle API.
|
||||
*/
|
||||
struct net_trickle {
|
||||
uint32_t Imin; /* Min interval size in ms */
|
||||
uint8_t Imax; /* Max number of doublings */
|
||||
uint8_t k; /* Redundancy constant */
|
||||
|
||||
uint32_t I; /* Current interval size */
|
||||
uint32_t Istart; /* Start of the interval in ms */
|
||||
uint8_t c; /* Consistency counter */
|
||||
|
||||
uint32_t Imax_abs; /* Max interval size in ms (not doublings)
|
||||
*/
|
||||
|
||||
struct k_delayed_work timer;
|
||||
net_trickle_cb_t cb; /* Callback to be called when timer expires */
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#define NET_TRICKLE_INFINITE_REDUNDANCY 0
|
||||
|
||||
/**
|
||||
* @brief Create a Trickle timer.
|
||||
*
|
||||
* @param trickle Pointer to Trickle struct.
|
||||
* @param Imin Imin configuration parameter in ms.
|
||||
* @param Imax Max number of doublings.
|
||||
* @param k Redundancy constant parameter. See RFC 6206 for details.
|
||||
*
|
||||
* @return Return 0 if ok and <0 if error.
|
||||
*/
|
||||
int net_trickle_create(struct net_trickle *trickle,
|
||||
uint32_t Imin,
|
||||
uint8_t Imax,
|
||||
uint8_t k);
|
||||
|
||||
/**
|
||||
* @brief Start a Trickle timer.
|
||||
*
|
||||
* @param trickle Pointer to Trickle struct.
|
||||
* @param cb User callback to call at time T within the current trickle
|
||||
* interval
|
||||
* @param user_data User pointer that is passed to callback.
|
||||
*
|
||||
* @return Return 0 if ok and <0 if error.
|
||||
*/
|
||||
int net_trickle_start(struct net_trickle *trickle,
|
||||
net_trickle_cb_t cb,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Stop a Trickle timer.
|
||||
*
|
||||
* @param trickle Pointer to Trickle struct.
|
||||
*
|
||||
* @return Return 0 if ok and <0 if error.
|
||||
*/
|
||||
int net_trickle_stop(struct net_trickle *trickle);
|
||||
|
||||
/**
|
||||
* @brief To be called by the protocol handler when it hears a consistent
|
||||
* network transmission.
|
||||
*
|
||||
* @param trickle Pointer to Trickle struct.
|
||||
*/
|
||||
void net_trickle_consistency(struct net_trickle *trickle);
|
||||
|
||||
/**
|
||||
* @brief To be called by the protocol handler when it hears an inconsistent
|
||||
* network transmission.
|
||||
*
|
||||
* @param trickle Pointer to Trickle struct.
|
||||
*/
|
||||
void net_trickle_inconsistency(struct net_trickle *trickle);
|
||||
|
||||
/**
|
||||
* @brief Check if the Trickle timer is running or not.
|
||||
*
|
||||
* @param trickle Pointer to Trickle struct.
|
||||
*
|
||||
* @return Return True if timer is running and False if not.
|
||||
*/
|
||||
static inline bool net_trickle_is_running(struct net_trickle *trickle)
|
||||
{
|
||||
NET_ASSERT(trickle);
|
||||
|
||||
return trickle->I != 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TRICKLE_H */
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
/** @file
|
||||
* @brief DHCPv4 Client Handler
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __DHCPV4_H
|
||||
#define __DHCPV4_H
|
||||
|
||||
#include <misc/slist.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** Current state of DHCPv4 client address negotiation */
|
||||
enum net_dhcpv4_state {
|
||||
NET_DHCPV4_INIT,
|
||||
NET_DHCPV4_DISCOVER,
|
||||
NET_DHCPV4_OFFER,
|
||||
NET_DHCPV4_REQUEST,
|
||||
NET_DHCPV4_RENEWAL,
|
||||
NET_DHCPV4_ACK,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Start DHCPv4 client
|
||||
*
|
||||
* @details Start DHCPv4 client on a given interface. DHCPv4 client
|
||||
* will start negotiation for IPv4 address. Once the negotiation is
|
||||
* success IPv4 address details will be added to interface.
|
||||
*
|
||||
* @param iface A valid pointer on an interface
|
||||
*/
|
||||
void net_dhcpv4_start(struct net_if *iface);
|
||||
|
||||
#endif /* __DHCPV4_H */
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief IEEE 802.15.4 L2 stack public header
|
||||
*/
|
||||
|
||||
#ifndef __IEEE802154_H__
|
||||
#define __IEEE802154_H__
|
||||
|
||||
#include <net/net_mgmt.h>
|
||||
|
||||
/* This not meant to be used by any code but 802.15.4 L2 stack */
|
||||
struct ieee802154_context {
|
||||
uint16_t pan_id;
|
||||
uint16_t channel;
|
||||
uint8_t sequence;
|
||||
struct k_sem ack_lock;
|
||||
uint8_t ack_received : 1;
|
||||
uint8_t ack_requested : 1;
|
||||
uint8_t _unused : 6;
|
||||
} __packed;
|
||||
|
||||
|
||||
/* Management part definitions */
|
||||
|
||||
#define _NET_IEEE802154_LAYER NET_MGMT_LAYER_L2
|
||||
#define _NET_IEEE802154_CODE 0x154
|
||||
#define _NET_IEEE802154_BASE (NET_MGMT_IFACE_BIT | \
|
||||
NET_MGMT_LAYER(_NET_IEEE802154_LAYER) |\
|
||||
NET_MGMT_LAYER_CODE(_NET_IEEE802154_CODE))
|
||||
|
||||
enum net_request_ieee802154_cmd {
|
||||
NET_REQUEST_IEEE802154_CMD_SET_ACK = 1,
|
||||
NET_REQUEST_IEEE802154_CMD_UNSET_ACK,
|
||||
};
|
||||
|
||||
|
||||
#define NET_REQUEST_IEEE802154_SET_ACK \
|
||||
(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_SET_ACK)
|
||||
|
||||
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_SET_ACK);
|
||||
|
||||
#define NET_REQUEST_IEEE802154_UNSET_ACK \
|
||||
(_NET_IEEE802154_BASE | NET_REQUEST_IEEE802154_CMD_UNSET_ACK)
|
||||
|
||||
NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_IEEE802154_UNSET_ACK);
|
||||
|
||||
#endif /* __IEEE802154_H__ */
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Public IEEE 802.15.4 Radio API
|
||||
*/
|
||||
|
||||
#ifndef __IEEE802154_RADIO_H__
|
||||
#define __IEEE802154_RADIO_H__
|
||||
|
||||
#include <device.h>
|
||||
#include <net/net_if.h>
|
||||
|
||||
struct ieee802154_radio_api {
|
||||
/**
|
||||
* Mandatory to get in first position.
|
||||
* A network device should indeed provide a pointer on such
|
||||
* net_if_api structure. So we make current structure pointer
|
||||
* that can be casted to a net_if_api structure pointer.
|
||||
*/
|
||||
struct net_if_api iface_api;
|
||||
|
||||
/** Clear Channel Assesment - Check channel's activity */
|
||||
int (*cca)(struct device *dev);
|
||||
|
||||
/** Set current channel */
|
||||
int (*set_channel)(struct device *dev, uint16_t channel);
|
||||
|
||||
/** Set current PAN id */
|
||||
int (*set_pan_id)(struct device *dev, uint16_t pan_id);
|
||||
|
||||
/** Set current device's short address */
|
||||
int (*set_short_addr)(struct device *dev, uint16_t short_addr);
|
||||
|
||||
/** Set current devices's full length address */
|
||||
int (*set_ieee_addr)(struct device *dev, const uint8_t *ieee_addr);
|
||||
|
||||
/** Set TX power level in dbm */
|
||||
int (*set_txpower)(struct device *dev, int16_t dbm);
|
||||
|
||||
/** Transmit a buffer */
|
||||
int (*tx)(struct device *dev, struct net_buf *buf);
|
||||
|
||||
/** Start the device */
|
||||
int (*start)(struct device *dev);
|
||||
|
||||
/** Stop the device */
|
||||
int (*stop)(struct device *dev);
|
||||
|
||||
/** Get latest Link Quality Information */
|
||||
uint8_t (*get_lqi)(struct device *dev);
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* @brief Radio driver sending function that hw drivers should use
|
||||
*
|
||||
* @details This function should be used to fill in struct net_if's send pointer.
|
||||
*
|
||||
* @param iface A valid pointer on a network interface to send from
|
||||
* @param buf A valid pointer on a buffer to send
|
||||
*
|
||||
* @return 0 on success, negative value otherwise
|
||||
*/
|
||||
extern int ieee802154_radio_send(struct net_if *iface,
|
||||
struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* @brief Radio driver ACK handling function that hw drivers should use
|
||||
*
|
||||
* @details ACK handling requires fast handling and thus such function
|
||||
* helps to hook direcly the hw drivers to the radio driver.
|
||||
*
|
||||
* @param iface A valid pointer on a network interface that received the packet
|
||||
* @param buf A valid pointer on a buffer to check
|
||||
*
|
||||
* @return NET_OK if it was handled, NET_CONTINUE otherwise
|
||||
*/
|
||||
extern enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface,
|
||||
struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* @brief Initialize L2 stack for a given interface
|
||||
*
|
||||
* @param iface A valid pointer on a network interface
|
||||
*/
|
||||
void ieee802154_init(struct net_if *iface);
|
||||
|
||||
#endif /* __IEEE802154_RADIO_H__ */
|
|
@ -1,931 +0,0 @@
|
|||
/** @file
|
||||
* @brief Network buffer API
|
||||
*
|
||||
* Network data is passed between different parts of the stack via
|
||||
* net_buf struct.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Data buffer API - used for all data to/from net */
|
||||
|
||||
#ifndef __NBUF_H
|
||||
#define __NBUF_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <net/buf.h>
|
||||
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_linkaddr.h>
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/net_context.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct net_context;
|
||||
|
||||
/** @cond ignore */
|
||||
enum net_nbuf_type {
|
||||
NET_NBUF_RX = 0,
|
||||
NET_NBUF_TX = 1,
|
||||
NET_NBUF_DATA = 2,
|
||||
};
|
||||
/** @endcond */
|
||||
|
||||
struct net_nbuf {
|
||||
/** Network connection context */
|
||||
struct net_context *context;
|
||||
|
||||
/** Network context token that user can set. This is passed
|
||||
* to user callback when data has been sent.
|
||||
*/
|
||||
void *token;
|
||||
|
||||
/** Network interface */
|
||||
struct net_if *iface;
|
||||
|
||||
/** @cond ignore */
|
||||
uint8_t *appdata; /* application data starts here */
|
||||
uint8_t *next_hdr; /* where is the next header */
|
||||
|
||||
/* Filled by layer 2 when network packet is received. */
|
||||
struct net_linkaddr lladdr_src;
|
||||
struct net_linkaddr lladdr_dst;
|
||||
|
||||
enum net_nbuf_type type;
|
||||
|
||||
uint16_t appdatalen;
|
||||
uint16_t reserve; /* length of the protocol headers */
|
||||
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 */
|
||||
uint8_t ext_len; /* length of extension headers */
|
||||
uint8_t ext_bitmap;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
uint8_t ext_opt_len; /* IPv6 ND option length */
|
||||
#endif
|
||||
/* @endcond */
|
||||
};
|
||||
|
||||
/** @cond ignore */
|
||||
|
||||
|
||||
/* The interface real ll address */
|
||||
static inline struct net_linkaddr *net_nbuf_ll_if(struct net_buf *buf)
|
||||
{
|
||||
return net_if_get_link_addr(
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->iface);
|
||||
}
|
||||
|
||||
static inline struct net_context *net_nbuf_context(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->context;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_context(struct net_buf *buf,
|
||||
struct net_context *ctx)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->context = ctx;
|
||||
}
|
||||
|
||||
static inline void *net_nbuf_token(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->token;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_token(struct net_buf *buf, void *token)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->token = token;
|
||||
}
|
||||
|
||||
static inline struct net_if *net_nbuf_iface(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->iface;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_iface(struct net_buf *buf, struct net_if *iface)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->iface = iface;
|
||||
}
|
||||
|
||||
static inline enum net_nbuf_type net_nbuf_type(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->type;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_type(struct net_buf *buf, uint8_t type)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->type = type;
|
||||
}
|
||||
|
||||
static inline uint8_t net_nbuf_family(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->family;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_family(struct net_buf *buf, uint8_t family)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->family = family;
|
||||
}
|
||||
|
||||
static inline uint8_t net_nbuf_ip_hdr_len(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *) net_buf_user_data(buf))->ip_hdr_len;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_ip_hdr_len(struct net_buf *buf, uint8_t len)
|
||||
{
|
||||
((struct net_nbuf *) net_buf_user_data(buf))->ip_hdr_len = len;
|
||||
}
|
||||
|
||||
static inline uint8_t net_nbuf_ext_len(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->ext_len;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_ext_len(struct net_buf *buf, uint8_t len)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->ext_len = len;
|
||||
}
|
||||
|
||||
static inline uint8_t net_nbuf_ext_bitmap(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->ext_bitmap;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_ext_bitmap(struct net_buf *buf, uint8_t bm)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->ext_bitmap = bm;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_add_ext_bitmap(struct net_buf *buf, uint8_t bm)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->ext_bitmap |= bm;
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_next_hdr(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->next_hdr;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_next_hdr(struct net_buf *buf, uint8_t *hdr)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->next_hdr = hdr;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static inline uint8_t net_nbuf_ext_opt_len(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->ext_opt_len;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_ext_opt_len(struct net_buf *buf, uint8_t len)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->ext_opt_len = len;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline uint16_t net_nbuf_get_len(struct net_buf *buf)
|
||||
{
|
||||
return buf->len;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_len(struct net_buf *buf, uint16_t len)
|
||||
{
|
||||
buf->len = len;
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_ip_data(struct net_buf *buf)
|
||||
{
|
||||
return buf->frags->data;
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_udp_data(struct net_buf *buf)
|
||||
{
|
||||
return &buf->frags->data[net_nbuf_ip_hdr_len(buf) +
|
||||
net_nbuf_ext_len(buf)];
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_tcp_data(struct net_buf *buf)
|
||||
{
|
||||
return &buf->frags->data[net_nbuf_ip_hdr_len(buf) +
|
||||
net_nbuf_ext_len(buf)];
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_icmp_data(struct net_buf *buf)
|
||||
{
|
||||
return &buf->frags->data[net_nbuf_ip_hdr_len(buf) +
|
||||
net_nbuf_ext_len(buf)];
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_appdata(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->appdata;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_appdata(struct net_buf *buf, uint8_t *data)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->appdata = data;
|
||||
}
|
||||
|
||||
static inline uint16_t net_nbuf_appdatalen(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->appdatalen;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_appdatalen(struct net_buf *buf, uint16_t len)
|
||||
{
|
||||
((struct net_nbuf *)net_buf_user_data(buf))->appdatalen = len;
|
||||
}
|
||||
|
||||
static inline uint16_t net_nbuf_reserve(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *)net_buf_user_data(buf))->reserve;
|
||||
}
|
||||
|
||||
static inline uint8_t net_nbuf_ll_reserve(struct net_buf *buf)
|
||||
{
|
||||
return ((struct net_nbuf *) net_buf_user_data(buf))->ll_reserve;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_set_ll_reserve(struct net_buf *buf, uint8_t len)
|
||||
{
|
||||
((struct net_nbuf *) net_buf_user_data(buf))->ll_reserve = len;
|
||||
}
|
||||
|
||||
static inline uint8_t *net_nbuf_ll(struct net_buf *buf)
|
||||
{
|
||||
return net_nbuf_ip_data(buf) - net_nbuf_ll_reserve(buf);
|
||||
}
|
||||
|
||||
static inline struct net_linkaddr *net_nbuf_ll_src(struct net_buf *buf)
|
||||
{
|
||||
return &((struct net_nbuf *)net_buf_user_data(buf))->lladdr_src;
|
||||
}
|
||||
|
||||
static inline struct net_linkaddr *net_nbuf_ll_dst(struct net_buf *buf)
|
||||
{
|
||||
return &((struct net_nbuf *)net_buf_user_data(buf))->lladdr_dst;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_ll_clear(struct net_buf *buf)
|
||||
{
|
||||
memset(net_nbuf_ll(buf), 0, net_nbuf_ll_reserve(buf));
|
||||
net_nbuf_ll_src(buf)->addr = NULL;
|
||||
net_nbuf_ll_src(buf)->len = 0;
|
||||
}
|
||||
|
||||
static inline void net_nbuf_ll_swap(struct net_buf *buf)
|
||||
{
|
||||
uint8_t *addr = net_nbuf_ll_src(buf)->addr;
|
||||
|
||||
net_nbuf_ll_src(buf)->addr = net_nbuf_ll_dst(buf)->addr;
|
||||
net_nbuf_ll_dst(buf)->addr = addr;
|
||||
}
|
||||
|
||||
#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))
|
||||
#define NET_UDP_BUF(buf) ((struct net_udp_hdr *)(net_nbuf_udp_data(buf)))
|
||||
#define NET_TCP_BUF(buf) ((struct net_tcp_hdr *)(net_nbuf_tcp_data(buf)))
|
||||
|
||||
static inline void net_nbuf_set_src_ipv6_addr(struct net_buf *buf)
|
||||
{
|
||||
net_if_ipv6_select_src_addr(net_context_get_iface(
|
||||
net_nbuf_context(buf)),
|
||||
&NET_IPV6_BUF(buf)->src);
|
||||
}
|
||||
|
||||
/* @endcond */
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
|
||||
/* Debug versions of the nbuf functions that are used when tracking
|
||||
* buffer usage.
|
||||
*/
|
||||
|
||||
struct net_buf *net_nbuf_get_rx_debug(struct net_context *context,
|
||||
const char *caller, int line);
|
||||
#define net_nbuf_get_rx(context) \
|
||||
net_nbuf_get_rx_debug(context, __func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_get_tx_debug(struct net_context *context,
|
||||
const char *caller, int line);
|
||||
#define net_nbuf_get_tx(context) \
|
||||
net_nbuf_get_tx_debug(context, __func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_get_data_debug(struct net_context *context,
|
||||
const char *caller, int line);
|
||||
#define net_nbuf_get_data(context) \
|
||||
net_nbuf_get_data_debug(context, __func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_get_reserve_rx_debug(uint16_t reserve_head,
|
||||
const char *caller, int line);
|
||||
#define net_nbuf_get_reserve_rx(res) \
|
||||
net_nbuf_get_reserve_rx_debug(res, __func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_get_reserve_tx_debug(uint16_t reserve_head,
|
||||
const char *caller, int line);
|
||||
#define net_nbuf_get_reserve_tx(res) \
|
||||
net_nbuf_get_reserve_tx_debug(res, __func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_get_reserve_data_debug(uint16_t reserve_head,
|
||||
const char *caller, int line);
|
||||
#define net_nbuf_get_reserve_data(res) \
|
||||
net_nbuf_get_reserve_data_debug(res, __func__, __LINE__)
|
||||
|
||||
void net_nbuf_unref_debug(struct net_buf *buf, const char *caller, int line);
|
||||
#define net_nbuf_unref(buf) net_nbuf_unref_debug(buf, __func__, __LINE__)
|
||||
|
||||
struct net_buf *net_nbuf_ref_debug(struct net_buf *buf, const char *caller,
|
||||
int line);
|
||||
#define net_nbuf_ref(buf) net_nbuf_ref_debug(buf, __func__, __LINE__)
|
||||
|
||||
/**
|
||||
* @brief Print fragment list and the fragment sizes
|
||||
*
|
||||
* @details Only available if debugging is activated.
|
||||
*
|
||||
* @param buf Network buffer fragment. This should be the first fragment (data)
|
||||
* in the fragment list.
|
||||
*/
|
||||
void net_nbuf_print_frags(struct net_buf *buf);
|
||||
|
||||
#else /* CONFIG_NET_DEBUG_NET_BUF */
|
||||
|
||||
#define net_nbuf_print_frags(...)
|
||||
|
||||
/**
|
||||
* @brief Get buffer from the RX buffers pool.
|
||||
*
|
||||
* @details Get network buffer from RX buffer pool. You must have
|
||||
* network context before able to use this function.
|
||||
*
|
||||
* @param context Network context that will be related to
|
||||
* this buffer.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_rx(struct net_context *context);
|
||||
|
||||
/**
|
||||
* @brief Get buffer from the TX buffers pool.
|
||||
*
|
||||
* @details Get network buffer from TX buffer pool. You must have
|
||||
* network context before able to use this function.
|
||||
*
|
||||
* @param context Network context that will be related to
|
||||
* this buffer.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_tx(struct net_context *context);
|
||||
|
||||
/**
|
||||
* @brief Get buffer from the DATA buffers pool.
|
||||
*
|
||||
* @details Get network buffer from DATA buffer pool. You must have
|
||||
* network context before able to use this function.
|
||||
*
|
||||
* @param context Network context that will be related to
|
||||
* this buffer.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_data(struct net_context *context);
|
||||
|
||||
/**
|
||||
* @brief Get RX buffer from pool but also reserve headroom for
|
||||
* potential headers.
|
||||
*
|
||||
* @details Normally this version is not useful for applications
|
||||
* but is mainly used by network fragmentation code.
|
||||
*
|
||||
* @param reserve_head How many bytes to reserve for headroom.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_reserve_rx(uint16_t reserve_head);
|
||||
|
||||
/**
|
||||
* @brief Get TX buffer from pool but also reserve headroom for
|
||||
* potential headers.
|
||||
*
|
||||
* @details Normally this version is not useful for applications
|
||||
* but is mainly used by network fragmentation code.
|
||||
*
|
||||
* @param reserve_head How many bytes to reserve for headroom.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_reserve_tx(uint16_t reserve_head);
|
||||
|
||||
/**
|
||||
* @brief Get DATA buffer from pool but also reserve headroom for
|
||||
* potential headers.
|
||||
*
|
||||
* @details Normally this version is not useful for applications
|
||||
* but is mainly used by network fragmentation code.
|
||||
*
|
||||
* @param reserve_head How many bytes to reserve for headroom.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_get_reserve_data(uint16_t reserve_head);
|
||||
|
||||
/**
|
||||
* @brief Place buffer back into the available buffers pool.
|
||||
*
|
||||
* @details Releases the buffer to other use. This needs to be
|
||||
* called by application after it has finished with
|
||||
* the buffer.
|
||||
*
|
||||
* @param buf Network buffer to release.
|
||||
*
|
||||
*/
|
||||
void net_nbuf_unref(struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* @brief Increase the ref count
|
||||
*
|
||||
* @details Mark the buffer to be used still.
|
||||
*
|
||||
* @param buf Network buffer to ref.
|
||||
*
|
||||
* @return Network buffer if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_ref(struct net_buf *buf);
|
||||
|
||||
#endif /* CONFIG_NET_DEBUG_NET_BUF */
|
||||
|
||||
/**
|
||||
* @brief Copy a buffer with fragments while reserving some extra space
|
||||
* in destination buffer before a copy.
|
||||
*
|
||||
* @details Note that the original buffer is not really usable after the copy
|
||||
* as the function will call net_buf_pull() internally and should be discarded.
|
||||
*
|
||||
* @param buf Network buffer fragment. This should be the first fragment (data)
|
||||
* in the fragment list.
|
||||
* @param amount Max amount of data to be copied.
|
||||
* @param reserve Amount of extra data (this is not link layer header) in the
|
||||
* first data fragment that is returned. The function will copy the original
|
||||
* buffer right after the reserved bytes in the first destination fragment.
|
||||
*
|
||||
* @return New fragment list if successful, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_copy(struct net_buf *buf, size_t amount,
|
||||
size_t reserve);
|
||||
|
||||
/**
|
||||
* @brief Copy a buffer with fragments while reserving some extra space
|
||||
* in destination buffer before a copy.
|
||||
*
|
||||
* @param buf Network buffer fragment. This should be the first fragment (data)
|
||||
* in the fragment list.
|
||||
* @param reserve Amount of extra data (this is not link layer header) in the
|
||||
* first data fragment that is returned. The function will copy the original
|
||||
* buffer right after the reserved bytes in the first destination fragment.
|
||||
*
|
||||
* @return New fragment list if successful, NULL otherwise.
|
||||
*/
|
||||
static inline struct net_buf *net_nbuf_copy_all(struct net_buf *buf,
|
||||
size_t reserve)
|
||||
{
|
||||
return net_nbuf_copy(buf, net_buf_frags_len(buf), reserve);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compact the fragment list.
|
||||
*
|
||||
* @details After this there is no more any free space in individual fragments.
|
||||
* @param buf Network buffer fragment. This should be the first fragment (data)
|
||||
* in the fragment list.
|
||||
*
|
||||
* @return Pointer to the start of the fragment list if ok, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_compact(struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* @brief Check if the buffer chain is compact or not.
|
||||
*
|
||||
* @details The compact here means that is there any free space in the
|
||||
* fragments. Only the last fragment can have some free space if the fragment
|
||||
* list is compact.
|
||||
*
|
||||
* @param buf Network buffer.
|
||||
*
|
||||
* @return True if there is no free space in the fragment list,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool net_nbuf_is_compact(struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* @brief Create some more space in front of the fragment list.
|
||||
*
|
||||
* @details After this there is more space available before the first
|
||||
* fragment. The existing data needs to be moved "down" which will
|
||||
* cause a cascading effect on fragment list because fragments are fixed
|
||||
* size.
|
||||
*
|
||||
* @param parent Pointer to parent of the network buffer. If there is
|
||||
* no parent, then set this parameter NULL.
|
||||
* @param buf Network buffer
|
||||
* @param amount Amount of data that is needed in front of the fragment list.
|
||||
*
|
||||
* @return Pointer to the start of the fragment list if ok, NULL otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_push(struct net_buf *parent, struct net_buf *buf,
|
||||
size_t amount);
|
||||
|
||||
/**
|
||||
* @brief Remove given amount of data from the beginning of fragment list.
|
||||
* This is similar thing to do as in net_buf_pull() but this function changes
|
||||
* the fragment list instead of one fragment.
|
||||
*
|
||||
* @param buf Network buffer fragment list.
|
||||
* @param amount Max amount of data to be remove.
|
||||
*
|
||||
* @return Pointer to start of the fragment list if successful. NULL can be
|
||||
* returned if all fragments were removed from the list.
|
||||
*/
|
||||
struct net_buf *net_nbuf_pull(struct net_buf *buf, size_t amount);
|
||||
|
||||
/**
|
||||
* @brief Append 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. Caller has to take care of endianness if needed.
|
||||
*
|
||||
* @param buf Network buffer fragment list.
|
||||
* @param len Total length of input data
|
||||
* @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).
|
||||
*/
|
||||
bool net_nbuf_append(struct net_buf *buf, uint16_t len, uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief Append uint8_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. Caller has to take care of endianness if needed.
|
||||
*
|
||||
* @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_u8(struct net_buf *buf, uint8_t data)
|
||||
{
|
||||
return net_nbuf_append(buf, 1, &data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Append uint16_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. Caller has to take care of endianness if needed.
|
||||
*
|
||||
* @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_be16(struct net_buf *buf, uint16_t data)
|
||||
{
|
||||
uint16_t value = sys_cpu_to_be16(data);
|
||||
|
||||
return net_nbuf_append(buf, sizeof(uint16_t), (uint8_t *)&value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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. Caller has to take care of endianness if needed.
|
||||
*
|
||||
* @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_be32(struct net_buf *buf, uint32_t data)
|
||||
{
|
||||
uint32_t value = sys_cpu_to_be32(data);
|
||||
|
||||
return net_nbuf_append(buf, sizeof(uint32_t), (uint8_t *)&value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get data from buffer
|
||||
*
|
||||
* @details Get N number of bytes starting from fragment's offset. If the total
|
||||
* length of data is placed in multiple framgents, this function will read from
|
||||
* all fragments until it reaches N number of bytes. Caller has to take care of
|
||||
* endianness if needed.
|
||||
*
|
||||
* @param buf Network buffer fragment.
|
||||
* @param offset Offset of input buffer.
|
||||
* @param pos Pointer to position of offset after reading n number of bytes,
|
||||
* this is with respect to return buffer(fragment).
|
||||
* @param len Total length of data to be read.
|
||||
* @param data Data will be copied here.
|
||||
*
|
||||
* @return Pointer to the fragment or
|
||||
* NULL and pos is 0 after successful read,
|
||||
* NULL and pos is 0xffff otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_read(struct net_buf *buf, uint16_t offset,
|
||||
uint16_t *pos, uint16_t len, uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief Skip N number of bytes while reading buffer
|
||||
*
|
||||
* @details Skip N number of bytes starting from fragment's offset. If the total
|
||||
* length of data is placed in multiple framgents, this function will skip from
|
||||
* all fragments until it reaches N number of bytes. This function is useful
|
||||
* when unwanted data (e.g. reserved or not supported data in message) is part
|
||||
* of fragment and want to skip it.
|
||||
*
|
||||
* @param buf Network buffer fragment.
|
||||
* @param offset Offset of input buffer.
|
||||
* @param pos Pointer to position of offset after reading n number of bytes,
|
||||
* this is with respect to return buffer(fragment).
|
||||
* @param len Total length of data to be read.
|
||||
*
|
||||
* @return Pointer to the fragment or
|
||||
* NULL and pos is 0 after successful skip,
|
||||
* NULL and pos is 0xffff otherwise.
|
||||
*/
|
||||
static inline struct net_buf *net_nbuf_skip(struct net_buf *buf,
|
||||
uint16_t offset,
|
||||
uint16_t *pos, uint16_t len)
|
||||
{
|
||||
return net_nbuf_read(buf, offset, pos, len, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a byte value from fragmented buffer
|
||||
*
|
||||
* @param buf Network buffer fragment.
|
||||
* @param offset Offset of input buffer.
|
||||
* @param pos Pointer to position of offset after reading 2 bytes,
|
||||
* this is with respect to return buffer(fragment).
|
||||
* @param value Value is returned
|
||||
*
|
||||
* @return Pointer to fragment after successful read,
|
||||
* NULL otherwise (if pos is 0, NULL is not a failure case).
|
||||
*/
|
||||
static inline struct net_buf *net_nbuf_read_u8(struct net_buf *buf,
|
||||
uint16_t offset,
|
||||
uint16_t *pos,
|
||||
uint8_t *value)
|
||||
{
|
||||
return net_nbuf_read(buf, offset, pos, 1, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get 16 bit big endian value from fragmented buffer
|
||||
*
|
||||
* @param buf Network buffer fragment.
|
||||
* @param offset Offset of input buffer.
|
||||
* @param pos Pointer to position of offset after reading 2 bytes,
|
||||
* this is with respect to return buffer(fragment).
|
||||
* @param value Value is returned
|
||||
*
|
||||
* @return Pointer to fragment after successful read,
|
||||
* NULL otherwise (if pos is 0, NULL is not a failure case).
|
||||
*/
|
||||
struct net_buf *net_nbuf_read_be16(struct net_buf *buf, uint16_t offset,
|
||||
uint16_t *pos, uint16_t *value);
|
||||
|
||||
/**
|
||||
* @brief Get 32 bit big endian value from fragmented buffer
|
||||
*
|
||||
* @param buf Network buffer fragment.
|
||||
* @param offset Offset of input buffer.
|
||||
* @param pos Pointer to position of offset after reading 4 bytes,
|
||||
* this is with respect to return buffer(fragment).
|
||||
* @param value Value is returned
|
||||
*
|
||||
* @return Pointer to fragment after successful read,
|
||||
* NULL otherwise (if pos is 0, NULL is not a failure case).
|
||||
*/
|
||||
struct net_buf *net_nbuf_read_be32(struct net_buf *buf, uint16_t offset,
|
||||
uint16_t *pos, uint32_t *value);
|
||||
|
||||
/**
|
||||
* @brief Write data to an arbitrary offset in a series of fragments.
|
||||
*
|
||||
* @details Write data to an arbitrary offset in a series of fragments.
|
||||
* Offset is based on fragment 'size' and calculates from input fragment
|
||||
* starting position.
|
||||
*
|
||||
* Size in this context refers the fragment full size without link layer header
|
||||
* part. The fragment might have user written data in it, the amount of such
|
||||
* data is stored in frag->len variable (the frag->len is always <= frag->size).
|
||||
* If using this API, the tailroom in the fragments will be taken into use.
|
||||
*
|
||||
* If offset is more than already allocated length in fragment, then empty space
|
||||
* or extra empty fragments is created to reach proper offset.
|
||||
* If there is any data present on input fragment offset, then it will be
|
||||
* 'overwritten'. Use net_nbuf_insert() api if you don't want to overwrite.
|
||||
*
|
||||
* Offset is calculated from starting point of data area in input fragment.
|
||||
* e.g. Buf(Tx/Rx) - Frag1 - Frag2 - Frag3 - Frag4
|
||||
* (Assume FRAG DATA SIZE is 100 bytes after link layer header)
|
||||
*
|
||||
* 1) net_nbuf_write(buf, frag2, 20, &pos, 20, data)
|
||||
* In this case write starts from "frag2->data + 20",
|
||||
* returns frag2, pos = 40
|
||||
*
|
||||
* 2) net_nbuf_write(buf, frag1, 150, &pos, 60, data)
|
||||
* In this case write starts from "frag2->data + 50"
|
||||
* returns frag3, pos = 10
|
||||
*
|
||||
* 3) net_nbuf_write(buf, frag1, 350, &pos, 30, data)
|
||||
* In this case write starts from "frag4->data + 50"
|
||||
* returns frag4, pos = 80
|
||||
*
|
||||
* 4) net_nbuf_write(buf, frag2, 110, &pos, 90, data)
|
||||
* In this case write starts from "frag3->data + 10"
|
||||
* returns frag4, pos = 0
|
||||
*
|
||||
* 5) net_nbuf_write(buf, frag4, 110, &pos, 20, data)
|
||||
* In this case write creates new data fragment and starts from
|
||||
* "frag5->data + 10"
|
||||
* returns frag5, pos = 30
|
||||
*
|
||||
* If input argument frag is NULL, it will create new data fragment
|
||||
* and append at the end of fragment list.
|
||||
*
|
||||
* @param buf Network buffer fragment list.
|
||||
* @param frag Network buffer fragment.
|
||||
* @param offset Offset
|
||||
* @param pos Position of offset after write completed (this will be
|
||||
* relative to return fragment)
|
||||
* @param len Length of the data to be written.
|
||||
* @param data Data to be written
|
||||
*
|
||||
* @return Pointer to the fragment and position (*pos) where write ended,
|
||||
* NULL and pos is 0xffff otherwise.
|
||||
*/
|
||||
struct net_buf *net_nbuf_write(struct net_buf *buf, struct net_buf *frag,
|
||||
uint16_t offset, uint16_t *pos, uint16_t len,
|
||||
uint8_t *data);
|
||||
|
||||
/* Write uint8_t data to an arbitrary offset in fragment. */
|
||||
static inline struct net_buf *net_nbuf_write_u8(struct net_buf *buf,
|
||||
struct net_buf *frag,
|
||||
uint16_t offset,
|
||||
uint16_t *pos,
|
||||
uint8_t data)
|
||||
{
|
||||
return net_nbuf_write(buf, frag, offset, pos, sizeof(uint8_t), &data);
|
||||
}
|
||||
|
||||
/* Write uint16_t big endian value to an arbitrary offset in fragment. */
|
||||
static inline struct net_buf *net_nbuf_write_be16(struct net_buf *buf,
|
||||
struct net_buf *frag,
|
||||
uint16_t offset,
|
||||
uint16_t *pos,
|
||||
uint16_t data)
|
||||
{
|
||||
uint16_t value = htons(data);
|
||||
|
||||
return net_nbuf_write(buf, frag, offset, pos, sizeof(uint16_t),
|
||||
(uint8_t *)&value);
|
||||
}
|
||||
|
||||
/* Write uint32_t big endian value to an arbitrary offset in fragment. */
|
||||
static inline struct net_buf *net_nbuf_write_be32(struct net_buf *buf,
|
||||
struct net_buf *frag,
|
||||
uint16_t offset,
|
||||
uint16_t *pos,
|
||||
uint32_t data)
|
||||
{
|
||||
uint32_t value = htonl(data);
|
||||
|
||||
return net_nbuf_write(buf, frag, offset, pos, sizeof(uint32_t),
|
||||
(uint8_t *)&value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Insert data at an arbitrary offset in a series of fragments.
|
||||
*
|
||||
* @details Insert data at an arbitrary offset in a series of fragments. Offset
|
||||
* is based on fragment length (only user written data length, any tailroom
|
||||
* in fragments does not come to consideration unlike net_nbuf_write()) and
|
||||
* calculates from input fragment starting position.
|
||||
*
|
||||
* Offset examples can be considered from net_nbuf_write() api.
|
||||
* If the offset is more than already allocated fragments length then it is an
|
||||
* error case.
|
||||
*
|
||||
* @param buf Network buffer fragment list.
|
||||
* @param frag Network buffer fragment.
|
||||
* @param offset Offset of fragment where insertion will start.
|
||||
* @param len Length of the data to be inserted.
|
||||
* @param data Data to be inserted
|
||||
*
|
||||
* @return True on success,
|
||||
* False otherwise.
|
||||
*/
|
||||
bool net_nbuf_insert(struct net_buf *buf, struct net_buf *frag,
|
||||
uint16_t offset, uint16_t len, uint8_t *data);
|
||||
|
||||
/* Insert uint8_t data at an arbitrary offset in a series of fragments. */
|
||||
static inline bool net_nbuf_insert_u8(struct net_buf *buf, struct net_buf *frag,
|
||||
uint16_t offset, uint8_t data)
|
||||
{
|
||||
return net_nbuf_insert(buf, frag, offset, sizeof(uint8_t), &data);
|
||||
}
|
||||
|
||||
/* Insert uint16_t big endian value at an arbitrary offset in a series of
|
||||
* fragments.
|
||||
*/
|
||||
static inline bool net_nbuf_insert_be16(struct net_buf *buf,
|
||||
struct net_buf *frag,
|
||||
uint16_t offset, uint16_t data)
|
||||
{
|
||||
uint16_t value = htons(data);
|
||||
|
||||
return net_nbuf_insert(buf, frag, offset, sizeof(uint16_t),
|
||||
(uint8_t *)&value);
|
||||
}
|
||||
|
||||
/* Insert uint32_t big endian value at an arbitrary offset in a series of
|
||||
* fragments.
|
||||
*/
|
||||
static inline bool net_nbuf_insert_be32(struct net_buf *buf,
|
||||
struct net_buf *frag,
|
||||
uint16_t offset, uint32_t data)
|
||||
{
|
||||
uint32_t value = htonl(data);
|
||||
|
||||
return net_nbuf_insert(buf, frag, offset, sizeof(uint32_t),
|
||||
(uint8_t *)&value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get information about available free buffer count in
|
||||
* various network buffer pools. The amount of free buffers is
|
||||
* only returned if network buffer debugging is enabled.
|
||||
*
|
||||
* @param tx_size Size of TX pool. Value is returned.
|
||||
* @param rx_size Size of RX pool. Value is returned.
|
||||
* @param data_size Size of DATA pool. Value is returned.
|
||||
* @param tx Amount of free buffers in TX pool. Value is returned.
|
||||
* @param rx Amount of free buffers in RX pool. Value is returned.
|
||||
* @param data Amount of free buffers in DATA pool. Value is returned.
|
||||
*/
|
||||
void net_nbuf_get_info(size_t *tx_size, size_t *rx_size, size_t *data_size,
|
||||
int *tx, int *rx, int *data);
|
||||
|
||||
#if defined(CONFIG_NET_DEBUG_NET_BUF)
|
||||
/**
|
||||
* @brief Debug helper to print out the buffer allocations
|
||||
*/
|
||||
void net_nbuf_print(void);
|
||||
#else
|
||||
#define net_nbuf_print(...)
|
||||
#endif /* CONFIG_NET_DEBUG_NET_BUF */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NBUF_H */
|
|
@ -1,670 +0,0 @@
|
|||
/** @file
|
||||
* @brief Network context definitions
|
||||
*
|
||||
* An API for applications to define a network connection.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __NET_CONTEXT_H
|
||||
#define __NET_CONTEXT_H
|
||||
|
||||
#include <kernel.h>
|
||||
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/net_stats.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Is this context used or not */
|
||||
#define NET_CONTEXT_IN_USE BIT(0)
|
||||
|
||||
/** State of the context (bits 1 & 2 in the flags) */
|
||||
enum net_context_state {
|
||||
NET_CONTEXT_IDLE = 0,
|
||||
NET_CONTEXT_UNCONNECTED = 0,
|
||||
NET_CONTEXT_CONFIGURING = 1,
|
||||
NET_CONTEXT_CONNECTING = 1,
|
||||
NET_CONTEXT_READY = 2,
|
||||
NET_CONTEXT_CONNECTED = 2,
|
||||
NET_CONTEXT_LISTENING = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* The address family, connection type and IP protocol are
|
||||
* stored into a bit field to save space.
|
||||
*/
|
||||
/** Protocol family of this connection */
|
||||
#define NET_CONTEXT_FAMILY BIT(4)
|
||||
|
||||
/** Type of the connection (datagram / stream) */
|
||||
#define NET_CONTEXT_TYPE BIT(5)
|
||||
|
||||
/** IP protocol (like UDP or TCP) */
|
||||
#define NET_CONTEXT_PROTO BIT(6)
|
||||
|
||||
/** Remote address set */
|
||||
#define NET_CONTEXT_REMOTE_ADDR_SET BIT(7)
|
||||
|
||||
struct net_context;
|
||||
|
||||
/**
|
||||
* @brief Network data receive callback.
|
||||
*
|
||||
* @details The recv callback is called after a network data is
|
||||
* received.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param buf Network buffer that is received. If the buf is not NULL,
|
||||
* then the callback will own the buffer and it needs to to unref the buf
|
||||
* as soon as it has finished working with it.
|
||||
* @param status Value is set to 0 if some data is received, <0 if
|
||||
* there was an error receiving data, in this case the buf parameter is
|
||||
* set to NULL.
|
||||
* @param user_data The user data given in net_recv() call.
|
||||
*/
|
||||
typedef void (*net_context_recv_cb_t)(struct net_context *context,
|
||||
struct net_buf *buf,
|
||||
int status,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Network data send callback.
|
||||
*
|
||||
* @details The send callback is called after a network data is
|
||||
* sent.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param status Value is set to 0 if all data was sent ok, <0 if
|
||||
* there was an error sending data. >0 amount of data that was
|
||||
* sent when not all data was sent ok.
|
||||
* @param token User specified value specified in net_send() call.
|
||||
* @param user_data The user data given in net_send() call.
|
||||
*/
|
||||
typedef void (*net_context_send_cb_t)(struct net_context *context,
|
||||
int status,
|
||||
void *token,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Accept callback
|
||||
*
|
||||
* @details The accept callback is called after a successful
|
||||
* connection is being established or if there was an error
|
||||
* while we were waiting for a connection attempt.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param addr The peer address.
|
||||
* @param addrlen Length of the peer address.
|
||||
* @param status The status code, 0 on success, < 0 otherwise
|
||||
* @param user_data The user data given in net_context_accept() call.
|
||||
*/
|
||||
typedef void (*net_context_accept_cb_t)(struct net_context *new_context,
|
||||
struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
int status,
|
||||
void *user_data);
|
||||
|
||||
struct net_tcp;
|
||||
|
||||
struct net_conn_handle;
|
||||
|
||||
/**
|
||||
* Note that we do not store the actual source IP address in the context
|
||||
* because the address is already be set in the network interface struct.
|
||||
* If there is no such source address there, the packet cannot be sent
|
||||
* anyway. This saves 12 bytes / context in IPv6.
|
||||
*/
|
||||
struct net_context {
|
||||
/** Local IP address. Note that the values are in network byte order.
|
||||
*/
|
||||
struct sockaddr_ptr local;
|
||||
|
||||
/** Remote IP address. Note that the values are in network byte order.
|
||||
*/
|
||||
struct sockaddr remote;
|
||||
|
||||
/** Connection handle */
|
||||
struct net_conn_handle *conn_handler;
|
||||
|
||||
/** Receive callback to be called when desired packet
|
||||
* has been received.
|
||||
*/
|
||||
net_context_recv_cb_t recv_cb;
|
||||
|
||||
/** Send callback to be called when the packet has been sent
|
||||
* successfully.
|
||||
*/
|
||||
net_context_send_cb_t send_cb;
|
||||
|
||||
/** User data.
|
||||
*/
|
||||
void *user_data;
|
||||
|
||||
#if defined(CONFIG_NET_CONTEXT_SYNC_RECV)
|
||||
/**
|
||||
* Mutex for synchronous recv API call.
|
||||
*/
|
||||
struct k_sem recv_data_wait;
|
||||
#endif /* CONFIG_NET_CONTEXT_SYNC_RECV */
|
||||
|
||||
/** Network interface assigned to this context */
|
||||
uint8_t iface;
|
||||
|
||||
/** Flags for the context */
|
||||
uint8_t flags;
|
||||
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
/** TCP connection information */
|
||||
struct net_tcp *tcp;
|
||||
|
||||
/** Accept callback to be called when the connection has been
|
||||
* established.
|
||||
*/
|
||||
net_context_accept_cb_t accept_cb;
|
||||
#endif /* CONFIG_NET_TCP */
|
||||
};
|
||||
|
||||
static inline bool net_context_is_used(struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
return context->flags & NET_CONTEXT_IN_USE;
|
||||
}
|
||||
|
||||
#define NET_CONTEXT_STATE_SHIFT 1
|
||||
#define NET_CONTEXT_STATE_MASK 0x03
|
||||
|
||||
/**
|
||||
* @brief Get state for this network context.
|
||||
*
|
||||
* @details This function returns the state of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
*
|
||||
* @return Network state.
|
||||
*/
|
||||
static inline
|
||||
enum net_context_state net_context_get_state(struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
return (context->flags >> NET_CONTEXT_STATE_SHIFT) &
|
||||
NET_CONTEXT_STATE_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set state for this network context.
|
||||
*
|
||||
* @details This function sets the state of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
* @param state New network context state.
|
||||
*/
|
||||
static inline void net_context_set_state(struct net_context *context,
|
||||
enum net_context_state state)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
context->flags |= ((state & NET_CONTEXT_STATE_MASK) <<
|
||||
NET_CONTEXT_STATE_SHIFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get address family for this network context.
|
||||
*
|
||||
* @details This function returns the address family (IPv4 or IPv6)
|
||||
* of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
*
|
||||
* @return Network state.
|
||||
*/
|
||||
static inline sa_family_t net_context_get_family(struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
if (context->flags & NET_CONTEXT_FAMILY) {
|
||||
return AF_INET6;
|
||||
}
|
||||
|
||||
return AF_INET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set address family for this network context.
|
||||
*
|
||||
* @details This function sets the address family (IPv4 or IPv6)
|
||||
* of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
* @param family Address family (AF_INET or AF_INET6)
|
||||
*/
|
||||
static inline void net_context_set_family(struct net_context *context,
|
||||
sa_family_t family)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
if (family == AF_INET6) {
|
||||
context->flags |= NET_CONTEXT_FAMILY;
|
||||
return;
|
||||
}
|
||||
|
||||
context->flags &= ~NET_CONTEXT_FAMILY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get context type for this network context.
|
||||
*
|
||||
* @details This function returns the context type (stream or datagram)
|
||||
* of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
*
|
||||
* @return Network context type.
|
||||
*/
|
||||
static inline
|
||||
enum net_sock_type net_context_get_type(struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
if (context->flags & NET_CONTEXT_TYPE) {
|
||||
return SOCK_STREAM;
|
||||
}
|
||||
|
||||
return SOCK_DGRAM;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set context type for this network context.
|
||||
*
|
||||
* @details This function sets the context type (stream or datagram)
|
||||
* of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
* @param type Context type (SOCK_STREAM or SOCK_DGRAM)
|
||||
*/
|
||||
static inline void net_context_set_type(struct net_context *context,
|
||||
enum net_sock_type type)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
if (type == SOCK_STREAM) {
|
||||
context->flags |= NET_CONTEXT_TYPE;
|
||||
return;
|
||||
}
|
||||
|
||||
context->flags &= ~NET_CONTEXT_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get context IP protocol for this network context.
|
||||
*
|
||||
* @details This function returns the context IP protocol (UDP / TCP)
|
||||
* of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
*
|
||||
* @return Network context IP protocol.
|
||||
*/
|
||||
static inline
|
||||
enum net_ip_protocol net_context_get_ip_proto(struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
if (context->flags & NET_CONTEXT_PROTO) {
|
||||
return IPPROTO_TCP;
|
||||
}
|
||||
|
||||
return IPPROTO_UDP;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set context IP protocol for this network context.
|
||||
*
|
||||
* @details This function sets the context IP protocol (UDP / TCP)
|
||||
* of the context.
|
||||
*
|
||||
* @param context Network context.
|
||||
* @param ip_proto Context IP protocol (IPPROTO_UDP or IPPROTO_TCP)
|
||||
*/
|
||||
static inline void net_context_set_ip_proto(struct net_context *context,
|
||||
enum net_ip_protocol ip_proto)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
if (ip_proto == IPPROTO_TCP) {
|
||||
context->flags |= NET_CONTEXT_PROTO;
|
||||
return;
|
||||
}
|
||||
|
||||
context->flags &= ~NET_CONTEXT_PROTO;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get network interface for this context.
|
||||
*
|
||||
* @details This function returns the used network interface.
|
||||
*
|
||||
* @param context Network context.
|
||||
*
|
||||
* @return Context network interface if context is bind to interface,
|
||||
* NULL otherwise.
|
||||
*/
|
||||
static inline
|
||||
struct net_if *net_context_get_iface(struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(context);
|
||||
|
||||
return net_if_get_by_index(context->iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set network interface for this context.
|
||||
*
|
||||
* @details This function binds network interface to this context.
|
||||
*
|
||||
* @param context Network context.
|
||||
* @param iface Network interface.
|
||||
*/
|
||||
static inline void net_context_set_iface(struct net_context *context,
|
||||
struct net_if *iface)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
|
||||
context->iface = net_if_get_by_iface(iface);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get network context.
|
||||
*
|
||||
* @details Network context is used to define the connection
|
||||
* 5-tuple (protocol, remote address, remote port, source
|
||||
* address and source port). This is similar as BSD socket()
|
||||
* function.
|
||||
*
|
||||
* @param family IP address family (AF_INET or AF_INET6)
|
||||
* @param type Type of the socket, SOCK_STREAM or SOCK_DGRAM
|
||||
* @param ip_proto IP protocol, IPPROTO_UDP or IPPROTO_TCP
|
||||
* @param context The allocated context is returned to the caller.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_get(sa_family_t family,
|
||||
enum net_sock_type type,
|
||||
enum net_ip_protocol ip_proto,
|
||||
struct net_context **context);
|
||||
|
||||
/**
|
||||
* @brief Free/close a network context.
|
||||
*
|
||||
* @details This releases the context. It is not possible to
|
||||
* send or receive data via this context after this call.
|
||||
* This is similar as BSD shutdown() function.
|
||||
*
|
||||
* @param context The context to be closed.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_put(struct net_context *context);
|
||||
|
||||
/**
|
||||
* @brief Assign a socket a local address.
|
||||
*
|
||||
* @details This is similar as BSD bind() function.
|
||||
*
|
||||
* @param context The context to be assigned.
|
||||
* @param addr Address to assigned.
|
||||
* @param addrlen Length of the address.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_bind(struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* @brief Mark the context as a listening one.
|
||||
*
|
||||
* @details This is similar as BSD listen() function.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param backlog The size of the pending connections backlog.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_listen(struct net_context *context,
|
||||
int backlog);
|
||||
|
||||
/**
|
||||
* @brief Connection callback.
|
||||
*
|
||||
* @details The connect callback is called after a connection is being
|
||||
* established.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param user_data The user data given in net_context_connect() call.
|
||||
*/
|
||||
typedef void (*net_context_connect_cb_t)(struct net_context *context,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Create a network connection.
|
||||
*
|
||||
* @details The net_context_connect function creates a network
|
||||
* connection to the host specified by addr. After the
|
||||
* connection is established, the user supplied callback (cb)
|
||||
* is executed. cb is called even if the timeout was set to
|
||||
* K_FOREVER. cb is not called if the timeout expires.
|
||||
* For datagram sockets (SOCK_DGRAM), this function only sets
|
||||
* the peer address.
|
||||
* This function is similar to the BSD connect() function.
|
||||
*
|
||||
* @param context The network context.
|
||||
* @param addr The peer address to connect to.
|
||||
* @param addrlen Peer address length.
|
||||
* @param cb Callback function. Set to NULL if not required.
|
||||
* @param timeout The timeout value for the connection. Possible values:
|
||||
* * K_NO_WAIT: this function will return immediately,
|
||||
* * K_FOREVER: this function will block until the
|
||||
* connection is established,
|
||||
* * >0: this function will wait the specified ms.
|
||||
* @param user_data Data passed to the callback function.
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return -EINVAL if an invalid parameter is passed as an argument.
|
||||
* @return -ENOTSUP if the operation is not supported or implemented.
|
||||
*/
|
||||
int net_context_connect(struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
net_context_connect_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Accept a network connection attempt.
|
||||
*
|
||||
* @details Accept a connection being established. This function
|
||||
* will return immediately if the timeout is set to K_NO_WAIT.
|
||||
* In this case the context will call the supplied callback when ever
|
||||
* there is a connection established to this context. This is "a register
|
||||
* handler and forget" type of call (async).
|
||||
* If the timeout is set to K_FOREVER, the function will wait
|
||||
* until the connection is established. Timeout value > 0, will wait as
|
||||
* many ms.
|
||||
* After the connection is established a caller supplied callback is called.
|
||||
* The callback is called even if timeout was set to K_FOREVER, the
|
||||
* callback is called before this function will return in this case.
|
||||
* The callback is not called if the timeout expires.
|
||||
* This is similar as BSD accept() function.
|
||||
*
|
||||
* @param context The context to use.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Timeout for the connection. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_accept(struct net_context *context,
|
||||
net_context_accept_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Send a network buffer to a peer.
|
||||
*
|
||||
* @details This function can be used to send network data to a peer
|
||||
* connection. This function will return immediately if the timeout
|
||||
* is set to K_NO_WAIT. If the timeout is set to K_FOREVER, the function
|
||||
* will wait until the network buffer is sent. Timeout value > 0 will
|
||||
* wait as many ms. After the network buffer is sent,
|
||||
* a caller supplied callback is called. The callback is called even
|
||||
* if timeout was set to K_FOREVER, the callback is called
|
||||
* before this function will return in this case. The callback is not
|
||||
* called if the timeout expires. For context of type SOCK_DGRAM,
|
||||
* the destination address must have been set by the call to
|
||||
* net_context_connect().
|
||||
* This is similar as BSD send() function.
|
||||
*
|
||||
* @param buf The network buffer to send.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Timeout for the connection. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param token Caller specified value that is passed as is to callback.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_send(struct net_buf *buf,
|
||||
net_context_send_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *token,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Send a network buffer to a peer specified by address.
|
||||
*
|
||||
* @details This function can be used to send network data to a peer
|
||||
* specified by address. This variant can only be used for datagram
|
||||
* connections of type SOCK_DGRAM. This function will return immediately
|
||||
* if the timeout is set to K_NO_WAIT. If the timeout is set to K_FOREVER,
|
||||
* the function will wait until the network buffer is sent. Timeout
|
||||
* value > 0 will wait as many ms. After the network buffer
|
||||
* is sent, a caller supplied callback is called. The callback is called
|
||||
* even if timeout was set to K_FOREVER, the callback is called
|
||||
* before this function will return. The callback is not called if the
|
||||
* timeout expires.
|
||||
* This is similar as BSD sendto() function.
|
||||
*
|
||||
* @param buf The network buffer to send.
|
||||
* @param dst_addr Destination address. This will override the address
|
||||
* already set in network buffer.
|
||||
* @param addrlen Length of the address.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Timeout for the connection. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param token Caller specified value that is passed as is to callback.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_sendto(struct net_buf *buf,
|
||||
const struct sockaddr *dst_addr,
|
||||
socklen_t addrlen,
|
||||
net_context_send_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *token,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Receive network data from a peer specified by context.
|
||||
*
|
||||
* @details This function can be used to register a callback function
|
||||
* that is called by the network stack when network data has been received
|
||||
* for this context. As this function registers a callback, then there
|
||||
* is no need to call this function multiple times if timeout is set to
|
||||
* K_NO_WAIT.
|
||||
* If callback function or user data changes, then the function can be called
|
||||
* multiple times to register new values.
|
||||
* This function will return immediately if the timeout is set to K_NO_WAIT.
|
||||
* If the timeout is set to K_FOREVER, the function will wait until the
|
||||
* network buffer is received. Timeout value > 0 will wait as many ms.
|
||||
* After the network buffer is received, a caller supplied callback is
|
||||
* called. The callback is called even if timeout was set to K_FOREVER,
|
||||
* the callback is called before this function will return in this case.
|
||||
* The callback is not called if the timeout expires. The timeout functionality
|
||||
* can be compiled out if synchronous behaviour is not needed. The sync call
|
||||
* logic requires some memory that can be saved if only async way of call is
|
||||
* used. If CONFIG_NET_CONTEXT_SYNC_RECV is not set, then the timeout parameter
|
||||
* value is ignored.
|
||||
* This is similar as BSD recv() function.
|
||||
*
|
||||
* @param context The network context to use.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Caller supplied timeout. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_context_recv(struct net_context *context,
|
||||
net_context_recv_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Internal function that is called when network packet is sent
|
||||
* successfully.
|
||||
*
|
||||
* @param context The network context to use.
|
||||
* @param token User supplied token tied to the net_buf that was sent.
|
||||
* @param err_code Error code
|
||||
*/
|
||||
static inline void net_context_send_cb(struct net_context *context,
|
||||
void *token,
|
||||
int err_code)
|
||||
{
|
||||
if (context->send_cb) {
|
||||
context->send_cb(context, err_code, token, context->user_data);
|
||||
}
|
||||
|
||||
if (net_context_get_ip_proto(context) == IPPROTO_UDP) {
|
||||
NET_STATS_UDP(++net_stats.udp.sent);
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*net_context_cb_t)(struct net_context *context, void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Go through all the network connections and call callback
|
||||
* for each network context.
|
||||
*
|
||||
* @param cb User supplied callback function to call.
|
||||
* @param user_data User specified data.
|
||||
*/
|
||||
void net_context_foreach(net_context_cb_t cb, void *user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NET_CONTEXT_H */
|
|
@ -1,212 +0,0 @@
|
|||
/** @file
|
||||
* @brief Network core definitions
|
||||
*
|
||||
* Definitions for networking support.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __NET_CORE_H
|
||||
#define __NET_CORE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Network subsystem logging helpers */
|
||||
|
||||
#if defined(CONFIG_NET_LOG)
|
||||
#if NET_DEBUG > 0
|
||||
#if !defined(SYS_LOG_DOMAIN)
|
||||
#define SYS_LOG_DOMAIN "net"
|
||||
#endif /* !SYS_LOG_DOMAIN */
|
||||
|
||||
#undef SYS_LOG_LEVEL
|
||||
#define SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
|
||||
#endif /* NET_DEBUG */
|
||||
|
||||
#define NET_DBG(fmt, ...) SYS_LOG_DBG("(%p): " fmt, k_current_get(), \
|
||||
##__VA_ARGS__)
|
||||
#define NET_ERR(fmt, ...) SYS_LOG_ERR(fmt, ##__VA_ARGS__)
|
||||
#define NET_WARN(fmt, ...) SYS_LOG_WRN(fmt, ##__VA_ARGS__)
|
||||
#define NET_INFO(fmt, ...) SYS_LOG_INF(fmt, ##__VA_ARGS__)
|
||||
#define NET_ASSERT(cond) do { \
|
||||
if (!(cond)) { \
|
||||
NET_ERR("{assert: '" #cond "' failed}"); \
|
||||
} } while (0)
|
||||
#define NET_ASSERT_INFO(cond, fmt, ...) do { \
|
||||
if (!(cond)) { \
|
||||
NET_ERR("{assert: '" #cond "' failed} " fmt, \
|
||||
##__VA_ARGS__); \
|
||||
} } while (0)
|
||||
#else /* CONFIG_NET_LOG */
|
||||
#define NET_DBG(...)
|
||||
#define NET_ERR(...)
|
||||
#define NET_INFO(...)
|
||||
#define NET_WARN(...)
|
||||
#define NET_ASSERT(...)
|
||||
#define NET_ASSERT_INFO(...)
|
||||
#endif /* CONFIG_NET_LOG */
|
||||
|
||||
#include <kernel.h>
|
||||
|
||||
struct net_buf;
|
||||
struct net_context;
|
||||
struct net_if;
|
||||
|
||||
#include <misc/sys_log.h>
|
||||
#include <string.h>
|
||||
|
||||
enum net_verdict {
|
||||
NET_OK, /** Packet has been taken care of */
|
||||
NET_CONTINUE, /** Packet has not been touched,
|
||||
other part should decide about its fate */
|
||||
NET_DROP, /** Packet must be dropped */
|
||||
};
|
||||
|
||||
/* Called by lower network stack when a network packet has been received */
|
||||
int net_recv_data(struct net_if *iface, struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* @brief Send data to network.
|
||||
*
|
||||
* @details Send data to network. This should not be used normally by
|
||||
* applications as it requires that the buffer and fragments are properly
|
||||
* constructed.
|
||||
*
|
||||
* @param buf Network buffer.
|
||||
*
|
||||
* @return 0 if ok, <0 if error. If <0 is returned, then the caller needs
|
||||
* to unref the buf in order to avoid buffer leak.
|
||||
*/
|
||||
int net_send_data(struct net_buf *buf);
|
||||
|
||||
struct net_stack_info {
|
||||
unsigned char *stack;
|
||||
const char *pretty_name;
|
||||
const char *name;
|
||||
size_t orig_size;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_SHELL)
|
||||
#define NET_STACK_GET_NAME(name, sfx) (__net_stack_##name##_##sfx)
|
||||
|
||||
#define NET_STACK_INFO_ADDR(_pretty, _name, _orig, _size, _addr, sfx) \
|
||||
static struct net_stack_info \
|
||||
(NET_STACK_GET_NAME(_name, sfx)) __used \
|
||||
__attribute__((__section__(".net_stack.data"))) = { \
|
||||
.stack = _addr, \
|
||||
.size = _size, \
|
||||
.orig_size = _orig, \
|
||||
.name = #_name, \
|
||||
.pretty_name = _pretty, \
|
||||
}
|
||||
|
||||
#define NET_STACK_INFO(_pretty_name, _name, _orig, _size) \
|
||||
NET_STACK_INFO_ADDR(_pretty_name, _name, _orig, _size, _name, 0)
|
||||
|
||||
#define NET_STACK_DEFINE(pretty_name, name, orig, size) \
|
||||
static unsigned char __noinit __stack name[size]; \
|
||||
NET_STACK_INFO(pretty_name, name, orig, size)
|
||||
|
||||
#else /* CONFIG_NET_SHELL */
|
||||
|
||||
#define NET_STACK_INFO(...)
|
||||
#define NET_STACK_INFO_ADDR(...)
|
||||
|
||||
#define NET_STACK_DEFINE(pretty_name, name, orig, size) \
|
||||
static unsigned char __noinit __stack name[size]
|
||||
|
||||
#endif /* CONFIG_NET_SHELL */
|
||||
|
||||
#define NET_STACK_DEFINE_EMBEDDED(name, size) unsigned char name[size]
|
||||
|
||||
/** @cond ignore */
|
||||
#if defined(CONFIG_INIT_STACKS)
|
||||
#include <offsets.h>
|
||||
|
||||
static inline void net_analyze_stack_get_values(unsigned char *stack,
|
||||
size_t size,
|
||||
unsigned *stack_offset,
|
||||
unsigned *pcnt,
|
||||
unsigned *unused)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
*unused = 0;
|
||||
|
||||
/* The TCS is always placed on a 4-byte aligned boundary - if
|
||||
* the stack beginning doesn't match that there will be some
|
||||
* unused bytes in the beginning.
|
||||
*/
|
||||
*stack_offset = K_THREAD_SIZEOF + ((4 - ((unsigned)stack % 4)) % 4);
|
||||
|
||||
/* TODO
|
||||
* Currently all supported platforms have stack growth down and there is no
|
||||
* Kconfig option to configure it so this always build "else" branch.
|
||||
* When support for platform with stack direction up (or configurable direction)
|
||||
* is added this check should be confirmed that correct Kconfig option is used.
|
||||
*/
|
||||
#if defined(CONFIG_STACK_GROWS_UP)
|
||||
for (i = size - 1; i >= *stack_offset; i--) {
|
||||
if ((unsigned char)stack[i] == 0xaa) {
|
||||
(*unused)++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (i = *stack_offset; i < size; i++) {
|
||||
if ((unsigned char)stack[i] == 0xaa) {
|
||||
(*unused)++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Calculate the real size reserved for the stack */
|
||||
size -= *stack_offset;
|
||||
*pcnt = ((size - *unused) * 100) / size;
|
||||
}
|
||||
|
||||
static inline void net_analyze_stack(const char *name,
|
||||
unsigned char *stack,
|
||||
size_t size)
|
||||
{
|
||||
unsigned stack_offset, pcnt, unused;
|
||||
|
||||
net_analyze_stack_get_values(stack, size, &stack_offset,
|
||||
&pcnt, &unused);
|
||||
|
||||
NET_INFO("net (%p): %s stack real size %u "
|
||||
"unused %u usage %u/%u (%u %%)",
|
||||
k_current_get(), name,
|
||||
size + stack_offset, unused, size - unused, size, pcnt);
|
||||
}
|
||||
#else
|
||||
#define net_analyze_stack(...)
|
||||
#define net_analyze_stack_get_values(...)
|
||||
#endif
|
||||
/* @endcond */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NET_CORE_H */
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Network Events code public header
|
||||
*/
|
||||
|
||||
#ifndef __NET_EVENT_H__
|
||||
#define __NET_EVENT_H__
|
||||
|
||||
/* IPv6 Events */
|
||||
#define _NET_IPV6_LAYER NET_MGMT_LAYER_L3
|
||||
#define _NET_IPV6_CORE_CODE 0x600
|
||||
#define _NET_EVENT_IPV6_BASE (NET_MGMT_EVENT_BIT | \
|
||||
NET_MGMT_IFACE_BIT | \
|
||||
NET_MGMT_LAYER(_NET_IPV6_LAYER) | \
|
||||
NET_MGMT_LAYER_CODE(_NET_IPV6_CORE_CODE))
|
||||
|
||||
enum net_event_ipv6_cmd {
|
||||
NET_EVENT_IPV6_CMD_ADDR_ADD = 0,
|
||||
NET_EVENT_IPV6_CMD_ADDR_DEL,
|
||||
NET_EVENT_IPV6_CMD_MADDR_ADD,
|
||||
NET_EVENT_IPV6_CMD_MADDR_DEL,
|
||||
NET_EVENT_IPV6_CMD_PREFIX_ADD,
|
||||
NET_EVENT_IPV6_CMD_PREFIX_DEL,
|
||||
};
|
||||
|
||||
#define NET_EVENT_IPV6_ADDR_ADD \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_ADD)
|
||||
|
||||
#define NET_EVENT_IPV6_ADDR_DEL \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_DEL)
|
||||
|
||||
#define NET_EVENT_IPV6_MADDR_ADD \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MADDR_ADD)
|
||||
|
||||
#define NET_EVENT_IPV6_MADDR_DEL \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MADDR_DEL)
|
||||
|
||||
#define NET_EVENT_IPV6_PREFIX_ADD \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PREFIX_ADD)
|
||||
|
||||
#define NET_EVENT_IPV6_PREFIX_DEL \
|
||||
(_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PREFIX_DEL)
|
||||
|
||||
#define _NET_IPV4_LAYER NET_MGMT_LAYER_L3
|
||||
#define _NET_IPV4_CORE_CODE 0x400
|
||||
#define _NET_EVENT_IPV4_BASE (NET_MGMT_EVENT_BIT | \
|
||||
NET_MGMT_IFACE_BIT | \
|
||||
NET_MGMT_LAYER(_NET_IPV4_LAYER) | \
|
||||
NET_MGMT_LAYER_CODE(_NET_IPV4_CORE_CODE))
|
||||
|
||||
/* IPv4 Events*/
|
||||
enum net_event_ipv4_cmd {
|
||||
NET_EVENT_IPV4_CMD_ADDR_ADD = 0,
|
||||
NET_EVENT_IPV4_CMD_ADDR_DEL,
|
||||
NET_EVENT_IPV4_CMD_ROUTER_ADD,
|
||||
};
|
||||
|
||||
#define NET_EVENT_IPV4_ADDR_ADD \
|
||||
(_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ADDR_ADD)
|
||||
|
||||
#define NET_EVENT_IPV4_ADDR_DEL \
|
||||
(_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ADDR_DEL)
|
||||
|
||||
#define NET_EVENT_IPV4_ROUTER_ADD \
|
||||
(_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ROUTER_ADD)
|
||||
|
||||
#endif /* __NET_EVENT_H__ */
|
File diff suppressed because it is too large
Load diff
|
@ -1,797 +0,0 @@
|
|||
/** @file
|
||||
* @brief IPv6 and IPv4 definitions
|
||||
*
|
||||
* Generic IPv6 and IPv4 address definitions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __NET_IP_H
|
||||
#define __NET_IP_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <misc/byteorder.h>
|
||||
#include <toolchain.h>
|
||||
|
||||
#include <net/net_linkaddr.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Protocol families */
|
||||
#define PF_UNSPEC 0 /* Unspecified. */
|
||||
#define PF_INET 2 /* IP protocol family. */
|
||||
#define PF_INET6 10 /* IP version 6. */
|
||||
|
||||
/** Address families. */
|
||||
#define AF_UNSPEC PF_UNSPEC
|
||||
#define AF_INET PF_INET
|
||||
#define AF_INET6 PF_INET6
|
||||
|
||||
/** Protocol numbers from IANA */
|
||||
enum net_ip_protocol {
|
||||
IPPROTO_ICMP = 1,
|
||||
IPPROTO_TCP = 6,
|
||||
IPPROTO_UDP = 17,
|
||||
IPPROTO_ICMPV6 = 58,
|
||||
};
|
||||
|
||||
/** Socket type */
|
||||
enum net_sock_type {
|
||||
SOCK_DGRAM = 1,
|
||||
SOCK_STREAM,
|
||||
};
|
||||
|
||||
#define ntohs(x) sys_be16_to_cpu(x)
|
||||
#define ntohl(x) sys_be32_to_cpu(x)
|
||||
#define htons(x) sys_cpu_to_be16(x)
|
||||
#define htonl(x) sys_cpu_to_be32(x)
|
||||
|
||||
/** IPv6 address structure */
|
||||
struct in6_addr {
|
||||
union {
|
||||
uint8_t u6_addr8[16];
|
||||
uint16_t u6_addr16[8]; /* In big endian */
|
||||
uint32_t u6_addr32[4]; /* In big endian */
|
||||
} in6_u;
|
||||
#define s6_addr in6_u.u6_addr8
|
||||
#define s6_addr16 in6_u.u6_addr16
|
||||
#define s6_addr32 in6_u.u6_addr32
|
||||
};
|
||||
|
||||
/** IPv4 address */
|
||||
struct in_addr {
|
||||
union {
|
||||
uint8_t u4_addr8[4];
|
||||
uint16_t u4_addr16[2]; /* In big endian */
|
||||
uint32_t u4_addr32[1]; /* In big endian */
|
||||
} in4_u;
|
||||
#define s4_addr in4_u.u4_addr8
|
||||
#define s4_addr16 in4_u.u4_addr16
|
||||
#define s4_addr32 in4_u.u4_addr32
|
||||
|
||||
#define s_addr s4_addr32
|
||||
};
|
||||
|
||||
typedef unsigned short int sa_family_t;
|
||||
typedef size_t socklen_t;
|
||||
|
||||
/**
|
||||
* Note that the sin_port and sin6_port are in network byte order
|
||||
* in various sockaddr* structs.
|
||||
*/
|
||||
struct sockaddr_in6 {
|
||||
sa_family_t sin6_family; /* AF_INET6 */
|
||||
uint16_t sin6_port; /* Port number */
|
||||
struct in6_addr sin6_addr; /* IPv6 address */
|
||||
uint8_t sin6_scope_id; /* interfaces for a scope */
|
||||
};
|
||||
|
||||
struct sockaddr_in6_ptr {
|
||||
sa_family_t sin6_family; /* AF_INET6 */
|
||||
uint16_t sin6_port; /* Port number */
|
||||
struct in6_addr *sin6_addr; /* IPv6 address */
|
||||
uint8_t sin6_scope_id; /* interfaces for a scope */
|
||||
};
|
||||
|
||||
struct sockaddr_in {
|
||||
sa_family_t sin_family; /* AF_INET */
|
||||
uint16_t sin_port; /* Port number */
|
||||
struct in_addr sin_addr; /* IPv4 address */
|
||||
};
|
||||
|
||||
struct sockaddr_in_ptr {
|
||||
sa_family_t sin_family; /* AF_INET */
|
||||
uint16_t sin_port; /* Port number */
|
||||
struct in_addr *sin_addr; /* IPv4 address */
|
||||
};
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
#define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_in6))
|
||||
#define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_in6_ptr))
|
||||
#elif defined(CONFIG_NET_IPV4)
|
||||
#define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_in))
|
||||
#define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_in_ptr))
|
||||
#else
|
||||
#if !defined(CONFIG_NET_L2_RAW_CHANNEL)
|
||||
#error "Either IPv6 or IPv4 needs to be selected."
|
||||
#else
|
||||
#define NET_SOCKADDR_MAX_SIZE (sizeof(struct sockaddr_in6))
|
||||
#define NET_SOCKADDR_PTR_MAX_SIZE (sizeof(struct sockaddr_in6_ptr))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct sockaddr {
|
||||
sa_family_t family;
|
||||
char data[NET_SOCKADDR_MAX_SIZE - sizeof(sa_family_t)];
|
||||
};
|
||||
|
||||
struct sockaddr_ptr {
|
||||
sa_family_t family;
|
||||
char data[NET_SOCKADDR_PTR_MAX_SIZE - sizeof(sa_family_t)];
|
||||
};
|
||||
|
||||
struct net_addr {
|
||||
sa_family_t family;
|
||||
union {
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
struct in6_addr in6_addr;
|
||||
#endif
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
struct in_addr in_addr;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
#define IN6ADDR_ANY_INIT { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0 } } }
|
||||
#define IN6ADDR_LOOPBACK_INIT { { { 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1 } } }
|
||||
|
||||
#define INET6_ADDRSTRLEN 46
|
||||
#define NET_IPV6_ADDR_LEN sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")
|
||||
#define NET_IPV4_ADDR_LEN sizeof("xxx.xxx.xxx.xxx")
|
||||
|
||||
#define INADDR_ANY 0
|
||||
|
||||
#define NET_IPV6_MTU 1280
|
||||
|
||||
/** IPv6 extension headers types */
|
||||
#define NET_IPV6_NEXTHDR_HBHO 0
|
||||
#define NET_IPV6_NEXTHDR_DESTO 60
|
||||
#define NET_IPV6_NEXTHDR_ROUTING 43
|
||||
#define NET_IPV6_NEXTHDR_FRAG 44
|
||||
#define NET_IPV6_NEXTHDR_NONE 59
|
||||
|
||||
/** IPv6/IPv4 network connection tuple */
|
||||
struct net_tuple {
|
||||
/** IPv6/IPv4 remote address */
|
||||
struct net_addr *remote_addr;
|
||||
/** IPv6/IPv4 local address */
|
||||
struct net_addr *local_addr;
|
||||
/** UDP/TCP remote port */
|
||||
uint16_t remote_port;
|
||||
/** UDP/TCP local port */
|
||||
uint16_t local_port;
|
||||
/** IP protocol */
|
||||
enum net_ip_protocol ip_proto;
|
||||
};
|
||||
|
||||
/** How the network address is assigned to network interface */
|
||||
enum net_addr_type {
|
||||
NET_ADDR_ANY = 0,
|
||||
NET_ADDR_AUTOCONF,
|
||||
NET_ADDR_DHCP,
|
||||
NET_ADDR_MANUAL,
|
||||
};
|
||||
|
||||
#if NET_DEBUG > 0
|
||||
static inline char *net_addr_type2str(enum net_addr_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case NET_ADDR_AUTOCONF:
|
||||
return "AUTO";
|
||||
case NET_ADDR_DHCP:
|
||||
return "DHCP";
|
||||
case NET_ADDR_MANUAL:
|
||||
return "MANUAL";
|
||||
case NET_ADDR_ANY:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "<unknown>";
|
||||
}
|
||||
#else
|
||||
static inline char *net_addr_type2str(enum net_addr_type type)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** What is the current state of the network address */
|
||||
enum net_addr_state {
|
||||
NET_ADDR_ANY_STATE = -1,
|
||||
NET_ADDR_TENTATIVE = 0,
|
||||
NET_ADDR_PREFERRED,
|
||||
NET_ADDR_DEPRECATED,
|
||||
};
|
||||
|
||||
struct net_ipv6_hdr {
|
||||
uint8_t vtc;
|
||||
uint8_t tcflow;
|
||||
uint16_t flow;
|
||||
uint8_t len[2];
|
||||
uint8_t nexthdr;
|
||||
uint8_t hop_limit;
|
||||
struct in6_addr src;
|
||||
struct in6_addr dst;
|
||||
} __packed;
|
||||
|
||||
struct net_ipv4_hdr {
|
||||
uint8_t vhl;
|
||||
uint8_t tos;
|
||||
uint8_t len[2];
|
||||
uint8_t id[2];
|
||||
uint8_t offset[2];
|
||||
uint8_t ttl;
|
||||
uint8_t proto;
|
||||
uint16_t chksum;
|
||||
struct in_addr src;
|
||||
struct in_addr dst;
|
||||
} __packed;
|
||||
|
||||
struct net_icmp_hdr {
|
||||
uint8_t type;
|
||||
uint8_t code;
|
||||
uint16_t chksum;
|
||||
} __packed;
|
||||
|
||||
struct net_udp_hdr {
|
||||
uint16_t src_port;
|
||||
uint16_t dst_port;
|
||||
uint16_t len;
|
||||
uint16_t chksum;
|
||||
} __packed;
|
||||
|
||||
struct net_tcp_hdr {
|
||||
uint16_t src_port;
|
||||
uint16_t dst_port;
|
||||
uint8_t seq[4];
|
||||
uint8_t ack[4];
|
||||
uint8_t offset;
|
||||
uint8_t flags;
|
||||
uint8_t wnd[2];
|
||||
uint16_t chksum;
|
||||
uint8_t urg[2];
|
||||
uint8_t optdata[0];
|
||||
} __packed;
|
||||
|
||||
#define NET_UDPH_LEN 8 /* Size of UDP header */
|
||||
#define NET_TCPH_LEN 20 /* Size of TCP header */
|
||||
#define NET_ICMPH_LEN 4 /* Size of ICMP header */
|
||||
|
||||
#define NET_IPV6H_LEN 40 /* Size of IPv6 header */
|
||||
#define NET_ICMPV6H_LEN NET_ICMPH_LEN /* Size of ICMPv6 header */
|
||||
#define NET_IPV6UDPH_LEN (NET_UDPH_LEN + NET_IPV6H_LEN) /* IPv6 + UDP */
|
||||
#define NET_IPV6TCPH_LEN (NET_TCPH_LEN + NET_IPV6H_LEN) /* IPv6 + TCP */
|
||||
#define NET_IPV6ICMPH_LEN (NET_IPV6H_LEN + NET_ICMPH_LEN) /* ICMPv6 + IPv6 */
|
||||
#define NET_IPV6_FRAGH_LEN 8
|
||||
|
||||
#define NET_IPV4H_LEN 20 /* Size of IPv4 header */
|
||||
#define NET_ICMPV4H_LEN NET_ICMPH_LEN /* Size of ICMPv4 header */
|
||||
#define NET_IPV4UDPH_LEN (NET_UDPH_LEN + NET_IPV4H_LEN) /* IPv4 + UDP */
|
||||
#define NET_IPV4TCPH_LEN (NET_TCPH_LEN + NET_IPV4H_LEN) /* IPv4 + TCP */
|
||||
#define NET_IPV4ICMPH_LEN (NET_IPV4H_LEN + NET_ICMPH_LEN) /* ICMPv4 + IPv4 */
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv6 address is a loopback address (::1).
|
||||
*
|
||||
* @param addr IPv6 address
|
||||
*
|
||||
* @return True if address is a loopback address, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv6_addr_loopback(struct in6_addr *addr)
|
||||
{
|
||||
return addr->s6_addr32[0] == 0 &&
|
||||
addr->s6_addr32[1] == 0 &&
|
||||
addr->s6_addr32[2] == 0 &&
|
||||
ntohl(addr->s6_addr32[3]) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv6 address is a multicast address.
|
||||
*
|
||||
* @param addr IPv6 address
|
||||
*
|
||||
* @return True if address is multicast address, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv6_addr_mcast(const struct in6_addr *addr)
|
||||
{
|
||||
return addr->s6_addr[0] == 0xFF;
|
||||
}
|
||||
|
||||
struct net_if;
|
||||
|
||||
extern struct net_if_addr *net_if_ipv6_addr_lookup(const struct in6_addr *addr,
|
||||
struct net_if **iface);
|
||||
|
||||
/**
|
||||
* @brief Check if IPv6 address is found in one of the network interfaces.
|
||||
*
|
||||
* @param addr IPv6 address
|
||||
*
|
||||
* @return True if address was found, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_my_ipv6_addr(struct in6_addr *addr)
|
||||
{
|
||||
return net_if_ipv6_addr_lookup(addr, NULL) != NULL;
|
||||
}
|
||||
|
||||
extern struct net_if_mcast_addr *net_if_ipv6_maddr_lookup(const struct in6_addr *addr,
|
||||
struct net_if **iface);
|
||||
|
||||
/**
|
||||
* @brief Check if IPv6 multicast address is found in one of the
|
||||
* network interfaces.
|
||||
*
|
||||
* @param maddr Multicast IPv6 address
|
||||
*
|
||||
* @return True if address was found, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_my_ipv6_maddr(struct in6_addr *maddr)
|
||||
{
|
||||
return net_if_ipv6_maddr_lookup(maddr, NULL) != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if two IPv6 addresses are same when compared after prefix mask.
|
||||
*
|
||||
* @param addr1 First IPv6 address.
|
||||
* @param addr2 Second IPv6 address.
|
||||
* @param length Prefix length (max length is 128).
|
||||
*
|
||||
* @return True if addresses are the same, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv6_prefix(const uint8_t *addr1,
|
||||
const uint8_t *addr2,
|
||||
uint8_t length)
|
||||
{
|
||||
uint8_t bits = 128 - length;
|
||||
uint8_t bytes = bits / 8;
|
||||
uint8_t remain = bits % 8;
|
||||
|
||||
if (length > 128) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(addr1, addr2, 16 - bytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((addr1[16 - bytes] & ((8 - remain) << 8))
|
||||
==
|
||||
(addr2[16 - bytes] & ((8 - remain) << 8)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv4 address is a loopback address (127.0.0.0/8).
|
||||
*
|
||||
* @param addr IPv4 address
|
||||
*
|
||||
* @return True if address is a loopback address, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv4_addr_loopback(struct in_addr *addr)
|
||||
{
|
||||
return addr->s4_addr[0] == 127;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv4 address is unspecified (all bits zero)
|
||||
*
|
||||
* @param addr IPv4 address.
|
||||
*
|
||||
* @return True if the address is unspecified, false otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv4_addr_unspecified(const struct in_addr *addr)
|
||||
{
|
||||
return addr->s_addr[0] == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv4 address is a multicast address.
|
||||
*
|
||||
* @param addr IPv4 address
|
||||
*
|
||||
* @return True if address is multicast address, False otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv4_addr_mcast(const struct in_addr *addr)
|
||||
{
|
||||
return (addr->s_addr[0] & 0xE0000000) == 0xE0000000;
|
||||
}
|
||||
|
||||
extern struct net_if_addr *net_if_ipv4_addr_lookup(const struct in_addr *addr,
|
||||
struct net_if **iface);
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv4 address is assigned to any network interface
|
||||
* in the system.
|
||||
*
|
||||
* @param addr A valid pointer on an IPv4 address
|
||||
*
|
||||
* @return True if IPv4 address is found in one of the network interfaces,
|
||||
* False otherwise.
|
||||
*/
|
||||
static inline bool net_is_my_ipv4_addr(const struct in_addr *addr)
|
||||
{
|
||||
return net_if_ipv4_addr_lookup(addr, NULL) != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @def net_ipaddr_copy
|
||||
* @brief Copy an IPv4 or IPv6 address
|
||||
*
|
||||
* @param dest Destination IP address.
|
||||
* @param src Source IP address.
|
||||
*
|
||||
* @return Destination address.
|
||||
*/
|
||||
#define net_ipaddr_copy(dest, src) \
|
||||
UNALIGNED_PUT(UNALIGNED_GET(src), dest)
|
||||
|
||||
/**
|
||||
* @brief Compare two IPv4 addresses
|
||||
*
|
||||
* @param addr1 Pointer to IPv4 address.
|
||||
* @param addr2 Pointer to IPv4 address.
|
||||
*
|
||||
* @return True if the addresses are the same, false otherwise.
|
||||
*/
|
||||
static inline bool net_ipv4_addr_cmp(const struct in_addr *addr1,
|
||||
const struct in_addr *addr2)
|
||||
{
|
||||
return addr1->s_addr[0] == addr2->s_addr[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare two IPv6 addresses
|
||||
*
|
||||
* @param addr1 Pointer to IPv6 address.
|
||||
* @param addr2 Pointer to IPv6 address.
|
||||
*
|
||||
* @return True if the addresses are the same, false otherwise.
|
||||
*/
|
||||
static inline bool net_ipv6_addr_cmp(const struct in6_addr *addr1,
|
||||
const struct in6_addr *addr2)
|
||||
{
|
||||
return !memcmp(addr1, addr2, sizeof(struct in6_addr));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the given IPv6 address is a link local address.
|
||||
*
|
||||
* @param addr A valid pointer on an IPv6 address
|
||||
*
|
||||
* @return True if it is, false otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv6_ll_addr(const struct in6_addr *addr)
|
||||
{
|
||||
return ((addr->s6_addr[0]) == 0xFE) &&
|
||||
((addr->s6_addr[1]) == 0x80);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return pointer to any (all bits zeros) IPv6 address.
|
||||
*
|
||||
* @return Any IPv6 address.
|
||||
*/
|
||||
const struct in6_addr *net_ipv6_unspecified_address(void);
|
||||
|
||||
/**
|
||||
* @brief Return pointer to any (all bits zeros) IPv4 address.
|
||||
*
|
||||
* @return Any IPv4 address.
|
||||
*/
|
||||
const struct in_addr *net_ipv4_unspecified_address(void);
|
||||
|
||||
/**
|
||||
* @brief Return pointer to broadcast (all bits ones) IPv4 address.
|
||||
*
|
||||
* @return Broadcast IPv4 address.
|
||||
*/
|
||||
const struct in_addr *net_ipv4_broadcast_address(void);
|
||||
|
||||
struct net_if;
|
||||
extern bool net_if_ipv4_addr_mask_cmp(struct net_if *iface,
|
||||
struct in_addr *addr);
|
||||
|
||||
/**
|
||||
* @brief Check if the given address belongs to same subnet that
|
||||
* has been configured for the interface.
|
||||
*
|
||||
* @param iface A valid pointer on an interface
|
||||
* @param addr pointer on an address
|
||||
*
|
||||
* @return True if address is in same subnet, false otherwise.
|
||||
*/
|
||||
static inline bool net_ipv4_addr_mask_cmp(struct net_if *iface,
|
||||
struct in_addr *addr)
|
||||
{
|
||||
return net_if_ipv4_addr_mask_cmp(iface, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv6 address is unspecified (all bits zero)
|
||||
*
|
||||
* @param addr IPv6 address.
|
||||
*
|
||||
* @return True if the address is unspecified, false otherwise.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv6 address is solicited node multicast address
|
||||
* FF02:0:0:0:0:1:FFXX:XXXX defined in RFC 3513
|
||||
*
|
||||
* @param addr IPv6 address.
|
||||
*
|
||||
* @return True if the address is solicited node address, false otherwise.
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the IPv6 address is a global multicast address (FFxE::/16).
|
||||
*
|
||||
* @param addr IPv6 address.
|
||||
*
|
||||
* @return True if the address is global multicast address, false otherwise.
|
||||
*/
|
||||
static inline bool net_is_ipv6_addr_mcast_global(const struct in6_addr *addr)
|
||||
{
|
||||
return addr->s6_addr[0] == 0xff &&
|
||||
(addr->s6_addr[1] & 0x0e) == 0x0e;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create solicited node IPv6 multicast address
|
||||
* FF02:0:0:0:0:1:FFXX:XXXX defined in RFC 3513
|
||||
*
|
||||
* @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)
|
||||
{
|
||||
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;
|
||||
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];
|
||||
}
|
||||
|
||||
/** @brief Construct an IPv6 address from eight 16-bit words.
|
||||
*
|
||||
* @param addr IPv6 address
|
||||
* @param addr0 16-bit word which is part of the address
|
||||
* @param addr1 16-bit word which is part of the address
|
||||
* @param addr2 16-bit word which is part of the address
|
||||
* @param addr3 16-bit word which is part of the address
|
||||
* @param addr4 16-bit word which is part of the address
|
||||
* @param addr5 16-bit word which is part of the address
|
||||
* @param addr6 16-bit word which is part of the address
|
||||
* @param addr7 16-bit word which is part of the address
|
||||
*/
|
||||
static inline void net_ipv6_addr_create(struct in6_addr *addr,
|
||||
uint16_t addr0, uint16_t addr1,
|
||||
uint16_t addr2, uint16_t addr3,
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create link local allnodes multicast IPv6 address
|
||||
*
|
||||
* @param addr IPv6 address
|
||||
*/
|
||||
static inline void net_ipv6_addr_create_ll_allnodes_mcast(struct in6_addr *addr)
|
||||
{
|
||||
net_ipv6_addr_create(addr, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create IPv6 address interface identifier
|
||||
*
|
||||
* @param addr IPv6 address
|
||||
* @param lladdr Link local address
|
||||
*/
|
||||
static inline void net_ipv6_addr_create_iid(struct in6_addr *addr,
|
||||
struct net_linkaddr *lladdr)
|
||||
{
|
||||
addr->s6_addr[0] = 0xfe;
|
||||
addr->s6_addr[1] = 0x80;
|
||||
addr->s6_addr16[1] = 0;
|
||||
addr->s6_addr32[1] = 0;
|
||||
|
||||
switch (lladdr->len) {
|
||||
case 2:
|
||||
addr->s6_addr32[2] = 0;
|
||||
addr->s6_addr[11] = 0xff;
|
||||
addr->s6_addr[12] = 0xfe;
|
||||
addr->s6_addr[13] = 0;
|
||||
addr->s6_addr[14] = lladdr->addr[0];
|
||||
addr->s6_addr[15] = lladdr->addr[1];
|
||||
addr->s6_addr[8] ^= 0x02;
|
||||
break;
|
||||
case 6:
|
||||
memcpy(&addr->s6_addr[8], lladdr->addr, 3);
|
||||
addr->s6_addr[11] = 0xff;
|
||||
addr->s6_addr[12] = 0xfe;
|
||||
memcpy(&addr->s6_addr[13], lladdr->addr + 3, 3);
|
||||
addr->s6_addr[8] ^= 0x02;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
memcpy(&addr->s6_addr[8], lladdr->addr, lladdr->len);
|
||||
addr->s6_addr[8] ^= 0x02;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if given address is based on link layer address
|
||||
*
|
||||
* @return True if it is, False otherwise
|
||||
*/
|
||||
static inline bool net_ipv6_addr_based_on_ll(const struct in6_addr *addr,
|
||||
const struct net_linkaddr *lladdr)
|
||||
{
|
||||
switch (lladdr->len) {
|
||||
case 2:
|
||||
if (!memcmp(&addr->s6_addr[14], lladdr->addr, lladdr->len) &&
|
||||
(addr->s6_addr[8] ^ 0x02) == lladdr->addr[0] &&
|
||||
addr->s6_addr[11] == 0xff &&
|
||||
addr->s6_addr[12] == 0xfe) {
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case 6:
|
||||
if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1], 2) &&
|
||||
!memcmp(&addr->s6_addr[13], &lladdr->addr[3], 3) &&
|
||||
addr->s6_addr[11] == 0xff &&
|
||||
addr->s6_addr[12] == 0xfe &&
|
||||
(addr->s6_addr[8] ^ 0x02) == lladdr->addr[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
case 8:
|
||||
if (!memcmp(&addr->s6_addr[9], &lladdr->addr[1],
|
||||
lladdr->len - 1) &&
|
||||
(addr->s6_addr[8] ^ 0x02) == lladdr->addr[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sockaddr_in6 from sockaddr. This is a helper so that
|
||||
* the code calling this function can be made shorter.
|
||||
*
|
||||
* @param addr Socket address
|
||||
*
|
||||
* @return Pointer to IPv6 socket address
|
||||
*/
|
||||
static inline struct sockaddr_in6 *net_sin6(const struct sockaddr *addr)
|
||||
{
|
||||
return (struct sockaddr_in6 *)addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sockaddr_in from sockaddr. This is a helper so that
|
||||
* the code calling this function can be made shorter.
|
||||
*
|
||||
* @param addr Socket address
|
||||
*
|
||||
* @return Pointer to IPv4 socket address
|
||||
*/
|
||||
static inline struct sockaddr_in *net_sin(const struct sockaddr *addr)
|
||||
{
|
||||
return (struct sockaddr_in *)addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sockaddr_in6_ptr from sockaddr_ptr. This is a helper so that
|
||||
* the code calling this function can be made shorter.
|
||||
*
|
||||
* @param addr Socket address
|
||||
*
|
||||
* @return Pointer to IPv6 socket address
|
||||
*/
|
||||
static inline
|
||||
struct sockaddr_in6_ptr *net_sin6_ptr(const struct sockaddr_ptr *addr)
|
||||
{
|
||||
return (struct sockaddr_in6_ptr *)addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get sockaddr_in_ptr from sockaddr_ptr. This is a helper so that
|
||||
* the code calling this function can be made shorter.
|
||||
*
|
||||
* @param addr Socket address
|
||||
*
|
||||
* @return Pointer to IPv4 socket address
|
||||
*/
|
||||
static inline
|
||||
struct sockaddr_in_ptr *net_sin_ptr(const struct sockaddr_ptr *addr)
|
||||
{
|
||||
return (struct sockaddr_in_ptr *)addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a string to IP address.
|
||||
*
|
||||
* @param family IP address family (AF_INET or AF_INET6)
|
||||
* @param src IP address in a null terminated string
|
||||
* @param dst Pointer to struct in_addr if family is AF_INET or
|
||||
* pointer to struct in6_addr if family is AF_INET6
|
||||
*
|
||||
* @note This function doesn't do precise error checking,
|
||||
* do not use for untrusted strings.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
int net_addr_pton(sa_family_t family, const char *src,
|
||||
struct sockaddr *dst);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NET_IP_H */
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Public API for network L2 interface
|
||||
*/
|
||||
|
||||
#ifndef __NET_L2_H__
|
||||
#define __NET_L2_H__
|
||||
|
||||
#include <net/buf.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct net_if;
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
struct net_l2_offload_ip;
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
|
||||
struct net_l2 {
|
||||
/**
|
||||
* This function is used by net core to get iface's L2 layer parsing
|
||||
* what's relevant to itself.
|
||||
*/
|
||||
enum net_verdict (*recv)(struct net_if *iface, struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* This function is used by net core to push a buffer to lower layer
|
||||
* (interface's L2), which in turn might work on the buffer relevantly.
|
||||
* (adding proper header etc...)
|
||||
*/
|
||||
enum net_verdict (*send)(struct net_if *iface, struct net_buf *buf);
|
||||
|
||||
/**
|
||||
* This function is used to get the amount of bytes the net core should
|
||||
* reserve as headroom in a net buffer. Such space is relevant to L2
|
||||
* layer only.
|
||||
*/
|
||||
uint16_t (*reserve)(struct net_if *iface, void *data);
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
struct net_l2_offload_ip *offload_ip;
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
};
|
||||
|
||||
#define NET_L2_GET_NAME(_name) (__net_l2_##_name)
|
||||
#define NET_L2_DECLARE_PUBLIC(_name) \
|
||||
extern const struct net_l2 const NET_L2_GET_NAME(_name)
|
||||
#define NET_L2_GET_CTX_TYPE(_name) _name##_CTX_TYPE
|
||||
|
||||
extern struct net_l2 __net_l2_start[];
|
||||
|
||||
#ifdef CONFIG_NET_L2_DUMMY
|
||||
#define DUMMY_L2 DUMMY
|
||||
#define DUMMY_L2_CTX_TYPE void*
|
||||
NET_L2_DECLARE_PUBLIC(DUMMY_L2);
|
||||
#endif /* CONFIG_NET_L2_DUMMY */
|
||||
|
||||
#ifdef CONFIG_NET_L2_ETHERNET
|
||||
#define ETHERNET_L2 ETHERNET
|
||||
#define ETHERNET_L2_CTX_TYPE void*
|
||||
NET_L2_DECLARE_PUBLIC(ETHERNET_L2);
|
||||
#endif /* CONFIG_NET_L2_ETHERNET */
|
||||
|
||||
#ifdef CONFIG_NET_L2_IEEE802154
|
||||
#include <net/ieee802154.h>
|
||||
#define IEEE802154_L2 IEEE802154
|
||||
#define IEEE802154_L2_CTX_TYPE struct ieee802154_context
|
||||
NET_L2_DECLARE_PUBLIC(IEEE802154_L2);
|
||||
#endif /* CONFIG_NET_L2_IEEE802154 */
|
||||
|
||||
#ifdef CONFIG_NET_L2_BLUETOOTH
|
||||
#define BLUETOOTH_L2 BLUETOOTH
|
||||
#define BLUETOOTH_L2_CTX_TYPE void*
|
||||
#endif /* CONFIG_NET_L2_BLUETOOTH */
|
||||
|
||||
#ifdef CONFIG_NET_L2_OFFLOAD_IP
|
||||
#define OFFLOAD_IP_L2 OFFLOAD_IP
|
||||
#define OFFLOAD_IP_L2_CTX_TYPE void*
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
|
||||
extern struct net_l2 __net_l2_end[];
|
||||
|
||||
#define NET_L2_INIT(_name, _recv_fn, _send_fn, _reserve_fn) \
|
||||
const struct net_l2 const (NET_L2_GET_NAME(_name)) __used \
|
||||
__attribute__((__section__(".net_l2.init"))) = { \
|
||||
.recv = (_recv_fn), \
|
||||
.send = (_send_fn), \
|
||||
.reserve = (_reserve_fn), \
|
||||
}
|
||||
|
||||
#define NET_L2_GET_DATA(name, sfx) (__net_l2_data_##name##sfx)
|
||||
|
||||
#define NET_L2_DATA_INIT(name, sfx, ctx_type) \
|
||||
static ctx_type NET_L2_GET_DATA(name, sfx) __used \
|
||||
__attribute__((__section__(".net_l2.data")));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NET_L2_H__ */
|
|
@ -1,182 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Network Management API public header
|
||||
*/
|
||||
|
||||
#ifndef __NET_MGMT_H__
|
||||
#define __NET_MGMT_H__
|
||||
|
||||
#include <misc/__assert.h>
|
||||
#include <net/net_core.h>
|
||||
|
||||
struct net_if;
|
||||
|
||||
/**
|
||||
* @brief NET MGMT event mask basics, normalizing parts of bit fields
|
||||
*/
|
||||
#define NET_MGMT_EVENT_MASK 0x80000000
|
||||
#define NET_MGMT_ON_IFACE_MASK 0x40000000
|
||||
#define NET_MGMT_LAYER_MASK 0x30000000
|
||||
#define NET_MGMT_LAYER_CODE_MASK 0x0FFF0000
|
||||
#define NET_MGMT_COMMAND_MASK 0x0000FFFF
|
||||
|
||||
#define NET_MGMT_EVENT_BIT BIT(31)
|
||||
#define NET_MGMT_IFACE_BIT BIT(30)
|
||||
|
||||
#define NET_MGMT_LAYER(_layer) (_layer << 28)
|
||||
#define NET_MGMT_LAYER_CODE(_code) (_code << 16)
|
||||
|
||||
#define NET_MGMT_EVENT(mgmt_request) \
|
||||
(mgmt_request & NET_MGMT_EVENT_MASK)
|
||||
|
||||
#define NET_MGMT_ON_IFACE(mgmt_request) \
|
||||
(mgmt_request & NET_MGMT_ON_IFACE_MASK)
|
||||
|
||||
#define NET_MGMT_GET_LAYER(mgmt_request) \
|
||||
(mgmt_request & NET_MGMT_LAYER_MASK)
|
||||
|
||||
#define NET_MGMT_GET_LAYER_CODE(mgmt_request) \
|
||||
(mgmt_request & NET_MGMT_LAYER_CODE_MASK)
|
||||
|
||||
#define NET_MGMT_GET_COMMAND(mgmt_request) \
|
||||
(mgmt_request & NET_MGMT_COMMAND_MASK)
|
||||
|
||||
|
||||
/* Useful generic definitions */
|
||||
#define NET_MGMT_LAYER_L1 1
|
||||
#define NET_MGMT_LAYER_L2 2
|
||||
#define NET_MGMT_LAYER_L3 3
|
||||
|
||||
#include <net/net_event.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Signature which all Net MGMT request handler need to follow
|
||||
* @param mgmt_request The exact request value the handler is being called
|
||||
* through
|
||||
* @param iface A valid pointer on struct net_if if the request is meant
|
||||
* to be tight to a network interface. NULL otherwise.
|
||||
* @param data A valid pointer on a data understood by the handler.
|
||||
* NULL otherwise.
|
||||
* @param len Length in byte of the memory pointed by data.
|
||||
*/
|
||||
typedef int (*net_mgmt_request_handler_t)(uint32_t mgmt_request,
|
||||
struct net_if *iface,
|
||||
void *data, size_t len);
|
||||
|
||||
#define net_mgmt(_mgmt_request, _iface, _data, _len) \
|
||||
net_mgmt_##_mgmt_request(_mgmt_request, _iface, _data, _len)
|
||||
|
||||
#define NET_MGMT_DEFINE_REQUEST_HANDLER(_mgmt_request) \
|
||||
extern int net_mgmt_##_mgmt_request(uint32_t mgmt_request, \
|
||||
struct net_if *iface, \
|
||||
void *data, size_t len)
|
||||
|
||||
#define NET_MGMT_REGISTER_REQUEST_HANDLER(_mgmt_request, _func) \
|
||||
FUNC_ALIAS(_func, net_mgmt_##_mgmt_request, int)
|
||||
|
||||
struct net_mgmt_event_callback;
|
||||
|
||||
/**
|
||||
* @typedef net_mgmt_event_handler_t
|
||||
* @brief Define the user's callback handler function signature
|
||||
* @param "struct net_mgmt_event_callback *cb"
|
||||
* Original struct net_mgmt_event_callback owning this handler.
|
||||
* @param "uint32_t mgmt_event" The network event being notified.
|
||||
* @param "struct net_if *iface" A pointer on a struct net_if to which the
|
||||
* the event belongs to, if it's an event on an iface. NULL otherwise.
|
||||
*/
|
||||
typedef void (*net_mgmt_event_handler_t)(struct net_mgmt_event_callback *cb,
|
||||
uint32_t mgmt_event,
|
||||
struct net_if *iface);
|
||||
|
||||
/**
|
||||
* @brief Network Management event callback structure
|
||||
* Used to register a callback into the network management event part, in order
|
||||
* to let the owner of this struct to get network event notification based on
|
||||
* given event mask.
|
||||
*/
|
||||
struct net_mgmt_event_callback {
|
||||
/** Meant to be used internally, to insert the callback into a list.
|
||||
* So nobody should mess with it.
|
||||
*/
|
||||
sys_snode_t node;
|
||||
|
||||
/** Actual callback function being used to notify the owner
|
||||
*/
|
||||
net_mgmt_event_handler_t handler;
|
||||
|
||||
/** A mask of network events on which the above handler should be
|
||||
* called in case those events come. Such mask can be modified
|
||||
* whenever necessary by the owner, and thus will affect the handler
|
||||
* being called or not.
|
||||
*/
|
||||
uint32_t event_mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Helper to initialize a struct net_mgmt_event_callback properly
|
||||
* @param cb A valid application's callback structure pointer.
|
||||
* @param handler A valid handler function pointer.
|
||||
* @param mgmt_event_mask A mask of relevant events for the handler
|
||||
*/
|
||||
static inline
|
||||
void net_mgmt_init_event_callback(struct net_mgmt_event_callback *cb,
|
||||
net_mgmt_event_handler_t handler,
|
||||
uint32_t mgmt_event_mask)
|
||||
{
|
||||
__ASSERT(cb, "Callback pointer should not be NULL");
|
||||
__ASSERT(handler, "Handler pointer should not be NULL");
|
||||
|
||||
cb->handler = handler;
|
||||
cb->event_mask = mgmt_event_mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Add a user callback
|
||||
* @param cb A valid pointer on user's callback to add.
|
||||
*/
|
||||
void net_mgmt_add_event_callback(struct net_mgmt_event_callback *cb);
|
||||
|
||||
/**
|
||||
* @brief Delete a user callback
|
||||
* @param cb A valid pointer on user's callback to delete.
|
||||
*/
|
||||
void net_mgmt_del_event_callback(struct net_mgmt_event_callback *cb);
|
||||
|
||||
#ifdef CONFIG_NET_MGMT_EVENT
|
||||
/**
|
||||
* @brief Used by the system to notify an event.
|
||||
* @param mgmt_event The actual network event code to notify
|
||||
* @param iface a valid pointer on a struct net_if if only the event is
|
||||
* based on an iface. NULL otherwise.
|
||||
*/
|
||||
void net_mgmt_event_notify(uint32_t mgmt_event, struct net_if *iface);
|
||||
|
||||
/**
|
||||
* @brief Used by the core of the network stack to initialize the network
|
||||
* event processing.
|
||||
*/
|
||||
void net_mgmt_event_init(void);
|
||||
#else
|
||||
#define net_mgmt_event_notify(...)
|
||||
#define net_mgmt_event_init(...)
|
||||
#endif /* CONFIG_NET_MGMT_EVENT */
|
||||
|
||||
#endif /* __NET_MGMT_H__ */
|
|
@ -1,449 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Public API for offloading IP stack
|
||||
*/
|
||||
|
||||
#ifndef __OFFLOAD_IP_H__
|
||||
#define __OFFLOAD_IP_H__
|
||||
|
||||
#if defined(CONFIG_NET_L2_OFFLOAD_IP)
|
||||
|
||||
#include <net/buf.h>
|
||||
#include <net/net_ip.h>
|
||||
#include <net/net_context.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** For return parameters and return values of the elements in this
|
||||
* struct, see similarly named functions in net_context.h
|
||||
*/
|
||||
struct net_l2_offload_ip {
|
||||
/**
|
||||
* This function is called when the socket is to be opened.
|
||||
*/
|
||||
int (*get)(sa_family_t family,
|
||||
enum net_sock_type type,
|
||||
enum net_ip_protocol ip_proto,
|
||||
struct net_context **context);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to bind to local IP address.
|
||||
*/
|
||||
int (*bind)(struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to mark the socket
|
||||
* to be a listening one.
|
||||
*/
|
||||
int (*listen)(struct net_context *context, int backlog);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to create a connection
|
||||
* to a peer host.
|
||||
*/
|
||||
int (*connect)(struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
net_context_connect_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to accept a connection
|
||||
* being established.
|
||||
*/
|
||||
int (*accept)(struct net_context *context,
|
||||
net_context_accept_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to send data to peer host.
|
||||
*/
|
||||
int (*send)(struct net_buf *buf,
|
||||
net_context_send_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *token,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to send data to peer host.
|
||||
*/
|
||||
int (*sendto)(struct net_buf *buf,
|
||||
const struct sockaddr *dst_addr,
|
||||
socklen_t addrlen,
|
||||
net_context_send_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *token,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to receive data from peer
|
||||
* host.
|
||||
*/
|
||||
int (*recv)(struct net_context *context,
|
||||
net_context_recv_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* This function is called when user wants to close the socket.
|
||||
*/
|
||||
int (*put)(struct net_context *context);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get a network socket/context from the offloaded IP stack.
|
||||
*
|
||||
* @details Network socket is used to define the connection
|
||||
* 5-tuple (protocol, remote address, remote port, source
|
||||
* address and source port). This is similar as BSD socket()
|
||||
* function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param family IP address family (AF_INET or AF_INET6)
|
||||
* @param type Type of the socket, SOCK_STREAM or SOCK_DGRAM
|
||||
* @param ip_proto IP protocol, IPPROTO_UDP or IPPROTO_TCP
|
||||
* @param context The allocated context is returned to the caller.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_get(struct net_if *iface,
|
||||
sa_family_t family,
|
||||
enum net_sock_type type,
|
||||
enum net_ip_protocol ip_proto,
|
||||
struct net_context **context)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->get);
|
||||
|
||||
return iface->l2->offload_ip->get(family, type, ip_proto, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assign a socket a local address.
|
||||
*
|
||||
* @details This is similar as BSD bind() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param context The context to be assigned.
|
||||
* @param addr Address to assigned.
|
||||
* @param addrlen Length of the address.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_bind(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->bind);
|
||||
|
||||
return iface->l2->offload_ip->bind(context, addr, addrlen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Mark the context as a listening one.
|
||||
*
|
||||
* @details This is similar as BSD listen() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param context The context to use.
|
||||
* @param backlog The size of the pending connections backlog.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_listen(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
int backlog)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->listen);
|
||||
|
||||
return iface->l2->offload_ip->listen(context, backlog);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a network connection.
|
||||
*
|
||||
* @details The net_context_connect function creates a network
|
||||
* connection to the host specified by addr. After the
|
||||
* connection is established, the user supplied callback (cb)
|
||||
* is executed. cb is called even if the timeout was set to
|
||||
* K_FOREVER. cb is not called if the timeout expires.
|
||||
* For datagram sockets (SOCK_DGRAM), this function only sets
|
||||
* the peer address.
|
||||
* This function is similar to the BSD connect() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param context The network context.
|
||||
* @param addr The peer address to connect to.
|
||||
* @param addrlen Peer address length.
|
||||
* @param cb Callback function. Set to NULL if not required.
|
||||
* @param timeout The timeout value for the connection. Possible values:
|
||||
* * K_NO_WAIT: this function will return immediately,
|
||||
* * K_FOREVER: this function will block until the
|
||||
* connection is established,
|
||||
* * >0: this function will wait the specified ms.
|
||||
* @param user_data Data passed to the callback function.
|
||||
*
|
||||
* @return 0 on success.
|
||||
* @return -EINVAL if an invalid parameter is passed as an argument.
|
||||
* @return -ENOTSUP if the operation is not supported or implemented.
|
||||
*/
|
||||
static inline int net_l2_offload_ip_connect(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
const struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
net_context_connect_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->connect);
|
||||
|
||||
return iface->l2->offload_ip->connect(context, addr, addrlen, cb,
|
||||
timeout, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Accept a network connection attempt.
|
||||
*
|
||||
* @details Accept a connection being established. This function
|
||||
* will return immediately if the timeout is set to K_NO_WAIT.
|
||||
* In this case the context will call the supplied callback when ever
|
||||
* there is a connection established to this context. This is "a register
|
||||
* handler and forget" type of call (async).
|
||||
* If the timeout is set to K_FOREVER, the function will wait
|
||||
* until the connection is established. Timeout value > 0, will wait as
|
||||
* many ms.
|
||||
* After the connection is established a caller supplied callback is called.
|
||||
* The callback is called even if timeout was set to K_FOREVER, the
|
||||
* callback is called before this function will return in this case.
|
||||
* The callback is not called if the timeout expires.
|
||||
* This is similar as BSD accept() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param context The context to use.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Timeout for the connection. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_accept(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
net_context_accept_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->accept);
|
||||
|
||||
return iface->l2->offload_ip->accept(context, cb, timeout, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a network buffer to a peer.
|
||||
*
|
||||
* @details This function can be used to send network data to a peer
|
||||
* connection. This function will return immediately if the timeout
|
||||
* is set to K_NO_WAIT. If the timeout is set to K_FOREVER, the function
|
||||
* will wait until the network buffer is sent. Timeout value > 0 will
|
||||
* wait as many ms. After the network buffer is sent,
|
||||
* a caller supplied callback is called. The callback is called even
|
||||
* if timeout was set to K_FOREVER, the callback is called
|
||||
* before this function will return in this case. The callback is not
|
||||
* called if the timeout expires. For context of type SOCK_DGRAM,
|
||||
* the destination address must have been set by the call to
|
||||
* net_context_connect().
|
||||
* This is similar as BSD send() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param buf The network buffer to send.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Timeout for the connection. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param token Caller specified value that is passed as is to callback.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_send(struct net_if *iface,
|
||||
struct net_buf *buf,
|
||||
net_context_send_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *token,
|
||||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->send);
|
||||
|
||||
return iface->l2->offload_ip->send(buf, cb, timeout, token, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a network buffer to a peer specified by address.
|
||||
*
|
||||
* @details This function can be used to send network data to a peer
|
||||
* specified by address. This variant can only be used for datagram
|
||||
* connections of type SOCK_DGRAM. This function will return immediately
|
||||
* if the timeout is set to K_NO_WAIT. If the timeout is set to K_FOREVER,
|
||||
* the function will wait until the network buffer is sent. Timeout
|
||||
* value > 0 will wait as many ms. After the network buffer
|
||||
* is sent, a caller supplied callback is called. The callback is called
|
||||
* even if timeout was set to K_FOREVER, the callback is called
|
||||
* before this function will return. The callback is not called if the
|
||||
* timeout expires.
|
||||
* This is similar as BSD sendto() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param buf The network buffer to send.
|
||||
* @param dst_addr Destination address. This will override the address
|
||||
* already set in network buffer.
|
||||
* @param addrlen Length of the address.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Timeout for the connection. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param token Caller specified value that is passed as is to callback.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_sendto(struct net_if *iface,
|
||||
struct net_buf *buf,
|
||||
const struct sockaddr *dst_addr,
|
||||
socklen_t addrlen,
|
||||
net_context_send_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *token,
|
||||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->sendto);
|
||||
|
||||
return iface->l2->offload_ip->sendto(buf, dst_addr, addrlen, cb,
|
||||
timeout, token, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive network data from a peer specified by context.
|
||||
*
|
||||
* @details This function can be used to register a callback function
|
||||
* that is called by the network stack when network data has been received
|
||||
* for this context. As this function registers a callback, then there
|
||||
* is no need to call this function multiple times if timeout is set to
|
||||
* K_NO_WAIT.
|
||||
* If callback function or user data changes, then the function can be called
|
||||
* multiple times to register new values.
|
||||
* This function will return immediately if the timeout is set to K_NO_WAIT.
|
||||
* If the timeout is set to K_FOREVER, the function will wait until the
|
||||
* network buffer is received. Timeout value > 0 will wait as many ms.
|
||||
* After the network buffer is received, a caller supplied callback is
|
||||
* called. The callback is called even if timeout was set to K_FOREVER,
|
||||
* the callback is called before this function will return in this case.
|
||||
* The callback is not called if the timeout expires. The timeout functionality
|
||||
* can be compiled out if synchronous behaviour is not needed. The sync call
|
||||
* logic requires some memory that can be saved if only async way of call is
|
||||
* used. If CONFIG_NET_CONTEXT_SYNC_RECV is not set, then the timeout parameter
|
||||
* value is ignored.
|
||||
* This is similar as BSD recv() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param context The network context to use.
|
||||
* @param cb Caller supplied callback function.
|
||||
* @param timeout Caller supplied timeout. Possible values
|
||||
* are K_FOREVER, K_NO_WAIT, >0.
|
||||
* @param user_data Caller supplied user data.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_recv(struct net_if *iface,
|
||||
struct net_context *context,
|
||||
net_context_recv_cb_t cb,
|
||||
int32_t timeout,
|
||||
void *user_data)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->recv);
|
||||
|
||||
return iface->l2->offload_ip->recv(context, cb, timeout, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Free/close a network context.
|
||||
*
|
||||
* @details This releases the context. It is not possible to
|
||||
* send or receive data via this context after this call.
|
||||
* This is similar as BSD shutdown() function.
|
||||
*
|
||||
* @param iface Network interface where the offloaded IP stack can be
|
||||
* reached.
|
||||
* @param context The context to be closed.
|
||||
*
|
||||
* @return 0 if ok, < 0 if error
|
||||
*/
|
||||
static inline int net_l2_offload_ip_put(struct net_if *iface,
|
||||
struct net_context *context)
|
||||
{
|
||||
NET_ASSERT(iface);
|
||||
NET_ASSERT(iface->l2);
|
||||
NET_ASSERT(iface->l2->offload_ip);
|
||||
NET_ASSERT(iface->l2->offload_ip->put);
|
||||
|
||||
return iface->l2->offload_ip->put(context);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NET_L2_OFFLOAD_IP */
|
||||
|
||||
#endif /* __OFFLOAD_IP_H__ */
|
|
@ -1,136 +0,0 @@
|
|||
/** @file
|
||||
* @brief Trickle timer library
|
||||
*
|
||||
* This implements Trickle timer as specified in RFC 6206
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __TRICKLE_H
|
||||
#define __TRICKLE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <kernel.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct net_trickle;
|
||||
|
||||
typedef void (*net_trickle_cb_t)(struct net_trickle *trickle,
|
||||
bool do_suppress, void *user_data);
|
||||
|
||||
/*
|
||||
* The variable names are taken directly from RFC when applicable.
|
||||
* Note that the struct members should not be accessed directly but
|
||||
* only via the Trickle API.
|
||||
*/
|
||||
struct net_trickle {
|
||||
uint32_t Imin; /* Min interval size in ms */
|
||||
uint8_t Imax; /* Max number of doublings */
|
||||
uint8_t k; /* Redundancy constant */
|
||||
|
||||
uint32_t I; /* Current interval size */
|
||||
uint32_t Istart; /* Start of the interval in ms */
|
||||
uint8_t c; /* Consistency counter */
|
||||
|
||||
uint32_t Imax_abs; /* Max interval size in ms (not doublings)
|
||||
*/
|
||||
|
||||
struct k_delayed_work timer;
|
||||
net_trickle_cb_t cb; /* Callback to be called when timer expires */
|
||||
void *user_data;
|
||||
};
|
||||
|
||||
#define NET_TRICKLE_INFINITE_REDUNDANCY 0
|
||||
|
||||
/**
|
||||
* @brief Create a Trickle timer.
|
||||
*
|
||||
* @param trickle Pointer to Trickle struct.
|
||||
* @param Imin Imin configuration parameter in ms.
|
||||
* @param Imax Max number of doublings.
|
||||
* @param k Redundancy constant parameter. See RFC 6206 for details.
|
||||
*
|
||||
* @return Return 0 if ok and <0 if error.
|
||||
*/
|
||||
int net_trickle_create(struct net_trickle *trickle,
|
||||
uint32_t Imin,
|
||||
uint8_t Imax,
|
||||
uint8_t k);
|
||||
|
||||
/**
|
||||
* @brief Start a Trickle timer.
|
||||
*
|
||||
* @param trickle Pointer to Trickle struct.
|
||||
* @param cb User callback to call at time T within the current trickle
|
||||
* interval
|
||||
* @param user_data User pointer that is passed to callback.
|
||||
*
|
||||
* @return Return 0 if ok and <0 if error.
|
||||
*/
|
||||
int net_trickle_start(struct net_trickle *trickle,
|
||||
net_trickle_cb_t cb,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* @brief Stop a Trickle timer.
|
||||
*
|
||||
* @param trickle Pointer to Trickle struct.
|
||||
*
|
||||
* @return Return 0 if ok and <0 if error.
|
||||
*/
|
||||
int net_trickle_stop(struct net_trickle *trickle);
|
||||
|
||||
/**
|
||||
* @brief To be called by the protocol handler when it hears a consistent
|
||||
* network transmission.
|
||||
*
|
||||
* @param trickle Pointer to Trickle struct.
|
||||
*/
|
||||
void net_trickle_consistency(struct net_trickle *trickle);
|
||||
|
||||
/**
|
||||
* @brief To be called by the protocol handler when it hears an inconsistent
|
||||
* network transmission.
|
||||
*
|
||||
* @param trickle Pointer to Trickle struct.
|
||||
*/
|
||||
void net_trickle_inconsistency(struct net_trickle *trickle);
|
||||
|
||||
/**
|
||||
* @brief Check if the Trickle timer is running or not.
|
||||
*
|
||||
* @param trickle Pointer to Trickle struct.
|
||||
*
|
||||
* @return Return True if timer is running and False if not.
|
||||
*/
|
||||
static inline bool net_trickle_is_running(struct net_trickle *trickle)
|
||||
{
|
||||
NET_ASSERT(trickle);
|
||||
|
||||
return trickle->I != 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TRICKLE_H */
|
|
@ -50,7 +50,6 @@ config NETWORKING
|
|||
select NANO_TIMEOUTS
|
||||
select NANO_TIMERS
|
||||
select NET_BUF
|
||||
select NET_YAIP
|
||||
select TEST_RANDOM_GENERATOR
|
||||
default n
|
||||
help
|
||||
|
@ -58,10 +57,6 @@ config NETWORKING
|
|||
|
||||
if NETWORKING
|
||||
|
||||
config NET_YAIP
|
||||
bool
|
||||
default y
|
||||
|
||||
source "net/yaip/Kconfig"
|
||||
|
||||
endif
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
obj-$(CONFIG_NET_BUF) += buf.o
|
||||
ifeq ($(CONFIG_NET_YAIP),y)
|
||||
|
||||
ifeq ($(CONFIG_NETWORKING),y)
|
||||
ifeq ($(CONFIG_NET_L2_RAW_CHANNEL),y)
|
||||
obj-y += yaip/nbuf.o
|
||||
else
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
# limitations under the License.
|
||||
#
|
||||
|
||||
menu "New IP stack [EXPERIMENTAL]"
|
||||
depends on NET_YAIP
|
||||
menu "IP stack"
|
||||
depends on NETWORKING
|
||||
|
||||
# Hidden option
|
||||
config NET_L2_RAW_CHANNEL
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_IPV6=n
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_ARP=y
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NANO_TIMEOUTS=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NANO_TIMEOUTS=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
|
|
|
@ -4,9 +4,8 @@ CONFIG_INIT_STACKS=y
|
|||
CONFIG_MAIN_STACK_SIZE=1024
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NANO_TIMEOUTS=y
|
||||
# YAIP Configuration
|
||||
# IP Stack Configuration
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_ARP=y
|
||||
CONFIG_NET_L2_ETHERNET=y
|
||||
CONFIG_NET_IPV4=y
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
CONFIG_ARC_INIT=n
|
||||
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
|
||||
CONFIG_NET_NBUF_RX_COUNT=10
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
ccflags-$(CONFIG_NET_UIP) +=-I${ZEPHYR_BASE}/net/ip
|
||||
ccflags-$(CONFIG_NETWORKING_WITH_BT) +=-I${ZEPHYR_BASE}/samples/bluetooth/
|
||||
|
||||
ifeq ($(CONFIG_NET_YAIP), y)
|
||||
obj-y = echo-client-yaip.o
|
||||
else
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os/lib
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os
|
||||
obj-y = echo-client.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET_TESTING), y)
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/samples/net/common/
|
||||
|
|
|
@ -1,605 +0,0 @@
|
|||
/* echo-client.c - Networking echo client */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The echo-client application is acting as a client that is run in Zephyr OS,
|
||||
* and echo-server is run in the host acting as a server. The client will send
|
||||
* either unicast or multicast packets to the server which will reply the packet
|
||||
* back to the originator.
|
||||
*/
|
||||
|
||||
#if 1
|
||||
#define SYS_LOG_DOMAIN "echo-client"
|
||||
#define SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
|
||||
#define NET_DEBUG 1
|
||||
#endif
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <sections.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <net/nbuf.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_context.h>
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_BT)
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <gatt/ipss.h>
|
||||
#endif
|
||||
|
||||
/* Generated by http://www.lipsum.com/
|
||||
* 3 paragraphs, 176 words, 1230 bytes of Lorem Ipsum
|
||||
*/
|
||||
static char *lorem_ipsum =
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
|
||||
"Vestibulum id cursus felis, sit amet suscipit velit. Integer "
|
||||
"facilisis malesuada porta. Nunc at accumsan mauris. Etiam vehicula, "
|
||||
"arcu consequat feugiat venenatis, tellus velit gravida ligula, quis "
|
||||
"posuere sem leo eget urna. Curabitur condimentum leo nec orci "
|
||||
"mattis, nec faucibus dui rutrum. Ut mollis orci in iaculis "
|
||||
"consequat. Nulla volutpat nibh eu velit sagittis, a iaculis dui "
|
||||
"aliquam."
|
||||
"\n"
|
||||
"Quisque interdum consequat eros a eleifend. Fusce dapibus nisl "
|
||||
"sit amet velit posuere imperdiet. Quisque accumsan tempor massa "
|
||||
"sit amet tincidunt. Integer sollicitudin vehicula tristique. Nulla "
|
||||
"sagittis massa turpis, ac ultricies neque posuere eu. Nulla et "
|
||||
"imperdiet ex. Etiam venenatis sed lacus tincidunt hendrerit. In "
|
||||
"libero nisl, congue id tellus vitae, tincidunt tristique mauris. "
|
||||
"Nullam sed porta massa. Sed condimentum sem eu convallis euismod. "
|
||||
"Suspendisse lobortis purus faucibus, gravida turpis id, mattis "
|
||||
"velit. Maecenas eleifend sapien eu tincidunt lobortis. Sed elementum "
|
||||
"sapien id enim laoreet consequat."
|
||||
"\n"
|
||||
"Aenean et neque aliquam, lobortis lectus in, consequat leo. Sed "
|
||||
"quis egestas nulla. Quisque ac risus quis elit mollis finibus. "
|
||||
"Phasellus efficitur imperdiet metus."
|
||||
"\n";
|
||||
|
||||
#define STACKSIZE 2048
|
||||
|
||||
static int ipsum_len;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
/* admin-local, dynamically allocated multicast address */
|
||||
#define MCAST_IP6ADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
|
||||
/* Define the peer IP address where to send messages */
|
||||
#define PEER_IP6ADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
|
||||
#define MY_IP6ADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } }
|
||||
|
||||
#define MY_PREFIX_LEN 64
|
||||
|
||||
static struct in6_addr in6addr_my = MY_IP6ADDR;
|
||||
static struct in6_addr in6addr_peer = PEER_IP6ADDR;
|
||||
static struct in6_addr in6addr_mcast = MCAST_IP6ADDR;
|
||||
static struct k_sem recv_ipv6;
|
||||
static int expecting_ipv6;
|
||||
static char __noinit __stack ipv6_stack[STACKSIZE];
|
||||
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
/* Organization-local 239.192.0.0/14 */
|
||||
#define MCAST_IP4ADDR { { { 239, 192, 0, 2 } } }
|
||||
|
||||
#define MY_IP4ADDR { { { 192, 0, 2, 1 } } }
|
||||
#define PEER_IP4ADDR { { { 192, 0, 2, 2 } } }
|
||||
|
||||
static struct in_addr in4addr_my = MY_IP4ADDR;
|
||||
static struct in_addr in4addr_peer = PEER_IP4ADDR;
|
||||
static struct k_sem recv_ipv4;
|
||||
static int expecting_ipv4;
|
||||
static char __noinit __stack ipv4_stack[STACKSIZE];
|
||||
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
|
||||
#define MY_PORT 8484
|
||||
#define PEER_PORT 4242
|
||||
|
||||
#define WAIT_TIME (2 * MSEC_PER_SEC)
|
||||
|
||||
static inline void init_app(void)
|
||||
{
|
||||
NET_INFO("Run echo client");
|
||||
|
||||
sys_rand32_init();
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
#if defined(CONFIG_NET_SAMPLES_MY_IPV6_ADDR)
|
||||
if (net_addr_pton(AF_INET6,
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR,
|
||||
(struct sockaddr *)&in6addr_my) < 0) {
|
||||
NET_ERR("Invalid IPv6 address %s",
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_SAMPLES_PEER_IPV6_ADDR)
|
||||
if (net_addr_pton(AF_INET6,
|
||||
CONFIG_NET_SAMPLES_PEER_IPV6_ADDR,
|
||||
(struct sockaddr *)&in6addr_peer) < 0) {
|
||||
NET_ERR("Invalid peer IPv6 address %s",
|
||||
CONFIG_NET_SAMPLES_PEER_IPV6_ADDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
do {
|
||||
struct net_if_addr *ifaddr;
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(net_if_get_default(),
|
||||
&in6addr_my, NET_ADDR_MANUAL, 0);
|
||||
} while (0);
|
||||
|
||||
net_if_ipv6_maddr_add(net_if_get_default(), &in6addr_mcast);
|
||||
|
||||
k_sem_init(&recv_ipv6, 0, UINT_MAX);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
#if defined(CONFIG_NET_DHCPV4)
|
||||
net_dhcpv4_start(net_if_get_default());
|
||||
#else
|
||||
#if defined(CONFIG_NET_SAMPLES_MY_IPV4_ADDR)
|
||||
if (net_addr_pton(AF_INET,
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR,
|
||||
(struct sockaddr *)&in4addr_my) < 0) {
|
||||
NET_ERR("Invalid IPv4 address %s",
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_SAMPLES_PEER_IPV4_ADDR)
|
||||
if (net_addr_pton(AF_INET,
|
||||
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR,
|
||||
(struct sockaddr *)&in4addr_peer) < 0) {
|
||||
NET_ERR("Invalid peer IPv4 address %s",
|
||||
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
net_if_ipv4_addr_add(net_if_get_default(), &in4addr_my,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
#endif /* CONFIG_NET_DHCPV4 */
|
||||
|
||||
k_sem_init(&recv_ipv4, 0, UINT_MAX);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool get_context(struct net_context **udp_recv4,
|
||||
struct net_context **udp_recv6,
|
||||
struct net_context **mcast_recv6)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
struct sockaddr_in6 mcast_addr6 = { 0 };
|
||||
struct sockaddr_in6 my_addr6 = { 0 };
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
struct sockaddr_in my_addr4 = { 0 };
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
net_ipaddr_copy(&mcast_addr6.sin6_addr, &in6addr_mcast);
|
||||
mcast_addr6.sin6_family = AF_INET6;
|
||||
|
||||
net_ipaddr_copy(&my_addr6.sin6_addr, &in6addr_my);
|
||||
my_addr6.sin6_family = AF_INET6;
|
||||
my_addr6.sin6_port = htons(MY_PORT);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
net_ipaddr_copy(&my_addr4.sin_addr, &in4addr_my);
|
||||
my_addr4.sin_family = AF_INET;
|
||||
my_addr4.sin_port = htons(MY_PORT);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_UDP)
|
||||
ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, udp_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context for IPv6 UDP (%d)",
|
||||
ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_bind(*udp_recv6, (struct sockaddr *)&my_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 UDP port %d (%d)",
|
||||
ntohs(my_addr6.sin6_port), ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, mcast_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get receiving IPv6 mcast "
|
||||
"network context (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_bind(*mcast_recv6, (struct sockaddr *)&mcast_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 mcast (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP)
|
||||
ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, udp_recv4);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context for IPv4 UDP (%d)",
|
||||
ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_bind(*udp_recv4, (struct sockaddr *)&my_addr4,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv4 UDP port %d (%d)",
|
||||
ntohs(my_addr4.sin_port), ret);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool wait_reply(const char *name,
|
||||
struct k_sem *sem)
|
||||
{
|
||||
int ret = k_sem_take(sem, WAIT_TIME);
|
||||
|
||||
if (!ret) {
|
||||
return true;
|
||||
}
|
||||
|
||||
NET_ERR("wait_reply returned %s",
|
||||
ret == -EAGAIN ? "on time out" : "directly");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct net_buf *prepare_send_buf(const char *name,
|
||||
struct net_context *context,
|
||||
int expecting_len)
|
||||
{
|
||||
struct net_buf *send_buf;
|
||||
bool status;
|
||||
|
||||
send_buf = net_nbuf_get_tx(context);
|
||||
|
||||
NET_ASSERT(send_buf);
|
||||
|
||||
status = net_nbuf_append(send_buf, expecting_len, lorem_ipsum);
|
||||
if (!status) {
|
||||
NET_ERR("%s: cannot create send buf", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return send_buf;
|
||||
}
|
||||
|
||||
static inline void udp_sent(struct net_context *context,
|
||||
int status,
|
||||
void *bytes_sent,
|
||||
void *user_data)
|
||||
{
|
||||
if (!status) {
|
||||
NET_INFO("%s: sent %u bytes", (char *)user_data,
|
||||
POINTER_TO_UINT(bytes_sent));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void set_dst_addr(sa_family_t family,
|
||||
struct net_buf *buf,
|
||||
struct sockaddr *dst_addr)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (family == AF_INET6) {
|
||||
net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr,
|
||||
&in6addr_peer);
|
||||
net_sin6(dst_addr)->sin6_family = AF_INET6;
|
||||
net_sin6(dst_addr)->sin6_port = htons(PEER_PORT);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
if (family == AF_INET) {
|
||||
net_ipaddr_copy(&net_sin(dst_addr)->sin_addr,
|
||||
&in4addr_peer);
|
||||
net_sin(dst_addr)->sin_family = AF_INET;
|
||||
net_sin(dst_addr)->sin_port = htons(PEER_PORT);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
}
|
||||
|
||||
static bool compare_data(struct net_buf *buf, int expecting_len)
|
||||
{
|
||||
uint8_t *ptr = net_nbuf_appdata(buf);
|
||||
int pos = 0;
|
||||
int len;
|
||||
|
||||
/* Buf will now point to first fragment with IP header
|
||||
* in it.
|
||||
*/
|
||||
buf = buf->frags;
|
||||
|
||||
/* Do not include the protocol headers in len for the
|
||||
* first fragment. The remaining fragments contain only
|
||||
* data so the user data length is directly the fragment len.
|
||||
*/
|
||||
len = buf->len - (ptr - buf->data);
|
||||
|
||||
while (buf) {
|
||||
if (memcmp(ptr, lorem_ipsum + pos, len)) {
|
||||
NET_DBG("Invalid data received");
|
||||
return false;
|
||||
} else {
|
||||
pos += len;
|
||||
|
||||
buf = buf->frags;
|
||||
if (!buf) {
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = buf->data;
|
||||
len = buf->len;
|
||||
}
|
||||
}
|
||||
|
||||
NET_DBG("Compared %d bytes, all ok", expecting_len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void setup_udp_recv(struct net_context *udp, void *user_data,
|
||||
net_context_recv_cb_t cb)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = net_context_recv(udp, cb, 0, user_data);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive UDP packets");
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
static bool send_ipv4_data(struct net_context *udp)
|
||||
{
|
||||
struct net_buf *send_buf;
|
||||
struct sockaddr dst_addr;
|
||||
bool status = false;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
expecting_ipv4 = sys_rand32_get() % ipsum_len;
|
||||
|
||||
send_buf = prepare_send_buf("IPv4", udp, expecting_ipv4);
|
||||
if (!send_buf) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = net_buf_frags_len(send_buf);
|
||||
|
||||
NET_ASSERT_INFO(expecting_ipv4 == len,
|
||||
"Data to send %d bytes, real len %d",
|
||||
expecting_ipv4, len);
|
||||
|
||||
set_dst_addr(AF_INET, send_buf, &dst_addr);
|
||||
|
||||
ret = net_context_sendto(send_buf, &dst_addr,
|
||||
sizeof(struct sockaddr_in),
|
||||
udp_sent, 0,
|
||||
UINT_TO_POINTER(len),
|
||||
"IPv4");
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot send IPv4 data to peer (%d)", ret);
|
||||
net_nbuf_unref(send_buf);
|
||||
} else {
|
||||
status = true;
|
||||
}
|
||||
out:
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void udp_ipv4_received(struct net_context *context,
|
||||
struct net_buf *buf,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
sa_family_t family = net_nbuf_family(buf);
|
||||
struct k_sem *recv = user_data;
|
||||
|
||||
if (family == AF_INET) {
|
||||
if (expecting_ipv4 != net_nbuf_appdatalen(buf)) {
|
||||
NET_ERR("Sent %d bytes, received %d bytes",
|
||||
expecting_ipv4, net_nbuf_appdatalen(buf));
|
||||
}
|
||||
|
||||
if (!compare_data(buf, expecting_ipv4)) {
|
||||
NET_DBG("Data mismatch");
|
||||
}
|
||||
|
||||
net_nbuf_unref(buf);
|
||||
|
||||
k_sem_give(recv);
|
||||
}
|
||||
}
|
||||
|
||||
static void send_ipv4(struct net_context *udp)
|
||||
{
|
||||
setup_udp_recv(udp, &recv_ipv4, udp_ipv4_received);
|
||||
|
||||
NET_INFO("Starting to send IPv4 data");
|
||||
|
||||
do {
|
||||
/* We first send a packet, then wait for a packet to arrive.
|
||||
* If the reply does not come in time, we send another packet.
|
||||
*/
|
||||
send_ipv4_data(udp);
|
||||
|
||||
NET_DBG("Waiting IPv4 packet");
|
||||
|
||||
if (!wait_reply("IPv4", &recv_ipv4)) {
|
||||
NET_DBG("Waited %d bytes but did not receive them.",
|
||||
expecting_ipv4);
|
||||
}
|
||||
|
||||
k_yield();
|
||||
} while (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static bool send_ipv6_data(struct net_context *udp)
|
||||
{
|
||||
struct net_buf *send_buf;
|
||||
struct sockaddr dst_addr;
|
||||
bool status = false;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
expecting_ipv6 = sys_rand32_get() % ipsum_len;
|
||||
|
||||
send_buf = prepare_send_buf("IPv6", udp, expecting_ipv6);
|
||||
if (!send_buf) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = net_buf_frags_len(send_buf);
|
||||
|
||||
NET_ASSERT_INFO(expecting_ipv6 == len,
|
||||
"Data to send %d bytes, real len %d",
|
||||
expecting_ipv6, len);
|
||||
|
||||
set_dst_addr(AF_INET6, send_buf, &dst_addr);
|
||||
|
||||
ret = net_context_sendto(send_buf, &dst_addr,
|
||||
sizeof(struct sockaddr_in6),
|
||||
udp_sent, 0,
|
||||
UINT_TO_POINTER(len),
|
||||
"IPv6");
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot send IPv6 data to peer (%d)", ret);
|
||||
net_nbuf_unref(send_buf);
|
||||
} else {
|
||||
status = true;
|
||||
}
|
||||
out:
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void udp_ipv6_received(struct net_context *context,
|
||||
struct net_buf *buf,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
sa_family_t family = net_nbuf_family(buf);
|
||||
struct k_sem *recv = user_data;
|
||||
|
||||
if (family == AF_INET6) {
|
||||
if (expecting_ipv6 != net_nbuf_appdatalen(buf)) {
|
||||
NET_ERR("Sent %d bytes, received %d bytes",
|
||||
expecting_ipv6, net_nbuf_appdatalen(buf));
|
||||
}
|
||||
|
||||
if (!compare_data(buf, expecting_ipv6)) {
|
||||
NET_DBG("Data mismatch");
|
||||
}
|
||||
|
||||
net_nbuf_unref(buf);
|
||||
|
||||
k_sem_give(recv);
|
||||
}
|
||||
}
|
||||
|
||||
static void send_ipv6(struct net_context *udp)
|
||||
{
|
||||
setup_udp_recv(udp, &recv_ipv6, udp_ipv6_received);
|
||||
|
||||
NET_INFO("Starting to send IPv6 data");
|
||||
|
||||
do {
|
||||
/* We first send a packet, then wait for a packet to arrive.
|
||||
* If the reply does not come in time, we send another packet.
|
||||
*/
|
||||
send_ipv6_data(udp);
|
||||
|
||||
NET_DBG("Waiting IPv6 packet");
|
||||
|
||||
if (!wait_reply("IPv6", &recv_ipv6)) {
|
||||
NET_DBG("Waited %d bytes but did not receive them.",
|
||||
expecting_ipv6);
|
||||
}
|
||||
|
||||
k_yield();
|
||||
} while (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void main(void)
|
||||
{
|
||||
struct net_context *udp_send4 = { 0 };
|
||||
struct net_context *udp_send6 = { 0 };
|
||||
struct net_context *mcast_send6 = { 0 };
|
||||
|
||||
init_app();
|
||||
|
||||
if (!get_context(&udp_send4, &udp_send6, &mcast_send6)) {
|
||||
NET_ERR("Cannot get network contexts");
|
||||
return;
|
||||
}
|
||||
|
||||
ipsum_len = strlen(lorem_ipsum);
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_BT)
|
||||
if (bt_enable(NULL)) {
|
||||
PRINT("Bluetooth init failed\n");
|
||||
return;
|
||||
}
|
||||
ipss_init();
|
||||
ipss_advertise();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
k_thread_spawn(ipv4_stack, STACKSIZE,
|
||||
(k_thread_entry_t)send_ipv4,
|
||||
udp_send4, NULL, NULL, K_PRIO_COOP(7), 0, 0);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
k_thread_spawn(ipv6_stack, STACKSIZE,
|
||||
(k_thread_entry_t)send_ipv6,
|
||||
udp_send6, NULL, NULL, K_PRIO_COOP(7), 0, 0);
|
||||
#endif
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/* echo-client.c - Send and receive unicast or multicast packets */
|
||||
/* echo-client.c - Networking echo client */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation.
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -23,458 +23,563 @@
|
|||
* back to the originator.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_STDOUT_CONSOLE)
|
||||
#include <stdio.h>
|
||||
#define PRINT printf
|
||||
#else
|
||||
#include <misc/printk.h>
|
||||
#define PRINT printk
|
||||
#if 1
|
||||
#define SYS_LOG_DOMAIN "echo-client"
|
||||
#define SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
|
||||
#define NET_DEBUG 1
|
||||
#endif
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <sections.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <drivers/rand32.h>
|
||||
|
||||
#include <net/ip_buf.h>
|
||||
#include <net/nbuf.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_socket.h>
|
||||
#include <net/net_context.h>
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_BT)
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <gatt/ipss.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_TESTING)
|
||||
#include <net_testing.h>
|
||||
#else
|
||||
#if defined(CONFIG_NETWORKING_WITH_IPV6)
|
||||
#include <contiki/ipv6/uip-ds6.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Generated by http://www.lipsum.com/
|
||||
* 3 paragraphs, 176 words, 1230 bytes of Lorem Ipsum
|
||||
*/
|
||||
static const char *lorem_ipsum =
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum id cursus felis, sit amet suscipit velit. Integer facilisis malesuada porta. Nunc at accumsan mauris. Etiam vehicula, arcu consequat feugiat venenatis, tellus velit gravida ligula, quis posuere sem leo eget urna. Curabitur condimentum leo nec orci mattis, nec faucibus dui rutrum. Ut mollis orci in iaculis consequat. Nulla volutpat nibh eu velit sagittis, a iaculis dui aliquam."
|
||||
static char *lorem_ipsum =
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
|
||||
"Vestibulum id cursus felis, sit amet suscipit velit. Integer "
|
||||
"facilisis malesuada porta. Nunc at accumsan mauris. Etiam vehicula, "
|
||||
"arcu consequat feugiat venenatis, tellus velit gravida ligula, quis "
|
||||
"posuere sem leo eget urna. Curabitur condimentum leo nec orci "
|
||||
"mattis, nec faucibus dui rutrum. Ut mollis orci in iaculis "
|
||||
"consequat. Nulla volutpat nibh eu velit sagittis, a iaculis dui "
|
||||
"aliquam."
|
||||
"\n"
|
||||
"Quisque interdum consequat eros a eleifend. Fusce dapibus nisl sit amet velit posuere imperdiet. Quisque accumsan tempor massa sit amet tincidunt. Integer sollicitudin vehicula tristique. Nulla sagittis massa turpis, ac ultricies neque posuere eu. Nulla et imperdiet ex. Etiam venenatis sed lacus tincidunt hendrerit. In libero nisl, congue id tellus vitae, tincidunt tristique mauris. Nullam sed porta massa. Sed condimentum sem eu convallis euismod. Suspendisse lobortis purus faucibus, gravida turpis id, mattis velit. Maecenas eleifend sapien eu tincidunt lobortis. Sed elementum sapien id enim laoreet consequat."
|
||||
"Quisque interdum consequat eros a eleifend. Fusce dapibus nisl "
|
||||
"sit amet velit posuere imperdiet. Quisque accumsan tempor massa "
|
||||
"sit amet tincidunt. Integer sollicitudin vehicula tristique. Nulla "
|
||||
"sagittis massa turpis, ac ultricies neque posuere eu. Nulla et "
|
||||
"imperdiet ex. Etiam venenatis sed lacus tincidunt hendrerit. In "
|
||||
"libero nisl, congue id tellus vitae, tincidunt tristique mauris. "
|
||||
"Nullam sed porta massa. Sed condimentum sem eu convallis euismod. "
|
||||
"Suspendisse lobortis purus faucibus, gravida turpis id, mattis "
|
||||
"velit. Maecenas eleifend sapien eu tincidunt lobortis. Sed elementum "
|
||||
"sapien id enim laoreet consequat."
|
||||
"\n"
|
||||
"Aenean et neque aliquam, lobortis lectus in, consequat leo. Sed quis egestas nulla. Quisque ac risus quis elit mollis finibus. Phasellus efficitur imperdiet metus."
|
||||
"Aenean et neque aliquam, lobortis lectus in, consequat leo. Sed "
|
||||
"quis egestas nulla. Quisque ac risus quis elit mollis finibus. "
|
||||
"Phasellus efficitur imperdiet metus."
|
||||
"\n";
|
||||
|
||||
static int expecting;
|
||||
#define STACKSIZE 2048
|
||||
|
||||
static int ipsum_len;
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_IPV6)
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
/* admin-local, dynamically allocated multicast address */
|
||||
#define MCAST_IPADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
#define MCAST_IP6ADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
|
||||
/* Define the peer IP address where to send messages */
|
||||
#if !defined(CONFIG_NET_TESTING)
|
||||
#define PEER_IPADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1 } } }
|
||||
#define MY_IPADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
#define PEER_IP6ADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
|
||||
#define MY_IP6ADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } }
|
||||
|
||||
#define MY_PREFIX_LEN 64
|
||||
#endif
|
||||
|
||||
static const struct in6_addr in6addr_my = MY_IPADDR;
|
||||
static const struct in6_addr in6addr_peer = PEER_IPADDR;
|
||||
static struct in6_addr in6addr_my = MY_IP6ADDR;
|
||||
static struct in6_addr in6addr_peer = PEER_IP6ADDR;
|
||||
static struct in6_addr in6addr_mcast = MCAST_IP6ADDR;
|
||||
static struct k_sem recv_ipv6;
|
||||
static int expecting_ipv6;
|
||||
static char __noinit __stack ipv6_stack[STACKSIZE];
|
||||
|
||||
#else /* CONFIG_NETWORKING_WITH_IPV6 */
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
/* Organization-local 239.192.0.0/14 */
|
||||
#define MCAST_IPADDR { { { 239, 192, 0, 2 } } }
|
||||
#define MCAST_IP4ADDR { { { 239, 192, 0, 2 } } }
|
||||
|
||||
#define UIP_IPADDR0 192
|
||||
#define UIP_IPADDR1 0
|
||||
#define UIP_IPADDR2 2
|
||||
#define UIP_IPADDR3 2
|
||||
#define MY_IP4ADDR { { { 192, 0, 2, 1 } } }
|
||||
#define PEER_IP4ADDR { { { 192, 0, 2, 2 } } }
|
||||
|
||||
#define UIP_IPADDR3_PEER 1
|
||||
static struct in_addr in4addr_my = MY_IP4ADDR;
|
||||
static struct in_addr in4addr_peer = PEER_IP4ADDR;
|
||||
static struct k_sem recv_ipv4;
|
||||
static int expecting_ipv4;
|
||||
static char __noinit __stack ipv4_stack[STACKSIZE];
|
||||
|
||||
#define UIP_DRIPADDR0 UIP_IPADDR0
|
||||
#define UIP_DRIPADDR1 UIP_IPADDR1
|
||||
#define UIP_DRIPADDR2 UIP_IPADDR2
|
||||
#define UIP_DRIPADDR3 42
|
||||
|
||||
uip_ipaddr_t uip_hostaddr = { { UIP_IPADDR0, UIP_IPADDR1,
|
||||
UIP_IPADDR2, UIP_IPADDR3 } };
|
||||
uip_ipaddr_t uip_draddr = { { UIP_DRIPADDR0, UIP_DRIPADDR1,
|
||||
UIP_DRIPADDR2, UIP_DRIPADDR3 } };
|
||||
uip_ipaddr_t uip_netmask = { { 255, 255, 255, 0 } };
|
||||
|
||||
#if !defined(CONFIG_NET_TESTING)
|
||||
#define PEER_IPADDR { { { UIP_IPADDR0, UIP_IPADDR1, UIP_IPADDR2, \
|
||||
UIP_IPADDR3_PEER } } }
|
||||
#define MY_IPADDR { { { UIP_IPADDR0, UIP_IPADDR1, UIP_IPADDR2, \
|
||||
UIP_IPADDR3 } } }
|
||||
#endif
|
||||
|
||||
static const struct in_addr in4addr_my = MY_IPADDR;
|
||||
|
||||
#endif /* CONFIG_NETWORKING_WITH_IPV6 */
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
|
||||
#define MY_PORT 8484
|
||||
#define PEER_PORT 4242
|
||||
|
||||
static struct net_context *unicast, *multicast;
|
||||
#define WAIT_TIME (2 * MSEC_PER_SEC)
|
||||
|
||||
static inline void init_app(void)
|
||||
{
|
||||
PRINT("%s: run mcast tester\n", __func__);
|
||||
NET_INFO("Run echo client");
|
||||
|
||||
sys_rand32_init();
|
||||
|
||||
#if defined(CONFIG_NET_TESTING)
|
||||
net_testing_setup();
|
||||
#else
|
||||
#if defined(CONFIG_NETWORKING_WITH_IPV6)
|
||||
uip_ds6_prefix_add((uip_ipaddr_t *)&in6addr_peer, MY_PREFIX_LEN, 0);
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
#if defined(CONFIG_NET_SAMPLES_MY_IPV6_ADDR)
|
||||
if (net_addr_pton(AF_INET6,
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR,
|
||||
(struct sockaddr *)&in6addr_my) < 0) {
|
||||
NET_ERR("Invalid IPv6 address %s",
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_SAMPLES_PEER_IPV6_ADDR)
|
||||
if (net_addr_pton(AF_INET6,
|
||||
CONFIG_NET_SAMPLES_PEER_IPV6_ADDR,
|
||||
(struct sockaddr *)&in6addr_peer) < 0) {
|
||||
NET_ERR("Invalid peer IPv6 address %s",
|
||||
CONFIG_NET_SAMPLES_PEER_IPV6_ADDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
do {
|
||||
struct net_if_addr *ifaddr;
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(net_if_get_default(),
|
||||
&in6addr_my, NET_ADDR_MANUAL, 0);
|
||||
} while (0);
|
||||
|
||||
net_if_ipv6_maddr_add(net_if_get_default(), &in6addr_mcast);
|
||||
|
||||
k_sem_init(&recv_ipv6, 0, UINT_MAX);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
#if defined(CONFIG_NET_DHCPV4)
|
||||
net_dhcpv4_start(net_if_get_default());
|
||||
#else
|
||||
#if defined(CONFIG_NET_SAMPLES_MY_IPV4_ADDR)
|
||||
if (net_addr_pton(AF_INET,
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR,
|
||||
(struct sockaddr *)&in4addr_my) < 0) {
|
||||
NET_ERR("Invalid IPv4 address %s",
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_SAMPLES_PEER_IPV4_ADDR)
|
||||
if (net_addr_pton(AF_INET,
|
||||
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR,
|
||||
(struct sockaddr *)&in4addr_peer) < 0) {
|
||||
NET_ERR("Invalid peer IPv4 address %s",
|
||||
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
net_if_ipv4_addr_add(net_if_get_default(), &in4addr_my,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
#endif /* CONFIG_NET_DHCPV4 */
|
||||
|
||||
k_sem_init(&recv_ipv4, 0, UINT_MAX);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void reverse(unsigned char *buf, int len)
|
||||
static inline bool get_context(struct net_context **udp_recv4,
|
||||
struct net_context **udp_recv6,
|
||||
struct net_context **mcast_recv6)
|
||||
{
|
||||
int i, last = len - 1;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < len / 2; i++) {
|
||||
unsigned char tmp = buf[i];
|
||||
buf[i] = buf[last - i];
|
||||
buf[last - i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
#define WAIT_TIME 2
|
||||
#define WAIT_TICKS (WAIT_TIME * sys_clock_ticks_per_sec)
|
||||
#else
|
||||
#define WAIT_TICKS TICKS_UNLIMITED
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
struct sockaddr_in6 mcast_addr6 = { 0 };
|
||||
struct sockaddr_in6 my_addr6 = { 0 };
|
||||
#endif
|
||||
|
||||
#define ONE_SEC (1 * sys_clock_ticks_per_sec)
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
struct sockaddr_in my_addr4 = { 0 };
|
||||
#endif
|
||||
|
||||
static inline int send_packet(const char *name,
|
||||
struct net_context *ctx,
|
||||
int ipsum_len,
|
||||
int pos)
|
||||
{
|
||||
static struct net_buf *buf;
|
||||
int ret = 0;
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
net_ipaddr_copy(&mcast_addr6.sin6_addr, &in6addr_mcast);
|
||||
mcast_addr6.sin6_family = AF_INET6;
|
||||
|
||||
if (buf) {
|
||||
/* We have a pending packet that needs to be sent
|
||||
* first.
|
||||
*/
|
||||
PRINT("%s: Trying to re-send %p len %d\n", __func__, buf,
|
||||
buf->len);
|
||||
ret = net_send(buf);
|
||||
if (ret == -EAGAIN || ret == -EINPROGRESS) {
|
||||
PRINT("%s: packet %p needs to be re-sent (%d)\n",
|
||||
name, buf, ret);
|
||||
return ret;
|
||||
} else if (ret < 0) {
|
||||
PRINT("%s: returned %d pending buffer discarded %p\n",
|
||||
name, ret, buf);
|
||||
ip_buf_unref(buf);
|
||||
buf = NULL;
|
||||
return ret;
|
||||
} else {
|
||||
PRINT("%s: returned %d pending buffer cleared %p\n",
|
||||
name, ret, buf);
|
||||
buf = NULL;
|
||||
return 0;
|
||||
}
|
||||
net_ipaddr_copy(&my_addr6.sin6_addr, &in6addr_my);
|
||||
my_addr6.sin6_family = AF_INET6;
|
||||
my_addr6.sin6_port = htons(MY_PORT);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
net_ipaddr_copy(&my_addr4.sin_addr, &in4addr_my);
|
||||
my_addr4.sin_family = AF_INET;
|
||||
my_addr4.sin_port = htons(MY_PORT);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_UDP)
|
||||
ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, udp_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context for IPv6 UDP (%d)",
|
||||
ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
buf = ip_buf_get_tx(ctx);
|
||||
if (buf) {
|
||||
uint8_t *ptr;
|
||||
int sending_len = ipsum_len - pos;
|
||||
|
||||
ptr = net_buf_add(buf, sending_len);
|
||||
memcpy(ptr, lorem_ipsum + pos, sending_len);
|
||||
|
||||
ip_buf_appdatalen(buf) = sending_len;
|
||||
|
||||
PRINT("%s: Trying to send %p buflen %d datalen %d\n",
|
||||
__func__, buf, buf->len, ip_buf_appdatalen(buf));
|
||||
ret = net_send(buf);
|
||||
if (ret < 0) {
|
||||
if (ret == -EINPROGRESS) {
|
||||
PRINT("%s: no connection yet, try again\n",
|
||||
__func__);
|
||||
} else if (ret == -EAGAIN || ret == -ECONNRESET) {
|
||||
PRINT("%s: no connection, try again later\n",
|
||||
__func__);
|
||||
} else {
|
||||
PRINT("%s: sending %d bytes failed\n",
|
||||
__func__, sending_len);
|
||||
ip_buf_unref(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
} else {
|
||||
PRINT("%s: sent %d bytes\n", __func__,
|
||||
sending_len);
|
||||
buf = NULL;
|
||||
}
|
||||
ret = net_context_bind(*udp_recv6, (struct sockaddr *)&my_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 UDP port %d (%d)",
|
||||
ntohs(my_addr6.sin6_port), ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, mcast_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get receiving IPv6 mcast "
|
||||
"network context (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_bind(*mcast_recv6, (struct sockaddr *)&mcast_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 mcast (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP)
|
||||
ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, udp_recv4);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context for IPv4 UDP (%d)",
|
||||
ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_bind(*udp_recv4, (struct sockaddr *)&my_addr4,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv4 UDP port %d (%d)",
|
||||
ntohs(my_addr4.sin_port), ret);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool wait_reply(const char *name,
|
||||
struct net_context *ctx,
|
||||
int ipsum_len,
|
||||
int pos)
|
||||
struct k_sem *sem)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
bool fail = false;
|
||||
int expected_len = ipsum_len - pos;
|
||||
int ret = k_sem_take(sem, WAIT_TIME);
|
||||
|
||||
/* Wait for the answer */
|
||||
#if defined(CONFIG_NETWORKING_WITH_TCP)
|
||||
again:
|
||||
buf = net_receive(ctx, WAIT_TICKS);
|
||||
if (buf) {
|
||||
int total_len = expected_len, sum = 0, count = 0;
|
||||
|
||||
if (ip_buf_appdatalen(buf) < expected_len) {
|
||||
if (memcmp(lorem_ipsum + pos, ip_buf_appdata(buf),
|
||||
ip_buf_appdatalen(buf))) {
|
||||
PRINT("%s: received %d bytes (total %d), "
|
||||
"partial data mismatch\n",
|
||||
name, ip_buf_appdatalen(buf),
|
||||
expected_len);
|
||||
fail = true;
|
||||
goto free_buf;
|
||||
}
|
||||
/* So far everything is ok, more data to come,
|
||||
* wait it all.
|
||||
*/
|
||||
pos += ip_buf_appdatalen(buf);
|
||||
expected_len -= ip_buf_appdatalen(buf);
|
||||
sum += ip_buf_appdatalen(buf);
|
||||
ip_buf_unref(buf);
|
||||
count++;
|
||||
goto again;
|
||||
} else {
|
||||
/* Did we get all the data back?
|
||||
*/
|
||||
sum += ip_buf_appdatalen(buf);
|
||||
|
||||
if (memcmp(lorem_ipsum + pos, ip_buf_appdata(buf),
|
||||
expected_len)) {
|
||||
PRINT("%s: received data mismatch in "
|
||||
"last packet.\n", name);
|
||||
fail = true;
|
||||
goto free_buf;
|
||||
}
|
||||
|
||||
if (total_len != sum) {
|
||||
PRINT("Received %d bytes, expected %d\n",
|
||||
sum, total_len);
|
||||
} else {
|
||||
PRINT("Received %d bytes (in %d messages)\n",
|
||||
total_len, count + 1);
|
||||
}
|
||||
}
|
||||
#else
|
||||
buf = net_receive(ctx, WAIT_TICKS);
|
||||
if (buf) {
|
||||
if (ip_buf_appdatalen(buf) != expected_len) {
|
||||
PRINT("%s: received %d bytes, expected %d\n",
|
||||
name, ip_buf_appdatalen(buf), expected_len);
|
||||
fail = true;
|
||||
goto free_buf;
|
||||
}
|
||||
|
||||
/* In this test we reverse the received bytes.
|
||||
* We could just pass the data back as is but
|
||||
* this way it is possible to see how the app
|
||||
* can manipulate the received data.
|
||||
*/
|
||||
reverse(ip_buf_appdata(buf), ip_buf_appdatalen(buf));
|
||||
|
||||
/* Did we get all the data back?
|
||||
*/
|
||||
if (memcmp(lorem_ipsum + pos, ip_buf_appdata(buf),
|
||||
expected_len)) {
|
||||
PRINT("%s: received data mismatch.\n", name);
|
||||
fail = true;
|
||||
goto free_buf;
|
||||
}
|
||||
|
||||
PRINT("%s: received %d bytes\n", __func__,
|
||||
expected_len);
|
||||
#endif
|
||||
|
||||
free_buf:
|
||||
ip_buf_unref(buf);
|
||||
} else {
|
||||
PRINT("%s: expected data, got none\n", name);
|
||||
fail = true;
|
||||
if (!ret) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return fail;
|
||||
NET_ERR("wait_reply returned %s",
|
||||
ret == -EAGAIN ? "on time out" : "directly");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static inline bool get_context(struct net_context **unicast,
|
||||
struct net_context **multicast)
|
||||
static struct net_buf *prepare_send_buf(const char *name,
|
||||
struct net_context *context,
|
||||
int expecting_len)
|
||||
{
|
||||
static struct net_addr mcast_addr;
|
||||
static struct net_addr any_addr;
|
||||
static struct net_addr peer_addr;
|
||||
static struct net_addr my_addr;
|
||||
int proto = IPPROTO_UDP;
|
||||
struct net_buf *send_buf;
|
||||
bool status;
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_IPV6)
|
||||
static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
|
||||
static const struct in6_addr in6addr_mcast = MCAST_IPADDR;
|
||||
send_buf = net_nbuf_get_tx(context);
|
||||
|
||||
mcast_addr.in6_addr = in6addr_mcast;
|
||||
mcast_addr.family = AF_INET6;
|
||||
NET_ASSERT(send_buf);
|
||||
|
||||
peer_addr.in6_addr = in6addr_peer;
|
||||
peer_addr.family = AF_INET6;
|
||||
|
||||
any_addr.in6_addr = in6addr_any;
|
||||
any_addr.family = AF_INET6;
|
||||
|
||||
my_addr.in6_addr = in6addr_my;
|
||||
my_addr.family = AF_INET6;
|
||||
#else
|
||||
static const struct in_addr in4addr_any = { { { 0 } } };
|
||||
static struct in_addr in4addr_mcast = MCAST_IPADDR;
|
||||
static struct in_addr in4addr_peer = PEER_IPADDR;
|
||||
|
||||
mcast_addr.in_addr = in4addr_mcast;
|
||||
mcast_addr.family = AF_INET;
|
||||
|
||||
peer_addr.in_addr = in4addr_peer;
|
||||
peer_addr.family = AF_INET;
|
||||
|
||||
any_addr.in_addr = in4addr_any;
|
||||
any_addr.family = AF_INET;
|
||||
|
||||
my_addr.in_addr = in4addr_my;
|
||||
my_addr.family = AF_INET;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NETWORKING_WITH_TCP
|
||||
proto = IPPROTO_TCP;
|
||||
#endif /* CONFIG_NETWORKING_WITH_TCP */
|
||||
|
||||
*unicast = net_context_get(proto,
|
||||
&peer_addr, PEER_PORT,
|
||||
&my_addr, MY_PORT);
|
||||
if (!*unicast) {
|
||||
PRINT("%s: Cannot get sending network context\n",
|
||||
__func__);
|
||||
return false;
|
||||
status = net_nbuf_append(send_buf, expecting_len, lorem_ipsum);
|
||||
if (!status) {
|
||||
NET_ERR("%s: cannot create send buf", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_NETWORKING_WITH_TCP)
|
||||
*multicast = net_context_get(IPPROTO_UDP,
|
||||
&mcast_addr, PEER_PORT,
|
||||
&my_addr, MY_PORT);
|
||||
if (!*multicast) {
|
||||
PRINT("%s: Cannot get mcast sending network context\n",
|
||||
__func__);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
*multicast = NULL;
|
||||
#endif
|
||||
return true;
|
||||
return send_buf;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NANOKERNEL)
|
||||
#define STACKSIZE 2000
|
||||
static char __noinit __stack stack_receiving[STACKSIZE];
|
||||
#endif
|
||||
|
||||
static bool sending(int resend)
|
||||
static inline void udp_sent(struct net_context *context,
|
||||
int status,
|
||||
void *bytes_sent,
|
||||
void *user_data)
|
||||
{
|
||||
static bool send_unicast = true;
|
||||
int ret;
|
||||
#if defined(CONFIG_NETWORKING_WITH_TCP)
|
||||
static const char *type = "TCP";
|
||||
#else
|
||||
static const char *type = "Unicast";
|
||||
#endif
|
||||
|
||||
PRINT("%s: Sending packet\n", __func__);
|
||||
|
||||
if (resend) {
|
||||
expecting = resend;
|
||||
} else {
|
||||
expecting = sys_rand32_get() % ipsum_len;
|
||||
if (!status) {
|
||||
NET_INFO("%s: sent %u bytes", (char *)user_data,
|
||||
POINTER_TO_UINT(bytes_sent));
|
||||
}
|
||||
}
|
||||
|
||||
if (send_unicast) {
|
||||
again:
|
||||
ret = send_packet(__func__, unicast, ipsum_len,
|
||||
expecting);
|
||||
if (ret == -EAGAIN || ret == -EINPROGRESS) {
|
||||
fiber_sleep(10);
|
||||
PRINT("retrying...\n");
|
||||
goto again;
|
||||
} else if (ret == -ETIMEDOUT) {
|
||||
PRINT("Connection timed out\n");
|
||||
static inline void set_dst_addr(sa_family_t family,
|
||||
struct net_buf *buf,
|
||||
struct sockaddr *dst_addr)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (family == AF_INET6) {
|
||||
net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr,
|
||||
&in6addr_peer);
|
||||
net_sin6(dst_addr)->sin6_family = AF_INET6;
|
||||
net_sin6(dst_addr)->sin6_port = htons(PEER_PORT);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
if (family == AF_INET) {
|
||||
net_ipaddr_copy(&net_sin(dst_addr)->sin_addr,
|
||||
&in4addr_peer);
|
||||
net_sin(dst_addr)->sin_family = AF_INET;
|
||||
net_sin(dst_addr)->sin_port = htons(PEER_PORT);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
}
|
||||
|
||||
static bool compare_data(struct net_buf *buf, int expecting_len)
|
||||
{
|
||||
uint8_t *ptr = net_nbuf_appdata(buf);
|
||||
int pos = 0;
|
||||
int len;
|
||||
|
||||
/* Buf will now point to first fragment with IP header
|
||||
* in it.
|
||||
*/
|
||||
buf = buf->frags;
|
||||
|
||||
/* Do not include the protocol headers in len for the
|
||||
* first fragment. The remaining fragments contain only
|
||||
* data so the user data length is directly the fragment len.
|
||||
*/
|
||||
len = buf->len - (ptr - buf->data);
|
||||
|
||||
while (buf) {
|
||||
if (memcmp(ptr, lorem_ipsum + pos, len)) {
|
||||
NET_DBG("Invalid data received");
|
||||
return false;
|
||||
} else if (ret < 0) {
|
||||
PRINT("%s sending %d bytes FAIL\n", type,
|
||||
ipsum_len - expecting);
|
||||
} else {
|
||||
PRINT("%s sent %d bytes\n", type,
|
||||
ipsum_len - expecting);
|
||||
pos += len;
|
||||
|
||||
buf = buf->frags;
|
||||
if (!buf) {
|
||||
break;
|
||||
}
|
||||
|
||||
ptr = buf->data;
|
||||
len = buf->len;
|
||||
}
|
||||
#if !defined(CONFIG_NETWORKING_WITH_TCP)
|
||||
} else {
|
||||
if (send_packet(__func__, multicast, ipsum_len,
|
||||
expecting)) {
|
||||
PRINT("Multicast sending %d bytes FAIL\n",
|
||||
ipsum_len - expecting);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NET_DBG("Compared %d bytes, all ok", expecting_len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void receiving(void)
|
||||
static void setup_udp_recv(struct net_context *udp, void *user_data,
|
||||
net_context_recv_cb_t cb)
|
||||
{
|
||||
int expecting_len = 0;
|
||||
int ret;
|
||||
|
||||
while (sending(expecting_len)) {
|
||||
PRINT("Waiting packet\n");
|
||||
|
||||
if (wait_reply(__func__, unicast,
|
||||
ipsum_len, expecting)) {
|
||||
if (expecting_len > 0) {
|
||||
PRINT("Resend %d bytes -> FAIL\n",
|
||||
ipsum_len - expecting);
|
||||
expecting_len = 0;
|
||||
} else {
|
||||
PRINT("Waiting %d bytes -> resending\n",
|
||||
ipsum_len - expecting);
|
||||
expecting_len = expecting;
|
||||
}
|
||||
}
|
||||
fiber_sleep(10);
|
||||
ret = net_context_recv(udp, cb, 0, user_data);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive UDP packets");
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
static bool send_ipv4_data(struct net_context *udp)
|
||||
{
|
||||
struct net_buf *send_buf;
|
||||
struct sockaddr dst_addr;
|
||||
bool status = false;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
expecting_ipv4 = sys_rand32_get() % ipsum_len;
|
||||
|
||||
send_buf = prepare_send_buf("IPv4", udp, expecting_ipv4);
|
||||
if (!send_buf) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = net_buf_frags_len(send_buf);
|
||||
|
||||
NET_ASSERT_INFO(expecting_ipv4 == len,
|
||||
"Data to send %d bytes, real len %d",
|
||||
expecting_ipv4, len);
|
||||
|
||||
set_dst_addr(AF_INET, send_buf, &dst_addr);
|
||||
|
||||
ret = net_context_sendto(send_buf, &dst_addr,
|
||||
sizeof(struct sockaddr_in),
|
||||
udp_sent, 0,
|
||||
UINT_TO_POINTER(len),
|
||||
"IPv4");
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot send IPv4 data to peer (%d)", ret);
|
||||
net_nbuf_unref(send_buf);
|
||||
} else {
|
||||
status = true;
|
||||
}
|
||||
out:
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void udp_ipv4_received(struct net_context *context,
|
||||
struct net_buf *buf,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
sa_family_t family = net_nbuf_family(buf);
|
||||
struct k_sem *recv = user_data;
|
||||
|
||||
if (family == AF_INET) {
|
||||
if (expecting_ipv4 != net_nbuf_appdatalen(buf)) {
|
||||
NET_ERR("Sent %d bytes, received %d bytes",
|
||||
expecting_ipv4, net_nbuf_appdatalen(buf));
|
||||
}
|
||||
|
||||
if (!compare_data(buf, expecting_ipv4)) {
|
||||
NET_DBG("Data mismatch");
|
||||
}
|
||||
|
||||
net_nbuf_unref(buf);
|
||||
|
||||
k_sem_give(recv);
|
||||
}
|
||||
}
|
||||
|
||||
static void send_ipv4(struct net_context *udp)
|
||||
{
|
||||
setup_udp_recv(udp, &recv_ipv4, udp_ipv4_received);
|
||||
|
||||
NET_INFO("Starting to send IPv4 data");
|
||||
|
||||
do {
|
||||
/* We first send a packet, then wait for a packet to arrive.
|
||||
* If the reply does not come in time, we send another packet.
|
||||
*/
|
||||
send_ipv4_data(udp);
|
||||
|
||||
NET_DBG("Waiting IPv4 packet");
|
||||
|
||||
if (!wait_reply("IPv4", &recv_ipv4)) {
|
||||
NET_DBG("Waited %d bytes but did not receive them.",
|
||||
expecting_ipv4);
|
||||
}
|
||||
|
||||
k_yield();
|
||||
} while (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
static bool send_ipv6_data(struct net_context *udp)
|
||||
{
|
||||
struct net_buf *send_buf;
|
||||
struct sockaddr dst_addr;
|
||||
bool status = false;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
expecting_ipv6 = sys_rand32_get() % ipsum_len;
|
||||
|
||||
send_buf = prepare_send_buf("IPv6", udp, expecting_ipv6);
|
||||
if (!send_buf) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = net_buf_frags_len(send_buf);
|
||||
|
||||
NET_ASSERT_INFO(expecting_ipv6 == len,
|
||||
"Data to send %d bytes, real len %d",
|
||||
expecting_ipv6, len);
|
||||
|
||||
set_dst_addr(AF_INET6, send_buf, &dst_addr);
|
||||
|
||||
ret = net_context_sendto(send_buf, &dst_addr,
|
||||
sizeof(struct sockaddr_in6),
|
||||
udp_sent, 0,
|
||||
UINT_TO_POINTER(len),
|
||||
"IPv6");
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot send IPv6 data to peer (%d)", ret);
|
||||
net_nbuf_unref(send_buf);
|
||||
} else {
|
||||
status = true;
|
||||
}
|
||||
out:
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void udp_ipv6_received(struct net_context *context,
|
||||
struct net_buf *buf,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
sa_family_t family = net_nbuf_family(buf);
|
||||
struct k_sem *recv = user_data;
|
||||
|
||||
if (family == AF_INET6) {
|
||||
if (expecting_ipv6 != net_nbuf_appdatalen(buf)) {
|
||||
NET_ERR("Sent %d bytes, received %d bytes",
|
||||
expecting_ipv6, net_nbuf_appdatalen(buf));
|
||||
}
|
||||
|
||||
if (!compare_data(buf, expecting_ipv6)) {
|
||||
NET_DBG("Data mismatch");
|
||||
}
|
||||
|
||||
net_nbuf_unref(buf);
|
||||
|
||||
k_sem_give(recv);
|
||||
}
|
||||
}
|
||||
|
||||
static void send_ipv6(struct net_context *udp)
|
||||
{
|
||||
setup_udp_recv(udp, &recv_ipv6, udp_ipv6_received);
|
||||
|
||||
NET_INFO("Starting to send IPv6 data");
|
||||
|
||||
do {
|
||||
/* We first send a packet, then wait for a packet to arrive.
|
||||
* If the reply does not come in time, we send another packet.
|
||||
*/
|
||||
send_ipv6_data(udp);
|
||||
|
||||
NET_DBG("Waiting IPv6 packet");
|
||||
|
||||
if (!wait_reply("IPv6", &recv_ipv6)) {
|
||||
NET_DBG("Waited %d bytes but did not receive them.",
|
||||
expecting_ipv6);
|
||||
}
|
||||
|
||||
k_yield();
|
||||
} while (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void main(void)
|
||||
{
|
||||
net_init();
|
||||
struct net_context *udp_send4 = { 0 };
|
||||
struct net_context *udp_send6 = { 0 };
|
||||
struct net_context *mcast_send6 = { 0 };
|
||||
|
||||
init_app();
|
||||
|
||||
if (!get_context(&udp_send4, &udp_send6, &mcast_send6)) {
|
||||
NET_ERR("Cannot get network contexts");
|
||||
return;
|
||||
}
|
||||
|
||||
ipsum_len = strlen(lorem_ipsum);
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_BT)
|
||||
|
@ -486,15 +591,15 @@ void main(void)
|
|||
ipss_advertise();
|
||||
#endif
|
||||
|
||||
if (!get_context(&unicast, &multicast)) {
|
||||
PRINT("%s: Cannot get network context\n", __func__);
|
||||
return;
|
||||
}
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
k_thread_spawn(ipv4_stack, STACKSIZE,
|
||||
(k_thread_entry_t)send_ipv4,
|
||||
udp_send4, NULL, NULL, K_PRIO_COOP(7), 0, 0);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MICROKERNEL)
|
||||
receiving();
|
||||
#else
|
||||
task_fiber_start(&stack_receiving[0], STACKSIZE,
|
||||
(nano_fiber_entry_t)receiving, 0, 0, 7, 0);
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
k_thread_spawn(ipv6_stack, STACKSIZE,
|
||||
(k_thread_entry_t)send_ipv6,
|
||||
udp_send6, NULL, NULL, K_PRIO_COOP(7), 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -4,9 +4,8 @@ CONFIG_INIT_STACKS=y
|
|||
CONFIG_MAIN_STACK_SIZE=1024
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_NANO_TIMEOUTS=y
|
||||
# YAIP Configuration
|
||||
# IP Stack Configuration
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_ARP=y
|
||||
CONFIG_NET_L2_ETHERNET=y
|
||||
CONFIG_NET_IPV4=y
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
CONFIG_ARC_INIT=n
|
||||
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
|
||||
CONFIG_NET_NBUF_RX_COUNT=10
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
CONFIG_SYS_LOG=y
|
||||
CONFIG_NETWORKING_IPV6_NO_ND=y
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NETWORKING_WITH_LOGGING=y
|
||||
CONFIG_NETWORKING_WITH_LOOPBACK=y
|
||||
CONFIG_NETWORKING_UART=y
|
||||
CONFIG_NETWORKING_DEBUG_UART=y
|
||||
CONFIG_IP_BUF_RX_SIZE=8
|
||||
CONFIG_IP_BUF_TX_SIZE=2
|
||||
CONFIG_NET_NBUF_TX_COUNT=8
|
||||
CONFIG_NET_NBUF_RX_COUNT=8
|
||||
CONFIG_NET_NBUF_DATA_COUNT=20
|
||||
CONFIG_NANO_TIMEOUTS=y
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
ccflags-$(CONFIG_NET_UIP) +=-I${ZEPHYR_BASE}/net/ip
|
||||
ccflags-$(CONFIG_NETWORKING_WITH_BT) +=-I${ZEPHYR_BASE}/samples/bluetooth/
|
||||
|
||||
ifeq ($(CONFIG_NET_YAIP), y)
|
||||
obj-y = echo-server-yaip.o
|
||||
else
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os/lib
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/net/ip/contiki/os
|
||||
obj-y = echo-server.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET_TESTING), y)
|
||||
ccflags-y +=-I${ZEPHYR_BASE}/samples/net/common/
|
||||
|
|
|
@ -1,562 +0,0 @@
|
|||
/* echo.c - Networking echo server */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if 1
|
||||
#define SYS_LOG_DOMAIN "echo-server"
|
||||
#define SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
|
||||
#define NET_DEBUG 1
|
||||
#endif
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <sections.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <net/nbuf.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_context.h>
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_BT)
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <gatt/ipss.h>
|
||||
#endif
|
||||
|
||||
/* Allow binding to ANY IP address. */
|
||||
#define NET_BIND_ANY_ADDR 1
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
/* admin-local, dynamically allocated multicast address */
|
||||
#define MCAST_IP6ADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
|
||||
struct in6_addr in6addr_mcast = MCAST_IP6ADDR;
|
||||
|
||||
/* Define my IP address where to expect messages */
|
||||
#define MY_IP6ADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } }
|
||||
#define MY_PREFIX_LEN 64
|
||||
|
||||
static struct in6_addr in6addr_my = MY_IP6ADDR;
|
||||
#endif /* IPv6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
/* Organization-local 239.192.0.0/14 */
|
||||
#define MCAST_IP4ADDR { { { 239, 192, 0, 2 } } }
|
||||
|
||||
/* The 192.0.2.0/24 is the private address space for documentation RFC 5737 */
|
||||
#define MY_IP4ADDR { { { 192, 0, 2, 1 } } }
|
||||
|
||||
#if !defined(CONFIG_NET_DHCPV4) || !NET_BIND_ANY_ADDR
|
||||
static struct in_addr in4addr_my = MY_IP4ADDR;
|
||||
#endif /* CONFIG_NET_DHCPV4 || !NET_BIND_ANY_ADDR */
|
||||
#endif /* IPv4 */
|
||||
|
||||
#define MY_PORT 4242
|
||||
|
||||
#define STACKSIZE 2000
|
||||
char __noinit __stack thread_stack[STACKSIZE];
|
||||
|
||||
#define MAX_DBG_PRINT 64
|
||||
|
||||
static struct k_sem quit_lock;
|
||||
|
||||
static inline void quit(void)
|
||||
{
|
||||
k_sem_give(&quit_lock);
|
||||
}
|
||||
|
||||
static inline void init_app(void)
|
||||
{
|
||||
NET_INFO("Run echo server");
|
||||
|
||||
k_sem_init(&quit_lock, 0, UINT_MAX);
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
#if defined(CONFIG_NET_SAMPLES_MY_IPV6_ADDR)
|
||||
if (net_addr_pton(AF_INET6,
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR,
|
||||
(struct sockaddr *)&in6addr_my) < 0) {
|
||||
NET_ERR("Invalid IPv6 address %s",
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
do {
|
||||
struct net_if_addr *ifaddr;
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(net_if_get_default(),
|
||||
&in6addr_my, NET_ADDR_MANUAL, 0);
|
||||
} while (0);
|
||||
|
||||
net_if_ipv6_maddr_add(net_if_get_default(), &in6addr_mcast);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
#if defined(CONFIG_NET_DHCPV4)
|
||||
net_dhcpv4_start(net_if_get_default());
|
||||
#else
|
||||
#if defined(CONFIG_NET_SAMPLES_MY_IPV4_ADDR)
|
||||
if (net_addr_pton(AF_INET,
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR,
|
||||
(struct sockaddr *)&in4addr_my) < 0) {
|
||||
NET_ERR("Invalid IPv4 address %s",
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
net_if_ipv4_addr_add(net_if_get_default(), &in4addr_my,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
#endif /* CONFIG_NET_DHCPV4 */
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
}
|
||||
|
||||
static inline bool get_context(struct net_context **udp_recv4,
|
||||
struct net_context **udp_recv6,
|
||||
struct net_context **tcp_recv4,
|
||||
struct net_context **tcp_recv6,
|
||||
struct net_context **mcast_recv6)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
struct sockaddr_in6 mcast_addr6 = { 0 };
|
||||
struct sockaddr_in6 my_addr6 = { 0 };
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
struct sockaddr_in my_addr4 = { 0 };
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
net_ipaddr_copy(&mcast_addr6.sin6_addr, &in6addr_mcast);
|
||||
mcast_addr6.sin6_family = AF_INET6;
|
||||
|
||||
#if !NET_BIND_ANY_ADDR
|
||||
net_ipaddr_copy(&my_addr6.sin6_addr, &in6addr_my);
|
||||
#endif
|
||||
|
||||
my_addr6.sin6_family = AF_INET6;
|
||||
my_addr6.sin6_port = htons(MY_PORT);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
#if !NET_BIND_ANY_ADDR
|
||||
net_ipaddr_copy(&my_addr4.sin_addr, &in4addr_my);
|
||||
#endif
|
||||
|
||||
my_addr4.sin_family = AF_INET;
|
||||
my_addr4.sin_port = htons(MY_PORT);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_UDP)
|
||||
ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, udp_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context for IPv6 UDP (%d)",
|
||||
ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_bind(*udp_recv6, (struct sockaddr *)&my_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 UDP port %d (%d)",
|
||||
ntohs(my_addr6.sin6_port), ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, mcast_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get receiving IPv6 mcast "
|
||||
"network context (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_bind(*mcast_recv6, (struct sockaddr *)&mcast_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 mcast (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP)
|
||||
ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, udp_recv4);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context for IPv4 UDP (%d)",
|
||||
ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_bind(*udp_recv4, (struct sockaddr *)&my_addr4,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv4 UDP port %d (%d)",
|
||||
ntohs(my_addr4.sin_port), ret);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_TCP)
|
||||
if (tcp_recv6) {
|
||||
ret = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP,
|
||||
tcp_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context "
|
||||
"for IPv6 TCP (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_bind(*tcp_recv6,
|
||||
(struct sockaddr *)&my_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 TCP port %d (%d)",
|
||||
ntohs(my_addr6.sin6_port), ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_listen(*tcp_recv6, 0);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot listen IPv6 TCP (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_TCP)
|
||||
if (tcp_recv4) {
|
||||
ret = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP,
|
||||
tcp_recv4);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context for IPv4 TCP");
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_bind(*tcp_recv4,
|
||||
(struct sockaddr *)&my_addr4,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv4 TCP port %d",
|
||||
ntohs(my_addr4.sin_port));
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_listen(*tcp_recv4, 0);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot listen IPv4 TCP");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct net_buf *build_reply_buf(const char *name,
|
||||
struct net_context *context,
|
||||
struct net_buf *buf)
|
||||
{
|
||||
struct net_buf *reply_buf, *frag, *tmp;
|
||||
int header_len, recv_len, reply_len;
|
||||
|
||||
NET_INFO("%s received %d bytes", name,
|
||||
net_nbuf_appdatalen(buf));
|
||||
|
||||
reply_buf = net_nbuf_get_tx(context);
|
||||
|
||||
NET_ASSERT(reply_buf);
|
||||
|
||||
recv_len = net_buf_frags_len(buf->frags);
|
||||
|
||||
tmp = buf->frags;
|
||||
|
||||
/* First fragment will contain IP header so move the data
|
||||
* down in order to get rid of it.
|
||||
*/
|
||||
header_len = net_nbuf_appdata(buf) - tmp->data;
|
||||
|
||||
NET_ASSERT(header_len < CONFIG_NET_NBUF_DATA_SIZE);
|
||||
|
||||
/* After this pull, the tmp->data points directly to application
|
||||
* data.
|
||||
*/
|
||||
net_buf_pull(tmp, header_len);
|
||||
|
||||
while (tmp) {
|
||||
frag = net_nbuf_get_data(context);
|
||||
|
||||
if (!net_buf_headroom(tmp)) {
|
||||
/* If there is no link layer headers in the
|
||||
* received fragment, then get rid of that also
|
||||
* in the sending fragment. We end up here
|
||||
* if MTU is larger than fragment size, this
|
||||
* is typical for ethernet.
|
||||
*/
|
||||
net_buf_push(frag, net_buf_headroom(frag));
|
||||
|
||||
frag->len = 0; /* to make fragment empty */
|
||||
|
||||
/* Make sure to set the reserve so that
|
||||
* in sending side we add the link layer
|
||||
* header if needed.
|
||||
*/
|
||||
net_nbuf_set_ll_reserve(reply_buf, 0);
|
||||
}
|
||||
|
||||
NET_ASSERT(net_buf_tailroom(frag) >= tmp->len);
|
||||
|
||||
memcpy(net_buf_add(frag, tmp->len), tmp->data, tmp->len);
|
||||
|
||||
net_buf_frag_add(reply_buf, frag);
|
||||
|
||||
net_buf_frag_del(buf, tmp);
|
||||
|
||||
tmp = buf->frags;
|
||||
}
|
||||
|
||||
reply_len = net_buf_frags_len(reply_buf->frags);
|
||||
|
||||
NET_ASSERT_INFO((recv_len - header_len) == reply_len,
|
||||
"Received %d bytes, sending %d bytes",
|
||||
recv_len - header_len, reply_len);
|
||||
|
||||
return reply_buf;
|
||||
}
|
||||
|
||||
static inline void pkt_sent(struct net_context *context,
|
||||
int status,
|
||||
void *token,
|
||||
void *user_data)
|
||||
{
|
||||
if (!status) {
|
||||
NET_INFO("Sent %d bytes", POINTER_TO_UINT(token));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
static inline void set_dst_addr(sa_family_t family,
|
||||
struct net_buf *buf,
|
||||
struct sockaddr *dst_addr)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (family == AF_INET6) {
|
||||
net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr,
|
||||
&NET_IPV6_BUF(buf)->src);
|
||||
net_sin6(dst_addr)->sin6_family = AF_INET6;
|
||||
net_sin6(dst_addr)->sin6_port = NET_UDP_BUF(buf)->src_port;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6) */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
if (family == AF_INET) {
|
||||
net_ipaddr_copy(&net_sin(dst_addr)->sin_addr,
|
||||
&NET_IPV4_BUF(buf)->src);
|
||||
net_sin(dst_addr)->sin_family = AF_INET;
|
||||
net_sin(dst_addr)->sin_port = NET_UDP_BUF(buf)->src_port;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6) */
|
||||
}
|
||||
|
||||
static void udp_received(struct net_context *context,
|
||||
struct net_buf *buf,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
struct net_buf *reply_buf;
|
||||
struct sockaddr dst_addr;
|
||||
sa_family_t family = net_nbuf_family(buf);
|
||||
static char dbg[MAX_DBG_PRINT + 1];
|
||||
int ret;
|
||||
|
||||
snprintf(dbg, MAX_DBG_PRINT, "UDP IPv%c",
|
||||
family == AF_INET6 ? '6' : '4');
|
||||
|
||||
set_dst_addr(family, buf, &dst_addr);
|
||||
|
||||
reply_buf = build_reply_buf(dbg, context, buf);
|
||||
|
||||
net_nbuf_unref(buf);
|
||||
|
||||
ret = net_context_sendto(reply_buf, &dst_addr,
|
||||
family == AF_INET6 ?
|
||||
sizeof(struct sockaddr_in6) :
|
||||
sizeof(struct sockaddr_in),
|
||||
pkt_sent, 0,
|
||||
UINT_TO_POINTER(net_buf_frags_len(reply_buf)),
|
||||
user_data);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot send data to peer (%d)", ret);
|
||||
net_nbuf_unref(reply_buf);
|
||||
|
||||
quit();
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_udp_recv(struct net_context *udp_recv4,
|
||||
struct net_context *udp_recv6)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
ret = net_context_recv(udp_recv6, udp_received, 0, NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive IPv6 UDP packets");
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
ret = net_context_recv(udp_recv4, udp_received, 0, NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive IPv4 UDP packets");
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
}
|
||||
#endif /* CONFIG_NET_UDP */
|
||||
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
static void tcp_received(struct net_context *context,
|
||||
struct net_buf *buf,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
static char dbg[MAX_DBG_PRINT + 1];
|
||||
sa_family_t family = net_nbuf_family(buf);
|
||||
struct net_buf *reply_buf;
|
||||
int ret;
|
||||
|
||||
snprintf(dbg, MAX_DBG_PRINT, "TCP IPv%c",
|
||||
family == AF_INET6 ? '6' : '4');
|
||||
|
||||
reply_buf = build_reply_buf(dbg, context, buf);
|
||||
|
||||
net_buf_unref(buf);
|
||||
|
||||
ret = net_context_send(reply_buf, pkt_sent, K_NO_WAIT,
|
||||
UINT_TO_POINTER(net_buf_frags_len(reply_buf)),
|
||||
NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot send data to peer (%d)", ret);
|
||||
net_nbuf_unref(reply_buf);
|
||||
|
||||
quit();
|
||||
}
|
||||
}
|
||||
|
||||
static void tcp_accepted(struct net_context *context,
|
||||
struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
int error,
|
||||
void *user_data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
NET_DBG("Accept called, context %p error %d", context, error);
|
||||
|
||||
ret = net_context_recv(context, tcp_received, 0, NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive TCP packet (family %d)",
|
||||
net_context_get_family(context));
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_tcp_accept(struct net_context *tcp_recv4,
|
||||
struct net_context *tcp_recv6)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
ret = net_context_accept(tcp_recv6, tcp_accepted, 0, NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive IPv6 TCP packets (%d)", ret);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
ret = net_context_accept(tcp_recv4, tcp_accepted, 0, NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive IPv4 TCP packets (%d)", ret);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
}
|
||||
#endif /* CONFIG_NET_TCP */
|
||||
|
||||
void receive(void)
|
||||
{
|
||||
struct net_context *udp_recv4 = { 0 };
|
||||
struct net_context *udp_recv6 = { 0 };
|
||||
struct net_context *tcp_recv4 = { 0 };
|
||||
struct net_context *tcp_recv6 = { 0 };
|
||||
struct net_context *mcast_recv6 = { 0 };
|
||||
|
||||
if (!get_context(&udp_recv4, &udp_recv6,
|
||||
&tcp_recv4, &tcp_recv6,
|
||||
&mcast_recv6)) {
|
||||
NET_ERR("Cannot get network contexts");
|
||||
return;
|
||||
}
|
||||
|
||||
NET_INFO("Starting to wait");
|
||||
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
setup_tcp_accept(tcp_recv4, tcp_recv6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
setup_udp_recv(udp_recv4, udp_recv6);
|
||||
#endif
|
||||
|
||||
k_sem_take(&quit_lock, K_FOREVER);
|
||||
|
||||
NET_INFO("Stopping...");
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_UDP)
|
||||
net_context_put(udp_recv6);
|
||||
net_context_put(mcast_recv6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP)
|
||||
net_context_put(udp_recv4);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_TCP)
|
||||
net_context_put(tcp_recv6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_TCP)
|
||||
net_context_put(tcp_recv4);
|
||||
#endif
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
init_app();
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_BT)
|
||||
if (bt_enable(NULL)) {
|
||||
NET_ERR("Bluetooth init failed");
|
||||
return;
|
||||
}
|
||||
ipss_init();
|
||||
ipss_advertise();
|
||||
#endif
|
||||
|
||||
k_thread_spawn(&thread_stack[0], STACKSIZE,
|
||||
(k_thread_entry_t)receive,
|
||||
NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/* echo.c - Networking echo server */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015 Intel Corporation.
|
||||
* Copyright (c) 2016 Intel Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,303 +16,547 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_STDOUT_CONSOLE)
|
||||
#include <stdio.h>
|
||||
#define PRINT printf
|
||||
#else
|
||||
#include <misc/printk.h>
|
||||
#define PRINT printk
|
||||
#if 1
|
||||
#define SYS_LOG_DOMAIN "echo-server"
|
||||
#define SYS_LOG_LEVEL SYS_LOG_LEVEL_DEBUG
|
||||
#define NET_DEBUG 1
|
||||
#endif
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <sections.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <net/ip_buf.h>
|
||||
#include <net/nbuf.h>
|
||||
#include <net/net_if.h>
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_socket.h>
|
||||
#include <net/net_context.h>
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_BT)
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <gatt/ipss.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_TESTING)
|
||||
#include <net_testing.h>
|
||||
#else
|
||||
#if defined(CONFIG_NETWORKING_WITH_IPV6)
|
||||
#include <contiki/ipv6/uip-ds6.h>
|
||||
#else
|
||||
#include <contiki/ip/uipaddr.h>
|
||||
#endif /* IPv6 */
|
||||
#endif /* CONFIG_NET_TESTING */
|
||||
/* Allow binding to ANY IP address. */
|
||||
#define NET_BIND_ANY_ADDR 1
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_IPV6)
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
/* admin-local, dynamically allocated multicast address */
|
||||
#define MCAST_IPADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
#define MCAST_IP6ADDR { { { 0xff, 0x84, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
|
||||
struct in6_addr in6addr_mcast = MCAST_IP6ADDR;
|
||||
|
||||
/* Define my IP address where to expect messages */
|
||||
#if !defined(CONFIG_NET_TESTING)
|
||||
#define MY_IPADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2 } } }
|
||||
#define MY_IP6ADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0x1 } } }
|
||||
#define MY_PREFIX_LEN 64
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_TESTING)
|
||||
static const struct in6_addr in6addr_my = IN6ADDR_ANY_INIT;
|
||||
#else
|
||||
static const struct in6_addr in6addr_my = MY_IPADDR;
|
||||
#endif
|
||||
|
||||
#else /* IPv6 */
|
||||
|
||||
/* Organization-local 239.192.0.0/14 */
|
||||
#define MCAST_IPADDR { { { 239, 192, 0, 2 } } }
|
||||
|
||||
#if !defined(CONFIG_NET_TESTING)
|
||||
/* The 192.0.2.0/24 is the private address space for documentation RFC 5737 */
|
||||
#define UIP_IPADDR0 192
|
||||
#define UIP_IPADDR1 0
|
||||
#define UIP_IPADDR2 2
|
||||
#define UIP_IPADDR3 2
|
||||
|
||||
#define UIP_DRIPADDR0 UIP_IPADDR0
|
||||
#define UIP_DRIPADDR1 UIP_IPADDR1
|
||||
#define UIP_DRIPADDR2 UIP_IPADDR2
|
||||
#define UIP_DRIPADDR3 42
|
||||
|
||||
#define MY_IPADDR { { { UIP_IPADDR0, UIP_IPADDR1, UIP_IPADDR2, UIP_IPADDR3 } } }
|
||||
|
||||
uip_ipaddr_t uip_hostaddr = { { UIP_IPADDR0, UIP_IPADDR1,
|
||||
UIP_IPADDR2, UIP_IPADDR3 } };
|
||||
uip_ipaddr_t uip_draddr = { { UIP_DRIPADDR0, UIP_DRIPADDR1,
|
||||
UIP_DRIPADDR2, UIP_DRIPADDR3 } };
|
||||
uip_ipaddr_t uip_netmask = { { 255, 255, 255, 0 } };
|
||||
#endif /* CONFIG_NET_TESTING */
|
||||
|
||||
static struct in6_addr in6addr_my = MY_IP6ADDR;
|
||||
#endif /* IPv6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
/* Organization-local 239.192.0.0/14 */
|
||||
#define MCAST_IP4ADDR { { { 239, 192, 0, 2 } } }
|
||||
|
||||
/* The 192.0.2.0/24 is the private address space for documentation RFC 5737 */
|
||||
#define MY_IP4ADDR { { { 192, 0, 2, 1 } } }
|
||||
|
||||
#if !defined(CONFIG_NET_DHCPV4) || !NET_BIND_ANY_ADDR
|
||||
static struct in_addr in4addr_my = MY_IP4ADDR;
|
||||
#endif /* CONFIG_NET_DHCPV4 || !NET_BIND_ANY_ADDR */
|
||||
#endif /* IPv4 */
|
||||
|
||||
#define MY_PORT 4242
|
||||
|
||||
#define STACKSIZE 2000
|
||||
char __noinit __stack thread_stack[STACKSIZE];
|
||||
|
||||
#define MAX_DBG_PRINT 64
|
||||
|
||||
static struct k_sem quit_lock;
|
||||
|
||||
static inline void quit(void)
|
||||
{
|
||||
k_sem_give(&quit_lock);
|
||||
}
|
||||
|
||||
static inline void init_app(void)
|
||||
{
|
||||
PRINT("%s: run echo server\n", __func__);
|
||||
NET_INFO("Run echo server");
|
||||
|
||||
#if defined(CONFIG_NET_TESTING)
|
||||
net_testing_setup();
|
||||
k_sem_init(&quit_lock, 0, UINT_MAX);
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
#if defined(CONFIG_NET_SAMPLES_MY_IPV6_ADDR)
|
||||
if (net_addr_pton(AF_INET6,
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR,
|
||||
(struct sockaddr *)&in6addr_my) < 0) {
|
||||
NET_ERR("Invalid IPv6 address %s",
|
||||
CONFIG_NET_SAMPLES_MY_IPV6_ADDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
do {
|
||||
struct net_if_addr *ifaddr;
|
||||
|
||||
ifaddr = net_if_ipv6_addr_add(net_if_get_default(),
|
||||
&in6addr_my, NET_ADDR_MANUAL, 0);
|
||||
} while (0);
|
||||
|
||||
net_if_ipv6_maddr_add(net_if_get_default(), &in6addr_mcast);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
#if defined(CONFIG_NET_DHCPV4)
|
||||
net_dhcpv4_start(net_if_get_default());
|
||||
#else
|
||||
#if defined(CONFIG_NETWORKING_WITH_IPV6)
|
||||
uip_ds6_prefix_add((uip_ipaddr_t *)&in6addr_my, MY_PREFIX_LEN, 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void reverse(unsigned char *buf, int len)
|
||||
{
|
||||
int i, last = len - 1;
|
||||
|
||||
for (i = 0; i < len / 2; i++) {
|
||||
unsigned char tmp = buf[i];
|
||||
buf[i] = buf[last - i];
|
||||
buf[last - i] = tmp;
|
||||
#if defined(CONFIG_NET_SAMPLES_MY_IPV4_ADDR)
|
||||
if (net_addr_pton(AF_INET,
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR,
|
||||
(struct sockaddr *)&in4addr_my) < 0) {
|
||||
NET_ERR("Invalid IPv4 address %s",
|
||||
CONFIG_NET_SAMPLES_MY_IPV4_ADDR);
|
||||
}
|
||||
#endif
|
||||
|
||||
net_if_ipv4_addr_add(net_if_get_default(), &in4addr_my,
|
||||
NET_ADDR_MANUAL, 0);
|
||||
#endif /* CONFIG_NET_DHCPV4 */
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
}
|
||||
|
||||
static inline struct net_buf *prepare_reply(const char *name,
|
||||
const char *type,
|
||||
struct net_buf *buf,
|
||||
int proto)
|
||||
static inline bool get_context(struct net_context **udp_recv4,
|
||||
struct net_context **udp_recv6,
|
||||
struct net_context **tcp_recv4,
|
||||
struct net_context **tcp_recv6,
|
||||
struct net_context **mcast_recv6)
|
||||
{
|
||||
PRINT("%s: %sreceived %d bytes data\n", name, type,
|
||||
ip_buf_appdatalen(buf));
|
||||
int ret;
|
||||
|
||||
if (proto != IPPROTO_TCP) {
|
||||
/* In this test we reverse the received bytes.
|
||||
* We could just pass the data back as is but
|
||||
* this way it is possible to see how the app
|
||||
* can manipulate the received data.
|
||||
*/
|
||||
reverse(ip_buf_appdata(buf), ip_buf_appdatalen(buf));
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
struct sockaddr_in6 mcast_addr6 = { 0 };
|
||||
struct sockaddr_in6 my_addr6 = { 0 };
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
struct sockaddr_in my_addr4 = { 0 };
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
net_ipaddr_copy(&mcast_addr6.sin6_addr, &in6addr_mcast);
|
||||
mcast_addr6.sin6_family = AF_INET6;
|
||||
|
||||
#if !NET_BIND_ANY_ADDR
|
||||
net_ipaddr_copy(&my_addr6.sin6_addr, &in6addr_my);
|
||||
#endif
|
||||
|
||||
my_addr6.sin6_family = AF_INET6;
|
||||
my_addr6.sin6_port = htons(MY_PORT);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
#if !NET_BIND_ANY_ADDR
|
||||
net_ipaddr_copy(&my_addr4.sin_addr, &in4addr_my);
|
||||
#endif
|
||||
|
||||
my_addr4.sin_family = AF_INET;
|
||||
my_addr4.sin_port = htons(MY_PORT);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_UDP)
|
||||
ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, udp_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context for IPv6 UDP (%d)",
|
||||
ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_TESTING)
|
||||
net_testing_set_reply_address(buf);
|
||||
ret = net_context_bind(*udp_recv6, (struct sockaddr *)&my_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 UDP port %d (%d)",
|
||||
ntohs(my_addr6.sin6_port), ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, mcast_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get receiving IPv6 mcast "
|
||||
"network context (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = net_context_bind(*mcast_recv6, (struct sockaddr *)&mcast_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 mcast (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return buf;
|
||||
}
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP)
|
||||
ret = net_context_get(AF_INET, SOCK_DGRAM, IPPROTO_UDP, udp_recv4);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context for IPv4 UDP (%d)",
|
||||
ret);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* How many tics to wait for a network packet */
|
||||
#if 1
|
||||
#define WAIT_TIME 0
|
||||
#define WAIT_TICKS (WAIT_TIME * sys_clock_ticks_per_sec / 10)
|
||||
#else
|
||||
#define WAIT_TICKS TICKS_UNLIMITED
|
||||
ret = net_context_bind(*udp_recv4, (struct sockaddr *)&my_addr4,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv4 UDP port %d (%d)",
|
||||
ntohs(my_addr4.sin_port), ret);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct nano_fifo *net_context_get_queue(struct net_context *context);
|
||||
static inline void receive_and_reply(const char *name,
|
||||
struct net_context *udp_recv,
|
||||
struct net_context *tcp_recv,
|
||||
struct net_context *mcast_recv)
|
||||
{
|
||||
struct net_buf *buf;
|
||||
|
||||
buf = net_receive(udp_recv, WAIT_TICKS);
|
||||
if (buf) {
|
||||
prepare_reply(name, "unicast ", buf, IPPROTO_UDP);
|
||||
|
||||
if (net_reply(udp_recv, buf)) {
|
||||
ip_buf_unref(buf);
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_TCP)
|
||||
if (tcp_recv6) {
|
||||
ret = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP,
|
||||
tcp_recv6);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context "
|
||||
"for IPv6 TCP (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
buf = net_receive(mcast_recv, WAIT_TICKS);
|
||||
if (buf) {
|
||||
prepare_reply(name, "multicast ", buf, IPPROTO_UDP);
|
||||
|
||||
if (net_reply(mcast_recv, buf)) {
|
||||
ip_buf_unref(buf);
|
||||
ret = net_context_bind(*tcp_recv6,
|
||||
(struct sockaddr *)&my_addr6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv6 TCP port %d (%d)",
|
||||
ntohs(my_addr6.sin6_port), ret);
|
||||
return false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_TCP)
|
||||
if (tcp_recv) {
|
||||
static struct net_buf *tcpbuf;
|
||||
|
||||
if (tcpbuf) {
|
||||
int ret;
|
||||
reply:
|
||||
ret = net_reply(tcp_recv, tcpbuf);
|
||||
if (ret && ret != -EAGAIN) {
|
||||
ip_buf_unref(tcpbuf);
|
||||
tcpbuf = NULL;
|
||||
} else if (!ret) {
|
||||
tcpbuf = NULL;
|
||||
} else {
|
||||
PRINT("Retrying to send packet %p\n", tcpbuf);
|
||||
}
|
||||
} else {
|
||||
tcpbuf = net_receive(tcp_recv, WAIT_TICKS);
|
||||
if (tcpbuf) {
|
||||
PRINT("Received packet %p len %d\n",
|
||||
tcpbuf, ip_buf_appdatalen(tcpbuf));
|
||||
prepare_reply(name, "tcp ", tcpbuf, IPPROTO_TCP);
|
||||
goto reply;
|
||||
}
|
||||
ret = net_context_listen(*tcp_recv6, 0);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot listen IPv6 TCP (%d)", ret);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
fiber_sleep(50);
|
||||
}
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_TCP)
|
||||
if (tcp_recv4) {
|
||||
ret = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP,
|
||||
tcp_recv4);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot get network context for IPv4 TCP");
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool get_context(struct net_context **udp_recv,
|
||||
struct net_context **tcp_recv,
|
||||
struct net_context **mcast_recv)
|
||||
{
|
||||
static struct net_addr mcast_addr;
|
||||
static struct net_addr any_addr;
|
||||
static struct net_addr my_addr;
|
||||
ret = net_context_bind(*tcp_recv4,
|
||||
(struct sockaddr *)&my_addr4,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot bind IPv4 TCP port %d",
|
||||
ntohs(my_addr4.sin_port));
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_IPV6)
|
||||
static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
|
||||
static const struct in6_addr in6addr_mcast = MCAST_IPADDR;
|
||||
|
||||
mcast_addr.in6_addr = in6addr_mcast;
|
||||
mcast_addr.family = AF_INET6;
|
||||
|
||||
any_addr.in6_addr = in6addr_any;
|
||||
any_addr.family = AF_INET6;
|
||||
|
||||
my_addr.in6_addr = in6addr_my;
|
||||
my_addr.family = AF_INET6;
|
||||
#else
|
||||
static const struct in_addr in4addr_any = { { { 0 } } };
|
||||
static struct in_addr in4addr_my = MY_IPADDR;
|
||||
static struct in_addr in4addr_mcast = MCAST_IPADDR;
|
||||
|
||||
mcast_addr.in_addr = in4addr_mcast;
|
||||
mcast_addr.family = AF_INET;
|
||||
|
||||
any_addr.in_addr = in4addr_any;
|
||||
any_addr.family = AF_INET;
|
||||
|
||||
my_addr.in_addr = in4addr_my;
|
||||
my_addr.family = AF_INET;
|
||||
#endif
|
||||
|
||||
*udp_recv = net_context_get(IPPROTO_UDP,
|
||||
&any_addr, 0,
|
||||
&my_addr, MY_PORT);
|
||||
if (!*udp_recv) {
|
||||
PRINT("%s: Cannot get network context\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_TCP)
|
||||
if (tcp_recv) {
|
||||
*tcp_recv = net_context_get(IPPROTO_TCP,
|
||||
&any_addr, 0,
|
||||
&my_addr, MY_PORT);
|
||||
if (!*tcp_recv) {
|
||||
PRINT("%s: Cannot get network context\n", __func__);
|
||||
return NULL;
|
||||
ret = net_context_listen(*tcp_recv4, 0);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot listen IPv4 TCP");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
*mcast_recv = net_context_get(IPPROTO_UDP,
|
||||
&any_addr, 0,
|
||||
&mcast_addr, MY_PORT);
|
||||
if (!*mcast_recv) {
|
||||
PRINT("%s: Cannot get receiving mcast network context\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NANOKERNEL)
|
||||
#define STACKSIZE 2000
|
||||
char __noinit __stack fiberStack[STACKSIZE];
|
||||
#endif
|
||||
static struct net_buf *build_reply_buf(const char *name,
|
||||
struct net_context *context,
|
||||
struct net_buf *buf)
|
||||
{
|
||||
struct net_buf *reply_buf, *frag, *tmp;
|
||||
int header_len, recv_len, reply_len;
|
||||
|
||||
NET_INFO("%s received %d bytes", name,
|
||||
net_nbuf_appdatalen(buf));
|
||||
|
||||
reply_buf = net_nbuf_get_tx(context);
|
||||
|
||||
NET_ASSERT(reply_buf);
|
||||
|
||||
recv_len = net_buf_frags_len(buf->frags);
|
||||
|
||||
tmp = buf->frags;
|
||||
|
||||
/* First fragment will contain IP header so move the data
|
||||
* down in order to get rid of it.
|
||||
*/
|
||||
header_len = net_nbuf_appdata(buf) - tmp->data;
|
||||
|
||||
NET_ASSERT(header_len < CONFIG_NET_NBUF_DATA_SIZE);
|
||||
|
||||
/* After this pull, the tmp->data points directly to application
|
||||
* data.
|
||||
*/
|
||||
net_buf_pull(tmp, header_len);
|
||||
|
||||
while (tmp) {
|
||||
frag = net_nbuf_get_data(context);
|
||||
|
||||
if (!net_buf_headroom(tmp)) {
|
||||
/* If there is no link layer headers in the
|
||||
* received fragment, then get rid of that also
|
||||
* in the sending fragment. We end up here
|
||||
* if MTU is larger than fragment size, this
|
||||
* is typical for ethernet.
|
||||
*/
|
||||
net_buf_push(frag, net_buf_headroom(frag));
|
||||
|
||||
frag->len = 0; /* to make fragment empty */
|
||||
|
||||
/* Make sure to set the reserve so that
|
||||
* in sending side we add the link layer
|
||||
* header if needed.
|
||||
*/
|
||||
net_nbuf_set_ll_reserve(reply_buf, 0);
|
||||
}
|
||||
|
||||
NET_ASSERT(net_buf_tailroom(frag) >= tmp->len);
|
||||
|
||||
memcpy(net_buf_add(frag, tmp->len), tmp->data, tmp->len);
|
||||
|
||||
net_buf_frag_add(reply_buf, frag);
|
||||
|
||||
net_buf_frag_del(buf, tmp);
|
||||
|
||||
tmp = buf->frags;
|
||||
}
|
||||
|
||||
reply_len = net_buf_frags_len(reply_buf->frags);
|
||||
|
||||
NET_ASSERT_INFO((recv_len - header_len) == reply_len,
|
||||
"Received %d bytes, sending %d bytes",
|
||||
recv_len - header_len, reply_len);
|
||||
|
||||
return reply_buf;
|
||||
}
|
||||
|
||||
static inline void pkt_sent(struct net_context *context,
|
||||
int status,
|
||||
void *token,
|
||||
void *user_data)
|
||||
{
|
||||
if (!status) {
|
||||
NET_INFO("Sent %d bytes", POINTER_TO_UINT(token));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
static inline void set_dst_addr(sa_family_t family,
|
||||
struct net_buf *buf,
|
||||
struct sockaddr *dst_addr)
|
||||
{
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
if (family == AF_INET6) {
|
||||
net_ipaddr_copy(&net_sin6(dst_addr)->sin6_addr,
|
||||
&NET_IPV6_BUF(buf)->src);
|
||||
net_sin6(dst_addr)->sin6_family = AF_INET6;
|
||||
net_sin6(dst_addr)->sin6_port = NET_UDP_BUF(buf)->src_port;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6) */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
if (family == AF_INET) {
|
||||
net_ipaddr_copy(&net_sin(dst_addr)->sin_addr,
|
||||
&NET_IPV4_BUF(buf)->src);
|
||||
net_sin(dst_addr)->sin_family = AF_INET;
|
||||
net_sin(dst_addr)->sin_port = NET_UDP_BUF(buf)->src_port;
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6) */
|
||||
}
|
||||
|
||||
static void udp_received(struct net_context *context,
|
||||
struct net_buf *buf,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
struct net_buf *reply_buf;
|
||||
struct sockaddr dst_addr;
|
||||
sa_family_t family = net_nbuf_family(buf);
|
||||
static char dbg[MAX_DBG_PRINT + 1];
|
||||
int ret;
|
||||
|
||||
snprintf(dbg, MAX_DBG_PRINT, "UDP IPv%c",
|
||||
family == AF_INET6 ? '6' : '4');
|
||||
|
||||
set_dst_addr(family, buf, &dst_addr);
|
||||
|
||||
reply_buf = build_reply_buf(dbg, context, buf);
|
||||
|
||||
net_nbuf_unref(buf);
|
||||
|
||||
ret = net_context_sendto(reply_buf, &dst_addr,
|
||||
family == AF_INET6 ?
|
||||
sizeof(struct sockaddr_in6) :
|
||||
sizeof(struct sockaddr_in),
|
||||
pkt_sent, 0,
|
||||
UINT_TO_POINTER(net_buf_frags_len(reply_buf)),
|
||||
user_data);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot send data to peer (%d)", ret);
|
||||
net_nbuf_unref(reply_buf);
|
||||
|
||||
quit();
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_udp_recv(struct net_context *udp_recv4,
|
||||
struct net_context *udp_recv6)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
ret = net_context_recv(udp_recv6, udp_received, 0, NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive IPv6 UDP packets");
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
ret = net_context_recv(udp_recv4, udp_received, 0, NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive IPv4 UDP packets");
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
}
|
||||
#endif /* CONFIG_NET_UDP */
|
||||
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
static void tcp_received(struct net_context *context,
|
||||
struct net_buf *buf,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
static char dbg[MAX_DBG_PRINT + 1];
|
||||
sa_family_t family = net_nbuf_family(buf);
|
||||
struct net_buf *reply_buf;
|
||||
int ret;
|
||||
|
||||
snprintf(dbg, MAX_DBG_PRINT, "TCP IPv%c",
|
||||
family == AF_INET6 ? '6' : '4');
|
||||
|
||||
reply_buf = build_reply_buf(dbg, context, buf);
|
||||
|
||||
net_buf_unref(buf);
|
||||
|
||||
ret = net_context_send(reply_buf, pkt_sent, K_NO_WAIT,
|
||||
UINT_TO_POINTER(net_buf_frags_len(reply_buf)),
|
||||
NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot send data to peer (%d)", ret);
|
||||
net_nbuf_unref(reply_buf);
|
||||
|
||||
quit();
|
||||
}
|
||||
}
|
||||
|
||||
static void tcp_accepted(struct net_context *context,
|
||||
struct sockaddr *addr,
|
||||
socklen_t addrlen,
|
||||
int error,
|
||||
void *user_data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
NET_DBG("Accept called, context %p error %d", context, error);
|
||||
|
||||
ret = net_context_recv(context, tcp_received, 0, NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive TCP packet (family %d)",
|
||||
net_context_get_family(context));
|
||||
}
|
||||
}
|
||||
|
||||
static void setup_tcp_accept(struct net_context *tcp_recv4,
|
||||
struct net_context *tcp_recv6)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined(CONFIG_NET_IPV6)
|
||||
ret = net_context_accept(tcp_recv6, tcp_accepted, 0, NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive IPv6 TCP packets (%d)", ret);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV6 */
|
||||
|
||||
#if defined(CONFIG_NET_IPV4)
|
||||
ret = net_context_accept(tcp_recv4, tcp_accepted, 0, NULL);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Cannot receive IPv4 TCP packets (%d)", ret);
|
||||
}
|
||||
#endif /* CONFIG_NET_IPV4 */
|
||||
}
|
||||
#endif /* CONFIG_NET_TCP */
|
||||
|
||||
void receive(void)
|
||||
{
|
||||
static struct net_context *udp_recv, *tcp_recv;
|
||||
static struct net_context *mcast_recv;
|
||||
struct net_context *udp_recv4 = { 0 };
|
||||
struct net_context *udp_recv6 = { 0 };
|
||||
struct net_context *tcp_recv4 = { 0 };
|
||||
struct net_context *tcp_recv6 = { 0 };
|
||||
struct net_context *mcast_recv6 = { 0 };
|
||||
|
||||
if (!get_context(&udp_recv, &tcp_recv, &mcast_recv)) {
|
||||
PRINT("%s: Cannot get network contexts\n", __func__);
|
||||
if (!get_context(&udp_recv4, &udp_recv6,
|
||||
&tcp_recv4, &tcp_recv6,
|
||||
&mcast_recv6)) {
|
||||
NET_ERR("Cannot get network contexts");
|
||||
return;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
receive_and_reply(__func__, udp_recv, tcp_recv, mcast_recv);
|
||||
}
|
||||
NET_INFO("Starting to wait");
|
||||
|
||||
#if defined(CONFIG_NET_TCP)
|
||||
setup_tcp_accept(tcp_recv4, tcp_recv6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_UDP)
|
||||
setup_udp_recv(udp_recv4, udp_recv6);
|
||||
#endif
|
||||
|
||||
k_sem_take(&quit_lock, K_FOREVER);
|
||||
|
||||
NET_INFO("Stopping...");
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_UDP)
|
||||
net_context_put(udp_recv6);
|
||||
net_context_put(mcast_recv6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_UDP)
|
||||
net_context_put(udp_recv4);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_TCP)
|
||||
net_context_put(tcp_recv6);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_TCP)
|
||||
net_context_put(tcp_recv4);
|
||||
#endif
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
net_init();
|
||||
|
||||
init_app();
|
||||
|
||||
#if defined(CONFIG_NETWORKING_WITH_BT)
|
||||
if (bt_enable(NULL)) {
|
||||
PRINT("Bluetooth init failed\n");
|
||||
NET_ERR("Bluetooth init failed");
|
||||
return;
|
||||
}
|
||||
ipss_init();
|
||||
ipss_advertise();
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_MICROKERNEL)
|
||||
receive();
|
||||
#else
|
||||
task_fiber_start (&fiberStack[0], STACKSIZE,
|
||||
(nano_fiber_entry_t)receive, 0, 0, 7, 0);
|
||||
#endif
|
||||
k_thread_spawn(&thread_stack[0], STACKSIZE,
|
||||
(k_thread_entry_t)receive,
|
||||
NULL, NULL, NULL, K_PRIO_COOP(7), 0, 0);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
CONFIG_ARC_INIT=n
|
||||
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
|
||||
CONFIG_NET_NBUF_RX_COUNT=6
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
|
||||
CONFIG_NET_NBUF_RX_COUNT=6
|
||||
|
|
|
@ -2,7 +2,6 @@ CONFIG_NETWORKING=y
|
|||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_SLIP_TAP=y
|
||||
CONFIG_SYS_LOG=y
|
||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||
|
|
|
@ -9,7 +9,6 @@ CONFIG_TEST_RANDOM_GENERATOR=y
|
|||
CONFIG_NANO_TIMEOUTS=y
|
||||
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_ARP=y
|
||||
CONFIG_NET_L2_ETHERNET=y
|
||||
CONFIG_NET_IPV4=y
|
||||
|
|
|
@ -4,7 +4,6 @@ CONFIG_MINIMAL_LIBC_EXTENDED=y
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_IPV6=n
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_LOG=y
|
||||
CONFIG_NET_SLIP=y
|
||||
|
|
|
@ -65,9 +65,7 @@ static unsigned char heap[20480];
|
|||
|
||||
const char *pers = "mini_client";
|
||||
|
||||
#if defined(CONFIG_NET_YAIP)
|
||||
static struct in_addr client_addr = CLIENT_IP_ADDR;
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
||||
#define ECJPAKE_PW_SIZE 6
|
||||
|
@ -303,17 +301,11 @@ uint8_t stack[STACK_SIZE];
|
|||
|
||||
static inline int init_app(void)
|
||||
{
|
||||
#if defined(CONFIG_NET_YAIP)
|
||||
if (!net_if_ipv4_addr_add(net_if_get_default(), &client_addr,
|
||||
NET_ADDR_MANUAL, 0)) {
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
net_init();
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void main(void)
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include <zephyr.h>
|
||||
#include <net/net_core.h>
|
||||
#include <net/net_context.h>
|
||||
#include <net/yaip/nbuf.h>
|
||||
#include <net/nbuf.h>
|
||||
#include <net/net_if.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
|
|
@ -14,7 +14,6 @@ CONFIG_UART_LINE_CTRL=y
|
|||
CONFIG_TI_CC2520_RAW=y
|
||||
CONFIG_NET_BUF=y
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
|
||||
CONFIG_NET_L2_IEEE802154=y
|
||||
CONFIG_NET_L2_IEEE802154_ORFD=y
|
||||
|
|
|
@ -10,7 +10,6 @@ CONFIG_UART_INTERRUPT_DRIVEN=y
|
|||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
|
||||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_L2_RAW_CHANNEL=y
|
||||
CONFIG_NET_NBUF_TX_COUNT=4
|
||||
CONFIG_NET_NBUF_DATA_SIZE=128
|
||||
|
|
|
@ -5,7 +5,6 @@ CONFIG_NET_IPV6=y
|
|||
CONFIG_NET_LOG=y
|
||||
CONFIG_NET_SLIP=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_SLIP_TAP=y
|
||||
CONFIG_SYS_LOG=y
|
||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||
|
|
|
@ -4,7 +4,6 @@ CONFIG_NET_IPV6=y
|
|||
CONFIG_NET_LOG=y
|
||||
CONFIG_NET_SLIP=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_SLIP_TAP=y
|
||||
CONFIG_SYS_LOG=y
|
||||
CONFIG_SYS_LOG_SHOW_COLOR=y
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
CONFIG_NETWORKING=y
|
||||
|
||||
# native IP stack support
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
|
||||
# enable the MQTT lib
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_L2_DUMMY=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV6_ND=n
|
||||
|
|
|
@ -2,7 +2,6 @@ CONFIG_NETWORKING=y
|
|||
CONFIG_NET_ARP=y
|
||||
CONFIG_NET_L2_ETHERNET=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_BUF=y
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
||||
CONFIG_NET_NBUF_RX_COUNT=5
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=n
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_L2_DUMMY=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_UDP=y
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_BUF=y
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
||||
CONFIG_NET_NBUF_RX_COUNT=2
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_L2_DUMMY=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV6_ND=n
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_BUF=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV6_NO_ND=y
|
||||
|
|
|
@ -3,7 +3,6 @@ CONFIG_NET_IPV6=y
|
|||
CONFIG_NET_IPV6_DAD=n
|
||||
CONFIG_NET_IPV6_ND=n
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_BUF=y
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
||||
CONFIG_NET_NBUF_RX_COUNT=2
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=n
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_BUF=y
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
||||
CONFIG_NET_NBUF_RX_COUNT=5
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_BUF=y
|
||||
#CONFIG_NET_BUF_DEBUG=y
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_BUF=y
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
||||
CONFIG_NET_NBUF_RX_COUNT=3
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=n
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=n
|
||||
|
|
|
@ -5,7 +5,6 @@ CONFIG_NET_MAX_CONN=64
|
|||
CONFIG_NET_CONN_CACHE=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_BUF=y
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
||||
CONFIG_NET_NBUF_RX_COUNT=5
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_UDP=y
|
||||
CONFIG_NET_TCP=n
|
||||
|
|
|
@ -5,7 +5,6 @@ CONFIG_NET_MAX_CONN=64
|
|||
CONFIG_NET_CONN_CACHE=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_BUF=y
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
||||
CONFIG_NET_NBUF_RX_COUNT=5
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NET_IPV6=y
|
||||
CONFIG_NET_IPV4=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_NET_BUF=y
|
||||
CONFIG_MAIN_STACK_SIZE=2048
|
||||
CONFIG_NET_NBUF_RX_COUNT=2
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
CONFIG_NETWORKING=y
|
||||
CONFIG_NETWORKING_WITH_IPV6=y
|
||||
CONFIG_NET_YAIP=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
CONFIG_ZOAP=y
|
Loading…
Reference in a new issue