/** \brief Indicate some packet was sent to some neighbor. This function should be called for each transmitted (non-ACK) packet so neighbor statistics in the neighbor table can be updated. The fields which are updated are: - numTx - numTxACK - asn \param[in] l2_dest MAC destination address of the packet, i.e. the neighbor who I just sent the packet to. \param[in] numTxAttempts Number of transmission attempts to this neighbor. \param[in] was_finally_acked TRUE iff the packet was ACK'ed by the neighbor on final transmission attempt. \param[in] asnTs ASN of the last transmission attempt. */ void neighbors_indicateTx(open_addr_t* l2_dest, uint8_t numTxAttempts, bool was_finally_acked, asn_t* asnTs) { uint8_t i; // don't run through this function if packet was sent to broadcast address if (packetfunctions_isBroadcastMulticast(l2_dest)==TRUE) { return; } // loop through neighbor table for (i=0;i<MAXNUMNEIGHBORS;i++) { if (isThisRowMatching(l2_dest,i)) { // handle roll-over case if (neighbors_vars.neighbors[i].numTx>(0xff-numTxAttempts)) { neighbors_vars.neighbors[i].numWraps++; //counting the number of times that tx wraps. neighbors_vars.neighbors[i].numTx/=2; neighbors_vars.neighbors[i].numTxACK/=2; } // update statistics neighbors_vars.neighbors[i].numTx += numTxAttempts; if (was_finally_acked==TRUE) { neighbors_vars.neighbors[i].numTxACK++; memcpy(&neighbors_vars.neighbors[i].asn,asnTs,sizeof(asn_t)); } break; } } }
OpenQueueEntry_t* openqueue_macGetDataPacket(open_addr_t* toNeighbor) { uint8_t i; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); if (toNeighbor->type==ADDR_64B) { // a neighbor is specified, look for a packet unicast to that neigbhbor for (i=0;i<QUEUELENGTH;i++) { if (openqueue_vars.queue[i].owner==COMPONENT_RES_TO_IEEE802154E && packetfunctions_sameAddress(toNeighbor,&openqueue_vars.queue[i].l2_nextORpreviousHop)) { ENABLE_INTERRUPTS(); return &openqueue_vars.queue[i]; } } } else if (toNeighbor->type==ADDR_ANYCAST) { // anycast case: look for a packet which is either not created by RES // or an KA (created by RES, but not broadcast) for (i=0;i<QUEUELENGTH;i++) { if (openqueue_vars.queue[i].owner==COMPONENT_RES_TO_IEEE802154E && ( openqueue_vars.queue[i].creator!=COMPONENT_RES || ( openqueue_vars.queue[i].creator==COMPONENT_RES && packetfunctions_isBroadcastMulticast(&(openqueue_vars.queue[i].l2_nextORpreviousHop))==FALSE ) ) ) { ENABLE_INTERRUPTS(); return &openqueue_vars.queue[i]; } } } ENABLE_INTERRUPTS(); return NULL; }
/** \brief Transfer packet to MAC. This function adds a IEEE802.15.4 header to the packet and leaves it the OpenQueue buffer. The very last thing it does is assigning this packet to the virtual component COMPONENT_RES_TO_IEEE802154E. Whenever it gets a change, IEEE802154E will handle the packet. \param [in] msg The packet to the transmitted \returns E_SUCCESS iff successful. */ error_t res_send_internal(OpenQueueEntry_t* msg) { // assign a number of retries if (packetfunctions_isBroadcastMulticast(&(msg->l2_nextORpreviousHop))==TRUE) { msg->l2_retriesLeft = 1; } else { msg->l2_retriesLeft = TXRETRIES; } // record this packet's dsn (for matching the ACK) msg->l2_dsn = res_vars.dsn++; // this is a new packet which I never attempted to send msg->l2_numTxAttempts = 0; // transmit with the default TX power msg->l1_txPower = TX_POWER; // record the location, in the packet, where the l2 payload starts msg->l2_payload = msg->payload; // add a IEEE802.15.4 header ieee802154_prependHeader(msg, msg->l2_frameType, IEEE154_SEC_NO_SECURITY, msg->l2_dsn, &(msg->l2_nextORpreviousHop) ); // reserve space for 2-byte CRC packetfunctions_reserveFooterSize(msg,2); // change owner to IEEE802154E fetches it from queue msg->owner = COMPONENT_RES_TO_IEEE802154E; return E_SUCCESS; }
OpenQueueEntry_t* openqueue_macGetAdvPacket() { uint8_t i; INTERRUPT_DECLARATION(); DISABLE_INTERRUPTS(); for (i=0;i<QUEUELENGTH;i++) { if (openqueue_vars.queue[i].owner==COMPONENT_RES_TO_IEEE802154E && openqueue_vars.queue[i].creator==COMPONENT_RES && packetfunctions_isBroadcastMulticast(&(openqueue_vars.queue[i].l2_nextORpreviousHop))) { ENABLE_INTERRUPTS(); return &openqueue_vars.queue[i]; } } ENABLE_INTERRUPTS(); return NULL; }
void forwarding_receive(OpenQueueEntry_t* msg, ipv6_header_iht ipv6_header) { msg->owner = COMPONENT_FORWARDING; msg->l4_protocol = ipv6_header.next_header; msg->l4_protocol_compressed = ipv6_header.next_header_compressed; if ((idmanager_isMyAddress(&ipv6_header.dest) || packetfunctions_isBroadcastMulticast(&ipv6_header.dest)) && ipv6_header.next_header!=SourceFWNxtHdr) {//for me and not having src routing header //destination address its me. memcpy(&(msg->l3_destinationAdd),&ipv6_header.dest,sizeof(open_addr_t)); memcpy(&(msg->l3_sourceAdd),&ipv6_header.src,sizeof(open_addr_t)); 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); } } else { //relay memcpy(&(msg->l3_destinationAdd),&ipv6_header.dest,sizeof(open_addr_t));//because initially contains source memcpy(&(msg->l3_sourceAdd),&ipv6_header.src,sizeof(open_addr_t)); //>>>>>> diodio //TBC: source address gets changed! // change the creator to this components (should have been MAC) msg->creator = COMPONENT_FORWARDING; if(ipv6_header.next_header !=SourceFWNxtHdr) { // resend as if from upper layer //>>>>>> diodio if (fowarding_send_internal(msg, ipv6_header,PCKTFORWARD)==E_FAIL) { openqueue_freePacketBuffer(msg); } } else { // source route if (fowarding_send_internal_SourceRouting(msg, ipv6_header)==E_FAIL) { openqueue_freePacketBuffer(msg); } } } }
void getNextHop(open_addr_t* destination128b, open_addr_t* addressToWrite64b) { uint8_t i; open_addr_t temp_prefix64btoWrite; if (packetfunctions_isBroadcastMulticast(destination128b)) { // IP destination is broadcast, send to 0xffffffffffffffff addressToWrite64b->type = ADDR_64B; for (i=0;i<8;i++) { addressToWrite64b->addr_64b[i] = 0xff; } } else if (neighbors_isStableNeighbor(destination128b)) { // IP destination is 1-hop neighbor, send directly packetfunctions_ip128bToMac64b(destination128b,&temp_prefix64btoWrite,addressToWrite64b); } else { // destination is remote, send to preferred parent neighbors_getPreferredParent(addressToWrite64b,ADDR_64B); } }
void neighbors_indicateTx(open_addr_t* dest, uint8_t numTxAttempts, bool was_finally_acked, asn_t* asnTimestamp) { uint8_t i=0; if (packetfunctions_isBroadcastMulticast(dest)==FALSE) { for (i=0;i<MAXNUMNEIGHBORS;i++) { if (isThisRowMatching(dest,i)) { if (neighbors_vars.neighbors[i].numTx==255) { neighbors_vars.neighbors[i].numTx/=2; neighbors_vars.neighbors[i].numTxACK/=2; } neighbors_vars.neighbors[i].numTx += numTxAttempts; if (was_finally_acked==TRUE) { neighbors_vars.neighbors[i].numTxACK++; memcpy(&neighbors_vars.neighbors[i].asn,asnTimestamp,sizeof(asn_t)); } return; } } } }
/** \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; }
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; }
/** \brief Indicates a packet was received. \param[in,out] msg The packet just sent. \param[in] ipv6_header The information contained in the IPv6 header. \param[in] ipv6_hop_header The hop-by-hop header present in the packet. \param[in] rpl_option The hop-by-hop options present in the packet. */ void forwarding_receive( OpenQueueEntry_t* msg, ipv6_header_iht* ipv6_header, ipv6_hopbyhop_iht* ipv6_hop_header, rpl_option_ht* rpl_option ) { uint8_t flags; uint16_t senderRank; // take ownership msg->owner = COMPONENT_FORWARDING; // determine L4 protocol if (ipv6_header->next_header==IANA_IPv6HOPOPT){ // get information from ipv6_hop_header msg->l4_protocol = ipv6_hop_header->nextHeader; msg->l4_protocol_compressed = ipv6_hop_header->next_header_compressed; } else { // get information from ipv6_header msg->l4_protocol = ipv6_header->next_header; msg->l4_protocol_compressed = ipv6_header->next_header_compressed; } // populate packets metadata with L3 information memcpy(&(msg->l3_destinationAdd),&ipv6_header->dest,sizeof(open_addr_t)); memcpy(&(msg->l3_sourceAdd), &ipv6_header->src, sizeof(open_addr_t)); if ( ( idmanager_isMyAddress(&ipv6_header->dest) || packetfunctions_isBroadcastMulticast(&ipv6_header->dest) ) && ipv6_header->next_header!=IANA_IPv6ROUTE ) { // this packet is for me, no source routing header. // indicate received packet to upper layer 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: // log error openserial_printError( COMPONENT_FORWARDING,ERR_WRONG_TRAN_PROTOCOL, (errorparameter_t)msg->l4_protocol, (errorparameter_t)1 ); // free packet openqueue_freePacketBuffer(msg); } } else { // this packet is not for me: relay // change the creator of the packet msg->creator = COMPONENT_FORWARDING; if (ipv6_header->next_header!=IANA_IPv6ROUTE) { // no source routing header present //check if flow label rpl header #ifdef FLOW_LABEL_RPL_DOMAIN flags = (uint8_t)((uint32_t)((ipv6_header->flow_label)>>16)&0xFF); senderRank = (uint16_t)((uint32_t)(ipv6_header->flow_label)>>8)&0xFFFF; senderRank = senderRank*MINHOPRANKINCREASE;//shift it according to HopRank Increase #else flags = rpl_option->flags; senderRank = rpl_option->senderRank; #endif if ((flags & O_FLAG)!=0){ // wrong direction // log error openserial_printError( COMPONENT_FORWARDING, ERR_WRONG_DIRECTION, (errorparameter_t)flags, (errorparameter_t)senderRank ); } if (senderRank < neighbors_getMyDAGrank()){ // loop // set flag #ifdef FLOW_LABEL_RPL_DOMAIN flags |= R_FLAG; ipv6_header->flow_label|= ((uint32_t)flags<<16); #else rpl_option->flags |= R_FLAG; #endif // log error openserial_printError( COMPONENT_FORWARDING, ERR_LOOP_DETECTED, (errorparameter_t) senderRank, (errorparameter_t) neighbors_getMyDAGrank() ); } forwarding_createRplOption(rpl_option, rpl_option->flags); #ifdef FLOW_LABEL_RPL_DOMAIN // do not recreate flow label, relay the same but adding current flags //forwarding_createFlowLabel(&(ipv6_header->flow_label),flags); #endif // resend as if from upper layer if ( forwarding_send_internal_RoutingTable( msg, ipv6_header, rpl_option, &(ipv6_header->flow_label), PCKTFORWARD )==E_FAIL ) { openqueue_freePacketBuffer(msg); } } else { // source routing header present if (forwarding_send_internal_SourceRouting(msg, ipv6_header)==E_FAIL) {
/** \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 ); }
/** \brief Indicates a packet was received. \param[in,out] msg The packet just sent. \param[in] ipv6_header The information contained in the IPv6 header. \param[in] ipv6_hop_header The hop-by-hop header present in the packet. \param[in] rpl_option The hop-by-hop options present in the packet. */ void forwarding_receive(OpenMote* self, OpenQueueEntry_t* msg, ipv6_header_iht* ipv6_outer_header, ipv6_header_iht* ipv6_inner_header, rpl_option_ht* rpl_option ) { uint8_t flags; uint16_t senderRank; // take ownership msg->owner = COMPONENT_FORWARDING; // determine L4 protocol // get information from ipv6_header msg->l4_protocol = ipv6_inner_header->next_header; msg->l4_protocol_compressed = ipv6_inner_header->next_header_compressed; // populate packets metadata with L3 information memcpy(&(msg->l3_destinationAdd),&ipv6_inner_header->dest, sizeof(open_addr_t)); memcpy(&(msg->l3_sourceAdd), &ipv6_inner_header->src, sizeof(open_addr_t)); if ( ( idmanager_isMyAddress(self, &(msg->l3_destinationAdd)) || packetfunctions_isBroadcastMulticast(self, &(msg->l3_destinationAdd)) ) && ipv6_outer_header->next_header!=IANA_IPv6ROUTE ) { if (ipv6_outer_header->src.type != ADDR_NONE){ packetfunctions_tossHeader(self, msg,ipv6_outer_header->header_length); } // this packet is for me, no source routing header // toss iphc inner header packetfunctions_tossHeader(self, msg,ipv6_inner_header->header_length); // indicate received packet to upper layer switch(msg->l4_protocol) { case IANA_TCP: opentcp_receive(self, msg); break; case IANA_UDP: openudp_receive(self, msg); break; case IANA_ICMPv6: icmpv6_receive(self, msg); break; default: // log error openserial_printError(self, COMPONENT_FORWARDING,ERR_WRONG_TRAN_PROTOCOL, (errorparameter_t)msg->l4_protocol, (errorparameter_t)1 ); // free packet openqueue_freePacketBuffer(self, msg); } } else { // this packet is not for me: relay // change the creator of the packet msg->creator = COMPONENT_FORWARDING; if (ipv6_outer_header->next_header!=IANA_IPv6ROUTE) { flags = rpl_option->flags; senderRank = rpl_option->senderRank; if ((flags & O_FLAG)!=0){ // 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); // resend as if from upper layer if ( forwarding_send_internal_RoutingTable(self, msg, ipv6_outer_header, ipv6_inner_header, rpl_option, &(ipv6_outer_header->flow_label), PCKTFORWARD )==E_FAIL ) { openqueue_freePacketBuffer(self, msg); } } else { // source routing header present if ( forwarding_send_internal_SourceRouting(self, msg, ipv6_outer_header, ipv6_inner_header, rpl_option )==E_FAIL ) { // log error openserial_printError(self, COMPONENT_FORWARDING, ERR_INVALID_FWDMODE, (errorparameter_t)0, (errorparameter_t)0 ); } } } }