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()
452 timeinfo = localtime(&rawtime);
456 struct tm *timeinfo = &_timeinfo;
457 localtime_s(timeinfo, &rawtime);
459 std::ostringstream filename_stream;
460 filename_stream <<
"trace_tcp_sender_u" << fLabel
461 <<
"_" << 1900 + timeinfo->tm_year
462 <<
"_" << timeinfo->tm_mon
463 <<
"_" << timeinfo->tm_mday
464 <<
"__" << timeinfo->tm_hour
465 <<
"_" << timeinfo->tm_min
466 <<
"_" << timeinfo->tm_sec
468 return filename_stream.str();
474 std::string filename;
482 filename = GenerateFilename();
491 void TCP_Sender::InitStatistics()
493 fNumberOfTimeouts = 0;
494 fNumberOfIdleTimeouts = 0;
495 fNumberOfFastRetransmits = 0;
496 fNumberOfRTTMeasurements = 0;
497 fNumberOfReceivedACKs = 0;
501 void TCP_Sender::StopTransientPhase()
507 void TCP_Sender::HandleUserMessageIndication(
itpp::Packet *user_data_p)
510 std::cout <<
"TCP_Sender::HandleUserMessageIndication"
511 <<
" byte_size=" << user_data_p->
bit_size() / 8
512 <<
" ptr=" << user_data_p
516 SocketWriteQueue.push(user_data_p);
523 void TCP_Sender::ReceiveMessageFromNet(
itpp::Packet *msg)
525 TCP_Packet & packet = (TCP_Packet &) * msg;
528 std::cout <<
"TCP_Sender::ReceiveMessageFromNet"
529 <<
" byte_size=" << msg->
bit_size() / 8
534 if ((packet.get_session_id() == fSessionId) &&
535 (packet.get_ACK() >= fSndUna)) {
543 void TCP_Sender::HandleACK(TCP_Packet &msg)
545 it_assert(msg.get_ACK() <= fSndMax,
"TCP_Sender::HandleACK, received ACK > SndMax at ");
547 fNumberOfReceivedACKs++;
550 TraceACKedSeqNo(msg.get_ACK());
554 std::cout <<
"sender " << fLabel <<
": "
561 fRecWnd = msg.get_wnd();
562 fMaxRecWnd =
max(fRecWnd, fMaxRecWnd);
564 if (msg.get_ACK() == fSndUna) {
566 bool ignoreDupACK = (fSndMax == fSndUna);
568 if (fIgnoreDupACKOnTORecovery) {
570 if (fCarefulMulFastRtxAvoidance) {
572 ignoreDupACK = ignoreDupACK || (fSndUna <= fRecoveryTO);
576 ignoreDupACK = ignoreDupACK || (fSndUna < fRecoveryTO);
583 if (fDupACKCnt == fDupACKThreshold) {
585 fNumberOfFastRetransmits++;
587 fRecoveryDupACK = fSndMax;
591 if ((fTCPVersion == kReno) || (fTCPVersion == kNewReno)) {
594 else if (fTCPVersion == kTahoe) {
598 if (fTCPVersion == kReno || fTCPVersion == kNewReno) {
600 if (fRenoConservation) {
601 fCWnd += fDupACKThreshold * fMSS;
604 else if (fTCPVersion == kTahoe) {
612 else if (fDupACKCnt > fDupACKThreshold) {
613 if (fTCPVersion == kReno || fTCPVersion == kNewReno) {
617 if (fRenoConservation) {
625 Sequence_Number oldSndUna = fSndUna;
626 fSndUna = msg.get_ACK();
627 fSndNxt =
max(fSndNxt, fSndUna);
631 if ((fSndUna > fTimUna) && fRtxTimer.
IsPending()) {
638 if (fImmediateBackoffReset) {
642 if (fPendingBackoffReset) {
644 fPendingBackoffReset =
false;
646 else if (fBackoff > 1) {
649 fPendingBackoffReset =
true;
655 if ((fSndUna > fRTTMByte) && fRTTMPending) {
657 fRTTMPending =
false;
662 if (fDupACKCnt >= fDupACKThreshold) {
664 if (fTCPVersion == kNewReno && fSndUna < fRecoveryDupACK) {
666 if (fRenoConservation) {
667 fCWnd =
max(fMSS, fCWnd - (fSndUna - oldSndUna) + fMSS);
672 FinishFastRecovery();
678 if (fCWnd < fSSThresh) {
680 fCWnd =
min(fCWnd + fMSS, fMaxCWnd);
684 fCWnd +=
max(fMSS * fMSS / fCWnd, 1);
685 fCWnd =
min(fCWnd, fMaxCWnd);
699 void TCP_Sender::SendNewData(
bool skipSWSA)
701 unsigned nextSegmentSize;
703 it_assert(fSndUna <= fSndNxt, "TCP_Sender::SendNewData, SndUna > SndNxt in sender
" + to_str(fLabel) + "!
");
705 if (fRestartAfterIdle) {
709 bool sillyWindowAvoidanceFailed = false;
711 while (!sillyWindowAvoidanceFailed &&
712 ((nextSegmentSize = GetNextSegmentSize(fSndNxt)) > 0)) {
713 // there is new data to send and window is large enough
715 // SWSA and Nagle (RFC 1122): assume PUSH to be set
716 unsigned queuedUnsent = fUserNxt - fSndNxt;
717 unsigned usableWindow = max(0, (fSndUna + SendWindow()) - fSndNxt);
719 if (((unsigned)min(queuedUnsent, usableWindow) >= fMSS) ||
720 ((!fNagle || (fSndUna == fSndNxt)) &&
721 ((queuedUnsent <= usableWindow) || // Silly W. A.
722 ((unsigned)min(queuedUnsent, usableWindow) >= fMaxRecWnd / 2)
727 // Silly Window Syndrome Avoidance (SWSA) and Nagle passed
729 TCP_Segment nextSegment(fSndNxt, fSndNxt + nextSegmentSize);
730 TCP_Packet & msg = * new TCP_Packet();
732 msg.set_segment(nextSegment);
733 msg.set_session_id(fSessionId);
734 msg.set_destination_port(fLabel); // The dest and src port are set to the same
735 msg.set_source_port(fLabel); // number for simplicity.
736 msg.set_bit_size(8 * (nextSegmentSize + fTCPIPHeaderLength));
739 std::cout << "TCP_Sender::SendNewData,
"
740 << " nextSegmentSize=
" << nextSegmentSize
741 << " fTCPIPHeaderLength=
" << fTCPIPHeaderLength
742 << " byte_size=
" << msg.bit_size() / 8
744 << " time=
" << Event_Queue::now() << std::endl;
747 // no RTT measurement for retransmitted segments
748 // changes on Dec. 13. 2002 (Ga, Bo, Scharf)
750 if (!fRTTMPending && fSndNxt >= fSndMax) { // ##Bo##
751 fRTTMStartTime = Event_Queue::now();
752 fRTTMByte = nextSegment.begin();
756 fSndNxt += nextSegmentSize;
757 fSndMax = max(fSndNxt, fSndMax);
759 // reset SWSA timer if necessary
763 else if (fSWSATimer.IsPending()) {
767 // set rtx timer if necessary
768 if (!fRtxTimer.IsPending()) {
774 msg.set_info(fSSThresh, fRecWnd, fCWnd, fRTTEstimate,
775 fSndUna, fSndNxt, false);
776 std::cout << "sender
" << fLabel
777 << ": send
new data:
"
778 << " t =
" << Event_Queue::now() << ",
"
785 sillyWindowAvoidanceFailed = true;
787 if (!fSWSATimer.IsPending()) {
788 fSWSATimer.Set(fSWSATimerValue);
793 // set timers in case that no new data could have been sent
794 if (!fRtxTimer.IsPending()) {
795 if (fSndMax > fSndUna) { // there is outstanding data
796 if (!fImmediateBackoffReset && fPendingBackoffReset) {
797 // backoff is reset if no new data could have been sent since last
798 // (successfull) retransmission; this is useful in case of
799 // Reno recovery and multiple losses to avoid that in
800 // the (unavoidable) series of timeouts the timer value
801 // increases exponentially as this is not the intention
802 // of the delayed backoff reset in Karn's algorithm
804 fPendingBackoffReset = false;
812 void TCP_Sender::UnaRetransmit()
814 // resend after timeout or fast retransmit
815 unsigned nextSegmentSize = GetNextSegmentSize(fSndUna);
817 if (nextSegmentSize > 0) {
818 TCP_Segment nextSegment(fSndUna, fSndUna + nextSegmentSize);
819 TCP_Packet & msg = *new TCP_Packet();
820 msg.set_segment(nextSegment);
821 msg.set_session_id(fSessionId);
822 msg.set_destination_port(fLabel); // The dest and src port are set to the same
823 msg.set_source_port(fLabel); // number for simplicity.
824 msg.set_bit_size(8 * (nextSegmentSize + fTCPIPHeaderLength));
826 fSndNxt = max(fSndNxt, fSndUna + nextSegmentSize);
827 fSndMax = max(fSndNxt, fSndMax);
829 // The RTT measurement is cancelled if the RTTM byte has a sequence
830 // number higher or equal than the first retransmitted byte as
831 // the ACK for the RTTM byte will be delayed by the rtx for at least
833 if (fKarn && (nextSegment.begin() <= fRTTMByte) && fRTTMPending) {
834 fRTTMPending = false;
840 msg.set_info(fSSThresh, fRecWnd, fCWnd, fRTTEstimate,
841 fSndUna, fSndNxt, true);
842 std::cout << "sender
" << fLabel;
843 if (fDupACKCnt >= fDupACKThreshold) {
844 std::cout << ": fast rtx:
";
847 std::cout << ": TO rtx:
";
849 std::cout << " t =
" << Event_Queue::now() << ",
"
856 // throw(UL_CException("TCP_Sender::UnaRetransmit
", "no bytes
to send
"));
861 void TCP_Sender::FinishFastRecovery()
863 if (fTCPVersion == kTahoe) {
866 else if (fTCPVersion == kReno) {
867 // Reno fast recovery
869 if (fFlightSizeRecovery) {
870 fCWnd = min(fSndMax - fSndUna + fMSS, fSSThresh);
876 else if (fTCPVersion == kNewReno) {
877 // New Reno fast recovery
878 // "Set CWnd
to ...
min (ssthresh, FlightSize + MSS)
880 if (fFlightSizeRecovery) {
881 fCWnd =
min(fSndMax - fSndUna + fMSS, fSSThresh);
891 void TCP_Sender::ReduceSSThresh()
893 if (fCarefulSSThreshReduction) {
899 fSSThresh =
max(2 * fMSS,
900 min(
min(fCWnd, fSndMax - fSndUna), fRecWnd) / 2);
904 fSSThresh =
max(2 * fMSS,
min(fSndMax - fSndUna, fRecWnd) / 2);
907 it_assert(fSSThresh <= fMaxCWnd, "TCP_Sender::HandleACK, internal error: SndSSThresh is > MaxCWnd
");
915 void TCP_Sender::SendMsg(TCP_Packet &msg)
918 TraceSentSeqNo(msg.get_segment().end());
921 if (fRestartAfterIdle) {
922 fLastSendTime = Event_Queue::now(); // needed for idle detection
929 void TCP_Sender::IdleCheck()
931 // idle detection according to Jacobson, SIGCOMM, 1988:
932 // sender is currently idle and nothing has been send since RTO
934 if (fSndMax == fSndUna && Event_Queue::now() - fLastSendTime > CalcRTOValue()) {
935 fCWnd = fInitialCWnd; // see RFC2581
937 fNumberOfIdleTimeouts++;
944 std::cout << "sender
" << fLabel
945 << ": idle timeout:
"
946 << "t =
" << Event_Queue::now()
947 << ", SndNxt =
" << fSndNxt
948 << ", SndUna =
" << fSndUna
949 << ", Backoff =
" << fBackoff
956 void TCP_Sender::HandleRtxTimeout(Ttype)
961 fBackoff = min(fMaxBackoff, fBackoff * 2);
962 if (!fImmediateBackoffReset) {
963 fPendingBackoffReset = false;
966 if (fDupACKCnt >= fDupACKThreshold) {
967 FinishFastRecovery(); // reset dup ACK cnt and CWnd
969 else if (fDupACKCnt > 0) {
970 fDupACKCnt = 0; // don't allow dupack action during TO recovery
973 // update CWnd and SSThresh
974 ReduceSSThresh(); // halve ssthresh (in most cases)
975 fCWnd = fMSS; // not initial CWnd, see RFC 2581
977 it_assert(fSSThresh <= fMaxCWnd, "TCP_Sender::HandleRtxTimeout,
internal error: SndSSThresh is > MaxCWnd
");
979 fRecoveryTO = fSndMax;
982 // go back N is mainly relevant in the case of multiple losses
983 // which would lead to a series of timeouts without resetting sndnxt
988 std::cout << "sender
" << fLabel
990 << "t =
" << Event_Queue::now()
991 << ", SndNxt =
" << fSndNxt
992 << ", SndUna =
" << fSndUna
1000 UnaRetransmit(); // initiate retransmission
1004 void TCP_Sender::HandleSWSATimeout(Ttype)
1010 unsigned TCP_Sender::GetNextSegmentSize(const Sequence_Number & begin)
1012 // try to get new user messages if available and necessary
1013 while ((fUserNxt < begin + fMSS) && (!SocketWriteQueue.empty())) {
1014 itpp::Packet *packet_p = SocketWriteQueue.front();
1015 SocketWriteQueue.pop();
1016 fUserNxt += (unsigned) packet_p->bit_size() / 8;
1020 Sequence_Number end = min(min(fUserNxt, begin + fMSS),
1021 fSndUna + SendWindow());
1024 std::cout << "TCP_Sender::GetNextSegmentSize,
"
1025 << " fUserNxt=
" << fUserNxt
1026 << " begin_seq_num=
" << begin
1028 << " fSndUna=
" << fSndUna
1029 << " SendWindow()=
" << SendWindow()
1030 << " end_seq_num=
" << end
1031 << " time=
" << Event_Queue::now() << std::endl;
1034 return max(0, end - begin);
1038 unsigned TCP_Sender::SendWindow() const
1040 return min(fRecWnd, min(fMaxCWnd, fCWnd));
1044 double TCP_Sender::CalcRTOValue() const
1046 static const double factor = 1 + 1e-8;
1047 // to avoid "simultaneous
" TO/receive ACK events in case of const. RTT
1049 double rto = fBackoff * fRTTEstimate * factor;
1051 if (rto > fMaxRTO) {
1059 void TCP_Sender::SetRtxTimer()
1061 double rto = CalcRTOValue();
1065 std::cout << "sender
" << fLabel
1066 << ":
set rtx timer:
"
1067 << "t =
" << Event_Queue::now()
1068 << ", RTO =
" << rto
1069 << ", Backoff =
" << fBackoff
1070 << ", TimUna =
" << fTimUna
1076 void TCP_Sender::UpdateRTTVariables(double sampleRTT)
1080 fRTTVar = sampleRTT / 2;
1083 // see, e.g., Comer for the values used as weights
1084 fSRTT = 0.875 * fSRTT + 0.125 * sampleRTT;
1085 fRTTVar = 0.75 * fRTTVar + 0.25 * fabs(sampleRTT - fSRTT);
1088 fRTTEstimate = round(fSRTT + 4 * fRTTVar, fTimerGranularity);
1091 TraceRTTVariables(sampleRTT);
1094 fNumberOfRTTMeasurements++;
1098 void TCP_Sender::TraceRTTVariables(double sampleRTT)
1101 std::cout << "sender
" << fLabel
1103 << "t =
" << Event_Queue::now()
1104 << ", sample =
" << sampleRTT
1105 << ", SRTT =
" << fSRTT
1106 << ", RTTVar =
" << fRTTVar
1107 << ", RTTEstimate =
" << fRTTEstimate
1111 if (RTTsample_index >= RTTsample_time.size()) {
1112 RTTsample_time.set_size(2*RTTsample_time.size(), true);
1113 RTTsample_val.set_size(2*RTTsample_val.size(), true);
1115 RTTsample_val(RTTsample_index) = sampleRTT;
1116 RTTsample_time(RTTsample_index) = Event_Queue::now();
1119 if (RTTEstimate_index >= RTTEstimate_time.size()) {
1120 RTTEstimate_time.set_size(2*RTTEstimate_time.size(), true);
1121 RTTEstimate_val.set_size(2*RTTEstimate_val.size(), true);
1123 RTTEstimate_val(RTTEstimate_index) = fRTTEstimate;
1124 RTTEstimate_time(RTTEstimate_index) = Event_Queue::now();
1125 RTTEstimate_index++;
1129 void TCP_Sender::TraceCWnd()
1132 std::cout << "sender
" << fLabel
1133 << " t =
" << Event_Queue::now()
1134 << " cwnd =
" << fCWnd << std::endl;
1136 if (CWnd_index >= CWnd_time.size()) {
1137 CWnd_time.set_size(2*CWnd_time.size(), true);
1138 CWnd_val.set_size(2*CWnd_val.size(), true);
1140 CWnd_val(CWnd_index) = fCWnd;
1141 CWnd_time(CWnd_index) = Event_Queue::now();
1146 void TCP_Sender::TraceSSThresh()
1149 std::cout << "sender
" << fLabel
1150 << " t =
" << Event_Queue::now()
1151 << " cwnd =
" << fSSThresh << std::endl;
1153 if (SSThresh_index >= SSThresh_time.size()) {
1154 SSThresh_time.set_size(2*SSThresh_time.size(), true);
1155 SSThresh_val.set_size(2*SSThresh_val.size(), true);
1157 SSThresh_val(SSThresh_index) = fSSThresh;
1158 SSThresh_time(SSThresh_index) = Event_Queue::now();
1163 void TCP_Sender::TraceSentSeqNo(const Sequence_Number sn)
1167 std::cout << "sender
" << fLabel
1168 << " t =
" << Event_Queue::now()
1172 if (sent_seq_num_index >= sent_seq_num_time.size()) {
1173 sent_seq_num_time.set_size(2*sent_seq_num_time.size(), true);
1174 sent_seq_num_val.set_size(2*sent_seq_num_val.size(), true);
1176 sent_seq_num_val(sent_seq_num_index) = sn.value();
1177 sent_seq_num_time(sent_seq_num_index) = Event_Queue::now();
1178 sent_seq_num_index++;
1182 void TCP_Sender::TraceACKedSeqNo(const Sequence_Number sn)
1185 std::cout << "sender
" << fLabel
1186 << " t =
" << Event_Queue::now()
1191 if (sender_recv_ack_seq_num_index >= sender_recv_ack_seq_num_time.size()) {
1192 sender_recv_ack_seq_num_time.set_size(2*sender_recv_ack_seq_num_time.size(), true);
1193 sender_recv_ack_seq_num_val.set_size(2*sender_recv_ack_seq_num_val.size(), true);
1195 sender_recv_ack_seq_num_val(sender_recv_ack_seq_num_index) = sn.value();
1196 sender_recv_ack_seq_num_time(sender_recv_ack_seq_num_index) = Event_Queue::now();
1197 sender_recv_ack_seq_num_index++;
1201 void TCP_Sender::save_trace(std::string filename)
1204 CWnd_val.set_size(CWnd_index, true);
1205 CWnd_time.set_size(CWnd_index, true);
1207 SSThresh_val.set_size(SSThresh_index, true);
1208 SSThresh_time.set_size(SSThresh_index, true);
1210 sent_seq_num_val.set_size(sent_seq_num_index, true);
1211 sent_seq_num_time.set_size(sent_seq_num_index, true);
1213 sender_recv_ack_seq_num_val.set_size(sender_recv_ack_seq_num_index, true);
1214 sender_recv_ack_seq_num_time.set_size(sender_recv_ack_seq_num_index, true);
1216 RTTEstimate_val.set_size(RTTEstimate_index, true);
1217 RTTEstimate_time.set_size(RTTEstimate_index, true);
1219 RTTsample_val.set_size(RTTsample_index, true);
1220 RTTsample_time.set_size(RTTsample_index, true);
1223 std::cout << "CWnd_val
" << CWnd_val << std::endl;
1224 std::cout << "CWnd_time
" << CWnd_time << std::endl;
1225 std::cout << "CWnd_index
" << CWnd_index << std::endl;
1227 std::cout << "SSThresh_val
" << SSThresh_val << std::endl;
1228 std::cout << "SSThresh_time
" << SSThresh_time << std::endl;
1229 std::cout << "SSThresh_index
" << SSThresh_index << std::endl;
1231 std::cout << "sent_seq_num_val
" << sent_seq_num_val << std::endl;
1232 std::cout << "sent_seq_num_time
" << sent_seq_num_time << std::endl;
1233 std::cout << "sent_seq_num_index
" << sent_seq_num_index << std::endl;
1235 std::cout << "sender_recv_ack_seq_num_val
" << sender_recv_ack_seq_num_val << std::endl;
1236 std::cout << "sender_recv_ack_seq_num_time
" << sender_recv_ack_seq_num_time << std::endl;
1237 std::cout << "sender_recv_ack_seq_num_index
" << sender_recv_ack_seq_num_index << std::endl;
1239 std::cout << "RTTEstimate_val
" << RTTEstimate_val << std::endl;
1240 std::cout << "RTTEstimate_time
" << RTTEstimate_time << std::endl;
1241 std::cout << "RTTEstimate_index
" << RTTEstimate_index << std::endl;
1243 std::cout << "RTTsample_val
" << RTTsample_val << std::endl;
1244 std::cout << "RTTsample_time
" << RTTsample_time << std::endl;
1245 std::cout << "RTTsample_index
" << RTTsample_index << std::endl;
1247 std::cout << "TCP_Sender::saving
to file:
" << filename << std::endl;
1253 ff2 << Name("CWnd_val
") << CWnd_val;
1254 ff2 << Name("CWnd_time
") << CWnd_time;
1255 ff2 << Name("CWnd_index
") << CWnd_index;
1257 ff2 << Name("SSThresh_val
") << SSThresh_val;
1258 ff2 << Name("SSThresh_time
") << SSThresh_time;
1259 ff2 << Name("SSThresh_index
") << SSThresh_index;
1261 ff2 << Name("sent_seq_num_val
") << sent_seq_num_val;
1262 ff2 << Name("sent_seq_num_time
") << sent_seq_num_time;
1263 ff2 << Name("sent_seq_num_index
") << sent_seq_num_index;
1265 ff2 << Name("sender_recv_ack_seq_num_val
") << sender_recv_ack_seq_num_val;
1266 ff2 << Name("sender_recv_ack_seq_num_time
") << sender_recv_ack_seq_num_time;
1267 ff2 << Name("sender_recv_ack_seq_num_index
") << sender_recv_ack_seq_num_index;
1269 ff2 << Name("RTTEstimate_val
") << RTTEstimate_val;
1270 ff2 << Name("RTTEstimate_time
") << RTTEstimate_time;
1271 ff2 << Name("RTTEstimate_index
") << RTTEstimate_index;
1273 ff2 << Name("RTTsample_val
") << RTTsample_val;
1274 ff2 << Name("RTTsample_time
") << RTTsample_time;
1275 ff2 << Name("RTTsample_index
") << RTTsample_index;
1282 void TCP_Sender::print_item(std::ostream &, const std::string & keyword)
1284 if (keyword == "Label
") {
1285 std::cout << fLabel;
1287 else if (keyword == "CWnd
") {
1290 else if (keyword == "SSThresh
") {
1291 std::cout << fSSThresh;
1293 else if (keyword == "SRTT
") {
1296 else if (keyword == "RTTvar
") {
1297 std::cout << fRTTVar;
1299 else if (keyword == "Backoff
") {
1300 std::cout << fBackoff;
1302 else if (keyword == "RTO
") {
1303 std::cout << CalcRTOValue();
1305 else if (keyword == "NoOfFastRets
") {
1306 std::cout << fNumberOfFastRetransmits;
1308 else if (keyword == "NoOfRetTOs
") {
1309 std::cout << fNumberOfTimeouts;
1311 else if (keyword == "NoOfIdleTOs
") {
1312 std::cout << fNumberOfIdleTimeouts;
1314 else if (keyword == "NoOfRTTMs
") {
1315 std::cout << fNumberOfRTTMeasurements;
1317 else if (keyword == "NoOfRecACKs
") {
1318 std::cout << fNumberOfReceivedACKs;
1325 // -------------------- TCP_Receiver_Buffer ----------------------------------------
1326 TCP_Receiver_Buffer::TCP_Receiver_Buffer() :
1332 TCP_Receiver_Buffer::TCP_Receiver_Buffer(const TCP_Receiver_Buffer & rhs) :
1333 fFirstByte(rhs.fFirstByte),
1334 fBufList(rhs.fBufList)
1339 void TCP_Receiver_Buffer::reset()
1346 TCP_Receiver_Buffer::~TCP_Receiver_Buffer()
1351 void TCP_Receiver_Buffer::write(TCP_Segment newBlock)
1354 it_assert(newBlock.begin() <= newBlock.end(), "TCP_Receiver_Buffer::Write, no valid segment
");
1356 // cut blocks beginning before fFirstByte
1357 if (newBlock.begin() < fFirstByte) {
1358 if (newBlock.end() > fFirstByte) {
1359 newBlock.set_begin(fFirstByte);
1362 return; //// TODO: Is this strange?
1366 if (newBlock.length() == 0) { // empty block, nothing to do
1370 if (fBufList.empty() || (newBlock.begin() > fBufList.back().end())) {
1371 // new block is behind last block in buffer
1372 fBufList.push_back(newBlock);
1375 // skip list entries if beginning of newBlock > end of current one
1376 // (search for correct list position)
1377 std::list<TCP_Segment>::iterator iter;
1378 iter = fBufList.begin();
1379 while (newBlock.begin() > iter->end()) {
1381 it_assert(iter != fBufList.end(), "TCP_Receiver_Buffer::Write,
internal error
");
1384 TCP_Segment & exBlock = *iter;
1386 if (exBlock.can_be_combined(newBlock)) {
1387 // overlapping or contiguous blocks -> combine
1388 exBlock.combine(newBlock);
1390 // check following blocks
1392 while ((iter != fBufList.end()) &&
1393 exBlock.can_be_combined(*iter)) {
1394 exBlock.combine(*iter);
1395 iter = fBufList.erase(iter);
1399 // no overlap, newBlock lies between two existing list entries
1400 // new list entry has to be created
1402 fBufList.insert(iter, newBlock);
1406 it_assert(!fBufList.empty() && fBufList.front().begin() >= fFirstByte, "TCP_Receiver_Buffer::Write,
internal error
");
1411 // The amount of data read from the buffer is given as parameter. It has
1412 // to be less than or equal to the size of the first block stored. This
1413 // mean the caller of Read should first check how much data is available
1414 // by calling FirstBlockSize.
1415 void TCP_Receiver_Buffer::read(unsigned noOfBytes)
1417 it_assert(first_block_size() > 0, "TCP_Receiver_Buffer::Read, No block
to read
");
1418 it_assert(noOfBytes <= first_block_size(), "TCP_Receiver_Buffer::Read, submitted block
size not valid
");
1421 if (noOfBytes < first_block_size()) {
1422 fBufList.front().set_begin(fBufList.front().begin() + noOfBytes);
1424 else { // first block will be read completely
1425 fBufList.pop_front();
1427 fFirstByte += noOfBytes;
1429 it_assert(fBufList.empty() || fBufList.front().begin() >= fFirstByte, "TCP_Receiver_Buffer::Read,
internal error
");
1433 // FirstBlockSize returns the size of the first block stored in the
1434 // buffer or 0 if the buffer is empty
1435 unsigned TCP_Receiver_Buffer::first_block_size() const
1437 if (!fBufList.empty() && (fBufList.front().begin() == fFirstByte)) {
1438 return fBufList.front().length();
1446 std::ostream & TCP_Receiver_Buffer::info(std::ostream &os, int detail) const
1448 os << "receiver buffer information
" << std::endl
1449 << "number of blocks:
" << fBufList.size() << std::endl
1450 << "first byte stored:
" << fFirstByte << std::endl
1451 << "last byte stored +1:
" << last_byte() << std::endl
1452 << "next byte expected:
" << next_expected() << std::endl;
1455 os << "segments in receiver buffer:
" << std::endl;
1457 typedef std::list<TCP_Segment>::const_iterator LI;
1458 for (LI i = fBufList.begin(); i != fBufList.end(); ++i) {
1459 const TCP_Segment & block = *i;
1460 os << ". segment:
" << block << std::endl;
1469 // -------------------- TCP_Receiver ----------------------------------------
1470 TCP_Receiver::TCP_Receiver(int label) :
1473 fTCPIPHeaderLength(TCP_HEADERLENGTH),
1475 fBufferSize(TCP_BUFFERSIZE),
1476 fDelayedACK(TCP_DELAYEDACK),
1477 fACKDelayTime(TCP_ACKDELAYTIME),
1478 fSendPeriodicACKs(TCP_SENDPERIODICACKS),
1479 fStrictPeriodicACKs(TCP_STRICTPERIODICACKS),
1480 fPeriodicACKInterval(TCP_PERIODICACKINTERVAL),
1481 fACKSchedulingDelay(TCP_ACKSCHEDULINGDELAY),
1482 fACKOnBufferWrite(TCP_ACKBUFFERWRITE),
1483 fACKOnBufferRead(TCP_ACKBUFFERREAD),
1484 fMaxUserBlockSize(TCP_MAXUSERBLOCKSIZE),
1485 fMinUserBlockSize(TCP_MINUSERBLOCKSIZE),
1486 fUserBlockProcDelay(TCP_USERBLOCKPROCDELAY),
1490 fDelayedACKTimer(*this, &TCP_Receiver::DelayedACKHandler),
1491 fPeriodicACKTimer(*this, &TCP_Receiver::PeriodicACKHandler),
1492 fACKSchedulingTimer(*this, &TCP_Receiver::SendACKMessage),
1494 fUserBlockProcTimer(*this, &TCP_Receiver::HandleEndOfProcessing)
1496 fUserMessage = NULL;
1499 if (!fACKOnBufferRead && !fACKOnBufferWrite) {
1500 // throw(UL_CException("TCP_Receiver::TCP_Receiver
",
1501 // "ACKs must be sent on buffer read or write or both
"));
1506 tcp_receive.forward(this, &TCP_Receiver::ReceiveMessageFromNet);
1507 tcp_receive.set_name("TCP Receive
");
1508 tcp_send_ack.set_name("TCP send ACK
");
1509 tcp_new_data.set_name("TCP New Data
");
1510 tcp_release.forward(this, &TCP_Receiver::release);
1511 tcp_release.set_name("TCP Release
");
1516 TCP_Receiver::~TCP_Receiver()
1518 delete fWaitingACKMsg;
1519 delete fUserMessage;
1523 void TCP_Receiver::set_debug(const bool enable_debug)
1525 fDebug = enable_debug;
1526 tcp_send_ack.set_debug(enable_debug);
1527 tcp_new_data.set_debug();
1530 void TCP_Receiver::set_debug(bool enable_debug, bool enable_signal_debug)
1532 fDebug = enable_debug;
1533 tcp_send_ack.set_debug(enable_signal_debug);
1534 tcp_new_data.set_debug();
1537 void TCP_Receiver::set_trace(const bool enable_trace)
1539 fTrace = enable_trace;
1544 void TCP_Receiver::setup()
1549 if (fSendPeriodicACKs) {
1550 fPeriodicACKTimer.Set(fPeriodicACKInterval);
1553 fReceiverBuffer.reset();
1555 received_seq_num_val.set_size(1000);
1556 received_seq_num_val.zeros();
1557 received_seq_num_time.set_size(1000);
1558 received_seq_num_time.zeros();
1559 received_seq_num_val(0) = 0;
1560 received_seq_num_time(0) = 0;
1561 received_seq_num_index = 1;
1564 std::string TCP_Receiver::GenerateFilename()
1568 struct tm *timeinfo;
1569 timeinfo = localtime(&rawtime);
1572 struct tm _timeinfo;
1573 struct tm *timeinfo = &_timeinfo;
1574 localtime_s(timeinfo, &rawtime);
1576 std::ostringstream filename_stream;
1577 filename_stream << "trace_tcp_receiver_u
" << fLabel
1578 << "_
" << 1900 + timeinfo->tm_year
1579 << "_
" << timeinfo->tm_mon
1580 << "_
" << timeinfo->tm_mday
1581 << "__
" << timeinfo->tm_hour
1582 << "_
" << timeinfo->tm_min
1583 << "_
" << timeinfo->tm_sec
1585 return filename_stream.str();
1588 void TCP_Receiver::release(std::string file)
1590 std::string filename;
1593 if (fWaitingACKMsg != 0) {
1594 delete fWaitingACKMsg;
1597 if (fUserMessage != 0) {
1598 delete fUserMessage;
1602 fUserBlockProcTimer.Reset();
1603 fDelayedACKTimer.Reset();
1604 fPeriodicACKTimer.Reset();
1605 fACKSchedulingTimer.Reset();
1609 filename = GenerateFilename();
1613 save_trace(filename);
1618 void TCP_Receiver::ReceiveMessageFromNet(itpp::Packet *msg)
1620 TCP_Packet & packet = (TCP_Packet &) * msg;
1621 if (packet.get_destination_port() == fLabel) {
1622 if (packet.get_session_id() == fSessionId) {
1623 ReceiveDataPacket(packet);
1626 it_warning("Received a TCP packet with wrong SessionId
");
1627 std::cout << "TCP_Receiver::ReceiveMessageFromNet,
"
1628 << "fLabel=
" << fLabel
1629 << "fSessionId=
" << fSessionId << std::endl;
1630 std::cout << "packet=
" << packet
1631 << ", next
exp. =
" << fReceiverBuffer.next_expected()
1637 it_warning("Received a TCP packet with label
");
1643 void TCP_Receiver::ReceiveDataPacket(TCP_Packet &msg)
1645 TCP_Segment segment = msg.get_segment();
1647 bool isOutOfOrder = (segment.begin() > fReceiverBuffer.next_expected()) ||
1648 (segment.end() <= fReceiverBuffer.next_expected());
1651 std::cout << "TCP_Receiver::ReceiveDataPacket receiver:
" << fLabel << ":
"
1653 << "t =
" << Event_Queue::now()
1654 << ", next
exp. =
" << fReceiverBuffer.next_expected()
1655 << ",
" << msg << std::endl;
1659 TraceReceivedSeqNo(segment.end());
1662 it_assert(segment.end() <= fReceiverBuffer.first_byte() + fBufferSize, "TCP_Receiver::ReceiveTCPPacket, packet exceeds window at
");
1663 it_assert(segment.begin() < segment.end(), "TCP_Receiver::ReceiveTCPPacket, silly packet received at
");
1665 fReceiverBuffer.write(segment);
1668 SendACK(true); // create dupack conditionless
1671 if (fACKOnBufferWrite) {
1674 IndicateUserMessage();
1681 void TCP_Receiver::IndicateUserMessage()
1683 if (fUserMessage == 0) {
1685 unsigned noOfBytes = min(fReceiverBuffer.first_block_size(),
1689 std::cout << "TCP_Receiver::IndicateUserMessage
"
1690 << "t =
" << Event_Queue::now()
1691 << " noOfBytes =
" << noOfBytes
1692 << " firstBlock =
" << fReceiverBuffer.first_block_size()
1696 if (noOfBytes >= fMinUserBlockSize) {
1697 fUserMessage = new Packet();
1698 fUserMessage->set_bit_size(8*noOfBytes);
1699 fUserBlockProcTimer.Set(fUserBlockProcDelay);
1705 bool TCP_Receiver::is_user_message_available()
1707 if (fUserMessage != 0) {
1711 unsigned noOfBytes = min(fReceiverBuffer.first_block_size(),
1714 if (noOfBytes >= fMinUserBlockSize) {
1715 fUserMessage = new Packet();
1716 fUserMessage->set_bit_size(8*noOfBytes);
1725 itpp::Packet & TCP_Receiver::get_user_message()
1727 it_assert(fUserMessage != 0, "TCP_Receiver::GetUserMessage, no message available
");
1729 std::cout << "TCP_Receiver::GetUserMessage
"
1730 << "receiver:
" << fLabel << ":
"
1731 << "read from buffer:
"
1732 << "t =
" << Event_Queue::now()
1733 << ", user msg
length =
" << (fUserMessage->bit_size() / 8)
1734 << ", first byte =
" << fReceiverBuffer.first_byte()
1735 << ", first block
size =
" << fReceiverBuffer.first_block_size()
1739 fReceiverBuffer.read(fUserMessage->bit_size() / 8);
1740 if (fACKOnBufferRead) {
1741 SendACK(false); // send acknowledgement
1744 itpp::Packet & msg = *fUserMessage;
1747 if (fReceiverBuffer.first_block_size() > 0) {
1748 IndicateUserMessage();
1756 void TCP_Receiver::HandleEndOfProcessing(Ttype)
1758 it_assert(fUserMessage != 0, "TCP_Receiver::HandleEndOfProcessing, no message available
");
1761 tcp_new_data(fLabel);
1765 void TCP_Receiver::DelayedACKHandler(Ttype)
1768 std::cout << "TCP_Receiver::DelayedACKHandler
"
1769 << "receiver
" << fLabel
1771 << "t =
" << Event_Queue::now() << std::endl;
1778 void TCP_Receiver::PeriodicACKHandler(Ttype)
1781 std::cout << "TCP_Receiver::PeriodicACKHandler
"
1782 << "receiver
" << fLabel
1783 << ": periodicACK TO:
"
1784 << "t =
" << Event_Queue::now() << std::endl;
1791 void TCP_Receiver::SendACK(bool sendConditionless)
1793 // sendConditionless is set
1794 // ... if packet was received out of order or
1795 // ... if delayed ACK timer has expired
1797 // Bei eingeschaltetem "delayed ACK
" wird ein ACK nur
1798 // gesendet, wenn das Fenster um 2MSS oder 35% der
1799 // maximalen Fenstergroesse verschoben worden ist
1800 // ... oder nach delayed ACK Timeout
1801 // ... oder wenn es das ACK fur ein Out of Order Segment ist
1802 // ... oder (in der Realitat), wenn ich auch was zu senden habe.
1804 if (sendConditionless || !fDelayedACK ||
1805 (fReceiverBuffer.next_expected() - fAdvRcvNxt >= (int)(2 * fMSS)) ||
1806 (fReceiverBuffer.next_expected() - fAdvRcvNxt >=
1807 (int)(0.35 * fBufferSize))) {
1808 // Remark: RFC2581 recommends to acknowledge every second
1809 // packet conditionless (without setting this as a requirement)
1810 // in order to avoid excessive ack delays when the receiver MSS
1811 // is larger than the sender MSS. In this uni-directional
1812 // implementation, the receiver's MSS is not actively
1813 // used for sending but only for deciding when acknowledgments
1814 // have to be returned. Thus, the best solution to account for
1815 // RFC2581 is to set the receiver's MSS always equal to the
1818 // Receiver Silly Window Syndrome Avoidance:
1820 if (fAdvRcvNxt + fAdvRcvWnd + min(fBufferSize / 2, fMSS)
1821 <= fReceiverBuffer.first_byte() + fBufferSize) {
1822 // Die rechte Grenze des Empfangerfensters wird nur anders angezeigt
1823 // als beim letzten ACK, wenn sie sich seither um mindestens
1824 // min (BufferSize/ 2, MSS) geandert hat.
1825 fAdvRcvWnd = fBufferSize - fReceiverBuffer.first_block_size();
1828 fAdvRcvWnd = fAdvRcvNxt + fAdvRcvWnd - fReceiverBuffer.next_expected();
1831 fAdvRcvNxt = fReceiverBuffer.next_expected();
1833 if (fSendPeriodicACKs &&
1834 (!fStrictPeriodicACKs || !fPeriodicACKTimer.IsPending())) {
1835 fPeriodicACKTimer.Set(fPeriodicACKInterval);
1838 if (fDelayedACK && fDelayedACKTimer.IsPending()) {
1839 fDelayedACKTimer.Reset();
1842 ScheduleACKMessage();
1845 if (!fDelayedACKTimer.IsPending()) {
1846 fDelayedACKTimer.Set(fACKDelayTime);
1848 std::cout << "TCP_Receiver::SendACK
"
1849 << "receiver
" << fLabel
1850 << ":
set delACK timer:
"
1851 << "t =
" << Event_Queue::now() << std::endl;
1858 void TCP_Receiver::ScheduleACKMessage()
1860 if (fWaitingACKMsg == 0) {
1861 fWaitingACKMsg = new TCP_Packet;
1864 fWaitingACKMsg->set_ACK(fAdvRcvNxt);
1865 fWaitingACKMsg->set_wnd(fAdvRcvWnd);
1866 fWaitingACKMsg->set_session_id(fSessionId);
1867 fWaitingACKMsg->set_destination_port(fLabel);
1868 fWaitingACKMsg->set_source_port(fLabel);
1869 fWaitingACKMsg->set_bit_size(8*fTCPIPHeaderLength);
1871 if (fACKSchedulingDelay > 0) {
1872 if (!fACKSchedulingTimer.IsPending()) {
1873 fACKSchedulingTimer.Set(fACKSchedulingDelay);
1877 SendACKMessage(Event_Queue::now());
1882 void TCP_Receiver::SendACKMessage(Ttype)
1884 it_assert(fWaitingACKMsg != 0, "TCP_Receiver::SendACKMessage, no ACK message waiting
");
1887 std::cout << "TCP_Receiver::SendACKMessage Ack sent
"
1888 << "receiver
" << fLabel
1890 << "t =
" << Event_Queue::now()
1891 << ",
" << (*fWaitingACKMsg)
1892 << " byte_size=
" << fWaitingACKMsg->bit_size() / 8
1893 << " ptr=
" << fWaitingACKMsg << std::endl;
1896 tcp_send_ack(fWaitingACKMsg);
1902 void TCP_Receiver::TraceReceivedSeqNo(const Sequence_Number &sn)
1905 std::cout << "TCP_Receiver::TraceReceivedSeqNo
"
1906 << "receiver
" << fLabel
1907 << " t =
" << Event_Queue::now()
1908 << " sn =
" << sn << std::endl;
1910 if (received_seq_num_index >= received_seq_num_time.size()) {
1911 received_seq_num_time.set_size(2*received_seq_num_time.size(), true);
1912 received_seq_num_val.set_size(2*received_seq_num_val.size(), true);
1914 received_seq_num_val(received_seq_num_index) = sn.value();
1915 received_seq_num_time(received_seq_num_index) = Event_Queue::now();
1916 received_seq_num_index++;
1920 void TCP_Receiver::save_trace(std::string filename)
1923 received_seq_num_val.set_size(received_seq_num_index, true);
1924 received_seq_num_time.set_size(received_seq_num_index, true);
1927 std::cout << "received_seq_num_val
" << received_seq_num_val << std::endl;
1928 std::cout << "received_seq_num_time
" << received_seq_num_time << std::endl;
1929 std::cout << "received_seq_num_index
" << received_seq_num_index << std::endl;
1930 std::cout << "TCP_Receiver::saving
to file:
" << filename << std::endl;
1936 ff2 << Name("received_seq_num_val
") << received_seq_num_val;
1937 ff2 << Name("received_seq_num_time
") << received_seq_num_time;
1938 ff2 << Name("received_seq_num_index
") << received_seq_num_index;
1948 #pragma warning(default:4355)