How to log message relay path in Bluetooth Mesh Chat sample (nRF52840DK, NCS v3.0.2)

Hi, I’m working on an nRF52840DK-based Bluetooth Mesh project derived from the Chat sample on nRF connect SDK extension for VS Code.


The setup involves three types of nodes:

  1. Setup Overview:
  • Client – Scans BLE devices using scan_cb(), computes the nearest, and sends that info in mesh messages using bt_mes_chat_cli_message_send() and setting the unicast address of gateway. It also occasionally receives messages from the gateway to update application-specific settings, such as the cooldown interval that limits how frequently it sends messages.

  • Relay – Forwards messages across mesh (fewer in number to reduce traffic).

  • Gateway – Receives messages from relays and uploads them to an MQTT broker(sent to esp32 via UART). It can also receive commands from MQTT and send them back to clients or relays.

    The message received at the gateway side is handled in model_handler.c in the following manner:

    static void handle_chat_message(struct bt_mesh_chat_cli *chat,
    				struct bt_mesh_msg_ctx *ctx,
    				const uint8_t *msg)
    {
    	/* Don't print own messages. */
    	if (address_is_local(chat->model, ctx->addr)) {
    		return;
    	}
    		char buffer[64] = {0};
        	snprintf(buffer, sizeof(buffer), "%04X,%s\r\n", ctx->addr, (const char *)msg);
    		print_uart(buffer);
    	// shell_print(chat_shell, "<0x%04X>: %s", ctx->addr, msg);
    }

  1. Goal:
    I want to log the full message relay path — which intermediate nodes relayed a given message before it reached its destination (gateway).
    Currently, I can log source and destination from the bt_mesh_msg_ctx, but I can’t determine which devices actually relayed it in between.

  2. What I've tried:

What I’ve Tried
Enabled CONFIG_BT_MESH_NET_LOG_LEVEL_INF. added logging in net.c as follows: (inside the bt_mesh_net_recv function)

LOG_INF("=== MESSAGE PASSING THROUGH ===");
	LOG_INF("Source: 0x%04x", rx.ctx.addr);
	LOG_INF("Destination: 0x%04x", rx.ctx.recv_dst);
	LOG_INF("TTL: %u", rx.ctx.recv_ttl);
	LOG_INF("Sequence: 0x%06x", rx.seq);
	LOG_INF("Control: %u", rx.ctl);
	LOG_INF("Subnet: 0x%04x", rx.sub->net_idx);
	LOG_INF("Payload (%u bytes): %s", buf.len, bt_hex(buf.data, buf.len));
Is there any API or internal hook that exposes the relay path or sequence of nodes that forwarded a message? or can the etwork or transport layers be modified to log the relay chain (without breaking the mesh stack)?
If not, what’s the recommended way to instrument the stack to log this relay trace (for debugging or analysis purposes)?

My prj.conf file is as follows: 
#
# Copyright (c) 2020 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
CONFIG_NCS_SAMPLES_DEFAULTS=y

# Deferred logging helps improve LPN power consumption
# when friendship is established.
CONFIG_LOG_MODE_DEFERRED=y

# General configuration
CONFIG_NCS_APPLICATION_BOOT_BANNER_STRING="Mesh Chat"
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_FLASH=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y
CONFIG_NVS_LOOKUP_CACHE=y
CONFIG_SETTINGS_NVS_NAME_CACHE=y
CONFIG_HWINFO=y
CONFIG_DK_LIBRARY=y
CONFIG_PM_PARTITION_SIZE_SETTINGS_STORAGE=0x8000
CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE=y

# Bluetooth configuration
CONFIG_BT=y
CONFIG_BT_DEVICE_NAME="Gateway"
CONFIG_BT_L2CAP_TX_BUF_COUNT=8
CONFIG_BT_OBSERVER=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_SETTINGS=y
CONFIG_PRINTK=y

# Disable unused Bluetooth features
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_CHAN_SEL_2=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_PRIVACY=n

# Bluetooth Mesh configuration
CONFIG_BT_MESH=y
CONFIG_BT_MESH_RELAY=y
CONFIG_BT_MESH_FRIEND=y
CONFIG_BT_MESH_RX_SEG_MAX=10
CONFIG_BT_MESH_TX_SEG_MAX=10
CONFIG_BT_MESH_PB_GATT=y
CONFIG_BT_MESH_GATT_PROXY=y
CONFIG_BT_MESH_DK_PROV=y

# Enable Bluetooth Mesh models debug logs
CONFIG_BT_MESH_LOG_LEVEL_DBG=y
# CONFIG_BT_MESH_NET_LOG_LEVEL_INF=y

# Enable Shell module and use UART as a backend
CONFIG_SHELL=y
CONFIG_SHELL_BACKEND_SERIAL=y
CONFIG_FLASH_SHELL=n

CONFIG_LOG_BACKEND_RTT=n

CONFIG_SHELL_PROMPT_UART=""
CONFIG_SERIAL=y
CONFIG_UART_NRFX=y

I’d really appreciate any guidance on whether the relay path can be traced via internal mesh structures or hooks. I’m okay with exploring internal APIs or debugging patches if needed, just want to understand the right entry point.

Best Regards.

Parents
  • Hello,

    There is no information regarding the path of the packet in a Bluetooth Mesh packet. 

    Since Bluetooth Mesh is a flooding mesh, and not a routed Mesh, so packets don't have a planned route when traversing the network.

    In addition, for this to work, the packet would need to include the address of the nodes that are relaying the message. This mean they would have to open the packet and modify it's content before relaying it. But since this is no longer following the mesh specification, then you will end up debugging your own network implementation, rather than the actual Mesh network you are trying to debug.

    I ran this by our Bluetooth Mesh team, and they had some ideas on how to approach this. Perhaps the simplest way is to use a fixed TTL for your messages, and when you receive a message, you can look at the TTL (time to live), which will tell you how many relays the packet has traversed. Mapping this against the source of the packets gives some idea of what nodes that are within reach, or how many hops there typically is between two nodes. Note that this may vary from message to message. 

    But this data needs to be gathered periodically e.g. by the gateway, for you to be able to represent it visually, e.g. every minute or so. 

    Alternatively, you can turn on logging on the network layer, to print the SRC (source address) and SEQ (sequence number), and print this information from each  node over UART. This then needs to be collected, and perhaps parsed using some python script to represent the statistics of your network. 

    May I ask what exactly you were hoping to find using this debugging? Did you encounter some issues while developing a certain feature?

    Best regards,

    Edvin

Reply
  • Hello,

    There is no information regarding the path of the packet in a Bluetooth Mesh packet. 

    Since Bluetooth Mesh is a flooding mesh, and not a routed Mesh, so packets don't have a planned route when traversing the network.

    In addition, for this to work, the packet would need to include the address of the nodes that are relaying the message. This mean they would have to open the packet and modify it's content before relaying it. But since this is no longer following the mesh specification, then you will end up debugging your own network implementation, rather than the actual Mesh network you are trying to debug.

    I ran this by our Bluetooth Mesh team, and they had some ideas on how to approach this. Perhaps the simplest way is to use a fixed TTL for your messages, and when you receive a message, you can look at the TTL (time to live), which will tell you how many relays the packet has traversed. Mapping this against the source of the packets gives some idea of what nodes that are within reach, or how many hops there typically is between two nodes. Note that this may vary from message to message. 

    But this data needs to be gathered periodically e.g. by the gateway, for you to be able to represent it visually, e.g. every minute or so. 

    Alternatively, you can turn on logging on the network layer, to print the SRC (source address) and SEQ (sequence number), and print this information from each  node over UART. This then needs to be collected, and perhaps parsed using some python script to represent the statistics of your network. 

    May I ask what exactly you were hoping to find using this debugging? Did you encounter some issues while developing a certain feature?

    Best regards,

    Edvin

Children
  • Thanks Edvin for your reply. TTL seems to be a good idea.
    To explain further on what I would like to achieve...
    I am preparing for a dense network, where Relay will be scattered. I would like to ensure that the message from Client Node follow specific Relay route. If I notice, that my messages are following non-desired path, I would like to move Relay away from those nodes or reduce the transmission power of the Client. For that to happen, I would like to know what is the MAC/Mesh address of earlier Relay that forwarded the message. e.g.

    CN1 -> R1 -> R2 -> GW1 = OK Path

    CN1 -> R1 -> R3 -> GW1 = NOT OK Path. In that case, I would move R3 away from R1.

    CN1 - Client Node
    R1/R2 - Relay
    GW1 - Gateway

  • I understand. 

    Well, as mentioned, the packet doesn't contain any information of the devices that has relayed it when it arrives. It is only the radio of the receiver that can see the address of the originator, and the last relay node. So if you want to see whether R3 was the one who relayed the packet to GW1, you need to look at the address of the packet. But I guess this was a simplified model. I guess you also want to check something like this:

    CN1 -> R1 -> R2 -> R3 -> GW1 = OK Path

    CN1 -> R1 -> R3 -> GW1 = NOT OK Path. R1 is within range of R3, and you don't want that.

    In that case, the GW1 received the packet from R3 in both cases, and it is not able to see directly whether R2 was involved or not. But that is not possible from GW1. The added challenge is that R2 will probably also get the packet and relay it, but R3 was just able to pick up the packet directly from R1 in one of the cases. So you would need to monitor logs on R3 to see what nodes it can pick up packets from, or you need to monitor the TTL on GW1 to see how many hops the packet has done.

    Best regards,

    Edvin

Related