49 #include "net/mac/tsch/tsch.h"
50 #include "net/mac/tsch/tsch-slot-operation.h"
51 #include "net/mac/tsch/tsch-queue.h"
53 #include "net/mac/tsch/tsch-log.h"
54 #include "net/mac/tsch/tsch-packet.h"
55 #include "net/mac/tsch/tsch-security.h"
56 #include "lib/random.h"
58 #if FRAME802154_VERSION < FRAME802154_IEEE802154E_2012
59 #error TSCH: FRAME802154_VERSION must be at least FRAME802154_IEEE802154E_2012
62 #if TSCH_LOG_LEVEL >= 1
63 #define DEBUG DEBUG_PRINT
65 #define DEBUG DEBUG_NONE
71 #ifndef TSCH_LINK_NEIGHBOR_CALLBACK
72 void uip_ds6_link_neighbor_callback(
int status,
int numtx);
73 #define TSCH_LINK_NEIGHBOR_CALLBACK(dest, status, num) uip_ds6_link_neighbor_callback(status, num)
83 #ifdef NETSTACK_CONF_MAC_SEQNO_HISTORY
84 #define MAX_SEQNOS NETSTACK_CONF_MAC_SEQNO_HISTORY
90 static struct seqno received_seqnos[MAX_SEQNOS];
94 #if TSCH_AUTOSELECT_TIME_SOURCE
95 int best_neighbor_eb_count;
100 NBR_TABLE(
struct eb_stat, eb_stats);
104 uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN];
105 struct asn_divisor_t tsch_hopping_sequence_length;
108 static const uint16_t tsch_default_timing_us[tsch_ts_elements_count] = {
109 TSCH_DEFAULT_TS_CCA_OFFSET,
111 TSCH_DEFAULT_TS_TX_OFFSET,
112 TSCH_DEFAULT_TS_RX_OFFSET,
113 TSCH_DEFAULT_TS_RX_ACK_DELAY,
114 TSCH_DEFAULT_TS_TX_ACK_DELAY,
115 TSCH_DEFAULT_TS_RX_WAIT,
116 TSCH_DEFAULT_TS_ACK_WAIT,
117 TSCH_DEFAULT_TS_RX_TX,
118 TSCH_DEFAULT_TS_MAX_ACK,
119 TSCH_DEFAULT_TS_MAX_TX,
120 TSCH_DEFAULT_TS_TIMESLOT_LENGTH,
123 rtimer_clock_t tsch_timing[tsch_ts_elements_count];
125 #if LINKADDR_SIZE == 8
127 const linkaddr_t tsch_broadcast_address = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
129 const linkaddr_t tsch_eb_address = { { 0, 0, 0, 0, 0, 0, 0, 0 } };
131 const linkaddr_t tsch_broadcast_address = { { 0xff, 0xff } };
132 const linkaddr_t tsch_eb_address = { { 0, 0 } };
136 int tsch_is_started = 0;
138 int tsch_is_initialized = 0;
140 int tsch_is_coordinator = 0;
142 int tsch_is_associated = 0;
144 int tsch_is_pan_secured = LLSEC802154_ENABLED;
146 struct asn_t current_asn;
149 uint8_t tsch_join_priority;
151 static uint8_t tsch_packet_seqno = 0;
153 static clock_time_t tsch_current_eb_period;
156 static struct ctimer keepalive_timer;
160 PROCESS(tsch_process,
"TSCH: main process");
161 PROCESS(tsch_send_eb_process,
"TSCH: send EB process");
162 PROCESS(tsch_pending_events_process,
"TSCH: pending events process");
165 static void packet_input(
void);
171 tsch_set_coordinator(
int enable)
173 tsch_is_coordinator = enable;
174 tsch_set_eb_period(TSCH_EB_PERIOD);
178 tsch_set_pan_secured(
int enable)
180 tsch_is_pan_secured = LLSEC802154_ENABLED && enable;
184 tsch_set_join_priority(uint8_t jp)
186 tsch_join_priority = jp;
190 tsch_set_eb_period(uint32_t period)
192 tsch_current_eb_period = period;
199 frame802154_set_pan_id(0xffff);
205 tsch_queue_free_unused_neighbors();
206 tsch_queue_update_time_source(
NULL);
208 tsch_join_priority = 0xff;
209 ASN_INIT(current_asn, 0, 0);
212 for(i = 0; i < tsch_ts_elements_count; i++) {
213 tsch_timing[i] = US_TO_RTIMERTICKS(tsch_default_timing_us[i]);
215 #ifdef TSCH_CALLBACK_LEAVING_NETWORK
216 TSCH_CALLBACK_LEAVING_NETWORK();
218 #if TSCH_AUTOSELECT_TIME_SOURCE
219 best_neighbor_eb_count = 0;
220 nbr_table_register(eb_stats,
NULL);
221 tsch_set_eb_period(TSCH_EB_PERIOD);
230 keepalive_packet_sent(
void *ptr,
int status,
int transmissions)
232 #ifdef TSCH_LINK_NEIGHBOR_CALLBACK
233 TSCH_LINK_NEIGHBOR_CALLBACK(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), status, transmissions);
235 PRINTF(
"TSCH: KA sent to %u, st %d-%d\n",
236 TSCH_LOG_ID_FROM_LINKADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)), status, transmissions);
237 tsch_schedule_keepalive();
244 if(tsch_is_associated) {
245 struct tsch_neighbor *n = tsch_queue_get_time_source();
248 packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &n->addr);
249 NETSTACK_LLSEC.send(keepalive_packet_sent,
NULL);
250 PRINTF(
"TSCH: sending KA to %u\n",
251 TSCH_LOG_ID_FROM_LINKADDR(&n->addr));
257 tsch_schedule_keepalive()
260 if(!tsch_is_coordinator && tsch_is_associated) {
261 unsigned long delay = (TSCH_KEEPALIVE_TIMEOUT - TSCH_KEEPALIVE_TIMEOUT / 10)
268 eb_input(
struct input_packet *current_input)
274 struct ieee802154_ies eb_ies;
276 if(tsch_packet_parse_eb(current_input->payload, current_input->len,
277 &frame, &eb_ies,
NULL, 1)) {
280 #if TSCH_AUTOSELECT_TIME_SOURCE
281 if(!tsch_is_coordinator) {
283 struct eb_stat *stat = (
struct eb_stat *)nbr_table_get_from_lladdr(eb_stats, &frame.
src_addr);
285 stat = (
struct eb_stat *)nbr_table_add_lladdr(eb_stats, &frame.
src_addr);
289 stat->jp = eb_ies.join_priority;
290 best_neighbor_eb_count = MAX(best_neighbor_eb_count, stat->rx_count);
293 struct eb_stat *best_stat =
NULL;
294 stat = nbr_table_head(eb_stats);
295 while(stat !=
NULL) {
297 if(stat->rx_count > best_neighbor_eb_count / 2) {
298 if(best_stat ==
NULL ||
299 stat->jp < best_stat->jp) {
303 stat = nbr_table_next(eb_stats, stat);
306 if(best_stat !=
NULL) {
307 tsch_queue_update_time_source(nbr_table_get_lladdr(eb_stats, best_stat));
308 tsch_join_priority = best_stat->jp + 1;
313 struct tsch_neighbor *n = tsch_queue_get_time_source();
317 int32_t asn_diff = ASN_DIFF(current_input->rx_asn, eb_ies.ie_asn);
320 PRINTF(
"TSCH:! ASN drifted by %ld, leaving the network\n", asn_diff);
324 if(eb_ies.ie_join_priority >= TSCH_MAX_JOIN_PRIORITY) {
326 PRINTF(
"TSCH:! EB JP too high %u, leaving the network\n",
327 eb_ies.ie_join_priority);
330 #if TSCH_AUTOSELECT_TIME_SOURCE
332 if(tsch_join_priority != eb_ies.ie_join_priority + 1) {
333 PRINTF(
"TSCH: update JP from EB %u -> %u\n",
334 tsch_join_priority, eb_ies.ie_join_priority + 1);
335 tsch_join_priority = eb_ies.ie_join_priority + 1;
346 tsch_rx_process_pending()
350 while((input_index = ringbufindex_peek_get(&input_ringbuf)) != -1) {
351 struct input_packet *current_input = &input_array[input_index];
353 uint8_t ret =
frame802154_parse(current_input->payload, current_input->len, &frame);
354 int is_data = ret && frame.
fcf.
frame_type == FRAME802154_DATAFRAME;
363 packetbuf_set_attr(PACKETBUF_ATTR_RSSI, current_input->rssi);
367 ringbufindex_get(&input_ringbuf);
373 eb_input(current_input);
381 tsch_tx_process_pending()
383 int16_t dequeued_index;
385 while((dequeued_index = ringbufindex_peek_get(&dequeued_ringbuf)) != -1) {
386 struct tsch_packet *p = dequeued_array[dequeued_index];
388 queuebuf_to_packetbuf(p->qb);
390 mac_call_sent_callback(p->sent, p->ptr, p->ret, p->transmissions);
392 tsch_queue_free_packet(p);
394 tsch_queue_free_unused_neighbors();
396 ringbufindex_get(&dequeued_ringbuf);
402 tsch_start_coordinator(
void)
404 frame802154_set_pan_id(IEEE802154_PANID);
406 memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE,
sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
407 ASN_DIVISOR_INIT(tsch_hopping_sequence_length,
sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
408 #if TSCH_SCHEDULE_WITH_6TISCH_MINIMAL
409 tsch_schedule_create_minimal();
412 tsch_is_associated = 1;
413 tsch_join_priority = 0;
415 PRINTF(
"TSCH: starting as coordinator, PAN ID %x, asn-%x.%lx\n",
416 frame802154_get_pan_id(), current_asn.ms1b, current_asn.ls4b);
419 tsch_slot_operation_sync(
RTIMER_NOW(), ¤t_asn);
424 tsch_disassociate(
void)
426 if(tsch_is_associated == 1) {
427 tsch_is_associated = 0;
429 PRINTF(
"TSCH: leaving the network\n");
435 tsch_associate(
const struct input_packet *input_eb, rtimer_clock_t timestamp)
438 struct ieee802154_ies ies;
442 if(input_eb ==
NULL || tsch_packet_parse_eb(input_eb->payload, input_eb->len,
443 &frame, &ies, &hdrlen, 0) == 0) {
444 PRINTF(
"TSCH:! failed to parse EB (len %u)\n", input_eb->len);
448 current_asn = ies.ie_asn;
449 tsch_join_priority = ies.ie_join_priority + 1;
451 #if TSCH_JOIN_SECURED_ONLY
453 PRINTF(
"TSCH:! parse_eb: EB is not secured\n");
458 #if LLSEC802154_ENABLED
459 if(!tsch_security_parse_frame(input_eb->payload, hdrlen,
460 input_eb->len - hdrlen - tsch_security_mic_len(&frame),
461 &frame, (linkaddr_t*)&frame.
src_addr, ¤t_asn)) {
462 PRINTF(
"TSCH:! parse_eb: failed to authenticate\n");
467 #if !LLSEC802154_ENABLED
469 PRINTF(
"TSCH:! parse_eb: we do not support security, but EB is secured\n");
474 #if TSCH_JOIN_MY_PANID_ONLY
476 if(frame.
src_pid != IEEE802154_PANID) {
477 PRINTF(
"TSCH:! parse_eb: PAN ID %x != %x\n", frame.
src_pid, IEEE802154_PANID);
483 if(ies.ie_join_priority == 0xff) {
484 PRINTF(
"TSCH:! parse_eb: no join priority\n");
489 for(i = 0; i < tsch_ts_elements_count; i++) {
490 if(ies.ie_tsch_timeslot_id == 0) {
491 tsch_timing[i] = US_TO_RTIMERTICKS(tsch_default_timing_us[i]);
493 tsch_timing[i] = US_TO_RTIMERTICKS(ies.ie_tsch_timeslot[i]);
498 if(ies.ie_channel_hopping_sequence_id == 0) {
499 memcpy(tsch_hopping_sequence, TSCH_DEFAULT_HOPPING_SEQUENCE,
sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
500 ASN_DIVISOR_INIT(tsch_hopping_sequence_length,
sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
502 if(ies.ie_hopping_sequence_len <=
sizeof(tsch_hopping_sequence)) {
503 memcpy(tsch_hopping_sequence, ies.ie_hopping_sequence_list, ies.ie_hopping_sequence_len);
504 ASN_DIVISOR_INIT(tsch_hopping_sequence_length, ies.ie_hopping_sequence_len);
506 PRINTF(
"TSCH:! parse_eb: hopping sequence too long (%u)\n", ies.ie_hopping_sequence_len);
511 #if TSCH_CHECK_TIME_AT_ASSOCIATION > 0
513 uint32_t expected_asn = 4096 * TSCH_CLOCK_TO_SLOTS(
clock_time() / 4096, tsch_timing_timeslot_length);
514 int32_t asn_threshold = TSCH_CHECK_TIME_AT_ASSOCIATION * 60ul * TSCH_CLOCK_TO_SLOTS(
CLOCK_SECOND, tsch_timing_timeslot_length);
515 int32_t asn_diff = (int32_t)current_asn.ls4b - expected_asn;
516 if(asn_diff > asn_threshold) {
517 PRINTF(
"TSCH:! EB ASN rejected %lx %lx %ld\n",
518 current_asn.ls4b, expected_asn, asn_diff);
523 #if TSCH_INIT_SCHEDULE_FROM_EB
525 if(ies.ie_tsch_slotframe_and_link.num_slotframes == 0) {
526 #if TSCH_SCHEDULE_WITH_6TISCH_MINIMAL
527 PRINTF(
"TSCH: parse_eb: no schedule, setting up minimal schedule\n");
528 tsch_schedule_create_minimal();
530 PRINTF(
"TSCH: parse_eb: no schedule\n");
534 tsch_schedule_remove_all_slotframes();
536 int num_links = ies.ie_tsch_slotframe_and_link.num_links;
537 if(num_links <= FRAME802154E_IE_MAX_LINKS) {
539 struct tsch_slotframe *sf = tsch_schedule_add_slotframe(
540 ies.ie_tsch_slotframe_and_link.slotframe_handle,
541 ies.ie_tsch_slotframe_and_link.slotframe_size);
542 for(i = 0; i < num_links; i++) {
543 tsch_schedule_add_link(sf,
544 ies.ie_tsch_slotframe_and_link.links[i].link_options,
545 LINK_TYPE_ADVERTISING, &tsch_broadcast_address,
546 ies.ie_tsch_slotframe_and_link.links[i].timeslot, ies.ie_tsch_slotframe_and_link.links[i].channel_offset);
549 PRINTF(
"TSCH:! parse_eb: too many links in schedule (%u)\n", num_links);
555 if(tsch_join_priority < TSCH_MAX_JOIN_PRIORITY) {
556 struct tsch_neighbor *n;
559 n = tsch_queue_add_nbr((linkaddr_t *)&frame.
src_addr);
562 tsch_queue_update_time_source((linkaddr_t *)&frame.
src_addr);
564 #ifdef TSCH_CALLBACK_JOINING_NETWORK
565 TSCH_CALLBACK_JOINING_NETWORK();
569 frame802154_set_pan_id(frame.
src_pid);
572 tsch_slot_operation_sync(timestamp - tsch_timing[tsch_ts_tx_offset], ¤t_asn);
575 tsch_is_associated = 1;
579 tsch_schedule_keepalive();
581 PRINTF(
"TSCH: association done, sec %u, PAN ID %x, asn-%x.%lx, jp %u, timeslot id %u, hopping id %u, slotframe len %u with %u links, from ",
584 current_asn.ms1b, current_asn.ls4b, tsch_join_priority,
585 ies.ie_tsch_timeslot_id,
586 ies.ie_channel_hopping_sequence_id,
587 ies.ie_tsch_slotframe_and_link.slotframe_size,
588 ies.ie_tsch_slotframe_and_link.num_links);
595 PRINTF(
"TSCH:! did not associate.\n");
610 static struct input_packet input_eb;
611 static struct etimer scan_timer;
613 ASN_INIT(current_asn, 0, 0);
617 while(!tsch_is_associated && !tsch_is_coordinator) {
619 static int current_channel = 0;
621 static clock_time_t current_channel_since = 0;
625 int is_packet_pending = 0;
629 if(current_channel == 0 || now_seconds != current_channel_since) {
631 uint8_t scan_channel = TSCH_JOIN_HOPPING_SEQUENCE[
632 random_rand() %
sizeof(TSCH_JOIN_HOPPING_SEQUENCE)];
633 if(current_channel != scan_channel) {
634 NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, scan_channel);
635 current_channel = scan_channel;
636 PRINTF(
"TSCH: scanning on channel %u\n", scan_channel);
638 current_channel_since = now_seconds;
644 is_packet_pending = NETSTACK_RADIO.pending_packet();
645 if(!is_packet_pending && NETSTACK_RADIO.receiving_packet()) {
648 BUSYWAIT_UNTIL_ABS((is_packet_pending = NETSTACK_RADIO.pending_packet()), t0, RTIMER_SECOND / 100);
651 if(is_packet_pending) {
653 NETSTACK_RADIO.get_object(RADIO_PARAM_LAST_PACKET_TIMESTAMP, &t0,
sizeof(rtimer_clock_t));
656 input_eb.len = NETSTACK_RADIO.read(input_eb.payload, TSCH_PACKET_MAX_LEN);
659 PRINTF(
"TSCH: association: received packet (%u bytes) on channel %u\n", input_eb.len, current_channel);
661 tsch_associate(&input_eb, t0);
664 if(tsch_is_associated) {
666 NETSTACK_RADIO.off();
667 }
else if(!tsch_is_coordinator) {
681 static struct pt scan_pt;
687 while(!tsch_is_associated) {
688 if(tsch_is_coordinator) {
690 tsch_start_coordinator();
698 tsch_slot_operation_start();
715 static struct etimer eb_timer;
721 while(!tsch_is_associated) {
727 if(!tsch_is_coordinator) {
735 if(tsch_is_associated && tsch_current_eb_period > 0) {
737 if(tsch_queue_packet_count(&tsch_eb_address) == 0) {
740 uint8_t tsch_sync_ie_offset;
744 if(++tsch_packet_seqno == 0) {
747 packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_BEACONFRAME);
748 packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, tsch_packet_seqno);
749 #if LLSEC802154_ENABLED
750 if(tsch_is_pan_secured) {
752 packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, TSCH_SECURITY_KEY_SEC_LEVEL_EB);
753 packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, FRAME802154_1_BYTE_KEY_ID_MODE);
754 packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, TSCH_SECURITY_KEY_INDEX_EB);
758 tsch_packet_seqno, &hdr_len, &tsch_sync_ie_offset);
760 struct tsch_packet *p;
763 if(!(p = tsch_queue_add_packet(&tsch_eb_address,
NULL,
NULL))) {
764 PRINTF(
"TSCH:! could not enqueue EB packet\n");
766 PRINTF(
"TSCH: enqueue EB packet %u %u\n", eb_len, hdr_len);
767 p->tsch_sync_ie_offset = tsch_sync_ie_offset;
768 p->header_len = hdr_len;
773 if(tsch_current_eb_period > 0) {
776 delay = (tsch_current_eb_period - tsch_current_eb_period / 4)
779 delay = TSCH_EB_PERIOD;
795 tsch_rx_process_pending();
796 tsch_tx_process_pending();
797 tsch_log_process_pending();
813 if(NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode) != RADIO_RESULT_OK) {
814 printf(
"TSCH:! radio does not support getting RADIO_PARAM_RX_MODE. Abort init.\n");
820 radio_rx_mode &= ~RADIO_RX_MODE_AUTOACK;
822 radio_rx_mode |= RADIO_RX_MODE_POLL_MODE;
823 if(NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode) != RADIO_RESULT_OK) {
824 printf(
"TSCH:! radio does not support setting required RADIO_PARAM_RX_MODE. Abort init.\n");
829 if(NETSTACK_RADIO.get_value(RADIO_PARAM_TX_MODE, &radio_tx_mode) != RADIO_RESULT_OK) {
830 printf(
"TSCH:! radio does not support getting RADIO_PARAM_TX_MODE. Abort init.\n");
835 if(NETSTACK_RADIO.set_value(RADIO_PARAM_TX_MODE, radio_tx_mode) != RADIO_RESULT_OK) {
836 printf(
"TSCH:! radio does not support setting required RADIO_PARAM_TX_MODE. Abort init.\n");
840 if(NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, TSCH_DEFAULT_HOPPING_SEQUENCE[0]) != RADIO_RESULT_OK) {
841 printf(
"TSCH:! radio does not support setting channel. Abort init.\n");
845 if(NETSTACK_RADIO.get_object(RADIO_PARAM_LAST_PACKET_TIMESTAMP, &t,
sizeof(rtimer_clock_t)) != RADIO_RESULT_OK) {
846 printf(
"TSCH:! radio does not support getting last packet timestamp. Abort init.\n");
850 if(TSCH_HOPPING_SEQUENCE_MAX_LEN <
sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE)) {
851 printf(
"TSCH:! TSCH_HOPPING_SEQUENCE_MAX_LEN < sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE). Abort init.\n");
857 tsch_schedule_init();
859 ringbufindex_init(&input_ringbuf, TSCH_MAX_INCOMING_PACKETS);
860 ringbufindex_init(&dequeued_ringbuf, TSCH_DEQUEUED_ARRAY_SIZE);
862 tsch_is_initialized = 1;
873 send_packet(mac_callback_t sent,
void *ptr)
876 int packet_count_before;
878 const linkaddr_t *
addr = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
880 if(!tsch_is_associated) {
881 if(!tsch_is_initialized) {
882 PRINTF(
"TSCH:! not initialized (see earlier logs), drop outgoing packet\n");
884 PRINTF(
"TSCH:! not associated, drop outgoing packet\n");
887 mac_call_sent_callback(sent, ptr, ret, 1);
893 if(++tsch_packet_seqno == 0) {
899 packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
904 addr = &tsch_broadcast_address;
907 packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
908 packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, tsch_packet_seqno);
910 #if LLSEC802154_ENABLED
911 if(tsch_is_pan_secured) {
913 packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, TSCH_SECURITY_KEY_SEC_LEVEL_OTHER);
914 packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, FRAME802154_1_BYTE_KEY_ID_MODE);
915 packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, TSCH_SECURITY_KEY_INDEX_OTHER);
919 packet_count_before = tsch_queue_packet_count(addr);
921 if((hdr_len = NETSTACK_FRAMER.create()) < 0) {
922 PRINTF(
"TSCH:! can't send packet due to framer error\n");
925 struct tsch_packet *p;
927 p = tsch_queue_add_packet(addr, sent, ptr);
929 PRINTF(
"TSCH:! can't send packet !tsch_queue_add_packet\n");
932 p->header_len = hdr_len;
933 PRINTF(
"TSCH: send packet to %u with seqno %u, queue %u %u, len %u %u\n",
934 TSCH_LOG_ID_FROM_LINKADDR(addr), tsch_packet_seqno,
936 tsch_queue_packet_count(addr),
938 queuebuf_datalen(p->qb));
939 (void)packet_count_before;
943 mac_call_sent_callback(sent, ptr, ret, 1);
950 int frame_parsed = 1;
952 frame_parsed = NETSTACK_FRAMER.parse();
954 if(frame_parsed < 0) {
960 if(packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO) != 0xffff) {
964 for(i = 0; i < MAX_SEQNOS; ++i) {
965 if(packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO) == received_seqnos[i].seqno &&
967 &received_seqnos[i].sender)) {
969 PRINTF(
"TSCH:! drop dup ll from %u seqno %u\n",
970 TSCH_LOG_ID_FROM_LINKADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)),
971 packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
976 for(i = MAX_SEQNOS - 1; i > 0; --i) {
977 memcpy(&received_seqnos[i], &received_seqnos[i - 1],
978 sizeof(
struct seqno));
980 received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO);
982 packetbuf_addr(PACKETBUF_ADDR_SENDER));
987 PRINTF(
"TSCH: received from %u with seqno %u\n",
988 TSCH_LOG_ID_FROM_LINKADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)),
989 packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
990 NETSTACK_LLSEC.input();
998 if(tsch_is_initialized == 1 && tsch_is_started == 0) {
1006 PRINTF(
"TSCH: starting as %s\n", tsch_is_coordinator ?
"coordinator" :
"node");
1013 turn_off(
int keep_radio_on)
1018 static unsigned short
1019 channel_check_interval(
void)
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
uint8_t security_enabled
1 bit.
uint16_t src_pid
Source PAN ID.
Header file for the radio API
static uip_ds6_addr_t * addr
Pointer to a router list entry.
frame802154_fcf_t fcf
Frame control field.
#define RTIMER_NOW()
Get the current clock time.
void packetbuf_clear(void)
Clear and reset the packetbuf.
CCIF clock_time_t clock_time(void)
Get the current clock time.
uint8_t src_addr[8]
Source address.
void etimer_set(struct etimer *et, clock_time_t interval)
Set an event timer.
#define PROCESS_END()
Define the end of a process.
#define PROCESS(name, strname)
Declare a process.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#define PT_WAIT_UNTIL(pt, condition)
Block and wait until condition is true.
Private TSCH definitions (meant for use by TSCH implementation files only) ...
#define PACKETBUF_SIZE
The size of the packetbuf, in bytes.
const linkaddr_t linkaddr_null
The null Rime address.
Header file for the Rime buffer (packetbuf) management
int process_post(struct process *p, process_event_t ev, process_data_t data)
Post an asynchronous event.
The MAC layer transmission could not be performed because of a fatal error.
The MAC layer transmission could not be performed because of an error.
A set of debugging macros for the netstack
void process_post_synch(struct process *p, process_event_t ev, process_data_t data)
Post a synchronous event to a process.
#define NULL
The null pointer.
int radio_value_t
Each radio has a set of parameters that designate the current configuration and state of the radio...
#define RADIO_RX_MODE_ADDRESS_FILTER
The radio reception mode controls address filtering and automatic transmission of acknowledgements in...
unsigned short random_rand(void)
Generates a new random number using the cc2538 RNG.
#define PT_THREAD(name_args)
Declaration of a protothread.
The structure of a MAC protocol driver in Contiki.
int etimer_expired(struct etimer *et)
Check if an event timer has expired.
#define PT_BEGIN(pt)
Declare the start of a protothread inside the C function implementing the protothread.
#define CLOCK_SECOND
A second, measured in system clock time.
int frame802154_parse(uint8_t *data, int len, frame802154_t *pf)
Parses an input frame.
#define RADIO_TX_MODE_SEND_ON_CCA
The radio transmission mode controls whether transmissions should be done using clear channel assessm...
unsigned short(* channel_check_interval)(void)
Returns the channel check interval, expressed in clock_time_t ticks.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
void process_start(struct process *p, process_data_t data)
Start a process.
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
int packetbuf_copyfrom(const void *from, uint16_t len)
Copy from external data into the packetbuf.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
#define PT_END(pt)
Declare the end of a protothread.
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Header file for the Rime queue buffer management
CCIF unsigned long clock_seconds(void)
Get the current value of the platform seconds.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two Rime addresses.
#define PROCESS_PT_SPAWN(pt, thread)
Spawn a protothread from the process.
#define PROCESS_WAIT_UNTIL(c)
Wait for a condition to occur.
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a Rime address.
uint8_t frame_version
2 bit.
Parameters used by the frame802154_create() function.
Include file for the Contiki low-layer network stack (NETSTACK)
void etimer_reset(struct etimer *et)
Reset an event timer with the same interval as was previously set.
#define PROCESS_BEGIN()
Define the beginning of a process.
A MAC framer for IEEE 802.15.4