owerror_t idmanager_setMyID(open_addr_t* newID) { INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); switch (newID->type) { case ADDR_16B: memcpy(&idmanager_vars.my16bID,newID,sizeof(open_addr_t)); break; case ADDR_64B: memcpy(&idmanager_vars.my64bID,newID,sizeof(open_addr_t)); break; case ADDR_PANID: memcpy(&idmanager_vars.myPANID,newID,sizeof(open_addr_t)); break; case ADDR_PREFIX: memcpy(&idmanager_vars.myPrefix,newID,sizeof(open_addr_t)); break; case ADDR_128B: //don't set 128b, but rather prefix and 64b default: openserial_printCritical(COMPONENT_IDMANAGER,ERR_WRONG_ADDR_TYPE, (errorparameter_t)newID->type, (errorparameter_t)1); ENABLE_INTERRUPTS(); return E_FAIL; } ENABLE_INTERRUPTS(); return E_SUCCESS; }
/** \brief Indicate whether some neighbor is a stable neighbor \param[in] address The address of the neighbor, a full 128-bit IPv6 addres. \returns TRUE if that neighbor is stable, FALSE otherwise. */ bool neighbors_isStableNeighbor(open_addr_t* address) { uint8_t i; open_addr_t temp_addr_64b; open_addr_t temp_prefix; bool returnVal; // by default, not stable returnVal = FALSE; // but neighbor's IPv6 address in prefix and EUI64 switch (address->type) { case ADDR_128B: packetfunctions_ip128bToMac64b(address,&temp_prefix,&temp_addr_64b); break; default: openserial_printCritical(COMPONENT_NEIGHBORS,ERR_WRONG_ADDR_TYPE, (errorparameter_t)address->type, (errorparameter_t)0); return returnVal; } // iterate through neighbor table for (i=0;i<MAXNUMNEIGHBORS;i++) { if (isThisRowMatching(&temp_addr_64b,i) && neighbors_vars.neighbors[i].stableNeighbor==TRUE) { returnVal = TRUE; break; } } return returnVal; }
open_addr_t* idmanager_getMyID(uint8_t type) { open_addr_t* res; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); switch (type) { case ADDR_16B: res= &idmanager_vars.my16bID; break; case ADDR_64B: res= &idmanager_vars.my64bID; break; case ADDR_PANID: res= &idmanager_vars.myPANID; break; case ADDR_PREFIX: res= &idmanager_vars.myPrefix; break; case ADDR_128B: // you don't ask for my full address, rather for prefix, then 64b default: openserial_printCritical(COMPONENT_IDMANAGER,ERR_WRONG_ADDR_TYPE, (errorparameter_t)type, (errorparameter_t)0); res= NULL; break; } ENABLE_INTERRUPTS(); return res; }
/** \brief Free a previously-allocated packet buffer. \param pkt A pointer to the previsouly-allocated packet buffer. \returns E_SUCCESS when the freeing was succeful. \returns E_FAIL when the module could not find the specified packet buffer. */ owerror_t openqueue_freePacketBuffer(OpenQueueEntry_t* pkt) { uint8_t i; uint8_t *pucAux = (uint8_t *) pkt; uint8_t creator; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); for (i=0;i<QUEUELENGTH;i++) { if (&openqueue_vars.queue[i]==pkt) { if (openqueue_vars.queue[i].owner==COMPONENT_NULL) { // log the error openserial_printCritical(COMPONENT_OPENQUEUE,ERR_FREEING_UNUSED, (errorparameter_t)0, (errorparameter_t)0); } creator = openqueue_vars.queue[i].creator; openqueue_reset_entry(&(openqueue_vars.queue[i])); ENABLE_INTERRUPTS(); #if ((ENABLE_DEBUG_RFF ==1) && (DBG_OPENQUEUE == 1)) { uint8_t pos=0; rffbuf[pos++]= RFF_OPENQUEUE_FREE; 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 E_SUCCESS; } } // log the error openserial_printCritical(COMPONENT_OPENQUEUE,ERR_FREEING_ERROR, (errorparameter_t)0, (errorparameter_t)0); ENABLE_INTERRUPTS(); return E_FAIL; }
/** \brief Write the 64-bit address of some neighbor to some location. */ void neighbors_getNeighbor(open_addr_t* address, uint8_t addr_type, uint8_t index){ switch(addr_type) { case ADDR_64B: memcpy(&(address->addr_64b),&(neighbors_vars.neighbors[index].addr_64b.addr_64b),LENGTH_ADDR64b); address->type=ADDR_64B; break; default: openserial_printCritical(COMPONENT_NEIGHBORS,ERR_WRONG_ADDR_TYPE, (errorparameter_t)addr_type, (errorparameter_t)1); break; } }
/** \brief Free a previously-allocated packet buffer. \param pkt A pointer to the previsouly-allocated packet buffer. \returns E_SUCCESS when the freeing was succeful. \returns E_FAIL when the module could not find the specified packet buffer. */ owerror_t openqueue_freePacketBuffer(OpenQueueEntry_t* pkt) { uint8_t i; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); for (i=0;i<QUEUELENGTH;i++) { if (&openqueue_vars.queue[i]==pkt) { if (openqueue_vars.queue[i].owner==COMPONENT_NULL) { // log the error openserial_printCritical(COMPONENT_OPENQUEUE,ERR_FREEING_UNUSED, (errorparameter_t)0, (errorparameter_t)0); } openqueue_reset_entry(&(openqueue_vars.queue[i])); ENABLE_INTERRUPTS(); return E_SUCCESS; } } // log the error openserial_printCritical(COMPONENT_OPENQUEUE,ERR_FREEING_ERROR, (errorparameter_t)0, (errorparameter_t)0); ENABLE_INTERRUPTS(); return E_FAIL; }
void icmpv6_sendDone(OpenQueueEntry_t* msg, error_t error) { msg->owner = COMPONENT_ICMPv6; switch (msg->l4_sourcePortORicmpv6Type) { case IANA_ICMPv6_ECHO_REQUEST: case IANA_ICMPv6_ECHO_REPLY: icmpv6echo_sendDone(msg, error); break; case IANA_ICMPv6_RPL: icmpv6rpl_sendDone(msg, error); break; default: openserial_printCritical(COMPONENT_ICMPv6,ERR_UNSUPPORTED_ICMPV6_TYPE, (errorparameter_t)msg->l4_sourcePortORicmpv6Type, (errorparameter_t)0); // free the corresponding packet buffer openqueue_freePacketBuffer(msg); break; } }
bool idmanager_isMyAddress(open_addr_t* addr) { open_addr_t temp_my128bID; bool res; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); switch (addr->type) { case ADDR_16B: res= packetfunctions_sameAddress(addr,&idmanager_vars.my16bID); ENABLE_INTERRUPTS(); return res; case ADDR_64B: res= packetfunctions_sameAddress(addr,&idmanager_vars.my64bID); ENABLE_INTERRUPTS(); return res; case ADDR_128B: //build temporary my128bID temp_my128bID.type = ADDR_128B; memcpy(&temp_my128bID.addr_128b[0],&idmanager_vars.myPrefix.prefix,8); memcpy(&temp_my128bID.addr_128b[8],&idmanager_vars.my64bID.addr_64b,8); res= packetfunctions_sameAddress(addr,&temp_my128bID); ENABLE_INTERRUPTS(); return res; case ADDR_PANID: res= packetfunctions_sameAddress(addr,&idmanager_vars.myPANID); ENABLE_INTERRUPTS(); return res; case ADDR_PREFIX: res= packetfunctions_sameAddress(addr,&idmanager_vars.myPrefix); ENABLE_INTERRUPTS(); return res; default: openserial_printCritical(COMPONENT_IDMANAGER,ERR_WRONG_ADDR_TYPE, (errorparameter_t)addr->type, (errorparameter_t)2); ENABLE_INTERRUPTS(); return FALSE; } }
/** \brief Indicates a packet has been sent. \param[in,out] msg The packet just sent. \param[in] error The outcome of sending it. */ void forwarding_sendDone(OpenQueueEntry_t* msg, owerror_t error) { // take ownership msg->owner = COMPONENT_FORWARDING; if (msg->creator==COMPONENT_RADIO || msg->creator==COMPONENT_FORWARDING) { // this is a relayed packet // free packet openqueue_freePacketBuffer(msg); } else { // this is a packet created by this mote // indicate sendDone to upper layer switch(msg->l4_protocol) { case IANA_TCP: opentcp_sendDone(msg,error); break; case IANA_UDP: openudp_sendDone(msg,error); break; case IANA_ICMPv6: icmpv6_sendDone(msg,error); break; default: // log error openserial_printCritical( COMPONENT_FORWARDING, ERR_WRONG_TRAN_PROTOCOL, (errorparameter_t)msg->l4_protocol, (errorparameter_t)0 ); // free packet openqueue_freePacketBuffer(msg); } } }
/** \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_DIO: if (idmanager_getIsBridge()==TRUE) { // stop here if I'm in bridge mode break; // break, don't return } // update neighbor table neighbors_indicateRxDIO(msg); // update DODAGID in DIO/DAO memcpy( &(icmpv6rpl_vars.dio.DODAGID[0]), &(((icmpv6rpl_dio_ht*)(msg->payload))->DODAGID[0]), sizeof(icmpv6rpl_vars.dio.DODAGID) ); memcpy( &(icmpv6rpl_vars.dao.DODAGID[0]), &(((icmpv6rpl_dio_ht*)(msg->payload))->DODAGID[0]), sizeof(icmpv6rpl_vars.dao.DODAGID) ); // remember I got a DODAGID icmpv6rpl_vars.DODAGIDFlagSet=1; // 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_printCritical(COMPONENT_ICMPv6RPL,ERR_MSG_UNKNOWN_TYPE, (errorparameter_t)icmpv6code, (errorparameter_t)0); break; } // free message openqueue_freePacketBuffer(msg); }
/** \brief Add a new active slot into the schedule. If udpate param is set then update it in case it exists. \param slotOffset \param type \param shared \param channelOffset \param neighbor \param isUpdate */ owerror_t schedule_addActiveSlot( slotOffset_t slotOffset, cellType_t type, bool shared, channelOffset_t channelOffset, open_addr_t* neighbor, bool isUpdate ) { owerror_t outcome; scheduleEntry_t* slotContainer; scheduleEntry_t* previousSlotWalker; scheduleEntry_t* nextSlotWalker; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); // find an empty schedule entry container slotContainer = &schedule_vars.scheduleBuf[0]; while (slotContainer->type!=CELLTYPE_OFF && slotContainer<=&schedule_vars.scheduleBuf[MAXACTIVESLOTS-1]) { //check that this entry for that neighbour and timeslot is not already scheduled. if (type!=CELLTYPE_SERIALRX && type!=CELLTYPE_MORESERIALRX && (packetfunctions_sameAddress(neighbor,&(slotContainer->neighbor))|| (slotContainer->neighbor.type==ADDR_ANYCAST && isUpdate==TRUE)) &&(slotContainer->slotOffset==slotOffset)){ //it exists so this is an update. slotContainer->type = type; slotContainer->shared = shared; slotContainer->channelOffset = channelOffset; memcpy(&slotContainer->neighbor,neighbor,sizeof(open_addr_t));//update the address too! schedule_dbg.numUpdatedSlotsCur++; ENABLE_INTERRUPTS(); return E_SUCCESS; //as this is an update. No need to re-insert as it is in the same position on the list. } slotContainer++; } if (isUpdate==TRUE) { //we are trying to update an item that is not in the schedule list. ENABLE_INTERRUPTS(); return E_FAIL; } if (slotContainer>&schedule_vars.scheduleBuf[MAXACTIVESLOTS-1]) { // schedule has overflown outcome=E_FAIL; openserial_printCritical(COMPONENT_SCHEDULE,ERR_SCHEDULE_OVERFLOWN, (errorparameter_t)0, (errorparameter_t)0); } // fill that schedule entry with parameters passed slotContainer->slotOffset = slotOffset; slotContainer->type = type; slotContainer->shared = shared; slotContainer->channelOffset = channelOffset; memcpy(&slotContainer->neighbor,neighbor,sizeof(open_addr_t)); if (schedule_vars.currentScheduleEntry==NULL) { // this is the first active slot added // the next slot of this slot is this slot slotContainer->next = slotContainer; // current slot points to this slot schedule_vars.currentScheduleEntry = slotContainer; } else { // this is NOT the first active slot added // find position in schedule previousSlotWalker = schedule_vars.currentScheduleEntry; while (1) { nextSlotWalker = previousSlotWalker->next; if ( ( (previousSlotWalker->slotOffset < slotContainer->slotOffset) && (slotContainer->slotOffset < nextSlotWalker->slotOffset) ) || ( (previousSlotWalker->slotOffset < slotContainer->slotOffset) && (nextSlotWalker->slotOffset <= previousSlotWalker->slotOffset) ) || ( (slotContainer->slotOffset < nextSlotWalker->slotOffset) && (nextSlotWalker->slotOffset <= previousSlotWalker->slotOffset) ) ) { break; } previousSlotWalker = nextSlotWalker; } // insert between previousSlotWalker and nextSlotWalker previousSlotWalker->next = slotContainer; slotContainer->next = nextSlotWalker; } // maintain debug stats schedule_dbg.numActiveSlotsCur++; if (schedule_dbg.numActiveSlotsCur>schedule_dbg.numActiveSlotsMax) { schedule_dbg.numActiveSlotsMax = schedule_dbg.numActiveSlotsCur; } outcome=E_SUCCESS; ENABLE_INTERRUPTS(); return outcome; }
/** \brief Prepend the IEEE802.15.4 MAC header to a (to be transmitted) packet. Note that we are writing the field from the end of the header to the beginning. \param[in,out] msg The message to append the header to. \param[in] frameType Type of IEEE802.15.4 frame. \param[in] ielistpresent Is the IE list present¿ \param[in] frameVersion IEEE802.15.4 frame version. \param[in] securityEnabled Is security enabled on this frame? \param[in] sequenceNumber Sequence number of this frame. \param[in] nextHop Address of the next hop */ void ieee802154_prependHeader(OpenQueueEntry_t* msg, uint8_t frameType, uint8_t ielistpresent, uint8_t frameVersion, bool securityEnabled, uint8_t sequenceNumber, open_addr_t* nextHop) { uint8_t temp_8b; //General IEs here (those that are carried in all packets) -- None by now. // previousHop address (always 64-bit) packetfunctions_writeAddress(msg,idmanager_getMyID(ADDR_64B),OW_LITTLE_ENDIAN); // nextHop address if (packetfunctions_isBroadcastMulticast(nextHop)) { //broadcast address is always 16-bit packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = 0xFF; packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = 0xFF; } else { switch (nextHop->type) { case ADDR_16B: case ADDR_64B: packetfunctions_writeAddress(msg,nextHop,OW_LITTLE_ENDIAN); break; default: openserial_printCritical(COMPONENT_IEEE802154,ERR_WRONG_ADDR_TYPE, (errorparameter_t)nextHop->type, (errorparameter_t)1); } } // destpan packetfunctions_writeAddress(msg,idmanager_getMyID(ADDR_PANID),OW_LITTLE_ENDIAN); //dsn packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = sequenceNumber; //fcf (2nd byte) packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); temp_8b = 0; if (packetfunctions_isBroadcastMulticast(nextHop)) { temp_8b |= IEEE154_ADDR_SHORT << IEEE154_FCF_DEST_ADDR_MODE; } else { switch (nextHop->type) { case ADDR_16B: temp_8b |= IEEE154_ADDR_SHORT << IEEE154_FCF_DEST_ADDR_MODE; break; case ADDR_64B: temp_8b |= IEEE154_ADDR_EXT << IEEE154_FCF_DEST_ADDR_MODE; break; // no need for a default, since it would have been caught above. } } temp_8b |= IEEE154_ADDR_EXT << IEEE154_FCF_SRC_ADDR_MODE; //poipoi xv IE list present temp_8b |= ielistpresent << IEEE154_FCF_IELIST_PRESENT; temp_8b |= frameVersion << IEEE154_FCF_FRAME_VERSION; *((uint8_t*)(msg->payload)) = temp_8b; //fcf (1st byte) packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); temp_8b = 0; temp_8b |= frameType << IEEE154_FCF_FRAME_TYPE; temp_8b |= securityEnabled << IEEE154_FCF_SECURITY_ENABLED; temp_8b |= IEEE154_PENDING_NO_FRAMEPENDING << IEEE154_FCF_FRAME_PENDING; if (frameType==IEEE154_TYPE_ACK || packetfunctions_isBroadcastMulticast(nextHop)) { temp_8b |= IEEE154_ACK_NO_ACK_REQ << IEEE154_FCF_ACK_REQ; } else { temp_8b |= IEEE154_ACK_YES_ACK_REQ << IEEE154_FCF_ACK_REQ; } temp_8b |= IEEE154_PANID_COMPRESSED << IEEE154_FCF_INTRAPAN; *((uint8_t*)(msg->payload)) = temp_8b; }
/** \brief Add a new active slot into the schedule. \param newFrameLength The new frame length. */ void schedule_addActiveSlot(slotOffset_t slotOffset, cellType_t type, bool shared, uint8_t channelOffset, open_addr_t* neighbor) { scheduleEntry_t* slotContainer; scheduleEntry_t* previousSlotWalker; scheduleEntry_t* nextSlotWalker; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); // find an empty schedule entry container slotContainer = &schedule_vars.scheduleBuf[0]; while (slotContainer->type!=CELLTYPE_OFF && slotContainer<=&schedule_vars.scheduleBuf[MAXACTIVESLOTS-1]) { slotContainer++; } if (slotContainer>&schedule_vars.scheduleBuf[MAXACTIVESLOTS-1]) { // schedule has overflown openserial_printCritical(COMPONENT_SCHEDULE,ERR_SCHEDULE_OVERFLOWN, (errorparameter_t)0, (errorparameter_t)0); } // fill that schedule entry with parameters passed slotContainer->slotOffset = slotOffset; slotContainer->type = type; slotContainer->shared = shared; slotContainer->channelOffset = channelOffset; memcpy(&slotContainer->neighbor,neighbor,sizeof(open_addr_t)); if (schedule_vars.currentScheduleEntry==NULL) { // this is the first active slot added // the next slot of this slot is this slot slotContainer->next = slotContainer; // current slot points to this slot schedule_vars.currentScheduleEntry = slotContainer; } else { // this is NOT the first active slot added // find position in schedule previousSlotWalker = schedule_vars.currentScheduleEntry; while (1) { nextSlotWalker = previousSlotWalker->next; if ( ( (previousSlotWalker->slotOffset < slotContainer->slotOffset) && (slotContainer->slotOffset < nextSlotWalker->slotOffset) ) || ( (previousSlotWalker->slotOffset < slotContainer->slotOffset) && (nextSlotWalker->slotOffset <= previousSlotWalker->slotOffset) ) || ( (slotContainer->slotOffset < nextSlotWalker->slotOffset) && (nextSlotWalker->slotOffset <= previousSlotWalker->slotOffset) ) ) { break; } previousSlotWalker = nextSlotWalker; } // insert between previousSlotWalker and nextSlotWalker previousSlotWalker->next = slotContainer; slotContainer->next = nextSlotWalker; } // maintain debug stats schedule_dbg.numActiveSlotsCur++; if (schedule_dbg.numActiveSlotsCur>schedule_dbg.numActiveSlotsMax) { schedule_dbg.numActiveSlotsMax = schedule_dbg.numActiveSlotsCur; } ENABLE_INTERRUPTS(); }
void task_sixtopNotifReceive() { OpenQueueEntry_t* msg; uint16_t lenIE; // get received packet from openqueue msg = openqueue_sixtopGetReceivedPacket(); if (msg==NULL) { openserial_printCritical( COMPONENT_SIXTOP, ERR_NO_RECEIVED_PACKET, (errorparameter_t)0, (errorparameter_t)0 ); return; } // take ownership msg->owner = COMPONENT_SIXTOP; // process the header IEs lenIE=0; if( msg->l2_frameType==IEEE154_TYPE_DATA && msg->l2_IEListPresent==IEEE154_IELIST_YES && sixtop_processIEs(msg, &lenIE) == FALSE ) { // free the packet's RAM memory openqueue_freePacketBuffer(msg); //log error return; } // toss the header IEs packetfunctions_tossHeader(msg,lenIE); // update neighbor statistics neighbors_indicateRx( &(msg->l2_nextORpreviousHop), msg->l1_rssi, &msg->l2_asn, msg->l2_joinPriorityPresent, msg->l2_joinPriority ); // reset it to avoid race conditions with this var. msg->l2_joinPriorityPresent = FALSE; // send the packet up the stack, if it qualifies switch (msg->l2_frameType) { case IEEE154_TYPE_BEACON: case IEEE154_TYPE_DATA: case IEEE154_TYPE_CMD: if (msg->length>0) { // send to upper layer iphc_receive(msg); } else { // free up the RAM openqueue_freePacketBuffer(msg); } break; case IEEE154_TYPE_ACK: default: // free the packet's RAM memory openqueue_freePacketBuffer(msg); // log the error openserial_printError( COMPONENT_SIXTOP, ERR_MSG_UNKNOWN_TYPE, (errorparameter_t)msg->l2_frameType, (errorparameter_t)0 ); break; } }
void task_sixtopNotifSendDone() { OpenQueueEntry_t* msg; // get recently-sent packet from openqueue msg = openqueue_sixtopGetSentPacket(); if (msg==NULL) { openserial_printCritical( COMPONENT_SIXTOP, ERR_NO_SENT_PACKET, (errorparameter_t)0, (errorparameter_t)0 ); return; } // take ownership msg->owner = COMPONENT_SIXTOP; // update neighbor statistics if (msg->l2_sendDoneError==E_SUCCESS) { neighbors_indicateTx( &(msg->l2_nextORpreviousHop), msg->l2_numTxAttempts, TRUE, &msg->l2_asn ); } else { neighbors_indicateTx( &(msg->l2_nextORpreviousHop), msg->l2_numTxAttempts, FALSE, &msg->l2_asn ); } // send the packet to where it belongs switch (msg->creator) { case COMPONENT_SIXTOP: if (msg->l2_frameType==IEEE154_TYPE_BEACON) { // this is a ADV // not busy sending ADV anymore sixtop_vars.busySendingEB = FALSE; } else { // this is a KA // not busy sending KA anymore sixtop_vars.busySendingKA = FALSE; } // discard packets openqueue_freePacketBuffer(msg); // restart a random timer sixtop_vars.periodMaintenance = 872+(openrandom_get16b()&0xff); opentimers_setPeriod( sixtop_vars.maintenanceTimerId, TIME_MS, sixtop_vars.periodMaintenance ); break; case COMPONENT_SIXTOP_RES: sixtop_six2six_sendDone(msg,msg->l2_sendDoneError); break; default: // send the rest up the stack iphc_sendDone(msg,msg->l2_sendDoneError); break; } }