/*---------------------------------------------------------------------------*/ static void handle_beacon_send_timer(struct net_buf *buf, void *p) { struct net_buf *mbuf; frame802154_t params; uint8_t len; mbuf = l2_buf_get_reserve(0); if(!mbuf) { return; } /* init to zeros */ memset(¶ms, 0, sizeof(params)); /* use packetbuf for sending ?? */ packetbuf_clear(mbuf); /* Build the FCF. */ params.fcf.frame_type = FRAME802154_BEACONFRAME; /* Insert IEEE 802.15.4 (2006) version bits. */ params.fcf.frame_version = FRAME802154_IEEE802154_2006; /* assume long for now */ params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE; linkaddr_copy((linkaddr_t *)¶ms.src_addr, &linkaddr_node_addr); /* Set the source PAN ID to the global variable. */ params.src_pid = panid; params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr[0] = 0xFF; params.dest_addr[1] = 0xFF; params.dest_pid = 0xffff; params.seq = framer_802154_next_seqno(); /* Calculate beacon length and copy it to packetbuf */ beacon_payload_len = handler_802154_calculate_beacon_payload_length(beacon_payload, BEACON_PAYLOAD_BUFFER_SIZE); packetbuf_copyfrom(mbuf, beacon_payload, beacon_payload_len); /* Set payload and payload length */ params.payload = packetbuf_dataptr(mbuf); params.payload_len = packetbuf_datalen(mbuf); len = frame802154_hdrlen(¶ms); if(packetbuf_hdralloc(mbuf, len)) { frame802154_create(¶ms, packetbuf_hdrptr(mbuf), len); if(NETSTACK_RADIO.send(mbuf, packetbuf_hdrptr(mbuf), packetbuf_totlen(mbuf)) != RADIO_TX_OK) { l2_buf_unref(mbuf); return; } HANDLER_802154_STAT(handler_802154_stats.beacons_sent++); } }
/* Construct enhanced ACK packet and return ACK length */ int tsch_packet_create_eack(uint8_t *buf, int buf_size, linkaddr_t *dest_addr, uint8_t seqno, int16_t drift, int nack) { int ret; uint8_t curr_len = 0; frame802154_t p; struct ieee802154_ies ies; memset(&p, 0, sizeof(p)); p.fcf.frame_type = FRAME802154_ACKFRAME; p.fcf.frame_version = FRAME802154_IEEE802154E_2012; p.fcf.ie_list_present = 1; /* Compression unset. According to IEEE802.15.4e-2012: * - if no address is present: elide PAN ID * - if at least one address is present: include exactly one PAN ID (dest by default) */ p.fcf.panid_compression = 0; p.dest_pid = IEEE802154_PANID; p.seq = seqno; #if TSCH_PACKET_EACK_WITH_DEST_ADDR if(dest_addr != NULL) { p.fcf.dest_addr_mode = LINKADDR_SIZE > 2 ? FRAME802154_LONGADDRMODE : FRAME802154_SHORTADDRMODE;; linkaddr_copy((linkaddr_t *)&p.dest_addr, dest_addr); } #endif #if TSCH_PACKET_EACK_WITH_SRC_ADDR p.fcf.src_addr_mode = LINKADDR_SIZE > 2 ? FRAME802154_LONGADDRMODE : FRAME802154_SHORTADDRMODE;; p.src_pid = IEEE802154_PANID; linkaddr_copy((linkaddr_t *)&p.src_addr, &linkaddr_node_addr); #endif #if LLSEC802154_ENABLED if(tsch_is_pan_secured) { p.fcf.security_enabled = 1; p.aux_hdr.security_control.security_level = TSCH_SECURITY_KEY_SEC_LEVEL_ACK; p.aux_hdr.security_control.key_id_mode = FRAME802154_1_BYTE_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 = TSCH_SECURITY_KEY_INDEX_ACK; } #endif /* LLSEC802154_ENABLED */ if((curr_len = frame802154_create(&p, buf)) == 0) { return 0; } /* Append IE timesync */ memset(&ies, 0, sizeof(ies)); ies.ie_time_correction = drift; ies.ie_is_nack = nack; if((ret = frame80215e_create_ie_header_ack_nack_time_correction(buf+curr_len, buf_size-curr_len, &ies)) == -1) { return -1; } curr_len += ret; return curr_len; }
/* called to send a beacon request */ void handler_802154_send_beacon_request(void) { struct net_buf *mbuf; frame802154_t params; uint8_t len; mbuf = l2_buf_get_reserve(0); if(!mbuf) { return; } /* init to zeros */ memset(¶ms, 0, sizeof(params)); /* use packetbuf for sending ?? */ packetbuf_clear(mbuf); /* Build the FCF. */ params.fcf.frame_type = FRAME802154_CMDFRAME; /* Insert IEEE 802.15.4 (2006) version bits. */ params.fcf.frame_version = FRAME802154_IEEE802154_2006; params.fcf.src_addr_mode = FRAME802154_NOADDR; params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr[0] = 0xFF; params.dest_addr[1] = 0xFF; params.dest_pid = 0xffff; params.seq = chseqno; packetbuf_set_datalen(mbuf, 1); params.payload = packetbuf_dataptr(mbuf); /* set the type in the payload */ params.payload[0] = FRAME802154_BEACONREQ; params.payload_len = packetbuf_datalen(mbuf); len = frame802154_hdrlen(¶ms); if(packetbuf_hdralloc(mbuf, len)) { frame802154_create(¶ms, packetbuf_hdrptr(mbuf), len); if(NETSTACK_RADIO.send(mbuf, packetbuf_hdrptr(mbuf), packetbuf_totlen(mbuf)) != RADIO_TX_OK) { l2_buf_unref(mbuf); return; } HANDLER_802154_STAT(handler_802154_stats.beacons_reqs_sent++); } }
/*---------------------------------------------------------------------------*/ static int create_frame(int type, int do_create) { frame802154_t params; int hdr_len; /* init to zeros */ memset(¶ms, 0, sizeof(params)); if(!initialized) { initialized = 1; mac_dsn = random_rand() & 0xff; } /* Build the FCF. */ params.fcf.frame_type = packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE); params.fcf.frame_pending = packetbuf_attr(PACKETBUF_ATTR_PENDING); if(packetbuf_holds_broadcast()) { params.fcf.ack_required = 0; } else { params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_MAC_ACK); } params.fcf.panid_compression = 0; /* Insert IEEE 802.15.4 (2006) version bits. */ params.fcf.frame_version = FRAME802154_IEEE802154_2006; #if LLSEC802154_SECURITY if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) { params.fcf.security_enabled = 1; } /* Setting security-related attributes */ params.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL); params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1); params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3); #if LLSEC802154_USES_EXPLICIT_KEYS params.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE); params.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX); params.aux_hdr.key_source.u16[0] = packetbuf_attr(PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1); #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ #endif /* LLSEC802154_SECURITY */ /* Increment and set the data sequence number. */ if(!do_create) { /* Only length calculation - no sequence number is needed and should not be consumed. */ } else if(packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) { params.seq = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO); } else { /* Ensure that the sequence number 0 is not used as it would bypass the above check. */ if(mac_dsn == 0) { mac_dsn++; } params.seq = mac_dsn++; packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, params.seq); } /* Complete the addressing fields. */ /** \todo For phase 1 the addresses are all long. We'll need a mechanism in the rime attributes to tell the mac to use long or short for phase 2. */ if(LINKADDR_SIZE == 2) { /* Use short address mode if linkaddr size is short. */ params.fcf.src_addr_mode = FRAME802154_SHORTADDRMODE; } else { params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE; } params.dest_pid = mac_dst_pan_id; if(packetbuf_holds_broadcast()) { /* Broadcast requires short address mode. */ params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr[0] = 0xFF; params.dest_addr[1] = 0xFF; } else { linkaddr_copy((linkaddr_t *)¶ms.dest_addr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); /* Use short address mode if linkaddr size is small */ if(LINKADDR_SIZE == 2) { params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; } else { params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE; } } /* Set the source PAN ID to the global variable. */ params.src_pid = mac_src_pan_id; /* * Set up the source address using only the long address mode for * phase 1. */ linkaddr_copy((linkaddr_t *)¶ms.src_addr, packetbuf_addr(PACKETBUF_ADDR_SENDER)); params.payload = packetbuf_dataptr(); params.payload_len = packetbuf_datalen(); hdr_len = frame802154_hdrlen(¶ms); if(!do_create) { /* Only calculate header length */ return hdr_len; } else if(packetbuf_hdralloc(hdr_len)) { frame802154_create(¶ms, packetbuf_hdrptr()); PRINTF("15.4-OUT: %2X", params.fcf.frame_type); PRINTADDR(params.dest_addr); PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen()); return hdr_len; } else { PRINTF("15.4-OUT: too large header: %u\n", hdr_len); return FRAMER_FAILED; } }
/*---------------------------------------------------------------------------*/ static int create(void) { frame802154_t params; int len; /* init to zeros */ memset(¶ms, 0, sizeof(params)); if(!initialized) { initialized = 1; mac_dsn = random_rand() & 0xff; } /* Build the FCF. */ params.fcf.frame_type = FRAME802154_DATAFRAME; params.fcf.security_enabled = 0; params.fcf.frame_pending = packetbuf_attr(PACKETBUF_ATTR_PENDING); if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null)) { params.fcf.ack_required = 0; } else { params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_MAC_ACK); } params.fcf.panid_compression = 0; /* Insert IEEE 802.15.4 (2003) version bit. */ params.fcf.frame_version = FRAME802154_IEEE802154_2003; /* Increment and set the data sequence number. */ if(packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) { params.seq = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO); } else { params.seq = mac_dsn++; packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, params.seq); } /* params.seq = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); */ /* Complete the addressing fields. */ /** \todo For phase 1 the addresses are all long. We'll need a mechanism in the rime attributes to tell the mac to use long or short for phase 2. */ if(sizeof(linkaddr_t) == 2) { /* Use short address mode if linkaddr size is short. */ params.fcf.src_addr_mode = FRAME802154_SHORTADDRMODE; } else { params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE; } params.dest_pid = mac_dst_pan_id; /* * If the output address is NULL in the Rime buf, then it is broadcast * on the 802.15.4 network. */ if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null)) { /* Broadcast requires short address mode. */ params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr[0] = 0xFF; params.dest_addr[1] = 0xFF; } else { linkaddr_copy((linkaddr_t *)¶ms.dest_addr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); /* Use short address mode if linkaddr size is small */ if(sizeof(linkaddr_t) == 2) { params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; } else { params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE; } } /* Set the source PAN ID to the global variable. */ params.src_pid = mac_src_pan_id; /* * Set up the source address using only the long address mode for * phase 1. */ linkaddr_copy((linkaddr_t *)¶ms.src_addr, &linkaddr_node_addr); params.payload = packetbuf_dataptr(); params.payload_len = packetbuf_datalen(); len = frame802154_hdrlen(¶ms); if(packetbuf_hdralloc(len)) { frame802154_create(¶ms, packetbuf_hdrptr(), len); PRINTF("15.4-OUT: %2X", params.fcf.frame_type); PRINTADDR(params.dest_addr); PRINTF("%d %u (%u)\n", len, packetbuf_datalen(), packetbuf_totlen()); return len; } else { PRINTF("15.4-OUT: too large header: %u\n", len); return FRAMER_FAILED; } }
/*---------------------------------------------------------------------------*/ static int send_packet(void) { frame802154_t params; uint8_t len; /* init to zeros */ memset(¶ms, 0, sizeof(params)); /* Build the FCF. */ params.fcf.frame_type = FRAME802154_DATAFRAME; params.fcf.security_enabled = 0; params.fcf.frame_pending = 0; params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_RELIABLE); params.fcf.panid_compression = 0; /* Insert IEEE 802.15.4 (2003) version bit. */ params.fcf.frame_version = FRAME802154_IEEE802154_2003; /* Increment and set the data sequence number. */ params.seq = mac_dsn++; /* Complete the addressing fields. */ /** \todo For phase 1 the addresses are all long. We'll need a mechanism in the rime attributes to tell the mac to use long or short for phase 2. */ params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE; params.dest_pid = mac_dst_pan_id; /* * If the output address is NULL in the Rime buf, then it is broadcast * on the 802.15.4 network. */ if(rimeaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &rimeaddr_null)) { /* Broadcast requires short address mode. */ params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr.u8[0] = 0xFF; params.dest_addr.u8[1] = 0xFF; } else { rimeaddr_copy(¶ms.dest_addr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE; } /* Set the source PAN ID to the global variable. */ params.src_pid = mac_src_pan_id; /* * Set up the source address using only the long address mode for * phase 1. */ rimeaddr_copy(¶ms.src_addr, &rimeaddr_node_addr); params.payload = packetbuf_dataptr(); params.payload_len = packetbuf_datalen(); len = frame802154_hdrlen(¶ms); PRINTF("payload=%s, len=%d, hdrlen=%d\n", params.payload, params.payload_len, len); if(packetbuf_hdralloc(len)) { frame802154_create(¶ms, packetbuf_hdrptr(), len); //PRINTF("6MAC-UT: %2X\n", params.fcf.frame_type); PRINTADDR(params.dest_addr.u8); //PRINTF("%u %u (%u)\n", len, packetbuf_datalen(), packetbuf_totlen()); return radio->send(packetbuf_hdrptr(), packetbuf_totlen()); } else { PRINTF("6MAC-UT: too large header: %u\n", len); } return 0; }
/* 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; }
/*---------------------------------------------------------------------------*/ static uint8_t send_packet(struct net_buf *buf, mac_callback_t sent, void *ptr) { frame802154_t params; uint8_t len; uint8_t ret = 0; /* init to zeros */ memset(¶ms, 0, sizeof(params)); /* Build the FCF. */ params.fcf.frame_type = FRAME802154_DATAFRAME; params.fcf.security_enabled = 0; params.fcf.frame_pending = 0; params.fcf.ack_required = packetbuf_attr(buf, PACKETBUF_ATTR_RELIABLE); params.fcf.panid_compression = 0; /* Insert IEEE 802.15.4 (2003) version bit. */ params.fcf.frame_version = FRAME802154_IEEE802154_2003; /* Increment and set the data sequence number. */ params.seq = mac_dsn++; /* Complete the addressing fields. */ /** \todo For phase 1 the addresses are all long. We'll need a mechanism in the rime attributes to tell the mac to use long or short for phase 2. */ params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE; params.dest_pid = mac_dst_pan_id; if(packetbuf_holds_broadcast(buf)) { /* Broadcast requires short address mode. */ params.fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; params.dest_addr[0] = 0xFF; params.dest_addr[1] = 0xFF; } else { linkaddr_copy((linkaddr_t *)¶ms.dest_addr, packetbuf_addr(buf, PACKETBUF_ADDR_RECEIVER)); params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE; } /* Set the source PAN ID to the global variable. */ params.src_pid = mac_src_pan_id; /* * Set up the source address using only the long address mode for * phase 1. */ #if NETSTACK_CONF_BRIDGE_MODE linkaddr_copy((linkaddr_t *)¶ms.src_addr,packetbuf_addr(PACKETBUF_ADDR_SENDER)); #else linkaddr_copy((linkaddr_t *)¶ms.src_addr, &linkaddr_node_addr); #endif params.payload = packetbuf_dataptr(buf); params.payload_len = packetbuf_datalen(buf); len = frame802154_hdrlen(¶ms); if(packetbuf_hdralloc(buf, len)) { frame802154_create(¶ms, packetbuf_hdrptr(buf), len); PRINTF("6MAC-UT: type %X dest ", params.fcf.frame_type); PRINTLLADDR((uip_lladdr_t *)params.dest_addr); PRINTF(" len %u datalen %u (totlen %u)\n", len, packetbuf_datalen(buf), packetbuf_totlen(buf)); ret = NETSTACK_RADIO.send(buf, packetbuf_hdrptr(buf), packetbuf_totlen(buf)); if(sent) { switch(ret) { case RADIO_TX_OK: sent(buf, ptr, MAC_TX_OK, 1); break; case RADIO_TX_ERR: sent(buf, ptr, MAC_TX_ERR, 1); break; case RADIO_TX_COLLISION: sent(buf, ptr, MAC_TX_COLLISION, 1); break; } } } else { PRINTF("6MAC-UT: too large header: %u\n", len); } return ret; }
/* Function to send beacon */ extern void mac_send_beacon() { static uint16_t macBSN = 0x00; uint8_t payload[10] = {0,0,0,0,0,0,0,0,0,0}; frame802154_t params; static frame802154_beacon_t beaconData; uint8_t len; /* init to zeros */ memset(¶ms, 0, sizeof(params)); memset(&beaconData, 0, sizeof(frame802154_beacon_t)); /* Build the FCF. */ params.fcf.frame_type = FRAME802154_BEACONFRAME; params.fcf.security_enabled = 0; params.fcf.frame_pending = 0; params.fcf.ack_required = 0; params.fcf.panid_compression = 0; /* Insert IEEE 802.15.4 (2003) version bit. */ params.fcf.frame_version = FRAME802154_IEEE802154_2003; /* Increment and set the beacon sequence number. */ params.seq = macBSN++; /* Complete the addressing fields. */ /** \todo For phase 1 the addresses are all long. We'll need a mechanism in the rime attributes to tell the mac to use long or short for phase 2. */ params.fcf.src_addr_mode = FRAME802154_LONGADDRMODE; /* Set the source PAN ID to the PAN ID as per spec. */ params.src_pid = mac_dst_pan_id; params.fcf.dest_addr_mode = FRAME802154_NOADDR; params.dest_pid = 0; // params.dest_addr[0] = 0xFF; // params.dest_addr[1] = 0xFF; //rimeaddr_copy((rimeaddr_t *)¶ms.dest_addr,\ packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); /* * Set up the source address using only the long address mode for * phase 1. */ rimeaddr_copy((rimeaddr_t *)¶ms.src_addr, &rimeaddr_node_addr); rimeaddr_copy((rimeaddr_t *)¶ms.dest_addr, &rimeaddr_null); /* Preparing the payload for beacon*/ beaconData.superFrSpec |= 0x000F; /* BO set to 15 */ beaconData.superFrSpec |= 0x00F0; /* SO set to 15 */ beaconData.superFrSpec |= 0x0F00; /* CAP lt:No relevance in beacon less */ beaconData.superFrSpec |= BV(14); /* PAN coordinator */ beaconData.superFrSpec |= BV(15); /* Association permitted */ beaconData.gtsInfo.gtsSpec = 0; /* If 0, direction and list are absent*/ beaconData.pendAddrInfo.pendAddrSpec = 0; /* If 0, no list present*/ packetbuf_clear(); len = frame802154_packBeacon((uint8_t*)packetbuf_dataptr(),&beaconData); packetbuf_set_datalen(len); params.payload = packetbuf_dataptr(); len = frame802154_hdrlen(¶ms); frame802154_create(¶ms, packetbuf_hdrptr(), len); NETSTACK_RADIO.send(packetbuf_hdrptr(), packetbuf_totlen()); return; }