Network: L2: remove IPSP

Remove IPSP support from the tree.

It has no maintainers, and is regularly broken. The fact that it's
nontrivial to set-up in linux makes it hard to fix reported issues.

Signed-off-by: Jonathan Rico <jonathan.rico@nordicsemi.no>
This commit is contained in:
Jonathan Rico 2024-02-27 11:14:33 +01:00 committed by Carles Cufí
commit e3ff993000
54 changed files with 20 additions and 2046 deletions

View file

@ -1,9 +0,0 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(ipsp)
target_sources(app PRIVATE
src/main.c
)

View file

@ -1,216 +0,0 @@
.. _bluetooth-ipsp-sample:
Bluetooth: IPSP Sample
######################
Overview
********
Application demonstrating the IPSP (Internet Protocol Support Profile) Node
role. IPSP is the Bluetooth profile that underneath utilizes 6LoWPAN, i.e. gives
you IPv6 connectivity over BLE.
Building and Running
********************
This sample can be found under :zephyr_file:`samples/bluetooth/ipsp` in the
Zephyr tree.
Sample can be built and executed for the nRF52840 DK NRF52840 as follows:
.. zephyr-app-commands::
:zephyr-app: samples/bluetooth/ipsp
:board: nrf52840dk/nrf52840
:goals: build flash
:compact:
To build a debug version, with logging and shell support, use the config file
:file:`prj_dbg.conf`:
.. zephyr-app-commands::
:zephyr-app: samples/bluetooth/ipsp
:board: nrf52840dk/nrf52840
:conf: prj_dbg.conf
:goals: build flash
:compact:
Building and Running for Linux kernels released before 4.12
===========================================================
.. note::
For hosts using kernels released before 4.12,
option :kconfig:option:`CONFIG_NET_L2_BT_ZEP1656`
must be selected. For more information, see :github:`Zephyr issue #3111
<3111>`.
.. zephyr-app-commands::
:zephyr-app: samples/bluetooth/ipsp
:board: nrf52840dk/nrf52840
:conf: "prj_zep1656.conf"
:goals: build flash
:compact:
Testing with a Linux host
=========================
Make sure the Linux kernel has been built with Bluetooth 6LoWPAN module
(CONFIG_BT_6LOWPAN=y) then proceed to enable it with with the following commands
(as root):
.. code-block:: console
# modprobe bluetooth_6lowpan
# echo 1 > /sys/kernel/debug/bluetooth/6lowpan_enable
If you connected your board to a UART console, you will see an output similar to
(may vary slightly by application and Zephyr versions):
.. code-block:: console
[bt] [WRN] set_static_addr: Using temporary static random address
[bt] [INF] show_dev_info: Identity: cb:af:14:57:d8:6e (random)
[bt] [INF] show_dev_info: HCI: version 5.0 (0x09) revision 0x0000, manufacturer 0xffff
[bt] [INF] show_dev_info: LMP: version 5.0 (0x09) subver 0xffff
[bt] [WRN] bt_pub_key_gen: ECC HCI commands not available
[ipsp] [INF] init_app: Run IPSP sample
[ipsp] [INF] listen: Starting to wait
The output above shows the BLE address assigned to your board for the
current session; the address will be different on subsequent sessions.
Alternatively, you may scan for your board on the host. The modern way to do
that is using ``bluetoothctl`` utility (included in the recent versions of
BlueZ package) and its ``scan on`` command:
.. code-block:: console
$ bluetoothctl
[NEW] Controller A3:24:97:EB:D6:23 ubuntu-0 [default]
[NEW] Device D7:5C:D6:18:14:87 Zephyr
[NEW] Device E1:E7:F9:56:EC:06 Zephyr
[NEW] Device C8:12:C5:08:86:E1 Zephyr
[bluetooth]# scan on
Discovery started
[NEW] Device DC:98:FB:22:CA:3A Zephyr
When started, ``bluetoothctl`` shows all BLE (and likely, BT/EDR) devices it
knows about. As discussed above, the IPSP uses static random addresses, so
entries for previously connected devices, as shown above, can accumulate and
become stale. You need to be extra careful to find an entry for the active
address. The best approach may be to reset your board after issuing
``scan on`` command. This way it will reinitialize with the BLE address
which will be discovered after the command.
As an alternative to ``bluetoothctl``, you can use the legacy ``hcitool``
utility which talks directly to hardware and always shows fresh scan results:
.. code-block:: console
$ sudo hcitool lescan
LE Scan ...
CB:AF:14:57:D8:6E (unknown)
CB:AF:14:57:D8:6E Test IPSP node
After you have found the board's BLE address, connect to the board (as root):
.. code-block:: console
# echo "connect <bdaddr> <type>" > /sys/kernel/debug/bluetooth/6lowpan_control
Where ``<bdaddr>`` is the BLE address and ``<type>`` is BLE address type:
1 for public address and 2 for random address. As you can see from
the IPSP sample output above, it uses a static random address. So, with the
sample output above, the command will be:
.. code-block:: console
# echo "connect CB:AF:14:57:D8:6E 2" > /sys/kernel/debug/bluetooth/6lowpan_control
Once connected a dedicated interface will be created, usually bt0. You can verify this
with the following command:
.. code-block:: console
# ifconfig
bt0 Link encap:UNSPEC HWaddr F8-2F-A8-FF-FE-EB-6D-8C-00-00-00-00-00-00-00-00
inet6 addr: fe80::fa2f:a8ff:feeb:6d8c/64 Scope:Link
UP POINTOPOINT RUNNING MULTICAST MTU:1280 Metric:1
RX packets:2 errors:0 dropped:3 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:92 (92.0 B) TX bytes:233 (233.0 B)
As can be seen from the output, only a link-local IPv6 address was assigned
to the interface.
At this point, you can test IPv6 connectivity (and discover your board's IPv6
address) by pinging "All local-link nodes" IPv6 address:
.. code-block:: console
# ping6 -I bt0 ff02::1
PING ff02::1(ff02::1) from fe80::fa54:a8ff:feeb:218f bt0: 56 data bytes
64 bytes from fe80::fa54:a8ff:feeb:218f: icmp_seq=1 ttl=64 time=0.088 ms
64 bytes from fe80::c9af:14ff:fe57:d86e: icmp_seq=1 ttl=64 time=285 ms (DUP!)
For each ping packet, both your host and the BLE board send a reply. You
can see the board's reply marked as ``(DUP!)``. You can ping the board
directly with:
.. code-block:: console
# ping6 fe80::c9af:14ff:fe57:d86e%bt0
PING fe80::c9af:14ff:fe57:d86e%bt0(fe80::c9af:14ff:fe57:d86e) 56 data bytes
64 bytes from fe80::c9af:14ff:fe57:d86e: icmp_seq=1 ttl=64 time=177 ms
64 bytes from fe80::c9af:14ff:fe57:d86e: icmp_seq=2 ttl=64 time=53.0 ms
Note that the command uses a "scoped IPv6 address", where the scope is
defined by the networking interface, with ``%bt0`` appended in this case.
A specification like that is an alternative to passing ``-I bt0`` to
``ping6`` (and works with other networking tools like ``telnet``, ``nc``,
``curl``, etc.)
While we can use a link-local address, it's not very convenient, as it must be
scoped and will change on each run. Instead, the IPSP sample is configured with
``2001:db8::1`` static address and we'll configure the host's interface to
access that address by configuring ``bt0`` with the complementary address
``2001:db8::2``:
.. code-block:: console
# ip address add 2001:db8::2/64 dev bt0
Now we can ping the board's static address with:
.. code-block:: console
# ping6 2001:db8::1
PING 2001:db8::1(2001:db8::1) 56 data bytes
64 bytes from 2001:db8::1: icmp_seq=1 ttl=64 time=282 ms
The IPSP sample includes builtin echo server for UDP and TCP on a port 4242,
which we can test with:
.. code-block:: console
$ telnet 2001:db8::1 4242
Trying 2001:db8::1...
Connected to 2001:db8::1.
Escape character is '^]'.
test
test
test2
test2
^]
telnet> quit
Connection closed.
In the output above, first ``test`` line was typed, next was echoed back by
the board. Likewise for ``test2``. To quit telnet tool, type Ctrl+], then
"quit" at the prompt.
As an alternative to using well-known networking tools above, and also to
test both TCP and UDP echo, you can use Zephyr's helper tool in the GitHub
``zephyrproject-rtos/net-tools`` repository:
.. code-block:: console
$ echo-client -i bt0 <ip>

View file

@ -1,22 +0,0 @@
/*
* Copyright 2019 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
&lptmr1 {
interrupt-parent = <&intmux0_ch2>;
};
&intmux0_ch2 {
status = "okay";
};
&intmux0_ch3 {
status = "okay";
};
&generic_fsk {
interrupt-parent = <&intmux0_ch3>;
status = "okay";
};

View file

@ -1,28 +0,0 @@
CONFIG_BT=y
CONFIG_LOG=y
CONFIG_BT_SMP=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y
CONFIG_BT_DEVICE_NAME="Test IPSP node"
CONFIG_NETWORKING=y
CONFIG_NET_IPV6=y
CONFIG_NET_IPV4=n
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_L2_BT=y
CONFIG_INIT_STACKS=y
CONFIG_NET_PKT_RX_COUNT=10
CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_BUF_RX_COUNT=20
CONFIG_NET_BUF_TX_COUNT=20
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=4
CONFIG_NET_MAX_CONTEXTS=6
CONFIG_NET_CONFIG_AUTO_INIT=y
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8::2"
CONFIG_NET_CONFIG_BT_NODE=y

View file

@ -1,33 +0,0 @@
CONFIG_BT=y
CONFIG_LOG=y
CONFIG_BT_SMP=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y
CONFIG_BT_DEVICE_NAME="Test IPSP node"
CONFIG_NETWORKING=y
CONFIG_NET_IPV6=y
CONFIG_NET_IPV4=n
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_LOG=y
CONFIG_NET_L2_BT=y
CONFIG_INIT_STACKS=y
CONFIG_NET_STATISTICS=y
CONFIG_NET_PKT_RX_COUNT=10
CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_BUF_RX_COUNT=20
CONFIG_NET_BUF_TX_COUNT=20
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=4
CONFIG_NET_MAX_CONTEXTS=6
CONFIG_NET_SHELL=y
CONFIG_BT_SHELL=y
CONFIG_NET_CONFIG_AUTO_INIT=y
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8::2"
CONFIG_NET_CONFIG_BT_NODE=y

View file

@ -1,29 +0,0 @@
CONFIG_BT=y
CONFIG_LOG=y
CONFIG_BT_SMP=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_L2CAP_DYNAMIC_CHANNEL=y
CONFIG_BT_DEVICE_NAME="Test IPSP node"
CONFIG_NETWORKING=y
CONFIG_NET_IPV6=y
CONFIG_NET_IPV4=n
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_L2_BT=y
CONFIG_NET_L2_BT_ZEP1656=y
CONFIG_INIT_STACKS=y
CONFIG_NET_PKT_RX_COUNT=10
CONFIG_NET_PKT_TX_COUNT=10
CONFIG_NET_BUF_RX_COUNT=20
CONFIG_NET_BUF_TX_COUNT=20
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=4
CONFIG_NET_MAX_CONTEXTS=6
CONFIG_NET_CONFIG_AUTO_INIT=y
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8::2"
CONFIG_NET_CONFIG_BT_NODE=y

View file

@ -1,25 +0,0 @@
sample:
name: Bluetooth IPSP Sample
description: IPSP (Internet Protocol Support Profile) Node role sample
tests:
sample.bluetooth.ipsp:
harness: bluetooth
platform_allow:
- qemu_x86
- qemu_cortex_m3
tags:
- bluetooth
- net
integration_platforms:
- qemu_x86
sample.bluetooth.ipsp.zep1656:
harness: bluetooth
extra_args: CONF_FILE="prj_zep1656.conf"
platform_allow:
- qemu_x86
- qemu_cortex_m3
tags:
- bluetooth
- net
integration_platforms:
- qemu_x86

View file

@ -1,323 +0,0 @@
/* main.c - Application main entry point */
/*
* Copyright (c) 2015-2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/logging/log.h>
#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL
LOG_MODULE_REGISTER(ipsp);
/* Preventing log module registration in net_core.h */
#define NET_LOG_ENABLED 0
#include <zephyr/kernel.h>
#include <zephyr/linker/sections.h>
#include <errno.h>
#include <stdio.h>
#include <zephyr/net/net_pkt.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/net_core.h>
#include <zephyr/net/net_context.h>
#include <zephyr/net/udp.h>
/* Define my IP address where to expect messages */
#define MY_IP6ADDR { { { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0x1 } } }
#define MY_PREFIX_LEN 64
static struct in6_addr in6addr_my = MY_IP6ADDR;
#define MY_PORT 4242
#define STACKSIZE 2000
K_THREAD_STACK_DEFINE(thread_stack, STACKSIZE);
static struct k_thread thread_data;
static uint8_t buf_tx[NET_IPV6_MTU];
#define MAX_DBG_PRINT 64
NET_PKT_TX_SLAB_DEFINE(echo_tx_tcp, 15);
NET_PKT_DATA_POOL_DEFINE(echo_data_tcp, 30);
static struct k_mem_slab *tx_tcp_pool(void)
{
return &echo_tx_tcp;
}
static struct net_buf_pool *data_tcp_pool(void)
{
return &echo_data_tcp;
}
static struct k_sem quit_lock;
static inline void quit(void)
{
k_sem_give(&quit_lock);
}
static inline void init_app(void)
{
LOG_INF("Run IPSP sample");
k_sem_init(&quit_lock, 0, K_SEM_MAX_LIMIT);
if (net_addr_pton(AF_INET6,
CONFIG_NET_CONFIG_MY_IPV6_ADDR,
&in6addr_my) < 0) {
LOG_ERR("Invalid IPv6 address %s",
CONFIG_NET_CONFIG_MY_IPV6_ADDR);
}
do {
struct net_if_addr *ifaddr;
ifaddr = net_if_ipv6_addr_add(net_if_get_default(),
&in6addr_my, NET_ADDR_MANUAL, 0);
} while (0);
}
static inline bool get_context(struct net_context **udp_recv6,
struct net_context **tcp_recv6)
{
int ret;
struct sockaddr_in6 my_addr6 = { 0 };
my_addr6.sin6_family = AF_INET6;
my_addr6.sin6_port = htons(MY_PORT);
ret = net_context_get(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, udp_recv6);
if (ret < 0) {
LOG_ERR("Cannot get network context for IPv6 UDP (%d)", ret);
return false;
}
ret = net_context_bind(*udp_recv6, (struct sockaddr *)&my_addr6,
sizeof(struct sockaddr_in6));
if (ret < 0) {
LOG_ERR("Cannot bind IPv6 UDP port %d (%d)",
ntohs(my_addr6.sin6_port), ret);
return false;
}
ret = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, tcp_recv6);
if (ret < 0) {
LOG_ERR("Cannot get network context for IPv6 TCP (%d)", ret);
return false;
}
net_context_setup_pools(*tcp_recv6, tx_tcp_pool, data_tcp_pool);
ret = net_context_bind(*tcp_recv6, (struct sockaddr *)&my_addr6,
sizeof(struct sockaddr_in6));
if (ret < 0) {
LOG_ERR("Cannot bind IPv6 TCP port %d (%d)",
ntohs(my_addr6.sin6_port), ret);
return false;
}
ret = net_context_listen(*tcp_recv6, 0);
if (ret < 0) {
LOG_ERR("Cannot listen IPv6 TCP (%d)", ret);
return false;
}
return true;
}
static int build_reply(const char *name,
struct net_pkt *pkt,
uint8_t *buf)
{
int reply_len = net_pkt_remaining_data(pkt);
int ret;
LOG_DBG("%s received %d bytes", name, reply_len);
ret = net_pkt_read(pkt, buf, reply_len);
if (ret < 0) {
LOG_ERR("cannot read packet: %d", ret);
return ret;
}
LOG_DBG("sending %d bytes", reply_len);
return reply_len;
}
static inline void pkt_sent(struct net_context *context,
int status,
void *user_data)
{
if (status >= 0) {
LOG_DBG("Sent %d bytes", status);
}
}
static inline void set_dst_addr(sa_family_t family,
struct net_pkt *pkt,
struct net_ipv6_hdr *ipv6_hdr,
struct net_udp_hdr *udp_hdr,
struct sockaddr *dst_addr)
{
net_ipv6_addr_copy_raw((uint8_t *)&net_sin6(dst_addr)->sin6_addr,
ipv6_hdr->src);
net_sin6(dst_addr)->sin6_family = AF_INET6;
net_sin6(dst_addr)->sin6_port = udp_hdr->src_port;
}
static void udp_received(struct net_context *context,
struct net_pkt *pkt,
union net_ip_header *ip_hdr,
union net_proto_header *proto_hdr,
int status,
void *user_data)
{
struct sockaddr dst_addr;
sa_family_t family = net_pkt_family(pkt);
static char dbg[MAX_DBG_PRINT + 1];
int ret;
snprintf(dbg, MAX_DBG_PRINT, "UDP IPv%c",
family == AF_INET6 ? '6' : '4');
set_dst_addr(family, pkt, ip_hdr->ipv6, proto_hdr->udp, &dst_addr);
ret = build_reply(dbg, pkt, buf_tx);
if (ret < 0) {
LOG_ERR("Cannot send data to peer (%d)", ret);
return;
}
net_pkt_unref(pkt);
ret = net_context_sendto(context, buf_tx, ret, &dst_addr,
family == AF_INET6 ?
sizeof(struct sockaddr_in6) :
sizeof(struct sockaddr_in),
pkt_sent, K_NO_WAIT, user_data);
if (ret < 0) {
LOG_ERR("Cannot send data to peer (%d)", ret);
}
}
static void setup_udp_recv(struct net_context *udp_recv6)
{
int ret;
ret = net_context_recv(udp_recv6, udp_received, K_NO_WAIT, NULL);
if (ret < 0) {
LOG_ERR("Cannot receive IPv6 UDP packets");
}
}
static void tcp_received(struct net_context *context,
struct net_pkt *pkt,
union net_ip_header *ip_hdr,
union net_proto_header *proto_hdr,
int status,
void *user_data)
{
static char dbg[MAX_DBG_PRINT + 1];
sa_family_t family;
int ret, len;
if (!pkt) {
/* EOF condition */
return;
}
family = net_pkt_family(pkt);
len = net_pkt_remaining_data(pkt);
snprintf(dbg, MAX_DBG_PRINT, "TCP IPv%c",
family == AF_INET6 ? '6' : '4');
ret = build_reply(dbg, pkt, buf_tx);
if (ret < 0) {
LOG_ERR("Cannot send data to peer (%d)", ret);
return;
}
(void)net_context_update_recv_wnd(context, len);
net_pkt_unref(pkt);
ret = net_context_send(context, buf_tx, ret, pkt_sent,
K_NO_WAIT, NULL);
if (ret < 0) {
LOG_ERR("Cannot send data to peer (%d)", ret);
quit();
}
}
static void tcp_accepted(struct net_context *context,
struct sockaddr *addr,
socklen_t addrlen,
int error,
void *user_data)
{
int ret;
NET_DBG("Accept called, context %p error %d", context, error);
net_context_set_accepting(context, false);
ret = net_context_recv(context, tcp_received, K_NO_WAIT, NULL);
if (ret < 0) {
LOG_ERR("Cannot receive TCP packet (family %d)",
net_context_get_family(context));
}
}
static void setup_tcp_accept(struct net_context *tcp_recv6)
{
int ret;
ret = net_context_accept(tcp_recv6, tcp_accepted, K_NO_WAIT, NULL);
if (ret < 0) {
LOG_ERR("Cannot receive IPv6 TCP packets (%d)", ret);
}
}
static void listen(void *p1, void *p2, void *p3)
{
ARG_UNUSED(p1);
ARG_UNUSED(p2);
ARG_UNUSED(p3);
struct net_context *udp_recv6 = { 0 };
struct net_context *tcp_recv6 = { 0 };
if (!get_context(&udp_recv6, &tcp_recv6)) {
LOG_ERR("Cannot get network contexts");
return;
}
LOG_INF("Starting to wait");
setup_tcp_accept(tcp_recv6);
setup_udp_recv(udp_recv6);
k_sem_take(&quit_lock, K_FOREVER);
LOG_INF("Stopping...");
net_context_put(udp_recv6);
net_context_put(tcp_recv6);
}
int main(void)
{
init_app();
k_thread_create(&thread_data, thread_stack, STACKSIZE,
listen,
NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
return 0;
}