NetSim Source Code Help v14.4
All 13 Components
 
Loading...
Searching...
No Matches
TCB.c
1/************************************************************************************
2* Copyright (C) 2023 *
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 "List.h"
17#include "TCP_Header.h"
18
19//Function prototype
20static void free_queue(PTCP_QUEUE queue);
21
22
23UINT32 calculate_initial_seq_num(double time)
24{
25 return max(1,(UINT32)(time/4.0));
26}
27
28char* state_to_str(TCP_CONNECTION_STATE state)
29{
30 switch (state)
31 {
32 case TCPCONNECTION_CLOSED:
33 return "Closed";
34 case TCPCONNECTION_LISTEN:
35 return "Listen";
36 case TCPCONNECTION_CLOSE_WAIT:
37 return "Close-Wait";
38 case TCPCONNECTION_CLOSING:
39 return "Closing";
40 case TCPCONNECTION_ESTABLISHED:
41 return "Established";
42 case TCPCONNECTION_FIN_WAIT_1:
43 return "Fin-Wait-1";
44 case TCPCONNECTION_FIN_WAIT_2:
45 return "Fin-wait-2";
46 case TCPCONNECTION_LAST_ACK:
47 return "Last-Ack";
48 case TCPCONNECTION_SYN_RECEIVED:
49 return "Syn-received";
50 case TCPCONNECTION_TIME_WAIT:
51 return "Time-wait";
52 case TCPCONNECTION_SYN_SENT:
53 return "Syn-sent";
54 default:
55 return "Unknown";
56 }
57}
58
59static void set_tcp_variant(PNETSIM_SOCKET s, PTCP_DEV_VAR t)
60{
61 s->tcb->variant = t->tcpVariant;
62 switch (s->tcb->variant)
63 {
64 case TCPVariant_OLDTAHOE:
65 case TCPVariant_TAHOE:
66 case TCPVariant_RENO:
67 case TCPVariant_NEWRENO:
68 case TCPVariant_BIC:
69 case TCPVariant_CUBIC:
70 congestion_setcallback(s);
71 break;
72 default:
73 fnNetSimError("Unknown tcp variant %d in %s\n",
74 t->tcpVariant,
75 __FUNCTION__);
76 break;
77 }
78}
79
80static void setSackPermitted(PNETSIM_SOCKET s, PTCP_DEV_VAR t)
81{
82 s->tcb->isSackPermitted = t->isSackPermitted;
83}
84
85static void set_timestamp_option(PNETSIM_SOCKET s, PTCP_DEV_VAR t)
86{
87 s->tcb->isTSopt = t->isTimestampOpt;
88}
89
90void create_TCB(PNETSIM_SOCKET s)
91{
92 PTCP_DEV_VAR tcp = GET_TCP_DEV_VAR(s->localDeviceId);
93 PTCB tcb = (PTCB)calloc(1, sizeof* tcb);
94 s->tcb = tcb;
95
96 set_tcp_variant(s, tcp);
97
98 set_ack_type(s, tcp);
99
100 setSackPermitted(s, tcp);
101
102 set_window_scaling_option(s, tcp);
103
104 set_timestamp_option(s, tcp);
105
106 TCP_RTO(tcb) = calculate_RTO(0,
107 &TCP_SRTT(tcb),
108 &TCP_RTTVAR(tcb));
109
110 print_tcp_log("New RTO = %0.2lf", TCP_RTO(tcb));
111
112 tcb->timeWaitTimer = tcp->timeWaitTimer;
113
114 tcb->ISS = calculate_initial_seq_num(pstruEventDetails->dEventTime);
115 tcb->SND.WND = tcb->get_WND(s);
116 tcb->RCV.WND = tcb->get_RCVWND(s);
117
118 //Start with closed state
119 tcb->tcp_state = TCPCONNECTION_CLOSED;
120 tcb->tcp_prev_state = TCPCONNECTION_CLOSED;
121
122 //Set initial RMSS and SMSS size
123 s->tcb->init_congestionalgo(s);
124}
125
126void free_tcb(PTCB tcb)
127{
128 free_queue(&tcb->retransmissionQueue);
129 free(tcb);
130}
131
132void delete_tcb(PNETSIM_SOCKET s)
133{
134 free_tcb(s->tcb);
135 s->tcb = NULL;
136}
137
138void tcp_change_state(PNETSIM_SOCKET s, TCP_CONNECTION_STATE state)
139{
140 PTCB tcb = s->tcb;
141 if (tcb->tcp_state != state)
142 {
143 tcb->tcp_prev_state = tcb->tcp_state;
144 tcb->tcp_state = state;
145 print_tcp_log("TCP state is changed to \"%s\" from \"%s\".",
146 state_to_str(tcb->tcp_state),
147 state_to_str(tcb->tcp_prev_state));
148 }
149}
150
151static void free_queue(PTCP_QUEUE queue)
152{
153 PQueueInfo info = queue->queue;
154 while (info)
155 {
156 NetSim_PACKET* p = info->packet;
157 PQueueInfo i = info;
158 info = info->next;
159 free(i);
160 fn_NetSim_Packet_FreePacket(p);
161 }
162}
163
164void add_packet_to_queue(PTCP_QUEUE queue, NetSim_PACKET* packet, double time)
165{
166 PQueueInfo info = queue->queue;
167
168 PQueueInfo ninfo = (PQueueInfo)calloc(1, sizeof* ninfo);
169 ninfo->packet = packet;
170 ninfo->time = time;
171
172 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(packet);
173
174 if (info)
175 {
176 PQueueInfo pinfo = NULL;
177 while (info)
178 {
179 NetSim_PACKET* p = info->packet;
180 PTCP_SEGMENT_HDR h = TCP_GET_SEGMENT_HDR(p);
181
182 if (h->SeqNum < hdr->SeqNum)
183 {
184 pinfo = info;
185 info = info->next;
186 }
187 else
188 {
189 if (pinfo)
190 {
191 pinfo->next = ninfo;
192 ninfo->next = info;
193 }
194 else
195 {
196 ninfo->next = info;
197 queue->queue = ninfo;
198 }
199 break;
200 }
201 }
202 if (!info)
203 {
204 pinfo->next = ninfo;
205 }
206 }
207 else
208 {
209 queue->queue = ninfo;
210 }
211 queue->size += (UINT)packet->pstruTransportData->dPacketSize;
212}
213
214bool isSegmentInQueue(PTCP_QUEUE queue, NetSim_PACKET* packet)
215{
216 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(packet);
217 PQueueInfo info = queue->queue;
218 while (info)
219 {
220 NetSim_PACKET* p = info->packet;
221 PTCP_SEGMENT_HDR h = TCP_GET_SEGMENT_HDR(p);
222 if (hdr->SeqNum == h->SeqNum)
223 return true;
224 info = info->next;
225 }
226 return false;
227}
228
229NetSim_PACKET* get_segment_from_queue(PTCP_QUEUE queue, UINT32 seqNo)
230{
231 PQueueInfo info = queue->queue;
232 PQueueInfo pr=NULL;
233 while (info)
234 {
235 NetSim_PACKET* p = info->packet;
236 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
237 if (hdr->SeqNum == seqNo)
238 {
239 queue->size -= (UINT)p->pstruTransportData->dPacketSize;
240 if (pr)
241 {
242 pr->next = info->next;
243 free(info);
244 }
245 else
246 {
247 queue->queue = info->next;
248 free(info);
249 }
250 return p;
251 }
252 pr = info;
253 info = info->next;
254 }
255 return NULL;
256}
257
258NetSim_PACKET* get_earliest_segment_from_queue(PTCP_QUEUE queue)
259{
260 PQueueInfo info = queue->queue;
261 if (info)
262 {
263 NetSim_PACKET* p = info->packet;
264 queue->size -= (UINT)p->pstruTransportData->dPacketSize;
265
266 queue->queue = info->next;
267 free(info);
268 return p;
269 }
270 return NULL;
271}
272
273NetSim_PACKET* get_earliest_copy_segment_from_queue(PTCP_QUEUE queue)
274{
275 PQueueInfo info = queue->queue;
276 if (info)
277 {
278 NetSim_PACKET* p = info->packet;
279
280 return fn_NetSim_Packet_CopyPacket(p);
281 }
282 return NULL;
283}
284
285NetSim_PACKET* get_copy_segment_from_queue(PTCP_QUEUE queue, UINT32 seqNo, bool* isSacked)
286{
287 PQueueInfo info = queue->queue;
288 PQueueInfo pr = NULL;
289 while (info)
290 {
291 NetSim_PACKET* p = info->packet;
292 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
293 if (hdr->SeqNum == seqNo)
294 {
295 NetSim_PACKET* pret = fn_NetSim_Packet_CopyPacket(p);
296 pret->pstruNextPacket = NULL;
297 *isSacked = info->isSacked;
298 return pret;
299 }
300 pr = info;
301 info = info->next;
302 }
303 return NULL;
304}
305
306
307UINT32 get_seg_len(NetSim_PACKET* p)
308{
309 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
310 if (hdr->Syn)
311 return 1;
312 else
313 return (UINT32)(p->pstruTransportData->dPayload);
314}
315
316void delete_segment_from_queue(PTCP_QUEUE queue, UINT32 ackNo)
317{
318 PQueueInfo info = queue->queue;
319 PQueueInfo pr = NULL;
320 while (info)
321 {
322 NetSim_PACKET* p = info->packet;
323 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
324 if (hdr->SeqNum + get_seg_len(p) <= ackNo)
325 {
326 //Delete
327 queue->size -= (UINT)p->pstruTransportData->dPacketSize;
328 if (pr)
329 {
330 pr->next = info->next;
331 free(info);
332 info = pr->next;
333 }
334 else
335 {
336 queue->queue = info->next;
337 free(info);
338 info = queue->queue;
339 }
340 fn_NetSim_Packet_FreePacket(p);
341 continue;
342 }
343 pr = info;
344 info = info->next;
345 }
346}
347
348bool isAnySegmentInQueue(PTCP_QUEUE queue)
349{
350 return queue->size > 0;
351}
352
353void delete_all_segment_from_queue(PTCP_QUEUE queue)
354{
355 free_queue(queue);
356}
357
358void update_seq_num_on_receiving(PNETSIM_SOCKET s,
359 NetSim_PACKET* p)
360{
361 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
362 PTCB t = s->tcb;
363 if (t)
364 {
365 t->SEG.ACK = hdr->AckNum;
366 t->SEG.LEN = get_seg_len(p);
367 t->SEG.SEQ = hdr->SeqNum;
368 t->SEG.WND = hdr->Window;
369 }
370}
371
372double get_RTT(PTCB tcb, UINT ackNo)
373{
374 PQueueInfo info = tcb->retransmissionQueue.queue;
375 while (info)
376 {
377 NetSim_PACKET* p = info->packet;
378 PTCP_SEGMENT_HDR hdr = TCP_GET_SEGMENT_HDR(p);
379 if (hdr->SeqNum + get_seg_len(p) == ackNo)
380 {
381 return pstruEventDetails->dEventTime - info->time;
382 }
383 info = info->next;
384 }
385 return 0;
386}
387
388NetSim_PACKET* check_for_other_segment_to_send_from_queue(PNETSIM_SOCKET s)
389{
390 PTCP_QUEUE queue = &s->tcb->outOfOrderSegment;
391 PQueueInfo info = queue->queue;
392 NetSim_PACKET* pr = NULL;
393 if (info)
394 {
395 pr = info->packet;
396 PTCP_SEGMENT_HDR h = TCP_GET_SEGMENT_HDR(pr);
397 if (h->SeqNum < s->tcb->RCV.NXT)
398 {
399 //Delete
400 queue->size -= (UINT)pr->pstruTransportData->dPacketSize;
401 queue->queue = info->next;
402 free(info);
403 }
404 else
405 pr = NULL;
406 }
407 return pr;
408}
409
410void check_segment_in_queue(PNETSIM_SOCKET s)
411{
412 PTCP_QUEUE queue = &s->tcb->outOfOrderSegment;
413 PQueueInfo info = queue->queue;
414 while (info)
415 {
416 NetSim_PACKET* pr = NULL;
417 pr = info->packet;
418 PTCP_SEGMENT_HDR h = TCP_GET_SEGMENT_HDR(pr);
419 if (h->SeqNum == s->tcb->RCV.NXT)
420 {
421 s->tcb->RCV.NXT += get_seg_len(pr);
422 }
423 info = info->next;
424 }
425}
426
427void set_timestamp_value(PNETSIM_SOCKET s,
428 PTCP_SEGMENT_HDR hdr,
429 PTSopt opt)
430{
431 if (hdr->Syn)
432 {
433 if (opt && s->tcb->isTSopt)
434 s->tcb->isTSopt = true;
435 else
436 s->tcb->isTSopt = false;
437 }
438
439 if (opt && s->tcb->isTSopt)
440 {
441 s->tcb->TSVal = opt->TSval;
442 }
443
444}
TCP_CONNECTION_STATE tcp_state
Present State of the TCP Connection.
Definition TCB.h:47
TCP_CONNECTION_STATE tcp_prev_state
Present State of the Connection.
Definition TCB.h:48