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