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); } } } }
/** \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) {
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 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 ); } } } }