Beispiel #1
0
 /// <returns>Main receive event</returns>
 public override Event ReceivePacket(Packet packet)
 {
     return () => {
     switch(packet.type) {
         case PacketType.ACK:
         ProcessACKPacket(packet);
         break;
         case PacketType.DATA:
             ProcessDataPacket(packet);
         break;
         default:
             // ignore routing packets
         break;
     }
     };
 }
Beispiel #2
0
 // On every ack, adjust the timeout
 // On 3DA, reset `seq_num` of the host
 public void ProcessAck(Packet pkt, Time current_time)
 {
     if (pkt.seq_num == 1) { // first packet
     AdjustTimeout(current_time - pkt.timestamp, true);
     }
     else {
     AdjustTimeout(current_time - pkt.timestamp, false);
     }
     if (pkt.seq_num > this.biggest_ack) {
     this.biggest_ack = pkt.seq_num;
     this.dup_cnt = 0;
     reset_seq = false;
     }
     else if (pkt.seq_num == this.biggest_ack) {
     this.dup_cnt++;
     if (dup_cnt == 3) { reset_seq = true; }
     else { reset_seq = false; }
     }
 }
Beispiel #3
0
 // On every timeout, reset `seq_num` of the host
 public void ProcessTimeout(Packet pkt, Time current_time)
 {
     reset_seq = true;
 }
Beispiel #4
0
 // On timeout, set window size to 1, and go into slow start
 // When the window size is 1, don't reset slow start thresh. (to 2)
 // It just means that the retransmitted packet (after 3DA) has been dropped.
 public void ProcessTimeout(Packet pkt, Time current_time)
 {
     if (window_size != 1.0) {
     slow_start_thresh = System.Math.Max(2.0, window_size / 2.0);
     window_size = 1.0;
     } else {
     dup_cnt = 0;
     }
     reset_seq = true;
     slow_start = true;
     Simulator.Message("SS:" + this);
 }
Beispiel #5
0
 // On every ack, update avg roundtrip time and its variance.
 // If the sequence number of the packet is bigger than the previous,
 // adjust the window size accordingly to the state it is in.
 // Otherwise, bump up the duplicate count.
 // Perform fast retransmit followed by congestion avoidance once you reach 3DA.
 public void ProcessAck(Packet pkt, Time current_time)
 {
     if (pkt.seq_num == 1) { // first packet
     AdjustTimeout(current_time - pkt.timestamp, true);
     }
     else {
     AdjustTimeout(current_time - pkt.timestamp, false);
     }
     if (pkt.seq_num > this.biggest_ack) {
     this.biggest_ack = pkt.seq_num;
     if (dup_cnt > 2) {
         this.dup_cnt = 0;
         window_size = slow_start_thresh;
         // finished fast recovery
         // time for congestion avoidance
         slow_start = false;
         reset_seq = true;
         Simulator.Message(this + ": TCP mode = CA");
     }
     else {
         this.dup_cnt = 0;
         if (slow_start) {
             window_size++;
             if (window_size > slow_start_thresh) {
                 slow_start = false;
                 Simulator.Message(this + ": Switching from SS to CA");
             }
         } else { // Congestion Avoidance
             window_size += 1/window_size;
         }
         reset_seq = false;
     }
     }
     else if (pkt.seq_num == this.biggest_ack) {
     this.dup_cnt++;
     if (dup_cnt == 2) {
         slow_start_thresh = System.Math.Max(2.0, window_size / 2.0);
         window_size = 1; // effectively resends a single packet
         slow_start = false;
         reset_seq = true;
         Simulator.Message(this + ": FAST TRANSMIT");
     }
     else {
         //window_size++;
         reset_seq = false;
     }
     }
 }
Beispiel #6
0
 /// <summary>
 /// The event where the Link stores the packet in the send buffer (or discards it if the buffer is full).
 /// </summary>
 /// <remarks>
 /// Note: A Link always immediately either accept a packet into the queue or discards it.
 /// The packet will be sent asynchronously at some later time.
 /// </remarks>
 /// <param name='packet'>
 /// The packet to be sent along this link
 /// </param>
 public Event EnqueuePacket(Packet packet)
 {
     return () => {
     if (!this.is_transmitting)
     {
         TransmitPacket(packet);
         //Simulator.Message(name + ":transmitting " + packet);
     }
     else if (this.buffer_occupancy + packet.size < this.buffer_size)
     {
         this.buffer.Enqueue(packet);
         //Simulator.Message(name + ":queueing " + packet);
     }
     else
     {
         this.lStatus.dropped_packets++;
         Simulator.Message("Link {0}: buffer {1}/{2}; dropping {3}",
             this.name,
             this.buffer_occupancy,
             this.buffer_size,
             packet);
     }
     //Logger.LogLinkStatus(lStatus);
     };
 }
Beispiel #7
0
 private void TransmitPacket(Packet packet)
 {
     Debug.Assert(!this.is_transmitting, "Bug: Tried to transmit two packets simultaneously");
     this.is_transmitting = true;
     double trans_duration = packet.size / this.rate;
     eqp.Add(eqp.current_time + trans_duration, this.PacketTransmissionComplete());
     double arrival_time = eqp.current_time + trans_duration + prop_delay;
     eqp.Add(arrival_time, dest.ReceivePacket(packet));
 }
Beispiel #8
0
 /// <returns>
 /// Event that occurs when this Node receives a packet.
 /// </returns>
 public abstract Event ReceivePacket(Packet packet);
Beispiel #9
0
 /// <summary>
 /// Event that router receives a packet.
 /// The router will immediately perform a routing-table lookup, and forward the packet along the appropriate link.
 /// </summary>
 /// <exception cref="InvalidOperationException">
 /// Throws an exception if the routing table has not been built yet.
 /// You should execute the RecalculateRoutingTableEvent event first.
 /// </exception>
 public override Event ReceivePacket(Packet packet)
 {
     return () => {
     if(packet.type == PacketType.LINK_STATE_ADVERTISEMENT)
         this.ProcessLinkStateAdvertisement(packet);
     else
         this.ForwardOrdinaryPacket(packet);
     };
 }
Beispiel #10
0
 /// <summary>
 /// Sends a new packet on all outgoing links.
 /// If during this round, an identical packet has already been sent, does nothing.
 /// This avoids sending infinite loops of link-state packets.
 /// </summary>
 public void Send(Packet pkt)
 {
     if(!already_seen.Contains(pkt)) {
     // Simulator.Message("Sending link-state packet {0} on links {1}", pkt, outgoing_links.ToDelimitedString());
     foreach(Link l in outgoing_links)
         eqp.Add(eqp.current_time, l.EnqueuePacket(pkt));
     already_seen.Add(pkt);
     }
 }
Beispiel #11
0
 /// <summary>
 /// Processes a received link-state advertisement by adding it to the table of known link costs.
 /// If the received packet gives us enough information, this triggers recalculation of the routing table.
 /// The advertisement will be forwarded on all outgoing links (if not already done).
 /// </summary>
 private void ProcessLinkStateAdvertisement(Packet pkt)
 {
     // Simulator.Message("Router {0} received link-state packet for link {1}", this.ip, pkt);
     Debug.Assert(pkt.seq_num <= this.routing_seq_num);
     if(pkt.seq_num == this.routing_seq_num) { // packet describes current round
     Link described_link = Simulator.LinksBySrcDest[Tuple.Create(Simulator.Nodes[pkt.src], Simulator.Nodes[pkt.link_dest])];
     Debug.Assert(described_link.cost == pkt.link_cost, "Sanity check failed: received link-state packet claiming incorrect link cost");
     if(known_link_costs.ContainsKey(described_link)) {
         Debug.Assert(known_link_costs[described_link] == pkt.link_cost);
     } else {
         known_link_costs.Add(described_link, pkt.link_cost);
     }
     RecalculateRoutingTableIfEnoughInfo();
     link_state_sender.Send(pkt);
     } else {
     Simulator.Message("Warning: received a link-state advertisement from a previous round {0} (current routing seq num = {1})",
         pkt.seq_num, this.routing_seq_num);
     }
 }
Beispiel #12
0
 /// <summary>
 /// Immediately performs a routing-table lookup and forwards an ordinary packet on the appropriate link.
 /// </summary>
 private void ForwardOrdinaryPacket(Packet packet)
 {
     if(routing_table == null)
     throw new InvalidOperationException("Cannot route packet before routing table is calculated: " + packet);
     //Simulator.Message(packet);
     Node next = routing_table[Simulator.Nodes[packet.dest]];
     Link to_next = Simulator.LinksBySrcDest[Tuple.Create((Node)this, next)];
     ///Simulator.Message(ip + ":sending " + to_next + packet);
     eqp.Add(eqp.current_time, to_next.EnqueuePacket(packet));
 }
Beispiel #13
0
 /// Sends a packet and registers timeout
 private void _SendPacket()
 {
     var packet = new Packet{
     payload_size=Packet.DEFAULT_PAYLOAD_SIZE,
     src=this.ip,
     dest=this.dest_ip,
     type=PacketType.DATA,
     seq_num=this.next_seq_num,
     timestamp = eqp.current_time
     };
     double completion_time = eqp.current_time + packet.size / link.rate;
     eqp.Add(eqp.current_time, link.EnqueuePacket(packet));
     is_busy = true;
     this.next_seq_num += 1;
     eqp.Add(completion_time, CompleteSend());
     eqp.Add(completion_time + this.timeout, CheckTimeout(packet, window_resets));
     hStat.flows[0].time = eqp.current_time;
     hStat.flows[0].window_size = window_size;
     hStat.flows[0].packets_sent++;
     //Logger.LogHostStatus(hStat);
 }
Beispiel #14
0
 /// return ack packet for a data packet
 private void ProcessDataPacket(Packet packet)
 {
     if (packet.seq_num == expected_seq_num) {
     expected_seq_num++;
     }
     var ack_p = new Packet{payload_size=Packet.DEFAULT_ACK_SIZE,
                         src=this.ip,
                         dest=packet.src,
                         type=PacketType.ACK,
                         seq_num=expected_seq_num,
                         timestamp=packet.timestamp};
     // Simulator.Message(name+":"+eqp.current_time+": Sending " + ack_p);
     UpdatePacketDelay(eqp.current_time - packet.timestamp);
     eqp.Add(eqp.current_time, link.EnqueuePacket(ack_p));
     this.flow_rec_stat.received_packets++;
 }
Beispiel #15
0
 /// Process ack packet if it lies on unacknowledged window
 private void ProcessACKPacket(Packet packet)
 {
     if (packet.seq_num >= ack_num && packet.seq_num <= next_seq_num) {
     this.tcp_strat.ProcessAck(packet, eqp.current_time);
     UpdateTCPState();
     if (this.tcp_strat.ResetSeq()) {
         window_resets++;
     }
     }
     else {
     Simulator.Message("Host {0} dropping ack {1}", this.ip, packet);
     }
     eqp.Add(eqp.current_time, SendPacket());
 }
Beispiel #16
0
 /// If the packet lies inside the unacknowledged window, process the timeout
 private Event CheckTimeout(Packet packet, int resets)
 {
     return () => {
     if (packet.seq_num >= ack_num &&
         packet.seq_num < next_seq_num &&
         window_resets == resets) {
         // timed out
         Simulator.Message("Host {0}: packet timed out: {1}", this.ip, packet);
         window_resets++;
         this.tcp_strat.ProcessTimeout(packet, eqp.current_time);
         UpdateTCPState();
         eqp.Add(eqp.current_time, SendPacket());
     }
     };
 }