Remove nanostack binary libraries
-Remove nanostack binary libraries -Remove content from sal-stack-nanostack -Update contribution rules. -Remove binary LICENSEpull/5511/head
|
@ -39,22 +39,18 @@ Send contributions directly to this repository.
|
|||
|
||||
## sal-stack-nanostack
|
||||
|
||||
This directory holds binary libraries generated from the Nanostack networking library.
|
||||
This directory holds source code snapshot of the Nanostack networking library. Master repository is available for **mbed Partners** in https://github.com/ARMmbed/sal-stack-nanostack-private.
|
||||
|
||||
**Only mbed Partners have access to the source code.**
|
||||
If you have access to the master repository, please send contributions against that repository.
|
||||
|
||||
If you have access, the source directory is available in https://github.com/ARMmbed/sal-stack-nanostack-private
|
||||
|
||||
You can replace the binary libraries with the source tree as follows:
|
||||
|
||||
* Remove the sal-stack-nanostack directory: `rm -rf sal-stack-nanostack`
|
||||
* Remove the binaries located one directory up: `rm -rf ../nanostack-binaries`
|
||||
* Clone the original source repository to root folder of your application: `git@github.com:ARMmbed/sal-stack-nanostack-private.git`
|
||||
To test changes with access to master repository:
|
||||
* Remove the sal-stack-nanostack directory: `rm -rf sal-stack-nanostack`
|
||||
* Clone the master repository `git clone git@github.com:ARMmbed/sal-stack-nanostack-private.git`as sal-stack-nanostack
|
||||
|
||||
Now you can modify, build and test your changes with the mbed OS build.
|
||||
|
||||
**NOTE:** You do not need to clone the Nanostack to exactly same location in the build tree. This may even cause build problems.
|
||||
**NOTE:** You do not need to clone the Nanostack master repository to exactly same location in the build tree.
|
||||
|
||||
If you don't have access to the master repository then you can send contributions directly to this repository.
|
||||
|
||||
### Instructions for generating the binary modules
|
||||
|
||||
Check `Releasing.md` from the Nanostack source repository.
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
upload.tar.gz
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
ARM mbed Networking Stack
|
||||
=========================
|
||||
|
||||
## Introduction
|
||||
This is Doxygen generated documentation of Nanostack.
|
||||
It should be used in conjunction with [ARM mbed Networking Stack](https://docs.mbed.com/docs/arm-ipv66lowpan-stack/en/latest/) manual
|
||||
hosted in http://docs.mbed.com
|
||||
|
||||
# API documentation
|
||||
|
||||
See [Files](files.html) section to find a documentation about specific api.
|
|
@ -1,14 +0,0 @@
|
|||
ARM IPV6/6LoWPAN stack.
|
||||
=======================
|
||||
|
||||
This repository contains the ARM IPv6/6LoWPAN/Thread Stack for mbed OS.
|
||||
|
||||
![](docs/img/thread_certified.png)
|
||||
|
||||
mbed OS is now a Thread Certified Component. Using IPv6 with 6LoWPAN as the foundation, Thread technology provides a low-power, self-healing mesh network designed for the home.
|
||||
|
||||
The documentation is hosted in http://docs.mbed.com/projects/arm-ipv66lowpan-stack/
|
||||
|
||||
On mbed OS, usage is through [mbed Mesh API](https://docs.mbed.com/docs/mbed-os-api-reference/en/latest/APIs/communication/mesh/) and [Socket API](https://docs.mbed.com/docs/mbed-os-api-reference/en/latest/APIs/communication/network_sockets/).
|
||||
|
||||
To see, how the 6LoWPAN Stack works, check the example application [mbed-os-example-mesh-minimal](https://github.com/ARMmbed/mbed-os-example-mesh-minimal).
|
|
@ -1,21 +0,0 @@
|
|||
# Welcome to the ARM mbed 6LoWPAN Stack Overview
|
||||
|
||||
|
||||
## About this document
|
||||
|
||||
This document provides third-party developers with an overview of the 6LoWPAN stack. It also outlines the stack architecture and associated standards that the stack implements.
|
||||
|
||||
## Intended audience
|
||||
|
||||
This document has been written for experienced software developers to assist with using the ARM software product range.
|
||||
|
||||
## Using this document
|
||||
|
||||
The document contains three chapters; you can read them in sequence, but they can also be read as stand-alone. They are:
|
||||
|
||||
1. [**Introduction**](02_N_arch.md): Read this to learn more about the 6LoWPAN stack architecture.
|
||||
|
||||
2. [**Usage**](03_N_usage.md): Read this to understand more about the application usage of the 6LoWPAN stack.
|
||||
|
||||
3. [**Networking**](04_N_networking.md): Read this to understand the networking topology and the protocols used.
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
Introduction
|
||||
============
|
||||
|
||||
This chapter introduces the _6LoWPAN stack architecture_. It contains the following sections:
|
||||
|
||||
- [_Architecture._](#architecture)
|
||||
- [_6LoWPAN stack._](#6lowpan-stack)
|
||||
|
||||
## Architecture
|
||||
|
||||
_IPv6 Low power Wireless Personal Area Network_ (6LoWPAN) is an adaptation layer that enables the use of IPv6 over low power wireless and supports IPv6 and _User Datagram Protocol_ (UDP) header compression. The Internet Protocol (IP) header compression allows 6LoWPAN packets to be compact, making it robust and, ideal for low power and lossy networks. It also handles fragmentation and reassembly of packets in scenarios where payloads larger than the _Maximum Transmission Unit_ (MTU) of the supported interface are transferred (a maximum of 1280 bytes).
|
||||
|
||||
The industry leading ARM 6LoWPAN stack is both highly scalable and reliable, but also provides an unrivaled feature set to include a compact source code base and optimal memory usage. Additionally, the 6LoWPAN stack can be supplied with optional software modules for security and embedded web services (mbed Device Server). The modular structure of the design makes it possible for ARM to accommodate most requirements.
|
||||
|
||||
The combination of 6LoWPAN stack and 6LoWPAN border router _Access Point_ (AP) software enables developers to use the extremely flexible and multi-purpose mesh communication solution for most applications (see _Figure 1-1_).
|
||||
|
||||
**Figure 1-1 6LoWPAN network architecture**
|
||||
|
||||
![nw-arc](img/6lowpan_network_architecture.png)
|
||||
|
||||
## 6LoWPAN stack
|
||||
|
||||
The 6LoWPAN stack is modular in design and uses an extremely lightweight event environment that allows the developer to run the stack completely in standalone mode without a need for a third-party _Operating System_ (OS). Additional benefits of the model are lower hardware requirements in the terms of flash and RAM usage. This approach significantly reduces integration effort and, thus, reduces your time-to-market. The stack can also be used in a configuration so that the developer can run it as a task or thread, for example, within a full _Real-time Operating System_ (RTOS). However, this will inevitably increase the system resource requirement because additional resources are required by the RTOS.
|
||||
|
||||
The stack architecture can be divided into four high-level components:
|
||||
|
||||
- Stack core (the event environment).
|
||||
- Protocol modules.
|
||||
- Security components (optional).
|
||||
- Application modules.
|
||||
|
||||
These components are illustrated in _Figure 1-2_.
|
||||
|
||||
**Figure 1-2 The components that comprise the 6LoWPAN stack architecture**
|
||||
|
||||
![stack-arc](img/6lowpan_stack_architecture.png)
|
||||
|
||||
<span class="notes">**Note**: For simplicity, the event core is shown to be part of the same component, alongside the protocol modules.</span>
|
||||
|
||||
### Event core
|
||||
|
||||
The event core is responsible for the low level events, scheduling and system timer functions. The core module provides all the basic functionality that the rest of the modules need (with the exception of the application modules) and is undertaken with a low resource requirement. The design objective has been to reserve and use minimal resources of the hardware platform and, instead, leave all unnecessary timers, for example, unused so that the developer has full control over these resources from the application layer.
|
||||
|
||||
The event system provides the application with the tools and functionality that it needs, for example, to post timed events to itself and create events with specific callback functions.
|
||||
|
||||
The event system relies on Platform API to provide portable set of functions that it needs. These platform drivers are then ported for each operating system or embedded platform you want to run the 6LoWPAN stack.
|
||||
|
||||
### Protocol modules
|
||||
|
||||
The 6LoWPAN stack implements a wide range of protocols as individual modules, which is illustrated in _Figure 1-2_. These modules are designed to use an internal data structure that is used to exchange packets. The stack uses a no-copy design wherever possible because in some modules a packet may be copied to provide a re-transmission functionality, as mandated by related standards.
|
||||
|
||||
The modular design of the 6LoWPAN stack allows some modules to be omitted from the build, for example, excluding the _Transmission Control Protocol_ (TCP) module would disable the TCP transport mechanism.
|
||||
|
||||
At the upper-edge of the 6LoWPAN stack, the Socket _Application Programming Interface_ (API) is exposed (see _Figure 1-2_). This API is designed to provide a _Berkeley Software Distribution_ (BSD) socket-like interface for the application to receive and transmit packets using standard IPv6 address and port number definitions. The function names also roughly follow the BSD socket definitions with some minor modifications due to the nature of the event environment. The intention is to clearly indicate to the developer that minute differences exist between the embedded socket interface and a full BSD socket interface.
|
||||
|
||||
### Optional security components
|
||||
|
||||
The 6LoWPAN stack can be delivered with optional security components. These components provide strong security mechanisms that offer data authentication, device authentication and authorization, and data encryption. The stack supports the following standards:
|
||||
|
||||
- PANA (requires EAP, TLS and SHA-256)
|
||||
- EAP (requires TLS and SHA-256)
|
||||
- TLS1.2 (requires SHA-256)
|
||||
- SHA-256
|
||||
- ECC (ECDSA and ECDHE) (requires X509.3)
|
||||
- X509.3 (requires ECC)
|
||||
|
||||
The _Elliptic Curve Cryptography_ (ECC) component supports the EEC curve NIST-P256 as defined in the Smart Grid standards collection of the _National Institute of Standards and Technology_ (NIST); see [NIST](http://www.nist.gov/smartgrid/). The stack also provides full x509.3 certificate support along with certificate chaining.
|
||||
|
||||
The stack essentially allows the end device to be a part of a full _Public Key Infrastructure_ (PKI) security scheme.
|
||||
|
||||
<span class="notes">**Note**: The 6LoWPAN stack is dependent of the _Advanced Encryption Standard_ (AES)-_Counter Mode Cipher_* (CCM*) component that is part of the core stack.</span>
|
||||
|
||||
### Application modules
|
||||
|
||||
The 6LoWPAN stack runs on a lightweight event-based system that allows low power consumption and minimal latency. Application logic is implemented in a specific event handler called tasklet. The 6LoWPAN stack allows the developer to define multiple tasklets to ease the task of application design. Each of these tasklets can then have full access to the network stack and its features. The system relies on events and does not attempt to provide real multi-thread services, so the developer does not need to be concerned about multiple access to resources.
|
||||
|
||||
One of the most important aspects of an application tasklet design is for the developer to understand how the event environment impacts it. The system does not support the capability for a multi-thread environment.
|
||||
|
||||
The application tasklet must be designed so that it cannot block the execution for an extended period of time. A simple design rule is that a tasklet needs to be implemented in a state machine fashion. The tasklet receives an event that it processes, performs an action, such as reading a sensor value, builds a packet and transmits it, sets up a new timed event, and eventually returns. When the tasklet returns, the event core system schedules the networking stack to take care of the actual transmission of the packet. The delay between the actual transmission of the packet and the `socket_sendto( )` function at the application layer depends on the overall loading of the device at that time. In an otherwise idle situation, the delay is subject to the performance of the processor, but is typically negligible.
|
||||
|
||||
_Figure 1-3_ shows the various protocol modules that make up the 6LoWPAN stack, which are placed alongside the Open Systems Interconnect (OSI) model.
|
||||
|
||||
**Figure 1-3 The 6LoWPAN stack placed alongside the OSI model**
|
||||
|
||||
![osi](img/6lowpan_stack_osi_model.png)
|
||||
|
||||
### Protocol layers and related standards
|
||||
|
||||
The related standards supported by the stack are:
|
||||
|
||||
- 6LoWPAN:
|
||||
* RFC4944
|
||||
* RFC6282
|
||||
* RFC6775
|
||||
- IPv6:
|
||||
* RFC2460
|
||||
* RFC2464
|
||||
* RFC3168 (parts)
|
||||
* RFC4291 (parts)
|
||||
* RFC6040
|
||||
* RFC6437
|
||||
* RFC6946
|
||||
- UDP:
|
||||
* RFC768
|
||||
- TCP:
|
||||
* RFC793 (parts)
|
||||
- RPL:
|
||||
* RFC6550
|
||||
* RFC6552
|
||||
* RFC6553
|
||||
* RFC6554
|
||||
* RFC6719
|
||||
* RFC2473 (parts)
|
||||
- ICMPv6:
|
||||
* RFC4443 (parts)
|
||||
* RFC4861 (parts)
|
||||
* RFC4862 (parts)
|
||||
- MLE:
|
||||
* IETF draft-kelsey-intarea-mesh-link-establishment-06
|
||||
* IEEE802.15.4
|
||||
* IEEE802.15.4-2006 (certified)
|
||||
* IEEE802.15.4g (parts)
|
||||
- MPL:
|
||||
* IETF draft-ietf-roll-trickle-mcast-12 (parts)
|
||||
- AES:
|
||||
* FIPS 197
|
||||
* SP 800-38C
|
||||
- PANA:
|
||||
* RFC5191
|
||||
* RFC6345
|
||||
* RFC6786
|
||||
- EAP:
|
||||
* RFC3748
|
||||
* RFC5216
|
||||
- TLS:
|
||||
* RFC4279
|
||||
* RFC5216
|
||||
* RFC5246
|
||||
* RFC6655
|
||||
* IETF draft-mcgrew-tls-aes-ccm-ecc-05
|
||||
- ECC:
|
||||
* RFC4492
|
||||
* RFC5289
|
||||
* IETF draft-mcgrew-tls-aes-ccm-ecc-05
|
||||
|
||||
### Interfaces
|
||||
|
||||
The 6LoWPAN stack offers application developers programming interfaces for configuring the 6LoWPAN network, defining security levels and sending and receiving packets. The 6LoWPAN stack requires the developers to provide functions for platform specific tasks and network drivers for physical layer. For more information on programming interfaces, see [_ARM mbed 6LoWPAN API Reference Manual_](05_reference.md).
|
||||
|
||||
### Operation modes
|
||||
|
||||
In 6LoWPAN network, the following roles are described in RFCs:
|
||||
<dl>
|
||||
<dt><b>6LoWPAN Node (6LN)</b></dt>
|
||||
<dd>A 6LoWPAN Node is any host or router participating in a network. This term is used when referring to situations in which either a host or router can play the role described.</dd>
|
||||
|
||||
<dt><b>6LoWPAN Router (6LR)</b></dt>
|
||||
<dd>A node that can route packets. This role is required to form a topological or mesh network.</dd>
|
||||
|
||||
<dt><b>6LoWPAN Border Router (6LBR)</b></dt>
|
||||
<dd>A border router located in between a 6LoWPAN network and IPv6 network. A 6LBR is the responsible authority for IPv6 Prefix propagation for the 6LoWPAN network it is serving.</dd>
|
||||
</dl>
|
||||
|
||||
A device running a 6LoWPAN stack can be configured in runtime to be in one of three modes:
|
||||
|
||||
- Router:
|
||||
* Is effectively a 6LoWPAN Router (6LR).
|
||||
* Routes packets to and from other devices in the network.
|
||||
* Typically always-on, that is, radio always on.
|
||||
* Stack automatically reduces power consumption by placing the processor into sleep when in idle, so that no packets are routed or processed.
|
||||
- Host:
|
||||
* Is a 6LoWPAN node (6LN) with no routing capability.
|
||||
* Does not route packets to and from other devices in the network.
|
||||
* Typically RF always on.
|
||||
* Can sleep, but parent router does not cache packets destined to this device.
|
||||
- Sleepy host:
|
||||
* Is a 6LoWPAN node (6LN) with no routing capability and utilizes prolonged sleep periods.
|
||||
* Does not route packets to and from other devices in the network.
|
||||
* Typically in sleep for prolonged time periods.
|
||||
* Duty cycle often less than 1%.
|
||||
* Wakes up due to timer trigger or external interrupt, performs some action, polls for data from parent router and goes back to sleep.
|
||||
* An MLE protocol or alternative is required.
|
||||
* May shut down the radio when sleeping.
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
Usage
|
||||
=====
|
||||
|
||||
This chapter describes the application usage of the 6LoWPAN stack. It contains the following sections:
|
||||
|
||||
- [_Application support_](#application-support)
|
||||
- [_Transmitting and receiving data_](#transmitting-and-receiving-data)
|
||||
- [_Features_](#features)
|
||||
- [_Hardware requirements_](#hardware-requirements)
|
||||
- [_Delivery models_](#delivery-models)
|
||||
- [_Interoperability with the 6LoWPAN border router_](#interoperability-with-the-6lowpan-border-router)
|
||||
|
||||
## Application support
|
||||
|
||||
The application running on top of the 6LoWPAN stack will follow some basic principles. Most crucially, all functions must return following any call. The exact time, that is, how long the application tasklet can block the operation varies according to how congested the network is. If the device is a router, meaning that it routes packets to and from other devices, the network is locally under heavy load and the stack will require additional time to perform routing.
|
||||
|
||||
## Transmitting and receiving data
|
||||
|
||||
TCP, UDP, or ICMP packets can be sent and received using the socket interface APIs that are exposed by the 6LoWPAN stack. Data can be sent using the `socket_send()` and `socket_sendto()` functions for TCP and UDP/ICMP, respectively.
|
||||
|
||||
For UDP/ICMP, a socket is ready to send and receive data after a successful call to `socket_open()` and when the `NET_READY` event has been received.
|
||||
|
||||
For TCP, when a socket is opened it is in _closed_ state. It must be set to either _listen_ or _connect_ state before using it for receiving or transmitting data. To receive data, the socket can be set to listen mode by calling `socket_listen()`. After that, the socket can accept an incoming connection from a remote host. To send data, `socket_connect()` is called with a set of arguments. When the socket event has confirmed the state change of the socket, data can then be sent using `socket_send()`. The function call `socket_shutdown()` is used to shut down the socket.
|
||||
|
||||
## Features
|
||||
|
||||
This section describes the typical features that are available to developers within the 6LoWPAN stack.
|
||||
|
||||
### Link security
|
||||
|
||||
There are three methods of using security with the 6LoWPAN stack, of which the first two use AES-128 encryption:
|
||||
|
||||
- Pre-shared network key (where the network key is provisioned at manufacturing).
|
||||
- Certificate-based security using _Protocol for carrying Authentication for Network Access_ (PANA) and _Extensible Authentication Protocol (EAP)-Transport Layer Security_ (TLS), in which case the PANA Server defines the network key material.
|
||||
- No security.
|
||||
|
||||
### Power saving features
|
||||
|
||||
The power saving features of the 6LoWPAN stack are enabled by default. For router devices, the stack automatically reduces power consumption by placing the processor into sleep when in idle, that is, no packets to route or process.
|
||||
|
||||
There are two sleep modes available:
|
||||
|
||||
- Default sleep mode:
|
||||
* This is where the host node wakes up periodically every ~7.5 seconds to check for packets being relayed from its parent router.
|
||||
- Long sleep mode:
|
||||
* This is where the application can control how long the node will sleep by using a timer event or external event such as an external interrupt to trigger the wake-up process.
|
||||
|
||||
## Hardware requirements
|
||||
|
||||
The 6LoWPAN stack is designed to support most platforms, even those with modest hardware resources. It supports the Cortex-M architecture, ranging from Cortex-M0 to more powerful Cortex-M4 processors.
|
||||
|
||||
The minimum recommended code space for a full featured 6LoWPAN stack is roughly 256KB on a 32-bit processor architecture without the optional security modules; including the security components adds approximately 17KB to the code size.
|
||||
|
||||
The data memory requirements are driven mainly by the scalability throughput requirements. Minimal stack features along with a simple application template can be supported on platforms with 8KB of memory. Additional features such as high security or embedded web services (mbed Device Server) will increase the memory requirement.
|
||||
|
||||
## Delivery models
|
||||
|
||||
The most common delivery method of the 6LoWPAN stack contains source code for a specific CPU, example applications, and device drivers for multiple MCUs and RF transceivers. The source code, drivers and applications are provided as an example for developers to get familiar with the 6LoWPAN stack.
|
||||
|
||||
The 6LoWPAN stack is built so that it eventually supports multiple toolchains. However, some RF drivers require compiler-specific code or headers. Therefore, driver support per each toolchain varies.
|
||||
|
||||
The initial release of ARM 6LoWPAN stack only supports the ARM GCC compiler for ARM Cortex-M class microcontrollers.
|
||||
|
||||
## Interoperability with the 6LoWPAN border router
|
||||
|
||||
The 6LoWPAN stack is designed to operate in RPL enabled networks, which means that the network must have a 6LoWPAN border router access point present.
|
||||
|
||||
Each M2M network uses an access point (or edge router) that allows it to connect seamlessly to a standard IP network. ARM 6LoWPAN border router software provides seamless handling of routing packets between the 6LoWPAN and the IP network. The 6LoWPAN border router software is available as an embedded C implementation running on Cortex M3/M4 processors (see _Figure 1-4_).
|
||||
|
||||
**Figure 1-4 6LoWPAN border router architecture with an embedded C implementation**
|
||||
|
||||
![img 1](img/6lowpan_border_router_embedded_C_architecture.png)
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
Networking
|
||||
==========
|
||||
|
||||
This chapter discusses the networking topology and the protocols used. It contains the following sections:
|
||||
|
||||
- [_Networking topology_](#networking-topology)
|
||||
- [_MAC_](#mac)
|
||||
- [_UDP_](#udp)
|
||||
- [_TCP_](#tcp)
|
||||
- [_RPL routing_](#rpl-routing)
|
||||
- [_Network join process_](#network-join-process)
|
||||
- [_Network rejoin process_](#network-rejoin-process)
|
||||
- [_Automatic network healing process_](#automatic-network-healing-process)
|
||||
|
||||
## Networking topology
|
||||
|
||||
The 6LoWPAN stack uses two types of networking topology, namely the star and tree topologies, as shown in _Figure 1-5_.
|
||||
|
||||
**Figure 1-5 Networking topologies supported by the 6LoWPAN stack ecosystem**
|
||||
|
||||
![nw-topologies](img/6lowpan_stack_networking_topologies.png)
|
||||
|
||||
## MAC
|
||||
|
||||
The _Media Access Control_ (MAC) implementation is based on the IEEE802.15.4-2006 standard (see [MAC]) and is used for MAC layer communication between nodes such as beacon scans and responses, and data requests and indications. The MAC implementation has already been certified on multiple platforms.
|
||||
|
||||
The MAC implements the non-beacon enabled modes of the standard. It does not implement _Guaranteed Time Slot_ (GTS).
|
||||
|
||||
## UDP
|
||||
|
||||
The 6LoWPAN stack supports the UDP transport protocol. Applications can use the Socket API to send and receive data using UDP sockets. UDP is typically used by applications to deliver short messages over IP. It is an unreliable, connectionless protocol, but can be used for broadcast and multicast messages. The advantage of UDP is that it does not require any kind of connection formation or handshake process to take place prior to communication. UDP is the classic fire-and-forget transport mechanism that combines inherent low reliability, requiring minimal overhead.
|
||||
|
||||
A disadvantage of UDP can easily be mitigated by using a simple application layer, end-to-end acknowledgment scheme. As an efficient and scalable example of such a solution, see the _Constrained Application Protocol_
|
||||
(CoAP) _Acknowledgement_ (ACK) mechanism as defined in [CoAP](http://tools.ietf.org/html/rfc7252).
|
||||
|
||||
## TCP
|
||||
|
||||
The 6LoWPAN stack supports the _Transmission Control Protocol_ (TCP) and applications can use the socket interface APIs of the stack to send and receive data using TCP sockets. Applications requiring a reliable, ordered transport for a stream of bytes can typically use TCP. However, TCP is not suitable for every application because it only supports unicast communication and reacts badly to packet loss. TCP is not suitable for very short transactions because the ratio of overhead to application data typically increases fairly quickly. Additionally, the use of TCP can have very adverse effects on the power consumption of a device because of the duration of the TCP handshake process.
|
||||
|
||||
## RPL routing
|
||||
|
||||
_Routing Protocol for Low power and Lossy networks_ (RPL) is a distance vector IPv6 routing protocol defined in the _Internet Engineering Task Force_ (IETF) for low power and lossy networks that specifies how to build a _Destination Oriented Directed Acyclic Graph_ (DODAG) using an objective function and a set of metrics and constraints. RPL is optimized for a many-to-one topology. Neighbors keep route records of the edge router as a final destination. The reverse route, or source route, is kept by the edge router and is used for sending data to any node in the network it has a route for. When a node sends a packet to another node, the packet travels up to a common ancestor in the DAG, at which point it is forwarded in the down direction to the destination.
|
||||
|
||||
## Network join process
|
||||
|
||||
The developer has full control as to when the 6LoWPAN stack attempts to join a network. The developer has the possibility to configure a channel, _Personal Area Network Identifier_ (PANID) and 128-bit _Network Identifier_ (NWKID) masks to filter out both unwanted channels or networks. With a few simple function calls the developer can inform the stack to initiate either a passive energy scan or a beacon scan to select channels. Network PANIDs and NWKIDs will be filtered and non-matching networks will be silently discarded. The stack will then proceed to perform the network level bootstrapping according to [6LOWPAN-ND](https://datatracker.ietf.org). When the stack joins a network or no network is found, the developer is notified using a standard system event. If the stack has not joined a network, the developer has the option to 1) select alternative parameters; 2) cease further attempts to join a network or 3) continue to retry the joining process. The stack will make no attempt to join a network when it informs the application layer of an unsuccessful attempt. However, the stack may choose to retry using the initial parameters.
|
||||
|
||||
**Figure 1-6 High level view of the network bootstrap process when using network authentication**
|
||||
|
||||
![high-level](img/network_bootstrap_high_level_view.png)
|
||||
|
||||
### Join a 6LoWPAN network
|
||||
|
||||
The initial process of joining a network involves a MAC level association where the node will perform a MAC beacon scan using the channels in its channel list. The resulting beacon will ignore responses from neighboring nodes using the beacon protocol ID filter where the node will associate with the best parent router in the network, typically the highest _Link Quality Indicator_ (LQI) that has a matching PANID. The node will then perform a _Mesh Link Establishment_ (MLE) request to the parent router, as well as other routers that have responded to the initial beacon scan. If the chosen router did not respond to the MLE request, the node will select a new router from the beacon scan results.
|
||||
|
||||
Subsequently, a node in a 6LoWPAN mesh network initiates the _6LoWPAN Neighbor Discovery_ (6LoWPAN-ND) process. The neighbor discovery protocol handles address assignment including _Duplicate Address Detection_ (DAD) and registration with the edge router. The edge router keeps a whiteboard of all nodes that have joined the 6LoWPAN network. In a 6LoWPAN mesh, the registration process is repeated over multiple hops for routers or host devices that are not adjacent to the edge router. The RPL is only for the router.
|
||||
|
||||
The last step, excluding anything above the RPL modules, is the RPL topology formation. The RPL DODAG formation is a multiphase process where the joining node actively attempts to find the best available parent to use for registration to the _6LoWPAN border router_ (6LBR).
|
||||
|
||||
_Figure 1-7_ shows the _6LoWPAN Node_ (6LN) join process to a 6LBR using a _6LoWPAN Router_ (6LR) in a mesh topology configuration. In the illustration, the vertical axis represents time. The 6LN will typically receive multiple
|
||||
_Router Advertisement_ (RA) messages.
|
||||
|
||||
**Figure 1-7 The join process for a mesh topology**
|
||||
|
||||
![join-mesh](img/join_process_to_router_mesh_6lowpan.png)
|
||||
|
||||
**Figure 1-8 High level state machine description for network bootstrap**
|
||||
|
||||
![state-machine](img/state_machine_6lowpan.png)
|
||||
|
||||
_Figure 1-9_ shows the RPL layer registration and topology formation process message flow for a scenario where the joining node may use multiple hops from the 6LBR.
|
||||
|
||||
<span class="notes">**Note**: The joining device can receive multiple DIO messages.</span>
|
||||
|
||||
**Figure 1-9 RPL routing layer message flow for multiple hops**
|
||||
|
||||
![rpl-multiple](img/rpl_layer_reg_multiple_hops.png)
|
||||
|
||||
**Figure 1-10 High level view of a mesh topology**
|
||||
|
||||
![rpl-high-level](img/rpl_mesh_high_level_view.png)
|
||||
|
||||
### Join a star network
|
||||
|
||||
The joining process for a node in a 6LoWPAN star network uses the same process as mentioned in _Join a 6LoWPAN network_. However, a star network differs insofar as the registration process is only undertaken as a one-hop sequence with the edge router.
|
||||
|
||||
_Figure 1-11_ shows the _Wireless Personal Area Network_ (WPAN) node (6LN) join process to a 6LBR in a star topology configuration. In the illustration, the vertical axis represents time.
|
||||
|
||||
<span class="notes">**Note**: Typically the 6LN will receive multiple RA messages.</span>
|
||||
|
||||
**Figure 1-11 6LoWPAN join process to a border router**
|
||||
|
||||
![join-star](img/join_process_star_6lowpan_router.png)
|
||||
|
||||
Figure 1-12_ shows the RPL layer registration and topology formation process message sequence for a scenario where the joining node is a single hop from the 6LBR.
|
||||
|
||||
<span class="notes">**Note**: The joining device can receive multiple DIO messages.</span>
|
||||
|
||||
**Figure 1-12 The RPL layer registration formation process**
|
||||
|
||||
![rpl-single](img/rpl_layer_reg_single_hop.png)
|
||||
|
||||
## Network rejoin process
|
||||
|
||||
If a device with the 6LoWPAN stack is forced into sleep mode for an extended period of time so that its registration with the 6LBR has expired, the stack will automatically detect this and update its registration. The stack is then ready for communication without any further action from the application when the device wakes up.
|
||||
|
||||
The exact time that it takes for the stack to refresh the registration depends on whether a full mesh network topology or a star topology is used. Additionally, in the mesh network scenario the exact location of the device (depth from the 6LBR to be specific) in the mesh has a small impact on the time when full networking capabilities are restored.
|
||||
|
||||
## Automatic network healing process
|
||||
|
||||
It is fairly common for the RF channel to change even if the physical location of the actual mesh network has not. The network must then adapt to the new channel immediately and with ease.
|
||||
|
||||
The standards that the 6LoWPAN stack uses provide feedback from multiple protocol layers, such as, the MAC, network, and routing layers. This multiple layer approach provides the stack with numerous sources of information that can be used to make automatic decisions as to when network reconfiguration can be initiated. It can also be delivered to other devices in the IP network using standard _Internet Control Message Protocol_ (ICMP)v6 messages. More specifically, these messages can either be ICMPv6 Destination Unreachable or No Route To Host types.
|
||||
|
||||
### MAC layer
|
||||
|
||||
When repeated notifications of _layer two_ (L2) ACKs are not passed up to the higher layers, a possible lost connection has occurred. If the ACK messages are lost from a parent device in the routing topology, this results in one of the following actions: 1) switch to a secondary parent, that is, an alternative parent that has been stored for backup; or 2) the stack should initiate a local network reconfiguration.
|
||||
|
||||
If the L2 ACKs are missing from a child node, the routing node typically transmits an ICMPv6 error message to the originator of the packet. If an application on the device itself is the originator, the application is notified of the error using a system event.
|
||||
|
||||
### Network layer
|
||||
|
||||
If the MAC layer informs _layer three_ (L3) of a connectivity issue toward the parent network, it becomes the responsibility of L3 to reconfigure the network. This is achieved simply by transmitting multicast _Router Solicitation_ (RS) messages using the configured channel in an attempt to find an alternative parent. Since 6LR and 6LBR devices that have already joined the RPL DODAG reply to RS messages with RA messages, the scanning device can be certain that all replies come from devices that are capable of routing packets. This step essentially ensures that the device can join a new network if the 6LBR, of the previously used network, has become unusable. It is important to understand that the 6LoWPAN-ND process is not used to form the network topology, but merely to establish the IPv6 prefix context information and the identities of the available
|
||||
(direct or multihop) 6LBR devices.
|
||||
|
||||
### Routing layer
|
||||
|
||||
If the device has made the decision to perform local reconfiguration and has updated the 6LoWPAN network information using the 6LoWPAN-ND process, the next step is to (re-)join the RPL DODAG. To achieve this, the device will follow the standard RPL network join process as described in [_Join a 6LoWPAN network_](#join-a-6lowpan-network).
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
#ARM mbed Networking Stack API Reference Manual
|
||||
|
||||
## About this manual
|
||||
|
||||
This manual describes the APIs regarding the ARM mbed Networking stack, for example, 6LoWPAN related APIs, Thread stack related APIs, General network related APIs, Socket APIs, Event OS APIs, Platform API, and Driver API.
|
||||
|
||||
As Thread runs on top of the 6LoWPAN stack, most of the networking stack functionality is shared. However, when building the stack you can cherry-pick the features, configurations or functionalities. In such case, please refer to [Build time configurations](quick_start_build.md).
|
||||
|
||||
To read even more of the APIs, check the [Doxygen documentation](https://docs.mbed.com/docs/arm-ipv66lowpan-stack/en/latest/api/index.html).
|
||||
|
||||
## Intended audience
|
||||
|
||||
This manual has been written for experienced software developers to assist with using the ARM software product range.
|
||||
|
||||
## Using this manual
|
||||
|
||||
The reference manual contains several chapters; you can read them in sequence, but they can also be read as stand-alone. They are:
|
||||
|
||||
1. [**Introduction to APIs**](06_API_introduction.md): Read this to understand more about the 6LoWPAN stack from API perspective.
|
||||
|
||||
2. [**IPv6/6LoWPAN Stack Initialization**](07_API_initialize.md): Read this to understand how to initialize the IPv6/6LoWPAN stack.
|
||||
|
||||
3. [**An Event-driven Scheduling Model**](08_API_events.md): Read this to understand more about the event-driven scheduling model. If you are using ARM mbed OS, skip this.
|
||||
|
||||
4. [**Platform API**](platform_API.md): Brief description of Platform API. Detailed discussion in Porting section.
|
||||
|
||||
5. [**Device Driver API**](driver_api.md): Brief description of Device Driver API. Detailed discussion in Porting section.
|
||||
|
||||
|
||||
6. [**Network API Definitions**](09_API_network_def.md): Read this to understand more about the network API definitions.
|
||||
|
||||
7. [**Library Timer API**](10_API_timer.md): Read this to understand more about the timer functionality.
|
||||
|
||||
8. [**Sockets Use and Available APIs**](11_API_sockets.md): Read this to understand more about socket use and the available APIs.
|
||||
|
||||
9. [**The Network Control Layer**](12_API_network.md): Read this to understand the functions of the network control layer.
|
||||
|
||||
10. [**Dynamic Memory API**](13_API_memory.md): Read this for an introduction to the dynamic memory API of the 6LoWPAN stack.
|
||||
|
||||
11. [**Data Structures, Types and Variables**](14_API_data.md): Read this to understand the data structure, types and variables used in the socket and RF layers.
|
||||
|
||||
12. [**Debug Statistics Interface API**](15_API_debug.md): Read this to understand the debug statistics interface API.
|
||||
|
||||
13. [**Thread Related APIs**](thread_APIs.md):Read this to familiarize yourself with the Thread protocol related APIs.
|
||||
|
||||
14. [**Load balancing API**](17_API_load_balancer.md):Read this to familiarize yourself with the Load balancing API
|
||||
|
||||
15. [**Warm restart**](18_warm_restart.md):Read this to familiarize yourself with the Warm restart feature
|
||||
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
API Introduction
|
||||
============
|
||||
|
||||
Thread protocol is a wrapping around the IPv6/6LoWPAN stack, and it is capable to work stand-alone in bare-metal implementations. In subsequent chapters of this manual, we walk through the base of the networking stack that is IPv6/6LoWPAN and proceed further to Thread.
|
||||
|
||||
**Figure 3-1 High level API interfaces over Networking stack**
|
||||
|
||||
![High level design Architecture](img/arch_general.png)
|
||||
|
||||
|
||||
|
||||
This chapter is an introduction to the 6LoWPAN stack, modules and API interfaces. It contains the following sections:
|
||||
|
||||
- [_About the 6LoWPAN stack_](#about-the-6lowpan-stack)
|
||||
- [_Eventing system_](#eventing-system)
|
||||
|
||||
|
||||
## About the 6LoWPAN stack
|
||||
|
||||
The 6LoWPAN stack is designed to be portable for various platforms and radio drivers. It uses a lightweight eventing system that allows to run on minimal design on the smallest microcontrollers even without operating systems. The application programming interfaces are designed to allow porting for new platforms. _Figure 3-2_ shows the high level APIs on the 6LoWPAN stack.
|
||||
|
||||
**Figure 3-2 High level API interfaces over 6LoWPAN stack**
|
||||
|
||||
![Bare metal 6LoWPAN](img/high_level_stack_API_interfaces.png)
|
||||
|
||||
The 6LoWPAN stack provides application designers with interfaces for sending and receiving packets, configuring the network and running the event base system in the form of tasklets. For more information on the interfaces, see chapters [_An Event-driven Scheduling Model_](08_API_events.md), [_Network API Definitions_](09_API_network_def.md) and [_Sockets Use and Available APIs_](11_API_sockets.md).
|
||||
|
||||
The 6LoWPAN stack relies on two interfaces that must be ported to run it on a specific platform. Platform API defines an abstraction layer of the underlying microcontrollers or operating system. For more information on the Platform API, see section _Platform API_ in chapter [_Porting 6LoWPAN Stack_](16_API_porting.md).
|
||||
|
||||
PHY driver API is an abstraction between the driver and the 6LoWPAN stack and allows 6LoWPAN network to be formed on any 802.15.4 compatible or similar radio chip. The PHY driver API is not limited to only radio chips, even serial communication may be used. For more information on the PHY driver API, see [_Device Driver API_](driver_api.md).
|
||||
|
||||
For more information on the 6LoWPAN stack architecture, and the protocol and application modules used by the 6LoWPAN stack, see [_ARM mbed 6LoWPAN Stack Overview_](01_overview.md).
|
||||
|
||||
## Eventing system
|
||||
|
||||
6LoWPAN stack eventing system is designed to be minimal and portable. Its main focus is on running in small embedded devices without any help of operating systems. The event-based approach allows 6LoWPAN stack based applications to be designed for extremely low power use cases where thread (not to be confused with Thread, the stack) based systems may consume too much battery life. The eventing system is designed to rely entirely on the Platform API so it is possible to port it to run on any operating system when the thread based approach is favored.
|
||||
|
||||
The eventing system specifies event handlers (tasklets) that form the application logic. The 6LoWPAN stack allows developers to define multiple tasklets to ease the task of writing complex applications. Each of these tasklets can then have full access to the network stack and its features through Socket, Eventing and NET APIs.
|
||||
|
||||
The following example shows the usage of a simple tasklet:
|
||||
|
||||
```
|
||||
/* Main event handler */
|
||||
void tasklet_main(arm_event_s *event)
|
||||
{
|
||||
switch(event->event_type) {
|
||||
case ARM_LIB_TASKLET_INIT_EVENT:
|
||||
// Initialzation event is given when tasklet is created.
|
||||
// It will be called after a tasklet is registered to event OS.
|
||||
|
||||
// Launch timer event to fire after a second
|
||||
timer_sys_event(MY_TX_TIMER, T_1000_MS);
|
||||
break;
|
||||
case ARM_LIB_SYSTEM_TIMER_EVENT:
|
||||
// Timer events are received in tasklet
|
||||
// Using a event type TIMER_EVENT
|
||||
// They receive 8bit identifier that
|
||||
// was passed to timer_sys_event().
|
||||
switch(event->event_id) {
|
||||
case MY_TX_TIMER:
|
||||
send_sensor_info();
|
||||
timer_sys_event(MY_TX_TIMER, T_1000_MS); //Relaunch
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
int8_t tasklet_id;
|
||||
eventOS_scheduler_init();
|
||||
eventOS_event_handler_create(&tasklet_main, ARM_LIB_TASKLET_INIT_EVENT);
|
||||
eventOS_scheduler_run(); // Enter the event loop
|
||||
}
|
||||
```
|
||||
|
||||
In this code example, the main application registers an event handler called `tasklet_main`. This event handler is then used to send and receive timed events in one-second intervals. For a description of the functions and their parameters, see chapter [_An Event-driven Scheduling Model_](08_API_events.md).
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
IPv6/6LoWPAN Stack Initialization
|
||||
===============================
|
||||
|
||||
This chapter describes the 6LoWPAN stack initialization sequence. It contains the following sections:
|
||||
|
||||
- [_About initalization_](#about-initalization)
|
||||
- [_Stack initialize sequence_](#stack-initialize-sequence)
|
||||
- [_How to configure a network interface_](#how-to-configure-a-network-interface)
|
||||
|
||||
## About initalization
|
||||
|
||||
To bring the 6LoWPAN stack into use, follow these instructions:
|
||||
|
||||
1. To initialize the event OS, call `eventOS_scheduler_init()`.
|
||||
2. To initialize the 6LoWPAN stack and platform, call `net_init_core()`.
|
||||
3. To allocate a dynamic tasklet for an application, call `eventOS_event_handler_create()`.
|
||||
4. Configure an interface and network.
|
||||
|
||||
## Stack initialize sequence
|
||||
|
||||
Perform stack initialization in the `main( )` function, as follows:
|
||||
|
||||
1. To initialize the event OS, call `eventOS_scheduler_init()`.
|
||||
2. To initialize the 6LoWPAN stack, call `net_init_core()`.
|
||||
3. To start the event dispatch loop, call `eventOS_scheduler_run();`. The 6LoWPAN stack scheduler will now run in an infinite loop.
|
||||
|
||||
The `eventOS_scheduler_run()` function call starts the processing of the 6LoWPAN stack events. This function is an infinite loop where the processor cannot execute any commands below the `eventOS_scheduler_run()` call.
|
||||
|
||||
An example 6LoWPAN stack initialization sequence:
|
||||
|
||||
```
|
||||
void main(void)
|
||||
{
|
||||
// Run any platform specific
|
||||
// initialization here
|
||||
board_init();
|
||||
// Initialize 6LoWPAN stack
|
||||
eventOS_scheduler_init();
|
||||
net_init_core();
|
||||
// Register a tasklet
|
||||
tasklet_id = eventOS_event_handler_create(&tasklet_main,
|
||||
ARM_LIB_TASKLET_INIT_EVENT);
|
||||
// Enter the event loop
|
||||
eventOS_scheduler_run();
|
||||
}
|
||||
```
|
||||
|
||||
## How to configure a network interface
|
||||
|
||||
To effectively use the 6LoWPAN stack, you must run at least one tasklet. Some API interfaces require tasklets for handling incoming events. The following resources must be configured from a tasklet:
|
||||
|
||||
- Interface:
|
||||
- When you generate an interface it is tied to the registering tasklet. If the application removes the tasklet, the interface events do not work anymore.
|
||||
|
||||
- Sockets:
|
||||
- When the sockets are generated, they are also tied to the tasklet used in registration.
|
||||
|
||||
To configure a network interface, follow these instructions:
|
||||
|
||||
1. To create an interface, call the function:
|
||||
* 802.15.4 `arm_nwk_interface_lowpan_init()`.
|
||||
* Ethernet or other `arm_nwk_interface_ethernet_init()`.
|
||||
2. To define the 6LoWPAN bootstrap, call the function `arm_nwk_interface_configure_6lowpan_bootstrap_set()`.
|
||||
3. To configure the 6LoWPAN link layer security, call the function `arm_nwk_6lowpan_link_layer_security_mode()`.
|
||||
4. (Optional) To configure the 6LoWPAN address mode, call the function `arm_nwk_6lowpan_gp_address_mode()`.
|
||||
5. (Optional) To configure the 6LoWPAN node NWK scan parameters, call the function `arm_nwk_6lowpan_link_scan_parameter_set()`.
|
||||
6. (Optional) To configure the 6LoWPAN node NWK scan filters, call the functions:
|
||||
* PAN ID: `arm_nwk_6lowpan_link_panid_filter_for_nwk_scan()`.
|
||||
* Network ID: `arm_nwk_6lowpan_link_nwk_id_filter_for_nwk_scan().`
|
||||
* Protocol ID: `arm_nwk_6lowpan_link_protocol_id_filter_for_nwk_scan()`.
|
||||
7. (Optional) To configure the PANA, if it is activated for link layer security, call the functions:
|
||||
* Server: `arm_pana_server_library_init()`.
|
||||
* Client: `arm_pana_client_library_init()`.
|
||||
8. To start the interface, call the function `arm_nwk_interface_up()`.
|
|
@ -1,307 +0,0 @@
|
|||
An Event-driven Scheduling Model & Eventing API
|
||||
================================
|
||||
This chapter describes the event-driven scheduling model. It contains the following sections:
|
||||
|
||||
- [_API Headers_](#api-headers)
|
||||
- [_About events_](#about-events)
|
||||
- [_Dynamic tasklet_](#dynamic-tasklet)
|
||||
- [_Event structure_](#event-structure)
|
||||
- [_Events sent by the stack_](#events-sent-by-the-stack)
|
||||
- [_Sending application-specific events_](#sending-application-specific-events)
|
||||
|
||||
## API Headers
|
||||
|
||||
To use the eventing API, include the following headers to your application:
|
||||
|
||||
```
|
||||
#include eventOS_event.h
|
||||
#include net_interface.h
|
||||
```
|
||||
|
||||
## About events
|
||||
|
||||
The 6LoWPAN stack uses an event-driven scheduling model and this section describes the event functionality at the application layer.
|
||||
|
||||
### Handling events
|
||||
|
||||
An application should register at least one event handler. The tasklets are then used to send and receive events between the stack or between other tasklets. Also socket events are sent to a tasklet that opened them.
|
||||
|
||||
The following is a prototype of a tasklet:
|
||||
|
||||
```
|
||||
void tasklet (arm_event_t *)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`arm_event_t`|A pointer to the event structure that contains the event information.
|
||||
|
||||
|
||||
The most important event information is the event type. There are four main types of events that a tasklet may receive. _Table 3-2_ lists the event types.
|
||||
|
||||
**Table 3-2 Event types**
|
||||
|
||||
Event type|Description
|
||||
----------|-----------
|
||||
`ARM_LIB_TASKLET_INIT_EVENT`|Can be used as an initialization event to a tasklet, when it is created. The initialization event is called only once.
|
||||
`ARM_LIB_NWK_INTERFACE_EVENT`|These event types give information about networking bootstrap to the application layer.
|
||||
`ARM_LIB_SYSTEM_TIMER_EVENT`|These events are user-launched timer events. They are used for timing events on an application.
|
||||
`APPLICATION_EVENT`|These events are sent from another tasklet and they do not originate from the stack. These are used for communicating between tasklets.
|
||||
|
||||
|
||||
The rest of the information is stored in the event structure received by the tasklet. For more information on the structure content, see section [_Event structure_](#event-structure).
|
||||
|
||||
The following example shows the basic structure of an empty tasklet:
|
||||
|
||||
```
|
||||
void tasklet(arm_event_t *event)
|
||||
{
|
||||
switch(event->event_type) {
|
||||
case ARM_LIB_TASKLET_INIT_EVENT:
|
||||
// Initialization tasks
|
||||
break;
|
||||
case ARM_LIB_NWK_INTERFACE_EVENT:
|
||||
// Network bootstrap events
|
||||
break;
|
||||
case ARM_LIB_SYSTEM_TIMER_EVENT:
|
||||
// Timers
|
||||
break;
|
||||
case APPLICATION_EVENT:
|
||||
// Application specific events
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Dynamic tasklet
|
||||
|
||||
With a dynamic tasklet, you can easily generate a small tasklet for an application.
|
||||
|
||||
### Register a tasklet
|
||||
|
||||
To register a tasklet handler:
|
||||
|
||||
```
|
||||
int8_t eventOS_event_handler_create
|
||||
(
|
||||
void (*tasklet_func_ptr)(arm_event_t*),
|
||||
uint8_t init_event_type
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`tasklet_func_ptr`|A function pointer to a tasklet event handler.
|
||||
`init_event_type`|An event type to be created when a tasklet handler is created. Usually, `ARM_LIB_TASKLET_INIT_EVENT`.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>>=0 Tasklet ID.</dd>
|
||||
<dd><0 Tasklet allocation fails.</dd>
|
||||
</dl>
|
||||
|
||||
## Event structure
|
||||
|
||||
Event structure is used to transfer information between the stack and tasklet or between tasklets. This structure is received by the tasklet when the event arrives. The tasklet uses this structure to find all information about the received event. The event structure comprises the following members:
|
||||
|
||||
```
|
||||
typedef struct arm_event_s
|
||||
{
|
||||
int8_t receiver;
|
||||
int8_t sender;
|
||||
uint8_t event_type;
|
||||
uint8_t event_id;
|
||||
void *data_ptr;
|
||||
arm_library_event_priority_e priority;
|
||||
uint32_t event_data;
|
||||
} arm_event_t;
|
||||
```
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`receiver`|Event tasklet handler ID.
|
||||
`sender`|Event tasklet sender ID. Zero means the sender is the stack.
|
||||
`event_type`|Represents the `typecast arm_library_event_type_e`.
|
||||
`event_id`|Timer ID, NWK interface ID or an application-specific ID.
|
||||
`data_ptr`|Application's ability to share a data pointer tasklet with a tasklet.
|
||||
`priority`|Event priority.
|
||||
`event_data`|Extra event data. Used in network events.
|
||||
|
||||
### Reference events
|
||||
|
||||
_Tables 3-3, 3-4 and 3-5_ below show some examples of different events within the system.
|
||||
|
||||
**Table 3-3 System timer event for timer ID 1**
|
||||
|
||||
Name|Value
|
||||
----|-----
|
||||
`receiver`|`tasklet id for timer order`
|
||||
`sender`|`0 (zero means the stack)`
|
||||
`event_type`|`ARM_LIB_SYSTEM_TIMER_EVENT:`
|
||||
`event_id`|`1`
|
||||
|
||||
**Table 3-4 Network ready event**
|
||||
|
||||
Name|Value
|
||||
----|-----
|
||||
`receiver`|`tasklet id for interface owner`
|
||||
`sender`|`0`
|
||||
`event_id`|`interface id for current event`
|
||||
`event_type`|`ARM_LIB_NWK_INTERFACE_EVENT:`
|
||||
`event_data`|`(arm_nwk_interface_status_type_e) event information for interface`
|
||||
|
||||
**Table 3-5 Tasklet init event**
|
||||
|
||||
Name|Value
|
||||
----|-----
|
||||
`receiver`|`tasklet id for timer order`
|
||||
`sender`|`0`
|
||||
`event_type`|`ARM_LIB_TASKLET_INIT_EVENT:`
|
||||
|
||||
## Events sent by the stack
|
||||
|
||||
This section describes all the events sent by the stack.
|
||||
|
||||
### Tasklet initialization event
|
||||
|
||||
When creating a tasklet, an initialization event type is defined as a parameter in a function call. The tasklet receives it after the startup. Usually, `ARM_LIB_TASKLET_INIT_EVENT` is used for this purpose. Typically, when an initialization event has been received, the application will set up all interfaces and open up the sockets for network communication.
|
||||
|
||||
### Timer events
|
||||
For information on timer events, see Chapter [_Library Timer API_](10_API_timer.md).
|
||||
|
||||
### Network interface event
|
||||
|
||||
Network interface events `ARM_LIB_NWK_INTERFACE_EVENT` are enabled after the interface has been started with an `arm_nwk_interface_up()` function call or after an indicated network failure status. The stack uses the events to inform the application of the network connection status. Possible event types are described in _Table 3-6._
|
||||
|
||||
**Table 3-6 Possible event types for network interface event**
|
||||
|
||||
Event type|Description
|
||||
----------|-----------
|
||||
`ARM_NWK_BOOTSTRAP_READY`|The interface configured bootstrap is ready.
|
||||
`ARM_NWK_SCAN_FAIL`|The interface has not detected any valid network or previously connected network lost.
|
||||
`ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL`|IP address allocation fails (ND, DHCPv4 or DHCPv6).
|
||||
`ARM_NWK_DUPLICATE_ADDRESS_DETECTED`|The user-specific GP16 was invalid.
|
||||
`ARM_NWK_AUHTENTICATION_START_FAIL`|An invalid authentication server was detected behind an access point.
|
||||
`ARM_NWK_AUHTENTICATION_FAIL`|Network authentication fails by handshake.
|
||||
`ARM_NWK_PARENT_POLL_FAIL`|Sleepy host poll fails three times.
|
||||
`ARM_NWK_PHY_CONNECTION_DOWN`|The interface PHY cable is off or the serial port interface does not respond anymore.
|
||||
|
||||
When an `ARM_NWK_SCAN_FAIL`, `ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL` or `ARM_NWK_DUPLICATE_ADDRESS_DETECTED` event type occurs, the stack will enter an IDLE state automatically. If the `ARM_NWK_CONNECTION_DOWN` event type is received, the stack will start scanning automatically for a new network; however, the application must wait for the result of the `arm_nwk_interface_up()` call before transmitting data.
|
||||
|
||||
_Table 3-7_ describes how to analyze the status events of a network interface.
|
||||
|
||||
**Table 3-7 Network status events**
|
||||
|
||||
Event structure field|Description
|
||||
---------------------|-----------
|
||||
`receiver`|The tasklet ID that has generated the interface.
|
||||
`sender`|This is always 0 (sent by the stack).
|
||||
`event_type`|`ARM_LIB_NWK_INTERFACE_EVENT`
|
||||
`event_id`|Indicates a network interface ID.
|
||||
`data_ptr`|`NULL.` Always when the sender is the stack.
|
||||
`event_data`|Defines the interface status. Typecast to `arm_nwk_interface_status_type_e.`
|
||||
|
||||
|
||||
### An Example: 6LoWPAN network bootstrap
|
||||
|
||||
When the network interface is brought up, the stack will perform a bootstrap process, as illustrated in **Figure 3-3** _The 6LoWPAN network bootstrapping process_. The result of the bootstrap phase is signaled to the tasklet that registered the network interface. Those phases and events are described in the following paragraphs.
|
||||
|
||||
In the _Media Access Control (MAC) beacon scan_ state, the stack will scan all channels that have been pre-defined. The stack will select the best available network coordinator and store the network setup and channel.
|
||||
|
||||
After a successful beacon scan and link layer coordinator selection, the stack will perform a _Mesh Link Establishment_ (MLE) request to the coordinator and to other nodes that responded to the active scan on the same channel. If the selected coordinator does not respond to the MLE request, the stack will select a new one if there are more coordinator devices that were returned in the scan result list. If the MLE request phase fails, the stack returns an `ARM_NWK_SCAN_FAIL` response event to the application.
|
||||
|
||||
After a successful scan and MLE request operation, the stack will initiate the _IPv6 over Low power Wireless Personal Area Network - Neighbor Discovery_ (6LoWPAN-ND) process. If no networks are available, the stack will report a failure event with the `ARM_NWK_SCAN_FAIL` status. During the ND process, the stack scans for ND routers, learns 6LoWPAN-ND parameters and performs _Internet Protocol_ (IP)v6 address allocation and registration. If the node does not reach any valid router device, it will report an `ARM_NWK_IP_ADDRESS_ALLOCATION_FAIL` or `ARM_NWK_DUPLICATE_ADDRESS_DETECTED` event to the application.
|
||||
|
||||
Alternatively, the node will proceed to advertise its own MLE security parameters and start the _Routing Protocol for Low power and Lossy networks_ (RPL) process. In the 6LoWPAN RPL state, the node will scan for RPL routers and join the best available DAG. The metric according to which the node will perform the RPL router or DAG selection is defined by the used objective function. After a successful completion of the join process, the stack will report an `ARM_NWK_BOOTSTRAP_READY` event to the application. If the RPL join process fails, the stack will re-start the bootstrap process.
|
||||
|
||||
**Figure 3-3 The 6LoWPAN network bootstrapping process**
|
||||
|
||||
![nw-bootstrap](img/network_bootstrapping_process.png)
|
||||
|
||||
## Sending application-specific events
|
||||
|
||||
This section describes how an application can transmit events to itself. This is useful if the application wants to, for example, receive a signal from an interrupt. _Table 3-8_ provides a generic description of the parameters an event can have.
|
||||
|
||||
**Table 3-8 Possible event parameters**
|
||||
|
||||
Name|Value
|
||||
----|-----
|
||||
`receiver`|Tasklet ID for the selected tasklet.
|
||||
`sender`|Tasklet ID for the sender.
|
||||
`priority`|Relative delivery priority (low, medium or high)
|
||||
`event_type`|Developer-defined event type.
|
||||
`event_data`|Developer can give a 32-bit data value, if required.
|
||||
`event_id`|Developer-defined ID.
|
||||
`data_ptr`|Developer can pass a data pointer using this field, if required.
|
||||
|
||||
### Event send API
|
||||
|
||||
To send an event:
|
||||
|
||||
```
|
||||
int8_t eventOS_event_send
|
||||
(
|
||||
const arm_event_t *event
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`event`|A pointer to an event to be sent.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>0 Process OK.</dd>
|
||||
<dd>-1 Memory allocation failed.</dd>
|
||||
</dl>
|
||||
|
||||
An example of sending an event from interrupt:
|
||||
|
||||
```
|
||||
void xx_button_interrupt_handler(void)
|
||||
{
|
||||
arm_event_t event = {0};
|
||||
/*Example of sending event to the application.
|
||||
event.event is user-defined event.
|
||||
In this application S1_BUTTON event is sent when IRQD interrupt occurs */
|
||||
event.receiver = main_tasklet_id
|
||||
event.sender = main_tasklet_id;
|
||||
event.priority = ARM_LIB_MED_PRIORITY_EVENT;
|
||||
event.event_type = APPLICATION_EVENT;
|
||||
event.event_id = S1_BUTTON;
|
||||
eventOS_event_send(&event);
|
||||
}
|
||||
```
|
||||
|
||||
To end a user-allocated event, avoiding the possibility of memory
|
||||
allocation failure:
|
||||
|
||||
```
|
||||
void eventOS_event_send_user_allocated
|
||||
(
|
||||
arm_event_storage_t *event
|
||||
)
|
||||
```
|
||||
|
||||
This sends an event, but without taking a copy of the event data. The event
|
||||
structure must remain valid until the event is delivered. See the
|
||||
documentation comments on the declaration for more details.
|
||||
|
||||
To send periodic events or events after a timeout, refer to [Library Timer API](10_API_timer.md).
|
||||
|
||||
### Cancelling an event
|
||||
|
||||
To cancel and event or timer before it is executed, call `eventOS_cancel()`
|
||||
|
||||
```
|
||||
void eventOS_cancel(arm_event_storage_t *event);
|
||||
```
|
||||
|
||||
Queued events are removed from the event-loop queue and/or the timer queue.
|
||||
Passing a NULL pointer is allowed, and it does nothing.
|
||||
|
||||
Event pointers are valid from the time they are queued until the event has stopped running or is cancelled.
|
||||
Cancelling a currently running event is only useful when you want to stop scheduling it, provided that it is on a periodic timer;
|
||||
it has no other effect.
|
||||
|
||||
Cancelling an already cancelled or already run single-shot event is undefined behaviour.
|
|
@ -1,534 +0,0 @@
|
|||
Network Definition APIs
|
||||
======================
|
||||
|
||||
This chapter describes the Network API that includes functionalities, such as network tasks, network authentication, and security. It contains the following sections:
|
||||
|
||||
- [_API Headers_](#api-headers)
|
||||
- [_PANA network authentication API_](#pana-network-authentication-api)
|
||||
- [_General security type definitions_](#general-security-type-definitions)
|
||||
- [_Ethernet interface bootstrap definition_](#ethernet-interface-bootstrap-definition)
|
||||
- [_RF 6LoWPAN interface configure definition_](#rf-6lowpan-interface-configure-definition)
|
||||
|
||||
## API Headers
|
||||
|
||||
To use Network API, include the following headers:
|
||||
|
||||
```
|
||||
#include net_interface.h
|
||||
#include net_nvm_api.h
|
||||
```
|
||||
|
||||
## PANA network authentication API
|
||||
|
||||
This section introduces the PANA network authentication API for server and client mode.
|
||||
|
||||
PANA network authentication is an authentication layer for network access. It supports configurable authentication methods and security parameters. The server controls that only devices that passed the network authentication get access to the network and receive security material for network layer encryption. The server also handles the key updates to nodes in a coordinated way.
|
||||
|
||||
Supported TLS 1.2 cipher modes for client and server are listed in _Table 3-9_:
|
||||
|
||||
**Table 3-9 Supported TLS 1.2 cipher modes**
|
||||
|
||||
Cipher mode|Description
|
||||
-----------|-----------
|
||||
`NET_TLS_PSK_CIPHER`|PSK authentication.
|
||||
`NET_TLS_ECC_CIPHER`|ECC authentication (ECC must be enabled).
|
||||
`NET_TLS_PSK_AND_ECC_CIPHER`|PSK and ECC authentication (if ECC is not enabled, only PSK is used).
|
||||
|
||||
In PSK mode, the client and server must use the same PSK key. The PSK key must be loaded to the stack by `arm_tls_add_psk_key()` function. Unused keys can be removed by `arm_tls_remove_psk_key()` function.
|
||||
|
||||
In ECC mode, the Network authentication certificate must be loaded to the stack by `arm_network_certificate_chain_set()`.
|
||||
|
||||
### Client API
|
||||
|
||||
_Table 3-10_ introduces the client functions used.
|
||||
|
||||
**Table 3-10 Client functions**
|
||||
|
||||
Function|Description
|
||||
--------|-----------
|
||||
`arm_pana_client_library_init()`|Initializes the PANA Protocol for client mode with a given setup.
|
||||
`arm_pana_client_key_pull()`|Manually pulls the key from the server. Only for testing purposes.
|
||||
|
||||
To initialize and configure the PANA network client interface, use the following function:
|
||||
|
||||
```
|
||||
int8_t arm_pana_client_library_init
|
||||
(
|
||||
int8_t interface_id,
|
||||
net_tls_cipher_e cipher_mode,
|
||||
uint32_t psk_key_id
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`interface_id`|The network interface ID.
|
||||
`cipher_mode`|The TLS 1.2 cipher mode; PSK, ECC or both.
|
||||
`psk_key_id`|The PSK key ID for the PSK setup.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Success.</dd>
|
||||
<dd>-1 Unknown network ID or PANA is not supported in this stack.</dd>
|
||||
<dd>-2 Interface active.</dd>
|
||||
</dl>
|
||||
|
||||
To pull the PANA client key manually for testing purposes:
|
||||
|
||||
```
|
||||
int8_t arm_pana_client_key_pull
|
||||
(
|
||||
int8_t interface_id
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`interface_id`|The network interface ID.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Success.</dd>
|
||||
<dd>-1 Unknown network ID.</dd>
|
||||
</dl>
|
||||
|
||||
### Server API
|
||||
|
||||
_Table 3-11_ introduces the server functions used.
|
||||
|
||||
**Table 3-11 Server functions**
|
||||
|
||||
Function|Description
|
||||
--------|-----------
|
||||
`arm_pana_server_library_init()`|Initializes the PANA server mode and security material.
|
||||
`arm_pana_server_key_update()`|Starts a key update process and key delivery to all authenticated nodes.
|
||||
`arm_pana_activate_new_key()`|Triggers new key material quicker after key delivery phase. Only for testing purposes.
|
||||
`arm_network_key_get()`|Reads PANA server key material. Only for testing purposes.
|
||||
|
||||
To initialize and configure the PANA network server interface:
|
||||
|
||||
```
|
||||
int8_t arm_pana_server_library_init
|
||||
(
|
||||
int8_t interface_id,
|
||||
net_tls_cipher_e cipher_mode,
|
||||
uint8_t *key_material,
|
||||
uint32_t time_period_before_activate_key
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`interface_id`|The network interface ID.
|
||||
`cipher_mode`|The TLS 1.2 cipher mode; PSK, ECC or both.
|
||||
`key_material`|A pointer to 128-bit key material or `NULL` when the PANA server generates the random key.
|
||||
`time_period_before_activate_key`|The guard period in seconds after a successful key delivery phase before the key is activated by the server.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Success.</dd>
|
||||
<dd>-1 Unknown network ID.</dd>
|
||||
<dd>-2 Interface active.</dd>
|
||||
</dl>
|
||||
|
||||
To trigger a network key update process, use the following function. This function will deliver a new network key to all routers that have registered a GP address with the server. The function call always triggers a new key ID. The key delivery is started in 300ms intervals between the nodes. This function does not cause any traffic if the server does not have any router device sessions.
|
||||
|
||||
```
|
||||
int8_t arm_pana_server_key_update
|
||||
(
|
||||
int8_t interface_id,
|
||||
uint8_t * network_key_material
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`interface_id`|The network interface ID.
|
||||
`network_key_material`|A pointer to new 128-bit key material or a NULL pointer to a randomly generated key.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Key update process is OK.</dd>
|
||||
<dd>-1 PANA server is not yet initialized.</dd>
|
||||
<dd>-2 Old key update is still active.</dd>
|
||||
<dd>-3 Memory allocation fail.</dd>
|
||||
</dl>
|
||||
|
||||
To activate the new key material quicker before a standard timeout, use the following function. This function is only used for testing purposes.
|
||||
|
||||
```
|
||||
int8_t arm_pana_activate_new_key
|
||||
(
|
||||
int8_t interface_id
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`interface_id`|The network interface ID.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Key activate process is OK.</dd>
|
||||
<dd>-1 No pending key update.</dd>
|
||||
<dd>-2 PANA server is not initialized or the PANA server API is disabled by this stack.</dd>
|
||||
</dl>
|
||||
|
||||
To read the security key material of the PANA server:
|
||||
|
||||
`previous_active_network_key` is only valid when `current_active_key_index` is bigger than 1.
|
||||
|
||||
```
|
||||
int8_t arm_network_key_get
|
||||
(
|
||||
int8_t interface_id, ns_keys_t *key
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`key`|A pointer for storing key material information.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Key read is OK.</dd>
|
||||
<dd>-1 PANA server key material is not available.</dd>
|
||||
</dl>
|
||||
|
||||
This structure defines the network keys used by the `net_network_key_get` function and comprises the following members:
|
||||
|
||||
```
|
||||
typedef struct ns_keys_t
|
||||
{
|
||||
uint8_t previous_active_network_key[16];
|
||||
uint8_t previous_active_key_index;
|
||||
uint8_t current_active_network_key[16];
|
||||
uint8_t current_active_key_index;
|
||||
} ns_keys_t;
|
||||
```
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`previous_active_network_key`|Contains the previous key. The key is still valid for reception.
|
||||
`previous_active_key_index`|Contains the key index for the previous key.
|
||||
`current_active_network_key`|Contains the current key.
|
||||
`current_active_key_index`|Contains the index for the current key.
|
||||
|
||||
### Resume API
|
||||
|
||||
The PANA Resume API allows the previously established PANA sessions to be resumed without going through a full authentication phase. This allows smaller low-power devices to join the network faster after the host or router is booted.
|
||||
|
||||
The resume functionality depends on the platform side to provide non-volatile storage space that is used for storing PANA session data. The storage is used for keeping the data when the device is powered off or rebooted. The data contains authentication keys so it must be kept secure. If no such secure storage can be provided, ARM recommends not to use the resume functionality because it may leak the authentication keys.
|
||||
|
||||
The resume functionality is divided into two parts, the client side API and the server side API. Both sides require the application to set a callback that receives new material when there are updates in the network. The client side callback receives key material immediately after a successful authentication and periodically after each network key update. On the server side, the callback receives an update when a new client joins the network or when network keys are updated.
|
||||
|
||||
Security material is basically divided into two parts, session keys and network keys. Each client session has unique authentication keys that are assigned to only one session. After a successful authentication, the client receives network keys that are shared with the whole network. The network keys are used for encryption and decryption for all clients. Therefore, a session resume requires you to store both keys.
|
||||
|
||||
#### Client side PANA resume API
|
||||
|
||||
To set a callback for storing PANA key material, use the following function. Before setting this callback, the application should allocate a buffer for transferring keys to the callback.
|
||||
|
||||
```
|
||||
int8_t pana_client_nvm_callback_set
|
||||
(
|
||||
pana_client_session_update_cb *nvm_update,
|
||||
pana_client_session_get_cb *nvm_get,
|
||||
uint8_t * nvm_static_buffer
|
||||
);
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`nvm_update`|A pointer to the callback function for session udate and removal.
|
||||
`nvm_get`|A pointer to the callback function for read session from NVM.
|
||||
`nvm_static_buffer`|A pointer to the allocated buffer. The required size is 86 bytes.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Initialization is OK.</dd>
|
||||
<dd>-1 Failure.</dd>
|
||||
</dl>
|
||||
|
||||
The callback function is called whenever the stack acquires new keys. The parameter passed to the callback tells which parts of the keys are updated. This enumeration defines the parameter types:
|
||||
|
||||
```
|
||||
typedef enum pana_client_nvm_update_process_t
|
||||
{
|
||||
PANA_CLIENT_SESSION_UPDATE,
|
||||
PANA_CLIENT_SESSION_REMOVE,
|
||||
}pana_client_nvm_update_process_t;
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`PANA_CLIENT_SESSION_UPDATE`|Full update of PANA session information.
|
||||
`PANA_CLIENT_SESSION_REMOVE`|Current session for the given PAN ID can be removed.
|
||||
|
||||
When a callback takes place with the parameter `PANA_CLIENT_SESSION_UPDATE`, the first 16 bytes in the data buffer are PANA session address and the following 70 bytes PANA session keys. The session address is associated with the node's parent address, so that is most probably required only on star topology networks. On the mesh network, the parent address can change, so storing the session address is unnecessary.
|
||||
|
||||
When multiple sessions are supported, the session address identifies each session. All sessions are then stored separately.
|
||||
|
||||
An example of a session saving functionality when the session address is not stored:
|
||||
|
||||
```
|
||||
#define PANA_SESSION_ADDRESS_SIZE 16
|
||||
#define PANA_SESSION_KEY_SIZE 70
|
||||
void pana_resume_callback(uint16_t pan_id, pana_client_nvm_update_process_t event)
|
||||
{
|
||||
if (PANA_CLIENT_SESSION_UPDATE == event) {
|
||||
// store now the Session keys, skip the session address
|
||||
//Discover by given pan-id
|
||||
write_to_storage(nvm_static_buffer+PANA_SESSION_ADDRESS_SIZE, PANA_SESSION_KEY_SIZE);
|
||||
} else if (PANA_CLIENT_SESSION_UPDATE == event) {
|
||||
//Discover by given pan-id and remove from NVM
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
An example for session get callback:
|
||||
|
||||
```
|
||||
bool pana_nvm_read_callback(uint16_t pan_id)
|
||||
{
|
||||
//Discover by given pan-id and remove from NVM
|
||||
if (discover_session_from_nvm_by_pan_id(pan_id)) {
|
||||
|
||||
//Write session to static memory buffer
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
#### Server side API
|
||||
|
||||
The server side API differs from the client side so that it stores multiple PANA sessions. This adds some complexity to storing of keys.
|
||||
|
||||
The first step is to allocate a buffer that is used to transfer keys to the callback function. The buffer size must be 116 bytes and is symbolically defined as `PANA_SERVER_CLIENT_NVM_SESSION_BUF_SIZE`.
|
||||
|
||||
The next step is to set a PANA key update callback that receives the key material:
|
||||
|
||||
```
|
||||
int8_t pana_server_nvm_callback_set
|
||||
(
|
||||
pana_server_update_cb *update_cb,
|
||||
pana_server_session_get_cb *nvm_get,
|
||||
pana_server_session_get_by_id_cb *nvm_session_get,
|
||||
uint8_t * nvm_static_buffer
|
||||
);
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`update_cb`|A pointer to the callback function.
|
||||
`nvm_get`|A pointer to the callback function to read the client session by session address.
|
||||
`nvm_session_get`|A pointer to the callback function to read the client session by PANA session ID.
|
||||
`nvm_static_buffer`|A pointer to the buffer used for storing the PANA keys.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Success.</dd>
|
||||
<dd>-1 Error.</dd>
|
||||
</dl>
|
||||
|
||||
The following enumeration defines the parameters to the callback:
|
||||
|
||||
```
|
||||
typedef enum pana_nvm_update_process_t
|
||||
{
|
||||
PANA_SERVER_MATERIAL_UPDATE,
|
||||
PANA_SERVER_CLIENT_SESSION_UPDATE,
|
||||
PANA_SERVER_CLIENT_SESSION_REMOVE_UPDATE,
|
||||
}pana_nvm_update_process_t;
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`PANA_SERVER_MATERIAL_UPDATE`|An update of the PANA server security material.
|
||||
`PANA_SERVER_CLIENT_SESSION_UPDATE`|An update of the PANA client session.
|
||||
`PANA_SERVER_CLIENT_SESSION_REMOVE_UPDATE`|Removes the PANA client session.
|
||||
|
||||
The buffer that is used to transfer data from the PANA process to the storage can contain server keys or client session data. When the server keys are stored, the buffer size is 90 bytes. On the client sessions, it depends on the event that the buffer contains.
|
||||
|
||||
When client session data is stored, the buffer is divided into the following parts:
|
||||
|
||||
1. Session addresses, 24 bytes, containing the following parts:
|
||||
1. 16-bit offset, 2 bytes.
|
||||
2. Client session IPv6 address, 16 bytes.
|
||||
3. Client port number, 2 bytes.
|
||||
4. Pana session Id, 4-bytes
|
||||
2. PANA client session data, 33 bytes.
|
||||
3. PANA client session private keys, 59 bytes.
|
||||
|
||||
Not all segments are valid by each call. The parameter that is passed to the callback function defines the parts that are valid. _Table 3-12_ defines the segments.
|
||||
|
||||
**Table 3-12 Callback parameters**
|
||||
|
||||
|Callback parameter|Buffer content|
|
||||
|------------------|-------------|
|
||||
|`PANA_SERVER_MATERIAL_UPDATE`|Buffer contains server key material. The size is defined by the symbol<br> `PANA_SERVER_MATERIAL_BUF_SIZE`.|
|
||||
|`PANA_SERVER_CLIENT_SESSION_UPDATE`|Add a new PANA session or update the previously stored one. All three segments are valid.<br> An offset number is used to determine which session this is. The offset number for new sessions is zero.<br> The callback should return the offset number for the sessions; this information is not used by the stack but is provided back on the following update.|
|
||||
|`PANA_SERVER_CLIENT_SESSION_SEQ_UPDATE`|Update only the client session data. The first two segments are stored in the buffer.<br>The callback should use the offset field to determine which session data this is.|
|
||||
|`PANA_SERVER_CLIENT_SESSION_REMOVE_UPDATE`|Remove the previously stored session. Only the first segment is stored in the buffer.<br>The callback should use the offset field to determine which session data this is.|
|
||||
|
||||
The following example shows the basic functionality of the PANA server callbacks:
|
||||
|
||||
```
|
||||
uint16_t app_nvm_pana_update(pana_nvm_update_process_t update_type )
|
||||
{
|
||||
uint16_t ret_val = 0;
|
||||
uint16_t offset;
|
||||
|
||||
switch(update_type) {
|
||||
case PANA_SERVER_MATERIAL_UPDATE:
|
||||
store_server_key(nvm_static_buffer, PANA_SERVER_MATERIAL_BUF_SIZE);
|
||||
return 0;
|
||||
case PANA_SERVER_CLIENT_SESSION_UPDATE:
|
||||
// Store a new session, or update full session record.
|
||||
offset = *((uint16_t*)nvm_static_buffer);
|
||||
if (0 == offset)
|
||||
return store_new_session(nvm_static_buffer);
|
||||
else
|
||||
return update_session(offset, nvm_static_buffer);
|
||||
case PANA_SERVER_CLIENT_SESSION_SEQ_UPDATE:
|
||||
// Update session data, but does not touch keys
|
||||
offset = *((uint16_t*)nvm_static_buffer);
|
||||
return update_session_data(offset, nvm_static_buffer);
|
||||
case PANA_SERVER_CLIENT_SESSION_REMOVE_UPDATE:
|
||||
// Remove previously stored session
|
||||
offset = *((uint16_t*)nvm_static_buffer);
|
||||
return remove_session(offset);
|
||||
}
|
||||
}
|
||||
|
||||
bool app_nvm_pana_read_session_by_session_id(uint32_t session_id)
|
||||
{
|
||||
//Discover session by address. Session id offset is 20 bytes from storaged data
|
||||
if (session_read_by_id(session_id) ) {
|
||||
//Write session data behind nvm_static_buffer
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool app_nvm_pana_read_session_by_address(uint8_t *linklocal_address)
|
||||
{
|
||||
//Discover session by address session. Address offset is 2 bytes from storaged data
|
||||
if (session_read_by_address(linklocal_address) ) {
|
||||
//Write session data behind nvm_static_buffer
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
```
|
||||
<span class="notes">**Note:** The previous example assumes that the user provides the functions `store_server_key()`, `store_new_session()`, `update_session()`, `update_session_data()` and `remove_session()`.</span>
|
||||
|
||||
When the server starts, it uses the following API to restore the previous server keys:
|
||||
|
||||
```
|
||||
int8_t pana_server_restore_from_nvm
|
||||
(
|
||||
uint8_t * nvm_data,
|
||||
int8_t interface_id
|
||||
);
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`nvm_data`|Full buffer content given to the callback previously.
|
||||
`interface_id`|The 6LoWPAN interface ID.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Success.</dd>
|
||||
<dd>-1 Failure.</dd>
|
||||
</dl>
|
||||
|
||||
After restoring the server data, each session previously stored must be restored:
|
||||
|
||||
```
|
||||
int8_t pana_server_nvm_client_session_load
|
||||
(
|
||||
uint8_t *nvm_pointer
|
||||
);
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`nvm_pointer`|A pointer to the full PANA session record containing all three defined fields.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Success.</dd>
|
||||
<dd>-1 Failure.</dd>
|
||||
</dl>
|
||||
|
||||
```
|
||||
int8_t net_nvm_data_clean
|
||||
(
|
||||
int8_t interface_id
|
||||
);
|
||||
```
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`interface_id`|The 6LoWPAN interface ID.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Success.</dd>
|
||||
<dd>-1 Failure.</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
```
|
||||
int8_t net_nvm_wpan_params_storage_enable
|
||||
(
|
||||
int8_t interface_id,
|
||||
wpan_params_updated *nvm_update_cb,
|
||||
wpan_params_get *nvm_get_cb
|
||||
);
|
||||
```
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`interface_id`|The 6LoWPAN interface ID.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Success.</dd>
|
||||
<dd>-1 Failure.</dd>
|
||||
<dd>-2 OOM Failure.</dd>
|
||||
</dl>
|
||||
|
||||
```
|
||||
int8_t net_nvm_wpan_params_storage_reset
|
||||
(
|
||||
int8_t interface_id
|
||||
);
|
||||
```
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`interface_id`|The 6LoWPAN interface ID.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Success.</dd>
|
||||
<dd>-1 Failure.</dd>
|
||||
</dl>
|
||||
|
||||
```
|
||||
int8_t net_nvm_wpan_params_storage_disable
|
||||
(
|
||||
int8_t interface_id
|
||||
);
|
||||
```
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`interface_id`|The 6LoWPAN interface ID.
|
||||
|
||||
<dl>
|
||||
<dt>Return value:</dt>
|
||||
<dd>0 Success.</dd>
|
||||
<dd>-1 Failure.</dd>
|
||||
</dl>
|
||||
|
||||
|
|
@ -1,182 +0,0 @@
|
|||
Library Timer API
|
||||
=================
|
||||
This chapter describes the timer functionality.
|
||||
|
||||
If an application requires a timer, it can allocate one with the `eventOS_event_timer_request_in( )` family of functions. Further to a successful allocation, the system timer event occurs.
|
||||
|
||||
Times are specified in ticks, which are currently 10ms, but use macros and converter functions in the header to avoid depending on this.
|
||||
|
||||
See the [Eventing API](08_API_events.md) chapter for more detail on events.
|
||||
|
||||
<span class="notes">**Note**: The library supports dynamic timer count at the application layer. The stack can multiplex a single timer for multiple purposes.</span>
|
||||
|
||||
## API Headers
|
||||
|
||||
To use Library Timer API, include the following header in your application:
|
||||
|
||||
```
|
||||
#include eventOS_event_timer.h
|
||||
```
|
||||
|
||||
## Read the current time
|
||||
|
||||
To read the current time:
|
||||
|
||||
```
|
||||
uint32_t eventOS_event_timer_ticks(void)
|
||||
```
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>Current time in ticks.</dd>
|
||||
</dl>
|
||||
|
||||
## Allocate timer
|
||||
|
||||
To allocate timer events:
|
||||
|
||||
```
|
||||
arm_event_storage_t *eventOS_event_timer_request_at
|
||||
(
|
||||
const arm_event_t *event
|
||||
unt32_t at
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`event`|A pointer to an event to be sent.
|
||||
`at`|The time to send the event.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>A pointer to event structure, if the timer allocation was successful.</dd>
|
||||
<dd>NULL if the timer allocation failed.</dd>
|
||||
</dl>
|
||||
|
||||
At the specified time, the event OS library will transmit the specified event.
|
||||
|
||||
```
|
||||
arm_event_storage_t *eventOS_event_timer_request_in
|
||||
(
|
||||
const arm_event_t *event
|
||||
int32_t in
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`event`|A pointer to an event to be sent.
|
||||
`in`|The requested period in ticks.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>A pointer to event structure, if the timer allocation was successful.</dd>
|
||||
<dd>NULL if the timer allocation failed.</dd>
|
||||
</dl>
|
||||
|
||||
Within the chosen time period, the event OS library will transmit the specified event. Requesting two ticks means that
|
||||
the event will trigger on the second tick from now. The elapsed time between requesting and sending is 1-2 ticks.
|
||||
|
||||
```
|
||||
arm_event_storage_t *eventOS_event_timer_request_after
|
||||
(
|
||||
const arm_event_t *event
|
||||
int32_t after
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`event`|A pointer to an event to be sent.
|
||||
`after`|The requested period in ticks.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>A pointer to event structure, if the timer allocation was successful.</dd>
|
||||
<dd>NULL if the timer allocation failed.</dd>
|
||||
</dl>
|
||||
|
||||
Within the chosen time period, the event OS library will transmit the specified event. Requesting two ticks means
|
||||
the event will trigger on the second tick from now. The elapsed time between requesting and sending is 1-2 ticks.
|
||||
|
||||
```
|
||||
arm_event_storage_t *eventOS_event_timer_request_every
|
||||
(
|
||||
const arm_event_t *event
|
||||
int32_t every
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`event`|A pointer to an event to be sent.
|
||||
`every`|The requested period in ticks.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>A pointer to event structure, if the timer allocation was successful.</dd>
|
||||
<dd>NULL if the timer allocation failed.</dd>
|
||||
</dl>
|
||||
|
||||
Every chosen time period, the event OS library will transmit the specified event.
|
||||
|
||||
## Cancel timer
|
||||
|
||||
To cancel allocated timer id:
|
||||
|
||||
```
|
||||
int8_t eventOS_event_timer_cancel
|
||||
(
|
||||
uint8_t event_id,
|
||||
int8_t tasklet_id
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`event_id`|The event ID of the event to be cancelled.
|
||||
`tasklet_id`|The tasklet ID of the event receiver.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>0 If the timer cancellation was successful.</dd>
|
||||
<dd>-1 If the timer cancellation failed, timer ID is invalid or the timer is already released.</dd>
|
||||
</dl>
|
||||
|
||||
To cancel an periodic event or event by its `arm_event_storage_t *` reference, use `eventOS_cancel()` API. Refer to [Eventing API](08_API_events.md).
|
||||
|
||||
## Millisecond timeout API
|
||||
|
||||
Timeout API provides simpler API for calling functions periodically or after a timeout.
|
||||
|
||||
Two forms of timeouts are provided, periodic one and single-shot.
|
||||
```
|
||||
timeout_t *eventOS_timeout_ms(void (*callback)(void *), uint32_t ms, void *arg);
|
||||
timeout_t *eventOS_timeout_every_ms(void (*callback)(void *), uint32_t every, void *arg);
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`callback`|A pointer to the function to be called.
|
||||
`ms` or `every`|The timeout or period in milliseconds.
|
||||
`arg`|An argument to be used in the function call.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>Reference to timeout structure.</dd>
|
||||
<dd>NULL on failure.</dd>
|
||||
</dl>
|
||||
|
||||
The `timeout_t` reference can be used to cancel an event before it has happened, or to cancel an periodically called event.
|
||||
|
||||
After a single shot event, or after cancelling the periodic one, the reference to `timeout_t` is invalid and should not be used.
|
||||
|
||||
To cancel the event, use:
|
||||
|
||||
```
|
||||
void eventOS_timeout_cancel(timeout_t *t);
|
||||
```
|
||||
Where `timeout_t *t` is the reference returned to you by `eventOS_timeout_ms()` or `eventOS_timeout_every_ms()`.
|
||||
|
||||
After cancelling the event, the handle is internally freed and becomes invalid and should not be used.
|
|
@ -1,559 +0,0 @@
|
|||
Socket API
|
||||
==============================
|
||||
This chapter describes the socket use and the available APIs.
|
||||
|
||||
## API Headers
|
||||
|
||||
Socket API can be fully harnessed by including the following header files:
|
||||
|
||||
```
|
||||
#include net_interface.h
|
||||
#include socket_api.h
|
||||
```
|
||||
|
||||
## Socket types available
|
||||
|
||||
Sockets are a common abstraction model for network communication and are used in most Operating Systems (OS). The 6LoWPAN stack API follows the _Berkeley Software Distribution_ (BSD) socket API conventions closely with some extensions necessitated by the event-based scheduling model. The stack supports the socket types shown in _Table 3-18_.
|
||||
|
||||
**Table 3-18 Socket types**
|
||||
|
||||
Socket name|Socket description
|
||||
-----------|------------------
|
||||
`SOCKET_UDP`|UDP socket type.
|
||||
`SOCKET_TCP`|TCP socket type.
|
||||
`SOCKET_ICMP`|ICMP raw socket type; see section _ICMP socket instruction_.
|
||||
`SOCKET_RAW`|raw IPv6 socket type.
|
||||
|
||||
### ICMP socket instruction
|
||||
|
||||
When using _Internet Control Message Protocol_ (ICMP) sockets, the minimum packet length is eight bytes where the first four bytes comprise the ICMP header, as described in _Table 3-19_. The stack will calculate the checksum automatically before transmitting the packet.
|
||||
|
||||
**Table 3-19 General ICMP packet structure**
|
||||
|
||||
Type|Code|Checksum|Payload|Notes
|
||||
----|----|--------|-------|-----
|
||||
1|1|2|n (min. 4)|Length in bytes
|
||||
`0xXX`|`0xXX`|`0x00 0x00`|n bytes|Transmit
|
||||
`0xXX`|`0xXX`|`0xXX 0xXX`|n bytes|Receive
|
||||
|
||||
|
||||
ICMP echo request with four bytes of payload (ping6), as shown in _Table 3-20_.
|
||||
|
||||
**Table 3-20 ICMP echo request**
|
||||
|
||||
Type|Code|Checksum|Payload
|
||||
----|----|--------|-------
|
||||
`0x80`|`0x00`|`0x00 0x00`|`0x00 0x01 0x02 0x03`
|
||||
|
||||
ICMP echo response for the message, as shown in _Table 6-4_.
|
||||
|
||||
**Table 3-21 ICMP echo response**
|
||||
|
||||
Type|Code|Checksum|Payload
|
||||
----|----|--------|-------
|
||||
`0x81`|`0x00`|`0xXX 0xXX`|`0x00 0x01 0x02 0x03`
|
||||
|
||||
## Receive callback structure
|
||||
|
||||
When there is data to read from the socket, a receive callback function is called from the stack with the socket event parameter. A socket event can be, for example, a change in the state of the _Transmission Control Protocol_ (TCP) socket and the socket _Transmit_ (TX) process is ready or the process failed `(SOCKET_TX_FAIL` or `SOCKET_TX_DONE)`. All supported socket event types are listed in _Table 3-22_. The receive callback function must be defined when a socket is opened using the `socket_open( )` API.
|
||||
|
||||
The socket call back structure, `socket_callback_t` is defined as below:
|
||||
|
||||
```
|
||||
typedef struct socket_callback_t {
|
||||
uint8_t event_type;
|
||||
int8_t socket_id;
|
||||
int8_t interface_id;
|
||||
uint16_t d_len;
|
||||
uint8_t LINK_LQI;
|
||||
} socket_callback_t;
|
||||
```
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`event_type`|Socket event type as provided in Table 3-22.
|
||||
`socket_id`|The ID of the socket that caused the event.
|
||||
`interface_id`|The network interface ID. Same as received from `arm_nwk_interface_init`.
|
||||
`d_len`|The length of data available or sent.
|
||||
`LINK_LQI`|The Link Quality Indicator value if the interface can provide any.
|
||||
|
||||
**Table 3-22 Supported socket event types**
|
||||
|
||||
Event type|Description
|
||||
----------|-----------
|
||||
`SOCKET_DATA`|Data received.
|
||||
`SOCKET_CONNECT_DONE`|TCP connection ready.
|
||||
`SOCKET_CONNECT_FAIL`|TCP connection failed.
|
||||
`SOCKET_CONNECT_AUTH_FAIL`|TCP connection authentication failed.
|
||||
`SOCKET_INCOMING_CONNECTION`|TCP connection state change from listen to establishment.
|
||||
`SOCKET_TX_FAIL`|Socket data send failed.
|
||||
`SOCKET_CONNECT_CLOSED`|TCP connection closed.
|
||||
`SOCKET_CONNECTION_RESET`|TCP connection reset.
|
||||
`SOCKET_NO_ROUTE`|No route available to destination.
|
||||
`SOCKET_TX_DONE`|TX process done (one per datagram, or if stream will be called each time some data acknowledged)
|
||||
`SOCKET_NO_RAM `|If no RAM is present.
|
||||
`SOCKET_CONNECTION_PROBLEM`|If TCP is suffering a connection problem (a soft event, it continues to retry).
|
||||
|
||||
An example parsing socket event:
|
||||
|
||||
```
|
||||
#define APP_SOCK_RX_SIZE 250
|
||||
|
||||
/*Application socket payload buffer used for RX and TX*/
|
||||
static uint8_t rx_buffer[APP_SOCK_RX_SIZE];
|
||||
|
||||
void main_receive
|
||||
(SOCKET_NO_ROUTE
|
||||
void *cb
|
||||
)
|
||||
{
|
||||
socket_callback_t *cb_res = cb;
|
||||
int16_t length;
|
||||
|
||||
if( cb_res->event_type == SOCKET_DATA )
|
||||
{
|
||||
sn_nsdl_addr_s sn_addr_s;
|
||||
|
||||
//Read data from the RX buffer
|
||||
length = socket_read( cb_res->socket_id,
|
||||
&app_src,
|
||||
rx_buffer,
|
||||
APP_SOCK_RX_SIZE );
|
||||
|
||||
if( length )
|
||||
{
|
||||
if( cb_res->socket_id == app_udp_socket )
|
||||
{
|
||||
// Handles data received in UDP socket
|
||||
|
||||
sn_nsdl_process_coap(rx_buffer, length, &sn_addr_s);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Using TCP sockets
|
||||
|
||||
When a TCP socket is opened, it is in an unusable state and must be set to either a _listen_ or _connect_ state before it can be used to receive or transmit data.
|
||||
|
||||
You can set the socket to a _listen_ state with the `socket_listen( )` function. After the call, the socket can accept an incoming connection from a remote host. The TCP implementation of the 6LoWPAN stack supports only one connection from a remote host.
|
||||
|
||||
To connect the TCP socket to a remote host, call `socket_connect( )` with the correct arguments. After the function call, an application (non-blocking) must await the socket event to confirm the successful state change of the socket.
|
||||
|
||||
After receiving a successful state event, data can be sent using the `socket_send( )` call.
|
||||
|
||||
The connection can be shut down by calling function `socket_shutdown( )`. The 6LoWPAN stack shuts down the connection automatically after a server timeout or when the remote end closes the connection. When the socket is no longer needed it must be released by calling the function `socket_close( )`.
|
||||
|
||||
## Using UDP and ICMP sockets
|
||||
|
||||
A _User Datagram Protocol_ (UDP) socket is ready to receive and send data immediately after a successful call to `socket_open( )`. Data can then be transmitted using the `socket_sendto( )` function call. The same function call can also be used for an ICMP socket.
|
||||
|
||||
## Detailed Socket API usage
|
||||
|
||||
This section describes the socket layer functions in more detail. Each function is presented with example parameters and possible return values.
|
||||
|
||||
### How to open a socket
|
||||
|
||||
To initialize a socket ready for communication:
|
||||
|
||||
```
|
||||
int8_t socket_open
|
||||
(
|
||||
uint8_t protocol,
|
||||
uint16_t identifier,
|
||||
void (*passed_fptr)(void *)
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`protocol`|The protocol to be used over this socket and valid values for the argument are:<br>`SOCKET_UDP` UDP: standard communication.<br>`SOCKET_TCP` TCP: standard communication.<br>`SOCKET_ICMP` ICMPv6: used for ping functionality.<br>`SOCKET_RAW` raw IPv6: used for other specialised protocols.
|
||||
`identifier`|The port identifier for UDP and TCP. 0 indicates that the port is not specified and it will be selected automatically when using the socket. The port can also be bound later with the function `socket_bind()`.
|
||||
`passed_fptr`|A function pointer to the desired socket receive callback function.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>0 Socket ID, used as a reference to the specific socket in subsequent calls.</dd>
|
||||
<dd>-1 No free sockets or invalid protocol.</dd>
|
||||
</dl>
|
||||
|
||||
### How to release a socket
|
||||
|
||||
To release a socket:
|
||||
|
||||
`int8_t socket_close( int8_t socket )`
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`socket`|The socket ID of the socket to be released.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>0 Socket release successful.</dd>
|
||||
<dd>-1 Socket release failed. Socket ID invalid or already released.</dd>
|
||||
</dl>
|
||||
|
||||
### How to bind a socket
|
||||
|
||||
To bind socket to a port and address:
|
||||
|
||||
```
|
||||
int8_t socket_bind
|
||||
(
|
||||
int8_t socket,
|
||||
const ns_address_t *address
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`socket`|The socket ID returned by `socket_open`.
|
||||
`address`|Structure that contains port and/or address to be bound to the socket.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>0 on success.</dd>
|
||||
<dd>-1 if given address is NULL.</dd>
|
||||
<dd>-2 if port is already bound to another socket.</dd>
|
||||
<dd>-4 if socket is already bound.</dd>
|
||||
<dd>-5 bind is not supported on this type of socket.</dd>
|
||||
</dl>
|
||||
|
||||
The port and the address can be bound only once. The port can also be bound to the socket with the function `socket_open( )`.
|
||||
|
||||
To bind a local address to a socket based on a destination address and address selection preferences:
|
||||
|
||||
```
|
||||
int8_t socket_bind2addrsel
|
||||
(
|
||||
int8_t socket,
|
||||
const ns_address_t *dst_address
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`socket`|The socket ID returned by `socket_open`.
|
||||
`dst_address`|Destination address to which the socket wants to communicate.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>0 on success.</dd>
|
||||
<dd>-1 if given address is NULL or socket ID is invalid.</dd>
|
||||
<dd>-2 if memory allocation failed.</dd>
|
||||
<dd>-3 if socket is already bound to address.</dd>
|
||||
<dd>-4 if interface cannot be found.</dd>
|
||||
<dd>-5 if source address selection fails.</dd>
|
||||
<dd>-6 bind2addrsel is not supported on this type of socket.</dd>
|
||||
</dl>
|
||||
|
||||
### How to connect a socket
|
||||
|
||||
To connect a socket to a remote host:
|
||||
|
||||
```
|
||||
int8_t socket_connect
|
||||
(
|
||||
int8_t socket,
|
||||
ns_address_t *address,
|
||||
uint8_t randomly_take_src_numbers
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`socket`|The socket ID, which is used to connect to the remote host.
|
||||
`address`|A pointer to an <code>address_t</code> structure that contains the address of the remote host.
|
||||
`randomly_take_src_numbers`|Value 1 indicates that a randomly selected source port number is used.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>0 Valid request.</dd>
|
||||
<dd>-1 Fail.</dd>
|
||||
</dl>
|
||||
|
||||
### How to read data from a socket
|
||||
|
||||
To read received data from a socket:
|
||||
|
||||
```
|
||||
int16_t socket_read
|
||||
(
|
||||
int8_t socket,
|
||||
ns_address_t *address,
|
||||
uint8_t *buffer,
|
||||
uint16_t length
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`socket`|The socket ID of the socket to be read.
|
||||
`address`|A pointer to an address structure containing the source address of the packet (populated by the stack). Can be NULL.
|
||||
`buffer`|A pointer to a byte array containing the payload of the packet.
|
||||
`length`|The length of the payload data to be stored in the buffer.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>> 0 The length of the data copied to the buffer.</dd>
|
||||
<dd>0 No data is available to read.</dd>
|
||||
<dd>-1 Invalid input parameters.</dd>
|
||||
</dl>
|
||||
|
||||
The application receives an event type `SOCKET_DATA` to its receive socket callback when the data is available. The application
|
||||
must read the data from the callback because the stack frees the data after it has called the receive socket callback.
|
||||
All data must be read by one call. If data is too long to fit in the supplied buffer the excess bytes are discarded.
|
||||
|
||||
### How to send data to a socket
|
||||
|
||||
To transmit data using a socket, the 6LoWPAN stack offers two different functions depending on the transport layer protocol that is used, as shown in _Table 3-23_.
|
||||
|
||||
After successfully calling the function, the application must await the TX process to complete.
|
||||
|
||||
**Table 3-23 The two transmit function calls**
|
||||
|
||||
Function|Socket types
|
||||
--------|------------
|
||||
`socket_sendto( )`|UDP, ICMP and RAW
|
||||
`socket_send( )`|TCP, or UDP if connected
|
||||
|
||||
|
||||
_Table 3-24_ describes the possible response events when the outcome of the function call is successful.
|
||||
|
||||
**Table 3-24 The possible response events following a successful function call**
|
||||
|
||||
Response Event|Socket Type|Description
|
||||
--------------|-----------|-----------
|
||||
`SOCKET_TX_DONE`|TCP/UDP|UDP: link layer TX ready (d_len = length of datagram). TCP: some data acknowledged (d_len = unacknowledged data remaining in send queue).
|
||||
`SOCKET_TX_FAIL`|TCP/UDP|UDP: link layer TX fails. TCP: transmit timeout (no ACKs) and connection closed.
|
||||
`SOCKET_CONNECTION_RESET`|TCP|Either the peer reset the connection or there was a protocol error. Connection closed.
|
||||
|
||||
To transmit data on an unconnected socket:
|
||||
|
||||
```
|
||||
int8_t socket_sendto
|
||||
(
|
||||
int8_t socket,
|
||||
ns_address_t address,
|
||||
uint8_t *buffer,
|
||||
uint16_t length
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`socket`|The socket ID to use for transmission.
|
||||
`address`|A pointer to an address structure containing the destination address of the packet (populated by the application).
|
||||
`buffer`|A pointer to a byte array containing the payload of the packet.
|
||||
`length`|The length of the payload data in the buffer.
|
||||
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>>0 Data packet accepted by the stack.</dd>
|
||||
<dd>-1 Fail.</dd>
|
||||
</dl>
|
||||
|
||||
To send data via a connected socket:
|
||||
|
||||
<span class="notes">**Note**: A socket connection must be ready before using this function. The stack will automatically use the address of the remote connected host address as the destination for the packet.</span>
|
||||
|
||||
```
|
||||
int8_t socket_send
|
||||
(
|
||||
int8_t socket,
|
||||
uint8_t *buffer,
|
||||
uint16_t length
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`socket`|The socket ID to use for transmission.
|
||||
`buffer`|A pointer to a byte array containing the payload of the packet.
|
||||
`length`|The length of the payload data in the buffer.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>>0 Data packet accepted by the stack.</dd>
|
||||
<dd>-1 Fail.</dd>
|
||||
</dl>
|
||||
|
||||
### TCP socket configuration
|
||||
|
||||
The TCP socket configuration API offers three function calls, as shown in _Table 3-25_ and are further described.
|
||||
|
||||
**Table 3-25 The TCP socket configuration functions**
|
||||
|
||||
Function|Description
|
||||
--------|-----------
|
||||
`socket_listen()`|Set socket to the listen state.
|
||||
`socket_accept()`|Accepts an incoming TCP connection.
|
||||
`socket_shutdown()`|Shut down socket connection.
|
||||
|
||||
To set a TCP socket into the listen state:
|
||||
|
||||
```
|
||||
int8_t socket_listen
|
||||
(
|
||||
int8_t socket,
|
||||
uint8_t backlog
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`socket`|The socket ID that is to be set to the listen state.
|
||||
`backlog`|The pending connections queue size.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>0 Valid request.</dd>
|
||||
<dd>-1 Fail.</dd>
|
||||
</dl>
|
||||
|
||||
For connecting a socket, please refer to the section above [How to connect a socket](#how-to-connect-a-socket).
|
||||
|
||||
There are three possible responses from the stack for `socket_connect( )`:
|
||||
|
||||
- `SOCKET_CONNECT_DONE`
|
||||
- TCP handshake ready.
|
||||
|
||||
- `SOCKET_CONNECT_FAIL`
|
||||
- TCP handshake fail - connection actively refused or protocol error.
|
||||
|
||||
- `SOCKET_TX_FAIL`
|
||||
- TCP handshake fail - timed out.
|
||||
|
||||
For accepting an incoming TCP connection, use `socket_accept()` function.
|
||||
|
||||
```
|
||||
int8_t socket_accept()
|
||||
(
|
||||
int8_t listen_socket_id,
|
||||
ns_address_t *addr,
|
||||
void (*passed_fptr) (void *)
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`listen_socket_id`|The socket ID of the listening socket.
|
||||
`addr`|Pointer to the address structure where you wish to save the address
|
||||
`passed_fptr`|A function pointer to a function that is called whenever a data frame is received to the new socket
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>0 or greter than zero, i.e., id for the new socket.</dd>
|
||||
<dd>-1 Fail.</dd>
|
||||
</dl>
|
||||
|
||||
To shut down a TCP connection:
|
||||
|
||||
```
|
||||
int8_t socket_shutdown
|
||||
(
|
||||
int8_t socket,
|
||||
uint8_t how
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`socket`|The socket ID of the socket to be shut down.
|
||||
`how`|How socket is to be shut down, one of `SOCKET_SHUT_RD`, `SOCKET_SHUT_WR` or `SOCKET_SHUT_RDWR`.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>0 Valid request.</dd>
|
||||
<dd><b>Note:</b>This does not imply that the state of the socket has been successfully changed.</dd>
|
||||
<dd>-1 Fail.</dd>
|
||||
</dl>
|
||||
|
||||
### Modifying socket options
|
||||
|
||||
To specify miscellaneous options for a socket:
|
||||
|
||||
```
|
||||
int8_t socket_setsockopt
|
||||
(
|
||||
int8_t socket,
|
||||
uint8_t level,
|
||||
uint8_t opt_name,
|
||||
const void *opt_value,
|
||||
uint16_t opt_len
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`socket`|The socket ID.
|
||||
`level`|The option level.
|
||||
`opt_name`|The option name.
|
||||
`opt_value`|A pointer to the value of the specified option.
|
||||
`opt_len`|The size of the data pointed to by a value.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>0 Done.</dd>
|
||||
<dd>-1 Invalid socket ID.</dd>
|
||||
<dd>-2 Invalid or unsupported option.</dd>
|
||||
<dd>-3 Invalid option value.</dd>
|
||||
</dl>
|
||||
|
||||
Each socket has unique control of the following items:
|
||||
|
||||
- IPv6 traffic class, option name: `SOCKET_IPV6_TCLASS`
|
||||
- Socket source address mode, option name: `SOCKET_IPV6_ADDRESS_SELECT`
|
||||
|
||||
A socket uses a configured setup until the user changes it with a new function call.
|
||||
|
||||
<span class="notes">**Note**: `SOCKET_IPV6_ADDRESS_SELECT` is only supported when the interface bootstrap address mode is `NET_6LOWPAN_MULTI_GP_ADDRESS`.</span>
|
||||
|
||||
#### How to set address mode for a socket
|
||||
|
||||
A socket can be configured to use a primary or secondary address as the source address when transmitting packets using `socket_sendto( )`. The primary (default) address is an IPv6 address that is created using a short address type, whereas the secondary address, also IPv6 based, is created using a MAC address type. The source address is currently the only configurable parameter using `socket_configuration` and when multimode is not used, the source address configuration has no effect. The primary address is the default address when no configuration is needed.
|
||||
|
||||
```
|
||||
int8_t set_coap_socket_src_address_mode(int16_t address_mode)
|
||||
{
|
||||
|
||||
return socket_setsockopt(app_udp_socket,SOCKET_IPPROTO_IPV6,
|
||||
SOCKET_IPV6_ADDRESS_SELECT, &address_mode),sizeof(address_mode)));
|
||||
}
|
||||
```
|
||||
|
||||
### How to set traffic class for a socket
|
||||
|
||||
You can use `socket_setsockopt()` to set the socket traffic class. When this option is set, it will stay until modified. Therefore, if you want to set the class for one specific packet, you must call `socket_setsockopt()` again with a default traffic class after the packet has been sent.
|
||||
|
||||
Parameters for Traffic class:
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`socket`|The socket identified.
|
||||
`level`|`SOCKET_IPPROTO_IPV6`
|
||||
`opt_name`|`SOCKET_IPV6_TCLASS`
|
||||
`opt_value`|A pointer to `int16_t` value. Valid values are from 0 to 255. -1 is for system default.
|
||||
`opt_len`|The size of `int16_t`, 2 bytes.
|
||||
|
||||
[RFC 4594](https://tools.ietf.org/html/rfc4594) specifies the appropriate traffic class values. The 6LoWPAN stack does not interpret the specified traffic class. It is just passed through.
|
||||
|
||||
### How to set flow label for a socket
|
||||
|
||||
You can use `socket_setsockopt()` to set the socket flow label.
|
||||
|
||||
Parameters for flow label:
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`socket`|The socket identified.
|
||||
`level`|`SOCKET_IPPROTO_IPV6`
|
||||
`opt_name`|`SOCKET_IPV6_FLOW_LABEL`
|
||||
`opt_value`|A pointer to `int32_t` value. Valid values are from `0` to `0xfffff`. -1 is for system default (set with `arm_nwk_ipv6_auto_flow_label()`). -2 will always autogenerate a flow label, regardless of system default.
|
||||
`opt_len`|The size of `int32_t`, 4 bytes.
|
||||
|
||||
The stack auto-generates flow labels on outgoing packets following the guidelines in [RFC 6437](https://tools.ietf.org/html/rfc6437). The stack does not interpret the flow label on received packets, and nor does the socket API report flow label to the application.
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
Dynamic Memory API
|
||||
==================
|
||||
This chapter introduces the dynamic memory API of the 6LoWPAN stack. It contains the following sections:
|
||||
|
||||
- [_About dynamic memory API_](#about-dynamic-memory-api)
|
||||
- [_Initialization, allocation and freeing_](#initialization-allocation-and-freeing)
|
||||
- [_Failure callback and reporting_](#failure-callback-and-reporting)
|
||||
|
||||
## API Header
|
||||
|
||||
```
|
||||
#include nsdynmemLIB.h
|
||||
```
|
||||
|
||||
## About dynamic memory API
|
||||
|
||||
This section introduces the dynamic memory API of the 6LoWPAN stack. Using this API, the application can specify the size of the 6LoWPAN stack heap to minimize the _Random Access Memory_ (RAM) usage.
|
||||
|
||||
It is not recommended to use heap size less than 2.5KB since the reliability of transmitting full-size packets will become compromised.
|
||||
|
||||
Depending on the network configuration and topology, a higher heap size is recommended.
|
||||
|
||||
The application can also allocate memory from the 6LoWPAN stack heap and receive failure reports in case of usage errors.
|
||||
|
||||
## Initialization, allocation and freeing
|
||||
|
||||
This section describes several APIs that allow you to initialize the 6LoWPAN stack memory block and allocate memory from the initialized block.
|
||||
|
||||
### Dynamic memory initialization
|
||||
|
||||
To initialize the 6LoWPAN stack dynamic memory, use the following function call:
|
||||
|
||||
```
|
||||
void ns_dyn_mem_init
|
||||
(
|
||||
uint8_t *heap_ptr,
|
||||
uint16_t heap_size
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`heap_ptr`|A pointer to data memory block that is reserved for the 6LoWPAN stack.
|
||||
`heap_size`|The size of the 6LoWPAN stack dynamic memory.
|
||||
|
||||
### Dynamic memory temporary allocation
|
||||
|
||||
To allocate memory temporarily from the 6LoWPAN stack heap, use the following function call:
|
||||
|
||||
```
|
||||
void *ns_dyn_mem_temporary_alloc
|
||||
(
|
||||
int16_t alloc_size
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`alloc_size`|Size of the allocation.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>0 Allocation fail.</dd>
|
||||
<dd>>0 Pointer to allocated memory.</dd>
|
||||
</dl>
|
||||
|
||||
### Dynamic memory long period allocation
|
||||
|
||||
To allocate memory from the 6LoWPAN stack heap for longer-term use, use the following function call:
|
||||
|
||||
```
|
||||
void *ns_dyn_mem_alloc
|
||||
(
|
||||
int16_t alloc_size
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`alloc_size`|Size of the allocation.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>0 Allocation fail.</dd>
|
||||
<dd>>0 Pointer to allocated memory.</dd>
|
||||
</dl>
|
||||
|
||||
### Dynamic memory freeing
|
||||
|
||||
To free allocated memory from the 6LoWPAN stack heap, use the following function call:
|
||||
|
||||
```
|
||||
void ns_dyn_mem_free
|
||||
(
|
||||
void *heap_ptr
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`heap_ptr`|A pointer to the start of the allocated memory.
|
||||
|
||||
## Failure callback and reporting
|
||||
|
||||
With the failure callback and delivered failure report, a developer can debug possible usage errors with the 6LoWPAN stack dynamic memory.
|
||||
|
||||
### Dynamic memory failure callback
|
||||
|
||||
To set a callback function for the heap failure report of the 6LoWPAN stack, use the following function:
|
||||
|
||||
```
|
||||
void ns_dyn_mem_heap_fail_callback
|
||||
(
|
||||
void (*passed_fptr)(heap_fail_t)
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`passed_fptr`|A pointer to the callback function of the 6LoWPAN stack memory failure on application.
|
||||
|
||||
### Dynamic memory failure report events
|
||||
|
||||
_Table 3-26_ lists the possible events of the dynamic memory failure report.
|
||||
|
||||
**Table 3-26 Possible events of the memory failure report**
|
||||
|
||||
Event Type|Description
|
||||
----------|-----------
|
||||
`NS_DYN_MEM_NULL_FREE`|Null pointer free detected.
|
||||
`NS_DYN_MEM_DOUBLE_FREE`|Double free detected.
|
||||
`NS_DYN_MEM_ALLOCATE_SIZE_NOT_VALID`|Allocation size not valid.
|
||||
`NS_DYN_MEM_POINTER_NOT_VALID`|Invalid pointer detected while freeing memory.
|
||||
`NS_DYN_MEM_HEAP_SECTOR_CORRUPTED`|Heap sector corruption detected.
|
||||
`NS_DYN_MEM_HEAP_SECTOR_UNITIALIZED`|Detected allocation attempt before dynamic memory is initialized.
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
Data Structures, Types and Variables
|
||||
====================================
|
||||
This chapter describes data structure, types and variables used in the socket and RF layers. It contains the following sections:
|
||||
|
||||
- [_Basic data types_](#basic-data-types)
|
||||
- [_Socket address type definition_](#socket-address-type-definition)
|
||||
- [_Address type_](#address-type)
|
||||
|
||||
## API Headers
|
||||
|
||||
```
|
||||
#include ns_types.h
|
||||
#include ns_addres.h
|
||||
```
|
||||
|
||||
## Basic data types
|
||||
|
||||
The basic data types used are:
|
||||
|
||||
Data type|Description
|
||||
---------|-----------
|
||||
`uint8_t`|An unsigned 8-bit integer.
|
||||
`int8_t`|A signed 8-bit integer.
|
||||
`uint16_t`|An unsigned 16-bit integer.
|
||||
`int16_t`|A signed 16-bit integer.
|
||||
`uint32_t`|An unsigned 32-bit integer.
|
||||
`int32_t`|A signed 32-bit integer.
|
||||
|
||||
## Socket address type definition
|
||||
|
||||
This structure defines the socket address type and has the following members:
|
||||
|
||||
```
|
||||
typedef struct ns_address_t
|
||||
{
|
||||
address_type_t type;
|
||||
uint8_t address[16];
|
||||
uint16_t identifier;
|
||||
}ns_address_t;
|
||||
```
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`type`|The address type.
|
||||
`address`|The address data in the format defined by type.
|
||||
`identifier`|The port for TCP/UDP, message ID for ICMP.
|
||||
</dl>
|
||||
|
||||
## Address type
|
||||
|
||||
This enumeration defines the address types:
|
||||
|
||||
```
|
||||
typedef enum address_type_t
|
||||
{
|
||||
ADDRESS_IPV6,
|
||||
ADDRESS_IPV4,
|
||||
ADDRESS_TUN_DRIVER_ID
|
||||
}address_type_t;
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`ADDRESS_IPV6`|IPv6 address type. The address is in 128-bit binary form.
|
||||
`ADDRESS_IPV4`|IPv4 address type. The address is in 32-bit binary form.
|
||||
`ADDRESS_TUN_DRIVER_ID`|Local socket address type. The address is an 8-bit driver ID for packet source.
|
||||
|
||||
## Address type
|
||||
|
||||
This constant defines the IPv6 address INADDR_ANY:
|
||||
|
||||
```
|
||||
extern const uint8_t ns_in6addr_any[16];
|
||||
```
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
Network debug statistics API
|
||||
==============================
|
||||
|
||||
This chapter describes the debug statistics interface API.
|
||||
|
||||
## API Header
|
||||
|
||||
Using the network debug statistics API, it is possible to collect statistics from the stack in real-time for debugging purposes. You can use this API by including the following header to your application:
|
||||
|
||||
```
|
||||
#include nwk_stats_api.h
|
||||
```
|
||||
|
||||
An overview of the function definitions and the Network statistics structure (`nwk_stats_t`) itself are presented further in this document.
|
||||
|
||||
##Initializing protocol stats collection
|
||||
|
||||
To initialize collection of network statistics in the network (NWK) statistics structure:
|
||||
|
||||
```
|
||||
void protocol_stats_init
|
||||
(
|
||||
void
|
||||
)
|
||||
```
|
||||
|
||||
## Start stats collection
|
||||
|
||||
To start collecting network statistics in the Network (NWK) statistics structure:
|
||||
|
||||
```
|
||||
void protocol_stats_start
|
||||
(
|
||||
nwk_stats_t *stats_ptr
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`stats_ptr`|A pointer to the statistics structure on application.
|
||||
|
||||
## Stop stats collection
|
||||
|
||||
To stop collecting network statistics in NWK statistics structure:
|
||||
|
||||
```
|
||||
void protocol_stats_stop
|
||||
(
|
||||
void
|
||||
)
|
||||
```
|
||||
|
||||
## Reset stats
|
||||
|
||||
To reset network statistics to clean slate state, that is, all the statistics counters are set to zero:
|
||||
|
||||
```
|
||||
void protocol_stats_reset
|
||||
(
|
||||
void
|
||||
)
|
||||
```
|
||||
|
||||
## Types of collectable stats
|
||||
|
||||
Various types of network stats can be collected using the structure `typedef struct nwk_stats_t `. The following statistics can be collected:
|
||||
|
||||
### General MAC related stats
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`mac_tx_buffer_overflow` | Provides a count MAC TX queue overflow.
|
||||
`mac_tx_queue_size` | Current MAC TX queue size.
|
||||
`mac_tx_queue_peak` | MAC TX queue peak size.
|
||||
`mac_rx_count` | Number of received MAC packets.
|
||||
`mac_tx_count` | Number of transmitted MAC packets.
|
||||
`mac_bc_tx_count` | >Number of transmitted MAC broadcast packets.
|
||||
`mac_rx_drop` | Number of dropped MAC packets.
|
||||
|
||||
### MAC payload flow
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`mac_tx_bytes` | Number of bytes transmitted.
|
||||
`mac_rx_bytes` | Number of bytes received.
|
||||
`mac_tx_failed` | Number of times a transmission failed.
|
||||
`mac_tx_retry` | Number of times retries were made.
|
||||
`mac_tx_cca_cnt` | Number of times clear channel assessment was made.
|
||||
`mac_tx_failed_cca` | Number of failed CCA attempts.
|
||||
`mac_security_drop` | Number of security packets dropped.
|
||||
|
||||
### FHSS related statistics
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`fhss_drift_compensation` | FHSS synchronization drift compensation (us/channel).
|
||||
`fhss_hop_count` | FHSS hop count.
|
||||
`fhss_synch_interval` | FHSS synchronization interval (s).
|
||||
`fhss_prev_avg_synch_fix` | Average of 5 preceding synchronization fixes (us).
|
||||
`fhss_synch_lost` | FHSS synchronization lost counter.
|
||||
|
||||
### 6LoWPAN related statistics
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`ip_rx_count` | Number of IP packets received.
|
||||
`ip_tx_count` | Number of IP packets transmitted.
|
||||
`ip_rx_drop` | Number of IP packets dropped.
|
||||
`ip_cksum_error` | IP checksum error count.
|
||||
|
||||
### IP payload flow
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`ip_tx_bytes` | Number of bytes transmitted as IP packets.
|
||||
`ip_rx_bytes` | Number of bytes received as IP packets.
|
||||
`ip_routed_up` | Number of bytes routed as IP packets.
|
||||
`ip_no_route` | Number of times an IP route was not found.
|
||||
|
||||
### Fragmentation statistics
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`frag_rx_errors` | Fragmentation errors in reception.
|
||||
`frag_tx_errors` | Fragmentation errors in transmission.
|
||||
|
||||
### RPL statistics
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`rpl_route_routecost_better_change` | Number of times an RPL parent was changed.
|
||||
`ip_routeloop_detect` | Number of times an RPL IP loop creation was detected.
|
||||
`rpl_memory_overflow` | Total of allocations failed due RPL memory overflow.
|
||||
`rpl_parent_tx_fail` | Number of times transmission to a DODAG parent failed.
|
||||
`rpl_unknown_instance` | Number of times a packet was received with an unknown RPL Instance ID.
|
||||
`rpl_local_repair` | Number of times local repair was initiated.
|
||||
`rpl_global_repair` | Number of times global repair was initiated.
|
||||
`rpl_malformed_message` | Number of malformed RPL messages received.
|
||||
`rpl_time_no_next_hop` | Number of seconds spent with no RPL next hop.
|
||||
`rpl_total_memory` | Total memory currently allocated by RPL.
|
||||
|
||||
### Various buffers
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`buf_alloc` | A count of buffer allocation.
|
||||
`buf_headroom_realloc` | A buffer headroom allocation count.
|
||||
`buf_headroom_shuffle` | A buffer headroom shuffling count.
|
||||
`buf_headroom_fail` | A buffer headroom failure count.
|
||||
|
||||
### ETX statistics
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`etx_1st_parent` | Primary parent ETX.
|
||||
`etx_2nd_parent` | Secondary parent ETX.
|
|
@ -1,308 +0,0 @@
|
|||
Porting 6LoWPAN Stack
|
||||
=====================
|
||||
|
||||
This chapter describes porting the 6LoWPAN stack to a new platform. It contains the following sections:
|
||||
|
||||
- [_Porting 6LoWPAN Stack to a new platform_](#porting-6lowpan-stack-to-a-new-platform)
|
||||
- [_Platform API_](#platform-api)
|
||||
|
||||
## Porting 6LoWPAN stack to a new platform
|
||||
|
||||
The 6LoWPAN stack has two sets of drivers that you must be aware of when porting it to a new platform. The drivers are divided into platform drivers and device drivers.
|
||||
|
||||
The platform drivers are a set of functions that the underlying platform must provide to run an event loop in a specific environment. These functions abstract away the underlying hardware and they can be ported to run on bare metal or from a full-featured operating system. Because the 6LoWPAN stack is provided as part of mbed OS you already have the platform drivers. Therefore, you do not need to port them yourself. See section [_How Nanostack runs inside mbed OS_](#how-nanostack-runs-inside-mbed-os)
|
||||
|
||||
Device drivers are a set of functions for providing PHY layer devices for the 6LoWPAN stack:
|
||||
|
||||
- registering the device
|
||||
- receiving function
|
||||
- a set of device controlling functions
|
||||
|
||||
For more detailed information on the device drivers, see [_Device driver API_](driver_api.md).
|
||||
|
||||
### How Nanostack runs inside mbed OS
|
||||
|
||||
The mbed OS port of Nanostack consist of a few helper modules that provide easier API for users and Platform API for working inside the operating system.
|
||||
|
||||
![Nanostack inside mbed OS](img/nanostack_in_mbed_OS.png)
|
||||
|
||||
* [mbed Mesh API](https://github.com/ARMmbed/mbed-os/tree/master/features/nanostack/FEATURE_NANOSTACK/mbed-mesh-api) controls and initializes Nanostack on mbed OS.
|
||||
* Security settings.
|
||||
* Channel configuration.
|
||||
* Connection and reconnection logic.
|
||||
* [nanostack-hal-mbed-cmsis-rtos](https://github.com/ARMmbed/mbed-os/tree/master/features/FEATURE_COMMON_PAL/nanostack-hal-mbed-cmsis-rtos) implements Platform API for mbed OS.
|
||||
* An internal event handler is initialized when the stack starts.
|
||||
* The event handler is running in its own thread. Not visible for users.
|
||||
* [NanostackInterface](https://github.com/ARMmbed/mbed-os/tree/master/features/nanostack/FEATURE_NANOSTACK/nanostack-interface) class implements the network stack abstration for the socket layer.
|
||||
* Initializes the RF driver. See [Providing RF driver](#providing-rf-driver-for-mbed-os-applications).
|
||||
|
||||
In mbed OS, Socket API hides the differences between the networking stacks. Users will only use one of its high level APIs:
|
||||
|
||||
* UDPSocket
|
||||
* TCPSocket
|
||||
* TCPServer
|
||||
|
||||
![Sockets in mbed OS](img/mbedOS_sockets.png)
|
||||
|
||||
For an example of a simple application using Nanostack, see [Example mesh application for mbed OS](https://github.com/ARMmbed/mbed-os-example-mesh-minimal).
|
||||
|
||||
For documentation of Socket API see the following links
|
||||
|
||||
* [Socket API: Getting started](https://developer.mbed.org/teams/NetworkSocketAPI/wiki/Getting-Started)
|
||||
* [Socket API: Doxygen](https://developer.mbed.org/teams/NetworkSocketAPI/code/NetworkSocketAPI/docs/tip/)
|
||||
|
||||
#### Providing RF driver for mbed OS applications
|
||||
|
||||
For mbed OS 5, the RF driver implements the `NanostackRfPhy` API.
|
||||
`MeshInterfaceNanostack` requires the driver object to be provided when
|
||||
initializing.
|
||||
|
||||
![NanostackRfPhy](img/NanostackRfPhy.png)
|
||||
|
||||
Applications use only `LoWPANNDInterface`, `ThreadInterface` or `NanostackEthernetInterface`
|
||||
directly to set up the network and provide a driver. Rest of the classes provide an abstration
|
||||
between Nanostack and Socket layers of mbed OS.
|
||||
|
||||
See [NanostackRfPhy.h](https://github.com/ARMmbed/mbed-os/blob/master/features/nanostack/FEATURE_NANOSTACK/nanostack-interface/NanostackRfPhy.h) for an up-to-date header file and API.
|
||||
|
||||
Driver API used for communication between the driver and Nanostack is documented in section [_Device Driver API_](driver_api.md).
|
||||
|
||||
## Platform API
|
||||
|
||||
This section introduces the API for platform drivers. These functions must be implemented to run the 6LoWPAN stack in a given platform. Here the platform may refer to a specific CPU or operating system.
|
||||
|
||||
### Required resources
|
||||
|
||||
The following resources are required for a platform driver API:
|
||||
|
||||
- A system timer and a MAC timer (a network timer):
|
||||
* Used as a source for SYSTEM TIMER TICK and MAC TIMER.
|
||||
* SYSTEM TIMER TICK multiplexed to CORE TIMER.
|
||||
* Resolution: 50us.
|
||||
* 16-bit or 32-bit resolution (platform specific).
|
||||
* Implementation guide: set the timer running and use the compare interrupt functionality of the timer.
|
||||
- A sleep timer (optional, application specific):
|
||||
* Accuracy: 1ms.
|
||||
* 32-bit resolution.
|
||||
- AES:
|
||||
* Implementation is optional.
|
||||
* SW or HW accelerated AES.
|
||||
* This function performs `Si=E[key,Ai]` (a simple ECB block).
|
||||
- A pseudorandom number generator:
|
||||
* 8-bit, 16-bit, 32-bit and n-bit (using length and pointer).
|
||||
* Statistically valid.
|
||||
- An RF interface:
|
||||
* PHY data flow API.
|
||||
* Extension to set Channel, Link ON/OFF, Reset, ED_SCAN, ShortAddress, PAN ID, PendingBit.
|
||||
* Calculate LQI from RSSI.
|
||||
* Energy detection.
|
||||
- An Ethernet interface (optional):
|
||||
* PHY data flow API.
|
||||
* Extension for BAUDRATE Read.
|
||||
* Link ON/OFF detection (cable ON and OFF detection).
|
||||
- `platform_enter_critical` and `platform_exit_critical`:
|
||||
* Recursive, general interrupt control.
|
||||
- CPU power mode control (optional, application specific).
|
||||
- Idle, sleep timer, external wakeup modes.
|
||||
|
||||
### 6LoWPAN stack event OS port
|
||||
|
||||
_Table 4-1_ describes the functions that the 6LoWPAN stack event base system requires for porting.
|
||||
|
||||
**Table 4-1 Functions required for porting**
|
||||
|
||||
Function|Desciption
|
||||
--------|----------
|
||||
`eventOS_scheduler_wait()`|Stack enters idle state and starts waiting for a signal.
|
||||
`eventOS_scheduler_signal()`|Stack wakes from idle.
|
||||
`eventOS_scheduler_sleep()`|CPU deep sleep for a given time.
|
||||
`platform_enter_critical()`|Disables global interrupts.
|
||||
`platform_exit_critical()`|Enables global interrupts.
|
||||
|
||||
For more information on the functions, see section [_Process API_](#process-api).
|
||||
|
||||
### 6LoWPAN stack peripherals API port
|
||||
|
||||
The 6LoWPAN stack requires the following peripherals for porting:
|
||||
|
||||
- 1 timer.
|
||||
- Random number seed for a pseudorandom generator.
|
||||
- AES Encode block for Si=E[key,Ai].
|
||||
|
||||
The 6LoWPAN stack only needs one timer that must give a 50us resolution for an ordered timer counter. For more information on the timer, see section [_NET timer API definition_](#net-timer-api-definition).
|
||||
|
||||
|
||||
### NET timer API definition
|
||||
|
||||
Timer Platform API is used for platform porting. _Table 4-2_ introduces the timer functions the 6LoWPAN stack is using.
|
||||
|
||||
**Table 4-2 Timer functions**
|
||||
|
||||
Function|Description
|
||||
--------|-----------
|
||||
`platform_timer_enable()`|Initializes the timer.
|
||||
`platform_timer_set_cb()`|API for setting the timer interrupt handler for the stack.
|
||||
`platform_timer_start()`|Starts the timer for a given period.
|
||||
`platform_timer_disable()`|Stops the timer.
|
||||
|
||||
#### Initialize platform timer peripheral
|
||||
|
||||
To initialize the peripheral driver of the 6LoWPAN stack timer:
|
||||
|
||||
```
|
||||
void platform_timer_enable
|
||||
(
|
||||
void
|
||||
)
|
||||
```
|
||||
|
||||
#### Disable platform timer
|
||||
|
||||
To stop the system timer source of the driver:
|
||||
|
||||
```
|
||||
void platform_timer_disable
|
||||
(
|
||||
void
|
||||
)
|
||||
```
|
||||
|
||||
#### Set compare timer
|
||||
|
||||
To set the compare timer event for the stack:
|
||||
|
||||
```
|
||||
void platform_system_timer_start
|
||||
(
|
||||
uint16_t slots
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`slots`|The number of 50us time slots the timer event stack wants.
|
||||
|
||||
#### Callback function set
|
||||
|
||||
To set the timer interrupt handler for the stack:
|
||||
|
||||
```
|
||||
void platform_system_timer_set_cb
|
||||
(
|
||||
void
|
||||
(*new_fp)(void)
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`new_fp`|A function pointer for stack giving timer handler.
|
||||
|
||||
### AES 128-bit block encode API
|
||||
|
||||
To perform a 128-bit `Si=E[key,Ai]` block encoding for given `Ai` data using the supplied key:
|
||||
|
||||
```
|
||||
void platform_aes128_block_encode
|
||||
(
|
||||
uint8_t * key_ptr ,
|
||||
uint8_t * Ai_ptr,
|
||||
uint8_t * Si_ptr
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`key_ptr`|A pointer to a 128-bit key.
|
||||
`Ai_ptr`|A pointer to a 128-bit data block that is to be decoded.
|
||||
`Si_ptr`|A pointer to a 128-bit data block where the encoded result is stored in.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>None.</dd>
|
||||
</dl>
|
||||
|
||||
### Random number API
|
||||
|
||||
To return a 32-bit seed for a pseudorandom generator:
|
||||
|
||||
```
|
||||
uint32_t platform_random_seed_get
|
||||
(
|
||||
void
|
||||
)
|
||||
```
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>A 32-bit random initialization seed value.</dd>
|
||||
</dl>
|
||||
|
||||
The pseudorandom generator requests this seed on initialization.
|
||||
|
||||
### Global interrupt control API
|
||||
|
||||
The platform driver code must provide protection for the stack when there are critical code sections. Some stack interfaces might be called within interrupts or from multiple threads, so protection is required. On some platform, these disable interrupts. On some platform, it is only a recursive mutex.
|
||||
|
||||
When the stack is about to enter a critical section, it uses the following function call:
|
||||
|
||||
```
|
||||
void platform_enter_critical
|
||||
(
|
||||
void
|
||||
)
|
||||
```
|
||||
|
||||
When the stack exits a critical section, it uses the following function call:
|
||||
|
||||
```
|
||||
void platform_exit_critical
|
||||
(
|
||||
void
|
||||
)
|
||||
```
|
||||
|
||||
### Process API
|
||||
|
||||
The functions described here provide a portable layer for handling idle states for the stack.
|
||||
|
||||
This function is called when the stack enters idle state and starts waiting for a signal. The 6LoWPAN stack calls this function whenever the event queue is empty. The function disables the current task or the CPU as follows:
|
||||
|
||||
1. Use pure 6LoWPAN stack 1 thread system:
|
||||
* Sets the global parameter to wait for a signal state and sets the CPU to idle.
|
||||
2. RTOS or any multithread:
|
||||
* Stops the running thread and waits for a signal.
|
||||
|
||||
```
|
||||
void eventOS_scheduler_wait
|
||||
(
|
||||
void
|
||||
)
|
||||
```
|
||||
|
||||
The 6LoWPAN stack calls this function when it receives an external event and wakes from idle. The function wakes the sleeping thread currently used by the OS.
|
||||
|
||||
```
|
||||
void eventOS_scheduler_signal
|
||||
(
|
||||
void
|
||||
)
|
||||
```
|
||||
|
||||
This function is called when the stack enters deep sleep state for a period of time. This function enables thread sleep or the CPU deep sleep for a given time. It may also set specific peripherals to sleep mode, if they are not required.
|
||||
|
||||
```
|
||||
uint32_t eventOS_scheduler_sleep
|
||||
(
|
||||
uint32_t sleep_time_ms
|
||||
)
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`sleep_time_ms`|Sleep time in milliseconds.
|
||||
|
||||
<dl>
|
||||
<dt>Return value</dt>
|
||||
<dd>Time slept in milliseconds.</dd>
|
||||
</dl>
|
|
@ -1,279 +0,0 @@
|
|||
The Load balancing API
|
||||
==================
|
||||
|
||||
This chapter describes the functions of the load balancing layer. It contains the following sections:
|
||||
|
||||
- [_Load balancing API_](#load-balancing-api)
|
||||
- [_Load balancing activity diagram_](#load-balancing-activity-diagram)
|
||||
|
||||
## API header
|
||||
|
||||
To use the Load balancing API, include the following header:
|
||||
|
||||
```
|
||||
#include "net_load_balance_api.h"
|
||||
```
|
||||
|
||||
## Load balancing API
|
||||
|
||||
This section describes the functions of the load balancing layer where each function is presented with its valid parameters.
|
||||
|
||||
**Table 1-1 The load balancing API features and related functions**
|
||||
|
||||
Feature|API function
|
||||
-------|------------
|
||||
Load balancer creation|`net_load_balance_create()`
|
||||
Load balancer deletion|`net_load_balance_delete()`
|
||||
Callback function type definition|`net_load_balance_network_switch_notify()`
|
||||
Callback setting function|`net_load_balance_network_switch_cb_set()`
|
||||
Load balancer thresholds setter function|`net_load_balance_threshold_set()`
|
||||
Load balancer maximum probability setter function|`net_load_balance_set_max_probability()`
|
||||
Load level automatic update enabling|`net_load_balance_load_level_update_enable()`
|
||||
Load level automatic update disabling|`net_load_balance_load_level_update_disable()`
|
||||
|
||||
### Create load balancer
|
||||
|
||||
Periodic beacon interval can be used to speed up the load balancing feature. The suggested value is `True`. Beacon sending interval is (usually) very long to prevent flooding in network.
|
||||
|
||||
To enable the load balancer feature, use the following function:
|
||||
|
||||
```
|
||||
int8_t net_load_balance_create
|
||||
(
|
||||
int8_t interface_id,
|
||||
bool enable_periodic_beacon_interval
|
||||
)
|
||||
```
|
||||
|
||||
Where:
|
||||
<dl>
|
||||
<dt><code>interface_id</code></dt>
|
||||
<dd>The network interface ID.</dd>
|
||||
|
||||
<dt><code>enable_periodic_beacon_interval</code></dt>
|
||||
<dd>Beacon interval is calculated from RPL config (Imax of the RPL DIO timer).</dd>
|
||||
<dd>True: The load balancing device advertises the network by sending periodic beacons.</dd>
|
||||
<dd>False: The load balancing is based on devices hearing beacons from other networks.</dd>
|
||||
|
||||
<dt><code>Return value</code></dt>
|
||||
<dd>0 Creation OK.</dd>
|
||||
<dd>-1 An unknown interface ID.</dd>
|
||||
<dd>-2 Out of memory.</dd>
|
||||
<dd>-3 Load balancing already active for this interface ID.</dd>
|
||||
</dl>
|
||||
|
||||
### Delete load balancer
|
||||
|
||||
To delete the load balancer, use the following function:
|
||||
|
||||
```
|
||||
int8_t net_load_balance_delete
|
||||
(
|
||||
int8_t interface_id
|
||||
)
|
||||
```
|
||||
|
||||
Where:
|
||||
<dl>
|
||||
<dt><code>interface_id</code></dt>
|
||||
<dd>The network interface ID.</dd>
|
||||
|
||||
<dt><code>Return value</code></dt>
|
||||
<dd>0 Delete OK.</dd>
|
||||
<dd>-1 An unknown interface ID.</dd>
|
||||
</dl>
|
||||
|
||||
### Callback function
|
||||
|
||||
To define a callback function for selecting whether a network switch is allowed or not, use the following `typedef`:
|
||||
|
||||
```
|
||||
typedef bool net_load_balance_network_switch_notify
|
||||
(
|
||||
)
|
||||
```
|
||||
|
||||
Where:
|
||||
<dl>
|
||||
<dt><code>Return value</code></dt>
|
||||
<dd>True: Network change is allowed.</dd>
|
||||
<dd>False: Network change is not allowed.</dd>
|
||||
</dl>
|
||||
|
||||
An example of a callback:
|
||||
|
||||
```
|
||||
bool my_decision(int8_t interface_id)
|
||||
{
|
||||
if (is_ok_to_change) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
```
|
||||
|
||||
### Use the callback
|
||||
|
||||
<span class="notes">**Note:** If the callback is not set, the load balancer changes the network automatically and the application only gets `ARM_LIB_NWK_INTERFACE_EVENT` with `event_id` of either `ARM_NWK_BOOTSTRAP_READY` or some error.</span>
|
||||
|
||||
To use the callback, use the following function:
|
||||
|
||||
```
|
||||
int8_t net_load_balance_network_switch_cb_set
|
||||
(
|
||||
int8_t interface_id,
|
||||
net_load_balance_network_switch_notify *network_switch_notify
|
||||
)
|
||||
```
|
||||
|
||||
Where:
|
||||
<dl>
|
||||
<dt><code>interface_id</code></dt>
|
||||
<dd>The network interface ID.</dd>
|
||||
|
||||
<dt><code>network_switch_notify</code></dt>
|
||||
<dd>The callback function to be called when the load balancer is about to start the network change sequence.</dd>
|
||||
|
||||
<dt>Return value</dt>
|
||||
<dd>0 Set OK.</dd>
|
||||
<dd>-1 An unknown interface id.</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
### Set the network threshold values
|
||||
|
||||
Threshold is used to limit the network changes. The difference between networks is calculated using joining priorities from network data. If the difference is less than the minimum threshold, the network change is never allowed. However, if the difference is more than the maximum threshold, the device does not necessarily change the network. Instead, the maximum probability will be used. This is described in the subsequent function description.
|
||||
|
||||
```
|
||||
if diff <= threshold_min: no change
|
||||
else if diff >= threshold_max: probability = max_probability
|
||||
else probability = (diff/(threshold_max-threshold_min))*max_probability
|
||||
```
|
||||
<span class="notes">**Note:** Suggested values are 32-64 for min and 64-96 for max. The border router must set both values to zero.</span>
|
||||
|
||||
To set the network threashold values, use the following function:
|
||||
|
||||
```
|
||||
int8_t net_load_balance_threshold_set
|
||||
(
|
||||
int8_t interface_id,
|
||||
uint8_t threshold_min,
|
||||
uint8_t threshold_max
|
||||
)
|
||||
```
|
||||
|
||||
Where:
|
||||
<dl>
|
||||
<dt><code>interface_id</code></dt>
|
||||
<dd>The network interface ID.</dd>
|
||||
|
||||
<dt><code>threshold_min</code></dt>
|
||||
<dd>The minimum difference needed between networks to allow network change.</dd>
|
||||
|
||||
<dt><code>threshold_max</code></dt>
|
||||
<dd>The minimum difference needed to reach max probability (see <code>net_load_balance_set_max_probability</code>).</dd>
|
||||
|
||||
<dt><code>Return value</code></dt>
|
||||
<dd>0 Set OK.</dd>
|
||||
<dd>-1 An unknown interface ID.</dd>
|
||||
</dl>
|
||||
|
||||
### Set the network change max probability
|
||||
|
||||
Maximum probability is used to prevent all devices from changing network when they hear a better one. There is a specific timeout before which the network statistics are changed to all nodes in the network (depending on the hop count of nodes). If all devices changed the network, that could cause some unwanted churn. The max probability value is very much dependent on the size of the actual networks. The suggested value is between 10 and 25. The lower the value, the slower the balancing of network loads. If the value was 99 it would cause the devices to switch the networks very agressively (depending on the threshold values). The default value 25 is suitable for two-hop networks.
|
||||
|
||||
To set the maximum probability for a device to change the network, use the following function:
|
||||
|
||||
```
|
||||
int8_t net_load_balance_set_max_probability
|
||||
(
|
||||
int8_t interface_id,
|
||||
uint8_t max_p
|
||||
)
|
||||
```
|
||||
|
||||
Where:
|
||||
<dl>
|
||||
<dt><code>interface_id</code></dt>
|
||||
<dd>The network interface ID.</dd>
|
||||
|
||||
<dt><code>max_p</code></dt>
|
||||
<dd>The maximum probability for a device to change the network. The default value is 25(%).</dd>
|
||||
|
||||
<dt><code>Return value</code></dt>
|
||||
<dd>0 Set OK.</dd>
|
||||
<dd>-1 An unknown interface ID.</dd>
|
||||
</dl>
|
||||
|
||||
### Set automatic calculation of DoDAG preference for the border router
|
||||
|
||||
<span class="notes">**Note:** This function should not do anything if the device is not a border router!</span>
|
||||
|
||||
To set automatic calculation of DoDAG preference for the border router, use the following function:
|
||||
|
||||
```
|
||||
int8_t net_load_balance_load_level_update_enable
|
||||
(
|
||||
int8_t interface_id,
|
||||
uint16_t expected_device_count
|
||||
)
|
||||
```
|
||||
|
||||
Where:
|
||||
<dl>
|
||||
<dt><code>interface_id</code></dt>
|
||||
<dd>The network interface ID.</dd>
|
||||
|
||||
<dt><code>expected_device_count</code></dt>
|
||||
<dd>Device count when DoDAG preference goes to worst possible.</dd>
|
||||
|
||||
<dt><code>Return value</code></dt>
|
||||
<dd>0 Set OK.</dd>
|
||||
<dd>-1 An unknown interface ID.</dd>
|
||||
<dd>-2 Out of memory.</dd>
|
||||
</dl>
|
||||
|
||||
### Disable automatic calculation of DoDAG preference for the border router
|
||||
|
||||
<span class="notes">**Note:** This function should not do anything if the device is not a border router!</span>
|
||||
|
||||
To disable automatic calculation of DoDAG preference for the border router, use the following function:
|
||||
|
||||
```
|
||||
int8_t net_load_balance_load_level_update_disable
|
||||
(
|
||||
int8_t interface_id
|
||||
)
|
||||
```
|
||||
|
||||
Where:
|
||||
<dl>
|
||||
<dt><code>interface_id</code></dt>
|
||||
<dd>The network interface ID.</dd>
|
||||
|
||||
<dt><code>Return value</code></dt>
|
||||
<dd>0 Disable OK.</dd>
|
||||
<dd>-1 An unknown interface ID.</dd>
|
||||
</dl>
|
||||
|
||||
## Load balancing activity diagram
|
||||
|
||||
Here is the activity diagram of the load balancer:
|
||||
|
||||
![nw-arc](img/load_balancer_activity_diagram.png)
|
||||
|
||||
Where:
|
||||
|
||||
1. Idle state indicates that a device has joined a network having `PanID=1` and the device is doing "normal" operations.
|
||||
2. `nwk_id` check is mandatory to prevent joining a wrong network.
|
||||
3. The load balancer is handling incoming beacons and deciding whether the device should change the network.
|
||||
4. If the load balancer is in block period, no beacons are handled.
|
||||
5. The difference is calculated by comparing the priority values of the networks.
|
||||
6. If the difference is less than the minimum threshold, the network change is not possible and the load balancer goes to block period state.
|
||||
7. The possibility is calculated by counting a linear probability multiplier (0..1) between the minimum and maximum threshold. If the network difference is higher than the maximum, the multiplier is 1. The multiplier is then multiplied with the maximum probability to get the possibility for the network change.
|
||||
8. A random value is generated and if it is higher than the probability, the load balancer goes to block state. Otherwise, the load balancer goes to waiting state.
|
||||
9. `Waiting for better beacons` is the active state of the load balancer, when a device is given a chance to hear better beacons. After a timeout period, the load balancer continues to the next state.
|
||||
10. In the `Query change from App` state, the application's callback function (if set) is called and if the returned value is false, the load balancer goes to block state. Otherwise, it continues to the change network state.
|
||||
11. The load balancer has got a permission to change the network. The sequence for the change starts.
|
||||
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
The warm restart feature
|
||||
========================
|
||||
|
||||
This chapter describes the functionality of the warm restart feature. It contains the following sections:
|
||||
|
||||
- [_Application configuration_](#application-configuration)
|
||||
- [_mbed TLS configuration_](#mbed-tls-configuration)
|
||||
|
||||
## Application configuration
|
||||
|
||||
This section describes the functionalities needed to enable load balancing from an application.
|
||||
|
||||
### NVM storage
|
||||
|
||||
To use the warm restart feature, your device needs to have non-volatile memory (NVM) available. The security parameters are stored into it, so a secure storage should be used when possible. The application must control the data storing intervals. If you are using a flash drive, you should save scarsely to ensure a long lifetime for it.
|
||||
|
||||
### WPAN & PANA configuration
|
||||
|
||||
To understand how to configure WPAN & PANA to receive security parameters, refer to [Network Definition APIs](09_API_network_def.md). Basically, you need to register callback functions for both to receive security paramaeters whenever they change.
|
||||
|
||||
<span class="notes">**Note:** WPAN parameters change very often. Make sure to store them regularly.</span>
|
||||
|
||||
To register WPAN callbacks, use the following function:
|
||||
|
||||
```
|
||||
net_nvm_wpan_params_storage_enable
|
||||
```
|
||||
|
||||
To register PANA callbacks, use one of the following functions (based on the type of device):
|
||||
|
||||
```
|
||||
pana_client_nvm_callback_set
|
||||
pana_server_nvm_callback_set
|
||||
```
|
||||
|
||||
## mbed TLS configuration
|
||||
|
||||
This section describes the needed configuration for mbed TLS to use the warm restart feature.
|
||||
|
||||
<span class="notes">**Note:** The server side must support mbed TLS session caching for warm restart to work. There is no extra logic needed even if the server does not support session caching (full handshake is performed every time).</span>
|
||||
|
||||
Every device initially "cold starts", meaning that a full handshake is performed with server. After the full handshake, the session parameters can be fetched by calling:
|
||||
|
||||
```
|
||||
mbedtls_ssl_get_session (See mbedtls/ssl.h for details)
|
||||
```
|
||||
|
||||
When the SSL session details are known, call the function:
|
||||
|
||||
```
|
||||
mbedtls_ssl_set_session (See mbedtls/ssl.h for details),
|
||||
```
|
||||
|
||||
Finally, to enable "session id" based SSL resume, call:
|
||||
|
||||
```
|
||||
mbedtls_ssl_handshake_step,
|
||||
```
|
||||
|
|
@ -1,419 +0,0 @@
|
|||
# API Changes
|
||||
|
||||
This document walks you through the API changes in the Nanostack version 4.0.x in detail and helps you to update your current applications to use the new and changed APIs.
|
||||
|
||||
**New APIs:**
|
||||
|
||||
- MLE router and host lifetime configuration API
|
||||
- MLE neighbor limits configuration API
|
||||
- MLE token bucket configuration API
|
||||
- API for adding/deleting routes
|
||||
- FHSS API
|
||||
|
||||
**Other changes:**
|
||||
|
||||
- Function `arm_nwk_6lowpan_link_scan_paramameter_set()` renamed to `arm_nwk_6lowpan_link_scan_parameter_set()` (due to misspelling)
|
||||
- Channel mask settings API changed
|
||||
- The parameters of function `cca_start()` changed
|
||||
|
||||
|
||||
## The Network Layer Control APIs
|
||||
|
||||
### MLE router and host lifetime configuration API
|
||||
|
||||
**Problem:**
|
||||
|
||||
MLE router and host lifetimes were not configurable.
|
||||
|
||||
**Solution:**
|
||||
|
||||
Added functions `arm_nwk_6lowpan_mle_router_lifetime_set()` and `arm_nwk_6lowpan_mle_host_lifetime_set()`
|
||||
that can be used to set the MLE neighbor lifetime. The router lifetime controls also the MLE advertisement period that
|
||||
is the router lifetime in seconds divided by four. The usage of the MLE router and host lifetime configuration is
|
||||
optional. If the lifetimes are not set, the default router lifetime is 128 seconds and host lifetime 400 seconds.
|
||||
|
||||
### MLE neighbor limits configuration API
|
||||
|
||||
**Problem:**
|
||||
|
||||
The size of the MLE neighbor list was not limited. It would take as much space as there are neighbors.
|
||||
|
||||
**Solution:**
|
||||
|
||||
Added function `arm_nwk_6lowpan_mle_neighbor_limits_set()` that can be used to set limits for the MLE
|
||||
neighbor list. With this function, you can set the lower threshold, upper threshold and maximum neighbor count. If the number of neighbors reaches the lower threshold, MLE starts to limit addition of new neighbors. If the number of neighbors reaches
|
||||
upper threshold, MLE stops adding new neighbors based on multicast MLE messages. The usage of the MLE neighbor list limits is optional. If no limits are set, the number of neighbors is unlimited.
|
||||
|
||||
## MLE token bucket configuration API
|
||||
|
||||
**Problem:**
|
||||
|
||||
The sending rate for MLE messages was not configurable.
|
||||
|
||||
**Solution:**
|
||||
|
||||
Added function `arm_nwk_6lowpan_mle_token_bucket_settings_set()` that can be used to configure the MLE message
|
||||
sending rate. With this function, you can set the token bucket size, rate and count. The token bucket size defines the
|
||||
bucket size. The token bucket rate defines the rate for adding new tokens. The count defines how many
|
||||
tokens at a time are added to the bucket. The minimum interval of the rate is 0.1 seconds (for example, if the rate is 3 and
|
||||
the count is 4, then 4 new tokens are added to bucket every 0.3 seconds). The usage of MLE token bucket is optional. If the token bucket is not used, the MLE message sending rate is unlimited.
|
||||
|
||||
## Applications
|
||||
|
||||
### Node application
|
||||
|
||||
**Problem:**
|
||||
|
||||
Misspelled function `arm_nwk_6lowpan_link_scan_paramameter_set()`.
|
||||
|
||||
**Solution:**
|
||||
|
||||
Rename the current `arm_nwk_6lowpan_link_scan_paramameter_set()` function call to `arm_nwk_6lowpan_link_scan_parameter_set()`.
|
||||
|
||||
**Problem:**
|
||||
|
||||
Parameter `uint32_t channel_mask` is removed from `arm_nwk_6lowpan_link_scan_parameter_set()` function.
|
||||
|
||||
**Solution:**
|
||||
|
||||
- Remove parameter `channel_mask` from all `arm_nwk_6lowpan_link_scan_parameter_set()` function calls.
|
||||
- Add a new function call `arm_nwk_set_channel_list();` after `arm_nwk_6lowpan_link_scan_parameter_set()` function call.
|
||||
|
||||
channel_list_s channel_list = {CHANNEL_PAGE_0, 0x07FFF800};
|
||||
int main(void)
|
||||
{
|
||||
.
|
||||
.
|
||||
.
|
||||
net_init_core();
|
||||
net_rf_id = arm_nwk_interface_init(NET_INTERFACE_RF_6LOWPAN, rf_phy_device_register_id,
|
||||
"6LoWPAN_ROUTER");
|
||||
int8_t retval = arm_nwk_6lowpan_link_scan_parameter_set(net_rf_id, 5);
|
||||
if (retval) {
|
||||
printf(" Scan parameter set failed! Return value = %d\n", retval);
|
||||
}
|
||||
retval = arm_nwk_set_channel_list(net_rf_id, &channel_list);
|
||||
if (retval) {
|
||||
printf("Channel set failed! Return value = %d\n", retval);
|
||||
}
|
||||
.
|
||||
.
|
||||
.
|
||||
}
|
||||
|
||||
Function `arm_nwk_set_channel_list(int8_t interface_id, const channel_list_s* nwk_channel_list)` is defined in `net_interface.h`. Instead of using a 32-bit variable, the new API is using structure `channel_list_s`
|
||||
to define the scanned channel page and channels.
|
||||
|
||||
Structure `channel_list_s` is defined in `net_interface.h`:
|
||||
|
||||
typedef struct channel_list_s
|
||||
{
|
||||
channel_page_e channel_page;
|
||||
uint32_t channel_mask[8];
|
||||
} channel_list_s;
|
||||
|
||||
where enumeration `channel_page_e` from `arm_hal_phy.h` defines the supported channel pages:
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CHANNEL_PAGE_0 = 0,
|
||||
CHANNEL_PAGE_1 = 1,
|
||||
CHANNEL_PAGE_2 = 2,
|
||||
CHANNEL_PAGE_3 = 3,
|
||||
CHANNEL_PAGE_4 = 4,
|
||||
CHANNEL_PAGE_5 = 5,
|
||||
CHANNEL_PAGE_6 = 6,
|
||||
CHANNEL_PAGE_9 = 9,
|
||||
CHANNEL_PAGE_10 = 10
|
||||
} channel_page_e;
|
||||
|
||||
`channel_mask` is an array of 32-bit variables allowing up to 255 channels.
|
||||
|
||||
The channel list can be defined using global a structure, for example:
|
||||
|
||||
// IEEE 802.15.4-2006 for 2.4GHz band (channels 11-26)
|
||||
channel_list_s channel_list = {CHANNEL_PAGE_0, 0x07FFF800};
|
||||
|
||||
or
|
||||
|
||||
// IEEE 802.15.4-2006 for Sub 1GHz band (channels 0-10)
|
||||
channel_list_s channel_list = {CHANNEL_PAGE_2, 0x000007ff};
|
||||
|
||||
### Border router application
|
||||
|
||||
#### Border router without external RF interface
|
||||
|
||||
**Problem:**
|
||||
|
||||
Structure `border_router_setup_s` content has changed because variable `channel` is removed.
|
||||
|
||||
**Solution:**
|
||||
|
||||
- Remove all references to `(border_router_setup_s) border_router_setup.channel`.
|
||||
- Add a new function call `arm_nwk_set_channel_list();` to set the channel.
|
||||
|
||||
void start_6lowpan(void)
|
||||
{
|
||||
uint8_t p[16];
|
||||
if (0 == arm_net_address_get(net_backhaul_id, ADDR_IPV6_GP, p)) {
|
||||
memcpy(br_def_prefix, p, 8);
|
||||
uint32_t lifetime = 0xffffffff;
|
||||
uint8_t t_flags = 0;
|
||||
uint8_t prefix_len =0;
|
||||
arm_nwk_interface_configure_6lowpan_bootstrap_set(net_6lowpan_id, operating_mode,
|
||||
operating_mode_extension);
|
||||
arm_nwk_set_channel_list(net_6lowpan_id, &channel_list);
|
||||
.
|
||||
.
|
||||
}
|
||||
}
|
||||
|
||||
Function `arm_nwk_set_channel_list(int8_t interface_id, const channel_list_s *nwk_channel_list)` is defined in `net_interface.h`.
|
||||
|
||||
Structure `channel_list_s` is defined in `net_interface.h`:
|
||||
|
||||
typedef struct channel_list_s
|
||||
{
|
||||
channel_page_e channel_page;
|
||||
uint32_t channel_mask[8];
|
||||
} channel_list_s;
|
||||
|
||||
where enumeration `channel_page_e` from `arm_hal_phy.h` defines the supported channel pages:
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CHANNEL_PAGE_0 = 0,
|
||||
CHANNEL_PAGE_1 = 1,
|
||||
CHANNEL_PAGE_2 = 2,
|
||||
CHANNEL_PAGE_3 = 3,
|
||||
CHANNEL_PAGE_4 = 4,
|
||||
CHANNEL_PAGE_5 = 5,
|
||||
CHANNEL_PAGE_6 = 6,
|
||||
CHANNEL_PAGE_9 = 9,
|
||||
CHANNEL_PAGE_10 = 10
|
||||
} channel_page_e;
|
||||
|
||||
`channel_mask` is an array of 32-bit variables allowing up to 255 channels.
|
||||
|
||||
The channel can be defined using a global structure, for example:
|
||||
|
||||
// IEEE 802.15.4-2006 for 2.4GHz band channel 11
|
||||
channel_list_s channel_list = {CHANNEL_PAGE_0, 0x00000800};
|
||||
|
||||
or
|
||||
|
||||
// IEEE 802.15.4-2006 for Sub 1GHz band channel 0
|
||||
channel_list_s channel_list = {CHANNEL_PAGE_2, 0x00000001};
|
||||
|
||||
#### Border router (linux) with external RF interface
|
||||
|
||||
In addition to what was changed in section [Border router without external RF interface](#border-router-without-external-rf-interface), channel setting needs to be updated also to the NAP interface.
|
||||
|
||||
**Problem:**
|
||||
|
||||
Instead of the channel number, channel page and channel mask need to be delivered to the RF interface.
|
||||
|
||||
**Solution:**
|
||||
|
||||
- Define the channel list as in the previous section and send it to the RF interface in configuration structure:
|
||||
|
||||
int app_nap_STATE_MACHINE(void)
|
||||
{
|
||||
uint16_t length = 0;
|
||||
libnap_network_parameters_s appNetworkSetup = {
|
||||
.beaconProtocolId = br.beacon_protocol_id,
|
||||
.channel_page = channel_list.channel_page,
|
||||
.network_mode = libNAP_RF_INTERFACE_BOOTSRAP,
|
||||
.panID = br.mac_panid,
|
||||
.shortAddress = br.mac_short_adr,
|
||||
.networkIdPtr = br.network_id,
|
||||
.steeringTlvLength = 0,
|
||||
.steeringTlvPtr = 0,
|
||||
};
|
||||
memcpy(appNetworkSetup.channel_mask, channel_list.channel_mask, sizeof(uint32_t) * 8);
|
||||
|
||||
switch (server_state) {
|
||||
.
|
||||
.
|
||||
.
|
||||
case libNAP_SET_CONFIGURATION:
|
||||
length = libNAPBuildMessage(tx_buffer, libNAP_SET_HOST_NETWORK_CONFIGURE_CMD,
|
||||
&appNetworkSetup, 0, 0);
|
||||
break;
|
||||
.
|
||||
.
|
||||
.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
### Network driver application
|
||||
|
||||
**Problem:**
|
||||
|
||||
In the new API, channel page and channel list are delivered instead of the channel number. The parameters in the function `arm_nwk_interface_network_driver_set()` have changed.
|
||||
|
||||
**Solution:**
|
||||
|
||||
- When the network driver application is parsing the `libNAP_SET_HOST_NETWORK_CONFIGURE_CMD` event received from the master device, it needs to read the channel page and channel mask from the received configuration
|
||||
and use them with the `arm_nwk_interface_network_driver_set()` function call.
|
||||
|
||||
void app_nap_parser_ok(libNAP_command_types_e type, libnap_network_parameters_s *config,
|
||||
uint8_t *data_ptr, uint16_t data_length)
|
||||
{
|
||||
channel_list_s channel_list;
|
||||
switch (type) {
|
||||
.
|
||||
.
|
||||
.
|
||||
case libNAP_SET_HOST_NETWORK_CONFIGURE_CMD:
|
||||
.
|
||||
.
|
||||
.
|
||||
channel_list.channel_page = (channel_page_e) config->channel_page;
|
||||
memcpy(channel_list.channel_mask, config->channel_mask, sizeof(uint32_t) * 8);
|
||||
arm_nwk_interface_configure_6lowpan_bootstrap_set(net_6lowpan_id, boot_mode,
|
||||
(net_6lowpan_mode_extension_e) 0);
|
||||
if (arm_nwk_interface_network_driver_set(net_6lowpan_id, tun_driver_id,
|
||||
&channel_list, conf_ptr) == 0) {
|
||||
host_state = libNAP_CONFIGURATION_READY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
.
|
||||
.
|
||||
.
|
||||
}
|
||||
|
||||
**Problem:**
|
||||
|
||||
Nanostack has introduced a public API for adding/deleting routes. As a consequence, default route ::/0 (on-link) is no longer automatically added by nanostack for tunnel interfaces. Border router needs to set a default route manually by using the route add/delete interface.
|
||||
|
||||
**Solution:**
|
||||
|
||||
Function `int8_t arm_net_route_add(const uint8_t *prefix, uint8_t prefix_len, const uint8_t *next_hop, uint32_t lifetime, uint8_t metric, int8_t interface_id)` is defined in `net_interface.h`.
|
||||
|
||||
For example, to add the same default route `::/0 (on-link)` which was earlier added by nanostack, add the following line to the border router application:
|
||||
|
||||
arm_net_route_add(NULL, 0, NULL, 0xffffffff, 128, interface_id);
|
||||
|
||||
where value `0xffffffff` denotes to infinite route lifetime, and value `128` to the default metric value. `NULL` value for `prefix` and `next_hop` parameters means `::/0` prefix and on-link route, respectively. Note that a proper configuration should _always_ add a next-hop value (e.g. link-local address of the neighbouring router) to a default route.
|
||||
|
||||
## PHY drivers
|
||||
|
||||
### PHY driver registration
|
||||
|
||||
**Problem:**
|
||||
|
||||
The content in structure `phy_device_driver_s` has changed. The structure `phy_device_channel_info_s` is replaced with `phy_device_channel_page_s` that contains information about supported channel pages,
|
||||
channel masks, RF configurations etc.
|
||||
|
||||
**Solution:**
|
||||
|
||||
- Remove the existing `phy_device_channel_info_s` structure and all references to it.
|
||||
- Create a new structure `phy_device_channel_page_s` (defined in `arm_hal_phy.h`):
|
||||
|
||||
const phy_device_channel_page_s phy_channel_pages[] = {
|
||||
{CHANNEL_PAGE_0, &phy_rf_conf},
|
||||
{CHANNEL_PAGE_0, NULL}
|
||||
};
|
||||
|
||||
where
|
||||
|
||||
const phy_rf_channel_configuration_s phy_rf_conf =
|
||||
{RF_FREQUENCY, RF_CHANNEL_SPACING, RF_DATARATE, RF_NUMBER_OF_CHANNELS, RF_MODULATION};
|
||||
|
||||
Fill the `phy_rf_conf` structure with:
|
||||
|
||||
- Channel 0 center frequency (Hz)
|
||||
- Channel spacing (Hz)
|
||||
- Datarate (bit/s)
|
||||
- Number of supported channels
|
||||
- Modulation (`M_OFDM`, `M_OQPSK`, `M_BPSK`, `M_GFSK`, `M_UNDEFINED`)
|
||||
|
||||
For example, if using channel page 0 as in IEEE 802.15.4-2006 for the 2.4GHz band (channels 11-26), create the following structures:
|
||||
|
||||
const phy_rf_channel_configuration_s phy_2_4ghz = {2405000000, 5000000, 250000, 16, M_OQPSK};
|
||||
|
||||
const phy_device_channel_page_s phy_channel_pages[] = {
|
||||
{ CHANNEL_PAGE_0, &phy_2_4ghz},
|
||||
{ CHANNEL_PAGE_0, NULL}
|
||||
};
|
||||
|
||||
If using channel page 2 as in IEEE 802.15.4-2006 for Sub 1GHz band (channels 0-10), create the following structures:
|
||||
|
||||
const phy_rf_channel_configuration_s phy_sub1ghz = {868300000, 2000000, 250000, 11, M_OQPSK};
|
||||
|
||||
const phy_device_channel_page_s phy_channel_pages[] = {
|
||||
{ CHANNEL_PAGE_2, &phy_sub1ghz},
|
||||
{ CHANNEL_PAGE_0, NULL}
|
||||
};
|
||||
|
||||
**Note**: Channel 0 is on 868MHz band and channels 1-10 above 900MHz and thereby, channel spacing 2MHz is not valid, but is acceptable in this case.
|
||||
|
||||
If the PHY driver is supporting several configurations, they can be all defined:
|
||||
|
||||
const phy_device_channel_page_s phy_channel_pages[] = {
|
||||
{ CHANNEL_PAGE_0, &phy_2_4ghz},
|
||||
{ CHANNEL_PAGE_2, &phy_sub1ghz},
|
||||
{ CHANNEL_PAGE_0, NULL}
|
||||
};
|
||||
|
||||
**Note**: `phy_device_channel_page_s` last entry MUST be `{CHANNEL_PAGE_0, NULL}`.
|
||||
|
||||
- Add supported channel pages in the device driver structure:
|
||||
|
||||
static phy_device_driver_s device_driver;
|
||||
.
|
||||
.
|
||||
.
|
||||
device_driver.phy_channel_pages = phy_channel_pages;
|
||||
|
||||
- Structure `phy_device_driver_s` is registered to NanoStack with `arm_net_phy_register()` function call as earlier:
|
||||
|
||||
rf_driver_id = arm_net_phy_register(&device_driver);
|
||||
|
||||
### CCA module
|
||||
|
||||
If the PHY driver was using NanoStack internal CCA module, the API call needs to be updated.
|
||||
|
||||
**Problem:**
|
||||
|
||||
The parameters of function `cca_start()` have changed. The function call now needs to tell the driver id that was given by the NanoStack library when the driver was registered.
|
||||
Parameters `cca_check_fptr` and `cca_done_fptr` are also now using `channel_status_e` enumeration that is defined in `cca_api.h`.
|
||||
|
||||
**Solution:**
|
||||
|
||||
- Replace the current `cca_start()` function call:
|
||||
|
||||
cca_start(CCA_RANDOM_IN_RANGE, RF_CCA_MIN, RF_CCA_MAX, rf_check_cca, rf_tx_start);
|
||||
|
||||
with:
|
||||
|
||||
cca_start(rf_driver_id, CCA_RANDOM_IN_RANGE, RF_CCA_MIN, RF_CCA_MAX, rf_check_cca, rf_tx_start);
|
||||
|
||||
where `rf_driver_id` is the return value from the `arm_net_phy_register()` function call.
|
||||
|
||||
- To fix the parameters `cca_check_fptr` and `cca_done_fptr`, replace the current definitions:
|
||||
|
||||
static int rf_check_cca(void); -> static channel_status_e rf_check_cca(void);
|
||||
static void rf_tx_start(int channel_status);
|
||||
-> static void rf_tx_start(channel_status_e channel_status);
|
||||
|
||||
- Fix also the corresponding channel status usage, for example:
|
||||
|
||||
static channel_status_e rf_check_cca(void) {
|
||||
if(rf_read_cca_status() == OK)
|
||||
return CHANNEL_IDLE;
|
||||
return CHANNEL_NOT_IDLE;
|
||||
}
|
||||
|
||||
static void rf_tx_start(channel_status_e channel_status) {
|
||||
if(channel_status == CHANNEL_NOT_IDLE) {
|
||||
arm_net_phy_tx_done(rf_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 1, 1);
|
||||
} else {
|
||||
.
|
||||
.
|
||||
.
|
||||
}
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
# About this document
|
||||
|
||||
This document walks you through the API changes in the Nanostack version 4.1.x in detail and helps you to update your current applications to use the new and changed APIs.
|
||||
|
||||
**New APIs:**
|
||||
|
||||
- Load balancing
|
||||
- Whiteboard API
|
||||
|
||||
**Changed APIs:**
|
||||
|
||||
- FHSS platform API
|
||||
- eDTLS API
|
||||
- dev_stat API
|
||||
|
||||
|
||||
## [**Load balancing**](17_API_load_balancer.md)
|
||||
|
||||
Load balancing (LB) is a new feature to allow devices to switch from a loaded network into a better one. Load balancing operates with given rules and developer(s) SHOULD NOT try to aim at evenly balanced networks (might cause churn).
|
||||
|
||||
To enable this feature, use the build time flag `HAVE_6LOWPAN_ND`.
|
||||
|
||||
The new LB functions are presented briefly here:
|
||||
|
||||
- `typedef bool net_load_balance_network_switch_notify(int8_t interface_id);`
|
||||
|
||||
Typedef of a callback function, that you can implement to control network switching. If you do not implement this, the network switch takes place automatically when applicable.
|
||||
|
||||
- `void net_load_balance_network_switch_cb_set(net_load_balance_network_switch_notify *network_switch_notify);`
|
||||
|
||||
A setter function to set (/unset with NULL) a callback function, which is called when the system has found a better network to join.
|
||||
|
||||
- `int8_t net_load_balance_create(int8_t interface_id, bool enable_periodic_beacon_interval);`
|
||||
|
||||
Creates and enables the load balancing feature.
|
||||
|
||||
- `int8_t net_load_balance_delete(int8_t interface_id);`
|
||||
|
||||
Deletes and disables the load balancing feature.
|
||||
|
||||
- `int8_t net_load_balance_threshold_set(int8_t interface_id, uint8_t threshold_min, uint8_t threshold_max);`
|
||||
|
||||
A setter for a threshold to control when a device can change the network. The difference (diff) of networks is counted. If the diff is smaller than the minimum treshold, nothing happens. If the diff is greater than or equal with the max threshold, the default or set probability value is used. Otherwise, min and max values affect the switch probability:
|
||||
|
||||
- If the diff is close to min -> very poor chance to switch.
|
||||
- If the diff is close to max --> almost the same probability as is set.
|
||||
|
||||
See `net_load_balance_set_max_probability` below for more details.
|
||||
|
||||
- `int8_t net_load_balance_set_max_probability(int8_t interface_id , uint8_t max_p);`
|
||||
|
||||
A setter for maximum probability for a device will switch the network. The proposed value is between 10 and 25 to prevent all devices from switching network at the same time (the default value is 25). Also a block period is activated if the device fails to change the network (this is automatic). Threshold minimum and maximum will add more probability on top of this and therefore, this value can be thought only as a maximum probability for switching.
|
||||
|
||||
- `int8_t net_load_balance_load_level_update_enable(int8_t interface_id, uint16_t expected_device_count);`
|
||||
|
||||
This needs the build time flag `HAVE_RPL`.
|
||||
|
||||
<span class="notes">**Note:** Border router (BR) feature only! Enables automatic updates of the DODAG preference, which is used to measure the quality of a network. The expected device count is calculated by network designer to set the number of devices this BR should connect. This is not a hard limit, it just tells when the designed device count has been reached!</span>
|
||||
|
||||
- `int8_t net_load_balance_load_level_update_disable(int8_t interface_id);`
|
||||
|
||||
This needs the build time flag `HAVE_RPL`.
|
||||
|
||||
<span class="notes">**Note:** Border router feature only! Disables automatic updates of DODAG preference. Also disables measurement of expected device count.</span>
|
||||
|
||||
## Whiteboard API
|
||||
|
||||
Whiteboard API is used to limit the number of devices allowed to join to network.
|
||||
|
||||
To enable this feature, use the build time flag `WHITEBOARD`.
|
||||
|
||||
The limit is needed in situations where one BR goes down and the devices connected to it start to find another networks. This can cause other BRs to have out-of-memory (OOM) situations, if there are lots of connected devices. When the limit is reached, the BR will not accept any new connection(s). If set to 0, there is no limit.
|
||||
|
||||
`void whiteboard_set_device_hard_limit(uint16_t limit);`
|
||||
|
||||
## Frequency-hopping Spread Spectrum (FHSS)
|
||||
|
||||
### FHSS platform API
|
||||
|
||||
FHSS platform API was simplified in this version of Nanostack. The FHSS time measurement functions were removed and replaced with the timestamp callback.
|
||||
|
||||
See the instructions below to fix any conflicts:
|
||||
|
||||
Remove the time measure callbacks from the FHSS platform function structure and replace them with the timestamp read callback:
|
||||
|
||||
static fhss_platform_functions_s fhss_functions = {
|
||||
&fhss_timer_start,
|
||||
&fhss_timer_stop,
|
||||
&fhss_timer_get_remaining_slots,
|
||||
+ &fhss_timestamp_read,
|
||||
- &fhss_time_measure_start,
|
||||
- &fhss_time_measure_read,
|
||||
- &fhss_time_measure_stop,
|
||||
RESOLUTION_DIVIDER
|
||||
};
|
||||
|
||||
Remove also corresponding time measure functions from the driver as they are not needed anymore.
|
||||
|
||||
The new timestamp callback function must be implemented:
|
||||
|
||||
uint32_t fhss_timestamp_read(void)
|
||||
{
|
||||
.
|
||||
.
|
||||
.
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
The timestamp function must return a 32-bit timestamp value with 1us resolution (if resolution divider is not used). The return value is time since the FHSS driver was started and a 32-bit counter is allowed to overflow.
|
||||
|
||||
## eDTLS API update
|
||||
|
||||
### eDTLS connection status update and sn_edtls_exec() call guidance
|
||||
|
||||
The eDTLS library calls the connection status callback by `EDTLS_ECC_CALCULATING` when it starts the ECC calculation. When ECC is started, the application should call the `sn_edtls_exec()` function rapidly to trigger a new event until the connection status gives `EDTLS_ECC_CALCULATION_READY`. This status means that callbacks to `sn_edtls_exec()` can be stopped.
|
||||
|
||||
The `sn_edtls_exec()` function should be called periodically using one second interval with the updated timer value, which triggers the re-transmission of the eDTLS library when needed. The `sn_edtls_exec()` should also be called when the eDTLS library has parsed the handshake message successfully (`sn_edtls_parse_data` returns 0). When the eDTLS callback has status `EDTLS_CONNECTION_OK`, `EDTLS_CONNECTION_CLOSED` or `EDTLS_CONNECTION_FAILED`, the periodical timer can be stopped until a new connection is started by the `sn_edtls_connect()` function.
|
||||
|
||||
## dev_stats_api API update
|
||||
|
||||
The `dev stats_api.h` file has been removed which means that the following functions are not available anymore:
|
||||
|
||||
- `dev_stat_internal_init()`
|
||||
- `dev_stat_get_longest_heap_sector()`
|
||||
- `dev_stat_get_runtime_seconds()`
|
||||
|
||||
The heap stats are still available when the `ns_dyn_mem_init()` call `info_pr` is defined. (`nsdynMEMLIB.h`)
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
# API Changes
|
||||
|
||||
This document walks you through the API changes in the Nanostack version 5.0.x in detail and helps you to update your current applications to use the new and changed APIs.
|
||||
|
||||
**New APIs:**
|
||||
|
||||
- MAC API
|
||||
- Ethernet MAC API
|
||||
- Serial MAC API
|
||||
- Virtual RF API
|
||||
- SW MAC API
|
||||
|
||||
**Deleted APIs:**
|
||||
- `br_list_nvm_api.h`
|
||||
- `br_mle_lib.h`
|
||||
- `socket_security.h`
|
||||
- `cca_api.h`
|
||||
|
||||
**Disabled APIs:**
|
||||
- `net_fhss.h`
|
||||
|
||||
|
||||
**Other changes:**
|
||||
|
||||
- `net_interface.h`: Separated `arm_nwk_interface_init()` to MAC-specific initialisers.
|
||||
* `arm_nwk_interface_ethernet_init()`
|
||||
* `arm_nwk_interface_lowpan_init()`
|
||||
|
||||
- `arm_hal_phy.h`: Added rx and tx_done callbacks to `phy_device_driver_s` to be settable instead of the function.
|
||||
* `arm_net_phy_rx()` changed to `phy_device_driver_s.phy_rx_cb`
|
||||
* `arm_net_phy_tx_done()` changed to `phy_device_driver_s.phy_tx_done_cb`
|
||||
|
||||
- `arm_hal_phy.h`: Added rx and tx virtual callbacks to `phy_device_driver_s` to be settable by the upper layer.
|
||||
* `phy_device_driver_s.arm_net_virtual_rx_cb`
|
||||
* `phy_device_driver_s.arm_net_virtual_tx_cb`
|
||||
|
||||
- `mac_common_defines.h` added
|
||||
|
||||
- `nanostack/mac_mcps.h` added
|
||||
|
||||
- `mlme.h` published
|
||||
|
||||
- `net_nwk_scan.h` minor changes
|
||||
|
||||
- Local socket "support" removed. Serial MAC should be used instead.
|
||||
|
||||
|
||||
|
|
@ -1,571 +0,0 @@
|
|||
# Device Driver API
|
||||
|
||||
The 6LoWPAN stack uses Device Driver API to communicate with different physical layer drivers. The 6LoWPAN stack supports different device types for PHY layer and special cases where raw IPv6 datagrams are forwarded to a driver.
|
||||
|
||||
The driver must first be registered with the 6LoWPAN stack using the `phy_device_driver_s` structure defined in section [_PHY device driver register_](#phy-device-driver-register). This structure defines all the functions that the stack uses when calling a device driver. When the device driver must call the driver API from the stack, it uses the ID number received in the registration phase to distinct between different devices. The following sections define the contents of the driver structures and API interfaces that the driver can use.
|
||||
|
||||
See Doxygen documentation for the latest [Device Drive API](https://docs.mbed.com/docs/arm-ipv66lowpan-stack/en/latest/api/arm__hal__phy_8h.html).
|
||||
|
||||
## Providing RF driver for Mbed OS applications
|
||||
|
||||
For Mbed OS 5, the RF driver implements the `NanostackRfPhy` API. `MeshInterfaceNanostack` requires the driver object to be provided when initializing.
|
||||
|
||||
![NanostackRfPhy](img/NanostackRfPhy.png)
|
||||
|
||||
Applications use only `LoWPANNDInterface`, `ThreadInterface` or `NanostackEthernetInterface`
|
||||
directly to set up the network and provide a driver. The rest of the classes provide an abstration
|
||||
between Nanostack and the socket layers of Mbed OS.
|
||||
|
||||
See [NanostackRfPhy.h](https://github.com/ARMmbed/mbed-os/blob/master/features/nanostack/FEATURE_NANOSTACK/nanostack-interface/NanostackRfPhy.h) for an up-to-date header file and API.
|
||||
|
||||
### How to create a new RF driver
|
||||
|
||||
The following steps describe how you can create a new RF driver:
|
||||
|
||||
1. Read through the section [_Example RF driver_](#example-rf-driver). You can use this example code as your starting point.
|
||||
|
||||
1. Fill in the actual transceiver-specific parts of the RF driver.
|
||||
|
||||
1. Register the driver to the 6LoWPAN stack on your application. You can use the example node applications with your driver.
|
||||
|
||||
1. Create a MAC that is suitable for your purpose (802.15.4, Ethernet or serial).
|
||||
|
||||
1. Configure the interface. See instructions in the chapter [_6LoWPAN stack Initialisation_](07_API_initialize.md#how-to-configure-a-network-interface).
|
||||
|
||||
1. Implement the `NanostackRfPhy` API.
|
||||
|
||||
1. Check with a RF sniffer tool that you can see RF packets transmitted when you start your device. The 6LoWPAN bootstrap should start with IEEE 802.15.4 Beacon Request packets.
|
||||
|
||||
#### Worker thread for Mbed OS
|
||||
|
||||
Nanostack's interfaces use mutexes for protecting the access from multiple threads. In Mbed OS, the mutex cannot be used
|
||||
from an interrupt. The same applies to all APIs that have internal locking and multithread support. Therefore, each driver must implement their own worker thread to handle the interrupt requests.
|
||||
|
||||
![Worker Thread](img/worker_thread.png)
|
||||
|
||||
Example: Use worked thread and signals from an interrupt
|
||||
|
||||
```
|
||||
// Signals from interrupt routines
|
||||
#define SIG_RADIO 1
|
||||
#define SIG_TIMER 2
|
||||
|
||||
// Worker thread
|
||||
Thread irq_thread;
|
||||
|
||||
// Interrupt routines
|
||||
static void rf_interrupt(void)
|
||||
{
|
||||
irq_thread.signal_set(SIG_RADIO);
|
||||
}
|
||||
|
||||
static void rf_timer_signal(void)
|
||||
{
|
||||
irq_thread.signal_set(SIG_TIMER);
|
||||
}
|
||||
|
||||
|
||||
// Worker thread
|
||||
void rf_worker_thread(void)
|
||||
{
|
||||
for (;;) {
|
||||
osEvent event = irq_thread.signal_wait(0);
|
||||
if (event.status != osEventSignal) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event.value.signals & SIG_RADIO) {
|
||||
rf_process_irq();
|
||||
}
|
||||
if (event.value.signals & SIG_TIMER) {
|
||||
rf_process_timer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
...
|
||||
// Somewhere in the initialization code
|
||||
irq_thread.start(rf_if_irq_task);
|
||||
|
||||
```
|
||||
|
||||
### RF driver states
|
||||
|
||||
_Figure 11-1_ below shows the basic states of the RF driver.
|
||||
|
||||
The basic states in more detail:
|
||||
|
||||
State|Description
|
||||
-----|-----------
|
||||
`DOWN`|This is the initial state of the driver. The radio is not used in this state.
|
||||
`RX ACTIVE`|In this state, the driver has the radio turned on and it can receive a packet or ACK from the radio. The driver can also go from this state to the `TX ACTIVE` state to transmit a packet.
|
||||
`TX ACTIVE`|In this state, the driver will try to start a transmission:<br>1. It must first check that it is not currently busy doing something else.<br>2. It must check that the channel is free.<br>3. Finally, it can try to transmit the packet.
|
||||
`SNIFFER`|This mode can be implemented to enable using the device as a packet sniffer. In this state, the RX is always on and the received packets are sent to the application layer but nothing is transmitted back.
|
||||
`ED SCAN`|This mode can be implemented to enable energy scan. It enables scanning the energy from channels one by one and nothing else.
|
||||
`ANY STATE`|This state represents all the states in the state machine.
|
||||
|
||||
<span class="notes">**Note**: The driver [initialization and registration](#phy-device-driver-register) using the function `arm_net_phy_register` must be performed before the driver is functional.</span>
|
||||
|
||||
For more details on the TX process, see _Figure 4-1_.
|
||||
|
||||
**Figure 4-1 RF driver states**
|
||||
|
||||
![scan](img/ed_scan_process.png)
|
||||
|
||||
In sniffer mode, the device only receives packets, never ACKs or sends them.
|
||||
|
||||
The following commands are received as a parameter of the function `state_control` defined in the struct of type `phy_device_driver_s`:
|
||||
|
||||
- `PHY_INTERFACE_UP`
|
||||
- `PHY_INTERFACE_DOWN`
|
||||
- `PHY_INTERFACE_RESET`
|
||||
- `PHY_INTERFACE_RX_ENERGY_STATE`
|
||||
- `PHY_INTERFACE_SNIFFER_STATE`
|
||||
|
||||
The following commands are received as a parameter of the function `extension` defined in the struct of type `phy_device_driver_s`:
|
||||
|
||||
- `PHY_EXTENSION_READ_CHANNEL_ENERGY`
|
||||
- `PHY_EXTENSION_SET_CHANNEL`
|
||||
|
||||
_Figure 4-2_ describes the TX process.
|
||||
|
||||
The following describes the states in more detail:
|
||||
|
||||
State|Description
|
||||
-----|-----------
|
||||
`CCA PROCESS`|In the _Clear Channel Assessment_ (CCA) process, the radio checks that the channel is free before it starts sending anything to avoid collisions. Before starting the actual CCA process, the driver checks that it is not currently receiving a packet from the radio, in which case the CCA process fails.
|
||||
`SEND PACKET`|In this state, the driver commands the radio to send the data given to the driver as a parameter from the function tx defined in the struct of type `phy_device_driver_s`.
|
||||
|
||||
**Figure 4-2 TX process**
|
||||
|
||||
![tx](img/tx_process.png)
|
||||
|
||||
### PHY device driver register
|
||||
|
||||
This function is for the dynamic registration of a PHY device driver. The 6LoWPAN stack allocates its own device driver list internally. This list is used when an application creates network interfaces to a specific PHY driver.
|
||||
|
||||
To register a PHY driver to the stack:
|
||||
|
||||
```
|
||||
int8_t arm_net_phy_register(phy_device_driver_s *phy_driver);
|
||||
```
|
||||
|
||||
See the [Doxygen](https://docs.mbed.com/docs/arm-ipv66lowpan-stack/en/latest/api/arm__hal__phy_8h.html#aff06eaa736d3784c956dc6eda9f27419) for the description.
|
||||
|
||||
|
||||
### PHY data RX API
|
||||
|
||||
This is a callback that is a part of the device driver structure and initialized by the stack when a driver is registered.
|
||||
|
||||
The driver calls this function to push the received data from a PHY to the stack:
|
||||
|
||||
```
|
||||
typedef int8_t arm_net_phy_rx_fn(const uint8_t *data_ptr, uint16_t data_len, uint8_t link_quality, int8_t dbm, int8_t driver_id);
|
||||
```
|
||||
|
||||
See [Doxygen: arm_net_phy_rx_fn](https://docs.mbed.com/docs/arm-ipv66lowpan-stack/en/latest/api/arm__hal__phy_8h.html#a962b27c1de3163a37d0e298e5107ab6f) for detailed description.
|
||||
|
||||
### PHY data TX done API
|
||||
|
||||
This is a callback that is a part of the device driver structure and initialized by the stack when a driver is registered.
|
||||
|
||||
The driver calls this function when it has completed a transmit attempt:
|
||||
|
||||
```
|
||||
typedef int8_t arm_net_phy_tx_done_fn(int8_t driver_id, uint8_t tx_handle, phy_link_tx_status_e status, uint8_t cca_retry, uint8_t tx_retry);
|
||||
```
|
||||
See [Doxygen: arm_net_phy_tx_done_fn](https://docs.mbed.com/docs/arm-ipv66lowpan-stack/en/latest/api/arm__hal__phy_8h.html#a045291825cbb1f29aec30891d44e8e52) for detailed description.
|
||||
|
||||
When the PHY device handles the CSMA-CA and auto-retry, the stack needs to know the total number of CCA attempts or TX attempts made in case of error. The stack retries the CCA phase 8 times and the TX attempt 4 times. These may be handled by the hardware.
|
||||
|
||||
If the CSMA-CA is handled by the hardware, the `cca_retry` should return a value larger than 7 if returning `PHY_LINK_CCA_FAIL` status to the stack. If the total number of CCA retries is less than 8, the stack initiates a new CCA phase.
|
||||
|
||||
When the hardware handles the auto-retry mode, the error cases should report the number of TX attempts made in the `tx_retry` parameter. If the total number of retries is less that 4, the stack initiates a retransmission.
|
||||
|
||||
### PHY driver structure and enumeration definitions
|
||||
|
||||
This section introduces driver API specific structures and enumerations.
|
||||
|
||||
#### PHY TX process status code
|
||||
|
||||
This enumeration defines the PHY TX process status code:
|
||||
|
||||
```
|
||||
typedef enum phy_link_tx_status_e
|
||||
{
|
||||
PHY_LINK_TX_DONE,
|
||||
PHY_LINK_TX_DONE_PENDING,
|
||||
PHY_LINK_TX_SUCCESS,
|
||||
PHY_LINK_TX_FAIL,
|
||||
PHY_LINK_CCA_FAIL
|
||||
} phy_link_tx_status_e;
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`TX_DONE`|TX process is Ready and ACK RX.
|
||||
`TX_DONE_PENDING`|TX process is OK with an ACK pending flag.
|
||||
`TX_SUCCESS`|MAC TX complete MAC will make a decision to enter a wait ack or TX Done state.
|
||||
`TX_FAIL`|The link TX process fails.
|
||||
`CCA_FAIL`|RF link CCA process fails.
|
||||
|
||||
#### PHY interface control types
|
||||
|
||||
This enumeration defines the PHY interface control types:
|
||||
|
||||
```
|
||||
typedef enum phy_interface_state_e
|
||||
{
|
||||
PHY_INTERFACE_RESET,
|
||||
PHY_INTERFACE_DOWN,
|
||||
PHY_INTERFACE_UP
|
||||
} phy_interface_state_e;
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`RESET`|Resets a PHY driver and sets it to idle.
|
||||
`DOWN`|Disables the PHY interface driver (RF radio disabled).
|
||||
`UP`|Enables the PHY interface driver (RF radio receiver ON).
|
||||
|
||||
|
||||
#### PHY device driver
|
||||
|
||||
This PHY device driver structure comprises the following members:
|
||||
|
||||
```
|
||||
typedef struct phy_device_driver_s
|
||||
{
|
||||
phy_link_type_e link_type;
|
||||
driver_data_request_e data_request_layer;
|
||||
uint8_t *PHY_MAC;
|
||||
uint16_t phy_MTU; /**< Define MAX PHY layer MTU size. */
|
||||
char * driver_description;
|
||||
uint16_t phy_MTU;
|
||||
uint8_t phy_tail_length;
|
||||
uint8_t phy_header_length;
|
||||
int8_t (*state_control)(phy_interface_state_e, uint8_t);
|
||||
int8_t (*tx)(uint8_t *,uint16_t,uint8_t, data_protocol_e);
|
||||
int8_t (*address_write)(phy_address_type_e ,uint8_t *);
|
||||
int8_t (*extension)(phy_extension_type_e,uint8_t *);
|
||||
const phy_device_channel_page_s *phy_channel_pages;
|
||||
|
||||
//Upper layer callbacks, set with arm_net_phy_init();
|
||||
arm_net_phy_rx *phy_rx_cb;
|
||||
arm_net_phy_tx_done *phy_tx_done_cb;
|
||||
//Virtual upper layer rx/tx functions
|
||||
arm_net_virtual_rx *arm_net_virtual_rx_cb;
|
||||
arm_net_virtual_tx *arm_net_virtual_tx_cb;
|
||||
uint16_t tunnel_type;
|
||||
} phy_device_driver_s;
|
||||
```
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`link_type`|Defines the device driver type.
|
||||
`data_request_layer`|Defines the interface Data OUT protocol.
|
||||
`PHY_MAC`|A pointer to a 48-bit or 64-bit MAC address.
|
||||
`PHY_MTU`|The size of the maximum transmission unit.
|
||||
`driver_description`|A short driver-specific description in Null-terminated string format.
|
||||
`phy_MTU`|The maximum MTU size of the physical layer.
|
||||
`phy_tail_length`|The tail length used by the PHY driver.
|
||||
`phy_header_length`|The header length used by the PDU PHY driver.
|
||||
`state_control`|A function pointer to the interface state control.
|
||||
`tx`|A function pointer to the interface TX functionality.
|
||||
`address_write`|A function pointer to the interface address writing (PAN ID, short address).
|
||||
`extension`|A function pointer to the interface extension control.
|
||||
`phy_channel_pages`|This pointer must be set only when the interface type is:<br>`NET_INTERFACE_WIFI`<br>`NET_INTERFACE_RF_6LOWPAN`<br>`NET_INTERFACE_RF_ZIGBEEIP`
|
||||
`phy_rx_cb`|A function pointer to the upper layer RX callback. Must be initialized to NULL, is set by MAC layer.
|
||||
`phy_tx_done_cb`|A function pointer to the upper layer TX callback. Must be initialized to NULL, is set by MAC layer.
|
||||
`arm_net_virtual_rx_cb`|A function pointer to the upper layer RX callback. Only needed by a virtual RF driver! Must be initialized to NULL, is set by MAC layer or virtual RF driver.
|
||||
`arm_net_virtual_tx_cb`|A function pointer to the upper layer tx callback. Only needed by virtual RF driver! Must be initialized to NULL, is set by MAC layer or virtual RF driver
|
||||
`tunnel_type`|TUN driver type this is only valid when link type is PHY_TUN
|
||||
|
||||
See [Doxygen: Device Drive API](https://docs.mbed.com/docs/arm-ipv66lowpan-stack/en/latest/api/arm__hal__phy_8h.html) for up to date descriptions.
|
||||
|
||||
#### PHY device channel page information
|
||||
|
||||
This structure defines the PHY device channel page information and comprises the following members:
|
||||
|
||||
```
|
||||
typedef struct phy_device_channel_page_s
|
||||
{
|
||||
channel_page_e channel_page;
|
||||
const phy_rf_channel_configuration_s *rf_channel_configuration;
|
||||
} phy_device_channel_page_s;
|
||||
```
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`channel_page`|The supported channel page(s).
|
||||
`rf_channel_configuration`|The used RF configuration for the channel page.
|
||||
|
||||
#### PHY device link type
|
||||
|
||||
This enumeration defines the PHY device link types:
|
||||
|
||||
```
|
||||
typedef enum phy_link_type_e
|
||||
{
|
||||
PHY_LINK_ETHERNET_TYPE,
|
||||
PHY_LINK_15_4_2_4GHZ_TYPE,
|
||||
PHY_LINK_15_4_SUBGHZ_TYPE,
|
||||
PHY_LINK_TUN,
|
||||
PHY_LINK_SLIP,
|
||||
} phy_link_type_e;
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`ETHERNET_TYPE`|The standard IEEE 802 Ethernet type.
|
||||
`15_4_2_4GHZ_TYPE`|The standard 802.15.4 2.4GHz radio.
|
||||
`15_4_SUBGHZ_TYPE`|The standard 802.15.4 sub-1GHz radio 868/915MHz.
|
||||
`TUN`|The Linux virtual TUN interface.
|
||||
`SLIP`|The SLIP interface.
|
||||
|
||||
#### PHY device RF channel configuration
|
||||
|
||||
This structure defines the PHY device RF configuration:
|
||||
|
||||
```
|
||||
typedef struct phy_rf_channel_configuration_s
|
||||
{
|
||||
uint32_t channel_0_center_frequency;
|
||||
uint32_t channel_spacing;
|
||||
uint32_t datarate;
|
||||
uint16_t number_of_channels;
|
||||
phy_modulation_e modulation;
|
||||
} phy_rf_channel_configuration_s;
|
||||
```
|
||||
|
||||
Member|Description
|
||||
------|-----------
|
||||
`channel_0_center_frequency`|The first channel center frequency.
|
||||
`channel_spacing`|The RF channel spacing.
|
||||
`datarate`|The RF datarate.
|
||||
`number_of_channels`|The number of supported channels.
|
||||
`modulation`|The RF modulation method.
|
||||
|
||||
#### PHY device RF modulation methods
|
||||
|
||||
This enumeration defines the PHY device RF modulation methods:
|
||||
|
||||
```
|
||||
typedef enum phy_modulation_e
|
||||
{
|
||||
M_OFDM,
|
||||
M_OQPSK,
|
||||
M_BPSK,
|
||||
M_GFSK,
|
||||
M_UNDEFINED
|
||||
} phy_modulation_e;
|
||||
```
|
||||
|
||||
Parameter|Description
|
||||
---------|-----------
|
||||
`M_OFDM`|The OFDM modulation method.
|
||||
`M_OQPSK`|The OQPSK modulation method.
|
||||
`M_BPSK`|The BPSK modulation method.
|
||||
`M_GFSK`|The GFSK modulation method.
|
||||
`M_UNDEFINED`|The RF modulation method undefined.
|
||||
|
||||
### Example RF driver
|
||||
|
||||
The following code example is not a complete driver but shows you how to use the API to create a RF driver.
|
||||
|
||||
```
|
||||
static uint8_t mac_address[8];
|
||||
static phy_device_driver_s device_driver;
|
||||
static int8_t rf_radio_driver_id = -1;
|
||||
|
||||
const phy_rf_channel_configuration_s phy_2_4ghz = {2405000000, 5000000, 250000, 16, M_OQPSK};
|
||||
const phy_rf_channel_configuration_s phy_subghz = {868300000, 2000000, 250000, 11, M_OQPSK};
|
||||
|
||||
static phy_device_channel_page_s phy_channel_pages[] = {
|
||||
{CHANNEL_PAGE_0, &phy_2_4ghz},
|
||||
{CHANNEL_PAGE_0, NULL}
|
||||
};
|
||||
|
||||
int8_t rf_device_register(void)
|
||||
{
|
||||
/* Do some initialization */
|
||||
rf_init();
|
||||
/* Set pointer to MAC address */
|
||||
device_driver.PHY_MAC = mac_address;
|
||||
/* Set driver Name */
|
||||
device_driver.driver_description = "Example";
|
||||
|
||||
if(subghz_radio) /* Configuration for Sub GHz Radio */
|
||||
{
|
||||
/*Type of RF PHY is SubGHz*/
|
||||
device_driver.link_type = PHY_LINK_15_4_SUBGHZ_TYPE;
|
||||
phy_channel_pages[0].channel_page = CHANNEL_PAGE_2;
|
||||
phy_channel_pages[0].rf_channel_configuration = &phy_subghz;
|
||||
}
|
||||
else /* Configuration for 2.4 GHz Radio */
|
||||
{
|
||||
/*Type of RF PHY is 2.4 GHz*/
|
||||
device_driver.link_type = PHY_LINK_15_4_2_4GHZ_TYPE;
|
||||
phy_channel_pages[0].channel_page = CHANNEL_PAGE_0;
|
||||
phy_channel_pages[0].rf_channel_configuration = &phy_2_4ghz;
|
||||
}
|
||||
|
||||
/*Maximum size of payload is 127*/
|
||||
device_driver.phy_MTU = 127;
|
||||
/*No header in PHY*/
|
||||
device_driver.phy_header_length = 0;
|
||||
/*No tail in PHY*/
|
||||
device_driver.phy_tail_length = 0;
|
||||
|
||||
/*Set up driver functions*/
|
||||
device_driver.address_write = &rf_address_write;
|
||||
device_driver.extension = &rf_extension;
|
||||
device_driver.state_control = &rf_interface_state_control;
|
||||
device_driver.tx = &rf_start_cca;
|
||||
/*Set supported channel pages*/
|
||||
device_driver.phy_channel_pages = phy_channel_pages;
|
||||
//Nullify rx/tx callbacks
|
||||
device_driver.phy_rx_cb = NULL;
|
||||
device_driver.phy_tx_done_cb = NULL;
|
||||
device_driver.arm_net_virtual_rx_cb = NULL;
|
||||
device_driver.arm_net_virtual_tx_cb = NULL;
|
||||
|
||||
/*Register device driver*/
|
||||
rf_radio_driver_id = arm_net_phy_register(&device_driver);
|
||||
|
||||
return rf_radio_driver_id;
|
||||
}
|
||||
|
||||
void rf_handle_rx_end(void)
|
||||
{
|
||||
uint8_t rf_lqi;
|
||||
int8_t rf_rssi;
|
||||
uint16_t rf_buffer_len;
|
||||
uint8_t *rf_buffer;
|
||||
|
||||
/* Get received data */
|
||||
rf_buffer_len = rf_get_rf_buffer(rf_buffer);
|
||||
if(!rf_buffer_len)
|
||||
return;
|
||||
|
||||
/* If waiting for ACK, check here if the packet is an ACK to a message previously sent */
|
||||
|
||||
/* Get link information */
|
||||
rf_rssi = rf_get_rssi();
|
||||
rf_lqi = rf_get_lqi();
|
||||
|
||||
/* Note: Checksum of the packet must be checked and removed before entering here */
|
||||
|
||||
/* Send received data and link information to the network stack */
|
||||
if( device_driver.phy_rx_cb ){
|
||||
device_driver.phy_rx_cb(rf_buffer, rf_buffer_len, rf_lqi, rf_rssi, rf_radio_driver_id);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t rf_start_cca(uint8_t *data_ptr, uint16_t data_length, uint8_t tx_handle, data_protocol_e data_protocol)
|
||||
{
|
||||
/*Check if transmitter is busy*/
|
||||
if(transmitter_busy)
|
||||
{
|
||||
/*Return busy*/
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*Check if transmitted data needs to be ACKed*/
|
||||
if(*data_ptr & 0x20)
|
||||
need_ack = 1;
|
||||
else
|
||||
need_ack = 0;
|
||||
/*Store the sequence number for ACK handling*/
|
||||
tx_sequence = *(data_ptr + 2);
|
||||
|
||||
/* Store date and start CCA process here */
|
||||
/* When the CCA process is ready send the packet */
|
||||
/* Note: Before sending the packet you need to calculate and add a checksum to it, unless done automatically by the radio */
|
||||
}
|
||||
|
||||
/*Return success*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t rf_interface_state_control(phy_interface_state_e new_state, uint8_t rf_channel)
|
||||
{
|
||||
int8_t ret_val = 0;
|
||||
switch (new_state)
|
||||
{
|
||||
/*Reset PHY driver and set to idle*/
|
||||
case PHY_INTERFACE_RESET:
|
||||
rf_reset();
|
||||
break;
|
||||
/*Disable PHY Interface driver*/
|
||||
case PHY_INTERFACE_DOWN:
|
||||
rf_shutdown();
|
||||
break;
|
||||
/*Enable PHY Interface driver*/
|
||||
case PHY_INTERFACE_UP:
|
||||
rf_channel_set(rf_channel);
|
||||
rf_receive();
|
||||
break;
|
||||
/*Enable wireless interface ED scan mode*/
|
||||
case PHY_INTERFACE_RX_ENERGY_STATE:
|
||||
break;
|
||||
/*Enable Sniffer state*/
|
||||
case PHY_INTERFACE_SNIFFER_STATE:
|
||||
rf_setup_sniffer(rf_channel);
|
||||
break;
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
static int8_t rf_extension(phy_extension_type_e extension_type, uint8_t *data_ptr)
|
||||
{
|
||||
switch (extension_type)
|
||||
{
|
||||
/*Control MAC pending bit for Indirect data transmission*/
|
||||
case PHY_EXTENSION_CTRL_PENDING_BIT:
|
||||
/*Return frame pending status*/
|
||||
case PHY_EXTENSION_READ_LAST_ACK_PENDING_STATUS:
|
||||
*data_ptr = rf_if_last_acked_pending();
|
||||
break;
|
||||
/*Set channel, used for setting channel for energy scan*/
|
||||
case PHY_EXTENSION_SET_CHANNEL:
|
||||
break;
|
||||
/*Read energy on the channel*/
|
||||
case PHY_EXTENSION_READ_CHANNEL_ENERGY:
|
||||
*data_ptr = rf_get_channel_energy();
|
||||
break;
|
||||
/*Read status of the link*/
|
||||
case PHY_EXTENSION_READ_LINK_STATUS:
|
||||
*data_ptr = rf_get_link_status();
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int8_t rf_address_write(phy_address_type_e address_type, uint8_t *address_ptr)
|
||||
{
|
||||
|
||||
switch (address_type)
|
||||
{
|
||||
/*Set 48-bit address*/
|
||||
case PHY_MAC_48BIT:
|
||||
/* Not used in this example */
|
||||
break;
|
||||
/*Set 64-bit address*/
|
||||
case PHY_MAC_64BIT:
|
||||
rf_set_mac_address(address_ptr);
|
||||
break;
|
||||
/*Set 16-bit address*/
|
||||
case PHY_MAC_16BIT:
|
||||
rf_set_short_adr(address_ptr);
|
||||
break;
|
||||
/*Set PAN Id*/
|
||||
case PHY_MAC_PANID:
|
||||
rf_set_pan_id(address_ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 4.4 KiB |
|
@ -1,66 +0,0 @@
|
|||
@startuml
|
||||
|
||||
package "mbed OS Socket abstraction" {
|
||||
abstract class MeshInterface -|> NetworkInterface
|
||||
|
||||
interface NetworkInterface {
|
||||
+connect();
|
||||
+disconnect();
|
||||
+NetworkStack *get_stack();
|
||||
}
|
||||
|
||||
interface NetworkStack
|
||||
}
|
||||
|
||||
package "Nanostack PHY driver interface" {
|
||||
interface NanostackPhy {
|
||||
+int8_t phy_register()
|
||||
+void get_mac_address(uint8_t *mac)
|
||||
+void set_mac_address(uint8_t *mac)
|
||||
}
|
||||
NanostackPhy <|-- abstract class NanostackRfPhy
|
||||
NanostackPhy <|-- abstract class NanostackEthernetPhy
|
||||
}
|
||||
|
||||
package "mesh API internals" {
|
||||
class NanostackInterface {
|
||||
{static} +NanostackInterface *get_stack()
|
||||
#socket_open()
|
||||
#socket_close()
|
||||
#socket_bind()
|
||||
#socket_listen()
|
||||
#socket_connect()
|
||||
#socket_accept()
|
||||
#socket_send()
|
||||
#socket_recv()
|
||||
#socket_sendto()
|
||||
#socket_recvfrom()
|
||||
#socket_attach()
|
||||
#setsockopt()
|
||||
#getsockopt()
|
||||
}
|
||||
NetworkStack <|-- NanostackInterface
|
||||
|
||||
abstract class MeshInterfaceNanostack {
|
||||
+initialize(NanostackPhy *phy)
|
||||
+connect()
|
||||
+disconnect()
|
||||
#NetworkStack *get_stack(void)
|
||||
}
|
||||
MeshInterface <|-- MeshInterfaceNanostack
|
||||
NanostackPhy --o MeshInterfaceNanostack
|
||||
MeshInterfaceNanostack -left-> NanostackInterface : get_stack()
|
||||
}
|
||||
|
||||
package "mbed-mesh-api" {
|
||||
MeshInterfaceNanostack <|-- LoWPANNDInterface
|
||||
MeshInterfaceNanostack <|-- ThreadInterface
|
||||
MeshInterfaceNanostack <|-- NanostackEthernetInterface
|
||||
}
|
||||
|
||||
|
||||
hide empty members
|
||||
hide empty attributes
|
||||
hide empty fields
|
||||
|
||||
@enduml
|
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 91 KiB |
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 58 KiB |
|
@ -1,28 +0,0 @@
|
|||
@startuml
|
||||
|
||||
package "mbed OS Socket abstraction" {
|
||||
interface NetworkStack
|
||||
NetworkStack -o Socket
|
||||
abstract class Socket
|
||||
Socket <|-- UDPSocket
|
||||
Socket <|-- TCPSocket
|
||||
Socket <|-- TCPServer
|
||||
}
|
||||
|
||||
interface NetworkInterface
|
||||
NetworkInterface --> NetworkStack : get_stack()
|
||||
EthernetInterface --|> NetworkInterface
|
||||
CellularInterface --|> NetworkInterface
|
||||
|
||||
package "mbed-mesh-api" {
|
||||
abstract class MeshInterfaceNanostack <|-- LoWPANNDInterface
|
||||
MeshInterfaceNanostack <|-- ThreadInterface
|
||||
MeshInterfaceNanostack --|> NetworkInterface
|
||||
}
|
||||
|
||||
|
||||
hide empty members
|
||||
hide empty attributes
|
||||
hide empty fields
|
||||
|
||||
@enduml
|
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 8.7 KiB |
Before Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 36 KiB |