Question: #include /********************************************************************* Modified from ALTERNATING BIT AND GO-BACK-N NETWORK EMULATOR: VERSION 1.1 J.F.Kurose inter-datagram time: uniformly random in [0, 2*lambda] (e.g., lambda = 20) propagation

#include /********************************************************************* Modified from ALTERNATING BIT AND GO-BACK-N NETWORK EMULATOR: VERSION 1.1 J.F.Kurose inter-datagram time: uniformly random in [0, 2*lambda] (e.g., lambda = 20) propagation time from A to B: uniformly random in [1, 10] You may determine the time-out value appropriately (e.g., 15) **********************************************************************/ #define BIDIRECTIONAL 0 /* Unidirectional */ /* a datagram "dgm" is the data unit passed from layer 3 (teachers code) to layer */ /* 2 (students' code). It contains the data (characters) to be delivered */ /* to layer 3 via the students data link layer protocol entities. */ struct dgm { char data[20]; }; /* a frame is the data unit passed from layer 2 (students code) to layer */ /* 1 (teachers code). Note the pre-defined frame structure, which all */ /* students must follow. */ struct frm { int seqnum; int acknum; int checksum; char payload[20]; }; /********* STUDENTS WRITE THE NEXT ROUTINES *********/ /*========== A_output ===========*/ /* called from layer 3, pass the datagram to be sent to other side */ A_output(datagram) struct dgm datagram; { } /*========== A_input ===========*/ /* called from layer 1, when a frame arrives for layer 2 */ A_input(frame) struct frm frame; { } /*========== A_timerinterrupt ===========*/ /* called when A's timer goes off */ A_timerinterrupt() { } /*========== A_init ===========*/ /* the following routine will be called once (only) before any other */ /* entity A routines are called. You can use it to do any initialization */ A_init() { } /*========== B_output (Do not need)===========*/ /* Note that with simplex transfer from A-to-B, there is no B_output() */ /* B_output(datagram) /* don't need for unidirectional communication */ struct dgm datagram; { } */ /*========== B_input ===========*/ /* called from layer 1, when a frame arrives for layer 2 at B*/ B_input(frame) struct frm frame; { } /*========== B_timerinterrupt (Do not need)===========*/ /* called when B's timer goes off */ B_timerinterrupt() /* don't need for unidirectional communication */ { } */ /*========== B_init ===========*/ /* the following routine will be called once (only) before any other */ /* entity B routines are called. You can use it to do any initialization */ B_init() { } /*========== main ===========*/ /***************************************************************** ***************** NETWORK EMULATION CODE STARTS BELOW *********** The code below emulates the layer 1 and below network environment: - emulates the transmission and delivery (possibly with bit-level corruption and frame loss) of frames across the layer 1/2 interface - handles the starting/stopping of a timer, and generates timer interrupts (resulting in calling students timer handler). - generates datagram to be sent (passed from later 3 to 2) 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 - but again, and you definitely should not have to modify. ******************************************************************/ struct event { float evtime; /* event time */ int evtype; /* event type code */ int eventity; /* entity where event occurs */ struct frm *frmptr; /* ptr to frame (if any) assoc w/ this event */ struct event *prev; /* previous event pointer */ struct event *next; /* next event pointer */ }; struct event *evlist = NULL; /* the event list */ /* possible events: */ #define TIMER_INTERRUPT 0 #define FROM_LAYER3 1 #define FROM_LAYER1 2 #define OFF 0 #define ON 1 #define A 0 #define B 1 int TRACE = 1; /* for my debugging */ int nsim = 0; /* number of datagrams from 3 to 2 so far */ int nsimmax = 0; /* number of max datagrams to generate, then stop */ float time = 0.000; float lossprob; /* probability that a frame is dropped */ float corruptprob; /* probability that one bit in frame is flipped */ float lambda; /* arrival rate of datagrams from layer 3 */ int ntolayer1; /* number of frames sent into layer 1 */ int nlost; /* number of frames lost in media */ int ncorrupt; /* number of frames corrupted by media */ main() { struct event *eventptr; struct dgm dgm2give; struct frm frm2give; int i,j; char c; init(); A_init(); B_init(); while (1) { eventptr = evlist; /* get the next event to simulate from the event list */ if (eventptr==NULL) goto terminate; evlist = evlist->next; /* remove the event from the event list */ if (evlist!=NULL) evlist->prev=NULL; if (TRACE>=2) { printf(" EVENT time: %f,",eventptr->evtime); printf(" type: %d",eventptr->evtype); if (eventptr->evtype==0) printf(", timerinterrupt "); else if (eventptr->evtype==1) printf(", fromlayer5 "); else printf(", fromlayer3 "); printf(" entity: %d ",eventptr->eventity); } time = eventptr->evtime; /* update time to the current event time */ if (nsim==nsimmax) break; /* all done with simulation */ if (eventptr->evtype == FROM_LAYER3 ) { generate_next_arrival(); /* set up future datagram arrival */ /* fill in datagram to give with string of the same letter */ j = nsim % 26; for (i=0; i<20; i++) dgm2give.data[i] = 97 + j; if (TRACE>2) { printf(" MAINLOOP: data given to student: "); for (i=0; i<20; i++) printf("%c", dgm2give.data[i]); printf(" "); } nsim++; if (eventptr->eventity == A) { A_output(dgm2give); } /* else { B_output(dgm2give); } */ else if (eventptr->evtype == FROM_LAYER1) { frm2give.seqnum = eventptr->frmptr->seqnum; frm2give.acknum = eventptr->frmptr->acknum; frm2give.checksum = eventptr->frmptr->checksum; for (i=0; i<20; i++) frm2give.payload[i] = eventptr->frmptr->payload[i]; if (eventptr->eventity ==A) { /* deliver frame by calling */ A_input(frm2give); /* appropriate entity */ } /* else { B_input(frm2give); } */ free(eventptr->frmptr); /* free the memory for frame */ } else if (eventptr->evtype == TIMER_INTERRUPT) { if (eventptr->eventity == A) { A_timerinterrupt(); } /* else { B_timerinterrupt(); } */ else { printf("INTERNAL PANIC: unknown event type "); } free(eventptr); } terminate: printf(" Simulator terminated at time %f after sending %d dgms from layer5 ",time,nsim); } /*========== main ===========*/ /*========== init ===========*/ init() /* initialize the simulator */ { int i; float sum, avg; float jimsrand(); printf("----- Stop and Wait Network Simulator Version 1.1 -------- "); printf("Enter the number of datagrams to simulate: "); scanf("%d",&nsimmax); printf("Enter the frame loss probability [0.0 for no loss]:"); scanf("%f",&lossprob); printf("Enter the frame corruption probability [0.0 for no corruption]:"); scanf("%f",&corruptprob); printf("Enter the average time between datagrams from sender's layer3 [ > 0.0]:"); scanf("%f",&lambda); printf("Enter TRACE:"); scanf("%d",&TRACE); srand(9999); /* init random number generator */ sum = 0.0; /* test random number generator for students */ for (i=0; i<1000; i++) sum=sum+jimsrand(); /* jimsrand() should be uniform in [0,1] */ avg = sum/1000.0; if (avg < 0.25 || avg > 0.75) { printf("It is likely that random number generation on your machine " ); printf("is different from what this emulator expects. Please take "); printf("a look at the routine jimsrand() in the emulator code. Sorry. "); exit(); } ntolayer1 = 0; nlost = 0; ncorrupt = 0; time=0.0; /* initialize time to 0.0 */ generate_next_arrival(); /* initialize the event list */ } /*========== init ===========*/ /*========== jimsrand ===========*/ /****************************************************************************/ /* jimsrand(): returns 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 the range [0,mmm] */ /****************************************************************************/ float jimsrand() { double mmm = 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); } /*========== jimsrand ===========*/ /************** EVENT HANDLINE ROUTINES **************/ /* The next set of routines handle the event list */ /*****************************************************/ /*========== generate_next_arrival ===========*/ generate_next_arrival() { double x,log(),ceil(); struct event *evptr; char *malloc(); float ttime; int tempint; if (TRACE>2) printf(" GENERATE NEXT ARRIVAL: creating new arrival "); x = lambda*jimsrand()*2; /* x is uniform on [0,2*lambda] */ /* having mean of lambda */ evptr = (struct event *)malloc(sizeof(struct event)); evptr->evtime = time + x; evptr->evtype = FROM_LAYER3; if (BIDIRECTIONAL && (jimsrand()>0.5) ) /* randomly create datagram arrival */ evptr->eventity = B; else evptr->eventity = A; insertevent(evptr); } /*========== generate_next_arrival ===========*/ /*========== insertevent ===========*/ insertevent(p) struct event *p; { struct event *q,*qold; if (TRACE>2) { printf(" INSERTEVENT: time is %lf ",time); printf(" INSERTEVENT: future time will be %lf ",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; } } } /*========== insertevent ===========*/ /*========== printevlist ===========*/ printevlist() { struct event *q; int i; printf("-------------- Event List Follows: "); for(q = evlist; q!=NULL; q=q->next) { printf("Event time: %f, type: %d entity: %d ",q->evtime,q->evtype,q->eventity); } printf("-------------- "); } /*========== printevlist ===========*/ /****************** Student-callable ROUTINES **********************/ /* called by students routine to cancel a previously-started timer */ /*******************************************************************/ /*========== stoptimer ===========*/ stoptimer(AorB) int AorB; /* A or B is trying to stop timer */ { struct event *q,*qold; if (TRACE>2) printf(" STOP TIMER: stopping timer at %f ",time); /* for (q=evlist; q!=NULL && q->next!=NULL; q = q->next) */ for (q=evlist; q!=NULL ; q = q->next) if ( (q->evtype==TIMER_INTERRUPT && q->eventity==AorB) ) { /* 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; } printf("Warning: unable to cancel your timer. It wasn't running. "); } /*========== stoptimer ===========*/ /*========== starttimer ===========*/ starttimer(AorB,increment) int AorB; /* A or B is trying to stop timer */ float increment; { struct event *q; struct event *evptr; char *malloc(); if (TRACE>2) printf(" START TIMER: starting timer at %f ",time); /* be nice: check to see if timer is already started, if so, then warn */ /* for (q=evlist; q!=NULL && q->next!=NULL; q = q->next) */ for (q=evlist; q!=NULL ; q = q->next) if ( (q->evtype==TIMER_INTERRUPT && q->eventity==AorB) ) { printf("Warning: attempt to start a timer that is already started "); return; } /* create future event for when timer goes off */ evptr = (struct event *)malloc(sizeof(struct event)); evptr->evtime = time + increment; evptr->evtype = TIMER_INTERRUPT; evptr->eventity = AorB; insertevent(evptr); } /*========== starttimer ===========*/ /********** TOLAYER1 *************/ /*========== tolayer1 ===========*/ tolayer1(AorB,frame) int AorB; /* A or B is trying to stop timer */ struct frm frame; { struct frm *myfrmptr; struct event *evptr,*q; char *malloc(); float lastime, x, jimsrand(); int i; ntolayer1++; /* simulate losses: */ if (jimsrand() < lossprob) { nlost++; if (TRACE>0) printf(" TOLAYER1: frame being lost "); return; } /* make a copy of the frame student just gave me since he/she may decide */ /* to do something with the frame after we return back to him/her */ myfrmptr = (struct frm *)malloc(sizeof(struct frm)); myfrmptr->seqnum = frame.seqnum; myfrmptr->acknum = frame.acknum; myfrmptr->checksum = frame.checksum; for (i=0; i<20; i++) myfrmptr->payload[i] = frame.payload[i]; if (TRACE>2) { printf(" TOLAYER3: seq: %d, ack %d, check: %d ", myfrmptr->seqnum, myfrmptr->acknum, myfrmptr->checksum); for (i=0; i<20; i++) printf("%c",myfrmptr->payload[i]); printf(" "); } /* create future event for arrival of frame at the other side */ evptr = (struct event *)malloc(sizeof(struct event)); evptr->evtype = FROM_LAYER1; /* frame will pop out from layer1 */ evptr->eventity = (AorB+1) % 2; /* event occurs at the other entity */ evptr->frmptr = myfrmptr; /* save ptr to my copy of frame */ /* finally, compute the arrival time of frame at the other end. medium cannot reorder, so make sure frame arrives between 1 and 10 time units after the latest arrival time of frames currently in the medium on their way to the destination */ lastime = time; /* for (q=evlist; q!=NULL && q->next!=NULL; q = q->next) */ for (q=evlist; q!=NULL ; q = q->next) if ( (q->evtype==FROM_LAYER1 && q->eventity==evptr->eventity) ) lastime = q->evtime; evptr->evtime = lastime + 1 + 9*jimsrand(); /* simulate corruption: */ if (jimsrand() < corruptprob) { ncorrupt++; if ( (x = jimsrand()) < .75) myfrmptr->payload[0]='Z'; /* corrupt payload */ else if (x < .875) myfrmptr->seqnum = 999999; else myfrmptr->acknum = 999999; if (TRACE>0) printf(" TOLAYER1: frame being corrupted "); } if (TRACE>2) printf(" TOLAYER1: scheduling arrival on other side "); insertevent(evptr); } /*========== tolayer1 ===========*/ /*========== tolayer3 ===========*/ tolayer3(AorB,datasent) int AorB; char datasent[20]; { int i; if (TRACE>2) { printf(" TOLAYER3: data received: "); for (i=0; i<20; i++) printf("%c",datasent[i]); printf(" "); } } /*========== tolayer3 ===========*/

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!