/*---------------------------------------------------------------------------*/ 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++); } }
/* 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; }
/*---------------------------------------------------------------------------*/ 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; }
params.fcf.dest_addr_mode = FRAME802154_LONGADDRMODE; params.dest_pid = mac_dst_pan_id; /* * 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_panCoord_addr); /* Preparing the payload for ASSOC REQ */ // Filling the last two bytes, reserving the earlier bytes for hdr payload[8] = MAC_ASSOC_REQ; // Filling capability Info byte // From Bit 7 to 0: // PAN Coord, FFD, Pwr Src, Rx always on, Res, Sec, 16bit address payload[9] |= 0x0; params.payload = &payload[8]; params.payload_len = 2; len = frame802154_hdrlen(¶ms); if(len <= 8) { frame802154_create(¶ms, &payload[8-len], len); NETSTACK_RADIO.send(&payload[8-len], len+2); return(0); // success } else { //PRINTF("6MAC-UT: too large header: %u\n", len); } return(1); // failure #endif