/***** Selective Repeat ARQ protocol SRN in NS2 Muhammad Hanif Abdul Wahid 0428935 hanifw@yahoo.com 29/02/2008 *****/ #include "srn.h" #include "math.h" #define MARKN 5000 int N=3; //default sender window size //int m=3; // SENDER SIDE int SF=0;//sender side window lower limit (First packet of the window) int SN=0;//sender side upper limit/current packet //RECEIVER SIDE int RN=0;//receiver current packet int Nmax=3; int sqnMax=3; int npkttosend=0; //the number of packet to be send //mark packet bool MarkS[MARKN]; bool MarkR[MARKN]; bool AckNeeded=false; bool NakSent=false; //initialization of class SRNClass that inherit from class TclClass static class SRNClass : public TclClass { public: SRNClass() : TclClass("Agent/SRN") {}; //function called when 'new Agent/SRN' is called in a tcl script TclObject* create(int, const char*const*) { return(new SRNAgent()); //call the SRNAgent class constructor } }class_srn; //declaration of selective repeat offset int hdr_srn::offset_; //newagent linkage header static class SRNHeaderClass: public PacketHeaderClass { public: SRNHeaderClass() : PacketHeaderClass("PacketHeader/SRN",sizeof(hdr_srn)) { bind_offset(&hdr_srn::offset_); } }class_srnhdr; //function to be executed when timeout void SRNAgentTimer::expire(Event*) { printf("%lf - RTO timeout\n\n",Scheduler::instance().clock()); a_->resendpkt();//resend unACKed packet } //SRNAgent class constructor SRNAgent::SRNAgent() : Agent(PT_UDP), rto_timer_(this) { //linkage between the OTcl variable of NewAgentOtcl object and C++ variable bind("packetSize_",&packetSize_);//the size of srn DATA packet bind("ackpacketSize_",&ackpacketSize_);//the size of srn ACK packet bind("nakpacketSize_",&nakpacketSize_);//the size of srn NAK packet bind("rto_",&rto_); //retransmission timeout bind("windowSize",&windowSize); bind("m", &m); for (int x=0; xNmax) { N=Nmax; }else{ N=windowSize; } sqnMax = (int)(pow(2,m)); bytestosend=atoi(argv[2]); npkttosend=((int)bytestosend/packetSize_)+1; printf("No. of Packets to send: %d\n",npkttosend); printf("Max Sequence No: %d,\nMax Window Size: %d,\nWindow Size: %d\n",sqnMax,Nmax,N); sendpkt();//send packet until Sender's Window full return(TCL_OK); //TCL_OK=0 } } return (Agent::command(argc, argv)); //if invalid argument } //function to send packet when REQUEST TO SEND arrive void SRNAgent::sendpkt(){ rto_timer_.sched(rto_);//schedule the retransmission timer while ( (SN-SF)< N ){ if(SN < npkttosend) { output(SN%sqnMax,0,Scheduler::instance().clock()); SN++; }else{ printf("%lf - Sender sent all packets\n",Scheduler::instance().clock()); break; } } if(SN-SF>=N) printf("%lf - Sender's Window full\n",Scheduler::instance().clock()); } //function to RESEND packet when timeout occurs void SRNAgent::resendpkt(){ printf("%lf - Resending unACKed DATA...\n",Scheduler::instance().clock()); rto_timer_.resched(rto_);//reschedule the retransmission timer int Temp=SN; SN=SF; while(SNseqno_=sqn; //set the packet's sequence no hp->ptype_=type; //set the packet type 0 for data and 1 for ack hp->send_time = sendTime; hdr_cmn* ch = hdr_cmn::access(p); //access the cmn header of the packet hdr_ip* hdrip = hdr_ip::access(p); int dst = hdrip->dst_.addr_>>Address::instance().NodeShift_[1]; int src = hdrip->src_.addr_ >> Address::instance().NodeShift_[1]; double time_now =Scheduler::instance().clock(); //if DATA packet if (type==0) { ch->size()=packetSize_; printf("%lf - n[%d] sends DATA[%d] to n[%d] | Size [%d]\n",time_now,src,sqn,dst,packetSize_ ); } //if ACK packet if (type==1) { ch->size()=ackpacketSize_; printf("%lf - n[%d] sends ACK[%d] to n[%d] | Size [%d]\n",time_now,src,sqn,dst,ackpacketSize_); } //if NAK packet if (type==2) { ch->size()=nakpacketSize_; printf("%lf - n[%d] sends NAK[%d] to n[%d] | Size [%d]\n",time_now,src,sqn,dst,nakpacketSize_); } send(p,0);//send function is implemented in the agent.h file } //function executed when receive any packet void SRNAgent::recv(Packet* p, Handler *) { hdr_srn* hp=hdr_srn::access(p); //access header of the packet hdr_ip* hdrip = hdr_ip::access(p); int dst = hdrip->dst_.addr_>>Address::instance().NodeShift_[1]; int src = hdrip->src_.addr_ >> Address::instance().NodeShift_[1]; double time_now =Scheduler::instance().clock(); bool clearMark=true; /** RECEIVER received DATA packet **/ if (hp->ptype_==0) { printf("%lf - n[%d] received DATA[%d] from n[%d]\n",time_now,dst,hp->seqno_,src); if(MarkR[hp->seqno_]) printf("%lf - n[%d] discarded DATA[%d] from n[%d] as it has been received previously\n",time_now,dst,hp->seqno_,src); if ((hp->seqno_ != RN%sqnMax)&&(!NakSent)){ int temp=RN%sqnMax; MarkR[hp->seqno_]=true; while(hp->seqno_ < temp && !MarkR[temp]){ output(temp,2,hp->send_time);//Sending NAK temp=(temp+1)%sqnMax; } while(hp->seqno_ > temp && !MarkR[temp]){ output(temp,2,hp->send_time);//Sending NAK temp=(temp+1)%sqnMax; } NakSent=true; }else if (!MarkR[hp->seqno_]){ //printf("Marked %d\n",hp->seqno_); MarkR[hp->seqno_]=true; while ( MarkR[RN%sqnMax]) { RN++; AckNeeded=true; if (RN%sqnMax == (sqnMax-1) ){ for (int x=0; xsend_time);//Sending ACK AckNeeded=false; NakSent=false; } } printf("%lf - n[%d]|[%d,%d]|[%d,%d]]\n",time_now,dst,RN%sqnMax, (RN+N-1)%sqnMax,RN, RN+N-1); /** SENDER received ACK packet **/ }else if (hp->ptype_== 1){ //if((hp->seqno_>= SF) && (hp->seqno_<= (SF+N))){ //printf("%d\n",N); printf("%lf - n[%d] received ACK[%d] from n[%d]; RTT: %lf \n",time_now,dst,hp->seqno_,src, (time_now - hp->send_time) ); while(SF%sqnMax>hp->seqno_){ MarkS[SF]=true; SF++; } while(SF%sqnMaxseqno_){ MarkS[SF]=true; SF++; } rto_timer_.force_cancel(); if (SFseqno_,0,hp->send_time); //rto_timer_.resched(rto_); sendpkt(); }else { printf("%lf - Receiver received all packets\n",time_now); } // }else { // printf("%lf - Invalid ACK[%d] received\n",time_now, hp->seqno_); /*if(!MarkS[hp->seqno_]) MarkS[hp->seqno_]=true;*/ //} }else if (hp->ptype_== 2){ // SENDER received NAK packet // if( (hp->seqno_>= (SF) && hp->seqno_<= (SF+N-1)) ){ printf("%lf - n[%d] received NAK[%d] from n[%d]\n",time_now,dst,hp->seqno_, src); output(hp->seqno_,0,hp->send_time); //Resend the DATA packet requested by NAK rto_timer_.resched(rto_); //re-schedule the retransmission timer // }else { // printf("%lf - Invalid NAK[%d] received\n",time_now,hp->seqno_); // } } printf("%lf - n[%d]|[%d,%d]|[%d,%d]\n",time_now,src, SF%sqnMax,SN%sqnMax, SF,SN); free(p);//free the alocated memory } /* printf("Data received: \n"); for (int j=0; j< nbptosend; j++) { if (MarkS[RN])printf("DATA[%d] ", RN); RN++; } */