Contiki-NG
sixtop.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016, Yasuyuki Tanaka
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28  * OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 /**
31  * \addtogroup sixtop
32  * @{
33  */
34 /**
35  * \file
36  * 6TiSCH Operation Sublayer (6top)
37  *
38  * \author
39  * Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
40  */
41 
42 #include "lib/assert.h"
43 
44 #include "net/netstack.h"
45 #include "net/packetbuf.h"
48 
49 #include "sixtop.h"
50 #include "sixtop-conf.h"
51 #include "sixp.h"
52 
53 /* Log configuration */
54 #include "sys/log.h"
55 #define LOG_MODULE "6top"
56 #define LOG_LEVEL LOG_LEVEL_6TOP
57 
58 const sixtop_sf_t *scheduling_functions[SIXTOP_MAX_SCHEDULING_FUNCTIONS];
59 
60 const sixtop_sf_t *sixtop_find_sf(uint8_t sfid);
61 
62 /*---------------------------------------------------------------------------*/
63 void
64 strip_payload_termination_ie(void)
65 {
66  uint8_t *ptr = packetbuf_dataptr();
67  if(ptr[0] == 0x00 && ptr[1] == 0xf8) {
68  /* Payload Termination IE is 2 octets long */
70  }
71 }
72 /*---------------------------------------------------------------------------*/
73 int
75 {
76  int i;
77 
78  assert(sf != NULL);
79 
80  LOG_INFO("6top: sixtop_add_sf() is adding a SF [SFID:%u]\n", sf->sfid);
81 
82  if(sixtop_find_sf(sf->sfid) != NULL) {
83  LOG_ERR("6top: sixtop_add_sf() fails because of duplicate SF\n");
84  return -1;
85  }
86 
87  for(i = 0; i < SIXTOP_MAX_SCHEDULING_FUNCTIONS; i++) {
88  if(scheduling_functions[i] == NULL) {
89  scheduling_functions[i] = sf;
90  if(sf->init != NULL) {
91  sf->init();
92  }
93  break;
94  }
95  }
96 
97  if(i == SIXTOP_MAX_SCHEDULING_FUNCTIONS) {
98  LOG_ERR("6top: sixtop_add_sf() fails because of no memory\n");
99  return -1;
100  }
101 
102  if(sf->init != NULL) {
103  sf->init();
104  }
105  LOG_INFO("6top: SF [SFID:%u] has been added and initialized\n", sf->sfid);
106  return 0;
107 }
108 /*---------------------------------------------------------------------------*/
109 const sixtop_sf_t *
110 sixtop_find_sf(uint8_t sfid)
111 {
112  int i;
113 
114  for(i = 0; i < SIXTOP_MAX_SCHEDULING_FUNCTIONS; i++) {
115  if(scheduling_functions[i] != NULL &&
116  scheduling_functions[i]->sfid == sfid) {
117  return (const sixtop_sf_t *)scheduling_functions[i];
118  }
119  }
120 
121  return NULL;
122 }
123 /*---------------------------------------------------------------------------*/
124 int
125 sixtop_output(const linkaddr_t *dest_addr, mac_callback_t callback, void *arg)
126 {
127  uint8_t *p;
128  struct ieee802154_ies ies;
129  int len;
130 
131  assert(dest_addr != NULL);
132  if(dest_addr == NULL) {
133  LOG_ERR("6top: sixtop_output() fails because dest_addr is NULL\n");
134  if(callback != NULL) {
135  callback(arg, MAC_TX_ERR_FATAL, 0);
136  }
137  return -1;
138  }
139 
140  /* prepend 6top Sub-IE ID */
141  if(packetbuf_hdralloc(1) != 1) {
142  LOG_ERR("6top: sixtop_output() fails because of no room for Sub-IE ID\n");
143  return -1;
144  }
145  p = packetbuf_hdrptr();
146  p[0] = SIXTOP_SUBIE_ID;
147 
148  /*
149  * prepend Payload IE header; 2 octets
150  * only sixtop_ie_content_len matters in frame80215e_create_ie_ietf().
151  */
152  memset(&ies, 0, sizeof(ies));
153  ies.sixtop_ie_content_len = packetbuf_totlen();
154  if(packetbuf_hdralloc(2) != 1 ||
155  (len = frame80215e_create_ie_ietf(packetbuf_hdrptr(),
156  2,
157  &ies)) < 0) {
158  LOG_ERR("6top: sixtop_output() fails because of Payload IE Header\n");
159  if(callback != NULL) {
160  callback(arg, MAC_TX_ERR_FATAL, 0);
161  }
162  return -1;
163  }
164 
165 #if SIXP_WITH_PAYLOAD_TERMINATION_IE
166  /* append Payload Termination IE to the data field; 2 octets */
167  memset(&ies, 0, sizeof(ies));
168  if((len = frame80215e_create_ie_payload_list_termination(
169  (uint8_t *)packetbuf_dataptr() + packetbuf_datalen(),
171  &ies)) < 0) {
172  LOG_ERR("6top: sixtop_output() fails because of Payload Termination IE\n");
173  callback(arg, MAC_TX_ERR_FATAL, 0);
174  return -1;
175  }
177 #endif /* SIXP_WITH_PAYLOAD_TERMINATION_IE */
178 
179  /* prepend Termination 1 IE to the header field; 2 octets */
180  memset(&ies, 0, sizeof(ies));
181  if(packetbuf_hdralloc(2) &&
182  frame80215e_create_ie_header_list_termination_1(packetbuf_hdrptr(),
183  2,
184  &ies) < 0) {
185  LOG_ERR("6top: sixtop_output() fails because of Header Termination 1 IE\n");
186  callback(arg, MAC_TX_ERR_FATAL, 0);
187  return -1;
188  }
189 
190  /* specify with PACKETBUF_ATTR_METADATA that packetbuf has IEs */
191  packetbuf_set_attr(PACKETBUF_ATTR_MAC_METADATA, 1);
192 
193  /* 6P packet is data frame */
194  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
195 
196  packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, dest_addr);
197  packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
198 
199  NETSTACK_MAC.send(callback, arg);
200  return 0;
201 }
202 /*---------------------------------------------------------------------------*/
203 void
205 {
206  uint8_t *hdr_ptr, *payload_ptr;
207  uint16_t hdr_len, payload_len;
208 
209  frame802154_t frame;
210  struct ieee802154_ies ies;
211  linkaddr_t src_addr;
212 
213  /*
214  * A received *DATA* frame is supposed to be stored in packetbuf by
215  * framer_802154.parse(). packetbuf_dataptr() points at the starting address
216  * of the IE field or Frame Payload field if it's available. FCS should not be
217  * in packetbuf, which is expected to be stripped at a radio.
218  */
219 
220  payload_ptr = packetbuf_dataptr();
221  payload_len = packetbuf_datalen();
222  hdr_len = packetbuf_hdrlen();
223  hdr_ptr = payload_ptr - hdr_len;
224 
225  memcpy(&src_addr, packetbuf_addr(PACKETBUF_ADDR_SENDER), sizeof(src_addr));
226 
227  if(frame802154_parse(hdr_ptr, hdr_len, &frame) == 0) {
228  /* parse error; should not occur, anyway */
229  LOG_ERR("6top: frame802154_parse error\n");
230  return;
231  }
232 
233  /*
234  * We don't need to check the frame version nor frame type. The frame version
235  * is turned out to be 0b10 automatically if the frame has a IE list. The
236  * frame type is supposed to be DATA as mentioned above.
237  */
238  assert(frame.fcf.frame_version == FRAME802154_IEEE802154_2015);
239  assert(frame.fcf.frame_type == FRAME802154_DATAFRAME);
240  memset(&ies, 0, sizeof(ies));
241  if(frame.fcf.ie_list_present &&
242  frame802154e_parse_information_elements(payload_ptr,
243  payload_len, &ies) >= 0 &&
244  ies.sixtop_ie_content_ptr != NULL &&
245  ies.sixtop_ie_content_len > 0) {
246 
247  sixp_input(ies.sixtop_ie_content_ptr, ies.sixtop_ie_content_len,
248  &src_addr);
249 
250  /*
251  * move payloadbuf_dataptr() to the beginning of the next layer for further
252  * processing
253  */
254  packetbuf_hdrreduce(ies.sixtop_ie_content_ptr - payload_ptr +
255  ies.sixtop_ie_content_len);
256  strip_payload_termination_ie();
257  }
258 }
259 /*---------------------------------------------------------------------------*/
260 void
262 {
263  int i;
264 
265  sixp_init();
266 
267  for(i = 0; i < SIXTOP_MAX_SCHEDULING_FUNCTIONS; i++) {
268  scheduling_functions[i] = NULL;
269  }
270 
271  sixtop_init_sf();
272 }
273 /*---------------------------------------------------------------------------*/
274 void
276 {
277  int i;
278 
279  for(i = 0; i < SIXTOP_MAX_SCHEDULING_FUNCTIONS; i++) {
280  if(scheduling_functions[i] != NULL &&
281  scheduling_functions[i]->init != NULL) {
282  scheduling_functions[i]->init();
283  }
284  }
285 }
286 /*---------------------------------------------------------------------------*/
287 /** @} */
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:143
/brief Scheduling Function Driver
Definition: sixtop.h:104
frame802154_fcf_t fcf
Frame control field.
Definition: frame802154.h:204
void(* init)(void)
Init Function.
Definition: sixtop.h:107
void sixtop_init_sf(void)
Initialize installed SFs which has been added in the system This function is supposed to be invoked e...
Definition: sixtop.c:275
int packetbuf_hdralloc(int size)
Extend the header of the packetbuf, for outbound packets.
Definition: packetbuf.c:107
#define SIXTOP_MAX_SCHEDULING_FUNCTIONS
The maximum number of Scheduling Functions in the system.
Definition: sixtop-conf.h:51
IEEE 802.15.4e Information Element (IE) creation and parsing.
int packetbuf_hdrreduce(int size)
Reduce the header in the packetbuf, for incoming packets.
Definition: packetbuf.c:124
int frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
Parses an input frame.
Definition: frame802154.c:500
const sixtop_sf_t * sixtop_find_sf(uint8_t sfid)
Find a SF which has been added by SFID.
Definition: sixtop.c:110
6top Protocol (6P) APIs
uint8_t packetbuf_hdrlen(void)
Get the length of the header in the packetbuf.
Definition: packetbuf.c:161
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Definition: packetbuf.c:155
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
Definition: linkaddr.c:48
void sixtop_init(void)
Initialize 6top module This initialization function removes all the SFs which has been installed into...
Definition: sixtop.c:261
void sixtop_input(void)
Input a packet stored in packetbuf.
Definition: sixtop.c:204
uint8_t sfid
SFID.
Definition: sixtop.h:105
uint8_t frame_version
2 bit.
Definition: frame802154.h:162
int sixtop_add_sf(const sixtop_sf_t *sf)
Add a Scheduling Function (SF) to 6top Sublayer.
Definition: sixtop.c:74
uint16_t packetbuf_totlen(void)
Get the total length of the header and data in the packetbuf.
Definition: packetbuf.c:167
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
Definition: packetbuf.h:67
802.15.4 frame creation and parsing functions
uint8_t frame_type
3 bit.
Definition: frame802154.h:153
Parameters used by the frame802154_create() function.
Definition: frame802154.h:198
6TiSCH Operation Sublayer (6top) APIs
void sixp_init(void)
Initialize 6P Module It invokes sixp_nbr_init() and sixp_trans_init().
Definition: sixp.c:532
void * packetbuf_hdrptr(void)
Get a pointer to the header in the packetbuf, for outbound packets.
Definition: packetbuf.c:149
void(* send)(mac_callback_t sent_callback, void *ptr)
Send a packet from the packetbuf.
Definition: mac.h:69
uint8_t ie_list_present
1 bit.
Definition: frame802154.h:160
Header file for the Packet buffer (packetbuf) management
Include file for the Contiki low-layer network stack (NETSTACK)
void sixp_input(const uint8_t *buf, uint16_t len, const linkaddr_t *src_addr)
Input a 6P packet.
Definition: sixp.c:205
Header file for the logging system
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:136
int sixtop_output(const linkaddr_t *dest_addr, mac_callback_t callback, void *arg)
Output a 6P packet which is supposestored in packetbuf.
Definition: sixtop.c:125
6top Configuration