00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <string.h>
00021 #include <assert.h>
00022 #include "TCP.h"
00023 #include "TCPConnection.h"
00024 #include "TCPSegment.h"
00025 #include "TCPCommand_m.h"
00026 #include "TCPSendQueue.h"
00027 #include "TCPReceiveQueue.h"
00028 #include "TCPAlgorithm.h"
00029 #include "TCPSACKRexmitQueue.h"
00030
00031
00032 TCPStateVariables::TCPStateVariables()
00033 {
00034
00035 active = false;
00036 fork = false;
00037 snd_mss = 0;
00038 snd_una = 0;
00039 snd_nxt = 0;
00040 snd_max = 0;
00041 snd_wnd = 0;
00042 snd_up = 0;
00043 snd_wl1 = 0;
00044 snd_wl2 = 0;
00045 iss = 0;
00046
00047 rcv_nxt = 0;
00048 rcv_wnd = 0;
00049 rcv_up = 0;
00050 irs = 0;
00051 rcv_adv = 0;
00052
00053 syn_rexmit_count = 0;
00054 syn_rexmit_timeout = 0;
00055
00056 fin_ack_rcvd = false;
00057 send_fin = false;
00058 snd_fin_seq = 0;
00059 fin_rcvd = false;
00060 rcv_fin_seq = 0;
00061 sentBytes = 0;
00062
00063 nagle_enabled = false;
00064 delayed_acks_enabled = false;
00065 limited_transmit_enabled = false;
00066 increased_IW_enabled = false;
00067 full_sized_segment_counter = 0;
00068 ack_now = false;
00069
00070 afterRto = false;
00071
00072 time_last_data_sent = 0;
00073
00074 ws_support = false;
00075 ws_enabled = false;
00076 snd_ws = false;
00077 rcv_ws = false;
00078 rcv_wnd_scale = 0;
00079 snd_wnd_scale = 0;
00080
00081 ts_support = false;
00082 ts_enabled = false;
00083 snd_initial_ts = false;
00084 rcv_initial_ts = false;
00085 ts_recent = 0;
00086 last_ack_sent = 0;
00087
00088 sack_support = false;
00089 sack_enabled = false;
00090 snd_sack_perm = false;
00091 rcv_sack_perm = false;
00092
00093 snd_sack = false;
00094 snd_dsack = false;
00095 start_seqno = 0;
00096 end_seqno = 0;
00097 highRxt = 0;
00098 pipe = 0;
00099 recoveryPoint = 0;
00100 sackedBytes = 0;
00101 sackedBytes_old = 0;
00102 lossRecovery = false;
00103
00104 dupacks = 0;
00105 snd_sacks = 0;
00106 rcv_sacks = 0;
00107 rcv_oooseg = 0;
00108
00109 maxRcvBuffer = 0;
00110 usedRcvBuffer = 0;
00111 freeRcvBuffer = 0;
00112 tcpRcvQueueDrops = 0;
00113 }
00114
00115 std::string TCPStateVariables::info() const
00116 {
00117 std::stringstream out;
00118 out << "snd_una=" << snd_una;
00119 out << " snd_nxt=" << snd_nxt;
00120 out << " snd_max=" << snd_max;
00121 out << " snd_wnd=" << snd_wnd;
00122 out << " rcv_nxt=" << rcv_nxt;
00123 out << " rcv_wnd=" << rcv_wnd;
00124 return out.str();
00125 }
00126
00127 std::string TCPStateVariables::detailedInfo() const
00128 {
00129 std::stringstream out;
00130 out << "active = " << active << "\n";
00131 out << "snd_mss = " << snd_mss << "\n";
00132 out << "snd_una = " << snd_una << "\n";
00133 out << "snd_nxt = " << snd_nxt << "\n";
00134 out << "snd_max = " << snd_max << "\n";
00135 out << "snd_wnd = " << snd_wnd << "\n";
00136 out << "snd_up = " << snd_up << "\n";
00137 out << "snd_wl1 = " << snd_wl1 << "\n";
00138 out << "snd_wl2 = " << snd_wl2 << "\n";
00139 out << "iss = " << iss << "\n";
00140 out << "rcv_nxt = " << rcv_nxt << "\n";
00141 out << "rcv_wnd = " << rcv_wnd << "\n";
00142 out << "rcv_up = " << rcv_up << "\n";
00143 out << "irs = " << irs << "\n";
00144 out << "rcv_adv = " << rcv_adv << "\n";
00145 out << "fin_ack_rcvd = " << fin_ack_rcvd << "\n";
00146 out << "nagle_enabled = " << nagle_enabled << "\n";
00147 out << "limited_transmit_enabled = " << limited_transmit_enabled << "\n";
00148 out << "increased_IW_enabled = " << increased_IW_enabled << "\n";
00149 out << "delayed_acks_enabled = " << delayed_acks_enabled << "\n";
00150 out << "ws_support = " << ws_support << "\n";
00151 out << "ws_enabled = " << ws_enabled << "\n";
00152 out << "ts_support = " << ts_support << "\n";
00153 out << "ts_enabled = " << ts_enabled << "\n";
00154 out << "sack_support = " << sack_support << "\n";
00155 out << "sack_enabled = " << sack_enabled << "\n";
00156 out << "snd_sack_perm = " << snd_sack_perm << "\n";
00157 out << "snd_sacks = " << snd_sacks << "\n";
00158 out << "rcv_sacks = " << rcv_sacks << "\n";
00159 out << "dupacks = " << dupacks << "\n";
00160 out << "rcv_oooseg = " << rcv_oooseg << "\n";
00161 return out.str();
00162 }
00163
00164 TCPConnection::TCPConnection()
00165 {
00166
00167
00168 sendQueue = NULL;
00169 rexmitQueue = NULL;
00170 receiveQueue = NULL;
00171 tcpAlgorithm = NULL;
00172 state = NULL;
00173 the2MSLTimer = connEstabTimer = finWait2Timer = synRexmitTimer = NULL;
00174 sndWndVector = rcvWndVector = rcvAdvVector = sndNxtVector = sndAckVector = rcvSeqVector = rcvAckVector = unackedVector =
00175 dupAcksVector = sndSacksVector = rcvSacksVector = rcvOooSegVector =
00176 tcpRcvQueueBytesVector = tcpRcvQueueDropsVector = pipeVector = sackedBytesVector = NULL;
00177 }
00178
00179
00180
00181
00182
00183 TCPConnection::TCPConnection(TCP *_mod, int _appGateIndex, int _connId)
00184 {
00185 tcpMain = _mod;
00186 appGateIndex = _appGateIndex;
00187 connId = _connId;
00188
00189 localPort = remotePort = -1;
00190
00191 char fsmname[24];
00192 sprintf(fsmname, "fsm-%d", connId);
00193 fsm.setName(fsmname);
00194 fsm.setState(TCP_S_INIT);
00195
00196
00197
00198 sendQueue = NULL;
00199 rexmitQueue = NULL;
00200 receiveQueue = NULL;
00201 tcpAlgorithm = NULL;
00202 state = NULL;
00203
00204 the2MSLTimer = new cMessage("2MSL");
00205 connEstabTimer = new cMessage("CONN-ESTAB");
00206 finWait2Timer = new cMessage("FIN-WAIT-2");
00207 synRexmitTimer = new cMessage("SYN-REXMIT");
00208
00209 the2MSLTimer->setContextPointer(this);
00210 connEstabTimer->setContextPointer(this);
00211 finWait2Timer->setContextPointer(this);
00212 synRexmitTimer->setContextPointer(this);
00213
00214
00215 sndWndVector = NULL;
00216 rcvWndVector = NULL;
00217 rcvAdvVector = NULL;
00218 sndNxtVector = NULL;
00219 sndAckVector = NULL;
00220 rcvSeqVector = NULL;
00221 rcvAckVector = NULL;
00222 unackedVector = NULL;
00223
00224 dupAcksVector = NULL;
00225 sndSacksVector = NULL;
00226 rcvSacksVector = NULL;
00227 rcvOooSegVector = NULL;
00228 tcpRcvQueueBytesVector = NULL;
00229 tcpRcvQueueDropsVector = NULL;
00230 pipeVector = NULL;
00231 sackedBytesVector = NULL;
00232
00233 if (getTcpMain()->recordStatistics)
00234 {
00235 sndWndVector = new cOutVector("send window");
00236 rcvWndVector = new cOutVector("receive window");
00237 rcvAdvVector = new cOutVector("advertised window");
00238 sndNxtVector = new cOutVector("sent seq");
00239 sndAckVector = new cOutVector("sent ack");
00240 rcvSeqVector = new cOutVector("rcvd seq");
00241 rcvAckVector = new cOutVector("rcvd ack");
00242 unackedVector = new cOutVector("unacked bytes");
00243 dupAcksVector = new cOutVector("rcvd dupAcks");
00244 pipeVector = new cOutVector("pipe");
00245 sndSacksVector = new cOutVector("sent sacks");
00246 rcvSacksVector = new cOutVector("rcvd sacks");
00247 rcvOooSegVector = new cOutVector("rcvd oooseg");
00248 sackedBytesVector = new cOutVector("rcvd sackedBytes");
00249 tcpRcvQueueBytesVector = new cOutVector("tcpRcvQueueBytes");
00250 tcpRcvQueueDropsVector = new cOutVector("tcpRcvQueueDrops");
00251 }
00252 }
00253
00254 TCPConnection::~TCPConnection()
00255 {
00256 delete sendQueue;
00257 delete rexmitQueue;
00258 delete receiveQueue;
00259 delete tcpAlgorithm;
00260 delete state;
00261
00262 if (the2MSLTimer) delete cancelEvent(the2MSLTimer);
00263 if (connEstabTimer) delete cancelEvent(connEstabTimer);
00264 if (finWait2Timer) delete cancelEvent(finWait2Timer);
00265 if (synRexmitTimer) delete cancelEvent(synRexmitTimer);
00266
00267
00268 delete sndWndVector;
00269 delete rcvWndVector;
00270 delete rcvAdvVector;
00271 delete sndNxtVector;
00272 delete sndAckVector;
00273 delete rcvSeqVector;
00274 delete rcvAckVector;
00275 delete unackedVector;
00276 delete dupAcksVector;
00277 delete sndSacksVector;
00278 delete rcvSacksVector;
00279 delete rcvOooSegVector;
00280 delete tcpRcvQueueBytesVector;
00281 delete tcpRcvQueueDropsVector;
00282 delete pipeVector;
00283 delete sackedBytesVector;
00284 }
00285
00286 bool TCPConnection::processTimer(cMessage *msg)
00287 {
00288 printConnBrief();
00289 tcpEV << msg->getName() << " timer expired\n";
00290
00291
00292 TCPEventCode event;
00293 if (msg==the2MSLTimer)
00294 {
00295 event = TCP_E_TIMEOUT_2MSL;
00296 process_TIMEOUT_2MSL();
00297 }
00298 else if (msg==connEstabTimer)
00299 {
00300 event = TCP_E_TIMEOUT_CONN_ESTAB;
00301 process_TIMEOUT_CONN_ESTAB();
00302 }
00303 else if (msg==finWait2Timer)
00304 {
00305 event = TCP_E_TIMEOUT_FIN_WAIT_2;
00306 process_TIMEOUT_FIN_WAIT_2();
00307 }
00308 else if (msg==synRexmitTimer)
00309 {
00310 event = TCP_E_IGNORE;
00311 process_TIMEOUT_SYN_REXMIT(event);
00312 }
00313 else
00314 {
00315 event = TCP_E_IGNORE;
00316 tcpAlgorithm->processTimer(msg, event);
00317 }
00318
00319
00320 return performStateTransition(event);
00321 }
00322
00323 bool TCPConnection::processTCPSegment(TCPSegment *tcpseg, IPvXAddress segSrcAddr, IPvXAddress segDestAddr)
00324 {
00325 printConnBrief();
00326 if (!localAddr.isUnspecified())
00327 {
00328 ASSERT(localAddr==segDestAddr);
00329 ASSERT(localPort==tcpseg->getDestPort());
00330 }
00331 if (!remoteAddr.isUnspecified())
00332 {
00333 ASSERT(remoteAddr==segSrcAddr);
00334 ASSERT(remotePort==tcpseg->getSrcPort());
00335 }
00336
00337 if (tryFastRoute(tcpseg))
00338 return true;
00339
00340
00341 TCPEventCode event = process_RCV_SEGMENT(tcpseg, segSrcAddr, segDestAddr);
00342
00343
00344 return performStateTransition(event);
00345 }
00346
00347 bool TCPConnection::processAppCommand(cMessage *msg)
00348 {
00349 printConnBrief();
00350
00351
00352 TCPCommand *tcpCommand = (TCPCommand *)(msg->removeControlInfo());
00353 TCPEventCode event = preanalyseAppCommandEvent(msg->getKind());
00354 tcpEV << "App command: " << eventName(event) << "\n";
00355 switch (event)
00356 {
00357 case TCP_E_OPEN_ACTIVE: process_OPEN_ACTIVE(event, tcpCommand, msg); break;
00358 case TCP_E_OPEN_PASSIVE: process_OPEN_PASSIVE(event, tcpCommand, msg); break;
00359 case TCP_E_SEND: process_SEND(event, tcpCommand, msg); break;
00360 case TCP_E_CLOSE: process_CLOSE(event, tcpCommand, msg); break;
00361 case TCP_E_ABORT: process_ABORT(event, tcpCommand, msg); break;
00362 case TCP_E_STATUS: process_STATUS(event, tcpCommand, msg); break;
00363 default: opp_error("wrong event code");
00364 }
00365
00366
00367 return performStateTransition(event);
00368 }
00369
00370
00371 TCPEventCode TCPConnection::preanalyseAppCommandEvent(int commandCode)
00372 {
00373 switch (commandCode)
00374 {
00375 case TCP_C_OPEN_ACTIVE: return TCP_E_OPEN_ACTIVE;
00376 case TCP_C_OPEN_PASSIVE: return TCP_E_OPEN_PASSIVE;
00377 case TCP_C_SEND: return TCP_E_SEND;
00378 case TCP_C_CLOSE: return TCP_E_CLOSE;
00379 case TCP_C_ABORT: return TCP_E_ABORT;
00380 case TCP_C_STATUS: return TCP_E_STATUS;
00381 default: opp_error("Unknown message kind in app command");
00382 return (TCPEventCode)0;
00383 }
00384 }
00385
00386 bool TCPConnection::performStateTransition(const TCPEventCode& event)
00387 {
00388 ASSERT(fsm.getState()!=TCP_S_CLOSED);
00389
00390 if (event==TCP_E_IGNORE)
00391 {
00392 tcpEV << "Staying in state: " << stateName(fsm.getState()) << " (no FSM event)\n";
00393 return true;
00394 }
00395
00396
00397
00398
00399 int oldState = fsm.getState();
00400 switch (fsm.getState())
00401 {
00402 case TCP_S_INIT:
00403 switch (event)
00404 {
00405 case TCP_E_OPEN_PASSIVE:FSM_Goto(fsm, TCP_S_LISTEN); break;
00406 case TCP_E_OPEN_ACTIVE: FSM_Goto(fsm, TCP_S_SYN_SENT); break;
00407 default:;
00408 }
00409 break;
00410
00411 case TCP_S_LISTEN:
00412 switch (event)
00413 {
00414 case TCP_E_OPEN_ACTIVE: FSM_Goto(fsm, TCP_S_SYN_SENT); break;
00415 case TCP_E_SEND: FSM_Goto(fsm, TCP_S_SYN_SENT); break;
00416 case TCP_E_CLOSE: FSM_Goto(fsm, TCP_S_CLOSED); break;
00417 case TCP_E_ABORT: FSM_Goto(fsm, TCP_S_CLOSED); break;
00418 case TCP_E_RCV_SYN: FSM_Goto(fsm, TCP_S_SYN_RCVD);break;
00419 default:;
00420 }
00421 break;
00422
00423 case TCP_S_SYN_RCVD:
00424 switch (event)
00425 {
00426 case TCP_E_CLOSE: FSM_Goto(fsm, TCP_S_FIN_WAIT_1); break;
00427 case TCP_E_ABORT: FSM_Goto(fsm, TCP_S_CLOSED); break;
00428 case TCP_E_TIMEOUT_CONN_ESTAB: FSM_Goto(fsm, state->active ? TCP_S_CLOSED : TCP_S_LISTEN); break;
00429 case TCP_E_RCV_RST: FSM_Goto(fsm, state->active ? TCP_S_CLOSED : TCP_S_LISTEN); break;
00430 case TCP_E_RCV_ACK: FSM_Goto(fsm, TCP_S_ESTABLISHED); break;
00431 case TCP_E_RCV_FIN: FSM_Goto(fsm, TCP_S_CLOSE_WAIT); break;
00432 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00433 default:;
00434 }
00435 break;
00436
00437 case TCP_S_SYN_SENT:
00438 switch (event)
00439 {
00440 case TCP_E_CLOSE: FSM_Goto(fsm, TCP_S_CLOSED); break;
00441 case TCP_E_ABORT: FSM_Goto(fsm, TCP_S_CLOSED); break;
00442 case TCP_E_TIMEOUT_CONN_ESTAB: FSM_Goto(fsm, TCP_S_CLOSED); break;
00443 case TCP_E_RCV_RST: FSM_Goto(fsm, TCP_S_CLOSED); break;
00444 case TCP_E_RCV_SYN_ACK: FSM_Goto(fsm, TCP_S_ESTABLISHED); break;
00445 case TCP_E_RCV_SYN: FSM_Goto(fsm, TCP_S_SYN_RCVD); break;
00446 default:;
00447 }
00448 break;
00449
00450 case TCP_S_ESTABLISHED:
00451 switch (event)
00452 {
00453 case TCP_E_CLOSE: FSM_Goto(fsm, TCP_S_FIN_WAIT_1); break;
00454 case TCP_E_ABORT: FSM_Goto(fsm, TCP_S_CLOSED); break;
00455 case TCP_E_RCV_FIN: FSM_Goto(fsm, TCP_S_CLOSE_WAIT); break;
00456 case TCP_E_RCV_RST: FSM_Goto(fsm, TCP_S_CLOSED); break;
00457 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00458 default:;
00459 }
00460 break;
00461
00462 case TCP_S_CLOSE_WAIT:
00463 switch (event)
00464 {
00465 case TCP_E_CLOSE: FSM_Goto(fsm, TCP_S_LAST_ACK); break;
00466 case TCP_E_ABORT: FSM_Goto(fsm, TCP_S_CLOSED); break;
00467 case TCP_E_RCV_RST: FSM_Goto(fsm, TCP_S_CLOSED); break;
00468 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00469 default:;
00470 }
00471 break;
00472
00473 case TCP_S_LAST_ACK:
00474 switch (event)
00475 {
00476 case TCP_E_ABORT: FSM_Goto(fsm, TCP_S_CLOSED); break;
00477 case TCP_E_RCV_ACK: FSM_Goto(fsm, TCP_S_CLOSED); break;
00478 case TCP_E_RCV_RST: FSM_Goto(fsm, TCP_S_CLOSED); break;
00479 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00480 default:;
00481 }
00482 break;
00483
00484 case TCP_S_FIN_WAIT_1:
00485 switch (event)
00486 {
00487 case TCP_E_ABORT: FSM_Goto(fsm, TCP_S_CLOSED); break;
00488 case TCP_E_RCV_FIN: FSM_Goto(fsm, TCP_S_CLOSING); break;
00489 case TCP_E_RCV_ACK: FSM_Goto(fsm, TCP_S_FIN_WAIT_2); break;
00490 case TCP_E_RCV_FIN_ACK: FSM_Goto(fsm, TCP_S_TIME_WAIT); break;
00491 case TCP_E_RCV_RST: FSM_Goto(fsm, TCP_S_CLOSED); break;
00492 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00493 default:;
00494 }
00495 break;
00496
00497 case TCP_S_FIN_WAIT_2:
00498 switch (event)
00499 {
00500 case TCP_E_ABORT: FSM_Goto(fsm, TCP_S_CLOSED); break;
00501 case TCP_E_RCV_FIN: FSM_Goto(fsm, TCP_S_TIME_WAIT); break;
00502 case TCP_E_TIMEOUT_FIN_WAIT_2: FSM_Goto(fsm, TCP_S_CLOSED); break;
00503 case TCP_E_RCV_RST: FSM_Goto(fsm, TCP_S_CLOSED); break;
00504 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00505 default:;
00506 }
00507 break;
00508
00509 case TCP_S_CLOSING:
00510 switch (event)
00511 {
00512 case TCP_E_ABORT: FSM_Goto(fsm, TCP_S_CLOSED); break;
00513 case TCP_E_RCV_ACK: FSM_Goto(fsm, TCP_S_TIME_WAIT); break;
00514 case TCP_E_RCV_RST: FSM_Goto(fsm, TCP_S_CLOSED); break;
00515 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00516 default:;
00517 }
00518 break;
00519
00520 case TCP_S_TIME_WAIT:
00521 switch (event)
00522 {
00523 case TCP_E_ABORT: FSM_Goto(fsm, TCP_S_CLOSED); break;
00524 case TCP_E_TIMEOUT_2MSL: FSM_Goto(fsm, TCP_S_CLOSED); break;
00525 case TCP_E_RCV_RST: FSM_Goto(fsm, TCP_S_CLOSED); break;
00526 case TCP_E_RCV_UNEXP_SYN: FSM_Goto(fsm, TCP_S_CLOSED); break;
00527 default:;
00528 }
00529 break;
00530
00531 case TCP_S_CLOSED:
00532 break;
00533 }
00534
00535 if (oldState!=fsm.getState())
00536 {
00537 tcpEV << "Transition: " << stateName(oldState) << " --> " << stateName(fsm.getState()) << " (event was: " << eventName(event) << ")\n";
00538 testingEV << tcpMain->getName() << ": " << stateName(oldState) << " --> " << stateName(fsm.getState()) << " (on " << eventName(event) << ")\n";
00539
00540
00541 stateEntered(fsm.getState());
00542 }
00543 else
00544 {
00545 tcpEV << "Staying in state: " << stateName(fsm.getState()) << " (event was: " << eventName(event) << ")\n";
00546 }
00547
00548 return fsm.getState()!=TCP_S_CLOSED;
00549 }
00550
00551 void TCPConnection::stateEntered(int state)
00552 {
00553
00554 switch (state)
00555 {
00556 case TCP_S_INIT:
00557
00558 break;
00559 case TCP_S_LISTEN:
00560
00561 ASSERT(connEstabTimer && synRexmitTimer);
00562 cancelEvent(connEstabTimer);
00563 cancelEvent(synRexmitTimer);
00564 break;
00565 case TCP_S_SYN_RCVD:
00566 case TCP_S_SYN_SENT:
00567 break;
00568 case TCP_S_ESTABLISHED:
00569
00570 delete cancelEvent(connEstabTimer);
00571 delete cancelEvent(synRexmitTimer);
00572 connEstabTimer = synRexmitTimer = NULL;
00573
00574 break;
00575 case TCP_S_CLOSE_WAIT:
00576 case TCP_S_LAST_ACK:
00577 case TCP_S_FIN_WAIT_1:
00578 case TCP_S_FIN_WAIT_2:
00579 case TCP_S_CLOSING:
00580 case TCP_S_TIME_WAIT:
00581
00582
00583 if (connEstabTimer) cancelEvent(connEstabTimer);
00584 if (synRexmitTimer) cancelEvent(synRexmitTimer);
00585 break;
00586 case TCP_S_CLOSED:
00587
00588 if (the2MSLTimer) cancelEvent(the2MSLTimer);
00589 if (connEstabTimer) cancelEvent(connEstabTimer);
00590 if (finWait2Timer) cancelEvent(finWait2Timer);
00591 if (synRexmitTimer) cancelEvent(synRexmitTimer);
00592 tcpAlgorithm->connectionClosed();
00593 break;
00594 }
00595 }
00596
00597