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);
84 handle_trans_timeout(
void *ptr)
88 assert(trans != NULL);
93 if(trans->sf->timeout != NULL) {
94 trans->sf->timeout(trans->cmd,
95 (
const linkaddr_t *)&trans->peer_addr);
104 ctimer_set(&trans->timer, trans->sf->timeout_interval,
105 handle_trans_timeout, trans);
109 process_trans(
void *ptr)
113 assert(trans != NULL);
122 if(trans->state == SIXP_TRANS_STATE_TERMINATING) {
124 LOG_INFO(
"6P-trans: trans [peer_addr:");
125 LOG_INFO_LLADDR((
const linkaddr_t *)&trans->peer_addr);
126 LOG_INFO_(
", seqno:%u] is going to be freed\n", trans->seqno);
131 switch(trans->state) {
133 case SIXP_TRANS_STATE_RESPONSE_SENT:
134 case SIXP_TRANS_STATE_RESPONSE_RECEIVED:
135 if(trans->mode == SIXP_TRANS_MODE_2_STEP) {
139 case SIXP_TRANS_STATE_CONFIRMATION_SENT:
140 case SIXP_TRANS_STATE_CONFIRMATION_RECEIVED:
143 case SIXP_TRANS_STATE_TERMINATING:
148 if(trans->state != SIXP_TRANS_STATE_TERMINATING) {
150 start_trans_timer(trans);
157 assert(trans != NULL);
163 ctimer_set(&trans->timer, 0, process_trans, trans);
169 assert(trans != NULL);
181 uint16_t cell_list_len;
185 return SIXP_TRANS_MODE_UNAVAILABLE;
196 NULL, &cell_list_len,
198 cell_list_len == 0) {
199 return SIXP_TRANS_MODE_3_STEP;
202 return SIXP_TRANS_MODE_2_STEP;
210 assert(trans != NULL);
212 LOG_ERR(
"6top: invalid argument, trans is NULL\n");
217 if(new_state == SIXP_TRANS_STATE_TERMINATING ||
218 (new_state == SIXP_TRANS_STATE_REQUEST_SENT &&
219 trans->state == SIXP_TRANS_STATE_INIT) ||
220 (new_state == SIXP_TRANS_STATE_REQUEST_RECEIVED &&
221 trans->state == SIXP_TRANS_STATE_INIT) ||
222 (new_state == SIXP_TRANS_STATE_RESPONSE_SENT &&
223 trans->state == SIXP_TRANS_STATE_REQUEST_RECEIVED) ||
224 (new_state == SIXP_TRANS_STATE_RESPONSE_RECEIVED &&
225 trans->state == SIXP_TRANS_STATE_REQUEST_SENT) ||
226 (new_state == SIXP_TRANS_STATE_CONFIRMATION_RECEIVED &&
227 trans->state == SIXP_TRANS_STATE_RESPONSE_SENT &&
228 trans->mode == SIXP_TRANS_MODE_3_STEP) ||
229 (new_state == SIXP_TRANS_STATE_CONFIRMATION_SENT &&
230 trans->state == SIXP_TRANS_STATE_RESPONSE_RECEIVED &&
231 trans->mode == SIXP_TRANS_MODE_3_STEP)) {
232 LOG_INFO(
"6P-trans: trans %p state changes from %u to %u\n",
233 trans, trans->state, new_state);
235 if(new_state == SIXP_TRANS_STATE_REQUEST_SENT) {
241 LOG_ERR(
"6top: cannot increment next_seqno\n");
250 }
else if(new_state == SIXP_TRANS_STATE_RESPONSE_SENT) {
252 LOG_ERR(
"6top: cannot update next_seqno\n");
255 if(trans->seqno != 0) {
262 trans->state = new_state;
263 schedule_trans_process(trans);
268 LOG_ERR(
"6P-trans: invalid transaction, from %u to %u, detected on trans %p\n",
269 trans->state, new_state, trans);
276 assert(trans != NULL);
286 assert(trans != NULL);
288 return SIXP_TRANS_STATE_UNAVAILABLE;
296 assert(trans != NULL);
298 LOG_ERR(
"6P-trans: sixp_trans_get_seqno() fails because trans is NULL\n");
307 assert(trans != NULL);
309 LOG_ERR(
"6P-trans: sixp_trans_get_mode() fails because trans is NULL\n");
310 return SIXP_TRANS_STATE_UNAVAILABLE;
318 assert(trans != NULL);
320 if(trans == NULL || trans->callback.func == NULL) {
323 trans->callback.func(trans->callback.arg, trans->callback.arg_len,
324 &trans->peer_addr, status);
331 assert(trans != NULL);
335 trans->callback.func = func;
336 trans->callback.arg = arg;
337 trans->callback.arg_len = arg_len;
346 assert(pkt != NULL && peer_addr != NULL);
347 if(pkt == NULL || peer_addr == NULL) {
348 LOG_ERR(
"6P-trans: sixp_trans_alloc() fails because of invalid argument\n");
353 LOG_ERR(
"6P-trans: sixp_trans_alloc() fails; no suitable SF [sfid:%u]\n",
359 LOG_ERR(
"6P-trans: sixp_trans_alloc() fails because another trans with ");
360 LOG_ERR_LLADDR((
const linkaddr_t *)peer_addr);
361 LOG_ERR_(
"is in process\n");
365 if((trans =
memb_alloc(&trans_memb)) == NULL) {
366 LOG_ERR(
"6P-trans: sixp_trans_alloc() fails because of lack of memory\n");
372 trans->peer_addr = *peer_addr;
373 trans->seqno = pkt->
seqno;
375 trans->state = SIXP_TRANS_STATE_INIT;
376 trans->mode = determine_trans_mode(pkt);
378 start_trans_timer(trans);
388 assert(peer_addr != NULL);
389 if(peer_addr == NULL) {
401 trans != NULL; trans = trans->next) {
402 if(memcmp(peer_addr, &trans->peer_addr,
sizeof(linkaddr_t)) == 0) {
417 trans != NULL; trans = next_trans) {
418 next_trans = trans->next;
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.
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.
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.
void list_init(list_t list)
Initialize a list.
#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.
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.
char memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
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.