IT++ Logo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
tcp.cpp
Go to the documentation of this file.
1 
32 #include <itpp/protocol/tcp.h>
33 #include <itpp/base/itfile.h>
34 #include <limits>
35 #include <cstdlib>
36 #include <ctime>
37 
39 
40 #ifdef _MSC_VER
41 #pragma warning(disable:4355)
42 #endif
43 
44 namespace itpp
45 {
46 
47 // -------------------- Default parameters ----------------------------------
48 
49 // TCP sender and receiver
50 
51 #define TCP_HEADERLENGTH 40
52 
53 // TCP sender
54 
55 #define TCP_VERSION kReno
56 #define TCP_SMSS 1460
57 #define TCP_INITIALCWNDREL 2 // related to MSS
58 #define TCP_INITIALSSTHRESHREL 1 // related to MaxCWnd
59 #define TCP_MAXCWNDREL 32 // related to MSS
60 #define TCP_DUPACKS 3
61 #define TCP_INITIALRTT 1
62 const double TCP_STIMERGRAN = 0.2;
63 const double TCP_SWSATIMERVALUE = 0.2;
64 #define TCP_MAXBACKOFF 64
65 const double TCP_MAXRTO = std::numeric_limits<double>::max();
66 #define TCP_IMMEDIATEBACKOFFRESET false
67 #define TCP_TIMESTAMPS false
68 #define TCP_KARN true
69 #define TCP_NAGLE false
70 #define TCP_GOBACKN true
71 #define TCP_FLIGHTSIZERECOVERY false
72 #define TCP_RENOCONSERVATION true
73 #define TCP_CAREFULSSTHRESHREDUCTION true
74 #define TCP_IGNOREDUPACKONTORECOVERY true
75 #define TCP_CAREFULMULFASTRTXAVOIDANCE true
76 #define TCP_RESTARTAFTERIDLE true
77 
78 // TCP receiver
79 
80 #define TCP_RMSS 1460
81 const int TCP_BUFFERSIZE = std::numeric_limits<int>::max() / 4;
82 #define TCP_DELAYEDACK true
83 const double TCP_ACKDELAYTIME = 0.2;
84 #define TCP_SENDPERIODICACKS false
85 #define TCP_STRICTPERIODICACKS false
86 #define TCP_PERIODICACKINTERVAL 1
87 #define TCP_ACKSCHEDULINGDELAY 0
88 #define TCP_ACKBUFFERWRITE false
89 #define TCP_ACKBUFFERREAD true
90 const int TCP_MAXUSERBLOCKSIZE = std::numeric_limits<int>::max() / 4;
91 #define TCP_MINUSERBLOCKSIZE 1
92 #define TCP_USERBLOCKPROCDELAY 0
93 
94 // TCP generator
95 
96 #define TCPGEN_BLOCKSIZE 1460
97 
98 // TCP applications
99 
100 #define TCPAPP_MAXNOOFACTIVEAPPS 500
101 #define TCPAPP_DISTSTATARRAYSIZE 100
102 #define TCPAPP_DISTSTATMAXGOODPUT 1000
103 #define TCPAPP_DISTSTATMAXTRANSFERTIME 10000
104 #define TCPAPP_CONDMEANSTATARRAYSIZE 100
105 #define TCPAPP_CONDMEANSTATMAXREQSIZE 100000
106 
107 
108 
109 inline int min(int opd1, int opd2)
110 {
111  return (opd1 < opd2) ? opd1 : opd2;
112 }
113 
114 
115 inline int max(int opd1, int opd2)
116 {
117  return (opd1 > opd2) ? opd1 : opd2;
118 }
119 
120 
121 // round is used to map a double value (e.g. RTO in TTCPSender) to the
122 // next higher value of a certain granularity (e.g. timer granularity).
123 inline double round(const double value, const double granularity)
124 {
125  return (std::ceil(value / granularity) * granularity);
126 }
127 
128 // -------------------- TCP_Segment ----------------------------------------
129 
131  seq_begin(),
132  seq_end()
133 {
134 }
135 
136 TCP_Segment::TCP_Segment(const Sequence_Number &sn_begin, const Sequence_Number &sn_end) :
137  seq_begin(sn_begin),
138  seq_end(sn_end)
139 {
140  it_assert(seq_begin <= seq_end, "TCP_Segment::TCP_Segment, end byte " + to_str(seq_end.value()) +
141  " < begin byte " + to_str(seq_begin.value()));
142 }
143 
144 
145 TCP_Segment::TCP_Segment(const TCP_Segment &segment) :
146  seq_begin(segment.seq_begin),
147  seq_end(segment.seq_end)
148 {
149 }
150 
151 
152 TCP_Segment &TCP_Segment::operator=(const TCP_Segment &segment)
153 {
154  this->seq_begin = segment.seq_begin;
155  this->seq_end = segment.seq_end;
156 
157  return *this;
158 }
159 
160 
161 void TCP_Segment::combine(const TCP_Segment &segment)
162 {
163  it_assert(can_be_combined(segment), "TCP_Segment::CombineWith, segments cannot be combined");
164 
165  seq_begin = min(seq_begin, segment.seq_begin);
166  seq_end = max(seq_end, segment.seq_end);
167 }
168 
169 
170 std::ostream & operator<<(std::ostream &os, const TCP_Segment &segment)
171 {
172  os << "(" << segment.seq_begin << "," << segment.seq_end << ")";
173  return os;
174 }
175 
176 
177 // -------------------- TCP_Packet ----------------------------------------
179  fSegment(),
180  fACK(),
181  fWnd(0),
182  fSessionId(0),
183  fInfo(0)
184 {
185 }
186 
187 
188 TCP_Packet::TCP_Packet(const TCP_Packet &packet) :
189  fSegment(packet.fSegment),
190  fACK(packet.fACK),
191  fWnd(packet.fWnd),
192  fSessionId(packet.fSessionId),
193  fInfo(0)
194 {
195  std::cout << "TCP_Packet::TCP_Packet ############" << " ";
196 
197  if (packet.fInfo != 0) {
198  std::cout << "TCP_Packet::TCP_Packet rhs.fInfo ###########" << " ";
199  fInfo = new TDebugInfo(*packet.fInfo);
200  }
201 }
202 
203 
205 {
206  delete fInfo;
207 }
208 
209 
210 TCP_Packet & TCP_Packet::clone() const
211 {
212  return *new TCP_Packet(*this);
213 }
214 
215 
216 void TCP_Packet::set_info(unsigned ssThresh, unsigned recWnd, unsigned cWnd,
217  double estRTT, Sequence_Number sndUna,
218  Sequence_Number sndNxt, bool isRtx)
219 {
220  if (fInfo == 0) {
221  fInfo = new TDebugInfo;
222  }
223 
224  fInfo->fSSThresh = ssThresh;
225  fInfo->fRecWnd = recWnd;
226  fInfo->fCWnd = cWnd;
227  fInfo->fRTTEstimate = estRTT;
228  fInfo->fSndUna = sndUna;
229  fInfo->fSndNxt = sndNxt;
230  fInfo->fRtxFlag = isRtx;
231 }
232 
233 
234 void TCP_Packet::print_header(std::ostream &) const
235 {
236  std::cout << "Hello!\n";
237 
238  std::cout << "Ses = " << get_session_id() << " ";
239 
240  std::cout << "Segment = " << get_segment() << " "
241  << "ACK = " << get_ACK() << " "
242  << "Wnd = " << get_wnd() << " ";
243 
244  std::cout << "DestPort = " << fDestinationPort << " "
245  << "SourcePort = " << fSourcePort << " ";
246 
247 
248  if (fInfo != 0) {
249  std::cout << "SndSSThresh = " << fInfo->fSSThresh << " ";
250  std::cout << "RecWnd = " << fInfo->fRecWnd << " ";
251  std::cout << "SndCWnd = " << fInfo->fCWnd << " ";
252  std::cout << "RTTEstimate = " << fInfo->fRTTEstimate << " ";
253  std::cout << "RtxFlag = " << fInfo->fRtxFlag;
254  }
255  else
256  std::cout << "fInfo = " << fInfo << " ";
257 
258  std::cout << std::endl;
259 
260 }
261 
262 
263 
264 std::ostream & operator<<(std::ostream & out, TCP_Packet & msg)
265 {
266  msg.print_header(out);
267  return out;
268 }
269 
270 
271 // -------------------- TCP_Sender ----------------------------------------
272 TCP_Sender::TCP_Sender(int label) :
273  fLabel(label),
274  fTCPVersion(TCP_VERSION),
275  fMSS(TCP_SMSS),
276  fTCPIPHeaderLength(TCP_HEADERLENGTH),
277  fInitialRTT(TCP_INITIALRTT),
278  fInitialCWnd(0), // default initialization see below
279  fInitialSSThresh(0), // default initialization see below
280  fMaxCWnd(0), // default initialization see below
281  fDupACKThreshold(TCP_DUPACKS),
282  fTimerGranularity(TCP_STIMERGRAN),
283  fMaxRTO(TCP_MAXRTO),
284  fMaxBackoff(TCP_MAXBACKOFF),
285  fImmediateBackoffReset(TCP_IMMEDIATEBACKOFFRESET),
286  fKarn(TCP_KARN),
287  fGoBackN(TCP_GOBACKN),
288  fFlightSizeRecovery(TCP_FLIGHTSIZERECOVERY),
289  fRenoConservation(TCP_RENOCONSERVATION),
290  fCarefulSSThreshReduction(TCP_CAREFULSSTHRESHREDUCTION),
291  fIgnoreDupACKOnTORecovery(TCP_IGNOREDUPACKONTORECOVERY),
292  fCarefulMulFastRtxAvoidance(TCP_CAREFULMULFASTRTXAVOIDANCE),
293  fNagle(TCP_NAGLE),
294  fSWSATimerValue(TCP_SWSATIMERVALUE),
295  fRestartAfterIdle(TCP_RESTARTAFTERIDLE),
296  fDebug(false),
297  fTrace(false),
298  fSessionId(0),
299  fRtxTimer(*this, &TCP_Sender::HandleRtxTimeout),
300  fSWSATimer(*this, &TCP_Sender::HandleSWSATimeout)/*,*/
301 {
302 
303  // default values and parameter check for MaxCWND, InitCWND, InitSSThresh
304  if (fMaxCWnd == 0) {
305  fMaxCWnd = (unsigned)(TCP_MAXCWNDREL * fMSS);
306  }
307  else if (fMaxCWnd < fMSS) {
308  // throw (UL_CException("TCP_Sender::TCP_Sender",
309  // "MaxCWnd must be >= MSS"));
310  }
311 
312  if (fInitialCWnd == 0) {
313  fInitialCWnd = (unsigned)(TCP_INITIALCWNDREL * fMSS);
314  }
315  else if ((fInitialCWnd < fMSS) || (fInitialCWnd > fMaxCWnd)) {
316  // throw (UL_CException("TCP_Sender::TCP_Sender",
317  // "initial CWnd must be >= MSS and <= MaxCWnd"));
318  }
319 
320  if ((fInitialSSThresh == 0) && (fMaxCWnd >= 2 * fMSS)) {
321  fInitialSSThresh = (unsigned)(TCP_INITIALSSTHRESHREL * fMaxCWnd);
322  }
323  else if ((fInitialSSThresh < 2*fMSS) || (fInitialCWnd > fMaxCWnd)) {
324  // throw (UL_CException("TCP_Sender::TCP_Sender",
325  // "initial CWnd must be >= 2*MSS and <= MaxCWnd"));
326  }
327 
328  setup();
329 
330  InitStatistics();
331 
332 
333  tcp_send.set_name("TCP Send");
334  tcp_receive_ack.forward(this, &TCP_Sender::ReceiveMessageFromNet);
335  tcp_receive_ack.set_name("TCP ACK");
336  tcp_socket_write.forward(this, &TCP_Sender::HandleUserMessageIndication);
337  tcp_socket_write.set_name("SocketWrite");
338  tcp_release.forward(this, &TCP_Sender::release);
339  tcp_release.set_name("Release");
340 
341 }
342 
343 
345 {
346 }
347 
348 void TCP_Sender::set_debug(const bool enable_debug)
349 {
350  fDebug = enable_debug;
351  tcp_send.set_debug(enable_debug);
352 }
353 
354 void TCP_Sender::set_debug(bool enable_debug, bool enable_signal_debug)
355 {
356  fDebug = enable_debug;
357  tcp_send.set_debug(enable_signal_debug);
358 }
359 
360 void TCP_Sender::set_trace(const bool enable_trace)
361 {
362  fTrace = enable_trace;
363 }
364 
365 void TCP_Sender::set_label(int label)
366 {
367  fLabel = label;
368 }
369 
370 void TCP_Sender::setup()
371 {
372  fSndUna = 0;
373  fSndNxt = 0;
374  fSndMax = 0;
375  fMaxRecWnd = 0;
376  fRecWnd = fMaxCWnd;
377  fUserNxt = 0;
378  fCWnd = fInitialCWnd;
379  fSSThresh = fInitialSSThresh;
380  fRecoveryDupACK = 0;
381  fRecoveryTO = 0;
382  fDupACKCnt = 0;
383 
384  // timers
385  fBackoff = 1;
386  fPendingBackoffReset = false;
387  fLastSendTime = Event_Queue::now();
388 
389  // RTT measurement
390  fTimUna = 0;
391  fSRTT = 0;
392  fRTTVar = 0;
393  fRTTEstimate = fInitialRTT;
394  fRTTMPending = false;
395  fRTTMByte = 0;
396 
397  CWnd_val.set_size(1000);
398  CWnd_val.zeros();
399  CWnd_time.set_size(1000);
400  CWnd_time.zeros();
401  CWnd_val(0) = fInitialCWnd;
402  CWnd_time(0) = 0;
403  CWnd_index = 1;
404 
405  SSThresh_val.set_size(1000);
406  SSThresh_val.zeros();
407  SSThresh_time.set_size(1000);
408  SSThresh_time.zeros();
409  SSThresh_val(0) = fInitialSSThresh;
410  SSThresh_time(0) = 0;
411  SSThresh_index = 1;
412 
413  sent_seq_num_val.set_size(1000);
414  sent_seq_num_val.zeros();
415  sent_seq_num_time.set_size(1000);
416  sent_seq_num_time.zeros();
417  sent_seq_num_val(0) = 0;
418  sent_seq_num_time(0) = 0;
419  sent_seq_num_index = 1;
420 
421  sender_recv_ack_seq_num_val.set_size(1000);
422  sender_recv_ack_seq_num_val.zeros();
423  sender_recv_ack_seq_num_time.set_size(1000);
424  sender_recv_ack_seq_num_time.zeros();
425  sender_recv_ack_seq_num_val(0) = 0;
426  sender_recv_ack_seq_num_time(0) = 0;
427  sender_recv_ack_seq_num_index = 1;
428 
429  RTTEstimate_val.set_size(1000);
430  RTTEstimate_val.zeros();
431  RTTEstimate_time.set_size(1000);
432  RTTEstimate_time.zeros();
433  RTTEstimate_val(0) = fInitialRTT;
434  RTTEstimate_time(0) = 0;
435  RTTEstimate_index = 1;
436 
437  RTTsample_val.set_size(1000);
438  RTTsample_val.zeros();
439  RTTsample_time.set_size(1000);
440  RTTsample_time.zeros();
441  RTTsample_val(0) = 0;
442  RTTsample_time(0) = 0;
443  RTTsample_index = 1;
444 
445 }
446 
447 std::string TCP_Sender::GenerateFilename()
448 {
449  time_t rawtime;
450  struct tm *timeinfo;
451  timeinfo = localtime(&rawtime);
452  std::ostringstream filename_stream;
453  filename_stream << "trace_tcp_sender_u" << fLabel
454  << "_" << 1900 + timeinfo->tm_year
455  << "_" << timeinfo->tm_mon
456  << "_" << timeinfo->tm_mday
457  << "__" << timeinfo->tm_hour
458  << "_" << timeinfo->tm_min
459  << "_" << timeinfo->tm_sec
460  << "_.it";
461  return filename_stream.str();
462 }
463 
464 
465 void TCP_Sender::release(std::string file)
466 {
467  std::string filename;
468  fSessionId++;
469 
470  fRtxTimer.Reset();
471  fSWSATimer.Reset();
472 
473  if (fTrace) {
474  if (file == "")
475  filename = GenerateFilename();
476  else
477  filename = file;
478 
479  save_trace(filename);
480  }
481 }
482 
483 
484 void TCP_Sender::InitStatistics()
485 {
486  fNumberOfTimeouts = 0;
487  fNumberOfIdleTimeouts = 0;
488  fNumberOfFastRetransmits = 0;
489  fNumberOfRTTMeasurements = 0;
490  fNumberOfReceivedACKs = 0;
491 }
492 
493 
494 void TCP_Sender::StopTransientPhase()
495 {
496  InitStatistics();
497 }
498 
499 
500 void TCP_Sender::HandleUserMessageIndication(itpp::Packet *user_data_p)
501 {
502  if (fDebug) {
503  std::cout << "TCP_Sender::HandleUserMessageIndication"
504  << " byte_size=" << user_data_p->bit_size() / 8
505  << " ptr=" << user_data_p
506  << " time=" << Event_Queue::now() << std::endl;
507  }
508 
509  SocketWriteQueue.push(user_data_p);
510 
511  SendNewData(); // will call GetMessage (via GetNextSegmentSize)
512  // if new data can be sent
513 }
514 
515 
516 void TCP_Sender::ReceiveMessageFromNet(itpp::Packet *msg)
517 {
518  TCP_Packet & packet = (TCP_Packet &) * msg;
519 
520  if (fDebug) {
521  std::cout << "TCP_Sender::ReceiveMessageFromNet"
522  << " byte_size=" << msg->bit_size() / 8
523  << " ptr=" << msg
524  << " time=" << Event_Queue::now() << std::endl;
525  }
526 
527  if ((packet.get_session_id() == fSessionId) && // ACK of current session
528  (packet.get_ACK() >= fSndUna)) { // ACK is OK
529  HandleACK(packet);
530  }
531 
532  delete &packet;
533 }
534 
535 
536 void TCP_Sender::HandleACK(TCP_Packet &msg)
537 {
538  it_assert(msg.get_ACK() <= fSndMax, "TCP_Sender::HandleACK, received ACK > SndMax at ");
539 
540  fNumberOfReceivedACKs++;
541 
542  if (fTrace) {
543  TraceACKedSeqNo(msg.get_ACK());
544  }
545 
546  if (fDebug) {
547  std::cout << "sender " << fLabel << ": "
548  << "receive ACK: "
549  << " t = " << Event_Queue::now() << ", "
550  << msg << std::endl;
551  }
552 
553  // update receiver advertised window size
554  fRecWnd = msg.get_wnd();
555  fMaxRecWnd = max(fRecWnd, fMaxRecWnd);
556 
557  if (msg.get_ACK() == fSndUna) { // duplicate ACK
558 
559  bool ignoreDupACK = (fSndMax == fSndUna); // no outstanding data
560 
561  if (fIgnoreDupACKOnTORecovery) {
562  // don't count dupacks during TO recovery!
563  if (fCarefulMulFastRtxAvoidance) { // see RFC 2582, Section 5
564  // like in Solaris
565  ignoreDupACK = ignoreDupACK || (fSndUna <= fRecoveryTO);
566  }
567  else {
568  // like in ns
569  ignoreDupACK = ignoreDupACK || (fSndUna < fRecoveryTO);
570  }
571  }
572 
573  if (!ignoreDupACK) {
574  fDupACKCnt++; // count the number of duplicate ACKs
575 
576  if (fDupACKCnt == fDupACKThreshold) {
577  // dupack threshold is reached
578  fNumberOfFastRetransmits++;
579 
580  fRecoveryDupACK = fSndMax;
581 
582  ReduceSSThresh(); // halve ssthresh (in most cases)
583 
584  if ((fTCPVersion == kReno) || (fTCPVersion == kNewReno)) {
585  fCWnd = fSSThresh;
586  }
587  else if (fTCPVersion == kTahoe) {
588  fCWnd = fMSS;
589  }
590 
591  if (fTCPVersion == kReno || fTCPVersion == kNewReno) {
592  // conservation of packets:
593  if (fRenoConservation) {
594  fCWnd += fDupACKThreshold * fMSS;
595  }
596  }
597  else if (fTCPVersion == kTahoe) {
598  if (fGoBackN) {
599  fSndNxt = fSndUna; // Go-Back-N (like in ns)
600  }
601  }
602 
603  UnaRetransmit(); // initiate retransmission
604  }
605  else if (fDupACKCnt > fDupACKThreshold) {
606  if (fTCPVersion == kReno || fTCPVersion == kNewReno) {
607  // conservation of packets
608  // CWnd may exceed MaxCWnd during fast recovery,
609  // however, the result of SendWindow() is always <= MaxCwnd
610  if (fRenoConservation) {
611  fCWnd += fMSS;
612  }
613  }
614  }
615  }
616  }
617  else { // new ACK
618  Sequence_Number oldSndUna = fSndUna; // required for NewReno partial ACK
619  fSndUna = msg.get_ACK();
620  fSndNxt = max(fSndNxt, fSndUna); // required in case of "Go-Back-N"
621 
622  // reset retransmission timer
623 
624  if ((fSndUna > fTimUna) && fRtxTimer.IsPending()) {
625  // seq. no. for which rtx timer is running has been received
626  fRtxTimer.Reset();
627  }
628 
629  // backoff reset
630 
631  if (fImmediateBackoffReset) {
632  fBackoff = 1;
633  }
634  else {
635  if (fPendingBackoffReset) {
636  fBackoff = 1;
637  fPendingBackoffReset = false;
638  }
639  else if (fBackoff > 1) {
640  // reset backoff counter only on next new ACK (this is probably
641  // the way to operate intended by Karn)
642  fPendingBackoffReset = true;
643  }
644  }
645 
646  // RTT measurement
647 
648  if ((fSndUna > fRTTMByte) && fRTTMPending) {
649  UpdateRTTVariables(Event_Queue::now() - fRTTMStartTime);
650  fRTTMPending = false;
651  }
652 
653  // update CWnd and reset dupack counter
654 
655  if (fDupACKCnt >= fDupACKThreshold) {
656  // we are in fast recovery
657  if (fTCPVersion == kNewReno && fSndUna < fRecoveryDupACK) {
658  // New Reno partial ACK handling
659  if (fRenoConservation) {
660  fCWnd = max(fMSS, fCWnd - (fSndUna - oldSndUna) + fMSS);
661  }
662  UnaRetransmit(); // start retransmit immediately
663  }
664  else {
665  FinishFastRecovery();
666  }
667  }
668  else {
669  // no fast recovery
670  fDupACKCnt = 0;
671  if (fCWnd < fSSThresh) {
672  // slow start phase
673  fCWnd = min(fCWnd + fMSS, fMaxCWnd);
674  }
675  else {
676  // congestion avoidance phase
677  fCWnd += max(fMSS * fMSS / fCWnd, 1); // RFC 2581
678  fCWnd = min(fCWnd, fMaxCWnd);
679  }
680  }
681  } // new ACK
682 
683  SendNewData(); // try to send new data (even in the case that a retransmit
684  // had to be performed)
685 
686  if (fTrace) {
687  TraceCWnd();
688  }
689 }
690 
691 
692 void TCP_Sender::SendNewData(bool skipSWSA)
693 {
694  unsigned nextSegmentSize;
695 
696  it_assert(fSndUna <= fSndNxt, "TCP_Sender::SendNewData, SndUna > SndNxt in sender " + to_str(fLabel) + "!");
697 
698  if (fRestartAfterIdle) {
699  IdleCheck();
700  }
701 
702  bool sillyWindowAvoidanceFailed = false;
703 
704  while (!sillyWindowAvoidanceFailed &&
705  ((nextSegmentSize = GetNextSegmentSize(fSndNxt)) > 0)) {
706  // there is new data to send and window is large enough
707 
708  // SWSA and Nagle (RFC 1122): assume PUSH to be set
709  unsigned queuedUnsent = fUserNxt - fSndNxt;
710  unsigned usableWindow = max(0, (fSndUna + SendWindow()) - fSndNxt);
711 
712  if (((unsigned)min(queuedUnsent, usableWindow) >= fMSS) ||
713  ((!fNagle || (fSndUna == fSndNxt)) &&
714  ((queuedUnsent <= usableWindow) || // Silly W. A.
715  ((unsigned)min(queuedUnsent, usableWindow) >= fMaxRecWnd / 2)
716  )
717  ) ||
718  skipSWSA
719  ) {
720  // Silly Window Syndrome Avoidance (SWSA) and Nagle passed
721 
722  TCP_Segment nextSegment(fSndNxt, fSndNxt + nextSegmentSize);
723  TCP_Packet & msg = * new TCP_Packet();
724 
725  msg.set_segment(nextSegment);
726  msg.set_session_id(fSessionId);
727  msg.set_destination_port(fLabel); // The dest and src port are set to the same
728  msg.set_source_port(fLabel); // number for simplicity.
729  msg.set_bit_size(8 * (nextSegmentSize + fTCPIPHeaderLength));
730 
731  if (fDebug) {
732  std::cout << "TCP_Sender::SendNewData,"
733  << " nextSegmentSize=" << nextSegmentSize
734  << " fTCPIPHeaderLength=" << fTCPIPHeaderLength
735  << " byte_size=" << msg.bit_size() / 8
736  << " ptr=" << &msg
737  << " time=" << Event_Queue::now() << std::endl;
738  }
739 
740  // no RTT measurement for retransmitted segments
741  // changes on Dec. 13. 2002 (Ga, Bo, Scharf)
742 
743  if (!fRTTMPending && fSndNxt >= fSndMax) { // ##Bo##
744  fRTTMStartTime = Event_Queue::now();
745  fRTTMByte = nextSegment.begin();
746  fRTTMPending = true;
747  }
748 
749  fSndNxt += nextSegmentSize;
750  fSndMax = max(fSndNxt, fSndMax);
751 
752  // reset SWSA timer if necessary
753  if (skipSWSA) {
754  skipSWSA = false;
755  }
756  else if (fSWSATimer.IsPending()) {
757  fSWSATimer.Reset();
758  }
759 
760  // set rtx timer if necessary
761  if (!fRtxTimer.IsPending()) {
762  SetRtxTimer();
763  }
764 
765 
766  if (fDebug) {
767  msg.set_info(fSSThresh, fRecWnd, fCWnd, fRTTEstimate,
768  fSndUna, fSndNxt, false);
769  std::cout << "sender " << fLabel
770  << ": send new data: "
771  << " t = " << Event_Queue::now() << ", "
772  << msg << std::endl;
773  }
774 
775  SendMsg(msg);
776  }
777  else {
778  sillyWindowAvoidanceFailed = true;
779  // set SWSA timer
780  if (!fSWSATimer.IsPending()) {
781  fSWSATimer.Set(fSWSATimerValue);
782  }
783  }
784  }
785 
786  // set timers in case that no new data could have been sent
787  if (!fRtxTimer.IsPending()) {
788  if (fSndMax > fSndUna) { // there is outstanding data
789  if (!fImmediateBackoffReset && fPendingBackoffReset) {
790  // backoff is reset if no new data could have been sent since last
791  // (successfull) retransmission; this is useful in case of
792  // Reno recovery and multiple losses to avoid that in
793  // the (unavoidable) series of timeouts the timer value
794  // increases exponentially as this is not the intention
795  // of the delayed backoff reset in Karn's algorithm
796  fBackoff = 1;
797  fPendingBackoffReset = false;
798  }
799  SetRtxTimer();
800  }
801  }
802 }
803 
804 
805 void TCP_Sender::UnaRetransmit()
806 {
807  // resend after timeout or fast retransmit
808  unsigned nextSegmentSize = GetNextSegmentSize(fSndUna);
809 
810  if (nextSegmentSize > 0) {
811  TCP_Segment nextSegment(fSndUna, fSndUna + nextSegmentSize);
812  TCP_Packet & msg = *new TCP_Packet();
813  msg.set_segment(nextSegment);
814  msg.set_session_id(fSessionId);
815  msg.set_destination_port(fLabel); // The dest and src port are set to the same
816  msg.set_source_port(fLabel); // number for simplicity.
817  msg.set_bit_size(8 * (nextSegmentSize + fTCPIPHeaderLength));
818 
819  fSndNxt = max(fSndNxt, fSndUna + nextSegmentSize);
820  fSndMax = max(fSndNxt, fSndMax);
821 
822  // The RTT measurement is cancelled if the RTTM byte has a sequence
823  // number higher or equal than the first retransmitted byte as
824  // the ACK for the RTTM byte will be delayed by the rtx for at least
825  // one round
826  if (fKarn && (nextSegment.begin() <= fRTTMByte) && fRTTMPending) {
827  fRTTMPending = false;
828  }
829 
830  SetRtxTimer();
831 
832  if (fDebug) {
833  msg.set_info(fSSThresh, fRecWnd, fCWnd, fRTTEstimate,
834  fSndUna, fSndNxt, true);
835  std::cout << "sender " << fLabel;
836  if (fDupACKCnt >= fDupACKThreshold) {
837  std::cout << ": fast rtx: ";
838  }
839  else {
840  std::cout << ": TO rtx: ";
841  }
842  std::cout << " t = " << Event_Queue::now() << ", "
843  << msg << std::endl;
844  }
845 
846  SendMsg(msg);
847  }
848  else {
849  // throw(UL_CException("TCP_Sender::UnaRetransmit", "no bytes to send"));
850  }
851 }
852 
853 
854 void TCP_Sender::FinishFastRecovery()
855 {
856  if (fTCPVersion == kTahoe) {
857  fDupACKCnt = 0;
858  }
859  else if (fTCPVersion == kReno) {
860  // Reno fast recovery
861  fDupACKCnt = 0;
862  if (fFlightSizeRecovery) {
863  fCWnd = min(fSndMax - fSndUna + fMSS, fSSThresh);
864  }
865  else {
866  fCWnd = fSSThresh;
867  }
868  }
869  else if (fTCPVersion == kNewReno) {
870  // New Reno fast recovery
871  // "Set CWnd to ... min (ssthresh, FlightSize + MSS)
872  // ... or ssthresh" (RFC 2582)
873  if (fFlightSizeRecovery) {
874  fCWnd = min(fSndMax - fSndUna + fMSS, fSSThresh);
875  }
876  else {
877  fCWnd = fSSThresh;
878  }
879  fDupACKCnt = 0;
880  }
881 }
882 
883 
884 void TCP_Sender::ReduceSSThresh()
885 {
886  if (fCarefulSSThreshReduction) {
887  // If Reno conservation is enabled the amount of
888  // outstanding data ("flight size") might be rather large
889  // and even larger than twice the old ssthresh value;
890  // so this corresponds more to the ns behaviour where always cwnd is
891  // taken instead of flight size.
892  fSSThresh = max(2 * fMSS,
893  min(min(fCWnd, fSndMax - fSndUna), fRecWnd) / 2);
894  }
895  else {
896  // use filght size / 2 as recommended in RFC 2581
897  fSSThresh = max(2 * fMSS, min(fSndMax - fSndUna, fRecWnd) / 2);
898  }
899 
900  it_assert(fSSThresh <= fMaxCWnd, "TCP_Sender::HandleACK, internal error: SndSSThresh is > MaxCWnd");
901 
902  if (fTrace) {
903  TraceSSThresh();
904  }
905 }
906 
907 
908 void TCP_Sender::SendMsg(TCP_Packet &msg)
909 {
910  if (fTrace) {
911  TraceSentSeqNo(msg.get_segment().end());
912  }
913 
914  if (fRestartAfterIdle) {
915  fLastSendTime = Event_Queue::now(); // needed for idle detection
916  }
917 
918  tcp_send(&msg);
919 }
920 
921 
922 void TCP_Sender::IdleCheck()
923 {
924  // idle detection according to Jacobson, SIGCOMM, 1988:
925  // sender is currently idle and nothing has been send since RTO
926 
927  if (fSndMax == fSndUna && Event_Queue::now() - fLastSendTime > CalcRTOValue()) {
928  fCWnd = fInitialCWnd; // see RFC2581
929 
930  fNumberOfIdleTimeouts++;
931 
932  if (fTrace) {
933  TraceCWnd();
934  }
935 
936  if (fDebug) {
937  std::cout << "sender " << fLabel
938  << ": idle timeout: "
939  << "t = " << Event_Queue::now()
940  << ", SndNxt = " << fSndNxt
941  << ", SndUna = " << fSndUna
942  << ", Backoff = " << fBackoff
943  << std::endl;
944  }
945  }
946 }
947 
948 
949 void TCP_Sender::HandleRtxTimeout(Ttype)
950 {
951  fNumberOfTimeouts++;
952 
953  // update backoff
954  fBackoff = min(fMaxBackoff, fBackoff * 2);
955  if (!fImmediateBackoffReset) {
956  fPendingBackoffReset = false;
957  }
958 
959  if (fDupACKCnt >= fDupACKThreshold) {
960  FinishFastRecovery(); // reset dup ACK cnt and CWnd
961  }
962  else if (fDupACKCnt > 0) {
963  fDupACKCnt = 0; // don't allow dupack action during TO recovery
964  }
965 
966  // update CWnd and SSThresh
967  ReduceSSThresh(); // halve ssthresh (in most cases)
968  fCWnd = fMSS; // not initial CWnd, see RFC 2581
969 
970  it_assert(fSSThresh <= fMaxCWnd, "TCP_Sender::HandleRtxTimeout, internal error: SndSSThresh is > MaxCWnd");
971 
972  fRecoveryTO = fSndMax;
973 
974  if (fGoBackN) {
975  // go back N is mainly relevant in the case of multiple losses
976  // which would lead to a series of timeouts without resetting sndnxt
977  fSndNxt = fSndUna;
978  }
979 
980  if (fDebug) {
981  std::cout << "sender " << fLabel
982  << ": rtx timeout: "
983  << "t = " << Event_Queue::now()
984  << ", SndNxt = " << fSndNxt
985  << ", SndUna = " << fSndUna
986  << std::endl;
987  }
988 
989  if (fTrace) {
990  TraceCWnd();
991  }
992 
993  UnaRetransmit(); // initiate retransmission
994 }
995 
996 
997 void TCP_Sender::HandleSWSATimeout(Ttype)
998 {
999  SendNewData(true);
1000 }
1001 
1002 
1003 unsigned TCP_Sender::GetNextSegmentSize(const Sequence_Number & begin)
1004 {
1005  // try to get new user messages if available and necessary
1006  while ((fUserNxt < begin + fMSS) && (!SocketWriteQueue.empty())) {
1007  itpp::Packet *packet_p = SocketWriteQueue.front();
1008  SocketWriteQueue.pop();
1009  fUserNxt += (unsigned) packet_p->bit_size() / 8;
1010  delete packet_p;
1011  }
1012 
1013  Sequence_Number end = min(min(fUserNxt, begin + fMSS),
1014  fSndUna + SendWindow());
1015 
1016  if (fDebug) {
1017  std::cout << "TCP_Sender::GetNextSegmentSize,"
1018  << " fUserNxt=" << fUserNxt
1019  << " begin_seq_num=" << begin
1020  << " fMSS=" << fMSS
1021  << " fSndUna=" << fSndUna
1022  << " SendWindow()=" << SendWindow()
1023  << " end_seq_num=" << end
1024  << " time=" << Event_Queue::now() << std::endl;
1025  }
1026 
1027  return max(0, end - begin);
1028 }
1029 
1030 
1031 unsigned TCP_Sender::SendWindow() const
1032 {
1033  return min(fRecWnd, min(fMaxCWnd, fCWnd));
1034 }
1035 
1036 
1037 double TCP_Sender::CalcRTOValue() const
1038 {
1039  static const double factor = 1 + 1e-8;
1040  // to avoid "simultaneous" TO/receive ACK events in case of const. RTT
1041 
1042  double rto = fBackoff * fRTTEstimate * factor;
1043 
1044  if (rto > fMaxRTO) {
1045  rto = fMaxRTO;
1046  }
1047 
1048  return rto;
1049 }
1050 
1051 
1052 void TCP_Sender::SetRtxTimer()
1053 {
1054  double rto = CalcRTOValue();
1055  fRtxTimer.Set(rto);
1056  fTimUna = fSndUna;
1057  if (fDebug) {
1058  std::cout << "sender " << fLabel
1059  << ": set rtx timer: "
1060  << "t = " << Event_Queue::now()
1061  << ", RTO = " << rto
1062  << ", Backoff = " << fBackoff
1063  << ", TimUna = " << fTimUna
1064  << std::endl;
1065  }
1066 }
1067 
1068 
1069 void TCP_Sender::UpdateRTTVariables(double sampleRTT)
1070 {
1071  if (fSRTT == 0) {
1072  fSRTT = sampleRTT;
1073  fRTTVar = sampleRTT / 2;
1074  }
1075  else {
1076  // see, e.g., Comer for the values used as weights
1077  fSRTT = 0.875 * fSRTT + 0.125 * sampleRTT;
1078  fRTTVar = 0.75 * fRTTVar + 0.25 * fabs(sampleRTT - fSRTT);
1079  }
1080 
1081  fRTTEstimate = round(fSRTT + 4 * fRTTVar, fTimerGranularity);
1082 
1083  if (fTrace) {
1084  TraceRTTVariables(sampleRTT);
1085  }
1086 
1087  fNumberOfRTTMeasurements++;
1088 }
1089 
1090 
1091 void TCP_Sender::TraceRTTVariables(double sampleRTT)
1092 {
1093  if (fDebug) {
1094  std::cout << "sender " << fLabel
1095  << ": RTT update: "
1096  << "t = " << Event_Queue::now()
1097  << ", sample = " << sampleRTT
1098  << ", SRTT = " << fSRTT
1099  << ", RTTVar = " << fRTTVar
1100  << ", RTTEstimate = " << fRTTEstimate
1101  << std::endl;
1102  }
1103 
1104  if (RTTsample_index >= RTTsample_time.size()) {
1105  RTTsample_time.set_size(2*RTTsample_time.size(), true);
1106  RTTsample_val.set_size(2*RTTsample_val.size(), true);
1107  }
1108  RTTsample_val(RTTsample_index) = sampleRTT;
1109  RTTsample_time(RTTsample_index) = Event_Queue::now();
1110  RTTsample_index++;
1111 
1112  if (RTTEstimate_index >= RTTEstimate_time.size()) {
1113  RTTEstimate_time.set_size(2*RTTEstimate_time.size(), true);
1114  RTTEstimate_val.set_size(2*RTTEstimate_val.size(), true);
1115  }
1116  RTTEstimate_val(RTTEstimate_index) = fRTTEstimate;
1117  RTTEstimate_time(RTTEstimate_index) = Event_Queue::now();
1118  RTTEstimate_index++;
1119 }
1120 
1121 
1122 void TCP_Sender::TraceCWnd()
1123 {
1124  if (fDebug) {
1125  std::cout << "sender " << fLabel
1126  << " t = " << Event_Queue::now()
1127  << " cwnd = " << fCWnd << std::endl;
1128  }
1129  if (CWnd_index >= CWnd_time.size()) {
1130  CWnd_time.set_size(2*CWnd_time.size(), true);
1131  CWnd_val.set_size(2*CWnd_val.size(), true);
1132  }
1133  CWnd_val(CWnd_index) = fCWnd;
1134  CWnd_time(CWnd_index) = Event_Queue::now();
1135  CWnd_index++;
1136 
1137 }
1138 
1139 void TCP_Sender::TraceSSThresh()
1140 {
1141  if (fDebug) {
1142  std::cout << "sender " << fLabel
1143  << " t = " << Event_Queue::now()
1144  << " cwnd = " << fSSThresh << std::endl;
1145  }
1146  if (SSThresh_index >= SSThresh_time.size()) {
1147  SSThresh_time.set_size(2*SSThresh_time.size(), true);
1148  SSThresh_val.set_size(2*SSThresh_val.size(), true);
1149  }
1150  SSThresh_val(SSThresh_index) = fSSThresh;
1151  SSThresh_time(SSThresh_index) = Event_Queue::now();
1152  SSThresh_index++;
1153 
1154 }
1155 
1156 void TCP_Sender::TraceSentSeqNo(const Sequence_Number sn)
1157 {
1159  if (fDebug) {
1160  std::cout << "sender " << fLabel
1161  << " t = " << Event_Queue::now()
1162  << " sent = " << sn
1163  << std::endl;
1164  }
1165  if (sent_seq_num_index >= sent_seq_num_time.size()) {
1166  sent_seq_num_time.set_size(2*sent_seq_num_time.size(), true);
1167  sent_seq_num_val.set_size(2*sent_seq_num_val.size(), true);
1168  }
1169  sent_seq_num_val(sent_seq_num_index) = sn.value();
1170  sent_seq_num_time(sent_seq_num_index) = Event_Queue::now();
1171  sent_seq_num_index++;
1172 }
1173 
1174 
1175 void TCP_Sender::TraceACKedSeqNo(const Sequence_Number sn)
1176 {
1177  if (fDebug) {
1178  std::cout << "sender " << fLabel
1179  << " t = " << Event_Queue::now()
1180  << " ACK = " << sn
1181  << std::endl;
1182  }
1183 
1184  if (sender_recv_ack_seq_num_index >= sender_recv_ack_seq_num_time.size()) {
1185  sender_recv_ack_seq_num_time.set_size(2*sender_recv_ack_seq_num_time.size(), true);
1186  sender_recv_ack_seq_num_val.set_size(2*sender_recv_ack_seq_num_val.size(), true);
1187  }
1188  sender_recv_ack_seq_num_val(sender_recv_ack_seq_num_index) = sn.value();
1189  sender_recv_ack_seq_num_time(sender_recv_ack_seq_num_index) = Event_Queue::now();
1190  sender_recv_ack_seq_num_index++;
1191 }
1192 
1193 
1194 void TCP_Sender::save_trace(std::string filename)
1195 {
1196 
1197  CWnd_val.set_size(CWnd_index, true);
1198  CWnd_time.set_size(CWnd_index, true);
1199 
1200  SSThresh_val.set_size(SSThresh_index, true);
1201  SSThresh_time.set_size(SSThresh_index, true);
1202 
1203  sent_seq_num_val.set_size(sent_seq_num_index, true);
1204  sent_seq_num_time.set_size(sent_seq_num_index, true);
1205 
1206  sender_recv_ack_seq_num_val.set_size(sender_recv_ack_seq_num_index, true);
1207  sender_recv_ack_seq_num_time.set_size(sender_recv_ack_seq_num_index, true);
1208 
1209  RTTEstimate_val.set_size(RTTEstimate_index, true);
1210  RTTEstimate_time.set_size(RTTEstimate_index, true);
1211 
1212  RTTsample_val.set_size(RTTsample_index, true);
1213  RTTsample_time.set_size(RTTsample_index, true);
1214 
1215  if (fDebug) {
1216  std::cout << "CWnd_val" << CWnd_val << std::endl;
1217  std::cout << "CWnd_time" << CWnd_time << std::endl;
1218  std::cout << "CWnd_index" << CWnd_index << std::endl;
1219 
1220  std::cout << "SSThresh_val" << SSThresh_val << std::endl;
1221  std::cout << "SSThresh_time" << SSThresh_time << std::endl;
1222  std::cout << "SSThresh_index" << SSThresh_index << std::endl;
1223 
1224  std::cout << "sent_seq_num_val" << sent_seq_num_val << std::endl;
1225  std::cout << "sent_seq_num_time" << sent_seq_num_time << std::endl;
1226  std::cout << "sent_seq_num_index" << sent_seq_num_index << std::endl;
1227 
1228  std::cout << "sender_recv_ack_seq_num_val" << sender_recv_ack_seq_num_val << std::endl;
1229  std::cout << "sender_recv_ack_seq_num_time" << sender_recv_ack_seq_num_time << std::endl;
1230  std::cout << "sender_recv_ack_seq_num_index" << sender_recv_ack_seq_num_index << std::endl;
1231 
1232  std::cout << "RTTEstimate_val" << RTTEstimate_val << std::endl;
1233  std::cout << "RTTEstimate_time" << RTTEstimate_time << std::endl;
1234  std::cout << "RTTEstimate_index" << RTTEstimate_index << std::endl;
1235 
1236  std::cout << "RTTsample_val" << RTTsample_val << std::endl;
1237  std::cout << "RTTsample_time" << RTTsample_time << std::endl;
1238  std::cout << "RTTsample_index" << RTTsample_index << std::endl;
1239 
1240  std::cout << "TCP_Sender::saving to file: " << filename << std::endl;
1241  }
1242 
1243  it_file ff2;
1244  ff2.open(filename);
1245 
1246  ff2 << Name("CWnd_val") << CWnd_val;
1247  ff2 << Name("CWnd_time") << CWnd_time;
1248  ff2 << Name("CWnd_index") << CWnd_index;
1249 
1250  ff2 << Name("SSThresh_val") << SSThresh_val;
1251  ff2 << Name("SSThresh_time") << SSThresh_time;
1252  ff2 << Name("SSThresh_index") << SSThresh_index;
1253 
1254  ff2 << Name("sent_seq_num_val") << sent_seq_num_val;
1255  ff2 << Name("sent_seq_num_time") << sent_seq_num_time;
1256  ff2 << Name("sent_seq_num_index") << sent_seq_num_index;
1257 
1258  ff2 << Name("sender_recv_ack_seq_num_val") << sender_recv_ack_seq_num_val;
1259  ff2 << Name("sender_recv_ack_seq_num_time") << sender_recv_ack_seq_num_time;
1260  ff2 << Name("sender_recv_ack_seq_num_index") << sender_recv_ack_seq_num_index;
1261 
1262  ff2 << Name("RTTEstimate_val") << RTTEstimate_val;
1263  ff2 << Name("RTTEstimate_time") << RTTEstimate_time;
1264  ff2 << Name("RTTEstimate_index") << RTTEstimate_index;
1265 
1266  ff2 << Name("RTTsample_val") << RTTsample_val;
1267  ff2 << Name("RTTsample_time") << RTTsample_time;
1268  ff2 << Name("RTTsample_index") << RTTsample_index;
1269 
1270  ff2.flush();
1271  ff2.close();
1272 }
1273 
1274 
1275 void TCP_Sender::print_item(std::ostream &, const std::string & keyword)
1276 {
1277  if (keyword == "Label") {
1278  std::cout << fLabel;
1279  }
1280  else if (keyword == "CWnd") {
1281  std::cout << fCWnd;
1282  }
1283  else if (keyword == "SSThresh") {
1284  std::cout << fSSThresh;
1285  }
1286  else if (keyword == "SRTT") {
1287  std::cout << fSRTT;
1288  }
1289  else if (keyword == "RTTvar") {
1290  std::cout << fRTTVar;
1291  }
1292  else if (keyword == "Backoff") {
1293  std::cout << fBackoff;
1294  }
1295  else if (keyword == "RTO") {
1296  std::cout << CalcRTOValue();
1297  }
1298  else if (keyword == "NoOfFastRets") {
1299  std::cout << fNumberOfFastRetransmits;
1300  }
1301  else if (keyword == "NoOfRetTOs") {
1302  std::cout << fNumberOfTimeouts;
1303  }
1304  else if (keyword == "NoOfIdleTOs") {
1305  std::cout << fNumberOfIdleTimeouts;
1306  }
1307  else if (keyword == "NoOfRTTMs") {
1308  std::cout << fNumberOfRTTMeasurements;
1309  }
1310  else if (keyword == "NoOfRecACKs") {
1311  std::cout << fNumberOfReceivedACKs;
1312  }
1313  else {
1314  }
1315 }
1316 
1317 
1318 // -------------------- TCP_Receiver_Buffer ----------------------------------------
1319 TCP_Receiver_Buffer::TCP_Receiver_Buffer() :
1320  fFirstByte()
1321 {
1322 }
1323 
1324 
1325 TCP_Receiver_Buffer::TCP_Receiver_Buffer(const TCP_Receiver_Buffer & rhs) :
1326  fFirstByte(rhs.fFirstByte),
1327  fBufList(rhs.fBufList)
1328 {
1329 }
1330 
1331 
1332 void TCP_Receiver_Buffer::reset()
1333 {
1334  fBufList.clear();
1335  fFirstByte = 0;
1336 }
1337 
1338 
1339 TCP_Receiver_Buffer::~TCP_Receiver_Buffer()
1340 {
1341 }
1342 
1343 
1344 void TCP_Receiver_Buffer::write(TCP_Segment newBlock)
1345 {
1346  // error cases
1347  it_assert(newBlock.begin() <= newBlock.end(), "TCP_Receiver_Buffer::Write, no valid segment");
1348 
1349  // cut blocks beginning before fFirstByte
1350  if (newBlock.begin() < fFirstByte) {
1351  if (newBlock.end() > fFirstByte) {
1352  newBlock.set_begin(fFirstByte);
1353  }
1354  else {
1355  return; //// TODO: Is this strange?
1356  }
1357  }
1358 
1359  if (newBlock.length() == 0) { // empty block, nothing to do
1360  return;
1361  }
1362 
1363  if (fBufList.empty() || (newBlock.begin() > fBufList.back().end())) {
1364  // new block is behind last block in buffer
1365  fBufList.push_back(newBlock);
1366  }
1367  else {
1368  // skip list entries if beginning of newBlock > end of current one
1369  // (search for correct list position)
1370  std::list<TCP_Segment>::iterator iter;
1371  iter = fBufList.begin();
1372  while (newBlock.begin() > iter->end()) {
1373  iter++;
1374  it_assert(iter != fBufList.end(), "TCP_Receiver_Buffer::Write, internal error");
1375  }
1376 
1377  TCP_Segment & exBlock = *iter;
1378 
1379  if (exBlock.can_be_combined(newBlock)) {
1380  // overlapping or contiguous blocks -> combine
1381  exBlock.combine(newBlock);
1382 
1383  // check following blocks
1384  iter++;
1385  while ((iter != fBufList.end()) &&
1386  exBlock.can_be_combined(*iter)) {
1387  exBlock.combine(*iter);
1388  iter = fBufList.erase(iter);
1389  }
1390  }
1391  else {
1392  // no overlap, newBlock lies between two existing list entries
1393  // new list entry has to be created
1394 
1395  fBufList.insert(iter, newBlock);
1396  }
1397  }
1398 
1399  it_assert(!fBufList.empty() && fBufList.front().begin() >= fFirstByte, "TCP_Receiver_Buffer::Write, internal error");
1400 
1401 }
1402 
1403 
1404 // The amount of data read from the buffer is given as parameter. It has
1405 // to be less than or equal to the size of the first block stored. This
1406 // mean the caller of Read should first check how much data is available
1407 // by calling FirstBlockSize.
1408 void TCP_Receiver_Buffer::read(unsigned noOfBytes)
1409 {
1410  it_assert(first_block_size() > 0, "TCP_Receiver_Buffer::Read, No block to read");
1411  it_assert(noOfBytes <= first_block_size(), "TCP_Receiver_Buffer::Read, submitted block size not valid");
1412 
1413 
1414  if (noOfBytes < first_block_size()) {
1415  fBufList.front().set_begin(fBufList.front().begin() + noOfBytes);
1416  }
1417  else { // first block will be read completely
1418  fBufList.pop_front();
1419  }
1420  fFirstByte += noOfBytes;
1421 
1422  it_assert(fBufList.empty() || fBufList.front().begin() >= fFirstByte, "TCP_Receiver_Buffer::Read, internal error");
1423 }
1424 
1425 
1426 // FirstBlockSize returns the size of the first block stored in the
1427 // buffer or 0 if the buffer is empty
1428 unsigned TCP_Receiver_Buffer::first_block_size() const
1429 {
1430  if (!fBufList.empty() && (fBufList.front().begin() == fFirstByte)) {
1431  return fBufList.front().length();
1432  }
1433  else {
1434  return 0;
1435  }
1436 }
1437 
1438 
1439 std::ostream & TCP_Receiver_Buffer::info(std::ostream &os, int detail) const
1440 {
1441  os << "receiver buffer information" << std::endl
1442  << "number of blocks: " << fBufList.size() << std::endl
1443  << "first byte stored: " << fFirstByte << std::endl
1444  << "last byte stored +1: " << last_byte() << std::endl
1445  << "next byte expected: " << next_expected() << std::endl;
1446 
1447  if (detail > 0) {
1448  os << "segments in receiver buffer:" << std::endl;
1449 
1450  typedef std::list<TCP_Segment>::const_iterator LI;
1451  for (LI i = fBufList.begin(); i != fBufList.end(); ++i) {
1452  const TCP_Segment & block = *i;
1453  os << ". segment: " << block << std::endl;
1454  }
1455 
1456  }
1457 
1458  return os;
1459 }
1460 
1461 
1462 // -------------------- TCP_Receiver ----------------------------------------
1463 TCP_Receiver::TCP_Receiver(int label) :
1464  fReceiverBuffer(),
1465  fLabel(label),
1466  fTCPIPHeaderLength(TCP_HEADERLENGTH),
1467  fMSS(TCP_RMSS),
1468  fBufferSize(TCP_BUFFERSIZE),
1469  fDelayedACK(TCP_DELAYEDACK),
1470  fACKDelayTime(TCP_ACKDELAYTIME),
1471  fSendPeriodicACKs(TCP_SENDPERIODICACKS),
1472  fStrictPeriodicACKs(TCP_STRICTPERIODICACKS),
1473  fPeriodicACKInterval(TCP_PERIODICACKINTERVAL),
1474  fACKSchedulingDelay(TCP_ACKSCHEDULINGDELAY),
1475  fACKOnBufferWrite(TCP_ACKBUFFERWRITE),
1476  fACKOnBufferRead(TCP_ACKBUFFERREAD),
1477  fMaxUserBlockSize(TCP_MAXUSERBLOCKSIZE),
1478  fMinUserBlockSize(TCP_MINUSERBLOCKSIZE),
1479  fUserBlockProcDelay(TCP_USERBLOCKPROCDELAY),
1480  fTrace(false),
1481  fDebug(false),
1482  fSessionId(0),
1483  fDelayedACKTimer(*this, &TCP_Receiver::DelayedACKHandler),
1484  fPeriodicACKTimer(*this, &TCP_Receiver::PeriodicACKHandler),
1485  fACKSchedulingTimer(*this, &TCP_Receiver::SendACKMessage),
1486  fWaitingACKMsg(0),
1487  fUserBlockProcTimer(*this, &TCP_Receiver::HandleEndOfProcessing)
1488 {
1489  fUserMessage = NULL;
1490 
1491 
1492  if (!fACKOnBufferRead && !fACKOnBufferWrite) {
1493  // throw(UL_CException("TCP_Receiver::TCP_Receiver",
1494  // "ACKs must be sent on buffer read or write or both"));
1495  }
1496 
1497  setup();
1498 
1499  tcp_receive.forward(this, &TCP_Receiver::ReceiveMessageFromNet);
1500  tcp_receive.set_name("TCP Receive");
1501  tcp_send_ack.set_name("TCP send ACK");
1502  tcp_new_data.set_name("TCP New Data");
1503  tcp_release.forward(this, &TCP_Receiver::release);
1504  tcp_release.set_name("TCP Release");
1505 
1506 }
1507 
1508 
1509 TCP_Receiver::~TCP_Receiver()
1510 {
1511  delete fWaitingACKMsg;
1512  delete fUserMessage;
1513 }
1514 
1515 
1516 void TCP_Receiver::set_debug(const bool enable_debug)
1517 {
1518  fDebug = enable_debug;
1519  tcp_send_ack.set_debug(enable_debug);
1520  tcp_new_data.set_debug();
1521 }
1522 
1523 void TCP_Receiver::set_debug(bool enable_debug, bool enable_signal_debug)
1524 {
1525  fDebug = enable_debug;
1526  tcp_send_ack.set_debug(enable_signal_debug);
1527  tcp_new_data.set_debug();
1528 }
1529 
1530 void TCP_Receiver::set_trace(const bool enable_trace)
1531 {
1532  fTrace = enable_trace;
1533 }
1534 
1535 
1536 
1537 void TCP_Receiver::setup()
1538 {
1539  fAdvRcvWnd = 0;
1540  fAdvRcvNxt = 0;
1541 
1542  if (fSendPeriodicACKs) {
1543  fPeriodicACKTimer.Set(fPeriodicACKInterval);
1544  }
1545 
1546  fReceiverBuffer.reset();
1547 
1548  received_seq_num_val.set_size(1000);
1549  received_seq_num_val.zeros();
1550  received_seq_num_time.set_size(1000);
1551  received_seq_num_time.zeros();
1552  received_seq_num_val(0) = 0;
1553  received_seq_num_time(0) = 0;
1554  received_seq_num_index = 1;
1555 }
1556 
1557 std::string TCP_Receiver::GenerateFilename()
1558 {
1559  time_t rawtime;
1560  struct tm *timeinfo;
1561  timeinfo = localtime(&rawtime);
1562  std::ostringstream filename_stream;
1563  filename_stream << "trace_tcp_receiver_u" << fLabel
1564  << "_" << 1900 + timeinfo->tm_year
1565  << "_" << timeinfo->tm_mon
1566  << "_" << timeinfo->tm_mday
1567  << "__" << timeinfo->tm_hour
1568  << "_" << timeinfo->tm_min
1569  << "_" << timeinfo->tm_sec
1570  << "_.it";
1571  return filename_stream.str();
1572 }
1573 
1574 void TCP_Receiver::release(std::string file)
1575 {
1576  std::string filename;
1577  fSessionId++;
1578 
1579  if (fWaitingACKMsg != 0) {
1580  delete fWaitingACKMsg;
1581  fWaitingACKMsg = 0;
1582  }
1583  if (fUserMessage != 0) {
1584  delete fUserMessage;
1585  fUserMessage = 0;
1586  }
1587 
1588  fUserBlockProcTimer.Reset();
1589  fDelayedACKTimer.Reset();
1590  fPeriodicACKTimer.Reset();
1591  fACKSchedulingTimer.Reset();
1592 
1593  if (fTrace) {
1594  if (file == "")
1595  filename = GenerateFilename();
1596  else
1597  filename = file;
1598 
1599  save_trace(filename);
1600  }
1601 }
1602 
1603 
1604 void TCP_Receiver::ReceiveMessageFromNet(itpp::Packet *msg)
1605 {
1606  TCP_Packet & packet = (TCP_Packet &) * msg;
1607  if (packet.get_destination_port() == fLabel) {
1608  if (packet.get_session_id() == fSessionId) {
1609  ReceiveDataPacket(packet);
1610  }
1611  else {
1612  it_warning("Received a TCP packet with wrong SessionId");
1613  std::cout << "TCP_Receiver::ReceiveMessageFromNet, "
1614  << "fLabel= " << fLabel
1615  << "fSessionId= " << fSessionId << std::endl;
1616  std::cout << "packet=" << packet
1617  << ", next exp. = " << fReceiverBuffer.next_expected()
1618  << std::endl;
1619  exit(0);
1620  }
1621  }
1622  else {
1623  it_warning("Received a TCP packet with label");
1624  exit(0);
1625  }
1626 }
1627 
1628 
1629 void TCP_Receiver::ReceiveDataPacket(TCP_Packet &msg)
1630 {
1631  TCP_Segment segment = msg.get_segment();
1632 
1633  bool isOutOfOrder = (segment.begin() > fReceiverBuffer.next_expected()) ||
1634  (segment.end() <= fReceiverBuffer.next_expected());
1635 
1636  if (fDebug) {
1637  std::cout << "TCP_Receiver::ReceiveDataPacket receiver: " << fLabel << ": "
1638  << "receive msg: "
1639  << "t = " << Event_Queue::now()
1640  << ", next exp. = " << fReceiverBuffer.next_expected()
1641  << ", " << msg << std::endl;
1642  }
1643 
1644  if (fTrace) {
1645  TraceReceivedSeqNo(segment.end());
1646  }
1647 
1648  it_assert(segment.end() <= fReceiverBuffer.first_byte() + fBufferSize, "TCP_Receiver::ReceiveTCPPacket, packet exceeds window at ");
1649  it_assert(segment.begin() < segment.end(), "TCP_Receiver::ReceiveTCPPacket, silly packet received at ");
1650 
1651  fReceiverBuffer.write(segment);
1652 
1653  if (isOutOfOrder) {
1654  SendACK(true); // create dupack conditionless
1655  }
1656  else {
1657  if (fACKOnBufferWrite) {
1658  SendACK(false);
1659  }
1660  IndicateUserMessage();
1661  }
1662 
1663  delete &msg;
1664 }
1665 
1666 
1667 void TCP_Receiver::IndicateUserMessage()
1668 {
1669  if (fUserMessage == 0) {
1670  // receive a block
1671  unsigned noOfBytes = min(fReceiverBuffer.first_block_size(),
1672  fMaxUserBlockSize);
1673 
1674  if (fDebug) {
1675  std::cout << "TCP_Receiver::IndicateUserMessage "
1676  << "t = " << Event_Queue::now()
1677  << " noOfBytes = " << noOfBytes
1678  << " firstBlock = " << fReceiverBuffer.first_block_size()
1679  << std::endl;
1680  }
1681 
1682  if (noOfBytes >= fMinUserBlockSize) {
1683  fUserMessage = new Packet();
1684  fUserMessage->set_bit_size(8*noOfBytes);
1685  fUserBlockProcTimer.Set(fUserBlockProcDelay);
1686  }
1687  }
1688 }
1689 
1690 
1691 bool TCP_Receiver::is_user_message_available()
1692 {
1693  if (fUserMessage != 0) {
1694  return true;
1695  }
1696 
1697  unsigned noOfBytes = min(fReceiverBuffer.first_block_size(),
1698  fMaxUserBlockSize);
1699 
1700  if (noOfBytes >= fMinUserBlockSize) {
1701  fUserMessage = new Packet();
1702  fUserMessage->set_bit_size(8*noOfBytes);
1703  return true;
1704  }
1705  else {
1706  return false;
1707  }
1708 }
1709 
1710 
1711 itpp::Packet & TCP_Receiver::get_user_message()
1712 {
1713  it_assert(fUserMessage != 0, "TCP_Receiver::GetUserMessage, no message available");
1714  if (fDebug) {
1715  std::cout << "TCP_Receiver::GetUserMessage "
1716  << "receiver: " << fLabel << ": "
1717  << "read from buffer: "
1718  << "t = " << Event_Queue::now()
1719  << ", user msg length = " << (fUserMessage->bit_size() / 8)
1720  << ", first byte = " << fReceiverBuffer.first_byte()
1721  << ", first block size = " << fReceiverBuffer.first_block_size()
1722  << std::endl;
1723  }
1724 
1725  fReceiverBuffer.read(fUserMessage->bit_size() / 8);
1726  if (fACKOnBufferRead) {
1727  SendACK(false); // send acknowledgement
1728  }
1729 
1730  itpp::Packet & msg = *fUserMessage;
1731  fUserMessage = 0;
1732 
1733  if (fReceiverBuffer.first_block_size() > 0) {
1734  IndicateUserMessage();
1735  }
1736 
1737  return msg;
1738 }
1739 
1740 
1741 
1742 void TCP_Receiver::HandleEndOfProcessing(Ttype)
1743 {
1744  it_assert(fUserMessage != 0, "TCP_Receiver::HandleEndOfProcessing, no message available");
1745 
1746 
1747  tcp_new_data(fLabel);
1748 }
1749 
1750 
1751 void TCP_Receiver::DelayedACKHandler(Ttype)
1752 {
1753  if (fDebug) {
1754  std::cout << "TCP_Receiver::DelayedACKHandler "
1755  << "receiver " << fLabel
1756  << ": delACK TO: "
1757  << "t = " << Event_Queue::now() << std::endl;
1758  }
1759 
1760  SendACK(true);
1761 }
1762 
1763 
1764 void TCP_Receiver::PeriodicACKHandler(Ttype)
1765 {
1766  if (fDebug) {
1767  std::cout << "TCP_Receiver::PeriodicACKHandler"
1768  << "receiver " << fLabel
1769  << ": periodicACK TO: "
1770  << "t = " << Event_Queue::now() << std::endl;
1771  }
1772 
1773  SendACK(true);
1774 }
1775 
1776 
1777 void TCP_Receiver::SendACK(bool sendConditionless)
1778 {
1779  // sendConditionless is set
1780  // ... if packet was received out of order or
1781  // ... if delayed ACK timer has expired
1782 
1783  // Bei eingeschaltetem "delayed ACK" wird ein ACK nur
1784  // gesendet, wenn das Fenster um 2MSS oder 35% der
1785  // maximalen Fenstergroesse verschoben worden ist
1786  // ... oder nach delayed ACK Timeout
1787  // ... oder wenn es das ACK fur ein Out of Order Segment ist
1788  // ... oder (in der Realitat), wenn ich auch was zu senden habe.
1789 
1790  if (sendConditionless || !fDelayedACK ||
1791  (fReceiverBuffer.next_expected() - fAdvRcvNxt >= (int)(2 * fMSS)) ||
1792  (fReceiverBuffer.next_expected() - fAdvRcvNxt >=
1793  (int)(0.35 * fBufferSize))) {
1794  // Remark: RFC2581 recommends to acknowledge every second
1795  // packet conditionless (without setting this as a requirement)
1796  // in order to avoid excessive ack delays when the receiver MSS
1797  // is larger than the sender MSS. In this uni-directional
1798  // implementation, the receiver's MSS is not actively
1799  // used for sending but only for deciding when acknowledgments
1800  // have to be returned. Thus, the best solution to account for
1801  // RFC2581 is to set the receiver's MSS always equal to the
1802  // sender's MSS.
1803 
1804  // Receiver Silly Window Syndrome Avoidance:
1805 
1806  if (fAdvRcvNxt + fAdvRcvWnd + min(fBufferSize / 2, fMSS)
1807  <= fReceiverBuffer.first_byte() + fBufferSize) {
1808  // Die rechte Grenze des Empfangerfensters wird nur anders angezeigt
1809  // als beim letzten ACK, wenn sie sich seither um mindestens
1810  // min (BufferSize/ 2, MSS) geandert hat.
1811  fAdvRcvWnd = fBufferSize - fReceiverBuffer.first_block_size();
1812  }
1813  else {
1814  fAdvRcvWnd = fAdvRcvNxt + fAdvRcvWnd - fReceiverBuffer.next_expected();
1815  }
1816 
1817  fAdvRcvNxt = fReceiverBuffer.next_expected();
1818 
1819  if (fSendPeriodicACKs &&
1820  (!fStrictPeriodicACKs || !fPeriodicACKTimer.IsPending())) {
1821  fPeriodicACKTimer.Set(fPeriodicACKInterval);
1822  }
1823 
1824  if (fDelayedACK && fDelayedACKTimer.IsPending()) {
1825  fDelayedACKTimer.Reset();
1826  }
1827 
1828  ScheduleACKMessage();
1829  }
1830  else {
1831  if (!fDelayedACKTimer.IsPending()) {
1832  fDelayedACKTimer.Set(fACKDelayTime);
1833  if (fDebug) {
1834  std::cout << "TCP_Receiver::SendACK"
1835  << "receiver " << fLabel
1836  << ": set delACK timer: "
1837  << "t = " << Event_Queue::now() << std::endl;
1838  }
1839  }
1840  }
1841 }
1842 
1843 
1844 void TCP_Receiver::ScheduleACKMessage()
1845 {
1846  if (fWaitingACKMsg == 0) {
1847  fWaitingACKMsg = new TCP_Packet;
1848  }
1849 
1850  fWaitingACKMsg->set_ACK(fAdvRcvNxt);
1851  fWaitingACKMsg->set_wnd(fAdvRcvWnd);
1852  fWaitingACKMsg->set_session_id(fSessionId);
1853  fWaitingACKMsg->set_destination_port(fLabel);
1854  fWaitingACKMsg->set_source_port(fLabel);
1855  fWaitingACKMsg->set_bit_size(8*fTCPIPHeaderLength);
1856 
1857  if (fACKSchedulingDelay > 0) {
1858  if (!fACKSchedulingTimer.IsPending()) {
1859  fACKSchedulingTimer.Set(fACKSchedulingDelay);
1860  }
1861  }
1862  else {
1863  SendACKMessage(Event_Queue::now());
1864  }
1865 }
1866 
1867 
1868 void TCP_Receiver::SendACKMessage(Ttype)
1869 {
1870  it_assert(fWaitingACKMsg != 0, "TCP_Receiver::SendACKMessage, no ACK message waiting");
1871 
1872  if (fDebug) {
1873  std::cout << "TCP_Receiver::SendACKMessage Ack sent"
1874  << "receiver " << fLabel
1875  << ": send ACK: "
1876  << "t = " << Event_Queue::now()
1877  << ", " << (*fWaitingACKMsg)
1878  << " byte_size=" << fWaitingACKMsg->bit_size() / 8
1879  << " ptr=" << fWaitingACKMsg << std::endl;
1880  }
1881 
1882  tcp_send_ack(fWaitingACKMsg);
1883 
1884  fWaitingACKMsg = 0;
1885 }
1886 
1887 
1888 void TCP_Receiver::TraceReceivedSeqNo(const Sequence_Number &sn)
1889 {
1890  if (fDebug) {
1891  std::cout << "TCP_Receiver::TraceReceivedSeqNo "
1892  << "receiver " << fLabel
1893  << " t = " << Event_Queue::now()
1894  << " sn = " << sn << std::endl;
1895  }
1896  if (received_seq_num_index >= received_seq_num_time.size()) {
1897  received_seq_num_time.set_size(2*received_seq_num_time.size(), true);
1898  received_seq_num_val.set_size(2*received_seq_num_val.size(), true);
1899  }
1900  received_seq_num_val(received_seq_num_index) = sn.value();
1901  received_seq_num_time(received_seq_num_index) = Event_Queue::now();
1902  received_seq_num_index++;
1903 }
1904 
1905 
1906 void TCP_Receiver::save_trace(std::string filename)
1907 {
1908 
1909  received_seq_num_val.set_size(received_seq_num_index, true);
1910  received_seq_num_time.set_size(received_seq_num_index, true);
1911 
1912  if (fDebug) {
1913  std::cout << "received_seq_num_val" << received_seq_num_val << std::endl;
1914  std::cout << "received_seq_num_time" << received_seq_num_time << std::endl;
1915  std::cout << "received_seq_num_index" << received_seq_num_index << std::endl;
1916  std::cout << "TCP_Receiver::saving to file: " << filename << std::endl;
1917  }
1918 
1919  it_file ff2;
1920  ff2.open(filename);
1921 
1922  ff2 << Name("received_seq_num_val") << received_seq_num_val;
1923  ff2 << Name("received_seq_num_time") << received_seq_num_time;
1924  ff2 << Name("received_seq_num_index") << received_seq_num_index;
1925 
1926  ff2.flush();
1927  ff2.close();
1928 }
1929 
1930 
1931 } //namespace itpp
1932 
1933 #ifdef _MSC_VER
1934 #pragma warning(default:4355)
1935 #endif
1936 
SourceForge Logo

Generated on Fri Mar 21 2014 17:14:14 for IT++ by Doxygen 1.8.1.2