/* * Copyright (c) 2016 Intel Corporation. * Copyright (c) 2022 Florian Grandel. * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief Packet data common to all IEEE 802.15.4 L2 layers * * All references to the spec refer to IEEE 802.15.4-2020. */ #ifndef ZEPHYR_INCLUDE_NET_IEEE802154_PKT_H_ #define ZEPHYR_INCLUDE_NET_IEEE802154_PKT_H_ #include #include #ifdef __cplusplus extern "C" { #endif /** @cond ignore */ #ifndef NET_PKT_HAS_CONTROL_BLOCK #define NET_PKT_HAS_CONTROL_BLOCK #endif /* See section 6.16.2.8 - Received Signal Strength Indicator (RSSI) */ #define IEEE802154_MAC_RSSI_MIN 0U /* corresponds to -174 dBm */ #define IEEE802154_MAC_RSSI_MAX 254U /* corresponds to 80 dBm */ #define IEEE802154_MAC_RSSI_UNDEFINED 255U /* used by us to indicate an undefined RSSI value */ #define IEEE802154_MAC_RSSI_DBM_MIN -174 /* in dBm */ #define IEEE802154_MAC_RSSI_DBM_MAX 80 /* in dBm */ #define IEEE802154_MAC_RSSI_DBM_UNDEFINED INT16_MIN /* represents an undefined RSSI value */ struct net_pkt_cb_ieee802154 { #if defined(CONFIG_NET_L2_OPENTHREAD) uint32_t ack_fc; /* Frame counter set in the ACK */ uint8_t ack_keyid; /* Key index set in the ACK */ #endif union { /* RX packets */ struct { uint8_t lqi; /* Link Quality Indicator */ /* See section 6.16.2.8 - Received Signal Strength Indicator (RSSI) * "RSSI is represented as one octet of integer [...]; therefore, * the minimum and maximum values are 0 (–174 dBm) and 254 (80 dBm), * respectively. 255 is reserved." (MAC PIB attribute macRssi, see * section 8.4.3.10, table 8-108) * * TX packets will show zero for this value. Drivers may set the * field to the reserved value 255 (0xff) to indicate that an RSSI * value is not available for this packet. */ uint8_t rssi; }; }; /* Flags */ uint8_t ack_fpb : 1; /* Frame Pending Bit was set in the ACK */ uint8_t frame_secured : 1; /* Frame is authenticated and * encrypted according to its * Auxiliary Security Header */ uint8_t mac_hdr_rdy : 1; /* Indicates if frame's MAC header * is ready to be transmitted or if * it requires further modifications, * e.g. Frame Counter injection. */ #if defined(CONFIG_NET_L2_OPENTHREAD) uint8_t ack_seb : 1; /* Security Enabled Bit was set in the ACK */ #endif }; struct net_pkt; static inline void *net_pkt_cb(struct net_pkt *pkt); static inline struct net_pkt_cb_ieee802154 *net_pkt_cb_ieee802154(struct net_pkt *pkt) { return (struct net_pkt_cb_ieee802154 *)net_pkt_cb(pkt); }; static inline uint8_t net_pkt_ieee802154_lqi(struct net_pkt *pkt) { return net_pkt_cb_ieee802154(pkt)->lqi; } static inline void net_pkt_set_ieee802154_lqi(struct net_pkt *pkt, uint8_t lqi) { net_pkt_cb_ieee802154(pkt)->lqi = lqi; } /** * @brief Get the unsigned RSSI value as defined in section 6.16.2.8, * Received Signal Strength Indicator (RSSI) * * @param pkt Pointer to the packet. * * @returns RSSI represented as unsigned byte value, ranging from * 0 (–174 dBm) to 254 (80 dBm). * The special value 255 (IEEE802154_MAC_RSSI_UNDEFINED) * indicates that an RSSI value is not available for this * packet. Will return zero for packets on the TX path. */ static inline uint8_t net_pkt_ieee802154_rssi(struct net_pkt *pkt) { return net_pkt_cb_ieee802154(pkt)->rssi; } /** * @brief Set the unsigned RSSI value as defined in section 6.16.2.8, * Received Signal Strength Indicator (RSSI). * * @param pkt Pointer to the packet that was received with the given * RSSI. * @param rssi RSSI represented as unsigned byte value, ranging from * 0 (–174 dBm) to 254 (80 dBm). * The special value 255 (IEEE802154_MAC_RSSI_UNDEFINED) * indicates that an RSSI value is not available for this * packet. */ static inline void net_pkt_set_ieee802154_rssi(struct net_pkt *pkt, uint8_t rssi) { net_pkt_cb_ieee802154(pkt)->rssi = rssi; } /** * @brief Get a signed RSSI value measured in dBm. * * @param pkt Pointer to the packet. * * @returns RSSI represented in dBm. Returns the special value * IEEE802154_MAC_RSSI_DBM_UNDEFINED if an RSSI value * is not available for this packet. Packets on the TX * path will always show -174 dBm (which corresponds to * an internal value of unsigned zero). */ static inline int16_t net_pkt_ieee802154_rssi_dbm(struct net_pkt *pkt) { int16_t rssi = net_pkt_cb_ieee802154(pkt)->rssi; return rssi == IEEE802154_MAC_RSSI_UNDEFINED ? IEEE802154_MAC_RSSI_DBM_UNDEFINED : rssi + IEEE802154_MAC_RSSI_DBM_MIN; } /** * @brief Set the RSSI value as a signed integer measured in dBm. * * @param pkt Pointer to the packet that was received with the given * RSSI. * @param rssi represented in dBm. Set to the special value * IEEE802154_MAC_RSSI_DBM_UNDEFINED if an RSSI value is * not available for this packet. Values above 80 dBm will * be mapped to 80 dBm, values below -174 dBm will be mapped * to -174 dBm. */ static inline void net_pkt_set_ieee802154_rssi_dbm(struct net_pkt *pkt, int16_t rssi) { if (likely(rssi >= IEEE802154_MAC_RSSI_DBM_MIN && rssi <= IEEE802154_MAC_RSSI_DBM_MAX)) { int16_t unsigned_rssi = rssi - IEEE802154_MAC_RSSI_DBM_MIN; net_pkt_cb_ieee802154(pkt)->rssi = unsigned_rssi; return; } else if (rssi == IEEE802154_MAC_RSSI_DBM_UNDEFINED) { net_pkt_cb_ieee802154(pkt)->rssi = IEEE802154_MAC_RSSI_UNDEFINED; return; } else if (rssi < IEEE802154_MAC_RSSI_DBM_MIN) { net_pkt_cb_ieee802154(pkt)->rssi = IEEE802154_MAC_RSSI_MIN; return; } else if (rssi > IEEE802154_MAC_RSSI_DBM_MAX) { net_pkt_cb_ieee802154(pkt)->rssi = IEEE802154_MAC_RSSI_MAX; return; } CODE_UNREACHABLE; } static inline bool net_pkt_ieee802154_ack_fpb(struct net_pkt *pkt) { return net_pkt_cb_ieee802154(pkt)->ack_fpb; } static inline void net_pkt_set_ieee802154_ack_fpb(struct net_pkt *pkt, bool fpb) { net_pkt_cb_ieee802154(pkt)->ack_fpb = fpb; } static inline bool net_pkt_ieee802154_frame_secured(struct net_pkt *pkt) { return net_pkt_cb_ieee802154(pkt)->frame_secured; } static inline void net_pkt_set_ieee802154_frame_secured(struct net_pkt *pkt, bool secured) { net_pkt_cb_ieee802154(pkt)->frame_secured = secured; } static inline bool net_pkt_ieee802154_mac_hdr_rdy(struct net_pkt *pkt) { return net_pkt_cb_ieee802154(pkt)->mac_hdr_rdy; } static inline void net_pkt_set_ieee802154_mac_hdr_rdy(struct net_pkt *pkt, bool rdy) { net_pkt_cb_ieee802154(pkt)->mac_hdr_rdy = rdy; } #if defined(CONFIG_NET_L2_OPENTHREAD) static inline uint32_t net_pkt_ieee802154_ack_fc(struct net_pkt *pkt) { return net_pkt_cb_ieee802154(pkt)->ack_fc; } static inline void net_pkt_set_ieee802154_ack_fc(struct net_pkt *pkt, uint32_t fc) { net_pkt_cb_ieee802154(pkt)->ack_fc = fc; } static inline uint8_t net_pkt_ieee802154_ack_keyid(struct net_pkt *pkt) { return net_pkt_cb_ieee802154(pkt)->ack_keyid; } static inline void net_pkt_set_ieee802154_ack_keyid(struct net_pkt *pkt, uint8_t keyid) { net_pkt_cb_ieee802154(pkt)->ack_keyid = keyid; } static inline bool net_pkt_ieee802154_ack_seb(struct net_pkt *pkt) { return net_pkt_cb_ieee802154(pkt)->ack_seb; } static inline void net_pkt_set_ieee802154_ack_seb(struct net_pkt *pkt, bool seb) { net_pkt_cb_ieee802154(pkt)->ack_seb = seb; } #endif /* CONFIG_NET_L2_OPENTHREAD */ /** @endcond */ #ifdef __cplusplus } #endif #endif /* ZEPHYR_INCLUDE_NET_IEEE802154_PKT_H_ */