Contiki-NG
sixp.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  * 6top Protocol (6P)
37  * \author
38  * Yasuyuki Tanaka <yasuyuki.tanaka@inf.ethz.ch>
39  */
40 
41 #include "contiki-lib.h"
42 #include "lib/assert.h"
43 
44 #include "sixtop.h"
45 #include "sixp-nbr.h"
46 #include "sixp-pkt.h"
47 #include "sixp-trans.h"
48 
49 /* Log configuration */
50 #include "sys/log.h"
51 #define LOG_MODULE "6top"
52 #define LOG_LEVEL LOG_LEVEL_6TOP
53 
54 static void mac_callback(void *ptr, int status, int transmissions);
55 static int send_back_error(sixp_pkt_type_t type, sixp_pkt_rc_t rc,
56  const sixp_pkt_t *pkt, const linkaddr_t *dest_addr);
57 static void handle_schedule_inconsistency(const sixtop_sf_t *sf,
58  const sixp_pkt_t *recved_pkt,
59  const linkaddr_t *peer_addr);
60 /*---------------------------------------------------------------------------*/
61 static void
62 mac_callback(void *ptr, int status, int transmissions)
63 {
64  sixp_trans_t *trans = (sixp_trans_t *)ptr;
65  sixp_trans_state_t new_state, current_state;
66 
67  assert(trans != NULL);
68  if(trans == NULL) {
69  LOG_ERR("6P: mac_callback() fails because trans is NULL\n");
70  return;
71  } else if(sixp_trans_get_state(trans) == SIXP_TRANS_STATE_WAIT_FREE) {
72  /* the transaction has been invalidated; free it now */
73  const sixtop_sf_t *sf = sixp_trans_get_sf(trans);
74  if(sf != NULL && sf->error != NULL) {
75  sf->error(SIXP_ERROR_TX_AFTER_TRANSACTION_TERMINATION,
76  sixp_trans_get_cmd(trans),
77  sixp_trans_get_seqno(trans),
79  }
80  sixp_trans_free(trans);
81  return;
82  }
83 
84  current_state = sixp_trans_get_state(trans);
85  new_state = SIXP_TRANS_STATE_UNAVAILABLE;
86  if(status == MAC_TX_OK) {
87  switch(current_state) {
88  case SIXP_TRANS_STATE_REQUEST_SENDING:
89  new_state = SIXP_TRANS_STATE_REQUEST_SENT;
90  break;
91  case SIXP_TRANS_STATE_RESPONSE_SENDING:
92  new_state = SIXP_TRANS_STATE_RESPONSE_SENT;
93  break;
94  case SIXP_TRANS_STATE_CONFIRMATION_SENDING:
95  new_state = SIXP_TRANS_STATE_CONFIRMATION_SENT;
96  break;
97  default:
98  LOG_ERR("6P: mac_callback() fails because of an unexpected state (%u)\n",
99  current_state);
100  /* don't change the state */
101  new_state = current_state;
102  break;
103  }
104  } else {
105  /*
106  * In a case of transmission failure of a request, a corresponding SF would
107  * retransmit the request with a new transaction. For a response or a
108  * confirmation, the same transaction will be used for retransmission as
109  * long as it doesn't have timeout.
110  */
111  if(current_state == SIXP_TRANS_STATE_REQUEST_SENDING) {
112  /* request case */
113  new_state = SIXP_TRANS_STATE_TERMINATING;
114  } else {
115  /* response or confirmation case: stay the same state */
116  new_state = current_state;
117  }
118  }
119 
120  if(new_state != current_state &&
121  sixp_trans_transit_state(trans, new_state) != 0) {
122  LOG_ERR("6P: mac_callback() fails because of state transition failure\n");
123  LOG_ERR("6P: something wrong; we're terminating the trans %p\n", trans);
124  (void)sixp_trans_transit_state(trans, SIXP_TRANS_STATE_TERMINATING);
125  return;
126  }
127 
129  status == MAC_TX_OK ?
132  sixp_trans_set_callback(trans, NULL, NULL, 0);
133 }
134 /*---------------------------------------------------------------------------*/
135 static int
136 send_back_error(sixp_pkt_type_t type, sixp_pkt_rc_t rc,
137  const sixp_pkt_t *pkt, const linkaddr_t *dest_addr)
138 {
139  sixp_trans_t *trans;
140 
141  assert(pkt != NULL);
142  assert(dest_addr != NULL);
143 
144  if((rc == SIXP_PKT_RC_ERR_VERSION) ||
145  (rc == SIXP_PKT_RC_ERR_SFID) ||
146  (rc == SIXP_PKT_RC_ERR_BUSY) ||
147  (rc == SIXP_PKT_RC_ERR_SEQNUM &&
148  (trans = sixp_trans_find(dest_addr)) != NULL &&
149  sixp_trans_get_state(trans) != SIXP_TRANS_STATE_REQUEST_RECEIVED)) {
150  /* create a 6P packet within packetbuf */
151  if(sixp_pkt_create(type, (sixp_pkt_code_t)(uint8_t)rc,
152  pkt->sfid, pkt->seqno, NULL, 0, NULL) < 0) {
153  LOG_ERR("6P: failed to create a 6P packet to return an error [rc:%u]\n",
154  rc);
155  return -1;
156  }
157  /*
158  * for RC_ERR_VERSION and RC_ERR_SFID, we don't care about how the
159  * transmission goes for unsupported packets; no need to set
160  * callback.
161  *
162  * for RC_ERR_BUSY, we cannot allocate another transaction. so we call
163  * sixtop_output() directly
164  *
165  * when we're going to send RC_ERR_SEQNUM to a peer to whom we
166  * have a transaction under way, we call sixtop_output() directly
167  * to prevent allocating another transaction
168  */
169  sixtop_output(dest_addr, NULL, NULL);
170  } else {
171  /*
172  * 6P creates a transaction to send an error other than listed
173  * above. we use sixp_output to make 'nbr' have a correct
174  * next_seqno.
175  */
176  sixp_output(type, (sixp_pkt_code_t)(uint8_t)rc, pkt->sfid,
177  NULL, 0, dest_addr, NULL, NULL, 0);
178  }
179  LOG_ERR("6P: send an error code %u to ", rc);
180  LOG_ERR_LLADDR(dest_addr);
181  LOG_ERR_("\n");
182  return 0;
183 }
184 /*---------------------------------------------------------------------------*/
185 static void
186 handle_schedule_inconsistency(const sixtop_sf_t *sf,
187  const sixp_pkt_t *recved_pkt,
188  const linkaddr_t *peer_addr)
189 {
190  assert(recved_pkt != NULL);
191  assert(peer_addr != NULL);
192 
194  recved_pkt, peer_addr) < 0) {
195  LOG_ERR("6P: sixp_input() fails to return an error response\n");
196  }
197  if(sf != NULL && sf->error != NULL) {
198  sf->error(SIXP_ERROR_SCHEDULE_INCONSISTENCY,
199  (sixp_pkt_cmd_t)recved_pkt->code.value, recved_pkt->seqno,
200  peer_addr);
201  }
202 }
203 /*---------------------------------------------------------------------------*/
204 void
205 sixp_input(const uint8_t *buf, uint16_t len, const linkaddr_t *src_addr)
206 {
207  sixp_pkt_t pkt;
208  sixp_trans_t *trans;
209  sixp_nbr_t *nbr;
210  const sixtop_sf_t *sf;
211  int16_t seqno;
212  int ret;
213 
214  assert(buf != NULL && src_addr != NULL);
215  if(buf == NULL || src_addr == NULL) {
216  return;
217  }
218 
219  if(sixp_pkt_parse(buf, len, &pkt) < 0) {
220  if(pkt.version != SIXP_PKT_VERSION) {
221  LOG_ERR("6P: sixp_input() unsupported version %u\n", pkt.version);
223  (const sixp_pkt_t *)&pkt, src_addr) < 0) {
224  LOG_ERR("6P: sixp_input() fails to send RC_ERR_VERSION\n");
225  }
226  } else {
227  LOG_ERR("6P: sixp_input() fails because of a malformed 6P packet\n");
228  }
229  return;
230  }
231 
232  if(pkt.type != SIXP_PKT_TYPE_REQUEST &&
233  pkt.type != SIXP_PKT_TYPE_RESPONSE &&
235  LOG_ERR("6P: sixp_input() fails because of unsupported type [type:%u]\n",
236  pkt.type);
237  return;
238  }
239 
240  if((sf = sixtop_find_sf(pkt.sfid)) == NULL) {
241  LOG_ERR("6P: sixp_input() fails because SF [sfid:%u] is unavailable\n",
242  pkt.sfid);
243  /*
244  * XXX: what if the incoming packet is a response? confirmation should be
245  * sent back?
246  */
247  if(send_back_error(SIXP_PKT_TYPE_RESPONSE, SIXP_PKT_RC_ERR_SFID,
248  (const sixp_pkt_t *)&pkt, src_addr) < 0) {
249  LOG_ERR("6P: sixp_input() fails to return an error response\n");
250  };
251  return;
252  }
253 
254  /* Transaction Management */
255  trans = sixp_trans_find(src_addr);
256 
257  if(pkt.type == SIXP_PKT_TYPE_REQUEST) {
258  if(trans != NULL) {
259  if(pkt.code.cmd != SIXP_PKT_CMD_CLEAR &&
260  ((pkt.seqno == 0 && sixp_trans_get_seqno(trans) != 0) ||
261  (pkt.seqno != 0 && sixp_trans_get_seqno(trans) == 0))) {
262  /*
263  * seems the peer had power-cycle; we're going to send back
264  * RC_ERR_SEQNUM. in this case, we don't want to allocate
265  * another transaction for this new request.
266  */
267  handle_schedule_inconsistency(sf, (const sixp_pkt_t *)&pkt, src_addr);
268  return;
269  } else {
270  /* Error: not supposed to have another transaction with the peer. */
271  LOG_ERR("6P: sixp_input() fails because another request [peer_addr:");
272  LOG_ERR_LLADDR((const linkaddr_t *)src_addr);
273  LOG_ERR_(" seqno:%u] is in process\n", sixp_trans_get_seqno(trans));
274  /*
275  * Although RFC 8480 says in Section 3.4.3 that we MUST send
276  * RC_RESET back in this case, we use RC_ERR_BUSY
277  * instead. RC_RESET requires the peer to revert SeqNum update
278  * by the corresponding transaction, which may cause
279  * unnecessary SeqNum disagreement. This also would make the
280  * implementation complex. At this moment, no benefit is seen
281  * in using RC_RESET over RC_ERR_BUSY.
282  */
283  if(send_back_error(SIXP_PKT_TYPE_RESPONSE, SIXP_PKT_RC_ERR_BUSY,
284  (const sixp_pkt_t *)&pkt, src_addr) < 0) {
285  LOG_ERR("6P: sixp_input() fails to return an error response");
286  }
287  return;
288  }
289  }
290 
291  if((pkt.code.cmd == SIXP_PKT_CMD_CLEAR) &&
292  (nbr = sixp_nbr_find(src_addr)) != NULL) {
293  LOG_INFO("6P: sixp_input() reset nbr's next_seqno by CLEAR Request\n");
295  }
296 
297  if((trans = sixp_trans_alloc(&pkt, src_addr)) == NULL) {
298  LOG_ERR("6P: sixp_input() fails because of lack of memory\n");
299  if(send_back_error(SIXP_PKT_TYPE_RESPONSE, SIXP_PKT_RC_ERR_BUSY,
300  (const sixp_pkt_t *)&pkt, src_addr) < 0) {
301  LOG_ERR("6P: sixp_input() fails to return an error response\n");
302  }
303  return;
304  }
305 
306  /* Inconsistency Management */
307  if(pkt.code.cmd != SIXP_PKT_CMD_CLEAR &&
308  (((nbr = sixp_nbr_find(src_addr)) == NULL &&
309  (pkt.seqno != 0)) ||
310  ((nbr != NULL) &&
311  (sixp_nbr_get_next_seqno(nbr) != 0) &&
312  pkt.seqno == 0))) {
313  if(trans != NULL) {
315  SIXP_TRANS_STATE_REQUEST_RECEIVED);
316  handle_schedule_inconsistency(sf, (const sixp_pkt_t *)&pkt, src_addr);
317  }
318  return;
319  }
320 
321  } else if(pkt.type == SIXP_PKT_TYPE_RESPONSE ||
323  if(trans == NULL) {
324  /* Error: should have a transaction for incoming packet */
325  LOG_ERR("6P: sixp_input() fails because of no trans [peer_addr:");
326  LOG_ERR_LLADDR((const linkaddr_t *)src_addr);
327  LOG_ERR_("]\n");
328  return;
329  } else if((seqno = sixp_trans_get_seqno(trans)) < 0 ||
330  seqno != pkt.seqno) {
331  LOG_ERR("6P: sixp_input() fails because of invalid seqno [seqno:%u, %u]\n",
332  seqno, pkt.seqno);
333  /*
334  * Figure 31 of RFC 8480 implies there is a chance to receive a
335  * 6P Response having RC_ERR_SEQNUM and SeqNum of 0. But, it
336  * shouldn't happen according to the definition of SeqNum
337  * described Section 3.2.2 of RFC 8480. We discard such a 6P
338  * Response silently without taking any action.
339  */
340  return;
341  }
342  }
343 
344  /* state transition */
345  assert(trans != NULL);
346  switch(pkt.type) {
348  ret = sixp_trans_transit_state(trans,
349  SIXP_TRANS_STATE_REQUEST_RECEIVED);
350  break;
352  ret = sixp_trans_transit_state(trans,
353  SIXP_TRANS_STATE_RESPONSE_RECEIVED);
354  break;
356  ret = sixp_trans_transit_state(trans,
357  SIXP_TRANS_STATE_CONFIRMATION_RECEIVED);
358  break;
359  default:
360  LOG_ERR("6P: sixp_input() fails because of unsupported type [type:%u]\n",
361  pkt.type);
362  return;
363  }
364  if(ret < 0) {
365  LOG_ERR("6P: sixp_input() fails because of state transition failure\n");
366  LOG_ERR("6P: maybe a duplicate packet to trans:%p\n", trans);
367  } else if(sf->input != NULL) {
368  sf->input(pkt.type, pkt.code, pkt.body, pkt.body_len, src_addr);
369  } else {
370  }
371 
372  return;
373 }
374 /*---------------------------------------------------------------------------*/
375 int
376 sixp_output(sixp_pkt_type_t type, sixp_pkt_code_t code, uint8_t sfid,
377  const uint8_t *body, uint16_t body_len,
378  const linkaddr_t *dest_addr,
379  sixp_sent_callback_t func, void *arg, uint16_t arg_len)
380 {
381  sixp_trans_t *trans;
382  sixp_nbr_t *nbr;
383  int16_t seqno;
384  sixp_pkt_t pkt;
385 
386  assert(dest_addr != NULL);
387 
388  /* validate the state of a transaction with a specified peer */
389  trans = sixp_trans_find(dest_addr);
390  if(type == SIXP_PKT_TYPE_REQUEST) {
391  if(trans != NULL) {
392  LOG_ERR("6P: sixp_output() fails because another trans for [peer_addr:");
393  LOG_ERR_LLADDR((const linkaddr_t *)dest_addr);
394  LOG_ERR_("] is in process\n");
395  return -1;
396  } else {
397  /* ready to send a request */
398  /* we're going to allocate a new transaction later */
399  }
400  } else if(type == SIXP_PKT_TYPE_RESPONSE) {
401  if(trans == NULL) {
402  LOG_ERR("6P: sixp_output() fails because of no transaction [peer_addr:");
403  LOG_ERR_LLADDR((const linkaddr_t *)dest_addr);
404  LOG_ERR_("]\n");
405  return -1;
406  } else if(sixp_trans_get_state(trans) !=
407  SIXP_TRANS_STATE_REQUEST_RECEIVED) {
408  LOG_ERR("6P: sixp_output() fails because of invalid transaction state\n");
409  return -1;
410  } else {
411  /* ready to send a response */
412  }
413  } else if(type == SIXP_PKT_TYPE_CONFIRMATION) {
414  if(trans == NULL) {
415  LOG_ERR("6P: sixp_output() fails because of no transaction [peer_addr:");
416  LOG_ERR_LLADDR((const linkaddr_t *)dest_addr);
417  LOG_ERR_("]\n");
418  return -1;
419  } else if(sixp_trans_get_state(trans) !=
420  SIXP_TRANS_STATE_RESPONSE_RECEIVED) {
421  LOG_ERR("6P: sixp_output() fails because of invalid transaction state\n");
422  return -1;
423  } else {
424  /* ready to send a confirmation */
425  }
426  } else {
427  LOG_ERR("6P: sixp_output() fails because of unsupported type [type:%u]\n",
428  type);
429  return -1;
430  }
431 
432  nbr = sixp_nbr_find(dest_addr);
433 
434  /*
435  * Make sure we have a nbr for the peer if the packet is a response
436  * with success so that we can manage the schedule generation unless
437  * the request is CLEAR or in an unsupported format, in such a case
438  * we're going to return RC_ERR_VERSION or RC_ERR_SFID.
439  */
440  if(nbr == NULL &&
441  type == SIXP_PKT_TYPE_RESPONSE &&
443  code.value != SIXP_PKT_RC_ERR_VERSION &&
444  code.value != SIXP_PKT_RC_ERR_SFID &&
445  (nbr = sixp_nbr_alloc(dest_addr)) == NULL) {
446  LOG_ERR("6P: sixp_output() fails because of no memory for another nbr\n");
447  return -1;
448  }
449 
450  /* set SeqNum */
451  if(type == SIXP_PKT_TYPE_REQUEST) {
452  if(nbr == NULL &&
453  (nbr = sixp_nbr_alloc(dest_addr)) == NULL) {
454  LOG_ERR("6P: sixp_output() fails because it fails to allocate a nbr\n");
455  return -1;
456  }
457  if((seqno = sixp_nbr_get_next_seqno(nbr)) < 0){
458  LOG_ERR("6P: sixp_output() fails to get the next sequence number\n");
459  return -1;
460  }
461  } else {
462  assert(trans != NULL);
463  if((seqno = sixp_trans_get_seqno(trans)) < 0) {
464  LOG_ERR("6P: sixp_output() fails because it fails to get seqno\n");
465  return -1;
466  }
467  }
468 
469  /* create a 6P packet within packetbuf */
470  if(sixp_pkt_create(type, code, sfid,
471  (uint8_t)seqno,
472  body, body_len,
473  type == SIXP_PKT_TYPE_REQUEST ? &pkt : NULL) < 0) {
474  LOG_ERR("6P: sixp_output() fails to create a 6P packet\n");
475  return -1;
476  }
477 
478  /* allocate a transaction for a sending request */
479  if(type == SIXP_PKT_TYPE_REQUEST) {
480  assert(trans == NULL);
481  if((trans = sixp_trans_alloc(&pkt, dest_addr)) == NULL) {
482  LOG_ERR("6P: sixp_output() is aborted because of no memory\n");
483  return -1;
484  } else {
485  /* ready for proceed */
486  LOG_DBG("6P: sixp_output() allocates trans:%p\n", trans);
487  }
488  }
489 
490  assert(trans != NULL);
491  sixp_trans_set_callback(trans, func, arg, arg_len);
492  if(sixtop_output(dest_addr, mac_callback, trans) == 0) {
493  /* sixtop_output() call ends without an error */
495  if(state == SIXP_TRANS_STATE_INIT) {
496  /*
497  * increment/update next_seqno immediately to prevent the next
498  * request from having the same seqno, although RFC8480
499  * describes a different way to manage seqno. If the next
500  * request has the same seqno as the previous request, a delayed
501  * response, which is for the previous transaction, may be
502  * handled mistakenly for the next request when the previous
503  * transaction is expired.
504  */
505  if(code.cmd == SIXP_PKT_CMD_CLEAR) {
506  LOG_INFO("6P: sixp_output() reset nbr's next_seqno by CLEAR Request\n");
508  } else {
510  }
511  sixp_trans_transit_state(trans, SIXP_TRANS_STATE_REQUEST_SENDING);
512  } else if(state == SIXP_TRANS_STATE_REQUEST_RECEIVED) {
513  sixp_trans_transit_state(trans, SIXP_TRANS_STATE_RESPONSE_SENDING);
514  } else if(state == SIXP_TRANS_STATE_RESPONSE_RECEIVED) {
515  sixp_trans_transit_state(trans, SIXP_TRANS_STATE_CONFIRMATION_SENDING);
516  } else {
517  /* shouldn't come here */
518  LOG_ERR("6P: sixp_output() is called trans:%p whose state is %u\n",
519  trans, state);
520  }
521  } else {
522  if(type == SIXP_PKT_TYPE_REQUEST) {
523  /* abort the transaction now */
524  sixp_trans_abort(trans);
525  }
526  }
527 
528  return 0;
529 }
530 /*---------------------------------------------------------------------------*/
531 void
533 {
534  sixp_nbr_init();
535  sixp_trans_init();
536 }
537 /*---------------------------------------------------------------------------*/
538 /** @} */
Transaction Management APIs for 6top Protocol (6P)
sixp_pkt_cmd_t
6P Command Identifiers
Definition: sixp-pkt.h:72
sixp_pkt_type_t
6P Message Types
Definition: sixp-pkt.h:62
struct sixp_nbr sixp_nbr_t
6P Neighbor Data Structure (for internal use)
int sixp_trans_init(void)
Initialize Memory and List for 6P transactions This function removes and frees existing transactions...
Definition: sixp-trans.c:489
/brief Scheduling Function Driver
Definition: sixtop.h:104
sixp_pkt_code_t code
Code.
Definition: sixp-pkt.h:124
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
Definition: uip-nd6.c:106
CMD_CLEAR.
Definition: sixp-pkt.h:79
sixp_pkt_rc_t
6P Return Codes
Definition: sixp-pkt.h:86
int sixp_nbr_reset_next_seqno(sixp_nbr_t *nbr)
Reset the next sequence number of a neighbor to zero.
Definition: sixp-nbr.c:144
RC_ERR_SFID.
Definition: sixp-pkt.h:92
void sixp_trans_set_callback(sixp_trans_t *trans, sixp_sent_callback_t func, void *arg, uint16_t arg_len)
Set an output callback to a specified transaction.
Definition: sixp-trans.c:375
void sixp_trans_abort(sixp_trans_t *trans)
Helper function to abort a transaction immediately.
Definition: sixp-trans.c:469
uint16_t body_len
The length of Other Fields.
Definition: sixp-pkt.h:128
uint8_t seqno
SeqNum.
Definition: sixp-pkt.h:126
const sixtop_sf_t * sixtop_find_sf(uint8_t sfid)
Find a SF which has been added by SFID.
Definition: sixtop.c:110
Neighbor Management APIs for 6top Protocol (6P)
void sixp_trans_invoke_callback(sixp_trans_t *trans, sixp_output_status_t status)
Invoke the output callback of a specified transaction.
Definition: sixp-trans.c:363
struct sixp_trans sixp_trans_t
6P Transaction Data Structure (for internal use)
int sixp_nbr_increment_next_seqno(sixp_nbr_t *nbr)
Increment the next sequence number of a neighbor.
Definition: sixp-nbr.c:156
uint8_t value
8-bit unsigned integer value
Definition: sixp-pkt.h:106
sixp_pkt_cmd_t sixp_trans_get_cmd(sixp_trans_t *trans)
Return the command associated with a specified transaction.
Definition: sixp-trans.c:310
6P Request
Definition: sixp-pkt.h:63
RC_ERR_BUSY.
Definition: sixp-pkt.h:95
uint8_t sfid
SFID.
Definition: sixp-pkt.h:125
sixtop_sf_input input
Input Handler.
Definition: sixtop.h:108
6P Codes integrating Command IDs and Return Codes
Definition: sixp-pkt.h:103
6P Response
Definition: sixp-pkt.h:64
sixp_trans_t * sixp_trans_find(const linkaddr_t *peer_addr)
Find a transaction.
Definition: sixp-trans.c:431
The MAC layer transmission was OK.
Definition: mac.h:87
void(* sixp_sent_callback_t)(void *arg, uint16_t arg_len, const linkaddr_t *dest_addr, sixp_output_status_t status)
6P Packet Sent Handler
Definition: sixp.h:74
const uint8_t * body
Other Fields...
Definition: sixp-pkt.h:127
sixp_trans_state_t sixp_trans_get_state(sixp_trans_t *trans)
Return the state of a specified transaction.
Definition: sixp-trans.c:320
sixp_pkt_type_t type
Type.
Definition: sixp-pkt.h:123
RC_ERR_VERSION.
Definition: sixp-pkt.h:91
sixtop_sf_error error
Internal Error Handler.
Definition: sixtop.h:110
sixp_nbr_t * sixp_nbr_alloc(const linkaddr_t *addr)
Allocate a neighbor.
Definition: sixp-nbr.c:80
6TiSCH Operation Sublayer (6top) APIs
int sixp_output(sixp_pkt_type_t type, sixp_pkt_code_t code, uint8_t sfid, const uint8_t *body, uint16_t body_len, const linkaddr_t *dest_addr, sixp_sent_callback_t func, void *arg, uint16_t arg_len)
Output a 6P packet.
Definition: sixp.c:376
6P Confirmation
Definition: sixp-pkt.h:65
void sixp_init(void)
Initialize 6P Module It invokes sixp_nbr_init() and sixp_trans_init().
Definition: sixp.c:532
const sixtop_sf_t * sixp_trans_get_sf(sixp_trans_t *trans)
Return the scheduling function associated with a specified transaction.
Definition: sixp-trans.c:299
const linkaddr_t * sixp_trans_get_peer_addr(sixp_trans_t *trans)
Return the peer addr of a specified transaction.
Definition: sixp-trans.c:352
6top IE Structure
Definition: sixp-pkt.h:121
6top Protocol (6P) Packet Manipulation APIs
int sixp_nbr_init(void)
Initialize 6p Neighbor Table.
Definition: sixp-nbr.c:175
int sixp_pkt_parse(const uint8_t *buf, uint16_t len, sixp_pkt_t *pkt)
Parse a 6P packet.
Definition: sixp-pkt.c:947
sixp_trans_state_t
6P Transaction States (for internal use)
Definition: sixp-trans.h:47
sixp_pkt_cmd_t cmd
6P Command Identifier
Definition: sixp-pkt.h:104
int16_t sixp_trans_get_seqno(sixp_trans_t *trans)
Return the sequence number associated with a specified transaction.
Definition: sixp-trans.c:330
void sixp_trans_free(sixp_trans_t *trans)
Free a transaction.
Definition: sixp-trans.c:166
int sixp_nbr_get_next_seqno(sixp_nbr_t *nbr)
Get the next sequence number of a neighbor.
Definition: sixp-nbr.c:121
sixp_nbr_t * sixp_nbr_find(const linkaddr_t *addr)
Find a neighbor.
Definition: sixp-nbr.c:70
int sixp_pkt_create(sixp_pkt_type_t type, sixp_pkt_code_t code, uint8_t sfid, uint8_t seqno, const uint8_t *body, uint16_t body_len, sixp_pkt_t *pkt)
Create a 6P packet.
Definition: sixp-pkt.c:1086
sixp_trans_t * sixp_trans_alloc(const sixp_pkt_t *pkt, const linkaddr_t *peer_addr)
Allocate a transaction.
Definition: sixp-trans.c:388
void sixp_input(const uint8_t *buf, uint16_t len, const linkaddr_t *src_addr)
Input a 6P packet.
Definition: sixp.c:205
int sixp_trans_transit_state(sixp_trans_t *trans, sixp_trans_state_t new_state)
Change the state of a specified transaction.
Definition: sixp-trans.c:224
RC_ERR_SEQNUM.
Definition: sixp-pkt.h:93
Header file for the logging system
sixp_pkt_version_t version
Version.
Definition: sixp-pkt.h:122
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