27#include "TCP_Header.h"
38double calculate_RTO(
double R,
49 rto = *srtt + max(G, K*(*rtt_var));
53 *rtt_var = (1 - beta) * (*rtt_var) + beta * fabs(*srtt - R);
54 *srtt = (1 - alpha) * (*srtt) + alpha * R;
55 rto = *srtt + max(G, K*(*rtt_var));
57 return min(max(rto, G), (60 * SECOND));
60static void Backoff_RTO(
double* rto)
62 *rto = min(max((*rto*2), G), (60 * SECOND));
63 print_tcp_log(
"New RTO = %0.2lf", *rto);
66void add_timeout_event(PNETSIM_SOCKET s,
67 NetSim_PACKET* packet)
69 NetSim_PACKET* p = fn_NetSim_Packet_CopyPacket(packet);
70 add_packet_to_queue(&s->tcb->retransmissionQueue, p, pstruEventDetails->dEventTime);
71 if (s->tcb->isRTOTimerRunning)
return;
72 s->tcb->isRTOTimerRunning =
true;
73 NetSim_EVENTDETAILS pevent;
74 memcpy(&pevent, pstruEventDetails,
sizeof pevent);
75 pevent.dEventTime += TCP_RTO(s->tcb);
76 pevent.dPacketSize = packet->pstruTransportData->dPacketSize;
77 pevent.nEventType = TIMER_EVENT;
78 pevent.nPacketId = packet->nPacketId;
79 if (packet->pstruAppData)
81 pevent.nApplicationId = packet->pstruAppData->nApplicationId;
82 pevent.nSegmentId = packet->pstruAppData->nSegmentId;
85 pevent.nSegmentId = 0;
86 pevent.nProtocolId = TX_PROTOCOL_TCP;
87 pevent.pPacket = fn_NetSim_Packet_CopyPacket(p);
88 pevent.szOtherDetails = NULL;
89 pevent.nSubEventType = TCP_RTO_TIMEOUT;
90 s->tcb->RTOEventId = fnpAddEvent(&pevent);
91 s->tcb->eventPacketptr = pevent.pPacket;
92 print_tcp_log(
"Adding RTO Timer at %0.1lf", pevent.dEventTime);
95static void handle_rto_timer_for_ctrl(PNETSIM_SOCKET s)
97 if (isSynbitSet(pstruEventDetails->pPacket))
100 fnNetSimError(
"Unknown packet %d arrives at %s\n",
101 pstruEventDetails->pPacket->nControlDataType,
104void handle_rto_timer()
106 PNETSIM_SOCKET s = find_socket_at_source(pstruEventDetails->pPacket);
110 fn_NetSim_Packet_FreePacket(pstruEventDetails->pPacket);
113 if (!s->tcb || s->tcb->isOtherTimerCancel)
115 fn_NetSim_Packet_FreePacket(pstruEventDetails->pPacket);
119 s->tcb->isRTOTimerRunning =
false;
120 bool isPresent = isAnySegmentInQueue(&s->tcb->retransmissionQueue);
124 NetSim_PACKET* segment = get_earliest_copy_segment_from_queue(&s->tcb->retransmissionQueue);
126 print_tcp_log(
"\nDevice %d, Time %0.2lf: RTO Time expire.",
127 pstruEventDetails->nDeviceId,
128 pstruEventDetails->dEventTime);
130 s->tcpMetrics->timesRTOExpired++;
132 Backoff_RTO(&TCP_RTO(s->tcb));
134 if (isTCPControl(segment))
136 handle_rto_timer_for_ctrl(s);
141 s->tcb->rto_expired(s);
143 resend_segment(s, segment);
146 fn_NetSim_Packet_FreePacket(segment);
152 fn_NetSim_Packet_FreePacket(pstruEventDetails->pPacket);
155void restart_rto_timer(PNETSIM_SOCKET s)
157 fnDeleteEvent(s->tcb->RTOEventId);
158 fn_NetSim_Packet_FreePacket(s->tcb->eventPacketptr);
159 s->tcb->eventPacketptr = NULL;
160 s->tcb->isRTOTimerRunning =
false;
162 bool isPresent = isAnySegmentInQueue(&s->tcb->retransmissionQueue);
165 s->tcb->isRTOTimerRunning =
true;
166 NetSim_PACKET* segment = get_earliest_copy_segment_from_queue(&s->tcb->retransmissionQueue);
167 NetSim_EVENTDETAILS pevent;
168 memcpy(&pevent, pstruEventDetails,
sizeof pevent);
169 pevent.dEventTime += TCP_RTO(s->tcb);
170 pevent.dPacketSize = segment->pstruTransportData->dPacketSize;
171 pevent.nEventType = TIMER_EVENT;
172 pevent.nPacketId = segment->nPacketId;
173 if (segment->pstruAppData)
175 pevent.nApplicationId = segment->pstruAppData->nApplicationId;
176 pevent.nSegmentId = segment->pstruAppData->nSegmentId;
179 pevent.nSegmentId = 0;
180 pevent.nProtocolId = TX_PROTOCOL_TCP;
181 pevent.pPacket = segment;
182 pevent.szOtherDetails = NULL;
183 pevent.nSubEventType = TCP_RTO_TIMEOUT;
184 s->tcb->RTOEventId = fnpAddEvent(&pevent);
185 s->tcb->eventPacketptr = segment;
186 print_tcp_log(
"Adding RTO Timer at %0.1lf", pevent.dEventTime);