1 /*
2 * Copyright (c) 2016 Intel Corporation.
3 * Copyright (c) 2022 Florian Grandel.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 /**
9 * @file
10 * @brief Packet data common to all IEEE 802.15.4 L2 layers
11 *
12 * All references to the spec refer to IEEE 802.15.4-2020.
13 */
14
15 #ifndef ZEPHYR_INCLUDE_NET_IEEE802154_PKT_H_
16 #define ZEPHYR_INCLUDE_NET_IEEE802154_PKT_H_
17
18 #include <string.h>
19
20 #include <zephyr/types.h>
21
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25
26 /** @cond ignore */
27
28 #ifndef NET_PKT_HAS_CONTROL_BLOCK
29 #define NET_PKT_HAS_CONTROL_BLOCK
30 #endif
31
32 /* See section 6.16.2.8 - Received Signal Strength Indicator (RSSI) */
33 #define IEEE802154_MAC_RSSI_MIN 0U /* corresponds to -174 dBm */
34 #define IEEE802154_MAC_RSSI_MAX 254U /* corresponds to 80 dBm */
35 #define IEEE802154_MAC_RSSI_UNDEFINED 255U /* used by us to indicate an undefined RSSI value */
36
37 #define IEEE802154_MAC_RSSI_DBM_MIN -174 /* in dBm */
38 #define IEEE802154_MAC_RSSI_DBM_MAX 80 /* in dBm */
39 #define IEEE802154_MAC_RSSI_DBM_UNDEFINED INT16_MIN /* represents an undefined RSSI value */
40
41 struct net_pkt_cb_ieee802154 {
42 #if defined(CONFIG_NET_L2_OPENTHREAD)
43 uint32_t ack_fc; /* Frame counter set in the ACK */
44 uint8_t ack_keyid; /* Key index set in the ACK */
45 #endif
46 union {
47 /* RX packets */
48 struct {
49 uint8_t lqi; /* Link Quality Indicator */
50 /* See section 6.16.2.8 - Received Signal Strength Indicator (RSSI)
51 * "RSSI is represented as one octet of integer [...]; therefore,
52 * the minimum and maximum values are 0 (–174 dBm) and 254 (80 dBm),
53 * respectively. 255 is reserved." (MAC PIB attribute macRssi, see
54 * section 8.4.3.10, table 8-108)
55 *
56 * TX packets will show zero for this value. Drivers may set the
57 * field to the reserved value 255 (0xff) to indicate that an RSSI
58 * value is not available for this packet.
59 */
60 uint8_t rssi;
61 };
62 #if defined(CONFIG_IEEE802154_SELECTIVE_TXPOWER)
63 /* TX packets */
64 struct {
65 int8_t txpwr; /* TX power in dBm. */
66 };
67 #endif /* CONFIG_IEEE802154_SELECTIVE_TXPOWER */
68 };
69
70 /* Flags */
71 uint8_t arb : 1; /* ACK Request Bit is set in the frame */
72 uint8_t ack_fpb : 1; /* Frame Pending Bit was set in the ACK */
73 uint8_t frame_secured : 1; /* Frame is authenticated and
74 * encrypted according to its
75 * Auxiliary Security Header
76 */
77 uint8_t mac_hdr_rdy : 1; /* Indicates if frame's MAC header
78 * is ready to be transmitted or if
79 * it requires further modifications,
80 * e.g. Frame Counter injection.
81 */
82 #if defined(CONFIG_NET_L2_OPENTHREAD)
83 uint8_t fv2015: 1; /* Frame version is IEEE 802.15.4 (0b10),
84 * see section 7.2.2.10, table 7-3.
85 */
86 uint8_t ack_seb : 1; /* Security Enabled Bit was set in the ACK */
87 #endif
88 };
89
90 struct net_pkt;
91 static inline void *net_pkt_cb(struct net_pkt *pkt);
92
net_pkt_cb_ieee802154(struct net_pkt * pkt)93 static inline struct net_pkt_cb_ieee802154 *net_pkt_cb_ieee802154(struct net_pkt *pkt)
94 {
95 return (struct net_pkt_cb_ieee802154 *)net_pkt_cb(pkt);
96 };
97
net_pkt_ieee802154_lqi(struct net_pkt * pkt)98 static inline uint8_t net_pkt_ieee802154_lqi(struct net_pkt *pkt)
99 {
100 return net_pkt_cb_ieee802154(pkt)->lqi;
101 }
102
net_pkt_set_ieee802154_lqi(struct net_pkt * pkt,uint8_t lqi)103 static inline void net_pkt_set_ieee802154_lqi(struct net_pkt *pkt, uint8_t lqi)
104 {
105 net_pkt_cb_ieee802154(pkt)->lqi = lqi;
106 }
107
108 /**
109 * @brief Get the unsigned RSSI value as defined in section 6.16.2.8,
110 * Received Signal Strength Indicator (RSSI)
111 *
112 * @param pkt Pointer to the packet.
113 *
114 * @returns RSSI represented as unsigned byte value, ranging from
115 * 0 (–174 dBm) to 254 (80 dBm).
116 * The special value 255 (IEEE802154_MAC_RSSI_UNDEFINED)
117 * indicates that an RSSI value is not available for this
118 * packet. Will return zero for packets on the TX path.
119 */
net_pkt_ieee802154_rssi(struct net_pkt * pkt)120 static inline uint8_t net_pkt_ieee802154_rssi(struct net_pkt *pkt)
121 {
122 return net_pkt_cb_ieee802154(pkt)->rssi;
123 }
124
125 /**
126 * @brief Set the unsigned RSSI value as defined in section 6.16.2.8,
127 * Received Signal Strength Indicator (RSSI).
128 *
129 * @param pkt Pointer to the packet that was received with the given
130 * RSSI.
131 * @param rssi RSSI represented as unsigned byte value, ranging from
132 * 0 (–174 dBm) to 254 (80 dBm).
133 * The special value 255 (IEEE802154_MAC_RSSI_UNDEFINED)
134 * indicates that an RSSI value is not available for this
135 * packet.
136 */
net_pkt_set_ieee802154_rssi(struct net_pkt * pkt,uint8_t rssi)137 static inline void net_pkt_set_ieee802154_rssi(struct net_pkt *pkt, uint8_t rssi)
138 {
139 net_pkt_cb_ieee802154(pkt)->rssi = rssi;
140 }
141
142 /**
143 * @brief Get a signed RSSI value measured in dBm.
144 *
145 * @param pkt Pointer to the packet.
146 *
147 * @returns RSSI represented in dBm. Returns the special value
148 * IEEE802154_MAC_RSSI_DBM_UNDEFINED if an RSSI value
149 * is not available for this packet. Packets on the TX
150 * path will always show -174 dBm (which corresponds to
151 * an internal value of unsigned zero).
152 */
net_pkt_ieee802154_rssi_dbm(struct net_pkt * pkt)153 static inline int16_t net_pkt_ieee802154_rssi_dbm(struct net_pkt *pkt)
154 {
155 int16_t rssi = net_pkt_cb_ieee802154(pkt)->rssi;
156 return rssi == IEEE802154_MAC_RSSI_UNDEFINED ? IEEE802154_MAC_RSSI_DBM_UNDEFINED
157 : rssi + IEEE802154_MAC_RSSI_DBM_MIN;
158 }
159
160 /**
161 * @brief Set the RSSI value as a signed integer measured in dBm.
162 *
163 * @param pkt Pointer to the packet that was received with the given
164 * RSSI.
165 * @param rssi represented in dBm. Set to the special value
166 * IEEE802154_MAC_RSSI_DBM_UNDEFINED if an RSSI value is
167 * not available for this packet. Values above 80 dBm will
168 * be mapped to 80 dBm, values below -174 dBm will be mapped
169 * to -174 dBm.
170 */
net_pkt_set_ieee802154_rssi_dbm(struct net_pkt * pkt,int16_t rssi)171 static inline void net_pkt_set_ieee802154_rssi_dbm(struct net_pkt *pkt, int16_t rssi)
172 {
173 if (likely(rssi >= IEEE802154_MAC_RSSI_DBM_MIN && rssi <= IEEE802154_MAC_RSSI_DBM_MAX)) {
174 int16_t unsigned_rssi = rssi - IEEE802154_MAC_RSSI_DBM_MIN;
175
176 net_pkt_cb_ieee802154(pkt)->rssi = unsigned_rssi;
177 return;
178 } else if (rssi == IEEE802154_MAC_RSSI_DBM_UNDEFINED) {
179 net_pkt_cb_ieee802154(pkt)->rssi = IEEE802154_MAC_RSSI_UNDEFINED;
180 return;
181 } else if (rssi < IEEE802154_MAC_RSSI_DBM_MIN) {
182 net_pkt_cb_ieee802154(pkt)->rssi = IEEE802154_MAC_RSSI_MIN;
183 return;
184 } else if (rssi > IEEE802154_MAC_RSSI_DBM_MAX) {
185 net_pkt_cb_ieee802154(pkt)->rssi = IEEE802154_MAC_RSSI_MAX;
186 return;
187 }
188
189 CODE_UNREACHABLE;
190 }
191
192 #if defined(CONFIG_IEEE802154_SELECTIVE_TXPOWER)
net_pkt_ieee802154_txpwr(struct net_pkt * pkt)193 static inline int8_t net_pkt_ieee802154_txpwr(struct net_pkt *pkt)
194 {
195 return net_pkt_cb_ieee802154(pkt)->txpwr;
196 }
197
net_pkt_set_ieee802154_txpwr(struct net_pkt * pkt,int8_t txpwr)198 static inline void net_pkt_set_ieee802154_txpwr(struct net_pkt *pkt, int8_t txpwr)
199 {
200 net_pkt_cb_ieee802154(pkt)->txpwr = txpwr;
201 }
202 #endif /* CONFIG_IEEE802154_SELECTIVE_TXPOWER */
203
net_pkt_ieee802154_arb(struct net_pkt * pkt)204 static inline bool net_pkt_ieee802154_arb(struct net_pkt *pkt)
205 {
206 return net_pkt_cb_ieee802154(pkt)->arb;
207 }
208
net_pkt_set_ieee802154_arb(struct net_pkt * pkt,bool arb)209 static inline void net_pkt_set_ieee802154_arb(struct net_pkt *pkt, bool arb)
210 {
211 net_pkt_cb_ieee802154(pkt)->arb = arb;
212 }
213
net_pkt_ieee802154_ack_fpb(struct net_pkt * pkt)214 static inline bool net_pkt_ieee802154_ack_fpb(struct net_pkt *pkt)
215 {
216 return net_pkt_cb_ieee802154(pkt)->ack_fpb;
217 }
218
net_pkt_set_ieee802154_ack_fpb(struct net_pkt * pkt,bool fpb)219 static inline void net_pkt_set_ieee802154_ack_fpb(struct net_pkt *pkt, bool fpb)
220 {
221 net_pkt_cb_ieee802154(pkt)->ack_fpb = fpb;
222 }
223
net_pkt_ieee802154_frame_secured(struct net_pkt * pkt)224 static inline bool net_pkt_ieee802154_frame_secured(struct net_pkt *pkt)
225 {
226 return net_pkt_cb_ieee802154(pkt)->frame_secured;
227 }
228
net_pkt_set_ieee802154_frame_secured(struct net_pkt * pkt,bool secured)229 static inline void net_pkt_set_ieee802154_frame_secured(struct net_pkt *pkt, bool secured)
230 {
231 net_pkt_cb_ieee802154(pkt)->frame_secured = secured;
232 }
233
net_pkt_ieee802154_mac_hdr_rdy(struct net_pkt * pkt)234 static inline bool net_pkt_ieee802154_mac_hdr_rdy(struct net_pkt *pkt)
235 {
236 return net_pkt_cb_ieee802154(pkt)->mac_hdr_rdy;
237 }
238
net_pkt_set_ieee802154_mac_hdr_rdy(struct net_pkt * pkt,bool rdy)239 static inline void net_pkt_set_ieee802154_mac_hdr_rdy(struct net_pkt *pkt, bool rdy)
240 {
241 net_pkt_cb_ieee802154(pkt)->mac_hdr_rdy = rdy;
242 }
243
244 #if defined(CONFIG_NET_L2_OPENTHREAD)
net_pkt_ieee802154_ack_fc(struct net_pkt * pkt)245 static inline uint32_t net_pkt_ieee802154_ack_fc(struct net_pkt *pkt)
246 {
247 return net_pkt_cb_ieee802154(pkt)->ack_fc;
248 }
249
net_pkt_set_ieee802154_ack_fc(struct net_pkt * pkt,uint32_t fc)250 static inline void net_pkt_set_ieee802154_ack_fc(struct net_pkt *pkt, uint32_t fc)
251 {
252 net_pkt_cb_ieee802154(pkt)->ack_fc = fc;
253 }
254
net_pkt_ieee802154_ack_keyid(struct net_pkt * pkt)255 static inline uint8_t net_pkt_ieee802154_ack_keyid(struct net_pkt *pkt)
256 {
257 return net_pkt_cb_ieee802154(pkt)->ack_keyid;
258 }
259
net_pkt_set_ieee802154_ack_keyid(struct net_pkt * pkt,uint8_t keyid)260 static inline void net_pkt_set_ieee802154_ack_keyid(struct net_pkt *pkt, uint8_t keyid)
261 {
262 net_pkt_cb_ieee802154(pkt)->ack_keyid = keyid;
263 }
264
net_pkt_ieee802154_fv2015(struct net_pkt * pkt)265 static inline bool net_pkt_ieee802154_fv2015(struct net_pkt *pkt)
266 {
267 return net_pkt_cb_ieee802154(pkt)->fv2015;
268 }
269
net_pkt_set_ieee802154_fv2015(struct net_pkt * pkt,bool fv2015)270 static inline void net_pkt_set_ieee802154_fv2015(struct net_pkt *pkt, bool fv2015)
271 {
272 net_pkt_cb_ieee802154(pkt)->fv2015 = fv2015;
273 }
274
net_pkt_ieee802154_ack_seb(struct net_pkt * pkt)275 static inline bool net_pkt_ieee802154_ack_seb(struct net_pkt *pkt)
276 {
277 return net_pkt_cb_ieee802154(pkt)->ack_seb;
278 }
279
net_pkt_set_ieee802154_ack_seb(struct net_pkt * pkt,bool seb)280 static inline void net_pkt_set_ieee802154_ack_seb(struct net_pkt *pkt, bool seb)
281 {
282 net_pkt_cb_ieee802154(pkt)->ack_seb = seb;
283 }
284 #endif /* CONFIG_NET_L2_OPENTHREAD */
285
286 /** @endcond */
287
288 #ifdef __cplusplus
289 }
290 #endif
291
292 #endif /* ZEPHYR_INCLUDE_NET_IEEE802154_PKT_H_ */
293