void udprand_task(){ OpenQueueEntry_t* pkt; // don't run if not synch if (ieee154e_isSynch() == FALSE) return; // don't run on dagroot if (idmanager_getIsDAGroot()) { opentimers_stop(udprand_vars.timerId); return; } //prepare packet pkt = openqueue_getFreePacketBuffer(COMPONENT_UDPRAND); if (pkt==NULL) { openserial_printError(COMPONENT_UDPRAND,ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0); return; } pkt->creator = COMPONENT_UDPRAND; pkt->owner = COMPONENT_UDPRAND; pkt->l4_protocol = IANA_UDP; pkt->l4_sourcePortORicmpv6Type = WKP_UDP_RAND; pkt->l4_destination_port = WKP_UDP_RAND; pkt->l3_destinationAdd.type = ADDR_128B; memcpy(&pkt->l3_destinationAdd.addr_128b[0],&ipAddr_motedata,16); packetfunctions_reserveHeaderSize(pkt,2); ((uint8_t*)pkt->payload)[0] = openrandom_get16b()%0xff; ((uint8_t*)pkt->payload)[1] = openrandom_get16b()%0xff; //send packet if ((openudp_send(pkt))==E_FAIL) { openqueue_freePacketBuffer(pkt); } }
/** \brief Request a new (free) packet buffer. Component throughout the protocol stack can call this function is they want to get a new packet buffer to start creating a new packet. \note Once a packet has been allocated, it is up to the creator of the packet to free it using the openqueue_freePacketBuffer() function. \returns A pointer to the queue entry when it could be allocated, or NULL when it could not be allocated (buffer full or not synchronized). */ OpenQueueEntry_t* openqueue_getFreePacketBuffer(uint8_t creator) { uint8_t i; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); // refuse to allocate if we're not in sync if (ieee154e_isSynch()==FALSE && creator > COMPONENT_IEEE802154E){ ENABLE_INTERRUPTS(); return NULL; } // if you get here, I will try to allocate a buffer for you // walk through queue and find free entry for (i=0;i<QUEUELENGTH;i++) { if (openqueue_vars.queue[i].owner==COMPONENT_NULL) { openqueue_vars.queue[i].creator=creator; openqueue_vars.queue[i].owner=COMPONENT_OPENQUEUE; ENABLE_INTERRUPTS(); return &openqueue_vars.queue[i]; } } ENABLE_INTERRUPTS(); return NULL; }
/** \brief Calculated how many slots have elapsed since last synchronized. \param[in] timeCorrection time to be corrected \param[in] timesource The address of neighbor. \return the number of slots */ void adaptive_sync_preprocess(int16_t timeCorrection, open_addr_t timesource){ uint8_t array[5]; // stop calculating compensation period when compensateThreshold exceeds KATIMEOUT and drift is not changed if( adaptive_sync_vars.compensateThreshold > MAXKAPERIOD && adaptive_sync_vars.driftChanged == FALSE ) { if(timeCorrection > LIMITLARGETIMECORRECTION) { //once I get a large time correction, it means previous calcluated drift is not accurate yet. The clock drift is changed. adaptive_sync_driftChanged(); } return; } // check whether I am synchronized and also check whether it's the same neighbor synchronized to last time? if( adaptive_sync_vars.driftChanged == FALSE && ieee154e_isSynch() && packetfunctions_sameAddress(×ource, &(adaptive_sync_vars.compensationInfo_vars.neighborID)) ) { // only calcluate when asnDiff > compensateThresholdThreshold. (this is used for guaranteeing accuracy ) if(ieee154e_asnDiff(&adaptive_sync_vars.oldASN) > adaptive_sync_vars.compensateThreshold) { // calculate compensation interval adaptive_sync_calculateCompensatedSlots(timeCorrection); // reset compensationtTicks and sumOfTC after calculation adaptive_sync_vars.compensateTicks = 0; adaptive_sync_vars.sumOfTC = 0; // update threshold adaptive_sync_vars.compensateThreshold *= 2; sixtop_setKaPeriod(adaptive_sync_vars.compensateThreshold); // update oldASN ieee154e_getAsn(array); adaptive_sync_vars.oldASN.bytes0and1 = ((uint16_t) array[1] << 8) | ((uint16_t) array[0]); adaptive_sync_vars.oldASN.bytes2and3 = ((uint16_t) array[3] << 8) | ((uint16_t) array[2]); adaptive_sync_vars.oldASN.byte4 = array[4]; } else { // record the timeCorrection, if not calculate. adaptive_sync_vars.sumOfTC += timeCorrection; } } else { adaptive_sync_vars.compensateThreshold = BASIC_COMPENSATION_THRESHOLD; sixtop_setKaPeriod(adaptive_sync_vars.compensateThreshold); // when I joined the network, or changed my time parent, reset adaptive_sync relative variables adaptive_sync_vars.clockState = S_NONE; adaptive_sync_vars.elapsedSlots = 0; adaptive_sync_vars.compensationTimeout = 0; adaptive_sync_vars.compensateTicks = 0; adaptive_sync_vars.sumOfTC = 0; // update oldASN ieee154e_getAsn(array); adaptive_sync_vars.oldASN.bytes0and1 = ((uint16_t) array[1] << 8) | ((uint16_t) array[0]); adaptive_sync_vars.oldASN.bytes2and3 = ((uint16_t) array[3] << 8) | ((uint16_t) array[2]); adaptive_sync_vars.oldASN.byte4 = array[4]; // record this neighbor as my time source memcpy(&(adaptive_sync_vars.compensationInfo_vars.neighborID), ×ource, sizeof(open_addr_t)); } }
/** \brief Send an keep-alive message, if necessary. This is one of the MAC management tasks. This function inlines in the timers_res_fired() function, but is declared as a separate function for better readability of the code. */ port_INLINE void sixtop_sendKA() { OpenQueueEntry_t* kaPkt; open_addr_t* kaNeighAddr; if (ieee154e_isSynch()==FALSE) { // I'm not sync'ed // delete packets genereted by this module (ADV and KA) from openqueue openqueue_removeAllCreatedBy(COMPONENT_SIXTOP); // I'm now busy sending a KA sixtop_vars.busySendingKA = FALSE; // stop here return; } if (sixtop_vars.busySendingKA==TRUE) { // don't proceed if I'm still sending a KA return; } kaNeighAddr = neighbors_getKANeighbor(sixtop_vars.kaPeriod); if (kaNeighAddr==NULL) { // don't proceed if I have no neighbor I need to send a KA to return; } // if I get here, I will send a KA // get a free packet buffer kaPkt = openqueue_getFreePacketBuffer(COMPONENT_SIXTOP); if (kaPkt==NULL) { openserial_printError(COMPONENT_SIXTOP,ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)1, (errorparameter_t)0); return; } // declare ownership over that packet kaPkt->creator = COMPONENT_SIXTOP; kaPkt->owner = COMPONENT_SIXTOP; // some l2 information about this packet kaPkt->l2_frameType = IEEE154_TYPE_DATA; memcpy(&(kaPkt->l2_nextORpreviousHop),kaNeighAddr,sizeof(open_addr_t)); // put in queue for MAC to handle sixtop_send_internal(kaPkt,IEEE154_IELIST_NO,IEEE154_FRAMEVERSION_2006); // I'm now busy sending a KA sixtop_vars.busySendingKA = TRUE; #ifdef OPENSIM debugpins_ka_set(); debugpins_ka_clr(); #endif }
void macpong_initSend(void) { if (idmanager_getIsDAGroot()==TRUE) { return; } if (ieee154e_isSynch()==TRUE && neighbors_getNumNeighbors()==1) { // send packet //poipoimacpong_send(0); // cancel timer opentimers_stop(macpong_vars.timerId); } }
/** \brief Request a new (free) packet buffer. Component throughout the protocol stack can call this function is they want to get a new packet buffer to start creating a new packet. \note Once a packet has been allocated, it is up to the creator of the packet to free it using the openqueue_freePacketBuffer() function. \returns A pointer to the queue entry when it could be allocated, or NULL when it could not be allocated (buffer full or not synchronized). */ OpenQueueEntry_t* openqueue_getFreePacketBuffer(uint8_t creator) { uint8_t i; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); // refuse to allocate if we're not in sync if (ieee154e_isSynch()==FALSE && creator > COMPONENT_IEEE802154E){ ENABLE_INTERRUPTS(); return NULL; } // if you get here, I will try to allocate a buffer for you // walk through queue and find free entry for (i=0;i<QUEUELENGTH;i++) { if (openqueue_vars.queue[i].owner==COMPONENT_NULL) { openqueue_vars.queue[i].creator=creator; openqueue_vars.queue[i].owner=COMPONENT_OPENQUEUE; ENABLE_INTERRUPTS(); #if ((ENABLE_DEBUG_RFF ==1) && (DBG_OPENQUEUE == 1)) { uint8_t *pucAux = (uint8_t *) &openqueue_vars.queue[i]; uint8_t pos=0; rffbuf[pos++]= RFF_OPENQUEUE_ALLOC; rffbuf[pos++]= 0x01; rffbuf[pos++]= creator; rffbuf[pos++]= i; rffbuf[pos++]= pucAux++; rffbuf[pos++]= pucAux++; rffbuf[pos++]= pucAux++; rffbuf[pos++]= pucAux; openserial_printStatus(STATUS_RFF,(uint8_t*)&rffbuf,pos); } #endif return &openqueue_vars.queue[i]; } } ENABLE_INTERRUPTS(); return NULL; }
void uinject_task_cb() { OpenQueueEntry_t* pkt; // don't run if not synch if (ieee154e_isSynch() == FALSE) return; // don't run on dagroot if (idmanager_getIsDAGroot()) { opentimers_stop(uinject_vars.timerId); return; } // if you get here, send a packet // get a free packet buffer pkt = openqueue_getFreePacketBuffer(COMPONENT_UINJECT); if (pkt==NULL) { openserial_printError( COMPONENT_UINJECT, ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0 ); return; } pkt->owner = COMPONENT_UINJECT; pkt->creator = COMPONENT_UINJECT; pkt->l4_protocol = IANA_UDP; pkt->l4_destination_port = WKP_UDP_INJECT; pkt->l4_sourcePortORicmpv6Type = WKP_UDP_INJECT; pkt->l3_destinationAdd.type = ADDR_128B; memcpy(&pkt->l3_destinationAdd.addr_128b[0],uinject_dst_addr,16); packetfunctions_reserveHeaderSize(pkt,sizeof(uint16_t)); *((uint16_t*)&pkt->payload[0]) = uinject_vars.counter++; if ((openudp_send(pkt))==E_FAIL) { openqueue_freePacketBuffer(pkt); } }
OpenQueueEntry_t* openqueue_getFreePacketBuffer(uint8_t creator) { uint8_t i; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); //enable only allocation of free buffers to MAC layer in case we are not sync if (ieee154e_isSynch()==FALSE && creator > COMPONENT_IEEE802154E){ ENABLE_INTERRUPTS(); return NULL; } //in synch or mac layer request for (i=0;i<QUEUELENGTH;i++) { if (openqueue_vars.queue[i].owner==COMPONENT_NULL) { openqueue_vars.queue[i].owner=COMPONENT_OPENQUEUE; openqueue_vars.queue[i].creator=creator; ENABLE_INTERRUPTS(); return &openqueue_vars.queue[i]; } } ENABLE_INTERRUPTS(); return NULL; }
/** \brief Prepare and a send a RPL DAO. */ void sendDAO() { OpenQueueEntry_t* msg; // pointer to DAO messages uint8_t nbrIdx; // running neighbor index uint8_t numTransitParents,numTargetParents; // the number of parents indicated in transit option open_addr_t address; open_addr_t* prefix; if (ieee154e_isSynch()==FALSE) { // I'm not sync'ed // delete packets genereted by this module (DIO and DAO) from openqueue openqueue_removeAllCreatedBy(COMPONENT_ICMPv6RPL); // I'm not busy sending a DIO/DAO icmpv6rpl_vars.busySending = FALSE; // stop here return; } // dont' send a DAO if you're in bridge mode if (idmanager_getIsBridge()==TRUE) { return; } // dont' send a DAO if you did not acquire a DAGrank if (neighbors_getMyDAGrank()==DEFAULTDAGRANK) { return; } // dont' send a DAO if you're still busy sending the previous one if (icmpv6rpl_vars.busySending==TRUE) { return; } // if you get here, you start construct DAO // reserve a free packet buffer for DAO msg = openqueue_getFreePacketBuffer(COMPONENT_ICMPv6RPL); if (msg==NULL) { openserial_printError(COMPONENT_ICMPv6RPL,ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0); return; } // take ownership msg->creator = COMPONENT_ICMPv6RPL; msg->owner = COMPONENT_ICMPv6RPL; // set transport information msg->l4_protocol = IANA_ICMPv6; msg->l4_sourcePortORicmpv6Type = IANA_ICMPv6_RPL; // set DAO destination msg->l3_destinationAdd.type=ADDR_128B; memcpy(msg->l3_destinationAdd.addr_128b,icmpv6rpl_vars.dio.DODAGID,sizeof(icmpv6rpl_vars.dio.DODAGID)); //===== fill in packet //NOTE: limit to preferrred parent only the number of DAO transit addresses to send //=== transit option -- from RFC 6550, page 55 - 1 transit information header per parent is required. //getting only preferred parent as transit numTransitParents=0; neighbors_getPreferredParentEui64(&address); packetfunctions_writeAddress(msg,&address,OW_BIG_ENDIAN); prefix=idmanager_getMyID(ADDR_PREFIX); packetfunctions_writeAddress(msg,prefix,OW_BIG_ENDIAN); // update transit info fields // from rfc6550 p.55 -- Variable, depending on whether or not the DODAG ParentAddress subfield is present. // poipoi xv: it is not very clear if this includes all fields in the header. or as target info 2 bytes are removed. // using the same pattern as in target information. icmpv6rpl_vars.dao_transit.optionLength = LENGTH_ADDR128b + sizeof(icmpv6rpl_dao_transit_ht)-2; icmpv6rpl_vars.dao_transit.PathControl=0; //todo. this is to set the preference of this parent. icmpv6rpl_vars.dao_transit.type=OPTION_TRANSIT_INFORMATION_TYPE; // write transit info in packet packetfunctions_reserveHeaderSize(msg,sizeof(icmpv6rpl_dao_transit_ht)); memcpy( ((icmpv6rpl_dao_transit_ht*)(msg->payload)), &(icmpv6rpl_vars.dao_transit), sizeof(icmpv6rpl_dao_transit_ht) ); numTransitParents++; //target information is required. RFC 6550 page 55. /* One or more Transit Information options MUST be preceded by one or more RPL Target options. */ numTargetParents = 0; for (nbrIdx=0;nbrIdx<MAXNUMNEIGHBORS;nbrIdx++) { if ((neighbors_isNeighborWithHigherDAGrank(nbrIdx))==TRUE) { // this neighbor is of higher DAGrank as I am. so it is my child // write it's address in DAO RFC6550 page 80 check point 1. neighbors_getNeighbor(&address,ADDR_64B,nbrIdx); packetfunctions_writeAddress(msg,&address,OW_BIG_ENDIAN); prefix=idmanager_getMyID(ADDR_PREFIX); packetfunctions_writeAddress(msg,prefix,OW_BIG_ENDIAN); // update target info fields // from rfc6550 p.55 -- Variable, length of the option in octets excluding the Type and Length fields. // poipoi xv: assuming that type and length fields refer to the 2 first bytes of the header icmpv6rpl_vars.dao_target.optionLength = LENGTH_ADDR128b +sizeof(icmpv6rpl_dao_target_ht) - 2; //no header type and length icmpv6rpl_vars.dao_target.type = OPTION_TARGET_INFORMATION_TYPE; icmpv6rpl_vars.dao_target.flags = 0; //must be 0 icmpv6rpl_vars.dao_target.prefixLength = 128; //128 leading bits -- full address. // write transit info in packet packetfunctions_reserveHeaderSize(msg,sizeof(icmpv6rpl_dao_target_ht)); memcpy( ((icmpv6rpl_dao_target_ht*)(msg->payload)), &(icmpv6rpl_vars.dao_target), sizeof(icmpv6rpl_dao_target_ht) ); // remember I found it numTargetParents++; } //limit to MAX_TARGET_PARENTS the number of DAO target addresses to send //section 8.2.1 pag 67 RFC6550 -- using a subset // poipoi TODO base selection on ETX rather than first X. if (numTargetParents>=MAX_TARGET_PARENTS) break; } // stop here if no parents found if (numTransitParents==0) { openqueue_freePacketBuffer(msg); return; } icmpv6rpl_vars.dao_transit.PathSequence++; //increment path sequence. // if you get here, you will send a DAO //=== DAO header packetfunctions_reserveHeaderSize(msg,sizeof(icmpv6rpl_dao_ht)); memcpy( ((icmpv6rpl_dao_ht*)(msg->payload)), &(icmpv6rpl_vars.dao), sizeof(icmpv6rpl_dao_ht) ); //=== ICMPv6 header packetfunctions_reserveHeaderSize(msg,sizeof(ICMPv6_ht)); ((ICMPv6_ht*)(msg->payload))->type = msg->l4_sourcePortORicmpv6Type; ((ICMPv6_ht*)(msg->payload))->code = IANA_ICMPv6_RPL_DAO; packetfunctions_calculateChecksum(msg,(uint8_t*)&(((ICMPv6_ht*)(msg->payload))->checksum)); //call last //===== send if (icmpv6_send(msg)==E_SUCCESS) { icmpv6rpl_vars.busySending = TRUE; } else { openqueue_freePacketBuffer(msg); } }
/** \brief Prepare and a send a RPL DIO. */ void sendDIO() { OpenQueueEntry_t* msg; // stop if I'm not sync'ed if (ieee154e_isSynch()==FALSE) { // remove packets genereted by this module (DIO and DAO) from openqueue openqueue_removeAllCreatedBy(COMPONENT_ICMPv6RPL); // I'm not busy sending a DIO/DAO icmpv6rpl_vars.busySending = FALSE; // stop here return; } // do not send DIO if I'm in in bridge mode if (idmanager_getIsBridge()==TRUE) { return; } // do not send DIO if I have the default DAG rank if (neighbors_getMyDAGrank()==DEFAULTDAGRANK) { return; } // do not send DIO if I'm already busy sending if (icmpv6rpl_vars.busySending==TRUE) { return; } // if you get here, all good to send a DIO // I'm now busy sending icmpv6rpl_vars.busySending = TRUE; // reserve a free packet buffer for DIO msg = openqueue_getFreePacketBuffer(COMPONENT_ICMPv6RPL); if (msg==NULL) { openserial_printError(COMPONENT_ICMPv6RPL,ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0); icmpv6rpl_vars.busySending = FALSE; return; } // take ownership msg->creator = COMPONENT_ICMPv6RPL; msg->owner = COMPONENT_ICMPv6RPL; // set transport information msg->l4_protocol = IANA_ICMPv6; msg->l4_sourcePortORicmpv6Type = IANA_ICMPv6_RPL; // set DIO destination memcpy(&(msg->l3_destinationAdd),&icmpv6rpl_vars.dioDestination,sizeof(open_addr_t)); //===== DIO payload // note: DIO is already mostly populated icmpv6rpl_vars.dio.rank = neighbors_getMyDAGrank(); packetfunctions_reserveHeaderSize(msg,sizeof(icmpv6rpl_dio_ht)); memcpy( ((icmpv6rpl_dio_ht*)(msg->payload)), &(icmpv6rpl_vars.dio), sizeof(icmpv6rpl_dio_ht) ); //===== ICMPv6 header packetfunctions_reserveHeaderSize(msg,sizeof(ICMPv6_ht)); ((ICMPv6_ht*)(msg->payload))->type = msg->l4_sourcePortORicmpv6Type; ((ICMPv6_ht*)(msg->payload))->code = IANA_ICMPv6_RPL_DIO; packetfunctions_calculateChecksum(msg,(uint8_t*)&(((ICMPv6_ht*)(msg->payload))->checksum));//call last //send if (icmpv6_send(msg)!=E_SUCCESS) { icmpv6rpl_vars.busySending = FALSE; openqueue_freePacketBuffer(msg); } else { icmpv6rpl_vars.busySending = FALSE; } }
void cexample_task_cb() { OpenQueueEntry_t* pkt; owerror_t outcome; uint8_t numOptions; uint8_t i; uint16_t x_int = 0; uint16_t sum = 0; uint16_t avg = 0; uint8_t N_avg = 10; // don't run if not synch if (ieee154e_isSynch() == FALSE) return; // don't run on dagroot if (idmanager_getIsDAGroot()) { opentimers_stop(cexample_vars.timerId); return; } for (i = 0; i < N_avg; i++) { sum += x_int; } avg = sum/N_avg; // create a CoAP RD packet pkt = openqueue_getFreePacketBuffer(COMPONENT_CEXAMPLE); if (pkt==NULL) { openserial_printError( COMPONENT_CEXAMPLE, ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0 ); openqueue_freePacketBuffer(pkt); return; } // take ownership over that packet pkt->creator = COMPONENT_CEXAMPLE; pkt->owner = COMPONENT_CEXAMPLE; // CoAP payload packetfunctions_reserveHeaderSize(pkt,PAYLOADLEN); for (i=0;i<PAYLOADLEN;i++) { pkt->payload[i] = i; } avg = openrandom_get16b(); pkt->payload[0] = (avg>>8)&0xff; pkt->payload[1] = (avg>>0)&0xff; numOptions = 0; // location-path option packetfunctions_reserveHeaderSize(pkt,sizeof(cexample_path0)-1); memcpy(&pkt->payload[0],&cexample_path0,sizeof(cexample_path0)-1); packetfunctions_reserveHeaderSize(pkt,1); pkt->payload[0] = ((COAP_OPTION_NUM_URIPATH) << 4) | (sizeof(cexample_path0)-1); numOptions++; // content-type option packetfunctions_reserveHeaderSize(pkt,2); pkt->payload[0] = (COAP_OPTION_NUM_CONTENTFORMAT << 4) | 1; pkt->payload[1] = COAP_MEDTYPE_APPOCTETSTREAM; numOptions++; // metadata pkt->l4_destination_port = WKP_UDP_COAP; pkt->l3_destinationAdd.type = ADDR_128B; memcpy(&pkt->l3_destinationAdd.addr_128b[0],&ipAddr_motesEecs,16); // send outcome = opencoap_send( pkt, COAP_TYPE_NON, COAP_CODE_REQ_PUT, numOptions, &cexample_vars.desc ); // avoid overflowing the queue if fails if (outcome==E_FAIL) { openqueue_freePacketBuffer(pkt); } return; }
/** \brief Send an advertisement. This is one of the MAC management tasks. This function inlines in the timers_res_fired() function, but is declared as a separate function for better readability of the code. */ port_INLINE void sixtop_sendEB() { OpenQueueEntry_t* adv; uint8_t len; len = 0; if (ieee154e_isSynch()==FALSE) { // I'm not sync'ed // delete packets genereted by this module (ADV and KA) from openqueue openqueue_removeAllCreatedBy(COMPONENT_SIXTOP); // I'm now busy sending an ADV sixtop_vars.busySendingEB = FALSE; // stop here return; } if (sixtop_vars.busySendingEB==TRUE) { // don't continue if I'm still sending a previous ADV } // if I get here, I will send an ADV // get a free packet buffer adv = openqueue_getFreePacketBuffer(COMPONENT_SIXTOP); if (adv==NULL) { openserial_printError(COMPONENT_SIXTOP,ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0); return; } // declare ownership over that packet adv->creator = COMPONENT_SIXTOP; adv->owner = COMPONENT_SIXTOP; // reserve space for ADV-specific header // reserving for IEs. len += processIE_prependSlotframeLinkIE(adv); len += processIE_prependSyncIE(adv); //add IE header processIE_prependMLMEIE(adv,len); // some l2 information about this packet adv->l2_frameType = IEEE154_TYPE_BEACON; adv->l2_nextORpreviousHop.type = ADDR_16B; adv->l2_nextORpreviousHop.addr_16b[0] = 0xff; adv->l2_nextORpreviousHop.addr_16b[1] = 0xff; //I has an IE in my payload adv->l2_IEListPresent = IEEE154_IELIST_YES; // put in queue for MAC to handle sixtop_send_internal(adv,IEEE154_IELIST_YES,IEEE154_FRAMEVERSION); // I'm now busy sending an ADV sixtop_vars.busySendingEB = TRUE; }
void table_update_task_cb() { OpenQueueEntry_t* pkt; owerror_t outcome; // don't run if not synch if (ieee154e_isSynch() == FALSE ) return; // don't run on dagroot if (idmanager_getIsDAGroot()) { opentimers_stop(table_update_vars.timerId); return; } // create a CoAP RD packet pkt = openqueue_getFreePacketBuffer(COMPONENT_TABLE_UPDATE); if (pkt==NULL) { openserial_printError( COMPONENT_TABLE_UPDATE, ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0 ); openqueue_freePacketBuffer(pkt); return; } // take ownership over that packet pkt->creator = COMPONENT_TABLE_UPDATE; pkt->owner = COMPONENT_TABLE_UPDATE; // CoAP payload packetfunctions_reserveHeaderSize(pkt,PAYLOADLEN); //construct packet int index = 0; pkt->payload[index++] = 255;//1 pkt->payload[index++] = action;//2 //pkt->payload[index++] = count++; pkt->payload[index++] = i;//3 //used pkt->payload[index++] = tableEntry->neighborEntry.used;//4 //parentRef pkt->payload[index++] = tableEntry->neighborEntry.parentPreference;//5 //stableNeighbor pkt->payload[index++] = tableEntry->neighborEntry.stableNeighbor;//6 //switchStability pkt->payload[index++] = tableEntry->neighborEntry.switchStabilityCounter;//7 //address type pkt->payload[index++] = tableEntry->neighborEntry.addr_64b.type;//8 // the address itself open_addr_t addr =tableEntry->neighborEntry.addr_64b;//16 memcpy(&pkt->payload[index],&addr.addr_64b,8); index = index+8; //dagrank pkt->payload[index++] = tableEntry->neighborEntry.DAGrank;//17 //rssi pkt->payload[index] = tableEntry->neighborEntry.rssi;//19 index = index+2; //numRx pkt->payload[index++] = tableEntry->neighborEntry.numRx;//20 //numTx pkt->payload[index++] = tableEntry->neighborEntry.numTx;//21 //numTxACK pkt->payload[index++] = tableEntry->neighborEntry.numTxACK;//22 //numWraps pkt->payload[index++] = tableEntry->neighborEntry.numWraps;//23 //asn pkt->payload[index++] = tableEntry->neighborEntry.asn.byte4;//24 pkt->payload[index] = tableEntry->neighborEntry.asn.bytes2and3;//26 index = index+2; pkt->payload[index] = tableEntry->neighborEntry.asn.bytes0and1;//28 index = index+2; //joinPrio pkt->payload[index] = tableEntry->neighborEntry.joinPrio;//29 // metadata pkt->l4_destination_port = WKP_UDP_COAP; pkt->l3_destinationAdd.type = ADDR_128B; //uint8_t* DODAGID = get_icmpv6rpl_vars()->dio.DODAGID; uint8_t manager_full_address[16]; // retrieve my prefix and EUI64 memcpy(&manager_full_address[0],idmanager_getMyID(ADDR_PREFIX)->prefix,8); // prefix memcpy(&manager_full_address[8],&manager_address,8); // manager address memcpy(&pkt->l3_destinationAdd.addr_128b[0],&manager_full_address,16); //free some memory free(tableEntry); // send outcome = opencoap_send( pkt, COAP_TYPE_NON, COAP_CODE_RESP_CONTENT, 1, &table_update_vars.desc ); // avoid overflowing the queue if fails if (outcome==E_FAIL) { openqueue_freePacketBuffer(pkt); } return; }
void light_receive_data(OpenQueueEntry_t* pkt) { light_ht* rxPkt; uint8_t pkt_burstId; uint8_t pkt_pktId; uint8_t pkt_light_state; // handle the packet do { // abort if I'm not sync'ed if (ieee154e_isSynch()==FALSE) { break; } // abort if I'm the SENSOR node if (idmanager_getMyShortID()==SENSOR_ID) { break; } // take ownserhip over the packet pkt->owner = COMPONENT_LIGHT; // parse packet rxPkt = (light_ht*)pkt->payload; pkt_burstId = (rxPkt->light_info & 0xf0)>>4; pkt_pktId = (rxPkt->light_info & 0x07)>>1; pkt_light_state = (rxPkt->light_info & 0x01)>>0; // filter burstID if (pkt_burstId!=light_vars.burstId) { if ( ((pkt_burstId-light_vars.burstId)&0x0f) <=7) { // new burstID // reset pktIDMap light_vars.pktIDMap = 0x00; // remove old packets from queue // TODO Fix #17 } else { // old burstID // abort break; } } // abort if this is a pktId I already sent if ( light_vars.pktIDMap & (1<<pkt_pktId) ) { // already sent break; } else { // remember I sent that one light_vars.pktIDMap |= (1<<pkt_pktId); } //== if I get here, I accept the data packet if (light_vars.burstId!=pkt_burstId) { // record number of missed bursts while (light_vars.burstId!=pkt_burstId) { light_vars.burstId = (light_vars.burstId+1)%16; light_vars.numMissedBursts++; } light_vars.numMissedBursts--; // update the light state light_update_light_state(pkt_light_state); } //=== if I get here, light_vars.burstId==pkt_burstId // retransmit packet if (idmanager_getMyShortID()!=SINK_ID) { light_send_one_packet(pkt_pktId); } } while(0); // free the packet openqueue_freePacketBuffer(pkt); }