00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <string.h>
00020 #include <algorithm>
00021 #include "TCP_old.h"
00022 #include "TCPConnection_old.h"
00023 #include "TCPSegment.h"
00024 #include "TCPCommand_m.h"
00025 #include "IPControlInfo.h"
00026 #include "IPv6ControlInfo.h"
00027 #include "TCPSendQueue_old.h"
00028 #include "TCPReceiveQueue_old.h"
00029 #include "TCPAlgorithm_old.h"
00030
00031 using namespace tcp_old;
00032
00033
00034
00035
00036
00037 const char *TCPConnection::stateName(int state)
00038 {
00039 #define CASE(x) case x: s=#x+6; break
00040 const char *s = "unknown";
00041 switch (state)
00042 {
00043 CASE(TCP_S_INIT);
00044 CASE(TCP_S_CLOSED);
00045 CASE(TCP_S_LISTEN);
00046 CASE(TCP_S_SYN_SENT);
00047 CASE(TCP_S_SYN_RCVD);
00048 CASE(TCP_S_ESTABLISHED);
00049 CASE(TCP_S_CLOSE_WAIT);
00050 CASE(TCP_S_LAST_ACK);
00051 CASE(TCP_S_FIN_WAIT_1);
00052 CASE(TCP_S_FIN_WAIT_2);
00053 CASE(TCP_S_CLOSING);
00054 CASE(TCP_S_TIME_WAIT);
00055 }
00056 return s;
00057 #undef CASE
00058 }
00059
00060 const char *TCPConnection::eventName(int event)
00061 {
00062 #define CASE(x) case x: s=#x+6; break
00063 const char *s = "unknown";
00064 switch (event)
00065 {
00066 CASE(TCP_E_IGNORE);
00067 CASE(TCP_E_OPEN_ACTIVE);
00068 CASE(TCP_E_OPEN_PASSIVE);
00069 CASE(TCP_E_SEND);
00070 CASE(TCP_E_CLOSE);
00071 CASE(TCP_E_ABORT);
00072 CASE(TCP_E_STATUS);
00073 CASE(TCP_E_RCV_DATA);
00074 CASE(TCP_E_RCV_ACK);
00075 CASE(TCP_E_RCV_SYN);
00076 CASE(TCP_E_RCV_SYN_ACK);
00077 CASE(TCP_E_RCV_FIN);
00078 CASE(TCP_E_RCV_FIN_ACK);
00079 CASE(TCP_E_RCV_RST);
00080 CASE(TCP_E_RCV_UNEXP_SYN);
00081 CASE(TCP_E_TIMEOUT_2MSL);
00082 CASE(TCP_E_TIMEOUT_CONN_ESTAB);
00083 CASE(TCP_E_TIMEOUT_FIN_WAIT_2);
00084 }
00085 return s;
00086 #undef CASE
00087 }
00088
00089 const char *TCPConnection::indicationName(int code)
00090 {
00091 #define CASE(x) case x: s=#x+6; break
00092 const char *s = "unknown";
00093 switch (code)
00094 {
00095 CASE(TCP_I_DATA);
00096 CASE(TCP_I_URGENT_DATA);
00097 CASE(TCP_I_ESTABLISHED);
00098 CASE(TCP_I_PEER_CLOSED);
00099 CASE(TCP_I_CLOSED);
00100 CASE(TCP_I_CONNECTION_REFUSED);
00101 CASE(TCP_I_CONNECTION_RESET);
00102 CASE(TCP_I_TIMED_OUT);
00103 CASE(TCP_I_STATUS);
00104 }
00105 return s;
00106 #undef CASE
00107 }
00108
00109 void TCPConnection::printConnBrief()
00110 {
00111 tcpEV << "Connection ";
00112 tcpEV << localAddr << ":" << localPort << " to " << remoteAddr << ":" << remotePort;
00113 tcpEV << " on app[" << appGateIndex << "],connId=" << connId;
00114 tcpEV << " in " << stateName(fsm.getState());
00115 tcpEV << " (ptr=0x" << this << ")\n";
00116 }
00117
00118 void TCPConnection::printSegmentBrief(TCPSegment *tcpseg)
00119 {
00120 tcpEV << "." << tcpseg->getSrcPort() << " > ";
00121 tcpEV << "." << tcpseg->getDestPort() << ": ";
00122
00123 if (tcpseg->getSynBit()) tcpEV << (tcpseg->getAckBit() ? "SYN+ACK " : "SYN ");
00124 if (tcpseg->getFinBit()) tcpEV << "FIN(+ACK) ";
00125 if (tcpseg->getRstBit()) tcpEV << (tcpseg->getAckBit() ? "RST+ACK " : "RST ");
00126 if (tcpseg->getPshBit()) tcpEV << "PSH ";
00127
00128 if (tcpseg->getPayloadLength()>0 || tcpseg->getSynBit())
00129 {
00130 tcpEV << tcpseg->getSequenceNo() << ":" << tcpseg->getSequenceNo()+tcpseg->getPayloadLength();
00131 tcpEV << "(" << tcpseg->getPayloadLength() << ") ";
00132 }
00133 if (tcpseg->getAckBit()) tcpEV << "ack " << tcpseg->getAckNo() << " ";
00134 tcpEV << "win " << tcpseg->getWindow() << "\n";
00135 if (tcpseg->getUrgBit()) tcpEV << "urg " << tcpseg->getUrgentPointer() << " ";
00136 }
00137
00138 TCPConnection *TCPConnection::cloneListeningConnection()
00139 {
00140 TCPConnection *conn = new TCPConnection(tcpMain,appGateIndex,connId);
00141
00142
00143 const char *sendQueueClass = sendQueue->getClassName();
00144 conn->sendQueue = check_and_cast<TCPSendQueue *>(createOne(sendQueueClass));
00145 conn->sendQueue->setConnection(conn);
00146
00147 const char *receiveQueueClass = receiveQueue->getClassName();
00148 conn->receiveQueue = check_and_cast<TCPReceiveQueue *>(createOne(receiveQueueClass));
00149 conn->receiveQueue->setConnection(conn);
00150
00151 const char *tcpAlgorithmClass = tcpAlgorithm->getClassName();
00152 conn->tcpAlgorithm = check_and_cast<TCPAlgorithm *>(createOne(tcpAlgorithmClass));
00153 conn->tcpAlgorithm->setConnection(conn);
00154
00155 conn->state = conn->tcpAlgorithm->getStateVariables();
00156 configureStateVariables();
00157 conn->tcpAlgorithm->initialize();
00158
00159
00160 conn->state->active = false;
00161 conn->state->fork = true;
00162 conn->localAddr = localAddr;
00163 conn->localPort = localPort;
00164 FSM_Goto(conn->fsm, TCP_S_LISTEN);
00165
00166 return conn;
00167 }
00168
00169 void TCPConnection::sendToIP(TCPSegment *tcpseg)
00170 {
00171
00172 if (sndNxtVector && tcpseg->getPayloadLength()!=0)
00173 sndNxtVector->record(tcpseg->getSequenceNo());
00174 if (sndAckVector) sndAckVector->record(tcpseg->getAckNo());
00175
00176
00177 tcpseg->setSrcPort(localPort);
00178 tcpseg->setDestPort(remotePort);
00179 tcpseg->setByteLength(TCP_HEADER_OCTETS+tcpseg->getPayloadLength());
00180
00181
00182 tcpEV << "Sending: ";
00183 printSegmentBrief(tcpseg);
00184
00185
00186
00187 if (!remoteAddr.isIPv6())
00188 {
00189
00190 IPControlInfo *controlInfo = new IPControlInfo();
00191 controlInfo->setProtocol(IP_PROT_TCP);
00192 controlInfo->setSrcAddr(localAddr.get4());
00193 controlInfo->setDestAddr(remoteAddr.get4());
00194 tcpseg->setControlInfo(controlInfo);
00195
00196 tcpMain->send(tcpseg,"ipOut");
00197 }
00198 else
00199 {
00200
00201 IPv6ControlInfo *controlInfo = new IPv6ControlInfo();
00202 controlInfo->setProtocol(IP_PROT_TCP);
00203 controlInfo->setSrcAddr(localAddr.get6());
00204 controlInfo->setDestAddr(remoteAddr.get6());
00205 tcpseg->setControlInfo(controlInfo);
00206
00207 tcpMain->send(tcpseg,"ipv6Out");
00208 }
00209 }
00210
00211 void TCPConnection::sendToIP(TCPSegment *tcpseg, IPvXAddress src, IPvXAddress dest)
00212 {
00213 tcpEV << "Sending: ";
00214 printSegmentBrief(tcpseg);
00215
00216 if (!dest.isIPv6())
00217 {
00218
00219 IPControlInfo *controlInfo = new IPControlInfo();
00220 controlInfo->setProtocol(IP_PROT_TCP);
00221 controlInfo->setSrcAddr(src.get4());
00222 controlInfo->setDestAddr(dest.get4());
00223 tcpseg->setControlInfo(controlInfo);
00224
00225 check_and_cast<TCP *>(simulation.getContextModule())->send(tcpseg,"ipOut");
00226 }
00227 else
00228 {
00229
00230 IPv6ControlInfo *controlInfo = new IPv6ControlInfo();
00231 controlInfo->setProtocol(IP_PROT_TCP);
00232 controlInfo->setSrcAddr(src.get6());
00233 controlInfo->setDestAddr(dest.get6());
00234 tcpseg->setControlInfo(controlInfo);
00235
00236 check_and_cast<TCP *>(simulation.getContextModule())->send(tcpseg,"ipv6Out");
00237 }
00238 }
00239
00240 TCPSegment *TCPConnection::createTCPSegment(const char *name)
00241 {
00242 return new TCPSegment(name);
00243 }
00244
00245 void TCPConnection::signalConnectionTimeout()
00246 {
00247 sendIndicationToApp(TCP_I_TIMED_OUT);
00248 }
00249
00250 void TCPConnection::sendIndicationToApp(int code)
00251 {
00252 tcpEV << "Notifying app: " << indicationName(code) << "\n";
00253 cMessage *msg = new cMessage(indicationName(code));
00254 msg->setKind(code);
00255 TCPCommand *ind = new TCPCommand();
00256 ind->setConnId(connId);
00257 msg->setControlInfo(ind);
00258 tcpMain->send(msg, "appOut", appGateIndex);
00259 }
00260
00261 void TCPConnection::sendEstabIndicationToApp()
00262 {
00263 tcpEV << "Notifying app: " << indicationName(TCP_I_ESTABLISHED) << "\n";
00264 cMessage *msg = new cMessage(indicationName(TCP_I_ESTABLISHED));
00265 msg->setKind(TCP_I_ESTABLISHED);
00266
00267 TCPConnectInfo *ind = new TCPConnectInfo();
00268 ind->setConnId(connId);
00269 ind->setLocalAddr(localAddr);
00270 ind->setRemoteAddr(remoteAddr);
00271 ind->setLocalPort(localPort);
00272 ind->setRemotePort(remotePort);
00273
00274 msg->setControlInfo(ind);
00275 tcpMain->send(msg, "appOut", appGateIndex);
00276 }
00277
00278 void TCPConnection::sendToApp(cMessage *msg)
00279 {
00280 tcpMain->send(msg, "appOut", appGateIndex);
00281 }
00282
00283 void TCPConnection::initConnection(TCPOpenCommand *openCmd)
00284 {
00285
00286 const char *sendQueueClass = openCmd->getSendQueueClass();
00287 if (!sendQueueClass || !sendQueueClass[0])
00288 sendQueueClass = tcpMain->par("sendQueueClass");
00289 sendQueue = check_and_cast<TCPSendQueue *>(createOne(sendQueueClass));
00290 sendQueue->setConnection(this);
00291
00292 const char *receiveQueueClass = openCmd->getReceiveQueueClass();
00293 if (!receiveQueueClass || !receiveQueueClass[0])
00294 receiveQueueClass = tcpMain->par("receiveQueueClass");
00295 receiveQueue = check_and_cast<TCPReceiveQueue *>(createOne(receiveQueueClass));
00296 receiveQueue->setConnection(this);
00297
00298
00299 const char *tcpAlgorithmClass = openCmd->getTcpAlgorithmClass();
00300 if (!tcpAlgorithmClass || !tcpAlgorithmClass[0])
00301 tcpAlgorithmClass = tcpMain->par("tcpAlgorithmClass");
00302 tcpAlgorithm = check_and_cast<TCPAlgorithm *>(createOne(tcpAlgorithmClass));
00303 tcpAlgorithm->setConnection(this);
00304
00305
00306 state = tcpAlgorithm->getStateVariables();
00307 configureStateVariables();
00308 tcpAlgorithm->initialize();
00309 }
00310
00311 void TCPConnection::configureStateVariables()
00312 {
00313 state->snd_mss = tcpMain->par("mss").longValue();
00314 long advertisedWindowPar = tcpMain->par("advertisedWindow").longValue();
00315 if (advertisedWindowPar > TCP_MAX_WIN || advertisedWindowPar <= 0)
00316 throw cRuntimeError("Invalid advertisedWindow parameter: %d", advertisedWindowPar);
00317 state->rcv_wnd = advertisedWindowPar;
00318 }
00319
00320 void TCPConnection::selectInitialSeqNum()
00321 {
00322
00323 state->iss = (unsigned long)fmod(SIMTIME_DBL(simTime())*250000.0, 1.0+(double)(unsigned)0xffffffffUL) & 0xffffffffUL;
00324
00325 state->snd_una = state->snd_nxt = state->snd_max = state->iss;
00326
00327 sendQueue->init(state->iss+1);
00328 }
00329
00330 bool TCPConnection::isSegmentAcceptable(TCPSegment *tcpseg)
00331 {
00332
00333
00334 return seqGE(tcpseg->getSequenceNo(),state->rcv_nxt) &&
00335 seqLE(tcpseg->getSequenceNo()+tcpseg->getPayloadLength(),state->rcv_nxt+state->rcv_wnd);
00336 }
00337
00338 void TCPConnection::sendSyn()
00339 {
00340 if (remoteAddr.isUnspecified() || remotePort==-1)
00341 opp_error("Error processing command OPEN_ACTIVE: foreign socket unspecified");
00342 if (localPort==-1)
00343 opp_error("Error processing command OPEN_ACTIVE: local port unspecified");
00344
00345
00346 TCPSegment *tcpseg = createTCPSegment("SYN");
00347 tcpseg->setSequenceNo(state->iss);
00348 tcpseg->setSynBit(true);
00349 tcpseg->setWindow(state->rcv_wnd);
00350
00351 state->snd_max = state->snd_nxt = state->iss+1;
00352
00353
00354 sendToIP(tcpseg);
00355 }
00356
00357 void TCPConnection::sendSynAck()
00358 {
00359
00360 TCPSegment *tcpseg = createTCPSegment("SYN+ACK");
00361 tcpseg->setSequenceNo(state->iss);
00362 tcpseg->setAckNo(state->rcv_nxt);
00363 tcpseg->setSynBit(true);
00364 tcpseg->setAckBit(true);
00365 tcpseg->setWindow(state->rcv_wnd);
00366
00367 state->snd_max = state->snd_nxt = state->iss+1;
00368
00369
00370 sendToIP(tcpseg);
00371
00372
00373 tcpAlgorithm->ackSent();
00374 }
00375
00376 void TCPConnection::sendRst(uint32 seqNo)
00377 {
00378 sendRst(seqNo, localAddr, remoteAddr, localPort, remotePort);
00379 }
00380
00381 void TCPConnection::sendRst(uint32 seq, IPvXAddress src, IPvXAddress dest, int srcPort, int destPort)
00382 {
00383 TCPSegment *tcpseg = createTCPSegment("RST");
00384
00385 tcpseg->setSrcPort(srcPort);
00386 tcpseg->setDestPort(destPort);
00387
00388 tcpseg->setRstBit(true);
00389 tcpseg->setSequenceNo(seq);
00390
00391
00392 sendToIP(tcpseg, src, dest);
00393 }
00394
00395 void TCPConnection::sendRstAck(uint32 seq, uint32 ack, IPvXAddress src, IPvXAddress dest, int srcPort, int destPort)
00396 {
00397 TCPSegment *tcpseg = createTCPSegment("RST+ACK");
00398
00399 tcpseg->setSrcPort(srcPort);
00400 tcpseg->setDestPort(destPort);
00401
00402 tcpseg->setRstBit(true);
00403 tcpseg->setAckBit(true);
00404 tcpseg->setSequenceNo(seq);
00405 tcpseg->setAckNo(ack);
00406
00407
00408 sendToIP(tcpseg, src, dest);
00409
00410
00411 tcpAlgorithm->ackSent();
00412 }
00413
00414 void TCPConnection::sendAck()
00415 {
00416 TCPSegment *tcpseg = createTCPSegment("ACK");
00417
00418 tcpseg->setAckBit(true);
00419 tcpseg->setSequenceNo(state->snd_nxt);
00420 tcpseg->setAckNo(state->rcv_nxt);
00421 tcpseg->setWindow(state->rcv_wnd);
00422
00423
00424 sendToIP(tcpseg);
00425
00426
00427 tcpAlgorithm->ackSent();
00428 }
00429
00430 void TCPConnection::sendFin()
00431 {
00432 TCPSegment *tcpseg = createTCPSegment("FIN");
00433
00434
00435
00436 tcpseg->setFinBit(true);
00437 tcpseg->setAckBit(true);
00438 tcpseg->setAckNo(state->rcv_nxt);
00439 tcpseg->setSequenceNo(state->snd_nxt);
00440 tcpseg->setWindow(state->rcv_wnd);
00441
00442
00443 sendToIP(tcpseg);
00444
00445
00446 tcpAlgorithm->ackSent();
00447 }
00448
00449 void TCPConnection::sendSegment(uint32 bytes)
00450 {
00451 ulong buffered = sendQueue->getBytesAvailable(state->snd_nxt);
00452 if (bytes > buffered)
00453 bytes = buffered;
00454
00455
00456 TCPSegment *tcpseg = sendQueue->createSegmentWithBytes(state->snd_nxt, bytes);
00457 tcpseg->setAckNo(state->rcv_nxt);
00458 tcpseg->setAckBit(true);
00459 tcpseg->setWindow(state->rcv_wnd);
00460
00461
00462 ASSERT(bytes==tcpseg->getPayloadLength());
00463
00464 state->snd_nxt += bytes;
00465
00466
00467 if (state->afterRto && seqGE(state->snd_nxt, state->snd_max))
00468 state->afterRto = false;
00469
00470 if (state->send_fin && state->snd_nxt==state->snd_fin_seq)
00471 {
00472 tcpEV << "Setting FIN on segment\n";
00473 tcpseg->setFinBit(true);
00474 state->snd_nxt = state->snd_fin_seq+1;
00475 }
00476
00477 sendToIP(tcpseg);
00478 }
00479
00480 bool TCPConnection::sendData(bool fullSegmentsOnly, int congestionWindow)
00481 {
00482 if (!state->afterRto)
00483 {
00484
00485 state->snd_nxt = state->snd_max;
00486 }
00487
00488
00489 ulong buffered = sendQueue->getBytesAvailable(state->snd_nxt);
00490 if (buffered==0)
00491 return false;
00492
00493
00494 long maxWindow = state->snd_wnd;
00495 if (congestionWindow>=0 && maxWindow > congestionWindow)
00496 maxWindow = congestionWindow;
00497
00498
00499 long effectiveWin = maxWindow - (state->snd_nxt - state->snd_una);
00500 if (effectiveWin <= 0)
00501 {
00502 tcpEV << "Effective window is zero (advertised window " << state->snd_wnd <<
00503 ", congestion window " << congestionWindow << "), cannot send.\n";
00504 return false;
00505 }
00506
00507 ulong bytesToSend = effectiveWin;
00508
00509 if (bytesToSend > buffered)
00510 bytesToSend = buffered;
00511
00512 if (fullSegmentsOnly && bytesToSend < state->snd_mss && buffered > (ulong) effectiveWin)
00513 {
00514 tcpEV << "Cannot send, not enough data for a full segment (SMSS=" << state->snd_mss
00515 << ", in buffer " << buffered << ")\n";
00516 return false;
00517 }
00518
00519
00520 tcpEV << "Will send " << bytesToSend << " bytes (effectiveWindow " << effectiveWin
00521 << ", in buffer " << buffered << " bytes)\n";
00522
00523 uint32 old_snd_nxt = state->snd_nxt;
00524 ASSERT(bytesToSend>0);
00525
00526 #ifdef TCP_SENDFRAGMENTS
00527
00528 while (bytesToSend>0)
00529 {
00530 ulong bytes = std::min(bytesToSend, state->snd_mss);
00531 sendSegment(bytes);
00532 bytesToSend -= bytes;
00533 }
00534 #else
00535
00536
00537 if (bytesToSend <= state->snd_mss)
00538 {
00539 sendSegment(bytesToSend);
00540 }
00541 else
00542 {
00543
00544 while (bytesToSend>=state->snd_mss)
00545 {
00546 sendSegment(state->snd_mss);
00547 bytesToSend -= state->snd_mss;
00548 }
00549
00550 buffered = sendQueue->getBytesAvailable(state->snd_nxt);
00551 if (bytesToSend==buffered && buffered!=0)
00552 sendSegment(bytesToSend);
00553 else if (bytesToSend>0)
00554 tcpEV << bytesToSend << " bytes of space left in effectiveWindow\n";
00555 }
00556 #endif
00557
00558
00559
00560
00561 if (seqGreater(state->snd_nxt, state->snd_max))
00562 state->snd_max = state->snd_nxt;
00563 if (unackedVector) unackedVector->record(state->snd_max - state->snd_una);
00564
00565
00566 tcpAlgorithm->ackSent();
00567 tcpAlgorithm->dataSent(old_snd_nxt);
00568
00569 return true;
00570 }
00571
00572 bool TCPConnection::sendProbe()
00573 {
00574
00575 state->snd_nxt = state->snd_max;
00576
00577
00578 if (sendQueue->getBytesAvailable(state->snd_nxt)==0)
00579 {
00580 tcpEV << "Cannot send probe because send buffer is empty\n";
00581 return false;
00582 }
00583
00584 uint32 old_snd_nxt = state->snd_nxt;
00585
00586 tcpEV << "Sending 1 byte as probe, with seq=" << state->snd_nxt << "\n";
00587 sendSegment(1);
00588
00589
00590
00591
00592 state->snd_max = state->snd_nxt;
00593 if (unackedVector) unackedVector->record(state->snd_max - state->snd_una);
00594
00595
00596 tcpAlgorithm->ackSent();
00597 tcpAlgorithm->dataSent(old_snd_nxt);
00598
00599 return true;
00600 }
00601
00602 void TCPConnection::retransmitOneSegment(bool called_at_rto)
00603 {
00604
00605 uint32 old_snd_nxt = state->snd_nxt;
00606
00607 state->snd_nxt = state->snd_una;
00608
00609 ulong bytes = std::min(state->snd_mss, state->snd_max - state->snd_nxt);
00610 ASSERT(bytes!=0);
00611
00612 sendSegment(bytes);
00613
00614 if (!called_at_rto)
00615 {
00616 if (seqGreater(old_snd_nxt, state->snd_nxt))
00617 state->snd_nxt = old_snd_nxt;
00618 }
00619
00620 tcpAlgorithm->ackSent();
00621 }
00622
00623 void TCPConnection::retransmitData()
00624 {
00625
00626 state->snd_nxt = state->snd_una;
00627
00628 uint32 bytesToSend = state->snd_max - state->snd_nxt;
00629 ASSERT(bytesToSend!=0);
00630
00631
00632 while (bytesToSend>0)
00633 {
00634 uint32 bytes = std::min(bytesToSend, state->snd_mss);
00635 bytes = std::min(bytes, (uint32)(sendQueue->getBytesAvailable(state->snd_nxt)));
00636 sendSegment(bytes);
00637
00638
00639 if (state->send_fin && state->snd_nxt==state->snd_fin_seq+1)
00640 break;
00641 bytesToSend -= bytes;
00642 }
00643 }
00644
00645