void idmanager_triggerAboutRoot() { uint8_t number_bytes_from_input_buffer; uint8_t input_buffer; // get command from OpenSerial number_bytes_from_input_buffer = openserial_getInputBuffer(&input_buffer,sizeof(input_buffer)); if (number_bytes_from_input_buffer!=sizeof(input_buffer)) { openserial_printError(COMPONENT_IDMANAGER,ERR_INPUTBUFFER_LENGTH, (errorparameter_t)number_bytes_from_input_buffer, (errorparameter_t)0); return; }; // handle command switch (input_buffer) { case ACTION_YES: idmanager_setIsDAGroot(TRUE); break; case ACTION_NO: idmanager_setIsDAGroot(FALSE); break; case ACTION_TOGGLE: if (idmanager_getIsDAGroot()) { idmanager_setIsDAGroot(FALSE); } else { idmanager_setIsDAGroot(TRUE); } break; } return; }
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 Initialize csensors and registers opensensors resources. */ void csensors_init(void) { uint8_t i; uint8_t numSensors; // do not run if DAGroot if(idmanager_getIsDAGroot()==TRUE) return; opensensors_init(); memset(&csensors_vars,0,sizeof(csensors_vars_t)); csensors_vars.desc.path0len = sizeof(csensors_path0)-1; csensors_vars.desc.path0val = (uint8_t*)(&csensors_path0); csensors_vars.desc.path1len = 0; csensors_vars.desc.path1val = NULL; csensors_vars.desc.componentID = COMPONENT_CSENSORS; csensors_vars.desc.securityContext = NULL; csensors_vars.desc.discoverable = TRUE; csensors_vars.desc.callbackRx = &csensors_receive; csensors_vars.desc.callbackSendDone = &csensors_sendDone; // register with the CoAP module opencoap_register(&csensors_vars.desc); numSensors = opensensors_getNumSensors(); csensors_vars.cb_put = 0; csensors_vars.cb_get = 0; csensors_vars.numCsensors = 0; for(i=0;i<numSensors;i++) { csensors_vars.csensors_resource[i].timerId = MAX_NUM_TIMERS; csensors_vars.csensors_resource[i].period = 0; csensors_vars.csensors_resource[i].opensensors_resource = opensensors_getResource(i); csensors_register(&csensors_vars.csensors_resource[i]); csensors_vars.numCsensors++; } }
void udplatency_init() { //don't run on dagroot if (idmanager_getIsDAGroot()) return; udplatency_vars.timerId = opentimers_start(UDPLATENCYPERIOD, TIMER_PERIODIC,TIME_MS, udplatency_timer); }
void registerNewNeighbor(open_addr_t* address, int8_t rssi, asn_t* asnTimestamp) { uint8_t i,j; bool iHaveAPreferedParent; // filter errors if (address->type!=ADDR_64B) { openserial_printError(COMPONENT_NEIGHBORS,ERR_WRONG_ADDR_TYPE, (errorparameter_t)address->type, (errorparameter_t)2); return; } // add this neighbor if (isNeighbor(address)==FALSE) { i=0; while(i<MAXNUMNEIGHBORS) { if (neighbors_vars.neighbors[i].used==FALSE) { // add this neighbor neighbors_vars.neighbors[i].used = TRUE; neighbors_vars.neighbors[i].parentPreference = 0; //neighbors_vars.neighbors[i].stableNeighbor = FALSE; // poipoi: all new neighbors are consider stable neighbors_vars.neighbors[i].stableNeighbor = TRUE; neighbors_vars.neighbors[i].switchStabilityCounter = 0; memcpy(&neighbors_vars.neighbors[i].addr_64b, address, sizeof(open_addr_t)); neighbors_vars.neighbors[i].DAGrank = 0xffff; neighbors_vars.neighbors[i].rssi = rssi; neighbors_vars.neighbors[i].numRx = 1; neighbors_vars.neighbors[i].numTx = 0; neighbors_vars.neighbors[i].numTxACK = 0; memcpy(&neighbors_vars.neighbors[i].asn,asnTimestamp,sizeof(asn_t)); // do I already have a preferred parent ? iHaveAPreferedParent = FALSE; for (j=0;j<MAXNUMNEIGHBORS;j++) { if (neighbors_vars.neighbors[j].parentPreference==MAXPREFERENCE) { iHaveAPreferedParent = TRUE; } } // if I have none, and I'm not DAGroot, the new neighbor is my preferred if (iHaveAPreferedParent==FALSE && idmanager_getIsDAGroot()==FALSE) { neighbors_vars.neighbors[i].parentPreference = MAXPREFERENCE; } break; } i++; } if (i==MAXNUMNEIGHBORS) { openserial_printError(COMPONENT_NEIGHBORS,ERR_NEIGHBORS_FULL, (errorparameter_t)MAXNUMNEIGHBORS, (errorparameter_t)0); return; } } }
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); } }
void neighbors_init() { uint8_t i; for (i=0;i<MAXNUMNEIGHBORS;i++){ neighbors_vars.neighbors[i].used=FALSE; } if (idmanager_getIsDAGroot()==TRUE) { neighbors_vars.myDAGrank=0; } else { neighbors_vars.myDAGrank=0xffff; } }
/** \brief Initializes this module. */ void neighbors_init() { // clear module variables memset(&neighbors_vars,0,sizeof(neighbors_vars_t)); // set myDAGrank if (idmanager_getIsDAGroot()==TRUE) { neighbors_vars.myDAGrank=MINHOPRANKINCREASE; } else { neighbors_vars.myDAGrank=DEFAULTDAGRANK; } }
void openbridge_triggerData(void) { uint8_t input_buffer[136];//worst case: 8B of next hop + 128B of data OpenQueueEntry_t* pkt; uint8_t numDataBytes; numDataBytes = openserial_getNumDataBytes(); //poipoi xv //this is a temporal workaround as we are never supposed to get chunks of data //longer than input buffer size.. I assume that HDLC will solve that. // MAC header is 13B + 8 next hop so we cannot accept packets that are longer than 118B if (numDataBytes>(136 - 21) || numDataBytes<8){ //to prevent too short or too long serial frames to kill the stack openserial_printError(COMPONENT_OPENBRIDGE,ERR_INPUTBUFFER_LENGTH, (errorparameter_t)numDataBytes, (errorparameter_t)0); return; } //copying the buffer once we know it is not too big openserial_getInputBuffer(&(input_buffer[0]),numDataBytes); if (idmanager_getIsDAGroot()==TRUE && numDataBytes>0) { pkt = openqueue_getFreePacketBuffer(COMPONENT_OPENBRIDGE); if (pkt==NULL) { openserial_printError(COMPONENT_OPENBRIDGE,ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0); return; } //admin pkt->creator = COMPONENT_OPENBRIDGE; pkt->owner = COMPONENT_OPENBRIDGE; //l2 pkt->l2_nextORpreviousHop.type = ADDR_64B; memcpy(&(pkt->l2_nextORpreviousHop.addr_64b[0]),&(input_buffer[0]),8); //payload packetfunctions_reserveHeaderSize(pkt,numDataBytes-8); memcpy(pkt->payload,&(input_buffer[8]),numDataBytes-8); //this is to catch the too short packet. remove it after fw-103 is solved. if (numDataBytes<16){ openserial_printError(COMPONENT_OPENBRIDGE,ERR_INVALIDSERIALFRAME, (errorparameter_t)0, (errorparameter_t)0); } //send if ((iphc_sendFromBridge(pkt))==E_FAIL) { openqueue_freePacketBuffer(pkt); } } }
void idmanager_triggerAboutRoot() { uint8_t number_bytes_from_input_buffer; uint8_t input_buffer[9]; open_addr_t myPrefix; uint8_t dodagid[16]; //=== get command from OpenSerial number_bytes_from_input_buffer = openserial_getInputBuffer(input_buffer,sizeof(input_buffer)); if (number_bytes_from_input_buffer!=sizeof(input_buffer)) { openserial_printError(COMPONENT_IDMANAGER,ERR_INPUTBUFFER_LENGTH, (errorparameter_t)number_bytes_from_input_buffer, (errorparameter_t)0); return; }; //=== handle command // take action (byte 0) switch (input_buffer[0]) { case ACTION_YES: idmanager_setIsDAGroot(TRUE); break; case ACTION_NO: idmanager_setIsDAGroot(FALSE); break; case ACTION_TOGGLE: if (idmanager_getIsDAGroot()) { idmanager_setIsDAGroot(FALSE); } else { idmanager_setIsDAGroot(TRUE); } break; } // store prefix (bytes 1-8) myPrefix.type = ADDR_PREFIX; memcpy( myPrefix.prefix, &input_buffer[1], sizeof(myPrefix.prefix) ); idmanager_setMyID(&myPrefix); // indicate DODAGid to RPL memcpy(&dodagid[0],idmanager_vars.myPrefix.prefix,8); // prefix memcpy(&dodagid[8],idmanager_vars.my64bID.addr_64b,8); // eui64 icmpv6rpl_writeDODAGid(dodagid); return; }
/** \brief Update my DAG rank and neighbor preference. Call this function whenever some data is changed that could cause this mote's routing decisions to change. Examples are: - I received a DIO which updated by neighbor table. If this DIO indicated a very low DAGrank, I may want to change by routing parent. - I became a DAGroot, so my DAGrank should be 0. */ void neighbors_updateMyDAGrankAndNeighborPreference() { uint8_t i; uint16_t rankIncrease; uint32_t tentativeDAGrank; // 32-bit since is used to sum uint8_t prefParentIdx; bool prefParentFound; uint32_t rankIncreaseIntermediary; // stores intermediary results of rankIncrease calculation // if I'm a DAGroot, my DAGrank is always MINHOPRANKINCREASE if ((idmanager_getIsDAGroot())==TRUE) { // the dagrank is not set through setting command, set rank to MINHOPRANKINCREASE here neighbors_vars.myDAGrank=MINHOPRANKINCREASE; return; } // reset my DAG rank to max value. May be lowered below. neighbors_vars.myDAGrank = MAXDAGRANK; // by default, I haven't found a preferred parent prefParentFound = FALSE; prefParentIdx = 0; // loop through neighbor table, update myDAGrank for (i=0;i<MAXNUMNEIGHBORS;i++) { if (neighbors_vars.neighbors[i].used==TRUE) { // reset parent preference neighbors_vars.neighbors[i].parentPreference=0; // calculate link cost to this neighbor if (neighbors_vars.neighbors[i].numTxACK==0) { rankIncrease = DEFAULTLINKCOST*2*MINHOPRANKINCREASE; } else { //6TiSCH minimal draft using OF0 for rank computation rankIncreaseIntermediary = (((uint32_t)neighbors_vars.neighbors[i].numTx) << 10); rankIncreaseIntermediary = (rankIncreaseIntermediary * 2 * MINHOPRANKINCREASE) / ((uint32_t)neighbors_vars.neighbors[i].numTxACK); rankIncrease = (uint16_t)(rankIncreaseIntermediary >> 10); } // cast the uint16_t summands to avoid an overflow if DAGrank == 0xFFFF (MAXDAGRANK) tentativeDAGrank = (uint32_t)neighbors_vars.neighbors[i].DAGrank + (uint32_t)rankIncrease; if ( tentativeDAGrank<neighbors_vars.myDAGrank && tentativeDAGrank<MAXDAGRANK) { // found better parent, lower my DAGrank neighbors_vars.myDAGrank = tentativeDAGrank; prefParentFound = TRUE; prefParentIdx = i; } } }
void cwellknown_init() { if(idmanager_getIsDAGroot()==TRUE) return; // prepare the resource descriptor for the /.well-known/core path cwellknown_vars.desc.path0len = sizeof(cwellknown_path0)-1; cwellknown_vars.desc.path0val = (uint8_t*)(&cwellknown_path0); cwellknown_vars.desc.path1len = sizeof(cwellknown_path1)-1; cwellknown_vars.desc.path1val = (uint8_t*)(&cwellknown_path1); cwellknown_vars.desc.componentID = COMPONENT_CWELLKNOWN; cwellknown_vars.desc.discoverable = FALSE; cwellknown_vars.desc.callbackRx = &cwellknown_receive; cwellknown_vars.desc.callbackSendDone = &cwellknown_sendDone; opencoap_register(&cwellknown_vars.desc); }
/** \brief Initialize this module. */ void cinfo_init(OpenMote* self) { // do not run if DAGroot if( idmanager_getIsDAGroot(self)==TRUE) return; // prepare the resource descriptor for the /i path cinfo_vars.desc.path0len = sizeof(cinfo_path0)-1; cinfo_vars.desc.path0val = (uint8_t*)(&cinfo_path0); cinfo_vars.desc.path1len = 0; cinfo_vars.desc.path1val = NULL; cinfo_vars.desc.componentID = COMPONENT_CINFO; cinfo_vars.desc.callbackRx = &cinfo_receive; cinfo_vars.desc.callbackSendDone = &cinfo_sendDone; // register with the CoAP module opencoap_register(self, &cinfo_vars.desc); }
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); } }
//update neighbors_vars.myDAGrank and neighbor preference void neighbors_updateMyDAGrankAndNeighborPreference() { uint8_t i; uint8_t temp_linkCost; uint32_t temp_myTentativeDAGrank; //has to be 16bit so that the sum can be larger than 255 "CHANGED BY Ahmad to be 32 bits since the DAGrank is 16 bits now", so the sum will be >(0xFFFF) uint8_t temp_preferredParentRow=0; bool temp_preferredParentExists=FALSE; if ((idmanager_getIsDAGroot())==FALSE) { neighbors_vars.myDAGrank=0xffff; i=0; while(i<MAXNUMNEIGHBORS) { neighbors_vars.neighbors[i].parentPreference=0; //poipoi xv if (neighbors_vars.neighbors[i].used==TRUE /*&& neighbors_vars.neighbors[i].stableNeighbor==TRUE*/) { if (neighbors_vars.neighbors[i].numTxACK==0) { temp_linkCost=15; //TODO: evaluate using RSSI? } else { temp_linkCost=(uint8_t)((((float)neighbors_vars.neighbors[i].numTx)/((float)neighbors_vars.neighbors[i].numTxACK))*10.0); } temp_myTentativeDAGrank=neighbors_vars.neighbors[i].DAGrank+temp_linkCost; //poipoi xv -- avoiding dynamic routing... if (idmanager_getIsDAGroot()==FALSE && temp_myTentativeDAGrank<neighbors_vars.myDAGrank && temp_myTentativeDAGrank<0xffff) { neighbors_vars.myDAGrank=temp_myTentativeDAGrank; temp_preferredParentExists=TRUE; temp_preferredParentRow=i; } //the following is equivalent to manual routing #ifdef FORCE_MULTIHOP #ifdef GINA_FORCE_MULTIHOP // below to enforce the routing switch ((idmanager_getMyID(ADDR_64B))->addr_64b[7]) { case 0x9B: if (neighbors_vars.neighbors[i].addr_64b.addr_64b[7]==0xDC) { neighbors_vars.myDAGrank=neighbors_vars.neighbors[i].DAGrank+temp_linkCost; temp_preferredParentExists=TRUE; temp_preferredParentRow=i; } break; case 0xDC: if (neighbors_vars.neighbors[i].addr_64b.addr_64b[7]==0xD8) { neighbors_vars.myDAGrank=neighbors_vars.neighbors[i].DAGrank+temp_linkCost; temp_preferredParentExists=TRUE; temp_preferredParentRow=i; } break; case 0xC9: if (neighbors_vars.neighbors[i].addr_64b.addr_64b[7]==0xED) { neighbors_vars.myDAGrank=neighbors_vars.neighbors[i].DAGrank+temp_linkCost; temp_preferredParentExists=TRUE; temp_preferredParentRow=i; } break; case 0xD8: if (neighbors_vars.neighbors[i].addr_64b.addr_64b[7]==0xC9) { neighbors_vars.myDAGrank=neighbors_vars.neighbors[i].DAGrank+temp_linkCost; temp_preferredParentExists=TRUE; temp_preferredParentRow=i; } break; default: break; } #endif #ifdef TELOSB_FORCE_MULTIHOP // below to enforce the routing switch ((idmanager_getMyID(ADDR_64B))->addr_64b[7]) { case 0x51: if (neighbors_vars.neighbors[i].addr_64b.addr_64b[7]==0xB9) { neighbors_vars.myDAGrank=neighbors_vars.neighbors[i].DAGrank+temp_linkCost; temp_preferredParentExists=TRUE; temp_preferredParentRow=i; } break; case 0x41: if (neighbors_vars.neighbors[i].addr_64b.addr_64b[7]==0x51) { neighbors_vars.myDAGrank=neighbors_vars.neighbors[i].DAGrank+temp_linkCost; temp_preferredParentExists=TRUE; temp_preferredParentRow=i; } break; case 0x80: if (neighbors_vars.neighbors[i].addr_64b.addr_64b[7]==0x41) { neighbors_vars.myDAGrank=neighbors_vars.neighbors[i].DAGrank+temp_linkCost; temp_preferredParentExists=TRUE; temp_preferredParentRow=i; } break; case 0xE1: if (neighbors_vars.neighbors[i].addr_64b.addr_64b[7]==0x80) { neighbors_vars.myDAGrank=neighbors_vars.neighbors[i].DAGrank+temp_linkCost; temp_preferredParentExists=TRUE; temp_preferredParentRow=i; } break; default: break; } #endif #endif } i++; } if (temp_preferredParentExists) { neighbors_vars.neighbors[temp_preferredParentRow].parentPreference=MAXPREFERENCE; neighbors_vars.neighbors[temp_preferredParentRow].stableNeighbor=TRUE; neighbors_vars.neighbors[temp_preferredParentRow].switchStabilityCounter = 0; } } else { neighbors_vars.myDAGrank=0; } }
/** \brief Called when RPL message received. \param[in] msg Pointer to the received message. */ void icmpv6rpl_receive(OpenQueueEntry_t* msg) { uint8_t icmpv6code; open_addr_t myPrefix; // take ownership msg->owner = COMPONENT_ICMPv6RPL; // retrieve ICMPv6 code icmpv6code = (((ICMPv6_ht*)(msg->payload))->code); // toss ICMPv6 header packetfunctions_tossHeader(msg,sizeof(ICMPv6_ht)); // handle message switch (icmpv6code) { case IANA_ICMPv6_RPL_DIS: icmpv6rpl_timer_DIO_task(); break; case IANA_ICMPv6_RPL_DIO: if (idmanager_getIsDAGroot()==TRUE) { // stop here if I'm in the DAG root break; // break, don't return } // update neighbor table neighbors_indicateRxDIO(msg); memcpy( &(icmpv6rpl_vars.dio), (icmpv6rpl_dio_ht*)(msg->payload), sizeof(icmpv6rpl_dio_ht) ); // write DODAGID in DIO and DAO icmpv6rpl_writeDODAGid(&(((icmpv6rpl_dio_ht*)(msg->payload))->DODAGID[0])); // update my prefix myPrefix.type = ADDR_PREFIX; memcpy( myPrefix.prefix, &((icmpv6rpl_dio_ht*)(msg->payload))->DODAGID[0], sizeof(myPrefix.prefix) ); idmanager_setMyID(&myPrefix); break; case IANA_ICMPv6_RPL_DAO: // this should never happen openserial_printCritical(COMPONENT_ICMPv6RPL,ERR_UNEXPECTED_DAO, (errorparameter_t)0, (errorparameter_t)0); break; default: // this should never happen openserial_printError(COMPONENT_ICMPv6RPL,ERR_MSG_UNKNOWN_TYPE, (errorparameter_t)icmpv6code, (errorparameter_t)0); break; } // free message openqueue_freePacketBuffer(msg); }
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 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 the DAG root if (idmanager_getIsDAGroot()==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); } }
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; }