/* Adds and returns a slotframe (NULL if failure) */ struct tsch_slotframe * tsch_schedule_add_slotframe(uint16_t handle, uint16_t size) { if(size == 0) { return NULL; } if(tsch_schedule_get_slotframe_by_handle(handle)) { /* A slotframe with this handle already exists */ return NULL; } if(tsch_get_lock()) { struct tsch_slotframe *sf = memb_alloc(&slotframe_memb); if(sf != NULL) { /* Initialize the slotframe */ sf->handle = handle; ASN_DIVISOR_INIT(sf->size, size); LIST_STRUCT_INIT(sf, links_list); /* Add the slotframe to the global list */ list_add(slotframe_list, sf); } PRINTF("TSCH-schedule: add_slotframe %u %u\n", handle, size); tsch_release_lock(); return sf; } return NULL; }
/* Create an EB packet */ int tsch_packet_create_eb(uint8_t *buf, int buf_size, uint8_t seqno, uint8_t *hdr_len, uint8_t *tsch_sync_ie_offset) { int ret = 0; uint8_t curr_len = 0; uint8_t mlme_ie_offset; frame802154_t p; struct ieee802154_ies ies; if(buf_size < TSCH_PACKET_MAX_LEN) { return 0; } /* Create 802.15.4 header */ memset(&p, 0, sizeof(p)); p.fcf.frame_type = FRAME802154_BEACONFRAME; p.fcf.ie_list_present = 1; p.fcf.frame_version = FRAME802154_IEEE802154E_2012; p.fcf.src_addr_mode = LINKADDR_SIZE > 2 ? FRAME802154_LONGADDRMODE : FRAME802154_SHORTADDRMODE; p.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; p.seq = seqno; p.fcf.sequence_number_suppression = FRAME802154_SUPPR_SEQNO; /* It is important not to compress PAN ID, as this would result in not including either * source nor destination PAN ID, leaving potential joining devices unaware of the PAN ID. */ p.fcf.panid_compression = 0; p.src_pid = frame802154_get_pan_id(); p.dest_pid = frame802154_get_pan_id(); linkaddr_copy((linkaddr_t *)&p.src_addr, &linkaddr_node_addr); p.dest_addr[0] = 0xff; p.dest_addr[1] = 0xff; #if LLSEC802154_ENABLED if(tsch_is_pan_secured) { p.fcf.security_enabled = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) > 0; p.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL); p.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE); p.aux_hdr.security_control.frame_counter_suppression = 1; p.aux_hdr.security_control.frame_counter_size = 1; p.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX); } #endif /* LLSEC802154_ENABLED */ if((curr_len = frame802154_create(&p, buf)) == 0) { return 0; } /* Prepare Information Elements for inclusion in the EB */ memset(&ies, 0, sizeof(ies)); /* Add TSCH timeslot timing IE. */ #if TSCH_PACKET_EB_WITH_TIMESLOT_TIMING { int i; ies.ie_tsch_timeslot_id = 1; for(i = 0; i < tsch_ts_elements_count; i++) { ies.ie_tsch_timeslot[i] = RTIMERTICKS_TO_US(tsch_timing[i]); } } #endif /* TSCH_PACKET_EB_WITH_TIMESLOT_TIMING */ /* Add TSCH hopping sequence IE */ #if TSCH_PACKET_EB_WITH_HOPPING_SEQUENCE if(tsch_hopping_sequence_length.val <= sizeof(ies.ie_hopping_sequence_list)) { ies.ie_channel_hopping_sequence_id = 1; ies.ie_hopping_sequence_len = tsch_hopping_sequence_length.val; memcpy(ies.ie_hopping_sequence_list, tsch_hopping_sequence, ies.ie_hopping_sequence_len); } #endif /* TSCH_PACKET_EB_WITH_HOPPING_SEQUENCE */ /* Add Slotframe and Link IE */ #if TSCH_PACKET_EB_WITH_SLOTFRAME_AND_LINK { /* Send slotframe 0 with link at timeslot 0 */ struct tsch_slotframe *sf0 = tsch_schedule_get_slotframe_by_handle(0); struct tsch_link *link0 = tsch_schedule_get_link_by_timeslot(sf0, 0); if(sf0 && link0) { ies.ie_tsch_slotframe_and_link.num_slotframes = 1; ies.ie_tsch_slotframe_and_link.slotframe_handle = sf0->handle; ies.ie_tsch_slotframe_and_link.slotframe_size = sf0->size.val; ies.ie_tsch_slotframe_and_link.num_links = 1; ies.ie_tsch_slotframe_and_link.links[0].timeslot = link0->timeslot; ies.ie_tsch_slotframe_and_link.links[0].channel_offset = link0->channel_offset; ies.ie_tsch_slotframe_and_link.links[0].link_options = link0->link_options; } } #endif /* TSCH_PACKET_EB_WITH_SLOTFRAME_AND_LINK */ /* First add header-IE termination IE to stipulate that next come payload IEs */ if((ret = frame80215e_create_ie_header_list_termination_1(buf + curr_len, buf_size - curr_len, &ies)) == -1) { return -1; } curr_len += ret; /* We start payload IEs, save offset */ if(hdr_len != NULL) { *hdr_len = curr_len; } /* Save offset of the MLME IE descriptor, we need to know the total length * before writing it */ mlme_ie_offset = curr_len; curr_len += 2; /* Space needed for MLME descriptor */ /* Save the offset of the TSCH Synchronization IE, needed to update ASN and join priority before sending */ if(tsch_sync_ie_offset != NULL) { *tsch_sync_ie_offset = curr_len; } if((ret = frame80215e_create_ie_tsch_synchronization(buf + curr_len, buf_size - curr_len, &ies)) == -1) { return -1; } curr_len += ret; if((ret = frame80215e_create_ie_tsch_timeslot(buf + curr_len, buf_size - curr_len, &ies)) == -1) { return -1; } curr_len += ret; if((ret = frame80215e_create_ie_tsch_channel_hopping_sequence(buf + curr_len, buf_size - curr_len, &ies)) == -1) { return -1; } curr_len += ret; if((ret = frame80215e_create_ie_tsch_slotframe_and_link(buf + curr_len, buf_size - curr_len, &ies)) == -1) { return -1; } curr_len += ret; ies.ie_mlme_len = curr_len - mlme_ie_offset - 2; if((ret = frame80215e_create_ie_mlme(buf + mlme_ie_offset, buf_size - mlme_ie_offset, &ies)) == -1) { return -1; } /* Payload IE list termination: optional */ /* if((ret = frame80215e_create_ie_payload_list_termination(buf + curr_len, buf_size - curr_len, &ies)) == -1) { return -1; } curr_len += ret; */ return curr_len; }