From patchwork Wed Nov 14 16:01:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jian-Hong Pan X-Patchwork-Id: 10682863 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B981D4B7E for ; Wed, 14 Nov 2018 16:03:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AAB7A2BB07 for ; Wed, 14 Nov 2018 16:03:01 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A8C2C2BB1C; Wed, 14 Nov 2018 16:03:01 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2C15C2BB0E for ; Wed, 14 Nov 2018 16:03:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387583AbeKOCGs (ORCPT ); Wed, 14 Nov 2018 21:06:48 -0500 Received: from mail-pf1-f195.google.com ([209.85.210.195]:43145 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387548AbeKOCGs (ORCPT ); Wed, 14 Nov 2018 21:06:48 -0500 Received: by mail-pf1-f195.google.com with SMTP id g7-v6so8121450pfo.10 for ; Wed, 14 Nov 2018 08:02:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=g.ncu.edu.tw; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=77gYbunc2jxqm/I5r4+ygvOWBZzB4agcgfgzeomRm40=; b=ap4jmn3tIyyl9WP4wGLge+eNcov8WwMHGcVF+4+HMmDq/ATWGb6YgZyyQW5a2NWB72 U1j/+zZjkBaVlvmc6i8HFGrtGYxnfr7JS61uczfnpnOf/g62Cy0etdIH0VUtm25CDbSr RGCuipsf1Jz9jZnHX7k2mioq9zEyZaK2ngG14= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=77gYbunc2jxqm/I5r4+ygvOWBZzB4agcgfgzeomRm40=; b=mZFKzQak2eG7t5ritm4Do88vI39lvggmewezLssodpxzRVSIvSqSHf8JFqURbtJCGA eKcE3TEMDV/AY1n8GC3fS0GFp/iycXi4CqRfem6ttUGJ3HrvZ8apkf4wvWxE1FFTcOVQ fRGGNLm4EzEEAstC+OZM19dB99AAd0lHbL59faS5eVBc6Xso49PiQjBLvPCoBo0prUB5 fJ4/4Gp6wwheKSLWo5mtP8j5gAqO+0xTr6Yg154O2OKveWTPJMLODDIY7R/RBdYzJRko xiLUU9fNMilxMexpkUua/27qPOdZ8cgS3jjxUhCdoWIhfprXskQbjiNiiUu5RkkxfIhg zpmA== X-Gm-Message-State: AGRZ1gJZKJshKrTIl736w52/+ZI//vmUDiIeEMd86q/GO8nY6mLC0O+v yxzuirCaLKIqusqq+8X0Ii7asA== X-Google-Smtp-Source: AJdET5fxGz6fNawGtbnyK939jLxmLnZ1wDN4lScMGryeZP4Hj7h0uF1b7uUnw2GNgab+tdPb6SvxVA== X-Received: by 2002:a62:5793:: with SMTP id i19-v6mr2618267pfj.158.1542211378543; Wed, 14 Nov 2018 08:02:58 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id s2-v6sm53449854pfk.133.2018.11.14.08.02.56 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 14 Nov 2018 08:02:58 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= , "David S . Miller" Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V3 1/7] net: lorawan: Add macro and definition for LoRaWAN Date: Thu, 15 Nov 2018 00:01:22 +0800 Message-Id: <20181114160126.4445-2-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181105.101610.1437737564548154497.davem@davemloft.net> References: <20181105.101610.1437737564548154497.davem@davemloft.net> MIME-Version: 1.0 Sender: linux-wpan-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds the macro and definition for the implementation of LoRaWAN protocol. Signed-off-by: Jian-Hong Pan --- V2: - Modify the commit message include/linux/socket.h | 5 ++++- include/uapi/linux/if_arp.h | 1 + include/uapi/linux/if_ether.h | 1 + net/core/dev.c | 4 ++-- security/selinux/hooks.c | 4 +++- security/selinux/include/classmap.h | 4 +++- 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/linux/socket.h b/include/linux/socket.h index aa1e288b1659..e5c8381fd1aa 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -209,8 +209,9 @@ struct ucred { */ #define AF_XDP 44 /* XDP sockets */ #define AF_LORA 45 /* LoRa sockets */ +#define AF_LORAWAN 46 /* LoRaWAN sockets */ -#define AF_MAX 46 /* For now.. */ +#define AF_MAX 47 /* For now.. */ /* Protocol families, same as address families. */ #define PF_UNSPEC AF_UNSPEC @@ -261,6 +262,7 @@ struct ucred { #define PF_SMC AF_SMC #define PF_XDP AF_XDP #define PF_LORA AF_LORA +#define PF_LORAWAN AF_LORAWAN #define PF_MAX AF_MAX /* Maximum queue length specifiable by listen. */ @@ -343,6 +345,7 @@ struct ucred { #define SOL_KCM 281 #define SOL_TLS 282 #define SOL_XDP 283 +#define SOL_LORAWAN 284 /* IPX options */ #define IPX_TYPE 1 diff --git a/include/uapi/linux/if_arp.h b/include/uapi/linux/if_arp.h index 1ed7cb3f2129..2376f7839355 100644 --- a/include/uapi/linux/if_arp.h +++ b/include/uapi/linux/if_arp.h @@ -99,6 +99,7 @@ #define ARPHRD_6LOWPAN 825 /* IPv6 over LoWPAN */ #define ARPHRD_VSOCKMON 826 /* Vsock monitor header */ #define ARPHRD_LORA 827 /* LoRa */ +#define ARPHRD_LORAWAN 828 /* LoRaWAN */ #define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */ #define ARPHRD_NONE 0xFFFE /* zero header length */ diff --git a/include/uapi/linux/if_ether.h b/include/uapi/linux/if_ether.h index 45644dcf5b39..b1ac70d4a377 100644 --- a/include/uapi/linux/if_ether.h +++ b/include/uapi/linux/if_ether.h @@ -148,6 +148,7 @@ * aggregation protocol */ #define ETH_P_LORA 0x00FA /* LoRa */ +#define ETH_P_LORAWAN 0x00FB /* LoRaWAN */ /* * This is an Ethernet frame header. diff --git a/net/core/dev.c b/net/core/dev.c index f68122f0ab02..b95ce79ec5a8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -297,7 +297,7 @@ static const unsigned short netdev_lock_type[] = { ARPHRD_IRDA, ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL, ARPHRD_FCFABRIC, ARPHRD_IEEE80211, ARPHRD_IEEE80211_PRISM, ARPHRD_IEEE80211_RADIOTAP, ARPHRD_PHONET, ARPHRD_PHONET_PIPE, - ARPHRD_IEEE802154, ARPHRD_VOID, ARPHRD_NONE}; + ARPHRD_IEEE802154, ARPHRD_LORAWAN, ARPHRD_VOID, ARPHRD_NONE}; static const char *const netdev_lock_name[] = { "_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25", @@ -314,7 +314,7 @@ static const char *const netdev_lock_name[] = { "_xmit_IRDA", "_xmit_FCPP", "_xmit_FCAL", "_xmit_FCPL", "_xmit_FCFABRIC", "_xmit_IEEE80211", "_xmit_IEEE80211_PRISM", "_xmit_IEEE80211_RADIOTAP", "_xmit_PHONET", "_xmit_PHONET_PIPE", - "_xmit_IEEE802154", "_xmit_VOID", "_xmit_NONE"}; + "_xmit_IEEE802154", "_xmit_LORAWAN", "_xmit_VOID", "_xmit_NONE"}; static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)]; static struct lock_class_key netdev_addr_lock_key[ARRAY_SIZE(netdev_lock_type)]; diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index aaf520a689d8..0da3a1d69cb8 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1477,7 +1477,9 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc return SECCLASS_XDP_SOCKET; case PF_LORA: return SECCLASS_LORA_SOCKET; -#if PF_MAX > 46 + case PF_LORAWAN: + return SECCLASS_LORAWAN_SOCKET; +#if PF_MAX > 47 #error New address family defined, please update this function. #endif } diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 060d4bf8385e..fa0151fe6f32 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -244,9 +244,11 @@ struct security_class_mapping secclass_map[] = { { COMMON_SOCK_PERMS, NULL } }, { "lora_socket", { COMMON_SOCK_PERMS, NULL } }, + { "lorawan_socket", + { COMMON_SOCK_PERMS, NULL } }, { NULL } }; -#if PF_MAX > 46 +#if PF_MAX > 47 #error New address family defined, please update secclass_map. #endif From patchwork Wed Nov 14 16:01:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jian-Hong Pan X-Patchwork-Id: 10682883 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8EA5913BF for ; Wed, 14 Nov 2018 16:03:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 794B62BB01 for ; Wed, 14 Nov 2018 16:03:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6BC612BB0C; Wed, 14 Nov 2018 16:03:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3A4DD2BB01 for ; Wed, 14 Nov 2018 16:03:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387432AbeKOCHM (ORCPT ); Wed, 14 Nov 2018 21:07:12 -0500 Received: from mail-pl1-f193.google.com ([209.85.214.193]:37813 "EHLO mail-pl1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387577AbeKOCHL (ORCPT ); Wed, 14 Nov 2018 21:07:11 -0500 Received: by mail-pl1-f193.google.com with SMTP id b5so1575294plr.4 for ; Wed, 14 Nov 2018 08:03:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=g.ncu.edu.tw; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FzpiwFPNwgA3QEht/V1MIw3EoW2EK8iygMEZRXVLWDM=; b=kwOdoITsV/jiQOs3AsPRss2B02PfVf/udsksrHPEYbaUpdEMHupxGfb7/SLuEl/Twz cXZW2GI1vI6q6pnLPwTCeZcOtJW8+bZqZ3UT9IPMN/Gel+wAKg2e+D51YeK9vNJ68rhC tgG6EF7iLZxs2cSrDao6obyE0hp9ohcd9GpWQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FzpiwFPNwgA3QEht/V1MIw3EoW2EK8iygMEZRXVLWDM=; b=ciNlneUsARwKgwPH8CGZ3DcrTtE7XQDFNZ8MHjBcNxHSOERkvCACqABTXCcRNM6WJh G4o91fonwyfF9qbOKTAqRa2h+YaE7kJLHP9QTxKgQQpyr+nEsyts300l3fFaNEBr5lVY Qd4A2PxFV2gcYMt8EgGUbwKvO4pY5tzAo5gIynC3jx8ag2MQNcRFmXyNc+9uqa8Xi0Hr oX27QP1tcI+mBMlRIO575S0PjIvBUzqI0KYfHHacsxqYsioulXPPfNRy9OPvz0nbONDY JPT5H7HCSH4PtPSszR37zM8oyhxWNRdKytVpSdDpew1BAtQ65p8aJbNk7qO2Kdh4o+dT NCmQ== X-Gm-Message-State: AGRZ1gLM01GkaM0rmZjo8WyD1/BJJsojRc70QEBzHHunIUKd4EL3KLPE poPUpNQvU0XGUQkppN926A+LzA== X-Google-Smtp-Source: AJdET5eB41gNC/SjqavyXPuDaf7ldiWf0GaTyajwMMVsXI98raJDW3elRTQGXVe2CHd4qbZzAoxpig== X-Received: by 2002:a17:902:aa84:: with SMTP id d4-v6mr2529225plr.25.1542211401636; Wed, 14 Nov 2018 08:03:21 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id s2-v6sm53449854pfk.133.2018.11.14.08.03.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 14 Nov 2018 08:03:21 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= , "David S . Miller" Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V3 2/7] net: lorawan: Add LoRaWAN socket module Date: Thu, 15 Nov 2018 00:01:23 +0800 Message-Id: <20181114160126.4445-3-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181105.101610.1437737564548154497.davem@davemloft.net> References: <20181105.101610.1437737564548154497.davem@davemloft.net> MIME-Version: 1.0 Sender: linux-wpan-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds a new address/protocol family for LoRaWAN network. It also implements the the functions and maps to Datagram socket for LoRaWAN unconfirmed data messages. Signed-off-by: Jian-Hong Pan --- V2: - Split the LoRaWAN class module patch in V1 into LoRaWAN socket and LoRaWAN Soft MAC modules - Add lorawan_netdev.h header file for network address related declaration - Use SPDX license identifiers V3: - Change the inline functions to a single line macro or just remove the decoration word - inline - Order local variables from longest to shortest line in the functions - Change mac_cb inline function to lrw_get_mac_cb macro include/linux/lora/lorawan_netdev.h | 49 ++ net/lorawan/Kconfig | 10 + net/lorawan/Makefile | 2 + net/lorawan/socket.c | 688 ++++++++++++++++++++++++++++ 4 files changed, 749 insertions(+) create mode 100644 include/linux/lora/lorawan_netdev.h create mode 100644 net/lorawan/Kconfig create mode 100644 net/lorawan/Makefile create mode 100644 net/lorawan/socket.c diff --git a/include/linux/lora/lorawan_netdev.h b/include/linux/lora/lorawan_netdev.h new file mode 100644 index 000000000000..f6689b7c4cb0 --- /dev/null +++ b/include/linux/lora/lorawan_netdev.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ +/*- + * LoRaWAN stack related definitions + * + * Copyright (c) 2018 Jian-Hong, Pan + * + */ + +#ifndef __LORAWAN_NET_DEVICE_H__ +#define __LORAWAN_NET_DEVICE_H__ + +enum { + LRW_ADDR_APPEUI, + LRW_ADDR_DEVEUI, + LRW_ADDR_DEVADDR, +}; + +struct lrw_addr_in { + int addr_type; + union { + u64 app_eui; + u64 dev_eui; + u32 devaddr; + }; +}; + +struct sockaddr_lorawan { + sa_family_t family; /* AF_LORAWAN */ + struct lrw_addr_in addr_in; +}; + +/** + * lrw_mac_cb - This structure holds the control buffer (cb) of sk_buff + * + * @devaddr: the LoRaWAN device address of this LoRaWAN hardware + */ +struct lrw_mac_cb { + u32 devaddr; +}; + +/** + * lrw_get_mac_cb - Get the LoRaWAN MAC control buffer of the sk_buff + * @skb: the exchanging sk_buff + * + * Return: the pointer of LoRaWAN MAC control buffer + */ +#define lrw_get_mac_cb(skb) ((struct lrw_mac_cb *)skb->cb) + +#endif diff --git a/net/lorawan/Kconfig b/net/lorawan/Kconfig new file mode 100644 index 000000000000..7f2f344085c4 --- /dev/null +++ b/net/lorawan/Kconfig @@ -0,0 +1,10 @@ +config LORAWAN + tristate "LoRaWAN Network support" + ---help--- + LoRaWAN defines low data rate, low power and long range wireless + wide area networks. It was designed to organize networks of automation + devices, such as sensors, switches and actuators. It can operate + multiple kilometers wide. + + Say Y here to compile LoRaWAN support into the kernel or say M to + compile it as a module. diff --git a/net/lorawan/Makefile b/net/lorawan/Makefile new file mode 100644 index 000000000000..8c923ca6541a --- /dev/null +++ b/net/lorawan/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_LORAWAN) += lorawan.o +lorawan-objs := socket.o diff --git a/net/lorawan/socket.c b/net/lorawan/socket.c new file mode 100644 index 000000000000..f0bd391c4137 --- /dev/null +++ b/net/lorawan/socket.c @@ -0,0 +1,688 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ +/*- + * LoRaWAN stack related definitions + * + * Copyright (c) 2018 Jian-Hong, Pan + * + */ + +#include +#include +#include +#include +#include +#include /* For TIOCOUTQ/INQ */ +#include +#include + +#define LORAWAN_MODULE_NAME "lorawan" + +#define LRW_DBG_STR(fmt) LORAWAN_MODULE_NAME": "fmt +#define lrw_info(fmt, ...) (pr_info(LRW_DBG_STR(fmt), ##__VA_ARGS__)) +#define lrw_dbg(fmt, ...) (pr_debug(LRW_DBG_STR(fmt), ##__VA_ARGS__)) + +/** + * dgram_sock - This structure holds the states of Datagram socket + * + * @sk: network layer representation of the socket + * sk must be the first member of dgram_sock + * @src_devaddr: the LoRaWAN device address for this connection + * @bound: this socket is bound or not + * @connected: this socket is connected to the destination or not + * @want_ack: this socket needs to ack for the connection or not + */ +struct dgram_sock { + struct sock sk; + u32 src_devaddr; + + u8 bound:1; + u8 connected:1; +}; + +static HLIST_HEAD(dgram_head); +static DEFINE_RWLOCK(dgram_lock); + +static struct dgram_sock * +dgram_sk(const struct sock *sk) +{ + return container_of(sk, struct dgram_sock, sk); +} + +static struct net_device * +lrw_get_dev_by_addr(struct net *net, u32 devaddr) +{ + __be32 be_addr = cpu_to_be32(devaddr); + struct net_device *ndev = NULL; + + rcu_read_lock(); + ndev = dev_getbyhwaddr_rcu(net, ARPHRD_LORAWAN, (char *)&be_addr); + if (ndev) + dev_hold(ndev); + rcu_read_unlock(); + + return ndev; +} + +static int +dgram_init(struct sock *sk) +{ + return 0; +} + +static void +dgram_close(struct sock *sk, long timeout) +{ + sk_common_release(sk); +} + +static int +dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len) +{ + struct sockaddr_lorawan *addr = (struct sockaddr_lorawan *)uaddr; + struct dgram_sock *ro = dgram_sk(sk); + struct net_device *ndev; + int ret; + + lock_sock(sk); + ro->bound = 0; + + ret = -EINVAL; + if (len < sizeof(*addr)) + goto dgram_bind_end; + + if (addr->family != AF_LORAWAN) + goto dgram_bind_end; + + if (addr->addr_in.addr_type != LRW_ADDR_DEVADDR) + goto dgram_bind_end; + + lrw_dbg("%s: bind address %X\n", __func__, addr->addr_in.devaddr); + ndev = lrw_get_dev_by_addr(sock_net(sk), addr->addr_in.devaddr); + if (!ndev) { + ret = -ENODEV; + goto dgram_bind_end; + } + netdev_dbg(ndev, "%s: get ndev\n", __func__); + + if (ndev->type != ARPHRD_LORAWAN) { + ret = -ENODEV; + goto dgram_bind_end; + } + + ro->src_devaddr = addr->addr_in.devaddr; + ro->bound = 1; + ret = 0; + dev_put(ndev); + lrw_dbg("%s: bound address %X\n", __func__, ro->src_devaddr); + +dgram_bind_end: + release_sock(sk); + return ret; +} + +static int +lrw_dev_hard_header(struct sk_buff *skb, struct net_device *ndev, + const u32 src_devaddr, size_t len) +{ + /* TODO: Prepare the LoRaWAN sending header here */ + return 0; +} + +static int +dgram_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) +{ + struct dgram_sock *ro = dgram_sk(sk); + struct net_device *ndev; + struct sk_buff *skb; + size_t hlen; + size_t tlen; + int ret; + + lrw_dbg("%s: going to send %zu bytes", __func__, size); + if (msg->msg_flags & MSG_OOB) { + lrw_dbg("msg->msg_flags = 0x%x\n", msg->msg_flags); + return -EOPNOTSUPP; + } + + lrw_dbg("%s: check msg_name\n", __func__); + if (!ro->connected && !msg->msg_name) + return -EDESTADDRREQ; + else if (ro->connected && msg->msg_name) + return -EISCONN; + + lrw_dbg("%s: check bound\n", __func__); + if (!ro->bound) + ndev = dev_getfirstbyhwtype(sock_net(sk), ARPHRD_LORAWAN); + else + ndev = lrw_get_dev_by_addr(sock_net(sk), ro->src_devaddr); + + if (!ndev) { + lrw_dbg("no dev\n"); + ret = -ENXIO; + goto dgram_sendmsg_end; + } + + if (size > ndev->mtu){ + netdev_dbg(ndev, "size = %zu, mtu = %u\n", size, ndev->mtu); + ret = -EMSGSIZE; + goto dgram_sendmsg_end; + } + + netdev_dbg(ndev, "%s: create skb\n", __func__); + hlen = LL_RESERVED_SPACE(ndev); + tlen = ndev->needed_tailroom; + skb = sock_alloc_send_skb(sk, hlen + tlen + size, + msg->msg_flags & MSG_DONTWAIT, + &ret); + + if (!skb) + goto dgram_sendmsg_no_skb; + + skb_reserve(skb, hlen); + skb_reset_network_header(skb); + + ret = lrw_dev_hard_header(skb, ndev, 0, size); + if (ret < 0) + goto dgram_sendmsg_no_skb; + + ret = memcpy_from_msg(skb_put(skb, size), msg, size); + if (ret > 0) + goto dgram_sendmsg_err_skb; + + skb->dev = ndev; + skb->protocol = htons(ETH_P_LORAWAN); + + netdev_dbg(ndev, "%s: push skb to xmit queue\n", __func__); + ret = dev_queue_xmit(skb); + if (ret > 0) + ret = net_xmit_errno(ret); + netdev_dbg(ndev, "%s: pushed skb to xmit queue with ret=%d\n", + __func__, ret); + dev_put(ndev); + + return ret ?: size; + +dgram_sendmsg_err_skb: + kfree_skb(skb); +dgram_sendmsg_no_skb: + dev_put(ndev); + +dgram_sendmsg_end: + return ret; +} + +static int +dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, + int noblock, int flags, int *addr_len) +{ + DECLARE_SOCKADDR(struct sockaddr_lorawan *, saddr, msg->msg_name); + struct sk_buff *skb; + size_t copied = 0; + int err; + + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) + goto dgram_recvmsg_end; + + copied = skb->len; + if (len < copied) { + msg->msg_flags |= MSG_TRUNC; + copied = len; + } + + err = skb_copy_datagram_msg(skb, 0, msg, copied); + if (err) + goto dgram_recvmsg_done; + + sock_recv_ts_and_drops(msg, sk, skb); + if(saddr) { + memset(saddr, 0, sizeof(*saddr)); + saddr->family = AF_LORAWAN; + saddr->addr_in.devaddr = lrw_get_mac_cb(skb)->devaddr; + *addr_len = sizeof(*saddr); + } + + if (flags & MSG_TRUNC) + copied = skb->len; + +dgram_recvmsg_done: + skb_free_datagram(sk, skb); + +dgram_recvmsg_end: + if (err) + return err; + return copied; +} + +static int +dgram_hash(struct sock *sk) +{ + lrw_dbg("%s\n", __func__); + write_lock_bh(&dgram_lock); + sk_add_node(sk, &dgram_head); + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); + write_unlock_bh(&dgram_lock); + + return 0; +} + +static void +dgram_unhash(struct sock *sk) +{ + lrw_dbg("%s\n", __func__); + write_lock_bh(&dgram_lock); + if (sk_del_node_init(sk)) + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); + write_unlock_bh(&dgram_lock); +} + +static int +dgram_connect(struct sock *sk, struct sockaddr *uaddr, int len) +{ + struct dgram_sock *ro = dgram_sk(sk); + + /* Nodes of LoRaWAN send data to a gateway only, then data is received + * and transferred to servers with the gateway's policy. + * So, the destination address is not used by nodes. + */ + lock_sock(sk); + ro->connected = 1; + release_sock(sk); + + return 0; +} + +static int +dgram_disconnect(struct sock *sk, int flags) +{ + struct dgram_sock *ro = dgram_sk(sk); + + lock_sock(sk); + ro->connected = 0; + release_sock(sk); + + return 0; +} + +static int +dgram_ioctl(struct sock *sk, int cmd, unsigned long arg) +{ + struct net_device *ndev = sk->sk_dst_cache->dev; + struct sk_buff *skb; + int amount; + int err; + + netdev_dbg(ndev, "%s: ioctl file (cmd=0x%X)\n", __func__, cmd); + switch (cmd) { + case SIOCOUTQ: + amount = sk_wmem_alloc_get(sk); + err = put_user(amount, (int __user *)arg); + break; + case SIOCINQ: + amount = 0; + spin_lock_bh(&sk->sk_receive_queue.lock); + skb = skb_peek(&sk->sk_receive_queue); + if (skb) { + /* We will only return the amount of this packet + * since that is all that will be read. + */ + amount = skb->len; + } + spin_unlock_bh(&sk->sk_receive_queue.lock); + err = put_user(amount, (int __user *)arg); + break; + default: + err = -ENOIOCTLCMD; + } + + return err; +} + +static int +dgram_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + int val, len; + + if (level != SOL_LORAWAN) + return -EOPNOTSUPP; + + if (get_user(len, optlen)) + return -EFAULT; + + len = min_t(unsigned int, len, sizeof(int)); + + switch (optname) { + default: + return -ENOPROTOOPT; + } + + if (put_user(len, optlen)) + return -EFAULT; + + if (copy_to_user(optval, &val, len)) + return -EFAULT; + + return 0; +} + +static int +dgram_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, unsigned int optlen) +{ + int val; + int err; + + err = 0; + + if (optlen < sizeof(int)) + return -EINVAL; + + if (get_user(val, (int __user *)optval)) + return -EFAULT; + + lock_sock(sk); + + switch (optname) { + default: + err = -ENOPROTOOPT; + break; + } + + release_sock(sk); + + return err; +} + +static struct proto lrw_dgram_prot = { + .name = "LoRaWAN", + .owner = THIS_MODULE, + .obj_size = sizeof(struct dgram_sock), + .init = dgram_init, + .close = dgram_close, + .bind = dgram_bind, + .sendmsg = dgram_sendmsg, + .recvmsg = dgram_recvmsg, + .hash = dgram_hash, + .unhash = dgram_unhash, + .connect = dgram_connect, + .disconnect = dgram_disconnect, + .ioctl = dgram_ioctl, + .getsockopt = dgram_getsockopt, + .setsockopt = dgram_setsockopt, +}; + +static int +lrw_sock_release(struct socket *sock) +{ + struct sock *sk = sock->sk; + + if (sk) { + sock->sk = NULL; + sk->sk_prot->close(sk, 0); + } + + return 0; +} + +static int +lrw_sock_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) +{ + struct sockaddr_lorawan *addr = (struct sockaddr_lorawan *)uaddr; + struct sock *sk = sock->sk; + + lrw_dbg("%s: bind address %X\n", __func__, addr->addr_in.devaddr); + if (sk->sk_prot->bind) + return sk->sk_prot->bind(sk, uaddr, addr_len); + + return sock_no_bind(sock, uaddr, addr_len); +} + +static int +lrw_sock_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags) +{ + struct sock *sk = sock->sk; + + if (addr_len < sizeof(uaddr->sa_family)) + return -EINVAL; + + return sk->sk_prot->connect(sk, uaddr, addr_len); +} + +static int +lrw_ndev_ioctl(struct sock *sk, struct ifreq __user *arg, unsigned int cmd) +{ + struct net_device *ndev; + struct ifreq ifr; + int ret; + + lrw_dbg("%s: cmd %ud\n", __func__, cmd); + ret = -ENOIOCTLCMD; + + if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) + return -EFAULT; + + ifr.ifr_name[IFNAMSIZ-1] = 0; + + dev_load(sock_net(sk), ifr.ifr_name); + ndev = dev_get_by_name(sock_net(sk), ifr.ifr_name); + + netdev_dbg(ndev, "%s: cmd %ud\n", __func__, cmd); + if (!ndev) + return -ENODEV; + + if (ndev->type == ARPHRD_LORAWAN && ndev->netdev_ops->ndo_do_ioctl) + ret = ndev->netdev_ops->ndo_do_ioctl(ndev, &ifr, cmd); + + if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq))) + ret = -EFAULT; + dev_put(ndev); + + return ret; +} + +static int +lrw_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) +{ + struct sock *sk = sock->sk; + + lrw_dbg("%s: cmd %ud\n", __func__, cmd); + switch (cmd) { + case SIOCGSTAMP: + return sock_get_timestamp(sk, (struct timeval __user *)arg); + case SIOCGSTAMPNS: + return sock_get_timestampns(sk, (struct timespec __user *)arg); + case SIOCOUTQ: + case SIOCINQ: + if (!sk->sk_prot->ioctl) + return -ENOIOCTLCMD; + return sk->sk_prot->ioctl(sk, cmd, arg); + default: + return lrw_ndev_ioctl(sk, (struct ifreq __user *)arg, cmd); + } +} + +static int +lrw_sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) +{ + struct sock *sk = sock->sk; + + lrw_dbg("%s: going to send %zu bytes\n", __func__, len); + return sk->sk_prot->sendmsg(sk, msg, len); +} + +static const struct proto_ops lrw_dgram_ops = { + .family = PF_LORAWAN, + .owner = THIS_MODULE, + .release = lrw_sock_release, + .bind = lrw_sock_bind, + .connect = lrw_sock_connect, + .socketpair = sock_no_socketpair, + .accept = sock_no_accept, + .getname = sock_no_getname, + .poll = datagram_poll, + .ioctl = lrw_sock_ioctl, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .setsockopt = sock_common_setsockopt, + .getsockopt = sock_common_getsockopt, + .sendmsg = lrw_sock_sendmsg, + .recvmsg = sock_common_recvmsg, + .mmap = sock_no_mmap, + .sendpage = sock_no_sendpage, +}; + +static int +lorawan_creat(struct net *net, struct socket *sock, int protocol, int kern) +{ + struct sock *sk; + int ret; + + if (!net_eq(net, &init_net)) + return -EAFNOSUPPORT; + + if (sock->type != SOCK_DGRAM) + return -EAFNOSUPPORT; + + /* Allocates enough memory for dgram_sock whose first member is sk */ + sk = sk_alloc(net, PF_LORAWAN, GFP_KERNEL, &lrw_dgram_prot, kern); + if (!sk) + return -ENOMEM; + + sock->ops = &lrw_dgram_ops; + sock_init_data(sock, sk); + sk->sk_family = PF_LORAWAN; + sock_set_flag(sk, SOCK_ZAPPED); + + if (sk->sk_prot->hash) { + ret = sk->sk_prot->hash(sk); + if (ret) { + sk_common_release(sk); + goto lorawan_creat_end; + } + } + + if (sk->sk_prot->init) { + ret = sk->sk_prot->init(sk); + if (ret) + sk_common_release(sk); + } + +lorawan_creat_end: + return ret; +} + +static const struct net_proto_family lorawan_family_ops = { + .owner = THIS_MODULE, + .family = PF_LORAWAN, + .create = lorawan_creat, +}; + +static int +lrw_dgram_deliver(struct net_device *ndev, struct sk_buff *skb) +{ + struct dgram_sock *ro; + struct sock *sk; + bool found; + int ret; + + ret = NET_RX_SUCCESS; + found = false; + + read_lock(&dgram_lock); + sk_for_each(sk, &dgram_head) { + ro = dgram_sk(sk); + if(cpu_to_le32(ro->src_devaddr) == *(__le32 *)ndev->dev_addr) { + found = true; + break; + } + } + read_unlock(&dgram_lock); + + if (!found) + goto lrw_dgram_deliver_err; + + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) + return NET_RX_DROP; + + if (sock_queue_rcv_skb(sk, skb) < 0) + goto lrw_dgram_deliver_err; + + return ret; + +lrw_dgram_deliver_err: + kfree_skb(skb); + ret = NET_RX_DROP; + return ret; +} + +static int +lorawan_rcv(struct sk_buff *skb, struct net_device *ndev, + struct packet_type *pt, struct net_device *orig_ndev) +{ + if (!netif_running(ndev)) + goto lorawan_rcv_drop; + + if (!net_eq(dev_net(ndev), &init_net)) + goto lorawan_rcv_drop; + + if (ndev->type != ARPHRD_LORAWAN) + goto lorawan_rcv_drop; + + if (skb->pkt_type != PACKET_OTHERHOST) + return lrw_dgram_deliver(ndev, skb); + +lorawan_rcv_drop: + kfree_skb(skb); + return NET_RX_DROP; +} + +static struct packet_type lorawan_packet_type = { + .type = htons(ETH_P_LORAWAN), + .func = lorawan_rcv, +}; + +static int __init +lrw_sock_init(void) +{ + int ret; + + lrw_info("module inserted\n"); + ret = proto_register(&lrw_dgram_prot, 1); + if(ret) + goto lrw_sock_init_end; + + /* Tell SOCKET that we are alive */ + ret = sock_register(&lorawan_family_ops); + if(ret) + goto lrw_sock_init_err; + + dev_add_pack(&lorawan_packet_type); + ret = 0; + goto lrw_sock_init_end; + +lrw_sock_init_err: + proto_unregister(&lrw_dgram_prot); + +lrw_sock_init_end: + return 0; +} + +static void __exit +lrw_sock_exit(void) +{ + dev_remove_pack(&lorawan_packet_type); + sock_unregister(PF_LORAWAN); + proto_unregister(&lrw_dgram_prot); + lrw_info("module removed\n"); +} + +module_init(lrw_sock_init); +module_exit(lrw_sock_exit); + +MODULE_AUTHOR("Jian-Hong Pan, "); +MODULE_DESCRIPTION("LoRaWAN socket kernel module"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS_NETPROTO(PF_LORAWAN); From patchwork Wed Nov 14 16:01:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jian-Hong Pan X-Patchwork-Id: 10682885 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D6AE013BF for ; Wed, 14 Nov 2018 16:03:31 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C360D26E90 for ; Wed, 14 Nov 2018 16:03:31 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B40562850D; Wed, 14 Nov 2018 16:03:31 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DDB672BB01 for ; Wed, 14 Nov 2018 16:03:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387679AbeKOCHO (ORCPT ); Wed, 14 Nov 2018 21:07:14 -0500 Received: from mail-pl1-f196.google.com ([209.85.214.196]:36537 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387577AbeKOCHN (ORCPT ); Wed, 14 Nov 2018 21:07:13 -0500 Received: by mail-pl1-f196.google.com with SMTP id y6-v6so424885plt.3 for ; Wed, 14 Nov 2018 08:03:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=g.ncu.edu.tw; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=277RPT5lwNcNZWinXpJrMFYhtW+VvY0zxQBKtONzPUQ=; b=V2OPRErysQ57p91Fvn/SO8ZwsgGss/3BTvGz7oo7MwTCrdiknZjUwET60ZLJoUTola Tbz0ZA/9+X+O/MlYIVPtddAufUyE4DD+qWVBKj1weEUTwbvMiGNQyoQf7Wk9OPwcD0h4 6x730O2xuNjbxT7Hc8TYhWEZbEdXwvtwLCK08= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=277RPT5lwNcNZWinXpJrMFYhtW+VvY0zxQBKtONzPUQ=; b=s5/d5EzrTc0DTQdEtmG/5dAQuK6MAhomeE4e3ZMZ9+0Y55XUzcL0yPhrzQQVfO/5zT FtGGHtCN4T9gTU4WigFT0ESMSiZgv8TAZS4zrhKjU6oF/KLqGvYXibNdSkW8P8KC8q9U hreCIJhSQ8H5dZgHXmFbahzlVUPHFd42gcz5gUXhfbLKMGoXOG+O9UXAjywwvtfhlkTG JRHS/iUkceajwVceJFbrv6dNNer3M4ZcFWGM2PLF8S94iHN4McMFkOBm0P8ZbHMxU7lC LG0IB8Ra717iKW0J0HK+WhIU2sAvKI5AuNwMlz4suY3g9a3ys85+li/sZLClGNShEU5M mLKA== X-Gm-Message-State: AGRZ1gInZeEKmJF/fzGIi6s+TMnUJinjiGWenIT8fCphqc6JeufGK2mM fXmqAKK0FvpPKF0zTjcm7vubOA== X-Google-Smtp-Source: AJdET5fehHAeWRy4GBqVrmAtIXvfv2JslMurWFpk5xiGG+2oXM6Zpy/t3Ls1sR4lFfFeGTRXU5NTmA== X-Received: by 2002:a17:902:ab83:: with SMTP id f3-v6mr2400993plr.122.1542211404094; Wed, 14 Nov 2018 08:03:24 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id s2-v6sm53449854pfk.133.2018.11.14.08.03.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 14 Nov 2018 08:03:23 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= , "David S . Miller" Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V3 3/7] net: lorawan: Add LoRaWAN API declaration for LoRa devices Date: Thu, 15 Nov 2018 00:01:24 +0800 Message-Id: <20181114160126.4445-4-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181105.101610.1437737564548154497.davem@davemloft.net> References: <20181105.101610.1437737564548154497.davem@davemloft.net> MIME-Version: 1.0 Sender: linux-wpan-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add public LoRaWAN API for compatible LoRa device drivers. Signed-off-by: Jian-Hong Pan --- V2: - Split the LoRaWAN class module patch in V1 into LoRaWAN socket and LoRaWAN Soft MAC modules - Merge the lrw_operations: set_bw, set_mod, set_sf into set_dr - Use SPDX license identifiers V3: - Remove the unused lrw_random_addr function include/linux/lora/lorawan.h | 131 +++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 include/linux/lora/lorawan.h diff --git a/include/linux/lora/lorawan.h b/include/linux/lora/lorawan.h new file mode 100644 index 000000000000..cdeb280b2261 --- /dev/null +++ b/include/linux/lora/lorawan.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ +/*- + * LoRaWAN compatible hardware's definitions + * + * Copyright (c) 2018 Jian-Hong, Pan + * + */ + +#ifndef __LORAWAN_H__ +#define __LORAWAN_H__ + +#include + +/* List the role of the LoRaWAN hardware */ +enum { + LRW_GATEWAY, + LRW_CLASS_A_NODE, + LRW_CLASS_B_NODE, + LRW_CLASS_C_NODE, +}; + +/* List the RF modes */ +enum { + LRW_LORA, + LRW_FSK, +}; + +/** + * lrw_dr - This structure holds the RF related configuration of the data rate. + * @bw: + * Bandwidth in Hz + * + * @sf: + * Spread factor of CSS modulation used by LoRa mode + * + * @mode: + * LoRa or FSK mode + */ +struct lrw_dr { + u32 bw; + u8 sf; + u8 mode; +}; + +#define LRW_DEVADDR_LEN (sizeof(__le32)) + +/* List the LoRa device's states of LoRaWAN hardware */ +enum { + LRW_STOP, + LRW_START, + LRW_STATE_IDLE, + LRW_STATE_TX, + LRW_STATE_RX, +}; + +/** + * lrw_hw - This structure holds the LoRa device of LoRaWAN hardware. + * @priv: + * points to the private data of the LoRa device + */ +struct lrw_hw { + void *priv; +}; + +/** + * lrw_operations - Lists the LoRaWAN device/interface's operations. + * These are callback functions for the LoRaWAN module. Compatible LoRa device + * driver should implement some of them according to the usage. The + * unimplemented callback functions must be assigned as NULL. + * + * @start: + * called when the interface is being up state + * + * @stop: + * called when the interface is being down state + * + * @xmit_async: + * called to xmit the data through the interface asynchronously + * + * @set_txpower: + * called to set xmitting RF power in mBm of the interface + * + * @set_frq: + * called to set carrier frequency in Hz of the interface + * + * @set_dr: + * called to set related RF configuration of the LoRaWAN data rate + * + * @start_rx_window: + * called to ask the LoRa device open a receiving window + * + * @set_state: + * called to set the LoRa device's working state + */ +struct lrw_operations { + int (*start)(struct lrw_hw *); + void (*stop)(struct lrw_hw *); + + int (*xmit_async)(struct lrw_hw *, struct sk_buff *); + int (*set_txpower)(struct lrw_hw *, s32); + int (*set_frq)(struct lrw_hw *, u32); + int (*set_dr)(struct lrw_hw *, struct lrw_dr *); + int (*start_rx_window)(struct lrw_hw *, u32); + int (*set_state)(struct lrw_hw *, u8); +}; + +struct lrw_hw *lrw_alloc_hw(size_t, struct lrw_operations *); +void lrw_free_hw(struct lrw_hw *); +int lrw_register_hw(struct lrw_hw *); +void lrw_unregister_hw(struct lrw_hw *); +void lrw_rx_irqsave(struct lrw_hw *, struct sk_buff *); +void lrw_xmit_complete(struct lrw_hw *, struct sk_buff *); + +void lrw_set_deveui(struct lrw_hw *, u64); +u64 lrw_get_deveui(struct lrw_hw *); +void lrw_set_appeui(struct lrw_hw *, u64); +u64 lrw_get_appeui(struct lrw_hw *); +void lrw_set_devaddr(struct lrw_hw *, u32); +u32 lrw_get_devaddr(struct lrw_hw *); + +enum { + LRW_APPKEY, + LRW_NWKSKEY, + LRW_APPSKEY, +}; + +#define LRW_KEY_LEN 16 + +int lrw_set_key(struct lrw_hw *, u8, u8 *, size_t); + +#endif From patchwork Wed Nov 14 16:01:25 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jian-Hong Pan X-Patchwork-Id: 10682895 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 00D2313BF for ; Wed, 14 Nov 2018 16:04:01 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E794E2AE21 for ; Wed, 14 Nov 2018 16:04:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DBF872BB31; Wed, 14 Nov 2018 16:04:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A28952B17A for ; Wed, 14 Nov 2018 16:03:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387732AbeKOCHU (ORCPT ); Wed, 14 Nov 2018 21:07:20 -0500 Received: from mail-pl1-f195.google.com ([209.85.214.195]:46053 "EHLO mail-pl1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732765AbeKOCHT (ORCPT ); Wed, 14 Nov 2018 21:07:19 -0500 Received: by mail-pl1-f195.google.com with SMTP id a14so3390919plm.12 for ; Wed, 14 Nov 2018 08:03:30 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=g.ncu.edu.tw; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=7NlOcQS1CVYAxETpCLLRykD6JVs/z/XSS1hZoJW810k=; b=JMgJeJqdUpopiQmpcleJDdwDA+1w6Ag6VS9X03nyaaK66vSQhfZhrk7yFYL93dggk5 WwBHkPJFEI5x4+Xs2DkPMVdHGPO8HyLY+My9Y5arDRw/VGIfuhodPBEmntutyTbLzCf+ Dp8tkbRJIjIwfTXGgLGehXs2hOy65zOYIFDB0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=7NlOcQS1CVYAxETpCLLRykD6JVs/z/XSS1hZoJW810k=; b=jh0D+lXUIfPQImEAyAcTFHg1mL/PD4IuxeiOZIAlsUMlnkFFn9EprbM/ZVJWqt4pIc wQ3GE9a+KcjcfjK0RlQWWHvz2yA7KMFVldcpyDxCagxevAovLR0t8t3OCsJ4skLK23Vb Ztnaf2/btnosA8+xz0rXCfJuBNJreD3bi7iPNWf9IazioIJ8v0ze16WbUlcDFqnySRu0 bvsRrlwWEstXy5DpGvo8s0vUywvAfmOvWqoapA8+ZhcY36DT1cUk0j0yizUPBEBUDDxc xSgLrSN7bRpEbPQVFTVJBXgxUon0eZUHn8FFB/r+L7qQ5E2s5e0tBdCMYe3pAy034XiL tRYA== X-Gm-Message-State: AGRZ1gKa/gckfVPGCgoAA5E9cv0fXG6MTtGVjV1AXtv/3PGtTclkFsfy 9/xUUk1ax25yU3OOv5WpSSWa/w== X-Google-Smtp-Source: AJdET5eRzRdNadvgZo2if0qGIQ8KT9erh30JD5LkJPqsCltWVwGtK/YLKdPm8VBKjpa0MyjZZHQYhQ== X-Received: by 2002:a17:902:f08f:: with SMTP id go15mr2513873plb.332.1542211410150; Wed, 14 Nov 2018 08:03:30 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id s2-v6sm53449854pfk.133.2018.11.14.08.03.27 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 14 Nov 2018 08:03:29 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= , "David S . Miller" Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V3 4/7] net: maclorawan: Add maclorawan module declaration Date: Thu, 15 Nov 2018 00:01:25 +0800 Message-Id: <20181114160126.4445-5-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181105.101610.1437737564548154497.davem@davemloft.net> References: <20181105.101610.1437737564548154497.davem@davemloft.net> MIME-Version: 1.0 Sender: linux-wpan-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Add the maclorawan header file for common APIs in the module. Signed-off-by: Jian-Hong Pan --- V2: - Split the LoRaWAN class module patch in V1 into LoRaWAN socket and LoRaWAN Soft MAC modules - Use SPDX license identifiers net/maclorawan/maclorawan.h | 199 ++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 net/maclorawan/maclorawan.h diff --git a/net/maclorawan/maclorawan.h b/net/maclorawan/maclorawan.h new file mode 100644 index 000000000000..66b87f051d51 --- /dev/null +++ b/net/maclorawan/maclorawan.h @@ -0,0 +1,199 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ +/*- + * LoRaWAN soft MAC + * + * Copyright (c) 2018 Jian-Hong, Pan + * + */ + +#ifndef __MAC_LORAWAN_H__ +#define __MAC_LORAWAN_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LORAWAN_MODULE_NAME "maclorawan" + +/* List the message types of LoRaWAN */ +enum { + LRW_JOIN_REQUEST, + LRW_JOIN_ACCEPT, + LRW_UNCONFIRMED_DATA_UP, + LRW_UNCONFIRMED_DATA_DOWN, + LRW_CONFIRMED_DATA_UP, + LRW_CONFIRMED_DATA_DOWN, + LRW_RFU, + LRW_PROPRIETARY, +}; + +/* List the communication directions */ +enum { + LRW_UPLINK, + LRW_DOWNLINK, +}; + +/* States of LoRaWAN slot timing */ +enum { + LRW_INIT_SS, + LRW_XMITTING_SS, + LRW_XMITTED, + LRW_RX1_SS, + LRW_RX2_SS, + LRW_RXTIMEOUT_SS, + LRW_RXRECEIVED_SS, + LRW_RETRANSMIT_SS, +}; + +#define LRW_MHDR_LEN 1 +#define LRW_FHDR_MAX_LEN 22 +#define LRW_FOPS_MAX_LEN 15 +#define LRW_FPORT_LEN 1 +#define LRW_MIC_LEN 4 + +/** + * lrw_fhdr - Hold the message's basic information of the frame + * + * @mtype: this message's type + * @fctrl: the frame control byte + * @fcnt: this message's frame counter value + * @fopts: this frame's options field + * @fopts_len: the length of the fopts + */ +struct lrw_fhdr { + u8 mtype; + u8 fctrl; + u16 fcnt; + u8 fopts[LRW_FPORT_LEN]; + u8 fopts_len; +}; + +/** + * lrw_session - LoRaWAN session for Class A end device + * + * @lrw_st: points to the belonging lrw_st + * @entry: the entry of the ss_list in lrw_struct + * @devaddr: the LoRaWAN device address of this LoRaWAN hardware + * @fcnt_up: uplink frame counter + * @fcnt_down: downlink frame counter + * @fport: the LoRaWAN data message's port field + * @tx_skb: points to the TX skb, the frame + * @rx_skb: points to the RX skb, the frame + * @tx_fhdr: hold the message's basic information of the TX frame + * @rx_fhdr: hold the message's basic information of the RX frame + * @tx_should_ack: flag for determining the TX which should be acked or not + * @retry: retry times for xmitting failed + * @state: this session's current state + * @state_lock: lock of the session's state + * @timer: timing for this session and the state transition + * @timeout_work: work if waiting acknowledge time out + * @rx_delay1: RX1 delay time in seconds + * @rx_delay2: RX2 delay time in seconds + * @rx1_window: RX1 window opening time in mini-seconds + * @rx2_window: RX2 window opening time in mini-seconds + * @ack_timeout: time out time for waiting acknowledge in seconds + */ +struct lrw_session { + struct lrw_struct *lrw_st; + struct list_head entry; + + u32 devaddr; + u16 fcnt_up; + u16 fcnt_down; + u8 fport; + struct sk_buff *tx_skb; + struct sk_buff *rx_skb; + struct lrw_fhdr tx_fhdr; + struct lrw_fhdr rx_fhdr; + + bool tx_should_ack; + u8 retry; + u8 state; + spinlock_t state_lock; + + struct timer_list timer; + struct work_struct timeout_work; + unsigned long rx_delay1; + unsigned long rx_delay2; + unsigned long rx1_window; + unsigned long rx2_window; + unsigned long ack_timeout; +}; + +/** + * lrw_struct - The full LoRaWAN hardware to the LoRa device. + * + * @dev: this LoRa device registed in system + * @hw: the LoRa device of this LoRaWAN hardware + * @ops: handle of LoRa operations interfaces + * @rx_skb_list: the list of received frames + * @ss_list: LoRaWAN session list of this LoRaWAN hardware + * @_cur_ss: pointer of the current processing session + * @rx_should_ack: represent the current session should be acked or not + * @state: the state of this LoRaWAN hardware + * @app_eui: the LoRaWAN application EUI + * @dev_eui: the LoRaWAN device EUI + * @devaddr: the LoRaWAN device address of this LoRaWAN hardware + * @appky: the Application key + * @nwkskey: the Network session key + * @appskey: the Application session key + * @nwks_shash_tfm: the hash handler for LoRaWAN network session + * @nwks_skc_tfm: the crypto handler for LoRaWAN network session + * @apps_skc_tfm: the crypto handler for LoRaWAN application session + * @fcnt_up: the counter of this LoRaWAN hardware's up frame + * @fcnt_down: the counter of this LoRaWAN hardware's down frame + * @xmit_task: the xmit task for the current LoRaWAN session + * @rx_work: the RX work in workqueue for the current LoRaWAN session + * @ndev: points to the emulating network device + * @_net: the current network namespace of this LoRaWAN hardware + */ +struct lrw_struct { + struct device dev; + struct lrw_hw hw; + struct lrw_operations *ops; + + struct sk_buff_head rx_skb_list; + struct list_head ss_list; + struct mutex ss_list_lock; + struct lrw_session *_cur_ss; + bool rx_should_ack; + u8 state; + + u64 app_eui; + u64 dev_eui; + u32 devaddr; + u8 appkey[LRW_KEY_LEN]; + u8 nwkskey[LRW_KEY_LEN]; + u8 appskey[LRW_KEY_LEN]; + struct crypto_shash *nwks_shash_tfm; + struct crypto_skcipher *nwks_skc_tfm; + struct crypto_skcipher *apps_skc_tfm; + + u16 fcnt_up; + u16 fcnt_down; + + struct tasklet_struct xmit_task; + struct work_struct rx_work; + + struct net_device *ndev; + possible_net_t _net; +}; + +#define NETDEV_2_LRW(ndev) ((struct lrw_struct *)netdev_priv(ndev)) + +struct lrw_session * lrw_alloc_ss(struct lrw_struct *); +void lrw_free_ss(struct lrw_session *); +void lrw_del_ss(struct lrw_session *); +int lrw_start_hw(struct lrw_struct *); +void lrw_stop_hw(struct lrw_struct *); +void lrw_prepare_tx_frame(struct lrw_session *); +void lrw_xmit(unsigned long); +void lrw_rx_work(struct work_struct *); + +#endif From patchwork Wed Nov 14 16:01:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jian-Hong Pan X-Patchwork-Id: 10682893 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DAEE214D6 for ; Wed, 14 Nov 2018 16:03:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CDCE82AB39 for ; Wed, 14 Nov 2018 16:03:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C1AAD2BB28; Wed, 14 Nov 2018 16:03:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2B7D82AB39 for ; Wed, 14 Nov 2018 16:03:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728085AbeKOCHX (ORCPT ); Wed, 14 Nov 2018 21:07:23 -0500 Received: from mail-pf1-f195.google.com ([209.85.210.195]:40503 "EHLO mail-pf1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728432AbeKOCHX (ORCPT ); Wed, 14 Nov 2018 21:07:23 -0500 Received: by mail-pf1-f195.google.com with SMTP id x2-v6so8123148pfm.7 for ; Wed, 14 Nov 2018 08:03:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=g.ncu.edu.tw; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FKT2FISMHyv8N3RNIMgKnskSouz7U+T77FZX5SCipNI=; b=Xe2o+RGU3sDy1iJDIH1MyLPEML1Ft1xD37Su332rVOhPMdqBWW8aRD9WQlVMm68B5s pQJ+/0xnT9A2nOGo6svH84cz4jmoj6qEFsxMoarWHUz5TzvXSMsESdHv5odwr0vvrk3G bbhT6gzTxC0WXW0TSPWbKtRhQQeynOymODbtc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FKT2FISMHyv8N3RNIMgKnskSouz7U+T77FZX5SCipNI=; b=llWoxffWMJMHznZGsJMVlkQ2cXxtrZNkfsTYn2FRLlqhHLkV4hDgqMhUiO2Q4te3s3 1IvFiF2+vxVGhEbi2J/p8cst5IYrmzIM0wK79eETUXYWW+vg3TFZg6kvTnb6OjsL2OLm qn78tPDyIjvcktHVdNkP9l4b3qGjuPYlZeJPwtcDHrQh7uK/gr4MHu61XvMTfsoKgBzt GJ+JGpixgowR8EZZ2cp0HMMbTMdk6K/ItVRO9WMxgW7dZXbEakrO+MIs8u/NNj46MG3U xivgWdwDglAFgocrNLLI6eZ1GIPAHKTkuxxDI+8JkATNFA41wBPGOjSkieQJTtMRwRMZ uMbw== X-Gm-Message-State: AGRZ1gJmZ9l0GWd657+yF9YnAARarA/YYcNhgNQy9PdyZxPac0Yed3uE A3DEiVI9E0dlOq8ojd/XxN2G8w== X-Google-Smtp-Source: AJdET5cRBkyXFJvUKq3VCfQxAZsyxYt/N0oZLeiEwqFa9U4pj3eupedXYixZEDOCSc9ct0Q5uqt3kg== X-Received: by 2002:a62:6fc7:: with SMTP id k190-v6mr2547163pfc.97.1542211413417; Wed, 14 Nov 2018 08:03:33 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id s2-v6sm53449854pfk.133.2018.11.14.08.03.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 14 Nov 2018 08:03:32 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= , "David S . Miller" Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V3 5/7] net: maclorawan: Implement the crypto of maclorawan module Date: Thu, 15 Nov 2018 00:01:26 +0800 Message-Id: <20181114160126.4445-6-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181105.101610.1437737564548154497.davem@davemloft.net> References: <20181105.101610.1437737564548154497.davem@davemloft.net> MIME-Version: 1.0 Sender: linux-wpan-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Implement the crypto for encryption/decryption and message integrity code (MIC) according to LoRaWAN(TM) Specification Ver. 1.0.2. Signed-off-by: Jian-Hong Pan --- V2: - Split the LoRaWAN class module patch in V1 into LoRaWAN socket and LoRaWAN Soft MAC modules - Rename the lrwsec files to crypto files - Modify for Big/Little-Endian - Use SPDX license identifiers V3: - Order local variables from longest to shortest line in the functions net/maclorawan/crypto.c | 209 ++++++++++++++++++++++++++++++++++++++++ net/maclorawan/crypto.h | 27 ++++++ 2 files changed, 236 insertions(+) create mode 100644 net/maclorawan/crypto.c create mode 100644 net/maclorawan/crypto.h diff --git a/net/maclorawan/crypto.c b/net/maclorawan/crypto.c new file mode 100644 index 000000000000..5337a661c9d0 --- /dev/null +++ b/net/maclorawan/crypto.c @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ +/*- + * LoRaWAN soft MAC + * + * Copyright (c) 2018 Jian-Hong, Pan + * + */ + +#include +#include +#include +#include "crypto.h" + +struct crypto_shash * +lrw_mic_key_setup(u8 *k, size_t k_len) +{ + struct crypto_shash *tfm; + char *algo = "cmac(aes)"; + int err; + + tfm = crypto_alloc_shash(algo, 0, 0); + if (!IS_ERR(tfm)) { + err = crypto_shash_setkey(tfm, k, k_len); + if (err) { + crypto_free_shash(tfm); + tfm = NULL; + } + } + + return tfm; +} + +int +lrw_aes_cmac(struct crypto_shash *tfm, u8 *bz, u8 *data, size_t len, u8 *out) +{ + SHASH_DESC_ON_STACK(desc, tfm); + int err; + + desc->tfm = tfm; + + err = crypto_shash_init(desc); + if (err) + goto lrw_aes_cmac_end; + + err = crypto_shash_update(desc, bz, 16); + if (err) + goto lrw_aes_cmac_end; + + err = crypto_shash_update(desc, data, len); + if (err) + goto lrw_aes_cmac_end; + + err = crypto_shash_final(desc, out); + +lrw_aes_cmac_end: + return err; +} + +int +lrw_set_bzero(u8 dir, u32 devaddr, u32 fcnt, u8 len, u8 *bz) +{ + __le32 le_devaddr = cpu_to_le32(devaddr); + __le32 le_fcnt = cpu_to_le32(fcnt); + + bz[0] = 0x49; + memset(bz + 1, 0x00, 4); + bz[5] = dir; + memcpy(bz + 6, &le_devaddr, 4); + memcpy(bz + 10, &le_fcnt, 4); + bz[14] = 0x00; + bz[15] = len; + + return 0; +} + +int +lrw_calc_mic(struct crypto_shash *tfm, + u8 dir, u32 devaddr, u32 fcnt, u8* buf, size_t len, u8 *mic4) +{ + u8 mic[16]; + u8 bz[16]; + int err; + + /* According to LoRaWAN Specification Version 1.0.2 + * - 4.4 Massege Integrity Code (MIC) */ + lrw_set_bzero(dir, devaddr, fcnt, len, bz); + err = lrw_aes_cmac(tfm, bz, buf, len, mic); + if (!err) + memcpy(mic4, mic, 4); + + return err; +} + +void +lrw_mic_key_free(struct crypto_shash *tfm) +{ + crypto_free_shash(tfm); +} + +struct crypto_skcipher * +lrw_aes_enc_key_setup(char *algo, u8 *k, size_t k_len) +{ + struct crypto_skcipher *tfm; + int err; + + tfm = crypto_alloc_skcipher(algo, 0, CRYPTO_ALG_ASYNC); + if (!IS_ERR(tfm)) { + err = crypto_skcipher_setkey(tfm, k, k_len); + if (err) { + crypto_free_skcipher(tfm); + tfm = NULL; + } + } + + return tfm; +} + +struct crypto_skcipher * +lrw_encrypt_key_setup(u8 *k, size_t k_len) +{ + return lrw_aes_enc_key_setup("cbc(aes)", k, k_len); +} + +int +lrw_aes_enc(struct crypto_skcipher *tfm, u8 *in, size_t len, u8 *out) +{ + SKCIPHER_REQUEST_ON_STACK(req, tfm); + struct scatterlist src, dst; + u8 iv[16]; + int err; + + memset(iv, 0, 16); + /* The buffer for sg_init_one cannot be a global or const local + * (will confuse the scatterlist) */ + sg_init_one(&src, in, len); + sg_init_one(&dst, out, len); + + skcipher_request_set_tfm(req, tfm); + skcipher_request_set_callback(req, 0, NULL, NULL); + skcipher_request_set_crypt(req, &src, &dst, len, iv); + err = crypto_skcipher_encrypt(req); + skcipher_request_zero(req); + + return err; +} + +#define LRW_SEQUENCE_OF_BLOCK_LEN 16 + +int +lrw_set_sob(u8 dir, u32 devaddr, u32 fcnt, u8 index, u8 *sob) +{ + __le32 le_devaddr = cpu_to_le32(devaddr); + __le32 _fcnt = cpu_to_le32(fcnt); + + sob[0] = 0x01; + memset(sob + 1, 0x00, 4); + sob[5] = dir; + memcpy(sob + 6, &le_devaddr, 4); + memcpy(sob + 10, &_fcnt, 4); + sob[14] = 0x00; + sob[15] = index; + + return 0; +} + +int +lrw_encrypt_sob(struct crypto_skcipher *tfm, u8 *sob) +{ + return lrw_aes_enc(tfm, sob, LRW_SEQUENCE_OF_BLOCK_LEN, sob); +} + +int +lrw_encrypt_buf(struct crypto_skcipher *tfm, + u8 dir, u32 devaddr, u32 fcnt, u8 *buf, size_t len) +{ + u8 sob[LRW_SEQUENCE_OF_BLOCK_LEN]; + u8 i, j; + + /* According to LoRaWAN Specification Version 1.0.2 + * - 4.3.3 MAC Frame Payload Encryption (FRMPayload) */ + for (i = 0; (i * LRW_SEQUENCE_OF_BLOCK_LEN) < len; i++) { + lrw_set_sob(dir, devaddr, fcnt, i, sob); + lrw_encrypt_sob(tfm, sob); + for (j = 0; (i * LRW_SEQUENCE_OF_BLOCK_LEN + j) < len; j++) + buf[i * LRW_SEQUENCE_OF_BLOCK_LEN + j] ^= sob[j]; + } + + return 0; +} + +int +lrw_decrypt_buf(struct crypto_skcipher *tfm, + u8 dir, u32 devaddr, u32 fcnt, u8 *buf, size_t len) +{ + /* Accoding to XOR swap algorithm */ + return lrw_encrypt_buf(tfm, dir, devaddr, fcnt, buf, len); +} + +void +lrw_aes_enc_key_free(struct crypto_skcipher *tfm) +{ + crypto_free_skcipher(tfm); +} + +void +lrw_encrypt_key_free(struct crypto_skcipher *tfm) +{ + lrw_aes_enc_key_free(tfm); +} diff --git a/net/maclorawan/crypto.h b/net/maclorawan/crypto.h new file mode 100644 index 000000000000..2ede02efb8c6 --- /dev/null +++ b/net/maclorawan/crypto.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ +/*- + * LoRaWAN soft MAC + * + * Copyright (c) 2018 Jian-Hong, Pan + * + */ + +#ifndef __LORAWAN_CRYPTO_H__ +#define __LORAWAN_CRYPTO_H__ + +#include +#include + +struct crypto_shash *lrw_mic_key_setup(u8 *k, size_t k_len); +int lrw_calc_mic(struct crypto_shash *tfm, + u8 dir, u32 devaddr, u32 fcnt, u8* buf, size_t len, u8 *mic4); +void lrw_mic_key_free(struct crypto_shash *tfm); + +struct crypto_skcipher *lrw_encrypt_key_setup(u8 *k, size_t k_len); +int lrw_encrypt_buf(struct crypto_skcipher *tfm, + u8 dir, u32 devaddr, u32 fcnt, u8 *buf, size_t len); +int lrw_decrypt_buf(struct crypto_skcipher *tfm, + u8 dir, u32 devaddr, u32 fcnt, u8 *buf, size_t len); +void lrw_encrypt_key_free(struct crypto_skcipher *tfm); + +#endif From patchwork Wed Nov 14 16:01:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jian-Hong Pan X-Patchwork-Id: 10682889 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CD30113BF for ; Wed, 14 Nov 2018 16:03:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B4D932BB1B for ; Wed, 14 Nov 2018 16:03:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A8F212BB39; Wed, 14 Nov 2018 16:03:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C72152BB1B for ; Wed, 14 Nov 2018 16:03:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1733107AbeKOCH2 (ORCPT ); Wed, 14 Nov 2018 21:07:28 -0500 Received: from mail-pg1-f194.google.com ([209.85.215.194]:43389 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387806AbeKOCH1 (ORCPT ); Wed, 14 Nov 2018 21:07:27 -0500 Received: by mail-pg1-f194.google.com with SMTP id n10-v6so7553442pgv.10 for ; Wed, 14 Nov 2018 08:03:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=g.ncu.edu.tw; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=bF4LPlIPfSu3Va/AibPiqjFl7Oj73sy9L6ykKNPL57Q=; b=g2sMImQzGW2D9KpC9EDF2Ie1dhbNLLCl6GkLJ3UkemBU3MmBphyPafgo0Lr6TGCR6i 9w2cpxFpmfo9gg+VM2Ef8HtoF/AdOimhCC+5nxxk1A6mKB+pd06XDFqPQ7aut9D1RiDb xCTiXqI1cr1ABk9ftCsXWSIvY9K9YnZ1J6JzM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bF4LPlIPfSu3Va/AibPiqjFl7Oj73sy9L6ykKNPL57Q=; b=F8F0EWDphh3nfERxaGRG8KkBtIzf9jx58EtPKvbt3fuVIeh+tZ631HclZ2ttVDUW+1 Lad5Ub0B6dLpBN8MOWHIYGgQs1L3phxqsJcNzDWJk1EXKC0Jq3bbc/2xSaFRrGhgZHk+ MNrZGhNwMoc1CpqXSkuS1Ud8oLA293DnRZiuoM/SoMM1+TMUQ1KK3ULuSPsaVrbrQFmL TYrIGtJbOE64k1ST0Lgipykm7GRHP+nCznoSUfjzBWQtfVL+e1pHTcd1j1JeUlbchU/f wU802Am88auG2wUFKlXJOmxaHpkOUP8nHelZC94PHunH3UTdxyWx01ZR/p+yOpvdxDR5 vhgg== X-Gm-Message-State: AGRZ1gIzYCKEpLrAwNGrplaFeB65+ACa/HtpxW2EGeCzOSlcKQkazn8v YPLOwUlVHwNzPXEWQXeDH4x6Bw== X-Google-Smtp-Source: AJdET5eVVQh6h/eLHMHebJ2HRnxlIGbHLZgJmQ5ch2X+ofjD8i5FV5sYuKzGI01Dp+6i8fCTdZwmZQ== X-Received: by 2002:a63:ab08:: with SMTP id p8mr2234756pgf.87.1542211417121; Wed, 14 Nov 2018 08:03:37 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id s2-v6sm53449854pfk.133.2018.11.14.08.03.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 14 Nov 2018 08:03:36 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= , "David S . Miller" Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V3 6/7] net: maclorawan: Implement maclorawan class module Date: Thu, 15 Nov 2018 00:01:27 +0800 Message-Id: <20181114160126.4445-7-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181105.101610.1437737564548154497.davem@davemloft.net> References: <20181105.101610.1437737564548154497.davem@davemloft.net> MIME-Version: 1.0 Sender: linux-wpan-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP LoRaWAN defined by LoRa Alliance(TM) is the MAC layer over LoRa devices. This patch implements part of Class A end-devices SoftMAC defined in LoRaWAN(TM) Specification Ver. 1.0.2: 1. End-device receive slot timing 2. Only single channel and single data rate for now 3. Unconfirmed data up/down message types On the other side, it defines the basic interface and operation functions for compatible LoRa device drivers. Signed-off-by: Jian-Hong Pan --- V2: - Split the LoRaWAN class module patch in V1 into LoRaWAN socket and LoRaWAN Soft MAC modules - Modify for Big/Little-Endian - Use SPDX license identifiers V3: - Remove the decoration word - inline of the functions - Order local variables from longest to shortest line in the functions - Change the calling mac_cb function to lrw_get_mac_cb macro net/maclorawan/Kconfig | 14 + net/maclorawan/Makefile | 2 + net/maclorawan/mac.c | 520 ++++++++++++++++++++++++++++++++++ net/maclorawan/main.c | 605 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1141 insertions(+) create mode 100644 net/maclorawan/Kconfig create mode 100644 net/maclorawan/Makefile create mode 100644 net/maclorawan/mac.c create mode 100644 net/maclorawan/main.c diff --git a/net/maclorawan/Kconfig b/net/maclorawan/Kconfig new file mode 100644 index 000000000000..177537d5f59f --- /dev/null +++ b/net/maclorawan/Kconfig @@ -0,0 +1,14 @@ +config MACLORAWAN + tristate "Generic LoRaWAN Soft Networking Stack (maclorawan)" + depends on LORAWAN + select CRYPTO + select CRYPTO_CMAC + select CRYPTO_CBC + select CRYPTO_AES + ---help--- + This option enables the hardware independent LoRaWAN + networking stack for SoftMAC devices (the ones implementing + only PHY level of LoRa standard). + + If you plan to use HardMAC LoRaWAN devices, you can say N + here. Alternatively you can say M to compile it as a module. diff --git a/net/maclorawan/Makefile b/net/maclorawan/Makefile new file mode 100644 index 000000000000..562831e66c82 --- /dev/null +++ b/net/maclorawan/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_MACLORAWAN) += maclorawan.o +maclorawan-objs := main.o mac.o crypto.o diff --git a/net/maclorawan/mac.c b/net/maclorawan/mac.c new file mode 100644 index 000000000000..2d9f322c364e --- /dev/null +++ b/net/maclorawan/mac.c @@ -0,0 +1,520 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ +/*- + * LoRaWAN soft MAC + * + * Copyright (c) 2018 Jian-Hong, Pan + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "maclorawan.h" +#include "crypto.h" + +static void rx_timeout_work(struct work_struct *work); + +struct lrw_session * +lrw_alloc_ss(struct lrw_struct *lrw_st) +{ + struct lrw_session *ss; + + ss = kzalloc(sizeof(struct lrw_session), GFP_KERNEL); + if (!ss) + goto lrw_alloc_ss_end; + + ss->lrw_st = lrw_st; + ss->devaddr = lrw_st->devaddr; + INIT_LIST_HEAD(&ss->entry); + + ss->tx_should_ack = false; + ss->retry = 3; + spin_lock_init(&ss->state_lock); + INIT_WORK(&ss->timeout_work, rx_timeout_work); + +lrw_alloc_ss_end: + return ss; +} + +void +lrw_free_ss(struct lrw_session *ss) +{ + netdev_dbg(ss->lrw_st->ndev, "%s\n", __func__); + if (ss->tx_skb) + consume_skb(ss->tx_skb); + netdev_dbg(ss->lrw_st->ndev, "%s: free rx skb\n", __func__); + if (ss->rx_skb) + consume_skb(ss->rx_skb); + + netdev_dbg(ss->lrw_st->ndev, "%s: free ss\n", __func__); + kfree(ss); +} + +void +lrw_del_ss(struct lrw_session *ss) +{ + netdev_dbg(ss->lrw_st->ndev, "%s\n", __func__); + list_del(&ss->entry); + lrw_free_ss(ss); +} + +void +lrw_del_all_ss(struct lrw_struct *lrw_st) +{ + struct lrw_session *ss, *tmp; + + mutex_lock(&lrw_st->ss_list_lock); + lrw_st->_cur_ss = NULL; + list_for_each_entry_safe(ss, tmp, &lrw_st->ss_list, entry) { + del_timer(&ss->timer); + lrw_del_ss(ss); + } + mutex_unlock(&lrw_st->ss_list_lock); +} + +void +lrw_ready_hw(struct lrw_struct *lrw_st) +{ + lrw_st->state = LRW_STATE_IDLE; +} + +int +lrw_start_hw(struct lrw_struct *lrw_st) +{ + int ret = 0; + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + lrw_st->nwks_shash_tfm = lrw_mic_key_setup(lrw_st->nwkskey, + LRW_KEY_LEN); + lrw_st->nwks_skc_tfm = lrw_encrypt_key_setup(lrw_st->nwkskey, + LRW_KEY_LEN); + lrw_st->apps_skc_tfm = lrw_encrypt_key_setup(lrw_st->appskey, + LRW_KEY_LEN); + lrw_st->state = LRW_START; + ret = lrw_st->ops->start(&lrw_st->hw); + if (!ret) + lrw_ready_hw(lrw_st); + + return ret; +} + +void +lrw_stop_hw(struct lrw_struct *lrw_st) +{ + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + lrw_st->state = LRW_STOP; + netdev_dbg(lrw_st->ndev, "%s: going to stop hardware\n", __func__); + lrw_st->ops->stop(&lrw_st->hw); + + netdev_dbg(lrw_st->ndev, "%s: going to kill tasks & flush works", __func__); + tasklet_kill(&lrw_st->xmit_task); + flush_work(&lrw_st->rx_work); + + netdev_dbg(lrw_st->ndev, "%s: going to delete all session\n", __func__); + lrw_del_all_ss(lrw_st); + + netdev_dbg(lrw_st->ndev, "%s: going to free mic tfm\n", __func__); + lrw_mic_key_free(lrw_st->nwks_shash_tfm); + netdev_dbg(lrw_st->ndev, "%s: going to free nwks tfm\n", __func__); + lrw_encrypt_key_free(lrw_st->nwks_skc_tfm); + netdev_dbg(lrw_st->ndev, "%s: going to free apps tfm\n", __func__); + lrw_encrypt_key_free(lrw_st->apps_skc_tfm); +} + +void +lrw_prepare_tx_frame(struct lrw_session *ss) +{ + struct lrw_struct *lrw_st = ss->lrw_st; + struct sk_buff *skb = ss->tx_skb; + u8 mhdr, fctrl, fport, mic[4]; + __le32 le_devaddr; + __le16 le_fcnt_up; + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + + /* Encrypt the plain buffer content */ + lrw_encrypt_buf(lrw_st->apps_skc_tfm, LRW_UPLINK, + ss->devaddr, ss->fcnt_up, skb->data, skb->len); + + /* Push FPort */ + if (skb->len) { + fport = ss->fport; + memcpy(skb_push(skb, LRW_FPORT_LEN), &fport, LRW_FPORT_LEN); + } + + /* Push FCnt_Up */ + le_fcnt_up = cpu_to_le16(ss->fcnt_up); + memcpy(skb_push(skb, 2), &le_fcnt_up, 2); + + /* Push FCtrl */ + fctrl = 0; + if (lrw_st->rx_should_ack) { + fctrl |= 0x20; + lrw_st->rx_should_ack = false; + } + memcpy(skb_push(skb, 1), &fctrl, 1); + + /* Push DevAddr */ + le_devaddr = cpu_to_le32(ss->devaddr); + memcpy(skb_push(skb, LRW_DEVADDR_LEN), &le_devaddr, LRW_DEVADDR_LEN); + + /* Push MHDR */ + mhdr = LRW_UNCONFIRMED_DATA_UP << 5; + if ((mhdr & (0x6 << 5)) == (0x4 << 5)) + ss->tx_should_ack = true; + memcpy(skb_push(skb, LRW_MHDR_LEN), &mhdr, LRW_MHDR_LEN); + + /* Put MIC */ + lrw_calc_mic(lrw_st->nwks_shash_tfm, LRW_UPLINK, + ss->devaddr, ss->fcnt_up, skb->data, skb->len, mic); + memcpy(skb_put(skb, LRW_MIC_LEN), mic, LRW_MIC_LEN); +} + +void +lrw_xmit(unsigned long data) +{ + struct lrw_struct *lrw_st = (struct lrw_struct *) data; + struct lrw_session *ss = lrw_st->_cur_ss; + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + ss->state = LRW_XMITTING_SS; + lrw_st->ops->xmit_async(&lrw_st->hw, ss->tx_skb); +} + +void +lrw_parse_frame(struct lrw_session *ss, struct sk_buff *skb) +{ + struct lrw_fhdr *fhdr = &ss->rx_fhdr; + __le16 *p_fcnt; + + pr_debug("%s: %s\n", LORAWAN_MODULE_NAME, __func__); + + /* Get message type */ + fhdr->mtype = skb->data[0]; + skb_pull(skb, LRW_MHDR_LEN); + + /* Trim Device Address */ + skb_pull(skb, 4); + + /* Get frame control */ + fhdr->fctrl = skb->data[0]; + skb_pull(skb, 1); + + /* Ack the original TX frame if it should be acked */ + if (ss->tx_should_ack && (fhdr->fctrl & 0x20)) + ss->tx_should_ack = false; + + /* Get frame count */ + p_fcnt = (__le16 *)skb->data; + fhdr->fcnt = le16_to_cpu(*p_fcnt); + skb_pull(skb, 2); + + /* Get frame options */ + fhdr->fopts_len = fhdr->fctrl & 0xF; + if (fhdr->fopts_len > 0) { + memcpy(fhdr->fopts, skb->data, fhdr->fopts_len); + skb_pull(skb, fhdr->fopts_len); + } + + /* TODO: Parse frame options */ + + /* Remove message integrity code */ + skb_trim(skb, skb->len - LRW_MIC_LEN); +} + +struct lrw_session * +lrw_rx_skb_2_session(struct lrw_struct *lrw_st, struct sk_buff *rx_skb) +{ + struct lrw_session *ss; + __le16 *p_fcnt; + u16 fcnt; + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + + p_fcnt = (__le16 *)(rx_skb->data + 6); + fcnt = le16_to_cpu(*p_fcnt); + + /* Find the corresponding session */ + ss = lrw_st->_cur_ss; + + /* Frame count downlink check */ + if (fcnt >= (ss->fcnt_down & 0xFFFF)) + ss->rx_skb = rx_skb; + else + ss = NULL; + + return ss; +} + +void +lrw_rx_work(struct work_struct *work) +{ + struct lrw_struct *lrw_st; + struct lrw_session *ss; + struct sk_buff *skb; + + lrw_st = container_of(work, struct lrw_struct, rx_work); + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + + skb = lrw_st->rx_skb_list.next; + skb_dequeue(&lrw_st->rx_skb_list); + + /* Check and parse the RX frame */ + ss = lrw_rx_skb_2_session(lrw_st, skb); + if (!ss) + goto lrw_rx_work_not_new_frame; + + lrw_parse_frame(ss, skb); + + /* Check the TX frame is acked or not */ + if (ss->tx_should_ack) { + ss->rx_skb = NULL; + goto lrw_rx_work_not_new_frame; + } + + /* The TX frame is acked or no need to be acked */ + del_timer(&ss->timer); + lrw_st->rx_should_ack = (ss->rx_fhdr.mtype & 0xC0) == 0x40; + + lrw_st->ndev->stats.rx_packets++; + lrw_st->ndev->stats.rx_bytes += ss->rx_skb->len; + + if (ss->rx_skb->len > 0) { + spin_lock_bh(&ss->state_lock); + ss->state = LRW_RXRECEIVED_SS; + spin_unlock_bh(&ss->state_lock); + + lrw_get_mac_cb(skb)->devaddr = lrw_st->devaddr; + netif_receive_skb(skb); + + ss->rx_skb = NULL; + } + + mutex_lock(&lrw_st->ss_list_lock); + lrw_st->fcnt_down = ss->rx_fhdr.fcnt; + lrw_st->_cur_ss = NULL; + lrw_del_ss(ss); + lrw_st->state = LRW_STATE_IDLE; + mutex_unlock(&lrw_st->ss_list_lock); + + return; + +lrw_rx_work_not_new_frame: + /* Drop the RX frame if checked failed */ + kfree_skb(skb); +} + +int +lrw_check_mic(struct crypto_shash *tfm, struct sk_buff *skb) +{ + u32 devaddr; + size_t len; + u8 cks[4]; + u16 fcnt; + u8 *buf; + u8 *mic; + + buf = skb->data; + devaddr = le32_to_cpu(*((__le32 *)(buf + LRW_MHDR_LEN))); + fcnt = le16_to_cpu(*(__le16 *)(buf + 6)); + len = skb->len - 4; + mic = skb->data + len; + + lrw_calc_mic(tfm, LRW_DOWNLINK, devaddr, fcnt, buf, len, cks); + + return (!memcmp(cks, mic, 4)); +} + +/** + * lrw_rx_irqsave - Tell LoRaWAN module that there is new received frame + * @hw: the LoRa device + * @skb: the new received frame + */ +void +lrw_rx_irqsave(struct lrw_hw *hw, struct sk_buff *skb) +{ + struct lrw_struct *lrw_st = container_of(hw, struct lrw_struct, hw); + u32 devaddr; + u8 mtype; + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + + mtype = skb->data[0] >> 5; + devaddr = le32_to_cpu(*(__le32 *)(skb->data + LRW_MHDR_LEN)); + + /* Check the frame is the downlink frame */ + if (((mtype == LRW_UNCONFIRMED_DATA_DOWN) + || (mtype == LRW_CONFIRMED_DATA_DOWN)) + && (devaddr == lrw_st->devaddr) + && lrw_check_mic(lrw_st->nwks_shash_tfm, skb)) { + skb_queue_tail(&lrw_st->rx_skb_list, skb); + schedule_work(&lrw_st->rx_work); + } + else { + kfree_skb(skb); + } +} +EXPORT_SYMBOL(lrw_rx_irqsave); + +static void +lrw_rexmit(struct timer_list *timer) +{ + struct lrw_session *ss = container_of(timer, struct lrw_session, timer); + struct lrw_struct *lrw_st = ss->lrw_st; + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + + lrw_st->state = LRW_STATE_TX; + lrw_xmit((unsigned long) lrw_st); +} + +static void +rx_timeout_work(struct work_struct *work) +{ + struct lrw_struct *lrw_st; + struct lrw_session *ss; + + ss = container_of(work, struct lrw_session, timeout_work); + lrw_st = ss->lrw_st; + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + mutex_lock(&lrw_st->ss_list_lock); + lrw_st->_cur_ss = NULL; + lrw_st->state = LRW_STATE_IDLE; + lrw_del_ss(ss); + mutex_unlock(&lrw_st->ss_list_lock); +} + +static void +rx2_timeout_isr(struct timer_list *timer) +{ + struct lrw_session *ss = container_of(timer, struct lrw_session, timer); + struct lrw_struct *lrw_st = ss->lrw_st; + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + + /* Check TX is acked or not */ + if (!ss->tx_should_ack) { + spin_lock_bh(&ss->state_lock); + if (ss->state != LRW_RXRECEIVED_SS) + ss->state = LRW_RXTIMEOUT_SS; + spin_unlock_bh(&ss->state_lock); + + if (ss->state == LRW_RXTIMEOUT_SS) { + netdev_dbg(lrw_st->ndev, "%s: rx time out\n", __func__); + goto rx2_timeout_isr_no_retry_rx_frame; + } + else { + return; + } + } + + /* Check the session need to be retransmitted or not */ + if (ss->retry > 0) { + ss->state = LRW_RETRANSMIT_SS; + ss->retry--; + + /* Start timer for ack timeout and retransmit */ + ss->timer.function = lrw_rexmit; + ss->timer.expires = jiffies_64 + ss->ack_timeout * HZ; + add_timer(&ss->timer); + } + else { + /* Retry failed */ +rx2_timeout_isr_no_retry_rx_frame: + schedule_work(&ss->timeout_work); + } +} + +static void +rx2_delay_isr(struct timer_list *timer) +{ + struct lrw_session *ss = container_of(timer, struct lrw_session, timer); + struct lrw_struct *lrw_st = ss->lrw_st; + unsigned long delay; + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + + /* Start timer for RX2 window */ + ss->timer.function = rx2_timeout_isr; + delay = jiffies_64 + (ss->rx2_window + 20) * HZ / 1000 + HZ; + ss->timer.expires = delay; + add_timer(&ss->timer); + + /* Start LoRa hardware to RX2 window */ + ss->state = LRW_RX2_SS; + lrw_st->ops->start_rx_window(&lrw_st->hw, ss->rx2_window + 20); +} + +static void +rx1_delay_isr(struct timer_list *timer) +{ + struct lrw_session *ss = container_of(timer, struct lrw_session, timer); + struct lrw_struct *lrw_st = ss->lrw_st; + unsigned long delay; + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + + /* Start timer for RX_Delay2 - RX_Delay2 */ + ss->timer.function = rx2_delay_isr; + delay = jiffies_64 + (ss->rx_delay2 - ss->rx_delay1) * HZ - 20 * HZ / 1000; + ss->timer.expires = delay; + add_timer(&ss->timer); + + /* Start LoRa hardware to RX1 window */ + ss->state = LRW_RX1_SS; + lrw_st->ops->start_rx_window(&lrw_st->hw, ss->rx1_window + 20); +} + +void +lrw_sent_tx_work(struct lrw_struct *lrw_st, struct sk_buff *skb) +{ + struct lrw_session *ss = lrw_st->_cur_ss; + struct net_device *ndev; + unsigned long delay; + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + + ss->state = LRW_XMITTED; + + /* Start session timer for RX_Delay1 */ + timer_setup(&ss->timer, rx1_delay_isr, 0); + delay = jiffies_64 + ss->rx_delay1 * HZ - 20 * HZ / 1000; + ss->timer.expires = delay; + add_timer(&ss->timer); + + ndev = skb->dev; + ndev->stats.tx_packets++; + ndev->stats.tx_bytes += skb->len; + dev_consume_skb_any(skb); + ss->tx_skb = NULL; +} + +/** + * lrw_xmit_complete - Tell LoRaWAN module that the frame is xmitted completely + * @hw: the LoRa device + * @skb: the xmitted frame + */ +void +lrw_xmit_complete(struct lrw_hw *hw, struct sk_buff *skb) +{ + struct lrw_struct *lrw_st = container_of(hw, struct lrw_struct, hw); + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + + lrw_sent_tx_work(lrw_st, skb); + lrw_st->state = LRW_STATE_RX; +} +EXPORT_SYMBOL(lrw_xmit_complete); diff --git a/net/maclorawan/main.c b/net/maclorawan/main.c new file mode 100644 index 000000000000..9ca778706880 --- /dev/null +++ b/net/maclorawan/main.c @@ -0,0 +1,605 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */ +/*- + * LoRaWAN soft MAC + * + * Copyright (c) 2018 Jian-Hong, Pan + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "maclorawan.h" + +#define PHY_NAME "lora" + +/* Need to find a way to define or assign */ +#define LORAWAN_MTU 20 + +static struct class *lrw_sys_class; + +static void +lrw_if_setup(struct net_device *ndev) +{ + ndev->addr_len = LRW_DEVADDR_LEN; + memset(ndev->broadcast, 0xFF, ndev->addr_len); + ndev->type = ARPHRD_LORAWAN; + + ndev->hard_header_len = LRW_MHDR_LEN + LRW_FHDR_MAX_LEN + LRW_FPORT_LEN; + ndev->needed_tailroom = LRW_MIC_LEN; + + /** + * TODO: M should be a dynamic value defined by Regional Parameters, + * Being fixed for now. Going to be changed. + */ + ndev->mtu = LORAWAN_MTU; +} + +/** + * lrw_alloc_hw - Allocate a memory space for the LoRa device + * @priv_data_len: the private data size + * @lrw_operations: the implemented operations of the LoRa device + * + * Return: address of the LoRa device or NULL for failed + */ +struct lrw_hw * +lrw_alloc_hw(size_t priv_data_len, struct lrw_operations *ops) +{ + struct lrw_struct *lrw_st; + struct net_device *ndev; + int ret; + + if (WARN_ON(!ops || !ops->start || !ops->stop || !ops->xmit_async || + !ops->set_txpower || !ops->set_dr || + !ops->start_rx_window || !ops->set_state)) + return NULL; + + /* In memory it'll be like this: + * + * +-----------------------+ + * | struct net_device | + * +-----------------------+ + * | struct lrw_struct | + * +-----------------------+ + * | driver's private data | + * +-----------------------+ + */ + ndev = alloc_netdev(sizeof(struct lrw_struct) + priv_data_len, + PHY_NAME"%d", NET_NAME_ENUM, lrw_if_setup); + if (!ndev) + return ERR_PTR(-ENOMEM); + ret = dev_alloc_name(ndev, ndev->name); + if (ret < 0) + goto lrw_alloc_hw_err; + + lrw_st = (struct lrw_struct *)netdev_priv(ndev); + lrw_st->ndev = ndev; + + lrw_st->state = LRW_STOP; + lrw_st->ops = ops; + lrw_st->hw.priv = (void *) lrw_st + sizeof(struct lrw_struct); + + ndev->flags |= IFF_NOARP; + ndev->features |= NETIF_F_HW_CSUM; + + return &lrw_st->hw; + +lrw_alloc_hw_err: + free_netdev(ndev); + return ERR_PTR(ret); +} +EXPORT_SYMBOL(lrw_alloc_hw); + +/** + * lrw_free_hw - Free the LoRa device's memory resource + * @hw: the LoRa device going to be freed + */ +void +lrw_free_hw(struct lrw_hw *hw) +{ + struct lrw_struct *lrw_st; + + lrw_st = container_of(hw, struct lrw_struct, hw); + free_netdev(lrw_st->ndev); +} +EXPORT_SYMBOL(lrw_free_hw); + +/** + * lrw_set_deveui - Set the LoRa device's DevEUI + * @hw: the LoRa device going to be set + * @eui: the global end-device ID in IEEE EUI64 address space + */ +void +lrw_set_deveui(struct lrw_hw *hw, u64 eui) +{ + struct lrw_struct *lrw_st; + + lrw_st = container_of(hw, struct lrw_struct, hw); + lrw_st->dev_eui = eui; +} +EXPORT_SYMBOL(lrw_set_deveui); + +/** + * lrw_get_deveui - Get the LoRa device's DevEUI + * @hw: the LoRa device going to be got from + * + * Return: the device's DevEUI in IEEE EUI64 address space + */ +u64 +lrw_get_deveui(struct lrw_hw *hw) +{ + struct lrw_struct *lrw_st; + + lrw_st = container_of(hw, struct lrw_struct, hw); + return lrw_st->dev_eui; +} +EXPORT_SYMBOL(lrw_get_deveui); + +/** + * lrw_set_appeui - Set the LoRa device's AppEUI + * @hw: the LoRa device going to be set + * @eui: the global end-device ID in IEEE EUI64 address space + */ +void +lrw_set_appeui(struct lrw_hw *hw, u64 eui) +{ + struct lrw_struct *lrw_st; + + lrw_st = container_of(hw, struct lrw_struct, hw); + lrw_st->app_eui = eui; +} +EXPORT_SYMBOL(lrw_set_appeui); + +/** + * lrw_get_appeui - Get the LoRa device's AppEUI + * @hw: the LoRa device going to be got from + * + * Return: the device's AppEUI in IEEE EUI64 address space + */ +u64 +lrw_get_appeui(struct lrw_hw *hw) +{ + struct lrw_struct *lrw_st; + + lrw_st = container_of(hw, struct lrw_struct, hw); + return lrw_st->app_eui; +} +EXPORT_SYMBOL(lrw_get_appeui); + +/** + * lrw_set_devaddr - Set the LoRa device's address + * @hw: the LoRa device going to be set + * @devaddr: the device address + */ +void +lrw_set_devaddr(struct lrw_hw *hw, u32 devaddr) +{ + struct lrw_struct *lrw_st; + + lrw_st = container_of(hw, struct lrw_struct, hw); + lrw_st->devaddr = devaddr; +} +EXPORT_SYMBOL(lrw_set_devaddr); + +/** + * lrw_get_devaddr - Get the LoRa device's address + * @hw: the LoRa device going to be got from + * + * Return: the device address + */ +u32 +lrw_get_devaddr(struct lrw_hw *hw) +{ + struct lrw_struct *lrw_st; + + lrw_st = container_of(hw, struct lrw_struct, hw); + return lrw_st->devaddr; +} +EXPORT_SYMBOL(lrw_get_devaddr); + +/** + * lrw_add_hw - Add a LoRaWAN hardware as a network device + * @lrw_st: the LoRa device going to be added + * + * Return: 0 / other number for success / failed + */ +static int +lrw_add_hw(struct lrw_struct *lrw_st) +{ + struct net_device *ndev = lrw_st->ndev; + __be32 be_addr; + int ret; + + lrw_st->fcnt_up = 0; + lrw_st->fcnt_down = 0; + lrw_st->_cur_ss = NULL; + + mutex_init(&lrw_st->ss_list_lock); + INIT_LIST_HEAD(&lrw_st->ss_list); + + tasklet_init(&lrw_st->xmit_task, lrw_xmit, (unsigned long) lrw_st); + INIT_WORK(&lrw_st->rx_work, lrw_rx_work); + + be_addr = cpu_to_be32(lrw_st->devaddr); + memcpy(ndev->perm_addr, &be_addr, ndev->addr_len); + memcpy(ndev->dev_addr, ndev->perm_addr, ndev->addr_len); + + write_pnet(&lrw_st->_net, &init_net); + ret = register_netdev(ndev); + + return ret; +} + +/** + * lrw_remove_hw - Remove a LoRaWAN hardware from a network device + * @lrw_st: the LoRa device going to be removed + */ +static void +lrw_remove_hw(struct lrw_struct *lrw_st) +{ + unregister_netdev(lrw_st->ndev); + tasklet_kill(&lrw_st->xmit_task); +} + +bool +ready2write(struct lrw_struct *lrw_st) +{ + bool status = false; + + if ((!lrw_st->_cur_ss) && (lrw_st->state == LRW_STATE_IDLE)) + status = true; + + return status; +} + +bool +ready2read(struct lrw_struct *lrw_st) +{ + struct lrw_session *ss; + bool status = false; + + if (!list_empty(&lrw_st->ss_list) && (lrw_st->state != LRW_STOP)) { + ss = list_first_entry(&lrw_st->ss_list, + struct lrw_session, + entry); + if (ss->state == LRW_RXRECEIVED_SS) + status = true; + } + + return status; +} + +static int +lrw_if_up(struct net_device *ndev) +{ + struct lrw_struct *lrw_st = NETDEV_2_LRW(ndev); + int ret = -EBUSY; + + if (lrw_st->state == LRW_STOP) { + ret = lrw_start_hw(lrw_st); + netif_start_queue(ndev); + } + + return ret; +} + +static int +lrw_if_down(struct net_device *ndev) +{ + struct lrw_struct *lrw_st = NETDEV_2_LRW(ndev); + + if (lrw_st->state != LRW_STOP) { + netif_stop_queue(ndev); + lrw_stop_hw(lrw_st); + } + + return 0; +} + +static netdev_tx_t +lrw_if_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + struct lrw_struct *lrw_st = NETDEV_2_LRW(ndev); + struct lrw_session *ss; + netdev_tx_t ret; + + ret = NETDEV_TX_OK; + + ss = lrw_alloc_ss(lrw_st); + if (!ss) + return NETDEV_TX_BUSY; + + mutex_lock(&lrw_st->ss_list_lock); + if (ready2write(lrw_st)) { + list_add_tail(&ss->entry, &lrw_st->ss_list); + lrw_st->state = LRW_STATE_TX; + lrw_st->_cur_ss = ss; + ss->fcnt_up = lrw_st->fcnt_up; + ss->fcnt_down = lrw_st->fcnt_down; + /* TODO: RX delay #1/#2 should be set by regional parameters */ + ss->rx_delay1 = 1; + ss->rx_delay2 = 2; + ss->rx1_window = 500; + ss->rx2_window = 500; + } + else + ret = NETDEV_TX_BUSY; + mutex_unlock(&lrw_st->ss_list_lock); + + if (ret == NETDEV_TX_OK) { + ss->state = LRW_INIT_SS; + ss->tx_skb = skb; + lrw_prepare_tx_frame(ss); + tasklet_schedule(&lrw_st->xmit_task); + } + else + lrw_free_ss(ss); + + return ret; +} + +static int +lrw_if_get_addr(struct lrw_struct *lrw_st, struct sockaddr_lorawan *addr) +{ + int ret = 0; + + switch (addr->addr_in.addr_type) { + case LRW_ADDR_DEVADDR: + addr->addr_in.devaddr = lrw_st->devaddr; + break; + case LRW_ADDR_DEVEUI: + addr->addr_in.dev_eui = lrw_st->dev_eui; + break; + case LRW_ADDR_APPEUI: + addr->addr_in.app_eui = lrw_st->app_eui; + break; + default: + ret = -ENOTSUPP; + } + + return ret; +} + +static int +lrw_if_set_addr(struct lrw_struct *lrw_st, struct sockaddr_lorawan *addr) +{ + struct lrw_hw *hw = &lrw_st->hw; + int ret = 0; + + if (netif_running(lrw_st->ndev)) + return -EBUSY; + + switch (addr->addr_in.addr_type) { + case LRW_ADDR_DEVADDR: + lrw_set_devaddr(hw, addr->addr_in.devaddr); + break; + case LRW_ADDR_DEVEUI: + lrw_set_deveui(hw, addr->addr_in.dev_eui); + break; + case LRW_ADDR_APPEUI: + lrw_set_appeui(hw, addr->addr_in.app_eui); + break; + default: + ret = -ENOTSUPP; + } + + return ret; +} + +static void +swap_bytes(u8 *dst, u8 *src, size_t l) +{ + /* Human reading is big-endian, but LoRaWAN is little-endian */ + unsigned int i; + for (i = 0; i < l; i++) + dst[i] = src[l - i - 1]; +} + +int +lrw_set_key(struct lrw_hw *hw, u8 type, u8 *key, size_t key_len) +{ + struct lrw_struct *lrw_st; + int ret = 0; + + lrw_st = container_of(hw, struct lrw_struct, hw); + + netdev_dbg(lrw_st->ndev, "%s: type=%d\n", __func__, type); + if (lrw_st->state != LRW_STOP) + return -EINVAL; + + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1, key, key_len, true); + switch (type) { + case LRW_APPKEY: + swap_bytes(lrw_st->appkey, key, key_len); + break; + case LRW_NWKSKEY: + swap_bytes(lrw_st->nwkskey, key, key_len); + break; + case LRW_APPSKEY: + swap_bytes(lrw_st->appskey, key, key_len); + break; + default: + ret = -ENOTSUPP; + } + + return ret; +} +EXPORT_SYMBOL(lrw_set_key); + +int +lrw_get_key(struct lrw_hw *hw, u8 type, u8 *key, size_t key_len) +{ + struct lrw_struct *lrw_st; + int ret = 0; + + lrw_st = container_of(hw, struct lrw_struct, hw); + + netdev_dbg(lrw_st->ndev, "%s: type=%d\n", __func__, type); + switch (type) { + case LRW_APPKEY: + swap_bytes(key, lrw_st->appkey, key_len); + break; + case LRW_NWKSKEY: + swap_bytes(key, lrw_st->nwkskey, key_len); + break; + case LRW_APPSKEY: + swap_bytes(key, lrw_st->appskey, key_len); + break; + default: + ret = -ENOTSUPP; + } + + return ret; +} + +static int +lrw_if_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) +{ + struct lrw_struct *lrw_st = NETDEV_2_LRW(ndev); + struct sockaddr_lorawan *addr; + int ret = 0; + + netdev_dbg(ndev, "%s: ioctl file (cmd=0x%X)\n", __func__, cmd); + + /* I/O control by each command */ + switch (cmd) { + /* Set & get the DevAddr, DevEUI and AppEUI */ + case SIOCSIFADDR: + addr = (struct sockaddr_lorawan *)&ifr->ifr_addr; + ret = lrw_if_set_addr(lrw_st, addr); + break; + case SIOCGIFADDR: + addr = (struct sockaddr_lorawan *)&ifr->ifr_addr; + ret = lrw_if_get_addr(lrw_st, addr); + break; + default: + ret = -ENOTSUPP; + } + + return ret; +} + +static int +lrw_if_set_mac(struct net_device *ndev, void *p) +{ + struct lrw_struct *lrw_st = NETDEV_2_LRW(ndev); + struct sockaddr *addr = p; + __be32 *be_addr; + + be_addr = (__be32 *)addr->sa_data; + + netdev_dbg(ndev, "%s: AF_TYPE:%d set mac address %X\n", + __func__, addr->sa_family, be32_to_cpu(*be_addr)); + + if (netif_running(ndev)) + return -EBUSY; + + lrw_set_devaddr(&lrw_st->hw, be32_to_cpu(*be_addr)); + memcpy(ndev->dev_addr, be_addr, ndev->addr_len); + + return 0; +} + +static const struct net_device_ops lrw_if_ops = { + .ndo_open = lrw_if_up, + .ndo_stop = lrw_if_down, + .ndo_start_xmit = lrw_if_start_xmit, + .ndo_do_ioctl = lrw_if_ioctl, + .ndo_set_mac_address = lrw_if_set_mac, +}; + +/** + * lrw_register_hw - Register as a LoRaWAN compatible device + * @hw: LoRa device going to be registered + * + * Return: 0 / negative number for success / error number + */ +int +lrw_register_hw(struct lrw_hw *hw) +{ + struct lrw_struct *lrw_st = container_of(hw, struct lrw_struct, hw); + int ret; + + device_initialize(&lrw_st->dev); + dev_set_name(&lrw_st->dev, netdev_name(lrw_st->ndev)); + lrw_st->dev.class = lrw_sys_class; + lrw_st->dev.platform_data = lrw_st; + + ret = device_add(&lrw_st->dev); + if (ret) + goto lrw_register_hw_end; + + /* Add a LoRa device node as a network device */ + lrw_st->ndev->netdev_ops = &lrw_if_ops; + ret = lrw_add_hw(lrw_st); + if (!ret) + netdev_info(lrw_st->ndev, "register\n"); + +lrw_register_hw_end: + return ret; +} +EXPORT_SYMBOL(lrw_register_hw); + +/** + * lrw_unregister_hw - Unregister the LoRaWAN compatible device + * @hw: LoRa device going to be unregistered + */ +void +lrw_unregister_hw(struct lrw_hw *hw) +{ + struct lrw_struct *lrw_st = container_of(hw, struct lrw_struct, hw); + + netdev_info(lrw_st->ndev, "unregister\n"); + + /* Stop and remove the LoRaWAM hardware from system */ + if (lrw_st->state != LRW_STOP) + lrw_stop_hw(lrw_st); + device_del(&lrw_st->dev); + lrw_remove_hw(lrw_st); + + return; +} +EXPORT_SYMBOL(lrw_unregister_hw); + +static int __init +lrw_init(void) +{ + int err = 0; + + pr_info("%s: module inserted\n", LORAWAN_MODULE_NAME); + + /* Create device class */ + lrw_sys_class = class_create(THIS_MODULE, LORAWAN_MODULE_NAME); + if (IS_ERR(lrw_sys_class)) { + pr_err("%s: Failed to create a class of LoRaWAN\n", + LORAWAN_MODULE_NAME); + err = PTR_ERR(lrw_sys_class); + goto lrw_init_end; + } + + pr_debug("%s: class created\n", LORAWAN_MODULE_NAME); + +lrw_init_end: + return err; +} + +static void __exit +lrw_exit(void) +{ + /* Delete device class */ + class_destroy(lrw_sys_class); + pr_info("%s: module removed\n", LORAWAN_MODULE_NAME); +} + +module_init(lrw_init); +module_exit(lrw_exit); + +MODULE_AUTHOR("Jian-Hong Pan, "); +MODULE_DESCRIPTION("LoRaWAN soft MAC kernel module"); +MODULE_LICENSE("Dual BSD/GPL"); From patchwork Wed Nov 14 16:01:28 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jian-Hong Pan X-Patchwork-Id: 10682891 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 786BE14D6 for ; Wed, 14 Nov 2018 16:03:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6A80C2AE21 for ; Wed, 14 Nov 2018 16:03:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5EE002BB26; Wed, 14 Nov 2018 16:03:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0C71A2AE21 for ; Wed, 14 Nov 2018 16:03:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387822AbeKOCHa (ORCPT ); Wed, 14 Nov 2018 21:07:30 -0500 Received: from mail-pl1-f196.google.com ([209.85.214.196]:36567 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387818AbeKOCHa (ORCPT ); Wed, 14 Nov 2018 21:07:30 -0500 Received: by mail-pl1-f196.google.com with SMTP id y6-v6so425256plt.3 for ; Wed, 14 Nov 2018 08:03:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=g.ncu.edu.tw; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=kzJ7XC6wtdrDpUUWZKeXw5i7kpwhAlXC/BrXonSslMQ=; b=bodb2KbqrSNPMZTFQ1cIqCB1pocQ000yBssTgUUld+aHd5DDtpksnDbCSeQ3NUt2XJ ZD4YLoGZfJhSn8DGaCxKhzGc3cJVFNpp7bhzfzyFql+n2d3Xb0uhw1oQQWMOahXFVFtL qv3oA1zZvtHy6uum+cwQI6PDope29msMMN6hs= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=kzJ7XC6wtdrDpUUWZKeXw5i7kpwhAlXC/BrXonSslMQ=; b=V/dxGt18FYnjVK+pkHDaH/OpORCGC3l+Ax8IOxJrtEI3ZS06hYBpvW5IaY0yYnqILO PVQWCkrDV5QXpoIQ9YyOu+3+MpdxGmMijBPB27EmauZUPY6RT+884UjPWc5hLjx9S3q1 vS0wYNmrN6NMBJ4XncR1KEvlPY/JYGH4gRrrxEdbw9mDnB4yVkTEHAKvJFXOVzRSwuoW wc/SPzlAIO6/bqcSla/2Vak+rWY98xkVWuBhmCdTdOnzoeJd+kqq8Gq7lyym+yx7oW3S xQqQmAKcUfGqZ/R8HC/dDegyt001z6Dd1clglaL67i9iSqMH4FW/HKASXwUlTHBAx7wC mlfA== X-Gm-Message-State: AGRZ1gIdqgigCqy28rAWrNubNRqhbBYDCgSXurLSgD9CsRZ1oCESgbfi rpoBTu7uaBf2hBAwLXKEVEZxJw== X-Google-Smtp-Source: AJdET5cBQTGNChAKvN6+sE3sRq7hspEbYH/BRWWQx02bU7MYpx7drFCKNcTCoVhol101s3LBI+QtUA== X-Received: by 2002:a17:902:8210:: with SMTP id x16-v6mr2497666pln.129.1542211420218; Wed, 14 Nov 2018 08:03:40 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id s2-v6sm53449854pfk.133.2018.11.14.08.03.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 14 Nov 2018 08:03:39 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= , "David S . Miller" Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V3 7/7] net: lorawan: List LORAWAN in menuconfig Date: Thu, 15 Nov 2018 00:01:28 +0800 Message-Id: <20181114160126.4445-8-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181105.101610.1437737564548154497.davem@davemloft.net> References: <20181105.101610.1437737564548154497.davem@davemloft.net> MIME-Version: 1.0 Sender: linux-wpan-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wpan@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP List LORAWAN and MACLORAWAN in menuconfig and make they can be built. Signed-off-by: Jian-Hong Pan --- V2: - Split the LoRaWAN class module patch in V1 into LoRaWAN socket and LoRaWAN Soft MAC modules net/Kconfig | 2 ++ net/Makefile | 2 ++ 2 files changed, 4 insertions(+) diff --git a/net/Kconfig b/net/Kconfig index 053b36998c18..b12b8bed6abb 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -224,6 +224,8 @@ source "net/6lowpan/Kconfig" source "net/ieee802154/Kconfig" source "net/mac802154/Kconfig" source "net/lora/Kconfig" +source "net/lorawan/Kconfig" +source "net/maclorawan/Kconfig" source "net/sched/Kconfig" source "net/dcb/Kconfig" source "net/dns_resolver/Kconfig" diff --git a/net/Makefile b/net/Makefile index e80b84313851..9d5515965a8f 100644 --- a/net/Makefile +++ b/net/Makefile @@ -63,6 +63,8 @@ obj-$(CONFIG_6LOWPAN) += 6lowpan/ obj-$(CONFIG_IEEE802154) += ieee802154/ obj-$(CONFIG_MAC802154) += mac802154/ obj-$(CONFIG_LORA) += lora/ +obj-$(CONFIG_LORAWAN) += lorawan/ +obj-$(CONFIG_MACLORAWAN) += maclorawan/ ifeq ($(CONFIG_NET),y) obj-$(CONFIG_SYSCTL) += sysctl_net.o