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))) ifneq (,$(filter netdev_tap,$(USEMODULE)))
USEMODULE += netif USEMODULE += netif
USEMODULE += netdev_eth USEMODULE += netdev_eth
USEMODULE += iolist
endif endif
ifneq (,$(filter gnrc_tftp,$(USEMODULE))) ifneq (,$(filter gnrc_tftp,$(USEMODULE)))

View File

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

View File

@ -33,22 +33,6 @@
#define _MAX_MHR_OVERHEAD (25) #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 */ /* Reference pointer for the IRQ handler */
static netdev_t *_dev; 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; 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; (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 */ start of the FIFO, so we can come back and update it later */
rfcore_write_byte(0); rfcore_write_byte(0);
for (unsigned i = 0; i < count; i++) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
pkt_len += vector[i].iov_len; pkt_len += iol->iol_len;
if (pkt_len > CC2538_RF_MAX_DATA_LEN) { if (pkt_len > CC2538_RF_MAX_DATA_LEN) {
DEBUG("cc2538_rf: packet too large (%u > %u)\n", 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; 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 #ifdef MODULE_NETSTATS_L2
@ -407,3 +391,12 @@ static int _init(netdev_t *netdev)
return 0; 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 <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/uio.h>
#include <unistd.h> #include <unistd.h>
/* needs to be included before native's declarations of ntohl etc. */ /* needs to be included before native's declarations of ntohl etc. */
@ -51,6 +52,7 @@
#include "async_read.h" #include "async_read.h"
#include "iolist.h"
#include "net/eui64.h" #include "net/eui64.h"
#include "net/netdev.h" #include "net/netdev.h"
#include "net/netdev/eth.h" #include "net/netdev/eth.h"
@ -64,7 +66,7 @@
/* netdev interface */ /* netdev interface */
static int _init(netdev_t *netdev); 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 int _recv(netdev_t *netdev, void *buf, size_t n, void *info);
static inline void _get_mac_addr(netdev_t *netdev, uint8_t *dst) 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; 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; 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 #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; netdev->stats.tx_bytes += bytes;
#else
(void)bytes;
#endif #endif
if (netdev->event_callback) { if (netdev->event_callback) {
netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE); netdev->event_callback(netdev, NETDEV_EVENT_TX_COMPLETE);

View File

@ -36,23 +36,6 @@
#define _UNIX_NTP_ERA_OFFSET (2208988800U) #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, static size_t _zep_hdr_fill_v2_data(socket_zep_t *dev, zep_v2_data_hdr_t *hdr,
size_t payload_len) 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); 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) unsigned n, struct iovec *out)
{ {
size_t bytes = 0; size_t bytes;
dev->chksum_buf = 0; dev->chksum_buf = 0;
for (unsigned i = 0; i < n; i++) { bytes = iolist_size(iolist);
bytes += vector[i].iov_len;
}
bytes += sizeof(uint16_t); /* FCS field */ bytes += sizeof(uint16_t); /* FCS field */
out[0].iov_base = &dev->snd_hdr_buf; out[0].iov_base = &dev->snd_hdr_buf;
out[0].iov_len = _zep_hdr_fill(dev, out[0].iov_base, bytes); out[0].iov_len = _zep_hdr_fill(dev, out[0].iov_base, bytes);
for (unsigned i = 0; i < n; i++) { for (unsigned i = 0; i < n; i++) {
/* discard const qualifier, we won't change anything. Promise! */ /* discard const qualifier, we won't change anything. Promise! */
out[i + 1].iov_base = vector[i].iov_base; out[i + 1].iov_base = iolist->iol_base;
out[i + 1].iov_len = vector[i].iov_len; out[i + 1].iov_len = iolist->iol_len;
dev->chksum_buf = ucrc16_calc_le(out[i + 1].iov_base, out[i + 1].iov_len, dev->chksum_buf = ucrc16_calc_le(out[i + 1].iov_base, out[i + 1].iov_len,
UCRC16_CCITT_POLY_LE, dev->chksum_buf); UCRC16_CCITT_POLY_LE, dev->chksum_buf);
iolist = iolist->iol_next;
} }
dev->chksum_buf = byteorder_btols(byteorder_htons(dev->chksum_buf)).u16; dev->chksum_buf = byteorder_btols(byteorder_htons(dev->chksum_buf)).u16;
out[n + 1].iov_base = &dev->chksum_buf; 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; 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; socket_zep_t *dev = (socket_zep_t *)netdev;
unsigned n = iolist_count(iolist);
struct iovec v[n + 2]; struct iovec v[n + 2];
size_t bytes; size_t bytes;
int res; int res;
assert((dev != NULL) && (dev->sock_fd != 0)); assert((dev != NULL) && (dev->sock_fd != 0));
bytes = _prep_vector(dev, vector, n, v); bytes = _prep_vector(dev, iolist, n, v);
DEBUG("socket_zep::send(%p, %p, %u)\n", (void *)netdev, (void *)vector, n); DEBUG("socket_zep::send(%p, %p, %u)\n", (void *)netdev, (void *)iolist, n);
/* simulate TX_STARTED interrupt */ /* simulate TX_STARTED interrupt */
if (netdev->event_callback) { if (netdev->event_callback) {
dev->last_event = NETDEV_EVENT_TX_STARTED; 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); 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) 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(); 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; (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 */ /* wait for any ongoing transmission to finish and go into idle state */
while (state == STATE_TX) {} 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 */ /* copy packet data into the transmit buffer */
int pos = 0; int pos = 0;
for (unsigned i = 0; i < count; i++) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
if ((pos + vector[i].iov_len) > NRFMIN_PKT_MAX) { if ((pos + iol->iol_len) > NRFMIN_PKT_MAX) {
DEBUG("[nrfmin] send: unable to do so, packet is too large!\n"); DEBUG("[nrfmin] send: unable to do so, packet is too large!\n");
return -EOVERFLOW; return -EOVERFLOW;
} }
memcpy(&tx_buf.raw[pos], vector[i].iov_base, vector[i].iov_len); memcpy(&tx_buf.raw[pos], iol->iol_base, iol->iol_len);
pos += vector[i].iov_len; pos += iol->iol_len;
} }
/* set output buffer and destination address */ /* 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->PACKETPTR = (uint32_t)(&tx_buf);
NRF_RADIO->BASE0 = (CONF_ADDR_BASE | hdr->dst_addr); 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; state = STATE_TX;
NRF_RADIO->TASKS_TXEN = 1; 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) 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) static int gnrc_nrfmin_send(gnrc_netif_t *dev, gnrc_pktsnip_t *pkt)
{ {
int res; int res;
struct iovec *vec;
size_t vec_len;
gnrc_pktsnip_t *vec_snip;
nrfmin_hdr_t nrfmin_hdr; nrfmin_hdr_t nrfmin_hdr;
assert(pkt); 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); res = hdr_netif_to_nrfmin(&nrfmin_hdr, pkt);
if (res < 0) { if (res < 0) {
DEBUG("[nrfmin_gnrc] send: failed to build nrfmin header\n"); DEBUG("[nrfmin_gnrc] send: failed to build nrfmin header\n");
gnrc_pktbuf_release(pkt); goto out;
return res;
} }
/* create iovec of data */ /* link first entry after netif hdr of the pkt to the nrfmin header */
vec_snip = gnrc_pktbuf_get_iovec(pkt, &vec_len); iolist_t iolist = {
if (vec_snip == NULL) { .iol_next = (iolist_t *)pkt->next,
DEBUG("[nrfmin_gnrc] send: failed to create IO vector\n"); .iol_base = &nrfmin_hdr,
gnrc_pktbuf_release(pkt); .iol_len = NRFMIN_HDR_LEN
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;
/* and finally send out the data and release the packet */ /* and finally send out the data and release the packet */
res = dev->dev->driver->send(dev->dev, vec, vec_len); res = dev->dev->driver->send(dev->dev, &iolist);
gnrc_pktbuf_release(vec_snip);
out:
gnrc_pktbuf_release(pkt);
return res; return res;
} }

View File

@ -112,6 +112,7 @@ ifneq (,$(filter encx24j600,$(USEMODULE)))
endif endif
ifneq (,$(filter ethos,$(USEMODULE))) ifneq (,$(filter ethos,$(USEMODULE)))
USEMODULE += iolist
USEMODULE += netdev_eth USEMODULE += netdev_eth
USEMODULE += random USEMODULE += random
USEMODULE += tsrb USEMODULE += tsrb
@ -306,6 +307,7 @@ endif
ifneq (,$(filter sx127%,$(USEMODULE))) ifneq (,$(filter sx127%,$(USEMODULE)))
FEATURES_REQUIRED += periph_gpio FEATURES_REQUIRED += periph_gpio
FEATURES_REQUIRED += periph_spi FEATURES_REQUIRED += periph_spi
USEMODULE += iolist
USEMODULE += xtimer USEMODULE += xtimer
USEMODULE += sx127x USEMODULE += sx127x
USEMODULE += netif 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 * 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 * 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 Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Kévin Roussel <Kevin.Roussel@inria.fr> * @author Kévin Roussel <Kevin.Roussel@inria.fr>
* @author Martine Lenders <mlenders@inf.fu-berlin.de> * @author Martine Lenders <mlenders@inf.fu-berlin.de>
* @author Kaspar Schleiser <kaspar@schleiser.de>
* *
* @} * @}
*/ */
@ -25,6 +27,8 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include "iolist.h"
#include "net/eui64.h" #include "net/eui64.h"
#include "net/ieee802154.h" #include "net/ieee802154.h"
#include "net/netdev.h" #include "net/netdev.h"
@ -40,7 +44,7 @@
#define _MAX_MHR_OVERHEAD (25) #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 _recv(netdev_t *netdev, void *buf, size_t len, void *info);
static int _init(netdev_t *netdev); static int _init(netdev_t *netdev);
static void _isr(netdev_t *netdev); static void _isr(netdev_t *netdev);
@ -93,18 +97,17 @@ static int _init(netdev_t *netdev)
return 0; 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; at86rf2xx_t *dev = (at86rf2xx_t *)netdev;
const struct iovec *ptr = vector;
size_t len = 0; size_t len = 0;
at86rf2xx_tx_prepare(dev); at86rf2xx_tx_prepare(dev);
/* load packet data into FIFO */ /* 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 */ /* 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", DEBUG("[at86rf2xx] error: packet too large (%u byte) to be send\n",
(unsigned)len + 2); (unsigned)len + 2);
return -EOVERFLOW; return -EOVERFLOW;
@ -112,7 +115,7 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
#ifdef MODULE_NETSTATS_L2 #ifdef MODULE_NETSTATS_L2
netdev->stats.tx_bytes += len; netdev->stats.tx_bytes += len;
#endif #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 */ /* send data out directly if pre-loading id disabled */

View File

@ -37,14 +37,12 @@
#define ENABLE_DEBUG (0) #define ENABLE_DEBUG (0)
#include "debug.h" #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__); DEBUG("%s:%u\n", __func__, __LINE__);
(void)count; netdev_cc110x_t *netdev_cc110x = (netdev_cc110x_t *)dev;
cc110x_pkt_t *cc110x_pkt = iolist->iol_base;
netdev_cc110x_t *netdev_cc110x = (netdev_cc110x_t*) dev;
cc110x_pkt_t *cc110x_pkt = vector[0].iov_base;
return cc110x_send(&netdev_cc110x->cc110x, cc110x_pkt); 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; cc110x_pkt.flags = 0;
} }
struct iovec vector; iolist_t iolist = {
vector.iov_base = (char*)&cc110x_pkt; .iol_base = (char *)&cc110x_pkt,
vector.iov_len = sizeof(cc110x_pkt_t); .iol_len = sizeof(cc110x_pkt_t)
};
unsigned payload_len = 0; unsigned payload_len = 0;
uint8_t *pos = cc110x_pkt.data; uint8_t *pos = cc110x_pkt.data;
@ -93,7 +94,7 @@ static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
payload = payload->next; 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); gnrc_pktbuf_release(pkt);
cc110x_pkt.length = (uint8_t) payload_len + CC110X_HEADER_LENGTH; 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.address,
(unsigned)cc110x_pkt.length); (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) 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); 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)) { if ((n > 0) && !(dev->options & CC2420_OPT_PRELOADING)) {
cc2420_tx_exec(dev); cc2420_tx_exec(dev);
@ -125,7 +125,7 @@ size_t cc2420_send(cc2420_t *dev, const struct iovec *data, unsigned count)
return n; 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) */ 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) {} while (cc2420_get_state(dev) & NETOPT_STATE_TX) {}
/* get and check the length of the packet */ /* get and check the length of the packet */
for (unsigned i = 0; i < count; i++) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
pkt_len += data[i].iov_len; pkt_len += iol->iol_len;
} }
if (pkt_len >= CC2420_PKT_MAXLEN) { if (pkt_len >= CC2420_PKT_MAXLEN) {
DEBUG("cc2420: tx_prep: unable to send, pkt too large\n"); 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 */ /* push packet length to TX FIFO */
cc2420_fifo_write(dev, (uint8_t *)&pkt_len, 1); cc2420_fifo_write(dev, (uint8_t *)&pkt_len, 1);
/* push packet to TX FIFO */ /* push packet to TX FIFO */
for (unsigned i = 0; i < count; i++) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
cc2420_fifo_write(dev, (uint8_t *)data[i].iov_base, data[i].iov_len); 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); DEBUG("cc2420: tx_prep: loaded %i byte into the TX FIFO\n", (int)pkt_len);

View File

@ -39,7 +39,7 @@
#include "debug.h" #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 _recv(netdev_t *netdev, void *buf, size_t len, void *info);
static int _init(netdev_t *netdev); static int _init(netdev_t *netdev);
static void _isr(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); 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; 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) 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); 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; enc28j60_t *dev = (enc28j60_t *)netdev;
uint8_t ctrl = 0; 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); cmd_w_addr(dev, ADDR_WRITE_PTR, BUF_TX_START);
/* write control byte and the actual data into the buffer */ /* write control byte and the actual data into the buffer */
cmd_wbm(dev, &ctrl, 1); cmd_wbm(dev, &ctrl, 1);
for (unsigned i = 0; i < count; i++) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
c += data[i].iov_len; c += iol->iol_len;
cmd_wbm(dev, (uint8_t *)data[i].iov_base, data[i].iov_len); cmd_wbm(dev, iol->iol_base, iol->iol_len);
} }
/* set TX end pointer */ /* set TX end pointer */
cmd_w_addr(dev, ADDR_TX_END, cmd_r_addr(dev, ADDR_WRITE_PTR) - 1); 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); static void _get_mac_addr(netdev_t *dev, uint8_t* buf);
/* netdev interface */ /* 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 _recv(netdev_t *netdev, void *buf, size_t len, void *info);
static int _init(netdev_t *dev); static int _init(netdev_t *dev);
static void _isr(netdev_t *dev); static void _isr(netdev_t *dev);
@ -291,7 +291,7 @@ static int _init(netdev_t *encdev)
return 0; 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; encx24j600_t * dev = (encx24j600_t *) netdev;
lock(dev); lock(dev);
@ -301,9 +301,9 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count) {
/* copy packet to SRAM */ /* copy packet to SRAM */
size_t len = 0; size_t len = 0;
for (unsigned i = 0; i < count; i++) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
sram_op(dev, ENC_WGPDATA, (i ? 0xFFFF : TX_BUFFER_START), vector[i].iov_base, vector[i].iov_len); sram_op(dev, ENC_WGPDATA, ((iol == iolist) ? TX_BUFFER_START : 0xFFFF), iol->iol_base, iol->iol_len);
len += vector[i].iov_len; len += iol->iol_len;
} }
/* set start of TX packet and length */ /* set start of TX packet and length */

View File

@ -189,12 +189,11 @@ static int _init(netdev_t *encdev)
return 0; 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; size_t result = 0;
while(count--) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
result += vector->iov_len; result += iol->iol_len;
vector++;
} }
return result; 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; ethos_t * dev = (ethos_t *) netdev;
(void)dev; (void)dev;
/* count total packet length */ /* 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 */ /* lock line in order to prevent multiple writes */
mutex_lock(&dev->out_mutex); 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; uint8_t frame_delim = ETHOS_FRAME_DELIMITER;
uart_write(dev->uart, &frame_delim, 1); uart_write(dev->uart, &frame_delim, 1);
/* send iovec */ /* send iolist */
while(count--) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
size_t n = vector->iov_len; size_t n = iol->iol_len;
uint8_t *ptr = vector->iov_base; uint8_t *ptr = iol->iol_base;
while(n--) { while(n--) {
_write_escaped(dev->uart, *ptr++); _write_escaped(dev->uart, *ptr++);
} }
vector++;
} }
uart_write(dev->uart, &frame_delim, 1); 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 * @note This function ignores the PRELOADING option
* *
* @param[in] dev device to use for sending * @param[in] dev device to use for sending
* @param[in] data data to send (must include IEEE802.15.4 header) * @param[in] iolist data to send (must include IEEE802.15.4 header)
* @param[in] count length of @p data
* *
* @return number of bytes that were actually send * @return number of bytes that were actually send
* @return 0 on error * @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 * @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. * data is possible after it was called.
* *
* @param[in] dev device to prepare for sending * @param[in] dev device to prepare for sending
* @param[in] data data to prepare (must include IEEE802.15.4 header) * @param[in] iolist data to prepare (must include IEEE802.15.4 header)
* @param[in] count length of @p data
*/ */
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 * @brief Trigger sending of data previously loaded into transmit buffer

View File

@ -195,8 +195,8 @@ extern "C" {
#endif #endif
#include <stdint.h> #include <stdint.h>
#include <sys/uio.h>
#include "iolist.h"
#include "net/netopt.h" #include "net/netopt.h"
#ifdef MODULE_NETSTATS_L2 #ifdef MODULE_NETSTATS_L2
@ -294,17 +294,14 @@ typedef struct netdev_driver {
/** /**
* @brief Send frame * @brief Send frame
* *
* @pre `(dev != NULL)` * @pre `(dev != NULL) && (iolist != NULL`
* @pre `(count == 0) || (vector != NULL)`
* (`(count != 0) => (vector != NULL)`)
* *
* @param[in] dev network device descriptor * @param[in] dev network device descriptor
* @param[in] vector io vector array to send * @param[in] iolist io vector list to send
* @param[in] count nr of entries in vector
* *
* @return number of bytes sent, or `< 0` on error * @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 * @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; kw2xrf_t *dev = (kw2xrf_t *)netdev;
const struct iovec *ptr = vector;
uint8_t *pkt_buf = &(dev->buf[1]); uint8_t *pkt_buf = &(dev->buf[1]);
size_t len = 0; size_t len = 0;
@ -149,14 +148,14 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
kw2xrf_wait_idle(dev); kw2xrf_wait_idle(dev);
/* load packet data into buffer */ /* 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 */ /* 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", LOG_ERROR("[kw2xrf] packet too large (%u byte) to be send\n",
(unsigned)len + IEEE802154_FCS_LEN); (unsigned)len + IEEE802154_FCS_LEN);
return -EOVERFLOW; 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); kw2xrf_set_sequence(dev, XCVSEQ_IDLE);

View File

@ -39,22 +39,6 @@
#define _MAX_MHR_OVERHEAD (25) #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) static void _irq_handler(void *arg)
{ {
netdev_t *dev = (netdev_t *) arg; netdev_t *dev = (netdev_t *) arg;
@ -83,18 +67,17 @@ static int _init(netdev_t *netdev)
return 0; 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; mrf24j40_t *dev = (mrf24j40_t *)netdev;
const struct iovec *ptr = vector;
size_t len = 0; size_t len = 0;
mrf24j40_tx_prepare(dev); mrf24j40_tx_prepare(dev);
/* load packet data into FIFO */ /* 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 */ /* 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", DEBUG("[mrf24j40] error: packet too large (%u byte) to be send\n",
(unsigned)len + 2); (unsigned)len + 2);
return -EOVERFLOW; return -EOVERFLOW;
@ -103,11 +86,12 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
#ifdef MODULE_NETSTATS_L2 #ifdef MODULE_NETSTATS_L2
netdev->stats.tx_bytes += len; netdev->stats.tx_bytes += len;
#endif #endif
len = mrf24j40_tx_load(dev, ptr->iov_base, ptr->iov_len, len); len = mrf24j40_tx_load(dev, iol->iol_base, iol->iol_len, len);
if (i == 0) { /* only on first iteration: */
if (iol == iolist) {
dev->header_len = len; dev->header_len = len;
/* Grab the FCF bits from the frame header */ /* 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"); 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_END_ESC (0xdcU)
#define SLIP_ESC_ESC (0xddU) #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) static void _slip_rx_cb(void *arg, uint8_t byte)
{ {
slipdev_t *dev = arg; 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); 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; slipdev_t *dev = (slipdev_t *)netdev;
int bytes = 0; int bytes = 0;
DEBUG("slipdev: sending vector of length %u\n", count); DEBUG("slipdev: sending iolist\n");
for (unsigned i = 0; i < count; i++) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
uint8_t *data = vector[i].iov_base; 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) { switch(*data) {
case SLIP_END: case SLIP_END:
/* escaping END byte*/ /* escaping END byte*/
@ -223,4 +198,21 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *value,
return -ENOTSUP; 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" #include "debug.h"
/* Internal helper functions */ /* 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 _set_state(sx127x_t *dev, netopt_state_t state);
static int _get_state(sx127x_t *dev, void *val); static int _get_state(sx127x_t *dev, void *val);
void _on_dio0_irq(void *arg); void _on_dio0_irq(void *arg);
@ -42,24 +41,7 @@ void _on_dio1_irq(void *arg);
void _on_dio2_irq(void *arg); void _on_dio2_irq(void *arg);
void _on_dio3_irq(void *arg); void _on_dio3_irq(void *arg);
/* Netdev driver api functions */ static int _send(netdev_t *netdev, const iolist_t *iolist)
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)
{ {
sx127x_t *dev = (sx127x_t*) netdev; sx127x_t *dev = (sx127x_t*) netdev;
@ -69,8 +51,8 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
return -ENOTSUP; return -ENOTSUP;
} }
uint8_t size; uint8_t size = iolist_size(iolist);
size = _get_tx_len(vector, count);
switch (dev->settings.modem) { switch (dev->settings.modem) {
case SX127X_MODEM_FSK: case SX127X_MODEM_FSK:
/* todo */ /* todo */
@ -91,8 +73,8 @@ static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count)
} }
/* Write payload buffer */ /* Write payload buffer */
for (size_t i = 0; i < count; i++) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
sx127x_write_fifo(dev, vector[i].iov_base, vector[i].iov_len); sx127x_write_fifo(dev, iol->iol_base, iol->iol_len);
} }
break; break;
default: default:
@ -489,17 +471,6 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *val, size_t len)
return res; 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) static int _set_state(sx127x_t *dev, netopt_state_t state)
{ {
switch (state) { switch (state) {
@ -717,3 +688,12 @@ void _on_dio3_irq(void *arg)
break; 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; w5100_t *dev = (w5100_t *)netdev;
int sum = 0; int sum = 0;
@ -210,9 +210,10 @@ static int send(netdev_t *netdev, const struct iovec *vector, unsigned count)
pos = S0_TX_BASE; pos = S0_TX_BASE;
} }
for (unsigned i = 0; i < count; i++) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
pos = tx_upload(dev, pos, vector[i].iov_base, vector[i].iov_len); size_t len = iol->iol_len;
sum += vector[i].iov_len; pos = tx_upload(dev, pos, iol->iol_base, len);
sum += len;
} }
waddr(dev, S0_TX_WR0, S0_TX_WR1, pos); 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; int res;
size_t size; size_t size;
size_t count;
gnrc_pktsnip_t *vec;
gnrc_netif_hdr_t *hdr; gnrc_netif_hdr_t *hdr;
uint8_t xhdr[XBEE_MAX_TXHDR_LENGTH]; 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 */ /* now let's send out the stuff */
vec = gnrc_pktbuf_get_iovec(pkt, &count); iolist_t iolist = {
if (vec != NULL) { .iol_next = (iolist_t *)pkt->next,
pkt = vec; .iol_base = xhdr,
struct iovec *vector = (struct iovec *)pkt->data; .iol_len = res
vector[0].iov_base = xhdr; };
vector[0].iov_len = res;
#ifdef MODULE_NETSTATS_L2 #ifdef MODULE_NETSTATS_L2
if (hdr->flags & BCAST) { if (hdr->flags & BCAST) {
netif->dev->stats.tx_mcast_count++; 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);
} }
else { 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); gnrc_pktbuf_release(pkt);

View File

@ -634,21 +634,23 @@ int xbee_init(netdev_t *dev)
return 0; 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; xbee_t *xbee = (xbee_t *)dev;
size_t size; size_t size;
uint8_t csum; uint8_t csum;
assert(xbee && vector && (count > 0)); assert(xbee && iolist);
/* calculate the checksum and the packet size */ /* calculate the checksum and the packet size */
size = vector[0].iov_len; size = iolist->iol_len;
csum = _cksum(3, (uint8_t *)vector[0].iov_base, size); csum = _cksum(3, (uint8_t *)iolist->iol_base, size);
for (unsigned i = 1; i < count; i++) { for (const iolist_t *iol = iolist->iol_next; iol; iol = iol->iol_next) {
size += vector[i].iov_len; size_t len = iol->iol_len;
for (size_t p = 0; p < vector[i].iov_len; p++) {
csum -= ((uint8_t *)vector[i].iov_base)[p]; 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 */ /* send the actual data packet */
DEBUG("[xbee] send: now sending out %i byte\n", (int)size); DEBUG("[xbee] send: now sending out %i byte\n", (int)size);
mutex_lock(&(xbee->tx_lock)); mutex_lock(&(xbee->tx_lock));
for (unsigned i = 0; i < count; i++) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
uart_write(xbee->p.uart, vector[i].iov_base, vector[i].iov_len); uart_write(xbee->p.uart, iol->iol_base, iol->iol_len);
} }
uart_write(xbee->p.uart, &csum, 1); uart_write(xbee->p.uart, &csum, 1);
mutex_unlock(&(xbee->tx_lock)); mutex_unlock(&(xbee->tx_lock));
/* return number of payload byte */ /* return number of payload bytes */
return (int)size; 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) static int8_t _netdev_send(const void *pr_payload, uint8_t c_len)
{ {
if (_dev != NULL) { if (_dev != NULL) {
const struct iovec vector = { iolist_t iolist = {
.iov_base = (void *)pr_payload, .iol_base = (void *)pr_payload,
.iov_len = c_len .iol_len = c_len,
}; };
if (_dev->driver->send(_dev, &vector, 1) < 0) { if (_dev->driver->send(_dev, &iolist) < 0) {
DEBUG("Error on send\n"); DEBUG("Error on send\n");
return RADIO_TX_ERR; 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 */ pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif #endif
LL_COUNT(p, q, count); 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++) { for (q = p, count = 0; q != NULL; q = q->next, count++) {
pkt[count].iov_base = q->payload; iolist_t *iol = &iolist[count];
pkt[count].iov_len = (size_t)q->len;
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 #if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif #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 #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); LWIP_ASSERT("p->next == NULL", p->next == NULL);
netdev_t *netdev = (netdev_t *)netif->state; netdev_t *netdev = (netdev_t *)netif->state;
struct iovec pkt = { iolist_t pkt = {
.iov_base = p->payload, .iol_base = p->payload,
.iov_len = (p->len - IEEE802154_FCS_LEN), /* FCS is written by driver */ .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 #endif

View File

@ -297,14 +297,15 @@ void otPlatRadioSetDefaultTxPower(otInstance *aInstance, int8_t aPower)
ThreadError otPlatRadioTransmit(otInstance *aInstance, RadioPacket *aPacket) ThreadError otPlatRadioTransmit(otInstance *aInstance, RadioPacket *aPacket)
{ {
(void) aInstance; (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 * Unlike RIOT, OpenThread includes two bytes FCS (0x00 0x00) so
* these bytes are removed * these bytes are removed
*/ */
pkt.iov_base = aPacket->mPsdu; iolist_t iolist = {
pkt.iov_len = aPacket->mLength - RADIO_IEEE802154_FCS_LEN; .iol_base = aPacket->mPsdu,
.iol_len = (aPacket->mLength - RADIO_IEEE802154_FCS_LEN)
};
/*Set channel and power based on transmit frame */ /*Set channel and power based on transmit frame */
DEBUG("otPlatRadioTransmit->channel: %i, length %d\n", (int) aPacket->mChannel, (int)aPacket->mLength); 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); _set_power(aPacket->mPower);
/* send packet though netdev */ /* send packet though netdev */
_dev->driver->send(_dev, &pkt, 1); _dev->driver->send(_dev, &iolist);
return kThreadError_None; 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) void SX127XSend(uint8_t *buffer, uint8_t size)
{ {
netdev_t *dev = (netdev_t *)&sx127x; netdev_t *dev = (netdev_t *)&sx127x;
struct iovec vec[1]; iolist_t iol = {
vec[0].iov_base = buffer; .iol_base = buffer,
vec[0].iov_len = size; .iol_len = size
dev->driver->send(dev, vec, 1); };
dev->driver->send(dev, &iol);
} }
void SX127XSetSleep(void) 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. * CSMA/CA, this feature is used. Otherwise, a software procedure is used.
* *
* @param[in] dev netdev device, needs to be already initialized * @param[in] dev netdev device, needs to be already initialized
* @param[in] vector pointer to the data * @param[in] iolist pointer to the data
* @param[in] count number of elements in @p vector
* @param[in] conf configuration for the backoff; * @param[in] conf configuration for the backoff;
* will be set to @ref CSMA_SENDER_CONF_DEFAULT if NULL. * 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 * @return -EBUSY if radio medium never was available
* to send the given data * to send the given data
*/ */
int csma_sender_csma_ca_send(netdev_t *dev, struct iovec *vector, int csma_sender_csma_ca_send(netdev_t *dev, iolist_t *iolist,
unsigned count, const csma_sender_conf_t *conf); const csma_sender_conf_t *conf);
/** /**
* @brief Sends a 802.15.4 frame when medium is avaiable. * @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(). * @ref csma_sender_csma_ca_send().
* *
* @param[in] dev netdev device, needs to be already initialized * @param[in] dev netdev device, needs to be already initialized
* @param[in] vector pointer to the data * @param[in] iolist pointer to the data
* @param[in] count number of elements in @p vector
* *
* @return number of bytes that were actually send out * @return number of bytes that were actually send out
* @return -ENODEV if @p dev is invalid * @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 * @return -EBUSY if radio medium was not available
* to send the given data * 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 #ifdef __cplusplus

View File

@ -96,20 +96,25 @@ extern "C" {
* | * L2 header 3 * | * L2 header 3
* * L2 header 4 * * 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 * @note This type has no initializer on purpose. Please use @ref net_gnrc_pktbuf
* as factory. * as factory.
*/ */
/* packed to be aligned correctly in the static packet buffer */ /* packed to be aligned correctly in the static packet buffer */
typedef struct gnrc_pktsnip { 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. * @brief Counter of threads currently having control over this packet.
* *
* @internal * @internal
*/ */
unsigned int users; 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 */ gnrc_nettype_t type; /**< protocol of the packet snip */
#ifdef MODULE_GNRC_NETERR #ifdef MODULE_GNRC_NETERR
kernel_pid_t err_sub; /**< subscriber to errors related to this kernel_pid_t err_sub; /**< subscriber to errors related to this

View File

@ -33,11 +33,10 @@
* static uint32_t sum = 0; * static uint32_t sum = 0;
* static mutex_t wait = MUTEX_INIT; * 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)dev;
* (void)vector; * (void)iolist;
* (void)count;
* *
* sum += (xtimer_now_usec() - last_start); * sum += (xtimer_now_usec() - last_start);
* mutex_unlock(&wait); * mutex_unlock(&wait);
@ -95,15 +94,12 @@ extern "C" {
* @brief Callback type to handle send command * @brief Callback type to handle send command
* *
* @param[in] dev network device descriptor * @param[in] dev network device descriptor
* @param[in] vector io vector array to send * @param[in] iolist io vector list to send
* @param[in] count number of entries in vector
* *
* @return number of bytes sent * @return number of bytes sent
* @return <= 0 on error * @return <= 0 on error
*/ */
typedef int (*netdev_test_send_cb_t)(netdev_t *dev, typedef int (*netdev_test_send_cb_t)(netdev_t *dev, const iolist_t *iolist);
const struct iovec *vector,
int count);
/** /**
* @brief Callback type to handle receive command * @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_t *dev = netif->dev;
netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev; netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev;
gnrc_netif_hdr_t *netif_hdr; gnrc_netif_hdr_t *netif_hdr;
gnrc_pktsnip_t *vec_snip;
const uint8_t *src, *dst = NULL; const uint8_t *src, *dst = NULL;
int res = 0; 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 mhr[IEEE802154_MAX_HDR_LEN];
uint8_t flags = (uint8_t)(state->flags & NETDEV_IEEE802154_SEND_MASK); uint8_t flags = (uint8_t)(state->flags & NETDEV_IEEE802154_SEND_MASK);
le_uint16_t dev_pan = byteorder_btols(byteorder_htons(state->pan)); 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"); DEBUG("_send_ieee802154: Error preperaring frame\n");
return -EINVAL; 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 */ /* prepare packet for sending */
vector = (struct iovec *)pkt->data; iolist_t iolist = {
vector[0].iov_base = mhr; .iol_next = (iolist_t *)pkt->next,
vector[0].iov_len = (size_t)res; .iol_base = mhr,
.iol_len = (size_t)res
};
#ifdef MODULE_NETSTATS_L2 #ifdef MODULE_NETSTATS_L2
if (netif_hdr->flags & if (netif_hdr->flags &
(GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) { (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
netif->dev->stats.tx_mcast_count++; 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
} }
else { 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 */ /* release old data */
gnrc_pktbuf_release(pkt); gnrc_pktbuf_release(pkt);
return res; 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_t *dev = netif->dev;
netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev; netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev;
gnrc_netif_hdr_t *netif_hdr; gnrc_netif_hdr_t *netif_hdr;
gnrc_pktsnip_t *vec_snip;
const uint8_t *src, *dst = NULL; const uint8_t *src, *dst = NULL;
int res = 0; 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 mhr[IEEE802154_MAX_HDR_LEN];
uint8_t flags = (uint8_t)(state->flags & NETDEV_IEEE802154_SEND_MASK); uint8_t flags = (uint8_t)(state->flags & NETDEV_IEEE802154_SEND_MASK);
le_uint16_t dev_pan = byteorder_btols(byteorder_htons(state->pan)); 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"); DEBUG("_send_ieee802154: Error preperaring frame\n");
return -EINVAL; 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 */ /* prepare packet for sending */
vector = (struct iovec *)pkt->data; iolist_t iolist = {
vector[0].iov_base = mhr; .iol_next = (iolist_t *)pkt->next,
vector[0].iov_len = (size_t)res; .iol_base = mhr,
.iol_len = (size_t)res
};
#ifdef MODULE_NETSTATS_L2 #ifdef MODULE_NETSTATS_L2
if (netif_hdr->flags & if (netif_hdr->flags &
(GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) { (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
netif->dev->stats.tx_mcast_count++; 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
} }
else { 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 */ /* release old data */
gnrc_pktbuf_release(pkt); gnrc_pktbuf_release(pkt);
return res; 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[0], hdr.dst[1], hdr.dst[2],
hdr.dst[3], hdr.dst[4], hdr.dst[5]); hdr.dst[3], hdr.dst[4], hdr.dst[5]);
size_t n; iolist_t iolist = {
payload = gnrc_pktbuf_get_iovec(pkt, &n); /* use payload as temporary .iol_next = (iolist_t *)payload,
* variable */ .iol_base = &hdr,
res = -ENOBUFS; .iol_len = sizeof(ethernet_hdr_t)
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);
#ifdef MODULE_NETSTATS_L2 #ifdef MODULE_NETSTATS_L2
if ((netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) || if ((netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) ||
(netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST)) { (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
dev->stats.tx_mcast_count++; dev->stats.tx_mcast_count++;
}
else {
dev->stats.tx_unicast_count++;
}
#endif
res = dev->driver->send(dev, vector, n);
} }
else {
dev->stats.tx_unicast_count++;
}
#endif
res = dev->driver->send(dev, &iolist);
gnrc_pktbuf_release(pkt); 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_t *dev = netif->dev;
netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev; netdev_ieee802154_t *state = (netdev_ieee802154_t *)netif->dev;
gnrc_netif_hdr_t *netif_hdr; gnrc_netif_hdr_t *netif_hdr;
gnrc_pktsnip_t *vec_snip;
const uint8_t *src, *dst = NULL; const uint8_t *src, *dst = NULL;
int res = 0; 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 mhr[IEEE802154_MAX_HDR_LEN];
uint8_t flags = (uint8_t)(state->flags & NETDEV_IEEE802154_SEND_MASK); uint8_t flags = (uint8_t)(state->flags & NETDEV_IEEE802154_SEND_MASK);
le_uint16_t dev_pan = byteorder_btols(byteorder_htons(state->pan)); 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"); DEBUG("_send_ieee802154: Error preperaring frame\n");
return -EINVAL; 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 */ /* prepare iolist for netdev / mac layer */
vector = (struct iovec *)pkt->data; iolist_t iolist = {
vector[0].iov_base = mhr; .iol_next = (iolist_t *)pkt->next,
vector[0].iov_len = (size_t)res; .iol_base = mhr,
.iol_len = (size_t)res
};
#ifdef MODULE_NETSTATS_L2 #ifdef MODULE_NETSTATS_L2
if (netif_hdr->flags & if (netif_hdr->flags &
(GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) { (GNRC_NETIF_HDR_FLAGS_BROADCAST | GNRC_NETIF_HDR_FLAGS_MULTICAST)) {
netif->dev->stats.tx_mcast_count++; 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
} }
else { 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 */ /* release old data */
gnrc_pktbuf_release(pkt); gnrc_pktbuf_release(pkt);
return res; 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) static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *pkt)
{ {
gnrc_pktsnip_t *vector;
int res = -ENOBUFS; int res = -ENOBUFS;
size_t n;
if (pkt->type == GNRC_NETTYPE_NETIF) { if (pkt->type == GNRC_NETTYPE_NETIF) {
/* we don't need the netif snip: remove it */ /* we don't need the netif snip: remove it */
pkt = gnrc_pktbuf_remove_snip(pkt, pkt); pkt = gnrc_pktbuf_remove_snip(pkt, pkt);
} }
/* prepare packet for sending */
vector = gnrc_pktbuf_get_iovec(pkt, &n); netdev_t *dev = netif->dev;
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;
#ifdef MODULE_NETSTATS_L2 #ifdef MODULE_NETSTATS_L2
dev->stats.tx_unicast_count++; dev->stats.tx_unicast_count++;
#endif #endif
res = dev->driver->send(dev, v, n);
} res = dev->driver->send(dev, (iolist_t *)pkt);
/* release old data */ /* release old data */
gnrc_pktbuf_release(pkt); gnrc_pktbuf_release(pkt);
return res; 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 * @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] device netdev device, needs to be already initialized
* @param[in] vector pointer to the data * @param[in] iolist pointer to the data
* @param[in] count number of elements in @p vector
* *
* @return the return value of device driver's * @return the return value of device driver's
* netdev_driver_t::send() function if medium was * 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 * @return -EBUSY if radio medium was not available
* to send the given data * 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; 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 medium is clear, send the packet and return */
if (hwfeat == NETOPT_ENABLE) { if (hwfeat == NETOPT_ENABLE) {
DEBUG("csma: Radio medium available: sending packet.\n"); 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 */ /* 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 -------------------------*/ /*------------------------- "EXPORTED" FUNCTIONS -------------------------*/
int csma_sender_csma_ca_send(netdev_t *dev, struct iovec *vector, int csma_sender_csma_ca_send(netdev_t *dev, iolist_t *iolist,
unsigned count, const csma_sender_conf_t *conf) const csma_sender_conf_t *conf)
{ {
netopt_enable_t hwfeat; netopt_enable_t hwfeat;
@ -153,7 +152,7 @@ int csma_sender_csma_ca_send(netdev_t *dev, struct iovec *vector,
if (ok) { if (ok) {
/* device does CSMA/CA all by itself: let it do its job */ /* device does CSMA/CA all by itself: let it do its job */
DEBUG("csma: Network device does hardware CSMA/CA\n"); 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 /* 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); xtimer_usleep(bp);
/* try to send after a CCA */ /* try to send after a CCA */
res = send_if_cca(dev, vector, count); res = send_if_cca(dev, iolist);
if (res >= 0) { if (res >= 0) {
/* TX done */ /* TX done */
return res; 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; netopt_enable_t hwfeat;
@ -226,12 +225,12 @@ int csma_sender_cca_send(netdev_t *dev, struct iovec *vector, unsigned count)
if (ok) { if (ok) {
/* device does auto-CCA: let him do its job */ /* device does auto-CCA: let him do its job */
DEBUG("csma: Network device does auto-CCA checking.\n"); 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 /* if we arrive here, we must do CCA ourselves to see if radio medium
is clear before sending */ is clear before sending */
res = send_if_cca(dev, vector, count); res = send_if_cca(dev, iolist);
if (res == -EBUSY) { if (res == -EBUSY) {
DEBUG("csma: Transmission cancelled!\n"); DEBUG("csma: Transmission cancelled!\n");
} }

View File

@ -19,32 +19,6 @@
#include "net/netdev_test.h" #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) void netdev_test_reset(netdev_test_t *dev)
{ {
mutex_lock(&dev->mutex); mutex_lock(&dev->mutex);
@ -57,14 +31,14 @@ void netdev_test_reset(netdev_test_t *dev)
mutex_unlock(&dev->mutex); 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; netdev_test_t *dev = (netdev_test_t *)netdev;
int res = (int)count; /* assume everything would be fine */ int res = -EINVAL;
mutex_lock(&dev->mutex); mutex_lock(&dev->mutex);
if (dev->send_cb != NULL) { if (dev->send_cb != NULL) {
res = dev->send_cb(netdev, vector, count); res = dev->send_cb(netdev, iolist);
} }
mutex_unlock(&dev->mutex); mutex_unlock(&dev->mutex);
return res; return res;
@ -140,5 +114,23 @@ static int _set(netdev_t *netdev, netopt_t opt, const void *value, size_t value_
return res; 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; int res;
netdev_ieee802154_t *dev; netdev_ieee802154_t *dev;
struct iovec vector[MAC_VECTOR_SIZE];
uint8_t *src; uint8_t *src;
size_t src_len; size_t src_len;
uint8_t mhr[IEEE802154_MAX_HDR_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; return 1;
} }
iolist_t iol_data = {
.iol_base = data,
.iol_len = strlen(data)
};
dev = (netdev_ieee802154_t *)&devs[iface]; dev = (netdev_ieee802154_t *)&devs[iface];
flags = (uint8_t)(dev->flags & NETDEV_IEEE802154_SEND_MASK); flags = (uint8_t)(dev->flags & NETDEV_IEEE802154_SEND_MASK);
flags |= IEEE802154_FCF_TYPE_DATA; flags |= IEEE802154_FCF_TYPE_DATA;
vector[1].iov_base = data;
vector[1].iov_len = strlen(data);
src_pan = byteorder_btols(byteorder_htons(dev->pan)); src_pan = byteorder_btols(byteorder_htons(dev->pan));
if (dst_pan.u16 == 0) { if (dst_pan.u16 == 0) {
dst_pan = src_pan; 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"); puts("txtsnd: Error preperaring frame");
return 1; return 1;
} }
vector[0].iov_base = mhr;
vector[0].iov_len = (size_t)res; iolist_t iol_hdr = {
res = dev->netdev.driver->send((netdev_t *)dev, vector, MAC_VECTOR_SIZE); .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) { if (res < 0) {
puts("txtsnd: Error on sending"); puts("txtsnd: Error on sending");
return 1; return 1;
} }
else { 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); print_addr(dst, dst_len);
printf(" (PAN: "); printf(" (PAN: ");
print_addr((uint8_t *)&dst_pan, sizeof(dst_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", printf("sending \"%s\" payload (%d bytes)\n",
argv[1], strlen(argv[1]) + 1); argv[1], strlen(argv[1]) + 1);
struct iovec vec[1]; iolist_t iolist = {
vec[0].iov_base = argv[1]; .iol_base = argv[1],
vec[0].iov_len = strlen(argv[1]) + 1; .iol_len = (strlen(argv[1]) + 1)
if (netdev->driver->send(netdev, vec, 1) == -ENOTSUP) { };
if (netdev->driver->send(netdev, &iolist) == -ENOTSUP) {
puts("Cannot send: radio is still transmitting"); 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 uint8_t tmp_buffer[ETHERNET_DATA_LEN];
static size_t tmp_buffer_bytes = 0; static size_t tmp_buffer_bytes = 0;
static int _dump_send_packet(netdev_t *netdev, const struct iovec *vector, static int _dump_send_packet(netdev_t *netdev, const iolist_t *iolist)
int count)
{ {
int res; int res;
@ -55,13 +54,13 @@ static int _dump_send_packet(netdev_t *netdev, const struct iovec *vector,
printf("unknown "); printf("unknown ");
} }
puts("device:"); puts("device:");
for (int i = 0; i < count; i++) { for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) {
if ((tmp_buffer_bytes + vector[i].iov_len) > ETHERNET_DATA_LEN) { size_t len = iol->iol_len;
if ((tmp_buffer_bytes + len) > ETHERNET_DATA_LEN) {
return -ENOBUFS; return -ENOBUFS;
} }
memcpy(&tmp_buffer[tmp_buffer_bytes], vector[i].iov_base, memcpy(&tmp_buffer[tmp_buffer_bytes], iol->iol_base, len);
vector[i].iov_len); tmp_buffer_bytes += len;
tmp_buffer_bytes += vector[i].iov_len;
} }
od_hex_dump(tmp_buffer, tmp_buffer_bytes, OD_WIDTH_DEFAULT); od_hex_dump(tmp_buffer, tmp_buffer_bytes, OD_WIDTH_DEFAULT);
res = (int)tmp_buffer_bytes; 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; 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 }; msg_t done = { .type = _SEND_DONE };
unsigned offset = 0; unsigned offset = 0;
(void)dev; (void)dev;
mutex_lock(&_netdev_buffer_mutex); mutex_lock(&_netdev_buffer_mutex);
for (int i = 0; i < count; i++) { for (; iolist; iolist = iolist->iol_next) {
memcpy(&_netdev_buffer[offset], vector[i].iov_base, vector[i].iov_len); memcpy(&_netdev_buffer[offset], iolist->iol_base, iolist->iol_len);
offset += vector[i].iov_len; offset += iolist->iol_len;
if (offset > sizeof(_netdev_buffer)) { if (offset > sizeof(_netdev_buffer)) {
mutex_unlock(&_netdev_buffer_mutex); mutex_unlock(&_netdev_buffer_mutex);
return -ENOBUFS; return -ENOBUFS;

View File

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

View File

@ -61,7 +61,7 @@ static uint8_t _tmp_len = 0;
static void _dev_isr(netdev_t *dev); static void _dev_isr(netdev_t *dev);
static int _dev_recv(netdev_t *dev, char *buf, int len, void *info); 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_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); 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; int idx = 0;
(void)dev; (void)dev;
/* check packet content with expected data */ /* check packet content with expected data */
for (int i = 0; i < count; i++) { for (; iolist; iolist = iolist->iol_next) {
if (memcmp(&(_tmp[idx]), vector[i].iov_base, vector[i].iov_len) != 0) { if (memcmp(&(_tmp[idx]), iolist->iol_base, iolist->iol_len) != 0) {
printf("Unexpected send data (vector index = %d)\n", i); puts("Unexpected send data:");
puts("==========================================================="); puts("===========================================================");
puts("expected"); puts("expected");
puts("==========================================================="); 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("===========================================================");
puts("send data"); puts("send data");
puts("==========================================================="); 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; return -EINVAL;
} }
idx += vector[i].iov_len; idx += iolist->iol_len;
} }
if (idx != _tmp_len) { if (idx != _tmp_len) {
printf("Unexpected send length: %d (expected: %d)\n", 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); _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); netdev_t *netdev = (netdev_t *)(&_dev);
int res;
puts("Send zero-length packet"); puts("Send zero-length packet");
res = netdev->driver->send(netdev, NULL, 0); int res = netdev->driver->send(netdev, NULL);
assert((res < 0) || (res == 0)); assert((res < 0) || (res == 0));
if ((res < 0) && (errno == ECONNREFUSED)) { if ((res < 0) && (errno == ECONNREFUSED)) {
puts("No remote socket exists (use scripts in `tests/` to have proper tests)"); 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") }, iolist_t iolist[] = { { .iol_base = "Hello", .iol_len = sizeof("Hello") },
{ .iov_base = "World", .iov_len = sizeof("World") } }; { .iol_base = "World", .iol_len = sizeof("World") } };
iolist[0].iol_next = &iolist[1];
netdev_t *netdev = (netdev_t *)(&_dev); netdev_t *netdev = (netdev_t *)(&_dev);
int res;
puts("Send 'Hello\\0World\\0'"); puts("Send 'Hello\\0World\\0'");
res = netdev->driver->send(netdev, vector, int res = netdev->driver->send(netdev, iolist);
sizeof(vector) / sizeof(struct iovec));
assert((res < 0) || (res == (sizeof("Hello")) + sizeof("World"))); assert((res < 0) || (res == (sizeof("Hello")) + sizeof("World")));
if ((res < 0) && (errno == ECONNREFUSED)) { if ((res < 0) && (errno == ECONNREFUSED)) {
puts("No remote socket exists (use scripts in `tests/` to have proper tests)"); 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; _main_pid = sched_active_pid;
test_init(); test_init();
test_send__vector_NULL__count_0(); test_send__iolist_NULL();
test_send__vector_not_NULL__count_2(); test_send__iolist_not_NULL();
test_recv(); /* does not return */ test_recv(); /* does not return */
puts("ALL TESTS SUCCESSFUL"); puts("ALL TESTS SUCCESSFUL");
return 0; return 0;

View File

@ -13,21 +13,27 @@
* @file * @file
*/ */
#include <errno.h> #include <errno.h>
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include "embUnit/embUnit.h" #include "embUnit/embUnit.h"
#include "net/gnrc/pkt.h" #include "net/gnrc/pkt.h"
#include "net/gnrc/nettype.h" #include "net/gnrc/nettype.h"
#include "iolist.h"
#include "unittests-constants.h" #include "unittests-constants.h"
#include "tests-pkt.h" #include "tests-pkt.h"
#define _INIT_ELEM(len, data, next) \ #define _INIT_ELEM(len, _data, _next) \
{ 1, (next), (data), (len), GNRC_NETTYPE_UNDEF } { .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_DATA(data, next) _INIT_ELEM(sizeof(data), data, next)
#define _INIT_ELEM_STATIC_TYPE(type, next) \ #define _INIT_ELEM_STATIC_TYPE(_type, _next) \
{ 1, (next), NULL, 0, (type) } { .users = 1, .next = (_next), .data = NULL, .size = 0, .type = (_type) }
static void test_pkt_len__NULL(void) 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)); 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) Test *tests_pkt_tests(void)
{ {
EMB_UNIT_TESTFIXTURES(fixtures) { 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__5_elem),
new_TestFixture(test_pkt_count__null), new_TestFixture(test_pkt_count__null),
new_TestFixture(test_pktsnip_search_type), new_TestFixture(test_pktsnip_search_type),
new_TestFixture(test_pkt_equals_iolist),
}; };
EMB_UNIT_TESTCALLER(pkt_tests, NULL, NULL, fixtures); 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) 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, TEST_ASSERT_NULL(gnrc_pktbuf_mark(&pkt, sizeof(TEST_STRING16) - 1,
GNRC_NETTYPE_TEST)); GNRC_NETTYPE_TEST));
@ -661,7 +661,7 @@ static void test_pktbuf_hold__pkt_null(void)
static void test_pktbuf_hold__pkt_external(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); gnrc_pktbuf_hold(&pkt, 1);
TEST_ASSERT(gnrc_pktbuf_is_empty()); TEST_ASSERT(gnrc_pktbuf_is_empty());

View File

@ -22,7 +22,7 @@
#include "tests-pktqueue.h" #include "tests-pktqueue.h"
#define PKT_INIT_ELEM(len, data, next) \ #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 PKT_INIT_ELEM_STATIC_DATA(data, next) PKT_INIT_ELEM(sizeof(data), data, next)
#define PKTQUEUE_INIT_ELEM(pkt) { NULL, pkt } #define PKTQUEUE_INIT_ELEM(pkt) { NULL, pkt }

View File

@ -23,7 +23,7 @@
#include "tests-priority_pktqueue.h" #include "tests-priority_pktqueue.h"
#define PKT_INIT_ELEM(len, data, next) \ #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 PKT_INIT_ELEM_STATIC_DATA(data, next) PKT_INIT_ELEM(sizeof(data), data, next)
#define PKTQUEUE_INIT_ELEM(pkt) { NULL, pkt } #define PKTQUEUE_INIT_ELEM(pkt) { NULL, pkt }