16#include "TCP_Header.h"
18static UINT get_max_sack_data(PTCP_SEGMENT_HDR hdr)
20 return (MAX_TCP_HDR_SIZE - hdr->HdrLength - SACK_OPTION_FIX_LEN) / SACKDATA_LEN;
23UINT32 get_highAck(PNETSIM_SOCKET s)
25 return s->tcb->SND.UNA;
28static UINT32 get_highData(PNETSIM_SOCKET s)
30 return s->tcb->SND.NXT;
33static UINT32 get_highRxt(PNETSIM_SOCKET s)
35 return s->tcb->HighRxt;
38void set_highRxt(PNETSIM_SOCKET s, UINT32 seq)
40 s->tcb->HighRxt = max(s->tcb->HighRxt, seq);
43static UINT32 get_rescueRxt(PNETSIM_SOCKET s)
45 return s->tcb->RescueRxt;
48void set_rescueRxt(PNETSIM_SOCKET s, UINT32 seq)
50 s->tcb->RescueRxt = max(s->tcb->RescueRxt, seq);
53void set_recoveryPoint(PNETSIM_SOCKET s, UINT32 val)
55 s->tcb->recoveryPoint = val;
58UINT32 get_recoveryPoint(PNETSIM_SOCKET s)
60 return s->tcb->recoveryPoint;
63UINT32 get_pipe(PNETSIM_SOCKET s)
68void set_sack_option(PNETSIM_SOCKET s, PTCP_SEGMENT_HDR hdr,
double time)
74 if (!s->tcb->isSackPermitted)
77 if (!s->tcb->outOfOrderSegment.size)
80 maxData = get_max_sack_data(hdr);
85 PSACK_OPTION sack = (PSACK_OPTION)calloc(1,
sizeof* sack);
86 sack->type = TCP_OPTION_SACK;
88 PQueueInfo queue = s->tcb->outOfOrderSegment.queue;
90 PSACKDATA* sackData = calloc(1,
sizeof *sackData);;
95 PTCP_SEGMENT_HDR h = TCP_GET_SEGMENT_HDR(queue->packet);
98 if (h->SeqNum == lastSeq + len)
100 len = get_seg_len(queue->packet);
101 sackData[i]->rightEdge = h->SeqNum + len;
104 else if (i < maxData - 1)
107 len = get_seg_len(queue->packet);
108 sackData = (PSACKDATA*)realloc(sackData, (i + 1) *
sizeof* sackData);
109 sackData[i] = (PSACKDATA)calloc(1,
sizeof* sackData[i]);
110 sackData[i]->leftEdge = h->SeqNum;
111 sackData[i]->rightEdge = h->SeqNum + len;
119 else if (i < maxData)
121 len = get_seg_len(queue->packet);
122 sackData[i] = (PSACKDATA)calloc(1,
sizeof* sackData[i]);
123 sackData[i]->leftEdge = h->SeqNum;
124 sackData[i]->rightEdge = h->SeqNum + len;
135 sack->sackData = sackData;
136 sack->len = SACK_OPTION_LEN(i + 1);
138 set_tcp_option(hdr, sack, TCP_OPTION_SACK, sack->len);
141static void update_sack_flag(PNETSIM_SOCKET s, UINT32 left, UINT32 right)
143 PQueueInfo queue = s->tcb->retransmissionQueue.queue;
146 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(queue->packet);
147 if (hdr->SeqNum >= left && hdr->SeqNum <= right)
148 queue->isSacked =
true;
153static void update_scoreboard(PNETSIM_SOCKET s, UINT left, UINT right, UINT index)
157 memcpy(&s->tcb->prevScoreboard, &s->tcb->scoreboard,
sizeof s->tcb->prevScoreboard);
159 s->tcb->scoreboard.leftEdge[index] = left;
160 s->tcb->scoreboard.rightEdge[index] = right;
171bool tcp_sack_isLost(PNETSIM_SOCKET s, UINT seqNum)
174 UINT SMSS = s->tcb->get_MSS(s);
175 UINT check = seqNum + SMSS;
177 if (s->tcb->scoreboard.leftEdge[0] >= check)
181 for (i = 0; i < 4; i++)
183 c += (s->tcb->scoreboard.rightEdge[i] - s->tcb->scoreboard.leftEdge[i]) / SMSS;
184 if (c >= TCP_DupThresh)
186 if (s->tcb->scoreboard.rightEdge[i] > (TCP_DupThresh - 1)*SMSS + seqNum)
193void tcp_sack_setPipe(PNETSIM_SOCKET s)
195 UINT32 highAck = get_highAck(s);
196 UINT32 highData = get_highData(s);
197 UINT32 highRxt = get_highRxt(s);
199 UINT SMSS = s->tcb->get_MSS(s);
202 for (s1 = highAck; s1 < highData; s1 += SMSS)
204 if (!tcp_sack_isLost(s, s1))
205 s->tcb->pipe += SMSS;
208 s->tcb->pipe += SMSS;
212UINT32 tcp_sack_nextSeg(PNETSIM_SOCKET s)
216 UINT32 highRxt = get_highRxt(s);
217 PQueueInfo queue = s->tcb->retransmissionQueue.queue;
223 if (!queue->isSacked)
225 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
228 tcp_sack_isLost(s, s2))
230 PQueueInfo q = queue->next;
243 UINT32 seq = s->tcb->SND.NXT;
244 p = fn_NetSim_Socket_GetPacketFromInterface(s->sId, 0);
245 s->tcb->SND.WND = s->tcb->get_WND(s);
248 UINT32 l = (UINT32)p->pstruAppData->dPacketSize;
249 if (seq + l <= s->tcb->SND.WND + s->tcb->SND.UNA)
250 return s->tcb->SND.NXT;
254 queue = s->tcb->retransmissionQueue.queue;
260 if (!queue->isSacked)
262 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
266 PQueueInfo q = queue->next;
281void receive_sack_option(PNETSIM_SOCKET s, PTCP_SEGMENT_HDR hdr)
283 s->tcb->isSackOption =
false;
285 if (!s->tcb->isSackPermitted)
288 PSACK_OPTION sack = get_tcp_option(hdr, TCP_OPTION_SACK);
292 UINT c = get_sack_data_count(sack);
297 s->tcb->isSackOption =
true;
300 for (i = 0; i < c; i++)
302 PSACKDATA data = sack->sackData[i];
303 UINT32 left = data->leftEdge;
304 UINT32 right = data->rightEdge;
305 update_sack_flag(s, left, right);
306 update_scoreboard(s, left, right, i);
310 update_scoreboard(s, 0, 0, i);
313void tcp_sack_fastRetransmit(PNETSIM_SOCKET s)
315 if (s->tcb->isSackOption)
317 set_recoveryPoint(s, get_highData(s));
322bool tcp_sack_lossRecoveryPhase(PNETSIM_SOCKET s)
324 if (s->tcb->SEG.ACK > s->tcb->recoveryPoint)
330 UINT32 wnd = s->tcb->get_WND(s);
331 UINT32 pipe = get_pipe(s);
332 UINT32 mss = s->tcb->get_MSS(s);
334 while (wnd >= mss + pipe)
336 UINT32 nextSeg = tcp_sack_nextSeg(s);
339 UINT32 highData = get_highData(s);
340 if (nextSeg < highData)
342 resend_segment_without_timeout(s, nextSeg);
343 set_highRxt(s, nextSeg);
348 UINT32 prev = s->tcb->SND.NXT;
350 len = s->tcb->SND.NXT - prev;