00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00031 #include <omnetpp.h>
00032
00033 #include <CommonMessages_m.h>
00034 #include <GlobalNodeListAccess.h>
00035 #include <GlobalStatisticsAccess.h>
00036
00037 #include <SimpleInfo.h>
00038 #include <SimpleUDP.h>
00039 #include "IPDatagram_m.h"
00040 #include "TCPSegment.h"
00041 #include "SimpleTCP.h"
00042 #include "TCPCommand_m.h"
00043 #include "IPControlInfo.h"
00044 #include "IPv6ControlInfo.h"
00045 #include "ICMPMessage_m.h"
00046 #include "ICMPv6Message_m.h"
00047 #include "IPAddressResolver.h"
00048 #include "TCPSendQueue.h"
00049 #include "TCPSACKRexmitQueue.h"
00050 #include "TCPReceiveQueue.h"
00051 #include "TCPAlgorithm.h"
00052
00053 #define EPHEMERAL_PORTRANGE_START 1024
00054 #define EPHEMERAL_PORTRANGE_END 5000
00055
00056 Define_Module( SimpleTCP );
00057
00058
00059
00060 static std::ostream& operator<<(std::ostream& os, const TCP::SockPair& sp)
00061 {
00062 os << "loc=" << IPvXAddress(sp.localAddr) << ":" << sp.localPort << " "
00063 << "rem=" << IPvXAddress(sp.remoteAddr) << ":" << sp.remotePort;
00064 return os;
00065 }
00066
00067 static std::ostream& operator<<(std::ostream& os, const TCP::AppConnKey& app)
00068 {
00069 os << "connId=" << app.connId << " appGateIndex=" << app.appGateIndex;
00070 return os;
00071 }
00072
00073 static std::ostream& operator<<(std::ostream& os, const TCPConnection& conn)
00074 {
00075 os << "connId=" << conn.connId << " " << TCPConnection::stateName(conn.getFsmState())
00076 << " state={" << const_cast<TCPConnection&>(conn).getState()->info() << "}";
00077 return os;
00078 }
00079
00080 void SimpleTCP::initialize(int stage)
00081 {
00082 if (stage == MIN_STAGE_UNDERLAY) {
00083 lastEphemeralPort = EPHEMERAL_PORTRANGE_START;
00084 WATCH(lastEphemeralPort);
00085
00086 WATCH_PTRMAP(tcpConnMap);
00087 WATCH_PTRMAP(tcpAppConnMap);
00088
00089 recordStatistics = par("recordStats");
00090
00091 cModule *netw = simulation.getSystemModule();
00092 testing = netw->hasPar("testing") && netw->par("testing").boolValue();
00093 logverbose = !testing && netw->hasPar("logverbose") && netw->par("logverbose").boolValue();
00094
00095
00096
00097 sad.numSent = 0;
00098 sad.numQueueLost = 0;
00099 sad.numPartitionLost = 0;
00100 sad.numDestUnavailableLost = 0;
00101 WATCH(sad.numQueueLost);
00102 WATCH(sad.numPartitionLost);
00103 WATCH(sad.numDestUnavailableLost);
00104
00105 sad.globalNodeList = GlobalNodeListAccess().get();
00106 sad.globalStatistics = GlobalStatisticsAccess().get();
00107 sad.constantDelay = par("constantDelay");
00108 sad.useCoordinateBasedDelay = par("useCoordinateBasedDelay");
00109
00110 sad.delayFaultTypeString = par("delayFaultType").stdstringValue();
00111 sad.delayFaultTypeMap["live_all"] = sad.delayFaultLiveAll;
00112 sad.delayFaultTypeMap["live_planetlab"] = sad.delayFaultLivePlanetlab;
00113 sad.delayFaultTypeMap["simulation"] = sad.delayFaultSimulation;
00114
00115 switch (sad.delayFaultTypeMap[sad.delayFaultTypeString]) {
00116 case StatisticsAndDelay::delayFaultLiveAll:
00117 case StatisticsAndDelay::delayFaultLivePlanetlab:
00118 case StatisticsAndDelay::delayFaultSimulation:
00119 sad.faultyDelay = true;
00120 break;
00121 default:
00122 sad.faultyDelay = false;
00123 }
00124
00125 sad.jitter = par("jitter");
00126 sad.nodeEntry = NULL;
00127 WATCH_PTR(sad.nodeEntry);
00128 }
00129 }
00130
00131 void SimpleTCP::finish()
00132 {
00133 sad.globalStatistics->addStdDev("SimpleTCP: Packets sent",
00134 sad.numSent);
00135 sad.globalStatistics->addStdDev("SimpleTCP: Packets dropped due to queue overflows",
00136 sad.numQueueLost);
00137 sad.globalStatistics->addStdDev("SimpleTCP: Packets dropped due to network partitions",
00138 sad.numPartitionLost);
00139 sad.globalStatistics->addStdDev("SimpleTCP: Packets dropped due to unavailable destination",
00140 sad.numDestUnavailableLost);
00141 }
00142
00143 void SimpleTCP::handleMessage(cMessage *msg)
00144 {
00145 if (msg->isSelfMessage())
00146 {
00147 SimpleTCPConnection *conn = (SimpleTCPConnection *) msg->getContextPointer();
00148 bool ret = conn->processTimer(msg);
00149 if (!ret)
00150 removeConnection(conn);
00151 }
00152 else if (msg->arrivedOn("ipIn") || msg->arrivedOn("ipv6In"))
00153 {
00154 if (dynamic_cast<ICMPMessage *>(msg) || dynamic_cast<ICMPv6Message *>(msg))
00155 {
00156 tcpEV << "ICMP error received -- discarding\n";
00157 delete msg;
00158 }
00159 else
00160 {
00161
00162 TCPSegment *tcpseg = check_and_cast<TCPSegment *>(msg);
00163
00164
00165 IPvXAddress srcAddr, destAddr;
00166 if (dynamic_cast<IPControlInfo *>(tcpseg->getControlInfo())!=NULL)
00167 {
00168 IPControlInfo *controlInfo = (IPControlInfo *)tcpseg->removeControlInfo();
00169 srcAddr = controlInfo->getSrcAddr();
00170 destAddr = controlInfo->getDestAddr();
00171 delete controlInfo;
00172 }
00173 else if (dynamic_cast<IPv6ControlInfo *>(tcpseg->getControlInfo())!=NULL)
00174 {
00175 IPv6ControlInfo *controlInfo = (IPv6ControlInfo *)tcpseg->removeControlInfo();
00176 srcAddr = controlInfo->getSrcAddr();
00177 destAddr = controlInfo->getDestAddr();
00178 delete controlInfo;
00179 }
00180 else
00181 {
00182 error("(%s)%s arrived without control info", tcpseg->getClassName(), tcpseg->getName());
00183 }
00184
00185
00186 SimpleTCPConnection *conn = dynamic_cast<SimpleTCPConnection*>(findConnForSegment(tcpseg, srcAddr, destAddr));
00187
00188 if (conn)
00189 {
00190 bool ret = conn->processTCPSegment(tcpseg, srcAddr, destAddr);
00191 if (!ret)
00192 removeConnection(conn);
00193 }
00194 else
00195 {
00196 segmentArrivalWhileClosed(tcpseg, srcAddr, destAddr);
00197 }
00198 }
00199 }
00200 else
00201 {
00202 TCPCommand *controlInfo = check_and_cast<TCPCommand *>(msg->getControlInfo());
00203 int appGateIndex = msg->getArrivalGate()->getIndex();
00204 int connId = controlInfo->getConnId();
00205
00206 SimpleTCPConnection *conn = (SimpleTCPConnection*)findConnForApp(appGateIndex, connId);
00207
00208 if (!conn)
00209 {
00210 conn = createConnection(appGateIndex, connId);
00211
00212
00213
00214 AppConnKey key;
00215 key.appGateIndex = appGateIndex;
00216 key.connId = connId;
00217 tcpAppConnMap[key] = conn;
00218
00219 tcpEV << "TCP connection created for " << msg << "\n";
00220 }
00221 bool ret = conn->processAppCommand(msg);
00222 if (!ret)
00223 removeConnection(conn);
00224 }
00225
00226 if (ev.isGUI())
00227 updateDisplayString();
00228 }
00229
00230 void SimpleTCP::setNodeEntry(SimpleNodeEntry* entry)
00231 {
00232 sad.nodeEntry = entry;
00233 }
00234
00235 SimpleTCPConnection *SimpleTCP::createConnection(int appGateIndex, int connId)
00236 {
00237 return new SimpleTCPConnection(this, appGateIndex, connId);
00238 }
00239
00240 void SimpleTCP::segmentArrivalWhileClosed(TCPSegment *tcpseg, IPvXAddress srcAddr, IPvXAddress destAddr)
00241 {
00242 SimpleTCPConnection *tmp = new SimpleTCPConnection();
00243 tmp->segmentArrivalWhileClosed(tcpseg, srcAddr, destAddr);
00244 delete tmp;
00245 delete tcpseg;
00246 }
00247
00248 SimpleTCPConnection *SimpleTCPConnection::cloneListeningConnection()
00249 {
00250 SimpleTCPConnection *conn = new SimpleTCPConnection(tcpMain,appGateIndex,connId);
00251
00252
00253 const char *sendQueueClass = sendQueue->getClassName();
00254 conn->sendQueue = check_and_cast<TCPSendQueue *>(createOne(sendQueueClass));
00255 conn->sendQueue->setConnection(conn);
00256
00257 const char *receiveQueueClass = receiveQueue->getClassName();
00258 conn->receiveQueue = check_and_cast<TCPReceiveQueue *>(createOne(receiveQueueClass));
00259 conn->receiveQueue->setConnection(conn);
00260
00261
00262 rexmitQueue = new TCPSACKRexmitQueue();
00263 rexmitQueue->setConnection(this);
00264
00265 const char *tcpAlgorithmClass = tcpAlgorithm->getClassName();
00266 conn->tcpAlgorithm = check_and_cast<TCPAlgorithm *>(createOne(tcpAlgorithmClass));
00267 conn->tcpAlgorithm->setConnection(conn);
00268
00269 conn->state = conn->tcpAlgorithm->getStateVariables();
00270 configureStateVariables();
00271 conn->tcpAlgorithm->initialize();
00272
00273
00274 conn->state->active = false;
00275 conn->state->fork = true;
00276 conn->localAddr = localAddr;
00277 conn->localPort = localPort;
00278 FSM_Goto(conn->fsm, TCP_S_LISTEN);
00279
00280 return conn;
00281 }
00282
00283
00284 void SimpleTCPConnection::sendRst(uint32 seq, IPvXAddress src, IPvXAddress dest, int srcPort, int destPort)
00285 {
00286 TCPSegment *tcpseg = createTCPSegment("RST");
00287
00288 tcpseg->setSrcPort(srcPort);
00289 tcpseg->setDestPort(destPort);
00290
00291 tcpseg->setRstBit(true);
00292 tcpseg->setSequenceNo(seq);
00293
00294
00295 SimpleTCPConnection::sendToIP(tcpseg, src, dest);
00296 }
00297
00298 void SimpleTCPConnection::sendRstAck(uint32 seq, uint32 ack, IPvXAddress src, IPvXAddress dest, int srcPort, int destPort)
00299 {
00300 TCPSegment *tcpseg = createTCPSegment("RST+ACK");
00301
00302 tcpseg->setSrcPort(srcPort);
00303 tcpseg->setDestPort(destPort);
00304
00305 tcpseg->setRstBit(true);
00306 tcpseg->setAckBit(true);
00307 tcpseg->setSequenceNo(seq);
00308 tcpseg->setAckNo(ack);
00309
00310
00311 SimpleTCPConnection::sendToIP(tcpseg, src, dest);
00312 }
00313
00314 void SimpleTCPConnection::sendToIP(TCPSegment *tcpseg)
00315 {
00316 StatisticsAndDelay& sad = dynamic_cast<SimpleTCP*>(tcpMain)->sad;
00317
00318 if (sndNxtVector && tcpseg->getPayloadLength()!=0)
00319 sndNxtVector->record(tcpseg->getSequenceNo());
00320 if (sndAckVector)
00321 sndAckVector->record(tcpseg->getAckNo());
00322
00323
00324 tcpseg->setSrcPort(localPort);
00325 tcpseg->setDestPort(remotePort);
00326 ASSERT(tcpseg->getHeaderLength() >= TCP_HEADER_OCTETS);
00327 ASSERT(tcpseg->getHeaderLength() <= TCP_MAX_HEADER_OCTETS);
00328
00329
00330 int ipHeaderBytes = 0;
00331 if (remoteAddr.isIPv6()) {
00332 ipHeaderBytes = IPv6_HEADER_BYTES;
00333 } else {
00334 ipHeaderBytes = IP_HEADER_BYTES;
00335 }
00336 tcpseg->setByteLength(tcpseg->getHeaderLength() +
00337 tcpseg->getPayloadLength() + ipHeaderBytes);
00338
00339 tcpEV << "Sending: ";
00340 printSegmentBrief(tcpseg);
00341
00342
00343
00344
00345
00346
00347 const IPvXAddress& src = IPAddressResolver().addressOf(tcpMain->getParentModule());
00348
00349 const IPvXAddress& dest = remoteAddr;
00350
00351 SimpleInfo* info = dynamic_cast<SimpleInfo*>(sad.globalNodeList->getPeerInfo(dest));
00352 sad.numSent++;
00353
00354 if (info == NULL) {
00355 EV << "[SimpleTCPConnection::sendToIP() @ " << src << "]\n"
00356 << " No route to host " << dest
00357 << endl;
00358
00359 delete tcpseg;
00360 sad.numDestUnavailableLost++;
00361 return;
00362 }
00363
00364 SimpleNodeEntry* destEntry = info->getEntry();
00365
00366
00367 simtime_t totalDelay = 0;
00368 if (src != dest) {
00369 SimpleNodeEntry::SimpleDelay temp;
00370 if (sad.faultyDelay) {
00371 SimpleInfo* thisInfo = static_cast<SimpleInfo*>(sad.globalNodeList->getPeerInfo(src));
00372 temp = sad.nodeEntry->calcDelay(tcpseg, *destEntry,
00373 !(thisInfo->getNpsLayer() == 0 ||
00374 info->getNpsLayer() == 0));
00375 } else {
00376 temp = sad.nodeEntry->calcDelay(tcpseg, *destEntry);
00377 }
00378 if (sad.useCoordinateBasedDelay == false) {
00379 totalDelay = sad.constantDelay;
00380 } else if (temp.second == false) {
00381 EV << "[SimpleTCPConnection::sendToIP() @ " << src << "]\n"
00382 << " Send queue full: packet " << tcpseg << " dropped"
00383 << endl;
00384 delete tcpseg;
00385 sad.numQueueLost++;
00386 return;
00387 } else {
00388 totalDelay = temp.first;
00389 }
00390 }
00391
00392 SimpleInfo* thisInfo = dynamic_cast<SimpleInfo*>(sad.globalNodeList->getPeerInfo(src));
00393
00394 if (!sad.globalNodeList->areNodeTypesConnected(thisInfo->getTypeID(), info->getTypeID())) {
00395 EV << "[SimpleTCPConnection::sendToIP() @ " << src << "]\n"
00396 << " Partition " << thisInfo->getTypeID() << "->" << info->getTypeID()
00397 << " is not connected"
00398 << endl;
00399 delete tcpseg;
00400 sad.numPartitionLost++;
00401 return;
00402 }
00403
00404 if (sad.jitter) {
00405
00406
00407
00408
00409 double temp = truncnormal(0, SIMTIME_DBL(totalDelay) * sad.jitter);
00410 while (temp == INFINITY || temp != temp) {
00411 std::cerr << "\n******* SimpleTCPConnection: truncnormal() -> inf !!\n"
00412 << std::endl;
00413 temp = truncnormal(0, SIMTIME_DBL(totalDelay) * sad.jitter);
00414 }
00415
00416 totalDelay += temp;
00417 }
00418
00419
00420
00421 EV << "[SimpleTCPConnection::sendToIP() @ " << src << "]\n"
00422 << " Packet " << tcpseg << " sent with delay = " << totalDelay
00423 << endl;
00424
00425
00426
00427
00428
00429
00430 if (!remoteAddr.isIPv6())
00431 {
00432
00433 IPControlInfo *controlInfo = new IPControlInfo();
00434 controlInfo->setProtocol(IP_PROT_TCP);
00435 controlInfo->setSrcAddr(src.get4());
00436 controlInfo->setDestAddr(dest.get4());
00437 tcpseg->setControlInfo(controlInfo);
00438
00439 tcpMain->sendDirect(tcpseg, totalDelay, 0, destEntry->getTcpIPv4Gate());
00440 }
00441 else
00442 {
00443
00444 IPv6ControlInfo *controlInfo = new IPv6ControlInfo();
00445 controlInfo->setProtocol(IP_PROT_TCP);
00446 controlInfo->setSrcAddr(src.get6());
00447 controlInfo->setDestAddr(dest.get6());
00448 tcpseg->setControlInfo(controlInfo);
00449
00450 tcpMain->sendDirect(tcpseg, totalDelay, 0, destEntry->getTcpIPv6Gate());
00451 }
00452 }
00453
00454 void SimpleTCPConnection::sendToIP(TCPSegment *tcpseg, IPvXAddress src, IPvXAddress dest)
00455 {
00456
00457
00458 StatisticsAndDelay& sad = dynamic_cast<SimpleTCP*>(tcpMain)->sad;
00459
00460 SimpleInfo* info = dynamic_cast<SimpleInfo*>(sad.globalNodeList->getPeerInfo(dest));
00461 sad.numSent++;
00462
00463 if (info == NULL) {
00464 EV << "[SimpleTCPConnection::sendToIP() @ " << src << "]\n"
00465 << " No route to host " << dest
00466 << endl;
00467
00468 delete tcpseg;
00469 sad.numDestUnavailableLost++;
00470 return;
00471 }
00472
00473 SimpleNodeEntry* destEntry = info->getEntry();
00474
00475
00476 simtime_t totalDelay = 0;
00477 if (src != dest) {
00478 SimpleNodeEntry::SimpleDelay temp;
00479 if (sad.faultyDelay) {
00480 SimpleInfo* thisInfo = static_cast<SimpleInfo*>(sad.globalNodeList->getPeerInfo(src));
00481 temp = sad.nodeEntry->calcDelay(tcpseg, *destEntry,
00482 !(thisInfo->getNpsLayer() == 0 ||
00483 info->getNpsLayer() == 0));
00484 } else {
00485 temp = sad.nodeEntry->calcDelay(tcpseg, *destEntry);
00486 }
00487 if (sad.useCoordinateBasedDelay == false) {
00488 totalDelay = sad.constantDelay;
00489 } else if (temp.second == false) {
00490 EV << "[SimpleTCPConnection::sendToIP() @ " << src << "]\n"
00491 << " Send queue full: packet " << tcpseg << " dropped"
00492 << endl;
00493 delete tcpseg;
00494 sad.numQueueLost++;
00495 return;
00496 } else {
00497 totalDelay = temp.first;
00498 }
00499 }
00500
00501 SimpleInfo* thisInfo = dynamic_cast<SimpleInfo*>(sad.globalNodeList->getPeerInfo(src));
00502
00503 if (!sad.globalNodeList->areNodeTypesConnected(thisInfo->getTypeID(), info->getTypeID())) {
00504 EV << "[SimpleTCPConnection::sendToIP() @ " << src << "]\n"
00505 << " Partition " << thisInfo->getTypeID() << "->" << info->getTypeID()
00506 << " is not connected"
00507 << endl;
00508 delete tcpseg;
00509 sad.numPartitionLost++;
00510 return;
00511 }
00512
00513 if (sad.jitter) {
00514
00515
00516
00517
00518 double temp = truncnormal(0, SIMTIME_DBL(totalDelay) * sad.jitter);
00519 while (temp == INFINITY || temp != temp) {
00520 std::cerr << "\n******* SimpleTCPConnection: truncnormal() -> inf !!\n"
00521 << std::endl;
00522 temp = truncnormal(0, SIMTIME_DBL(totalDelay) * sad.jitter);
00523 }
00524
00525 totalDelay += temp;
00526 }
00527
00528
00529
00530 EV << "[SimpleTCPConnection::sendToIP() @ " << src << "]\n"
00531 << " Packet " << tcpseg << " sent with delay = " << totalDelay
00532 << endl;
00533
00534
00535
00536
00537
00538
00539 tcpEV << "Sending: ";
00540 printSegmentBrief(tcpseg);
00541
00542 if (!dest.isIPv6())
00543 {
00544
00545 IPControlInfo *controlInfo = new IPControlInfo();
00546 controlInfo->setProtocol(IP_PROT_TCP);
00547 controlInfo->setSrcAddr(src.get4());
00548 controlInfo->setDestAddr(dest.get4());
00549 tcpseg->setControlInfo(controlInfo);
00550
00551 check_and_cast<TCP *>(simulation.getContextModule())->sendDirect(tcpseg, totalDelay, 0, destEntry->getTcpIPv4Gate());
00552 }
00553 else
00554 {
00555
00556 IPv6ControlInfo *controlInfo = new IPv6ControlInfo();
00557 controlInfo->setProtocol(IP_PROT_TCP);
00558 controlInfo->setSrcAddr(src.get6());
00559 controlInfo->setDestAddr(dest.get6());
00560 tcpseg->setControlInfo(controlInfo);
00561
00562 check_and_cast<TCP *>(simulation.getContextModule())->sendDirect(tcpseg, totalDelay, 0, destEntry->getTcpIPv6Gate());
00563 }
00564 }