41 #include "contiki-lib.h" 42 #include "lib/assert.h" 51 #define LOG_MODULE "6top" 52 #define LOG_LEVEL LOG_LEVEL_6TOP 57 typedef struct sixp_trans {
58 struct sixp_trans *next;
73 static void handle_trans_timeout(
void *ptr);
74 static void process_trans(
void *ptr);
83 handle_trans_timeout(
void *ptr)
87 assert(trans != NULL);
92 if(trans->sf->timeout != NULL) {
93 trans->sf->timeout(trans->cmd,
94 (
const linkaddr_t *)&trans->peer_addr);
103 ctimer_set(&trans->timer, trans->sf->timeout_interval,
104 handle_trans_timeout, trans);
108 process_trans(
void *ptr)
112 assert(trans != NULL);
121 if(trans->state == SIXP_TRANS_STATE_TERMINATING) {
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);
130 switch(trans->state) {
132 case SIXP_TRANS_STATE_RESPONSE_SENT:
133 case SIXP_TRANS_STATE_RESPONSE_RECEIVED:
134 if(trans->mode == SIXP_TRANS_MODE_2_STEP) {
138 case SIXP_TRANS_STATE_CONFIRMATION_SENT:
139 case SIXP_TRANS_STATE_CONFIRMATION_RECEIVED:
142 case SIXP_TRANS_STATE_TERMINATING:
147 if(trans->state != SIXP_TRANS_STATE_TERMINATING) {
149 start_trans_timer(trans);
156 assert(trans != NULL);
162 ctimer_set(&trans->timer, 0, process_trans, trans);
168 assert(trans != NULL);
173 if (trans->state == SIXP_TRANS_STATE_WAIT_FREE) {
174 trans->state = SIXP_TRANS_STATE_UNAVAILABLE;
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) {
189 trans->state = SIXP_TRANS_STATE_WAIT_FREE;
199 uint16_t cell_list_len;
203 return SIXP_TRANS_MODE_UNAVAILABLE;
214 NULL, &cell_list_len,
216 cell_list_len == 0) {
217 return SIXP_TRANS_MODE_3_STEP;
220 return SIXP_TRANS_MODE_2_STEP;
229 assert(trans != NULL);
230 assert(new_state != SIXP_TRANS_STATE_UNAVAILABLE);
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);
260 if(new_state == SIXP_TRANS_STATE_REQUEST_SENT) {
262 }
else if(new_state == SIXP_TRANS_STATE_RESPONSE_SENT) {
264 LOG_ERR(
"6top: cannot update next_seqno\n");
274 trans->state = new_state;
275 schedule_trans_process(trans);
277 }
else if (trans != NULL){
279 LOG_ERR(
"6P-trans: invalid transition, from %u to %u, on trans %p\n",
280 trans->state, new_state, trans);
282 assert(trans->sf != NULL);
283 if(trans->sf->error != NULL) {
284 trans->sf->error(SIXP_ERROR_INVALID_TRANS_STATE_TRANSITION,
292 LOG_ERR(
"6top: invalid argument, trans is NULL\n");
301 assert(trans != NULL);
312 assert(trans != NULL);
322 assert(trans != NULL);
324 return SIXP_TRANS_STATE_UNAVAILABLE;
332 assert(trans != NULL);
334 LOG_ERR(
"6P-trans: sixp_trans_get_seqno() fails because trans is NULL\n");
343 assert(trans != NULL);
345 LOG_ERR(
"6P-trans: sixp_trans_get_mode() fails because trans is NULL\n");
346 return SIXP_TRANS_STATE_UNAVAILABLE;
354 assert(trans != NULL);
358 return (
const linkaddr_t *)&trans->peer_addr;
365 assert(trans != NULL);
367 if(trans == NULL || trans->callback.func == NULL) {
370 trans->callback.func(trans->callback.arg, trans->callback.arg_len,
371 &trans->peer_addr, status);
378 assert(trans != NULL);
382 trans->callback.func = func;
383 trans->callback.arg = arg;
384 trans->callback.arg_len = arg_len;
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");
400 LOG_ERR(
"6P-trans: sixp_trans_alloc() fails; no suitable SF [sfid:%u]\n",
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");
412 if((trans =
memb_alloc(&trans_memb)) == NULL) {
413 LOG_ERR(
"6P-trans: sixp_trans_alloc() fails because of lack of memory\n");
419 trans->peer_addr = *peer_addr;
420 trans->seqno = pkt->
seqno;
422 trans->state = SIXP_TRANS_STATE_INIT;
423 trans->mode = determine_trans_mode(pkt);
425 start_trans_timer(trans);
435 assert(peer_addr != NULL);
436 if(peer_addr == NULL) {
448 trans != NULL; trans = trans->next) {
449 if(memcmp(peer_addr, &trans->peer_addr,
sizeof(linkaddr_t)) == 0) {
460 assert(trans != NULL);
471 assert(trans != NULL);
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);
484 process_trans((
void *)trans);
495 trans != NULL; trans = next_trans) {
496 next_trans = trans->next;
int ctimer_expired(struct ctimer *c)
Check if a callback timer has expired.
Transaction Management APIs for 6top Protocol (6P)
sixp_pkt_cmd_t
6P Command Identifiers
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
sixp_trans_mode_t
6P Transaction Modes (for internal use)
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...
/brief Scheduling Function Driver
sixp_pkt_code_t code
Code.
static uip_ds6_nbr_t * nbr
Pointer to llao option in uip_buf.
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
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.
void sixp_trans_abort(sixp_trans_t *trans)
Helper function to abort a transaction immediately.
uint16_t body_len
The length of Other Fields.
const sixtop_sf_t * sixtop_find_sf(uint8_t sfid)
Find a SF which has been added by SFID.
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.
struct sixp_trans sixp_trans_t
6P Transaction Data Structure (for internal use)
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.
int sixp_nbr_increment_next_seqno(sixp_nbr_t *nbr)
Increment the next sequence number of a neighbor.
uint8_t value
8-bit unsigned integer value
sixp_pkt_cmd_t sixp_trans_get_cmd(sixp_trans_t *trans)
Return the command associated with a specified transaction.
#define SIXTOP_MAX_TRANSACTIONS
The maximum number of transactions which the sixtop module can handle at the same time...
6P Codes integrating Command IDs and Return Codes
sixp_trans_t * sixp_trans_find(const linkaddr_t *peer_addr)
Find a transaction.
void * list_head(list_t list)
Get a pointer to the first element of a list.
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
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
const uint8_t * body
Other Fields...
sixp_trans_state_t sixp_trans_get_state(sixp_trans_t *trans)
Return the state of a specified transaction.
sixp_pkt_type_t type
Type.
6TiSCH Operation Sublayer (6top) APIs
void list_add(list_t list, void *item)
Add an item at the end of a list.
const sixtop_sf_t * sixp_trans_get_sf(sixp_trans_t *trans)
Return the scheduling function associated with a specified transaction.
void list_init(list_t list)
Initialize a list.
const linkaddr_t * sixp_trans_get_peer_addr(sixp_trans_t *trans)
Return the peer addr of a specified transaction.
#define LIST(name)
Declare a linked list.
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
sixp_trans_state_t
6P Transaction States (for internal use)
sixp_pkt_cmd_t cmd
6P Command Identifier
int16_t sixp_trans_get_seqno(sixp_trans_t *trans)
Return the sequence number associated with a specified transaction.
void sixp_trans_terminate(sixp_trans_t *trans)
Helper function to terminate a transaction.
void sixp_trans_free(sixp_trans_t *trans)
Free a transaction.
int sixp_nbr_get_next_seqno(sixp_nbr_t *nbr)
Get the next sequence number of a neighbor.
sixp_nbr_t * sixp_nbr_find(const linkaddr_t *addr)
Find a neighbor.
sixp_output_status_t
6P Send Status, which represents sixp_output() result.
sixp_trans_t * sixp_trans_alloc(const sixp_pkt_t *pkt, const linkaddr_t *peer_addr)
Allocate a transaction.
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
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.
int sixp_trans_transit_state(sixp_trans_t *trans, sixp_trans_state_t new_state)
Change the state of a specified transaction.
Header file for the logging system
sixp_trans_mode_t sixp_trans_get_mode(sixp_trans_t *trans)
Return the mode, 2-step or 3-step, of a specified transaction.
void list_remove(list_t list, void *item)
Remove a specific element from a list.
#define MEMB(name, structure, num)
Declare a memory block.