drivers: ieee802154: improve ACK header IE config

Improves standard conformance of the IEEE802154_CONFIG_ENH_ACK_HEADER_IE
option and introduces certain "soft MAC" capabilities around header IEs:
 * Introduces types and helpers that allow driver maintainers to
   represent, parse, write and validate header IEs.
 * Introduces helper functions to access non-aligned fields in header
   IEs, namely element IDs.

Updates the only existing L2 and driver pair that uses
IEEE802154_CONFIG_ENH_ACK_HEADER_IE: OpenThread platform radio and nRF5
and improves header IE validation in the nRF5 driver.

This change should help further driver maintainers to support
OpenThread's CSL and vendor IE extensions. It is based on the rules
specified in RFC #61227.

It is also a precondition to generically support both, "soft MAC" and
"hard MAC", approaches to header IEs in the TSCH protocol, namely the
time synchronization IE.

Fixes: #62940

Signed-off-by: Florian Grandel <fgrandel@code-for-humans.de>
This commit is contained in:
Florian Grandel 2023-09-20 19:31:47 +02:00 committed by Carles Cufí
parent 62396443fc
commit 80da9ddfef
5 changed files with 532 additions and 65 deletions

View file

@ -877,27 +877,46 @@ static int nrf5_configure(const struct device *dev,
#endif /* CONFIG_NRF_802154_ENCRYPTION */
case IEEE802154_CONFIG_ENH_ACK_HEADER_IE: {
uint8_t short_addr_le[SHORT_ADDRESS_SIZE];
uint8_t ext_addr_le[EXTENDED_ADDRESS_SIZE];
uint8_t short_addr_le[SHORT_ADDRESS_SIZE];
uint8_t element_id;
if (config->ack_ie.short_addr == IEEE802154_BROADCAST_ADDRESS ||
config->ack_ie.ext_addr == NULL) {
return -ENOTSUP;
}
element_id = ieee802154_header_ie_get_element_id(config->ack_ie.header_ie);
if (element_id != IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE &&
(!IS_ENABLED(CONFIG_NET_L2_OPENTHREAD) ||
element_id != IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE)) {
return -ENOTSUP;
}
#if defined(CONFIG_NET_L2_OPENTHREAD)
uint8_t vendor_oui_le[IEEE802154_OPENTHREAD_VENDOR_OUI_LEN] =
IEEE802154_OPENTHREAD_THREAD_IE_VENDOR_OUI;
if (element_id == IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE &&
memcmp(config->ack_ie.header_ie->content.vendor_specific.vendor_oui,
vendor_oui_le, sizeof(vendor_oui_le))) {
return -ENOTSUP;
}
#endif
sys_put_le16(config->ack_ie.short_addr, short_addr_le);
/**
* The extended address field passed to this function starts
* with the most significant octet and ends with the least
* significant octet (i.e. big endian byte order).
* The IEEE 802.15.4 transmission order mandates this order to be
* reversed (i.e. little endian byte order) in a transmitted frame.
*
* The nrf_802154_ack_data_set expects extended address in transmission
* order.
*/
sys_memcpy_swap(ext_addr_le, config->ack_ie.ext_addr, EXTENDED_ADDRESS_SIZE);
if (config->ack_ie.data_len > 0) {
nrf_802154_ack_data_set(short_addr_le, false, config->ack_ie.data,
config->ack_ie.data_len, NRF_802154_ACK_DATA_IE);
nrf_802154_ack_data_set(ext_addr_le, true, config->ack_ie.data,
config->ack_ie.data_len, NRF_802154_ACK_DATA_IE);
if (config->ack_ie.header_ie && config->ack_ie.header_ie->length > 0) {
nrf_802154_ack_data_set(short_addr_le, false, config->ack_ie.header_ie,
config->ack_ie.header_ie->length +
IEEE802154_HEADER_IE_HEADER_LENGTH,
NRF_802154_ACK_DATA_IE);
nrf_802154_ack_data_set(ext_addr_le, true, config->ack_ie.header_ie,
config->ack_ie.header_ie->length +
IEEE802154_HEADER_IE_HEADER_LENGTH,
NRF_802154_ACK_DATA_IE);
} else {
nrf_802154_ack_data_clear(short_addr_le, false, NRF_802154_ACK_DATA_IE);
nrf_802154_ack_data_clear(ext_addr_le, true, NRF_802154_ACK_DATA_IE);

View file

@ -0,0 +1,356 @@
/*
* Copyright (c) 2023 Florian Grandel, Zephyr Project.
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file
* @brief IEEE 802.15.4 MAC information element (IE) related types and helpers
*
* This is not to be included by the application. This file contains only those
* parts of the types required for IE support that need to be visible to IEEE
* 802.15.4 drivers and L2 at the same time, i.e. everything related to header
* IE representation, parsing and generation.
*
* All specification references in this file refer to IEEE 802.15.4-2020.
*
* @note All structs and attributes in this file that directly represent parts
* of IEEE 802.15.4 frames are in LITTLE ENDIAN, see section 4, especially
* section 4.3.
*/
#ifndef ZEPHYR_INCLUDE_NET_IEEE802154_IE_H_
#define ZEPHYR_INCLUDE_NET_IEEE802154_IE_H_
#include <zephyr/net/buf.h>
#include <zephyr/sys/byteorder.h>
/**
* @addtogroup ieee802154_driver
* @{
*
* @name IEEE 802.15.4, section 7.4.2: MAC header information elements
* @{
*/
/**
* @brief Information Element Types.
*
* @details See sections 7.4.2.1 and 7.4.3.1.
*/
enum ieee802154_ie_type {
IEEE802154_IE_TYPE_HEADER = 0x0,
IEEE802154_IE_TYPE_PAYLOAD,
};
/**
* @brief Header Information Element IDs.
*
* @details See section 7.4.2.1, table 7-7, partial list, only IEs actually used
* are implemented.
*/
enum ieee802154_header_ie_element_id {
IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE = 0x00,
IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE = 0x1a,
IEEE802154_HEADER_IE_ELEMENT_ID_RIT_IE = 0x1b,
IEEE802154_HEADER_IE_ELEMENT_ID_RENDEZVOUS_TIME_IE = 0x1d,
IEEE802154_HEADER_IE_ELEMENT_ID_TIME_CORRECTION_IE = 0x1e,
IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_1 = 0x7e,
IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_2 = 0x7f,
/* partial list, add additional ids as needed */
};
/** @cond INTERNAL_HIDDEN */
#define IEEE802154_VENDOR_SPECIFIC_IE_OUI_LEN 3
/** INTERNAL_HIDDEN @endcond */
/** @brief Vendor Specific Header IE, see section 7.4.2.3. */
struct ieee802154_header_ie_vendor_specific {
uint8_t vendor_oui[IEEE802154_VENDOR_SPECIFIC_IE_OUI_LEN];
uint8_t *vendor_specific_info;
} __packed;
/** @brief Full CSL IE, see section 7.4.2.3. */
struct ieee802154_header_ie_csl_full {
uint16_t csl_phase;
uint16_t csl_period;
uint16_t csl_rendezvous_time;
} __packed;
/** @brief Reduced CSL IE, see section 7.4.2.3. */
struct ieee802154_header_ie_csl_reduced {
uint16_t csl_phase;
uint16_t csl_period;
} __packed;
/** @brief Generic CSL IE, see section 7.4.2.3. */
struct ieee802154_header_ie_csl {
union {
struct ieee802154_header_ie_csl_full full;
struct ieee802154_header_ie_csl_reduced reduced;
};
} __packed;
/** @brief RIT IE, see section 7.4.2.4. */
struct ieee802154_header_ie_rit {
uint8_t time_to_first_listen;
uint8_t number_of_repeat_listen;
uint16_t repeat_listen_interval;
} __packed;
/**
* @brief Full Rendezvous Time IE, see section 7.4.2.6
* (macCslInterval is nonzero).
*/
struct ieee802154_header_ie_rendezvous_time_full {
uint16_t rendezvous_time;
uint16_t wakeup_interval;
} __packed;
/**
* @brief Reduced Rendezvous Time IE, see section 7.4.2.6
* (macCslInterval is zero).
*/
struct ieee802154_header_ie_rendezvous_time_reduced {
uint16_t rendezvous_time;
} __packed;
/** @brief Rendezvous Time IE, see section 7.4.2.6. */
struct ieee802154_header_ie_rendezvous_time {
union {
struct ieee802154_header_ie_rendezvous_time_full full;
struct ieee802154_header_ie_rendezvous_time_reduced reduced;
};
} __packed;
/** @brief Time Correction IE, see section 7.4.2.7. */
struct ieee802154_header_ie_time_correction {
uint16_t time_sync_info;
} __packed;
/* @brief Generic Header IE, see section 7.4.2.1. */
struct ieee802154_header_ie {
#if CONFIG_LITTLE_ENDIAN
uint16_t length : 7;
uint16_t element_id_low : 1; /* see enum ieee802154_header_ie_element_id */
uint16_t element_id_high : 7;
uint16_t type : 1; /* always 0 */
#else
uint16_t element_id_low : 1; /* see enum ieee802154_header_ie_element_id */
uint16_t length : 7;
uint16_t type : 1; /* always 0 */
uint16_t element_id_high : 7;
#endif
union {
struct ieee802154_header_ie_vendor_specific vendor_specific;
struct ieee802154_header_ie_csl csl;
struct ieee802154_header_ie_rit rit;
struct ieee802154_header_ie_rendezvous_time rendezvous_time;
struct ieee802154_header_ie_time_correction time_correction;
/* add additional supported header IEs here */
} content;
} __packed;
/** @brief The header IE's header length (2 bytes). */
#define IEEE802154_HEADER_IE_HEADER_LENGTH sizeof(uint16_t)
/** @cond INTERNAL_HIDDEN */
#define IEEE802154_DEFINE_HEADER_IE(_element_id, _length, _content, _content_type) \
(struct ieee802154_header_ie) { \
.length = (_length), \
.element_id_high = (_element_id) >> 1U, .element_id_low = (_element_id) & 0x01, \
.type = IEEE802154_IE_TYPE_HEADER, \
.content._content_type = _content, \
}
#define IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC_CONTENT_LEN(_vendor_specific_info_len) \
(IEEE802154_VENDOR_SPECIFIC_IE_OUI_LEN + (_vendor_specific_info_len))
#define IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC_CONTENT(_vendor_oui, _vendor_specific_info) \
(struct ieee802154_header_ie_vendor_specific) { \
.vendor_oui = _vendor_oui, .vendor_specific_info = (_vendor_specific_info), \
}
#define IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED_CONTENT(_csl_phase, _csl_period) \
(struct ieee802154_header_ie_csl_reduced) { \
.csl_phase = sys_cpu_to_le16(_csl_phase), \
.csl_period = sys_cpu_to_le16(_csl_period), \
}
#define IEEE802154_DEFINE_HEADER_IE_CSL_FULL_CONTENT(_csl_phase, _csl_period, \
_csl_rendezvous_time) \
(struct ieee802154_header_ie_csl_full) { \
.csl_phase = sys_cpu_to_le16(_csl_phase), \
.csl_period = sys_cpu_to_le16(_csl_period), \
.csl_rendezvous_time = sys_cpu_to_le16(_csl_rendezvous_time), \
}
#define IEEE802154_HEADER_IE_TIME_CORRECTION_NACK 0x8000
#define IEEE802154_HEADER_IE_TIME_CORRECTION_MASK 0x0fff
#define IEEE802154_HEADER_IE_TIME_CORRECTION_SIGN_BIT_MASK 0x0800
#define IEEE802154_DEFINE_HEADER_IE_TIME_CORRECTION_CONTENT(_ack, _time_correction_us) \
(struct ieee802154_header_ie_time_correction) { \
.time_sync_info = sys_cpu_to_le16( \
(!(_ack) * IEEE802154_HEADER_IE_TIME_CORRECTION_NACK) | \
((_time_correction_us) & IEEE802154_HEADER_IE_TIME_CORRECTION_MASK)), \
}
/** INTERNAL_HIDDEN @endcond */
/**
* @brief Define a vendor specific header IE, see section 7.4.2.3.
*
* @details Example usage (all parameters in little endian):
*
* @code{.c}
* uint8_t vendor_specific_info[] = {...some vendor specific IE content...};
* struct ieee802154_header_ie header_ie = IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC(
* {0x9b, 0xb8, 0xea}, vendor_specific_info, sizeof(vendor_specific_info));
* @endcode
*
* @param _vendor_oui an initializer for a 3 byte vendor oui array in little
* endian
* @param _vendor_specific_info pointer to a variable length uint8_t array with
* the vendor specific IE content
* @param _vendor_specific_info_len the length of the vendor specific IE content
* (in bytes)
*/
#define IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC(_vendor_oui, _vendor_specific_info, \
_vendor_specific_info_len) \
IEEE802154_DEFINE_HEADER_IE(IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE, \
IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC_CONTENT_LEN( \
_vendor_specific_info_len), \
IEEE802154_DEFINE_HEADER_IE_VENDOR_SPECIFIC_CONTENT( \
_vendor_oui, _vendor_specific_info), \
vendor_specific)
/**
* @brief Define a reduced CSL IE, see section 7.4.2.3.
*
* @details Example usage (all parameters in CPU byte order):
*
* @code{.c}
* uint16_t csl_phase = ...;
* uint16_t csl_period = ...;
* struct ieee802154_header_ie header_ie =
* IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED(csl_phase, csl_period);
* @endcode
*
* @param _csl_phase CSL phase in CPU byte order
* @param _csl_period CSL period in CPU byte order
*/
#define IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED(_csl_phase, _csl_period) \
IEEE802154_DEFINE_HEADER_IE( \
IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE, \
sizeof(struct ieee802154_header_ie_csl_reduced), \
IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED_CONTENT(_csl_phase, _csl_period), \
csl.reduced)
/**
* @brief Define a full CSL IE, see section 7.4.2.3.
*
* @details Example usage (all parameters in CPU byte order):
*
* @code{.c}
* uint16_t csl_phase = ...;
* uint16_t csl_period = ...;
* uint16_t csl_rendezvous_time = ...;
* struct ieee802154_header_ie header_ie =
* IEEE802154_DEFINE_HEADER_IE_CSL_REDUCED(csl_phase, csl_period, csl_rendezvous_time);
* @endcode
*
* @param _csl_phase CSL phase in CPU byte order
* @param _csl_period CSL period in CPU byte order
* @param _csl_rendezvous_time CSL rendezvous time in CPU byte order
*/
#define IEEE802154_DEFINE_HEADER_IE_CSL_FULL(_csl_phase, _csl_period, _csl_rendezvous_time) \
IEEE802154_DEFINE_HEADER_IE(IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE, \
sizeof(struct ieee802154_header_ie_csl_full), \
IEEE802154_DEFINE_HEADER_IE_CSL_FULL_CONTENT( \
_csl_phase, _csl_period, _csl_rendezvous_time), \
csl.full)
/**
* @brief Define a Time Correction IE, see section 7.4.2.7.
*
* @details Example usage (parameter in CPU byte order):
*
* @code{.c}
* uint16_t time_sync_info = ...;
* struct ieee802154_header_ie header_ie =
* IEEE802154_DEFINE_HEADER_IE_TIME_CORRECTION(true, time_sync_info);
* @endcode
*
* @param _ack whether or not the enhanced ACK frame that receives this IE is an
* ACK (true) or NACK (false)
* @param _time_correction_us the positive or negative deviation from expected
* RX time in microseconds
*/
#define IEEE802154_DEFINE_HEADER_IE_TIME_CORRECTION(_ack, _time_correction_us) \
IEEE802154_DEFINE_HEADER_IE( \
IEEE802154_HEADER_IE_ELEMENT_ID_TIME_CORRECTION_IE, \
sizeof(struct ieee802154_header_ie_time_correction), \
IEEE802154_DEFINE_HEADER_IE_TIME_CORRECTION_CONTENT(_ack, _time_correction_us), \
time_correction)
/**
* @brief Retrieve the time correction value in microseconds from a Time Correction IE,
* see section 7.4.2.7.
*
* @param[in] ie pointer to the Time Correction IE structure
*
* @return The time correction value in microseconds.
*/
static inline int16_t
ieee802154_header_ie_get_time_correction_us(struct ieee802154_header_ie_time_correction *ie)
{
if (ie->time_sync_info & IEEE802154_HEADER_IE_TIME_CORRECTION_SIGN_BIT_MASK) {
/* Negative integer */
return (int16_t)ie->time_sync_info | ~IEEE802154_HEADER_IE_TIME_CORRECTION_MASK;
}
/* Positive integer */
return (int16_t)ie->time_sync_info & IEEE802154_HEADER_IE_TIME_CORRECTION_MASK;
}
/**
* @brief Set the element ID of a header IE.
*
* @param[in] ie pointer to a header IE
* @param[in] element_id IE element id in CPU byte order
*/
static inline void ieee802154_header_ie_set_element_id(struct ieee802154_header_ie *ie,
uint8_t element_id)
{
ie->element_id_high = element_id >> 1U;
ie->element_id_low = element_id & 0x01;
}
/**
* @brief Get the element ID of a header IE.
*
* @param[in] ie pointer to a header IE
*
* @return header IE element id in CPU byte order
*/
static inline uint8_t ieee802154_header_ie_get_element_id(struct ieee802154_header_ie *ie)
{
return (ie->element_id_high << 1U) | ie->element_id_low;
}
/** @brief The length in bytes of a "Time Correction" header IE. */
#define IEEE802154_TIME_CORRECTION_HEADER_IE_LEN \
(IEEE802154_HEADER_IE_HEADER_LENGTH + sizeof(struct ieee802154_header_ie_time_correction))
/** @brief The length in bytes of a "Header Termination 1" header IE. */
#define IEEE802154_HEADER_TERMINATION_1_HEADER_IE_LEN IEEE802154_HEADER_IE_HEADER_LENGTH
/**
* @}
*
* @}
*/
#endif /* ZEPHYR_INCLUDE_NET_IEEE802154_IE_H_ */

View file

@ -20,6 +20,7 @@
#include <zephyr/net/net_pkt.h>
#include <zephyr/net/net_time.h>
#include <zephyr/net/ieee802154.h>
#include <zephyr/net/ieee802154_ie.h>
#include <zephyr/sys/util.h>
#ifdef __cplusplus
@ -837,15 +838,78 @@ enum ieee802154_config_type {
IEEE802154_CONFIG_CSL_RX_TIME,
/**
* Indicates whether to inject IE into ENH ACK Frame for specific address
* or not. Disabling the ENH ACK with no address provided (NULL pointer)
* should disable it for all enabled addresses.
* Adds a header information element (IE) to be injected into enhanced
* ACK frames generated by the driver if the given destination address
* filter matches.
*
* @note Available in any interface operational state.
* @details Drivers implementing the @ref IEEE802154_HW_RX_TX_ACK
* capability generate ACK frames autonomously. Setting this
* configuration will ask the driver to inject the given preconfigured
* header IE when generating enhanced ACK frames where appropriate by
* the standard. IEs for all other frame types SHALL be provided by L2.
*
* @warning This configuration option does not conform to the
* requirements specified in #61227 as it is incompatible with standard
* primitives and may therefore be modified in the future.
* The driver shall return -ENOTSUP in the following cases:
* - It does not support the @ref IEEE802154_HW_RX_TX_ACK,
* - It does not support header IE injection,
* - It cannot inject the runtime fields on-the-fly required for the
* given IE element ID (see list below).
*
* Enhanced ACK header IEs (element IDs in parentheses) that either
* need to be rejected or explicitly supported and parsed by the driver
* because they require on-the-fly timing information injection are:
* - CSL IE (0x1a)
* - Rendezvous Time IE (0x1d)
* - Time Correction IE (0x1e)
*
* Drivers accepting this configuration option SHALL check the list of
* configured IEs for each outgoing enhanced ACK frame, select the ones
* appropriate for the received frame based on their element ID, inject
* any required runtime information on-the-fly and include the selected
* IEs into the enhanced ACK frame's MAC header.
*
* Drivers supporting enhanced ACK header IE injection SHALL
* autonomously inject header termination IEs as required by the
* standard.
*
* A destination short address and extended address MAY be given by L2
* to filter the devices to which the given IE is included. Setting the
* short address to the broadcast address and the extended address to
* NULL will inject the given IE into all ACK frames unless a more
* specific filter is also present for any given destination device
* (fallback configuration). L2 SHALL take care to either set both
* address fields to valid device addresses or none.
*
* This configuration type may be called several times with distinct
* element IDs and/or addresses. The driver SHALL either store all
* configured IE/address combinations or return -ENOMEM if no
* additional configuration can be stored.
*
* Configuring a header IE with a previously configured element ID and
* address filter SHALL override the previous configuration. This
* implies that repetition of the same header IE/address combination is
* NOT supported.
*
* Configuring an existing element ID/address filter combination with
* the header IE's length field set to zero SHALL remove that
* configuration. SHALL remove the fallback configuration if no address
* is given.
*
* Configuring a header IE for an address filter with the header IE
* pointer set to NULL SHALL remove all header IE's for that address
* filter. SHALL remove ALL header IE configuration (including but not
* limited to fallbacks) if no address is given.
*
* If any of the deleted configurations didn't previously exist, then
* the call SHALL be ignored. Whenever the length field is set to zero,
* the content fields MUST NOT be accessed by the driver.
*
* L2 SHALL minimize the space required to keep IE configuration inside
* the driver by consolidating address filters and by removing
* configuation that is no longer required.
*
* @note requires @ref IEEE802154_HW_RX_TX_ACK capability and is
* available in any interface operational state. Currently we only
* support header IEs but that may change in the future.
*/
IEEE802154_CONFIG_ENH_ACK_HEADER_IE,
@ -970,32 +1034,37 @@ struct ieee802154_config {
/** see @ref IEEE802154_CONFIG_ENH_ACK_HEADER_IE */
struct {
/**
* Header IEs to be added to the Enh-Ack frame.
* Pointer to the header IE, see section 7.4.2.1,
* figure 7-21
*
* in little endian
* Certain header IEs may be incomplete if they require
* timing information to be injected at runtime
* on-the-fly, see the list in @ref
* IEEE802154_CONFIG_ENH_ACK_HEADER_IE.
*/
const uint8_t *data;
/** length of the header IEs */
uint16_t data_len;
struct ieee802154_header_ie *header_ie;
/**
* Filters the devices that will receive this IE by
* short address. MAY be set to @ref
* IEEE802154_BROADCAST_ADDRESS to disable the filter.
*
* in CPU byte order
*/
uint16_t short_addr;
/**
* Filters the devices that will receive this IE by
* extended address. MAY be set to NULL to disable the
* filter.
* extended address. MAY be set to NULL to configure a
* fallback for all devices (implies that short_addr
* MUST also be set to @ref
* IEEE802154_BROADCAST_ADDRESS).
*
* in big endian
*/
const uint8_t *ext_addr;
/**
* Filters the devices that will receive this IE by
* short address. MAY be set to @ref
* IEEE802154_BROADCAST_ADDRESS to configure a fallback
* for all devices (implies that ext_addr MUST also set
* to NULL in this case).
*
* in CPU byte order
*/
uint16_t short_addr;
} ack_ie;
};
};

View file

@ -79,6 +79,17 @@ enum ieee802154_openthread_config_type {
IEEE802154_OPENTHREAD_CONFIG_MAX_EXTRA_CCA_ATTEMPTS = IEEE802154_CONFIG_PRIV_START
};
/**
* Thread vendor OUI for vendor specific header or nested information elements,
* see IEEE 802.15.4-2020, sections 7.4.2.2 and 7.4.4.30.
*
* in little endian
*/
#define IEEE802154_OPENTHREAD_THREAD_IE_VENDOR_OUI { 0x9b, 0xb8, 0xea }
/** length of IEEE 802.15.4-2020 vendor OUIs */
#define IEEE802154_OPENTHREAD_VENDOR_OUI_LEN 3
/** OpenThread specific configuration data of ieee802154 driver. */
struct ieee802154_openthread_config {
union {

View file

@ -1234,29 +1234,42 @@ void otPlatRadioSetMacFrameCounterIfLarger(otInstance *aInstance, uint32_t aMacF
otError otPlatRadioEnableCsl(otInstance *aInstance, uint32_t aCslPeriod, otShortAddress aShortAddr,
const otExtAddress *aExtAddr)
{
struct ieee802154_config config = {
.ack_ie.short_addr = aShortAddr,
.ack_ie.ext_addr = aExtAddr->m8,
};
int result;
uint8_t ie_header[OT_IE_HEADER_SIZE + OT_CSL_IE_SIZE];
struct ieee802154_config config;
ARG_UNUSED(aInstance);
ie_header[0] = CSL_IE_HEADER_BYTES_LO;
ie_header[1] = CSL_IE_HEADER_BYTES_HI;
/* Leave CSL Phase empty intentionally */
sys_put_le16(aCslPeriod, &ie_header[OT_IE_HEADER_SIZE + 2]);
config.ack_ie.data = ie_header;
config.ack_ie.short_addr = aShortAddr;
config.ack_ie.ext_addr = aExtAddr->m8;
if (aCslPeriod > 0) {
config.ack_ie.data_len = OT_IE_HEADER_SIZE + OT_CSL_IE_SIZE;
} else {
config.ack_ie.data_len = 0;
}
result = radio_api->configure(radio_dev, IEEE802154_CONFIG_ENH_ACK_HEADER_IE, &config);
/* Configure the CSL period first to give drivers a chance to validate
* the IE for consistency if they wish to.
*/
config.csl_period = aCslPeriod;
result += radio_api->configure(radio_dev, IEEE802154_CONFIG_CSL_PERIOD, &config);
result = radio_api->configure(radio_dev, IEEE802154_CONFIG_CSL_PERIOD, &config);
if (result) {
return OT_ERROR_FAILED;
}
/* Configure the CSL IE. */
if (aCslPeriod > 0) {
uint8_t header_ie_buf[OT_IE_HEADER_SIZE + OT_CSL_IE_SIZE] = {
CSL_IE_HEADER_BYTES_LO,
CSL_IE_HEADER_BYTES_HI,
};
struct ieee802154_header_ie *header_ie =
(struct ieee802154_header_ie *)header_ie_buf;
/* Write CSL period and leave CSL phase empty as it will be
* injected on-the-fly by the driver.
*/
header_ie->content.csl.reduced.csl_period = sys_cpu_to_le16(aCslPeriod);
config.ack_ie.header_ie = header_ie;
} else {
config.ack_ie.header_ie = NULL;
}
result = radio_api->configure(radio_dev, IEEE802154_CONFIG_ENH_ACK_HEADER_IE, &config);
return result ? OT_ERROR_FAILED : OT_ERROR_NONE;
}
@ -1384,20 +1397,19 @@ otError otPlatRadioConfigureEnhAckProbing(otInstance *aInstance, otLinkMetrics a
const otShortAddress aShortAddress,
const otExtAddress *aExtAddress)
{
int result;
uint8_t ie_header[OT_ACK_IE_MAX_SIZE];
uint16_t ie_header_len;
struct ieee802154_config config = {
.ack_ie.short_addr = aShortAddress,
.ack_ie.ext_addr = aExtAddress->m8,
};
uint8_t header_ie_buf[OT_ACK_IE_MAX_SIZE];
uint16_t header_ie_len;
int result;
ARG_UNUSED(aInstance);
ie_header_len = set_vendor_ie_header_lm(aLinkMetrics.mLqi, aLinkMetrics.mLinkMargin,
aLinkMetrics.mRssi, ie_header);
config.ack_ie.data = ie_header;
config.ack_ie.data_len = ie_header_len;
header_ie_len = set_vendor_ie_header_lm(aLinkMetrics.mLqi, aLinkMetrics.mLinkMargin,
aLinkMetrics.mRssi, header_ie_buf);
config.ack_ie.header_ie = (struct ieee802154_ie_header *)header_ie_buf;
result = radio_api->configure(radio_dev, IEEE802154_CONFIG_ENH_ACK_HEADER_IE, &config);
return result ? OT_ERROR_FAILED : OT_ERROR_NONE;