NetSim Source Code Help
Loading...
Searching...
No Matches
SACK.c
Go to the documentation of this file.
1/************************************************************************************
2* Copyright (C) 2020 *
3* TETCOS, Bangalore. India *
4* *
5* Tetcos owns the intellectual property rights in the Product and its content. *
6* The copying, redistribution, reselling or publication of any or all of the *
7* Product or its content without express prior written consent of Tetcos is *
8* prohibited. Ownership and / or any other right relating to the software and all *
9* intellectual property rights therein shall remain at all times with Tetcos. *
10* *
11* Author: Shashi Kant Suman *
12* *
13* ---------------------------------------------------------------------------------*/
14#include "main.h"
15#include "TCP.h"
16#include "TCP_Header.h"
17
19{
21}
22
24{
25 return s->tcb->SND.UNA;
26}
27
29{
30 return s->tcb->SND.NXT;
31}
32
34{
35 return s->tcb->HighRxt;
36}
37
39{
40 s->tcb->HighRxt = max(s->tcb->HighRxt, seq);
41}
42
44{
45 return s->tcb->RescueRxt;
46}
47
49{
50 s->tcb->RescueRxt = max(s->tcb->RescueRxt, seq);
51}
52
54{
55 s->tcb->recoveryPoint = val;
56}
57
59{
60 return s->tcb->recoveryPoint;
61}
62
64{
65 return s->tcb->pipe;
66}
67
69{
70 UINT maxData;
71 UINT i=0;
72
73 if (!s->tcb->isSackPermitted)
74 return; // Sack is not permitted
75
76 if (!s->tcb->outOfOrderSegment.size)
77 return; // Sack option is not required as no out of order segment.
78
79 maxData = get_max_sack_data(hdr);
80
81 if (!maxData)
82 return; // No space is left in TCP header
83
84 PSACK_OPTION sack = (PSACK_OPTION)calloc(1, sizeof* sack);
85 sack->type = TCP_OPTION_SACK;
86
88
89 PSACKDATA* sackData = calloc(1, sizeof *sackData);;
90 UINT len = 0;
91 UINT32 lastSeq = 0;
92 while (queue)
93 {
95 if (lastSeq)
96 {
97 if (h->SeqNum == lastSeq + len)
98 {
99 len = get_seg_len(queue->packet);
100 sackData[i]->rightEdge = h->SeqNum + len;
101 lastSeq = h->SeqNum;
102 }
103 else if (i < maxData - 1)
104 {
105 i++;
106 len = get_seg_len(queue->packet);
107 sackData = (PSACKDATA*)realloc(sackData, (i + 1) * sizeof* sackData);
108 sackData[i] = (PSACKDATA)calloc(1, sizeof* sackData[i]);
109 sackData[i]->leftEdge = h->SeqNum;
110 sackData[i]->rightEdge = h->SeqNum + len;
111 lastSeq = h->SeqNum;
112 }
113 else
114 {
115 break; // Reached Max Sack Data count
116 }
117 }
118 else if (i < maxData)
119 {
120 len = get_seg_len(queue->packet);
121 sackData[i] = (PSACKDATA)calloc(1, sizeof* sackData[i]);
122 sackData[i]->leftEdge = h->SeqNum;
123 sackData[i]->rightEdge = h->SeqNum + len;
124 lastSeq = h->SeqNum;
125 }
126 else
127 {
128 break; // Reached Max Sack Data count
129 }
130
131 queue = queue->next;
132 }
133
134 sack->sackData = sackData;
135 sack->len = SACK_OPTION_LEN(i + 1);
136
137 set_tcp_option(hdr, sack, TCP_OPTION_SACK, sack->len);
138}
139
140static void update_sack_flag(PNETSIM_SOCKET s, UINT32 left, UINT32 right)
141{
143 while (queue)
144 {
146 if (hdr->SeqNum >= left && hdr->SeqNum <= right)
147 queue->isSacked = true;
148 queue = queue->next;
149 }
150}
151
152static void update_scoreboard(PNETSIM_SOCKET s, UINT left, UINT right, UINT index)
153{
154 //Store current to prev
155 if (!index)
156 memcpy(&s->tcb->prevScoreboard, &s->tcb->scoreboard, sizeof s->tcb->prevScoreboard);
157
158 s->tcb->scoreboard.leftEdge[index] = left;
159 s->tcb->scoreboard.rightEdge[index] = right;
160}
161
162/*
163This routine returns whether the given sequence number is
164considered to be lost. The routine returns true when either
165DupThresh discontiguous SACKed sequences have arrived above
166'SeqNum' or more than (DupThresh - 1) * SMSS bytes with sequence
167numbers greater than 'SeqNum' have been SACKed. Otherwise, the
168routine returns false.
169*/
171{
172 UINT i;
173 UINT SMSS = s->tcb->get_MSS(s);
174 UINT check = seqNum + SMSS;
175
176 if (s->tcb->scoreboard.leftEdge[0] >= check)
177 {
178 UINT c = 0;
179 //Discontinuous
180 for (i = 0; i < 4; i++)
181 {
182 c += (s->tcb->scoreboard.rightEdge[i] - s->tcb->scoreboard.leftEdge[i]) / SMSS;
183 if (c >= TCP_DupThresh)
184 return true;
185 if (s->tcb->scoreboard.rightEdge[i] > (TCP_DupThresh - 1)*SMSS + seqNum)
186 return true;
187 }
188 }
189 return false;
190}
191
193{
194 UINT32 highAck = get_highAck(s);
195 UINT32 highData = get_highData(s);
196 UINT32 highRxt = get_highRxt(s);
197 s->tcb->pipe = 0;
198 UINT SMSS = s->tcb->get_MSS(s);
199 UINT32 s1;
200
201 for (s1 = highAck; s1 < highData; s1 += SMSS)
202 {
203 if (!tcp_sack_isLost(s, s1))
204 s->tcb->pipe += SMSS;
205
206 if (s1 <= highRxt)
207 s->tcb->pipe += SMSS;
208 }
209}
210
212{
213 NetSim_PACKET* p;
214 UINT32 s2;
215 UINT32 highRxt = get_highRxt(s);
217 while (queue)
218 {
219 p = queue->packet;
220
221 //Rule 1
222 if (!queue->isSacked)
223 {
225 s2 = hdr->SeqNum;
226 if (s2 > highRxt &&
227 tcp_sack_isLost(s, s2))
228 {
229 PQueueInfo q = queue->next;
230 while (q)
231 {
232 if (q->isSacked)
233 return s2;
234 q = q->next;
235 }
236 }
237 }
238 queue = queue->next;
239 }
240
241 //Rule 2
242 UINT32 seq = s->tcb->SND.NXT;
244 s->tcb->SND.WND = s->tcb->get_WND(s);
245 if (p)
246 {
248 if (seq + l <= s->tcb->SND.WND + s->tcb->SND.UNA)
249 return s->tcb->SND.NXT;
250 }
251
252 //Rule 3
253 queue = s->tcb->retransmissionQueue.queue;
254 while (queue)
255 {
256 p = queue->packet;
257
258 //Rule 1
259 if (!queue->isSacked)
260 {
262 s2 = hdr->SeqNum;
263 if (s2 > highRxt)
264 {
265 PQueueInfo q = queue->next;
266 while (q)
267 {
268 if (q->isSacked)
269 return s2;
270 q = q->next;
271 }
272 }
273 }
274 queue = queue->next;
275 }
276
277 return 0;
278}
279
281{
282 s->tcb->isSackOption = false;
283
284 if (!s->tcb->isSackPermitted)
285 return; // Sack is not permitted
286
288 if (!sack)
289 return; // No sack option is present
290
291 UINT c = get_sack_data_count(sack);
292
293 if (!c)
294 return; //No sack data present
295
296 s->tcb->isSackOption = true;
297
298 UINT i;
299 for (i = 0; i < c; i++)
300 {
301 PSACKDATA data = sack->sackData[i];
302 UINT32 left = data->leftEdge;
303 UINT32 right = data->rightEdge;
304 update_sack_flag(s, left, right);
305 update_scoreboard(s, left, right, i);
306 }
307
308 for(;i<4;i++)
309 update_scoreboard(s, 0, 0, i);
310}
311
313{
314 if (s->tcb->isSackOption)
315 {
318 }
319}
320
322{
323 if (s->tcb->SEG.ACK > s->tcb->recoveryPoint)
324 return false; //End loss recovery phase
325 else
326 {
328
329 UINT32 wnd = s->tcb->get_WND(s);
330 UINT32 pipe = get_pipe(s);
331 UINT32 mss = s->tcb->get_MSS(s);
332
333 while (wnd >= mss + pipe)
334 {
335 UINT32 nextSeg = tcp_sack_nextSeg(s);
336 if (nextSeg)
337 {
338 UINT32 highData = get_highData(s);
339 if (nextSeg < highData)
340 {
342 set_highRxt(s, nextSeg);
343 }
344 else
345 {
346 UINT32 len;
347 UINT32 prev = s->tcb->SND.NXT;
348 send_segment(s);
349 len = s->tcb->SND.NXT - prev;
350 pipe += len;
351 s->tcb->pipe += len;
352 }
353 }
354 else
355 {
356 return true;
357 }
358 }
359 return true; //Continue in Loss recovery phase
360 }
361}
#define c
#define UINT
Definition: Linux.h:38
#define UINT32
Definition: Linux.h:35
#define max(a, b)
Definition: Linux.h:107
#define realloc(p, s)
Definition: Memory.h:32
#define calloc(c, s)
Definition: Memory.h:29
static UINT get_max_sack_data(PTCP_SEGMENT_HDR hdr)
Definition: SACK.c:18
bool tcp_sack_lossRecoveryPhase(PNETSIM_SOCKET s)
Definition: SACK.c:321
UINT32 get_highAck(PNETSIM_SOCKET s)
Definition: SACK.c:23
void tcp_sack_fastRetransmit(PNETSIM_SOCKET s)
Definition: SACK.c:312
static UINT32 get_rescueRxt(PNETSIM_SOCKET s)
Definition: SACK.c:43
static UINT32 get_highRxt(PNETSIM_SOCKET s)
Definition: SACK.c:33
UINT32 tcp_sack_nextSeg(PNETSIM_SOCKET s)
Definition: SACK.c:211
void set_rescueRxt(PNETSIM_SOCKET s, UINT32 seq)
Definition: SACK.c:48
void tcp_sack_setPipe(PNETSIM_SOCKET s)
Definition: SACK.c:192
void set_recoveryPoint(PNETSIM_SOCKET s, UINT32 val)
Definition: SACK.c:53
void set_sack_option(PNETSIM_SOCKET s, PTCP_SEGMENT_HDR hdr, double time)
Definition: SACK.c:68
void receive_sack_option(PNETSIM_SOCKET s, PTCP_SEGMENT_HDR hdr)
Definition: SACK.c:280
void set_highRxt(PNETSIM_SOCKET s, UINT32 seq)
Definition: SACK.c:38
static UINT32 get_highData(PNETSIM_SOCKET s)
Definition: SACK.c:28
static void update_scoreboard(PNETSIM_SOCKET s, UINT left, UINT right, UINT index)
Definition: SACK.c:152
bool tcp_sack_isLost(PNETSIM_SOCKET s, UINT seqNum)
Definition: SACK.c:170
UINT32 get_pipe(PNETSIM_SOCKET s)
Definition: SACK.c:63
UINT32 get_recoveryPoint(PNETSIM_SOCKET s)
Definition: SACK.c:58
static void update_sack_flag(PNETSIM_SOCKET s, UINT32 left, UINT32 right)
Definition: SACK.c:140
NetSim_PACKET * fn_NetSim_Socket_GetPacketFromInterface(ptrSOCKETINTERFACE s, int moveFlag)
UINT32 get_seg_len(NetSim_PACKET *p)
Definition: TCB.c:307
void resend_segment_without_timeout(PNETSIM_SOCKET s, UINT seq)
Definition: TCP_Outgoing.c:79
void send_segment(PNETSIM_SOCKET s)
Definition: TCP_Outgoing.c:18
#define TCP_DupThresh
Definition: TCP.h:51
struct stru_sack_data * PSACKDATA
#define get_sack_data_count(sack)
Definition: TCP_Header.h:146
#define SACKDATA_LEN
Definition: TCP_Header.h:136
#define SACK_OPTION_FIX_LEN
Definition: TCP_Header.h:144
#define SACK_OPTION_LEN(n)
Definition: TCP_Header.h:145
void set_tcp_option(PTCP_SEGMENT_HDR hdr, void *option, TCP_OPTION type, UINT32 size)
Definition: TCP_Packet.c:45
struct stru_sack_option * PSACK_OPTION
@ TCP_OPTION_SACK
Definition: TCP_Header.h:43
void * get_tcp_option(PTCP_SEGMENT_HDR hdr, TCP_OPTION type)
Definition: TCP_Packet.c:65
static PTCP_SEGMENT_HDR TCP_GET_SEGMENT_HDR(NetSim_PACKET *packet)
Definition: TCP_Header.h:107
#define MAX_TCP_HDR_SIZE
Definition: TCP_Header.h:105
struct stru_NetSim_Packet_AppLayer * pstruAppData
Definition: Packet.h:273
PTCB tcb
Definition: TCP.h:132
ptrSOCKETINTERFACE sId
Definition: TCP.h:127
UINT32 leftEdge
Definition: TCP_Header.h:133
UINT32 rightEdge
Definition: TCP_Header.h:134
PSACKDATA * sackData
Definition: TCP_Header.h:142
struct stru_tcp_Transmission_Control_Block::stru_sack_scoreboard prevScoreboard
struct stru_tcp_Transmission_Control_Block::stru_tcb_send_seq_var SND
UINT16(* get_MSS)(PNETSIM_SOCKET)
Definition: TCB.h:134
UINT16(* get_WND)(PNETSIM_SOCKET)
Definition: TCB.h:135
struct stru_tcp_Transmission_Control_Block::stru_sack_scoreboard scoreboard
struct stru_tcp_Transmission_Control_Block::stru_tcb_curr_seg_var SEG
UINT32 HdrLength
Definition: TCP_Header.h:90
bool isSacked
Definition: TCB.h:36
NetSim_PACKET * packet
Definition: TCB.h:34
struct stru_tcp_queue_info * next
Definition: TCB.h:37
UINT size
Definition: TCB.h:41
PQueueInfo queue
Definition: TCB.h:42