From dd52f5fedde3c1c315d1795acf64f05c9a51c1c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20H=C3=BC=C3=9Fler?= Date: Tue, 14 Mar 2023 10:30:15 +0100 Subject: [PATCH] sys/net: add l2scan list module --- sys/Makefile | 3 + sys/include/net/l2scan_list.h | 73 ++++++++++++++++ sys/net/link_layer/l2scan_list/Kconfig | 9 ++ sys/net/link_layer/l2scan_list/Makefile | 1 + sys/net/link_layer/l2scan_list/l2scan_list.c | 90 ++++++++++++++++++++ 5 files changed, 176 insertions(+) create mode 100644 sys/include/net/l2scan_list.h create mode 100644 sys/net/link_layer/l2scan_list/Kconfig create mode 100644 sys/net/link_layer/l2scan_list/Makefile create mode 100644 sys/net/link_layer/l2scan_list/l2scan_list.c diff --git a/sys/Makefile b/sys/Makefile index b7724719a7..de159e8680 100644 --- a/sys/Makefile +++ b/sys/Makefile @@ -101,6 +101,9 @@ endif ifneq (,$(filter l2filter,$(USEMODULE))) DIRS += net/link_layer/l2filter endif +ifneq (,$(filter l2scan_list,$(USEMODULE))) + DIRS += net/link_layer/l2scan_list +endif ifneq (,$(filter l2util,$(USEMODULE))) DIRS += net/link_layer/l2util endif diff --git a/sys/include/net/l2scan_list.h b/sys/include/net/l2scan_list.h new file mode 100644 index 0000000000..fde5a445d0 --- /dev/null +++ b/sys/include/net/l2scan_list.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2023 ML!PA Consulting Gmbh + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup net_l2scanlist Scan List - List of wireless access points + * @ingroup net + * @brief Internal list data structure of scanned access points + * @ref NETOPT_SCAN + * @{ + * + * @file + * @brief L2 Scan list API + * + * @author Fabian Hüßler + */ + +#ifndef NET_L2SCAN_LIST_H +#define NET_L2SCAN_LIST_H + +#include + +#include "list.h" +#include "net/netopt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Type of a Link Layer scan list + */ +typedef struct l2scan_list { + list_node_t *head; /**< Pointer to the list head node */ + /* items */ +} l2scan_list_t; + +/** + * @brief Empty the list to start a new scan + * + * @param[in, out] list Pointer to list + * @param[in, out] nodes Pointer to nodes array + * @param[in] nodes_numof Number of nodes in the array + * @param[in] node_size Size of one node element in the array + */ +void l2scan_list_empty(l2scan_list_t *list, + list_node_t *nodes, unsigned nodes_numof, + size_t node_size); + +/** + * @brief Insert a new scan result into the list + * + * @param[in, out] list Pointer to list + * @param[in, out] nodes Pointer to nodes array + * @param[in] nodes_numof Number of nodes in the array + * @param[in] node_size Size of one node element in the array + * @param[in] result New result to insert + */ +void l2scan_list_insert(l2scan_list_t *list, + list_node_t *nodes, unsigned nodes_numof, + size_t node_size, + const netopt_scan_result_t *result); + +#ifdef __cplusplus +} +#endif + +#endif /* NET_L2SCAN_LIST_H */ +/** @} */ diff --git a/sys/net/link_layer/l2scan_list/Kconfig b/sys/net/link_layer/l2scan_list/Kconfig new file mode 100644 index 0000000000..accb7e2595 --- /dev/null +++ b/sys/net/link_layer/l2scan_list/Kconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2023 ML!PA Consulting Gmbh +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. +# + +config MODULE_L2SCAN_LIST + bool "List of scanned Link Layer access points" diff --git a/sys/net/link_layer/l2scan_list/Makefile b/sys/net/link_layer/l2scan_list/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/sys/net/link_layer/l2scan_list/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/sys/net/link_layer/l2scan_list/l2scan_list.c b/sys/net/link_layer/l2scan_list/l2scan_list.c new file mode 100644 index 0000000000..7322a404b0 --- /dev/null +++ b/sys/net/link_layer/l2scan_list/l2scan_list.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2023 ML!PA Consulting Gmbh + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup net_l2scan_list + * @{ + * + * @file + * @brief List to store the result of a network scan + * + * @author Fabian Hüßler + * + * @} + */ + +#include + +#include "list.h" +#include "net/netopt.h" +#include "net/l2scan_list.h" + +#define SCAN_LIST_NODE_AT(array, pos, size) ((void *)(((uint8_t *)(array)) + ((pos) * (size)))) + +/** + * @brief Basic type of a scan result in a list + */ +typedef struct scan_list_node { + list_node_t node; /* Basic node */ + netopt_scan_result_t result; /* Basic scan result */ +} scan_list_node_t; + +static scan_list_node_t *_scan_list_get_insert(l2scan_list_t *list, + list_node_t *array, unsigned array_numof, + size_t item_size) +{ + scan_list_node_t *lowest = (scan_list_node_t *)array; + for (unsigned i = 0; i < array_numof; i++) { + /* look for free slot or lowest element */ + scan_list_node_t *result = SCAN_LIST_NODE_AT(array, i, item_size); + if (!result->result.strength) { + return result; /* free slot */ + } + if (result->result.strength < lowest->result.strength) { + lowest = result; /* override lowest element */ + } + } + list_node_t l = { .next = list->head }; + list_remove(&l, &lowest->node); + return lowest; +} + +void l2scan_list_empty(l2scan_list_t *list, + list_node_t *nodes, unsigned nodes_numof, + size_t node_size) +{ + list->head = NULL; + memset(nodes, 0, nodes_numof * node_size); +} + +void l2scan_list_insert(l2scan_list_t *list, + list_node_t *nodes, unsigned nodes_numof, + size_t node_size, + const netopt_scan_result_t *result) +{ + scan_list_node_t *insert = _scan_list_get_insert(list, nodes, + nodes_numof, node_size); + *insert = (scan_list_node_t) { .node = { .next = NULL }, }; + memcpy(&insert->result, result, node_size - sizeof(list_node_t)); + + if (!list->head) { + list->head = &insert->node; + } + else if (((scan_list_node_t *)list->head)->result.strength < result->strength) { + insert->node.next = list->head; + list->head = &insert->node; + } + else { + scan_list_node_t *next, *before = (scan_list_node_t *)list->head; + while ((next = (scan_list_node_t *)before->node.next) && + next->result.strength > result->strength) { + before = (scan_list_node_t *)before->node.next; + } + list_add(&before->node, &insert->node); + } +}