📄 shr.h
字号:
printf( "SP: sn%08X; max hop %d; %f\n", pkt->hdr.seq_number, pkt->hdr.max_hop, SimTime());#endif // VISUAL_ROUTE } pkt->hdr.newSeqNumber = false; shrPrint( ("SP: ea %3d; sn%08X; actHC %2d; pathHC %2d; sending %s @ %f\n", (int) MyEtherAddr, pkt->hdr.seq_number, pkt->hdr.actual_hop, pkt->hdr.path.getLength(), pkt->dump().c_str(), SimTime())); SentPackets++; if( m_mac_busy == false) { m_mac_busy = true; m_active_packet = pkt; m_active_packet->inc_ref(); SendToMac( pkt); } else { shrPrint( ("SP: ea %3d; sn%08X; mac busy, delaying\n", (int) MyEtherAddr, pkt->hdr.seq_number)); AddToSendQueue( pkt); } return;}/*** SendToMac was added in February 2006.**** Its purpose is to simulate the small amount of time that elapses between** when the hardware stops sensing the carrier and it is able to actually start** transmission of the packet.**** For backwards compatibility, the transition time may be zero. In this case,** forward the packet directly to the mac layer instead of starting a timer.*/template <class PLD>void SHR<PLD>::SendToMac( packet_t *pkt){ m_mac_busy = true; if( transitionTime != 0) { // start timer transitionTimer.Set( SimTime() + transitionTime); // save packet transitionPkt = pkt; } else to_mac( pkt, pkt->hdr.size, 0); return;}/*** TransitionTimer was added in February 2006.**** Timer has expired indicating that the hardware has finished its transition** from sensing the carrier and is finally starting to transmit the packet.*/template <class PLD>void SHR<PLD>::TransitionTimer( trigger_t &){ // send saved packet to mac to_mac( transitionPkt, transitionPkt->hdr.size, 0); transitionPkt = 0; return;}/*** Find the packet's source address in this node's cache. If the entry is not** found, create it. If the hop count in the cache is greater than the hop** count of the packet, update the cache.**** Return true if the entry was created or updated, false otherwise.*/template <class PLD>bool SHR<PLD>::updateHopCountInCache( ether_addr_t dst, unsigned int hopCount, UpdateType type, const char *str, packet_t *mwl){ if( dst == MyEtherAddr) return false; cache_t::iterator iter; iter = m_seq_cache.find( dst); // If the destination address is not found, create a new record. if( iter == m_seq_cache.end()) { shrPrint( ("%10s: uHCIC: ea %3d; sn%08X; dst %3d; hc %2d new @ %f\n", str, (int) MyEtherAddr, mwl->hdr.seq_number, (int) dst, hopCount, SimTime())); iter = (m_seq_cache.insert( make_pair( dst, seq_number_t()))).first; iter->second.hopCount( hopCount, true, false); // true/false doesn't matter since the entry is new return true; } // if there's no change, return if( iter->second.hopCount() == hopCount) return false; // if the new packet won't update the cost table entry, return false if( type != Always && iter->second.hopCount() <= hopCount) return false; // update the cost table entry shrPrint( ("%10s: uHCIC: ea %3d; sn%08X; dst %3d; hc %2d->%2d update @ %f", str, (int) MyEtherAddr, mwl->hdr.seq_number, (int) dst, iter->second.hopCount(), hopCount, SimTime())); //mwl remember print in method hopCount iter->second.hopCount( hopCount, type == Hello ? true : false, shrDoPrint); return true;}/*** Interface that is used by the adjacency matrix channel model. Do not use** them with the radio model.*/template <class PLD>void SHR<PLD>::HelloTimer( trigger_t &){#ifdef USE_CONFIG_FILE// shrPrint( ("HT: ea %3d; HELLO timer @ %f\n", (int) MyEtherAddr, SimTime())); generateHELLO();#else // USE_CONFIG_FILE printf( "SHR::HelloTimer may only be used with a configuration file\n"); assert( 0);#endif // USE_CONFIG_FILE return;}template <class PLD>void SHR<PLD>::scheduleHELLO( double time){#ifdef USE_CONFIG_FILE printf( "schedHELLO: ea %3d @ %f ", (int) MyEtherAddr, time); if( backOff == SHRBackOff_SHR && RouteRepairEnabled == true) { printf( "enabled\n"); helloTimer.Set( time); } else printf( "ignored\n");#else // USE_CONFIG_FILE printf( "SHR::scheduleHELLO may only be used with a configuration file\n"); assert( 0);#endif // USE_CONFIG_FILE return;}/*** The inport that is called when the power manager wakes the node up.** If the configuration file is in use, this must be defined, but it must not** do anything*/template <class PLD>void SHR<PLD>::from_pm_node_up(){#ifndef USE_CONFIG_FILE generateHELLO();#endif // USE_CONFIG_FILE return;}/*** The node has just come back up. Send out a HELLO packet for each entry in** the Cost Table.*/template <class PLD>void SHR<PLD>::generateHELLO(){ cache_t::iterator iter; ether_addr_t dest; // convert entire cost table into hop count list for( iter = m_seq_cache.begin(); iter != m_seq_cache.end(); iter++) { packet_t *pkt; dest = iter->first; if( dest == MyEtherAddr) continue; pkt = (packet_t *) createHelloPkt( dest, iter->second.hopCount()); SendPacket( pkt); // send with new sequence number } return;}/*** The purpose of the HELLO packet is to inform the receiving node that sending** node has come back to life. The HELLO packet contains a list of <addr, dist>** pairs. For each pair, the node determines if the entry in its cost table** needs to be updated. If so, update the cost table and add the updated entry** to a list that will be used to generate a new HELLO packet. If no changes** are made to the cost table, then no HELLO packet is sent.*/template <class PLD>void SHR<PLD>::receiveHelloPacket( packet_t *pkt){ cache_t::iterator iter; ether_addr_t destAddr = pkt->hdr.dst_addr; int hopCount = pkt->hdr.helloData; shrPrint( ("rHP: ea %3d; from %3d; for %3d; hc %d @ %f\n", (int) MyEtherAddr, (int) pkt->hdr.cur_addr, (int) destAddr, hopCount, SimTime()));/*** Assume that the path from this node to the destination must go through the** node that sent the HELLO packet. Therefore, increment the hop count.** If this assumption is wrong, then the hop count in the HELLO packet is** greater than the Cost Table entry.*/ hopCount++; // if the Cost Table entry is updated, forward the HELLO packet. if( updateHopCountInCache( destAddr, hopCount, Hello, "HELLO", pkt) == true) SendPacket( (packet_t *) createHelloPkt( destAddr, hopCount)); return;}/******************************************************************* * We are now receiving a packet from the mac layer. *******************************************************************/template <class PLD>void SHR<PLD>::from_mac_data( packet_t *pkt, double power){ ether_addr_t src = pkt->hdr.src_addr; bool costTableUpdated = false; RecvPackets++; addToNeighborMatrix( (int) pkt->hdr.cur_addr, (int) MyEtherAddr); Printf((DumpPackets,"%d SHR: %d %d %s \n", (int) MyEtherAddr, (int) pkt->hdr.cur_addr, (int) MyEtherAddr, pkt->dump().c_str())); shrPrint( ("fmd: ea %3d<-%3d sn%08X %s @ %f\n", (int) MyEtherAddr, (int) pkt->hdr.cur_addr, pkt->hdr.seq_number, pkt->dump().c_str(), SimTime())); if( pkt->hdr.type == HELLO) { receiveHelloPacket( pkt); pkt->free(); return; } cache_t::iterator iter; /*** If the packet is not an ACK, then update the cost table.**** The result of updating the cost table is used if the packet is a RREP.*/ if( pkt->hdr.type != ACK) { costTableUpdated = updateHopCountInCache( src, pkt->hdr.actual_hop, Lower, "rRRDP", pkt); iter = m_seq_cache.find( src); }/*** The method check (defined at the top of this file) determines if this** sequence number is greater than the sequence number in the cache. If the** packet's sequence number is greater, then this packet is new. This** comparison is not valid for resent packets.*/ if( pkt->hdr.type != ACK && (!iter->second.check( pkt->hdr.seq_number) || pkt->hdr.resend)) { // the received packet is new RecvUniPackets++; if( pkt->hdr.dst_addr == MyEtherAddr) { if( pkt->hdr.resend == 0) { switch( pkt->hdr.type) { // this case can't happen, but it makes the compiler happy case HELLO: case ACK: break; case REQUEST: { packet_t *rp = (packet_t *) createReplyPkt( pkt->hdr.src_addr, iter->second.hopCount()); Printf( (DumpPackets, "%d SHR: %d->%d %s\n", (int) MyEtherAddr, (int) MyEtherAddr, (int) pkt->hdr.src_addr, rp->dump().c_str())); shrPrint( ("rPAD: ea %d creates REPLY %s @ %f\n", (int) MyEtherAddr, rp->dump().c_str(), SimTime())); // Send reply and check if any packets need to be sent to the src // of the request SendPacket( rp); CheckBuffer( pkt->hdr.src_addr, iter->second.hopCount()); } break; case REPLY: Printf((DumpPackets,"%d SHR: %d<-%d %s\n", (int)MyEtherAddr, (int)MyEtherAddr, (int)pkt->hdr.src_addr, pkt->dump().c_str())); // Packet arrives at destination, Ack after AckWindow SendAck( pkt->hdr.src_addr, MyEtherAddr, pkt->hdr.cur_addr, pkt->hdr.seq_number, AckWindow, true); CheckBuffer( pkt->hdr.src_addr, iter->second.hopCount()); break; case DATA: // the packets arrives at its destination // Packet arrives at destination, Ack after AckWindow SendAck( pkt->hdr.src_addr, MyEtherAddr, pkt->hdr.cur_addr, pkt->hdr.seq_number, AckWindow, true); pkt->inc_pld_ref(); to_transport(pkt->pld); { int hc = pkt->hdr.actual_hop; TotalHop += hc; if( hc > HCArraySize-1) hc = HCArraySize-1; HopCounts[hc]++; } RecvDataPackets++; pkt->hdr.path.AddNode(MyEtherAddr);#ifdef VISUAL_ROUTE // this printf is used by the compareHC and checkHC utilities printf( "VR: %f; %3d->%3d; sn%08X; %f; %d; %s\n", SimTime(), (int) pkt->hdr.src_addr, (int) pkt->hdr.dst_addr, pkt->hdr.seq_number, (SimTime() - pkt->hdr.send_time), pkt->hdr.actual_hop, pkt->hdr.path.ToString());#endif //VISUAL_ROUTE visualizer->writePath( (int) pkt->hdr.src_addr, (int) pkt->hdr.dst_addr,pkt->hdr.seq_number, pkt->hdr.path, true); break; } } } else {/*** If the hop count in the cost table is less than the maximum allowed by the** received packet, then forward the packet.*/ if( pkt->hdr.actual_hop < pkt->hdr.max_hop) { packet_t* np = pkt->copy(); // create copy of packet np->hdr.cur_addr = MyEtherAddr; np->hdr.pre_addr = pkt->hdr.cur_addr; np->hdr.resend = 0; np->hdr.actual_hop++; np->hdr.suboptimal = false; np->hdr.path.AddNode( MyEtherAddr);/*** How the packet is forwarded depends on the packet type.**** Data packet require an election. If the destination isn't found in the cost** table, don't participate in the election. Otherwise, the delay is dependent** on the value of the cost table entry relative to the expected hop of the** received packet.*/ if( np->hdr.type == DATA) { iter = m_seq_cache.find( np->hdr.dst_addr); if( iter != m_seq_cache.end()) { // If the packet is on the ACK list, remove it. // This happens when the retransmission is lost and the upstream // node resends the packet. { packet_t *pktFromList = (packet_t *) getFromAckList( pkt); if( pktFromList != NULL) removeFromAckList( pktFromList, true); } np->hdr.expected_hop = (*iter).second.hopCount(); double hop, backOffTime; switch( backOff) {/*** Calculate the amount of time to wait before responding.** The form of this equation is different than that of the paper. In the paper** the sender decrements the expected hop count before putting the value into** the packet. In the simulation, the hop count is not decremented.*/ case SHRBackOff_SSR: case SHRBackOff_Incorrect: shrPrint( ("FP: ea %3d; cost table %2d; pkt %2d\n", (int) MyEtherAddr, iter->second.hopCount(), pkt->hdr.expected_hop)); if( iter->second.hopCount() < pkt->hdr.expected_hop) hop = Random( 1.0/(pkt->hdr.expected_hop - iter->second.hopCount())); else { hop = Random( iter->second.hopCount() - pkt->hdr.expected_hop +1.0); if( backOff == SHRBackOff_SSR) hop += 1.0; SentSuboptimal++; np->hdr.suboptimal = true; } break;/*** Implement the fix that Boleslaw proposed on 3/21/2006.** If h_table <= h_expected, then** backoff = lambda * U(0,1)/(h_e - h_t + 1)** else** backoff = lambda * (h_t - h_e + U(0,1))*/ case SHRBackOff_SHR: if( iter->second.hopCount() < pkt->hdr.expected_hop) hop = Random(1.0)/(pkt->hdr.expected_hop - iter->second.hopCount()); else { hop = iter->second.hopCount() - pkt->hdr.expected_hop + 1.0 + Random( 1.0); SentSuboptimal++; np->hdr.suboptimal = true; } break; default: hop = 1; // shouldn't happen, but quiets gcc assert( 0); break; } backOffTime = hop * ForwardDelay#ifdef MWL_DOUBLE_DELAY * (1 << pkt->hdr.resend)#endif // MWL_DOUBLE_DELAY ; if( continuousBackOff == false) // convert lambda to slot { int slot; slot = (int) (backOffTime / slotWidth); backOffTime = slot * slotWidth + Random( transitionTime); } // Don't forward packets until after the AckWindow np->hdr.delay = backOffTime + AckWindow; shrPrint( ("FP: ea %3d; from %3d; 0x%08X; sn%08X; pkt %2d; table %2d; backoff %f\n", (int) MyEtherAddr, (int) pkt->hdr.cur_addr, (int) pkt, pkt->hdr.seq_number, pkt->hdr.expected_hop-1, np->hdr.expected_hop, backOffTime)); SendPacket( np); } else { shrPrint( ("FP: ea %3d; from %3d; 0x%08X; sn%08X; not in cache\n", (int) MyEtherAddr, (int) pkt->hdr.cur_addr, (int) pkt, pkt->hdr.seq_number)); np->free(); } }/*** Request packets are flooded: No election, forward after a random delay*/ else if( np->hdr.type == REQUEST) forwardAsFlood( np);/*** Reply packets are conditionally flooded.**** RREP (Z -> Y) from X, where Y generated the RREQ for Z and X has forwarded** the packet to this node.** If (Y is not in the cost table)** then the packet is dropped.** else (Y is in the cost table)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -