?? ashr.h
字號:
/************************************************************************* * @<title> Autonomic Self-Healing Routing </title>@ * * @<!-- Copyright 2006 Mark Lisee, Joel Branch, Gilbert (Gang) Chen, * Boleslaw K. Szymanski and Rensselaer Polytechnic Institute. * * Copyright 2003 Gilbert (Gang) Chen, Boleslaw K. Szymanski * and Rensselaer Polytechnic Institute. All worldwide rights * reserved. A license to use, copy, modify and distribute this * software for non-commercial research purposes only is hereby * granted, provided that this copyright notice and accompanying * disclaimer is not modified or removed from the software. * * DISCLAIMER: The software is distributed "AS IS" without any * express or implied warranty, including but not limited to, any * implied warranties of merchantability or fitness for a particular * purpose or any warranty of non-infringement of any current or * pending patent rights. The authors of the software make no * representations about the suitability of this software for any * particular purpose. The entire risk as to the quality and * performance of the software is with the user. Should the software * prove defective, the user assumes the cost of all necessary * servicing, repair or correction. In particular, neither Rensselaer * Polytechnic Institute, nor the authors of the software are liable * for any indirect, special, consequential, or incidental damages * related to the software, to the maximum extent the law * permits.-->@ * *************************************************************************//*** Modifications from rr.h** - replaced lambda by slotting** - Added T1, T2 & T3 time periods** - code to gather statistics** - code to set # slots per period from command line** - Added handling of collision packet** - new packet type & field in header changed from int to enum** - Transmission is scheduled when a collision is detected** - Added # slots to packet header** - I added this when I thought it would be required for v2. It no longer** is, but it's staying** - Sender may modify its hop count based on slot during which response is** sent.*/#ifndef SSRv02_h#define SSRv02_h#include <map>#include <list>#ifdef MWL_PRINT//#define mwlDoPrint (SimTime() > 1400. && SimTime() < 1500.)//#define mwlPrint(x) if( mwlDoPrint) printf x#define mwlDoPrint (true)#define mwlPrint(x) printf x#else //MWL_PRINT#define mwlPrint(x)#define mwlDoPrint (false)#endif //MWL_PRINTtemplate <class PLD>struct SSRv02_Struct{ enum PktType { REQUEST, REPLY, DATA, ACK, COLL, HELLO, BACKUP}; // REQUEST: type + src_addr + dst_addr + seq_number + hop enum { REQUEST_SIZE = 3 * sizeof(int) + 2 * ether_addr_t::LENGTH }; // REPLY: type + src_addr + dst_addr + seq_number + 2 * hop + flag enum { REPLY_SIZE = 4 * sizeof(int) + 4 * ether_addr_t::LENGTH + sizeof( bool) }; // DATA: type + src_addr + dst_addr + seq_number + 2 * hop + flag enum { DATA_SIZE = 4 * sizeof(int) + 4 * ether_addr_t::LENGTH + sizeof( bool) }; // ACK: type + src_addr + dst_addr + seq_number enum { ACK_SIZE = 3 * sizeof(int) + 2 * ether_addr_t::LENGTH }; // COLL: type + src_addr + dst_addr + seq_number + slot number enum { COLL_SIZE = 3 * sizeof(int) + 2 * ether_addr_t::LENGTH }; // BACKUP: type + src_addr + dst_addr + seq_number enum { BACKUP_SIZE = 2 * sizeof(int) + 2 * ether_addr_t::LENGTH }; // HELLO: type + src_addr + dst_addr + seq_number + hop count enum { HELLO_SIZE = 3 * sizeof(int) + 2 * ether_addr_t::LENGTH }; struct hdr_struct { PktType type; ether_addr_t src_addr; ether_addr_t dst_addr; ether_addr_t cur_addr; ether_addr_t pre_addr; unsigned int seq_number; unsigned int size; double send_time; // time received from transport double xmit_start_time; // time sent to mac layer double xmit_end_time; // time sent to mac layer unsigned int actual_hop; unsigned int expected_hop; unsigned int max_hop; double delay; int t1Index; // id of endT1Timer int t2Index; // id of endT2Timer//mwl int t3Index; // id of endT3Timer int collIndex; // id of endCollTimer bool canceled; int resend; int numSlots; // k, the number of slots in T2 int slotNumber; bool collDetected; bool collPktSent; bool t3Flag; // if true, nodes may forward this pkt in T3#ifdef VISUAL_ROUTE#ifndef VR_SIZE#define VR_SIZE 20#endif path_t<VR_SIZE> path;#endif bool dump(std::string& str) const; }; typedef PLD payload_t; typedef smart_packet_t<hdr_struct,PLD> packet_t;};#define HCArraySize (20+1)#define MaxT2Slots 100#define DefaultNumT2Slots 3#define MaxT3Slots 10#define DefaultNumT3Slots 2/*** The AckWindow is a period of time during which only Acks from intermediate** nodes are sent. This prevents the Acks from colliding with packets that are** being forwarded. Note that the destination sends its Ack as a normal packet,** i.e. after the AckWindow. This is because when node N forwards a packet, it** causes node N-1 to send an Ack (during the AckWindow) and N+1 to forward the** packet (after the AckWindow).*/template <class PLD>component SSRv02 : public TypeII, public SSRv02_Struct<PLD>{ public: ether_addr_t MyEtherAddr; simtime_t ForwardDelay; double RXThresh; bool DumpPackets; double AckWindow; // see comment above int MaxResend; unsigned int TimeToLive; unsigned int AdditionalHop; int SentPackets; int RecvPackets; int RecvUniPackets; double TotalDelay; int TotalSamples; int TotalHop; int RecvDataPackets; int HopCounts[ HCArraySize]; int T1PktsSent; int T2PktsSent[ MaxT2Slots]; int T3PktsSent[ MaxT3Slots]; int T3AbnormalPktsSent; int DropPkts; // # times h_table > h_pkt+n int T1Collisions; int T2Collisions[ MaxT2Slots]; int T3Collisions[ MaxT3Slots]; int IgnoreCollisions; // collision after end of T3 int T1PktsRcvd[2]; int T2PktsRcvd[2][ MaxT2Slots]; int T3PktsRcvd[2][ MaxT3Slots]; int T4PktsRcvd[2];//mwl int OtherPktsRcvd[2]; int CanceledPktsRcvd[2]; int BadAddrPktsRcvd[2]; int WrongHopPktsRcvd[2]; static const char *pktRcvdName[2]; typedef std::list<packet_t* > packet_queue_t;/*** Fields that support the transition timer.** This timer simulates the amount of time it takes the hardware to transition** from sensing the carrier to actually transmitting a packet.*/ Timer <trigger_t> transitionTimer; packet_t *transitionPkt; // pkt to be sent when timer expires inport void TransitionTimer( trigger_t &);/*** When a COLL packet is sent, the original packet is added to the** m_collPktsSent_queue. A list of collision packets is required to properly** implement BACKUP messages.**** In some situations, a timer is required to remove packets from the queue.** For example, N1 sends a packet. N2 forwards it, but N1 detects it as a** collision when there is no interference at N2. (N1 could be located between** the two nodes.) In this case, N1 will schedule a COLL. If the COLL** is received by N2 after N3 has forwarded the packet, the COLL packet will be** ignored. In this case, the original packet needs to be removed from N1.*/ InfiTimer <SSRv02_Struct<PLD>::packet_t*> endCollTimer; inport void EndCollTimer( packet_t *pkt, unsigned int index); packet_queue_t m_collPktsSent_queue; // pkts for which a COLL packet has been sent/*** Fields that support the timers that expire at the ends of T1, T2 & T3.*/ InfiTimer <SSRv02_Struct<PLD>::packet_t*> endT1Timer; InfiTimer <SSRv02_Struct<PLD>::packet_t*> endT2Timer;//mwl InfiTimer <SSRv02_Struct<PLD>::packet_t*> endT3Timer; inport void EndT1Timer( packet_t *pkt, unsigned int index); inport void EndT2Timer( packet_t *pkt, unsigned int index);//mwl inport void EndT3Timer( packet_t *pkt, unsigned int index); packet_queue_t m_T3_queue; // packets w/ t3 timer pending/*** Connections to transport (layer above) and mac (layer below)*/ inport inline void from_transport( payload_t& pld, ether_addr_t& dst, unsigned int size); inport inline void from_mac_data( packet_t* pkt, double power); inport inline void from_mac_ack( bool errflag); inport inline void from_mac_recv_recv_coll( packet_t *pkt1, packet_t *pkt2); outport void cancel(); outport void to_transport( payload_t& pld ); outport void to_mac( packet_t* pkt, unsigned int size, double backoff); void Start(); void Stop(); SSRv02(); virtual ~SSRv02(); int mwlGetHC( int addr);/*** Added static members for slot width, transition timer and back off*/ static void setSlotWidth( double); static double getSlotWidth(); static void setTransitionTime( double); static double getTransitionTime(); static void setNumT2Slots( int); static int getNumT2Slots(); static void setNumT3Slots( int); static int getNumT3Slots(); private: void updateHopCountInCache( ether_addr_t src, unsigned int hopCount, bool always, const char *, packet_t *pkt); protected: static double slotWidth; static double transitionTime; static int numT2Slots; static int numT3Slots; void CancelPacket( ether_addr_t& src, unsigned int seq_number); void CancelRetransmission( ether_addr_t& src, unsigned int seq); void SendPacket( packet_t *p, bool new_seq = true); void ForwardPacket( packet_t *p); void SendToMac( packet_t *pkt); void SendAck( ether_addr_t, ether_addr_t, ether_addr_t, unsigned int, simtime_t); void CheckBuffer( ether_addr_t, unsigned int); void sendCollisionPacket( packet_t *pkt); void receiveCollisionPacket( packet_t *pkt); void receiveHelloPacket( packet_t *pkt); void receiveBackupPacket( packet_t *pkt); void receiveAckPacket( packet_t *pkt); void receiveReqRepDataPacket( packet_t *pkt); bool determineAckStatus( packet_t *pkt); void performAck( packet_t *pkt); // these return pointers to packet_t, but I wasn't able to figure out // how to avoid compiler errors, therefore cast them to void * void *createBasicPkt(); void *createDataPkt( payload_t &pld, ether_addr_t dst, unsigned int size); void *createT3Pkt( packet_t *pkt); void *createRequestPkt( ether_addr_t dst); void *createReplyPkt( ether_addr_t src, unsigned int expectedHop); void *createAckPkt( ether_addr_t src_addr, ether_addr_t cur_addr, ether_addr_t pre_addr, unsigned int seq_number, simtime_t delay); void *createCollPkt( packet_t *pkt); void *createBackupPkt( packet_t *pkt); void *createHelloPkt(); bool m_mac_busy; // if the mac layer is busy unsigned int m_seq_number; // current sequence number packet_queue_t m_send_queue; // list of packets to send packet_t *m_active_packet; class seq_number_t { public: seq_number_t () : state( Initial), current(0), bits(0u) {} bool check(int n) { if( n + (int)sizeof(unsigned long) <= current ) return true; if ( n > current ) { bits = bits << (n - current); current = n; } unsigned long flag = 1 << (current - n); unsigned long r = flag & bits; bits |= flag; return r; } unsigned int hopCount() const; void hopCount( unsigned int newHC, bool print); private: unsigned int currentHC; unsigned int pendingHC; enum { Initial, Steady, Changing} state; int updateCtr; int current; uint32_t bits; static int maxCounter; };/******************************************************************* * For each source, we must maintain a @seq_number_t@ object, so we better * keep them in a map. *******************************************************************/ typedef std::map<ether_addr_t, seq_number_t, ether_addr_t::compare> cache_t; cache_t m_seq_cache; packet_queue_t m_data_buffer; void recvPktAtDest( packet_t *pkt, cache_t::iterator iter);};template <class PLD> double SSRv02<PLD>::slotWidth = 0.010;template <class PLD> double SSRv02<PLD>::transitionTime = 0.0001;template <class PLD> int SSRv02<PLD>::numT2Slots = DefaultNumT2Slots;template <class PLD> int SSRv02<PLD>::numT3Slots = DefaultNumT3Slots;template <class PLD> const char *SSRv02<PLD>::pktRcvdName[2] = {"REP", "DAT"};template <class PLD> int SSRv02<PLD>::seq_number_t::maxCounter = 2;template <class PLD>unsigned int SSRv02<PLD>::seq_number_t::hopCount() const{ switch( state) { case Initial: return 99; case Steady: case Changing: return currentHC; default: assert( 0); // something really bad happened return 0; }}template <class PLD>void SSRv02<PLD>::seq_number_t::hopCount( unsigned int newHC, bool print){ switch( state) { case Initial: currentHC = newHC; updateCtr = maxCounter; state = Steady; break; case Steady: if( newHC != currentHC) { --updateCtr; pendingHC = newHC; state = Changing; if( print) printf( " start change\n"); } break; case Changing: if( newHC == currentHC) { if( ++updateCtr == maxCounter) { state = Steady; if( print) printf(" back out of change\n"); } else if( print) printf(" reversing\n"); } else if( newHC == pendingHC) { if( --updateCtr == 0) { currentHC = newHC; updateCtr = maxCounter; state = Steady; if( print) printf(" end change\n"); } else if( print) printf(" still changing\n"); } else // newHC is neither the old nor new HC { pendingHC = newHC; if( print) printf(" new HC during change\n"); } break; default: assert( 0); // something really bad happened } return;}template <class PLD>void SSRv02<PLD>::setSlotWidth( double sw){ slotWidth = sw; return;}template <class PLD>double SSRv02<PLD>::getSlotWidth(){ return slotWidth;}template <class PLD>void SSRv02<PLD>::setTransitionTime( double tt){ transitionTime = tt; return;}template <class PLD>double SSRv02<PLD>::getTransitionTime(){ return transitionTime;}template <class PLD>void SSRv02<PLD>::setNumT2Slots( int num){ numT2Slots = num; return;}template <class PLD>int SSRv02<PLD>::getNumT2Slots(){ return numT2Slots;}template <class PLD>void SSRv02<PLD>::setNumT3Slots( int num){ numT3Slots = num; return;}template <class PLD>int SSRv02<PLD>::getNumT3Slots(){ return numT3Slots;}template <class PLD>void *SSRv02<PLD>::createBasicPkt(){ packet_t *newPkt = packet_t::alloc(); newPkt->hdr.send_time = SimTime(); newPkt->hdr.actual_hop = 1; newPkt->hdr.resend = 0; newPkt->hdr.seq_number = 0; newPkt->hdr.numSlots = numT2Slots; newPkt->hdr.collDetected = false; newPkt->hdr.collPktSent = false; newPkt->hdr.slotNumber = 0; newPkt->hdr.delay = 0.0; newPkt->hdr.t1Index = 12345; //mwl newPkt->hdr.t2Index = 12345; //mwl
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -