- /* ******************************************************************
- Door Anne Westerhof (0815012) & Willem Burgers (0814830)
- ********************************************************************/
- /* ******************************************************************
- link simulator Theo Schouten april 2002
- adapted from
- ALTERNATING BIT AND GO-BACK-N NETWORK EMULATOR: VERSION 1.1 J.F.Kurose
- This code can be used for unidirectional or bidirectional
- data transfer protocols.
- Network properties:
- - one way packet delay averages 20 time units (flat distribution between
- 10 and 30), packets are received at least 2 time units apart
- - packets can be lost or corrupted (either the header or the data portion)
- according to user-defined probabilities
- - packets will be delivered in the order in which they were sent
- (although some can be lost).
- **********************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #define BIDIRECTIONAL 1 /* 1 if for bidirectional, 0 for only A to B transfer */
- /* Do not change the definitions below */
- #define A 0
- #define B 1
- #define OFF 0
- #define ON 1
- typedef int bool;
- #define FALSE 0
- #define TRUE 1
- /* a "msg" is the data unit passed from layer 5 (teachers code) to layer */
- /* 4 (students' code). It contains the data (characters) to be delivered */
- /* to layer 5 via the students transport level protocol entities. */
- struct msg {
- unsigned char data[20];
- };
- /* a packet is the data unit passed from layer 4 (students code) to layer */
- /* 3 (teachers code). */
- struct pkt {
- int seqnum;
- int acknum;
- int checksum;
- struct msg mes;
- };
- static void tolayer3 (int AorB, struct pkt packet);
- static void tolayer5 (int AorB, struct msg mes );
- static void starttimer (int AorB, int tnum, float increment);
- static void stoptimer (int AorB, int tnum);
- static void onofflayer5 (int AorB, int ONorOFF);
- static double gettime();
- /********* STUDENTS WRITE THE NEXT TEN ROUTINES *********/
- static int DEBUG = 1; /* 0: the student code should print out nothing
- >0: printout relevant information */
- #define MAX_SEQ_NR 15
- #define NRBUFS 8 /* ( (MAX_SEQ_NR + 1) / 2 ) for selective repeat protocols */
- #define TO_PKT 50.0 /* Time-out for the packets */
- #define TO_ACK 20.0 /* Time-out for the acknowledgments */
- int seqnumA, seqnumA2, seqnumB, seqnumB2;
- int ackA, sentA, receivedA, ackB, sentB, receivedB;
- int arrA, arrB;
- bool resendA, resendB;
- bool timerA, acktimerA, timerB, acktimerB;
- int Checksum (int seqnum, int acknum, struct msg mes)
- {
- int som = seqnum + acknum;
- int i = 0;
- for (i; i < 20;i++)
- {
- som = som + (int)mes.data[i];
- }
- return som;
- }
- struct pkt MsgToPkt (struct msg m, bool AofB)
- {
- struct pkt packetX;
- if(AofB == A)
- {
- packetX.seqnum = seqnumA;
- packetX.acknum = ackA;
- }
- else
- {
- packetX.seqnum = seqnumB;
- packetX.acknum = ackB;
- }
- packetX.checksum = Checksum (packetX.seqnum, packetX.acknum, m);
- packetX.mes = m;
- return packetX;
- }
- struct pkt Ack (bool AofB)
- {
- struct pkt Ack;
- Ack.seqnum = -1;
- if(AofB == A)
- Ack.acknum = ackA;
- else
- Ack.acknum = ackB;
- Ack.checksum = Checksum(Ack.seqnum, Ack.acknum, Ack.mes);
- return Ack;
- }
- struct pkt window[2][NRBUFS];
- bool buffervol (bool AofB)
- {
- if (AofB == A)
- if (arrA == NRBUFS)
- return TRUE;
- else
- return FALSE;
- else
- if (arrB == NRBUFS)
- return TRUE;
- else
- return FALSE;
- }
- void addToBuffer(int AofB, struct pkt packet)
- {
- if(AofB == A)
- {
- window[A][arrA] = packet;
- arrA = arrA + 1;
- }
- else
- {
- window[B][arrB] = packet;
- arrB = arrB + 1;
- }
- }
- void deleteFromBuffer(bool AofB, int aantal)
- {
- if(aantal != 0)
- {
- window[AofB][0]=window[AofB][1];
- window[AofB][1]=window[AofB][2];
- window[AofB][2]=window[AofB][3];
- window[AofB][3]=window[AofB][4];
- window[AofB][4]=window[AofB][5];
- window[AofB][5]=window[AofB][6];
- window[AofB][6]=window[AofB][7];
- if(AofB == A)
- arrA = arrA - 1;
- else
- arrB = arrB - 1;
- deleteFromBuffer(AofB,(aantal-1));
- }
- }
- struct pkt repack (struct pkt X, bool AofB)
- {
- if(AofB == A)
- X.acknum = ackA;
- else
- X.acknum = ackB;
- X.checksum = Checksum (X.seqnum, X.acknum, X.mes);
- return X;
- }
- void resend (bool AofB)
- {
- if(AofB == A)
- {
- if(acktimerA==TRUE)
- {
- stoptimer(A,-1);
- acktimerA = FALSE;
- }
- }
- else
- {
- if(acktimerB==TRUE)
- {
- stoptimer(B,-1);
- acktimerB = FALSE;
- }
- }
- tolayer3(AofB,repack(window[AofB][0],AofB));
- int index = 1;
- if(AofB == A)
- {
- for(index;index<arrA;index++)
- {
- tolayer3(A,repack(window[A][index],A));
- }
- }
- else
- {
- for(index;index<arrB;index++)
- {
- tolayer3(B,repack(window[B][index],B));
- }
- }
- }
- void deletePacket(bool AofB, int recAck)
- {
- int index = 0;
- for(index; index < NRBUFS; index++)
- {
- if (window[AofB][index].seqnum == recAck)
- {
- deleteFromBuffer(AofB,(index+1));
- onofflayer5(AofB,ON);
- break;
- }
- }
- }
- static void A_init()
- {
- onofflayer5(A,ON); seqnumA = MAX_SEQ_NR; seqnumA2 = 0; ackA = 0;
- sentA = 0; receivedA = 0; arrA = 0; resendA = FALSE;
- }
- static void B_init()
- {
- onofflayer5(B,ON); seqnumB = MAX_SEQ_NR; seqnumB2 = 0; ackB = 0;
- sentB = 0; receivedB = 0; arrB = 0; resendB = FALSE;
- }
- static void A_output(struct msg m)
- {
- seqnumA = (seqnumA+1)%(MAX_SEQ_NR+1);
- sentA = sentA + 1;
- if(acktimerA==TRUE)
- {
- stoptimer(A,-1);
- acktimerA = FALSE;
- }
- struct pkt packet = MsgToPkt(m,A);
- addToBuffer(A, packet);
- tolayer3(A,packet);
- if(buffervol(A) == TRUE)
- onofflayer5(A,OFF);
- }
- static void B_output(struct msg m)
- {
- seqnumB = (seqnumB+1)%(MAX_SEQ_NR+1);
- sentB = sentB + 1;
- if(acktimerB==TRUE)
- {
- stoptimer(B,-1);
- acktimerB = FALSE;
- }
- struct pkt packet = MsgToPkt(m,B);
- addToBuffer(B, packet);
- tolayer3(B,packet);
- if(buffervol(B) == TRUE)
- onofflayer5(B,OFF);
- }
- static void A_input(struct pkt p)
- {
- if (p.checksum == Checksum(p.seqnum, p.acknum, p.mes))
- {
- if (p.seqnum >= 0)
- {
- if (p.seqnum != seqnumA2)
- {
- //resend ack
- }
- else
- {
- seqnumA2 = (seqnumA2+1) % (MAX_SEQ_NR+1);
- ackA = receivedA + 1;
- receivedA = (receivedA+1) % (MAX_SEQ_NR+1);
- tolayer5(A,p.mes);
- if(acktimerA == FALSE)
- {
- starttimer(A,-1,TO_ACK);
- acktimerA = TRUE;
- }
- }
- }
- if(p.acknum > 0)
- {
- int recAck;
- recAck = (p.acknum-1) % (MAX_SEQ_NR+1);
- deletePacket(A,recAck);
- }
- if(p.acknum < 0)
- {
- int recAck;
- recAck = ((0-p.acknum)-2) % (MAX_SEQ_NR+1);
- deletePacket(A,recAck);
- resend(A);
- }
- }
- else
- {
- ackA = 0-(receivedA+1);
- if(acktimerA == FALSE)
- {
- starttimer(A,-1,TO_ACK);
- acktimerA = TRUE;
- }
- }
- }
- static void B_input(struct pkt p)
- {
- if (p.checksum == Checksum(p.seqnum, p.acknum, p.mes))
- {
- if (p.seqnum >= 0)
- {
- if (p.seqnum != seqnumB2)
- {
- //resend ack
- }
- else
- {
- seqnumB2 = (seqnumB2+1) % (MAX_SEQ_NR+1);
- ackB = receivedB + 1;
- receivedB = (receivedB+1) % (MAX_SEQ_NR+1);
- tolayer5(B,p.mes);
- if(acktimerB == FALSE)
- {
- starttimer(B,-1,TO_ACK);
- acktimerB = TRUE;
- }
- }
- }
- if(p.acknum > 0)
- {
- int recAck;
- recAck = (p.acknum-1) % (MAX_SEQ_NR+1);
- deletePacket(B,recAck);
- }
- if(p.acknum < 0)
- {
- int recAck;
- recAck = ((0-p.acknum)-2) % (MAX_SEQ_NR+1);
- deletePacket(B,recAck);
- resend(B);
- }
- }
- else
- {
- ackB = 0-(receivedB+1);
- if(acktimerB == FALSE)
- {
- starttimer(B,-1,TO_ACK);
- acktimerB = TRUE;
- }
- }
- }
- static void A_timerinterrupt(int tnum)
- {
- if(tnum<0)
- {
- acktimerA = FALSE;
- tolayer3(A,Ack(A));
- }
- }
- static void B_timerinterrupt(int tnum)
- {
- if(tnum<0)
- {
- acktimerB = FALSE;
- tolayer3(B,Ack(B));
- }
- }
- static void A_finish() {}
- static void B_finish() {}
- /*****************************************************************
- ***************** NETWORK EMULATION CODE STARTS BELOW ***********
- The code below emulates the layer 3 and below network environment:
- - emulates the tranmission and delivery (possibly with bit-level corruption
- and packet loss) of packets across the layer 3/4 interface
- - handles the starting/stopping of timers, and generates timer
- interrupts (resulting in calling students timer handler).
- - generates message to be sent (passed from later 5 to 4)
- The code is designed such that it can ran on nearly any machine that supports
- C, no use is made of UNIX features.
- A exception might be the random number generator that is needed.
- That is placed in the function simrand() and should return a float with
- a flat distribution in the range [0,1].
- ******************************************************************/
- /****************************************************************************/
- /* simrand(): return a float in range [0,1]. The routine below is used to */
- /* isolate all random number generation in one location. We assume that the*/
- /* system-supplied rand() function return an int in therange [0,mmm] */
- /****************************************************************************/
- static float simrand()
- {
- double mmm = RAND_MAX; /*2147483647; largest int - MACHINE DEPENDENT!!!!!!!! */
- float x; /* individual students may need to change mmm */
- x = rand()/mmm; /* x should be uniform in [0,1] */
- return(x);
- }
- /****************************************************************************
- THERE IS NOT REASON THAT ANY STUDENT SHOULD HAVE TO READ OR UNDERSTAND
- THE CODE BELOW. YOU SHOLD NOT TOUCH, OR REFERENCE (in your code) ANY
- OF THE DATA STRUCTURES BELOW.
- If you're interested in how I designed the emulator, you're welcome
- to look at the code.
- *****************************************************************************/
- struct event {
- double evtime; /* event time, allow very long*/
- int evtype; /* event type code */
- int eventity; /* entity where event occurs */
- int tnum; /* number of the timer or dropped packet indicator */
- struct pkt *pktptr; /* ptr to packet (if any) assoc w/ this event */
- struct event *prev;
- struct event *next;
- };
- static struct event *evlist = NULL; /* the event list */
- /* possible events: */
- #define TIMER_INTERRUPT 0
- #define FROM_LAYER5 1
- #define FROM_LAYER3 2
- static int nsimmax = 10; /* number of msgs to generate, then stop */
- static float lossprob = 0.1; /* probability that a packet is dropped */
- static float corruptprob=0.1; /* probability that one bit is packet is flipped */
- static float lambda=1000.0; /* arrival rate of messages from layer 5 */
- static int TRACE=0; /* Trace level, set at command line
- >= 3: print when packet is lost or currupted
- >= 4: print events in main loop, used to call the student written functions
- >= 5: print a lot of details
- */
- static double simtime = 0.000; /* current simulation time */
- static int OOA=OFF, OOB=OFF; /* turn Layer5 OFF */
- static int nsim = 0; /* number of messages from 5 to 4 so far */
- static int nrec = 0; /* number received on layer 5 so far */
- static int nsimA=0, nsimB=0, nrecA=0, nrecB=0; /* detailed per A and B */
- static int seqA = -1, seqB = -1; /* last encoded sequence number received */
- static int okA = 1, okB = 1; /* order of receiving is correct */
- static int nrestartA=0, nrestartB=0; /* number of starts of running timer */
- static int nstopA=0, nstopB=0; /* number of stops of not-running timer */
- static int ntoA=0, ntoB=0; /* number of timeouts */
- static int nto3A=0, nto3B=0; /* number sent into layer 3 */
- static int nlostA=0, nlostB=0; /* number lost in media */
- static int ncorA=0, ncorB=0; /* number corrupted by media*/
- static void generate_next_arrival();
- static void insertevent(struct event *p);
- static float simrand();
- static void init(int argc, char *argv[]) /* initialize the simulator */
- {
- int i;
- float sum, avg;
- int count[10], k;
- #define SIMRC 10000
- printf("----- Link level Network Simulator Version 2 -------- n");
- printf(" %s n",(BIDIRECTIONAL == 1)?"Bidirectional":"Only A to B");
- srand(9999); /* init random number generator */
- /* test random number generator for students */
- sum = 0.0;
- for(i=0; i < 10; i++) count[i] = 0;
- for (i=0; i<SIMRC; i++) {
- avg = simrand(); /* simrand() should be uniform in [0,1] */
- k= avg * 10; if( k < 0) k =0; else if(k > 9) k = 9;
- count[k]++;
- sum += avg;
- }
- avg = sum/SIMRC;
- /*for(i=0; i < 10; i++) printf("%d ",count[i]);
- printf("n avg: %fn",avg); */
- k=0;
- for(i=0; i < 10; i++) if ( count[i] < 0.09 * SIMRC || count[i] > 0.11 *SIMRC) k++;
- if (avg < 0.45 || avg > 0.55 || k > 0) {
- printf("It is likely that random number generation on your machinen" );
- printf("is different from what this emulator expects. Please taken");
- printf("a look at the routine simrand() in the emulator code. Sorry. n");
- printf(" average of %d calls: %fn Per bin of 0.1:n",SIMRC,avg);
- for(i=0; i < 10; i++) printf("%d ",count[i]);
- printf("n");
- exit(1);
- }
- if(argc == 1) {
- printf("Enter the number of messages to simulate: ");
- scanf("%d",&nsimmax);
- printf("Enter packet loss probability [enter 0.0 for no loss]:");
- scanf("%f",&lossprob);
- printf("Enter packet corruption probability [0.0 for no corruption]:");
- scanf("%f",&corruptprob);
- printf("Enter average time between messages from sender's layer5 [ > 0.0]:");
- scanf("%f",&lambda);
- printf("Enter TRACE:");
- scanf("%d",&TRACE);
- } else {
- if(argc >6) argc=6;
- switch (argc) {
- case 6: TRACE= atoi(argv[5]);
- case 5: lambda = atof(argv[4]);
- case 4: corruptprob = atof(argv[3]);
- case 3: lossprob = atof(argv[2]);
- case 2: nsimmax = atof(argv[1]);
- }
- }
- if(nsimmax <=0 ) {
- printf("nsinmax %d should be >0 n",nsimmax); exit(1);
- }
- if( lossprob <0.0 || lossprob >= 1.0) {
- printf("loss prob %f should be >=0.0 and <1.0n",lossprob); exit(1);
- }
- if( corruptprob <0.0 || corruptprob >= 1.0) {
- printf("corrupt prob %f should be >=0.0 and <1.0n",corruptprob); exit(1);
- }
- if(lambda <= 0 ) {
- printf("average time %f should be >0.0 n",lambda); exit(1);
- }
- generate_next_arrival(A); /* initialize event list */
- if (BIDIRECTIONAL ) generate_next_arrival(B);
- }
- static void simprcont(struct msg mes)
- {
- int i;
- for (i=0; i<16; i++) printf("%c", isprint(mes.data[i])?mes.data[i]:'*');
- i = ((mes.data[16]*256 + mes.data[17])*256 + mes.data[18])*256 + mes.data[19];
- printf(" NR: %dn", i);
- }
- static void simprpacket(struct pkt *p)
- {
- printf("seq: %d, ack %d, ch: %d ", p->seqnum, p->acknum, p->checksum);
- simprcont(p->mes);
- }
- /********************* EVENT HANDLINE ROUTINES *******/
- /* The next set of routines handle the event list */
- /*****************************************************/
- static void generate_next_arrival(int AorB)
- {
- float x;
- struct event *evptr;
- x = lambda*(0.5 +simrand() ); /* x is uniform on [0.5*lambda, 1.5*lambda] */
- evptr = (struct event *)malloc(sizeof(struct event));
- evptr->evtime = simtime + x;
- evptr->evtype = FROM_LAYER5;
- /* if (BIDIRECTIONAL && (simrand()>0.5) ) evptr->eventity = B;
- else evptr->eventity = A;
- */
- evptr->eventity = AorB;
- if (TRACE>4) printf(" GENERATE NEXT MESSAGE for %c at %fn",
- (evptr->eventity == A)?'A':'B',evptr->evtime);
- insertevent(evptr);
- }
- static void insertevent(struct event *p)
- {
- struct event *q,*qold;
- /* if (TRACE>4) printf(" INSERTEVENT: time: %f,future time: %fn",
- simtime,p->evtime);*/
- q = evlist; /* q points to header of list in which p struct inserted */
- if (q==NULL) { /* list is empty */
- evlist=p;
- p->next=NULL;
- p->prev=NULL;
- }
- else {
- for (qold = q; q !=NULL && p->evtime >= q->evtime; q=q->next) qold=q;
- if (q==NULL) { /* end of list */
- qold->next = p;
- p->prev = qold;
- p->next = NULL;
- }
- else if (q==evlist) { /* front of list */
- p->next=evlist;
- p->prev=NULL;
- p->next->prev=p;
- evlist = p;
- }
- else { /* middle of list */
- p->next=q;
- p->prev=q->prev;
- q->prev->next=p;
- q->prev=p;
- }
- }
- }
- static void printevlist() /* currently not called */
- {
- struct event *q;
- /* printf("-------------- Event List Follows:n");*/
- for(q = evlist; q!=NULL; q=q->next) {
- printf("EV %f, t: %d entity: %c ",q->evtime,q->evtype,
- (q->eventity==A)?'A':'B');
- if(q->evtype == TIMER_INTERRUPT) printf("%dn",q->tnum);
- else if(q->evtype ==FROM_LAYER3) simprpacket(q->pktptr);
- else printf("n");
- }
- /* printf("--------------n");*/
- }
- /********************** Student-callable ROUTINES ***********************/
- static double gettime() { return simtime;}
- static void onofflayer5(int AorB, int ONorOFF)
- {
- if(AorB == A) OOA = ONorOFF;
- else OOB = ONorOFF;
- }
- /* called by students routine to cancel a previously-started timer */
- static void stoptimer( int AorB, int tnum)
- {
- struct event *q;
- if (TRACE>4)
- printf(" STOP TIMER: %c %d at %fn",(AorB==A)?'A':'B', tnum,simtime);
- for (q=evlist; q!=NULL ; q = q->next)
- if ( q->evtype==TIMER_INTERRUPT && q->eventity==AorB && q->tnum == tnum ) {
- /* remove this event */
- if (q->next==NULL && q->prev==NULL)
- evlist=NULL; /* remove first and only event on list */
- else if (q->next==NULL) /* end of list - there is one in front */
- q->prev->next = NULL;
- else if (q==evlist) { /* front of list - there must be event after */
- q->next->prev=NULL;
- evlist = q->next;
- }
- else { /* middle of list */
- q->next->prev = q->prev;
- q->prev->next = q->next;
- }
- free(q);
- return;
- }
- if(AorB==A) {
- nstopA++;
- if(nstopA==1) {
- printf("PANIC cannot stop timer A %d, it is not runningn",tnum);
- printf(" this message is given only oncen");
- }
- } else {
- nstopB++;
- if(nstopB==1) {
- printf("PANIC cannot stop timer B %d, it is not runningn",tnum);
- printf(" this message is given only oncen");
- }
- }
- }
- static void starttimer(int AorB, int tnum, float increment)
- {
- struct event *q;
- struct event *evptr;
- if (TRACE>4)
- printf(" START TIMER: %c %d at %f, incr %f, timeout: %fn",
- (AorB==A)?'A':'B', tnum, simtime, increment, simtime+increment);
- /* be nice: check to see if timer is already started, if so, then warn */
- for (q=evlist; q!=NULL ; q = q->next)
- if ( q->evtype==TIMER_INTERRUPT && q->eventity==AorB && q->tnum == tnum ) {
- /* timer is already running */
- if(AorB==A) {
- nrestartA++;
- if(nrestartA==1) {
- printf("PANIC cannot start timer A %d, it is already runningn",tnum);
- printf(" this message is given only oncen");
- }
- } else {
- nrestartB++;
- if(nrestartB==1) {
- printf("PANIC cannot start timer B %d, it is already runningn", tnum);
- printf(" this message is given only oncen");
- }
- }
- return;
- }
- /* create future event for when timer goes off */
- evptr = (struct event *)malloc(sizeof(struct event));
- evptr->evtime = simtime + increment;
- for (q=evlist; q!=NULL ; q = q->next)
- if ( (q->evtype==TIMER_INTERRUPT && q->eventity==AorB) )
- if( evptr->evtime == q->evtime) { evptr->evtime += 0.1 ;}
- evptr->evtype = TIMER_INTERRUPT;
- evptr->eventity = AorB;
- evptr->tnum = tnum;
- insertevent(evptr);
- }
- /************************** TOLAYER3 ***************/
- static void tolayer3(int AorB, struct pkt packet)
- {
- struct pkt *mypktptr;
- struct event *evptr, *q;
- double lastime, at;
- float x;
- int i;
- char prAB;
- prAB= (AorB==A) ? 'A' : 'B';
- (AorB==A) ? nto3A++ : nto3B++;
- if (TRACE>4) {
- printf(" TOLAYER3 %c: ", prAB);
- simprpacket(&packet);
- }
- /* make a copy of the packet for the event list */
- mypktptr = (struct pkt *)malloc(sizeof(struct pkt));
- *mypktptr = packet;
- /* create future event for arrival of packet at the other side */
- evptr = (struct event *)malloc(sizeof(struct event));
- evptr->evtype = FROM_LAYER3; /* packet will pop out from layer3 */
- evptr->eventity = (AorB==A) ? B : A; /* event occurs at other entity */
- evptr->pktptr = mypktptr; /* save ptr to my copy of packet */
- /* finally, compute the arrival time of packet at the other end. */
- lastime = simtime;
- for (q=evlist; q!=NULL ; q = q->next)
- if ( (q->evtype==FROM_LAYER3 && q->eventity==evptr->eventity) )
- lastime = q->evtime;
- at = simtime + 10.0 + 20.0 * simrand();
- if( at < lastime +2.0 ) at = lastime + 2.0; /* maximum 10 packets in pipeline */
- evptr->evtime = at;
- evptr->tnum = 0;
- if (simrand() < lossprob) { /* simulate losses: */
- (AorB==A) ? nlostA++ : nlostB++;
- if (TRACE>2) printf(" TOLAYER3 %c: packet being lostn",prAB);
- evptr->tnum = 1; /*other side should drop packet */
- } else if (simrand() < corruptprob) { /* simulate corruption: */
- (AorB==A) ? ncorA++ : ncorB++;
- if ( (x = simrand()) < .75) mypktptr->mes.data[0]='Z'; /* corrupt payload*/
- else if (x < .875) mypktptr->seqnum = packet.seqnum+1;
- else mypktptr->acknum = packet.acknum+1;
- if (TRACE>2) printf(" TOLAYER3 %c: packet being corruptedn",prAB);
- }
- if (TRACE>4) printf(" TOLAYER3 %c: arrival on other side %fn",prAB,
- evptr->evtime);
- insertevent(evptr);
- }
- static void tolayer5(int AorB, struct msg mes)
- {
- int nr;
- nrec++;
- if(TRACE==0 /*&& (nrec%1000) == 0*/) { printf("%8dr",nrec); fflush(stdout);}
- (AorB == A) ? nrecA++ : nrecB++ ;
- nr = ((mes.data[16]*256 + mes.data[17])*256 + mes.data[18])*256 + mes.data[19];
- if ( AorB == A ) {
- if (nr != seqA+1 && okA == 1) {
- printf("PANIC A received message %d should be %dn",nr, seqA+1);
- printf(" this message is given only oncen");
- okA=0;
- }
- seqA++;
- } else {
- if (nr != seqB+1 && okB == 1) {
- printf("PANIC B received message %d should be %dn",nr, seqB+1);
- printf(" this message is given only oncen");
- okB=0;
- }
- seqB++;
- }
- if (TRACE>4) {
- printf(" TOLAYER5 %c: data received: ",(AorB==A)?'A':'B');
- simprcont(mes);
- }
- }
- /************************** MAIN ***************/
- main(int argc, char *argv[])
- {
- struct event *ep;
- struct msg msg2give;
- int side;
- int i,j;
- init(argc, argv);
- A_init();
- B_init();
- while (1) {
- /*printevlist();*/
- ep = evlist; /* get next event to simulate */
- if (ep == NULL) {
- break;
- }
- evlist = evlist->next; /* remove this event from event list */
- if (evlist!=NULL) evlist->prev = NULL;
- simtime = ep->evtime; /* update time to next event time */
- side = ep->eventity;
- if (TRACE>=4) {
- printf("nEVENT for %c time: %f type: ",(side==A)?'A':'B',simtime);
- switch (ep->evtype) {
- case TIMER_INTERRUPT: printf("Timerinterrupt %dn",ep->tnum); break;
- case FROM_LAYER5: printf("Fromlayer5 %sn",
- (side==A)?((OOA==OFF)?"OFF":"ON"):((OOB==OFF)?"OFF":"ON"));break;
- case FROM_LAYER3: printf("Fromlayer3n");
- printf(" ");
- simprpacket(ep->pktptr);break;
- default: printf("UNKNOWNn");
- }
- }
- if (ep->evtype == FROM_LAYER5 ) {
- if( (side==A && OOA==OFF) || (side==B && OOB==OFF) ) {
- if(evlist == NULL) {
- printf("PANIC layer5 %c message is waiting butn",(side==A)?'A':'B');
- printf(" layer is OFF and no other event is in the list.n");
- printf(" No student code will be called which could switch ONn");
- break;
- } else { /* put event back in */
- ep->evtime = evlist->evtime + 0.05; /* with delay */
- if( TRACE>=4) {
- printf(" ");
- printf("message delayed untill %fn",ep->evtime);
- }
- insertevent(ep); ep=NULL; /* it should not be freed */
- }
- } else {
- j = (side == A) ? nsimA : nsimB;
- for (i=0; i<16; i++) msg2give.data[i] = 97 + (j%26);
- msg2give.data[19] = j % 256; j = j/256;
- msg2give.data[18] = j % 256; j = j/256;
- msg2give.data[17] = j % 256; j = j/256;
- msg2give.data[16] = j % 256;
- if (TRACE>4) {
- printf(" MAINLOOP: data given to %c_output: ",
- (side == A)?'A':'B');
- simprcont(msg2give);
- }
- if (side == A) nsimA++, A_output(msg2give);
- else nsimB++, B_output(msg2give);
- nsim++;
- if(nsim < ( (BIDIRECTIONAL ==0) ? nsimmax : nsimmax-1 ) )
- generate_next_arrival(side); /* */
- }
- }
- else if (ep->evtype == FROM_LAYER3) {
- if(ep->tnum == 0) {
- if (side ==A) A_input(*(ep->pktptr)); /* deliver packet by calling */
- else B_input(*(ep->pktptr)); /* appropriate entity */
- }
- free(ep->pktptr); /* free the memory for packet */
- }
- else if (ep->evtype == TIMER_INTERRUPT) {
- if (side == A) ntoA++, A_timerinterrupt(ep->tnum);
- else ntoB++, B_timerinterrupt(ep->tnum);
- }
- else printf("INTERNAL PANIC: unknown event type n");
- if(ep != NULL) free(ep);
- }
- printf("n Terminated at time %fn",simtime);
- if(nsimA==nrecB && nsimB==nrecA && okA==1 && okB==1 && nrestartA==0 && nrestartB == 0
- && nstopA==0 && nstopB==0 && nsim==nsimmax)
- printf("Everything looks OKnn");
- else printf("Something is wrong, check belownn");
- printf("Requested messages from layer5: %dn",nsimmax);
- printf(" send from layer5 %6d msgs, received at layer5 %6d msgsn",nsim, nrec);
- printf(" send from layer5 A %6d msgs, received at layer5 B %6d msgsn",nsimA, nrecB);
- printf(" send from layer5 B %6d msgs, received at layer5 A %6d msgsn",nsimB, nrecA);
- printf("nOrder of received messages:n");
- printf(" messages received at A are %s ordern",(okA==1)? "in" : "out of");
- printf(" messages received at B are %s ordern",(okB==1)? "in" : "out of");
- printf("nTimer usage:n");
- printf(" timer A is started %d times while already runningn",nrestartA);
- printf(" timer B is started %d times while already runningn",nrestartB);
- printf(" timer A is stopped %d times while not runningn",nstopA);
- printf(" timer B is stopped %d times while not runningn",nstopB);
- printf(" number of timeouts: A %d B %dn",ntoA,ntoB);
- printf("nStatistics from layer 3:n");
- printf(" send from layer3 %8d pkts, lost %8d, corrupted %8dn",
- nto3A+nto3B, nlostA + nlostB, ncorA + ncorB);
- printf(" send from layer3 A %8d pkts, lost %8d, corrupted %8dn",nto3A,nlostA, ncorA);
- printf(" send from layer3 B %8d pkts, lost %8d, corrupted %8dn",nto3B,nlostB, ncorB);
- A_finish(); B_finish();
- printf("n %d %f %f %f %dn",nsimmax, lossprob,corruptprob, lambda, TRACE);
- system("PAUSE");
- return 0;
- }
code
By: S W | Date: Jan 6 2010 16:22 | Format: None | Expires: never | Size: 27.91 KB | Hits: 2058
Latest pastes
15 hours ago
16 hours ago
1 days ago
2 days ago
4 days ago