211 lines
8.2 KiB
Text
211 lines
8.2 KiB
Text
|
/**
|
||
|
\addtogroup uip
|
||
|
@{
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* \defgroup sicslowpan 6LoWPAN implementation
|
||
|
* @{
|
||
|
|
||
|
6lowpan is a Working Group in IETF which defines the use of IPv6 on
|
||
|
IEEE 802.15.4 links.
|
||
|
|
||
|
Our implementation is based on RFC4944 <em>Transmission of IPv6
|
||
|
Packets over IEEE 802.15.4 Networks</em>, draft-hui-6lowpan-interop-00
|
||
|
<em>Interoperability Test for 6LoWPAN</em>, and draft-hui-6lowpan-hc-01
|
||
|
<em>Compression format for IPv6 datagrams in 6lowpan Networks</em>.
|
||
|
|
||
|
<HR>
|
||
|
|
||
|
\section drafts Specifications implemented
|
||
|
|
||
|
\note We currently only support 802.15.4 64-bit addresses.
|
||
|
|
||
|
\subsection rfc4944 RFC 4944
|
||
|
|
||
|
RFC4944 defines address configuration mechanisms based on 802.15.4
|
||
|
16-bit and 64-bit addresses, fragmentation of IPv6 packets below IP
|
||
|
layer, IPv6 and UDP header compression, a mesh header to enable link-layer
|
||
|
forwarding in a mesh under topology, and a broadcast header to enable
|
||
|
broadcast in a mesh under topology.
|
||
|
|
||
|
|
||
|
We implement addressing, fragmentation, and header compression. We support
|
||
|
the header compression scenarios defined in draft-hui-6lowpan-interop-00.
|
||
|
This draft defines an interoperability scenario which was used between
|
||
|
ArchRock and Sensinode implementations.
|
||
|
|
||
|
We do not implement mesh under related features, as we target route over
|
||
|
techniques.
|
||
|
|
||
|
\subsection hc01 draft-hui-6lowpan-hc-01
|
||
|
|
||
|
draft-hui-6lowpan-hc-01 defines a stateful header compression mechanism
|
||
|
which should soon deprecate the stateless header compression mechanism
|
||
|
defined in RFC4944. It is much more powerfull and flexible, in
|
||
|
particular it allows compression of some multicast addresses and of all
|
||
|
global unicast addresses.
|
||
|
|
||
|
<HR>
|
||
|
|
||
|
\section general Implementation overview
|
||
|
|
||
|
6lowpan does not run as a separate process. It is called by the MAC %process
|
||
|
when a 6lowpan packet is received, and by the tcpip %process when an
|
||
|
IPv6 packet needs to be sent.
|
||
|
|
||
|
It is initialized from the MAC %process, which calls sicslowpan_init
|
||
|
(giving as argument a pointer to the mac_driver structure).
|
||
|
|
||
|
The main 6lowpan functions are implemented in the sicslowpan.h and
|
||
|
sicslowpan.c files. They are used to format packets between the
|
||
|
802.15.4 and the IPv6 layers.
|
||
|
|
||
|
6lowpan also creates a few IPv6 and link-layer dependencies which are
|
||
|
detailed in the next section.
|
||
|
|
||
|
<HR>
|
||
|
|
||
|
\section implementation Implementation details
|
||
|
|
||
|
\subsection Addressing
|
||
|
|
||
|
<b>Link-layer addresses</b><br>
|
||
|
The format of a 802.15.4 address is defined in uip.h.
|
||
|
\code
|
||
|
/** \brief 64 bit 802.15.4 address */
|
||
|
struct uip_802154_shortaddr {
|
||
|
u8_t addr[2];
|
||
|
};
|
||
|
/** \brief 16 bit 802.15.4 address */
|
||
|
struct uip_802154_longaddr {
|
||
|
u8_t addr[8];
|
||
|
};
|
||
|
/** \brief 802.15.4 address */
|
||
|
typedef struct uip_802154_longaddr uip_lladdr_t;
|
||
|
#define UIP_802154_SHORTADDR_LEN 2
|
||
|
#define UIP_802154_LONGADDR_LEN 8
|
||
|
#define UIP_LLADDR_LEN UIP_802154_LONGADDR_LEN
|
||
|
\endcode
|
||
|
|
||
|
<b>Neighbor Discovery Link Layer Address options </b><br>
|
||
|
The format of ND link-layer address options depends on the length of
|
||
|
the link-layer addresses.
|
||
|
802.15.4 specificities regarding link-layer address options are implemented in uip-nd6.h.
|
||
|
\code
|
||
|
#define UIP_ND6_OPT_SHORT_LLAO_LEN 8
|
||
|
#define UIP_ND6_OPT_LONG_LLAO_LEN 16
|
||
|
#define UIP_ND6_OPT_LLAO_LEN UIP_ND6_OPT_LONG_LLAO_LEN
|
||
|
\endcode
|
||
|
|
||
|
<b>Address Autoconfiguration</b><br>
|
||
|
The address autoconfiguration mechanism also depends on the format of
|
||
|
the link-layer address. The dependency is reflected in the
|
||
|
#uip_netif_addr_autoconf_set function in #uip-netif.c.
|
||
|
\code
|
||
|
#if (UIP_LLADDR_LEN == 8)
|
||
|
memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN);
|
||
|
ipaddr->u8[8] ^= 0x02;
|
||
|
\endcode
|
||
|
|
||
|
\subsection io Packet Input/Output
|
||
|
|
||
|
At initialization, the #input function in sicslowpan.c is set as the
|
||
|
function to be called by the MAC upon packet reception. The #output
|
||
|
function is set as the tcpip_output function.<br>
|
||
|
At packet reception, the link-layer copies the 802.15.4 payload in the
|
||
|
rime buffer, and sets its length. It also stores the source and
|
||
|
destination link-layer addresses as two rime addresses.
|
||
|
\code
|
||
|
rimebuf_copyfrom(&rx_frame.payload, rx_frame.payload_length);
|
||
|
rimebuf_set_datalen(rx_frame.payload_length);
|
||
|
rimebuf_set_addr(RIMEBUF_ADDR_RECEIVER, (const rimeaddr_t *)&rx_frame.dest_addr);
|
||
|
rimebuf_set_addr(RIMEBUF_ADDR_SENDER, (const rimeaddr_t *)&rx_frame.src_addr);
|
||
|
\endcode
|
||
|
It then calls the sicslowpan #input function. Similarly, when the IPv6 layer
|
||
|
has a packet to send over the radio, it puts the packet in uip_buf,
|
||
|
sets uip_len and calls the sicslowpan #output function.
|
||
|
|
||
|
\subsection frag Fragmentation
|
||
|
|
||
|
\li #output function: When an IP packet, after header compression, is
|
||
|
too big to fit in a 802.15.4 frame, it is fragmented in several packets
|
||
|
which are sent successively over the radio. The packets are formatted
|
||
|
as defined in RFC 4944. Only the first fragment contains the IP/UDP
|
||
|
compressed or uncompressed header fields.
|
||
|
|
||
|
\li #input function: This function takes care of fragment
|
||
|
reassembly. We do not assume that the fragments are received in order.
|
||
|
When reassembly of a packet is ongoing, we discard any non fragmented
|
||
|
packet or fragment from another packet. Reassembly times out after
|
||
|
#SICSLOWPAN_REASS_MAXAGE = 20s.
|
||
|
|
||
|
\note Fragmentation support is enabled by setting the #SICSLOWPAN_CONF_FRAG
|
||
|
compilation option.
|
||
|
|
||
|
\note As we do not support complex buffer allocation mechanism, for now
|
||
|
we define a new 1280 bytes buffer (#sicslowpan_buf) to reassemble packets.
|
||
|
At reception, once all the fragments are received, we copy the packet
|
||
|
to #uip_buf, set #uip_len, and call #tcpip_input.
|
||
|
|
||
|
\note #MAC_MAX_PAYLOAD defines the maximum payload
|
||
|
length in a 802.15.4 frame. For now it is constant and equal to 102
|
||
|
bytes (the 802.15.4 frame can be maximum 127 bytes long, and
|
||
|
the header 25 bytes long).
|
||
|
|
||
|
\subsection hc Header Compression
|
||
|
|
||
|
<b>Compression schemes</b><br>
|
||
|
The #SICSLOWPAN_CONF_COMPRESSION compilation option defines the
|
||
|
compression scheme supported. We support HC1, HC01, and IPv6 compression.
|
||
|
HC1 and IPv6 compression are defined in RFC4944, HC01 in
|
||
|
draft-hui-6lowpan-hc. What we call IPv6 compression means sending packets
|
||
|
with no compression, and adding the IPv6 dispatch before the IPv6 header.<br>
|
||
|
If at compile time IPv6 "compression" is chosen, packets sent will never
|
||
|
be compressed, and compressed packets will not be processed at reception.<br>
|
||
|
If at compile time either HC1 or HC01 are chosen, we will try to compress
|
||
|
all fields at sending, and will accept packets compressed with the
|
||
|
chosen scheme, as well as uncompressed packets.<br>
|
||
|
Note that HC1 and HC01 supports are mutually exclusive. HC01 should soon
|
||
|
deprecate HC1.
|
||
|
|
||
|
<b>Compression related functions</b><br>
|
||
|
When a packet is received, the #input function is called. Fragmentation
|
||
|
issues are handled, then we check the dispatch byte: if it is IPv6, we
|
||
|
treat the packet inline. If it is HC1 or HC01, the corresponding
|
||
|
decompression function (#uncompress_hdr_hc1 or #uncompress_hdr_hc01)
|
||
|
is called.<br>
|
||
|
When a packet needs to be sent, we try to compress it. If only the IPv6
|
||
|
compression support is enabled, we just add the IPv6 dispatch before the
|
||
|
802.15.4 payload. If HC1 or HC01 support is enabled, we call the
|
||
|
corresponding compression function (#compress_hdr_hc1 or #compress_hdr_hc01)
|
||
|
to compress the packet as much as possible.
|
||
|
|
||
|
<b>HC1 comments</b><br>
|
||
|
In HC1, if the IPv6 flow label is not compressed, we would need to copy
|
||
|
the fields after the flow label starting in the middle of a byte (the
|
||
|
flow label is 20 bits long). To avoid this, we compress the packets only
|
||
|
if all fields can be compressed. If we cannot, we use the IPv6 dispatch
|
||
|
and send all headers fields inline. This behavior is the one defined in
|
||
|
draft-hui-6lowpan-interop-00.<br>
|
||
|
In the same way, if the packet is an UDP packet, we compress the UDP
|
||
|
header only if all fields can be compressed.<br>
|
||
|
Note that HC1 can only compress unicast link local addresses. For this
|
||
|
reason, we recommend using HC01.
|
||
|
|
||
|
<b>HC01 comments</b><br>
|
||
|
HC01 uses address contexts to enable compression of global unicast
|
||
|
addresses. All nodes must share context (namely the global prefixes in
|
||
|
use) to compress and uncompress such addresses successfully. The context
|
||
|
number is defined by 2 bits. Context 00 is reserved for the link local
|
||
|
context. Other contexts have to be distributed within the LoWPAN
|
||
|
dynamically, by means of ND extensions yet to be defined.<br>
|
||
|
Until then, if you want to test global address compression, you need
|
||
|
to configure the global contexts manually.
|
||
|
|
||
|
<HR>
|
||
|
|
||
|
*/
|
||
|
/** @} */
|
||
|
/** @} */
|