NetSim Source Code Help
Loading...
Searching...
No Matches
TCP_Incoming.c
Go to the documentation of this file.
1/************************************************************************************
2* Copyright (C) 2022 *
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* This source code is licensed per the NetSim license agreement. *
12* *
13* No portion of this source code may be used as the basis for a derivative work, *
14* or used, for any purpose other than its intended use per the NetSim license *
15* agreement. *
16* *
17* This source code and the algorithms contained within it are confidential trade *
18* secrets of TETCOS and may not be used as the basis for any other software, *
19* hardware, product or service. *
20* *
21* Author: Shashi Kant Suman *
22* *
23* ----------------------------------------------------------------------------------*/
24#include "main.h"
25#include "TCP.h"
26#include "TCP_Header.h"
27
28//#define _LOG_INCOMING_
29
30#ifdef _LOG_INCOMING_
31static FILE* fp;
32#endif
33
35{
36 /*RFC 793 Sept 1981 Page 69
37 There are four cases for the acceptability test for an incoming
38 segment:
39
40 Segment Receive Test
41 Length Window
42 ------- ------- -------------------------------------------
43
44 0 0 SEG.SEQ = RCV.NXT
45
46 0 >0 RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
47
48 >0 0 not acceptable
49
50 >0 >0 RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
51 or RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND
52 */
53 PTCB t = s->tcb;
54 if (!t->SEG.LEN && !t->RCV.WND)
55 return t->SEG.SEQ == t->RCV.NXT;
56 else if (!t->SEG.LEN && t->RCV.WND > 0)
57 return (t->RCV.NXT <= t->SEG.SEQ) &&
58 (t->SEG.SEQ < t->RCV.NXT + t->RCV.WND);
59 else if (t->SEG.LEN > 0 && t->RCV.WND == 0)
60 return false;
61 else if (t->SEG.LEN > 0 && t->RCV.WND > 0)
62 return ((t->RCV.NXT <= t->SEG.SEQ) &&
63 (t->SEG.SEQ < t->RCV.NXT + t->RCV.WND)) ||
64 ((t->RCV.NXT <= t->SEG.SEQ + t->SEG.LEN - 1) &&
65 (t->SEG.SEQ + t->SEG.LEN - 1 < t->RCV.NXT + t->RCV.WND));
66
67 assert(false); // TCP is now mad. Enjoy debugging....:(
68 return false;
69}
70
72{
73 switch (s->tcb->tcp_state)
74 {
76 {
79 {
80 //Passive open case
82 }
83 else
84 {
85 //Active open case
86 print_tcp_log("Connection Refused for local addr %s:%d, remote addr %s:%d",
87 s->localAddr->ip->str_ip,
88 s->localAddr->port,
89 s->remoteAddr->ip->str_ip,
90 s->remoteAddr->port);
92 }
93 }
94 break;
99 {
100 print_tcp_log("Connection Reset for local addr %s:%d, remote addr %s:%d",
101 s->localAddr->ip->str_ip,
102 s->localAddr->port,
103 s->remoteAddr->ip->str_ip,
104 s->remoteAddr->port);
105 }
110 break;
111 }
114}
115
117{
118 switch (s->tcb->tcp_state)
119 {
121 //Correction made by RFC 1122 Page 94
123 break;
131 print_tcp_log("Connection Reset for local addr %s:%d, remote addr %s:%d",
132 s->localAddr->ip->str_ip,
133 s->localAddr->port,
134 s->remoteAddr->ip->str_ip,
135 s->remoteAddr->port);
137 break;
138 }
141}
142
144{
145#ifdef _LOG_INCOMING_
146 fprintf(fp, "%lf,,,,,%d,\n",
148 s->tcb->SEG.ACK);
149 fflush(fp);
150#endif
151
152 PTCB t = s->tcb;
153
154 //Call Sack
155 receive_sack_option(s, hdr);
156
157 if (s->tcb->isTSopt)
158 {
159 //Store the timestamp option based on peer device
160 PTSopt tsopt = get_tcp_option(hdr,
162 set_timestamp_value(s, hdr, tsopt);
163 }
164
165 //Call congestion algorithm
166 t->ack_received(s);
167
168
170
171 if (t->SND.UNA < t->SEG.ACK &&
172 t->SEG.ACK <= t->SND.NXT) //RFC 793
173 {
174
175 //Update the RTO
177 &TCP_SRTT(s->tcb),
178 &TCP_RTTVAR(s->tcb));
179
180
181 t->SND.UNA = t->SEG.ACK;
184 if (t->SND.WL1 < t->SEG.SEQ ||
185 (t->SND.WL1 == t->SEG.SEQ &&
186 t->SND.WL2 <= t->SEG.ACK))
187 {
188 t->SND.WND = t->SEG.WND;
189 t->SND.WL1 = t->SEG.SEQ;
190 t->SND.WL2 = t->SEG.ACK;
191 }
192 return true;
193 }
194 //else if (t->SEG.ACK < t->SND.UNA) //RFC 793
195 else if (t->SEG.ACK <= t->SND.UNA) //RFC 1122 Page 94
196 {
197 //Duplicate ack. Ignore
199 return false;
200 }
201 else if (t->SEG.ACK > t->SND.NXT)
202 {
204 return false;
205 }
206
207 return false;
208}
209
211{
213 bool isContinueProcessing=false;
214 switch (s->tcb->tcp_state)
215 {
217 {
218 if (!(s->tcb->SND.UNA <= s->tcb->SEG.ACK &&
219 s->tcb->SEG.ACK <= s->tcb->SND.NXT))
220 {
221 send_rst(s, p, 1);
222 break;
223 }
224 else
225 {
226 //Correction made by RFC 1122 page 94
227 s->tcb->SND.WND = s->tcb->SEG.WND;
228 s->tcb->SND.WL1 = s->tcb->SEG.SEQ;
229 s->tcb->SND.WL2 = s->tcb->SEG.ACK;
230
232 }
233 }
235 {
236 isContinueProcessing = process_ack_in_establishedState(s, hdr);
237 if (isContinueProcessing)
238 send_segment(s);
239 }
240 break;
242 isContinueProcessing = process_ack_in_establishedState(s, hdr);
243 if (isContinueProcessing)
244 send_segment(s);
245 if(hdr->Fin)
247 break;
250 isContinueProcessing = process_ack_in_establishedState(s, hdr);
251 if (isContinueProcessing)
252 send_segment(s);
253 break;
255 isContinueProcessing = process_ack_in_establishedState(s, hdr);
256 if (isContinueProcessing)
257 send_segment(s);
258 if (hdr->Fin)
259 {
262 }
263 break;
266 delete_tcb(s);
268 break;
272 s->tcb->istimewaittimerrestarted = true;
273 break;
274 default:
275 fnNetSimError("Unknown TCP connection state %d in %s",
276 s->tcb->tcp_state,
277 __FUNCTION__);
278 break;
279 }
282}
283
285{
286 switch (s->tcb->tcp_state)
287 {
291 goto DISCARD_SEGMENT;
292 }
293
294 switch (s->tcb->tcp_state)
295 {
300 //User will call close
301 send_fin(s);
303 print_tcp_log("Canceling all timer.");
304 s->tcb->isOtherTimerCancel = true;
305 break;
309 break;
314 break;
318 // No operation
319 break;
321 s->tcb->istimewaittimerrestarted = true;
323 break;
324 default:
325 fnNetSimError("Unknown tcp state %d", s->tcb->tcp_state);
326 break;
327 }
328DISCARD_SEGMENT:
331}
332
334{
336 if (s->tcb->RCV.NXT == hdr->SeqNum)
337 {
338 s->tcb->RCV.NXT += s->tcb->SEG.LEN;
339 //Check from queue
341 return true;
342 }
343 else if ((s->tcb->RCV.NXT > hdr->SeqNum))
344 {
345 //Duplicate segment
347 return false;
348 }
349 else
350 {
354 else
356 return false;
357 }
358}
359
361{
363
364#ifdef _LOG_INCOMING_
365 fprintf(fp, "%lf,%d,,,,,\n",
367 s->tcb->SEG.SEQ);
368 fflush(fp);
369#endif
370
373
374 if (s->tcb->isTSopt)
375 {
376 //Store the timestamp option based on peer device
377 PTSopt tsopt = get_tcp_option(hdr,
379 set_timestamp_value(s, hdr, tsopt);
380 }
381
385 {
386 bool isinorder = check_segment(s, p);
387
388 if((!isinorder || send_ack_or_not(s)) && !hdr->Fin)
390
391 if(isinorder)
393
394 return true;
395 }
396 else if (hdr->Fin)
397 {
398 return true; //FIN Packet
399 }
400 else if (s->tcb->tcp_state == TCPCONNECTION_CLOSE_WAIT ||
404 {
407 return false;
408 }
410 {
411 // May be ack got error. Ignore segment
414 return false;
415 }
416 else
417 {
418 fnNetSimError("Unknown TCP connection state %s in %s",
420 __FUNCTION__);
423 return false;
424 }
425}
426
428{
429 bool isContinue;
430
431#ifdef _LOG_INCOMING_
432 if (!fp)
433 {
434 fp = fopen("IncomingTCP.csv", "w");
435 fprintf(fp, "Time,Seq,,,Ack\n");
436 fflush(fp);
437 }
438#endif
439
441
442 bool isValidSeg = Validate_segment(s);
443
444 if (isValidSeg)
445 {
446 if (hdr->Rst)
447 process_rst_packet(s, p);
448 else if (hdr->Syn)
449 process_syn_packet(s, p);
450 else if (hdr->Ack)
451 process_ack_packet(s, p);
452 else
453 {
454 isContinue = process_segment_text(s, p);
455
456 if (isContinue && hdr->Fin)
457 process_fin_packet(s, p);
458 }
459 }
460 else
461 {
462 print_tcp_log("unacceptable segment");
463
464 if (!hdr->Rst)
465 send_ack(s,
467 s->tcb->SND.NXT,
468 s->tcb->RCV.NXT);
469
472 }
473}
bool send_ack_or_not(PNETSIM_SOCKET s)
Definition: DelayedAck.c:24
#define fnNetSimError(x,...)
Definition: Linux.h:56
double calculate_RTO(double R, double *srtt, double *rtt_var)
Definition: RTO.c:35
void restart_rto_timer(PNETSIM_SOCKET s)
Definition: RTO.c:152
void receive_sack_option(PNETSIM_SOCKET s, PTCP_SEGMENT_HDR hdr)
Definition: SACK.c:280
EXPORTED struct stru_NetSim_EventDetails * pstruEventDetails
Definition: Stack.h:837
void delete_all_segment_from_queue(PTCP_QUEUE queue)
Definition: TCB.c:353
void tcp_change_state(PNETSIM_SOCKET s, TCP_CONNECTION_STATE state)
Definition: TCB.c:138
bool isSegmentInQueue(PTCP_QUEUE queue, NetSim_PACKET *packet)
Definition: TCB.c:214
void delete_segment_from_queue(PTCP_QUEUE queue, UINT32 ackNo)
Definition: TCB.c:316
void check_segment_in_queue(PNETSIM_SOCKET s)
Definition: TCB.c:410
double get_RTT(PTCB tcb, UINT ackNo)
Definition: TCB.c:372
void set_timestamp_value(PNETSIM_SOCKET s, PTCP_SEGMENT_HDR hdr, PTSopt opt)
Definition: TCB.c:427
void delete_tcb(PNETSIM_SOCKET s)
Definition: TCB.c:132
char * state_to_str(TCP_CONNECTION_STATE state)
Definition: TCB.c:28
void add_packet_to_queue(PTCP_QUEUE queue, NetSim_PACKET *packet, double time)
Definition: TCB.c:164
#define TCP_RTO(tcb)
Definition: TCB.h:118
#define TCP_RTTVAR(tcb)
Definition: TCB.h:120
#define TCP_SRTT(tcb)
Definition: TCB.h:119
void start_timewait_timer(PNETSIM_SOCKET s)
Definition: TCP.c:246
void write_congestion_plot(PNETSIM_SOCKET s, NetSim_PACKET *packet)
Definition: TCP.c:276
void send_ack(PNETSIM_SOCKET s, double time, UINT32 seqNo, UINT32 ackNo)
void send_rst(PNETSIM_SOCKET s, NetSim_PACKET *p, UINT c)
void send_to_application(PNETSIM_SOCKET s, NetSim_PACKET *p)
void send_fin(PNETSIM_SOCKET s)
@ TCPCONNECTION_LAST_ACK
Definition: TCP.h:67
@ TCPCONNECTION_FIN_WAIT_2
Definition: TCP.h:64
@ TCPCONNECTION_LISTEN
Definition: TCP.h:59
@ TCPCONNECTION_CLOSED
Definition: TCP.h:58
@ TCPCONNECTION_SYN_RECEIVED
Definition: TCP.h:61
@ TCPCONNECTION_TIME_WAIT
Definition: TCP.h:68
@ TCPCONNECTION_CLOSING
Definition: TCP.h:66
@ TCPCONNECTION_CLOSE_WAIT
Definition: TCP.h:65
@ TCPCONNECTION_FIN_WAIT_1
Definition: TCP.h:63
@ TCPCONNECTION_SYN_SENT
Definition: TCP.h:60
@ TCPCONNECTION_ESTABLISHED
Definition: TCP.h:62
void print_tcp_log(char *format,...)
void send_segment(PNETSIM_SOCKET s)
Definition: TCP_Outgoing.c:18
void send_fin_ack(PNETSIM_SOCKET s, double time, UINT32 seqNo, UINT32 ackNo)
void tcp_close_socket(PNETSIM_SOCKET s, NETSIM_ID devId)
Definition: TCP_Socket.c:187
@ TCP_OPTION_TIMESTAMP
Definition: TCP_Header.h:46
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
static bool process_ack_in_establishedState(PNETSIM_SOCKET s, PTCP_SEGMENT_HDR hdr)
Definition: TCP_Incoming.c:143
static void process_ack_packet(PNETSIM_SOCKET s, NetSim_PACKET *p)
Definition: TCP_Incoming.c:210
static bool process_segment_text(PNETSIM_SOCKET s, NetSim_PACKET *p)
Definition: TCP_Incoming.c:360
static void process_syn_packet(PNETSIM_SOCKET s, NetSim_PACKET *p)
Definition: TCP_Incoming.c:116
static void process_rst_packet(PNETSIM_SOCKET s, NetSim_PACKET *p)
Definition: TCP_Incoming.c:71
static void process_fin_packet(PNETSIM_SOCKET s, NetSim_PACKET *p)
Definition: TCP_Incoming.c:284
static bool check_segment(PNETSIM_SOCKET s, NetSim_PACKET *p)
Definition: TCP_Incoming.c:333
void packet_arrives_at_incoming_tcp(PNETSIM_SOCKET s, NetSim_PACKET *p)
Definition: TCP_Incoming.c:427
static bool Validate_segment(PNETSIM_SOCKET s)
Definition: TCP_Incoming.c:34
#define fn_NetSim_Packet_FreePacket(pstruPacket)
Definition: main.h:177
struct stru_NetSim_Packet * pPacket
Definition: Stack.h:754
NETSIM_ID nDeviceId
Definition: Stack.h:750
PTCB tcb
Definition: TCP.h:132
PSOCKETADDRESS localAddr
Definition: TCP.h:121
NETSIM_ID localDeviceId
Definition: TCP.h:125
PSOCKETADDRESS remoteAddr
Definition: TCP.h:122
PTCP_METRICS tcpMetrics
Definition: TCP.h:140
char str_ip[_NETSIM_IP_LEN]
Definition: IP_Addressing.h:54
NETSIM_IPAddress ip
Definition: TCP.h:114
UINT16 port
Definition: TCP.h:115
TCP_CONNECTION_STATE tcp_state
Present State of the TCP Connection.
Definition: TCB.h:47
struct stru_tcp_Transmission_Control_Block::stru_tcb_send_seq_var SND
struct stru_tcp_Transmission_Control_Block::stru_tcb_recv_seq_var RCV
void(* ack_received)(PNETSIM_SOCKET)
Definition: TCB.h:132
TCP_CONNECTION_STATE tcp_prev_state
Present State of the Connection.
Definition: TCB.h:48
struct stru_tcp_Transmission_Control_Block::stru_tcb_curr_seg_var SEG
UINT ackReceived
Definition: TCP.h:101
UINT segmentReceived
Definition: TCP.h:98
UINT dupAckReceived
Definition: TCP.h:102
UINT dupSegmentReceived
Definition: TCP.h:104
UINT outOfOrderSegmentReceived
Definition: TCP.h:105