This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

OpenThread provisioning response

Hello,

I have a device which sends a provisioning request to two other devices in a Thread network. They both receive the request and both send a provisioning response, i.e. both devices receiving the provisioning requests calls provisioning_response_send(). However, the requester device only receives one response, not two as it is supposed to. I.e., on_provisioning_reply is only called one time at the requester side. Why is this? I am trying to append the IPv6 addresses received in the responses in a list to make it possible to send unicast messages to a particular device at a later time, but this is not possible with this issue occurring.

Update: I reckon this provisioning procedure is sample-specific and not part of the OpenThread specification, thus, only one server may be paired with a client at a time this way? In that case, where can I find the IPv6-addresses of the connected nodes on the thread network in the application code? I can find them via uart openthread commands, but not in the source code. Furthermore, I want to be able to address a specific device in the network, say device A, located at a specific physical position. Therefore, I need to use e.g. a MAC or EUI64 address or DEVICEID/FICR address or something similar to look up the device's IPv6 address before communicating. Where can I find such information?

  • Hello,

    I am sorry for the late reply (on your other ticket as well). Most of our Thread team is on vacation right now, but some are coming back on Monday. I was hoping to hand your tickets over to him when he returns. I am sorry for the delay. In the meantime, I will try to check with some different people and see if I can find someone who can answer your questions.

    Best regards,

    Edvin

  • Hello,

    I spoke to our thread team regarding your ticket. Here is a summary of what they said:

    Provisioning works like this in the coap server/client examples:
    1. The Coap server enables provisioning, now it listens to the multicast message from coap clients.
    2. The Coap client sends a multicast provisioning request.
    3. The Coap server receives the request, and executes on provisioning_request()
    https://github.com/nrfconnect/fw-nrfconnect-nrf/blob/master/samples/openthread/coap_server/src/ot_coap_utils.c#L184 
    4. In our case on provisioning_request() calls deactivate_provisioning()
    https://github.com/nrfconnect/fw-nrfconnect-nrf/blob/master/samples/openthread/coap_server/src/coap_server.c#L62
    5. The Coap server replies to the coap server with a unicast message.
    6. The Coap client receives the unicast message, now it knows the unicast address of the coap server and sends light toggle requests directly to it. 

    So the functions that you need to change are in the files that are linked. 

    You say that you know "how to find them (the addresses) via uart and openthread commands". You can look at the implementation of the CLI commands in the openthread repo on github:

    https://github.com/openthread/openthread/blob/8370395c47333a612e117b38c3b034e61e3b8597/src/cli/cli.cpp

    For example the ipaddr command is found here:
    https://github.com/openthread/openthread/blob/8370395c47333a612e117b38c3b034e61e3b8597/src/cli/cli.cpp#L1639

    I assume you are using OpenThread in NCS. All the header files comes from this repo:

    https://github.com/nrfconnect/sdk-nrfxlib/tree/master/openthread/include/openthread

    So you can use this to check the OT API.

    One extra note on addressing:

    There is something called ML-EID, which you can use when communicating between the nodes. This is a randomly assigned address that is provided after provisioning. This address remains the same over power cycles and is never changed during the lifetime of the device, unlike the IP address, which may change if the device is powered off, and then reconnected to the network. 

    Hopefully there are some useful pointers here. 

    Best regards,

    Edvin

  • Thank you for your answer. 

    The outlined procedure, however, only works with one server at a time. E.g. if I enable provisioning on two servers simultaneously, and send a multicast provisioning request with a client, both servers receive this message and sends a provisioning unicast response. However, the client only receives one of these responses, and I reckon this is due to how coap_set_response_callback() is defined; that the callback is cleared after the first call or something like that. Thus, only one server can be provisioned at a time. If possible, I want to be able to acquire the IPv6 addresses of several servers without needing to provision one by one like this.

    Since the thread network already is established before this provisioning routine, shouldn't the IPv6 addresses be readily available for the thread routers somewhere?  E.g. the link and mesh local addresses? I was of the impression that such information was exchanged during the thread network creation and that the routers could address any node in the network by its IPv6 address without the need of "extra" provisioning by making the servers reply with their address upon receiving a multicast provisioning request like in the sample. Is this possible?

    Yes, I can observe any IPv6 address of any node by uart commands in the console, but I cannot find a way to observe all nodes and their corresponding IPv6 addresses from one particular (router) device. I.e. I need to call ot ipaddr on the separate nodes to see their addresses, but ideally I want to observe all addresses from one device.

    For instance, in the OpenThread specification, it says "A Full Thread Device (FTD) always has its radio on, subscribes to the all-routers multicast address, and maintains IPv6 address mappings." Doesn't this mean that addresses of the network nodes should be available (for the FTD's) somewhere?

    Thank you for the ML-EUD advice. I have also found a way to retrieve the EUI64 addresses of my devices, which I think is static and does not change, which is useful to me.

  • Update: I temporary fixed the problem by, instead of sending an otCoapSendResponse() in provisioning_response_send(), I use the Zephyr Thread Api and call coap_send_request(). This way, the client who sent the provisioning request receives a message from both (currently) two servers. I tried first using the OpenThread API and otCoapSendRequest() instead of otCoapSendResponse(), but that does not work; the client does not receive any messages. Any takes on why?

    However, I still think that the thread network IP addresses should be available somewhere without the need of this provisioning procedure.
    Furthermore, coap_send_request() calls coap_init_request() in ncs/nrf/subsys/net/lib/coap_utils.c. This function takes a coap_msgtype argument but this is set to COAP_TYPE_NON_CON. Why is this? Why doesn't coap_send_request() take a coap_msgtype argument so that this could be specified at the application level without the need of changing the SDK? Is there any reason for this, i.e. that confirmable messages not are stable or anything like that?
  • Hello,

    First of all, sorry for the late reply. 

    Have you checked out the CLI example? (NB: If you use the NCS one, you need to add "ot " before the CLI commands.

    You can use commands like "ot cli router table" to see a table of all the routers, with some parameters like number of hops, extended MAC address, and RLOC address. 

    The RLOC address can be used to reach the node from within the network using a Mesh Local address.

    I used the following cli commands to ping another device:

    uart:~$ ot router table
    | ID | RLOC16 | Next Hop | Path Cost | LQ In | LQ Out | Age | Extended MAC     |
    +----+--------+----------+-----------+-------+--------+-----+------------------+
    |  9 | 0x2400 |       43 |         1 |     3 |      3 |   6 | b643fd5dc3a95b44 |
    | 25 | 0x6400 |       63 |         0 |     0 |      0 |   0 | e6c92d2a39ea47b3 |
    | 43 | 0xac00 |        9 |         1 |     3 |      3 |   5 | e6675f027885bdf7 |
    
    Done
    uart:~$ ot ping fdde:ad00:beef::ff:fe00:2400
    Done
    16 bytes from fdde:ad00:beef:0:0:ff:fe00:2400: icmp_seq=2 hlim=64 time=22ms
    uart:~$
    

    As you can see from Jørgen's answer here, the mesh local address will always be: 

    fdde:ad00:beef::ff:fe00:<RLOC>

    You can access the openthread cli implementation from the openthread github. E.g. the router table command is implemented here:

    https://github.com/openthread/openthread/blob/b940baf9b6cad48feaab60848f6e006bffe79d4e/src/cli/cli.cpp#L3425

    You can use this api from your application.

    Is this something you can use?

    Best regards,

    Edvin

Related