From patchwork Mon Nov 5 16:55:39 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: 10668679 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 89C9714E2 for ; Mon, 5 Nov 2018 16:57:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 753C728A75 for ; Mon, 5 Nov 2018 16:57:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 654F529463; Mon, 5 Nov 2018 16:57:21 +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 D797828A75 for ; Mon, 5 Nov 2018 16:57:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387771AbeKFCRx (ORCPT ); Mon, 5 Nov 2018 21:17:53 -0500 Received: from mail-pg1-f194.google.com ([209.85.215.194]:35591 "EHLO mail-pg1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387774AbeKFCRx (ORCPT ); Mon, 5 Nov 2018 21:17:53 -0500 Received: by mail-pg1-f194.google.com with SMTP id 32-v6so4499210pgu.2 for ; Mon, 05 Nov 2018 08:57:18 -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=TcjhjxRcuEq6Vagp7zxH0a5k8JsQ9nZ/TxE6xCSuA2pD4VNKA73FE1ig91RIakiDnB LTtmmX3MCusBf07i5uURvBBpLKruv6p0yNCZgk4ESJ5uioFuYIvPB3nvAjRT6Z6j1UY+ 2D9nJ0BNUAhY72/eN0GyTCdsxnElm1lg4CmRw= 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=Z0KTKtk+HtdW7ujXAE2oduYZls7xkFHoCYmjTHIWkayByhS2s+8dCOaWaKlYgfA8l9 q3sjUE6d5bKGokiSO5wdH3agVAJiUZ9X2GnbA75DxwPIC4ab7J0dU4olLbcnUVFc3XXx TrQmjMAadzPSfaWW6fXgcRC2Cvx6kBmRd7UusVZNbi9mYkfhA173QvO3ay2ggAyGGMQh KPIvtKJi7r50/UdhKnCsh23XeT6JE181Z3TVtfgUO4i8ViiAJkseifxTdTRdRCobRPX7 z1WibYYYJeB1ILA1lRzgEK3zz7hO20LkG9sWa5SHw5pyxN3dP0gyLw/5v9yJGEy8O1tF JW3Q== X-Gm-Message-State: AGRZ1gJnlHzaI0uWwohCY7IIQmltwZ/SBQIdDvjQwDVCgo1uXXJ9Kkxm Ka4QQd8AsrnUW7REIOP9cMBCdQ== X-Google-Smtp-Source: AJdET5c3ALSI96HyPMBiNvub2H1725a1jDr4LaKadNQhD3LsqdDE7bYHXltbOoaZphIeURSOf8Hk3A== X-Received: by 2002:aa7:8252:: with SMTP id e18-v6mr23053099pfn.164.1541437038423; Mon, 05 Nov 2018 08:57:18 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id l16-v6sm58445129pfj.179.2018.11.05.08.57.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Nov 2018 08:57:17 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , "David S . Miller" , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V2 1/7] net: lorawan: Add macro and definition for LoRaWAN Date: Tue, 6 Nov 2018 00:55:39 +0800 Message-Id: <20181105165544.5215-2-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: References: 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 Mon Nov 5 16:55:40 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: 10668719 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 E5C9514BD for ; Mon, 5 Nov 2018 16:58:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D080D29B9F for ; Mon, 5 Nov 2018 16:58:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C43BD29B8D; Mon, 5 Nov 2018 16:58:59 +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=unavailable 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 A41EE29B8D for ; Mon, 5 Nov 2018 16:58:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387515AbeKFCSH (ORCPT ); Mon, 5 Nov 2018 21:18:07 -0500 Received: from mail-pl1-f195.google.com ([209.85.214.195]:33848 "EHLO mail-pl1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387810AbeKFCSH (ORCPT ); Mon, 5 Nov 2018 21:18:07 -0500 Received: by mail-pl1-f195.google.com with SMTP id f12-v6so3556881plo.1 for ; Mon, 05 Nov 2018 08:57:32 -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=OywV690BuOb+YRKrey/PZlE9zCGEwyFDXgT0ImO6Zvk=; b=Eucz5uQ7hDE372GRB2SmtPSA1bwkyW1PIP8CSfK+TSsSuG/CTl4yKnlYk2CMrxDvUX RtDIyip0/giP0PHqbj0Sj3V+L+JEZRBq5UTquNKq4fzedHvIBf0cx8KDbL+0dRQtLVMa yT6ThnvIVd39Poh69YXC2IYp1bWup6Z6DfDPc= 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=OywV690BuOb+YRKrey/PZlE9zCGEwyFDXgT0ImO6Zvk=; b=L/xEk/MSFqGHHoJCDHJXqjHR1b2MpwbszKxDPjIVyUbXnJppDniJXmYLJ64DmE9DKX xTOdD1Hmztvt4+MtozCHrv/u9wpApTZK/stDtYXJhZ7I8ikU2YHqx0LTOcpj6q2qr5G/ Mfo2pLUu2rmlWAWg1YJ7XaTQ7oK67QaKQHZB8REoystLJXqDy08oarozYY9/O+FHVxCX dfDQBG0EzoXeOpqgoezOBQ5R5aidXMOeFzyLtgBS0d+yoZvUCXD9cAljX5QrvjCX1NnS 716LmQdybO5WH4cMym4r2xcLLsn0pFC16WFqkC/XEPD7KC+VJoZbmRloKJTcu9/qyItl 52Lg== X-Gm-Message-State: AGRZ1gJZ9FVJX6ge0E8TpgjGd75ATpo/uj7kv4mkhDAkSG4XLIv+SgUw 4Y1UmNLIqRaq/JG4spYVEPv4xg== X-Google-Smtp-Source: AJdET5eL8xlJCf86tZ1Y/nNnCdh4QZOF3uxS1wMUwtC8sn5x0VGtSJUhTVxQqHvvV9W2BTSIZrOlLw== X-Received: by 2002:a17:902:2d81:: with SMTP id p1-v6mr18752414plb.97.1541437052172; Mon, 05 Nov 2018 08:57:32 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id l16-v6sm58445129pfj.179.2018.11.05.08.57.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Nov 2018 08:57:31 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , "David S . Miller" , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V2 2/7] net: lorawan: Add LoRaWAN socket module Date: Tue, 6 Nov 2018 00:55:40 +0800 Message-Id: <20181105165544.5215-3-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: References: 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 include/linux/lora/lorawan_netdev.h | 52 +++ net/lorawan/Kconfig | 10 + net/lorawan/Makefile | 2 + net/lorawan/socket.c | 681 ++++++++++++++++++++++++++++ 4 files changed, 745 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..4adf93fd06c5 --- /dev/null +++ b/include/linux/lora/lorawan_netdev.h @@ -0,0 +1,52 @@ +/* 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; +}; + +/** + * 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 + */ +static inline struct lrw_mac_cb * mac_cb(struct sk_buff *skb) +{ + return (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..0c03f7a0fb0e --- /dev/null +++ b/net/lorawan/socket.c @@ -0,0 +1,681 @@ +/* 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 inline struct dgram_sock * +dgram_sk(const struct sock *sk) +{ + return container_of(sk, struct dgram_sock, sk); +} + +static inline struct net_device * +lrw_get_dev_by_addr(struct net *net, u32 devaddr) +{ + struct net_device *ndev = NULL; + __be32 be_addr = cpu_to_be32(devaddr); + + 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 inline 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) +{ + struct sk_buff *skb; + size_t copied = 0; + DECLARE_SOCKADDR(struct sockaddr_lorawan *, saddr, msg->msg_name); + 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 = 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 sk_buff *skb; + int amount; + int err; + struct net_device *ndev = sk->sk_dst_cache->dev; + + 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 = 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 sock *sk = sock->sk; + struct sockaddr_lorawan *addr = (struct sockaddr_lorawan *)uaddr; + + 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 ifreq ifr; + int ret = -ENOIOCTLCMD; + struct net_device *ndev; + + lrw_dbg("%s: cmd %ud\n", __func__, cmd); + 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 inline int +lrw_dgram_deliver(struct net_device *ndev, struct sk_buff *skb) +{ + struct sock *sk; + struct dgram_sock *ro; + bool found = false; + int ret = NET_RX_SUCCESS; + + 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 Mon Nov 5 16:55:41 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: 10668691 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 6110314BD for ; Mon, 5 Nov 2018 16:57:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4F1C128A75 for ; Mon, 5 Nov 2018 16:57:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 42EBB29463; Mon, 5 Nov 2018 16:57:43 +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 C6C8C28A75 for ; Mon, 5 Nov 2018 16:57:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387773AbeKFCSN (ORCPT ); Mon, 5 Nov 2018 21:18:13 -0500 Received: from mail-pg1-f196.google.com ([209.85.215.196]:40968 "EHLO mail-pg1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387530AbeKFCSM (ORCPT ); Mon, 5 Nov 2018 21:18:12 -0500 Received: by mail-pg1-f196.google.com with SMTP id k13so4486649pga.8 for ; Mon, 05 Nov 2018 08:57:38 -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=TAwtNH3X/PuUVOl9EdiLivVR3IjM86vXPbiBNqHFfzM=; b=ZZQQRuhAwAq/imjo3FcU7XUqWro2njmoEZ/kcB4d9fEi6zqRj0Pkl1wb8dttMXaGWm c73xF/KVsa3rZjKp52bQ9mDm5AjAiX49v5bCBRd+P0fOLkaY9qJzHz+B+uVDke1nH8N+ 3MnUqPvD2t99TEXF4T0zHgq7ObF51KgUxmfGo= 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=TAwtNH3X/PuUVOl9EdiLivVR3IjM86vXPbiBNqHFfzM=; b=DMnZOX6h/PD4v6bWrSAjBbE0bK9fSwW6girFELfkMhVjw5gUNDL/aCQVIFir+yFTyo zbi6Ny7VxALnh1JjEv79wpR2jTjBAM31i2hgEhXaTTV2vzWwWYSNhChpt07mCnPgti5B Js5DLlOVHsYmcWY9o3lUdH/+xiNQdCZYYZHOppqHgLT6OsrzpQSqE9Sk6fvtVExxumIL e9X8P89Ani3hEVSnCuG0rlje8c9o9zDYcxWv3Fdmf9TzQcTO+5SQREkQIEtaj+zHCCpn O/y643DtpxwvHtRWKOg5jVIGwrP9A3OMSsouqqXg8HkhFJudRKoinnHoFUX+VBqAAEdb bhVg== X-Gm-Message-State: AGRZ1gJOjL0HbYw/ZfR5Xi5ET0XUKd5IfJkX74u/ZWpcxy1ktMWMo/Ku B033qKlON8xoyyxHP80IZ/ZTzA== X-Google-Smtp-Source: AJdET5fV6tN2RpAbt8i6WKymm9On/enCD/7rUp8eAYnv0I4Msg4UHWUEQxMJOXWH5TtKVEs5XVLjHw== X-Received: by 2002:a62:6a88:: with SMTP id f130-v6mr7493767pfc.98.1541437057744; Mon, 05 Nov 2018 08:57:37 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id l16-v6sm58445129pfj.179.2018.11.05.08.57.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Nov 2018 08:57:37 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , "David S . Miller" , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V2 3/7] net: lorawan: Add LoRaWAN API declaration for LoRa devices Date: Tue, 6 Nov 2018 00:55:41 +0800 Message-Id: <20181105165544.5215-4-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: References: 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 include/linux/lora/lorawan.h | 137 +++++++++++++++++++++++++++++++++++ 1 file changed, 137 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..684c9e2eb018 --- /dev/null +++ b/include/linux/lora/lorawan.h @@ -0,0 +1,137 @@ +/* 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 +#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 *); + +static inline void lrw_random_addr(u64 *addr) +{ + get_random_bytes(addr, sizeof(u64)); +} + +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 Mon Nov 5 16:55:42 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: 10668693 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 EBBDB175A for ; Mon, 5 Nov 2018 16:57:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D9CDA28A75 for ; Mon, 5 Nov 2018 16:57:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CE1AC2946D; Mon, 5 Nov 2018 16:57:48 +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 DB3A728A75 for ; Mon, 5 Nov 2018 16:57:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387852AbeKFCSR (ORCPT ); Mon, 5 Nov 2018 21:18:17 -0500 Received: from mail-pl1-f193.google.com ([209.85.214.193]:33862 "EHLO mail-pl1-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387854AbeKFCSQ (ORCPT ); Mon, 5 Nov 2018 21:18:16 -0500 Received: by mail-pl1-f193.google.com with SMTP id f12-v6so3557069plo.1 for ; Mon, 05 Nov 2018 08:57:42 -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=M224mRVqO1uf/shjgk21pma7NRKvPKLnKlG6kLCbxzr1RYmugjCaNOOvQIfNpxMCww iO2GtnZmDPr96WYdObZCnxf5FL+zmtnrOwrAOdZRfmMqN7RVT3EuFX7fwb5uIbJaFk6Z ryTSMaLNRNSsNB8tVLbC+RT1PRBU3wOYTvZGA= 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=NmaPwj90/LwB3zVq+qua5OM7s5ACs7PcQ6vwzkhmcyy4FHpZPbEv8ePp3mp71NWdhN fUBAo9+wmpaLOZ7qDs4RjquMGmvrOFhmX2jwks1DsFsL98v9lMzqf3+cwf16oVBo+YS/ g1QJaJ+ygjsbx0OEJNZzoo1vmzdEpxmygjGXLzBcoJAiyqJs9FQcxK3Fhqok5JTAA4iv gUcSX5Gc7gzXVdp6sPyy8oCcyDHs2HWGJ5XQ9UkyXKiYSj9RfW3IIIZ73ONarL6XFQxv hptgwt/qXtT5+kcvKICh2/eYdm6/A3rjwqCEGDvJf2OC9B6hYPkgwQBe03l63CBppR96 ICmw== X-Gm-Message-State: AGRZ1gKUTe7c0kKNdI8Ht5wonqlkyXnYqTltCIiBSOMcU7Xyjd8n9vfc 16ucYKWqlIzfgTfoLF+PVSNJaA== X-Google-Smtp-Source: AJdET5cJdLi+SiGoOgqJdlP4ULccI+GrmaioFaUAykQizgykx82w8gME2JgZ8OHIfE3+KXU85NBpLw== X-Received: by 2002:a17:902:703:: with SMTP id 3-v6mr22966730pli.38.1541437061798; Mon, 05 Nov 2018 08:57:41 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id l16-v6sm58445129pfj.179.2018.11.05.08.57.39 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Nov 2018 08:57:41 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , "David S . Miller" , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V2 4/7] net: maclorawan: Add maclorawan module declaration Date: Tue, 6 Nov 2018 00:55:42 +0800 Message-Id: <20181105165544.5215-5-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: References: 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 Mon Nov 5 16:55:43 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: 10668695 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 639F314E2 for ; Mon, 5 Nov 2018 16:57:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5202C28A75 for ; Mon, 5 Nov 2018 16:57:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 45E9529463; Mon, 5 Nov 2018 16:57:49 +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 A526B293D9 for ; Mon, 5 Nov 2018 16:57:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387873AbeKFCSV (ORCPT ); Mon, 5 Nov 2018 21:18:21 -0500 Received: from mail-pf1-f194.google.com ([209.85.210.194]:44193 "EHLO mail-pf1-f194.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387872AbeKFCSU (ORCPT ); Mon, 5 Nov 2018 21:18:20 -0500 Received: by mail-pf1-f194.google.com with SMTP id j13-v6so4699279pff.11 for ; Mon, 05 Nov 2018 08:57:45 -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=7DP8u6/v9c8feRMreql7UvqsPhDnurFdaDHiNdwdKJQ=; b=I1swyP6Or9ilFd8+86vx+yY1OFKu0OPAas/aGPON1zwAzJYdZb3AuOWQ/S+AuWEq19 1J3YRb0qtnhSxwSag2ntGWMd9i7X7RgbRWAcfMJPF9yB0zv0Xin/ROvfFmrZ5sNPQNq9 nRUy9adn4j8+ThBVBS5vGW7dozzEk/06CVw84= 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=7DP8u6/v9c8feRMreql7UvqsPhDnurFdaDHiNdwdKJQ=; b=o9UZE/+KAGYN/GQR6AbiRFlRRi65d0M2WOKN/HSkF30YjKAlcSDmF+Xvp8PZ6gHQJR kZshw1qXgkzE/1t9EP9/Wnd8pv2d/J+uFXmPoWoR8B6JnPeUWMHTHUn7oSmUzg14LuQH crQ9xEQXCbtaoyZPAYaG0Rz2yJ4S2c2Y+7Gn0Hnup2jg88NX7eVemWvzXuewFwnQ/KdW V9U/0HDwtHT3Mqqd0Zb+OfMoSuH1w5UtwkvXgIi2MEE9Rl4rAOGnqvGldSyMhUUj+cQz Q8ddAjma7Lm4x5DsYQNmF4WVvrX9ekdHcYlPyQdF3X40Jl/7g7xabW271W2bAjPu09/Q 23dA== X-Gm-Message-State: AGRZ1gLPOSlWB9MAFfzl3lu2l/JsTyLMzMLoGoJXoVZUwvcPnnl9aP1m I4tHSlzBgn8Orgne25udfpULrw== X-Google-Smtp-Source: AJdET5cpooibiASTqiFgMZGeAyGHQnPJt//x/0E8sZCIXqZTAIcciMths+2OirYnWHK96zjy5DgQ5g== X-Received: by 2002:a63:c0f:: with SMTP id b15mr20975118pgl.314.1541437065297; Mon, 05 Nov 2018 08:57:45 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id l16-v6sm58445129pfj.179.2018.11.05.08.57.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Nov 2018 08:57:44 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , "David S . Miller" , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V2 5/7] net: maclorawan: Implement the crypto of maclorawan module Date: Tue, 6 Nov 2018 00:55:43 +0800 Message-Id: <20181105165544.5215-6-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: References: 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 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..a839fd074ad8 --- /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) +{ + char *algo = "cmac(aes)"; + struct crypto_shash *tfm; + 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 _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, &_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) +{ + u8 iv[16]; + struct scatterlist src, dst; + SKCIPHER_REQUEST_ON_STACK(req, tfm); + 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 Mon Nov 5 16:55:44 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: 10668697 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 6B5EC14BD for ; Mon, 5 Nov 2018 16:57:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 57174293D9 for ; Mon, 5 Nov 2018 16:57:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 493D9295E8; Mon, 5 Nov 2018 16:57:54 +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 63D45293D9 for ; Mon, 5 Nov 2018 16:57:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387904AbeKFCSY (ORCPT ); Mon, 5 Nov 2018 21:18:24 -0500 Received: from mail-pl1-f195.google.com ([209.85.214.195]:41047 "EHLO mail-pl1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387872AbeKFCSY (ORCPT ); Mon, 5 Nov 2018 21:18:24 -0500 Received: by mail-pl1-f195.google.com with SMTP id p16-v6so4737798plr.8 for ; Mon, 05 Nov 2018 08:57:49 -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=dhMlKJwcmF5zffOMMaBtnvS7rH9dnos0a1QbbzuUklI=; b=OcQ1lm/Tpj70lJll+1ot3KaEENvfg8td0MazP8U6SMk6NalN/8zxT51IB/cPRbXUYu sdFXt/h8M94DVB/Ch6Phdj6Yt80gAmrXDmWdYdREIRkd1uQKVrjxLCNmjV2k2WNNCHn5 szXru2/r3fgDabrJdkeMTo8pza3H8G4Q6nZLM= 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=dhMlKJwcmF5zffOMMaBtnvS7rH9dnos0a1QbbzuUklI=; b=ohXydiYpHNTraISMQZGQwDuXgR2z4ILb7hsdJh/Q7/MjpzFN8BlQzx8bhoW2WPpzRx WnD0uhaCaePv3WnerTarHaFp/sAqQsewGm4zBvqvzSWDu4JUDpXxzxF1CdBMmWVypFBf z0o/M5mqnYvuIyb0V2E3KaMcWqqim3yLJ5yJUyIzhSQMdcLN+aLFdxd2JAwfw0dX/tnI xo8sXoAbf8Df9/NfKNp8wt8BlVhiGdgEOFmiWF4KYw1rVncUAp4xGf49ZZEEUjacWgc6 yJrIvflwQ1ihRgO4oJC0hJpPOlhIGt636Szrij6ZpL4yL6xPig6w1kLu3zbxd+X78avT XMiw== X-Gm-Message-State: AGRZ1gL75NhbqMDzCy0J/3yspY9jkFsSnsGsB6OQK7donA3AFneFC/jY KxLQn+cc7lC9mQ01IxaaeEzRuA== X-Google-Smtp-Source: AJdET5fxae6azZyL+2HPqbdo0Jhg/At0FrYW0LvzmYvyjM2KMEQpJ+hqis+B9StMZ5AgFsw+hdM2gw== X-Received: by 2002:a17:902:5a09:: with SMTP id q9-v6mr23040032pli.186.1541437068785; Mon, 05 Nov 2018 08:57:48 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id l16-v6sm58445129pfj.179.2018.11.05.08.57.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Nov 2018 08:57:48 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , "David S . Miller" , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V2 6/7] net: maclorawan: Implement maclorawan class module Date: Tue, 6 Nov 2018 00:55:44 +0800 Message-Id: <20181105165544.5215-7-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: References: 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 net/maclorawan/Kconfig | 14 + net/maclorawan/Makefile | 2 + net/maclorawan/mac.c | 522 ++++++++++++++++++++++++++++++++++ net/maclorawan/main.c | 600 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1138 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..343fe729a883 --- /dev/null +++ b/net/maclorawan/mac.c @@ -0,0 +1,522 @@ +/* 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; + __le32 le_devaddr = cpu_to_le32(ss->devaddr); + u8 mhdr, fctrl, fport; + u8 mic[4]; + + netdev_dbg(lrw_st->ndev, "%s\n", __func__); + + mhdr = LRW_UNCONFIRMED_DATA_UP << 5; + if ((mhdr & (0x6 << 5)) == (0x4 << 5)) + ss->tx_should_ack = true; + + fctrl = 0; + if (lrw_st->rx_should_ack) { + fctrl |= 0x20; + lrw_st->rx_should_ack = false; + } + + /* 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 */ + memcpy(skb_push(skb, 2), &ss->fcnt_up, 2); + + /* Push FCtrl */ + memcpy(skb_push(skb, 1), &fctrl, 1); + + /* Push DevAddr */ + memcpy(skb_push(skb, LRW_DEVADDR_LEN), &le_devaddr, LRW_DEVADDR_LEN); + + /* Push MHDR */ + 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; + u16 fcnt; + __le16 *p_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); + + 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) +{ + u8 *buf; + size_t len; + u32 devaddr; + u16 fcnt; + __le16 *p_fcnt; + u8 cks[4]; + u8 *mic; + + buf = skb->data; + len = skb->len - 4; + devaddr = le32_to_cpu(*((__le32 *)(buf + 1))); + p_fcnt = (__le16 *)(buf + 6); + fcnt = le16_to_cpu(*p_fcnt); + 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); + u8 mtype; + u32 devaddr; + + 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_session *ss; + struct lrw_struct *lrw_st; + + 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..002781295369 --- /dev/null +++ b/net/maclorawan/main.c @@ -0,0 +1,600 @@ +/* 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 net_device *ndev; + struct lrw_struct *lrw_st; + 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 + */ +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 + */ +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) +{ + bool status = false; + struct lrw_session *ss; + + 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; +} + +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 = 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; +} + +inline 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; +} + +inline 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; +} + +inline 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 = (__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); + +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); + + pr_info("%s: unregister %s\n", + LORAWAN_MODULE_NAME, dev_name(&lrw_st->dev)); + + /* 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 Mon Nov 5 16:55:45 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: 10668699 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 0A19514E2 for ; Mon, 5 Nov 2018 16:57:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EB0EC29536 for ; Mon, 5 Nov 2018 16:57:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DBEF628A75; Mon, 5 Nov 2018 16:57:54 +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 898F4293D9 for ; Mon, 5 Nov 2018 16:57:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387924AbeKFCS1 (ORCPT ); Mon, 5 Nov 2018 21:18:27 -0500 Received: from mail-pl1-f196.google.com ([209.85.214.196]:39976 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387922AbeKFCS1 (ORCPT ); Mon, 5 Nov 2018 21:18:27 -0500 Received: by mail-pl1-f196.google.com with SMTP id q19-v6so1744644pll.7 for ; Mon, 05 Nov 2018 08:57:52 -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=mSxcJ+NqUwwsDva2pIi4AZ2HPVWuV9mkjnC/RXmq2wk=; b=JYEIx2Q7cXi2hk0D/Ee6F/5wwEzR94WovjwJaIwXSIlY57n1HcB8qp8WmyKRF4KmPZ JZGWaJrIzkc3qmAc9Qx2HoF8ewtf0gkLH/A5qBjs/8TFwA0gR/kdzl2po8vLba6PR03t G8m95rCtmrz8/rhpI3bCqTHCWheOyNbFlHOeE= 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=mSxcJ+NqUwwsDva2pIi4AZ2HPVWuV9mkjnC/RXmq2wk=; b=CAPCPfaYzIpikaSPkEqankyyG3BykL+Qn5XYV2CGrVXnkN4mvW/bCzph29tP7ym7sS XCLkpwCJgroMvxer4/fkYevXuRS+p7ApinBEBbGBBqTzmVYrJTzgKLHR7ePRzkBUyHz0 oTpATqed4JL0ix21Po0mH5xI2PNgn6Bjm2os/eQ6lCUdVelmY9ynVuJqj5Q0Y2RaYPoR lmo6cYPsoX8HD6fO1n6fAXbXwWNY5NPADQJVaa3kU19sG+BBLDEvC0HU+xDeSxbYx2E2 j5R17NMcDgprbjvtmB5fGb/gpJtek01oJWWtfuZ28eymrkI9o+Wbqp6qvmIOe8FGOBep 75+A== X-Gm-Message-State: AGRZ1gIm2S35sCnRQcpc5wlhBVWqrWuW9yphOguq50EXCq5qK2vVSKz8 y8hCVwhB6LkNSvtJRReRdXDvPg== X-Google-Smtp-Source: AJdET5dzRpilVyXatJ8OXLK+w7bWGn37bT6HDjck+62jGvSCQMz4pJZ+eSimiAkTuDfJKWgAbIYjSw== X-Received: by 2002:a17:902:a418:: with SMTP id p24-v6mr22029953plq.29.1541437072012; Mon, 05 Nov 2018 08:57:52 -0800 (PST) Received: from starnight.local ([150.116.248.145]) by smtp.gmail.com with ESMTPSA id l16-v6sm58445129pfj.179.2018.11.05.08.57.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 05 Nov 2018 08:57:51 -0800 (PST) From: Jian-Hong Pan To: =?utf-8?q?Andreas_F=C3=A4rber?= Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Marcel Holtmann , "David S . Miller" , Dollar Chen , Ken Yu , linux-wpan@vger.kernel.org, Stefan Schmidt , Jian-Hong Pan Subject: [PATCH V2 7/7] net: lorawan: List LORAWAN in menuconfig Date: Tue, 6 Nov 2018 00:55:45 +0800 Message-Id: <20181105165544.5215-8-starnight@g.ncu.edu.tw> X-Mailer: git-send-email 2.19.1 In-Reply-To: References: 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 enable them to 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