50#include "net/nbr-table.h"
61#define LOG_MODULE "TSCH Sched"
62#define LOG_LEVEL LOG_LEVEL_MAC
94 LOG_INFO(
"add_slotframe %u %u\n",
107 while((sf =
list_head(slotframe_list))) {
119 if(slotframe != NULL) {
122 while((l =
list_head(slotframe->links_list))) {
128 LOG_INFO(
"remove slotframe %u %u\n", slotframe->handle, slotframe->size.val);
145 if(sf->handle == handle) {
164 if(l->handle == handle) {
176print_link_options(uint16_t link_options)
178 static char buffer[20];
182 if(link_options & LINK_OPTION_TX) {
183 strcat(buffer,
"Tx|");
185 if(link_options & LINK_OPTION_RX) {
186 strcat(buffer,
"Rx|");
188 if(link_options & LINK_OPTION_SHARED) {
189 strcat(buffer,
"Sh|");
191 length = strlen(buffer);
193 buffer[length - 1] =
'\0';
203 case LINK_TYPE_NORMAL:
205 case LINK_TYPE_ADVERTISING:
207 case LINK_TYPE_ADVERTISING_ONLY:
218 uint16_t timeslot, uint16_t channel_offset, uint8_t do_remove)
221 if(slotframe != NULL) {
225 if(timeslot > (slotframe->size.val - 1)) {
226 LOG_ERR(
"! add_link invalid timeslot: %u\n", timeslot);
236 LOG_ERR(
"! add_link memb_alloc couldn't take lock\n");
240 LOG_ERR(
"! add_link memb_alloc failed\n");
243 static int current_link_handle = 0;
248 l->handle = current_link_handle++;
249 l->link_options = link_options;
251 l->slotframe_handle = slotframe->handle;
252 l->timeslot = timeslot;
253 l->channel_offset = channel_offset;
255 if(address == NULL) {
260 LOG_INFO(
"add_link sf=%u opt=%s type=%s ts=%u ch=%u addr=",
262 print_link_options(link_options),
263 print_link_type(
link_type), timeslot, channel_offset);
264 LOG_INFO_LLADDR(address);
269 if(l->link_options & LINK_OPTION_TX) {
274 if(!(l->link_options & LINK_OPTION_SHARED)) {
275 n->dedicated_tx_links_count++;
289 if(slotframe != NULL && l != NULL && l->slotframe_handle == slotframe->handle) {
291 uint8_t link_options;
296 link_options = l->link_options;
301 if(l == current_link) {
304 LOG_INFO(
"remove_link sf=%u opt=%s type=%s ts=%u ch=%u addr=",
306 print_link_options(l->link_options),
307 print_link_type(l->link_type), l->timeslot, l->channel_offset);
308 LOG_INFO_LLADDR(&l->addr);
318 if(link_options & LINK_OPTION_TX) {
322 if(!(link_options & LINK_OPTION_SHARED)) {
323 n->dedicated_tx_links_count--;
330 LOG_ERR(
"! remove_link memb_alloc couldn't take lock\n");
339 uint16_t timeslot, uint16_t channel_offset)
343 if(slotframe != NULL) {
348 if(l->timeslot == timeslot && l->channel_offset == channel_offset) {
363 uint16_t timeslot, uint16_t channel_offset)
366 if(slotframe != NULL) {
370 if(l->timeslot == timeslot && l->channel_offset == channel_offset) {
384 if(!(a->link_options & LINK_OPTION_TX)) {
396 return a_packet_count >= b_packet_count ? a : b;
409 uint16_t time_to_curr_best = 0;
423 uint16_t time_to_timeslot =
424 l->timeslot > timeslot ?
425 l->timeslot - timeslot :
426 sf->size.val + l->timeslot - timeslot;
427 if(curr_best == NULL || time_to_timeslot < time_to_curr_best) {
428 time_to_curr_best = time_to_timeslot;
431 }
else if(time_to_timeslot == time_to_curr_best) {
435 if((curr_best->link_options & LINK_OPTION_TX) == (l->link_options & LINK_OPTION_TX)) {
437 if(l->slotframe_handle != curr_best->slotframe_handle) {
438 if(l->slotframe_handle < curr_best->slotframe_handle) {
443 new_best = TSCH_LINK_COMPARATOR(curr_best, l);
447 if(l->link_options & LINK_OPTION_TX) {
454 if(new_best != l && (l->link_options & LINK_OPTION_RX)) {
455 if(curr_backup == NULL || l->slotframe_handle < curr_backup->slotframe_handle) {
460 if(new_best != curr_best && (curr_best->link_options & LINK_OPTION_RX)) {
461 if(curr_backup == NULL || curr_best->slotframe_handle < curr_backup->slotframe_handle) {
462 curr_backup = curr_best;
467 if(new_best != NULL) {
468 curr_best = new_best;
476 if(time_offset != NULL) {
477 *time_offset = time_to_curr_best;
480 if(backup_link != NULL) {
481 *backup_link = curr_backup;
516 (LINK_OPTION_RX | LINK_OPTION_TX | LINK_OPTION_SHARED | LINK_OPTION_TIME_KEEPING),
517 LINK_TYPE_ADVERTISING, &tsch_broadcast_address,
540 LOG_PRINT(
"----- start slotframe list -----\n");
545 LOG_PRINT(
"Slotframe Handle %u, size %u\n", sf->handle, sf->size.val);
548 LOG_PRINT(
"* Link Options %02x, type %u, timeslot %u, channel offset %u, address ",
549 l->link_options, l->link_type, l->timeslot, l->channel_offset);
550 LOG_PRINT_LLADDR(&l->addr);
558 LOG_PRINT(
"----- end slotframe list -----\n");
802.15.4 frame creation and parsing functions
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
const linkaddr_t linkaddr_null
The null link-layer address.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
void list_init(list_t list)
Initialize a list.
void * list_head(const list_t list)
Get a pointer to the first element of a list.
#define LIST(name)
Declare a linked list.
void list_add(list_t list, void *item)
Add an item at the end of a list.
void list_remove(list_t list, const void *item)
Remove a specific element from a list.
void * list_item_next(const void *item)
Get the next item following this item.
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
void memb_init(struct memb *m)
Initialize a memory block that was declared with MEMB().
#define MEMB(name, structure, num)
Declare a memory block.
struct tsch_neighbor * tsch_queue_get_nbr(const linkaddr_t *addr)
Get a TSCH neighbor.
int tsch_schedule_init(void)
Module initialization, call only once at init.
struct tsch_slotframe * tsch_schedule_get_slotframe_by_handle(uint16_t handle)
Looks up a slotframe by handle.
struct tsch_link * tsch_schedule_get_next_active_link(struct tsch_asn_t *asn, uint16_t *time_offset, struct tsch_link **backup_link)
Returns the next active link after a given ASN, and a backup link (for the same ASN,...
struct tsch_link * tsch_schedule_add_link(struct tsch_slotframe *slotframe, uint8_t link_options, enum link_type link_type, const linkaddr_t *address, uint16_t timeslot, uint16_t channel_offset, uint8_t do_remove)
Adds a link to a slotframe.
int tsch_schedule_remove_slotframe(struct tsch_slotframe *slotframe)
Removes a slotframe.
#define TSCH_ASN_DIVISOR_INIT(div, val_)
Initialize a struct asn_divisor_t.
struct tsch_slotframe * tsch_schedule_slotframe_head(void)
Access the first item in the list of slotframes.
void tsch_schedule_create_minimal(void)
Create a 6tisch minimal schedule with length TSCH_SCHEDULE_DEFAULT_LENGTH.
struct tsch_link * tsch_schedule_get_link_by_handle(uint16_t handle)
Looks for a link from a handle.
int tsch_schedule_remove_all_slotframes(void)
Removes all slotframes, resulting in an empty schedule.
int tsch_get_lock(void)
Takes the TSCH lock.
void tsch_release_lock(void)
Releases the TSCH lock.
void tsch_schedule_print(void)
Prints out the current schedule (all slotframes and links)
struct tsch_neighbor * tsch_queue_add_nbr(const linkaddr_t *addr)
Add a TSCH neighbor queue.
#define TSCH_ASN_MOD(asn, div)
Returns the result (16 bits) of a modulo operation on ASN, with divisor being a struct asn_divisor_t.
link_type
802.15.4e link types.
int tsch_is_locked(void)
Checks if the TSCH lock is set.
struct tsch_link * tsch_schedule_get_link_by_timeslot(struct tsch_slotframe *slotframe, uint16_t timeslot, uint16_t channel_offset)
Looks within a slotframe for a link with a given timeslot.
struct tsch_slotframe * tsch_schedule_add_slotframe(uint16_t handle, uint16_t size)
Creates and adds a new slotframe.
int tsch_schedule_remove_link_by_timeslot(struct tsch_slotframe *slotframe, uint16_t timeslot, uint16_t channel_offset)
Removes a link from a slotframe and timeslot.
int tsch_schedule_remove_link(struct tsch_slotframe *slotframe, struct tsch_link *l)
Removes a link.
struct tsch_slotframe * tsch_schedule_slotframe_next(struct tsch_slotframe *sf)
Access the next item in the list of slotframes.
Header file for the LED HAL.
Header file for the logging system.
Memory block allocation routines.
Header file for the Packet buffer (packetbuf) management.
Header file for the Contiki process interface.
Header file for the Packet queue buffer management.
int ringbufindex_elements(const struct ringbufindex *r)
Return the number of elements currently in the ring buffer.
Header file for the real-time timer module.
The ASN is an absolute slot number over 5 bytes.
An IEEE 802.15.4-2015 TSCH link (also called cell or slot)
TSCH neighbor information.
802.15.4e slotframe (contains links)
Main API declarations for TSCH.
static uip_ds6_addr_t * addr
Pointer to a nbr cache entry.