Merge pull request #8351 from kaspar030/introduce_iolists

net: Introduce iolists
This commit is contained in:
Kaspar Schleiser 2018-03-07 09:56:13 +01:00 committed by GitHub
commit d025de32ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 628 additions and 514 deletions

View File

@ -110,6 +110,7 @@ endif
ifneq (,$(filter netdev_tap,$(USEMODULE)))
USEMODULE += netif
USEMODULE += netdev_eth
USEMODULE += iolist
endif
ifneq (,$(filter gnrc_tftp,$(USEMODULE)))

View File

@ -14,6 +14,7 @@ ifneq (,$(filter can,$(USEMODULE)))
endif
ifneq (,$(filter socket_zep,$(USEMODULE)))
USEMODULE += iolist
USEMODULE += netdev_ieee802154
USEMODULE += checksum
USEMODULE += random

View File

@ -33,22 +33,6 @@
#define _MAX_MHR_OVERHEAD (25)
static int _get(netdev_t *dev, netopt_t opt, void *value, size_t max_len);
static int _set(netdev_t *dev, netopt_t opt, const void *value, size_t value_len);
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count);
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info);
static void _isr(netdev_t *netdev);
static int _init(netdev_t *dev);
const netdev_driver_t cc2538_rf_driver = {
.get = _get,
.set = _set,
.send = _send,
.recv = _recv,
.isr = _isr,
.init = _init,
};
/* Reference pointer for the IRQ handler */
static netdev_t *_dev;
@ -253,7 +237,7 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *value, size_t value_
return res;
}
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
static int _send(netdev_t *netdev, const iolist_t *iolist)
{
(void) netdev;
@ -268,8 +252,8 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
start of the FIFO, so we can come back and update it later */
rfcore_write_byte(0);
for (unsigned i = 0; i < count; i++) {
pkt_len += vector[i].iov_len;
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
pkt_len += iol->iol_len;
if (pkt_len > CC2538_RF_MAX_DATA_LEN) {
DEBUG("cc2538_rf: packet too large (%u > %u)\n",
@ -277,7 +261,7 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
return -EOVERFLOW;
}
rfcore_write_fifo(vector[i].iov_base, vector[i].iov_len);
rfcore_write_fifo(iol->iol_base, iol->iol_len);
}
#ifdef MODULE_NETSTATS_L2
@ -407,3 +391,12 @@ static int _init(netdev_t *netdev)
return 0;
}
const netdev_driver_t cc2538_rf_driver = {
.get = _get,
.set = _set,
.send = _send,
.recv = _recv,
.isr = _isr,
.init = _init,
};

View File

@ -26,6 +26,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <unistd.h>
/* needs to be included before native's declarations of ntohl etc. */
@ -51,6 +52,7 @@
#include "async_read.h"
#include "iolist.h"
#include "net/eui64.h"
#include "net/netdev.h"
#include "net/netdev/eth.h"
@ -64,7 +66,7 @@
/* netdev interface */
static int _init(netdev_t *netdev);
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned n);
static int _send(netdev_t *netdev, const iolist_t *iolist);
static int _recv(netdev_t *netdev, void *buf, size_t n, void *info);
static inline void _get_mac_addr(netdev_t *netdev, uint8_t *dst)
@ -273,17 +275,20 @@ static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
return -1;
}
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned n)
static int _send(netdev_t *netdev, const iolist_t *iolist)
{
netdev_tap_t *dev = (netdev_tap_t*)netdev;
int res = _native_writev(dev->tap_fd, vector, n);
struct iovec iov[iolist_count(iolist)];
unsigned n;
size_t bytes = iolist_to_iovec(iolist, iov, &n);
int res = _native_writev(dev->tap_fd, iov, n);
#ifdef MODULE_NETSTATS_L2
size_t bytes = 0;
for (unsigned i = 0; i < n; i++) {
bytes += vector->iov_len;
vector++;
}
netdev->stats.tx_bytes += bytes;
#else
(void)bytes;
#endif
if (netdev->event_callback) {
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);

View File

@ -36,23 +36,6 @@
#define _UNIX_NTP_ERA_OFFSET (2208988800U)
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned n);
static int _recv(netdev_t *netdev, void *buf, size_t n, void *info);
static void _isr(netdev_t *netdev);
static int _init(netdev_t *netdev);
static int _get(netdev_t *netdev, netopt_t opt, void *value, size_t max_len);
static int _set(netdev_t *netdev, netopt_t opt, const void *value,
size_t value_len);
static const netdev_driver_t socket_zep_driver = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};
static size_t _zep_hdr_fill_v2_data(socket_zep_t *dev, zep_v2_data_hdr_t *hdr,
size_t payload_len)
{
@ -85,24 +68,23 @@ static inline size_t _zep_hdr_fill(socket_zep_t *dev, zep_hdr_t *hdr,
payload_len);
}
static size_t _prep_vector(socket_zep_t *dev, const struct iovec *vector,
static size_t _prep_vector(socket_zep_t *dev, const iolist_t *iolist,
unsigned n, struct iovec *out)
{
size_t bytes = 0;
size_t bytes;
dev->chksum_buf = 0;
for (unsigned i = 0; i < n; i++) {
bytes += vector[i].iov_len;
}
bytes = iolist_size(iolist);
bytes += sizeof(uint16_t); /* FCS field */
out[0].iov_base = &dev->snd_hdr_buf;
out[0].iov_len = _zep_hdr_fill(dev, out[0].iov_base, bytes);
for (unsigned i = 0; i < n; i++) {
/* discard const qualifier, we won't change anything. Promise! */
out[i + 1].iov_base = vector[i].iov_base;
out[i + 1].iov_len = vector[i].iov_len;
out[i + 1].iov_base = iolist->iol_base;
out[i + 1].iov_len = iolist->iol_len;
dev->chksum_buf = ucrc16_calc_le(out[i + 1].iov_base, out[i + 1].iov_len,
UCRC16_CCITT_POLY_LE, dev->chksum_buf);
iolist = iolist->iol_next;
}
dev->chksum_buf = byteorder_btols(byteorder_htons(dev->chksum_buf)).u16;
out[n + 1].iov_base = &dev->chksum_buf;
@ -110,16 +92,17 @@ static size_t _prep_vector(socket_zep_t *dev, const struct iovec *vector,
return bytes;
}
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned n)
static int _send(netdev_t *netdev, const iolist_t *iolist)
{
socket_zep_t *dev = (socket_zep_t *)netdev;
unsigned n = iolist_count(iolist);
struct iovec v[n + 2];
size_t bytes;
int res;
assert((dev != NULL) && (dev->sock_fd != 0));
bytes = _prep_vector(dev, vector, n, v);
DEBUG("socket_zep::send(%p, %p, %u)\n", (void *)netdev, (void *)vector, n);
bytes = _prep_vector(dev, iolist, n, v);
DEBUG("socket_zep::send(%p, %p, %u)\n", (void *)netdev, (void *)iolist, n);
/* simulate TX_STARTED interrupt */
if (netdev->event_callback) {
dev->last_event = NETDEV_EVENT_TX_STARTED;
@ -350,6 +333,14 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *value,
value, value_len);
}
static const netdev_driver_t socket_zep_driver = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};
void socket_zep_setup(socket_zep_t *dev, const socket_zep_params_t *params)
{

View File

@ -325,11 +325,11 @@ void isr_radio(void)
cortexm_isr_end();
}
static int nrfmin_send(netdev_t *dev, const struct iovec *vector, unsigned count)
static int nrfmin_send(netdev_t *dev, const iolist_t *iolist)
{
(void)dev;
assert((vector != NULL) && (count > 0) && (state != STATE_OFF));
assert((iolist) && (state != STATE_OFF));
/* wait for any ongoing transmission to finish and go into idle state */
while (state == STATE_TX) {}
@ -337,17 +337,17 @@ static int nrfmin_send(netdev_t *dev, const struct iovec *vector, unsigned count
/* copy packet data into the transmit buffer */
int pos = 0;
for (unsigned i = 0; i < count; i++) {
if ((pos + vector[i].iov_len) > NRFMIN_PKT_MAX) {
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
if ((pos + iol->iol_len) > NRFMIN_PKT_MAX) {
DEBUG("[nrfmin] send: unable to do so, packet is too large!\n");
return -EOVERFLOW;
}
memcpy(&tx_buf.raw[pos], vector[i].iov_base, vector[i].iov_len);
pos += vector[i].iov_len;
memcpy(&tx_buf.raw[pos], iol->iol_base, iol->iol_len);
pos += iol->iol_len;
}
/* set output buffer and destination address */
nrfmin_hdr_t *hdr = (nrfmin_hdr_t *)vector[0].iov_base;
nrfmin_hdr_t *hdr = (nrfmin_hdr_t *)iolist->iol_base;
NRF_RADIO->PACKETPTR = (uint32_t)(&tx_buf);
NRF_RADIO->BASE0 = (CONF_ADDR_BASE | hdr->dst_addr);
@ -356,7 +356,7 @@ static int nrfmin_send(netdev_t *dev, const struct iovec *vector, unsigned count
state = STATE_TX;
NRF_RADIO->TASKS_TXEN = 1;
return (int)count;
return (int)pos;
}
static int nrfmin_recv(netdev_t *dev, void *buf, size_t len, void *info)

View File

@ -79,9 +79,6 @@ static int hdr_netif_to_nrfmin(nrfmin_hdr_t *nrfmin, gnrc_pktsnip_t *pkt)
static int gnrc_nrfmin_send(gnrc_netif_t *dev, gnrc_pktsnip_t *pkt)
{
int res;
struct iovec *vec;
size_t vec_len;
gnrc_pktsnip_t *vec_snip;
nrfmin_hdr_t nrfmin_hdr;
assert(pkt);
@ -95,26 +92,21 @@ static int gnrc_nrfmin_send(gnrc_netif_t *dev, gnrc_pktsnip_t *pkt)
res = hdr_netif_to_nrfmin(&nrfmin_hdr, pkt);
if (res < 0) {
DEBUG("[nrfmin_gnrc] send: failed to build nrfmin header\n");
gnrc_pktbuf_release(pkt);
return res;
goto out;
}
/* create iovec of data */
vec_snip = gnrc_pktbuf_get_iovec(pkt, &vec_len);
if (vec_snip == NULL) {
DEBUG("[nrfmin_gnrc] send: failed to create IO vector\n");
gnrc_pktbuf_release(pkt);
return -ENOBUFS;
}
/* link first entry of the vector to the nrfmin header */
vec = (struct iovec *)vec_snip->data;
vec[0].iov_base = &nrfmin_hdr;
vec[0].iov_len = NRFMIN_HDR_LEN;
/* link first entry after netif hdr of the pkt to the nrfmin header */
iolist_t iolist = {
.iol_next = (iolist_t *)pkt->next,
.iol_base = &nrfmin_hdr,
.iol_len = NRFMIN_HDR_LEN
};
/* and finally send out the data and release the packet */
res = dev->dev->driver->send(dev->dev, vec, vec_len);
gnrc_pktbuf_release(vec_snip);
res = dev->dev->driver->send(dev->dev, &iolist);
out:
gnrc_pktbuf_release(pkt);
return res;
}

View File

@ -112,6 +112,7 @@ ifneq (,$(filter encx24j600,$(USEMODULE)))
endif
ifneq (,$(filter ethos,$(USEMODULE)))
USEMODULE += iolist
USEMODULE += netdev_eth
USEMODULE += random
USEMODULE += tsrb
@ -306,6 +307,7 @@ endif
ifneq (,$(filter sx127%,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio
FEATURES_REQUIRED += periph_spi
USEMODULE += iolist
USEMODULE += xtimer
USEMODULE += sx127x
USEMODULE += netif

View File

@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Freie Universität Berlin
* Copyright (C) 2018 Kaspar Schleiser <kaspar@schleiser.de>
* 2015 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -17,6 +18,7 @@
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Kévin Roussel <Kevin.Roussel@inria.fr>
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author Kaspar Schleiser <kaspar@schleiser.de>
*
* @}
*/
@ -25,6 +27,8 @@
#include <assert.h>
#include <errno.h>
#include "iolist.h"
#include "net/eui64.h"
#include "net/ieee802154.h"
#include "net/netdev.h"
@ -40,7 +44,7 @@
#define _MAX_MHR_OVERHEAD (25)
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count);
static int _send(netdev_t *netdev, const iolist_t *iolist);
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info);
static int _init(netdev_t *netdev);
static void _isr(netdev_t *netdev);
@ -93,18 +97,17 @@ static int _init(netdev_t *netdev)
return 0;
}
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
static int _send(netdev_t *netdev, const iolist_t *iolist)
{
at86rf2xx_t *dev = (at86rf2xx_t *)netdev;
const struct iovec *ptr = vector;
size_t len = 0;
at86rf2xx_tx_prepare(dev);
/* load packet data into FIFO */
for (unsigned i = 0; i < count; ++i, ++ptr) {
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
/* current packet data + FCS too long */
if ((len + ptr->iov_len + 2) > AT86RF2XX_MAX_PKT_LENGTH) {
if ((len + iol->iol_len + 2) > AT86RF2XX_MAX_PKT_LENGTH) {
DEBUG("[at86rf2xx] error: packet too large (%u byte) to be send\n",
(unsigned)len + 2);
return -EOVERFLOW;
@ -112,7 +115,7 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
#ifdef MODULE_NETSTATS_L2
netdev->stats.tx_bytes += len;
#endif
len = at86rf2xx_tx_load(dev, ptr->iov_base, ptr->iov_len, len);
len = at86rf2xx_tx_load(dev, iol->iol_base, iol->iol_len, len);
}
/* send data out directly if pre-loading id disabled */

View File

@ -37,14 +37,12 @@
#define ENABLE_DEBUG (0)
#include "debug.h"
static int _send(netdev_t *dev, const struct iovec *vector, unsigned count)
static int _send(netdev_t *dev, const iolist_t *iolist)
{
DEBUG("%s:%u\n", __func__, __LINE__);
(void)count;
netdev_cc110x_t *netdev_cc110x = (netdev_cc110x_t*) dev;
cc110x_pkt_t *cc110x_pkt = vector[0].iov_base;
netdev_cc110x_t *netdev_cc110x = (netdev_cc110x_t *)dev;
cc110x_pkt_t *cc110x_pkt = iolist->iol_base;
return cc110x_send(&netdev_cc110x->cc110x, cc110x_pkt);
}

View File

@ -71,9 +71,10 @@ static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
cc110x_pkt.flags = 0;
}
struct iovec vector;
vector.iov_base = (char*)&cc110x_pkt;
vector.iov_len = sizeof(cc110x_pkt_t);
iolist_t iolist = {
.iol_base = (char *)&cc110x_pkt,
.iol_len = sizeof(cc110x_pkt_t)
};
unsigned payload_len = 0;
uint8_t *pos = cc110x_pkt.data;
@ -93,7 +94,7 @@ static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
payload = payload->next;
}
/* pkt has been copied into iovec, we're done with it. */
/* pkt has been copied into cc110x_pkt, we're done with it. */
gnrc_pktbuf_release(pkt);
cc110x_pkt.length = (uint8_t) payload_len + CC110X_HEADER_LENGTH;
@ -104,7 +105,7 @@ static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
(unsigned)cc110x_pkt.address,
(unsigned)cc110x_pkt.length);
return dev->driver->send(dev, &vector, 1);
return dev->driver->send(dev, &iolist);
}
static gnrc_pktsnip_t *_recv(gnrc_netif_t *netif)

View File

@ -114,9 +114,9 @@ bool cc2420_cca(cc2420_t *dev)
return gpio_read(dev->params.pin_cca);
}
size_t cc2420_send(cc2420_t *dev, const struct iovec *data, unsigned count)
size_t cc2420_send(cc2420_t *dev, const iolist_t *iolist)
{
size_t n = cc2420_tx_prepare(dev, data, count);
size_t n = cc2420_tx_prepare(dev, iolist);
if ((n > 0) && !(dev->options & CC2420_OPT_PRELOADING)) {
cc2420_tx_exec(dev);
@ -125,7 +125,7 @@ size_t cc2420_send(cc2420_t *dev, const struct iovec *data, unsigned count)
return n;
}
size_t cc2420_tx_prepare(cc2420_t *dev, const struct iovec *data, unsigned count)
size_t cc2420_tx_prepare(cc2420_t *dev, const iolist_t *iolist)
{
size_t pkt_len = 2; /* include the FCS (frame check sequence) */
@ -134,8 +134,8 @@ size_t cc2420_tx_prepare(cc2420_t *dev, const struct iovec *data, unsigned count
while (cc2420_get_state(dev) & NETOPT_STATE_TX) {}
/* get and check the length of the packet */
for (unsigned i = 0; i < count; i++) {
pkt_len += data[i].iov_len;
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
pkt_len += iol->iol_len;
}
if (pkt_len >= CC2420_PKT_MAXLEN) {
DEBUG("cc2420: tx_prep: unable to send, pkt too large\n");
@ -147,8 +147,8 @@ size_t cc2420_tx_prepare(cc2420_t *dev, const struct iovec *data, unsigned count
/* push packet length to TX FIFO */
cc2420_fifo_write(dev, (uint8_t *)&pkt_len, 1);
/* push packet to TX FIFO */
for (unsigned i = 0; i < count; i++) {
cc2420_fifo_write(dev, (uint8_t *)data[i].iov_base, data[i].iov_len);
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
cc2420_fifo_write(dev, iol->iol_base, iol->iol_len);
}
DEBUG("cc2420: tx_prep: loaded %i byte into the TX FIFO\n", (int)pkt_len);

View File

@ -39,7 +39,7 @@
#include "debug.h"
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count);
static int _send(netdev_t *netdev, const iolist_t *iolist);
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info);
static int _init(netdev_t *netdev);
static void _isr(netdev_t *netdev);
@ -150,10 +150,10 @@ static void _isr(netdev_t *netdev)
netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE);
}
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
static int _send(netdev_t *netdev, const iolist_t *iolist)
{
cc2420_t *dev = (cc2420_t *)netdev;
return (int)cc2420_send(dev, vector, count);
return (int)cc2420_send(dev, iolist);
}
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)

View File

@ -240,7 +240,7 @@ static void on_int(void *arg)
netdev->event_callback(arg, NETDEV_EVENT_ISR);
}
static int nd_send(netdev_t *netdev, const struct iovec *data, unsigned count)
static int nd_send(netdev_t *netdev, const iolist_t *iolist)
{
enc28j60_t *dev = (enc28j60_t *)netdev;
uint8_t ctrl = 0;
@ -256,9 +256,9 @@ static int nd_send(netdev_t *netdev, const struct iovec *data, unsigned count)
cmd_w_addr(dev, ADDR_WRITE_PTR, BUF_TX_START);
/* write control byte and the actual data into the buffer */
cmd_wbm(dev, &ctrl, 1);
for (unsigned i = 0; i < count; i++) {
c += data[i].iov_len;
cmd_wbm(dev, (uint8_t *)data[i].iov_base, data[i].iov_len);
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
c += iol->iol_len;
cmd_wbm(dev, iol->iol_base, iol->iol_len);
}
/* set TX end pointer */
cmd_w_addr(dev, ADDR_TX_END, cmd_r_addr(dev, ADDR_WRITE_PTR) - 1);

View File

@ -64,7 +64,7 @@ static inline int _packets_available(encx24j600_t *dev);
static void _get_mac_addr(netdev_t *dev, uint8_t* buf);
/* netdev interface */
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count);
static int _send(netdev_t *netdev, const iolist_t *iolist);
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info);
static int _init(netdev_t *dev);
static void _isr(netdev_t *dev);
@ -291,7 +291,7 @@ static int _init(netdev_t *encdev)
return 0;
}
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count) {
static int _send(netdev_t *netdev, const iolist_t *iolist) {
encx24j600_t * dev = (encx24j600_t *) netdev;
lock(dev);
@ -301,9 +301,9 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count) {
/* copy packet to SRAM */
size_t len = 0;
for (unsigned i = 0; i < count; i++) {
sram_op(dev, ENC_WGPDATA, (i ? 0xFFFF : TX_BUFFER_START), vector[i].iov_base, vector[i].iov_len);
len += vector[i].iov_len;
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
sram_op(dev, ENC_WGPDATA, ((iol == iolist) ? TX_BUFFER_START : 0xFFFF), iol->iol_base, iol->iol_len);
len += iol->iol_len;
}
/* set start of TX packet and length */

View File

@ -189,12 +189,11 @@ static int _init(netdev_t *encdev)
return 0;
}
static size_t iovec_count_total(const struct iovec *vector, int count)
static size_t iolist_count_total(const iolist_t *iolist)
{
size_t result = 0;
while(count--) {
result += vector->iov_len;
vector++;
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
result += iol->iol_len;
}
return result;
}
@ -256,13 +255,13 @@ void ethos_send_frame(ethos_t *dev, const uint8_t *data, size_t len, unsigned fr
}
}
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
static int _send(netdev_t *netdev, const iolist_t *iolist)
{
ethos_t * dev = (ethos_t *) netdev;
(void)dev;
/* count total packet length */
size_t pktlen = iovec_count_total(vector, count);
size_t pktlen = iolist_count_total(iolist);
/* lock line in order to prevent multiple writes */
mutex_lock(&dev->out_mutex);
@ -271,14 +270,13 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
uint8_t frame_delim = ETHOS_FRAME_DELIMITER;
uart_write(dev->uart, &frame_delim, 1);
/* send iovec */
while(count--) {
size_t n = vector->iov_len;
uint8_t *ptr = vector->iov_base;
/* send iolist */
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
size_t n = iol->iol_len;
uint8_t *ptr = iol->iol_base;
while(n--) {
_write_escaped(dev->uart, *ptr++);
}
vector++;
}
uart_write(dev->uart, &frame_delim, 1);

View File

@ -263,13 +263,12 @@ netopt_state_t cc2420_get_state(cc2420_t *dev);
* @note This function ignores the PRELOADING option
*
* @param[in] dev device to use for sending
* @param[in] data data to send (must include IEEE802.15.4 header)
* @param[in] count length of @p data
* @param[in] iolist data to send (must include IEEE802.15.4 header)
*
* @return number of bytes that were actually send
* @return 0 on error
*/
size_t cc2420_send(cc2420_t *dev, const struct iovec *data, unsigned count);
size_t cc2420_send(cc2420_t *dev, const iolist_t *iolist);
/**
* @brief Prepare for sending of data
@ -278,10 +277,9 @@ size_t cc2420_send(cc2420_t *dev, const struct iovec *data, unsigned count);
* data is possible after it was called.
*
* @param[in] dev device to prepare for sending
* @param[in] data data to prepare (must include IEEE802.15.4 header)
* @param[in] count length of @p data
* @param[in] iolist data to prepare (must include IEEE802.15.4 header)
*/
size_t cc2420_tx_prepare(cc2420_t *dev, const struct iovec *data, unsigned count);
size_t cc2420_tx_prepare(cc2420_t *dev, const iolist_t *iolist);
/**
* @brief Trigger sending of data previously loaded into transmit buffer

View File

@ -195,8 +195,8 @@ extern "C" {
#endif
#include <stdint.h>
#include <sys/uio.h>
#include "iolist.h"
#include "net/netopt.h"
#ifdef MODULE_NETSTATS_L2
@ -294,17 +294,14 @@ typedef struct netdev_driver {
/**
* @brief Send frame
*
* @pre `(dev != NULL)`
* @pre `(count == 0) || (vector != NULL)`
* (`(count != 0) => (vector != NULL)`)
* @pre `(dev != NULL) && (iolist != NULL`
*
* @param[in] dev network device descriptor
* @param[in] vector io vector array to send
* @param[in] count nr of entries in vector
* @param[in] iolist io vector list to send
*
* @return number of bytes sent, or `< 0` on error
*/
int (*send)(netdev_t *dev, const struct iovec *vector, unsigned count);
int (*send)(netdev_t *dev, const iolist_t *iolist);
/**
* @brief Get a received frame

View File

@ -138,10 +138,9 @@ static void kw2xrf_wait_idle(kw2xrf_t *dev)
}
}
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
static int _send(netdev_t *netdev, const iolist_t *iolist)
{
kw2xrf_t *dev = (kw2xrf_t *)netdev;
const struct iovec *ptr = vector;
uint8_t *pkt_buf = &(dev->buf[1]);
size_t len = 0;
@ -149,14 +148,14 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
kw2xrf_wait_idle(dev);
/* load packet data into buffer */
for (unsigned i = 0; i < count; i++, ptr++) {
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
/* current packet data + FCS too long */
if ((len + ptr->iov_len + IEEE802154_FCS_LEN) > KW2XRF_MAX_PKT_LENGTH) {
if ((len + iol->iol_len + IEEE802154_FCS_LEN) > KW2XRF_MAX_PKT_LENGTH) {
LOG_ERROR("[kw2xrf] packet too large (%u byte) to be send\n",
(unsigned)len + IEEE802154_FCS_LEN);
return -EOVERFLOW;
}
len = kw2xrf_tx_load(pkt_buf, ptr->iov_base, ptr->iov_len, len);
len = kw2xrf_tx_load(pkt_buf, iol->iol_base, iol->iol_len, len);
}
kw2xrf_set_sequence(dev, XCVSEQ_IDLE);

View File

@ -39,22 +39,6 @@
#define _MAX_MHR_OVERHEAD (25)
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count);
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info);
static int _init(netdev_t *netdev);
static void _isr(netdev_t *netdev);
static int _get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len);
static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t len);
const netdev_driver_t mrf24j40_driver = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};
static void _irq_handler(void *arg)
{
netdev_t *dev = (netdev_t *) arg;
@ -83,18 +67,17 @@ static int _init(netdev_t *netdev)
return 0;
}
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
static int _send(netdev_t *netdev, const iolist_t *iolist)
{
mrf24j40_t *dev = (mrf24j40_t *)netdev;
const struct iovec *ptr = vector;
size_t len = 0;
mrf24j40_tx_prepare(dev);
/* load packet data into FIFO */
for (unsigned i = 0; i < count; i++, ptr++) {
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
/* current packet data + FCS too long */
if ((len + ptr->iov_len + 2) > IEEE802154_FRAME_LEN_MAX) {
if ((len + iol->iol_len + 2) > IEEE802154_FRAME_LEN_MAX) {
DEBUG("[mrf24j40] error: packet too large (%u byte) to be send\n",
(unsigned)len + 2);
return -EOVERFLOW;
@ -103,11 +86,12 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
#ifdef MODULE_NETSTATS_L2
netdev->stats.tx_bytes += len;
#endif
len = mrf24j40_tx_load(dev, ptr->iov_base, ptr->iov_len, len);
if (i == 0) {
len = mrf24j40_tx_load(dev, iol->iol_base, iol->iol_len, len);
/* only on first iteration: */
if (iol == iolist) {
dev->header_len = len;
/* Grab the FCF bits from the frame header */
dev->fcf_low = *(uint8_t*)(ptr->iov_base);
dev->fcf_low = *(uint8_t*)(iol->iol_base);
}
}
@ -581,3 +565,12 @@ static void _isr(netdev_t *netdev)
}
DEBUG("[mrf24j40] END IRQ\n");
}
const netdev_driver_t mrf24j40_driver = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};

View File

@ -27,31 +27,6 @@
#define SLIP_END_ESC (0xdcU)
#define SLIP_ESC_ESC (0xddU)
static int _send(netdev_t *dev, const struct iovec *vector, unsigned count);
static int _recv(netdev_t *dev, void *buf, size_t len, void *info);
static int _init(netdev_t *dev);
static void _isr(netdev_t *dev);
static int _get(netdev_t *dev, netopt_t opt, void *value, size_t max_len);
static int _set(netdev_t *dev, netopt_t opt, const void *value,
size_t value_len);
static const netdev_driver_t slip_driver = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};
void slipdev_setup(slipdev_t *dev, const slipdev_params_t *params)
{
/* set device descriptor fields */
memcpy(&dev->config, params, sizeof(dev->config));
dev->inesc = 0U;
dev->netdev.driver = &slip_driver;
}
static void _slip_rx_cb(void *arg, uint8_t byte)
{
slipdev_t *dev = arg;
@ -84,16 +59,16 @@ static inline void _write_byte(slipdev_t *dev, uint8_t byte)
uart_write(dev->config.uart, &byte, 1);
}
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
static int _send(netdev_t *netdev, const iolist_t *iolist)
{
slipdev_t *dev = (slipdev_t *)netdev;
int bytes = 0;
DEBUG("slipdev: sending vector of length %u\n", count);
for (unsigned i = 0; i < count; i++) {
uint8_t *data = vector[i].iov_base;
DEBUG("slipdev: sending iolist\n");
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
uint8_t *data = iol->iol_base;
for (unsigned j = 0; j < vector[i].iov_len; j++, data++) {
for (unsigned j = 0; j < iol->iol_len; j++, data++) {
switch(*data) {
case SLIP_END:
/* escaping END byte*/
@ -223,4 +198,21 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *value,
return -ENOTSUP;
}
static const netdev_driver_t slip_driver = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};
void slipdev_setup(slipdev_t *dev, const slipdev_params_t *params)
{
/* set device descriptor fields */
memcpy(&dev->config, params, sizeof(dev->config));
dev->inesc = 0U;
dev->netdev.driver = &slip_driver;
}
/** @} */

View File

@ -34,7 +34,6 @@
#include "debug.h"
/* Internal helper functions */
static uint8_t _get_tx_len(const struct iovec *vector, unsigned count);
static int _set_state(sx127x_t *dev, netopt_state_t state);
static int _get_state(sx127x_t *dev, void *val);
void _on_dio0_irq(void *arg);
@ -42,24 +41,7 @@ void _on_dio1_irq(void *arg);
void _on_dio2_irq(void *arg);
void _on_dio3_irq(void *arg);
/* Netdev driver api functions */
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count);
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info);
static int _init(netdev_t *netdev);
static void _isr(netdev_t *netdev);
static int _get(netdev_t *netdev, netopt_t opt, void *val, size_t max_len);
static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t len);
const netdev_driver_t sx127x_driver = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
static int _send(netdev_t *netdev, const iolist_t *iolist)
{
sx127x_t *dev = (sx127x_t*) netdev;
@ -69,8 +51,8 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
return -ENOTSUP;
}
uint8_t size;
size = _get_tx_len(vector, count);
uint8_t size = iolist_size(iolist);
switch (dev->settings.modem) {
case SX127X_MODEM_FSK:
/* todo */
@ -91,8 +73,8 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
}
/* Write payload buffer */
for (size_t i = 0; i < count; i++) {
sx127x_write_fifo(dev, vector[i].iov_base, vector[i].iov_len);
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
sx127x_write_fifo(dev, iol->iol_base, iol->iol_len);
}
break;
default:
@ -489,17 +471,6 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t len)
return res;
}
static uint8_t _get_tx_len(const struct iovec *vector, unsigned count)
{
uint8_t len = 0;
for (unsigned i = 0 ; i < count ; i++) {
len += vector[i].iov_len;
}
return len;
}
static int _set_state(sx127x_t *dev, netopt_state_t state)
{
switch (state) {
@ -717,3 +688,12 @@ void _on_dio3_irq(void *arg)
break;
}
}
const netdev_driver_t sx127x_driver = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};

View File

@ -194,7 +194,7 @@ static uint16_t tx_upload(w5100_t *dev, uint16_t start, void *data, size_t len)
}
}
static int send(netdev_t *netdev, const struct iovec *vector, unsigned count)
static int send(netdev_t *netdev, const iolist_t *iolist)
{
w5100_t *dev = (w5100_t *)netdev;
int sum = 0;
@ -210,9 +210,10 @@ static int send(netdev_t *netdev, const struct iovec *vector, unsigned count)
pos = S0_TX_BASE;
}
for (unsigned i = 0; i < count; i++) {
pos = tx_upload(dev, pos, vector[i].iov_base, vector[i].iov_len);
sum += vector[i].iov_len;
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
size_t len = iol->iol_len;
pos = tx_upload(dev, pos, iol->iol_base, len);
sum += len;
}
waddr(dev, S0_TX_WR0, S0_TX_WR1, pos);

View File

@ -104,8 +104,6 @@ static int xbee_adpt_send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
{
int res;
size_t size;
size_t count;
gnrc_pktsnip_t *vec;
gnrc_netif_hdr_t *hdr;
uint8_t xhdr[XBEE_MAX_TXHDR_LENGTH];
@ -146,27 +144,23 @@ static int xbee_adpt_send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
}
}
/* now let's extract the iovector and send out the stuff */
vec = gnrc_pktbuf_get_iovec(pkt, &count);
if (vec != NULL) {
pkt = vec;
struct iovec *vector = (struct iovec *)pkt->data;
vector[0].iov_base = xhdr;
vector[0].iov_len = res;
/* now let's send out the stuff */
iolist_t iolist = {
.iol_next = (iolist_t *)pkt->next,
.iol_base = xhdr,
.iol_len = res
};
#ifdef MODULE_NETSTATS_L2
if (hdr->flags & BCAST) {
netif->dev->stats.tx_mcast_count++;
}
else {
netif->dev->stats.tx_unicast_count++;
}
#endif
DEBUG("[xbee-gnrc] send: triggering the drivers send function\n");
res = netif->dev->driver->send(netif->dev, vector, count);
if (hdr->flags & BCAST) {
netif->dev->stats.tx_mcast_count++;
}
else {
DEBUG("[xbee-gnrc] send: unable to create iovec\n");
netif->dev->stats.tx_unicast_count++;
}
#endif
DEBUG("[xbee-gnrc] send: triggering the drivers send function\n");
res = netif->dev->driver->send(netif->dev, &iolist);
gnrc_pktbuf_release(pkt);

View File

@ -634,21 +634,23 @@ int xbee_init(netdev_t *dev)
return 0;
}
static int xbee_send(netdev_t *dev, const struct iovec *vector, unsigned count)
static int xbee_send(netdev_t *dev, const iolist_t *iolist)
{
xbee_t *xbee = (xbee_t *)dev;
size_t size;
uint8_t csum;
assert(xbee && vector && (count > 0));
assert(xbee && iolist);
/* calculate the checksum and the packet size */
size = vector[0].iov_len;
csum = _cksum(3, (uint8_t *)vector[0].iov_base, size);
for (unsigned i = 1; i < count; i++) {
size += vector[i].iov_len;
for (size_t p = 0; p < vector[i].iov_len; p++) {
csum -= ((uint8_t *)vector[i].iov_base)[p];
size = iolist->iol_len;
csum = _cksum(3, (uint8_t *)iolist->iol_base, size);
for (const iolist_t *iol = iolist->iol_next; iol; iol = iol->iol_next) {
size_t len = iol->iol_len;
size += len;
for (size_t p = 0; p < len; p++) {
csum -= ((uint8_t *)iol->iol_base)[p];
}
}
@ -661,13 +663,13 @@ static int xbee_send(netdev_t *dev, const struct iovec *vector, unsigned count)
/* send the actual data packet */
DEBUG("[xbee] send: now sending out %i byte\n", (int)size);
mutex_lock(&(xbee->tx_lock));
for (unsigned i = 0; i < count; i++) {
uart_write(xbee->p.uart, vector[i].iov_base, vector[i].iov_len);
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
uart_write(xbee->p.uart, iol->iol_base, iol->iol_len);
}
uart_write(xbee->p.uart, &csum, 1);
mutex_unlock(&(xbee->tx_lock));
/* return number of payload byte */
/* return number of payload bytes */
return (int)size;
}

View File

@ -138,11 +138,11 @@ static int8_t _netdev_init(s_ns_t *p_ns)
static int8_t _netdev_send(const void *pr_payload, uint8_t c_len)
{
if (_dev != NULL) {
const struct iovec vector = {
.iov_base = (void *)pr_payload,
.iov_len = c_len
iolist_t iolist = {
.iol_base = (void *)pr_payload,
.iol_len = c_len,
};
if (_dev->driver->send(_dev, &vector, 1) < 0) {
if (_dev->driver->send(_dev, &iolist) < 0) {
DEBUG("Error on send\n");
return RADIO_TX_ERR;
}

View File

@ -185,15 +185,24 @@ static err_t _eth_link_output(struct netif *netif, struct pbuf *p)
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
LL_COUNT(p, q, count);
struct iovec pkt[count];
iolist_t iolist[count];
/* make last point to the last entry of iolist[] */
iolist_t *last = &iolist[count];
last--;
for (q = p, count = 0; q != NULL; q = q->next, count++) {
pkt[count].iov_base = q->payload;
pkt[count].iov_len = (size_t)q->len;
iolist_t *iol = &iolist[count];
iol->iol_next = (iol == last) ? NULL : &iolist[count + 1];
iol->iol_base = q->payload;
iol->iol_len = (size_t)q->len;
}
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
return (netdev->driver->send(netdev, pkt, count) > 0) ? ERR_OK : ERR_BUF;
return (netdev->driver->send(netdev, iolist) > 0) ? ERR_OK : ERR_BUF;
}
#endif
@ -202,12 +211,12 @@ static err_t _ieee802154_link_output(struct netif *netif, struct pbuf *p)
{
LWIP_ASSERT("p->next == NULL", p->next == NULL);
netdev_t *netdev = (netdev_t *)netif->state;
struct iovec pkt = {
.iov_base = p->payload,
.iov_len = (p->len - IEEE802154_FCS_LEN), /* FCS is written by driver */
iolist_t pkt = {
.iol_base = p->payload,
.iol_len = (p->len - IEEE802154_FCS_LEN), /* FCS is written by driver */
};
return (netdev->driver->send(netdev, &pkt, 1) > 0) ? ERR_OK : ERR_BUF;
return (netdev->driver->send(netdev, &pkt) > 0) ? ERR_OK : ERR_BUF;
}
#endif

View File

@ -297,14 +297,15 @@ void otPlatRadioSetDefaultTxPower(otInstance *aInstance, int8_t aPower)
ThreadError otPlatRadioTransmit(otInstance *aInstance, RadioPacket *aPacket)
{
(void) aInstance;
struct iovec pkt;
/* Populate iovec with transmit data
/* Populate iolist with transmit data
* Unlike RIOT, OpenThread includes two bytes FCS (0x00 0x00) so
* these bytes are removed
*/
pkt.iov_base = aPacket->mPsdu;
pkt.iov_len = aPacket->mLength - RADIO_IEEE802154_FCS_LEN;
iolist_t iolist = {
.iol_base = aPacket->mPsdu,
.iol_len = (aPacket->mLength - RADIO_IEEE802154_FCS_LEN)
};
/*Set channel and power based on transmit frame */
DEBUG("otPlatRadioTransmit->channel: %i, length %d\n", (int) aPacket->mChannel, (int)aPacket->mLength);
@ -316,7 +317,7 @@ ThreadError otPlatRadioTransmit(otInstance *aInstance, RadioPacket *aPacket)
_set_power(aPacket->mPower);
/* send packet though netdev */
_dev->driver->send(_dev, &pkt, 1);
_dev->driver->send(_dev, &iolist);
return kThreadError_None;
}

View File

@ -136,10 +136,11 @@ uint32_t SX127XGetTimeOnAir(RadioModems_t modem, uint8_t pktLen)
void SX127XSend(uint8_t *buffer, uint8_t size)
{
netdev_t *dev = (netdev_t *)&sx127x;
struct iovec vec[1];
vec[0].iov_base = buffer;
vec[0].iov_len = size;
dev->driver->send(dev, vec, 1);
iolist_t iol = {
.iol_base = buffer,
.iol_len = size
};
dev->driver->send(dev, &iol);
}
void SX127XSetSleep(void)

87
sys/include/iolist.h Normal file
View File

@ -0,0 +1,87 @@
/*
* Copyright (C) 2018 Kaspar Schleiser <kaspar@schleiser.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup sys_util_iolist iolist scatter / gather IO
* @ingroup sys_util
* @brief Provides linked-list scatter / gather IO
*
* @{
*
* @file
* @brief iolist scatter / gather IO
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
*/
#ifndef IOLIST_H
#define IOLIST_H
#include <unistd.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @brief iolist forward declaration */
typedef struct iolist iolist_t;
/**
* @brief iolist structure definition
*/
struct iolist {
iolist_t *iol_next; /**< ptr to next list entry */
void *iol_base; /**< ptr to this list entries data */
size_t iol_len; /**< size of data pointet to by ptr */
};
/**
* @brief Count number of entries in an iolist_t
*
* @param[in] iolist iolist to count
*
* @returns number of entries (zero for NULL parameter)
*/
unsigned iolist_count(const iolist_t *iolist);
/**
* @brief Sum up number of bytes in iolist
*
* This function returns the summed ip lenght values of all entries in @p
* iolist.
*
* @param[in] iolist iolist to sum up
*
* @returns summed up number of bytes or zero if @p iolist == NULL
*/
size_t iolist_size(const iolist_t *iolist);
/** @brief struct iovec anonymous declaration */
struct iovec;
/**
* @brief Create struct iovec from iolist
*
* This function fills an array of struct iovecs with the contents of @p
* iolist. It will write the number of used array entries into @p count.
*
* The caller *must* ensure that @p iov p points to an array of size >= count!
*
* @param[in] iolist iolist to read from
* @param[out] iov ptr to array of struct iovec that will be filled
* @param[out] count number of elements in @p iolist
*
* @returns iolist_size(iolist)
*/
size_t iolist_to_iovec(const iolist_t *iolist, struct iovec *iov, unsigned *count);
#ifdef __cplusplus
}
#endif
#endif /* IOLIST_H */
/** @} */

View File

@ -87,8 +87,7 @@ extern const csma_sender_conf_t CSMA_SENDER_CONF_DEFAULT;
* CSMA/CA, this feature is used. Otherwise, a software procedure is used.
*
* @param[in] dev netdev device, needs to be already initialized
* @param[in] vector pointer to the data
* @param[in] count number of elements in @p vector
* @param[in] iolist pointer to the data
* @param[in] conf configuration for the backoff;
* will be set to @ref CSMA_SENDER_CONF_DEFAULT if NULL.
*
@ -101,8 +100,8 @@ extern const csma_sender_conf_t CSMA_SENDER_CONF_DEFAULT;
* @return -EBUSY if radio medium never was available
* to send the given data
*/
int csma_sender_csma_ca_send(netdev_t *dev, struct iovec *vector,
unsigned count, const csma_sender_conf_t *conf);
int csma_sender_csma_ca_send(netdev_t *dev, iolist_t *iolist,
const csma_sender_conf_t *conf);
/**
* @brief Sends a 802.15.4 frame when medium is avaiable.
@ -121,8 +120,7 @@ int csma_sender_csma_ca_send(netdev_t *dev, struct iovec *vector,
* @ref csma_sender_csma_ca_send().
*
* @param[in] dev netdev device, needs to be already initialized
* @param[in] vector pointer to the data
* @param[in] count number of elements in @p vector
* @param[in] iolist pointer to the data
*
* @return number of bytes that were actually send out
* @return -ENODEV if @p dev is invalid
@ -133,7 +131,7 @@ int csma_sender_csma_ca_send(netdev_t *dev, struct iovec *vector,
* @return -EBUSY if radio medium was not available
* to send the given data
*/
int csma_sender_cca_send(netdev_t *dev, struct iovec *vector, unsigned count);
int csma_sender_cca_send(netdev_t *dev, iolist_t *iolist);
#ifdef __cplusplus

View File

@ -96,20 +96,25 @@ extern "C" {
* | * L2 header 3
* * L2 header 4
*
* The first three fields (next, data, size) match iolist_t (named iol_next,
* iol_base and iol_len there). That means that any pktsnip can be casted to
* iolist_t for direct passing to e.g., netdev send() functions.
*
* @note This type has no initializer on purpose. Please use @ref net_gnrc_pktbuf
* as factory.
*/
/* packed to be aligned correctly in the static packet buffer */
typedef struct gnrc_pktsnip {
/* the first three fields *MUST* match iolist_t! */
struct gnrc_pktsnip *next; /**< next snip in the packet */
void *data; /**< pointer to the data of the snip */
size_t size; /**< the length of the snip in byte */
/**
* @brief Counter of threads currently having control over this packet.
*
* @internal
*/
unsigned int users;
struct gnrc_pktsnip *next; /**< next snip in the packet */
void *data; /**< pointer to the data of the snip */
size_t size; /**< the length of the snip in byte */
gnrc_nettype_t type; /**< protocol of the packet snip */
#ifdef MODULE_GNRC_NETERR
kernel_pid_t err_sub; /**< subscriber to errors related to this

View File

@ -33,11 +33,10 @@
* static uint32_t sum = 0;
* static mutex_t wait = MUTEX_INIT;
*
* int _send_timer(netdev_t *dev, const struct iovec *vector, int count)
* int _send_timer(netdev_t *dev, const iolist_t *iolist)
* {
* (void)dev;
* (void)vector;
* (void)count;
* (void)iolist;
*
* sum += (xtimer_now_usec() - last_start);
* mutex_unlock(&wait);
@ -95,15 +94,12 @@ extern "C" {
* @brief Callback type to handle send command
*
* @param[in] dev network device descriptor
* @param[in] vector io vector array to send
* @param[in] count number of entries in vector
* @param[in] iolist io vector list to send
*
* @return number of bytes sent
* @return <= 0 on error
*/
typedef int (*netdev_test_send_cb_t)(netdev_t *dev,
const struct iovec *vector,
int count);
typedef int (*netdev_test_send_cb_t)(netdev_t *dev, const iolist_t *iolist);
/**
* @brief Callback type to handle receive command

1
sys/iolist/Makefile Normal file
View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

61
sys/iolist/iolist.c Normal file
View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2018 Kaspar Schleiser <kaspar@schleiser.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup sys_util
* @{
*
* @file
* @brief iolist scatter / gather IO
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @}
*/
#include <sys/uio.h>
#include "iolist.h"
unsigned iolist_count(const iolist_t *iolist)
{
unsigned count = 0;
while (iolist) {
count++;
iolist = iolist->iol_next;
}
return count;
}
size_t iolist_size(const iolist_t *iolist)
{
size_t result = 0;
while (iolist) {
result += iolist->iol_len;
iolist = iolist->iol_next;
}
return result;
}
size_t iolist_to_iovec(const iolist_t *iolist, struct iovec *iov, unsigned *count)
{
size_t bytes = 0;
unsigned _count = 0;
while (iolist) {
iov->iov_base = iolist->iol_base;
iov->iov_len = iolist->iol_len;
bytes += iov->iov_len;
_count++;
iolist = iolist->iol_next;
iov++;
}
*count = _count;
return bytes;
}

View File

@ -50,10 +50,9 @@ int _gnrc_gomach_transmit(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
netdev_t *dev = netif->dev;
netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev;
gnrc_netif_hdr_t *netif_hdr;
gnrc_pktsnip_t *vec_snip;
const uint8_t *src, *dst = NULL;
int res = 0;
size_t n, src_len, dst_len;
size_t src_len, dst_len;
uint8_t mhr[IEEE802154_MAX_HDR_LEN];
uint8_t flags = (uint8_t)(state->flags & NETDEV_IEEE802154_SEND_MASK);
le_uint16_t dev_pan = byteorder_btols(byteorder_htons(state->pan));
@ -93,38 +92,34 @@ int _gnrc_gomach_transmit(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
DEBUG("_send_ieee802154: Error preperaring frame\n");
return -EINVAL;
}
/* prepare packet for sending */
vec_snip = gnrc_pktbuf_get_iovec(pkt, &n);
if (vec_snip != NULL) {
struct iovec *vector;
pkt = vec_snip; /* reassign for later release; vec_snip is prepended to pkt */
vector = (struct iovec *)pkt->data;
vector[0].iov_base = mhr;
vector[0].iov_len = (size_t)res;
/* prepare packet for sending */
iolist_t iolist = {
.iol_next = (iolist_t *)pkt->next,
.iol_base = mhr,
.iol_len = (size_t)res
};
#ifdef MODULE_NETSTATS_L2
if (netif_hdr->flags &
if (netif_hdr->flags &
(GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
netif->dev->stats.tx_mcast_count++;
}
else {
netif->dev->stats.tx_unicast_count++;
}
#endif
#ifdef MODULE_GNRC_MAC
if (netif->mac.mac_info & GNRC_NETIF_MAC_INFO_CSMA_ENABLED) {
res = csma_sender_csma_ca_send(dev, vector, n, &netif->mac.csma_conf);
}
else {
res = dev->driver->send(dev, vector, n);
}
#else
res = dev->driver->send(dev, vector, n);
#endif
netif->dev->stats.tx_mcast_count++;
}
else {
return -ENOBUFS;
netif->dev->stats.tx_unicast_count++;
}
#endif
#ifdef MODULE_GNRC_MAC
if (netif->mac.mac_info & GNRC_NETIF_MAC_INFO_CSMA_ENABLED) {
res = csma_sender_csma_ca_send(dev, &iolist, &netif->mac.csma_conf);
}
else {
res = dev->driver->send(dev, &iolist);
}
#else
res = dev->driver->send(dev, &iolist);
#endif
/* release old data */
gnrc_pktbuf_release(pkt);
return res;

View File

@ -37,10 +37,9 @@ int _gnrc_lwmac_transmit(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
netdev_t *dev = netif->dev;
netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev;
gnrc_netif_hdr_t *netif_hdr;
gnrc_pktsnip_t *vec_snip;
const uint8_t *src, *dst = NULL;
int res = 0;
size_t n, src_len, dst_len;
size_t src_len, dst_len;
uint8_t mhr[IEEE802154_MAX_HDR_LEN];
uint8_t flags = (uint8_t)(state->flags & NETDEV_IEEE802154_SEND_MASK);
le_uint16_t dev_pan = byteorder_btols(byteorder_htons(state->pan));
@ -80,38 +79,34 @@ int _gnrc_lwmac_transmit(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
DEBUG("_send_ieee802154: Error preperaring frame\n");
return -EINVAL;
}
/* prepare packet for sending */
vec_snip = gnrc_pktbuf_get_iovec(pkt, &n);
if (vec_snip != NULL) {
struct iovec *vector;
pkt = vec_snip; /* reassign for later release; vec_snip is prepended to pkt */
vector = (struct iovec *)pkt->data;
vector[0].iov_base = mhr;
vector[0].iov_len = (size_t)res;
/* prepare packet for sending */
iolist_t iolist = {
.iol_next = (iolist_t *)pkt->next,
.iol_base = mhr,
.iol_len = (size_t)res
};
#ifdef MODULE_NETSTATS_L2
if (netif_hdr->flags &
if (netif_hdr->flags &
(GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
netif->dev->stats.tx_mcast_count++;
}
else {
netif->dev->stats.tx_unicast_count++;
}
#endif
#ifdef MODULE_GNRC_MAC
if (netif->mac.mac_info & GNRC_NETIF_MAC_INFO_CSMA_ENABLED) {
res = csma_sender_csma_ca_send(dev, vector, n, &netif->mac.csma_conf);
}
else {
res = dev->driver->send(dev, vector, n);
}
#else
res = dev->driver->send(dev, vector, n);
#endif
netif->dev->stats.tx_mcast_count++;
}
else {
return -ENOBUFS;
netif->dev->stats.tx_unicast_count++;
}
#endif
#ifdef MODULE_GNRC_MAC
if (netif->mac.mac_info & GNRC_NETIF_MAC_INFO_CSMA_ENABLED) {
res = csma_sender_csma_ca_send(dev, &iolist, &netif->mac.csma_conf);
}
else {
res = dev->driver->send(dev, &iolist);
}
#else
res = dev->driver->send(dev, &iolist);
#endif
/* release old data */
gnrc_pktbuf_release(pkt);
return res;

View File

@ -135,26 +135,22 @@ static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
hdr.dst[0], hdr.dst[1], hdr.dst[2],
hdr.dst[3], hdr.dst[4], hdr.dst[5]);
size_t n;
payload = gnrc_pktbuf_get_iovec(pkt, &n); /* use payload as temporary
* variable */
res = -ENOBUFS;
if (payload != NULL) {
pkt = payload; /* reassign for later release; vec_snip is prepended to pkt */
struct iovec *vector = (struct iovec *)pkt->data;
vector[0].iov_base = (char *)&hdr;
vector[0].iov_len = sizeof(ethernet_hdr_t);
iolist_t iolist = {
.iol_next = (iolist_t *)payload,
.iol_base = &hdr,
.iol_len = sizeof(ethernet_hdr_t)
};
#ifdef MODULE_NETSTATS_L2
if ((netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) ||
(netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
dev->stats.tx_mcast_count++;
}
else {
dev->stats.tx_unicast_count++;
}
#endif
res = dev->driver->send(dev, vector, n);
if ((netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) ||
(netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
dev->stats.tx_mcast_count++;
}
else {
dev->stats.tx_unicast_count++;
}
#endif
res = dev->driver->send(dev, &iolist);
gnrc_pktbuf_release(pkt);

View File

@ -168,10 +168,9 @@ static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
netdev_t *dev = netif->dev;
netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev;
gnrc_netif_hdr_t *netif_hdr;
gnrc_pktsnip_t *vec_snip;
const uint8_t *src, *dst = NULL;
int res = 0;
size_t n, src_len, dst_len;
size_t src_len, dst_len;
uint8_t mhr[IEEE802154_MAX_HDR_LEN];
uint8_t flags = (uint8_t)(state->flags & NETDEV_IEEE802154_SEND_MASK);
le_uint16_t dev_pan = byteorder_btols(byteorder_htons(state->pan));
@ -211,38 +210,34 @@ static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
DEBUG("_send_ieee802154: Error preperaring frame\n");
return -EINVAL;
}
/* prepare packet for sending */
vec_snip = gnrc_pktbuf_get_iovec(pkt, &n);
if (vec_snip != NULL) {
struct iovec *vector;
pkt = vec_snip; /* reassign for later release; vec_snip is prepended to pkt */
vector = (struct iovec *)pkt->data;
vector[0].iov_base = mhr;
vector[0].iov_len = (size_t)res;
/* prepare iolist for netdev / mac layer */
iolist_t iolist = {
.iol_next = (iolist_t *)pkt->next,
.iol_base = mhr,
.iol_len = (size_t)res
};
#ifdef MODULE_NETSTATS_L2
if (netif_hdr->flags &
(GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
netif->dev->stats.tx_mcast_count++;
}
else {
netif->dev->stats.tx_unicast_count++;
}
#endif
#ifdef MODULE_GNRC_MAC
if (netif->mac.mac_info & GNRC_NETIF_MAC_INFO_CSMA_ENABLED) {
res = csma_sender_csma_ca_send(dev, vector, n, &netif->mac.csma_conf);
}
else {
res = dev->driver->send(dev, vector, n);
}
#else
res = dev->driver->send(dev, vector, n);
#endif
(GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
netif->dev->stats.tx_mcast_count++;
}
else {
return -ENOBUFS;
netif->dev->stats.tx_unicast_count++;
}
#endif
#ifdef MODULE_GNRC_MAC
if (netif->mac.mac_info & GNRC_NETIF_MAC_INFO_CSMA_ENABLED) {
res = csma_sender_csma_ca_send(dev, &iolist, &netif->mac.csma_conf);
}
else {
res = dev->driver->send(dev, &iolist);
}
#else
res = dev->driver->send(dev, &iolist);
#endif
/* release old data */
gnrc_pktbuf_release(pkt);
return res;

View File

@ -92,27 +92,20 @@ static gnrc_pktsnip_t *_recv(gnrc_netif_t *netif)
static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
{
gnrc_pktsnip_t *vector;
int res = -ENOBUFS;
size_t n;
if (pkt->type == GNRC_NETTYPE_NETIF) {
/* we don't need the netif snip: remove it */
pkt = gnrc_pktbuf_remove_snip(pkt, pkt);
}
/* prepare packet for sending */
vector = gnrc_pktbuf_get_iovec(pkt, &n);
if (vector != NULL) {
/* reassign for later release; vector is prepended to pkt */
pkt = vector;
struct iovec *v = (struct iovec *)vector->data;
netdev_t *dev = netif->dev;
netdev_t *dev = netif->dev;
#ifdef MODULE_NETSTATS_L2
dev->stats.tx_unicast_count++;
dev->stats.tx_unicast_count++;
#endif
res = dev->driver->send(dev, v, n);
}
res = dev->driver->send(dev, (iolist_t *)pkt);
/* release old data */
gnrc_pktbuf_release(pkt);
return res;

View File

@ -78,8 +78,7 @@ static inline uint32_t choose_backoff_period(int be,
* @brief Perform a CCA and send the given packet if medium is available
*
* @param[in] device netdev device, needs to be already initialized
* @param[in] vector pointer to the data
* @param[in] count number of elements in @p vector
* @param[in] iolist pointer to the data
*
* @return the return value of device driver's
* netdev_driver_t::send() function if medium was
@ -88,7 +87,7 @@ static inline uint32_t choose_backoff_period(int be,
* @return -EBUSY if radio medium was not available
* to send the given data
*/
static int send_if_cca(netdev_t *device, struct iovec *vector, unsigned count)
static int send_if_cca(netdev_t *device, iolist_t *iolist)
{
netopt_enable_t hwfeat;
@ -107,7 +106,7 @@ static int send_if_cca(netdev_t *device, struct iovec *vector, unsigned count)
/* if medium is clear, send the packet and return */
if (hwfeat == NETOPT_ENABLE) {
DEBUG("csma: Radio medium available: sending packet.\n");
return device->driver->send(device, vector, count);
return device->driver->send(device, iolist);
}
/* if we arrive here, medium was not available for transmission */
@ -117,8 +116,8 @@ static int send_if_cca(netdev_t *device, struct iovec *vector, unsigned count)
/*------------------------- "EXPORTED" FUNCTIONS -------------------------*/
int csma_sender_csma_ca_send(netdev_t *dev, struct iovec *vector,
unsigned count, const csma_sender_conf_t *conf)
int csma_sender_csma_ca_send(netdev_t *dev, iolist_t *iolist,
const csma_sender_conf_t *conf)
{
netopt_enable_t hwfeat;
@ -153,7 +152,7 @@ int csma_sender_csma_ca_send(netdev_t *dev, struct iovec *vector,
if (ok) {
/* device does CSMA/CA all by itself: let it do its job */
DEBUG("csma: Network device does hardware CSMA/CA\n");
return dev->driver->send(dev, vector, count);
return dev->driver->send(dev, iolist);
}
/* if we arrive here, then we must perform the CSMA/CA procedure
@ -169,7 +168,7 @@ int csma_sender_csma_ca_send(netdev_t *dev, struct iovec *vector,
xtimer_usleep(bp);
/* try to send after a CCA */
res = send_if_cca(dev, vector, count);
res = send_if_cca(dev, iolist);
if (res >= 0) {
/* TX done */
return res;
@ -195,7 +194,7 @@ int csma_sender_csma_ca_send(netdev_t *dev, struct iovec *vector,
}
int csma_sender_cca_send(netdev_t *dev, struct iovec *vector, unsigned count)
int csma_sender_cca_send(netdev_t *dev, iolist_t *iolist)
{
netopt_enable_t hwfeat;
@ -226,12 +225,12 @@ int csma_sender_cca_send(netdev_t *dev, struct iovec *vector, unsigned count)
if (ok) {
/* device does auto-CCA: let him do its job */
DEBUG("csma: Network device does auto-CCA checking.\n");
return dev->driver->send(dev, vector, count);
return dev->driver->send(dev, iolist);
}
/* if we arrive here, we must do CCA ourselves to see if radio medium
is clear before sending */
res = send_if_cca(dev, vector, count);
res = send_if_cca(dev, iolist);
if (res == -EBUSY) {
DEBUG("csma: Transmission cancelled!\n");
}

View File

@ -19,32 +19,6 @@
#include "net/netdev_test.h"
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count);
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info);
static int _init(netdev_t *dev);
static void _isr(netdev_t *dev);
static int _get(netdev_t *dev, netopt_t opt, void *value, size_t max_len);
static int _set(netdev_t *dev, netopt_t opt, const void *value, size_t value_len);
static const netdev_driver_t _driver = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};
void netdev_test_setup(netdev_test_t *dev, void *state)
{
netdev_t *netdev = (netdev_t *)dev;
netdev->driver = &_driver;
dev->state = state;
mutex_init(&dev->mutex);
netdev_test_reset(dev);
}
void netdev_test_reset(netdev_test_t *dev)
{
mutex_lock(&dev->mutex);
@ -57,14 +31,14 @@ void netdev_test_reset(netdev_test_t *dev)
mutex_unlock(&dev->mutex);
}
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
static int _send(netdev_t *netdev, const iolist_t *iolist)
{
netdev_test_t *dev = (netdev_test_t *)netdev;
int res = (int)count; /* assume everything would be fine */
int res = -EINVAL;
mutex_lock(&dev->mutex);
if (dev->send_cb != NULL) {
res = dev->send_cb(netdev, vector, count);
res = dev->send_cb(netdev, iolist);
}
mutex_unlock(&dev->mutex);
return res;
@ -140,5 +114,23 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *value, size_t value_
return res;
}
static const netdev_driver_t _driver = {
.send = _send,
.recv = _recv,
.init = _init,
.isr = _isr,
.get = _get,
.set = _set,
};
void netdev_test_setup(netdev_test_t *dev, void *state)
{
netdev_t *netdev = (netdev_t *)dev;
netdev->driver = &_driver;
dev->state = state;
mutex_init(&dev->mutex);
netdev_test_reset(dev);
}
/** @} */

View File

@ -250,7 +250,6 @@ static int send(int iface, le_uint16_t dst_pan, uint8_t *dst, size_t dst_len,
{
int res;
netdev_ieee802154_t *dev;
struct iovec vector[MAC_VECTOR_SIZE];
uint8_t *src;
size_t src_len;
uint8_t mhr[IEEE802154_MAX_HDR_LEN];
@ -262,11 +261,14 @@ static int send(int iface, le_uint16_t dst_pan, uint8_t *dst, size_t dst_len,
return 1;
}
iolist_t iol_data = {
.iol_base = data,
.iol_len = strlen(data)
};
dev = (netdev_ieee802154_t *)&devs[iface];
flags = (uint8_t)(dev->flags & NETDEV_IEEE802154_SEND_MASK);
flags |= IEEE802154_FCF_TYPE_DATA;
vector[1].iov_base = data;
vector[1].iov_len = strlen(data);
src_pan = byteorder_btols(byteorder_htons(dev->pan));
if (dst_pan.u16 == 0) {
dst_pan = src_pan;
@ -287,15 +289,20 @@ static int send(int iface, le_uint16_t dst_pan, uint8_t *dst, size_t dst_len,
puts("txtsnd: Error preperaring frame");
return 1;
}
vector[0].iov_base = mhr;
vector[0].iov_len = (size_t)res;
res = dev->netdev.driver->send((netdev_t *)dev, vector, MAC_VECTOR_SIZE);
iolist_t iol_hdr = {
.iol_next = &iol_data,
.iol_base = mhr,
.iol_len = (size_t)res
};
res = dev->netdev.driver->send((netdev_t *)dev, &iol_hdr);
if (res < 0) {
puts("txtsnd: Error on sending");
return 1;
}
else {
printf("txtsnd: send %u bytes to ", (unsigned)vector[1].iov_len);
printf("txtsnd: send %u bytes to ", (unsigned)iol_data.iol_len);
print_addr(dst, dst_len);
printf(" (PAN: ");
print_addr((uint8_t *)&dst_pan, sizeof(dst_pan));

View File

@ -224,10 +224,12 @@ int send_cmd(int argc, char **argv)
printf("sending \"%s\" payload (%d bytes)\n",
argv[1], strlen(argv[1]) + 1);
struct iovec vec[1];
vec[0].iov_base = argv[1];
vec[0].iov_len = strlen(argv[1]) + 1;
if (netdev->driver->send(netdev, vec, 1) == -ENOTSUP) {
iolist_t iolist = {
.iol_base = argv[1],
.iol_len = (strlen(argv[1]) + 1)
};
if (netdev->driver->send(netdev, &iolist) == -ENOTSUP) {
puts("Cannot send: radio is still transmitting");
}

View File

@ -37,8 +37,7 @@ static msg_t _main_msg_queue[MSG_QUEUE_SIZE];
static uint8_t tmp_buffer[ETHERNET_DATA_LEN];
static size_t tmp_buffer_bytes = 0;
static int _dump_send_packet(netdev_t *netdev, const struct iovec *vector,
int count)
static int _dump_send_packet(netdev_t *netdev, const iolist_t *iolist)
{
int res;
@ -55,13 +54,13 @@ static int _dump_send_packet(netdev_t *netdev, const struct iovec *vector,
printf("unknown ");
}
puts("device:");
for (int i = 0; i < count; i++) {
if ((tmp_buffer_bytes + vector[i].iov_len) > ETHERNET_DATA_LEN) {
for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
size_t len = iol->iol_len;
if ((tmp_buffer_bytes + len) > ETHERNET_DATA_LEN) {
return -ENOBUFS;
}
memcpy(&tmp_buffer[tmp_buffer_bytes], vector[i].iov_base,
vector[i].iov_len);
tmp_buffer_bytes += vector[i].iov_len;
memcpy(&tmp_buffer[tmp_buffer_bytes], iol->iol_base, len);
tmp_buffer_bytes += len;
}
od_hex_dump(tmp_buffer, tmp_buffer_bytes, OD_WIDTH_DEFAULT);
res = (int)tmp_buffer_bytes;

View File

@ -141,16 +141,16 @@ static int _netdev_recv(netdev_t *dev, char *buf, int len, void *info)
return res;
}
static int _netdev_send(netdev_t *dev, const struct iovec *vector, int count)
static int _netdev_send(netdev_t *dev, const iolist_t *iolist)
{
msg_t done = { .type = _SEND_DONE };
unsigned offset = 0;
(void)dev;
mutex_lock(&_netdev_buffer_mutex);
for (int i = 0; i < count; i++) {
memcpy(&_netdev_buffer[offset], vector[i].iov_base, vector[i].iov_len);
offset += vector[i].iov_len;
for (; iolist; iolist = iolist->iol_next) {
memcpy(&_netdev_buffer[offset], iolist->iol_base, iolist->iol_len);
offset += iolist->iol_len;
if (offset > sizeof(_netdev_buffer)) {
mutex_unlock(&_netdev_buffer_mutex);
return -ENOBUFS;

View File

@ -143,16 +143,16 @@ static int _netdev_recv(netdev_t *dev, char *buf, int len, void *info)
return res;
}
static int _netdev_send(netdev_t *dev, const struct iovec *vector, int count)
static int _netdev_send(netdev_t *dev, const iolist_t *iolist)
{
msg_t done = { .type = _SEND_DONE };
unsigned offset = 0;
(void)dev;
mutex_lock(&_netdev_buffer_mutex);
for (int i = 0; i < count; i++) {
memcpy(&_netdev_buffer[offset], vector[i].iov_base, vector[i].iov_len);
offset += vector[i].iov_len;
for (; iolist; iolist = iolist->iol_next) {
memcpy(&_netdev_buffer[offset], iolist->iol_base, iolist->iol_len);
offset += iolist->iol_len;
if (offset > sizeof(_netdev_buffer)) {
mutex_unlock(&_netdev_buffer_mutex);
return -ENOBUFS;

View File

@ -61,7 +61,7 @@ static uint8_t _tmp_len = 0;
static void _dev_isr(netdev_t *dev);
static int _dev_recv(netdev_t *dev, char *buf, int len, void *info);
static int _dev_send(netdev_t *dev, const struct iovec *vector, int count);
static int _dev_send(netdev_t *dev, const iolist_t *iolist);
static int _dev_get_addr(netdev_t *dev, void *value, size_t max_len);
static int _dev_set_addr(netdev_t *dev, const void *value, size_t max_len);
@ -296,26 +296,26 @@ static int _dev_recv(netdev_t *dev, char *buf, int len, void *info)
}
}
static int _dev_send(netdev_t *dev, const struct iovec *vector, int count)
static int _dev_send(netdev_t *dev, const iolist_t *iolist)
{
int idx = 0;
(void)dev;
/* check packet content with expected data */
for (int i = 0; i < count; i++) {
if (memcmp(&(_tmp[idx]), vector[i].iov_base, vector[i].iov_len) != 0) {
printf("Unexpected send data (vector index = %d)\n", i);
for (; iolist; iolist = iolist->iol_next) {
if (memcmp(&(_tmp[idx]), iolist->iol_base, iolist->iol_len) != 0) {
puts("Unexpected send data:");
puts("===========================================================");
puts("expected");
puts("===========================================================");
od_hex_dump(&_tmp[idx], vector[i].iov_len, OD_WIDTH_DEFAULT);
od_hex_dump(&_tmp[idx], iolist->iol_len, OD_WIDTH_DEFAULT);
puts("===========================================================");
puts("send data");
puts("===========================================================");
od_hex_dump(vector[i].iov_base, vector[i].iov_len, OD_WIDTH_DEFAULT);
od_hex_dump(iolist->iol_base, iolist->iol_len, OD_WIDTH_DEFAULT);
return -EINVAL;
}
idx += vector[i].iov_len;
idx += iolist->iol_len;
}
if (idx != _tmp_len) {
printf("Unexpected send length: %d (expected: %d)\n", idx, _tmp_len);

View File

@ -56,29 +56,29 @@ static void test_init(void)
_print_info(netdev);
}
static void test_send__vector_NULL__count_0(void)
static void test_send__iolist_NULL(void)
{
netdev_t *netdev = (netdev_t *)(&_dev);
int res;
puts("Send zero-length packet");
res = netdev->driver->send(netdev, NULL, 0);
int res = netdev->driver->send(netdev, NULL);
assert((res < 0) || (res == 0));
if ((res < 0) && (errno == ECONNREFUSED)) {
puts("No remote socket exists (use scripts in `tests/` to have proper tests)");
}
}
static void test_send__vector_not_NULL__count_2(void)
static void test_send__iolist_not_NULL(void)
{
struct iovec vector[] = { { .iov_base = "Hello", .iov_len = sizeof("Hello") },
{ .iov_base = "World", .iov_len = sizeof("World") } };
iolist_t iolist[] = { { .iol_base = "Hello", .iol_len = sizeof("Hello") },
{ .iol_base = "World", .iol_len = sizeof("World") } };
iolist[0].iol_next = &iolist[1];
netdev_t *netdev = (netdev_t *)(&_dev);
int res;
puts("Send 'Hello\\0World\\0'");
res = netdev->driver->send(netdev, vector,
sizeof(vector) / sizeof(struct iovec));
int res = netdev->driver->send(netdev, iolist);
assert((res < 0) || (res == (sizeof("Hello")) + sizeof("World")));
if ((res < 0) && (errno == ECONNREFUSED)) {
puts("No remote socket exists (use scripts in `tests/` to have proper tests)");
@ -109,8 +109,8 @@ int main(void)
_main_pid = sched_active_pid;
test_init();
test_send__vector_NULL__count_0();
test_send__vector_not_NULL__count_2();
test_send__iolist_NULL();
test_send__iolist_not_NULL();
test_recv(); /* does not return */
puts("ALL TESTS SUCCESSFUL");
return 0;

View File

@ -13,21 +13,27 @@
* @file
*/
#include <errno.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "embUnit/embUnit.h"
#include "net/gnrc/pkt.h"
#include "net/gnrc/nettype.h"
#include "iolist.h"
#include "unittests-constants.h"
#include "tests-pkt.h"
#define _INIT_ELEM(len, data, next) \
{ 1, (next), (data), (len), GNRC_NETTYPE_UNDEF }
#define _INIT_ELEM(len, _data, _next) \
{ .users = 1, .next = (_next), .data = (_data), \
.size = (len), .type = GNRC_NETTYPE_UNDEF \
}
#define _INIT_ELEM_STATIC_DATA(data, next) _INIT_ELEM(sizeof(data), data, next)
#define _INIT_ELEM_STATIC_TYPE(type, next) \
{ 1, (next), NULL, 0, (type) }
#define _INIT_ELEM_STATIC_TYPE(_type, _next) \
{ .users = 1, .next = (_next), .data = NULL, .size = 0, .type = (_type) }
static void test_pkt_len__NULL(void)
{
@ -129,6 +135,40 @@ static void test_pktsnip_search_type(void)
TEST_ASSERT_NULL(gnrc_pktsnip_search_type(&snip3, GNRC_NETTYPE_NUMOF));
}
static void test_pkt_equals_iolist(void)
{
iolist_t iol;
gnrc_pktsnip_t pkt;
memset(&iol, '\0', sizeof(iol));
memset(&pkt, '\0', sizeof(pkt));
/* compare empty structs */
TEST_ASSERT_EQUAL_INT(0, memcmp(&iol, &pkt, sizeof(iol)));
/* check next pointer position */
iol.iol_next = (void *)0xAAAAAAAA;
pkt.next = (void *)0xAAAAAAAA;
TEST_ASSERT_EQUAL_INT(0, memcmp(&iol, &pkt, sizeof(iol)));
/* check data pointer position */
iol.iol_base = &iol;
pkt.data = &iol;
TEST_ASSERT_EQUAL_INT(0, memcmp(&iol, &pkt, sizeof(iol)));
/* check size position */
iol.iol_len = 0x12345678;
pkt.size = 0x12345678;
TEST_ASSERT_EQUAL_INT(0, memcmp(&iol, &pkt, sizeof(iol)));
TEST_ASSERT_EQUAL_INT(offsetof(iolist_t, iol_next), offsetof(gnrc_pktsnip_t, next));
TEST_ASSERT_EQUAL_INT(offsetof(iolist_t, iol_base), offsetof(gnrc_pktsnip_t, data));
TEST_ASSERT_EQUAL_INT(offsetof(iolist_t, iol_len), offsetof(gnrc_pktsnip_t, size));
}
Test *tests_pkt_tests(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
@ -143,6 +183,7 @@ Test *tests_pkt_tests(void)
new_TestFixture(test_pkt_count__5_elem),
new_TestFixture(test_pkt_count__null),
new_TestFixture(test_pktsnip_search_type),
new_TestFixture(test_pkt_equals_iolist),
};
EMB_UNIT_TESTCALLER(pkt_tests, NULL, NULL, fixtures);

View File

@ -321,7 +321,7 @@ static void test_pktbuf_mark__pkt_NOT_NULL__size_greater_than_pkt_size(void)
static void test_pktbuf_mark__pkt_NOT_NULL__pkt_data_NULL(void)
{
gnrc_pktsnip_t pkt = { 1, NULL, NULL, sizeof(TEST_STRING16), GNRC_NETTYPE_TEST };
gnrc_pktsnip_t pkt = { NULL, NULL, sizeof(TEST_STRING16), 1, GNRC_NETTYPE_TEST };
TEST_ASSERT_NULL(gnrc_pktbuf_mark(&pkt, sizeof(TEST_STRING16) - 1,
GNRC_NETTYPE_TEST));
@ -661,7 +661,7 @@ static void test_pktbuf_hold__pkt_null(void)
static void test_pktbuf_hold__pkt_external(void)
{
gnrc_pktsnip_t pkt = { 1, NULL, TEST_STRING8, sizeof(TEST_STRING8), GNRC_NETTYPE_TEST };
gnrc_pktsnip_t pkt = { NULL, TEST_STRING8, sizeof(TEST_STRING8), 1, GNRC_NETTYPE_TEST };
gnrc_pktbuf_hold(&pkt, 1);
TEST_ASSERT(gnrc_pktbuf_is_empty());

View File

@ -22,7 +22,7 @@
#include "tests-pktqueue.h"
#define PKT_INIT_ELEM(len, data, next) \
{ 1, (next), (data), (len), GNRC_NETTYPE_UNDEF }
{ (next), (data), (len), 1, GNRC_NETTYPE_UNDEF }
#define PKT_INIT_ELEM_STATIC_DATA(data, next) PKT_INIT_ELEM(sizeof(data), data, next)
#define PKTQUEUE_INIT_ELEM(pkt) { NULL, pkt }

View File

@ -23,7 +23,7 @@
#include "tests-priority_pktqueue.h"
#define PKT_INIT_ELEM(len, data, next) \
{ 1, (next), (data), (len), GNRC_NETTYPE_UNDEF }
{ (next), (data), (len), 1, GNRC_NETTYPE_UNDEF }
#define PKT_INIT_ELEM_STATIC_DATA(data, next) PKT_INIT_ELEM(sizeof(data), data, next)
#define PKTQUEUE_INIT_ELEM(pkt) { NULL, pkt }