diff --git a/makefiles/pseudomodules.inc.mk b/makefiles/pseudomodules.inc.mk index 0960db51d4..77cd399323 100644 --- a/makefiles/pseudomodules.inc.mk +++ b/makefiles/pseudomodules.inc.mk @@ -122,6 +122,7 @@ PSEUDOMODULES += slipdev_stdio PSEUDOMODULES += sock PSEUDOMODULES += sock_async PSEUDOMODULES += sock_aux_local +PSEUDOMODULES += sock_aux_rssi PSEUDOMODULES += sock_aux_timestamp PSEUDOMODULES += sock_dtls PSEUDOMODULES += sock_ip diff --git a/sys/include/net/sock.h b/sys/include/net/sock.h index 451bf26e2e..6fb24f227b 100644 --- a/sys/include/net/sock.h +++ b/sys/include/net/sock.h @@ -286,6 +286,22 @@ enum { * @ref sock_ip_aux_tx_t::timestamp, or @ref sock_dtls_aux_tx_t::timestamp. */ SOCK_AUX_GET_TIMESTAMP = (1LU << 1), + /** + * @brief Flag to request the RSSI value of received frame + * + * @note Select module `sock_aux_rssi` and a compatible network stack to + * use this + * + * Set this flag in the auxiliary data structure prior to the call of + * @ref sock_udp_recv_aux / @ref sock_ip_recv_aux / etc. to request the + * RSSI value of a received frame. This flag will be cleared if the + * timestamp was stored, otherwise it remains set. + * + * Depending on the family of the socket, the RSSI value will be stored in + * @ref sock_udp_aux_rx_t::rssi, @ref sock_ip_aux_rx_t::rssi, or + * @ref sock_dtls_aux_rx_t::rssi. + */ + SOCK_AUX_GET_RSSI = (1LU << 2), }; /** diff --git a/sys/include/net/sock/ip.h b/sys/include/net/sock/ip.h index 46e73add53..81437d1293 100644 --- a/sys/include/net/sock/ip.h +++ b/sys/include/net/sock/ip.h @@ -316,7 +316,15 @@ typedef struct { * @see SOCK_AUX_GET_TIMESTAMP */ uint64_t timestamp; -#endif /* MODULE_SOCK_AUX_TIMESTAP*/ +#endif /* MODULE_SOCK_AUX_TIMESTAP */ +#if defined(MODULE_SOCK_AUX_RSSI) || defined(DOXYGEN) + /** + * @brief RSSI value of the received frame + * + * @see SOCK_AUX_GET_RSSI + */ + int16_t rssi; +#endif /* MODULE_SOCK_AUX_RSSI */ sock_aux_flags_t flags; /**< Flags used request information */ } sock_ip_aux_rx_t; diff --git a/sys/include/net/sock/udp.h b/sys/include/net/sock/udp.h index 8c071ba483..4e1193d51e 100644 --- a/sys/include/net/sock/udp.h +++ b/sys/include/net/sock/udp.h @@ -318,7 +318,15 @@ typedef struct { * @see SOCK_AUX_GET_TIMESTAMP */ uint64_t timestamp; -#endif /* MODULE_SOCK_AUX_TIMESTAP*/ +#endif /* MODULE_SOCK_AUX_TIMESTAP */ +#if defined(MODULE_SOCK_AUX_RSSI) || defined(DOXYGEN) + /** + * @brief RSSI value of the received frame + * + * @see SOCK_AUX_GET_RSSI + */ + int16_t rssi; +#endif /* MODULE_SOCK_AUX_RSSI */ sock_aux_flags_t flags; /**< Flags used request information */ } sock_udp_aux_rx_t; diff --git a/sys/net/gnrc/sock/gnrc_sock.c b/sys/net/gnrc/sock/gnrc_sock.c index aabee4c349..b70928ccb2 100644 --- a/sys/net/gnrc/sock/gnrc_sock.c +++ b/sys/net/gnrc/sock/gnrc_sock.c @@ -174,6 +174,12 @@ ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt_out, } } #endif /* MODULE_SOCK_AUX_TIMESTAMP */ +#if IS_USED(MODULE_SOCK_AUX_RSSI) + if ((aux->rssi) && (netif_hdr->rssi != GNRC_NETIF_HDR_NO_RSSI)) { + aux->flags |= GNRC_SOCK_RECV_AUX_FLAG_RSSI; + *aux->rssi = netif_hdr->rssi; + } +#endif /* MODULE_SOCK_AUX_RSSI */ } *pkt_out = pkt; /* set out parameter */ diff --git a/sys/net/gnrc/sock/include/gnrc_sock_internal.h b/sys/net/gnrc/sock/include/gnrc_sock_internal.h index 485278f742..550a0e164a 100644 --- a/sys/net/gnrc/sock/include/gnrc_sock_internal.h +++ b/sys/net/gnrc/sock/include/gnrc_sock_internal.h @@ -72,6 +72,9 @@ typedef struct { #endif #if IS_USED(MODULE_SOCK_AUX_TIMESTAMP) || DOXYGEN uint64_t *timestamp; /**< timestamp PDU was received at in nanoseconds */ +#endif +#if IS_USED(MODULE_SOCK_AUX_RSSI) || DOXYGEN + int16_t *rssi; /**< RSSI value of received PDU */ #endif /** * @brief Flags @@ -80,6 +83,7 @@ typedef struct { } gnrc_sock_recv_aux_t; #define GNRC_SOCK_RECV_AUX_FLAG_TIMESTAMP 0x01 /**< Timestamp valid */ +#define GNRC_SOCK_RECV_AUX_FLAG_RSSI 0x02 /**< RSSI valid */ /** * @brief Internal helper functions for GNRC diff --git a/sys/net/gnrc/sock/ip/gnrc_sock_ip.c b/sys/net/gnrc/sock/ip/gnrc_sock_ip.c index ee3de88fdf..ac649d3c54 100644 --- a/sys/net/gnrc/sock/ip/gnrc_sock_ip.c +++ b/sys/net/gnrc/sock/ip/gnrc_sock_ip.c @@ -139,6 +139,11 @@ ssize_t sock_ip_recv_buf_aux(sock_ip_t *sock, void **data, void **buf_ctx, if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_TIMESTAMP)) { _aux.timestamp = &aux->timestamp; } +#endif +#if IS_USED(MODULE_SOCK_AUX_RSSI) + if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_RSSI)) { + _aux.rssi = &aux->rssi; + } #endif res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp, &_aux); if (res < 0) { @@ -166,6 +171,11 @@ ssize_t sock_ip_recv_buf_aux(sock_ip_t *sock, void **data, void **buf_ctx, if ((aux != NULL) && (_aux.flags & GNRC_SOCK_RECV_AUX_FLAG_TIMESTAMP)) { aux->flags &= ~(SOCK_AUX_GET_TIMESTAMP); } +#endif +#if IS_USED(MODULE_SOCK_AUX_RSSI) + if ((aux != NULL) && (_aux.flags & GNRC_SOCK_RECV_AUX_FLAG_RSSI)) { + aux->flags &= ~(SOCK_AUX_GET_RSSI); + } #endif *data = pkt->data; *buf_ctx = pkt; diff --git a/sys/net/gnrc/sock/udp/gnrc_sock_udp.c b/sys/net/gnrc/sock/udp/gnrc_sock_udp.c index caf03da1e8..b9d91dea9f 100644 --- a/sys/net/gnrc/sock/udp/gnrc_sock_udp.c +++ b/sys/net/gnrc/sock/udp/gnrc_sock_udp.c @@ -228,6 +228,11 @@ ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx, if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_TIMESTAMP)) { _aux.timestamp = &aux->timestamp; } +#endif +#if IS_USED(MODULE_SOCK_AUX_RSSI) + if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_RSSI)) { + _aux.rssi = &aux->rssi; + } #endif res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp, &_aux); if (res < 0) { @@ -261,6 +266,11 @@ ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx, if ((aux != NULL) && (_aux.flags & GNRC_SOCK_RECV_AUX_FLAG_TIMESTAMP)) { aux->flags &= ~SOCK_AUX_GET_TIMESTAMP; } +#endif +#if IS_USED(MODULE_SOCK_AUX_RSSI) + if ((aux != NULL) && (_aux.flags & GNRC_SOCK_RECV_AUX_FLAG_RSSI)) { + aux->flags &= ~SOCK_AUX_GET_RSSI; + } #endif *data = pkt->data; *buf_ctx = pkt; diff --git a/tests/gnrc_sock_ip/Makefile b/tests/gnrc_sock_ip/Makefile index 737b60e7fb..212af52183 100644 --- a/tests/gnrc_sock_ip/Makefile +++ b/tests/gnrc_sock_ip/Makefile @@ -2,6 +2,7 @@ include ../Makefile.tests_common AUX_LOCAL ?= 1 AUX_TIMESTAMP ?= 1 +AUX_RSSI ?= 1 ifeq (1, $(AUX_LOCAL)) USEMODULE += sock_aux_local @@ -11,6 +12,10 @@ ifeq (1, $(AUX_TIMESTAMP)) USEMODULE += sock_aux_timestamp endif +ifeq (1, $(AUX_RSSI)) + USEMODULE += sock_aux_rssi +endif + USEMODULE += sock_ip USEMODULE += gnrc_ipv6 USEMODULE += ps diff --git a/tests/gnrc_sock_ip/main.c b/tests/gnrc_sock_ip/main.c index fb8c3ae66b..ec69bf92eb 100644 --- a/tests/gnrc_sock_ip/main.c +++ b/tests/gnrc_sock_ip/main.c @@ -352,7 +352,7 @@ static void test_sock_ip_recv__aux(void) static const inject_aux_t inject_aux = { .timestamp = 42 }; sock_ip_ep_t result; sock_ip_aux_rx_t aux = { - .flags = SOCK_AUX_GET_LOCAL | SOCK_AUX_GET_TIMESTAMP + .flags = SOCK_AUX_GET_LOCAL | SOCK_AUX_GET_TIMESTAMP | SOCK_AUX_GET_RSSI }; expect(0 == sock_ip_create(&_sock, &local, NULL, _TEST_PROTO, @@ -376,6 +376,12 @@ static void test_sock_ip_recv__aux(void) expect(aux.timestamp == inject_aux.timestamp); #else expect(aux.flags & SOCK_AUX_GET_TIMESTAMP); +#endif +#if IS_USED(MODULE_SOCK_AUX_RSSI) + expect(!(aux.flags & SOCK_AUX_GET_RSSI)); + expect(aux.rssi == inject_aux.rssi); +#else + expect(aux.flags & SOCK_AUX_GET_RSSI); #endif expect(_check_net()); } diff --git a/tests/gnrc_sock_ip/stack.c b/tests/gnrc_sock_ip/stack.c index 5fa35c787f..3f23ffccd3 100644 --- a/tests/gnrc_sock_ip/stack.c +++ b/tests/gnrc_sock_ip/stack.c @@ -72,6 +72,7 @@ static gnrc_pktsnip_t *_build_ipv6_packet(const ipv6_addr_t *src, netif_hdr->if_pid = (kernel_pid_t)netif; if (aux) { gnrc_netif_hdr_set_timestamp(netif_hdr, aux->timestamp); + netif_hdr->rssi = aux->rssi; } return gnrc_pkt_append(payload, netif_hdr_snip); } diff --git a/tests/gnrc_sock_ip/stack.h b/tests/gnrc_sock_ip/stack.h index b2e3e804dc..75484ae631 100644 --- a/tests/gnrc_sock_ip/stack.h +++ b/tests/gnrc_sock_ip/stack.h @@ -44,6 +44,7 @@ void _prepare_send_checks(void); */ typedef struct { uint64_t timestamp; /**< Timestamp of reception */ + int16_t rssi; /**< Fake RSSI value */ } inject_aux_t; /** diff --git a/tests/gnrc_sock_udp/Makefile b/tests/gnrc_sock_udp/Makefile index 749135a2b4..caa22a1f4c 100644 --- a/tests/gnrc_sock_udp/Makefile +++ b/tests/gnrc_sock_udp/Makefile @@ -2,6 +2,7 @@ include ../Makefile.tests_common AUX_LOCAL ?= 1 AUX_TIMESTAMP ?= 1 +AUX_RSSI ?= 1 ifeq (1, $(AUX_LOCAL)) USEMODULE += sock_aux_local @@ -11,6 +12,10 @@ ifeq (1, $(AUX_TIMESTAMP)) USEMODULE += sock_aux_timestamp endif +ifeq (1, $(AUX_RSSI)) + USEMODULE += sock_aux_rssi +endif + USEMODULE += gnrc_sock_check_reuse USEMODULE += sock_udp USEMODULE += gnrc_ipv6 diff --git a/tests/gnrc_sock_udp/main.c b/tests/gnrc_sock_udp/main.c index c12e06d893..b367b97e1e 100644 --- a/tests/gnrc_sock_udp/main.c +++ b/tests/gnrc_sock_udp/main.c @@ -429,10 +429,10 @@ static void test_sock_udp_recv__aux(void) static const ipv6_addr_t dst_addr = { .u8 = _TEST_ADDR_LOCAL }; static const sock_udp_ep_t local = { .family = AF_INET6, .port = _TEST_PORT_LOCAL }; - static const inject_aux_t inject_aux = { .timestamp = 1337 }; + static const inject_aux_t inject_aux = { .timestamp = 1337, .rssi = -11 }; sock_udp_ep_t result; sock_udp_aux_rx_t aux = { - .flags = SOCK_AUX_GET_LOCAL | SOCK_AUX_GET_TIMESTAMP + .flags = SOCK_AUX_GET_LOCAL | SOCK_AUX_GET_TIMESTAMP | SOCK_AUX_GET_RSSI }; expect(0 == sock_udp_create(&_sock, &local, NULL, SOCK_FLAGS_REUSE_EP)); @@ -458,6 +458,12 @@ static void test_sock_udp_recv__aux(void) expect(inject_aux.timestamp == aux.timestamp); #else expect(aux.flags & SOCK_AUX_GET_TIMESTAMP); +#endif +#if IS_USED(MODULE_SOCK_AUX_RSSI) + expect(!(aux.flags & SOCK_AUX_GET_RSSI)); + expect(inject_aux.rssi == aux.rssi); +#else + expect(aux.flags & SOCK_AUX_GET_RSSI); #endif expect(_check_net()); } diff --git a/tests/gnrc_sock_udp/stack.c b/tests/gnrc_sock_udp/stack.c index a5c7556117..f3957f5b8f 100644 --- a/tests/gnrc_sock_udp/stack.c +++ b/tests/gnrc_sock_udp/stack.c @@ -95,6 +95,7 @@ static gnrc_pktsnip_t *_build_udp_packet(const ipv6_addr_t *src, netif_hdr->if_pid = (kernel_pid_t)netif; if (aux) { gnrc_netif_hdr_set_timestamp(netif_hdr, aux->timestamp); + netif_hdr->rssi = aux->rssi; } return gnrc_pkt_append(udp, netif_hdr_snip); } diff --git a/tests/gnrc_sock_udp/stack.h b/tests/gnrc_sock_udp/stack.h index 6975c1c01e..e8adc5d7c4 100644 --- a/tests/gnrc_sock_udp/stack.h +++ b/tests/gnrc_sock_udp/stack.h @@ -44,6 +44,7 @@ void _prepare_send_checks(void); */ typedef struct { uint64_t timestamp; /**< Timestamp of reception */ + int16_t rssi; /**< Fake RSSI value */ } inject_aux_t; /** diff --git a/tests/sock_udp_aux/Makefile b/tests/sock_udp_aux/Makefile new file mode 100644 index 0000000000..46b19ff524 --- /dev/null +++ b/tests/sock_udp_aux/Makefile @@ -0,0 +1,23 @@ +BOARD ?= nucleo-f767zi +include ../Makefile.tests_common + +# Enable hardware timestamping, if possible +FEATURES_OPTIONAL += periph_ptp periph_eth + +USEMODULE += auto_init_gnrc_netif +USEMODULE += fmt +USEMODULE += gnrc_icmpv6_echo +USEMODULE += gnrc_ipv6_default +USEMODULE += gnrc_netdev_default +USEMODULE += gnrc_sock_udp +USEMODULE += netstats_ipv6 +USEMODULE += netstats_l2 +USEMODULE += ps +USEMODULE += shell +USEMODULE += shell_commands + +USEMODULE += sock_aux_local +USEMODULE += sock_aux_rssi +USEMODULE += sock_aux_timestamp + +include $(RIOTBASE)/Makefile.include diff --git a/tests/sock_udp_aux/Makefile.ci b/tests/sock_udp_aux/Makefile.ci new file mode 100644 index 0000000000..87058a9a21 --- /dev/null +++ b/tests/sock_udp_aux/Makefile.ci @@ -0,0 +1,35 @@ +BOARD_INSUFFICIENT_MEMORY := \ + arduino-duemilanove \ + arduino-leonardo \ + arduino-mega2560 \ + arduino-nano \ + arduino-nano-33-iot \ + arduino-uno \ + atmega1284p \ + atmega328p \ + calliope-mini \ + derfmega128 \ + i-nucleo-lrwan1 \ + mega-xplained \ + microduino-corerf \ + msb-430 \ + msb-430h \ + nucleo-f030r8 \ + nucleo-f031k6 \ + nucleo-f042k6 \ + nucleo-f303k8 \ + nucleo-f334r8 \ + nucleo-f410rb \ + nucleo-l011k4 \ + nucleo-l031k6 \ + nucleo-l053r8 \ + samd10-xmini \ + slstk3400a \ + stk3200 \ + stm32f030f4-demo \ + stm32f0discovery \ + stm32l0538-disco \ + telosb \ + waspmote-pro \ + z1 \ + # diff --git a/tests/sock_udp_aux/main.c b/tests/sock_udp_aux/main.c new file mode 100644 index 0000000000..f755d38684 --- /dev/null +++ b/tests/sock_udp_aux/main.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2020 Otto-von-Guericke-Universität Magdeburg + * + * 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 tests + * @{ + * + * @file + * @brief Test application for accessing auxiliary data using the UDP SOCK API + * + * @author Marian Buschsieweke + * + * @} + */ + +#include +#include + +#include "fmt.h" +#include "net/sock/udp.h" +#include "shell.h" +#include "shell_commands.h" +#include "net/ipv6/addr.h" + +#define MAIN_QUEUE_SIZE (8) + +#define PORT_UDP 12345 +#define _QUOTE(x) #x +#define QUOTE(x) _QUOTE(x) + +static msg_t _main_msg_queue[MAIN_QUEUE_SIZE]; +char server_thread_stack[THREAD_STACKSIZE_DEFAULT]; + +static const sock_aux_flags_t flags_rx = SOCK_AUX_GET_LOCAL + | SOCK_AUX_GET_TIMESTAMP + | SOCK_AUX_GET_RSSI; +static const sock_aux_flags_t flags_tx = SOCK_AUX_GET_TIMESTAMP; + +static void *server_thread(void *arg) +{ + (void)arg; + sock_udp_ep_t local = SOCK_IPV6_EP_ANY; + sock_udp_t sock; + local.port = PORT_UDP; + if (sock_udp_create(&sock, &local, NULL, 0) < 0) { + print_str("Error creating UDP sock\n"); + return NULL; + } + print_str("UDP echo server listening at port " QUOTE(PORT_UDP) "\n"); + while (1) { + sock_udp_ep_t remote; + ssize_t res; + sock_udp_aux_rx_t rx_aux = { .flags = flags_rx }; + sock_udp_aux_tx_t tx_aux = { .flags = flags_tx }; + char buf[128]; + if (0 <= (res = sock_udp_recv_aux(&sock, buf, sizeof(buf), + SOCK_NO_TIMEOUT, &remote, &rx_aux))) + { + print_str("Received a message via: ["); + if (!(rx_aux.flags & SOCK_AUX_GET_LOCAL)) { + char tmp[IPV6_ADDR_MAX_STR_LEN + 1]; + ipv6_addr_to_str(tmp, (ipv6_addr_t *)rx_aux.local.addr.ipv6, + sizeof(tmp)); + print_str(tmp); + print_str("]:"); + print_u32_dec(rx_aux.local.port); + print_str("\n"); + } + else { + print_str("Unknown endpoint\n"); + } + print_str("Received a message at: "); + if (!(rx_aux.flags & SOCK_AUX_GET_TIMESTAMP)) { + print_u64_dec(rx_aux.timestamp); + print_str(" ns\n"); + } + else { + print_str("No timestamp\n"); + } + print_str("Received a message with: "); + if (!(rx_aux.flags & SOCK_AUX_GET_RSSI)) { + print_s32_dec(rx_aux.rssi); + print_str(" dBm\n"); + } + else { + print_str("No RSSI value\n"); + } + if (sock_udp_send_aux(&sock, buf, res, &remote, &tx_aux) < 0) { + print_str("Error sending reply\n"); + } + else { + print_str("Sent echo at: "); + if (!(tx_aux.flags & SOCK_AUX_GET_TIMESTAMP)) { + print_u64_dec(tx_aux.timestamp); + print_str(" ns\n"); + } + else { + print_str("No timestamp\n"); + } + } + } + } + return 0; +} + +int main(void) +{ + /* we need a message queue for the thread running the shell in order to + * receive potentially fast incoming networking packets */ + msg_init_queue(_main_msg_queue, MAIN_QUEUE_SIZE); + + thread_create(server_thread_stack, sizeof(server_thread_stack), + THREAD_PRIORITY_MAIN - 1, THREAD_CREATE_STACKTEST, + server_thread, NULL, "UDP echo server"); + + char line_buf[SHELL_DEFAULT_BUFSIZE]; + shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE); + + return 0; +}