diff --git a/Makefile.dep b/Makefile.dep index 5dece5690e..5afb81bdb9 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -89,7 +89,6 @@ ifneq (,$(filter gnrc_lorawan,$(USEMODULE))) USEMODULE += hashes USEMODULE += crypto_aes USEMODULE += netdev_layer - USEMODULE += gnrc_neterr USEMODULE += gnrc_nettype_lorawan endif diff --git a/examples/gnrc_lorawan/Makefile b/examples/gnrc_lorawan/Makefile index 3d8a22d523..ab320f4094 100644 --- a/examples/gnrc_lorawan/Makefile +++ b/examples/gnrc_lorawan/Makefile @@ -7,6 +7,7 @@ USEMODULE += gnrc_netdev_default USEMODULE += auto_init_gnrc_netif USEMODULE += gnrc_lorawan USEMODULE += gnrc_pktdump +USEMODULE += gnrc_neterr BOARD ?= b-l072z-lrwan1 RIOTBASE ?= ../../ diff --git a/examples/gnrc_lorawan/main.c b/examples/gnrc_lorawan/main.c index 6e488d22c5..fa83bf0238 100644 --- a/examples/gnrc_lorawan/main.c +++ b/examples/gnrc_lorawan/main.c @@ -35,7 +35,8 @@ #include "net/gnrc/pktdump.h" #include "net/gnrc/netreg.h" -#define LORAWAN_PORT (2U) +#define LORAWAN_PORT (2U) +#define LORAWAN_QUEUE_SIZE (4U) static void _usage(void) { @@ -75,16 +76,17 @@ int tx_cmd(int argc, char **argv) gnrc_netapi_set(interface, NETOPT_LORAWAN_TX_PORT, 0, &port, sizeof(port)); gnrc_netif_send(gnrc_netif_get_by_pid(interface), pkt); - msg_t msg; /* wait for packet status and check */ + msg_t msg; msg_receive(&msg); if ((msg.type != GNRC_NETERR_MSG_TYPE) || (msg.content.value != GNRC_NETERR_SUCCESS)) { - puts("Error sending packet (not joined?)"); + printf("Error sending packet: (status: %d\n)", (int) msg.content.value); } else { puts("Successfully sent packet"); } + return 0; } diff --git a/sys/include/net/gnrc/lorawan.h b/sys/include/net/gnrc/lorawan.h index dd4cc5fc44..8bcbb74793 100644 --- a/sys/include/net/gnrc/lorawan.h +++ b/sys/include/net/gnrc/lorawan.h @@ -63,7 +63,6 @@ extern "C" { typedef enum { MCPS_EVENT_RX, /**< MCPS RX event */ MCPS_EVENT_NO_RX, /**< MCPS no RX event */ - MCPS_EVENT_ACK_TIMEOUT /**< MCPS retrans event */ } mcps_event_t; /** @@ -153,9 +152,9 @@ typedef struct { * @brief Mac Common Part Sublayer (MCPS) confirm representation */ typedef struct { - void *data; /**< data of the MCPS confirm */ int16_t status; /**< status of the MCPS confirm */ mcps_type_t type; /**< type of the MCPS confirm */ + iolist_t *msdu; /**< pointer to the msdu */ } mcps_confirm_t; /** @@ -230,9 +229,11 @@ void gnrc_lorawan_mcps_request(gnrc_lorawan_t *mac, const mcps_request_t *mcps_r * To be called on radio RX done event. * * @param[in] mac pointer to the MAC descriptor - * @param[in] pkt pointer to the packet + * @param[in] data pointer to the psdu. Pass NULL if the packet was wrong (or + * allocation failed) + * @param[in] size size of the PSDU */ -void gnrc_lorawan_radio_rx_done_cb(gnrc_lorawan_t *mac, gnrc_pktsnip_t *pkt); +void gnrc_lorawan_radio_rx_done_cb(gnrc_lorawan_t *mac, uint8_t *data, size_t size); /** * @brief MCPS indication callback diff --git a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c index 059d7ca6bc..fc134d7c0c 100644 --- a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c +++ b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan.c @@ -175,10 +175,8 @@ void gnrc_lorawan_radio_rx_timeout_cb(gnrc_lorawan_t *mac) mac->state = LORAWAN_STATE_RX_2; break; case LORAWAN_STATE_RX_2: - gnrc_lorawan_mlme_no_rx(mac); - gnrc_lorawan_mcps_event(mac, MCPS_EVENT_NO_RX, 0); + gnrc_lorawan_event_no_rx(mac); mac->state = LORAWAN_STATE_IDLE; - gnrc_lorawan_mac_release(mac); break; default: assert(false); @@ -222,57 +220,44 @@ static uint32_t lora_time_on_air(size_t payload_size, uint8_t dr, uint8_t cr) return t_preamble + t_payload; } -void gnrc_lorawan_send_pkt(gnrc_lorawan_t *mac, gnrc_pktsnip_t *pkt, uint8_t dr) +void gnrc_lorawan_send_pkt(gnrc_lorawan_t *mac, iolist_t *psdu, uint8_t dr) { netdev_t *dev = gnrc_lorawan_get_netdev(mac); mac->state = LORAWAN_STATE_TX; - iolist_t iolist = { - .iol_base = pkt->data, - .iol_len = pkt->size, - .iol_next = (iolist_t *) pkt->next - }; - uint32_t chan = gnrc_lorawan_pick_channel(mac); _config_radio(mac, chan, dr, false); - mac->last_dr = dr; - uint8_t cr; dev->driver->get(dev, NETOPT_CODING_RATE, &cr, sizeof(cr)); - mac->toa = lora_time_on_air(gnrc_pkt_len(pkt), dr, cr + 4); + mac->toa = lora_time_on_air(iolist_size(psdu), dr, cr + 4); - if (dev->driver->send(dev, &iolist) == -ENOTSUP) { + if (dev->driver->send(dev, psdu) == -ENOTSUP) { DEBUG("gnrc_lorawan: Cannot send: radio is still transmitting"); } } -void gnrc_lorawan_radio_rx_done_cb(gnrc_lorawan_t *mac, gnrc_pktsnip_t *pkt) +void gnrc_lorawan_radio_rx_done_cb(gnrc_lorawan_t *mac, uint8_t *psdu, size_t size) { _sleep_radio(mac); - if (pkt == NULL) { + if (psdu == NULL) { return; } mac->state = LORAWAN_STATE_IDLE; xtimer_remove(&mac->rx); - uint8_t *p = pkt->data; - - uint8_t mtype = (*p & MTYPE_MASK) >> 5; + uint8_t mtype = (*psdu & MTYPE_MASK) >> 5; switch (mtype) { case MTYPE_JOIN_ACCEPT: - gnrc_lorawan_mlme_process_join(mac, pkt); + gnrc_lorawan_mlme_process_join(mac, psdu, size); break; case MTYPE_CNF_DOWNLINK: case MTYPE_UNCNF_DOWNLINK: - gnrc_lorawan_mcps_process_downlink(mac, pkt); + gnrc_lorawan_mcps_process_downlink(mac, psdu, size); break; default: - gnrc_pktbuf_release(pkt); break; } - - gnrc_lorawan_mac_release(mac); } diff --git a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_crypto.c b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_crypto.c index f6b74ca817..e0a2da03c6 100644 --- a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_crypto.c +++ b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_crypto.c @@ -45,20 +45,17 @@ typedef struct __attribute__((packed)) { uint8_t len; } lorawan_block_t; -void gnrc_lorawan_calculate_join_mic(const iolist_t *io, const uint8_t *key, le_uint32_t *out) +void gnrc_lorawan_calculate_join_mic(const uint8_t *buf, size_t len, const uint8_t *key, le_uint32_t *out) { cmac_init(&CmacContext, key, LORAMAC_APPKEY_LEN); - while (io != NULL) { - cmac_update(&CmacContext, io->iol_base, io->iol_len); - io = io->iol_next; - } + cmac_update(&CmacContext, buf, len); cmac_final(&CmacContext, digest); memcpy(out, digest, sizeof(le_uint32_t)); } void gnrc_lorawan_calculate_mic(const le_uint32_t *dev_addr, uint32_t fcnt, - uint8_t dir, iolist_t *pkt, const uint8_t *nwkskey, le_uint32_t *out) + uint8_t dir, iolist_t *frame, const uint8_t *nwkskey, le_uint32_t *out) { lorawan_block_t block; @@ -72,11 +69,16 @@ void gnrc_lorawan_calculate_mic(const le_uint32_t *dev_addr, uint32_t fcnt, block.u32_pad = 0; - block.len = iolist_size(pkt); + block.len = iolist_size(frame); - iolist_t io = { .iol_base = &block, .iol_len = sizeof(block), - .iol_next = pkt }; - gnrc_lorawan_calculate_join_mic(&io, nwkskey, out); + cmac_init(&CmacContext, nwkskey, LORAMAC_APPKEY_LEN); + cmac_update(&CmacContext, &block, sizeof(block)); + for (iolist_t *io = frame; io != NULL; io = io->iol_next) { + cmac_update(&CmacContext, io->iol_base, io->iol_len); + } + cmac_final(&CmacContext, digest); + + memcpy(out, digest, sizeof(le_uint32_t)); } void gnrc_lorawan_encrypt_payload(iolist_t *iolist, const le_uint32_t *dev_addr, uint32_t fcnt, uint8_t dir, const uint8_t *appskey) diff --git a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c index d689c70bad..fdbb857ab7 100644 --- a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c +++ b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mcps.c @@ -30,17 +30,19 @@ #define _16_UPPER_BITMASK 0xFFFF0000 #define _16_LOWER_BITMASK 0xFFFF -int gnrc_lorawan_mic_is_valid(gnrc_pktsnip_t *mic, uint8_t *nwkskey) +static void _end_of_tx(gnrc_lorawan_t *mac, int type, int status); + +static int gnrc_lorawan_mic_is_valid(uint8_t *buf, size_t len, uint8_t *nwkskey) { le_uint32_t calc_mic; - assert(mic->size == MIC_SIZE); - assert(mic->next->data); - lorawan_hdr_t *lw_hdr = (lorawan_hdr_t *) mic->next->data; + lorawan_hdr_t *lw_hdr = (lorawan_hdr_t *) buf; uint32_t fcnt = byteorder_ntohs(byteorder_ltobs(lw_hdr->fcnt)); - gnrc_lorawan_calculate_mic(&lw_hdr->addr, fcnt, GNRC_LORAWAN_DIR_DOWNLINK, (iolist_t *) mic->next, nwkskey, &calc_mic); - return calc_mic.u32 == ((le_uint32_t *) mic->data)->u32; + iolist_t iol = {.iol_base = buf, .iol_len = len - MIC_SIZE, .iol_next = NULL}; + gnrc_lorawan_calculate_mic(&lw_hdr->addr, fcnt, GNRC_LORAWAN_DIR_DOWNLINK, + &iol, nwkskey, &calc_mic); + return calc_mic.u32 == ((le_uint32_t *) (buf+len-MIC_SIZE))->u32; } uint32_t gnrc_lorawan_fcnt_stol(uint32_t fcnt_down, uint16_t s_fcnt) @@ -54,120 +56,139 @@ uint32_t gnrc_lorawan_fcnt_stol(uint32_t fcnt_down, uint16_t s_fcnt) return u32_fcnt; } -void gnrc_lorawan_mcps_process_downlink(gnrc_lorawan_t *mac, gnrc_pktsnip_t *pkt) -{ - gnrc_pktsnip_t *hdr, *data, *fopts = NULL, *fport = NULL; - int release = true; - int error = true; +/** + * @brief holder of parsed packet + */ +struct parsed_packet { + uint32_t fcnt_down; /**< frame counter */ + lorawan_hdr_t *hdr; /**< pointer to the LoRaWAN header */ + bool ack_req; /**< whether an ACK was requested or not */ + iolist_t fopts; /**< iolist with Fopts information */ + iolist_t enc_payload; /**< iolist with encrypted payload */ + uint8_t port; /**< Fport of the packet */ + bool ack; /**< whether the ACK bit was set or not */ + bool frame_pending; /**< whether there's pending data or not */ +}; - /* mark MIC */ - if (!(data = gnrc_pktbuf_mark(pkt, (pkt->size - MIC_SIZE > 0) ? pkt->size - MIC_SIZE : 0, GNRC_NETTYPE_UNDEF))) { - DEBUG("gnrc_lorawan: failed to mark MIC\n"); - goto out; +int gnrc_lorawan_parse_dl(gnrc_lorawan_t *mac, uint8_t *buf, size_t len, + struct parsed_packet *pkt) +{ + memset(pkt, 0, sizeof(struct parsed_packet)); + + lorawan_hdr_t *_hdr = (lorawan_hdr_t*) buf; + uint8_t *p_mic = buf + len - MIC_SIZE; + + pkt->hdr = _hdr; + buf += sizeof(lorawan_hdr_t); + + /* Validate header */ + if (_hdr->addr.u32 != mac->dev_addr.u32) { + DEBUG("gnrc_lorawan: received packet with wrong dev addr. Drop\n"); + return -1; } + uint32_t _fcnt = gnrc_lorawan_fcnt_stol(mac->mcps.fcnt_down, _hdr->fcnt.u16); + if (mac->mcps.fcnt_down > _fcnt || mac->mcps.fcnt_down + + LORAMAC_DEFAULT_MAX_FCNT_GAP < _fcnt) { + DEBUG("gnrc_lorawan: wrong frame counter\n"); + return -1; + } + + pkt->fcnt_down = _fcnt; + + int fopts_length = lorawan_hdr_get_frame_opts_len(_hdr); + if(fopts_length) { + pkt->fopts.iol_base = buf; + pkt->fopts.iol_len = fopts_length; + buf += fopts_length; + } + + if(buf < p_mic) { + pkt->port = *(buf++); + + if (!pkt->port && fopts_length) { + DEBUG("gnrc_lorawan: packet with fopts and port == 0. Drop\n"); + return -1; + } + + if (buf < p_mic) { + pkt->enc_payload.iol_base = buf; + pkt->enc_payload.iol_len = p_mic - buf; + } + } + + pkt->ack_req = lorawan_hdr_get_mtype(_hdr) == MTYPE_CNF_DOWNLINK; + pkt->ack = lorawan_hdr_get_ack(_hdr); + pkt->frame_pending = lorawan_hdr_get_frame_pending(_hdr); + + return 0; +} + +void gnrc_lorawan_mcps_process_downlink(gnrc_lorawan_t *mac, uint8_t *psdu, size_t size) +{ + struct parsed_packet _pkt; + /* NOTE: MIC is in pkt */ - if (!gnrc_lorawan_mic_is_valid(pkt, mac->nwkskey)) { + if (!gnrc_lorawan_mic_is_valid(psdu, size, mac->nwkskey)) { DEBUG("gnrc_lorawan: invalid MIC\n"); - goto out; + gnrc_lorawan_event_no_rx(mac); + return; } - /* remove snip */ - pkt = gnrc_pktbuf_remove_snip(pkt, pkt); - - if (!(hdr = gnrc_pktbuf_mark(pkt, sizeof(lorawan_hdr_t), GNRC_NETTYPE_UNDEF))) { - DEBUG("gnrc_lorawan: failed to allocate hdr\n"); - goto out; + if (gnrc_lorawan_parse_dl(mac, psdu, size, &_pkt) < 0) { + DEBUG("gnrc_lorawan: couldn't parse packet\n"); + gnrc_lorawan_event_no_rx(mac); + return; } - int _fopts_length = lorawan_hdr_get_frame_opts_len((lorawan_hdr_t *) hdr->data); - if (_fopts_length && !(fopts = gnrc_pktbuf_mark(pkt, _fopts_length, GNRC_NETTYPE_UNDEF))) { - DEBUG("gnrc_lorawan: failed to allocate fopts\n"); - goto out; + iolist_t *fopts = NULL; + if(_pkt.fopts.iol_base) { + fopts = &_pkt.fopts; } - assert(pkt != NULL); - - int fopts_in_payload = 0; - /* only for download frames with payload the FPort must be present */ - if (pkt->size) { - if ((fport = gnrc_pktbuf_mark(pkt, 1, GNRC_NETTYPE_UNDEF)) == NULL) { - DEBUG("gnrc_lorawan: failed to allocate fport\n"); - goto out; + if(_pkt.enc_payload.iol_base) { + uint8_t *key; + if(_pkt.port) { + key = mac->appskey; } - - assert(fport->data); - - fopts_in_payload = *((uint8_t *) fport->data) == 0; - if (fopts && fopts_in_payload) { - DEBUG("gnrc_lorawan: packet with fopts and port == 0. Drop\n"); - goto out; + else { + key = mac->nwkskey; + fopts = &_pkt.enc_payload; } + gnrc_lorawan_encrypt_payload(&_pkt.enc_payload, &_pkt.hdr->addr, byteorder_ntohs(byteorder_ltobs(_pkt.hdr->fcnt)), GNRC_LORAWAN_DIR_DOWNLINK, key); } - lorawan_hdr_t *lw_hdr = hdr->data; - - if (lw_hdr->addr.u32 != mac->dev_addr.u32) { - DEBUG("gnrc_lorawan: received packet with wrong dev addr. Drop\n"); - goto out; + mac->mcps.fcnt_down = _pkt.fcnt_down; + if (mac->mcps.waiting_for_ack && !_pkt.ack) { + DEBUG("gnrc_lorawan: expected ACK packet\n"); + gnrc_lorawan_event_no_rx(mac); + return; } - uint32_t fcnt = gnrc_lorawan_fcnt_stol(mac->mcps.fcnt_down, lw_hdr->fcnt.u16); - if (mac->mcps.fcnt_down > fcnt || mac->mcps.fcnt_down + - LORAMAC_DEFAULT_MAX_FCNT_GAP < fcnt) { - goto out; - } - - mac->mcps.fcnt_down = fcnt; - error = false; - - int ack_req = lorawan_hdr_get_mtype(lw_hdr) == MTYPE_CNF_DOWNLINK; - if (ack_req) { + if (_pkt.ack_req) { mac->mcps.ack_requested = true; } - iolist_t payload = { .iol_base = pkt->data, .iol_len = pkt->size }; - if (pkt->data) { - gnrc_lorawan_encrypt_payload(&payload, &lw_hdr->addr, - byteorder_ntohs(byteorder_ltobs(lw_hdr->fcnt)), - GNRC_LORAWAN_DIR_DOWNLINK, - fopts_in_payload ? mac->nwkskey : mac->appskey); - } - /* if there are fopts, it's either an empty packet or application payload */ if (fopts) { - gnrc_lorawan_process_fopts(mac, fopts->data, fopts->size); - } - else if (fopts_in_payload) { - gnrc_lorawan_process_fopts(mac, pkt->data, pkt->size); + DEBUG("gnrc_lorawan: processing fopts\n"); + gnrc_lorawan_process_fopts(mac, fopts->iol_base, fopts->iol_len); } - gnrc_lorawan_mcps_event(mac, MCPS_EVENT_RX, lorawan_hdr_get_ack(lw_hdr)); - if (pkt->data && fport && *((uint8_t *) fport->data) != 0) { - pkt->type = GNRC_NETTYPE_LORAWAN; - release = false; + _end_of_tx(mac, MCPS_CONFIRMED, GNRC_LORAWAN_REQ_STATUS_SUCCESS); - mcps_indication_t mcps_indication; - mcps_indication.type = ack_req; - mcps_indication.data.pkt = pkt; - mcps_indication.data.port = *((uint8_t *) fport->data); - gnrc_lorawan_mcps_indication(mac, &mcps_indication); - } - - if (lorawan_hdr_get_frame_pending(lw_hdr)) { + if (_pkt.frame_pending) { mlme_indication_t mlme_indication; mlme_indication.type = MLME_SCHEDULE_UPLINK; gnrc_lorawan_mlme_indication(mac, &mlme_indication); } -out: - if (error) { - gnrc_lorawan_mcps_event(mac, MCPS_EVENT_NO_RX, 0); - } - - if (release) { - DEBUG("gnrc_lorawan: release packet\n"); - gnrc_pktbuf_release(pkt); + if (_pkt.port) { + mcps_indication_t mcps_indication; + mcps_indication.type = _pkt.ack_req; + mcps_indication.data.pkt = &_pkt.enc_payload; + mcps_indication.data.port = _pkt.port; + gnrc_lorawan_mcps_indication(mac, &mcps_indication); } } @@ -193,95 +214,130 @@ size_t gnrc_lorawan_build_hdr(uint8_t mtype, le_uint32_t *dev_addr, uint32_t fcn return sizeof(lorawan_hdr_t); } -gnrc_pktsnip_t *gnrc_lorawan_build_uplink(gnrc_lorawan_t *mac, gnrc_pktsnip_t *payload, int confirmed_data, uint8_t port) +size_t gnrc_lorawan_build_uplink(gnrc_lorawan_t *mac, iolist_t *payload, int confirmed_data, uint8_t port) { - /* Encrypt payload (it's block encryption so we can use the same buffer!) */ - gnrc_lorawan_encrypt_payload((iolist_t *) payload, &mac->dev_addr, mac->mcps.fcnt, GNRC_LORAWAN_DIR_UPLINK, port ? mac->appskey : mac->nwkskey); - - /* We try to allocate the whole header with fopts at once */ - uint8_t fopts_length = gnrc_lorawan_build_options(mac, NULL); - - gnrc_pktsnip_t *mac_hdr = gnrc_pktbuf_add(payload, NULL, sizeof(lorawan_hdr_t) + fopts_length + 1, GNRC_NETTYPE_UNDEF); - - if (!mac_hdr) { - gnrc_pktbuf_release_error(payload, -ENOBUFS); - return NULL; - } - - gnrc_pktsnip_t *mic = gnrc_pktbuf_add(NULL, NULL, MIC_SIZE, GNRC_NETTYPE_UNDEF); - if (!mic) { - gnrc_pktbuf_release_error(mac_hdr, -ENOBUFS); - return NULL; - } - lorawan_buffer_t buf = { - .data = (uint8_t *) mac_hdr->data, - .size = mac_hdr->size, + .data = (uint8_t *) mac->mcps.mhdr_mic, + .size = sizeof(mac->mcps.mhdr_mic), .index = 0 }; + lorawan_hdr_t *lw_hdr = (lorawan_hdr_t *) buf.data; - gnrc_lorawan_build_hdr(confirmed_data ? MTYPE_CNF_UPLINK : MTYPE_UNCNF_UPLINK, - &mac->dev_addr, mac->mcps.fcnt, mac->mcps.ack_requested, fopts_length, &buf); + lw_hdr->mt_maj = 0; + lorawan_hdr_set_mtype(lw_hdr, confirmed_data ? MTYPE_CNF_UPLINK : MTYPE_UNCNF_UPLINK); + lorawan_hdr_set_maj(lw_hdr, MAJOR_LRWAN_R1); - gnrc_lorawan_build_options(mac, &buf); + lw_hdr->addr = mac->dev_addr; + lw_hdr->fctrl = 0; - assert(buf.index == mac_hdr->size - 1); + lorawan_hdr_set_ack(lw_hdr, mac->mcps.ack_requested); + + lw_hdr->fcnt = byteorder_btols(byteorder_htons(mac->mcps.fcnt)); + + buf.index += sizeof(lorawan_hdr_t); + + int fopts_length = gnrc_lorawan_build_options(mac, &buf); + assert(fopts_length < 16); + lorawan_hdr_set_frame_opts_len(lw_hdr, fopts_length); buf.data[buf.index++] = port; + gnrc_lorawan_encrypt_payload(payload, &mac->dev_addr, mac->mcps.fcnt, GNRC_LORAWAN_DIR_UPLINK, port ? mac->appskey : mac->nwkskey); + + iolist_t iol = {.iol_base = buf.data, .iol_len = buf.index, .iol_next = payload}; gnrc_lorawan_calculate_mic(&mac->dev_addr, mac->mcps.fcnt, GNRC_LORAWAN_DIR_UPLINK, - (iolist_t *) mac_hdr, mac->nwkskey, mic->data); + &iol, mac->nwkskey, (le_uint32_t*) &buf.data[buf.index]); - LL_APPEND(payload, mic); - - return mac_hdr; + return buf.index; } static void _end_of_tx(gnrc_lorawan_t *mac, int type, int status) { + mlme_confirm_t mlme_confirm; + mcps_confirm_t mcps_confirm; + mac->mcps.waiting_for_ack = false; - mcps_confirm_t mcps_confirm; + mac->mcps.fcnt++; + + gnrc_lorawan_mac_release(mac); + + if (mac->mlme.pending_mlme_opts & GNRC_LORAWAN_MLME_OPTS_LINK_CHECK_REQ) { + mlme_confirm.type = MLME_LINK_CHECK; + mlme_confirm.status = -ETIMEDOUT; + mac->mlme.pending_mlme_opts &= ~GNRC_LORAWAN_MLME_OPTS_LINK_CHECK_REQ; + gnrc_lorawan_mlme_confirm(mac, &mlme_confirm); + } mcps_confirm.type = type; mcps_confirm.status = status; + mcps_confirm.msdu = mac->mcps.msdu; + mac->mcps.msdu = NULL; gnrc_lorawan_mcps_confirm(mac, &mcps_confirm); - - mac->mcps.fcnt += 1; } -void gnrc_lorawan_mcps_event(gnrc_lorawan_t *mac, int event, int data) +static void _transmit_pkt(gnrc_lorawan_t *mac) { + size_t mhdr_size = sizeof(lorawan_hdr_t) + 1 + lorawan_hdr_get_frame_opts_len((void*) mac->mcps.mhdr_mic); + + iolist_t header = {.iol_base = mac->mcps.mhdr_mic, .iol_len = mhdr_size, .iol_next = mac->mcps.msdu}; + iolist_t footer = {.iol_base = mac->mcps.mhdr_mic + header.iol_len, .iol_len = MIC_SIZE, .iol_next = NULL}; + iolist_t *last_snip = mac->mcps.msdu; + while (last_snip->iol_next != NULL) { + last_snip = last_snip->iol_next; + } + + last_snip->iol_next = &footer; + gnrc_lorawan_send_pkt(mac, &header, mac->last_dr); + + /* cppcheck-suppress redundantAssignment + * (reason: cppcheck bug. The pointer is temporally modified to add a footer. + * The `gnrc_lorawan_send_pkt` function uses this hack to append + * the MIC independently of `gnrc_pktsnip_t` structures) */ + last_snip->iol_next = NULL; +} + +void gnrc_lorawan_event_ack_timeout(gnrc_lorawan_t *mac) +{ + _transmit_pkt(mac); +} + +static void _handle_retransmissions(gnrc_lorawan_t *mac) +{ + if (mac->mcps.nb_trials-- == 0) { + _end_of_tx(mac, MCPS_CONFIRMED, -ETIMEDOUT); + } else { + mac->msg.type = MSG_TYPE_MCPS_ACK_TIMEOUT; + xtimer_set_msg(&mac->rx, 1000000 + random_uint32_range(0, 2000000), &mac->msg, thread_getpid()); + } +} + +void gnrc_lorawan_event_no_rx(gnrc_lorawan_t *mac) +{ + mlme_confirm_t mlme_confirm; + if (mac->mlme.activation == MLME_ACTIVATION_NONE) { + /* This was a Join Request */ + mlme_confirm.type = MLME_JOIN; + mlme_confirm.status = -ETIMEDOUT; + gnrc_lorawan_mac_release(mac); + gnrc_lorawan_mlme_confirm(mac, &mlme_confirm); return; } - if (event == MCPS_EVENT_ACK_TIMEOUT) { - gnrc_lorawan_send_pkt(mac, mac->mcps.outgoing_pkt, mac->last_dr); + /* Otherwise check if retransmission should be handled */ + + if (mac->mcps.waiting_for_ack) { + _handle_retransmissions(mac); } else { - int state = mac->mcps.waiting_for_ack ? MCPS_CONFIRMED : MCPS_UNCONFIRMED; - if (state == MCPS_CONFIRMED && ((event == MCPS_EVENT_RX && !data) || - event == MCPS_EVENT_NO_RX)) { - if (mac->mcps.nb_trials-- == 0) { - _end_of_tx(mac, MCPS_CONFIRMED, -ETIMEDOUT); - } - } - else { - _end_of_tx(mac, state, GNRC_LORAWAN_REQ_STATUS_SUCCESS); - } - - mac->msg.type = MSG_TYPE_MCPS_ACK_TIMEOUT; - if (mac->mcps.outgoing_pkt) { - xtimer_set_msg(&mac->rx, 1000000 + random_uint32_range(0, 2000000), &mac->msg, thread_getpid()); - } + _end_of_tx(mac, MCPS_UNCONFIRMED, GNRC_LORAWAN_REQ_STATUS_SUCCESS); } } void gnrc_lorawan_mcps_request(gnrc_lorawan_t *mac, const mcps_request_t *mcps_request, mcps_confirm_t *mcps_confirm) { - int release = true; - gnrc_pktsnip_t *pkt = mcps_request->data.pkt; + iolist_t *pkt = mcps_request->data.pkt; if (mac->mlme.activation == MLME_ACTIVATION_NONE) { DEBUG("gnrc_lorawan_mcps: LoRaWAN not activated\n"); @@ -305,39 +361,35 @@ void gnrc_lorawan_mcps_request(gnrc_lorawan_t *mac, const mcps_request_t *mcps_r goto out; } - int waiting_for_ack = mcps_request->type == MCPS_CONFIRMED; - if (!(pkt = gnrc_lorawan_build_uplink(mac, pkt, waiting_for_ack, mcps_request->data.port))) { - /* This function releases the pkt if fails */ - release = false; - mcps_confirm->status = -ENOBUFS; - goto out; - } + uint8_t fopts_length = gnrc_lorawan_build_options(mac, NULL); + /* We don't include the port because `MACPayload` doesn't consider + * the MHDR...*/ + size_t mac_payload_size = sizeof(lorawan_hdr_t) + fopts_length + + iolist_size(pkt); - if ((gnrc_pkt_len(pkt) - MIC_SIZE - 1) > gnrc_lorawan_region_mac_payload_max(mcps_request->data.dr)) { + if (mac_payload_size > gnrc_lorawan_region_mac_payload_max(mcps_request->data.dr)) { mcps_confirm->status = -EMSGSIZE; goto out; } - release = false; + int waiting_for_ack = mcps_request->type == MCPS_CONFIRMED; + + gnrc_lorawan_build_uplink(mac, pkt, waiting_for_ack, mcps_request->data.port); + mac->mcps.waiting_for_ack = waiting_for_ack; mac->mcps.ack_requested = false; mac->mcps.nb_trials = LORAMAC_DEFAULT_RETX; - assert(mac->mcps.outgoing_pkt == NULL); - mac->mcps.outgoing_pkt = pkt; - - gnrc_lorawan_send_pkt(mac, pkt, mcps_request->data.dr); + mac->mcps.msdu = pkt; + mac->last_dr = mcps_request->data.dr; + _transmit_pkt(mac); mcps_confirm->status = GNRC_LORAWAN_REQ_STATUS_DEFERRED; out: if (mcps_confirm->status != GNRC_LORAWAN_REQ_STATUS_DEFERRED) { gnrc_lorawan_mac_release(mac); } - - if (release) { - gnrc_pktbuf_release_error(pkt, mcps_confirm->status); - } } /** @} */ diff --git a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mlme.c b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mlme.c index 48f46cd446..61e5e39432 100644 --- a/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mlme.c +++ b/sys/net/gnrc/link_layer/lorawan/gnrc_lorawan_mlme.c @@ -28,32 +28,24 @@ #define ENABLE_DEBUG (0) #include "debug.h" -static gnrc_pktsnip_t *_build_join_req_pkt(uint8_t *appeui, uint8_t *deveui, uint8_t *appkey, uint8_t *dev_nonce) +static void _build_join_req_pkt(uint8_t *appeui, uint8_t *deveui, uint8_t *appkey, uint8_t *dev_nonce, uint8_t *psdu) { - gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, NULL, sizeof(lorawan_join_request_t), GNRC_NETTYPE_UNDEF); + lorawan_join_request_t *hdr = (lorawan_join_request_t *) psdu; - if (pkt) { - lorawan_join_request_t *hdr = (lorawan_join_request_t *) pkt->data; + hdr->mt_maj = 0; + lorawan_hdr_set_mtype((lorawan_hdr_t *) hdr, MTYPE_JOIN_REQUEST); + lorawan_hdr_set_maj((lorawan_hdr_t *) hdr, MAJOR_LRWAN_R1); - hdr->mt_maj = 0; - lorawan_hdr_set_mtype((lorawan_hdr_t *) hdr, MTYPE_JOIN_REQUEST); - lorawan_hdr_set_maj((lorawan_hdr_t *) hdr, MAJOR_LRWAN_R1); + le_uint64_t l_appeui = *((le_uint64_t *) appeui); + le_uint64_t l_deveui = *((le_uint64_t *) deveui); - le_uint64_t l_appeui = *((le_uint64_t *) appeui); - le_uint64_t l_deveui = *((le_uint64_t *) deveui); + hdr->app_eui = l_appeui; + hdr->dev_eui = l_deveui; - hdr->app_eui = l_appeui; - hdr->dev_eui = l_deveui; + le_uint16_t l_dev_nonce = *((le_uint16_t *) dev_nonce); + hdr->dev_nonce = l_dev_nonce; - le_uint16_t l_dev_nonce = *((le_uint16_t *) dev_nonce); - hdr->dev_nonce = l_dev_nonce; - - iolist_t io = { .iol_base = pkt->data, .iol_len = JOIN_REQUEST_SIZE - MIC_SIZE, - .iol_next = NULL }; - gnrc_lorawan_calculate_join_mic(&io, appkey, &hdr->mic); - } - - return pkt; + gnrc_lorawan_calculate_join_mic(psdu, JOIN_REQUEST_SIZE - MIC_SIZE, appkey, &hdr->mic); } static int gnrc_lorawan_send_join_request(gnrc_lorawan_t *mac, uint8_t *deveui, @@ -69,56 +61,54 @@ static int gnrc_lorawan_send_join_request(gnrc_lorawan_t *mac, uint8_t *deveui, mac->mlme.dev_nonce[1] = (random_number >> 8) & 0xFF; /* build join request */ - gnrc_pktsnip_t *pkt = _build_join_req_pkt(appeui, deveui, appkey, mac->mlme.dev_nonce); - if (!pkt) { - return -ENOBUFS; - } + uint8_t psdu[sizeof(lorawan_join_request_t)]; + + iolist_t pkt = {.iol_base = &psdu, .iol_len = sizeof(psdu), .iol_next = NULL}; + _build_join_req_pkt(appeui, deveui, appkey, mac->mlme.dev_nonce, psdu); /* We need a random delay for join request. Otherwise there might be * network congestion if a group of nodes start at the same time */ xtimer_usleep(random_uint32() & GNRC_LORAWAN_JOIN_DELAY_U32_MASK); - gnrc_lorawan_send_pkt(mac, pkt, dr); + gnrc_lorawan_send_pkt(mac, &pkt, dr); mac->mlme.backoff_budget -= mac->toa; - gnrc_pktbuf_release(pkt); return GNRC_LORAWAN_REQ_STATUS_DEFERRED; } -void gnrc_lorawan_mlme_process_join(gnrc_lorawan_t *mac, gnrc_pktsnip_t *pkt) +void gnrc_lorawan_mlme_process_join(gnrc_lorawan_t *mac, uint8_t *data, size_t size) { int status; + mlme_confirm_t mlme_confirm; if (mac->mlme.activation != MLME_ACTIVATION_NONE) { status = -EBADMSG; goto out; } - if (pkt->size != GNRC_LORAWAN_JOIN_ACCEPT_MAX_SIZE - CFLIST_SIZE && - pkt->size != GNRC_LORAWAN_JOIN_ACCEPT_MAX_SIZE) { + if (size != GNRC_LORAWAN_JOIN_ACCEPT_MAX_SIZE - CFLIST_SIZE && + size != GNRC_LORAWAN_JOIN_ACCEPT_MAX_SIZE) { status = -EBADMSG; goto out; } /* Subtract 1 from join accept max size, since the MHDR was already read */ uint8_t out[GNRC_LORAWAN_JOIN_ACCEPT_MAX_SIZE - 1]; - uint8_t has_cflist = (pkt->size - 1) >= CFLIST_SIZE; - gnrc_lorawan_decrypt_join_accept(mac->appskey, ((uint8_t *) pkt->data) + 1, + uint8_t has_cflist = (size - 1) >= CFLIST_SIZE; + gnrc_lorawan_decrypt_join_accept(mac->appskey, data + 1, has_cflist, out); - memcpy(((uint8_t *) pkt->data) + 1, out, pkt->size - 1); + memcpy(data + 1, out, size - 1); - iolist_t io = { .iol_base = pkt->data, .iol_len = pkt->size - MIC_SIZE, - .iol_next = NULL }; le_uint32_t mic; - le_uint32_t *expected_mic = (le_uint32_t *) (((uint8_t *) pkt->data) + pkt->size - MIC_SIZE); - gnrc_lorawan_calculate_join_mic(&io, mac->appskey, &mic); + le_uint32_t *expected_mic = (le_uint32_t *) (data + size - MIC_SIZE); + gnrc_lorawan_calculate_join_mic(data, size - MIC_SIZE, mac->appskey, &mic); if (mic.u32 != expected_mic->u32) { DEBUG("gnrc_lorawan_mlme: wrong MIC.\n"); status = -EBADMSG; goto out; } - lorawan_join_accept_t *ja_hdr = (lorawan_join_accept_t *) pkt->data; + lorawan_join_accept_t *ja_hdr = (lorawan_join_accept_t *) data; gnrc_lorawan_generate_session_keys(ja_hdr->app_nonce, mac->mlme.dev_nonce, mac->appskey, mac->nwkskey, mac->appskey); le_uint32_t le_nid; @@ -138,11 +128,10 @@ void gnrc_lorawan_mlme_process_join(gnrc_lorawan_t *mac, gnrc_pktsnip_t *pkt) status = GNRC_LORAWAN_REQ_STATUS_SUCCESS; out: - gnrc_pktbuf_release(pkt); - mlme_confirm_t mlme_confirm; mlme_confirm.type = MLME_JOIN; mlme_confirm.status = status; + gnrc_lorawan_mac_release(mac); gnrc_lorawan_mlme_confirm(mac, &mlme_confirm); } @@ -321,20 +310,3 @@ uint8_t gnrc_lorawan_build_options(gnrc_lorawan_t *mac, lorawan_buffer_t *buf) return size; } - -void gnrc_lorawan_mlme_no_rx(gnrc_lorawan_t *mac) -{ - mlme_confirm_t mlme_confirm; - - mlme_confirm.status = -ETIMEDOUT; - - if (mac->mlme.activation == MLME_ACTIVATION_NONE) { - mlme_confirm.type = MLME_JOIN; - gnrc_lorawan_mlme_confirm(mac, &mlme_confirm); - } - else if (mac->mlme.pending_mlme_opts & GNRC_LORAWAN_MLME_OPTS_LINK_CHECK_REQ) { - mlme_confirm.type = MLME_LINK_CHECK; - gnrc_lorawan_mlme_confirm(mac, &mlme_confirm); - mac->mlme.pending_mlme_opts &= ~GNRC_LORAWAN_MLME_OPTS_LINK_CHECK_REQ; - } -} diff --git a/sys/net/gnrc/link_layer/lorawan/include/gnrc_lorawan_internal.h b/sys/net/gnrc/link_layer/lorawan/include/gnrc_lorawan_internal.h index 5e19c86099..167aea346a 100644 --- a/sys/net/gnrc/link_layer/lorawan/include/gnrc_lorawan_internal.h +++ b/sys/net/gnrc/link_layer/lorawan/include/gnrc_lorawan_internal.h @@ -99,6 +99,17 @@ extern "C" { #define GNRC_LORAWAN_NET_ID_SIZE (3U) /**< Net ID size */ #define GNRC_LORAWAN_DEV_NONCE_SIZE (2U) /**< Dev Nonce size */ +#define GNRC_LORAWAN_FOPTS_MAX_SIZE (15U) /**< Maximum size of Fopts field */ +#define GNRC_LORAWAN_FPORT_SIZE (1U) /**< Size of the Fport field */ + +/** + * @brief Size of the internal MHDR-MIC buffer + */ +#define MHDR_MIC_BUF_SIZE (sizeof(lorawan_hdr_t) + \ + GNRC_LORAWAN_FOPTS_MAX_SIZE + \ + GNRC_LORAWAN_FPORT_SIZE + \ + MIC_SIZE) + /** * @brief buffer helper for parsing and constructing LoRaWAN packets. */ @@ -130,7 +141,7 @@ typedef struct { * @brief MCPS data */ typedef struct { - gnrc_pktsnip_t *pkt; /**< packet of the request */ + iolist_t *pkt; /**< packet of the request */ uint8_t port; /**< port of the request */ uint8_t dr; /**< datarate of the request */ } mcps_data_t; @@ -141,10 +152,11 @@ typedef struct { typedef struct { uint32_t fcnt; /**< uplink framecounter */ uint32_t fcnt_down; /**< downlink frame counter */ - gnrc_pktsnip_t *outgoing_pkt; /**< holds the outgoing packet in case of retransmissions */ + iolist_t *msdu; /**< current MSDU */ int nb_trials; /**< holds the remaining number of retransmissions */ int ack_requested; /**< whether the network server requested an ACK */ int waiting_for_ack; /**< true if the MAC layer is waiting for an ACK */ + char mhdr_mic[MHDR_MIC_BUF_SIZE]; /**< internal retransmissions buffer */ } gnrc_lorawan_mcps_t; /** @@ -189,7 +201,7 @@ typedef struct { * * @note This function is also used for decrypting a LoRaWAN packet. The LoRaWAN server encrypts the packet using decryption, so the end device only needs to implement encryption * - * @param[in] iolist packet iolist representation + * @param[in] iolist pointer to the MSDU frame * @param[in] dev_addr device address * @param[in] fcnt frame counter * @param[in] dir direction of the packet (0 if uplink, 1 if downlink) @@ -243,7 +255,7 @@ int gnrc_lorawan_set_dr(gnrc_lorawan_t *mac, uint8_t datarate); * @return full LoRaWAN frame including payload * @return NULL if packet buffer is full. `payload` is released */ -gnrc_pktsnip_t *gnrc_lorawan_build_uplink(gnrc_lorawan_t *mac, gnrc_pktsnip_t *payload, int confirmed_data, uint8_t port); +size_t gnrc_lorawan_build_uplink(gnrc_lorawan_t *mac, iolist_t *payload, int confirmed_data, uint8_t port); /** * @brief pick a random available LoRaWAN channel @@ -277,11 +289,12 @@ void gnrc_lorawan_process_fopts(gnrc_lorawan_t *mac, uint8_t *fopts, size_t size /** * @brief calculate join Message Integrity Code * - * @param[in] io iolist representation of the packet + * @param[in] buf pointer to the frame + * @param[in] len length of the frame * @param[in] key key used to calculate the MIC * @param[out] out calculated MIC */ -void gnrc_lorawan_calculate_join_mic(const iolist_t *io, const uint8_t *key, le_uint32_t *out); +void gnrc_lorawan_calculate_join_mic(const uint8_t *buf, size_t len, const uint8_t *key, le_uint32_t *out); /** * @brief Calculate Message Integrity Code for a MCPS message @@ -289,13 +302,12 @@ void gnrc_lorawan_calculate_join_mic(const iolist_t *io, const uint8_t *key, le * @param[in] dev_addr the Device Address * @param[in] fcnt frame counter * @param[in] dir direction of the packet (0 is uplink, 1 is downlink) - * @param[in] pkt the pkt + * @param[in] frame pointer to the PSDU frame (witout MIC) * @param[in] nwkskey pointer to the Network Session Key * @param[out] out calculated MIC */ void gnrc_lorawan_calculate_mic(const le_uint32_t *dev_addr, uint32_t fcnt, - uint8_t dir, iolist_t *pkt, const uint8_t *nwkskey, le_uint32_t *out); - + uint8_t dir, iolist_t *frame, const uint8_t *nwkskey, le_uint32_t *out); /** * @brief Build a MCPS LoRaWAN header * @@ -314,9 +326,10 @@ size_t gnrc_lorawan_build_hdr(uint8_t mtype, le_uint32_t *dev_addr, uint32_t fcn * @brief Process an MCPS downlink message (confirmable or non comfirmable) * * @param[in] mac pointer to the MAC descriptor - * @param[in] pkt pointer to the downlink message + * @param[in] psdu pointer to the downlink PSDU + * @param[in] size size of the PSDU */ -void gnrc_lorawan_mcps_process_downlink(gnrc_lorawan_t *mac, gnrc_pktsnip_t *pkt); +void gnrc_lorawan_mcps_process_downlink(gnrc_lorawan_t *mac, uint8_t *psdu, size_t size); /** * @brief Init regional channel settings. @@ -340,18 +353,19 @@ void gnrc_lorawan_reset(gnrc_lorawan_t *mac); * @brief Send a LoRaWAN packet * * @param[in] mac pointer to the MAC descriptor - * @param[in] pkt the packet to be sent + * @param[in] psdu the psdu frame to be sent * @param[in] dr the datarate used for the transmission */ -void gnrc_lorawan_send_pkt(gnrc_lorawan_t *mac, gnrc_pktsnip_t *pkt, uint8_t dr); +void gnrc_lorawan_send_pkt(gnrc_lorawan_t *mac, iolist_t *psdu, uint8_t dr); /** * @brief Process join accept message * * @param[in] mac pointer to the MAC descriptor - * @param[in] pkt the Join Accept packet + * @param[in] data the Join Accept packet + * @param[in] size size of the Join Accept packet */ -void gnrc_lorawan_mlme_process_join(gnrc_lorawan_t *mac, gnrc_pktsnip_t *pkt); +void gnrc_lorawan_mlme_process_join(gnrc_lorawan_t *mac, uint8_t *data, size_t size); /** * @brief Inform the MAC layer that no packet was received during reception. @@ -364,13 +378,18 @@ void gnrc_lorawan_mlme_process_join(gnrc_lorawan_t *mac, gnrc_pktsnip_t *pkt); void gnrc_lorawan_mlme_no_rx(gnrc_lorawan_t *mac); /** - * @brief Trigger a MCPS event + * @brief Mac callback for no RX * * @param[in] mac pointer to the MAC descriptor - * @param[in] event the event to be processed. - * @param[in] data set to true if the packet contains payload */ -void gnrc_lorawan_mcps_event(gnrc_lorawan_t *mac, int event, int data); +void gnrc_lorawan_event_no_rx(gnrc_lorawan_t *mac); + +/** + * @brief Mac callback for ACK timeout event + * + * @param[in] mac pointer to the MAC descriptor + */ +void gnrc_lorawan_event_ack_timeout(gnrc_lorawan_t *mac); /** * @brief Get the maximum MAC payload (M value) for a given datarate. @@ -400,7 +419,7 @@ void gnrc_lorawan_mlme_backoff_expire(gnrc_lorawan_t *mac); * @param[in] mac pointer to the MAC descriptor * @param[in] pkt the received packet */ -void gnrc_lorawan_process_pkt(gnrc_lorawan_t *mac, gnrc_pktsnip_t *pkt); +void gnrc_lorawan_process_pkt(gnrc_lorawan_t *mac, iolist_t *pkt); /** * @brief Open a reception window diff --git a/sys/net/gnrc/netif/lorawan/gnrc_netif_lorawan.c b/sys/net/gnrc/netif/lorawan/gnrc_netif_lorawan.c index 43e213282a..7f89896dcd 100644 --- a/sys/net/gnrc/netif/lorawan/gnrc_netif_lorawan.c +++ b/sys/net/gnrc/netif/lorawan/gnrc_netif_lorawan.c @@ -85,9 +85,10 @@ static inline void _set_be_addr(gnrc_lorawan_t *mac, uint8_t *be_addr) void gnrc_lorawan_mcps_indication(gnrc_lorawan_t *mac, mcps_indication_t *ind) { (void) mac; + gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, ind->data.pkt->iol_base, ind->data.pkt->iol_len, GNRC_NETTYPE_LORAWAN); if (!gnrc_netapi_dispatch_receive(GNRC_NETTYPE_LORAWAN, ind->data.port, - ind->data.pkt)) { - gnrc_pktbuf_release(ind->data.pkt); + pkt)) { + gnrc_pktbuf_release(pkt); } } @@ -99,13 +100,12 @@ void gnrc_lorawan_mlme_indication(gnrc_lorawan_t *mac, mlme_indication_t *ind) void gnrc_lorawan_mcps_confirm(gnrc_lorawan_t *mac, mcps_confirm_t *confirm) { - if (confirm->status == 0) { - gnrc_pktbuf_release(mac->mcps.outgoing_pkt); - } - else { - gnrc_pktbuf_release_error(mac->mcps.outgoing_pkt, 1); - } - mac->mcps.outgoing_pkt = NULL; + (void)mac; + + gnrc_pktbuf_release_error((gnrc_pktsnip_t *)confirm->msdu, confirm->status); + + DEBUG("gnrc_lorawan: transmission finished with status %i\n", + confirm->status); } static void _rx_done(gnrc_lorawan_t *mac) @@ -116,20 +116,21 @@ static void _rx_done(gnrc_lorawan_t *mac) struct netdev_radio_rx_info rx_info; gnrc_pktsnip_t *pkt = gnrc_pktbuf_add(NULL, NULL, bytes_expected, GNRC_NETTYPE_UNDEF); if (pkt == NULL) { - DEBUG("_recv_ieee802154: cannot allocate pktsnip.\n"); + DEBUG("_recv_lorawan: cannot allocate pktsnip.\n"); /* Discard packet on netdev device */ dev->driver->recv(dev, NULL, bytes_expected, NULL); - gnrc_lorawan_radio_rx_done_cb(mac, NULL); + gnrc_lorawan_radio_rx_done_cb(mac, NULL, 0); return; } nread = dev->driver->recv(dev, pkt->data, bytes_expected, &rx_info); if (nread <= 0) { gnrc_pktbuf_release(pkt); - gnrc_lorawan_radio_rx_done_cb(mac, NULL); + gnrc_lorawan_radio_rx_done_cb(mac, NULL, 0); return; } - gnrc_lorawan_radio_rx_done_cb(mac, pkt); + gnrc_lorawan_radio_rx_done_cb(mac, pkt->data, pkt->size); + gnrc_pktbuf_release(pkt); } static void _driver_cb(netdev_t *dev, netdev_event_t event) @@ -229,10 +230,13 @@ static int _send(gnrc_netif_t *netif, gnrc_pktsnip_t *payload) gnrc_lorawan_mlme_request(&netif->lorawan.mac, &mlme_request, &mlme_confirm); } mcps_request_t req = { .type = netif->lorawan.ack_req ? MCPS_CONFIRMED : MCPS_UNCONFIRMED, - .data = { .pkt = payload, .port = netif->lorawan.port, + .data = { .pkt = (iolist_t*) payload, .port = netif->lorawan.port, .dr = netif->lorawan.datarate } }; mcps_confirm_t conf; gnrc_lorawan_mcps_request(&netif->lorawan.mac, &req, &conf); + if (conf.status < 0) { + gnrc_pktbuf_release_error(payload, conf.status); + } return conf.status; } @@ -245,7 +249,7 @@ static void _msg_handler(gnrc_netif_t *netif, msg_t *msg) gnrc_lorawan_open_rx_window(&netif->lorawan.mac); break; case MSG_TYPE_MCPS_ACK_TIMEOUT: - gnrc_lorawan_mcps_event(&netif->lorawan.mac, MCPS_EVENT_ACK_TIMEOUT, 0); + gnrc_lorawan_event_ack_timeout(&netif->lorawan.mac); break; case MSG_TYPE_MLME_BACKOFF_EXPIRE: gnrc_lorawan_mlme_backoff_expire(&netif->lorawan.mac);