Contiki-NG
sixp-trans.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  * Transaction Management for 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 "sixtop-conf.h"
46 #include "sixp-nbr.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 /**
55  * \brief 6P Transaction Data Structure (for internal use)
56  */
57 typedef struct sixp_trans {
58  struct sixp_trans *next;
59  const sixtop_sf_t *sf;
60  linkaddr_t peer_addr;
61  uint8_t seqno;
62  sixp_pkt_cmd_t cmd;
63  sixp_trans_state_t state;
64  sixp_trans_mode_t mode;
65  struct {
67  void *arg;
68  uint16_t arg_len;
69  } callback;
70  struct ctimer timer;
71 } sixp_trans_t;
72 
73 static void handle_trans_timeout(void *ptr);
74 static void process_trans(void *ptr);
75 static void schedule_trans_process(sixp_trans_t *trans);
76 static sixp_trans_mode_t determine_trans_mode(const sixp_pkt_t *req);
77 
79 LIST(trans_list);
80 
81 /*---------------------------------------------------------------------------*/
82 static void
83 handle_trans_timeout(void *ptr)
84 {
85  sixp_trans_t *trans = (sixp_trans_t *)ptr;
86 
87  assert(trans != NULL);
88  if(trans == NULL) {
89  return;
90  }
91 
92  if(trans->sf->timeout != NULL) {
93  trans->sf->timeout(trans->cmd,
94  (const linkaddr_t *)&trans->peer_addr);
95  }
96 
97  (void)sixp_trans_transit_state(trans, SIXP_TRANS_STATE_TERMINATING);
98 }
99 /*---------------------------------------------------------------------------*/
100 static void
101 start_trans_timer(sixp_trans_t *trans)
102 {
103  ctimer_set(&trans->timer, trans->sf->timeout_interval,
104  handle_trans_timeout, trans);
105 }
106 /*---------------------------------------------------------------------------*/
107 static void
108 process_trans(void *ptr)
109 {
110  sixp_trans_t *trans = (sixp_trans_t *)ptr;
111 
112  assert(trans != NULL);
113  if(trans == NULL) {
114  return;
115  }
116 
117  /* make sure that the timer is stopped */
118  ctimer_stop(&trans->timer);
119 
120  /* state-specific operation */
121  if(trans->state == SIXP_TRANS_STATE_TERMINATING) {
122  /* handle the terminating state first */
123  LOG_INFO("6P-trans: trans [peer_addr:");
124  LOG_INFO_LLADDR((const linkaddr_t *)&trans->peer_addr);
125  LOG_INFO_(", seqno:%u] is going to be freed\n", trans->seqno);
126  sixp_trans_free(trans);
127  return;
128  }
129 
130  switch(trans->state) {
131  /* do for others */
132  case SIXP_TRANS_STATE_RESPONSE_SENT:
133  case SIXP_TRANS_STATE_RESPONSE_RECEIVED:
134  if(trans->mode == SIXP_TRANS_MODE_2_STEP) {
135  (void)sixp_trans_transit_state(trans, SIXP_TRANS_STATE_TERMINATING);
136  }
137  break;
138  case SIXP_TRANS_STATE_CONFIRMATION_SENT:
139  case SIXP_TRANS_STATE_CONFIRMATION_RECEIVED:
140  (void)sixp_trans_transit_state(trans, SIXP_TRANS_STATE_TERMINATING);
141  break;
142  case SIXP_TRANS_STATE_TERMINATING:
143  default:
144  break;
145  }
146 
147  if(trans->state != SIXP_TRANS_STATE_TERMINATING) {
148  /* set the timer with a timeout values defined by the SF */
149  start_trans_timer(trans);
150  }
151 }
152 /*---------------------------------------------------------------------------*/
153 static void
154 schedule_trans_process(sixp_trans_t *trans)
155 {
156  assert(trans != NULL);
157  if(trans == NULL) {
158  return;
159  }
160 
161  ctimer_stop(&trans->timer);
162  ctimer_set(&trans->timer, 0, process_trans, trans); /* expires immediately */
163 }
164 /*---------------------------------------------------------------------------*/
165 void
167 {
168  assert(trans != NULL);
169  if(trans == NULL) {
170  return;
171  }
172 
173  if (trans->state == SIXP_TRANS_STATE_WAIT_FREE) {
174  trans->state = SIXP_TRANS_STATE_UNAVAILABLE;
175  } else {
176  /* stop the timer that may still be running */
177  ctimer_stop(&trans->timer);
178  /*
179  * remove this trans from the list so that a new trans can be
180  * started with the same peer
181  */
182  list_remove(trans_list, trans);
183  }
184 
185  if(trans->state == SIXP_TRANS_STATE_REQUEST_SENDING ||
186  trans->state == SIXP_TRANS_STATE_RESPONSE_SENDING ||
187  trans->state == SIXP_TRANS_STATE_CONFIRMATION_SENDING) {
188  /* memory is freed later, when mac_callback in sixp.c is called */
189  trans->state = SIXP_TRANS_STATE_WAIT_FREE;
190  } else {
191  memset(trans, 0, sizeof(sixp_trans_t));
192  memb_free(&trans_memb, trans);
193  }
194 }
195 /*---------------------------------------------------------------------------*/
196 static sixp_trans_mode_t
197 determine_trans_mode(const sixp_pkt_t *req)
198 {
199  uint16_t cell_list_len;
200 
201  assert(req != NULL);
202  if(req == NULL) {
203  return SIXP_TRANS_MODE_UNAVAILABLE;
204  }
205 
206  /*
207  * We consider a transaction as 3-step if and only if its request command is
208  * either Add or Delete AND its cell_list is empty. Otherwise, 2-step.
209  */
210  if(req->type == SIXP_PKT_TYPE_REQUEST &&
211  (req->code.cmd == SIXP_PKT_CMD_ADD ||
212  req->code.cmd == SIXP_PKT_CMD_DELETE) &&
214  NULL, &cell_list_len,
215  req->body, req->body_len) == 0 &&
216  cell_list_len == 0) {
217  return SIXP_TRANS_MODE_3_STEP;
218  }
219 
220  return SIXP_TRANS_MODE_2_STEP;
221 }
222 /*---------------------------------------------------------------------------*/
223 int
225 {
226  sixp_nbr_t *nbr;
227  int ret_val;
228 
229  assert(trans != NULL);
230  assert(new_state != SIXP_TRANS_STATE_UNAVAILABLE);
231  /* enforce state transition rules */
232  if(trans != NULL &&
233  (new_state == SIXP_TRANS_STATE_TERMINATING ||
234  (new_state == SIXP_TRANS_STATE_REQUEST_SENDING &&
235  trans->state == SIXP_TRANS_STATE_INIT) ||
236  (new_state == SIXP_TRANS_STATE_REQUEST_SENT &&
237  trans->state == SIXP_TRANS_STATE_REQUEST_SENDING) ||
238  (new_state == SIXP_TRANS_STATE_REQUEST_RECEIVED &&
239  trans->state == SIXP_TRANS_STATE_INIT) ||
240  (new_state == SIXP_TRANS_STATE_RESPONSE_SENDING &&
241  trans->state == SIXP_TRANS_STATE_REQUEST_RECEIVED) ||
242  (new_state == SIXP_TRANS_STATE_RESPONSE_SENT &&
243  trans->state == SIXP_TRANS_STATE_RESPONSE_SENDING) ||
244  (new_state == SIXP_TRANS_STATE_RESPONSE_RECEIVED &&
245  (trans->state == SIXP_TRANS_STATE_REQUEST_SENDING ||
246  trans->state == SIXP_TRANS_STATE_REQUEST_SENT)) ||
247  (new_state == SIXP_TRANS_STATE_CONFIRMATION_RECEIVED &&
248  (trans->state == SIXP_TRANS_STATE_RESPONSE_SENT ||
249  trans->state == SIXP_TRANS_STATE_RESPONSE_SENDING) &&
250  trans->mode == SIXP_TRANS_MODE_3_STEP) ||
251  (new_state == SIXP_TRANS_STATE_CONFIRMATION_SENDING &&
252  trans->state == SIXP_TRANS_STATE_RESPONSE_RECEIVED &&
253  trans->mode == SIXP_TRANS_MODE_3_STEP) ||
254  (new_state == SIXP_TRANS_STATE_CONFIRMATION_SENT &&
255  trans->state == SIXP_TRANS_STATE_CONFIRMATION_SENDING &&
256  trans->mode == SIXP_TRANS_MODE_3_STEP))) {
257  LOG_INFO("6P-trans: trans %p state changes from %u to %u\n",
258  trans, trans->state, new_state);
259 
260  if(new_state == SIXP_TRANS_STATE_REQUEST_SENT) {
261  /* next_seqno should have been updated in sixp_output() */
262  } else if(new_state == SIXP_TRANS_STATE_RESPONSE_SENT) {
263  if((nbr = sixp_nbr_find(&trans->peer_addr)) == NULL) {
264  LOG_ERR("6top: cannot update next_seqno\n");
265  } else if(trans->cmd == SIXP_PKT_CMD_CLEAR) {
266  /* next_seqno must have been reset to 0 already; keep it */
267  assert(sixp_nbr_get_next_seqno(nbr) == 0);
268  } else {
269  /* override next_seqno with the one in the request */
270  sixp_nbr_set_next_seqno(nbr, trans->seqno);
272  }
273  }
274  trans->state = new_state;
275  schedule_trans_process(trans);
276  ret_val = 0;
277  } else if (trans != NULL){
278  /* invalid transition */
279  LOG_ERR("6P-trans: invalid transition, from %u to %u, on trans %p\n",
280  trans->state, new_state, trans);
281  /* inform the corresponding SF */
282  assert(trans->sf != NULL);
283  if(trans->sf->error != NULL) {
284  trans->sf->error(SIXP_ERROR_INVALID_TRANS_STATE_TRANSITION,
285  sixp_trans_get_cmd(trans),
286  sixp_trans_get_seqno(trans),
287  sixp_trans_get_peer_addr(trans));
288  }
289  ret_val = -1;
290  } else {
291  /* trans == NULL */
292  LOG_ERR("6top: invalid argument, trans is NULL\n");
293  ret_val = -1;
294  }
295  return ret_val;
296 }
297 /*---------------------------------------------------------------------------*/
298 const sixtop_sf_t *
300 {
301  assert(trans != NULL);
302  if(trans == NULL) {
303  return NULL;
304  } else {
305  return trans->sf;
306  }
307 }
308 /*---------------------------------------------------------------------------*/
311 {
312  assert(trans != NULL);
313  if(trans == NULL) {
315  }
316  return trans->cmd;
317 }
318 /*---------------------------------------------------------------------------*/
321 {
322  assert(trans != NULL);
323  if(trans == NULL) {
324  return SIXP_TRANS_STATE_UNAVAILABLE;
325  }
326  return trans->state;
327 }
328 /*---------------------------------------------------------------------------*/
329 int16_t
331 {
332  assert(trans != NULL);
333  if(trans == NULL) {
334  LOG_ERR("6P-trans: sixp_trans_get_seqno() fails because trans is NULL\n");
335  return -1;
336  }
337  return trans->seqno;
338 }
339 /*---------------------------------------------------------------------------*/
342 {
343  assert(trans != NULL);
344  if(trans == NULL) {
345  LOG_ERR("6P-trans: sixp_trans_get_mode() fails because trans is NULL\n");
346  return SIXP_TRANS_STATE_UNAVAILABLE;
347  }
348  return trans->mode;
349 }
350 /*---------------------------------------------------------------------------*/
351 const linkaddr_t *
353 {
354  assert(trans != NULL);
355  if(trans == NULL) {
356  return NULL;
357  } else {
358  return (const linkaddr_t *)&trans->peer_addr;
359  }
360 }
361 /*---------------------------------------------------------------------------*/
362 void
364 {
365  assert(trans != NULL);
366 
367  if(trans == NULL || trans->callback.func == NULL) {
368  return;
369  }
370  trans->callback.func(trans->callback.arg, trans->callback.arg_len,
371  &trans->peer_addr, status);
372 }
373 /*---------------------------------------------------------------------------*/
374 void
376  sixp_sent_callback_t func, void *arg, uint16_t arg_len)
377 {
378  assert(trans != NULL);
379  if(trans == NULL) {
380  return;
381  }
382  trans->callback.func = func;
383  trans->callback.arg = arg;
384  trans->callback.arg_len = arg_len;
385 }
386 /*---------------------------------------------------------------------------*/
387 sixp_trans_t *
388 sixp_trans_alloc(const sixp_pkt_t *pkt, const linkaddr_t *peer_addr)
389 {
390  const sixtop_sf_t *sf;
391  sixp_trans_t *trans;
392 
393  assert(pkt != NULL && peer_addr != NULL);
394  if(pkt == NULL || peer_addr == NULL) {
395  LOG_ERR("6P-trans: sixp_trans_alloc() fails because of invalid argument\n");
396  return NULL;
397  }
398 
399  if((sf = sixtop_find_sf(pkt->sfid)) == NULL) {
400  LOG_ERR("6P-trans: sixp_trans_alloc() fails; no suitable SF [sfid:%u]\n",
401  pkt->sfid);
402  return NULL;
403  }
404 
405  if(sixp_trans_find(peer_addr) != NULL) {
406  LOG_ERR("6P-trans: sixp_trans_alloc() fails because another trans with ");
407  LOG_ERR_LLADDR((const linkaddr_t *)peer_addr);
408  LOG_ERR_("is in process\n");
409  return NULL;
410  }
411 
412  if((trans = memb_alloc(&trans_memb)) == NULL) {
413  LOG_ERR("6P-trans: sixp_trans_alloc() fails because of lack of memory\n");
414  return NULL;
415  }
416 
417  memset(trans, 0, sizeof(sixp_trans_t));
418  trans->sf = sf;
419  trans->peer_addr = *peer_addr;
420  trans->seqno = pkt->seqno;
421  trans->cmd = pkt->code.value;
422  trans->state = SIXP_TRANS_STATE_INIT;
423  trans->mode = determine_trans_mode(pkt);
424  list_add(trans_list, trans);
425  start_trans_timer(trans);
426 
427  return trans;
428 }
429 /*---------------------------------------------------------------------------*/
430 sixp_trans_t *
431 sixp_trans_find(const linkaddr_t *peer_addr)
432 {
433  sixp_trans_t *trans;
434 
435  assert(peer_addr != NULL);
436  if(peer_addr == NULL) {
437  return NULL;
438  }
439 
440  /*
441  * XXX: we don't support concurrent 6P transactions which is mentioned in
442  * Section 4.3.3, draft-ietf-6tisch-6top-protocol-03.
443  *
444  * The assumption here is that there is one transactions for a single peer at
445  * most.
446  */
447  for(trans = list_head(trans_list);
448  trans != NULL; trans = trans->next) {
449  if(memcmp(peer_addr, &trans->peer_addr, sizeof(linkaddr_t)) == 0) {
450  return trans;
451  }
452  }
453 
454  return NULL;
455 }
456 /*---------------------------------------------------------------------------*/
457 void
459 {
460  assert(trans != NULL);
461  if(trans == NULL) {
462  return;
463  } else {
464  sixp_trans_transit_state(trans, SIXP_TRANS_STATE_TERMINATING);
465  }
466 }
467 /*---------------------------------------------------------------------------*/
468 void
470 {
471  assert(trans != NULL);
472  if(trans == NULL) {
473  return;
474  } else {
475  LOG_INFO("6P-trans: trans [peer_addr:");
476  LOG_INFO_LLADDR((const linkaddr_t *)&trans->peer_addr);
477  LOG_INFO_(", seqno:%u] is going to be aborted\n", trans->seqno);
478  sixp_trans_terminate(trans);
480  /* process_trans() should be scheduled, which we will be stop */
481  assert(ctimer_expired(&trans->timer) == 0);
482  ctimer_stop(&trans->timer);
483  /* call process_trans() directly*/
484  process_trans((void *)trans);
485  }
486 }
487 /*---------------------------------------------------------------------------*/
488 int
490 {
491  sixp_trans_t *trans, *next_trans;
492 
493  /* make sure there's no timer task left before the initialization */
494  for(trans = list_head(trans_list);
495  trans != NULL; trans = next_trans) {
496  next_trans = trans->next;
497  ctimer_stop(&trans->timer);
498  sixp_trans_free(trans);
499  }
500 
501  list_init(trans_list);
502  memb_init(&trans_memb);
503  return 0;
504 }
505 /*---------------------------------------------------------------------------*/
506 /** @} */
int ctimer_expired(struct ctimer *c)
Check if a callback timer has expired.
Definition: ctimer.c:161
Transaction Management APIs for 6top Protocol (6P)
sixp_pkt_cmd_t
6P Command Identifiers
Definition: sixp-pkt.h:72
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149
sixp_trans_mode_t
6P Transaction Modes (for internal use)
Definition: sixp-trans.h:66
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
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
Definition: memb.c:78
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)
A timer.
Definition: timer.h:82
int sixp_pkt_get_cell_list(sixp_pkt_type_t type, sixp_pkt_code_t code, const uint8_t **cell_list, sixp_pkt_offset_t *cell_list_len, const uint8_t *body, uint16_t body_len)
Read CellList in "Other Fields" of 6P packet.
Definition: sixp-pkt.c:608
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
uint8_t sfid
SFID.
Definition: sixp-pkt.h:125
#define SIXTOP_MAX_TRANSACTIONS
The maximum number of transactions which the sixtop module can handle at the same time...
Definition: sixtop-conf.h:61
for internal use
Definition: sixp-pkt.h:80
6P Codes integrating Command IDs and Return Codes
Definition: sixp-pkt.h:103
sixp_trans_t * sixp_trans_find(const linkaddr_t *peer_addr)
Find a transaction.
Definition: sixp-trans.c:431
void * list_head(list_t list)
Get a pointer to the first element of a list.
Definition: list.c:82
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
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
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
CMD_DELETE.
Definition: sixp-pkt.h:74
6TiSCH Operation Sublayer (6top) APIs
void list_add(list_t list, void *item)
Add an item at the end of a list.
Definition: list.c:142
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
void list_init(list_t list)
Initialize a list.
Definition: list.c:65
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
#define LIST(name)
Declare a linked list.
Definition: list.h:89
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
Definition: memb.c:59
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_terminate(sixp_trans_t *trans)
Helper function to terminate a transaction.
Definition: sixp-trans.c:458
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
sixp_output_status_t
6P Send Status, which represents sixp_output() result.
Definition: sixp.h:65
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 memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
Definition: memb.c:52
int sixp_nbr_set_next_seqno(sixp_nbr_t *nbr, uint16_t seqno)
Set the specified value to the next sequence number of a neighbor.
Definition: sixp-nbr.c:132
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
Header file for the logging system
CMD_ADD.
Definition: sixp-pkt.h:73
sixp_trans_mode_t sixp_trans_get_mode(sixp_trans_t *trans)
Return the mode, 2-step or 3-step, of a specified transaction.
Definition: sixp-trans.c:341
6top Configuration
void list_remove(list_t list, void *item)
Remove a specific element from a list.
Definition: list.c:237
#define MEMB(name, structure, num)
Declare a memory block.
Definition: memb.h:90