From a47677da0630c3891596d1edbff7932c201915e8 Mon Sep 17 00:00:00 2001 From: Eduardo Montoya Date: Wed, 5 May 2021 10:26:54 +0200 Subject: [PATCH] net: openthread: add CSL transmitter API This commit implements the OpenThread APIs to pass MAC keys and frame counter to the radio layer in order to process the transmission security. This is needed for the correct functioning of a CSL transmitter. Signed-off-by: Eduardo Montoya --- drivers/ieee802154/Kconfig | 5 ++ include/net/ieee802154_radio.h | 21 +++++- include/net/net_pkt.h | 63 +++++++++++++++++- .../platform/openthread-core-zephyr-config.h | 31 +++++++++ subsys/net/lib/openthread/platform/radio.c | 64 ++++++++++++++++++- 5 files changed, 181 insertions(+), 3 deletions(-) diff --git a/drivers/ieee802154/Kconfig b/drivers/ieee802154/Kconfig index 2cdb1528bb7..611af2b01b9 100644 --- a/drivers/ieee802154/Kconfig +++ b/drivers/ieee802154/Kconfig @@ -130,6 +130,11 @@ endif # IEEE802154_UPIPE_RANDOM_MAC endif # IEEE802154_UPIPE +config IEEE802154_2015 + bool "Enable support for IEEE 802.15.4-2015 frames" + help + Enable radio driver support for IEEE 802.15.4-2015 frames, including security handling of frames and ACKs. + module = IEEE802154_DRIVER module-str = IEEE 802.15.4 driver module-help = Sets log level for IEEE 802.15.4 Device Drivers. diff --git a/include/net/ieee802154_radio.h b/include/net/ieee802154_radio.h index bd43324732a..c49ec1b518d 100644 --- a/include/net/ieee802154_radio.h +++ b/include/net/ieee802154_radio.h @@ -55,6 +55,7 @@ enum ieee802154_hw_caps { IEEE802154_HW_ENERGY_SCAN = BIT(7), /* Energy scan supported */ IEEE802154_HW_TXTIME = BIT(8), /* TX at specified time supported */ IEEE802154_HW_SLEEP_TO_TX = BIT(9), /* TX directly from sleep supported */ + IEEE802154_HW_TX_SEC = BIT(10), /* TX security hadling supported */ }; enum ieee802154_filter_type { @@ -150,7 +151,13 @@ enum ieee802154_config_type { /** Specifies new radio event handler. Specifying NULL as a handler * will disable radio events notification. */ - IEEE802154_CONFIG_EVENT_HANDLER + IEEE802154_CONFIG_EVENT_HANDLER, + + /** Updates MAC keys and key index for radios supporting transmit security. */ + IEEE802154_CONFIG_MAC_KEYS, + + /** Sets the current MAC frame counter value for radios supporting transmit security. */ + IEEE802154_CONFIG_FRAME_COUNTER, }; /** IEEE802.15.4 driver configuration data. */ @@ -178,6 +185,18 @@ struct ieee802154_config { /** ``IEEE802154_CONFIG_EVENT_HANDLER`` */ ieee802154_event_cb_t event_handler; + + /** ``IEEE802154_CONFIG_MAC_KEYS`` */ + struct { + uint8_t key_id_mode; + uint8_t key_id; + uint8_t *prev_key; + uint8_t *curr_key; + uint8_t *next_key; + } mac_keys; + + /** ``IEEE802154_CONFIG_FRAME_COUNTER`` */ + uint32_t frame_counter; }; }; diff --git a/include/net/net_pkt.h b/include/net/net_pkt.h index d25d9d1c62a..49c116c0f01 100644 --- a/include/net/net_pkt.h +++ b/include/net/net_pkt.h @@ -244,7 +244,14 @@ struct net_pkt { #if defined(CONFIG_IEEE802154) uint8_t ieee802154_rssi; /* Received Signal Strength Indication */ uint8_t ieee802154_lqi; /* Link Quality Indicator */ + uint8_t ieee802154_arb : 1; /* ACK Request Bit is set in the frame */ uint8_t ieee802154_ack_fpb : 1; /* Frame Pending Bit was set in the ACK */ +#if defined(CONFIG_IEEE802154_2015) + uint8_t ieee802154_fv2015 : 1; /* Frame version is IEEE 802.15.4-2015 */ + uint8_t ieee802154_ack_seb : 1; /* Security Enabled Bit was set in the ACK */ + uint32_t ieee802154_ack_fc; /* Frame counter set in the ACK */ + uint8_t ieee802154_ack_keyid; /* Key index set in the ACK */ +#endif #endif #if defined(CONFIG_NET_L2_CANBUS) union { @@ -991,6 +998,16 @@ static inline void net_pkt_set_ieee802154_lqi(struct net_pkt *pkt, pkt->ieee802154_lqi = lqi; } +static inline bool net_pkt_ieee802154_arb(struct net_pkt *pkt) +{ + return pkt->ieee802154_arb; +} + +static inline void net_pkt_set_ieee802154_arb(struct net_pkt *pkt, bool arb) +{ + pkt->ieee802154_arb = arb; +} + static inline bool net_pkt_ieee802154_ack_fpb(struct net_pkt *pkt) { return pkt->ieee802154_ack_fpb; @@ -1001,7 +1018,51 @@ static inline void net_pkt_set_ieee802154_ack_fpb(struct net_pkt *pkt, { pkt->ieee802154_ack_fpb = fpb; } -#endif + +#if defined(CONFIG_IEEE802154_2015) +static inline bool net_pkt_ieee802154_fv2015(struct net_pkt *pkt) +{ + return pkt->ieee802154_fv2015; +} + +static inline void net_pkt_set_ieee802154_fv2015(struct net_pkt *pkt, bool fv2015) +{ + pkt->ieee802154_fv2015 = fv2015; +} + +static inline bool net_pkt_ieee802154_ack_seb(struct net_pkt *pkt) +{ + return pkt->ieee802154_ack_seb; +} + +static inline void net_pkt_set_ieee802154_ack_seb(struct net_pkt *pkt, bool seb) +{ + pkt->ieee802154_ack_seb = seb; +} + +static inline uint32_t net_pkt_ieee802154_ack_fc(struct net_pkt *pkt) +{ + return pkt->ieee802154_ack_fc; +} + +static inline void net_pkt_set_ieee802154_ack_fc(struct net_pkt *pkt, + uint32_t fc) +{ + pkt->ieee802154_ack_fc = fc; +} + +static inline uint8_t net_pkt_ieee802154_ack_keyid(struct net_pkt *pkt) +{ + return pkt->ieee802154_ack_keyid; +} + +static inline void net_pkt_set_ieee802154_ack_keyid(struct net_pkt *pkt, + uint8_t keyid) +{ + pkt->ieee802154_ack_keyid = keyid; +} +#endif /* CONFIG_IEEE802154_2015 */ +#endif /* CONFIG_IEEE802154 || CONFIG_IEEE802154_RAW_MODE */ #if defined(CONFIG_NET_IPV4_AUTO) static inline bool net_pkt_ipv4_auto(struct net_pkt *pkt) diff --git a/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h b/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h index f47a5c2f5f5..c0e54879050 100644 --- a/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h +++ b/subsys/net/lib/openthread/platform/openthread-core-zephyr-config.h @@ -91,6 +91,37 @@ #define OPENTHREAD_CONFIG_MAC_SOFTWARE_CSMA_BACKOFF_ENABLE 1 #endif +/** + * @def OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE + * + * Define to 1 to enable software transmission target time logic. + * + */ +#ifndef OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE +#define OPENTHREAD_CONFIG_MAC_SOFTWARE_TX_TIMING_ENABLE \ + (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +#endif + +/** + * @def OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT + * + * Define as 1 to support IEEE 802.15.4-2015 Header IE (Information Element) generation and parsing, + * it must be set to support following features: + * 1. Time synchronization service feature (i.e., OPENTHREAD_CONFIG_TIME_SYNC_ENABLE is set). + * 2. Thread 1.2. + * + * @note If it's enabled, platform must support interrupt context and concurrent access AES. + * + */ +#ifndef OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT +#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE || \ + (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2) +#define OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 1 +#else +#define OPENTHREAD_CONFIG_MAC_HEADER_IE_SUPPORT 0 +#endif +#endif + /** * @def OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE * diff --git a/subsys/net/lib/openthread/platform/radio.c b/subsys/net/lib/openthread/platform/radio.c index adf965d8bcf..27c37a4153c 100644 --- a/subsys/net/lib/openthread/platform/radio.c +++ b/subsys/net/lib/openthread/platform/radio.c @@ -39,7 +39,11 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_OPENTHREAD_L2_LOG_LEVEL); #define SHORT_ADDRESS_SIZE 2 #define FCS_SIZE 2 +#if defined(CONFIG_IEEE802154_2015) +#define ACK_PKT_LENGTH 127 +#else #define ACK_PKT_LENGTH 3 +#endif #define FRAME_TYPE_MASK 0x07 #define FRAME_TYPE_ACK 0x02 @@ -131,7 +135,7 @@ enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface, size_t ack_len = net_pkt_get_len(pkt); - if (ack_len != ACK_PKT_LENGTH) { + if (ack_len > ACK_PKT_LENGTH) { return NET_CONTINUE; } @@ -328,6 +332,17 @@ static void openthread_handle_received_frame(otInstance *instance, time->second * USEC_PER_SEC + time->nanosecond / NSEC_PER_USEC; #endif +#if defined(CONFIG_IEEE802154_2015) + if (net_pkt_ieee802154_arb(pkt) && net_pkt_ieee802154_fv2015(pkt)) { + recv_frame.mInfo.mRxInfo.mAckedWithSecEnhAck = + net_pkt_ieee802154_ack_seb(pkt); + recv_frame.mInfo.mRxInfo.mAckFrameCounter = + net_pkt_ieee802154_ack_fc(pkt); + recv_frame.mInfo.mRxInfo.mAckKeyId = + net_pkt_ieee802154_ack_keyid(pkt); + } +#endif + if (IS_ENABLED(CONFIG_OPENTHREAD_DIAG) && otPlatDiagModeGet()) { otPlatDiagRadioReceiveDone(instance, &recv_frame, OT_ERROR_NONE); } else { @@ -663,6 +678,18 @@ otRadioCaps otPlatRadioGetCaps(otInstance *aInstance) caps |= OT_RADIO_CAPS_SLEEP_TO_TX; } +#if defined(CONFIG_IEEE802154_2015) + if (radio_caps & IEEE802154_HW_TX_SEC) { + caps |= OT_RADIO_CAPS_TRANSMIT_SEC; + } +#endif + +#if defined(CONFIG_NET_PKT_TXTIME) + if (radio_caps & IEEE802154_HW_TXTIME) { + caps |= OT_RADIO_CAPS_TRANSMIT_TIMING; + } +#endif + return caps; } @@ -888,9 +915,44 @@ otError otPlatRadioSetTransmitPower(otInstance *aInstance, int8_t aPower) return OT_ERROR_NONE; } +#if defined(CONFIG_NET_PKT_TXTIME) uint64_t otPlatRadioGetNow(otInstance *aInstance) { ARG_UNUSED(aInstance); return radio_api->get_time(radio_dev); } +#endif + +#if defined(CONFIG_IEEE802154_2015) +void otPlatRadioSetMacKey(otInstance *aInstance, uint8_t aKeyIdMode, + uint8_t aKeyId, const otMacKey *aPrevKey, + const otMacKey *aCurrKey, const otMacKey *aNextKey) +{ + ARG_UNUSED(aInstance); + __ASSERT_NO_MSG(aPrevKey != NULL && aCurrKey != NULL && + aNextKey != NULL); + + struct ieee802154_config config = { + .mac_keys.key_id_mode = aKeyIdMode, + .mac_keys.key_id = aKeyId, + .mac_keys.prev_key = (uint8_t *)aPrevKey->m8, + .mac_keys.curr_key = (uint8_t *)aCurrKey->m8, + .mac_keys.next_key = (uint8_t *)aNextKey->m8, + }; + + (void)radio_api->configure(radio_dev, IEEE802154_CONFIG_MAC_KEYS, + &config); +} + +void otPlatRadioSetMacFrameCounter(otInstance *aInstance, + uint32_t aMacFrameCounter) +{ + ARG_UNUSED(aInstance); + + struct ieee802154_config config = { .frame_counter = aMacFrameCounter }; + + (void)radio_api->configure(radio_dev, IEEE802154_CONFIG_FRAME_COUNTER, + &config); +} +#endif