gnrc_lorawan_internal.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2019 HAW Hamburg
3  *
4  * This file is subject to the terms and conditions of the GNU Lesser
5  * General Public License v2.1. See the file LICENSE in the top level
6  * directory for more details.
7  */
8 
18 #ifndef GNRC_LORAWAN_INTERNAL_H
19 #define GNRC_LORAWAN_INTERNAL_H
20 
21 #include <stdio.h>
22 #include <string.h>
23 #include "iolist.h"
24 #include "net/lora.h"
25 #include "net/lorawan/hdr.h"
26 #include "net/gnrc/pktbuf.h"
27 #include "net/netdev.h"
28 #include "net/loramac.h"
29 
30 #ifdef __cplusplus
31 extern "C" {
32 #endif
33 
34 #define MSG_TYPE_TIMEOUT (0x3457)
36 #define MTYPE_MASK 0xE0
37 #define MTYPE_JOIN_REQUEST 0x0
38 #define MTYPE_JOIN_ACCEPT 0x1
39 #define MTYPE_UNCNF_UPLINK 0x2
40 #define MTYPE_UNCNF_DOWNLINK 0x3
41 #define MTYPE_CNF_UPLINK 0x4
42 #define MTYPE_CNF_DOWNLINK 0x5
43 #define MTYPE_REJOIN_REQ 0x6
44 #define MTYPE_PROPIETARY 0x7
46 #define MAJOR_MASK 0x3
47 #define MAJOR_LRWAN_R1 0x0
49 #define MINOR_LRWAN 0x1
51 #define JOIN_REQUEST_SIZE (23U)
52 #define MIC_SIZE (4U)
53 #define CFLIST_SIZE (16U)
55 #define GNRC_LORAWAN_MAX_CHANNELS (16U)
57 #define LORAWAN_STATE_IDLE (0)
58 #define LORAWAN_STATE_RX_1 (1)
59 #define LORAWAN_STATE_RX_2 (2)
60 #define LORAWAN_STATE_TX (3)
61 #define LORAWAN_STATE_JOIN (4)
63 #define GNRC_LORAWAN_DIR_UPLINK (0U)
64 #define GNRC_LORAWAN_DIR_DOWNLINK (1U)
66 #define GNRC_LORAWAN_BACKOFF_WINDOW_TICK (3600000000LL)
68 #define GNRC_LORAWAN_BACKOFF_BUDGET_1 (36000000LL)
69 #define GNRC_LORAWAN_BACKOFF_BUDGET_2 (36000000LL)
70 #define GNRC_LORAWAN_BACKOFF_BUDGET_3 (8700000LL)
72 #define GNRC_LORAWAN_MLME_OPTS_LINK_CHECK_REQ (1 << 0)
73 #define GNRC_LORAWAN_MLME_OPTS_REKEY_IND_REQ (1 << 1)
75 #define GNRC_LORAWAN_CID_SIZE (1U)
76 #define GNRC_LORAWAN_CID_LINK_CHECK_ANS (0x02)
78 #define GNCR_LORAWAN_REKEY_IND_SIZE (1U)
79 #define GNCR_LORAWAN_CID_REKEY_CONF (0x0B)
81 #define GNRC_LORAWAN_FOPT_LINK_CHECK_ANS_SIZE (3U)
82 #define GNRC_LORAWAN_FOPT_REKEY_CONF_SIZE (2U)
84 #define GNRC_LORAWAN_JOIN_DELAY_U32_MASK (0x1FFFFF)
86 #define GNRC_LORAWAN_MAX_PAYLOAD_1 (59U)
87 #define GNRC_LORAWAN_MAX_PAYLOAD_2 (123U)
88 #define GNRC_LORAWAN_MAX_PAYLOAD_3 (250U)
90 #define GNRC_LORAWAN_CFLIST_ENTRY_SIZE (3U)
91 #define GNRC_LORAWAN_JOIN_ACCEPT_MAX_SIZE (33U)
93 #define GNRC_LORAWAN_BACKOFF_STATE_1 (0U)
94 #define GNRC_LORAWAN_BACKOFF_STATE_2 (1U)
95 #define GNRC_LORAWAN_BACKOFF_STATE_3 (2U)
97 #define GNRC_LORAWAN_BACKOFF_TIME_1 (1U)
98 #define GNRC_LORAWAN_BACKOFF_TIME_2 (10U)
99 #define GNRC_LORAWAN_BACKOFF_TIME_3 (24U)
101 #define GNRC_LORAWAN_APP_NONCE_SIZE (3U)
102 #define GNRC_LORAWAN_JOIN_NONCE_SIZE (3U)
103 #define GNRC_LORAWAN_NET_ID_SIZE (3U)
104 #define GNRC_LORAWAN_DEV_NONCE_SIZE (2U)
106 #define GNRC_LORAWAN_FOPTS_MAX_SIZE (15U)
107 #define GNRC_LORAWAN_FPORT_SIZE (1U)
109 #if defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || \
110  defined(CPU_FAM_STM32F7)
111 #define GNRC_LORAWAN_STATE_FLASHPAGE_NUM (0x7)
112 #else
113 #define GNRC_LORAWAN_STATE_FLASHPAGE_NUM (FLASHPAGE_NUMOF - 0x4)
114 #endif
115 #define GNRC_LORAWAN_INITIALIZED_MARKER (0x52f94f54U)
120 #define MHDR_MIC_BUF_SIZE (sizeof(lorawan_hdr_t) + \
121  GNRC_LORAWAN_FOPTS_MAX_SIZE + \
122  GNRC_LORAWAN_FPORT_SIZE + \
123  MIC_SIZE)
124 
128 typedef struct {
129  uint8_t *data;
130  uint8_t size;
131  uint8_t index;
133 
137 typedef struct {
138  void *deveui;
139  void *joineui;
140  void *nwkkey;
141 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
142  void *appkey;
143 #endif
144  uint8_t dr;
146 
150 typedef enum {
154  JOIN_REQ = 0xFF
156 
160 typedef struct {
161  uint8_t margin;
162  uint8_t num_gateways;
164 
168 typedef struct {
170  uint8_t port;
171  uint8_t dr;
172 } mcps_data_t;
173 
177 typedef struct {
178  uint32_t fcnt;
179  uint32_t fcnt_down;
180 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
181  uint32_t afcnt_down;
182  uint32_t last_fcnt_down;
183 #endif
185  int nb_trials;
188  uint8_t redundancy;
189  char mhdr_mic[MHDR_MIC_BUF_SIZE];
191 
195 typedef struct {
196  uint8_t activation;
198  uint32_t nid;
199  int32_t backoff_budget;
200  uint8_t dev_nonce[2];
201  uint8_t backoff_state;
203 
207 typedef struct {
208  uint8_t *appskey;
209  uint8_t *fnwksintkey;
210  uint8_t *snwksintkey;
211  uint8_t *nwksenckey;
212 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
213  uint8_t *jsintkey;
214  uint8_t *jsenckey;
215 #endif
217 
220 typedef struct {
223  void *mlme_buf;
224  void *mcps_buf;
225  uint8_t *joineui;
227 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
228  bool optneg;
229 #endif
230  uint32_t channel[GNRC_LORAWAN_MAX_CHANNELS];
231  uint16_t channel_mask;
232  uint32_t toa;
233  int busy;
236  int state;
237  uint8_t dl_settings;
238  uint8_t rx_delay;
239  uint8_t dr_range[GNRC_LORAWAN_MAX_CHANNELS];
240  uint8_t last_dr;
241  uint8_t last_chan_idx;
243 
247 typedef struct {
249  uint8_t dev_nonce[2];
251 
264  uint32_t fcnt, uint8_t dir,
265  const uint8_t *appskey);
266 
281 void gnrc_lorawan_encrypt_fopts(uint8_t *fopts, size_t len,
282  const le_uint32_t *dev_addr, uint32_t fcnt,
283  bool afcnt, uint8_t dir, const uint8_t *key);
284 
293 void gnrc_lorawan_decrypt_join_accept(const uint8_t *key, uint8_t *pkt,
294  int has_clist, uint8_t *out);
295 
307 void gnrc_lorawan_generate_session_keys(const uint8_t *join_nonce,
308  const uint8_t *dev_nonce,
309  const uint8_t *joineui,
310  gnrc_lorawan_t *mac);
311 
325  const uint8_t *nwkkey,
326  uint8_t *jsintkey,
327  uint8_t *jsenckey);
337 int gnrc_lorawan_set_dr(gnrc_lorawan_t *mac, uint8_t datarate);
338 
351  int confirmed_data, uint8_t port);
352 
361 
372 
380 void gnrc_lorawan_process_fopts(gnrc_lorawan_t *mac, uint8_t *fopts,
381  size_t size);
382 
391 void gnrc_lorawan_calculate_join_req_mic(const uint8_t *buf, size_t len,
392  uint8_t *key, le_uint32_t *out);
393 
402 void gnrc_lorawan_calculate_join_acpt_mic(const uint8_t *buf, size_t len,
403  gnrc_lorawan_t *mac, le_uint32_t *out);
404 
414 void gnrc_lorawan_calculate_mic_uplink(iolist_t *frame, uint16_t conf_fcnt,
415  gnrc_lorawan_t *mac, le_uint32_t *out);
416 
428  uint32_t fcnt, uint16_t conf_fcnt,
429  iolist_t *frame,
430  const uint8_t *snwksintkey,
431  le_uint32_t *out);
432 
445 size_t gnrc_lorawan_build_hdr(uint8_t mtype, le_uint32_t *dev_addr,
446  uint32_t fcnt, uint8_t ack, uint8_t fopts_length,
447  lorawan_buffer_t *buf);
448 
457  size_t size);
458 
467 
476 
485 void gnrc_lorawan_send_pkt(gnrc_lorawan_t *mac, iolist_t *psdu, uint8_t dr,
486  uint32_t chan);
487 
496  size_t size);
497 
507 
514 
521 
531 uint8_t gnrc_lorawan_region_mac_payload_max(uint8_t datarate);
532 
542 
552 
561 
569 
579 {
580  int _c = mac->busy;
581 
582  mac->busy = true;
583  return !_c;
584 }
585 
591 static inline void gnrc_lorawan_mac_release(gnrc_lorawan_t *mac)
592 {
593  mac->busy = false;
594 }
595 
602 void gnrc_lorawan_set_rx2_dr(gnrc_lorawan_t *mac, uint8_t rx2_dr);
603 
610 
616 void gnrc_lorawan_store_dev_nonce(uint8_t *dev_nonce);
617 
631 static inline bool gnrc_lorawan_optneg_is_set(const gnrc_lorawan_t *mac)
632 {
633  (void)mac;
634 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
635  return mac->optneg;
636 #else
637  return 1; /* NO-OP */
638 #endif
639 }
640 
653 static inline void gnrc_lorawan_set_optneg(gnrc_lorawan_t *mac, uint8_t optneg)
654 {
655  (void)mac;
656  (void)optneg;
657 
658 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
659  mac->optneg = optneg;
660 #endif
661 }
662 
672 static inline uint8_t *gnrc_lorawan_get_jsintkey(const gnrc_lorawan_t *mac)
673 {
674  (void)mac;
675 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
676  return mac->ctx.jsintkey;
677 #else
678  return NULL; /* NO-OP */
679 #endif
680 }
681 
691 static inline uint8_t *gnrc_lorawan_get_jsenckey(const gnrc_lorawan_t *mac)
692 {
693  (void)mac;
694 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
695  return mac->ctx.jsenckey;
696 #else
697  return NULL; /* NO-OP */
698 #endif
699 }
700 
710 static inline uint32_t gnrc_lorawan_get_afcnt_down(const gnrc_lorawan_t *mac)
711 {
712  (void)mac;
713 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
714  return mac->mcps.afcnt_down;
715 #else
716  return 0; /* NO-OP */
717 #endif
718 }
719 
729 static inline void gnrc_lorawan_set_afcnt_down(gnrc_lorawan_t *mac, uint32_t afcnt_down)
730 {
731  (void)mac;
732  (void)afcnt_down;
733 
734 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
735  mac->mcps.afcnt_down = afcnt_down;
736 #endif
737 }
738 
747 static inline uint32_t gnrc_lorawan_get_last_fcnt_down(const gnrc_lorawan_t *mac)
748 {
749  (void)mac;
750 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
751  return mac->mcps.last_fcnt_down;
752 #else
753  return 0; /* NO-OP */
754 #endif
755 }
756 
766 static inline void gnrc_lorawan_set_last_fcnt_down(gnrc_lorawan_t *mac, uint32_t last_fcnt_down)
767 {
768  (void)mac;
769  (void)last_fcnt_down;
770 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
771  mac->mcps.last_fcnt_down = last_fcnt_down;
772 #endif
773 }
774 
784 static inline uint8_t * gnrc_lorawan_mlme_join_get_appkey(const mlme_lorawan_join_t *mlme_join)
785 {
786  (void)mlme_join;
787 
788 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
789  return mlme_join->appkey;
790 #else
791  return NULL; /* NO-OP */
792 #endif
793 }
794 
804 static inline void gnrc_lorawan_mlme_join_set_appkey(mlme_lorawan_join_t *mlme_join, uint8_t *key)
805 {
806  (void)mlme_join;
807  (void)key;
808 
809 #if IS_USED(MODULE_GNRC_LORAWAN_1_1)
810  mlme_join->appkey = key;
811 #endif
812 }
813 
814 #ifdef __cplusplus
815 }
816 #endif
817 
818 #endif /* GNRC_LORAWAN_INTERNAL_H */
Definitions low-level network driver interface.
void gnrc_lorawan_mcps_process_downlink(gnrc_lorawan_t *mac, uint8_t *psdu, size_t size)
Process an MCPS downlink message (confirmable or non comfirmable)
static uint8_t * gnrc_lorawan_get_jsintkey(const gnrc_lorawan_t *mac)
Get the join session integrity key from the MAC descriptor.
static uint32_t gnrc_lorawan_get_afcnt_down(const gnrc_lorawan_t *mac)
Get the application downlink frame counter from the MAC descriptor.
void gnrc_lorawan_reset(gnrc_lorawan_t *mac)
Reset MAC parameters.
void gnrc_lorawan_perform_save(gnrc_lorawan_t *mac)
save internal MAC state in non-volatile storage and shutdown the MAC layer gracefully.
uint8_t gnrc_lorawan_build_options(gnrc_lorawan_t *mac, lorawan_buffer_t *buf)
Build fopts header.
void gnrc_lorawan_mlme_backoff_expire_cb(gnrc_lorawan_t *mac)
MLME Backoff expiration tick.
void gnrc_lorawan_process_fopts(gnrc_lorawan_t *mac, uint8_t *fopts, size_t size)
Process an fopts frame.
void gnrc_lorawan_mlme_no_rx(gnrc_lorawan_t *mac)
Inform the MAC layer that no packet was received during reception.
void gnrc_lorawan_calculate_mic_uplink(iolist_t *frame, uint16_t conf_fcnt, gnrc_lorawan_t *mac, le_uint32_t *out)
Calculate Message Integrity Code for an uplink MCPS message.
static void gnrc_lorawan_set_afcnt_down(gnrc_lorawan_t *mac, uint32_t afcnt_down)
Set the application downlink frame counter in the MAC descriptor.
size_t gnrc_lorawan_build_uplink(gnrc_lorawan_t *mac, iolist_t *payload, int confirmed_data, uint8_t port)
build uplink frame
static void gnrc_lorawan_set_last_fcnt_down(gnrc_lorawan_t *mac, uint32_t last_fcnt_down)
Set the last downlink frame counter in the MAC descriptor.
static void gnrc_lorawan_mlme_join_set_appkey(mlme_lorawan_join_t *mlme_join, uint8_t *key)
Se the app key in the MLME join request data.
void gnrc_lorawan_send_pkt(gnrc_lorawan_t *mac, iolist_t *psdu, uint8_t dr, uint32_t chan)
Send a LoRaWAN packet.
void gnrc_lorawan_calculate_join_req_mic(const uint8_t *buf, size_t len, uint8_t *key, le_uint32_t *out)
Calculate join-request Message Integrity Code.
void gnrc_lorawan_mlme_process_join(gnrc_lorawan_t *mac, uint8_t *data, size_t size)
Process join accept message.
void gnrc_lorawan_calculate_join_acpt_mic(const uint8_t *buf, size_t len, gnrc_lorawan_t *mac, le_uint32_t *out)
Calculate join-accept Message Integrity Code.
void gnrc_lorawan_decrypt_join_accept(const uint8_t *key, uint8_t *pkt, int has_clist, uint8_t *out)
Decrypts join accept message.
void gnrc_lorawan_generate_lifetime_session_keys(const uint8_t *deveui, const uint8_t *nwkkey, uint8_t *jsintkey, uint8_t *jsenckey)
Generate LoRaWAN 1.1x lifetime session keys.
size_t gnrc_lorawan_build_hdr(uint8_t mtype, le_uint32_t *dev_addr, uint32_t fcnt, uint8_t ack, uint8_t fopts_length, lorawan_buffer_t *buf)
Build a MCPS LoRaWAN header.
void gnrc_lorawan_store_dev_nonce(uint8_t *dev_nonce)
Store DevNonce in flash memory.
static void gnrc_lorawan_set_optneg(gnrc_lorawan_t *mac, uint8_t optneg)
Set OptNeg bit in the MAC descriptor.
static uint32_t gnrc_lorawan_get_last_fcnt_down(const gnrc_lorawan_t *mac)
Get the last downlink frame counter from the MAC descriptor.
void gnrc_lorawan_open_rx_window(gnrc_lorawan_t *mac)
Open a reception window.
uint8_t gnrc_lorawan_region_mac_payload_max(uint8_t datarate)
Get the maximum MAC payload (M value) for a given datarate.
void gnrc_lorawan_trigger_join(gnrc_lorawan_t *mac)
Trigger the transmission of the Join Request packet.
static uint8_t * gnrc_lorawan_get_jsenckey(const gnrc_lorawan_t *mac)
Get the join session encryption key from the MAC descriptor.
static int gnrc_lorawan_mac_acquire(gnrc_lorawan_t *mac)
Acquire the MAC layer.
void gnrc_lorawan_generate_session_keys(const uint8_t *join_nonce, const uint8_t *dev_nonce, const uint8_t *joineui, gnrc_lorawan_t *mac)
Generate LoRaWAN session keys.
void gnrc_lorawan_set_rx2_dr(gnrc_lorawan_t *mac, uint8_t rx2_dr)
Set the datarate of the second reception window.
mlme_join_req_type_t
MLME Join Request type.
@ REJOIN_REQ_2
Rejoin-request type 2.
@ JOIN_REQ
Join-request type.
@ REJOIN_REQ_0
Rejoin-request type 0.
@ REJOIN_REQ_1
Rejoin-request type 1.
void gnrc_lorawan_process_pkt(gnrc_lorawan_t *mac, iolist_t *pkt)
Process and dispatch a full LoRaWAN packet.
void gnrc_lorawan_event_retrans_timeout(gnrc_lorawan_t *mac)
Mac callback for retransmission timeout event.
static void gnrc_lorawan_mac_release(gnrc_lorawan_t *mac)
Release the MAC layer.
int gnrc_lorawan_set_dr(gnrc_lorawan_t *mac, uint8_t datarate)
Set datarate for the next transmission.
void gnrc_lorawan_encrypt_fopts(uint8_t *fopts, size_t len, const le_uint32_t *dev_addr, uint32_t fcnt, bool afcnt, uint8_t dir, const uint8_t *key)
Encrypts FOpts field.
static bool gnrc_lorawan_optneg_is_set(const gnrc_lorawan_t *mac)
Check whether OptNeg bit is set.
void gnrc_lorawan_event_no_rx(gnrc_lorawan_t *mac)
Mac callback for no RX.
void gnrc_lorawan_channels_init(gnrc_lorawan_t *mac)
Init regional channel settings.
#define MHDR_MIC_BUF_SIZE
Size of the internal MHDR-MIC buffer.
void gnrc_lorawan_encrypt_payload(iolist_t *iolist, const le_uint32_t *dev_addr, uint32_t fcnt, uint8_t dir, const uint8_t *appskey)
Encrypts LoRaWAN payload.
static uint8_t * gnrc_lorawan_mlme_join_get_appkey(const mlme_lorawan_join_t *mlme_join)
Get the app key from the MLME join request data.
void gnrc_lorawan_calculate_mic_downlink(const le_uint32_t *dev_addr, uint32_t fcnt, uint16_t conf_fcnt, iolist_t *frame, const uint8_t *snwksintkey, le_uint32_t *out)
Calculate Message Integrity Code for downlink MCPS message.
uint8_t gnrc_lorawan_pick_channel(gnrc_lorawan_t *mac)
pick a random available LoRaWAN channel
#define GNRC_LORAWAN_MAX_CHANNELS
Maximum number of channels.
iolist scatter / gather IO
LoRaMAC header definitions.
LoRaWAN header type and helper function definitions.
Interface definition for the global network buffer.
stdio wrapper to extend the C libs stdio
GNRC LoRaWAN key context struct.
uint8_t * snwksintkey
pointer to Serving Network session integrity key
uint8_t * nwksenckey
pointer to Network session encryption key
uint8_t * appskey
pointer to Application SKey buffer
uint8_t * fnwksintkey
pointer to Forwarding Network session integrity key
MCPS service access point descriptor.
int ack_requested
whether the network server requested an ACK
iolist_t * msdu
current MSDU
uint32_t fcnt
uplink framecounter
int waiting_for_ack
true if the MAC layer is waiting for an ACK
uint32_t fcnt_down
downlink frame counter.
int nb_trials
holds the remaining number of retransmissions
uint8_t redundancy
unconfirmed uplink redundancy
MLME service access point descriptor.
uint8_t backoff_state
state in the backoff state machine
uint8_t activation
Activation mechanism of the MAC layer.
int pending_mlme_opts
holds pending mlme opts
uint32_t nid
current Network ID
int32_t backoff_budget
remaining Time On Air budget
LoRaWAN state that needs to be preserved across reboots.
uint32_t initialized_marker
state initialized marker
GNRC LoRaWAN mac descriptor.
void * mlme_buf
pointer to MLME buffer
uint8_t rx_delay
Delay of first reception window.
uint8_t * joineui
pointer to Join EUI
int shutdown_req
MAC Shutdown request.
uint8_t last_dr
datarate of the last transmission
uint8_t last_chan_idx
index of channel used for last transmission
int state
state of MAC layer
void * mcps_buf
pointer to MCPS buffer
le_uint32_t dev_addr
Device address.
uint8_t dl_settings
downlink settings
uint32_t toa
Time on Air of the last transmission.
gnrc_lorawan_mlme_t mlme
MLME descriptor.
uint16_t channel_mask
channel mask
gnrc_lorawan_mcps_t mcps
MCPS descriptor.
gnrc_lorawan_key_ctx_t ctx
GNRC LoRaWAN key context struct.
iolist structure definition
Definition: iolist.h:39
buffer helper for parsing and constructing LoRaWAN packets.
uint8_t * data
pointer to the beginning of the buffer holding data
uint8_t size
size of the buffer
uint8_t index
current index in the buffer
uint8_t port
port of the request
uint8_t dr
datarate of the request
iolist_t * pkt
packet of the request
MLME Join Request data.
void * joineui
pointer to the Join EUI
uint8_t dr
datarate for the Join Request
void * deveui
pointer to the Device EUI
void * nwkkey
pointer to the Network Key.
LoRa modulation header definitions.
A 32 bit integer in little endian.
Definition: byteorder.h:48