-
Notifications
You must be signed in to change notification settings - Fork 2.1k
netdev: iolist not checked for empty elements on send #11163
Description
Description
It is not possible to send an UDP packet with an empty payload via an at86rf2xx-shipping board (considering #11161 is merged), as an assertion in the device driver is hit. I was able to find the same problem in cc2420 but did not check any more devices.
Edit: the discussion came to the conclusion that (3) should be implemented (see Tracking list)
I am raising this issue instead of fixing it, since I'm not sure where to fix it exactly, as I see three possible solutions. The assert (see "Actual results" section) itself is correct, so the deepest level to fix this would be to add a check for len in at86rf2xx_sram_write() (1).
RIOT/drivers/at86rf2xx/at86rf2xx_internal.c
Lines 71 to 81 in b50ad9e
| void at86rf2xx_sram_write(const at86rf2xx_t *dev, uint8_t offset, | |
| const uint8_t *data, size_t len) | |
| { | |
| uint8_t reg = (AT86RF2XX_ACCESS_SRAM | AT86RF2XX_ACCESS_WRITE); | |
| getbus(dev); | |
| spi_transfer_byte(SPIDEV, CSPIN, true, reg); | |
| spi_transfer_byte(SPIDEV, CSPIN, true, offset); | |
| spi_transfer_bytes(SPIDEV, CSPIN, false, data, NULL, len); | |
| spi_release(SPIDEV); | |
| } |
or at86rf2xx_tx_load() (2) if we just want to solve this for sending specifically by checking there for len
RIOT/drivers/at86rf2xx/at86rf2xx.c
Lines 158 to 164 in b50ad9e
| size_t at86rf2xx_tx_load(at86rf2xx_t *dev, const uint8_t *data, | |
| size_t len, size_t offset) | |
| { | |
| dev->tx_frame_len += (uint8_t)len; | |
| at86rf2xx_sram_write(dev, offset + 1, data, len); | |
| return offset + len; | |
| } |
However, one typically knows what they are doing when they are sending with the device driver directly, so maybe we rather want to fix the netdev interface handling of the device(s) by checking in this loop for iol->iol_len == 0 (3).
RIOT/drivers/at86rf2xx/at86rf2xx_netdev.c
Lines 102 to 110 in b50ad9e
| for (const iolist_t *iol = iolist; iol; iol = iol->iol_next) { | |
| /* current packet data + FCS too long */ | |
| 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; | |
| } | |
| len = at86rf2xx_tx_load(dev, iol->iol_base, iol->iol_len, len); | |
| } |
Lastly, we could just fix it in GNRC, which would be the least intrusive fix, as we only need to fix the gnrc_pktsnip_t to iolist_t conversion instead of checking all device drivers somewhere here (4)
RIOT/sys/net/gnrc/netif/ieee802154/gnrc_netif_ieee802154.c
Lines 265 to 290 in b50ad9e
| /* 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->stats.tx_mcast_count++; | |
| } | |
| else { | |
| netif->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 |
(which would however remove the advantage of mapping the gnrc_pktsnip_t list directly to iolist_t).
Steps to reproduce the issue
Merge #11161 and (was merged) try to send a UDP packet with empty payload using gnrc_networking on samr21-xpro (with other boards the actual result might differ):
udp send ff02::1 1337 ""
Expected results
The packet is sent and can be received by another radio (or sniffed with a sniffer).
Actual results
The node aborts on a failed assertion in this line
RIOT/cpu/sam0_common/periph/spi.c
Line 162 in b50ad9e
| assert(out || in); |
Versions
Current master (4af3548) with #11161 merged.
Tracking
To implement (3) and close this issue the following tasks need to be completed:
- adapt and amend to doc of
netdev_driver_t::_sendnetdev: document valid values for iolist in send() #11195 - fix the device drivers
-
cc2538_rf@kYc0o not affected netdev: iolist not checked for empty elements on send #11163 (comment) -
esp32/esp-eth@gschorcht cpu/esp32: esp_eth doesn't call memcpy if iol_len is 0 #11186 -
esp32/esp-wifi@gschorcht cpu/esp32: esp_wifi doesn't call memcpy if iol_len is 0 #11184 -
esp8266/esp-wifi; not affected as it copies the data byte-by-byte (@gschorcht) -
esp-now@gschorcht, also should check ifiol_baseis a NULL pointer here cpu/esp_common: esp_now doesn't call memcpy if iol_len is 0 #11187 -
netdev_tap; not affected since it is wrappingwritev() -
socket_zep; not affected since it is wrappingwritev() -
nrf802154@bergzand nrf802154: don't call memcpy if iolist->iol_len==0 #11176 -
nrfble; not affected, see netdev: iolist not checked for empty elements on send #11163 (comment) -
nrfmin@haukepetersen ->cpu/nrf5x/nrfmin: ignore empty iolist elements #11194shown to be working without problems in current master -
at86rf2xx@miri64 at86rf2xx: don't call tx_load when iol->iol_len == 0 #11196 -
cc110x; not affected according to netdev: iolist not checked for empty elements on send #11163 (comment) -
cc2420@kYc0o drivers/cc2420: don't append to FIFO if iol->iol_len == 0 #11331 -
enc28j60@maribu drivers/enc28j60: Allow sending with empty chunks #11214 -
encx24j600@kaspar030, @maribu drivers/encx24j600: Allow empty iolist elements #11325 -
ethos; not affected as it copies the data byte-by-byte, usingiol_lenfor the length check -
kw2xrf@PeterKietzmann -> NOT AFFECTED netdev: iolist not checked for empty elements on send #11163 (comment) -
mrf24j40@bergzand -> mrf24j40: don't load data if iol->iol_len == 0 #11321 -
slipdev; not affected as it copies the data byte-by-byte, usingiol_lenfor the length check -
sx127x@jia200x -> sx127x: ignore empty iolist element #11215 -
w5100@maribu; not affected, see netdev: iolist not checked for empty elements on send #11163 (comment) -
xbee; (checksum calculation not affected) @kYc0o drivers/xbee: prevent 0 length packet sent to UART #11332
-