50#include "net/nbr-table.h"
61#define LOG_MODULE "TSCH Sched"
62#define LOG_LEVEL LOG_LEVEL_MAC
94 LOG_INFO(
"Adding slotframe %u, size %u\n", handle, size);
106 while((sf =
list_head(slotframe_list))) {
118 if(slotframe != NULL) {
121 while((l =
list_head(slotframe->links_list))) {
127 LOG_INFO(
"Remove slotframe %u, size %u\n",
128 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);
242 LOG_ERR(
"! add_link memb_alloc couldn't take lock\n");
246 LOG_ERR(
"! add_link memb_alloc failed\n");
249 static int current_link_handle = 0;
254 l->handle = current_link_handle++;
255 l->link_options = link_options;
257 l->slotframe_handle = slotframe->handle;
258 l->timeslot = timeslot;
259 l->channel_offset = channel_offset;
261 if(address == NULL) {
266 LOG_INFO(
"add_link sf=%u opt=%s type=%s ts=%u ch=%u addr=",
268 print_link_options(link_options),
269 print_link_type(
link_type), timeslot, channel_offset);
270 LOG_INFO_LLADDR(address);
275 if(l->link_options & LINK_OPTION_TX) {
280 if(!(l->link_options & LINK_OPTION_SHARED)) {
281 n->dedicated_tx_links_count++;
295 if(slotframe != NULL && l != NULL && l->slotframe_handle == slotframe->handle) {
297 uint8_t link_options;
302 link_options = l->link_options;
307 if(l == current_link) {
310 LOG_INFO(
"remove_link sf=%u opt=%s type=%s ts=%u ch=%u addr=",
312 print_link_options(l->link_options),
313 print_link_type(l->link_type), l->timeslot, l->channel_offset);
314 LOG_INFO_LLADDR(&l->addr);
324 if(link_options & LINK_OPTION_TX) {
328 if(!(link_options & LINK_OPTION_SHARED)) {
329 n->dedicated_tx_links_count--;
336 LOG_ERR(
"! remove_link memb_alloc couldn't take lock\n");
346 uint16_t timeslot, uint16_t channel_offset)
350 if(slotframe != NULL) {
355 if(l->timeslot == timeslot && l->channel_offset == channel_offset) {
371 uint16_t timeslot, uint16_t channel_offset)
374 if(slotframe != NULL) {
379 if(l->timeslot == timeslot && l->channel_offset == channel_offset) {
396 if(slotframe != NULL) {
400 if(l->timeslot == timeslot) {
414 if(!(a->link_options & LINK_OPTION_TX)) {
426 return a_packet_count >= b_packet_count ? a : b;
439 uint16_t time_to_curr_best = 0;
453 uint16_t time_to_timeslot =
454 l->timeslot > timeslot ?
455 l->timeslot - timeslot :
456 sf->size.val + l->timeslot - timeslot;
457 if(curr_best == NULL || time_to_timeslot < time_to_curr_best) {
458 time_to_curr_best = time_to_timeslot;
461 }
else if(time_to_timeslot == time_to_curr_best) {
465 if((curr_best->link_options & LINK_OPTION_TX) == (l->link_options & LINK_OPTION_TX)) {
467 if(l->slotframe_handle != curr_best->slotframe_handle) {
468 if(l->slotframe_handle < curr_best->slotframe_handle) {
473 new_best = TSCH_LINK_COMPARATOR(curr_best, l);
477 if(l->link_options & LINK_OPTION_TX) {
484 if(new_best != l && (l->link_options & LINK_OPTION_RX)) {
485 if(curr_backup == NULL || l->slotframe_handle < curr_backup->slotframe_handle) {
490 if(new_best != curr_best && (curr_best->link_options & LINK_OPTION_RX)) {
491 if(curr_backup == NULL || curr_best->slotframe_handle < curr_backup->slotframe_handle) {
492 curr_backup = curr_best;
497 if(new_best != NULL) {
498 curr_best = new_best;
506 if(time_offset != NULL) {
507 *time_offset = time_to_curr_best;
510 if(backup_link != NULL) {
511 *backup_link = curr_backup;
546 (LINK_OPTION_RX | LINK_OPTION_TX | LINK_OPTION_SHARED | LINK_OPTION_TIME_KEEPING),
547 LINK_TYPE_ADVERTISING, &tsch_broadcast_address,
570 LOG_PRINT(
"----- start slotframe list -----\n");
575 LOG_PRINT(
"Slotframe Handle %u, size %u\n", sf->handle, sf->size.val);
578 LOG_PRINT(
"* Link Options %s, type %s, timeslot %u, " \
579 "channel offset %u, address ",
580 print_link_options(l->link_options),
581 print_link_type(l->link_type),
582 l->timeslot, l->channel_offset);
583 LOG_PRINT_LLADDR(&l->addr);
591 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.
bool linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
const linkaddr_t linkaddr_null
The null link-layer address.
static void list_init(list_t list)
Initialize a list.
#define LIST(name)
Declare a linked list.
static void * list_item_next(const void *item)
Get the next item following this item.
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.
#define LIST_STRUCT_INIT(struct_ptr, name)
Initialize a linked list that is part of a structure.
static void * list_head(const_list_t list)
Get a pointer to the first element of a list.
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.
struct tsch_link * tsch_schedule_get_link_by_timeslot(struct tsch_slotframe *slotframe, uint16_t timeslot)
Looks within a slotframe for a link with a given timeslot.
int tsch_get_lock(void)
Takes the TSCH lock.
void tsch_release_lock(void)
Releases the TSCH lock.
int tsch_schedule_remove_link_by_offsets(struct tsch_slotframe *slotframe, uint16_t timeslot, uint16_t channel_offset)
Removes a link from a slotframe and timeslot + channel offset.
void tsch_schedule_print(void)
Prints out the current schedule (all slotframes and links)
struct tsch_link * tsch_schedule_get_link_by_offsets(struct tsch_slotframe *slotframe, uint16_t timeslot, uint16_t channel_offset)
Looks within a slotframe for a link with a given timeslot and channel offset.
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_slotframe * tsch_schedule_add_slotframe(uint16_t handle, uint16_t size)
Creates and adds a new slotframe.
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.
static 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.