Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gnrc/lorawan: add basic LoRaWAN 1.1 features #17884

Merged
merged 3 commits into from
Sep 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions examples/gnrc_lorawan/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ USEMODULE += auto_init_gnrc_netif

# Add support for GNRC LoRaWAN
USEMODULE += gnrc_lorawan
# Add support for GNRC LoRaWAN 1.1
# USEMODULE += gnrc_lorawan_1_1

# Use GNRC pktdump to print downlink messages
USEMODULE += gnrc_pktdump
Expand Down Expand Up @@ -55,7 +57,9 @@ ifndef CONFIG_KCONFIG_USEMODULE_LORAWAN
CFLAGS += -DCONFIG_GNRC_NETIF_LORAWAN_NETIF_HDR

CFLAGS += -DCONFIG_LORAMAC_APP_KEY_DEFAULT=\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"
CFLAGS += -DCONFIG_LORAMAC_NWK_KEY_DEFAULT=\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"
CFLAGS += -DCONFIG_LORAMAC_APP_EUI_DEFAULT=\"BBBBBBBBBBBBBBBB\"
CFLAGS += -DCONFIG_LORAMAC_JOIN_EUI_DEFAULT=\"BBBBBBBBBBBBBBBB\"
CFLAGS += -DCONFIG_LORAMAC_DEV_EUI_DEFAULT=\"CCCCCCCCCCCCCCCC\"

# For TTN, It's necessary to set the RX2 DR to 3 in EU_868 region
Expand Down
4 changes: 2 additions & 2 deletions examples/lorawan/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ static uint8_t appskey[LORAMAC_APPSKEY_LEN];

static void _alarm_cb(void *arg)
{
(void) arg;
(void)arg;
msg_t msg;
msg_send(&msg, sender_pid);
}
Expand All @@ -98,7 +98,7 @@ static void _send_message(void)
/* Try to send the message */
uint8_t ret = semtech_loramac_send(&loramac,
(uint8_t *)message, strlen(message));
if (ret != SEMTECH_LORAMAC_TX_DONE) {
if (ret != SEMTECH_LORAMAC_TX_DONE) {
printf("Cannot send message '%s', ret code: %d\n", message, ret);
return;
}
Expand Down
1 change: 1 addition & 0 deletions makefiles/pseudomodules.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ PSEUDOMODULES += gnrc_ipv6_nib_dns
PSEUDOMODULES += gnrc_ipv6_nib_rio
PSEUDOMODULES += gnrc_ipv6_nib_router
PSEUDOMODULES += gnrc_ipv6_nib_rtr_adv_pio_cb
PSEUDOMODULES += gnrc_lorawan_1_1
PSEUDOMODULES += gnrc_netdev_default
PSEUDOMODULES += gnrc_neterr
PSEUDOMODULES += gnrc_netapi_callbacks
Expand Down
6 changes: 3 additions & 3 deletions sys/include/net/gnrc/lorawan.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,10 +199,10 @@ void gnrc_lorawan_timeout_cb(gnrc_lorawan_t *mac);
* @brief Init GNRC LoRaWAN
*
* @param[in] mac pointer to the MAC descriptor
* @param[in] nwkskey buffer to store the NwkSKey. Should be at least 16 bytes long
* @param[in] appskey buffer to store the AppsKey. Should be at least 16 bytes long
* @param[in] joineui pointer to Join EUI
* @param[in] ctx pointer to LoRaWAN context
*/
void gnrc_lorawan_init(gnrc_lorawan_t *mac, uint8_t *nwkskey, uint8_t *appskey);
void gnrc_lorawan_init(gnrc_lorawan_t *mac, uint8_t *joineui, const gnrc_lorawan_key_ctx_t *ctx);

/**
* @brief Perform a MLME request
Expand Down
140 changes: 125 additions & 15 deletions sys/include/net/gnrc/netif/lorawan.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,23 +50,133 @@ extern "C" {
* @brief GNRC LoRaWAN interface descriptor
*/
typedef struct {
uint8_t nwkskey[LORAMAC_NWKSKEY_LEN]; /**< network SKey buffer */
uint8_t appskey[LORAMAC_APPSKEY_LEN]; /**< App SKey buffer */
uint8_t appkey[LORAMAC_APPKEY_LEN]; /**< App Key buffer */
uint8_t deveui[LORAMAC_DEVEUI_LEN]; /**< Device EUI buffer */
uint8_t appeui[LORAMAC_APPEUI_LEN]; /**< App EUI buffer */
gnrc_lorawan_t mac; /**< gnrc lorawan mac descriptor */
ztimer_t timer; /**< General purpose timer */
ztimer_t backoff_timer; /**< Backoff timer */
uint8_t flags; /**< flags for the LoRaWAN interface */
uint8_t demod_margin; /**< value of last demodulation margin */
uint8_t num_gateways; /**< number of gateways of last link check */
uint8_t datarate; /**< LoRaWAN datarate for the next transmission */
uint8_t port; /**< LoRaWAN port for the next transmission */
uint8_t ack_req; /**< Request ACK in the next transmission */
uint8_t otaa; /**< whether the next transmission is OTAA or not */
uint8_t appskey[LORAMAC_APPSKEY_LEN]; /**< App SKey buffer */
Ollrogge marked this conversation as resolved.
Show resolved Hide resolved
uint8_t fnwksintkey[LORAMAC_FNWKSINTKEY_LEN]; /**< Forwarding Network session integrity key buffer */
uint8_t nwkkey[LORAMAC_NWKKEY_LEN]; /**< Network key buffer. Mapped to AppKey if LoRaWAN 1.0x */
#if IS_USED(MODULE_GNRC_LORAWAN_1_1)
uint8_t appkey[LORAMAC_APPKEY_LEN]; /**< App Key buffer. The AppKey used in LoRaWAN 1.0x has been mapped to the nwkkey in LoRaWAN 1.1x */
uint8_t snwksintkey[LORAMAC_SNWKSINTKEY_LEN]; /**< Serving Network session integrity key buffer */
uint8_t nwksenckey[LORAMAC_NWKSENCKEY_LEN]; /**< Network session encryption key buffer */
uint8_t jsintkey[LORAMAC_JSINTKEY_LEN]; /**< Join session integrity key buffer */
uint8_t jsenckey[LORAMAC_JSENCKEY_LEN]; /**< Join session encryption key buffer */
#endif
uint8_t deveui[LORAMAC_DEVEUI_LEN]; /**< Device EUI buffer */
uint8_t joineui[LORAMAC_JOINEUI_LEN]; /**< Join EUI buffer */
gnrc_lorawan_t mac; /**< gnrc lorawan mac descriptor */
ztimer_t timer; /**< General purpose timer */
ztimer_t backoff_timer; /**< Backoff timer */
uint8_t flags; /**< flags for the LoRaWAN interface */
uint8_t demod_margin; /**< value of last demodulation margin */
uint8_t num_gateways; /**< number of gateways of last link check */
uint8_t datarate; /**< LoRaWAN datarate for the next transmission */
uint8_t port; /**< LoRaWAN port for the next transmission */
uint8_t ack_req; /**< Request ACK in the next transmission */
uint8_t otaa; /**< whether the next transmission is OTAA or not */
} gnrc_netif_lorawan_t;

/**
* @brief Set the app key in the interface descriptor
*
* This getter function exists to allow if (IS_USED(...)) constructs in the
* LoRaWAN code in order to increase code coverage.
*
* @param[in] lw_netif pointer to the interface descriptor
* @param[in] key pointer to the app key
* @param[in] len length of the app key
* @return 0 on success
* @return <0 on failure
*/
static inline int gnrc_netif_lorawan_set_appkey(gnrc_netif_lorawan_t *lw_netif, const uint8_t *key,
size_t len)
{
(void)lw_netif;
(void)key;
(void)len;

#if IS_USED(MODULE_GNRC_LORAWAN_1_1)
if (sizeof(lw_netif->appkey) < len) {
return -1;
}
memcpy(lw_netif->appkey, key, len);
#endif
return 0;
}

/**
* @brief Get the app key from the interface descriptor
*
* This getter function exists to allow if (IS_USED(...)) constructs in the
* LoRaWAN code in order to increase code coverage.
*
* @param[in] lw_netif pointer to the interface descriptor
* @return pointer to the app key
*/
static inline uint8_t * gnrc_netif_lorawan_get_appkey(gnrc_netif_lorawan_t *lw_netif)
{
(void)lw_netif;

#if IS_USED(MODULE_GNRC_LORAWAN_1_1)
return lw_netif->appkey;
#endif
return NULL; /* NO-OP */
}

/**
* @brief Set the serving network session integrity key in the interface descriptor
*
* This getter function exists to allow if (IS_USED(...)) constructs in the
* LoRaWAN code in order to increase code coverage.
*
* @param[in] lw_netif pointer to the interface descriptor
* @param[in] key pointer to the serving network session integrity key
* @param[in] len length of serving network session integrity key
* @return 0 on success
* @return <0 on failure
*/
static inline int gnrc_netif_lorawan_set_snwksintkey(gnrc_netif_lorawan_t *lw_netif,
const uint8_t *key, size_t len)
{
(void)lw_netif;
(void)key;
(void)len;

#if IS_USED(MODULE_GNRC_LORAWAN_1_1)
if (sizeof(lw_netif->snwksintkey) < len) {
return -1;
}
memcpy(lw_netif->snwksintkey, key, len);
#endif
return 0;
}

/**
* @brief Set the network session encryption key in the interface descriptor
*
* This getter function exists to allow if (IS_USED(...)) constructs in the
* LoRaWAN code in order to increase code coverage.
*
* @param[in] lw_netif pointer to the interface descriptor
* @param[in] key pointer to the network session encryption key
* @param[in] len length of network session encryption key
* @return 0 on success
* @return <0 on failure
*/
static inline int gnrc_netif_lorawan_set_nwksenckey(gnrc_netif_lorawan_t *lw_netif,
const uint8_t *key, size_t len)
{
(void)lw_netif;
(void)key;
(void)len;

#if IS_USED(MODULE_GNRC_LORAWAN_1_1)
if (sizeof(lw_netif->nwksenckey) < len) {
return -1;
}
memcpy(lw_netif->nwksenckey, key, len);
#endif
return 0;
}

#ifdef __cplusplus
}
#endif
Expand Down
90 changes: 90 additions & 0 deletions sys/include/net/loramac.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ extern "C" {
#define CONFIG_LORAMAC_DEV_EUI_DEFAULT "0000000000000000"
#endif

/**
* @brief Default join EUI
*
* 8 bytes key, required for join procedure
*/
#ifndef CONFIG_LORAMAC_JOIN_EUI_DEFAULT
#define CONFIG_LORAMAC_JOIN_EUI_DEFAULT "0000000000000000"
#endif

/**
* @brief Default application EUI
*
Expand All @@ -64,6 +73,15 @@ extern "C" {
#define CONFIG_LORAMAC_APP_KEY_DEFAULT "00000000000000000000000000000000"
#endif

/**
* @brief Default network key
*
* 16 bytes key, required for join procedure
*/
#ifndef CONFIG_LORAMAC_NWK_KEY_DEFAULT
#define CONFIG_LORAMAC_NWK_KEY_DEFAULT "00000000000000000000000000000000"
#endif

/**
* @brief Default application session key
*
Expand All @@ -82,6 +100,33 @@ extern "C" {
#define CONFIG_LORAMAC_NWK_SKEY_DEFAULT "00000000000000000000000000000000"
#endif

/**
* @brief Default network session integrity key
*
* 16 bytes key, required for join procedure
*/
#ifndef CONFIG_LORAMAC_FNWKSINT_KEY_DEFAULT
#define CONFIG_LORAMAC_FNWKSINT_KEY_DEFAULT "00000000000000000000000000000000"
#endif

/**
* @brief Default serving network session integrity key
*
* 16 bytes key, required for join procedure
*/
#ifndef CONFIG_LORAMAC_SNWKSINT_KEY_DEFAULT
#define CONFIG_LORAMAC_SNWKSINT_KEY_DEFAULT "00000000000000000000000000000000"
#endif

/**
* @brief Default network session encryption key
*
* 16 bytes key, required for join procedure
*/
#ifndef CONFIG_LORAMAC_NWKSENC_KEY_DEFAULT
#define CONFIG_LORAMAC_NWKSENC_KEY_DEFAULT "00000000000000000000000000000000"
#endif

/**
* @brief Default device address
*/
Expand Down Expand Up @@ -514,11 +559,21 @@ extern "C" {
*/
#define LORAMAC_APPEUI_LEN (8U)

/**
* @brief Join EUI length in bytes
*/
#define LORAMAC_JOINEUI_LEN (8U)

/**
* @brief Application key length in bytes
*/
#define LORAMAC_APPKEY_LEN (16U)

/**
* @brief Network key length in bytes
*/
#define LORAMAC_NWKKEY_LEN (16U)

/**
* @brief Application session key length in bytes
*/
Expand All @@ -529,6 +584,36 @@ extern "C" {
*/
#define LORAMAC_NWKSKEY_LEN (16U)

/**
* @brief Forwarding Network session integrity key length in bytes
*/
#define LORAMAC_FNWKSINTKEY_LEN (16U)

/**
* @brief Serving Network session integrity key length in bytes
*/
#define LORAMAC_SNWKSINTKEY_LEN (16U)

/**
* @brief Network session encryption key length in bytes
*/
#define LORAMAC_NWKSENCKEY_LEN (16U)

/**
* @brief Join session integrity key length in bytes
*/
#define LORAMAC_JSINTKEY_LEN (16U)

/**
* @brief Join session encryption key length in bytes
*/
#define LORAMAC_JSENCKEY_LEN (16U)

/**
* @brief Network session encryption key length in bytes
*/
#define LORAMAC_JSINTKEY_LEN (16U)

/**
* @brief Minimum port value
*/
Expand All @@ -544,6 +629,11 @@ extern "C" {
*/
#define LORAMAC_APP_NONCE_LEN (3U)

/**
* @brief Join nonce length in bytes
*/
#define LORAMAC_JOIN_NONCE_LEN (3U)

/**
* @brief Network ID length in bytes
*/
Expand Down
19 changes: 17 additions & 2 deletions sys/include/net/lorawan/hdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
#define LORAWAN_HDR_FOPTS_LEN_MASK (0x0F) /**< Frame options mask */
#define LORAWAN_HDR_FOPTS_LEN_POS (0U) /**< Frame options position */

#define LORAWAN_JA_HDR_OPTNEG_MASK (0x80) /**< OptNeg bit mask */
#define LORAWAN_JA_HDR_OPTNEG_POS (7U) /**< OptNeg bit position */

#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -92,7 +95,7 @@ typedef struct __attribute__((packed)) {
*/
typedef struct __attribute__((packed)) {
uint8_t mt_maj; /**< mtype and major version holder */
le_uint64_t app_eui; /**< application EUI */
le_uint64_t join_eui; /**< join EUI. Mapped to app EUI if LoRaWAN 1.0x */
le_uint64_t dev_eui; /**< device EUI */
le_uint16_t dev_nonce; /**< device nonce */
le_uint32_t mic; /**< message integrity code */
Expand All @@ -103,7 +106,7 @@ typedef struct __attribute__((packed)) {
*/
typedef struct __attribute__((packed)) {
uint8_t mt_maj; /**< mtype and major version holder */
uint8_t app_nonce[LORAMAC_APP_NONCE_LEN]; /**< application nonce */
uint8_t join_nonce[LORAMAC_JOIN_NONCE_LEN]; /**< join nonce. Mapped to application nonce if LoRaWAN 1.0x */
uint8_t net_id[LORAMAC_NETWORK_ID_LEN]; /**< network id */
uint8_t dev_addr[LORAMAC_DEVADDR_LEN]; /**< device address */
uint8_t dl_settings; /**< downlink settings */
Expand Down Expand Up @@ -278,6 +281,18 @@ static inline uint8_t lorawan_hdr_get_frame_opts_len(lorawan_hdr_t *hdr)
return (hdr->fctrl & LORAWAN_HDR_FOPTS_LEN_MASK) >> LORAWAN_HDR_FOPTS_LEN_POS;
}

/**
* @brief Get LoRaWAN join accept message OptNeg bit
*
* @param[in] ja_hdr Join accept message header
*
* @return value of the OptNeg bit
*/
static inline bool lorawan_ja_hdr_get_optneg(lorawan_join_accept_t *ja_hdr)
{
return (ja_hdr->dl_settings & LORAWAN_JA_HDR_OPTNEG_MASK) >> LORAWAN_JA_HDR_OPTNEG_POS;
}

#ifdef __cplusplus
}
#endif
Expand Down
Loading