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 	};
63 
64 	/* Flags */
65 	uint8_t ack_fpb : 1;	   /* Frame Pending Bit was set in the ACK */
66 	uint8_t frame_secured : 1; /* Frame is authenticated and
67 				    * encrypted according to its
68 				    * Auxiliary Security Header
69 				    */
70 	uint8_t mac_hdr_rdy : 1;   /* Indicates if frame's MAC header
71 				    * is ready to be transmitted or if
72 				    * it requires further modifications,
73 				    * e.g. Frame Counter injection.
74 				    */
75 #if defined(CONFIG_NET_L2_OPENTHREAD)
76 	uint8_t ack_seb : 1; /* Security Enabled Bit was set in the ACK */
77 #endif
78 };
79 
80 struct net_pkt;
81 static inline void *net_pkt_cb(struct net_pkt *pkt);
82 
net_pkt_cb_ieee802154(struct net_pkt * pkt)83 static inline struct net_pkt_cb_ieee802154 *net_pkt_cb_ieee802154(struct net_pkt *pkt)
84 {
85 	return (struct net_pkt_cb_ieee802154 *)net_pkt_cb(pkt);
86 };
87 
net_pkt_ieee802154_lqi(struct net_pkt * pkt)88 static inline uint8_t net_pkt_ieee802154_lqi(struct net_pkt *pkt)
89 {
90 	return net_pkt_cb_ieee802154(pkt)->lqi;
91 }
92 
net_pkt_set_ieee802154_lqi(struct net_pkt * pkt,uint8_t lqi)93 static inline void net_pkt_set_ieee802154_lqi(struct net_pkt *pkt, uint8_t lqi)
94 {
95 	net_pkt_cb_ieee802154(pkt)->lqi = lqi;
96 }
97 
98 /**
99  * @brief Get the unsigned RSSI value as defined in section 6.16.2.8,
100  *        Received Signal Strength Indicator (RSSI)
101  *
102  * @param pkt Pointer to the packet.
103  *
104  * @returns RSSI represented as unsigned byte value, ranging from
105  *          0 (–174 dBm) to 254 (80 dBm).
106  *          The special value 255 (IEEE802154_MAC_RSSI_UNDEFINED)
107  *          indicates that an RSSI value is not available for this
108  *          packet. Will return zero for packets on the TX path.
109  */
net_pkt_ieee802154_rssi(struct net_pkt * pkt)110 static inline uint8_t net_pkt_ieee802154_rssi(struct net_pkt *pkt)
111 {
112 	return net_pkt_cb_ieee802154(pkt)->rssi;
113 }
114 
115 /**
116  * @brief Set the unsigned RSSI value as defined in section 6.16.2.8,
117  *        Received Signal Strength Indicator (RSSI).
118  *
119  * @param pkt Pointer to the packet that was received with the given
120  *            RSSI.
121  * @param rssi RSSI represented as unsigned byte value, ranging from
122  *             0 (–174 dBm) to 254 (80 dBm).
123  *             The special value 255 (IEEE802154_MAC_RSSI_UNDEFINED)
124  *             indicates that an RSSI value is not available for this
125  *             packet.
126  */
net_pkt_set_ieee802154_rssi(struct net_pkt * pkt,uint8_t rssi)127 static inline void net_pkt_set_ieee802154_rssi(struct net_pkt *pkt, uint8_t rssi)
128 {
129 	net_pkt_cb_ieee802154(pkt)->rssi = rssi;
130 }
131 
132 /**
133  * @brief Get a signed RSSI value measured in dBm.
134  *
135  * @param pkt Pointer to the packet.
136  *
137  * @returns RSSI represented in dBm. Returns the special value
138  *          IEEE802154_MAC_RSSI_DBM_UNDEFINED if an RSSI value
139  *          is not available for this packet. Packets on the TX
140  *          path will always show -174 dBm (which corresponds to
141  *          an internal value of unsigned zero).
142  */
net_pkt_ieee802154_rssi_dbm(struct net_pkt * pkt)143 static inline int16_t net_pkt_ieee802154_rssi_dbm(struct net_pkt *pkt)
144 {
145 	int16_t rssi = net_pkt_cb_ieee802154(pkt)->rssi;
146 	return rssi == IEEE802154_MAC_RSSI_UNDEFINED ? IEEE802154_MAC_RSSI_DBM_UNDEFINED
147 						     : rssi + IEEE802154_MAC_RSSI_DBM_MIN;
148 }
149 
150 /**
151  * @brief Set the RSSI value as a signed integer measured in dBm.
152  *
153  * @param pkt Pointer to the packet that was received with the given
154  *            RSSI.
155  * @param rssi represented in dBm. Set to the special value
156  *             IEEE802154_MAC_RSSI_DBM_UNDEFINED if an RSSI value is
157  *             not available for this packet. Values above 80 dBm will
158  *             be mapped to 80 dBm, values below -174 dBm will be mapped
159  *             to -174 dBm.
160  */
net_pkt_set_ieee802154_rssi_dbm(struct net_pkt * pkt,int16_t rssi)161 static inline void net_pkt_set_ieee802154_rssi_dbm(struct net_pkt *pkt, int16_t rssi)
162 {
163 	if (likely(rssi >= IEEE802154_MAC_RSSI_DBM_MIN && rssi <= IEEE802154_MAC_RSSI_DBM_MAX)) {
164 		int16_t unsigned_rssi = rssi - IEEE802154_MAC_RSSI_DBM_MIN;
165 
166 		net_pkt_cb_ieee802154(pkt)->rssi = unsigned_rssi;
167 		return;
168 	} else if (rssi == IEEE802154_MAC_RSSI_DBM_UNDEFINED) {
169 		net_pkt_cb_ieee802154(pkt)->rssi = IEEE802154_MAC_RSSI_UNDEFINED;
170 		return;
171 	} else if (rssi < IEEE802154_MAC_RSSI_DBM_MIN) {
172 		net_pkt_cb_ieee802154(pkt)->rssi = IEEE802154_MAC_RSSI_MIN;
173 		return;
174 	} else if (rssi > IEEE802154_MAC_RSSI_DBM_MAX) {
175 		net_pkt_cb_ieee802154(pkt)->rssi = IEEE802154_MAC_RSSI_MAX;
176 		return;
177 	}
178 
179 	CODE_UNREACHABLE;
180 }
181 
net_pkt_ieee802154_ack_fpb(struct net_pkt * pkt)182 static inline bool net_pkt_ieee802154_ack_fpb(struct net_pkt *pkt)
183 {
184 	return net_pkt_cb_ieee802154(pkt)->ack_fpb;
185 }
186 
net_pkt_set_ieee802154_ack_fpb(struct net_pkt * pkt,bool fpb)187 static inline void net_pkt_set_ieee802154_ack_fpb(struct net_pkt *pkt, bool fpb)
188 {
189 	net_pkt_cb_ieee802154(pkt)->ack_fpb = fpb;
190 }
191 
net_pkt_ieee802154_frame_secured(struct net_pkt * pkt)192 static inline bool net_pkt_ieee802154_frame_secured(struct net_pkt *pkt)
193 {
194 	return net_pkt_cb_ieee802154(pkt)->frame_secured;
195 }
196 
net_pkt_set_ieee802154_frame_secured(struct net_pkt * pkt,bool secured)197 static inline void net_pkt_set_ieee802154_frame_secured(struct net_pkt *pkt, bool secured)
198 {
199 	net_pkt_cb_ieee802154(pkt)->frame_secured = secured;
200 }
201 
net_pkt_ieee802154_mac_hdr_rdy(struct net_pkt * pkt)202 static inline bool net_pkt_ieee802154_mac_hdr_rdy(struct net_pkt *pkt)
203 {
204 	return net_pkt_cb_ieee802154(pkt)->mac_hdr_rdy;
205 }
206 
net_pkt_set_ieee802154_mac_hdr_rdy(struct net_pkt * pkt,bool rdy)207 static inline void net_pkt_set_ieee802154_mac_hdr_rdy(struct net_pkt *pkt, bool rdy)
208 {
209 	net_pkt_cb_ieee802154(pkt)->mac_hdr_rdy = rdy;
210 }
211 
212 #if defined(CONFIG_NET_L2_OPENTHREAD)
net_pkt_ieee802154_ack_fc(struct net_pkt * pkt)213 static inline uint32_t net_pkt_ieee802154_ack_fc(struct net_pkt *pkt)
214 {
215 	return net_pkt_cb_ieee802154(pkt)->ack_fc;
216 }
217 
net_pkt_set_ieee802154_ack_fc(struct net_pkt * pkt,uint32_t fc)218 static inline void net_pkt_set_ieee802154_ack_fc(struct net_pkt *pkt, uint32_t fc)
219 {
220 	net_pkt_cb_ieee802154(pkt)->ack_fc = fc;
221 }
222 
net_pkt_ieee802154_ack_keyid(struct net_pkt * pkt)223 static inline uint8_t net_pkt_ieee802154_ack_keyid(struct net_pkt *pkt)
224 {
225 	return net_pkt_cb_ieee802154(pkt)->ack_keyid;
226 }
227 
net_pkt_set_ieee802154_ack_keyid(struct net_pkt * pkt,uint8_t keyid)228 static inline void net_pkt_set_ieee802154_ack_keyid(struct net_pkt *pkt, uint8_t keyid)
229 {
230 	net_pkt_cb_ieee802154(pkt)->ack_keyid = keyid;
231 }
232 
net_pkt_ieee802154_ack_seb(struct net_pkt * pkt)233 static inline bool net_pkt_ieee802154_ack_seb(struct net_pkt *pkt)
234 {
235 	return net_pkt_cb_ieee802154(pkt)->ack_seb;
236 }
237 
net_pkt_set_ieee802154_ack_seb(struct net_pkt * pkt,bool seb)238 static inline void net_pkt_set_ieee802154_ack_seb(struct net_pkt *pkt, bool seb)
239 {
240 	net_pkt_cb_ieee802154(pkt)->ack_seb = seb;
241 }
242 #endif /* CONFIG_NET_L2_OPENTHREAD */
243 
244 /** @endcond */
245 
246 #ifdef __cplusplus
247 }
248 #endif
249 
250 #endif /* ZEPHYR_INCLUDE_NET_IEEE802154_PKT_H_ */
251