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