41 #pragma warning(disable:4355)
51 #define TCP_HEADERLENGTH 40
55 #define TCP_VERSION kReno
57 #define TCP_INITIALCWNDREL 2 // related to MSS
58 #define TCP_INITIALSSTHRESHREL 1 // related to MaxCWnd
59 #define TCP_MAXCWNDREL 32 // related to MSS
61 #define TCP_INITIALRTT 1
62 const double TCP_STIMERGRAN = 0.2;
63 const double TCP_SWSATIMERVALUE = 0.2;
64 #define TCP_MAXBACKOFF 64
66 #define TCP_IMMEDIATEBACKOFFRESET false
67 #define TCP_TIMESTAMPS false
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
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
91 #define TCP_MINUSERBLOCKSIZE 1
92 #define TCP_USERBLOCKPROCDELAY 0
96 #define TCPGEN_BLOCKSIZE 1460
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
109 inline int min(
int opd1,
int opd2)
111 return (opd1 < opd2) ? opd1 : opd2;
115 inline int max(
int opd1,
int opd2)
117 return (opd1 > opd2) ? opd1 : opd2;
123 inline double round(
const double value,
const double granularity)
125 return (
std::ceil(value / granularity) * granularity);
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()));
146 seq_begin(segment.seq_begin),
147 seq_end(segment.seq_end)
155 this->
seq_end = segment.seq_end;
170 std::ostream &
operator<<(std::ostream &os,
const TCP_Segment &segment)
172 os <<
"(" << segment.seq_begin <<
"," << segment.seq_end <<
")";
189 fSegment(packet.fSegment),
192 fSessionId(packet.fSessionId),
195 std::cout <<
"TCP_Packet::TCP_Packet ############" <<
" ";
197 if (packet.fInfo != 0) {
198 std::cout <<
"TCP_Packet::TCP_Packet rhs.fInfo ###########" <<
" ";
199 fInfo =
new TDebugInfo(*packet.fInfo);
217 double estRTT, Sequence_Number sndUna,
218 Sequence_Number sndNxt,
bool isRtx)
221 fInfo =
new TDebugInfo;
236 std::cout <<
"Hello!\n";
241 <<
"ACK = " <<
get_ACK() <<
" "
242 <<
"Wnd = " <<
get_wnd() <<
" ";
251 std::cout <<
"SndCWnd = " <<
fInfo->
fCWnd <<
" ";
256 std::cout <<
"fInfo = " <<
fInfo <<
" ";
258 std::cout << std::endl;
264 std::ostream &
operator<<(std::ostream & out, TCP_Packet & msg)
266 msg.print_header(out);
274 fTCPVersion(TCP_VERSION),
276 fTCPIPHeaderLength(TCP_HEADERLENGTH),
277 fInitialRTT(TCP_INITIALRTT),
281 fDupACKThreshold(TCP_DUPACKS),
282 fTimerGranularity(TCP_STIMERGRAN),
284 fMaxBackoff(TCP_MAXBACKOFF),
285 fImmediateBackoffReset(TCP_IMMEDIATEBACKOFFRESET),
287 fGoBackN(TCP_GOBACKN),
288 fFlightSizeRecovery(TCP_FLIGHTSIZERECOVERY),
289 fRenoConservation(TCP_RENOCONSERVATION),
290 fCarefulSSThreshReduction(TCP_CAREFULSSTHRESHREDUCTION),
291 fIgnoreDupACKOnTORecovery(TCP_IGNOREDUPACKONTORECOVERY),
292 fCarefulMulFastRtxAvoidance(TCP_CAREFULMULFASTRTXAVOIDANCE),
294 fSWSATimerValue(TCP_SWSATIMERVALUE),
295 fRestartAfterIdle(TCP_RESTARTAFTERIDLE),
299 fRtxTimer(*this, &TCP_Sender::HandleRtxTimeout),
300 fSWSATimer(*this, &TCP_Sender::HandleSWSATimeout)
305 fMaxCWnd = (unsigned)(TCP_MAXCWNDREL * fMSS);
307 else if (fMaxCWnd < fMSS) {
312 if (fInitialCWnd == 0) {
313 fInitialCWnd = (unsigned)(TCP_INITIALCWNDREL * fMSS);
315 else if ((fInitialCWnd < fMSS) || (fInitialCWnd > fMaxCWnd)) {
320 if ((fInitialSSThresh == 0) && (fMaxCWnd >= 2 * fMSS)) {
321 fInitialSSThresh = (unsigned)(TCP_INITIALSSTHRESHREL * fMaxCWnd);
323 else if ((fInitialSSThresh < 2*fMSS) || (fInitialCWnd > fMaxCWnd)) {
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");
339 tcp_release.set_name(
"Release");
350 fDebug = enable_debug;
356 fDebug = enable_debug;
362 fTrace = enable_trace;
365 void TCP_Sender::set_label(
int label)
378 fCWnd = fInitialCWnd;
379 fSSThresh = fInitialSSThresh;
386 fPendingBackoffReset =
false;
393 fRTTEstimate = fInitialRTT;
394 fRTTMPending =
false;
397 CWnd_val.set_size(1000);
399 CWnd_time.set_size(1000);
401 CWnd_val(0) = fInitialCWnd;
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;
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;
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;
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;
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;
447 std::string TCP_Sender::GenerateFilename()
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
461 return filename_stream.str();
467 std::string filename;
475 filename = GenerateFilename();
484 void TCP_Sender::InitStatistics()
486 fNumberOfTimeouts = 0;
487 fNumberOfIdleTimeouts = 0;
488 fNumberOfFastRetransmits = 0;
489 fNumberOfRTTMeasurements = 0;
490 fNumberOfReceivedACKs = 0;
494 void TCP_Sender::StopTransientPhase()
500 void TCP_Sender::HandleUserMessageIndication(
itpp::Packet *user_data_p)
503 std::cout <<
"TCP_Sender::HandleUserMessageIndication"
504 <<
" byte_size=" << user_data_p->
bit_size() / 8
505 <<
" ptr=" << user_data_p
509 SocketWriteQueue.push(user_data_p);
516 void TCP_Sender::ReceiveMessageFromNet(
itpp::Packet *msg)
518 TCP_Packet & packet = (TCP_Packet &) * msg;
521 std::cout <<
"TCP_Sender::ReceiveMessageFromNet"
522 <<
" byte_size=" << msg->
bit_size() / 8
527 if ((packet.get_session_id() == fSessionId) &&
528 (packet.get_ACK() >= fSndUna)) {
536 void TCP_Sender::HandleACK(TCP_Packet &msg)
538 it_assert(msg.get_ACK() <= fSndMax,
"TCP_Sender::HandleACK, received ACK > SndMax at ");
540 fNumberOfReceivedACKs++;
543 TraceACKedSeqNo(msg.get_ACK());
547 std::cout <<
"sender " << fLabel <<
": "
554 fRecWnd = msg.get_wnd();
555 fMaxRecWnd =
max(fRecWnd, fMaxRecWnd);
557 if (msg.get_ACK() == fSndUna) {
559 bool ignoreDupACK = (fSndMax == fSndUna);
561 if (fIgnoreDupACKOnTORecovery) {
563 if (fCarefulMulFastRtxAvoidance) {
565 ignoreDupACK = ignoreDupACK || (fSndUna <= fRecoveryTO);
569 ignoreDupACK = ignoreDupACK || (fSndUna < fRecoveryTO);
576 if (fDupACKCnt == fDupACKThreshold) {
578 fNumberOfFastRetransmits++;
580 fRecoveryDupACK = fSndMax;
584 if ((fTCPVersion == kReno) || (fTCPVersion == kNewReno)) {
587 else if (fTCPVersion == kTahoe) {
591 if (fTCPVersion == kReno || fTCPVersion == kNewReno) {
593 if (fRenoConservation) {
594 fCWnd += fDupACKThreshold * fMSS;
597 else if (fTCPVersion == kTahoe) {
605 else if (fDupACKCnt > fDupACKThreshold) {
606 if (fTCPVersion == kReno || fTCPVersion == kNewReno) {
610 if (fRenoConservation) {
618 Sequence_Number oldSndUna = fSndUna;
619 fSndUna = msg.get_ACK();
620 fSndNxt =
max(fSndNxt, fSndUna);
624 if ((fSndUna > fTimUna) && fRtxTimer.
IsPending()) {
631 if (fImmediateBackoffReset) {
635 if (fPendingBackoffReset) {
637 fPendingBackoffReset =
false;
639 else if (fBackoff > 1) {
642 fPendingBackoffReset =
true;
648 if ((fSndUna > fRTTMByte) && fRTTMPending) {
650 fRTTMPending =
false;
655 if (fDupACKCnt >= fDupACKThreshold) {
657 if (fTCPVersion == kNewReno && fSndUna < fRecoveryDupACK) {
659 if (fRenoConservation) {
660 fCWnd =
max(fMSS, fCWnd - (fSndUna - oldSndUna) + fMSS);
665 FinishFastRecovery();
671 if (fCWnd < fSSThresh) {
673 fCWnd =
min(fCWnd + fMSS, fMaxCWnd);
677 fCWnd +=
max(fMSS * fMSS / fCWnd, 1);
678 fCWnd =
min(fCWnd, fMaxCWnd);
692 void TCP_Sender::SendNewData(
bool skipSWSA)
694 unsigned nextSegmentSize;
696 it_assert(fSndUna <= fSndNxt, "TCP_Sender::SendNewData, SndUna > SndNxt in sender
" + to_str(fLabel) + "!
");
698 if (fRestartAfterIdle) {
702 bool sillyWindowAvoidanceFailed = false;
704 while (!sillyWindowAvoidanceFailed &&
705 ((nextSegmentSize = GetNextSegmentSize(fSndNxt)) > 0)) {
706 // there is new data to send and window is large enough
708 // SWSA and Nagle (RFC 1122): assume PUSH to be set
709 unsigned queuedUnsent = fUserNxt - fSndNxt;
710 unsigned usableWindow = max(0, (fSndUna + SendWindow()) - fSndNxt);
712 if (((unsigned)min(queuedUnsent, usableWindow) >= fMSS) ||
713 ((!fNagle || (fSndUna == fSndNxt)) &&
714 ((queuedUnsent <= usableWindow) || // Silly W. A.
715 ((unsigned)min(queuedUnsent, usableWindow) >= fMaxRecWnd / 2)
720 // Silly Window Syndrome Avoidance (SWSA) and Nagle passed
722 TCP_Segment nextSegment(fSndNxt, fSndNxt + nextSegmentSize);
723 TCP_Packet & msg = * new TCP_Packet();
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));
732 std::cout << "TCP_Sender::SendNewData,
"
733 << " nextSegmentSize=
" << nextSegmentSize
734 << " fTCPIPHeaderLength=
" << fTCPIPHeaderLength
735 << " byte_size=
" << msg.bit_size() / 8
737 << " time=
" << Event_Queue::now() << std::endl;
740 // no RTT measurement for retransmitted segments
741 // changes on Dec. 13. 2002 (Ga, Bo, Scharf)
743 if (!fRTTMPending && fSndNxt >= fSndMax) { // ##Bo##
744 fRTTMStartTime = Event_Queue::now();
745 fRTTMByte = nextSegment.begin();
749 fSndNxt += nextSegmentSize;
750 fSndMax = max(fSndNxt, fSndMax);
752 // reset SWSA timer if necessary
756 else if (fSWSATimer.IsPending()) {
760 // set rtx timer if necessary
761 if (!fRtxTimer.IsPending()) {
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() << ",
"
778 sillyWindowAvoidanceFailed = true;
780 if (!fSWSATimer.IsPending()) {
781 fSWSATimer.Set(fSWSATimerValue);
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
797 fPendingBackoffReset = false;
805 void TCP_Sender::UnaRetransmit()
807 // resend after timeout or fast retransmit
808 unsigned nextSegmentSize = GetNextSegmentSize(fSndUna);
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));
819 fSndNxt = max(fSndNxt, fSndUna + nextSegmentSize);
820 fSndMax = max(fSndNxt, fSndMax);
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
826 if (fKarn && (nextSegment.begin() <= fRTTMByte) && fRTTMPending) {
827 fRTTMPending = false;
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:
";
840 std::cout << ": TO rtx:
";
842 std::cout << " t =
" << Event_Queue::now() << ",
"
849 // throw(UL_CException("TCP_Sender::UnaRetransmit
", "no bytes
to send
"));
854 void TCP_Sender::FinishFastRecovery()
856 if (fTCPVersion == kTahoe) {
859 else if (fTCPVersion == kReno) {
860 // Reno fast recovery
862 if (fFlightSizeRecovery) {
863 fCWnd = min(fSndMax - fSndUna + fMSS, fSSThresh);
869 else if (fTCPVersion == kNewReno) {
870 // New Reno fast recovery
871 // "Set CWnd
to ...
min (ssthresh, FlightSize + MSS)
873 if (fFlightSizeRecovery) {
874 fCWnd =
min(fSndMax - fSndUna + fMSS, fSSThresh);
884 void TCP_Sender::ReduceSSThresh()
886 if (fCarefulSSThreshReduction) {
892 fSSThresh =
max(2 * fMSS,
893 min(
min(fCWnd, fSndMax - fSndUna), fRecWnd) / 2);
897 fSSThresh =
max(2 * fMSS,
min(fSndMax - fSndUna, fRecWnd) / 2);
900 it_assert(fSSThresh <= fMaxCWnd, "TCP_Sender::HandleACK, internal error: SndSSThresh is > MaxCWnd
");
908 void TCP_Sender::SendMsg(TCP_Packet &msg)
911 TraceSentSeqNo(msg.get_segment().end());
914 if (fRestartAfterIdle) {
915 fLastSendTime = Event_Queue::now(); // needed for idle detection
922 void TCP_Sender::IdleCheck()
924 // idle detection according to Jacobson, SIGCOMM, 1988:
925 // sender is currently idle and nothing has been send since RTO
927 if (fSndMax == fSndUna && Event_Queue::now() - fLastSendTime > CalcRTOValue()) {
928 fCWnd = fInitialCWnd; // see RFC2581
930 fNumberOfIdleTimeouts++;
937 std::cout << "sender
" << fLabel
938 << ": idle timeout:
"
939 << "t =
" << Event_Queue::now()
940 << ", SndNxt =
" << fSndNxt
941 << ", SndUna =
" << fSndUna
942 << ", Backoff =
" << fBackoff
949 void TCP_Sender::HandleRtxTimeout(Ttype)
954 fBackoff = min(fMaxBackoff, fBackoff * 2);
955 if (!fImmediateBackoffReset) {
956 fPendingBackoffReset = false;
959 if (fDupACKCnt >= fDupACKThreshold) {
960 FinishFastRecovery(); // reset dup ACK cnt and CWnd
962 else if (fDupACKCnt > 0) {
963 fDupACKCnt = 0; // don't allow dupack action during TO recovery
966 // update CWnd and SSThresh
967 ReduceSSThresh(); // halve ssthresh (in most cases)
968 fCWnd = fMSS; // not initial CWnd, see RFC 2581
970 it_assert(fSSThresh <= fMaxCWnd, "TCP_Sender::HandleRtxTimeout,
internal error: SndSSThresh is > MaxCWnd
");
972 fRecoveryTO = fSndMax;
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
981 std::cout << "sender
" << fLabel
983 << "t =
" << Event_Queue::now()
984 << ", SndNxt =
" << fSndNxt
985 << ", SndUna =
" << fSndUna
993 UnaRetransmit(); // initiate retransmission
997 void TCP_Sender::HandleSWSATimeout(Ttype)
1003 unsigned TCP_Sender::GetNextSegmentSize(const Sequence_Number & begin)
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;
1013 Sequence_Number end = min(min(fUserNxt, begin + fMSS),
1014 fSndUna + SendWindow());
1017 std::cout << "TCP_Sender::GetNextSegmentSize,
"
1018 << " fUserNxt=
" << fUserNxt
1019 << " begin_seq_num=
" << begin
1021 << " fSndUna=
" << fSndUna
1022 << " SendWindow()=
" << SendWindow()
1023 << " end_seq_num=
" << end
1024 << " time=
" << Event_Queue::now() << std::endl;
1027 return max(0, end - begin);
1031 unsigned TCP_Sender::SendWindow() const
1033 return min(fRecWnd, min(fMaxCWnd, fCWnd));
1037 double TCP_Sender::CalcRTOValue() const
1039 static const double factor = 1 + 1e-8;
1040 // to avoid "simultaneous
" TO/receive ACK events in case of const. RTT
1042 double rto = fBackoff * fRTTEstimate * factor;
1044 if (rto > fMaxRTO) {
1052 void TCP_Sender::SetRtxTimer()
1054 double rto = CalcRTOValue();
1058 std::cout << "sender
" << fLabel
1059 << ":
set rtx timer:
"
1060 << "t =
" << Event_Queue::now()
1061 << ", RTO =
" << rto
1062 << ", Backoff =
" << fBackoff
1063 << ", TimUna =
" << fTimUna
1069 void TCP_Sender::UpdateRTTVariables(double sampleRTT)
1073 fRTTVar = sampleRTT / 2;
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);
1081 fRTTEstimate = round(fSRTT + 4 * fRTTVar, fTimerGranularity);
1084 TraceRTTVariables(sampleRTT);
1087 fNumberOfRTTMeasurements++;
1091 void TCP_Sender::TraceRTTVariables(double sampleRTT)
1094 std::cout << "sender
" << fLabel
1096 << "t =
" << Event_Queue::now()
1097 << ", sample =
" << sampleRTT
1098 << ", SRTT =
" << fSRTT
1099 << ", RTTVar =
" << fRTTVar
1100 << ", RTTEstimate =
" << fRTTEstimate
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);
1108 RTTsample_val(RTTsample_index) = sampleRTT;
1109 RTTsample_time(RTTsample_index) = Event_Queue::now();
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);
1116 RTTEstimate_val(RTTEstimate_index) = fRTTEstimate;
1117 RTTEstimate_time(RTTEstimate_index) = Event_Queue::now();
1118 RTTEstimate_index++;
1122 void TCP_Sender::TraceCWnd()
1125 std::cout << "sender
" << fLabel
1126 << " t =
" << Event_Queue::now()
1127 << " cwnd =
" << fCWnd << std::endl;
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);
1133 CWnd_val(CWnd_index) = fCWnd;
1134 CWnd_time(CWnd_index) = Event_Queue::now();
1139 void TCP_Sender::TraceSSThresh()
1142 std::cout << "sender
" << fLabel
1143 << " t =
" << Event_Queue::now()
1144 << " cwnd =
" << fSSThresh << std::endl;
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);
1150 SSThresh_val(SSThresh_index) = fSSThresh;
1151 SSThresh_time(SSThresh_index) = Event_Queue::now();
1156 void TCP_Sender::TraceSentSeqNo(const Sequence_Number sn)
1160 std::cout << "sender
" << fLabel
1161 << " t =
" << Event_Queue::now()
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);
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++;
1175 void TCP_Sender::TraceACKedSeqNo(const Sequence_Number sn)
1178 std::cout << "sender
" << fLabel
1179 << " t =
" << Event_Queue::now()
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);
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++;
1194 void TCP_Sender::save_trace(std::string filename)
1197 CWnd_val.set_size(CWnd_index, true);
1198 CWnd_time.set_size(CWnd_index, true);
1200 SSThresh_val.set_size(SSThresh_index, true);
1201 SSThresh_time.set_size(SSThresh_index, true);
1203 sent_seq_num_val.set_size(sent_seq_num_index, true);
1204 sent_seq_num_time.set_size(sent_seq_num_index, true);
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);
1209 RTTEstimate_val.set_size(RTTEstimate_index, true);
1210 RTTEstimate_time.set_size(RTTEstimate_index, true);
1212 RTTsample_val.set_size(RTTsample_index, true);
1213 RTTsample_time.set_size(RTTsample_index, true);
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;
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;
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;
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;
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;
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;
1240 std::cout << "TCP_Sender::saving
to file:
" << filename << std::endl;
1246 ff2 << Name("CWnd_val
") << CWnd_val;
1247 ff2 << Name("CWnd_time
") << CWnd_time;
1248 ff2 << Name("CWnd_index
") << CWnd_index;
1250 ff2 << Name("SSThresh_val
") << SSThresh_val;
1251 ff2 << Name("SSThresh_time
") << SSThresh_time;
1252 ff2 << Name("SSThresh_index
") << SSThresh_index;
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;
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;
1262 ff2 << Name("RTTEstimate_val
") << RTTEstimate_val;
1263 ff2 << Name("RTTEstimate_time
") << RTTEstimate_time;
1264 ff2 << Name("RTTEstimate_index
") << RTTEstimate_index;
1266 ff2 << Name("RTTsample_val
") << RTTsample_val;
1267 ff2 << Name("RTTsample_time
") << RTTsample_time;
1268 ff2 << Name("RTTsample_index
") << RTTsample_index;
1275 void TCP_Sender::print_item(std::ostream &, const std::string & keyword)
1277 if (keyword == "Label
") {
1278 std::cout << fLabel;
1280 else if (keyword == "CWnd
") {
1283 else if (keyword == "SSThresh
") {
1284 std::cout << fSSThresh;
1286 else if (keyword == "SRTT
") {
1289 else if (keyword == "RTTvar
") {
1290 std::cout << fRTTVar;
1292 else if (keyword == "Backoff
") {
1293 std::cout << fBackoff;
1295 else if (keyword == "RTO
") {
1296 std::cout << CalcRTOValue();
1298 else if (keyword == "NoOfFastRets
") {
1299 std::cout << fNumberOfFastRetransmits;
1301 else if (keyword == "NoOfRetTOs
") {
1302 std::cout << fNumberOfTimeouts;
1304 else if (keyword == "NoOfIdleTOs
") {
1305 std::cout << fNumberOfIdleTimeouts;
1307 else if (keyword == "NoOfRTTMs
") {
1308 std::cout << fNumberOfRTTMeasurements;
1310 else if (keyword == "NoOfRecACKs
") {
1311 std::cout << fNumberOfReceivedACKs;
1318 // -------------------- TCP_Receiver_Buffer ----------------------------------------
1319 TCP_Receiver_Buffer::TCP_Receiver_Buffer() :
1325 TCP_Receiver_Buffer::TCP_Receiver_Buffer(const TCP_Receiver_Buffer & rhs) :
1326 fFirstByte(rhs.fFirstByte),
1327 fBufList(rhs.fBufList)
1332 void TCP_Receiver_Buffer::reset()
1339 TCP_Receiver_Buffer::~TCP_Receiver_Buffer()
1344 void TCP_Receiver_Buffer::write(TCP_Segment newBlock)
1347 it_assert(newBlock.begin() <= newBlock.end(), "TCP_Receiver_Buffer::Write, no valid segment
");
1349 // cut blocks beginning before fFirstByte
1350 if (newBlock.begin() < fFirstByte) {
1351 if (newBlock.end() > fFirstByte) {
1352 newBlock.set_begin(fFirstByte);
1355 return; //// TODO: Is this strange?
1359 if (newBlock.length() == 0) { // empty block, nothing to do
1363 if (fBufList.empty() || (newBlock.begin() > fBufList.back().end())) {
1364 // new block is behind last block in buffer
1365 fBufList.push_back(newBlock);
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()) {
1374 it_assert(iter != fBufList.end(), "TCP_Receiver_Buffer::Write,
internal error
");
1377 TCP_Segment & exBlock = *iter;
1379 if (exBlock.can_be_combined(newBlock)) {
1380 // overlapping or contiguous blocks -> combine
1381 exBlock.combine(newBlock);
1383 // check following blocks
1385 while ((iter != fBufList.end()) &&
1386 exBlock.can_be_combined(*iter)) {
1387 exBlock.combine(*iter);
1388 iter = fBufList.erase(iter);
1392 // no overlap, newBlock lies between two existing list entries
1393 // new list entry has to be created
1395 fBufList.insert(iter, newBlock);
1399 it_assert(!fBufList.empty() && fBufList.front().begin() >= fFirstByte, "TCP_Receiver_Buffer::Write,
internal error
");
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)
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
");
1414 if (noOfBytes < first_block_size()) {
1415 fBufList.front().set_begin(fBufList.front().begin() + noOfBytes);
1417 else { // first block will be read completely
1418 fBufList.pop_front();
1420 fFirstByte += noOfBytes;
1422 it_assert(fBufList.empty() || fBufList.front().begin() >= fFirstByte, "TCP_Receiver_Buffer::Read,
internal error
");
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
1430 if (!fBufList.empty() && (fBufList.front().begin() == fFirstByte)) {
1431 return fBufList.front().length();
1439 std::ostream & TCP_Receiver_Buffer::info(std::ostream &os, int detail) const
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;
1448 os << "segments in receiver buffer:
" << std::endl;
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;
1462 // -------------------- TCP_Receiver ----------------------------------------
1463 TCP_Receiver::TCP_Receiver(int label) :
1466 fTCPIPHeaderLength(TCP_HEADERLENGTH),
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),
1483 fDelayedACKTimer(*this, &TCP_Receiver::DelayedACKHandler),
1484 fPeriodicACKTimer(*this, &TCP_Receiver::PeriodicACKHandler),
1485 fACKSchedulingTimer(*this, &TCP_Receiver::SendACKMessage),
1487 fUserBlockProcTimer(*this, &TCP_Receiver::HandleEndOfProcessing)
1489 fUserMessage = NULL;
1492 if (!fACKOnBufferRead && !fACKOnBufferWrite) {
1493 // throw(UL_CException("TCP_Receiver::TCP_Receiver
",
1494 // "ACKs must be sent on buffer read or write or both
"));
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
");
1509 TCP_Receiver::~TCP_Receiver()
1511 delete fWaitingACKMsg;
1512 delete fUserMessage;
1516 void TCP_Receiver::set_debug(const bool enable_debug)
1518 fDebug = enable_debug;
1519 tcp_send_ack.set_debug(enable_debug);
1520 tcp_new_data.set_debug();
1523 void TCP_Receiver::set_debug(bool enable_debug, bool enable_signal_debug)
1525 fDebug = enable_debug;
1526 tcp_send_ack.set_debug(enable_signal_debug);
1527 tcp_new_data.set_debug();
1530 void TCP_Receiver::set_trace(const bool enable_trace)
1532 fTrace = enable_trace;
1537 void TCP_Receiver::setup()
1542 if (fSendPeriodicACKs) {
1543 fPeriodicACKTimer.Set(fPeriodicACKInterval);
1546 fReceiverBuffer.reset();
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;
1557 std::string TCP_Receiver::GenerateFilename()
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
1571 return filename_stream.str();
1574 void TCP_Receiver::release(std::string file)
1576 std::string filename;
1579 if (fWaitingACKMsg != 0) {
1580 delete fWaitingACKMsg;
1583 if (fUserMessage != 0) {
1584 delete fUserMessage;
1588 fUserBlockProcTimer.Reset();
1589 fDelayedACKTimer.Reset();
1590 fPeriodicACKTimer.Reset();
1591 fACKSchedulingTimer.Reset();
1595 filename = GenerateFilename();
1599 save_trace(filename);
1604 void TCP_Receiver::ReceiveMessageFromNet(itpp::Packet *msg)
1606 TCP_Packet & packet = (TCP_Packet &) * msg;
1607 if (packet.get_destination_port() == fLabel) {
1608 if (packet.get_session_id() == fSessionId) {
1609 ReceiveDataPacket(packet);
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()
1623 it_warning("Received a TCP packet with label
");
1629 void TCP_Receiver::ReceiveDataPacket(TCP_Packet &msg)
1631 TCP_Segment segment = msg.get_segment();
1633 bool isOutOfOrder = (segment.begin() > fReceiverBuffer.next_expected()) ||
1634 (segment.end() <= fReceiverBuffer.next_expected());
1637 std::cout << "TCP_Receiver::ReceiveDataPacket receiver:
" << fLabel << ":
"
1639 << "t =
" << Event_Queue::now()
1640 << ", next
exp. =
" << fReceiverBuffer.next_expected()
1641 << ",
" << msg << std::endl;
1645 TraceReceivedSeqNo(segment.end());
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
");
1651 fReceiverBuffer.write(segment);
1654 SendACK(true); // create dupack conditionless
1657 if (fACKOnBufferWrite) {
1660 IndicateUserMessage();
1667 void TCP_Receiver::IndicateUserMessage()
1669 if (fUserMessage == 0) {
1671 unsigned noOfBytes = min(fReceiverBuffer.first_block_size(),
1675 std::cout << "TCP_Receiver::IndicateUserMessage
"
1676 << "t =
" << Event_Queue::now()
1677 << " noOfBytes =
" << noOfBytes
1678 << " firstBlock =
" << fReceiverBuffer.first_block_size()
1682 if (noOfBytes >= fMinUserBlockSize) {
1683 fUserMessage = new Packet();
1684 fUserMessage->set_bit_size(8*noOfBytes);
1685 fUserBlockProcTimer.Set(fUserBlockProcDelay);
1691 bool TCP_Receiver::is_user_message_available()
1693 if (fUserMessage != 0) {
1697 unsigned noOfBytes = min(fReceiverBuffer.first_block_size(),
1700 if (noOfBytes >= fMinUserBlockSize) {
1701 fUserMessage = new Packet();
1702 fUserMessage->set_bit_size(8*noOfBytes);
1711 itpp::Packet & TCP_Receiver::get_user_message()
1713 it_assert(fUserMessage != 0, "TCP_Receiver::GetUserMessage, no message available
");
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()
1725 fReceiverBuffer.read(fUserMessage->bit_size() / 8);
1726 if (fACKOnBufferRead) {
1727 SendACK(false); // send acknowledgement
1730 itpp::Packet & msg = *fUserMessage;
1733 if (fReceiverBuffer.first_block_size() > 0) {
1734 IndicateUserMessage();
1742 void TCP_Receiver::HandleEndOfProcessing(Ttype)
1744 it_assert(fUserMessage != 0, "TCP_Receiver::HandleEndOfProcessing, no message available
");
1747 tcp_new_data(fLabel);
1751 void TCP_Receiver::DelayedACKHandler(Ttype)
1754 std::cout << "TCP_Receiver::DelayedACKHandler
"
1755 << "receiver
" << fLabel
1757 << "t =
" << Event_Queue::now() << std::endl;
1764 void TCP_Receiver::PeriodicACKHandler(Ttype)
1767 std::cout << "TCP_Receiver::PeriodicACKHandler
"
1768 << "receiver
" << fLabel
1769 << ": periodicACK TO:
"
1770 << "t =
" << Event_Queue::now() << std::endl;
1777 void TCP_Receiver::SendACK(bool sendConditionless)
1779 // sendConditionless is set
1780 // ... if packet was received out of order or
1781 // ... if delayed ACK timer has expired
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.
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
1804 // Receiver Silly Window Syndrome Avoidance:
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();
1814 fAdvRcvWnd = fAdvRcvNxt + fAdvRcvWnd - fReceiverBuffer.next_expected();
1817 fAdvRcvNxt = fReceiverBuffer.next_expected();
1819 if (fSendPeriodicACKs &&
1820 (!fStrictPeriodicACKs || !fPeriodicACKTimer.IsPending())) {
1821 fPeriodicACKTimer.Set(fPeriodicACKInterval);
1824 if (fDelayedACK && fDelayedACKTimer.IsPending()) {
1825 fDelayedACKTimer.Reset();
1828 ScheduleACKMessage();
1831 if (!fDelayedACKTimer.IsPending()) {
1832 fDelayedACKTimer.Set(fACKDelayTime);
1834 std::cout << "TCP_Receiver::SendACK
"
1835 << "receiver
" << fLabel
1836 << ":
set delACK timer:
"
1837 << "t =
" << Event_Queue::now() << std::endl;
1844 void TCP_Receiver::ScheduleACKMessage()
1846 if (fWaitingACKMsg == 0) {
1847 fWaitingACKMsg = new TCP_Packet;
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);
1857 if (fACKSchedulingDelay > 0) {
1858 if (!fACKSchedulingTimer.IsPending()) {
1859 fACKSchedulingTimer.Set(fACKSchedulingDelay);
1863 SendACKMessage(Event_Queue::now());
1868 void TCP_Receiver::SendACKMessage(Ttype)
1870 it_assert(fWaitingACKMsg != 0, "TCP_Receiver::SendACKMessage, no ACK message waiting
");
1873 std::cout << "TCP_Receiver::SendACKMessage Ack sent
"
1874 << "receiver
" << fLabel
1876 << "t =
" << Event_Queue::now()
1877 << ",
" << (*fWaitingACKMsg)
1878 << " byte_size=
" << fWaitingACKMsg->bit_size() / 8
1879 << " ptr=
" << fWaitingACKMsg << std::endl;
1882 tcp_send_ack(fWaitingACKMsg);
1888 void TCP_Receiver::TraceReceivedSeqNo(const Sequence_Number &sn)
1891 std::cout << "TCP_Receiver::TraceReceivedSeqNo
"
1892 << "receiver
" << fLabel
1893 << " t =
" << Event_Queue::now()
1894 << " sn =
" << sn << std::endl;
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);
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++;
1906 void TCP_Receiver::save_trace(std::string filename)
1909 received_seq_num_val.set_size(received_seq_num_index, true);
1910 received_seq_num_time.set_size(received_seq_num_index, true);
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;
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;
1934 #pragma warning(default:4355)