Merge "Merge net branch into master"

This commit is contained in:
Anas Nashif 2017-02-08 12:03:09 +00:00
commit 31f01f8ed6
121 changed files with 2507 additions and 1034 deletions

View file

@ -58,7 +58,7 @@ static int frdm_k64f_pinmux_init(struct device *dev)
pinmux_pin_set(porte, 26, PORT_PCR_MUX(kPORT_MuxAsGpio));
pinmux_pin_set(portb, 21, PORT_PCR_MUX(kPORT_MuxAsGpio));
#ifdef CONFIG_NXP_MCR20A
#ifdef CONFIG_IEEE802154_MCR20A
/* FRDM-MCR20A Reset (D5) */
pinmux_pin_set(porta, 2, PORT_PCR_MUX(kPORT_MuxAsGpio));
/* FRDM-MCR20A IRQ_B (D2) */

View file

@ -46,26 +46,26 @@ endif
config BLUETOOTH_MONITOR_ON_DEV_NAME
default UART_QMSI_1_NAME if BLUETOOTH_DEBUG_MONITOR
if TI_CC2520_LEGACY || TI_CC2520 || TI_CC2520_RAW
if IEEE802154_CC2520_LEGACY || IEEE802154_CC2520 || IEEE802154_CC2520_RAW
config SPI
def_bool y
config GPIO
def_bool y
config TI_CC2520_SPI_DRV_NAME
config IEEE802154_CC2520_SPI_DRV_NAME
default SPI_1_NAME
config TI_CC2520_SPI_FREQ
config IEEE802154_CC2520_SPI_FREQ
default 4
config TI_CC2520_SPI_SLAVE
config IEEE802154_CC2520_SPI_SLAVE
default 1
if GPIO_QMSI
config TI_CC2520_GPIO_0_NAME
config IEEE802154_CC2520_GPIO_0_NAME
default GPIO_QMSI_0_NAME
config TI_CC2520_GPIO_1_NAME
config IEEE802154_CC2520_GPIO_1_NAME
default GPIO_QMSI_1_NAME
endif # GPIO_QMSI
@ -77,14 +77,14 @@ config SPI_1_CS_GPIO_PORT
default GPIO_QMSI_0_NAME
config SPI_1_CS_GPIO_PIN
default 11
config TI_CC2520_GPIO_0_NAME
config IEEE802154_CC2520_GPIO_0_NAME
string
default GPIO_QMSI_0_NAME
config TI_CC2520_GPIO_1_NAME
config IEEE802154_CC2520_GPIO_1_NAME
string
default GPIO_QMSI_1_NAME
endif
endif # TI_CC2520_LEGACY || TI_CC2520 || TI_CC2520_RAW
endif # IEEE802154_CC2520_LEGACY || IEEE802154_CC2520 || IEEE802154_CC2520_RAW
endif # BOARD_QUARK_SE_C1000_DEVBOARD

View file

@ -10,9 +10,9 @@
#include <device.h>
#include <init.h>
#if defined(CONFIG_TI_CC2520_LEGACY) || \
defined(CONFIG_TI_CC2520) || \
defined(CONFIG_TI_CC2520_RAW)
#if defined(CONFIG_IEEE802154_CC2520_LEGACY) || \
defined(CONFIG_IEEE802154_CC2520) || \
defined(CONFIG_IEEE802154_CC2520_RAW)
#include <ieee802154/cc2520.h>
#include <gpio.h>
@ -34,7 +34,7 @@ struct cc2520_gpio_configuration *cc2520_configure_gpios(void)
GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE);
struct device *gpio;
gpio = device_get_binding(CONFIG_TI_CC2520_GPIO_1_NAME);
gpio = device_get_binding(CONFIG_IEEE802154_CC2520_GPIO_1_NAME);
gpio_pin_configure(gpio, cc2520_gpios[CC2520_GPIO_IDX_VREG_EN].pin,
flags_noint_out);
gpio_pin_configure(gpio, cc2520_gpios[CC2520_GPIO_IDX_RESET].pin,
@ -43,7 +43,7 @@ struct cc2520_gpio_configuration *cc2520_configure_gpios(void)
cc2520_gpios[CC2520_GPIO_IDX_VREG_EN].dev = gpio;
cc2520_gpios[CC2520_GPIO_IDX_RESET].dev = gpio;
gpio = device_get_binding(CONFIG_TI_CC2520_GPIO_0_NAME);
gpio = device_get_binding(CONFIG_IEEE802154_CC2520_GPIO_0_NAME);
gpio_pin_configure(gpio, cc2520_gpios[CC2520_GPIO_IDX_SFD].pin,
flags_int_in);
gpio_pin_configure(gpio, cc2520_gpios[CC2520_GPIO_IDX_FIFOP].pin,
@ -61,4 +61,6 @@ struct cc2520_gpio_configuration *cc2520_configure_gpios(void)
return cc2520_gpios;
}
#endif /* CONFIG_TI_CC2520_LEGACY || CONFIG_TI_CC2520 || CONFIG_TI_CC2520_RAW */
#endif /* CONFIG_IEEE802154_CC2520_LEGACY || CONFIG_IEEE802154_CC2520 ||
* CONFIG_IEEE802154_CC2520_RAW
*/

View file

@ -21,9 +21,9 @@
#define LED0_GPIO_PORT CONFIG_GPIO_QMSI_0_NAME
#define LED0_GPIO_PIN 25
#if defined(CONFIG_TI_CC2520_LEGACY) || \
defined(CONFIG_TI_CC2520) || \
defined(CONFIG_TI_CC2520_RAW)
#if defined(CONFIG_IEEE802154_CC2520_LEGACY) || \
defined(CONFIG_IEEE802154_CC2520) || \
defined(CONFIG_IEEE802154_CC2520_RAW)
/* GPIO numbers where the TI cc2520 chip is connected to */
#define CC2520_GPIO_VREG_EN 0 /* PIN ?, ATP_AON_INT0 (out) */
@ -33,7 +33,9 @@
#define CC2520_GPIO_CCA 6 /* PIN 6, GPIO6 (in) */
#define CC2520_GPIO_SFD 29 /* PIN 33, GPIO29 (in) */
#endif /* CONFIG_TI_CC2520_LEGACY || CONFIG_TI_CC2520 || CONFIG_TI_CC2520_RAW */
#endif /* CONFIG_IEEE802154_CC2520_LEGACY || CONFIG_IEEE802154_CC2520 ||
* CONFIG_IEEE802154_CC2520_RAW
*/
#if defined(CONFIG_USB)
/* GPIO driver name */

View file

@ -95,7 +95,7 @@ static struct net_buf *udp_recv(const char *name,
NET_INFO("%s received %u bytes", name,
net_nbuf_appdatalen(buf));
reply_buf = net_nbuf_get_tx(context);
reply_buf = net_nbuf_get_tx(context, K_FOREVER);
NET_ASSERT(reply_buf);
@ -113,7 +113,7 @@ static struct net_buf *udp_recv(const char *name,
net_buf_pull(tmp, header_len);
while (tmp) {
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
memcpy(net_buf_add(frag, tmp->len), tmp->data, tmp->len);

View file

@ -0,0 +1,154 @@
.. _l2_and_drivers:
L2 Stack and Drivers
####################
The L2 stack is designed to hide the whole networking link-layer part
and the related device drivers from the higher IP stack. This is made
through a unique object known as the "network interface object":
:c:type:`struct net_if` declared in `include/net/net_if.h`.
The IP layer is unaware of implementation details beyond the net_if
object and the generic API provided by the L2 layer in
`include/net/net_l2.h` as :c:type:`struct net_l2`.
Only the L2 layer can talk to the device driver, linked to the net_if
object. The L2 layer dictates the API provided by the device driver,
specific for that device, and optimized for working together.
Currently, there are L2 layers for Ethernet, IEEE 802.15.4 Soft-MAC,
Bluetooth IPSP, and a dummy one, which is a generic layer example that
can be used as a template for writing a new one.
L2 layer API
************
In order to create an L2 layer, or even a driver for a specific L2
layer, one needs to understand how the IP layer interacts with it and
how the L2 layer is supposed to behave. The generic L2 API has 3
functions:
- recv: All device drivers, once they receive a packet which they put
into a :c:type:`struct net_nbuf`, will push this buffer to the IP
core stack via :c:func:`net_recv_data()`. At this point, the IP core
stack does not know what to do with it. Instead, it passes the
buffer along to the L2 stack's recv() function for handling. The L2
stack does what it needs to do with the packet, for example, parsing
the link layer header, or handling link-layer only packets. The
recv() function will return NET_DROP in case of an erroneous packet,
NET_OK if the packet was fully consumed by the L2, or NET_CONTINUE
if the IP stack should then handle it as an IP packet.
- reserve: Prior to creating any network buffer content, the Zephyr
core stack needs to know how much dedicated buffer space is needed
for the L2 layer (for example, space for the link layer header). This
reserve function returns the number of bytes needed.
- send: Similar to recv, the IP core stack will call this function to
actually send a packet. All relevant link-layer content will be
generated and added by this function. As for recv, send returns a
verdict and can decide to drop the packet via NET_DROP if something
wrong happened, or will return NET_OK.
Network Device drivers
**********************
Network device drivers fully follows Zephyr device driver model as a
basis. Please refer to :ref:`device_drivers`.
There are, however, two differences:
- the driver_api pointer must point to a valid :c:type:`struct
net_if_api` pointer.
- The network device driver must use NET_DEVICE_INIT_INSTANCE(). This
macro will call the DEVICE_AND_API_INIT() macro, and also
instantiate a unique :c:type:`struct net_if` related to the created
device driver instance.
Implementing a network device driver depends on the L2 stack it
belongs to: Ethernet, IEEE 802.15.4, etc. In the next section, we will
describe how a device driver should behave when receiving or sending a
packet. The rest is really hardware dependent and thus does not need
to be detailed here.
Ethernet device driver
======================
On reception, it is up to the device driver to fill-in the buffer with
as many data fragments as required. The buffer itself is a
:c:type:`struct net_nbuf` and should be allocated through
:c:func:`net_nbuf_get_reserve_rx(0)`. Then all fragments will be
allocated through :c:func:`net_nbuf_get_reserve_data(0)`. Of course
the amount of required fragments depends on the size of the received
packet and on the size of a fragment, which is given by
`CONFIG_NET_NBUF_DATA_SIZE`.
Note that it is not up to the device driver to decide on the
link-layer space to be reserved in the buffer. Hence the 0 given as
parameter here. The Ethernet L2 layer will update such information
once the packet's Ethernet header has been successfully parsed.
In case :c:func:`net_recv_data()` call fails, it will be up to the
device driver to un-reference the buffer via
:c:func:`net_nbuf_unref()`.
On sending, it is up to the device driver to send the buffer all at
once, with all the fragments.
In case of a fully successful packet transmission only, the device
driver must un-reference the buffer via `net_nbuf_unref()`.
Each Ethernet device driver will need, in the end, to call
`NET_DEVICE_INIT_INSTANCE()` like this:
.. code-block:: c
NET_DEVICE_INIT_INSTANCE(...,
CONFIG_ETH_INIT_PRIORITY
&the_valid_net_if_api_instance,
ETHERNET_L2,
NET_L2_GET_CTX_TYPE(ETHERNET_L2), 1500);
IEEE 802.15.4 device driver
===========================
Device drivers for IEEE 802.15.4 L2 work basically the same as for
Ethernet. What has been described above, especially for recv, applies
here as well. There are two specific differences however:
- It requires a dedicated device driver API: :c:type:`struct
ieee802154_radio_api`, which overloads :c:type:`struct
net_if_api`. This is because 802.15.4 L2 needs more from the device
driver than just send and recv functions. This dedicated API is
declared in `include/net/ieee802154_radio.h`. Each and every IEEE
802.15.4 device driver must provide a valid pointer on such
relevantly filled-in API structure.
- Sending a packet is slightly particular. IEEE 802.15.4 sends
relatively small frames, 127 bytes all inclusive: frame header,
payload and frame checksum. Buffer fragments are meant to fit such
frame size limitation. But a buffer containing an IPv6/UDP packet
might have more than one fragment. In the Ethernet device driver, it
is up to the driver to handle all fragments. IEEE 802.15.4 drivers
handle only one fragment at a time. This is why the :c:type:`struct
ieee802154_radio_api` requires a tx function pointer which differs
from the :c:type:`struct net_if_api` send function pointer.
Instead, the IEEE 802.15.4 L2, provides a generic
:c:func:`ieee802154_radio_send()` meant to be given as
:c:type:`struct net_if` send function. It turn, the implementation
of :c:func:`ieee802154_radio_send()` will ensure the same behavior:
sending one fragment at a time through :c:type:`struct
ieee802154_radio_api` tx function, and un-referencing the buffer
only when all the transmission were successful.
Each IEEE 802.15.4 device driver, in the end, will need to call
`NET_DEVICE_INIT_INSTANCE()` that way:
.. code-block:: c
NET_DEVICE_INIT_INSTANCE(...,
the_device_init_prio,
&the_valid_ieee802154_radio_api_instance,
IEEE802154_L2,
NET_L2_GET_CTX_TYPE(IEEE802154_L2), 125);

View file

@ -14,7 +14,7 @@ operation of the stacks and how they were implemented.
ip-stack-migrate.rst
ip-stack-architecture.rst
networking-api-usage.rst
l2-and-drivers.rst
network-management-api.rst
buffers.rst
qemu_setup.rst

View file

@ -125,7 +125,7 @@ static void telnet_end_client_connection(void)
static int telnet_setup_out_buf(struct net_context *client)
{
out_buf = net_nbuf_get_tx(client);
out_buf = net_nbuf_get_tx(client, K_FOREVER);
if (!out_buf) {
/* Cannot happen atm, nbuf waits indefinitely */
return -ENOBUFS;
@ -234,7 +234,7 @@ static inline bool telnet_send(void)
struct line_buf *lb = telnet_rb_get_line_out();
if (lb) {
net_nbuf_append(out_buf, lb->len, lb->buf);
net_nbuf_append(out_buf, lb->len, lb->buf, K_FOREVER);
/* We reinitialize the line buffer */
lb->len = 0;
@ -258,7 +258,7 @@ static int telnet_console_out_nothing(int c)
static inline void telnet_command_send_reply(uint8_t *msg, uint16_t len)
{
net_nbuf_append(out_buf, len, msg);
net_nbuf_append(out_buf, len, msg, K_FOREVER);
net_context_send(out_buf, telnet_sent_cb,
K_NO_WAIT, NULL, NULL);

View file

@ -551,7 +551,7 @@ static int eth_enc28j60_rx(struct device *dev)
lengthfr = frm_len;
/* Get the frame from the buffer */
buf = net_nbuf_get_reserve_rx(0);
buf = net_nbuf_get_reserve_rx(0, K_NO_WAIT);
if (!buf) {
SYS_LOG_ERR("Could not allocate rx buffer");
goto done;
@ -565,7 +565,7 @@ static int eth_enc28j60_rx(struct device *dev)
size_t spi_frame_len;
/* Reserve a data frag to receive the frame */
pkt_buf = net_nbuf_get_reserve_data(0);
pkt_buf = net_nbuf_get_reserve_data(0, K_NO_WAIT);
if (!pkt_buf) {
SYS_LOG_ERR("Could not allocate data buffer");
net_buf_unref(buf);

View file

@ -170,10 +170,11 @@
/* Receive filters enabled:
* - Unicast
* - Multicast
* - Broadcast
* - CRC Check
*/
#define ENC28J60_RECEIVE_FILTERS 0xA1
#define ENC28J60_RECEIVE_FILTERS 0xA3
/* MAC configuration:
* - Automatic Padding

View file

@ -145,7 +145,7 @@ static void eth_rx(struct device *iface)
return;
}
buf = net_nbuf_get_reserve_rx(0);
buf = net_nbuf_get_reserve_rx(0, K_NO_WAIT);
if (!buf) {
/* We failed to get a receive buffer. We don't add
* any further logging here because the allocator
@ -162,7 +162,7 @@ static void eth_rx(struct device *iface)
if (sizeof(context->frame_buf) < frame_length) {
SYS_LOG_ERR("frame too large (%d)\n", frame_length);
net_buf_unref(buf);
net_nbuf_unref(buf);
status = ENET_ReadFrame(ENET, &context->enet_handle, NULL, 0);
assert(status == kStatus_Success);
return;
@ -178,7 +178,7 @@ static void eth_rx(struct device *iface)
if (status) {
irq_unlock(imask);
SYS_LOG_ERR("ENET_ReadFrame failed: %d\n", status);
net_buf_unref(buf);
net_nbuf_unref(buf);
return;
}
@ -188,11 +188,11 @@ static void eth_rx(struct device *iface)
struct net_buf *pkt_buf;
size_t frag_len;
pkt_buf = net_nbuf_get_reserve_data(0);
pkt_buf = net_nbuf_get_reserve_data(0, K_NO_WAIT);
if (!pkt_buf) {
irq_unlock(imask);
SYS_LOG_ERR("Failed to get fragment buf\n");
net_buf_unref(buf);
net_nbuf_unref(buf);
assert(status == kStatus_Success);
return;
}

View file

@ -162,7 +162,7 @@ static int rx_descriptors_init(Gmac *gmac, struct gmac_queue *queue)
rx_nbuf_list->tail = 0;
for (int i = 0; i < rx_desc_list->len; i++) {
rx_buf = net_nbuf_get_reserve_data(0);
rx_buf = net_nbuf_get_reserve_data(0, K_NO_WAIT);
if (rx_buf == NULL) {
free_rx_bufs(rx_nbuf_list);
SYS_LOG_ERR("Failed to reserve data net buffers");
@ -470,7 +470,7 @@ static struct net_buf *frame_get(struct gmac_queue *queue)
return NULL;
}
rx_frame = net_nbuf_get_reserve_rx(0);
rx_frame = net_nbuf_get_reserve_rx(0, K_NO_WAIT);
/* Process a frame */
prev_frag = rx_frame;
@ -509,7 +509,7 @@ static struct net_buf *frame_get(struct gmac_queue *queue)
DCACHE_INVALIDATE(frag_data, frag_len);
/* Get a new data net buffer from the buffer pool */
new_frag = net_nbuf_get_reserve_data(0);
new_frag = net_nbuf_get_reserve_data(0, K_NO_WAIT);
if (new_frag == NULL) {
queue->err_rx_frames_dropped++;
net_buf_unref(rx_frame);

View file

@ -54,198 +54,20 @@ config SYS_LOG_IEEE802154_DRIVER_LEVEL
- 4 DEBUG, write SYS_LOG_DBG in adition to previous levels
config TI_CC2520
bool "TI CC2520 Driver support"
depends on NETWORKING
select NET_L2_IEEE802154
default n
source "drivers/ieee802154/Kconfig.cc2520"
config TI_CC2520_RAW
bool "TI CC2520 Driver RAW channel"
select NET_L2_RAW_CHANNEL
default n
help
Enable TI_CC2520 driver with RAW channel
source "drivers/ieee802154/Kconfig.mcr20a"
The CC2520 driver with RAW channel allows to export radio interface
over USB making an USB 802.15.4 dongle.
if TI_CC2520 || TI_CC2520_RAW
config TI_CC2520_DRV_NAME
string "TI CC2520 Driver's name"
default "cc2520"
help
This option sets the driver name
config TI_CC2520_SPI_DRV_NAME
string "SPI driver's name to use to access CC2520"
default ""
help
This option is mandatory to set which SPI controller to use in order
to actually control the CC2520 chip.
config TI_CC2520_SPI_FREQ
int "SPI system frequency"
default 0
help
This option sets the SPI controller's frequency. Beware this value
depends on the SPI controller being used and also on the system
clock.
config TI_CC2520_SPI_SLAVE
int "SPI slave linked to CC2520"
default 0
help
This option sets the SPI slave number SPI controller has to switch
to when dealing with CC2520 chip.
config TI_CC2520_RX_STACK_SIZE
int "Driver's internal rx thread stack size"
default 800
help
This option sets the driver's stack size for its internal rx thread.
The default value should be sufficient, but in case it prooves to be
a too little one, this option makes it easy to play with the size.
config TI_CC2520_INIT_PRIO
int "CC2520 intialization priority"
default 80
help
Set the initialization priority number. Do not mess with it unless
you know what you are doing. Beware cc2520 requires gpio and spi to
be ready first (and sometime gpio should be the very first as spi
might need it too). And of course it has to start before the net stack.
endif
config UPIPE_15_4
menuconfig IEEE802154_UPIPE
bool "UART PIPE fake radio driver support for QEMU"
depends on BOARD_QEMU_X86
select NETWORKING
select UART_PIPE
default n
config UPIPE_15_4_DRV_NAME
config IEEE802154_UPIPE_DRV_NAME
string "UART PIPE Driver name"
default "upipe_15_4"
depends on UPIPE_15_4
config NXP_MCR20A
bool "NXP MCR20A Driver support"
depends on NETWORKING && SPI
select NET_L2_IEEE802154
default n
config NXP_MCR20A_RAW
bool "NXP MCR20A Driver RAW channel"
depends on SPI
select NET_L2_RAW_CHANNEL
default n
help
Enable NXP_MCR20A driver with RAW channel
The MCR20A driver with RAW channel allows to export radio interface
over USB making an USB 802.15.4 dongle.
if NXP_MCR20A || NXP_MCR20A_RAW
config NXP_MCR20A_DRV_NAME
string "NXP MCR20A Driver's name"
default "mcr20a"
help
This option sets the driver name
config NXP_MCR20A_SPI_DRV_NAME
string "SPI driver's name to use to access MCR20A"
default SPI_0_NAME
help
This option is mandatory to set which SPI controller to use in order
to actually control the MCR20A chip.
config NXP_MCR20A_SPI_FREQ
int "SPI system frequency"
default 4000000
help
This option sets the SPI controller's frequency. Beware this value
depends on the SPI controller being used and also on the system
clock.
config NXP_MCR20A_SPI_SLAVE
int "SPI slave linked to MCR20A"
default 0
help
This option sets the SPI slave number SPI controller has to switch
to when dealing with MCR20A chip.
config MCR20A_GPIO_IRQ_B_NAME
string "GPIO device used for IRQ_B output of MCR20A"
default GPIO_MCUX_PORTB_NAME
config MCR20A_GPIO_IRQ_B_PIN
int "GPIO pin connected to IRQ_B output of MCR20A"
default 9
config MCR20A_GPIO_RESET_NAME
string "GPIO device used for RESET input of MCR20A"
default GPIO_MCUX_PORTA_NAME
config MCR20A_GPIO_RESET_PIN
int "GPIO pin connected to RESET input of MCR20A"
default 2
choice
prompt "CLK_OUT frequency"
default MCR20A_CLK_OUT_DISABLED
help
Configuration of the MCR20A clock output pin.
config MCR20A_CLK_OUT_DISABLED
bool "Disabled"
config MCR20A_CLK_OUT_32MHZ
bool "32 MHz"
config MCR20A_CLK_OUT_16MHZ
bool "16 MHz"
config MCR20A_CLK_OUT_8MHZ
bool "8 MHz"
config MCR20A_CLK_OUT_4MHZ
bool "4 MHz"
config MCR20A_CLK_OUT_1MHZ
bool "1 MHz"
config MCR20A_CLK_OUT_250KHZ
bool "250 kHz"
config MCR20A_CLK_OUT_62500HZ
bool "62500 Hz"
config MCR20A_CLK_OUT_32768HZ
bool "32768 Hz"
endchoice
config NXP_MCR20A_RX_STACK_SIZE
int "Driver's internal rx thread stack size"
default 800
help
This option sets the driver's stack size for its internal rx thread.
The default value should be sufficient, but in case it proves to be
a too little one, this option makes it easy to play with the size.
config NXP_MCR20A_INIT_PRIO
int "MCR20A intialization priority"
default 80
help
Set the initialization priority number. Do not mess with it unless
you know what you are doing. Beware mcr20a requires gpio and spi to
be ready first (and sometime gpio should be the very first as spi
might need it too). And of course it has to start before the net stack.
endif
default "IEEE802154_UPIPE"
depends on IEEE802154_UPIPE
endmenu

View file

@ -0,0 +1,67 @@
# Kconfig.cc2520 - TI CC2520 configuration options
#
menuconfig IEEE802154_CC2520
bool "TI CC2520 Driver support"
depends on NETWORKING
select NET_L2_IEEE802154
default n
menuconfig IEEE802154_CC2520_RAW
bool "TI CC2520 Driver RAW channel"
select NET_L2_RAW_CHANNEL
default n
help
Enable IEEE802154_CC2520 driver with RAW channel
The CC2520 driver with RAW channel allows to export radio interface
over USB making an USB 802.15.4 dongle.
if IEEE802154_CC2520 || IEEE802154_CC2520_RAW
config IEEE802154_CC2520_DRV_NAME
string "TI CC2520 Driver's name"
default "cc2520"
help
This option sets the driver name
config IEEE802154_CC2520_SPI_DRV_NAME
string "SPI driver's name to use to access CC2520"
default ""
help
This option is mandatory to set which SPI controller to use in order
to actually control the CC2520 chip.
config IEEE802154_CC2520_SPI_FREQ
int "SPI system frequency"
default 0
help
This option sets the SPI controller's frequency. Beware this value
depends on the SPI controller being used and also on the system
clock.
config IEEE802154_CC2520_SPI_SLAVE
int "SPI slave linked to CC2520"
default 0
help
This option sets the SPI slave number SPI controller has to switch
to when dealing with CC2520 chip.
config IEEE802154_CC2520_RX_STACK_SIZE
int "Driver's internal rx thread stack size"
default 800
help
This option sets the driver's stack size for its internal rx thread.
The default value should be sufficient, but in case it prooves to be
a too little one, this option makes it easy to play with the size.
config IEEE802154_CC2520_INIT_PRIO
int "CC2520 intialization priority"
default 80
help
Set the initialization priority number. Do not mess with it unless
you know what you are doing. Beware cc2520 requires gpio and spi to
be ready first (and sometime gpio should be the very first as spi
might need it too). And of course it has to start before the net stack.
endif

View file

@ -0,0 +1,120 @@
# Kconfig.mcr20a - NXP MCR20A configuration options
#
menuconfig IEEE802154_MCR20A
bool "NXP MCR20A Driver support"
depends on NETWORKING && SPI
select NET_L2_IEEE802154
default n
menuconfig IEEE802154_MCR20A_RAW
bool "NXP MCR20A Driver RAW channel"
depends on SPI
select NET_L2_RAW_CHANNEL
default n
help
Enable IEEE802154_MCR20A driver with RAW channel
The MCR20A driver with RAW channel allows to export radio interface
over USB making an USB 802.15.4 dongle.
if IEEE802154_MCR20A || IEEE802154_MCR20A_RAW
config IEEE802154_MCR20A_DRV_NAME
string "NXP MCR20A Driver's name"
default "mcr20a"
help
This option sets the driver name
config IEEE802154_MCR20A_SPI_DRV_NAME
string "SPI driver's name to use to access MCR20A"
default SPI_0_NAME
help
This option is mandatory to set which SPI controller to use in order
to actually control the MCR20A chip.
config IEEE802154_MCR20A_SPI_FREQ
int "SPI system frequency"
default 4000000
help
This option sets the SPI controller's frequency. Beware this value
depends on the SPI controller being used and also on the system
clock.
config IEEE802154_MCR20A_SPI_SLAVE
int "SPI slave linked to MCR20A"
default 0
help
This option sets the SPI slave number SPI controller has to switch
to when dealing with MCR20A chip.
config MCR20A_GPIO_IRQ_B_NAME
string "GPIO device used for IRQ_B output of MCR20A"
default GPIO_MCUX_PORTB_NAME
config MCR20A_GPIO_IRQ_B_PIN
int "GPIO pin connected to IRQ_B output of MCR20A"
default 9
config MCR20A_GPIO_RESET_NAME
string "GPIO device used for RESET input of MCR20A"
default GPIO_MCUX_PORTA_NAME
config MCR20A_GPIO_RESET_PIN
int "GPIO pin connected to RESET input of MCR20A"
default 2
choice
prompt "CLK_OUT frequency"
default MCR20A_CLK_OUT_DISABLED
help
Configuration of the MCR20A clock output pin.
config MCR20A_CLK_OUT_DISABLED
bool "Disabled"
config MCR20A_CLK_OUT_32MHZ
bool "32 MHz"
config MCR20A_CLK_OUT_16MHZ
bool "16 MHz"
config MCR20A_CLK_OUT_8MHZ
bool "8 MHz"
config MCR20A_CLK_OUT_4MHZ
bool "4 MHz"
config MCR20A_CLK_OUT_1MHZ
bool "1 MHz"
config MCR20A_CLK_OUT_250KHZ
bool "250 kHz"
config MCR20A_CLK_OUT_62500HZ
bool "62500 Hz"
config MCR20A_CLK_OUT_32768HZ
bool "32768 Hz"
endchoice
config IEEE802154_MCR20A_RX_STACK_SIZE
int "Driver's internal rx thread stack size"
default 800
help
This option sets the driver's stack size for its internal rx thread.
The default value should be sufficient, but in case it proves to be
a too little one, this option makes it easy to play with the size.
config IEEE802154_MCR20A_INIT_PRIO
int "MCR20A intialization priority"
default 80
help
Set the initialization priority number. Do not mess with it unless
you know what you are doing. Beware mcr20a requires gpio and spi to
be ready first (and sometime gpio should be the very first as spi
might need it too). And of course it has to start before the net stack.
endif

View file

@ -1,5 +1,5 @@
obj-$(CONFIG_TI_CC2520) += ieee802154_cc2520.o
obj-$(CONFIG_TI_CC2520_RAW) += ieee802154_cc2520.o
obj-$(CONFIG_UPIPE_15_4) += ieee802154_uart_pipe.o
obj-$(CONFIG_NXP_MCR20A) += ieee802154_mcr20a.o
obj-$(CONFIG_NXP_MCR20A_RAW) += ieee802154_mcr20a.o
obj-$(CONFIG_IEEE802154_CC2520) += ieee802154_cc2520.o
obj-$(CONFIG_IEEE802154_CC2520_RAW) += ieee802154_cc2520.o
obj-$(CONFIG_IEEE802154_UPIPE) += ieee802154_uart_pipe.o
obj-$(CONFIG_IEEE802154_MCR20A) += ieee802154_mcr20a.o
obj-$(CONFIG_IEEE802154_MCR20A_RAW) += ieee802154_mcr20a.o

View file

@ -594,19 +594,19 @@ static void cc2520_rx(int arg)
goto flush;
}
buf = net_nbuf_get_reserve_rx(0);
buf = net_nbuf_get_reserve_rx(0, K_NO_WAIT);
if (!buf) {
SYS_LOG_ERR("No buf available");
goto flush;
}
#if defined(CONFIG_TI_CC2520_RAW)
#if defined(CONFIG_IEEE802154_CC2520_RAW)
/**
* Reserve 1 byte for length
*/
pkt_buf = net_nbuf_get_reserve_data(1);
pkt_buf = net_nbuf_get_reserve_data(1, K_NO_WAIT);
#else
pkt_buf = net_nbuf_get_reserve_data(0);
pkt_buf = net_nbuf_get_reserve_data(0, K_NO_WAIT);
#endif
if (!pkt_buf) {
SYS_LOG_ERR("No pkt_buf available");
@ -615,7 +615,7 @@ static void cc2520_rx(int arg)
net_buf_frag_insert(buf, pkt_buf);
#if defined(CONFIG_TI_CC2520_RAW)
#if defined(CONFIG_IEEE802154_CC2520_RAW)
if (!read_rxfifo_content(&cc2520->spi, pkt_buf, pkt_len)) {
SYS_LOG_ERR("No content read");
goto flush;
@ -651,7 +651,7 @@ static void cc2520_rx(int arg)
goto out;
}
#if defined(CONFIG_TI_CC2520_RAW)
#if defined(CONFIG_IEEE802154_CC2520_RAW)
net_buf_add_u8(pkt_buf, cc2520->lqi);
#endif
@ -665,7 +665,7 @@ static void cc2520_rx(int arg)
net_analyze_stack("CC2520 Rx Fiber stack",
(unsigned char *)cc2520->cc2520_rx_stack,
CONFIG_TI_CC2520_RX_STACK_SIZE);
CONFIG_IEEE802154_CC2520_RX_STACK_SIZE);
continue;
flush:
_cc2520_print_exceptions(cc2520);
@ -990,16 +990,17 @@ static inline int configure_spi(struct device *dev)
struct cc2520_context *cc2520 = dev->driver_data;
struct spi_config spi_conf = {
.config = SPI_WORD(8),
.max_sys_freq = CONFIG_TI_CC2520_SPI_FREQ,
.max_sys_freq = CONFIG_IEEE802154_CC2520_SPI_FREQ,
};
cc2520->spi.dev = device_get_binding(CONFIG_TI_CC2520_SPI_DRV_NAME);
cc2520->spi.dev = device_get_binding(
CONFIG_IEEE802154_CC2520_SPI_DRV_NAME);
if (!cc2520->spi.dev) {
SYS_LOG_ERR("Unable to get SPI device");
return -ENODEV;
}
cc2520->spi.slave = CONFIG_TI_CC2520_SPI_SLAVE;
cc2520->spi.slave = CONFIG_IEEE802154_CC2520_SPI_SLAVE;
if (spi_configure(cc2520->spi.dev, &spi_conf) != 0 ||
spi_slave_select(cc2520->spi.dev,
@ -1037,7 +1038,7 @@ static int cc2520_init(struct device *dev)
}
k_thread_spawn(cc2520->cc2520_rx_stack,
CONFIG_TI_CC2520_RX_STACK_SIZE,
CONFIG_IEEE802154_CC2520_RX_STACK_SIZE,
(k_thread_entry_t)cc2520_rx,
dev, NULL, NULL,
K_PRIO_COOP(2), 0, 0);
@ -1080,21 +1081,21 @@ static struct ieee802154_radio_api cc2520_radio_api = {
.get_lqi = cc2520_get_lqi,
};
#if defined(CONFIG_TI_CC2520_RAW)
DEVICE_AND_API_INIT(cc2520, CONFIG_TI_CC2520_DRV_NAME,
#if defined(CONFIG_IEEE802154_CC2520_RAW)
DEVICE_AND_API_INIT(cc2520, CONFIG_IEEE802154_CC2520_DRV_NAME,
cc2520_init, &cc2520_context_data, NULL,
POST_KERNEL, CONFIG_TI_CC2520_INIT_PRIO,
POST_KERNEL, CONFIG_IEEE802154_CC2520_INIT_PRIO,
&cc2520_radio_api);
#else
NET_DEVICE_INIT(cc2520, CONFIG_TI_CC2520_DRV_NAME,
NET_DEVICE_INIT(cc2520, CONFIG_IEEE802154_CC2520_DRV_NAME,
cc2520_init, &cc2520_context_data, NULL,
CONFIG_TI_CC2520_INIT_PRIO,
CONFIG_IEEE802154_CC2520_INIT_PRIO,
&cc2520_radio_api, IEEE802154_L2,
NET_L2_GET_CTX_TYPE(IEEE802154_L2), 125);
NET_STACK_INFO_ADDR(RX, cc2520,
CONFIG_TI_CC2520_RX_STACK_SIZE,
CONFIG_TI_CC2520_RX_STACK_SIZE,
CONFIG_IEEE802154_CC2520_RX_STACK_SIZE,
CONFIG_IEEE802154_CC2520_RX_STACK_SIZE,
((struct cc2520_context *)(&__device_cc2520))->
cc2520_rx_stack,
0);

View file

@ -40,7 +40,7 @@ struct cc2520_context {
struct k_sem tx_sync;
atomic_t tx;
/************RX************/
char __stack cc2520_rx_stack[CONFIG_TI_CC2520_RX_STACK_SIZE];
char __stack cc2520_rx_stack[CONFIG_IEEE802154_CC2520_RX_STACK_SIZE];
struct k_sem rx_lock;
bool overflow;
uint8_t lqi;

View file

@ -137,6 +137,8 @@ uint8_t _mcr20a_read_reg(struct mcr20a_spi *spi, bool dreg, uint8_t addr)
{
uint8_t len = dreg ? 2 : 3;
k_sem_take(&spi->spi_sem, K_FOREVER);
spi->cmd_buf[0] = dreg ? (MCR20A_REG_READ | addr) :
(MCR20A_IAR_INDEX | MCR20A_REG_WRITE);
spi->cmd_buf[1] = dreg ? 0 : (addr | MCR20A_REG_READ);
@ -146,9 +148,12 @@ uint8_t _mcr20a_read_reg(struct mcr20a_spi *spi, bool dreg, uint8_t addr)
if (spi_transceive(spi->dev, spi->cmd_buf, len,
spi->cmd_buf, len) == 0) {
k_sem_give(&spi->spi_sem);
return spi->cmd_buf[len - 1];
}
k_sem_give(&spi->spi_sem);
return 0;
}
@ -157,6 +162,9 @@ bool _mcr20a_write_reg(struct mcr20a_spi *spi, bool dreg, uint8_t addr,
uint8_t value)
{
uint8_t len = dreg ? 2 : 3;
bool retval;
k_sem_take(&spi->spi_sem, K_FOREVER);
spi->cmd_buf[0] = dreg ? (MCR20A_REG_WRITE | addr) :
(MCR20A_IAR_INDEX | MCR20A_REG_WRITE);
@ -164,14 +172,21 @@ bool _mcr20a_write_reg(struct mcr20a_spi *spi, bool dreg, uint8_t addr,
spi->cmd_buf[2] = dreg ? 0 : value;
spi_slave_select(spi->dev, spi->slave);
retval = (spi_write(spi->dev, spi->cmd_buf, len) == 0);
return (spi_write(spi->dev, spi->cmd_buf, len) == 0);
k_sem_give(&spi->spi_sem);
return retval;
}
/* Write multiple bytes to direct or indirect register */
bool _mcr20a_write_burst(struct mcr20a_spi *spi, bool dreg, uint16_t addr,
uint8_t *data_buf, uint8_t len)
{
bool retval;
k_sem_take(&spi->spi_sem, K_FOREVER);
if ((len + 2) > sizeof(spi->cmd_buf)) {
SYS_LOG_ERR("Buffer length too large");
}
@ -188,14 +203,19 @@ bool _mcr20a_write_burst(struct mcr20a_spi *spi, bool dreg, uint16_t addr,
}
spi_slave_select(spi->dev, spi->slave);
retval = (spi_write(spi->dev, spi->cmd_buf, len) == 0);
return (spi_write(spi->dev, spi->cmd_buf, len) == 0);
k_sem_give(&spi->spi_sem);
return retval;
}
/* Read multiple bytes from direct or indirect register */
bool _mcr20a_read_burst(struct mcr20a_spi *spi, bool dreg, uint16_t addr,
uint8_t *data_buf, uint8_t len)
{
k_sem_take(&spi->spi_sem, K_FOREVER);
if ((len + 2) > sizeof(spi->cmd_buf)) {
SYS_LOG_ERR("Buffer length too large");
}
@ -213,6 +233,7 @@ bool _mcr20a_read_burst(struct mcr20a_spi *spi, bool dreg, uint16_t addr,
if (spi_transceive(spi->dev, spi->cmd_buf, len,
spi->cmd_buf, len) != 0) {
k_sem_give(&spi->spi_sem);
return 0;
}
@ -222,6 +243,8 @@ bool _mcr20a_read_burst(struct mcr20a_spi *spi, bool dreg, uint16_t addr,
memcpy(data_buf, &spi->cmd_buf[2], len - 2);
}
k_sem_give(&spi->spi_sem);
return 1;
}
@ -472,17 +495,21 @@ static inline bool read_rxfifo_content(struct mcr20a_spi *spi,
return false;
}
data[0] = MCR20A_BUF_READ;
k_sem_take(&spi->spi_sem, K_FOREVER);
data[0] = MCR20A_BUF_READ;
spi_slave_select(spi->dev, spi->slave);
if (spi_transceive(spi->dev, data, len+1, data, len+1) != 0) {
k_sem_give(&spi->spi_sem);
return false;
}
memcpy(buf->data, &data[1], len);
net_buf_add(buf, len);
k_sem_give(&spi->spi_sem);
return true;
}
@ -497,20 +524,20 @@ static inline void mcr20a_rx(struct mcr20a_context *mcr20a)
pkt_len = read_reg_rx_frm_len(&mcr20a->spi);
pkt_len -= MCR20A_FCS_LENGTH;
buf = net_nbuf_get_reserve_rx(0);
buf = net_nbuf_get_reserve_rx(0, K_NO_WAIT);
if (!buf) {
SYS_LOG_ERR("No buf available");
goto out;
}
#if defined(CONFIG_NXP_MCR20A_RAW)
#if defined(CONFIG_IEEE802154_MCR20A_RAW)
/* TODO: Test raw mode */
/**
* Reserve 1 byte for length
*/
pkt_buf = net_nbuf_get_reserve_data(1);
pkt_buf = net_nbuf_get_reserve_data(1, K_NO_WAIT);
#else
pkt_buf = net_nbuf_get_reserve_data(0);
pkt_buf = net_nbuf_get_reserve_data(0, K_NO_WAIT);
#endif
if (!pkt_buf) {
SYS_LOG_ERR("No pkt_buf available");
@ -534,7 +561,7 @@ static inline void mcr20a_rx(struct mcr20a_context *mcr20a)
pkt_len, mcr20a->lqi,
mcr20a_get_rssi(mcr20a->lqi));
#if defined(CONFIG_NXP_MCR20A_RAW)
#if defined(CONFIG_IEEE802154_MCR20A_RAW)
net_buf_add_u8(pkt_buf, mcr20a->lqi);
#endif
@ -545,7 +572,7 @@ static inline void mcr20a_rx(struct mcr20a_context *mcr20a)
net_analyze_stack("MCR20A Rx Fiber stack",
mcr20a->mcr20a_rx_stack,
CONFIG_NXP_MCR20A_RX_STACK_SIZE);
CONFIG_IEEE802154_MCR20A_RX_STACK_SIZE);
return;
out:
if (buf) {
@ -1078,6 +1105,9 @@ static inline bool write_txfifo_content(struct mcr20a_spi *spi,
uint8_t cmd[2 + MCR20A_PSDU_LENGTH];
uint8_t payload_len = net_nbuf_ll_reserve(buf) + frag->len;
uint8_t *payload = frag->data - net_nbuf_ll_reserve(buf);
bool retval;
k_sem_take(&spi->spi_sem, K_FOREVER);
cmd[0] = MCR20A_BUF_WRITE;
/**
@ -1095,7 +1125,13 @@ static inline bool write_txfifo_content(struct mcr20a_spi *spi,
spi_slave_select(spi->dev, spi->slave);
return (spi_write(spi->dev, cmd, (2 + payload_len)) == 0);
retval = (spi_transceive(spi->dev,
cmd, (2 + payload_len),
cmd, (2 + payload_len)) == 0);
k_sem_give(&spi->spi_sem);
return retval;
}
static int mcr20a_tx(struct device *dev,
@ -1233,6 +1269,8 @@ static int mcr20a_update_overwrites(struct mcr20a_context *dev)
goto error;
}
k_sem_take(&spi->spi_sem, K_FOREVER);
for (uint8_t i = 0;
i < sizeof(overwrites_indirect) / sizeof(overwrites_t);
i++) {
@ -1244,10 +1282,13 @@ static int mcr20a_update_overwrites(struct mcr20a_context *dev)
spi_slave_select(spi->dev, spi->slave);
if (spi_write(spi->dev, spi->cmd_buf, 3)) {
k_sem_give(&spi->spi_sem);
goto error;
}
}
k_sem_give(&spi->spi_sem);
return 0;
error:
@ -1356,16 +1397,17 @@ static inline int configure_spi(struct device *dev)
struct mcr20a_context *mcr20a = dev->driver_data;
struct spi_config spi_conf = {
.config = SPI_WORD(8),
.max_sys_freq = CONFIG_NXP_MCR20A_SPI_FREQ,
.max_sys_freq = CONFIG_IEEE802154_MCR20A_SPI_FREQ,
};
mcr20a->spi.dev = device_get_binding(CONFIG_NXP_MCR20A_SPI_DRV_NAME);
mcr20a->spi.dev = device_get_binding(
CONFIG_IEEE802154_MCR20A_SPI_DRV_NAME);
if (!mcr20a->spi.dev) {
SYS_LOG_ERR("Unable to get SPI device");
return -ENODEV;
}
mcr20a->spi.slave = CONFIG_NXP_MCR20A_SPI_SLAVE;
mcr20a->spi.slave = CONFIG_IEEE802154_MCR20A_SPI_SLAVE;
if (spi_configure(mcr20a->spi.dev, &spi_conf) != 0 ||
spi_slave_select(mcr20a->spi.dev,
@ -1374,8 +1416,9 @@ static inline int configure_spi(struct device *dev)
return -EIO;
}
SYS_LOG_DBG("SPI configured %s, %d", CONFIG_NXP_MCR20A_SPI_DRV_NAME,
CONFIG_NXP_MCR20A_SPI_SLAVE);
SYS_LOG_DBG("SPI configured %s, %d",
CONFIG_IEEE802154_MCR20A_SPI_DRV_NAME,
CONFIG_IEEE802154_MCR20A_SPI_SLAVE);
return 0;
}
@ -1384,6 +1427,9 @@ static int mcr20a_init(struct device *dev)
{
struct mcr20a_context *mcr20a = dev->driver_data;
k_sem_init(&mcr20a->spi.spi_sem, 0, UINT_MAX);
k_sem_give(&mcr20a->spi.spi_sem);
atomic_set(&mcr20a->busy, 0);
k_sem_init(&mcr20a->trig_sem, 0, UINT_MAX);
@ -1407,7 +1453,7 @@ static int mcr20a_init(struct device *dev)
}
k_thread_spawn(mcr20a->mcr20a_rx_stack,
CONFIG_NXP_MCR20A_RX_STACK_SIZE,
CONFIG_IEEE802154_MCR20A_RX_STACK_SIZE,
(k_thread_entry_t)mcr20a_thread_main,
dev, NULL, NULL,
K_PRIO_COOP(2), 0, 0);
@ -1448,15 +1494,15 @@ static struct ieee802154_radio_api mcr20a_radio_api = {
.get_lqi = mcr20a_get_lqi,
};
#if defined(CONFIG_NXP_MCR20A_RAW)
DEVICE_AND_API_INIT(mcr20a, CONFIG_NXP_MCR20A_DRV_NAME,
#if defined(CONFIG_IEEE802154_MCR20A_RAW)
DEVICE_AND_API_INIT(mcr20a, CONFIG_IEEE802154_MCR20A_DRV_NAME,
mcr20a_init, &mcr20a_context_data, NULL,
POST_KERNEL, CONFIG_NXP_MCR20A_INIT_PRIO,
POST_KERNEL, CONFIG_IEEE802154_MCR20A_INIT_PRIO,
&mcr20a_radio_api);
#else
NET_DEVICE_INIT(mcr20a, CONFIG_NXP_MCR20A_DRV_NAME,
NET_DEVICE_INIT(mcr20a, CONFIG_IEEE802154_MCR20A_DRV_NAME,
mcr20a_init, &mcr20a_context_data, NULL,
CONFIG_NXP_MCR20A_INIT_PRIO,
CONFIG_IEEE802154_MCR20A_INIT_PRIO,
&mcr20a_radio_api, IEEE802154_L2,
NET_L2_GET_CTX_TYPE(IEEE802154_L2), 125);
#endif

View file

@ -20,6 +20,7 @@
struct mcr20a_spi {
struct device *dev;
uint32_t slave;
struct k_sem spi_sem;
/**
* cmd_buf will use at most 9 bytes:
* dummy bytes + 8 ieee address bytes
@ -40,7 +41,7 @@ struct mcr20a_context {
atomic_t busy;
atomic_t seq_retval;
/************RX************/
char __stack mcr20a_rx_stack[CONFIG_NXP_MCR20A_RX_STACK_SIZE];
char __stack mcr20a_rx_stack[CONFIG_IEEE802154_MCR20A_RX_STACK_SIZE];
struct k_sem trig_sem;
uint8_t lqi;
};

View file

@ -54,13 +54,13 @@ static uint8_t *upipe_rx(uint8_t *buf, size_t *off)
upipe->rx_buf[upipe->rx_off++] = *buf;
if (upipe->rx_len == upipe->rx_off) {
nbuf = net_nbuf_get_reserve_rx(0);
nbuf = net_nbuf_get_reserve_rx(0, K_NO_WAIT);
if (!nbuf) {
SYS_LOG_DBG("No buf available");
goto flush;
}
pkt_buf = net_nbuf_get_reserve_data(0);
pkt_buf = net_nbuf_get_reserve_data(0, K_NO_WAIT);
if (!pkt_buf) {
SYS_LOG_DBG("No fragment available");
goto out;
@ -282,7 +282,7 @@ static struct ieee802154_radio_api upipe_radio_api = {
.stop = upipe_stop,
};
NET_DEVICE_INIT(upipe_15_4, CONFIG_UPIPE_15_4_DRV_NAME,
NET_DEVICE_INIT(upipe_15_4, CONFIG_IEEE802154_UPIPE_DRV_NAME,
upipe_init, &upipe_context_data, NULL,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&upipe_radio_api, IEEE802154_L2,

View file

@ -267,12 +267,12 @@ static inline int slip_input_byte(struct slip_context *slip,
}
if (!slip->rx) {
slip->rx = net_nbuf_get_reserve_rx(0);
slip->rx = net_nbuf_get_reserve_rx(0, K_NO_WAIT);
if (!slip->rx) {
return 0;
}
slip->last = net_nbuf_get_reserve_data(0);
slip->last = net_nbuf_get_reserve_data(0, K_NO_WAIT);
if (!slip->last) {
net_nbuf_unref(slip->rx);
slip->rx = NULL;
@ -287,7 +287,7 @@ static inline int slip_input_byte(struct slip_context *slip,
/* We need to allocate a new fragment */
struct net_buf *frag;
frag = net_nbuf_get_reserve_data(0);
frag = net_nbuf_get_reserve_data(0, K_NO_WAIT);
if (!frag) {
SYS_LOG_ERR("[%p] cannot allocate data fragment",
slip);

View file

@ -10,7 +10,7 @@
MCUX_DEVICE = $(shell echo $(CONFIG_SOC) | tr '[:lower:]' '[:upper:]')
MCUX_CPU = CPU_$(subst $(DQUOTE),,$(CONFIG_SOC_PART_NUMBER))
ifdef CONFIG_NXP_MCR20A
ifdef CONFIG_IEEE802154_MCR20A
ZEPHYRINCLUDE += -I$(srctree)/ext/hal/nxp/mcux/components/mcr20a
endif

View file

@ -311,34 +311,40 @@ static inline void net_nbuf_set_src_ipv6_addr(struct net_buf *buf)
*/
struct net_buf *net_nbuf_get_rx_debug(struct net_context *context,
int32_t timeout,
const char *caller, int line);
#define net_nbuf_get_rx(context) \
net_nbuf_get_rx_debug(context, __func__, __LINE__)
#define net_nbuf_get_rx(context, timeout) \
net_nbuf_get_rx_debug(context, timeout, __func__, __LINE__)
struct net_buf *net_nbuf_get_tx_debug(struct net_context *context,
int32_t timeout,
const char *caller, int line);
#define net_nbuf_get_tx(context) \
net_nbuf_get_tx_debug(context, __func__, __LINE__)
#define net_nbuf_get_tx(context, timeout) \
net_nbuf_get_tx_debug(context, timeout, __func__, __LINE__)
struct net_buf *net_nbuf_get_data_debug(struct net_context *context,
int32_t timeout,
const char *caller, int line);
#define net_nbuf_get_data(context) \
net_nbuf_get_data_debug(context, __func__, __LINE__)
#define net_nbuf_get_data(context, timeout) \
net_nbuf_get_data_debug(context, timeout, __func__, __LINE__)
struct net_buf *net_nbuf_get_reserve_rx_debug(uint16_t reserve_head,
int32_t timeout,
const char *caller, int line);
#define net_nbuf_get_reserve_rx(res) \
net_nbuf_get_reserve_rx_debug(res, __func__, __LINE__)
#define net_nbuf_get_reserve_rx(res, timeout) \
net_nbuf_get_reserve_rx_debug(res, timeout, __func__, __LINE__)
struct net_buf *net_nbuf_get_reserve_tx_debug(uint16_t reserve_head,
int32_t timeout,
const char *caller, int line);
#define net_nbuf_get_reserve_tx(res) \
net_nbuf_get_reserve_tx_debug(res, __func__, __LINE__)
#define net_nbuf_get_reserve_tx(res, timeout) \
net_nbuf_get_reserve_tx_debug(res, timeout, __func__, __LINE__)
struct net_buf *net_nbuf_get_reserve_data_debug(uint16_t reserve_head,
int32_t timeout,
const char *caller, int line);
#define net_nbuf_get_reserve_data(res) \
net_nbuf_get_reserve_data_debug(res, __func__, __LINE__)
#define net_nbuf_get_reserve_data(res, timeout) \
net_nbuf_get_reserve_data_debug(res, timeout, __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__)
@ -369,10 +375,15 @@ void net_nbuf_print_frags(struct net_buf *buf);
*
* @param context Network context that will be related to
* this buffer.
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
* wait as long as necessary. Otherwise, wait up to the specified
* number of milliseconds before timing out.
*
* @return Network buffer if successful, NULL otherwise.
*/
struct net_buf *net_nbuf_get_rx(struct net_context *context);
struct net_buf *net_nbuf_get_rx(struct net_context *context,
int32_t timeout);
/**
* @brief Get buffer from the TX buffers pool.
@ -382,10 +393,15 @@ struct net_buf *net_nbuf_get_rx(struct net_context *context);
*
* @param context Network context that will be related to
* this buffer.
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
* wait as long as necessary. Otherwise, wait up to the specified
* number of milliseconds before timing out.
*
* @return Network buffer if successful, NULL otherwise.
*/
struct net_buf *net_nbuf_get_tx(struct net_context *context);
struct net_buf *net_nbuf_get_tx(struct net_context *context,
int32_t timeout);
/**
* @brief Get buffer from the DATA buffers pool.
@ -395,10 +411,15 @@ struct net_buf *net_nbuf_get_tx(struct net_context *context);
*
* @param context Network context that will be related to
* this buffer.
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
* wait as long as necessary. Otherwise, wait up to the specified
* number of milliseconds before timing out.
*
* @return Network buffer if successful, NULL otherwise.
*/
struct net_buf *net_nbuf_get_data(struct net_context *context);
struct net_buf *net_nbuf_get_data(struct net_context *context,
int32_t timeout);
/**
* @brief Get RX buffer from pool but also reserve headroom for
@ -408,10 +429,15 @@ struct net_buf *net_nbuf_get_data(struct net_context *context);
* but is mainly used by network fragmentation code.
*
* @param reserve_head How many bytes to reserve for headroom.
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
* wait as long as necessary. Otherwise, wait up to the specified
* number of milliseconds before timing out.
*
* @return Network buffer if successful, NULL otherwise.
*/
struct net_buf *net_nbuf_get_reserve_rx(uint16_t reserve_head);
struct net_buf *net_nbuf_get_reserve_rx(uint16_t reserve_head,
int32_t timeout);
/**
* @brief Get TX buffer from pool but also reserve headroom for
@ -421,10 +447,15 @@ struct net_buf *net_nbuf_get_reserve_rx(uint16_t reserve_head);
* but is mainly used by network fragmentation code.
*
* @param reserve_head How many bytes to reserve for headroom.
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
* wait as long as necessary. Otherwise, wait up to the specified
* number of milliseconds before timing out.
*
* @return Network buffer if successful, NULL otherwise.
*/
struct net_buf *net_nbuf_get_reserve_tx(uint16_t reserve_head);
struct net_buf *net_nbuf_get_reserve_tx(uint16_t reserve_head,
int32_t timeout);
/**
* @brief Get DATA buffer from pool but also reserve headroom for
@ -434,10 +465,15 @@ struct net_buf *net_nbuf_get_reserve_tx(uint16_t reserve_head);
* but is mainly used by network fragmentation code.
*
* @param reserve_head How many bytes to reserve for headroom.
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
* wait as long as necessary. Otherwise, wait up to the specified
* number of milliseconds before timing out.
*
* @return Network buffer if successful, NULL otherwise.
*/
struct net_buf *net_nbuf_get_reserve_data(uint16_t reserve_head);
struct net_buf *net_nbuf_get_reserve_data(uint16_t reserve_head,
int32_t timeout);
/**
* @brief Place buffer back into the available buffers pool.
@ -477,11 +513,15 @@ struct net_buf *net_nbuf_ref(struct net_buf *buf);
* @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.
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
* wait as long as necessary. Otherwise, wait up to the specified
* number of milliseconds before timing out.
*
* @return New fragment list if successful, NULL otherwise.
*/
struct net_buf *net_nbuf_copy(struct net_buf *buf, size_t amount,
size_t reserve);
size_t reserve, int32_t timeout);
/**
* @brief Copy a buffer with fragments while reserving some extra space
@ -492,27 +532,32 @@ struct net_buf *net_nbuf_copy(struct net_buf *buf, size_t amount,
* @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.
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
* wait as long as necessary. Otherwise, wait up to the specified
* number of milliseconds before timing out.
*
* @return New fragment list if successful, NULL otherwise.
*/
static inline struct net_buf *net_nbuf_copy_all(struct net_buf *buf,
size_t reserve)
size_t reserve,
int32_t timeout)
{
return net_nbuf_copy(buf, net_buf_frags_len(buf), reserve);
return net_nbuf_copy(buf, net_buf_frags_len(buf), reserve, timeout);
}
/**
* @brief net_nbuf_linear_copy Copy len bytes from src starting from
* offset to dst
* @details This routine assumes that dst is conformed by
* one fragment with enough space to store len
* bytes starting from offset at src.
* @param dst Destination buffer
* @param src Source buffer that may be fragmented
* @param offset Starting point to copy from
* @param len Number of bytes to copy
* @return 0 on success
* @return -ENOMEM on error
* @brief Copy len bytes from src starting from offset to dst
*
* This routine assumes that dst is conformed by one fragment with enough space
* to store @a len bytes starting from offset at src.
*
* @param dst Destination buffer
* @param src Source buffer that may be fragmented
* @param offset Starting point to copy from
* @param len Number of bytes to copy
* @return 0 on success
* @return -ENOMEM on error
*/
int net_nbuf_linear_copy(struct net_buf *dst, struct net_buf *src,
uint16_t offset, uint16_t len);
@ -521,12 +566,13 @@ int net_nbuf_linear_copy(struct net_buf *dst, struct net_buf *src,
* @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.
* @param buf Network buffer fragment. This should be the Tx/Rx buffer.
*
* @return True if compact success, False otherwise. (Note that it fails only
* when input is data fragment)
*
* @return Pointer to the start of the fragment list if ok, NULL otherwise.
*/
struct net_buf *net_nbuf_compact(struct net_buf *buf);
bool net_nbuf_compact(struct net_buf *buf);
/**
* @brief Check if the buffer chain is compact or not.
@ -542,24 +588,6 @@ struct net_buf *net_nbuf_compact(struct net_buf *buf);
*/
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
@ -583,12 +611,17 @@ struct net_buf *net_nbuf_pull(struct net_buf *buf, size_t amount);
* @param buf Network buffer fragment list.
* @param len Total length of input data
* @param data Data to be added
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
* wait as long as necessary. Otherwise, wait up to the specified
* number of milliseconds before timing out.
*
* @return 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);
bool net_nbuf_append(struct net_buf *buf, uint16_t len, uint8_t *data,
int32_t timeout);
/**
* @brief Append uint8_t data to last fragment in fragment list
@ -606,7 +639,7 @@ bool net_nbuf_append(struct net_buf *buf, uint16_t len, uint8_t *data);
*/
static inline bool net_nbuf_append_u8(struct net_buf *buf, uint8_t data)
{
return net_nbuf_append(buf, 1, &data);
return net_nbuf_append(buf, 1, &data, K_FOREVER);
}
/**
@ -627,7 +660,8 @@ 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);
return net_nbuf_append(buf, sizeof(uint16_t), (uint8_t *)&value,
K_FOREVER);
}
/**
@ -648,7 +682,8 @@ 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);
return net_nbuf_append(buf, sizeof(uint32_t), (uint8_t *)&value,
K_FOREVER);
}
/**
@ -770,23 +805,23 @@ struct net_buf *net_nbuf_read_be32(struct net_buf *buf, uint16_t offset,
* 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)
* 1) net_nbuf_write(buf, frag2, 20, &pos, 20, data, K_FOREVER)
* In this case write starts from "frag2->data + 20",
* returns frag2, pos = 40
*
* 2) net_nbuf_write(buf, frag1, 150, &pos, 60, data)
* 2) net_nbuf_write(buf, frag1, 150, &pos, 60, data, K_FOREVER)
* In this case write starts from "frag2->data + 50"
* returns frag3, pos = 10
*
* 3) net_nbuf_write(buf, frag1, 350, &pos, 30, data)
* 3) net_nbuf_write(buf, frag1, 350, &pos, 30, data, K_FOREVER)
* In this case write starts from "frag4->data + 50"
* returns frag4, pos = 80
*
* 4) net_nbuf_write(buf, frag2, 110, &pos, 90, data)
* 4) net_nbuf_write(buf, frag2, 110, &pos, 90, data, K_FOREVER)
* In this case write starts from "frag3->data + 10"
* returns frag4, pos = 0
*
* 5) net_nbuf_write(buf, frag4, 110, &pos, 20, data)
* 5) net_nbuf_write(buf, frag4, 110, &pos, 20, data, K_FOREVER)
* In this case write creates new data fragment and starts from
* "frag5->data + 10"
* returns frag5, pos = 30
@ -801,13 +836,17 @@ struct net_buf *net_nbuf_read_be32(struct net_buf *buf, uint16_t offset,
* relative to return fragment)
* @param len Length of the data to be written.
* @param data Data to be written
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
* wait as long as necessary. Otherwise, wait up to the specified
* number of milliseconds before timing out.
*
* @return 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);
uint8_t *data, int32_t timeout);
/* Write uint8_t data to an arbitrary offset in fragment. */
static inline struct net_buf *net_nbuf_write_u8(struct net_buf *buf,
@ -816,7 +855,8 @@ static inline struct net_buf *net_nbuf_write_u8(struct net_buf *buf,
uint16_t *pos,
uint8_t data)
{
return net_nbuf_write(buf, frag, offset, pos, sizeof(uint8_t), &data);
return net_nbuf_write(buf, frag, offset, pos, sizeof(uint8_t),
&data, K_FOREVER);
}
/* Write uint16_t big endian value to an arbitrary offset in fragment. */
@ -829,7 +869,7 @@ static inline struct net_buf *net_nbuf_write_be16(struct net_buf *buf,
uint16_t value = htons(data);
return net_nbuf_write(buf, frag, offset, pos, sizeof(uint16_t),
(uint8_t *)&value);
(uint8_t *)&value, K_FOREVER);
}
/* Write uint32_t big endian value to an arbitrary offset in fragment. */
@ -842,7 +882,7 @@ static inline struct net_buf *net_nbuf_write_be32(struct net_buf *buf,
uint32_t value = htonl(data);
return net_nbuf_write(buf, frag, offset, pos, sizeof(uint32_t),
(uint8_t *)&value);
(uint8_t *)&value, K_FOREVER);
}
/**
@ -862,18 +902,26 @@ static inline struct net_buf *net_nbuf_write_be32(struct net_buf *buf,
* @param offset Offset of fragment where insertion will start.
* @param len Length of the data to be inserted.
* @param data Data to be inserted
* @param timeout Affects the action taken should the net buf pool be empty.
* If K_NO_WAIT, then return immediately. If K_FOREVER, then
* wait as long as necessary. Otherwise, wait up to the specified
* number of milliseconds before timing out.
*
* @return 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);
uint16_t offset, uint16_t len, uint8_t *data,
int32_t timeout);
/* 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)
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);
return net_nbuf_insert(buf, frag, offset, sizeof(uint8_t), &data,
K_FOREVER);
}
/* Insert uint16_t big endian value at an arbitrary offset in a series of
@ -881,12 +929,13 @@ static inline bool net_nbuf_insert_u8(struct net_buf *buf, struct net_buf *frag,
*/
static inline bool net_nbuf_insert_be16(struct net_buf *buf,
struct net_buf *frag,
uint16_t offset, uint16_t data)
uint16_t offset,
uint16_t data)
{
uint16_t value = htons(data);
return net_nbuf_insert(buf, frag, offset, sizeof(uint16_t),
(uint8_t *)&value);
(uint8_t *)&value, K_FOREVER);
}
/* Insert uint32_t big endian value at an arbitrary offset in a series of
@ -894,12 +943,13 @@ static inline bool net_nbuf_insert_be16(struct net_buf *buf,
*/
static inline bool net_nbuf_insert_be32(struct net_buf *buf,
struct net_buf *frag,
uint16_t offset, uint32_t data)
uint16_t offset,
uint32_t data)
{
uint32_t value = htonl(data);
return net_nbuf_insert(buf, frag, offset, sizeof(uint32_t),
(uint8_t *)&value);
(uint8_t *)&value, K_FOREVER);
}
/**

View file

@ -145,7 +145,7 @@ static struct net_buf *build_reply_buf(const char *name,
printk("%s received %d bytes", name,
net_nbuf_appdatalen(buf));
reply_buf = net_nbuf_get_tx(context);
reply_buf = net_nbuf_get_tx(context, K_FOREVER);
recv_len = net_buf_frags_len(buf->frags);

View file

@ -58,12 +58,12 @@ int udp_tx(void *context, const unsigned char *buf, size_t size)
udp_ctx = ctx->net_ctx;
send_buf = net_nbuf_get_tx(udp_ctx);
send_buf = net_nbuf_get_tx(udp_ctx, K_FOREVER);
if (!send_buf) {
return MBEDTLS_ERR_SSL_ALLOC_FAILED;
}
rc = net_nbuf_append(send_buf, size, (uint8_t *) buf);
rc = net_nbuf_append(send_buf, size, (uint8_t *) buf, K_FOREVER);
if (!rc) {
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
}

View file

@ -47,13 +47,13 @@ int udp_tx(void *context, const unsigned char *buf, size_t size)
net_ctx = ctx->net_ctx;
send_buf = net_nbuf_get_tx(net_ctx);
send_buf = net_nbuf_get_tx(net_ctx, K_FOREVER);
if (!send_buf) {
printk("cannot create buf\n");
return -EIO;
}
rc = net_nbuf_append(send_buf, size, (uint8_t *) buf);
rc = net_nbuf_append(send_buf, size, (uint8_t *) buf, K_FOREVER);
if (!rc) {
printk("cannot write buf\n");
return -EIO;

View file

@ -36,8 +36,8 @@ CONFIG_NET_L2_IEEE802154_ORFD=y
CONFIG_NET_L2_IEEE802154_FRAGMENT=y
CONFIG_NET_DEBUG_L2_IEEE802154_FRAGMENT=y
CONFIG_TI_CC2520=y
CONFIG_TI_CC2520_AUTO_ACK=y
CONFIG_IEEE802154_CC2520=y
CONFIG_IEEE802154_CC2520_AUTO_ACK=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1
CONFIG_GPIO=y
@ -47,6 +47,6 @@ CONFIG_SPI_1=y
CONFIG_SPI_CS_GPIO=y
CONFIG_SPI_1_CS_GPIO_PORT="GPIO_0"
CONFIG_SPI_1_CS_GPIO_PIN=0
CONFIG_TI_CC2520_SPI_DRV_NAME="SPI_1"
CONFIG_TI_CC2520_SPI_FREQ=4
CONFIG_TI_CC2520_SPI_SLAVE=1
CONFIG_IEEE802154_CC2520_SPI_DRV_NAME="SPI_1"
CONFIG_IEEE802154_CC2520_SPI_FREQ=4
CONFIG_IEEE802154_CC2520_SPI_SLAVE=1

View file

@ -38,8 +38,8 @@ CONFIG_NET_L2_IEEE802154_ORFD=y
CONFIG_NET_L2_IEEE802154_FRAGMENT=y
CONFIG_NET_DEBUG_L2_IEEE802154_FRAGMENT=y
CONFIG_TI_CC2520=y
CONFIG_TI_CC2520_AUTO_ACK=y
CONFIG_IEEE802154_CC2520=y
CONFIG_IEEE802154_CC2520_AUTO_ACK=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1
CONFIG_NET_SAMPLES_IP_ADDRESSES=y

View file

@ -42,12 +42,12 @@ CONFIG_SPI_0=y
CONFIG_SYS_LOG_SPI_LEVEL=1
CONFIG_TI_CC2520=y
CONFIG_TI_CC2520_AUTO_ACK=y
CONFIG_IEEE802154_CC2520=y
CONFIG_IEEE802154_CC2520_AUTO_ACK=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1
CONFIG_TI_CC2520_SPI_DRV_NAME="SPI_0"
CONFIG_TI_CC2520_SPI_FREQ=4000000
CONFIG_TI_CC2520_SPI_SLAVE=0
CONFIG_IEEE802154_CC2520_SPI_DRV_NAME="SPI_0"
CONFIG_IEEE802154_CC2520_SPI_FREQ=4000000
CONFIG_IEEE802154_CC2520_SPI_SLAVE=0
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1"

View file

@ -40,7 +40,7 @@ CONFIG_GPIO=y
CONFIG_SPI=y
CONFIG_SPI_0=y
CONFIG_NXP_MCR20A=y
CONFIG_IEEE802154_MCR20A=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1
CONFIG_NET_SAMPLES_IP_ADDRESSES=y

View file

@ -40,7 +40,7 @@ CONFIG_NET_L2_IEEE802154_ORFD=y
CONFIG_NET_L2_IEEE802154_FRAGMENT=y
CONFIG_NET_DEBUG_L2_IEEE802154_FRAGMENT=y
CONFIG_UPIPE_15_4=y
CONFIG_IEEE802154_UPIPE=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1
CONFIG_NET_SAMPLES_IP_ADDRESSES=y

View file

@ -1,6 +1,6 @@
obj-y = echo-client.o
ifeq ($(CONFIG_TI_CC2520),y)
ifeq ($(CONFIG_IEEE802154_CC2520),y)
ifeq ($(CONFIG_BOARD_ARDUINO_101),y)
ccflags-y +=-I${ZEPHYR_BASE}/include/drivers/

View file

@ -364,11 +364,12 @@ static struct net_buf *prepare_send_buf(const char *name,
struct net_buf *send_buf;
bool status;
send_buf = net_nbuf_get_tx(context);
send_buf = net_nbuf_get_tx(context, K_FOREVER);
NET_ASSERT(send_buf);
status = net_nbuf_append(send_buf, expecting_len, lorem_ipsum);
status = net_nbuf_append(send_buf, expecting_len, lorem_ipsum,
K_FOREVER);
if (!status) {
NET_ERR("%s: cannot create send buf", name);
return NULL;

View file

@ -36,8 +36,8 @@ CONFIG_NET_L2_IEEE802154_ORFD=y
CONFIG_NET_L2_IEEE802154_FRAGMENT=y
CONFIG_NET_DEBUG_L2_IEEE802154_FRAGMENT=y
CONFIG_TI_CC2520=y
CONFIG_TI_CC2520_AUTO_ACK=y
CONFIG_IEEE802154_CC2520=y
CONFIG_IEEE802154_CC2520_AUTO_ACK=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1
CONFIG_GPIO=y
@ -47,6 +47,6 @@ CONFIG_SPI_1=y
CONFIG_SPI_CS_GPIO=y
CONFIG_SPI_1_CS_GPIO_PORT="GPIO_0"
CONFIG_SPI_1_CS_GPIO_PIN=0
CONFIG_TI_CC2520_SPI_DRV_NAME="SPI_1"
CONFIG_TI_CC2520_SPI_FREQ=4
CONFIG_TI_CC2520_SPI_SLAVE=1
CONFIG_IEEE802154_CC2520_SPI_DRV_NAME="SPI_1"
CONFIG_IEEE802154_CC2520_SPI_FREQ=4
CONFIG_IEEE802154_CC2520_SPI_SLAVE=1

View file

@ -38,8 +38,8 @@ CONFIG_NET_L2_IEEE802154_ORFD=y
CONFIG_NET_L2_IEEE802154_FRAGMENT=y
#CONFIG_NET_DEBUG_L2_IEEE802154_FRAGMENT=y
CONFIG_TI_CC2520=y
CONFIG_TI_CC2520_AUTO_ACK=y
CONFIG_IEEE802154_CC2520=y
CONFIG_IEEE802154_CC2520_AUTO_ACK=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1
CONFIG_NET_SAMPLES_IP_ADDRESSES=y

View file

@ -42,12 +42,12 @@ CONFIG_SPI_0=y
CONFIG_SYS_LOG_SPI_LEVEL=1
CONFIG_TI_CC2520=y
CONFIG_TI_CC2520_AUTO_ACK=y
CONFIG_IEEE802154_CC2520=y
CONFIG_IEEE802154_CC2520_AUTO_ACK=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1
CONFIG_TI_CC2520_SPI_DRV_NAME="SPI_0"
CONFIG_TI_CC2520_SPI_FREQ=4000000
CONFIG_TI_CC2520_SPI_SLAVE=0
CONFIG_IEEE802154_CC2520_SPI_DRV_NAME="SPI_0"
CONFIG_IEEE802154_CC2520_SPI_FREQ=4000000
CONFIG_IEEE802154_CC2520_SPI_SLAVE=0
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::2"

View file

@ -39,7 +39,7 @@ CONFIG_GPIO=y
CONFIG_SPI=y
CONFIG_SPI_0=y
CONFIG_NXP_MCR20A=y
CONFIG_IEEE802154_MCR20A=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1
CONFIG_NET_SAMPLES_IP_ADDRESSES=y

View file

@ -40,7 +40,7 @@ CONFIG_NET_L2_IEEE802154_ORFD=y
CONFIG_NET_L2_IEEE802154_FRAGMENT=y
CONFIG_NET_DEBUG_L2_IEEE802154_FRAGMENT=y
CONFIG_UPIPE_15_4=y
CONFIG_IEEE802154_UPIPE=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1
CONFIG_NET_SAMPLES_IP_ADDRESSES=y

View file

@ -1,6 +1,6 @@
obj-y = echo-server.o
ifeq ($(CONFIG_TI_CC2520),y)
ifeq ($(CONFIG_IEEE802154_CC2520),y)
ifeq ($(CONFIG_BOARD_ARDUINO_101),y)
ccflags-y +=-I${ZEPHYR_BASE}/include/drivers/

View file

@ -271,7 +271,7 @@ static struct net_buf *build_reply_buf(const char *name,
return NULL;
}
reply_buf = net_nbuf_get_tx(context);
reply_buf = net_nbuf_get_tx(context, K_FOREVER);
NET_ASSERT(reply_buf);
@ -292,7 +292,7 @@ static struct net_buf *build_reply_buf(const char *name,
net_buf_pull(tmp, header_len);
while (tmp) {
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!net_buf_headroom(tmp)) {
/* If there is no link layer headers in the
@ -429,8 +429,8 @@ static void tcp_received(struct net_context *context,
void *user_data)
{
static char dbg[MAX_DBG_PRINT + 1];
sa_family_t family = net_nbuf_family(buf);
struct net_buf *reply_buf;
sa_family_t family;
int ret;
if (!buf) {
@ -438,6 +438,8 @@ static void tcp_received(struct net_context *context,
return;
}
family = net_nbuf_family(buf);
snprintk(dbg, MAX_DBG_PRINT, "TCP IPv%c",
family == AF_INET6 ? '6' : '4');

View file

@ -0,0 +1,10 @@
#
# Copyright (c) 2017 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
BOARD ?= frdm_k64f
CONF_FILE ?= prj_$(BOARD).conf
include $(ZEPHYR_BASE)/Makefile.inc

View file

@ -0,0 +1,229 @@
HTTP Client
###########
Overview
********
This sample application shows how to create HTTP 1.1 requests to
an HTTP server and how to parse the incoming responses.
Supported HTTP 1.1 methods are: GET, HEAD, OPTIONS and POST.
The source code for this sample application can be found at:
:file:`samples/net/http_client`.
Requirements
************
- Freedom Board (FRDM-K64F)
- LAN for testing purposes (Ethernet)
- Terminal emulator software
- HTTP Server
Building and Running
********************
Open the project configuration file for your platform, for example:
:file:`prj_frdm_k64f.conf` is the configuration file for the
:ref:`frdm_k64f` board. For IPv4 networks, set the following variables:
.. code-block:: console
CONFIG_NET_IPV4=y
CONFIG_NET_IPV6=n
IPv6 is the preferred routing technology for this sample application,
if CONFIG_NET_IPV6=y is set, the value of CONFIG_NET_IPV4=y is ignored.
In this sample application, only static IP addresses are supported,
those addresses are specified in the project configuration file,
for example:
.. code-block:: console
CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2"
are the IPv6 addresses for the HTTP client running Zephyr and the
HTTP server, respectively.
Alternatively, the IP addresses may be specified in the
:file:`src/config.h` file.
Open the :file:`src/config.h` file and set the server port
to match the HTTP server setup, for example:
.. code-block:: c
#define SERVER_PORT 80
assumes that the HTTP server is listening at the TCP port 80.
HTTP Server
===========
Setting up an HTTP server on your host computer is beyond the scope
of this document.
(We used `Apache 2 <http://httpd.apache.org/docs/2.4/getting-started.html>`_
for testing this sample application.
However, this application assumes that there is a server's
resource that can process an HTTP 1.1 POST request.
For example, assuming that the Apache 2 server with PHP support
is used, and that the client sends a POST request with
"Content-Type = application/x-www-form-urlencoded" the following
PHP script will echo the POST payload back to the client:
.. code-block:: html
<html>
<head>
<title>HTTP Server POST test</title>
</head>
<body>
<?php
echo '<p>POST key/values:</p>';
foreach ($_POST as $key => $value) {
echo "<p> {$key} : {$value} </p>";
}
?>
</body>
</html>
In the machine hosting the HTTP server, this php script is at
:file:`/var/www/html/post_test.php`. However, for your test machine
this path can be different, but should be at your server's root folder.
HTTP Responses
==============
Server's responses are processed by the http_receive_cb routine
defined inside the :file:`src/http_client_rcv.c` file.
This sample application only prints the HTTP header fields via
the HTTP Parser Library, see :file:`include/net/http_parser.h`.
To process the HTTP response's body, use the HTTP Parser's callbacks
to determine where the body begins. Depending on the payload's size,
it may be necessary to traverse the network buffer's fragment chain.
See the :file:`src/http_client_rcv.c` file at line 70 for sample code
that shows how to walk the fragment chain.
FRDM K64F
=========
Open a terminal window and type:
.. code-block:: console
$ make BOARD=frdm_k64f
The FRDM K64F board is detected as a USB storage device. The board
must be mounted (i.e. to /mnt) to 'flash' the binary:
.. code-block:: console
$ cp outdir/frdm_k64f/zephyr.bin /mnt
On Linux, use the 'dmesg' program to find the right USB device for the
FRDM serial console. Assuming that this device is ttyACM0, open a
terminal window and type:
.. code-block:: console
$ screen /dev/ttyACM0 115200
Once the binary is loaded into the FRDM board, press the RESET button.
Refer to the board documentation in Zephyr, :ref:`frdm_k64f`,
for more information about this board and how to access the FRDM
serial console under other operating systems.
Sample Output
=============
This sample application loops a specified number of times doing four
HTTP 1.1 requests and displays the header fields that were extracted
from the server's response. The four requests are:
- GET "/index.html"
- HEAD "/"
- OPTIONS "/"
- POST "/post_test.php"
The terminal window where screen is running will show something similar
to the following:
.. code-block:: console
*******************************************
HTTP Client: 2001:db8::1
Connecting to: 2001:db8::2 port 80
Hostname: 2001:db8::2
HTTP Request: GET
--------- HTTP response (headers) ---------
Date: Thu, 02 Feb 2017 00:51:31 GMT
Server: Apache/2.4.10 (Debian)
Last-Modified: Sat, 28 Jan 2017 02:55:09 GMT
ETag: "3c-5471eb5db3c73"
Accept-Ranges: bytes
Content-Length: 60
Connection: close
Content-Type: text/html
HTTP server response status: OK
HTTP parser status: success
HTTP body: 60 bytes, expected: 60 bytes
*******************************************
HTTP Client: 2001:db8::1
Connecting to: 2001:db8::2 port 80
Hostname: 2001:db8::2
HTTP Request: HEAD
--------- HTTP response (headers) ---------
Date: Thu, 02 Feb 2017 00:51:37 GMT
Server: Apache/2.4.10 (Debian)
Last-Modified: Sat, 28 Jan 2017 02:55:09 GMT
ETag: "3c-5471eb5db3c73"
Accept-Ranges: bytes
Content-Length: 60
Connection: close
Content-Type: text/html
HTTP server response status: OK
HTTP parser status: success
*******************************************
HTTP Client: 2001:db8::1
Connecting to: 2001:db8::2 port 80
Hostname: 2001:db8::2
HTTP Request: OPTIONS
--------- HTTP response (headers) ---------
Date: Thu, 02 Feb 2017 00:51:43 GMT
Server: Apache/2.4.10 (Debian)
Allow: GET,HEAD,POST,OPTIONS
Content-Length: 0
Connection: close
Content-Type: text/html
HTTP server response status: OK
HTTP parser status: success
*******************************************
HTTP Client: 2001:db8::1
Connecting to: 2001:db8::2 port 80
Hostname: 2001:db8::2
HTTP Request: POST
--------- HTTP response (headers) ---------
Date: Thu, 02 Feb 2017 00:51:49 GMT
Server: Apache/2.4.10 (Debian)
Vary: Accept-Encoding
Content-Length: 231
Connection: close
Content-Type: text/html; charset=UTF-8
HTTP server response status: OK
HTTP parser status: success

View file

@ -0,0 +1,34 @@
CONFIG_RANDOM_GENERATOR=y
CONFIG_NETWORKING=y
CONFIG_NET_TCP=y
CONFIG_NET_ARP=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_IPV6_RA_RDNSS=y
CONFIG_NET_IFACE_UNICAST_IPV4_ADDR_COUNT=3
CONFIG_NET_NBUF_RX_COUNT=64
CONFIG_NET_NBUF_TX_COUNT=64
CONFIG_NET_NBUF_DATA_COUNT=16
CONFIG_NET_IPV4=n
CONFIG_NET_IPV6=y
CONFIG_HTTP_PARSER=y
CONFIG_STDOUT_CONSOLE=y
# Set the IP addresses here or in the
# src/config.h file
#
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_SAMPLES_PEER_IPV6_ADDR="2001:db8::2"
CONFIG_NET_SAMPLES_MY_IPV4_ADDR="192.168.1.101"
CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.168.1.10"
#CONFIG_MAIN_STACK_SIZE=8192
# See the config.h file and the LINEARIZE_BUFFER define
#
#CONFIG_NET_NBUF_DATA_SIZE=512

View file

@ -0,0 +1,11 @@
#
# Copyright (c) 2017 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
obj-y += main.o
obj-y += tcp_client.o
obj-y += http_client.o
obj-y += http_client_rcv.o
obj-y += http_client_cb.o

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <net/net_ip.h>
#define APP_NAP_TIME 3000
#define HTTP_POOL_BUF_CTR 4
#define HTTP_POOL_BUF_SIZE 1024
#define HTTP_STATUS_STR_SIZE 32
/* server port */
#define SERVER_PORT 80
/* rx tx timeout */
#define HTTP_NETWORK_TIMEOUT 300
#ifdef CONFIG_NET_SAMPLES_IP_ADDRESSES
#ifdef CONFIG_NET_IPV6
#define LOCAL_ADDR CONFIG_NET_SAMPLES_MY_IPV6_ADDR
#define SERVER_ADDR CONFIG_NET_SAMPLES_PEER_IPV6_ADDR
#else
#define LOCAL_ADDR CONFIG_NET_SAMPLES_MY_IPV4_ADDR
#define SERVER_ADDR CONFIG_NET_SAMPLES_PEER_IPV4_ADDR
#endif
#else
#ifdef CONFIG_NET_IPV6
#define LOCAL_ADDR "2001:db8::1"
#define SERVER_ADDR "2001:db8::2"
#else
#define LOCAL_ADDR "192.168.1.101"
#define SERVER_ADDR "192.168.1.10"
#endif
#endif /* CONFIG */
/* It seems enough to hold 'Content-Length' and its value */
#define CON_LEN_SIZE 48
/* Default HTTP Header Field values for HTTP Requests */
#define ACCEPT "text/plain"
#define ACCEPT_ENC "identity"
#define ACCEPT_LANG "en-US"
#define CONNECTION "Close"
#define USER_AGENT "ZephyrHTTPClient/1.7"
#define HOST_NAME SERVER_ADDR /* or example.com, www.example.com */
#define HEADER_FIELDS "Accept: "ACCEPT"\r\n" \
"Accept-Encoding: "ACCEPT_ENC"\r\n" \
"Accept-Language: "ACCEPT_LANG"\r\n" \
"User-Agent: "USER_AGENT"\r\n" \
"Host: "HOST_NAME"\r\n" \
"Connection: "CONNECTION"\r\n"
/* Parsing and token tracking becomes a bit complicated if the
* RX buffer is fragmented. for example: an HTTP response with
* header fields that lie in two fragments. So, here we have
* two options:
*
* - Use the fragmented buffer, but increasing the fragment size
* - Linearize the buffer, it works better but consumes more memory
*
* Comment the following define to test the first case, set the
* CONFIG_NET_NBUF_DATA_SIZE variable to 384 or 512. See the
* prj_frdm_k64f.conf file.
*/
#define LINEARIZE_BUFFER
#ifndef LINEARIZE_BUFFER
#if CONFIG_NET_NBUF_DATA_SIZE <= 256
#error set CONFIG_NET_NBUF_DATA_SIZE to 384 or 512
#endif
#endif

View file

@ -0,0 +1,158 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "http_client.h"
#include "http_client_rcv.h"
#include "http_client_cb.h"
#include "config.h"
#include <misc/printk.h>
#include <net/nbuf.h>
int http_init(struct http_client_ctx *http_ctx)
{
memset(http_ctx, 0, sizeof(struct http_client_ctx));
http_ctx->settings.on_body = on_body;
http_ctx->settings.on_chunk_complete = on_chunk_complete;
http_ctx->settings.on_chunk_header = on_chunk_header;
http_ctx->settings.on_headers_complete = on_headers_complete;
http_ctx->settings.on_header_field = on_header_field;
http_ctx->settings.on_header_value = on_header_value;
http_ctx->settings.on_message_begin = on_message_begin;
http_ctx->settings.on_message_complete = on_message_complete;
http_ctx->settings.on_status = on_status;
http_ctx->settings.on_url = on_url;
return 0;
}
int http_reset_ctx(struct http_client_ctx *http_ctx)
{
http_parser_init(&http_ctx->parser, HTTP_RESPONSE);
memset(http_ctx->http_status, 0, sizeof(http_ctx->http_status));
http_ctx->cl_present = 0;
http_ctx->content_length = 0;
http_ctx->processed = 0;
http_ctx->body_found = 0;
return 0;
}
static
int http_send_request(struct http_client_ctx *http_ctx, const char *method,
const char *url, const char *protocol,
const char *content_type_value, const char *payload)
{
const char *content_type = "Content-Type: ";
const char *sep = "\r\n\r\n";
struct net_buf *tx;
int rc;
tx = net_nbuf_get_tx(http_ctx->tcp_ctx.net_ctx, K_FOREVER);
if (tx == NULL) {
return -ENOMEM;
}
if (!net_nbuf_append(tx, strlen(method), (uint8_t *)method,
K_FOREVER)) {
goto lb_exit;
}
if (!net_nbuf_append(tx, strlen(url), (uint8_t *)url, K_FOREVER)) {
goto lb_exit;
}
if (!net_nbuf_append(tx, strlen(protocol), (uint8_t *)protocol,
K_FOREVER)) {
goto lb_exit;
}
if (!net_nbuf_append(tx, strlen(HEADER_FIELDS),
(uint8_t *)HEADER_FIELDS, K_FOREVER)) {
goto lb_exit;
}
if (content_type_value && payload) {
char content_len_str[CON_LEN_SIZE];
if (!net_nbuf_append(tx, strlen(content_type),
(uint8_t *)content_type, K_FOREVER)) {
rc = -ENOMEM;
goto lb_exit;
}
if (!net_nbuf_append(tx, strlen(content_type_value),
(uint8_t *)content_type_value,
K_FOREVER)) {
rc = -ENOMEM;
goto lb_exit;
}
rc = snprintk(content_len_str, sizeof(content_len_str),
"\r\nContent-Length: %u\r\n\r\n",
strlen(payload));
if (rc <= 0 || rc >= sizeof(content_len_str)) {
rc = -ENOMEM;
goto lb_exit;
}
if (!net_nbuf_append(tx, strlen(content_len_str),
(uint8_t *)content_len_str, K_FOREVER)) {
rc = -ENOMEM;
goto lb_exit;
}
if (!net_nbuf_append(tx, strlen(payload), (uint8_t *)payload,
K_FOREVER)) {
rc = -ENOMEM;
goto lb_exit;
}
} else {
if (!net_nbuf_append(tx, strlen(sep), (uint8_t *)sep,
K_FOREVER)) {
rc = -ENOMEM;
goto lb_exit;
}
}
return net_context_send(tx, NULL, http_ctx->tcp_ctx.timeout,
NULL, NULL);
lb_exit:
net_buf_unref(tx);
return rc;
}
int http_send_get(struct http_client_ctx *http_ctx, const char *url)
{
return http_send_request(http_ctx, "GET ", url, " HTTP/1.1\r\n",
NULL, NULL);
}
int http_send_head(struct http_client_ctx *http_ctx, const char *url)
{
return http_send_request(http_ctx, "HEAD ", url, " HTTP/1.1\r\n",
NULL, NULL);
}
int http_send_options(struct http_client_ctx *http_ctx, const char *url,
const char *content_type_value, const char *payload)
{
return http_send_request(http_ctx, "OPTIONS ", url, " HTTP/1.1\r\n",
content_type_value, payload);
}
int http_send_post(struct http_client_ctx *http_ctx, const char *url,
const char *content_type_value, const char *payload)
{
return http_send_request(http_ctx, "POST ", url, " HTTP/1.1\r\n",
content_type_value, payload);
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _HTTP_CLIENT_H_
#define _HTTP_CLIENT_H_
#include "http_client_types.h"
int http_init(struct http_client_ctx *http_ctx);
int http_reset_ctx(struct http_client_ctx *http_ctx);
/* Reception callback executed by the IP stack */
void http_receive_cb(struct tcp_client_ctx *tcp_ctx, struct net_buf *rx);
/* Sends an HTTP GET request for URL url */
int http_send_get(struct http_client_ctx *ctx, const char *url);
/* Sends an HTTP HEAD request for URL url */
int http_send_head(struct http_client_ctx *ctx, const char *url);
/* Sends an HTTP OPTIONS request for URL url. From RFC 2616:
* If the OPTIONS request includes an entity-body (as indicated by the
* presence of Content-Length or Transfer-Encoding), then the media type
* MUST be indicated by a Content-Type field.
* Note: Transfer-Encoding is not yet supported.
*/
int http_send_options(struct http_client_ctx *http_ctx, const char *url,
const char *content_type_value, const char *payload);
/* Sends an HTTP POST request for URL url with payload as content */
int http_send_post(struct http_client_ctx *http_ctx, const char *url,
const char *content_type_value, const char *payload);
#endif

View file

@ -0,0 +1,133 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "http_client_cb.h"
#include "http_client_types.h"
#include <stdlib.h>
#include <stdio.h>
#define MAX_NUM_DIGITS 16
int on_url(struct http_parser *parser, const char *at, size_t length)
{
ARG_UNUSED(parser);
printf("URL: %.*s\n", length, at);
return 0;
}
int on_status(struct http_parser *parser, const char *at, size_t length)
{
struct http_client_ctx *ctx;
uint16_t len;
ARG_UNUSED(parser);
ctx = CONTAINER_OF(parser, struct http_client_ctx, parser);
len = min(length, sizeof(ctx->http_status) - 1);
memcpy(ctx->http_status, at, len);
ctx->http_status[len] = 0;
return 0;
}
int on_header_field(struct http_parser *parser, const char *at, size_t length)
{
char *content_len = "Content-Length";
struct http_client_ctx *ctx;
uint16_t len;
ctx = CONTAINER_OF(parser, struct http_client_ctx, parser);
len = strlen(content_len);
if (length >= len && memcmp(at, content_len, len) == 0) {
ctx->cl_present = 1;
}
printf("%.*s: ", length, at);
return 0;
}
int on_header_value(struct http_parser *parser, const char *at, size_t length)
{
struct http_client_ctx *ctx;
char str[MAX_NUM_DIGITS];
ctx = CONTAINER_OF(parser, struct http_client_ctx, parser);
if (ctx->cl_present) {
if (length <= MAX_NUM_DIGITS - 1) {
long int num;
memcpy(str, at, length);
str[length] = 0;
num = strtol(str, NULL, 10);
if (num == LONG_MIN || num == LONG_MAX) {
return -EINVAL;
}
ctx->content_length = num;
}
ctx->cl_present = 0;
}
printf("%.*s\n", length, at);
return 0;
}
int on_body(struct http_parser *parser, const char *at, size_t length)
{
struct http_client_ctx *ctx;
ctx = CONTAINER_OF(parser, struct http_client_ctx, parser);
ctx->body_found = 1;
ctx->processed += length;
return 0;
}
int on_headers_complete(struct http_parser *parser)
{
ARG_UNUSED(parser);
return 0;
}
int on_message_begin(struct http_parser *parser)
{
ARG_UNUSED(parser);
printf("\n--------- HTTP response (headers) ---------\n");
return 0;
}
int on_message_complete(struct http_parser *parser)
{
ARG_UNUSED(parser);
return 0;
}
int on_chunk_header(struct http_parser *parser)
{
ARG_UNUSED(parser);
return 0;
}
int on_chunk_complete(struct http_parser *parser)
{
ARG_UNUSED(parser);
return 0;
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _HTTP_CLIENT_CB_H_
#define _HTTP_CLIENT_CB_H_
#include <net/http_parser.h>
/*
* This are the callbacks executed by the parser. Some of them
* are only useful when parsing requests (or responses).
* Unused callbacks may be removed.
*/
int on_url(struct http_parser *parser, const char *at, size_t length);
int on_status(struct http_parser *parser, const char *at, size_t length);
int on_header_field(struct http_parser *parser, const char *at, size_t length);
int on_header_value(struct http_parser *parser, const char *at, size_t length);
int on_body(struct http_parser *parser, const char *at, size_t length);
int on_headers_complete(struct http_parser *parser);
int on_message_begin(struct http_parser *parser);
int on_message_complete(struct http_parser *parser);
int on_chunk_header(struct http_parser *parser);
int on_chunk_complete(struct http_parser *parser);
#endif

View file

@ -0,0 +1,101 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "http_client_rcv.h"
#include "http_client_types.h"
#include "config.h"
#include <net/nbuf.h>
#ifdef LINEARIZE_BUFFER
NET_BUF_POOL_DEFINE(http_pool, HTTP_POOL_BUF_CTR, HTTP_POOL_BUF_SIZE, 0, NULL);
void http_receive_cb(struct tcp_client_ctx *tcp_ctx, struct net_buf *rx)
{
struct http_client_ctx *http_ctx;
struct net_buf *data_buf = NULL;
uint16_t data_len;
uint16_t offset;
int rc;
if (!rx) {
return;
}
data_buf = net_buf_alloc(&http_pool, tcp_ctx->timeout);
if (data_buf == NULL) {
goto lb_exit;
}
data_len = min(net_nbuf_appdatalen(rx), HTTP_POOL_BUF_SIZE);
offset = net_buf_frags_len(rx) - data_len;
rc = net_nbuf_linear_copy(data_buf, rx, offset, data_len);
if (rc != 0) {
rc = -ENOMEM;
goto lb_exit;
}
http_ctx = CONTAINER_OF(tcp_ctx, struct http_client_ctx, tcp_ctx);
/* The parser's error can be catched outside, reading the
* http_errno struct member
*/
http_parser_execute(&http_ctx->parser, &http_ctx->settings,
data_buf->data, data_buf->len);
lb_exit:
net_buf_unref(data_buf);
net_buf_unref(rx);
}
#else
void http_receive_cb(struct tcp_client_ctx *tcp_ctx, struct net_buf *rx)
{
struct http_client_ctx *http_ctx;
struct net_buf *buf = rx;
uint16_t offset;
if (!rx) {
return;
}
http_ctx = CONTAINER_OF(tcp_ctx, struct http_client_ctx, tcp_ctx);
offset = net_buf_frags_len(buf) - net_nbuf_appdatalen(buf);
/* find the fragment */
while (buf && offset >= buf->len) {
offset -= buf->len;
buf = buf->frags;
}
while (buf) {
(void)http_parser_execute(&http_ctx->parser,
&http_ctx->settings,
buf->data + offset,
buf->len - offset);
/* after the first iteration, we set offset to 0 */
offset = 0;
/* The parser's error can be catched outside, reading the
* http_errno struct member
*/
if (http_ctx->parser.http_errno != HPE_OK) {
goto lb_exit;
}
buf = buf->frags;
}
lb_exit:
net_buf_unref(rx);
}
#endif

View file

@ -0,0 +1,15 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _HTTP_CLIENT_RCV_H_
#define _HTTP_CLIENT_RCV_H_
#include "tcp_client.h"
/* HTTP reception callback */
void http_receive_cb(struct tcp_client_ctx *tcp_ctx, struct net_buf *rx);
#endif

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _HTTP_CLIENT_TYPES_H_
#define _HTTP_CLIENT_TYPES_H_
#include <net/http_parser.h>
#include "tcp_client.h"
#include "config.h"
struct http_client_ctx {
struct http_parser parser;
struct http_parser_settings settings;
struct tcp_client_ctx tcp_ctx;
uint32_t content_length;
uint32_t processed;
char http_status[HTTP_STATUS_STR_SIZE];
uint8_t cl_present:1;
uint8_t body_found:1;
};
#endif

View file

@ -0,0 +1,128 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <errno.h>
#include <misc/printk.h>
#include "http_client_types.h"
#include "http_client.h"
#include "config.h"
#define POST_CONTENT_TYPE "application/x-www-form-urlencoded"
#define POST_PAYLOAD "os=ZephyrRTOS&arch="CONFIG_ARCH
#define MAX_ITERATIONS 100
static struct http_client_ctx http_ctx;
static void send_http_method(enum http_method method, const char *url,
const char *content_type, const char *payload);
void main(void)
{
int i = MAX_ITERATIONS;
int rc;
http_init(&http_ctx);
http_ctx.tcp_ctx.receive_cb = http_receive_cb;
http_ctx.tcp_ctx.timeout = HTTP_NETWORK_TIMEOUT;
rc = tcp_set_local_addr(&http_ctx.tcp_ctx, LOCAL_ADDR);
if (rc) {
printk("tcp_set_local_addr error\n");
goto lb_exit;
}
while (i-- > 0) {
send_http_method(HTTP_GET, "/index.html", NULL, NULL);
k_sleep(APP_NAP_TIME);
send_http_method(HTTP_HEAD, "/", NULL, NULL);
k_sleep(APP_NAP_TIME);
send_http_method(HTTP_OPTIONS, "/index.html", NULL, NULL);
k_sleep(APP_NAP_TIME);
send_http_method(HTTP_POST, "/post_test.php",
POST_CONTENT_TYPE, POST_PAYLOAD);
k_sleep(APP_NAP_TIME);
}
lb_exit:
printk("\nBye!\n");
}
void print_banner(enum http_method method)
{
printk("\n*******************************************\n"
"HTTP Client: %s\nConnecting to: %s port %d\n"
"Hostname: %s\nHTTP Request: %s\n",
LOCAL_ADDR, SERVER_ADDR, SERVER_PORT,
HOST_NAME, http_method_str(method));
}
static
void send_http_method(enum http_method method, const char *url,
const char *content_type, const char *payload)
{
int rc;
print_banner(method);
http_reset_ctx(&http_ctx);
rc = tcp_connect(&http_ctx.tcp_ctx, SERVER_ADDR, SERVER_PORT);
if (rc) {
printk("tcp_connect error\n");
return;
}
switch (method) {
case HTTP_GET:
rc = http_send_get(&http_ctx, url);
break;
case HTTP_POST:
rc = http_send_post(&http_ctx, url, content_type, payload);
break;
case HTTP_HEAD:
rc = http_send_head(&http_ctx, url);
break;
case HTTP_OPTIONS:
rc = http_send_options(&http_ctx, url, NULL, NULL);
break;
default:
printk("Not yet implemented\n");
goto lb_exit;
}
if (rc) {
printk("Send error\n");
goto lb_exit;
}
/* this is async, so we wait until the reception callback
* processes the server's response (if any)
*/
k_sleep(APP_NAP_TIME);
printk("\nHTTP server response status: %s\n", http_ctx.http_status);
printk("HTTP parser status: %s\n",
http_errno_description(http_ctx.parser.http_errno));
if (method == HTTP_GET) {
if (http_ctx.body_found) {
printk("HTTP body: %u bytes, expected: %u bytes\n",
http_ctx.processed, http_ctx.content_length);
} else {
printk("Error detected during HTTP msg processing\n");
}
}
lb_exit:
tcp_disconnect(&http_ctx.tcp_ctx);
}

View file

@ -0,0 +1,162 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "tcp_client.h"
#include "config.h"
#include <net/net_core.h>
#include <net/net_if.h>
#include <net/nbuf.h>
#include <misc/printk.h>
static
int set_addr(struct sockaddr *sock_addr, const char *addr, uint16_t server_port)
{
void *ptr = NULL;
int rc;
#ifdef CONFIG_NET_IPV6
net_sin6(sock_addr)->sin6_port = htons(server_port);
sock_addr->family = AF_INET6;
ptr = &(net_sin6(sock_addr)->sin6_addr);
rc = net_addr_pton(AF_INET6, addr, ptr);
#else
net_sin(sock_addr)->sin_port = htons(server_port);
sock_addr->family = AF_INET;
ptr = &(net_sin(sock_addr)->sin_addr);
rc = net_addr_pton(AF_INET, addr, ptr);
#endif
if (rc) {
printk("Invalid IP address: %s\n", addr);
}
return rc;
}
static
int if_addr_add(struct sockaddr *local_sock)
{
void *p = NULL;
#ifdef CONFIG_NET_IPV6
p = net_if_ipv6_addr_add(net_if_get_default(),
&net_sin6(local_sock)->sin6_addr,
NET_ADDR_MANUAL, 0);
#else
p = net_if_ipv4_addr_add(net_if_get_default(),
&net_sin(local_sock)->sin_addr,
NET_ADDR_MANUAL, 0);
#endif
if (p) {
return 0;
}
return -EINVAL;
}
int tcp_set_local_addr(struct tcp_client_ctx *ctx, const char *local_addr)
{
int rc;
rc = set_addr(&ctx->local_sock, local_addr, 0);
if (rc) {
printk("set_addr (local) error\n");
goto lb_exit;
}
rc = if_addr_add(&ctx->local_sock);
if (rc) {
printk("if_addr_add error\n");
}
lb_exit:
return rc;
}
static
void recv_cb(struct net_context *net_ctx, struct net_buf *rx, int status,
void *data)
{
struct tcp_client_ctx *ctx = (struct tcp_client_ctx *)data;
ARG_UNUSED(net_ctx);
if (status) {
return;
}
if (rx == NULL || net_nbuf_appdatalen(rx) == 0) {
goto lb_exit;
}
/* receive_cb must take ownership of the rx buffer */
if (ctx->receive_cb) {
ctx->receive_cb(ctx, rx);
return;
}
lb_exit:
net_buf_unref(rx);
}
int tcp_connect(struct tcp_client_ctx *ctx, const char *server_addr,
uint16_t server_port)
{
#if CONFIG_NET_IPV6
socklen_t addr_len = sizeof(struct sockaddr_in6);
sa_family_t family = AF_INET6;
#else
socklen_t addr_len = sizeof(struct sockaddr_in);
sa_family_t family = AF_INET;
#endif
struct sockaddr server_sock;
int rc;
rc = net_context_get(family, SOCK_STREAM, IPPROTO_TCP, &ctx->net_ctx);
if (rc) {
printk("net_context_get error\n");
return rc;
}
rc = net_context_bind(ctx->net_ctx, &ctx->local_sock, addr_len);
if (rc) {
printk("net_context_bind error\n");
goto lb_exit;
}
rc = set_addr(&server_sock, server_addr, server_port);
if (rc) {
printk("set_addr (server) error\n");
goto lb_exit;
}
rc = net_context_connect(ctx->net_ctx, &server_sock, addr_len, NULL,
ctx->timeout, NULL);
if (rc) {
printk("net_context_connect error\n");
goto lb_exit;
}
(void)net_context_recv(ctx->net_ctx, recv_cb, K_NO_WAIT, ctx);
return 0;
lb_exit:
net_context_put(ctx->net_ctx);
return rc;
}
int tcp_disconnect(struct tcp_client_ctx *ctx)
{
if (ctx->net_ctx) {
net_context_put(ctx->net_ctx);
ctx->net_ctx = NULL;
}
return 0;
}

View file

@ -0,0 +1,31 @@
/*
* Copyright (c) 2017 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef _TCP_CLIENT_H_
#define _TCP_CLIENT_H_
#include <net/net_context.h>
#include <net/net_ip.h>
struct tcp_client_ctx {
/* IP stack network context */
struct net_context *net_ctx;
/* Local sock address */
struct sockaddr local_sock;
/* Network timeout */
int32_t timeout;
/* User defined call back*/
void (*receive_cb)(struct tcp_client_ctx *ctx, struct net_buf *rx);
};
int tcp_set_local_addr(struct tcp_client_ctx *ctx, const char *local_addr);
int tcp_connect(struct tcp_client_ctx *ctx, const char *server_addr,
uint16_t server_port);
int tcp_disconnect(struct tcp_client_ctx *ctx);
#endif

View file

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

View file

@ -22,7 +22,7 @@ uint16_t http_strlen(const char *str)
int http_add_header(struct net_buf *tx, const char *str)
{
net_nbuf_append(tx, strlen(str), (uint8_t *)str);
net_nbuf_append(tx, strlen(str), (uint8_t *)str, K_FOREVER);
return 0;
}
@ -36,13 +36,13 @@ int http_add_chunk(struct net_buf *tx, const char *str)
str_len = http_strlen(str);
snprintf(chunk_header, sizeof(chunk_header), "%x\r\n", str_len);
net_nbuf_append(tx, strlen(chunk_header), chunk_header);
net_nbuf_append(tx, strlen(chunk_header), chunk_header, K_FOREVER);
if (str_len) {
net_nbuf_append(tx, str_len, (uint8_t *)str);
net_nbuf_append(tx, str_len, (uint8_t *)str, K_FOREVER);
}
net_nbuf_append(tx, strlen(rn), rn);
net_nbuf_append(tx, strlen(rn), rn, K_FOREVER);
return 0;
}
@ -54,7 +54,7 @@ int http_write(struct http_server_ctx *ctx, const char *http_header,
struct net_buf *tx;
int rc = -EINVAL;
tx = net_nbuf_get_tx(ctx->net_ctx);
tx = net_nbuf_get_tx(ctx->net_ctx, K_FOREVER);
printf("[%s:%d] net_nbuf_get_tx, rc: %d <%s>\n",
__func__, __LINE__, !tx, RC_STR(!tx));
if (tx == NULL) {

View file

@ -37,8 +37,8 @@ CONFIG_NET_L2_IEEE802154_RFD=y
CONFIG_NET_L2_IEEE802154_FRAGMENT=y
#CONFIG_NET_DEBUG_L2_IEEE802154_FRAGMENT=y
CONFIG_TI_CC2520=y
CONFIG_TI_CC2520_AUTO_ACK=y
CONFIG_IEEE802154_CC2520=y
CONFIG_IEEE802154_CC2520_AUTO_ACK=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1
CONFIG_NET_L2_IEEE802154_SHELL=y

View file

@ -39,7 +39,7 @@ CONFIG_NET_L2_IEEE802154_RFD=y
CONFIG_NET_L2_IEEE802154_FRAGMENT=y
#CONFIG_NET_DEBUG_L2_IEEE802154_FRAGMENT=y
CONFIG_NXP_MCR20A=y
CONFIG_IEEE802154_MCR20A=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1
CONFIG_NET_L2_IEEE802154_SHELL=y

View file

@ -15,11 +15,11 @@
#include <misc/printk.h>
#define PRINT printk
#ifdef CONFIG_TI_CC2520_DRV_NAME
#define IEEE802154_DRV_NAME CONFIG_TI_CC2520_DRV_NAME
#ifdef CONFIG_IEEE802154_CC2520_DRV_NAME
#define IEEE802154_DRV_NAME CONFIG_IEEE802154_CC2520_DRV_NAME
#endif
#ifdef CONFIG_NXP_MCR20A_DRV_NAME
#define IEEE802154_DRV_NAME CONFIG_NXP_MCR20A_DRV_NAME
#ifdef CONFIG_IEEE802154_MCR20A_DRV_NAME
#define IEEE802154_DRV_NAME CONFIG_IEEE802154_MCR20A_DRV_NAME
#endif
#ifndef CONFIG_NET_L2_IEEE802154_SHELL

View file

@ -35,5 +35,5 @@ CONFIG_NET_L2_IEEE802154_ORFD=y
CONFIG_NET_L2_IEEE802154_FRAGMENT=y
#CONFIG_NET_DEBUG_L2_IEEE802154_FRAGMENT=y
CONFIG_UPIPE_15_4=y
CONFIG_IEEE802154_UPIPE=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=4

View file

@ -26,7 +26,7 @@ static struct net_if *init_device(void)
struct net_if *iface;
struct device *dev;
dev = device_get_binding(CONFIG_UPIPE_15_4_DRV_NAME);
dev = device_get_binding(CONFIG_IEEE802154_UPIPE_DRV_NAME);
if (!dev) {
PRINT("Cannot get UPIPE device\n");
return NULL;

View file

@ -146,12 +146,12 @@ transmit(struct net_context *ctx, char buffer[], size_t len)
{
struct net_buf *send_buf;
send_buf = net_nbuf_get_tx(ctx);
send_buf = net_nbuf_get_tx(ctx, K_FOREVER);
if (!send_buf) {
return -ENOMEM;
}
if (!net_nbuf_append(send_buf, len, buffer)) {
if (!net_nbuf_append(send_buf, len, buffer, K_FOREVER)) {
return -EINVAL;
}
@ -312,7 +312,7 @@ on_context_recv(struct net_context *ctx, struct net_buf *buf,
if (cmd_len + len > sizeof(cmd_buf)) {
/* overrun cmd_buf - bail out */
NET_ERR("CMD BUFFER OVERRUN!! %lu > %lu",
NET_ERR("CMD BUFFER OVERRUN!! %zu > %zu",
cmd_len + len,
sizeof(cmd_buf));
break;

View file

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

View file

@ -8,5 +8,5 @@ CONFIG_NET_LOG=y
CONFIG_NET_UDP=y
CONFIG_NET_YAIP=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_TI_CC2520=y
CONFIG_IEEE802154_CC2520=y
CONFIG_ZOAP=y

View file

@ -100,12 +100,12 @@ static int led_get(struct zoap_resource *resource,
id = zoap_header_get_id(request);
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}
@ -167,12 +167,12 @@ static int led_post(struct zoap_resource *resource,
id = zoap_header_get_id(request);
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}
@ -245,12 +245,12 @@ static int led_put(struct zoap_resource *resource,
id = zoap_header_get_id(request);
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}
@ -307,12 +307,12 @@ static int dummy_get(struct zoap_resource *resource,
id = zoap_header_get_id(request);
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}

View file

@ -66,13 +66,13 @@ int udp_tx(void *context, const unsigned char *buf, size_t size)
udp_ctx = ctx->net_ctx;
send_buf = net_nbuf_get_tx(udp_ctx);
send_buf = net_nbuf_get_tx(udp_ctx, K_FOREVER);
if (!send_buf) {
printk("cannot create buf\n");
return -EIO;
}
rc = net_nbuf_append(send_buf, size, (uint8_t *) buf);
rc = net_nbuf_append(send_buf, size, (uint8_t *) buf, K_FOREVER);
if (!rc) {
printk("cannot write buf\n");
return -EIO;

View file

@ -60,13 +60,13 @@ int udp_tx(void *context, const unsigned char *buf, size_t size)
net_ctx = ctx->net_ctx;
send_buf = net_nbuf_get_tx(net_ctx);
send_buf = net_nbuf_get_tx(net_ctx, K_FOREVER);
if (!send_buf) {
printk("cannot create buf\n");
return -EIO;
}
rc = net_nbuf_append(send_buf, size, (uint8_t *) buf);
rc = net_nbuf_append(send_buf, size, (uint8_t *) buf, K_FOREVER);
if (!rc) {
printk("cannot write buf\n");
return -EIO;

View file

@ -4,7 +4,7 @@
# SPDX-License-Identifier: Apache-2.0
#
BOARD = galileo
CONF_FILE = prj_galileo.conf
BOARD ?= galileo
CONF_FILE ?= prj_$(BOARD).conf
include $(ZEPHYR_BASE)/Makefile.inc

View file

@ -0,0 +1,34 @@
CONFIG_SYS_LOG=y
CONFIG_NET_LOG=y
CONFIG_INIT_STACKS=y
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NETWORKING=y
CONFIG_NET_ARP=y
CONFIG_NET_L2_ETHERNET=y
CONFIG_NET_IPV4=y
CONFIG_NET_IPV6=n
CONFIG_NET_TCP=y
CONFIG_NET_BUF=y
CONFIG_NET_IFACE_UNICAST_IPV4_ADDR_COUNT=3
CONFIG_NET_NBUF_RX_COUNT=4
CONFIG_NET_NBUF_TX_COUNT=4
CONFIG_NET_NBUF_DATA_COUNT=12
CONFIG_ETH_ENC28J60=y
CONFIG_ETH_ENC28J60_0=y
CONFIG_ETH_ENC28J60_0_SPI_PORT_NAME="SPI_1"
CONFIG_ETH_ENC28J60_0_SPI_BUS_FREQ=2
CONFIG_ETH_ENC28J60_0_MAC3=0x2D
CONFIG_ETH_ENC28J60_0_MAC4=0x30
CONFIG_ETH_ENC28J60_0_MAC5=0x32
CONFIG_SPI=y
CONFIG_SPI_CS_GPIO=y
CONFIG_SPI_1_CS_GPIO_PORT="GPIO_0"
CONFIG_SPI_1_CS_GPIO_PIN=0
CONFIG_MBEDTLS=y
CONFIG_MBEDTLS_BUILTIN=y
CONFIG_MBEDTLS_CFG_FILE="config-ccm-psk-tls1_2.h"

View file

@ -54,13 +54,13 @@ int tcp_tx(void *context, const unsigned char *buf, size_t size)
tcp_ctx = ctx->net_ctx;
send_buf = net_nbuf_get_tx(tcp_ctx);
send_buf = net_nbuf_get_tx(tcp_ctx, K_FOREVER);
if (!send_buf) {
printk("cannot create buf\n");
return -EIO;
}
rc = net_nbuf_append(send_buf, size, (uint8_t *) buf);
rc = net_nbuf_append(send_buf, size, (uint8_t *) buf, K_FOREVER);
if (!rc) {
printk("cannot write buf\n");
return -EIO;

View file

@ -10,7 +10,7 @@ CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_UART_LINE_CTRL=y
CONFIG_TI_CC2520_RAW=y
CONFIG_IEEE802154_CC2520_RAW=y
CONFIG_NET_BUF=y
CONFIG_NETWORKING=y

View file

@ -1,3 +1,3 @@
ccflags-$(CONFIG_TI_CC2520_RAW) += -I${ZEPHYR_BASE}/subsys/net/ip
ccflags-$(CONFIG_IEEE802154_CC2520_RAW) += -I${ZEPHYR_BASE}/subsys/net/ip
obj-y += main.o

View file

@ -143,12 +143,12 @@ static int slip_process_byte(unsigned char c)
#endif
if (!pkt_curr) {
pkt_curr = net_nbuf_get_reserve_rx(0);
pkt_curr = net_nbuf_get_reserve_rx(0, K_NO_WAIT);
if (!pkt_curr) {
SYS_LOG_ERR("No more buffers");
return 0;
}
buf = net_nbuf_get_reserve_data(0);
buf = net_nbuf_get_reserve_data(0, K_NO_WAIT);
if (!buf) {
SYS_LOG_ERR("No more buffers");
net_nbuf_unref(pkt_curr);
@ -220,13 +220,13 @@ static void send_data(uint8_t *cfg, uint8_t *data, size_t len)
{
struct net_buf *buf, *pkt;
pkt = net_nbuf_get_reserve_rx(0);
pkt = net_nbuf_get_reserve_rx(0, K_NO_WAIT);
if (!pkt) {
SYS_LOG_DBG("No buf available");
return;
}
buf = net_nbuf_get_reserve_data(0);
buf = net_nbuf_get_reserve_data(0, K_NO_WAIT);
if (!buf) {
SYS_LOG_DBG("No fragment available");
net_nbuf_unref(pkt);
@ -505,7 +505,7 @@ static bool init_ieee802154(void)
SYS_LOG_INF("Initialize ieee802.15.4");
ieee802154_dev = device_get_binding(CONFIG_TI_CC2520_DRV_NAME);
ieee802154_dev = device_get_binding(CONFIG_IEEE802154_CC2520_DRV_NAME);
if (!ieee802154_dev) {
SYS_LOG_ERR("Cannot get CC250 device");
return false;

View file

@ -15,8 +15,8 @@ CONFIG_NET_NBUF_DATA_SIZE=128
CONFIG_NET_L2_IEEE802154=y
#CONFIG_TI_CC2520=y
CONFIG_TI_CC2520_RAW=y
#CONFIG_IEEE802154_CC2520=y
CONFIG_IEEE802154_CC2520_RAW=y
CONFIG_SYS_LOG=y
CONFIG_SYS_LOG_IEEE802154_DRIVER_LEVEL=1

View file

@ -1,9 +1,9 @@
ccflags-y += -I${ZEPHYR_BASE}/usb/include -I${ZEPHYR_BASE}/include/drivers/usb -I${ZEPHYR_BASE}/include/usb/
ccflags-$(CONFIG_TI_CC2520_LEGACY) += -I${ZEPHYR_BASE}/net/ip/contiki/os
ccflags-$(CONFIG_TI_CC2520_LEGACY) += -I${ZEPHYR_BASE}/net/ip/contiki
ccflags-$(CONFIG_TI_CC2520_LEGACY) += -I${ZEPHYR_BASE}/net/ip
ccflags-$(CONFIG_IEEE802154_CC2520_LEGACY) += -I${ZEPHYR_BASE}/net/ip/contiki/os
ccflags-$(CONFIG_IEEE802154_CC2520_LEGACY) += -I${ZEPHYR_BASE}/net/ip/contiki
ccflags-$(CONFIG_IEEE802154_CC2520_LEGACY) += -I${ZEPHYR_BASE}/net/ip
ccflags-$(CONFIG_TI_CC2520_RAW) += -I${ZEPHYR_BASE}/subsys/net/ip
ccflags-$(CONFIG_IEEE802154_CC2520_RAW) += -I${ZEPHYR_BASE}/subsys/net/ip
obj-y += wpanusb.o

View file

@ -382,8 +382,17 @@ static int wpanusb_vendor_handler(struct usb_setup_packet *setup,
{
struct net_buf *pkt, *buf;
pkt = net_nbuf_get_reserve_tx(0);
buf = net_nbuf_get_reserve_data(0);
pkt = net_nbuf_get_reserve_tx(0, K_NO_WAIT);
if (!pkt) {
return -ENOMEM;
}
buf = net_nbuf_get_reserve_data(0, K_NO_WAIT);
if (!buf) {
net_nbuf_unref(pkt);
return -ENOMEM;
}
net_buf_frag_insert(pkt, buf);
net_buf_add_u8(buf, setup->bRequest);
@ -587,7 +596,7 @@ void main(void)
#if DYNAMIC_REGISTER
ieee802154_dev = ieee802154_register_raw();
#else
ieee802154_dev = device_get_binding(CONFIG_TI_CC2520_DRV_NAME);
ieee802154_dev = device_get_binding(CONFIG_IEEE802154_CC2520_DRV_NAME);
if (!ieee802154_dev) {
SYS_LOG_ERR("Cannot get CC250 device");
return;

View file

@ -173,13 +173,13 @@ static void event_iface_up(struct net_mgmt_event_callback *cb,
k_delayed_work_init(&retransmit_work, retransmit_request);
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
printk("Unable to get TX buffer, not enough memory.\n");
return;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
printk("Unable to get DATA buffer, not enough memory.\n");
return;

View file

@ -8,7 +8,7 @@ CONFIG_NET_LOG=y
CONFIG_NET_UDP=y
CONFIG_NET_YAIP=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_TI_CC2520=y
CONFIG_IEEE802154_CC2520=y
CONFIG_ZOAP=y
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
CONFIG_NET_SAMPLES_MY_IPV6_ADDR="2001:db8::1"

View file

@ -64,12 +64,12 @@ static int test_del(struct zoap_resource *resource,
NET_INFO("type: %u code %u id %u\n", type, code, id);
NET_INFO("*******\n");
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}
@ -123,12 +123,12 @@ static int test_put(struct zoap_resource *resource,
NET_INFO("type: %u code %u id %u\n", type, code, id);
NET_INFO("*******\n");
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}
@ -188,12 +188,12 @@ static int test_post(struct zoap_resource *resource,
NET_INFO("type: %u code %u id %u\n", type, code, id);
NET_INFO("*******\n");
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}
@ -257,12 +257,12 @@ static int location_query_post(struct zoap_resource *resource,
NET_INFO("type: %u code %u id %u\n", type, code, id);
NET_INFO("*******\n");
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}
@ -317,12 +317,12 @@ static int piggyback_get(struct zoap_resource *resource,
NET_INFO("type: %u code %u id %u\n", type, code, id);
NET_INFO("*******\n");
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}
@ -419,12 +419,12 @@ static int query_get(struct zoap_resource *resource,
NET_INFO("*******\n");
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}
@ -494,12 +494,12 @@ static int separate_get(struct zoap_resource *resource,
goto done;
}
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}
@ -525,12 +525,12 @@ static int separate_get(struct zoap_resource *resource,
}
done:
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}
@ -614,12 +614,12 @@ static int large_get(struct zoap_resource *resource,
NET_INFO("type: %u code %u id %u\n", type, code, id);
NET_INFO("*******\n");
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}
@ -712,12 +712,12 @@ static int large_update_put(struct zoap_resource *resource,
NET_INFO("type: %u code %u id %u\n", type, code, id);
NET_INFO("*******\n");
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
return -ENOMEM;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
return -ENOMEM;
}

View file

@ -26,7 +26,7 @@ CONFIG_NET_L2_IEEE802154_ORFD_PAN_ID=0xabcd
CONFIG_NET_L2_IEEE802154_ORFD_CHANNEL=26
CONFIG_NET_L2_IEEE802154_FRAGMENT=y
CONFIG_TI_CC2520=y
CONFIG_IEEE802154_CC2520=y
CONFIG_NET_6LO=y
CONFIG_NET_6LO_CONTEXT=y

View file

@ -54,23 +54,24 @@ void zperf_tcp_upload(struct net_context *ctx,
loop_time = k_cycle_get_32();
last_loop_time = loop_time;
buf = net_nbuf_get_tx(ctx);
buf = net_nbuf_get_tx(ctx, K_FOREVER);
if (!buf) {
printk(TAG "ERROR! Failed to retrieve a buffer\n");
continue;
break;
}
frag = net_nbuf_get_data(ctx);
frag = net_nbuf_get_data(ctx, K_FOREVER);
if (!frag) {
net_nbuf_unref(buf);
printk(TAG "ERROR! Failed to retrieve a fragment\n");
continue;
break;
}
net_buf_frag_add(buf, frag);
/* Fill in the TCP payload */
st = net_nbuf_append(buf, sizeof(sample_packet),
sample_packet);
sample_packet, K_FOREVER);
if (!st) {
printk(TAG "ERROR! Failed to fill packet\n");

View file

@ -67,8 +67,8 @@ static inline struct net_buf *build_reply_buf(struct net_context *context,
printk(TAG "received %d bytes\n", net_nbuf_appdatalen(buf));
reply_buf = net_nbuf_get_tx(context);
frag = net_nbuf_get_data(context);
reply_buf = net_nbuf_get_tx(context, K_FOREVER);
frag = net_nbuf_get_data(context, K_FOREVER);
net_buf_frag_add(reply_buf, frag);

View file

@ -86,13 +86,13 @@ static inline void zperf_upload_fin(struct net_context *context,
struct net_buf *buf, *frag;
bool status;
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
printk(TAG "ERROR! Failed to retrieve a buffer\n");
continue;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
printk(TAG "ERROR! Failed to retrieve a fragment\n");
continue;
@ -107,7 +107,7 @@ static inline void zperf_upload_fin(struct net_context *context,
USEC_PER_SEC);
status = net_nbuf_append(buf, sizeof(datagram),
(uint8_t *)&datagram);
(uint8_t *)&datagram, K_FOREVER);
if (!status) {
printk(TAG "ERROR! Cannot append datagram data\n");
break;
@ -121,7 +121,8 @@ static inline void zperf_upload_fin(struct net_context *context,
frag = net_nbuf_write(buf, net_buf_frag_last(buf),
sizeof(struct zperf_udp_datagram),
&pos, size, sample_packet);
&pos, size, sample_packet,
K_FOREVER);
}
/* Send the packet */
@ -229,13 +230,13 @@ void zperf_udp_upload(struct net_context *context,
last_loop_time = loop_time;
buf = net_nbuf_get_tx(context);
buf = net_nbuf_get_tx(context, K_FOREVER);
if (!buf) {
printk(TAG "ERROR! Failed to retrieve a buffer\n");
continue;
}
frag = net_nbuf_get_data(context);
frag = net_nbuf_get_data(context, K_FOREVER);
if (!frag) {
printk(TAG "ERROR! Failed to retrieve a frag\n");
continue;
@ -250,7 +251,7 @@ void zperf_udp_upload(struct net_context *context,
htonl(HW_CYCLES_TO_USEC(loop_time) % USEC_PER_SEC);
status = net_nbuf_append(buf, sizeof(datagram),
(uint8_t *)&datagram);
(uint8_t *)&datagram, K_FOREVER);
if (!status) {
printk(TAG "ERROR! Cannot append datagram data\n");
break;
@ -264,7 +265,8 @@ void zperf_udp_upload(struct net_context *context,
frag = net_nbuf_write(buf, net_buf_frag_last(buf),
sizeof(struct zperf_udp_datagram),
&pos, size, sample_packet);
&pos, size, sample_packet,
K_FOREVER);
}
/* Send the packet */

View file

@ -299,3 +299,19 @@ Here are some generic guidelines for network testing.
for details.
This entry should be split more to include various
network testing frameworks.
CAN
===
CAN (Controller Area Network) is a networking technology
which is used in automation, embedded devices, and
automotive fields.
- Implement CAN support
Priority: Medium
Complexity: C8
This is a placeholder for CAN support and should be
split into smaller pieces.

View file

@ -712,10 +712,7 @@ static inline bool compress_IPHC_header(struct net_buf *buf,
return false;
}
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf));
if (!frag) {
return false;
}
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf), K_FOREVER);
IPHC[offset++] = NET_6LO_DISPATCH_IPHC;
IPHC[offset++] = 0;
@ -787,7 +784,7 @@ end:
net_buf_frag_insert(buf, frag);
/* Compact the fragments, so that gaps will be filled */
net_nbuf_compact(buf->frags);
net_nbuf_compact(buf);
if (fragment) {
return fragment(buf, compressed - offset);
@ -1287,10 +1284,7 @@ static inline bool uncompress_IPHC_header(struct net_buf *buf)
#endif
}
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf));
if (!frag) {
return false;
}
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf), K_FOREVER);
ipv6 = (struct net_ipv6_hdr *)(frag->data);
@ -1378,7 +1372,7 @@ end:
/* Insert the fragment (this one holds uncompressed headers) */
net_buf_frag_insert(buf, frag);
net_nbuf_compact(buf->frags);
net_nbuf_compact(buf);
/* Set IPv6 header and UDP (if next header is) length */
len = net_buf_frags_len(buf) - NET_IPV6H_LEN;
@ -1406,10 +1400,7 @@ static inline bool compress_ipv6_header(struct net_buf *buf,
{
struct net_buf *frag;
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf));
if (!frag) {
return false;
}
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf), K_FOREVER);
frag->data[0] = NET_6LO_DISPATCH_IPV6;
net_buf_add(frag, 1);
@ -1417,7 +1408,7 @@ static inline bool compress_ipv6_header(struct net_buf *buf,
net_buf_frag_insert(buf, frag);
/* Compact the fragments, so that gaps will be filled */
buf->frags = net_nbuf_compact(buf->frags);
net_nbuf_compact(buf);
if (fragment) {
return fragment(buf, -1);

View file

@ -452,7 +452,7 @@ int net_conn_register(enum net_ip_protocol proto,
if (remote_addr) {
if (remote_addr->family != AF_INET &&
remote_addr->family != AF_INET6) {
NET_DBG("Remote address family not set.");
NET_ERR("Remote address family not set.");
return -EINVAL;
}
@ -488,7 +488,7 @@ int net_conn_register(enum net_ip_protocol proto,
if (local_addr) {
if (local_addr->family != AF_INET &&
local_addr->family != AF_INET6) {
NET_DBG("Local address family not set.");
NET_ERR("Local address family not set.");
return -EINVAL;
}
@ -522,7 +522,7 @@ int net_conn_register(enum net_ip_protocol proto,
if (remote_addr && local_addr) {
if (remote_addr->family != local_addr->family) {
NET_DBG("Address families different.");
NET_ERR("Address families different.");
return -EINVAL;
}
}

View file

@ -132,7 +132,8 @@ static inline void unset_dhcpv4_on_iface(struct net_if *iface)
/* Add magic cookie to DCHPv4 messages */
static inline bool add_cookie(struct net_buf *buf)
{
return net_nbuf_append(buf, sizeof(magic_cookie), magic_cookie);
return net_nbuf_append(buf, sizeof(magic_cookie), magic_cookie,
K_FOREVER);
}
/* Add DHCPv4 message type */
@ -140,7 +141,7 @@ static inline bool add_msg_type(struct net_buf *buf, uint8_t type)
{
uint8_t data[3] = { DHCPV4_OPTIONS_MSG_TYPE, 1, type };
return net_nbuf_append(buf, sizeof(data), data);
return net_nbuf_append(buf, sizeof(data), data, K_FOREVER);
}
/* Add DHCPv4 minimum required options for server to reply.
@ -154,7 +155,7 @@ static inline bool add_req_options(struct net_buf *buf)
DHCPV4_OPTIONS_ROUTER,
DHCPV4_OPTIONS_DNS_SERVER };
return net_nbuf_append(buf, sizeof(data), data);
return net_nbuf_append(buf, sizeof(data), data, K_FOREVER);
}
static inline bool add_server_id(struct net_buf *buf)
@ -163,16 +164,17 @@ static inline bool add_server_id(struct net_buf *buf)
uint8_t data;
data = DHCPV4_OPTIONS_SERVER_ID;
if (!net_nbuf_append(buf, 1, &data)) {
if (!net_nbuf_append(buf, 1, &data, K_FOREVER)) {
return false;
}
data = 4;
if (!net_nbuf_append(buf, 1, &data)) {
if (!net_nbuf_append(buf, 1, &data, K_FOREVER)) {
return false;
}
if (!net_nbuf_append(buf, 4, iface->dhcpv4.server_id.s4_addr)) {
if (!net_nbuf_append(buf, 4, iface->dhcpv4.server_id.s4_addr,
K_FOREVER)) {
return false;
}
@ -185,16 +187,17 @@ static inline bool add_req_ipaddr(struct net_buf *buf)
uint8_t data;
data = DHCPV4_OPTIONS_REQ_IPADDR;
if (!net_nbuf_append(buf, 1, &data)) {
if (!net_nbuf_append(buf, 1, &data, K_FOREVER)) {
return false;
}
data = 4;
if (!net_nbuf_append(buf, 1, &data)) {
if (!net_nbuf_append(buf, 1, &data, K_FOREVER)) {
return false;
}
if (!net_nbuf_append(buf, 4, iface->dhcpv4.requested_ip.s4_addr)) {
if (!net_nbuf_append(buf, 4, iface->dhcpv4.requested_ip.s4_addr,
K_FOREVER)) {
return false;
}
@ -206,7 +209,7 @@ static inline bool add_end(struct net_buf *buf)
{
uint8_t data = DHCPV4_OPTIONS_END;
return net_nbuf_append(buf, 1, &data);
return net_nbuf_append(buf, 1, &data, K_FOREVER);
}
/* File is empty ATM */
@ -216,7 +219,7 @@ static inline bool add_file(struct net_buf *buf)
uint8_t data = 0;
while (len-- > 0) {
if (!net_nbuf_append(buf, 1, &data)) {
if (!net_nbuf_append(buf, 1, &data, K_FOREVER)) {
return false;
}
}
@ -231,7 +234,7 @@ static inline bool add_sname(struct net_buf *buf)
uint8_t data = 0;
while (len-- > 0) {
if (!net_nbuf_append(buf, 1, &data)) {
if (!net_nbuf_append(buf, 1, &data, K_FOREVER)) {
return false;
}
}
@ -278,15 +281,10 @@ static struct net_buf *prepare_message(struct net_if *iface, uint8_t type)
struct net_buf *frag;
struct dhcp_msg *msg;
buf = net_nbuf_get_reserve_tx(0);
if (!buf) {
return NULL;
}
buf = net_nbuf_get_reserve_tx(0, K_FOREVER);
frag = net_nbuf_get_reserve_data(net_if_get_ll_reserve(iface, NULL));
if (!frag) {
goto fail;
}
frag = net_nbuf_get_reserve_data(net_if_get_ll_reserve(iface, NULL),
K_FOREVER);
net_nbuf_set_ll_reserve(buf, net_buf_headroom(frag));
net_nbuf_set_iface(buf, iface);

View file

@ -106,7 +106,7 @@ int net_icmpv4_send_echo_request(struct net_if *iface,
/* Take the first address of the network interface */
src = &iface->ipv4.unicast[0].address.in_addr;
buf = net_nbuf_get_reserve_tx(0);
buf = net_nbuf_get_reserve_tx(0, K_FOREVER);
/* We cast to IPv6 address but that should be ok in this case
* as IPv4 cannot be used in 802.15.4 where it is the reserve
@ -115,7 +115,7 @@ int net_icmpv4_send_echo_request(struct net_if *iface,
reserve = net_if_get_ll_reserve(iface,
(const struct in6_addr *)dst);
frag = net_nbuf_get_reserve_data(reserve);
frag = net_nbuf_get_reserve_data(reserve, K_FOREVER);
net_buf_frag_add(buf, frag);
net_nbuf_set_family(buf, AF_INET);
@ -192,7 +192,7 @@ int net_icmpv4_send_error(struct net_buf *orig, uint8_t type, uint8_t code)
iface = net_nbuf_iface(orig);
buf = net_nbuf_get_reserve_tx(0);
buf = net_nbuf_get_reserve_tx(0, K_FOREVER);
reserve = sizeof(struct net_ipv4_hdr) + sizeof(struct net_icmp_hdr) +
NET_ICMPV4_UNUSED_LEN;
@ -223,7 +223,7 @@ int net_icmpv4_send_error(struct net_buf *orig, uint8_t type, uint8_t code)
/* We only copy minimal IPv4 + next header from original message.
* This is so that the memory pressure is minimized.
*/
frag = net_nbuf_copy(orig->frags, extra_len, reserve);
frag = net_nbuf_copy(orig->frags, extra_len, reserve, K_FOREVER);
if (!frag) {
goto drop;
}

View file

@ -78,7 +78,7 @@ static enum net_verdict handle_echo_request(struct net_buf *orig)
iface = net_nbuf_iface(orig);
buf = net_nbuf_get_reserve_tx(0);
buf = net_nbuf_get_reserve_tx(0, K_FOREVER);
/* We need to remember the original location of source and destination
* addresses as the net_nbuf_copy() will mangle the original buffer.
@ -96,7 +96,7 @@ static enum net_verdict handle_echo_request(struct net_buf *orig)
payload_len = sys_get_be16(NET_IPV6_BUF(orig)->len) -
sizeof(NET_ICMPH_LEN) - NET_ICMPV6_UNUSED_LEN;
frag = net_nbuf_copy_all(orig->frags, 0);
frag = net_nbuf_copy_all(orig->frags, 0, K_FOREVER);
if (!frag) {
goto drop;
}
@ -181,7 +181,7 @@ int net_icmpv6_send_error(struct net_buf *orig, uint8_t type, uint8_t code,
iface = net_nbuf_iface(orig);
buf = net_nbuf_get_reserve_tx(0);
buf = net_nbuf_get_reserve_tx(0, K_FOREVER);
/* We need to remember the original location of source and destination
* addresses as the net_nbuf_copy() will mangle the original buffer.
@ -215,7 +215,7 @@ int net_icmpv6_send_error(struct net_buf *orig, uint8_t type, uint8_t code,
/* We only copy minimal IPv6 + next header from original message.
* This is so that the memory pressure is minimized.
*/
frag = net_nbuf_copy(orig->frags, extra_len, reserve);
frag = net_nbuf_copy(orig->frags, extra_len, reserve, K_FOREVER);
if (!frag) {
goto drop;
}
@ -294,7 +294,7 @@ int net_icmpv6_send_echo_request(struct net_if *iface,
src = net_if_ipv6_select_src_addr(iface, dst);
buf = net_nbuf_get_reserve_tx(0);
buf = net_nbuf_get_reserve_tx(0, K_FOREVER);
reserve = net_if_get_ll_reserve(iface, dst);

View file

@ -30,7 +30,7 @@ struct net_buf *net_ipv4_create_raw(struct net_buf *buf,
{
struct net_buf *header;
header = net_nbuf_get_reserve_data(reserve);
header = net_nbuf_get_reserve_data(reserve, K_FOREVER);
net_buf_frag_insert(buf, header);

View file

@ -292,7 +292,7 @@ struct net_buf *net_ipv6_create_raw(struct net_buf *buf,
{
struct net_buf *header;
header = net_nbuf_get_reserve_data(reserve);
header = net_nbuf_get_reserve_data(reserve, K_FOREVER);
net_buf_frag_insert(buf, header);
@ -520,7 +520,7 @@ static struct net_buf *update_ll_reserve(struct net_buf *buf,
while (orig_frag) {
if (!room_len) {
frag = net_nbuf_get_reserve_data(reserve);
frag = net_nbuf_get_reserve_data(reserve, K_FOREVER);
net_buf_frag_add(buf, frag);
@ -874,11 +874,12 @@ int net_ipv6_send_na(struct net_if *iface, struct in6_addr *src,
struct net_buf *buf, *frag;
uint8_t llao_len;
buf = net_nbuf_get_reserve_tx(0);
buf = net_nbuf_get_reserve_tx(0, K_FOREVER);
NET_ASSERT_INFO(buf, "Out of TX buffers");
frag = net_nbuf_get_reserve_data(net_if_get_ll_reserve(iface, dst));
frag = net_nbuf_get_reserve_data(net_if_get_ll_reserve(iface, dst),
K_FOREVER);
NET_ASSERT_INFO(frag, "Out of DATA buffers");
@ -1349,11 +1350,12 @@ send_pending:
cached_lladdr->len));
if (net_send_data(pending) < 0) {
net_nbuf_unref(pending);
nbr_clear_ns_pending(net_ipv6_nbr_data(nbr));
} else {
net_ipv6_nbr_data(nbr)->pending = NULL;
}
net_nbuf_unref(pending);
}
return true;
@ -1452,6 +1454,8 @@ static enum net_verdict handle_na_input(struct net_buf *buf)
goto drop;
}
net_nbuf_unref(buf);
net_stats_update_ipv6_nd_sent();
return NET_OK;
@ -1473,11 +1477,12 @@ int net_ipv6_send_ns(struct net_if *iface,
struct net_nbr *nbr;
uint8_t llao_len;
buf = net_nbuf_get_reserve_tx(0);
buf = net_nbuf_get_reserve_tx(0, K_FOREVER);
NET_ASSERT_INFO(buf, "Out of TX buffers");
frag = net_nbuf_get_reserve_data(net_if_get_ll_reserve(iface, dst));
frag = net_nbuf_get_reserve_data(net_if_get_ll_reserve(iface, dst),
K_FOREVER);
NET_ASSERT_INFO(frag, "Out of DATA buffers");
@ -1608,10 +1613,11 @@ int net_ipv6_send_rs(struct net_if *iface)
bool unspec_src;
uint8_t llao_len = 0;
buf = net_nbuf_get_reserve_tx(0);
buf = net_nbuf_get_reserve_tx(0, K_FOREVER);
frag = net_nbuf_get_reserve_data(
net_if_get_ll_reserve(iface, &NET_IPV6_BUF(buf)->dst));
net_if_get_ll_reserve(iface, &NET_IPV6_BUF(buf)->dst),
K_FOREVER);
net_buf_frag_add(buf, frag);

View file

@ -107,12 +107,13 @@ static inline struct net_buf *prepare_arp(struct net_if *iface,
struct net_eth_hdr *eth;
struct in_addr *my_addr;
buf = net_nbuf_get_reserve_tx(0);
buf = net_nbuf_get_reserve_tx(0, K_FOREVER);
if (!buf) {
goto fail;
}
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr));
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr),
K_FOREVER);
if (!frag) {
goto fail;
}
@ -202,9 +203,12 @@ struct net_buf *net_arp_prepare(struct net_buf *buf)
net_nbuf_set_ll_reserve(buf, sizeof(struct net_eth_hdr));
header = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr));
header = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr),
K_FOREVER);
hdr = (struct net_eth_hdr *)(header->data -
net_nbuf_ll_reserve(buf));
hdr = (struct net_eth_hdr *)net_nbuf_ll(header);
hdr->type = htons(NET_ETH_PTYPE_IP);
ll = net_nbuf_ll_dst(buf);
@ -221,7 +225,7 @@ struct net_buf *net_arp_prepare(struct net_buf *buf)
net_buf_frag_insert(buf, header);
buf = net_nbuf_compact(buf);
net_nbuf_compact(buf);
}
hdr = (struct net_eth_hdr *)net_nbuf_ll(buf);
@ -371,12 +375,13 @@ static inline struct net_buf *prepare_arp_reply(struct net_if *iface,
struct net_arp_hdr *hdr, *query;
struct net_eth_hdr *eth, *eth_query;
buf = net_nbuf_get_reserve_tx(0);
buf = net_nbuf_get_reserve_tx(0, K_FOREVER);
if (!buf) {
goto fail;
}
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr));
frag = net_nbuf_get_reserve_data(sizeof(struct net_eth_hdr),
K_FOREVER);
if (!frag) {
goto fail;
}

View file

@ -191,7 +191,7 @@ static void ipsp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
net_buf_frags_len(buf));
/* Get buffer for bearer / protocol related data */
nbuf = net_nbuf_get_reserve_rx(0);
nbuf = net_nbuf_get_reserve_rx(0, K_FOREVER);
/* Set destination address */
net_nbuf_ll_dst(nbuf)->addr = ctxt->src.val;
@ -216,7 +216,7 @@ static struct net_buf *ipsp_alloc_buf(struct bt_l2cap_chan *chan)
{
NET_DBG("Channel %p requires buffer", chan);
return net_nbuf_get_reserve_data(0);
return net_nbuf_get_reserve_data(0, K_FOREVER);
}
static struct bt_l2cap_chan_ops ipsp_ops = {

View file

@ -92,12 +92,12 @@ static inline void ieee802154_acknowledge(struct net_if *iface,
return;
}
buf = net_nbuf_get_reserve_tx(0);
buf = net_nbuf_get_reserve_tx(0, K_FOREVER);
if (!buf) {
return;
}
frag = net_nbuf_get_reserve_data(IEEE802154_ACK_PKT_LENGTH);
frag = net_nbuf_get_reserve_data(IEEE802154_ACK_PKT_LENGTH, K_FOREVER);
net_buf_frag_insert(buf, frag);
net_nbuf_set_ll_reserve(buf, net_buf_headroom(frag));

View file

@ -78,6 +78,28 @@ static struct frag_cache cache[REASS_CACHE_SIZE];
* +-+-+-+-+-+-+-+-+
*/
static inline struct net_buf *prepare_new_fragment(struct net_buf *buf,
uint8_t offset)
{
struct net_buf *frag;
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf), K_FOREVER);
if (!frag) {
return NULL;
}
/* Reserve space for fragmentation header */
if (!offset) {
net_buf_add(frag, NET_6LO_FRAG1_HDR_LEN);
} else {
net_buf_add(frag, NET_6LO_FRAGN_HDR_LEN);
}
net_buf_frag_add(buf, frag);
return frag;
}
static inline void set_datagram_size(uint8_t *ptr, uint16_t size)
{
ptr[0] |= ((size & 0x7FF) >> 8);
@ -126,28 +148,43 @@ static inline uint8_t calc_max_payload(struct net_buf *buf,
static inline uint8_t move_frag_data(struct net_buf *frag,
struct net_buf *next,
uint8_t max, uint8_t moved,
uint8_t offset,
int hdr_diff)
uint8_t max,
bool first,
int hdr_diff,
uint8_t *room_left)
{
uint8_t remaining = max - moved;
uint8_t room;
uint8_t move;
uint8_t occupied;
if (!offset) {
remaining -= hdr_diff;
/* First fragment */
if (first) {
occupied = frag->len - NET_6LO_FRAG1_HDR_LEN;
} else {
occupied = frag->len - NET_6LO_FRAGN_HDR_LEN;
}
/* Calculate remaining space for data to move */
move = next->len > remaining ? remaining : next->len;
/* Remaining room for data */
room = max - occupied;
if (first) {
room -= hdr_diff;
}
/* Calculate remaining room space for data to move */
move = next->len > room ? room : next->len;
memmove(frag->data + frag->len, next->data, move);
net_buf_add(frag, move);
/* Room left in current fragment */
*room_left = room - move;
return move;
}
static inline uint8_t compact_frag(struct net_buf *frag, uint8_t moved)
static inline void compact_frag(struct net_buf *frag, uint8_t moved)
{
uint8_t remaining = frag->len - moved;
@ -155,13 +192,10 @@ static inline uint8_t compact_frag(struct net_buf *frag, uint8_t moved)
* (leave space for header).
*/
if (remaining) {
memmove(frag->data + NET_6LO_FRAGN_HDR_LEN,
frag->data + moved, remaining);
memmove(frag->data, frag->data + moved, remaining);
}
frag->len = NET_6LO_FRAGN_HDR_LEN + remaining;
return remaining;
frag->len = remaining;
}
/**
@ -194,9 +228,10 @@ bool ieee802154_fragment(struct net_buf *buf, int hdr_diff)
uint16_t processed;
uint16_t offset;
uint16_t size;
uint8_t moved;
uint8_t room;
uint8_t move;
uint8_t max;
bool first;
if (!buf || !buf->frags) {
return false;
@ -207,65 +242,55 @@ bool ieee802154_fragment(struct net_buf *buf, int hdr_diff)
return true;
}
datagram_tag++;
/* Datagram_size: total length before compression */
size = net_buf_frags_len(buf) + hdr_diff;
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf));
if (!frag) {
return false;
}
/* Reserve space for fragmentation header */
net_buf_add(frag, NET_6LO_FRAG1_HDR_LEN);
net_buf_frag_insert(buf, frag);
room = 0;
offset = 0;
moved = 0;
processed = 0;
next = frag->frags;
first = true;
datagram_tag++;
next = buf->frags;
buf->frags = NULL;
/* First fragment has compressed header, but SIZE and OFFSET
* values in fragmentation header are based on uncompressed
* IP packet.
*/
while (1) {
/* Set fragmentation header in the beginning */
set_up_frag_hdr(frag, size, offset);
/* Calculate max payload in multiples of 8 bytes */
max = calc_max_payload(buf, frag, offset);
/* Move data from next fragment to current fragment */
move = move_frag_data(frag, next, max, moved, offset,
hdr_diff);
/* Compact the next fragment, returns how much data moved */
moved = compact_frag(next, move);
/* Calculate how much data is processed */
processed += max;
offset = processed >> 3;
/** If next fragment is last and data already moved to previous
* fragment, then delete this fragment, if data is left insert
* header.
*/
if (!next->frags) {
if (next->len == NET_6LO_FRAGN_HDR_LEN) {
net_buf_frag_del(frag, next);
} else {
set_up_frag_hdr(next, size, offset);
if (!room) {
/* Prepare new fragment based on offset */
frag = prepare_new_fragment(buf, offset);
if (!frag) {
return false;
}
break;
/* Set fragmentation header in the beginning */
set_up_frag_hdr(frag, size, offset);
/* Calculate max payload in multiples of 8 bytes */
max = calc_max_payload(buf, frag, offset);
/* Calculate how much data is processed */
processed += max;
offset = processed >> 3;
}
/* Repeat the steps */
frag = next;
next = next->frags;
/* Move data from next fragment to current fragment */
move = move_frag_data(frag, next, max, first, hdr_diff, &room);
first = false;
/* Compact the next fragment */
compact_frag(next, move);
if (!next->len) {
next = net_buf_frag_del(NULL, next);
if (!next) {
break;
}
}
}
return true;
@ -397,7 +422,7 @@ static inline bool copy_frag(struct net_buf *buf,
while (input) {
write = net_nbuf_write(buf, write, pos, &pos, input->len,
input->data);
input->data, K_FOREVER);
if (!write && pos == 0xffff) {
return false;
}

View file

@ -635,12 +635,12 @@ ieee802154_create_mac_cmd_frame(struct net_if *iface,
struct net_buf *buf, *frag;
uint8_t *p_buf;
buf = net_nbuf_get_reserve_tx(0);
buf = net_nbuf_get_reserve_tx(0, K_FOREVER);
if (!buf) {
return NULL;
}
frag = net_nbuf_get_reserve_data(0);
frag = net_nbuf_get_reserve_data(0, K_FOREVER);
if (!frag) {
goto error;
}

View file

@ -311,11 +311,13 @@ void net_nbuf_print_frags(struct net_buf *buf)
static struct net_buf *net_nbuf_get_reserve_debug(struct net_buf_pool *pool,
uint16_t reserve_head,
int32_t timeout,
const char *caller,
int line)
#else /* CONFIG_NET_DEBUG_NET_BUF */
static struct net_buf *net_nbuf_get_reserve(struct net_buf_pool *pool,
uint16_t reserve_head)
uint16_t reserve_head,
int32_t timeout)
#endif /* CONFIG_NET_DEBUG_NET_BUF */
{
struct net_buf *buf = NULL;
@ -327,11 +329,12 @@ static struct net_buf *net_nbuf_get_reserve(struct net_buf_pool *pool,
if (k_is_in_isr()) {
buf = net_buf_alloc(pool, K_NO_WAIT);
if (!buf) {
return NULL;
}
} else {
buf = net_buf_alloc(pool, K_FOREVER);
buf = net_buf_alloc(pool, timeout);
}
if (!buf) {
return NULL;
}
if (pool == &data_buffers) {
@ -356,41 +359,47 @@ static struct net_buf *net_nbuf_get_reserve(struct net_buf_pool *pool,
#if defined(CONFIG_NET_DEBUG_NET_BUF)
struct net_buf *net_nbuf_get_reserve_rx_debug(uint16_t reserve_head,
int32_t timeout,
const char *caller, int line)
{
return net_nbuf_get_reserve_debug(&rx_buffers, reserve_head,
return net_nbuf_get_reserve_debug(&rx_buffers, reserve_head, timeout,
caller, line);
}
struct net_buf *net_nbuf_get_reserve_tx_debug(uint16_t reserve_head,
int32_t timeout,
const char *caller, int line)
{
return net_nbuf_get_reserve_debug(&tx_buffers, reserve_head,
return net_nbuf_get_reserve_debug(&tx_buffers, reserve_head, timeout,
caller, line);
}
struct net_buf *net_nbuf_get_reserve_data_debug(uint16_t reserve_head,
int32_t timeout,
const char *caller, int line)
{
return net_nbuf_get_reserve_debug(&data_buffers, reserve_head,
caller, line);
timeout, caller, line);
}
#else /* CONFIG_NET_DEBUG_NET_BUF */
struct net_buf *net_nbuf_get_reserve_rx(uint16_t reserve_head)
struct net_buf *net_nbuf_get_reserve_rx(uint16_t reserve_head,
int32_t timeout)
{
return net_nbuf_get_reserve(&rx_buffers, reserve_head);
return net_nbuf_get_reserve(&rx_buffers, reserve_head, timeout);
}
struct net_buf *net_nbuf_get_reserve_tx(uint16_t reserve_head)
struct net_buf *net_nbuf_get_reserve_tx(uint16_t reserve_head,
int32_t timeout)
{
return net_nbuf_get_reserve(&tx_buffers, reserve_head);
return net_nbuf_get_reserve(&tx_buffers, reserve_head, timeout);
}
struct net_buf *net_nbuf_get_reserve_data(uint16_t reserve_head)
struct net_buf *net_nbuf_get_reserve_data(uint16_t reserve_head,
int32_t timeout)
{
return net_nbuf_get_reserve(&data_buffers, reserve_head);
return net_nbuf_get_reserve(&data_buffers, reserve_head, timeout);
}
#endif /* CONFIG_NET_DEBUG_NET_BUF */
@ -399,10 +408,12 @@ struct net_buf *net_nbuf_get_reserve_data(uint16_t reserve_head)
#if defined(CONFIG_NET_DEBUG_NET_BUF)
static struct net_buf *net_nbuf_get_debug(struct net_buf_pool *pool,
struct net_context *context,
int32_t timeout,
const char *caller, int line)
#else
static struct net_buf *net_nbuf_get(struct net_buf_pool *pool,
struct net_context *context)
struct net_context *context,
int32_t timeout)
#endif /* CONFIG_NET_DEBUG_NET_BUF */
{
struct in6_addr *addr6 = NULL;
@ -425,9 +436,9 @@ static struct net_buf *net_nbuf_get(struct net_buf_pool *pool,
reserve = net_if_get_ll_reserve(iface, addr6);
#if defined(CONFIG_NET_DEBUG_NET_BUF)
buf = net_nbuf_get_reserve_debug(pool, reserve, caller, line);
buf = net_nbuf_get_reserve_debug(pool, reserve, timeout, caller, line);
#else
buf = net_nbuf_get_reserve(pool, reserve);
buf = net_nbuf_get_reserve(pool, reserve, timeout);
#endif
if (!buf) {
return buf;
@ -449,44 +460,48 @@ static struct net_buf *net_nbuf_get(struct net_buf_pool *pool,
#if defined(CONFIG_NET_DEBUG_NET_BUF)
struct net_buf *net_nbuf_get_rx_debug(struct net_context *context,
int32_t timeout,
const char *caller, int line)
{
return net_nbuf_get_debug(&rx_buffers, context, caller, line);
return net_nbuf_get_debug(&rx_buffers, context, timeout, caller, line);
}
struct net_buf *net_nbuf_get_tx_debug(struct net_context *context,
int32_t timeout,
const char *caller, int line)
{
return net_nbuf_get_debug(&tx_buffers, context, caller, line);
return net_nbuf_get_debug(&tx_buffers, context, timeout, caller, line);
}
struct net_buf *net_nbuf_get_data_debug(struct net_context *context,
int32_t timeout,
const char *caller, int line)
{
return net_nbuf_get_debug(&data_buffers, context, caller, line);
return net_nbuf_get_debug(&data_buffers, context, timeout,
caller, line);
}
#else /* CONFIG_NET_DEBUG_NET_BUF */
struct net_buf *net_nbuf_get_rx(struct net_context *context)
struct net_buf *net_nbuf_get_rx(struct net_context *context, int32_t timeout)
{
NET_ASSERT_INFO(context, "RX context not set");
return net_nbuf_get(&rx_buffers, context);
return net_nbuf_get(&rx_buffers, context, timeout);
}
struct net_buf *net_nbuf_get_tx(struct net_context *context)
struct net_buf *net_nbuf_get_tx(struct net_context *context, int32_t timeout)
{
NET_ASSERT_INFO(context, "TX context not set");
return net_nbuf_get(&tx_buffers, context);
return net_nbuf_get(&tx_buffers, context, timeout);
}
struct net_buf *net_nbuf_get_data(struct net_context *context)
struct net_buf *net_nbuf_get_data(struct net_context *context, int32_t timeout)
{
NET_ASSERT_INFO(context, "Data context not set");
return net_nbuf_get(&data_buffers, context);
return net_nbuf_get(&data_buffers, context, timeout);
}
#endif /* CONFIG_NET_DEBUG_NET_BUF */
@ -564,7 +579,7 @@ struct net_buf *net_nbuf_ref(struct net_buf *buf)
}
struct net_buf *net_nbuf_copy(struct net_buf *orig, size_t amount,
size_t reserve)
size_t reserve, int32_t timeout)
{
uint16_t ll_reserve = net_buf_headroom(orig);
struct net_buf *frag, *first;
@ -574,7 +589,10 @@ struct net_buf *net_nbuf_copy(struct net_buf *orig, size_t amount,
return NULL;
}
frag = net_nbuf_get_reserve_data(ll_reserve);
frag = net_nbuf_get_reserve_data(ll_reserve, timeout);
if (!frag) {
return NULL;
}
if (reserve > net_buf_tailroom(frag)) {
NET_ERR("Reserve %zu is too long, max is %zu",
@ -622,7 +640,12 @@ struct net_buf *net_nbuf_copy(struct net_buf *orig, size_t amount,
* We must allocate a new one.
*/
struct net_buf *new_frag =
net_nbuf_get_reserve_data(ll_reserve);
net_nbuf_get_reserve_data(ll_reserve,
timeout);
if (!new_frag) {
net_nbuf_unref(first);
return NULL;
}
net_buf_frag_add(frag, new_frag);
@ -728,20 +751,19 @@ bool net_nbuf_is_compact(struct net_buf *buf)
return false;
}
struct net_buf *net_nbuf_compact(struct net_buf *buf)
bool net_nbuf_compact(struct net_buf *buf)
{
struct net_buf *first, *prev;
struct net_buf *prev;
first = buf;
if (!is_from_data_pool(buf)) {
NET_DBG("Buffer %p is not a data fragment", buf);
buf = buf->frags;
if (is_from_data_pool(buf)) {
NET_DBG("Buffer %p is a data fragment", buf);
return false;
}
prev = NULL;
NET_DBG("Compacting data to buf %p", buf);
NET_DBG("Compacting data to buf %p", first);
buf = buf->frags;
prev = NULL;
while (buf) {
if (buf->frags) {
@ -766,16 +788,10 @@ struct net_buf *net_nbuf_compact(struct net_buf *buf)
/* Is there any more space in this fragment */
if (net_buf_tailroom(buf)) {
struct net_buf *frag;
/* There is. This also means that the next
* fragment is empty as otherwise we could
* not have copied all data.
*/
frag = buf->frags;
/* Remove next fragment as there is no
* data in it any more.
* not have copied all data. Remove next
* fragment as there is no data in it any more.
*/
net_buf_frag_del(buf, buf->frags);
@ -787,10 +803,9 @@ struct net_buf *net_nbuf_compact(struct net_buf *buf)
/* Remove the last fragment because there is no
* data in it.
*/
NET_ASSERT_INFO(prev,
"First element cannot be deleted!");
net_buf_frag_del(prev, buf);
break;
}
}
@ -798,36 +813,7 @@ struct net_buf *net_nbuf_compact(struct net_buf *buf)
buf = buf->frags;
}
return first;
}
struct net_buf *net_nbuf_push(struct net_buf *parent,
struct net_buf *buf,
size_t amount)
{
struct net_buf *frag;
NET_ASSERT_INFO(amount > 3,
"Amount %zu very small and not recommended", amount);
if (amount > buf->len) {
NET_DBG("Cannot move amount %zu because the buf "
"length is only %u bytes", amount, buf->len);
return NULL;
}
frag = net_nbuf_get_reserve_data(net_buf_headroom(buf));
net_buf_add(frag, amount);
if (parent) {
net_buf_frag_insert(parent, frag);
} else {
net_buf_frag_insert(frag, buf);
parent = frag;
}
return net_nbuf_compact(parent);
return true;
}
struct net_buf *net_nbuf_pull(struct net_buf *buf, size_t amount)
@ -898,7 +884,7 @@ struct net_buf *net_nbuf_pull(struct net_buf *buf, size_t amount)
* the buffer. It assumes that the buffer has at least one fragment.
*/
static inline bool net_nbuf_append_bytes(struct net_buf *buf, uint8_t *value,
uint16_t len)
uint16_t len, int32_t timeout)
{
struct net_buf *frag = net_buf_frag_last(buf);
uint16_t ll_reserve = net_nbuf_ll_reserve(buf);
@ -915,7 +901,7 @@ static inline bool net_nbuf_append_bytes(struct net_buf *buf, uint8_t *value,
return true;
}
frag = net_nbuf_get_reserve_data(ll_reserve);
frag = net_nbuf_get_reserve_data(ll_reserve, timeout);
if (!frag) {
return false;
}
@ -926,7 +912,8 @@ static inline bool net_nbuf_append_bytes(struct net_buf *buf, uint8_t *value,
return false;
}
bool net_nbuf_append(struct net_buf *buf, uint16_t len, uint8_t *data)
bool net_nbuf_append(struct net_buf *buf, uint16_t len, uint8_t *data,
int32_t timeout)
{
struct net_buf *frag;
@ -944,7 +931,8 @@ bool net_nbuf_append(struct net_buf *buf, uint16_t len, uint8_t *data)
}
if (!buf->frags) {
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf));
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf),
timeout);
if (!frag) {
return false;
}
@ -952,7 +940,7 @@ bool net_nbuf_append(struct net_buf *buf, uint16_t len, uint8_t *data)
net_buf_frag_add(buf, frag);
}
return net_nbuf_append_bytes(buf, data, len);
return net_nbuf_append_bytes(buf, data, len, timeout);
}
/* Helper routine to retrieve single byte from fragment and move
@ -1069,7 +1057,8 @@ struct net_buf *net_nbuf_read_be32(struct net_buf *buf, uint16_t offset,
}
static inline struct net_buf *check_and_create_data(struct net_buf *buf,
struct net_buf *data)
struct net_buf *data,
int32_t timeout)
{
struct net_buf *frag;
@ -1077,7 +1066,8 @@ static inline struct net_buf *check_and_create_data(struct net_buf *buf,
return data;
}
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf));
frag = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf),
timeout);
if (!frag) {
return NULL;
}
@ -1090,12 +1080,13 @@ static inline struct net_buf *check_and_create_data(struct net_buf *buf,
static inline struct net_buf *adjust_write_offset(struct net_buf *buf,
struct net_buf *frag,
uint16_t offset,
uint16_t *pos)
uint16_t *pos,
int32_t timeout)
{
uint16_t tailroom;
do {
frag = check_and_create_data(buf, frag);
frag = check_and_create_data(buf, frag, timeout);
if (!frag) {
return NULL;
}
@ -1122,7 +1113,8 @@ static inline struct net_buf *adjust_write_offset(struct net_buf *buf,
*pos = 0;
return check_and_create_data(buf, frag->frags);
return check_and_create_data(buf, frag->frags,
timeout);
}
/* If the offset is more than current fragment length, remove
@ -1150,7 +1142,9 @@ static inline struct net_buf *adjust_write_offset(struct net_buf *buf,
*pos = 0;
return check_and_create_data(buf, frag->frags);
return check_and_create_data(buf,
frag->frags,
timeout);
}
if (offset > tailroom) {
@ -1158,7 +1152,9 @@ static inline struct net_buf *adjust_write_offset(struct net_buf *buf,
net_buf_add(frag, tailroom);
offset -= tailroom;
frag = check_and_create_data(buf, frag->frags);
frag = check_and_create_data(buf,
frag->frags,
timeout);
}
}
@ -1169,7 +1165,8 @@ static inline struct net_buf *adjust_write_offset(struct net_buf *buf,
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)
uint16_t len, uint8_t *data,
int32_t timeout)
{
uint16_t ll_reserve;
@ -1180,7 +1177,7 @@ struct net_buf *net_nbuf_write(struct net_buf *buf, struct net_buf *frag,
ll_reserve = net_nbuf_ll_reserve(buf);
frag = adjust_write_offset(buf, frag, offset, &offset);
frag = adjust_write_offset(buf, frag, offset, &offset, timeout);
if (!frag) {
NET_DBG("Failed to adjust offset");
goto error;
@ -1213,7 +1210,7 @@ struct net_buf *net_nbuf_write(struct net_buf *buf, struct net_buf *frag,
frag = frag->frags;
if (!frag) {
frag = net_nbuf_get_reserve_data(ll_reserve);
frag = net_nbuf_get_reserve_data(ll_reserve, timeout);
if (!frag) {
goto error;
}
@ -1230,7 +1227,8 @@ error:
static inline bool insert_data(struct net_buf *buf, struct net_buf *frag,
struct net_buf *temp, uint16_t offset,
uint16_t len, uint8_t *data)
uint16_t len, uint8_t *data,
int32_t timeout)
{
struct net_buf *insert;
@ -1262,7 +1260,8 @@ static inline bool insert_data(struct net_buf *buf, struct net_buf *frag,
data += count;
offset = 0;
insert = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf));
insert = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf),
timeout);
if (!insert) {
return false;
}
@ -1314,7 +1313,8 @@ static inline struct net_buf *adjust_insert_offset(struct net_buf *buf,
}
bool net_nbuf_insert(struct net_buf *buf, struct net_buf *frag,
uint16_t offset, uint16_t len, uint8_t *data)
uint16_t offset, uint16_t len, uint8_t *data,
int32_t timeout)
{
struct net_buf *temp = NULL;
uint16_t bytes;
@ -1333,7 +1333,8 @@ bool net_nbuf_insert(struct net_buf *buf, struct net_buf *frag,
*/
bytes = frag->len - offset;
if (bytes) {
temp = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf));
temp = net_nbuf_get_reserve_data(net_nbuf_ll_reserve(buf),
timeout);
if (!temp) {
return false;
}
@ -1344,7 +1345,7 @@ bool net_nbuf_insert(struct net_buf *buf, struct net_buf *frag,
}
/* Insert data into current(frag) fragment from "offset". */
return insert_data(buf, frag, temp, offset, len, data);
return insert_data(buf, frag, temp, offset, len, data, timeout);
}
void net_nbuf_get_info(size_t *tx_size, size_t *rx_size, size_t *data_size,

View file

@ -422,7 +422,9 @@ int net_context_put(struct net_context *context)
#if defined(CONFIG_NET_TCP)
if (net_context_get_ip_proto(context) == IPPROTO_TCP) {
if (!context->tcp->fin_rcvd) {
if ((net_context_get_state(context) == NET_CONTEXT_CONNECTED ||
net_context_get_state(context) == NET_CONTEXT_LISTENING)
&& !context->tcp->fin_rcvd) {
NET_DBG("TCP connection in active close, not "
"disposing yet");
queue_fin(context);
@ -446,6 +448,7 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
struct net_if *iface;
struct in6_addr *ptr;
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
int ret;
if (addrlen < sizeof(struct sockaddr_in6)) {
return -EINVAL;
@ -479,7 +482,7 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
}
if (!iface) {
NET_DBG("Cannot bind to %s",
NET_ERR("Cannot bind to %s",
net_sprint_ipv6_addr(&addr6->sin6_addr));
return -EADDRNOTAVAIL;
@ -500,7 +503,18 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
net_sin6_ptr(&context->local)->sin6_family = AF_INET6;
net_sin6_ptr(&context->local)->sin6_addr = ptr;
net_sin6_ptr(&context->local)->sin6_port = addr6->sin6_port;
if (addr6->sin6_port) {
ret = check_used_port(AF_INET6, addr6->sin6_port,
addr);
if (!ret) {
net_sin6_ptr(&context->local)->sin6_port =
addr6->sin6_port;
} else {
NET_ERR("Port %d is in use!",
ntohs(addr6->sin6_port));
return ret;
}
}
NET_DBG("Context %p binding to [%s]:%d iface %p", context,
net_sprint_ipv6_addr(ptr), ntohs(addr6->sin6_port),
@ -516,6 +530,7 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
struct net_if_addr *ifaddr;
struct net_if *iface;
struct in_addr *ptr;
int ret;
if (addrlen < sizeof(struct sockaddr_in)) {
return -EINVAL;
@ -536,7 +551,7 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
}
if (!iface) {
NET_DBG("Cannot bind to %s",
NET_ERR("Cannot bind to %s",
net_sprint_ipv4_addr(&addr4->sin_addr));
return -EADDRNOTAVAIL;
@ -557,7 +572,18 @@ int net_context_bind(struct net_context *context, const struct sockaddr *addr,
net_sin_ptr(&context->local)->sin_family = AF_INET;
net_sin_ptr(&context->local)->sin_addr = ptr;
net_sin_ptr(&context->local)->sin_port = addr4->sin_port;
if (addr4->sin_port) {
ret = check_used_port(AF_INET, addr4->sin_port,
addr);
if (!ret) {
net_sin_ptr(&context->local)->sin_port =
addr4->sin_port;
} else {
NET_ERR("Port %d is in use!",
ntohs(addr4->sin_port));
return ret;
}
}
NET_DBG("Context %p binding to %s:%d iface %p", context,
net_sprint_ipv4_addr(ptr),
@ -758,7 +784,7 @@ NET_CONN_CB(tcp_established)
NET_ASSERT(context && context->tcp);
if (net_tcp_get_state(context->tcp) != NET_TCP_ESTABLISHED) {
NET_DBG("Context %p in wrong state %d",
NET_ERR("Context %p in wrong state %d",
context, net_tcp_get_state(context->tcp));
return NET_DROP;
}

Some files were not shown because too many files have changed in this diff Show more