123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- #include <stdio.h>
- #include <stdlib.h>
- #include "prog2.h"
- /* ******************************************************************
- ALTERNATING BIT AND GO-BACK-N NETWORK EMULATOR: VERSION 1.1 J.F.Kurose
- This code should be used for PA2, unidirectional or bidirectional
- data transfer protocols (from A to B. Bidirectional transfer of data
- is for extra credit and is not required). Network properties:
- - one way network delay averages five time units (longer if there
- are other messages in the channel for GBN), but can be larger
- - packets can be corrupted (either the header or the data portion)
- or lost, according to user-defined probabilities
- - packets will be delivered in the order in which they were sent
- (although some can be lost).
- **********************************************************************/
- /*****************************************************************
- ***************** 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 a timer, and generates timer
- interrupts (resulting in calling students timer handler).
- - generates message to be sent (passed from later 5 to 4)
- 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 - but again, you should have
- to, and you defeinitely should not have to modify
- ******************************************************************/
- event_t *evlist = NULL; /* the event list */
- int TRACE = 1; /* for my debugging */
- int nsim = 0; /* number of messages from 5 to 4 so far */
- int nsimmax = 0; /* number of msgs to generate, then stop */
- float time = 0.000;
- float lossprob; /* probability that a packet is dropped */
- float corruptprob; /* probability that one bit is packet is flipped */
- float lambda; /* arrival rate of messages from layer 5 */
- int ntolayer3; /* number sent into layer 3 */
- int nlost; /* number lost in media */
- int ncorrupt; /* number corrupted by media*/
- int main() {
-
- event_t *eventptr;
- msg_t msg2give;
- pkt_t pkt2give;
- int i,j;
- init();
- A_init();
- B_init();
- while (1) {
- /* get next event to simulate */
- eventptr = evlist;
-
- if ( eventptr == NULL )
- goto terminate;
-
- /* remove this event from event list */
- evlist = evlist->next;
-
- if (evlist != NULL)
- evlist->prev=NULL;
- if ( TRACE >= 2 ) {
- printf("\nEVENT 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\n",eventptr->eventity);
- }
- /* update time to next event time */
- time = eventptr->evtime;
-
- if ( nsim == nsimmax )
- break; /* all done with simulation */
-
- if ( eventptr->evtype == FROM_LAYER5 ) {
-
- /* set up future arrival */
- generate_next_arrival();
-
- /* fill in msg to give with string of same letter */
- j = nsim % 26;
-
- for ( i = 0; i < 20; i++ )
- msg2give.data[i] = 97 + j;
-
- if ( TRACE > 2 ) {
-
- printf(" MAINLOOP: data given to student: ");
-
- for ( i = 0; i < 20; i++ )
- printf("%c", msg2give.data[i]);
-
- printf("\n");
- }
-
- nsim++;
-
- if ( eventptr->eventity == A )
- A_output(msg2give);
- else
- B_output(msg2give);
- } else if ( eventptr->evtype == FROM_LAYER3 ) {
-
- pkt2give.seqnum = eventptr->pktptr->seqnum;
- pkt2give.acknum = eventptr->pktptr->acknum;
- pkt2give.checksum = eventptr->pktptr->checksum;
-
- for (i=0; i<20; i++)
- pkt2give.payload[i] = eventptr->pktptr->payload[i];
-
- if ( eventptr->eventity == A ) /* deliver packet by calling */
- A_input(pkt2give); /* appropriate entity */
- else
- B_input(pkt2give);
-
- free( eventptr->pktptr ); /* free the memory for packet */
-
- } else if ( eventptr->evtype == TIMER_INTERRUPT ) {
-
- if ( eventptr->eventity == A )
- A_timerinterrupt();
- else
- B_timerinterrupt();
-
- } else
- printf("INTERNAL PANIC: unknown event type \n");
- free(eventptr);
- }
- terminate:
- printf(" Simulator terminated at time %f\n after sending %d msgs from layer5\n",time,nsim);
- return EXIT_SUCCESS;
- }
- /* initialize the simulator */
- void init() {
-
- int i;
- float sum, avg;
- float jimsrand();
- printf("----- Stop and Wait Network Simulator Version 1.1 -------- \n\n");
- 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);
- /* init random number generator */
- srand(9999);
- /* test random number generator for students */
- sum = 0.0;
-
- /* jimsrand() should be uniform in [0,1] */
- for ( i = 0; i < 1000; i++ )
- sum = sum + jimsrand();
-
- avg = sum / 1000.0;
-
- if ( avg < 0.25 || avg > 0.75 ) {
- printf("It is likely that random number generation on your machine\n" );
- printf("is different from what this emulator expects. Please take\n");
- printf("a look at the routine jimsrand() in the emulator code. Sorry. \n");
- exit(1);
- }
- ntolayer3 = 0;
- nlost = 0;
- ncorrupt = 0;
- /* initialize time to 0.0 */
- time=0.0;
- /* initialize event list */
- generate_next_arrival();
- }
- /****************************************************************************/
- /* jimsrand(): 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] */
- /****************************************************************************/
- float jimsrand() {
- /* largest int - MACHINE DEPENDENT!!!!!!!! */
- double mmm = 2147483647;
- /* individual students may need to change mmm */
- float x;
- /* x should be uniform in [0,1] */
- x = rand() / mmm;
-
- return(x);
- }
- /********************* EVENT HANDLINE ROUTINES *******/
- /* The next set of routines handle the event list */
- /*****************************************************/
- void generate_next_arrival()
- {
- double x, log(), ceil();
- event_t *evptr;
- if ( TRACE > 2 )
- printf(" GENERATE NEXT ARRIVAL: creating new arrival\n");
- /* x is uniform on [0,2*lambda] */
- x = lambda * jimsrand()*2;
- /* having mean of lambda */
- evptr = (event_t *)malloc(sizeof(event_t));
- evptr->evtime = time + x;
- evptr->evtype = FROM_LAYER5;
-
- if (BIDIRECTIONAL && (jimsrand()>0.5) )
- evptr->eventity = B;
- else
- evptr->eventity = A;
- insertevent(evptr);
- }
- void insertevent( event_t *p ) {
- event_t *q,*qold;
- if ( TRACE > 2 ) {
- printf(" INSERTEVENT: time is %f\n",time);
- printf(" INSERTEVENT: future time will be %f\n",p->evtime);
- }
- /* q points to header of list in which p struct inserted */
- q = evlist;
-
- 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;
- }
- }
- }
- void printevlist()
- {
- event_t *q;
-
- printf("--------------\nEvent List Follows:\n");
-
- for(q = evlist; q!=NULL; q=q->next)
- printf("Event time: %f, type: %d entity: %d\n",q->evtime,q->evtype,q->eventity);
-
- printf("--------------\n");
- }
- /********************** Student-callable ROUTINES ***********************/
- /* called by students routine to cancel a previously-started timer */
- void stoptimer(int AorB) {
-
- event_t *q;
- if ( TRACE > 2 )
- printf(" STOP TIMER: stopping timer at %f\n",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) {
- /* remove first and only event on list */
- evlist = NULL;
- } 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.\n");
- }
- void starttimer( int AorB, float increment ) {
- event_t *q;
- event_t *evptr;
- if ( TRACE > 2 )
- printf(" START TIMER: starting timer at %f\n",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\n");
- return;
- }
- /* create future event for when timer goes off */
- evptr = (event_t *) malloc( sizeof( event_t ) );
- evptr->evtime = time + increment;
- evptr->evtype = TIMER_INTERRUPT;
- evptr->eventity = AorB;
-
- insertevent(evptr);
- }
- /************************** TOLAYER3 ***************/
- /* A or B is trying to stop timer*/
- void tolayer3( int AorB, pkt_t packet ) {
- pkt_t *mypktptr;
- event_t *evptr,*q;
- float lastime, x, jimsrand();
- int i;
- ntolayer3++;
- /* simulate losses: */
- if (jimsrand() < lossprob) {
- nlost++;
- if ( TRACE > 0 )
- printf(" TOLAYER3: packet being lost\n");
-
- return;
- }
- /* make a copy of the packet student just gave me since he/she may decide */
- /* to do something with the packet after we return back to him/her */
- mypktptr = (pkt_t *)malloc(sizeof(pkt_t));
- mypktptr->seqnum = packet.seqnum;
- mypktptr->acknum = packet.acknum;
- mypktptr->checksum = packet.checksum;
-
- for ( i = 0; i < 20; i++ )
- mypktptr->payload[i] = packet.payload[i];
-
- if ( TRACE > 2 ) {
- printf(" TOLAYER3: seq: %d, ack %d, check: %d ", mypktptr->seqnum,
-
- mypktptr->acknum, mypktptr->checksum);
-
- for ( i = 0; i < 20; i++ )
- printf( "%c", mypktptr->payload[i] );
- printf("\n");
- }
- /* create future event for arrival of packet at the other side */
- evptr = (event_t *)malloc(sizeof(event_t));
- evptr->evtype = FROM_LAYER3; /* packet will pop out from layer3 */
- evptr->eventity = (AorB+1) % 2; /* 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.
- medium can not reorder, so make sure packet arrives between 1 and 10
- time units after the latest arrival time of packets
- 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_LAYER3 && q->eventity == evptr->eventity ) )
- lastime = q->evtime;
-
- evptr->evtime = lastime + 1 + 9*jimsrand();
- /* simulate corruption: */
- if (jimsrand() < corruptprob) {
- ncorrupt++;
- if ( (x = jimsrand()) < .75) /* corrupt payload */
- mypktptr->payload[0]='Z';
- else if (x < .875)
- mypktptr->seqnum = 999999;
- else
- mypktptr->acknum = 999999;
-
- if ( TRACE > 0 )
- printf(" TOLAYER3: packet being corrupted\n");
- }
- if ( TRACE > 2 )
- printf(" TOLAYER3: scheduling arrival on other side\n");
-
- insertevent(evptr);
- }
- void tolayer5(int AorB, char datasent[20]) {
- int i;
-
- if (TRACE>2) {
- printf(" TOLAYER5: data received: ");
-
- for ( i = 0; i < 20; i++ )
- printf("%c",datasent[i]);
- printf("\n");
- }
- }
|