CIS 677 LAB ASSIGNMENT I(b)
Due Friday, May 15, by the beginning of class.

1 Goal

2 Layered architecture

For the purpose of this lab, assume that each node in the network has three layers: physical layer, datalink layer (DLC) and application layer. Nodes in the network are connected to one another via links. Each layer in a node can be thought of as an abstract entity that performs certain functions. Similarly, links are also entities that have some functionality. Figure 1 outlines the three layers in a node connected by a link entity. In this lab, you will learn how these entities communicate with one another, and will develop a DLC layer entity that performs error correction using the Go-Back-N protocol.



Figure 1Layered Architecture

3 Protocol Data Units

Each layer communicates through Protocol Data Units (PDU). The application layer PDU is called A PDU, the DLC PDU is called D_PDU, and the physical layer PDU is called PH_PDU. The A_PDU, D PDU and PH_PDU formats are defined below. These definitions, together with some others are provided to you in the file pdu.h .

 typedef struct {          int  snode;                    /* source node address      */          int  dnode;                    /* destination node address */          char data[DATASIZE];           /* data                     */  } A_PDU_TYPE;    /* ---------- D_PDU Definition ----- */  #define D_INFO 0  #define D_ACK  1  #define D_NAK  2    typedef struct {       int               curr_node;   /* address of this node */       int               next_node;   /* address of next node */         /* ----------- Begin: New fields -------- */       int               type;        /* One of D_INFO, D_ACK, D_NAK   */       int               seq_number;  /* Sequence number of this D_PDU */       int               ack_number;  /* Sequence number of ACK/NAK    */       /* ----------- End: New fields -------- */         A_PDU_TYPE        a_pdu;       enum boolean      error;       /* YES if the packet is corrupted;         otherwise NO.            */  } D_PDU_TYPE;    /* data unit between physical layers */  typedef struct {       int               type;        /* ERR, DATA                */       D_PDU_TYPE        d_pdu;  } PH_PDU_TYPE;    typedef struct {          union {                               /* structure containing a_pdu */                  A_PDU_TYPE        a_pdu;      /* d_pdu or ph_pdu as a union */                  D_PDU_TYPE        d_pdu;                  PH_PDU_TYPE       ph_pdu;          } u;          int type;  /* One of: TYPE_IS_A_PDU, TYPE_IS_D_PDU, TYPE_IS_PH_PDU */  } PDU_TYPE;

NOTE: The D_PDU definition has three extra fields, and these are used by the Go-Back-N protocol.

4 The Go-Back-N Protocol

This section describes how you must implement the Go-Back-N algorithm for the lab. Several parts of the implementation have already been provided to you as part of the lab.

4.1 The Go-Back-N variables

To implement the Go-Back-N protocol, the DLC layer maintains a structure DLC_Conn_Info_TYPE as shown below. A pointer to this structure is automatically passed to the dlc layer entity that you need to write.

 #define MAXWIN 7  #define MAXBUFFER 7  #define MAXCONNECTIONS 4    typedef struct {      int snd_nxt,    /* Sequence number of next D_PDU to be sent */          snd_una,    /* Sequence number of the first unacknowledged D_PDU */          rcv_nxt,    /* Sequence number of next D_PDU expected to be received */          nak_already_sent, /* 0 => Can send Nak. 1 => Can't send Nak */          window_size; /* Window size for go-back-N. Initialized to MAXWIN. */         PDU_BUFFER_TYPE pdu_buffer;  /* This is the transmission buffer   */       /* This is only accessible through the following functions:       */       /*              InsertPDUIntoBuffer(dlc_layer_entity,pdu,dci);    */       /*              UpdatePDUBuffer(dlc_layer_entity,pdu,dci);        */       /*              int DataInPDUBuffer(dci);                         */       /*              PDU_TYPE * GetPDUFromBuffer(dci);                 */  } DLC_Conn_Info_TYPE;

The DLC_Conn_Info_TYPE structure contains the following fields

4.2 The Go-Back-N Window

The Go-Back-N protocol manages two windows- the sender window and the receiver window. Both windows have a size of MAXWIN. In your implementation, the sender window should be managed using the variables snd_nxt and snd_una, and the receiver window is managed using rcv_nxt. The difference (modulo the sequence number space) between snd_nxt and snd_una gives the amount of window that has been been used up by the sender, i.e., the pdu's that have been sent, but not acked. The snd nxt variable moves to the right from snd_una to snd_una + MAXWIN. For every pdu acked, snd_una moves to the right towards snd_nxt, but can never exceed snd_nxt. Since, snd_nxt denotes the next pdu that must be sent, setting it to snd_una has the effect of retransmitting the unacked packets (or doing the Go-Back-N). Note that these operations are performed modulo the sequence number space, and we have provided you with functions to perform these operations.

4.3 The Algorithm

The following algorithm describes the events that the dlc layer must process, and the action that it must take to process these events. This algorithm is also outlined in the skeleton code provided to you in dlc layer.c

4.4 List of available functions

5 Methodology

In this lab, you will design the Go-Back-N protocol for the datalink layer. The skeleton of this code is given in the Appendix, and provided in the file dlc_layer.c

  1. In directory /usr/class/cis677/Lab2/Files/, you will find these files:

  2. Copy the above files to your directory.
  3. Experiment with lab2_demo.
  4. Study the source code files carefully. (don't worry about the config files).
  5. Now you are ready to write your program for the datalink layer. All you have to do in this lab is fill in the appropriate code in dlc_layer.c
  6. To compile your program, type make. This will produce an executable called lab2_exec in your working directory.
  7. Now execute your version of the code and use the configuration files to make sure it works.
  8. Run the script drawgraphs. The script will run your executable and produce several postscript files (one for each configuration). These files will contain graphs of the number of pdu's received by each dlc entity plotted against time. You must submit hard copies of these graphs.

6 Submissions

You must submit the following by email to cis677@netlab.ohio-state.edu. The subject line of your email should contain "cis677 lab1b submission userid" where userid is your cis login.

You must submit hard copies of the following:

7 Appendix: dlc_layer.c

   /****************************************************/  /* ----- DO NOT REMOVE OR MODIFY ---- */  #include "cisePort.h"  #include "sim.h"  #include "component.h"  #include "comptypes.h"  #include "list.h"  #include "eventdefs.h"  #include "main.h"  #include "route_activity.h"  #include "sim_tk.h"    #include "dlc_layer.h"    /* Sequence Number Manipulation/Test Macros:     Accounts for Data Availability in Buffer and Wrap Around */    #define IncrementSequenceNumber(i,N) {(i) = ((i)+1)%(N);}  #define out_of_sequence_pdu(pdu,dci) (pdu->u.d_pdu.seq_number != dci->rcv_nxt)    static int  window_open(DLC_Conn_Info_TYPE *dci)  {  int result;  int data_available = DataInPDUBuffer(dci);  int occupied_window;    occupied_window = ((dci->snd_nxt >= dci->snd_una) ?     (dci->snd_nxt - dci->snd_una) :     (dci->snd_nxt + dci->window_size + 1 - dci->snd_una));  result = ((occupied_window < data_available) &&           (occupied_window < dci->window_size));    return result;  }    static  dlc_layer_receive(DLC_LAYER_ENTITY_TYPE *dlc_layer_entity,    GENERIC_LAYER_ENTITY_TYPE *generic_layer_entity,    PDU_TYPE *pdu)  {    DLC_Conn_Info_TYPE *dci;          dci = Datalink_Get_Conn_Info(dlc_layer_entity,pdu);            /* Gets the appropriate  DLC_Conn_Info_TYPE structure */     if (DatalinkFromApplication(generic_layer_entity)) {          InsertPDUIntoBuffer(dlc_layer_entity,pdu,dci);         /* Insert A_PDU into dci->buf */        AttemptToSend(dlc_layer_entity, dci); /* Sends from the buffer */     } else if (DatalinkFromPhysical(generic_layer_entity)) {          if (pdu->u.d_pdu.error == YES){     DatalinkProcessError(dlc_layer_entity, pdu,dci);        }        else if (pdu->u.d_pdu.type == D_ACK) {     DatalinkProcessACK(dlc_layer_entity, pdu,dci);        }        else if (pdu->u.d_pdu.type == D_NAK) {     DatalinkProcessNAK(dlc_layer_entity, pdu,dci);        }        else if (pdu->u.d_pdu.type == D_INFO) {     DatalinkProcessInfo(dlc_layer_entity, pdu,dci);        }       }     return 0;  }  /********************************************************************/  /* DO YOUR CODING HERE */    static  DatalinkProcessError(DLC_LAYER_ENTITY_TYPE *dlc_layer_entity,       PDU_TYPE *pdu,       DLC_Conn_Info_TYPE *dci)  {         /* Simply Free PDU */         /* Optional : Send NAK */         return 0;  }  /********************************************************************/  static  DatalinkProcessACK(DLC_LAYER_ENTITY_TYPE *dlc_layer_entity,       PDU_TYPE *pdu,       DLC_Conn_Info_TYPE *dci)  {       /* Free up space in the retransmission buffer */       /* Use UpdatePDUBuffer();  */         /* Update snd_una   */         /* Send as many pdu's as allowed by window */       /* Use window_open() */       /* and AttemptToSend() */         /* Free pdu */       return 0;  }  /********************************************************************/  static  DatalinkProcessNAK(DLC_LAYER_ENTITY_TYPE *dlc_layer_entity,       PDU_TYPE *pdu,       DLC_Conn_Info_TYPE *dci)  {       /* Free up space in the retransmission buffer */       /* because a NAK may ack a few PDUs */         /* set snd_una and snd_next */         /* Send as many pdu's as allowed by window */       /* Use window_open() */       /* and AttemptToSend() */         /* Free pdu */       return 0;  }  /********************************************************************/  static  DatalinkProcessInfo(DLC_LAYER_ENTITY_TYPE *dlc_layer_entity,       PDU_TYPE *pdu,       DLC_Conn_Info_TYPE *dci)  {  PDU_TYPE *pdu_to_application;         /* OutOfSequence PDU => send Nak, Discard pdu and return 0 */       /* Use out_of_sequence_pdu() */       /* and SendNak() */         /* Expected PDU => Increment rcv_nxt. */       /* Use a maximum sequence of one more than window size  */       /* use IncrementSequenceNumber(dci->rcv_nxt,(dci->window_size + 1)); */       /* Reset nak_already_sent . Ack received => Naks may be sent */       /* send an Ack            */       /* use SendAck(); */         /* You can Ignore Piggybacked Acks if you want */       /* If you choose to ignore them, then make sure you send */       /* non piggybacked acks */           /* --- Send pdu to application : Same as Lab1 --- */       /* -- Send to app -- */       send_pdu_to_application_layer(dlc_layer_entity,pdu_to_application);         pdu_free(pdu);       return 0;  }  /********************************************************************/  /* Do not change the name of the following function */  /* This function is automatically called when the timer expires */  static  DatalinkTimerExpired(DLC_LAYER_ENTITY_TYPE *dlc_layer_entity,       DLC_Conn_Info_TYPE *dci)  {         dci->snd_nxt = dci->snd_una;       /* Retransmit All Unacknowledged D_PDUs */       /* Send as many pdu's as allowed by window */       /* Use window_open() */       /* and AttemptToSend() */             return 0;  }  /*******************************************************************/  /* -------- similar to former DatalinkToPhysical -----------  */  static  AttemptToSend(DLC_LAYER_ENTITY_TYPE *dlc_layer_entity,       DLC_Conn_Info_TYPE *dci)  {  PDU_TYPE *pdu_to_send;  PDU_TYPE *pdu_to_physical = pdu_alloc();         if(window_open(dci)){         /* set a retransmission timer */    /* use SetTimer(); */      /* get PDU from buffer */      /* Copy it to pdu_to_physical and */    /* fill the remaining fields of pdu_to_physical */        /* send_pdu_to_physical_layer(); */      /* increment snd_nxt */       }         return 0;  }  /********************************************************************/    static  SendAck(DLC_LAYER_ENTITY_TYPE *dlc_layer_entity, PDU_TYPE *pdu,       DLC_Conn_Info_TYPE *dci)  {  PDU_TYPE *pdu_to_physical = pdu_alloc();    /* Fill in the needed fields */    /* Send to Physical layer */       return 0;  }  /********************************************************************/  static  SendNak(DLC_LAYER_ENTITY_TYPE *dlc_layer_entity, PDU_TYPE *pdu,       DLC_Conn_Info_TYPE *dci)  {  PDU_TYPE *pdu_to_physical;    /* Don't send Nak if nak_already_sent is 1 */  /* But do send an Ack */      pdu_to_physical =  pdu_alloc();    /* Fill in the needed fields */    /* Send to Physical layer */    /* Set nak_already_sent to 1 */         return 0;  }    }