From 4fe1da9f588230d690d3df4232d066243bbe7b19 Mon Sep 17 00:00:00 2001 From: Robert Lubos Date: Thu, 11 Apr 2019 15:32:41 +0200 Subject: [PATCH] net: openthread: Process real ACK frame instead of fake one OpenThread radio layer did not implement `ieee802154_radio_handle_ack` API and provided fake ACK frame to the OpenThread. This prevented proper Sleepy End Device operation, as it expects to receive information in the ACK whether it should wait for more data to come or should it put the radio to sleep. Signed-off-by: Robert Lubos --- subsys/net/l2/openthread/openthread.c | 10 ---- subsys/net/lib/openthread/platform/radio.c | 67 +++++++++++++++++----- 2 files changed, 53 insertions(+), 24 deletions(-) diff --git a/subsys/net/l2/openthread/openthread.c b/subsys/net/l2/openthread/openthread.c index 02a917260ff..c9882cb49c6 100644 --- a/subsys/net/l2/openthread/openthread.c +++ b/subsys/net/l2/openthread/openthread.c @@ -313,16 +313,6 @@ exit: return len; } -enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface, - struct net_buf *buf) -{ - ARG_UNUSED(iface); - ARG_UNUSED(buf); - NET_DBG(""); - - return NET_CONTINUE; -} - static void openthread_start(struct openthread_context *ot_context) { otInstance *ot_instance = ot_context->instance; diff --git a/subsys/net/lib/openthread/platform/radio.c b/subsys/net/lib/openthread/platform/radio.c index 8bef7f01c01..2e2ed2e8029 100644 --- a/subsys/net/lib/openthread/platform/radio.c +++ b/subsys/net/lib/openthread/platform/radio.c @@ -38,10 +38,16 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define SHORT_ADDRESS_SIZE 2 #define FCS_SIZE 2 +#define ACK_PKT_LENGTH 3 + +#define FRAME_TYPE_MASK 0x07 +#define FRAME_TYPE_ACK 0x02 static otRadioState sState = OT_RADIO_STATE_DISABLED; static otRadioFrame sTransmitFrame; +static otRadioFrame ack_frame; +static u8_t ack_psdu[ACK_PKT_LENGTH]; static struct net_pkt *tx_pkt; static struct net_buf *tx_payload; @@ -52,6 +58,38 @@ static struct ieee802154_radio_api *radio_api; static s8_t tx_power; static u16_t channel; +enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface, + struct net_pkt *pkt) +{ + ARG_UNUSED(iface); + + size_t ack_len = net_pkt_get_len(pkt); + + if (ack_len != ACK_PKT_LENGTH) { + return NET_CONTINUE; + } + + if ((*net_pkt_data(pkt) & FRAME_TYPE_MASK) != FRAME_TYPE_ACK) { + return NET_CONTINUE; + } + + if (ack_frame.mLength != 0) { + LOG_ERR("Overwriting unhandled ACK frame."); + } + + if (net_pkt_read(pkt, ack_psdu, ack_len) < 0) { + LOG_ERR("Failed to read ACK frame."); + return NET_CONTINUE; + } + + ack_frame.mPsdu = ack_psdu; + ack_frame.mLength = ack_len; + ack_frame.mInfo.mRxInfo.mLqi = net_pkt_ieee802154_lqi(pkt); + ack_frame.mInfo.mRxInfo.mRssi = net_pkt_ieee802154_rssi(pkt); + + return NET_OK; +} + static void dataInit(void) { tx_pkt = net_pkt_alloc(K_NO_WAIT); @@ -123,25 +161,26 @@ void platformRadioProcess(otInstance *aInstance) } else #endif { - if (sTransmitFrame.mPsdu[0] & 0x20) { - /* - * TODO: Get real ACK frame - * instead of making a spoofed one - */ - otRadioFrame ackFrame; - u8_t ackPsdu[] = {0x02, 0x00, 0x00, 0x00, 0x00}; + if (sTransmitFrame.mPsdu[0] & IEEE802154_AR_FLAG_SET) { + if (ack_frame.mLength == 0) { + LOG_DBG("No ACK received."); - ackPsdu[2] = sTransmitFrame.mPsdu[2]; - ackFrame.mPsdu = ackPsdu; - ackFrame.mInfo.mRxInfo.mLqi = 80; - ackFrame.mInfo.mRxInfo.mRssi = -40; - ackFrame.mLength = 5; + result = OT_ERROR_NO_ACK; + + otPlatRadioTxDone(aInstance, + &sTransmitFrame, + NULL, result); + + return; + } otPlatRadioTxDone(aInstance, &sTransmitFrame, - &ackFrame, result); + &ack_frame, result); + + ack_frame.mLength = 0; } else { otPlatRadioTxDone(aInstance, &sTransmitFrame, - NULL, result); + NULL, result); } } }