53 #include "lib/random.h" 60 #define LOG_MODULE "TSCH Queue" 61 #define LOG_LEVEL LOG_LEVEL_MAC 64 #if (TSCH_QUEUE_NUM_PER_NEIGHBOR & (TSCH_QUEUE_NUM_PER_NEIGHBOR - 1)) != 0 65 #error TSCH_QUEUE_NUM_PER_NEIGHBOR must be power of two 128 while(curr_nbr != NULL) {
129 if(curr_nbr->is_time_source) {
143 if(!tsch_is_coordinator) {
147 if(new_addr != NULL) {
150 if(new_time_src == NULL) {
155 if(new_time_src != old_time_src) {
156 LOG_INFO(
"update time source: ");
157 LOG_INFO_LLADDR(old_time_src ? &old_time_src->addr : NULL);
159 LOG_INFO_LLADDR(new_time_src ? &new_time_src->addr : NULL);
163 if(new_time_src != NULL) {
164 new_time_src->is_time_source = 1;
172 if(old_time_src != NULL) {
173 old_time_src->is_time_source = 0;
176 tsch_stats_reset_neighbor_stats();
178 #ifdef TSCH_CALLBACK_NEW_TIME_SOURCE 179 TSCH_CALLBACK_NEW_TIME_SOURCE(old_time_src, new_time_src);
198 LOG_WARN(
"! flushing packet\n");
200 mac_call_sent_callback(p->sent, p->ptr, p->ret, p->transmissions);
220 tsch_queue_flush_nbr_queue(n);
231 mac_callback_t sent,
void *ptr)
234 int16_t put_index = -1;
240 if(put_index != -1) {
244 #ifdef TSCH_CALLBACK_PACKET_READY 245 TSCH_CALLBACK_PACKET_READY();
247 p->qb = queuebuf_new_from_packetbuf();
252 p->transmissions = 0;
253 p->max_transmissions = max_transmissions;
255 n->tx_array[put_index] = p;
257 LOG_DBG(
"packet is added put_index %u, packet %p\n",
267 LOG_ERR(
"! add packet failed: %u %p %d %p %p\n",
tsch_is_locked(), n, put_index, p, p ? p->qb : NULL);
275 return QUEUEBUF_NUM - memb_numfree(&packet_memb);
300 if(get_index != -1) {
301 return n->tx_array[get_index];
315 queuebuf_free(p->qb);
323 struct tsch_link *link, uint8_t mac_tx_status)
326 int is_shared_link = link->link_options & LINK_OPTION_SHARED;
327 int is_unicast = !n->is_broadcast;
344 if(p->transmissions >= p->max_transmissions) {
373 tsch_queue_flush_nbr_queue(n);
392 if(!n->is_broadcast && !n->is_time_source && !n->tx_links_count
394 tsch_queue_remove_nbr(n);
413 int is_shared_link = link != NULL && link->link_options & LINK_OPTION_SHARED;
416 if(get_index != -1 &&
419 #if TSCH_WITH_LINK_SELECTOR 420 int packet_attr_slotframe = queuebuf_attr(n->tx_array[get_index]->qb, PACKETBUF_ATTR_TSCH_SLOTFRAME);
421 int packet_attr_timeslot = queuebuf_attr(n->tx_array[get_index]->qb, PACKETBUF_ATTR_TSCH_TIMESLOT);
422 if(packet_attr_slotframe != 0xffff && packet_attr_slotframe != link->slotframe_handle) {
425 if(packet_attr_timeslot != 0xffff && packet_attr_timeslot != link->timeslot) {
429 return n->tx_array[get_index];
454 while(curr_nbr != NULL) {
455 if(!curr_nbr->is_broadcast && curr_nbr->tx_links_count == 0) {
475 return n->backoff_window == 0;
482 n->backoff_window = 0;
483 n->backoff_exponent = TSCH_MAC_MIN_BE;
491 n->backoff_exponent = MIN(n->backoff_exponent + 1, TSCH_MAC_MAX_BE);
495 n->backoff_window = (
random_rand() >> 6) % (1 << n->backoff_exponent);
506 int is_broadcast =
linkaddr_cmp(dest_addr, &tsch_broadcast_address);
509 if(n->backoff_window != 0
510 && ((n->tx_links_count == 0 && is_broadcast)
511 || (n->tx_links_count > 0 &&
linkaddr_cmp(dest_addr, &n->addr)))) {
int tsch_queue_global_packet_count(void)
Returns the number of packets currently in all TSCH queues.
struct tsch_neighbor * tsch_queue_get_nbr(const linkaddr_t *addr)
Get a TSCH neighbor.
void ringbufindex_init(struct ringbufindex *r, uint8_t size)
Initialize a ring buffer.
The MAC layer transmission could not be performed because of a fatal error.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.
int ringbufindex_peek_get(const struct ringbufindex *r)
Return the index of the first element which will be removed if calling ringbufindex_get.
int tsch_get_lock(void)
Takes the TSCH lock.
void tsch_release_lock(void)
Releases the TSCH lock.
TSCH neighbor information.
void tsch_queue_init(void)
Initialize TSCH queue module.
void tsch_queue_update_all_backoff_windows(const linkaddr_t *dest_addr)
Decrement backoff window for the queue(s) able to Tx to a given address.
struct tsch_neighbor * tsch_queue_get_time_source(void)
Get the TSCH time source (we currently assume there is only one)
void tsch_set_ka_timeout(uint32_t timeout)
Set the desynchronization timeout after which a node sends a unicasst keep-alive (KA) to its time sou...
struct tsch_packet * tsch_queue_get_packet_for_dest_addr(const linkaddr_t *addr, struct tsch_link *link)
Returns the first packet that can be sent to a given address on a given link.
void tsch_queue_free_unused_neighbors(void)
Deallocate all neighbors with empty queue.
int tsch_queue_backoff_expired(const struct tsch_neighbor *n)
Is the neighbor backoff timer expired?
struct tsch_neighbor * tsch_queue_add_nbr(const linkaddr_t *addr)
Add a TSCH neighbor queue.
Header file for the Packet queue buffer management
Linked list manipulation routines.
void tsch_queue_backoff_inc(struct tsch_neighbor *n)
Increment backoff exponent of a given neighbor queue, pick a new window.
void * list_head(list_t list)
Get a pointer to the first element of a list.
The MAC layer transmission was OK.
int tsch_queue_update_time_source(const linkaddr_t *new_addr)
Update TSCH time source.
The MAC layer transmission could not be performed because of an error.
Main API declarations for TSCH.
struct tsch_packet * tsch_queue_get_packet_for_nbr(const struct tsch_neighbor *n, struct tsch_link *link)
Returns the first packet that can be sent from a queue on a given link.
int ringbufindex_elements(const struct ringbufindex *r)
Return the number of elements currently in the ring buffer.
Memory block allocation routines.
int tsch_is_locked(void)
Checks if the TSCH lock is set.
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
void list_add(list_t list, void *item)
Add an item at the end of a list.
int tsch_queue_packet_sent(struct tsch_neighbor *n, struct tsch_packet *p, struct tsch_link *link, uint8_t mac_tx_status)
Updates neighbor queue state after a transmission.
struct tsch_packet * tsch_queue_remove_packet_from_queue(struct tsch_neighbor *n)
Remove first packet from a neighbor queue.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
void tsch_queue_reset(void)
Reset neighbor queues module.
void list_init(list_t list)
Initialize a list.
int tsch_queue_is_empty(const struct tsch_neighbor *n)
Is the neighbor queue empty?
#define LIST(name)
Declare a linked list.
int tsch_queue_packet_count(const linkaddr_t *addr)
Returns the number of packets currently a given neighbor queue.
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
int ringbufindex_get(struct ringbufindex *r)
Remove the first element and return its index.
int ringbufindex_peek_put(const struct ringbufindex *r)
Check if there is space to put an element.
An IEEE 802.15.4-2015 TSCH link (also called cell or slot)
struct tsch_packet * tsch_queue_get_unicast_packet_for_any(struct tsch_neighbor **n, struct tsch_link *link)
Gets the head packet of any neighbor queue with zero backoff counter.
void tsch_queue_free_packet(struct tsch_packet *p)
Free a packet.
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
struct tsch_packet * tsch_queue_add_packet(const linkaddr_t *addr, uint8_t max_transmissions, mac_callback_t sent, void *ptr)
Add packet to neighbor queue.
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
int ringbufindex_put(struct ringbufindex *r)
Put one element to the ring buffer.
void list_remove(list_t list, void *item)
Remove a specific element from a list.
void * list_item_next(void *item)
Get the next item following this item.
void tsch_queue_backoff_reset(struct tsch_neighbor *n)
Reset neighbor backoff.
#define MEMB(name, structure, num)
Declare a memory block.
int ringbufindex_empty(const struct ringbufindex *r)
Is the ring buffer empty?