Overview
This example demonstrates how the lwIP stack can be used on Nordic's 6lowpan interface to listen on a UDP port. Port number 9000 is used in this example. The UDP listen port is not bound to a particular address and therefore it is possible to send data to the port on a link-local or on global address(es).
UDP Request Format
In order to demonstrate data exchange on the UDP port, the application is designed to expect an 8-byte echo request in the following format from the UDP Client.
Field | Sequence number in uint32 format | 'P' | 'i' | 'n' | 'g' |
Size (octets) | 4 (Network Order) | 1 | 1 | 1 | 1 |
UDP Response Format
In response to a request from the client, this application responds back to request with a 8-byte response packet of following format:
Field | Requested Sequence number in uint32 format | 'P' | 'o' | 'n' | 'g' |
Size (octets) | 4 (Network Order) | 1 | 1 | 1 | 1 |
The UDP client could be a PC application communicating to the UDP server on the kit as shown in Figure 1 below.
Figure 1: Setup of the lwIP based IPv6 UDP server application.
Or, the UDP client could be the example client application included in the SDK sending requests to the server, as shown in Figure 2.
Figure 2: Setup of the lwIP based IPv6 UDP client with UDP server application.
Common Modules Dependency and Usage
This section summarizes the usage of nRF51 resources and common modules in the examples apart from the IoT 6lowpan and lwIP stack library.
Module | Inclusion/Usage | Description |
Timer | 1 | One timer is used to periodically service the lwIP with a 200 ms interval. |
Button | 0 | No buttons are used in the example. |
LEDs | 2 | LEDs are used to indicate the application states. See the LED assignment section. |
Adv Data Encoder | Yes | The device name used is 'LwIPUDPServer', IPSP Service UUID is included in the UUID list. |
Scheduler | No | Scheduler is not used for processing stack events. |
UART Trace | Included not enabled | Tracing is included but not enabled by default. |
- Note
- The lwIP library used for this example is under BSD-style license; this is different from the Nordic SDK license. The license text can be found at <InstallFolder>/Nordic/nrf51/external/lwip/license.txt
Setup
The name of the example is iot_lwip_udp_server. The source code and project file of the example can be found at: <InstallFolder>/Nordic/nrf51/examples/iot/udp/lwip/server
See below for a state diagram that describes the application states.
Figure 3: Application State Diagram.
LED assignments
Application State | LED 1 State | LED 2 State |
Idle | OFF | OFF |
Advertising | ON | OFF |
IPv6 Interface Up | OFF | ON |
IPv6 Interface Down | ON | OFF |
UDP Ping | Refer to table below | Refer to table below |
ASSERT | ON | ON |
By using the LEDs on the board, the remainder after division of the received Sequence number by 4 is displayed in the following manner.
Value | Binary | LED 1 State | LED 2 State |
0 | 00000000 | OFF | OFF |
1 | 00000001 | ON | OFF |
2 | 00000010 | OFF | ON |
3 | 00000011 | ON | ON |
- Note
- If the application asserts, it is halted.
-
This application is not power optimized!
Testing
See Connecting devices to the router for a list of relevant Linux commands.
- Compile and program the application. Observe that the advertising LED is lit. Ensure that the custom SoftDevice located at <InstallFolder>/Nordic/nrf51/components/softdevice/s110_for_ipv6 is used.
- Prepare the Linux router device by initializing the 6LoWPAN module.
- Discover the advertising device by using the hcitool lescan command.
- Connect to the discovered device from the Linux console by using the Bluetooth 6LoWPAN connect command.
- Now the advertising LED is turned off and the connected LED is lit.
- Run the Wireshark or hcidump program and observe the btX interface. Observe the periodic Neighbor Solicitation messages sent by the lwIP stack.
- An ICMP ping can be used on the link-local and on the global IPv6 address assigned to the device to ensure that the device is reachable.
- Note
- To find the global address, use the prefix assigned to the interface in Router Advertisement.
- Use a UDP client to send request packets as described in the section UDP Request Format to the global address of the nRF51 and UDP port number 9000. The UDP client application can be another nRF51 running the lwIP UDP Client application or a local UDP client that connects to the server and sends data to the application.
- Disconnect from device by using the Bluetooth 6LoWPAN disconnect command.
- Observe that only the advertising LED is lit.
Python Client Example
Below is a Python client example that connects to the server application, sends 100 ping requests and then exits. The server address used here is an example address and will need to be modified to the server address of the nRF51 that runs the lwIP UDP server application.
import socket
import struct
#This example assumes the server BD address to be 00:AA:BB:CC:DD:EE and global prefix used to be 2004::/64.
#Therefore global IPv6 address of the server will be 2004::02AA:BBFF:FECC:DDEE.
SERVER_ADDR = '2004::02AA:BBFF:FECC:DDEE'
SERVER_PORT = 9000
sequence_number = 1
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
while sequence_number < 101 :
data = struct.pack("!I", sequence_number)
data += 'Ping'
sock.sendto(data, (SERVER_ADDR, SERVER_PORT, 0, 0))
recv_data = sock.recvfrom(8)
print recv_data
rx_sequence_number = struct.unpack("!I", recv_data[0][:4])[0]
if sequence_number is not rx_sequence_number:
print "Sequence number mismatch!"
sequence_number+= 1
sock.close()
del sock
Troubleshooting guide
- It is possible that the global address is not immediately available on the connection as the Neighbor Discovery, Router Advertisement, and Duplicate Address Detection procedures take a few seconds to complete.
- In case no global address is assigned to the nRF51, the lwIP stack does not permit sending packets to a global address. This means that if a UDP request packet was received from a global address, the response will not be sent as there is no global address available for this application. This is usually detected with the ERR_RTE error code when calling the udp_sendto_ip6 API of lwIP stack in the application.
- If you observe that the client requests are initiated on Ethernet but not sent on the Bluetooth network interface to the nRF51 running the UDP Server, it is possible that the forwarding between networks is not enabled. This can be done on Linux using the command
sysctl -w net.ipv6.conf.all.forwarding=1
.