int mote_main(void) { board_init(); scheduler_init(); openstack_init(); if (idmanager_getMyID(ADDR_64B)->addr_64b[7]==0xbb) { idmanager_setIsDAGroot(TRUE); } scheduler_start(); return 0; // this line should never be reached }
owerror_t openserial_printStatus(uint8_t statusElement,uint8_t* buffer, uint8_t length) { uint8_t i; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); openserial_vars.outputBufFilled = TRUE; outputHdlcOpen(); outputHdlcWrite(SERFRAME_MOTE2PC_STATUS); outputHdlcWrite(idmanager_getMyID(ADDR_16B)->addr_16b[0]); outputHdlcWrite(idmanager_getMyID(ADDR_16B)->addr_16b[1]); outputHdlcWrite(statusElement); for (i=0;i<length;i++){ outputHdlcWrite(buffer[i]); } outputHdlcClose(); ENABLE_INTERRUPTS(); return E_SUCCESS; }
void construct_demo(demo_t* data) { data->start = COMPONENT_BBK; data->id = idmanager_getMyID(ADDR_16B)->addr_16b[1]; data->seq[0] = (uint8_t)((bbk_vars.sequence & 0xff000000)>>24); data->seq[1] = (uint8_t)((bbk_vars.sequence & 0x00ff0000)>>16); data->seq[2] = (uint8_t)((bbk_vars.sequence & 0x0000ff00)>>8); data->seq[3] = (uint8_t)(bbk_vars.sequence & 0x00000000ff); data->channel = 0xab; data->retry = 0xcd; data->end = 0x99; }
owerror_t openserial_printStatus( uint8_t statusElement, uint8_t* buffer, uint8_t length ) { uint8_t i; outputHdlcOpen(); outputHdlcWrite(SERFRAME_MOTE2PC_STATUS); outputHdlcWrite(idmanager_getMyID(ADDR_16B)->addr_16b[0]); outputHdlcWrite(idmanager_getMyID(ADDR_16B)->addr_16b[1]); outputHdlcWrite(statusElement); for (i=0;i<length;i++){ outputHdlcWrite(buffer[i]); } outputHdlcClose(); // start TX'ing openserial_flush(); return E_SUCCESS; }
error_t openserial_printStatus(uint8_t statusElement,uint8_t* buffer, uint16_t length) { uint8_t counter; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); openserial_vars.somethingInOutputBuffer=TRUE; openserial_vars.output_buffer[output_buffer_index_write_increment()]=(uint8_t)'^'; //preamble openserial_vars.output_buffer[output_buffer_index_write_increment()]=(uint8_t)'^'; openserial_vars.output_buffer[output_buffer_index_write_increment()]=(uint8_t)'^'; openserial_vars.output_buffer[output_buffer_index_write_increment()]=(uint8_t)'S'; //this is an status update openserial_vars.output_buffer[output_buffer_index_write_increment()]=(uint8_t)((idmanager_getMyID(ADDR_16B))->addr_16b[1]); openserial_vars.output_buffer[output_buffer_index_write_increment()]=(uint8_t)((idmanager_getMyID(ADDR_16B))->addr_16b[0]); openserial_vars.output_buffer[output_buffer_index_write_increment()]=(uint8_t)statusElement; //type of element for (counter=0; counter<length; counter++) { openserial_vars.output_buffer[output_buffer_index_write_increment()]=(uint8_t)buffer[counter]; } openserial_vars.output_buffer[output_buffer_index_write_increment()]=(uint8_t)'$'; //postamble openserial_vars.output_buffer[output_buffer_index_write_increment()]=(uint8_t)'$'; openserial_vars.output_buffer[output_buffer_index_write_increment()]=(uint8_t)'$'; ENABLE_INTERRUPTS(); return E_SUCCESS; }
/** \brief Receive a frame at the openbridge, which sends it out over serial. */ void openbridge_receive(OpenQueueEntry_t* msg) { // prepend previous hop packetfunctions_reserveHeaderSize(msg,LENGTH_ADDR64b); memcpy(msg->payload,msg->l2_nextORpreviousHop.addr_64b,LENGTH_ADDR64b); // prepend next hop (me) packetfunctions_reserveHeaderSize(msg,LENGTH_ADDR64b); memcpy(msg->payload,idmanager_getMyID(ADDR_64B)->addr_64b,LENGTH_ADDR64b); // send packet over serial (will be memcopied into serial buffer) openserial_printData((uint8_t*)(msg->payload),msg->length); // free packet openqueue_freePacketBuffer(msg); }
/** \brief Timer handlers which triggers MAC management task. This function is called in task context by the scheduler after the RES timer has fired. This timer is set to fire every second, on average. The body of this function executes one of the MAC management task. */ void timers_res_fired() { res_vars.MacMgtTaskCounter = (res_vars.MacMgtTaskCounter+1)%2; if (idmanager_getMyID(ADDR_16B)->addr_16b[1]==DEBUG_MOTEID_MASTER) { if (res_vars.MacMgtTaskCounter==0) { sendAdv(); } else { // don't send KAs if you're the master } } else { if (res_vars.MacMgtTaskCounter==0) { sendAdv(); // don't send ADVs if you're not the master } else { sendKa(); } } }
bool topology_isAcceptablePacket(ieee802154_header_iht* ieee802514_header) { #ifdef FORCETOPOLOGY bool returnVal; returnVal=FALSE; uint16_t my_addr = idmanager_getMyID(ADDR_64B)->addr_64b[7] | (idmanager_getMyID(ADDR_64B)->addr_64b[6] << 8); uint16_t src_addr = ieee802514_header->src.addr_64b[7] | (ieee802514_header->src.addr_64b[6] << 8); switch (my_addr) { case 0x0001: if ( src_addr==0x0002|| src_addr==0x0003|| src_addr==0x0004|| src_addr==0x0005|| src_addr==0x0006|| src_addr==0x0007|| src_addr==0x0008|| src_addr==0x0009|| src_addr==0x000a|| src_addr==0x000b|| src_addr==0x000c|| src_addr==0x000d|| src_addr==0x000e|| src_addr==0x000f|| src_addr==0x0011|| src_addr==0x0013|| src_addr==0x001d|| src_addr==0x001f|| src_addr==0x0020 ) { returnVal=TRUE; } break; case 0x0002: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0003: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0004: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0005: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0006: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0007: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0008: if ( src_addr==0x0001|| src_addr==0x0016|| src_addr==0x0018|| src_addr==0x001a ) { returnVal=TRUE; } break; case 0x0009: if ( src_addr==0x0001|| src_addr==0x001b|| src_addr==0x001c ) { returnVal=TRUE; } break; case 0x000a: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x000b: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x000c: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x000d: if ( src_addr==0x0001|| src_addr==0x0017 ) { returnVal=TRUE; } break; case 0x000e: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x000f: if ( src_addr==0x0001|| src_addr==0x0015|| src_addr==0x002b|| src_addr==0x002d ) { returnVal=TRUE; } break; case 0x0010: if ( src_addr==0x0020 ) { returnVal=TRUE; } break; case 0x0011: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0012: if ( src_addr==0x001f ) { returnVal=TRUE; } break; case 0x0013: if ( src_addr==0x0001|| src_addr==0x0014|| src_addr==0x0019 ) { returnVal=TRUE; } break; case 0x0014: if ( src_addr==0x0013 ) { returnVal=TRUE; } break; case 0x0015: if ( src_addr==0x000f ) { returnVal=TRUE; } break; case 0x0016: if ( src_addr==0x0008 ) { returnVal=TRUE; } break; case 0x0017: if ( src_addr==0x000d ) { returnVal=TRUE; } break; case 0x0018: if ( src_addr==0x0008 ) { returnVal=TRUE; } break; case 0x0019: if ( src_addr==0x0013 ) { returnVal=TRUE; } break; case 0x001a: if ( src_addr==0x0008 ) { returnVal=TRUE; } break; case 0x001b: if ( src_addr==0x0009 ) { returnVal=TRUE; } break; case 0x001c: if ( src_addr==0x0009 ) { returnVal=TRUE; } break; case 0x001d: if ( src_addr==0x0001|| src_addr==0x002a ) { returnVal=TRUE; } break; case 0x001e: if ( src_addr==0x001f ) { returnVal=TRUE; } break; case 0x001f: if ( src_addr==0x0001|| src_addr==0x0012|| src_addr==0x001e|| src_addr==0x0023|| src_addr==0x0024|| src_addr==0x0025|| src_addr==0x0026|| src_addr==0x0027|| src_addr==0x0028|| src_addr==0x0029 ) { returnVal=TRUE; } break; case 0x0020: if ( src_addr==0x0001|| src_addr==0x0010|| src_addr==0x0021|| src_addr==0x0022 ) { returnVal=TRUE; } break; case 0x0021: if ( src_addr==0x0020 ) { returnVal=TRUE; } break; case 0x0022: if ( src_addr==0x0020 ) { returnVal=TRUE; } break; case 0x0023: if ( src_addr==0x001f ) { returnVal=TRUE; } break; case 0x0024: if ( src_addr==0x001f ) { returnVal=TRUE; } break; case 0x0025: if ( src_addr==0x001f ) { returnVal=TRUE; } break; case 0x0026: if ( src_addr==0x001f ) { returnVal=TRUE; } break; case 0x0027: if ( src_addr==0x001f ) { returnVal=TRUE; } break; case 0x0028: if ( src_addr==0x001f ) { returnVal=TRUE; } break; case 0x0029: if ( src_addr==0x001f ) { returnVal=TRUE; } break; case 0x002a: if ( src_addr==0x001d ) { returnVal=TRUE; } break; case 0x002b: if ( src_addr==0x000f|| src_addr==0x002c ) { returnVal=TRUE; } break; case 0x002c: if ( src_addr==0x002b ) { returnVal=TRUE; } break; case 0x002d: if ( src_addr==0x000f ) { returnVal=TRUE; } break; } return returnVal; #else return TRUE; #endif }
void ieee802154_prependHeader(OpenQueueEntry_t* msg, uint8_t frameType, bool securityEnabled, uint8_t sequenceNumber, open_addr_t* nextHop) { uint8_t temp_8b; //previousHop address (always 64-bit) packetfunctions_writeAddress(msg,idmanager_getMyID(ADDR_64B),LITTLE_ENDIAN); // poipoi: using 16-bit source address //packetfunctions_writeAddress(msg,idmanager_getMyID(ADDR_16B),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 { // poipoi: using 16-bit destination address // packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); // *((uint8_t*)(msg->payload)) = nextHop->addr_64b[6]; // packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); // *((uint8_t*)(msg->payload)) = nextHop->addr_64b[7]; // switch (nextHop->type) { case ADDR_16B: case ADDR_64B: packetfunctions_writeAddress(msg,nextHop,LITTLE_ENDIAN); break; default: openserial_printError(COMPONENT_IEEE802154,ERR_WRONG_ADDR_TYPE, (errorparameter_t)nextHop->type, (errorparameter_t)1); } } //destpan packetfunctions_writeAddress(msg,idmanager_getMyID(ADDR_PANID),LITTLE_ENDIAN); //dsn packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = sequenceNumber; //fcf (2nd byte) temp_8b = 0; // poipoi: 16-bit source/dest addresses // temp_8b |= IEEE154_ADDR_SHORT << IEEE154_FCF_DEST_ADDR_MODE; //temp_8b |= IEEE154_ADDR_SHORT << IEEE154_FCF_SRC_ADDR_MODE; 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; } } temp_8b |= IEEE154_ADDR_EXT << IEEE154_FCF_SRC_ADDR_MODE; packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = temp_8b; //fcf (1st byte) 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; packetfunctions_reserveHeaderSize(msg,sizeof(uint8_t)); *((uint8_t*)(msg->payload)) = temp_8b; }
void openrandom_init() { // seed the random number generator with the last 2 bytes of the MAC address random_vars.shift_reg = 0; random_vars.shift_reg += idmanager_getMyID(ADDR_16B)->addr_16b[0]*256; random_vars.shift_reg += idmanager_getMyID(ADDR_16B)->addr_16b[1]; }
void security_incomingFrame(OpenQueueEntry_t* msg){ uint8_t match; //open_addr_t* panid; uint32_t tempfr; tempfr = m_macFrameCounter; //panid = &tempheader->panid; m_deviceDescriptor *devpoint; m_keyDescriptor *keypoint; m_securityLevelDescriptor *secLevel; //check that Security Level is not zero, impossible for me /*if(msg->securityLevel == ASH_SLF_TYPE_NOSEC){ return; }*/ //f key descriptor lookup match = keyDescriptorLookup(msg->l2_keyIdMode, &msg->l2_keySource, msg->l2_keyIndex, &msg->l2_nextORpreviousHop, //panid, msg->l2_frameType); keypoint = &MacKeyTable.KeyDescriptorElement[match]; if(match == 25){ msg->l2_toDiscard = TRUE; return; } //g device descriptor lookup open_addr_t Address; Address = msg->l2_nextORpreviousHop; if(msg->l2_keyIdMode == 0){ if(neighbors_haveSomeChild() == TRUE){ Address = *(idmanager_getMyID(ADDR_64B)); } } match = deviceDescriptorLookup(&Address, //idmanager_getMyID(ADDR_PANID); keypoint); devpoint = &MacDeviceTable.DeviceDescriptorEntry[match]; //h Security Level lookup secLevel = securityLevelDescriptorLookup(msg->l2_frameType, 0,//msg->commandFrameIdentifier, secLevel); //i+j+k if(incomingSecurityLevelChecking(secLevel,msg->l2_securityLevel,devpoint->Exempt)==FALSE){ //return; } //l+m Anti-Replay if(msg->l2_frameCounter < devpoint->FrameCounter){ msg->l2_toDiscard = TRUE; } //n Control of key used if(incomingKeyUsagePolicyChecking(keypoint, msg->l2_frameType, 0 ) ==FALSE){ //return; // improper key used } uint8_t i; for(i=0; i<8; i++){ nonce[i] = msg->l2_keySource.addr_64b[i]; } uint32_t temp; temp = msg->l2_frameCounter; nonce[8] = temp; nonce[9] = temp << 8; nonce[10] = temp <<16; nonce[11] = temp <<24; nonce[12] = msg->l2_securityLevel; //CCMstarInverse(msg,keypoint->key); //q increment frame counter and save msg->l2_frameCounter +=1; //showing MACkeyTable content /*if(idmanager_getIsDAGroot() == TRUE){ for(i=0;i<10;i++){ openserial_printError(COMPONENT_RES,ERR_OK, (errorparameter_t)MacKeyTable.KeyDescriptorElement[i].key, (errorparameter_t)i); } }*/ devpoint->FrameCounter = msg->l2_frameCounter; m_macFrameCounter = tempfr; }
//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; } }
/* piggy902: addr-specific schedule */ void schedule_init() { uint8_t i; open_addr_t temp_neighbor; // reset local variables memset(&schedule_vars,0,sizeof(schedule_vars_t)); memset(&schedule_dbg, 0,sizeof(schedule_dbg_t)); for (i=0;i<MAXACTIVESLOTS;i++){ schedule_resetEntry(&schedule_vars.scheduleBuf[i]); } // set frame length schedule_setFrameLength(11); // slot 0 is advertisement slot i = 0; memset(&temp_neighbor,0,sizeof(temp_neighbor)); schedule_addActiveSlot(i, CELLTYPE_ADV, FALSE, 0, &temp_neighbor); switch(idmanager_getMyID(ADDR_16B)->addr_16b[1]){ case DEBUG_MOTEID_MASTER: // slot 1 is shared TXRX, but with specific neighbour rather than anycast i = 1; memset(&temp_neighbor,0,sizeof(temp_neighbor)); temp_neighbor.type = ADDR_64B; temp_neighbor.addr_64b[6] = 0xED; temp_neighbor.addr_64b[7] = DEBUG_MOTEID_2; schedule_addActiveSlot(i, CELLTYPE_TXRX, FALSE, 0, &temp_neighbor); // slot 2 is shared TXRX, but with specific neighbour rather than anycast i = 2; memset(&temp_neighbor,0,sizeof(temp_neighbor)); schedule_addActiveSlot(i, CELLTYPE_MORESERIALRX, FALSE, 0, &temp_neighbor); i = 3; memset(&temp_neighbor,0,sizeof(temp_neighbor)); schedule_addActiveSlot(i, CELLTYPE_MORESERIALRX, FALSE, 0, &temp_neighbor); break; case DEBUG_MOTEID_2: // slot 1 is shared TXRX, but with specific neighbour rather than anycast i = 1; memset(&temp_neighbor,0,sizeof(temp_neighbor)); temp_neighbor.type = ADDR_64B; temp_neighbor.addr_64b[6] = 0xED; temp_neighbor.addr_64b[7] = DEBUG_MOTEID_MASTER; schedule_addActiveSlot(i, CELLTYPE_TXRX, FALSE, 0, &temp_neighbor); i = 2; memset(&temp_neighbor,0,sizeof(temp_neighbor)); schedule_addActiveSlot(i, CELLTYPE_MORESERIALRX, FALSE, 0, &temp_neighbor); i = 3; memset(&temp_neighbor,0,sizeof(temp_neighbor)); schedule_addActiveSlot(i, CELLTYPE_MORESERIALRX, FALSE, 0, &temp_neighbor); break; default: break; } // slot 4 is SERIALRX i = 4; memset(&temp_neighbor,0,sizeof(temp_neighbor)); schedule_addActiveSlot(i, CELLTYPE_SERIALRX, FALSE, 0, &temp_neighbor); // slot 5 is MORESERIALRX i = 5; memset(&temp_neighbor,0,sizeof(temp_neighbor)); schedule_addActiveSlot(i, CELLTYPE_MORESERIALRX, FALSE, 0, &temp_neighbor); // Noise Floor Probe i = 6; memset(&temp_neighbor,0,sizeof(temp_neighbor)); schedule_addActiveSlot(i, CELLTYPE_NF, FALSE, 0, &temp_neighbor); i = 7; memset(&temp_neighbor,0,sizeof(temp_neighbor)); schedule_addActiveSlot(i, CELLTYPE_NF, FALSE, 0, &temp_neighbor); //for RPL DIOs? i = 8; memset(&temp_neighbor,0,sizeof(temp_neighbor)); temp_neighbor.type = ADDR_64B; temp_neighbor.addr_64b[0] = 0xff; temp_neighbor.addr_64b[1] = 0xff; temp_neighbor.addr_64b[2] = 0xff; temp_neighbor.addr_64b[3] = 0xff; temp_neighbor.addr_64b[4] = 0xff; temp_neighbor.addr_64b[5] = 0xff; temp_neighbor.addr_64b[6] = 0xff; temp_neighbor.addr_64b[7] = 0xff; schedule_addActiveSlot(i, CELLTYPE_TXRX, FALSE, 0, &temp_neighbor); }
/** \brief Send a packet using the source rout to find the next hop. \note This is always called for packets being forwarded. How to process the routing header is detailed in http://tools.ietf.org/html/rfc6554#page-9. \param[in,out] msg The packet to send. \param[in] ipv6_header The packet's IPv6 header. */ owerror_t forwarding_send_internal_SourceRouting(OpenMote* self, OpenQueueEntry_t* msg, ipv6_header_iht* ipv6_outer_header, ipv6_header_iht* ipv6_inner_header, rpl_option_ht* rpl_option ) { uint8_t temp_8b; uint8_t type; uint8_t next_type; uint8_t size; uint8_t next_size; uint8_t hlen; open_addr_t firstAddr; open_addr_t nextAddr; open_addr_t temp_prefix; open_addr_t temp_addr64; uint8_t rpi_length; uint8_t flags; uint16_t senderRank; uint8_t RH3_copy[127]; uint8_t RH3_length; memset(&RH3_copy[0],0,127); RH3_length = 0; memcpy(&msg->l3_destinationAdd,&ipv6_inner_header->dest,sizeof(open_addr_t)); memcpy(&msg->l3_sourceAdd,&ipv6_inner_header->src,sizeof(open_addr_t)); // initial first Address by compression reference firstAddr.type = ADDR_128B; if (ipv6_outer_header->src.type != ADDR_NONE){ if (rpl_option->rplInstanceID == 0){ icmpv6rpl_getRPLDODAGid(self, &firstAddr.addr_128b[0]); } } else { memcpy(&firstAddr,&ipv6_inner_header->src,sizeof(open_addr_t)); } hlen = 0; temp_8b = *((uint8_t*)(msg->payload)+hlen); type = *((uint8_t*)(msg->payload)+hlen+1); hlen += 2; // get the first address switch(type){ case RH3_6LOTH_TYPE_0: memcpy(&firstAddr.addr_128b[15],msg->payload+hlen,1); hlen += 1; break; case RH3_6LOTH_TYPE_1: memcpy(&firstAddr.addr_128b[14],msg->payload+hlen,2); hlen += 2; break; case RH3_6LOTH_TYPE_2: memcpy(&firstAddr.addr_128b[12],msg->payload+hlen,4); hlen += 4; break; case RH3_6LOTH_TYPE_3: memcpy(&firstAddr.addr_128b[8],msg->payload+hlen,8); hlen += 8; break; case RH3_6LOTH_TYPE_4: memcpy(&firstAddr.addr_128b[0],msg->payload+hlen,16); hlen += 16; break; } packetfunctions_ip128bToMac64b(self, &firstAddr,&temp_prefix,&temp_addr64); if ( packetfunctions_sameAddress(self, &temp_prefix, idmanager_getMyID(self, ADDR_PREFIX)) && packetfunctions_sameAddress(self, &temp_addr64, idmanager_getMyID(self, ADDR_64B)) ){ size = temp_8b & RH3_6LOTH_SIZE_MASK; if (size > 0){ // there are at least 2 entries in the header, // the router removes the first entry and decrements the Size (by 1) size -= 1; packetfunctions_tossHeader(self, msg,hlen); packetfunctions_reserveHeaderSize(self, msg,2); msg->payload[0] = CRITICAL_6LORH | size; msg->payload[1] = type; // get next hop memcpy(&nextAddr,&firstAddr,sizeof(open_addr_t)); switch(type){ case RH3_6LOTH_TYPE_0: memcpy(&nextAddr.addr_128b[15],msg->payload+2,1); break; case RH3_6LOTH_TYPE_1: memcpy(&nextAddr.addr_128b[14],msg->payload+2,2); break; case RH3_6LOTH_TYPE_2: memcpy(&nextAddr.addr_128b[12],msg->payload+2,4); break; case RH3_6LOTH_TYPE_3: memcpy(&nextAddr.addr_128b[8],msg->payload+2,8); break; case RH3_6LOTH_TYPE_4: memcpy(&nextAddr.addr_128b[0],msg->payload+2,16); break; } packetfunctions_ip128bToMac64b(self, &nextAddr, &temp_prefix, &msg->l2_nextORpreviousHop ); } else { temp_8b = *((uint8_t*)(msg->payload)+hlen); next_type = *((uint8_t*)(msg->payload)+hlen+1); if ( (temp_8b & FORMAT_6LORH_MASK) == CRITICAL_6LORH && next_type<=RH3_6LOTH_TYPE_4 ) { // there is another RH3-6LoRH following, check the type if (next_type >= type){ packetfunctions_tossHeader(self, msg,hlen); // get next hop memcpy(&nextAddr,&firstAddr,sizeof(open_addr_t)); switch(next_type){ case RH3_6LOTH_TYPE_0: memcpy(&nextAddr.addr_128b[15],msg->payload+2,1); break; case RH3_6LOTH_TYPE_1: memcpy(&nextAddr.addr_128b[14],msg->payload+2,2); break; case RH3_6LOTH_TYPE_2: memcpy(&nextAddr.addr_128b[12],msg->payload+2,4); break; case RH3_6LOTH_TYPE_3: memcpy(&nextAddr.addr_128b[8],msg->payload+2,8); break; case RH3_6LOTH_TYPE_4: memcpy(&nextAddr.addr_128b[0],msg->payload+2,16); break; } packetfunctions_ip128bToMac64b(self, &nextAddr, &temp_prefix, &msg->l2_nextORpreviousHop ); } else { hlen += 2; switch(next_type){ case RH3_6LOTH_TYPE_0: memcpy(&firstAddr.addr_128b[15],msg->payload+hlen,1); hlen += 1; break; case RH3_6LOTH_TYPE_1: memcpy(&firstAddr.addr_128b[14],msg->payload+hlen,2); hlen += 2; break; case RH3_6LOTH_TYPE_2: memcpy(&firstAddr.addr_128b[12],msg->payload+hlen,4); hlen += 4; break; case RH3_6LOTH_TYPE_3: memcpy(&firstAddr.addr_128b[8],msg->payload+hlen,8); hlen += 8; break; } next_size = temp_8b & RH3_6LOTH_SIZE_MASK; packetfunctions_tossHeader(self, msg,hlen); if (next_size>0){ next_size -= 1; packetfunctions_reserveHeaderSize(self, msg,2); msg->payload[0] = CRITICAL_6LORH | next_size; msg->payload[1] = next_type; } // add first address switch(type){ case RH3_6LOTH_TYPE_0: packetfunctions_reserveHeaderSize(self, msg,1); msg->payload[0] = firstAddr.addr_128b[15]; break; case RH3_6LOTH_TYPE_1: packetfunctions_reserveHeaderSize(self, msg,2); memcpy(&msg->payload[0],&firstAddr.addr_128b[14],2); break; case RH3_6LOTH_TYPE_2: packetfunctions_reserveHeaderSize(self, msg,4); memcpy(&msg->payload[0],&firstAddr.addr_128b[12],4); break; case RH3_6LOTH_TYPE_3: packetfunctions_reserveHeaderSize(self, msg,8); memcpy(&msg->payload[0],&firstAddr.addr_128b[8],8); break; case RH3_6LOTH_TYPE_4: packetfunctions_reserveHeaderSize(self, msg,16); memcpy(&msg->payload[0],&firstAddr.addr_128b[0],16); break; } packetfunctions_reserveHeaderSize(self, msg,2); msg->payload[0] = CRITICAL_6LORH | 0; msg->payload[1] = type; packetfunctions_ip128bToMac64b(self, &firstAddr, &temp_prefix, &msg->l2_nextORpreviousHop ); } } else { // there is no next RH3-6loRH, remove current one packetfunctions_tossHeader(self, msg,hlen); packetfunctions_ip128bToMac64b(self, &msg->l3_destinationAdd, &temp_prefix, &msg->l2_nextORpreviousHop ); } } } else { // log error openserial_printError(self, COMPONENT_IPHC, ERR_6LOWPAN_UNSUPPORTED, (errorparameter_t)16, (errorparameter_t)(temp_addr64.addr_64b[7]) ); } // copy RH3s before toss them if ( ipv6_outer_header->src.type != ADDR_NONE && ipv6_outer_header->hopByhop_option != NULL ){ // check the length of RH3s RH3_length = ipv6_outer_header->hopByhop_option-msg->payload; memcpy(&RH3_copy[0],msg->payload,RH3_length); packetfunctions_tossHeader(self, msg,RH3_length); // retrieve hop-by-hop header (includes RPL option) rpi_length = iphc_retrieveIPv6HopByHopHeader(self, msg, rpl_option ); // toss the headers packetfunctions_tossHeader(self, msg, rpi_length ); flags = rpl_option->flags; senderRank = rpl_option->senderRank; if ((flags & O_FLAG)!=O_FLAG){ // wrong direction // log error openserial_printError(self, COMPONENT_FORWARDING, ERR_WRONG_DIRECTION, (errorparameter_t)flags, (errorparameter_t)senderRank ); } if (senderRank > neighbors_getMyDAGrank(self)){ // loop detected // set flag rpl_option->flags |= R_FLAG; // log error openserial_printError(self, COMPONENT_FORWARDING, ERR_LOOP_DETECTED, (errorparameter_t) senderRank, (errorparameter_t) neighbors_getMyDAGrank(self) ); } forwarding_createRplOption(self, rpl_option, rpl_option->flags); // toss the IP in IP 6LoRH packetfunctions_tossHeader(self, msg, ipv6_outer_header->header_length); } else { RH3_length = 0; } // send to next lower layer return iphc_sendFromForwarding(self, msg, ipv6_outer_header, ipv6_inner_header, rpl_option, &ipv6_outer_header->flow_label, &RH3_copy[0], RH3_length, PCKTFORWARD ); }
/** \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; }
bool topology_isAcceptablePacket(ieee802154_header_iht* ieee802514_header) { #ifdef FORCETOPOLOGY bool returnVal; returnVal=FALSE; uint16_t my_addr = idmanager_getMyID(ADDR_64B)->addr_64b[7] | (idmanager_getMyID(ADDR_64B)->addr_64b[6] << 8); uint16_t src_addr = ieee802514_header->src.addr_64b[7] | (ieee802514_header->src.addr_64b[6] << 8); switch (my_addr) { case 0x0001: if ( src_addr==0x0002|| src_addr==0x0003|| src_addr==0x0004|| src_addr==0x0005|| src_addr==0x0006|| src_addr==0x0007|| src_addr==0x0008|| src_addr==0x0009|| src_addr==0x000a|| src_addr==0x000b|| src_addr==0x000c|| src_addr==0x000d|| src_addr==0x000e|| src_addr==0x000f ) { returnVal=TRUE; } break; case 0x0002: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0003: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0004: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0005: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0006: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0007: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0008: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x0009: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x000a: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x000b: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x000c: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x000d: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x000e: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; case 0x000f: if ( src_addr==0x0001 ) { returnVal=TRUE; } break; } return returnVal; #else return TRUE; #endif }
/** \brief Initialize this module. */ void icmpv6rpl_init() { uint8_t dodagid[16]; uint32_t dioPeriod; uint32_t daoPeriod; // retrieve my prefix and EUI64 memcpy(&dodagid[0],idmanager_getMyID(ADDR_PREFIX)->prefix,8); // prefix memcpy(&dodagid[8],idmanager_getMyID(ADDR_64B)->addr_64b,8); // eui64 //===== reset local variables memset(&icmpv6rpl_vars,0,sizeof(icmpv6rpl_vars_t)); //=== admin icmpv6rpl_vars.busySending = FALSE; icmpv6rpl_vars.fDodagidWritten = 0; //=== DIO icmpv6rpl_vars.dio.rplinstanceId = 0x00; ///< TODO: put correct value icmpv6rpl_vars.dio.verNumb = 0x00; ///< TODO: put correct value // rank: to be populated upon TX icmpv6rpl_vars.dio.rplOptions = MOP_DIO_A | \ MOP_DIO_B | \ MOP_DIO_C | \ PRF_DIO_A | \ PRF_DIO_B | \ PRF_DIO_C | \ G_DIO ; icmpv6rpl_vars.dio.DTSN = 0x33; ///< TODO: put correct value icmpv6rpl_vars.dio.flags = 0x00; icmpv6rpl_vars.dio.reserved = 0x00; memcpy( &(icmpv6rpl_vars.dio.DODAGID[0]), dodagid, sizeof(icmpv6rpl_vars.dio.DODAGID) ); // can be replaced later icmpv6rpl_vars.dioDestination.type = ADDR_128B; memcpy(&icmpv6rpl_vars.dioDestination.addr_128b[0],all_routers_multicast,sizeof(all_routers_multicast)); icmpv6rpl_vars.dioPeriod = TIMER_DIO_TIMEOUT; dioPeriod = icmpv6rpl_vars.dioPeriod - 0x80 + (openrandom_get16b()&0xff); icmpv6rpl_vars.timerIdDIO = opentimers_start( dioPeriod, TIMER_PERIODIC, TIME_MS, icmpv6rpl_timer_DIO_cb ); //=== DAO icmpv6rpl_vars.dao.rplinstanceId = 0x00; ///< TODO: put correct value icmpv6rpl_vars.dao.K_D_flags = FLAG_DAO_A | \ FLAG_DAO_B | \ FLAG_DAO_C | \ FLAG_DAO_D | \ FLAG_DAO_E | \ PRF_DIO_C | \ FLAG_DAO_F | \ D_DAO | K_DAO; icmpv6rpl_vars.dao.reserved = 0x00; icmpv6rpl_vars.dao.DAOSequence = 0x00; memcpy( &(icmpv6rpl_vars.dao.DODAGID[0]), dodagid, sizeof(icmpv6rpl_vars.dao.DODAGID) ); // can be replaced later icmpv6rpl_vars.dao_transit.type = OPTION_TRANSIT_INFORMATION_TYPE; // optionLength: to be populated upon TX icmpv6rpl_vars.dao_transit.E_flags = E_DAO_Transit_Info; icmpv6rpl_vars.dao_transit.PathControl = PC1_A_DAO_Transit_Info | \ PC1_B_DAO_Transit_Info | \ PC2_A_DAO_Transit_Info | \ PC2_B_DAO_Transit_Info | \ PC3_A_DAO_Transit_Info | \ PC3_B_DAO_Transit_Info | \ PC4_A_DAO_Transit_Info | \ PC4_B_DAO_Transit_Info; icmpv6rpl_vars.dao_transit.PathSequence = 0x00; // to be incremented at each TX icmpv6rpl_vars.dao_transit.PathLifetime = 0xAA; //target information icmpv6rpl_vars.dao_target.type = OPTION_TARGET_INFORMATION_TYPE; icmpv6rpl_vars.dao_target.optionLength = 0; icmpv6rpl_vars.dao_target.flags = 0; icmpv6rpl_vars.dao_target.prefixLength = 0; icmpv6rpl_vars.daoPeriod = TIMER_DAO_TIMEOUT; daoPeriod = icmpv6rpl_vars.daoPeriod - 0x80 + (openrandom_get16b()&0xff); icmpv6rpl_vars.timerIdDAO = opentimers_start( daoPeriod, TIMER_PERIODIC, TIME_MS, icmpv6rpl_timer_DAO_cb ); }
error_t fowarding_send_internal_SourceRouting(OpenQueueEntry_t *msg, ipv6_header_iht ipv6_header) { // It has to be forwarded to dest. so, next hop should be extracted from the message. uint8_t local_CmprE; uint8_t local_CmprI,numAddr,hlen; uint8_t addressposition; uint8_t* runningPointer; uint8_t octetsAddressSize; ipv6_Source_Routing_Header_t * ipv6_Source_Routing_Header; open_addr_t* prefix=idmanager_getMyID(ADDR_PREFIX); ipv6_Source_Routing_Header=(ipv6_Source_Routing_Header_t*)(msg->payload); runningPointer=(msg->payload) + sizeof(ipv6_Source_Routing_Header_t); // getting local_CmprE and CmprI; local_CmprE=ipv6_Source_Routing_Header->CmprICmprE & 0xf; local_CmprI= ipv6_Source_Routing_Header->CmprICmprE & 0xf0; //local_CmprI>>4; // shifting it by 4. local_CmprI=local_CmprI>>4; // shifting it by 4. // foundFlag=0; //see processing header algorithm in RFC6554 page 9 numAddr=(((ipv6_Source_Routing_Header->HdrExtLen*8)-ipv6_Source_Routing_Header->PadRes -(16-local_CmprE))/(16-local_CmprI))+1; if(ipv6_Source_Routing_Header->SegmentsLeft==0){ //we are there!.. //process the next header in the pkt.. i.e push stack up.. msg->l4_protocol=ipv6_Source_Routing_Header->nextHeader; hlen=ipv6_Source_Routing_Header->HdrExtLen; //toss header packetfunctions_tossHeader(msg,sizeof(ipv6_Source_Routing_Header_t)); //toss list of addresses. if(local_CmprE==0) { octetsAddressSize=2; //remove packetfunctions_tossHeader(msg,octetsAddressSize*hlen); } else if(local_CmprE==8) { octetsAddressSize=8; packetfunctions_tossHeader(msg,octetsAddressSize*hlen); } else if(local_CmprE==2) { octetsAddressSize=16; packetfunctions_tossHeader(msg,octetsAddressSize*hlen); } else { msg->l2_nextORpreviousHop.type = ADDR_NONE; //error! while(1); } switch(msg->l4_protocol) { case IANA_TCP: opentcp_receive(msg); break; case IANA_UDP: openudp_receive(msg); break; case IANA_ICMPv6: icmpv6_receive(msg); break; default: openserial_printError(COMPONENT_FORWARDING,ERR_WRONG_TRAN_PROTOCOL, (errorparameter_t)msg->l4_protocol, (errorparameter_t)1); } return E_SUCCESS; }else{ if(ipv6_Source_Routing_Header->SegmentsLeft>numAddr){ //not good.. error. //send and ICMPv6 parameter problem, code 0, to the src address //then discard the packet. //TODO while (1); }else{ //still hops remaining ipv6_Source_Routing_Header->SegmentsLeft--; //find the address in the vector. addressposition=numAddr-(ipv6_Source_Routing_Header->SegmentsLeft); if(local_CmprE==0) { msg->l2_nextORpreviousHop.type = ADDR_16B; msg->l3_destinationAdd.type = ADDR_16B; octetsAddressSize=2; memcpy(&(msg->l2_nextORpreviousHop.addr_16b),runningPointer+((addressposition-1)*octetsAddressSize),octetsAddressSize); memcpy(&(msg->l3_destinationAdd.addr_16b),runningPointer+((addressposition-1)*octetsAddressSize),octetsAddressSize); } else if(local_CmprE==8) { msg->l2_nextORpreviousHop.type = ADDR_64B; msg->l3_destinationAdd.type = ADDR_128B; octetsAddressSize=8; memcpy(&(msg->l2_nextORpreviousHop.addr_64b),runningPointer+((addressposition-1)*octetsAddressSize),octetsAddressSize); memcpy(&(msg->l3_destinationAdd.addr_128b[0]),prefix->prefix,8); memcpy(&(msg->l3_destinationAdd.addr_128b[8]),runningPointer+((addressposition-1)*octetsAddressSize),octetsAddressSize); } else if(local_CmprE==2) { msg->l2_nextORpreviousHop.type = ADDR_128B; msg->l3_destinationAdd.type = ADDR_128B; octetsAddressSize=16; memcpy(&(msg->l2_nextORpreviousHop.addr_128b),runningPointer+((addressposition-1)*octetsAddressSize),octetsAddressSize); memcpy(&(msg->l3_destinationAdd.addr_128b),runningPointer+((addressposition-1)*octetsAddressSize),octetsAddressSize); } else { msg->l2_nextORpreviousHop.type = ADDR_NONE; //error! while(1); } } } if (msg->l2_nextORpreviousHop.type==ADDR_NONE) { openserial_printError(COMPONENT_FORWARDING,ERR_NO_NEXTHOP, (errorparameter_t)0, (errorparameter_t)0); return E_FAIL; } return iphc_sendFromForwarding(msg, ipv6_header,PCKTFORWARD); }
/** \brief Send a packet originating at this mote. This function is called by an upper layer, and only concerns packets originated at this mote. \param[in,out] msg Packet to send. */ owerror_t forwarding_send(OpenMote* self, OpenQueueEntry_t* msg) { ipv6_header_iht ipv6_outer_header; ipv6_header_iht ipv6_inner_header; rpl_option_ht rpl_option; open_addr_t* myprefix; open_addr_t* myadd64; uint32_t flow_label = 0; open_addr_t temp_dest_prefix; open_addr_t temp_dest_mac64b; open_addr_t* p_dest; open_addr_t* p_src; open_addr_t temp_src_prefix; open_addr_t temp_src_mac64b; uint8_t sam; uint8_t m; uint8_t dam; // take ownership over the packet msg->owner = COMPONENT_FORWARDING; m = IPHC_M_NO; // retrieve my prefix and EUI64 myprefix = idmanager_getMyID(self, ADDR_PREFIX); myadd64 = idmanager_getMyID(self, ADDR_64B); // set source address (me) msg->l3_sourceAdd.type=ADDR_128B; memcpy(&(msg->l3_sourceAdd.addr_128b[0]),myprefix->prefix,8); memcpy(&(msg->l3_sourceAdd.addr_128b[8]),myadd64->addr_64b,8); // initialize IPv6 header memset(&ipv6_outer_header,0,sizeof(ipv6_header_iht)); memset(&ipv6_inner_header,0,sizeof(ipv6_header_iht)); // Set hop limit to the default in-network value as this packet is being // sent from upper layer. This is done here as send_internal() is used by // forwarding of packets as well which carry a hlim. This value is required // to be set to a value as the following function can decrement it. ipv6_inner_header.hop_limit = IPHC_DEFAULT_HOP_LIMIT; // create the RPL hop-by-hop option forwarding_createRplOption(self, &rpl_option, // rpl_option to fill in 0x00 // flags ); packetfunctions_ip128bToMac64b(self, &(msg->l3_destinationAdd),&temp_dest_prefix,&temp_dest_mac64b); //xv poipoi -- get the src prefix as well packetfunctions_ip128bToMac64b(self, &(msg->l3_sourceAdd),&temp_src_prefix,&temp_src_mac64b); //XV -poipoi we want to check if the source address prefix is the same as destination prefix if ( packetfunctions_sameAddress(self, &temp_dest_prefix,&temp_src_prefix)) { // same prefix use 64B address sam = IPHC_SAM_64B; dam = IPHC_DAM_64B; p_dest = &temp_dest_mac64b; p_src = &temp_src_mac64b; } else { //not the same prefix. so the packet travels to another network //check if this is a source routing pkt. in case it is then the DAM is elided as it is in the SrcRouting header. if ( packetfunctions_isBroadcastMulticast(self, &(msg->l3_destinationAdd))==FALSE){ sam = IPHC_SAM_128B; dam = IPHC_DAM_128B; p_dest = &(msg->l3_destinationAdd); p_src = &(msg->l3_sourceAdd); ipv6_outer_header.src.type = ADDR_128B; memcpy(&ipv6_outer_header.src,p_src,sizeof(open_addr_t)); ipv6_outer_header.hop_limit = IPHC_DEFAULT_HOP_LIMIT; } else { // this is DIO, source address elided, multicast bit is set sam = IPHC_SAM_ELIDED; m = IPHC_M_YES; dam = IPHC_DAM_ELIDED; p_dest = &(msg->l3_destinationAdd); p_src = &(msg->l3_sourceAdd); } } //IPHC inner header and NHC IPv6 header will be added at here iphc_prependIPv6Header(self, msg, IPHC_TF_ELIDED, flow_label, // value_flowlabel IPHC_NH_INLINE, msg->l4_protocol, IPHC_HLIM_64, ipv6_outer_header.hop_limit, IPHC_CID_NO, IPHC_SAC_STATELESS, sam, m, IPHC_DAC_STATELESS, dam, p_dest, p_src, PCKTSEND ); // both of them are compressed ipv6_outer_header.next_header_compressed = TRUE; return forwarding_send_internal_RoutingTable(self, msg, &ipv6_outer_header, &ipv6_inner_header, &rpl_option, &flow_label, PCKTSEND ); }
void rreg_timer() { OpenQueueEntry_t* pkt; uint8_t temp8b; error_t outcome; uint8_t numOptions; // create a CoAP RD packet pkt = openqueue_getFreePacketBuffer(COMPONENT_RREG); if (pkt==NULL) { openserial_printError(COMPONENT_RREG,ERR_NO_FREE_PACKET_BUFFER, (errorparameter_t)0, (errorparameter_t)0); openqueue_freePacketBuffer(pkt); return; } // take ownership over that packet pkt->creator = COMPONENT_RREG; pkt->owner = COMPONENT_RREG; // CoAP payload opencoap_writeLinks(pkt); numOptions = 0; // URI-query packetfunctions_reserveHeaderSize(pkt,sizeof(rreg_uriquery)-1+2); memcpy(&pkt->payload[0],&rreg_uriquery,sizeof(rreg_uriquery)-1); temp8b = idmanager_getMyID(ADDR_16B)->addr_16b[1]; pkt->payload[sizeof(rreg_uriquery)-1] = hexToAscii((temp8b>>4) & 0x0f); pkt->payload[sizeof(rreg_uriquery)-0] = hexToAscii((temp8b>>0) & 0x0f); packetfunctions_reserveHeaderSize(pkt,1); pkt->payload[0] = (COAP_OPTION_URIQUERY-COAP_OPTION_URIPATH) << 4 | sizeof(rreg_uriquery)-1+2; numOptions++; // URI-path packetfunctions_reserveHeaderSize(pkt,2); pkt->payload[0] = 'r'; pkt->payload[1] = 'd'; packetfunctions_reserveHeaderSize(pkt,1); pkt->payload[0] = (COAP_OPTION_URIPATH-COAP_OPTION_CONTENTTYPE) << 4 | 2; numOptions++; // add content-type option packetfunctions_reserveHeaderSize(pkt,2); pkt->payload[0] = COAP_OPTION_CONTENTTYPE << 4 | 1; pkt->payload[1] = COAP_MEDTYPE_APPLINKFORMAT; numOptions++; // metadata pkt->l4_destination_port = WKP_UDP_COAP; pkt->l3_destinationORsource.type = ADDR_128B; memcpy(&pkt->l3_destinationORsource.addr_128b[0],&ipAddr_ipsoRD,16); // send outcome = opencoap_send(pkt, COAP_TYPE_CON, COAP_CODE_REQ_POST, numOptions, &rreg_vars.desc); // avoid overflowing the queue if fails if (outcome==E_FAIL) { openqueue_freePacketBuffer(pkt); } return; }
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; }
/** \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 Force a topology. This function is used to force a certain topology, by hard-coding the list of acceptable neighbors for a given mote. This function is invoked each time a packet is received. If it returns FALSE, the packet is silently dropped, as if it were never received. If it returns TRUE, the packet is accepted. Typically, filtering packets is done by analyzing the IEEE802.15.4 header. An example body for this function which forces a topology is: switch (idmanager_getMyID(ADDR_64B)->addr_64b[7]) { case TOPOLOGY_MOTE1: if (ieee802514_header->src.addr_64b[7]==TOPOLOGY_MOTE2) { returnVal=TRUE; } else { returnVal=FALSE; } break; case TOPOLOGY_MOTE2: if (ieee802514_header->src.addr_64b[7]==TOPOLOGY_MOTE1 || ieee802514_header->src.addr_64b[7]==TOPOLOGY_MOTE3) { returnVal=TRUE; } else { returnVal=FALSE; } break; default: returnVal=TRUE; } return returnVal; By default, however, the function should return TRUE to *not* force any topology. \param[in] ieee802514_header The parsed IEEE802.15.4 MAC header. \return TRUE if the packet can be received. \return FALSE if the packet should be silently dropped. */ bool topology_isAcceptablePacket(ieee802154_header_iht* ieee802514_header) { #ifdef PLUGFEST bool returnVal; returnVal=FALSE; switch (idmanager_getMyID(ADDR_64B)->addr_64b[7]) { case 0x4c: if ( ieee802514_header->src.addr_64b[7]==0x00 || ieee802514_header->src.addr_64b[7]==0x60 ) { returnVal=TRUE; } break; case 0x60: if ( ieee802514_header->src.addr_64b[7]==0x4c || ieee802514_header->src.addr_64b[7]==0x97 || ieee802514_header->src.addr_64b[7]==0xc8 ) { returnVal=TRUE; } break; case 0xc8: if ( ieee802514_header->src.addr_64b[7]==0x60 || ieee802514_header->src.addr_64b[7]==0x6f || ieee802514_header->src.addr_64b[7]==0x50 ) { returnVal=TRUE; } break; case 0x50: if ( ieee802514_header->src.addr_64b[7]==0xc8 ) { returnVal=TRUE; } break; case 0x6f: if ( ieee802514_header->src.addr_64b[7]==0x85 || ieee802514_header->src.addr_64b[7]==0x97 || ieee802514_header->src.addr_64b[7]==0xc8 ) { returnVal=TRUE; } break; case 0x85: if ( ieee802514_header->src.addr_64b[7]==0x5c || ieee802514_header->src.addr_64b[7]==0x97 || ieee802514_header->src.addr_64b[7]==0x6f ) { returnVal=TRUE; } break; case 0xa8: if ( ieee802514_header->src.addr_64b[7]==0x5c || ieee802514_header->src.addr_64b[7]==0x97 || ieee802514_header->src.addr_64b[7]==0x00 ) { returnVal=TRUE; } break; case 0x00: if ( ieee802514_header->src.addr_64b[7]==0x4c || ieee802514_header->src.addr_64b[7]==0xa8 ) { returnVal=TRUE; } break; case 0x97: if ( ieee802514_header->src.addr_64b[7]==0xa8 || ieee802514_header->src.addr_64b[7]==0x85 || ieee802514_header->src.addr_64b[7]==0x6f || ieee802514_header->src.addr_64b[7]==0x60 ) { returnVal=TRUE; } break; case 0x5c: if ( ieee802514_header->src.addr_64b[7]==0x85 || ieee802514_header->src.addr_64b[7]==0xa8 ) { returnVal=TRUE; } break; } return returnVal; #else return TRUE; #endif }