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 <algorithm>
00022 #include "TCP.h"
00023 #include "TCPConnection.h"
00024 #include "TCPSegment.h"
00025 #include "TCPCommand_m.h"
00026 #include "IPControlInfo.h"
00027 #include "IPv6ControlInfo.h"
00028 #include "TCPSendQueue.h"
00029 #include "TCPSACKRexmitQueue.h"
00030 #include "TCPReceiveQueue.h"
00031 #include "TCPAlgorithm.h"
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 const char *TCPConnection::optionName(int option)
00110 {
00111 switch (option)
00112 {
00113 case TCPOPTION_END_OF_OPTION_LIST: return "EOL";
00114 case TCPOPTION_NO_OPERATION: return "NOP";
00115 case TCPOPTION_MAXIMUM_SEGMENT_SIZE: return "MSS";
00116 case TCPOPTION_WINDOW_SCALE: return "WS";
00117 case TCPOPTION_SACK_PERMITTED: return "SACK_PERMITTED";
00118 case TCPOPTION_SACK: return "SACK";
00119 case TCPOPTION_TIMESTAMP: return "TS";
00120 default: return "unknown";
00121 }
00122 }
00123
00124 void TCPConnection::printConnBrief()
00125 {
00126 tcpEV << "Connection ";
00127 tcpEV << localAddr << ":" << localPort << " to " << remoteAddr << ":" << remotePort;
00128 tcpEV << " on app[" << appGateIndex << "],connId=" << connId;
00129 tcpEV << " in " << stateName(fsm.getState());
00130 tcpEV << " (ptr=0x" << this << ")\n";
00131 }
00132
00133 void TCPConnection::printSegmentBrief(TCPSegment *tcpseg)
00134 {
00135 tcpEV << "." << tcpseg->getSrcPort() << " > ";
00136 tcpEV << "." << tcpseg->getDestPort() << ": ";
00137
00138 if (tcpseg->getSynBit()) tcpEV << (tcpseg->getAckBit() ? "SYN+ACK " : "SYN ");
00139 if (tcpseg->getFinBit()) tcpEV << "FIN(+ACK) ";
00140 if (tcpseg->getRstBit()) tcpEV << (tcpseg->getAckBit() ? "RST+ACK " : "RST ");
00141 if (tcpseg->getPshBit()) tcpEV << "PSH ";
00142
00143 if (tcpseg->getPayloadLength()>0 || tcpseg->getSynBit())
00144 {
00145 tcpEV << "[" << tcpseg->getSequenceNo() << ".." << (tcpseg->getSequenceNo()+tcpseg->getPayloadLength()) << ") ";
00146 tcpEV << "(l=" << tcpseg->getPayloadLength() << ") ";
00147 }
00148 if (tcpseg->getAckBit()) tcpEV << "ack " << tcpseg->getAckNo() << " ";
00149 tcpEV << "win " << tcpseg->getWindow() << " ";
00150 if (tcpseg->getUrgBit()) tcpEV << "urg " << tcpseg->getUrgentPointer() << " ";
00151 if (tcpseg->getHeaderLength() > TCP_HEADER_OCTETS)
00152 {
00153 tcpEV << "options ";
00154 for (uint i=0; i<tcpseg->getOptionsArraySize(); i++)
00155 {
00156 const TCPOption& option = tcpseg->getOptions(i);
00157 short kind = option.getKind();
00158 tcpEV << optionName(kind) << " ";
00159 }
00160 }
00161 tcpEV << "\n";
00162 }
00163
00164 TCPConnection *TCPConnection::cloneListeningConnection()
00165 {
00166 TCPConnection *conn = new TCPConnection(tcpMain,appGateIndex,connId);
00167
00168
00169 const char *sendQueueClass = sendQueue->getClassName();
00170 conn->sendQueue = check_and_cast<TCPSendQueue *>(createOne(sendQueueClass));
00171 conn->sendQueue->setConnection(conn);
00172
00173 const char *receiveQueueClass = receiveQueue->getClassName();
00174 conn->receiveQueue = check_and_cast<TCPReceiveQueue *>(createOne(receiveQueueClass));
00175 conn->receiveQueue->setConnection(conn);
00176
00177
00178 rexmitQueue = new TCPSACKRexmitQueue();
00179 rexmitQueue->setConnection(this);
00180
00181 const char *tcpAlgorithmClass = tcpAlgorithm->getClassName();
00182 conn->tcpAlgorithm = check_and_cast<TCPAlgorithm *>(createOne(tcpAlgorithmClass));
00183 conn->tcpAlgorithm->setConnection(conn);
00184
00185 conn->state = conn->tcpAlgorithm->getStateVariables();
00186 configureStateVariables();
00187 conn->tcpAlgorithm->initialize();
00188
00189
00190 conn->state->active = false;
00191 conn->state->fork = true;
00192 conn->localAddr = localAddr;
00193 conn->localPort = localPort;
00194 FSM_Goto(conn->fsm, TCP_S_LISTEN);
00195
00196 return conn;
00197 }
00198
00199 void TCPConnection::sendToIP(TCPSegment *tcpseg)
00200 {
00201
00202 if (sndNxtVector && tcpseg->getPayloadLength()!=0)
00203 sndNxtVector->record(tcpseg->getSequenceNo());
00204 if (sndAckVector)
00205 sndAckVector->record(tcpseg->getAckNo());
00206
00207
00208 tcpseg->setSrcPort(localPort);
00209 tcpseg->setDestPort(remotePort);
00210 ASSERT(tcpseg->getHeaderLength() >= TCP_HEADER_OCTETS);
00211 ASSERT(tcpseg->getHeaderLength() <= TCP_MAX_HEADER_OCTETS);
00212 tcpseg->setByteLength(tcpseg->getHeaderLength() + tcpseg->getPayloadLength());
00213 state->sentBytes = tcpseg->getPayloadLength();
00214
00215 tcpEV << "Sending: ";
00216 printSegmentBrief(tcpseg);
00217
00218
00219
00220 if (!remoteAddr.isIPv6())
00221 {
00222
00223 IPControlInfo *controlInfo = new IPControlInfo();
00224 controlInfo->setProtocol(IP_PROT_TCP);
00225 controlInfo->setSrcAddr(localAddr.get4());
00226 controlInfo->setDestAddr(remoteAddr.get4());
00227 tcpseg->setControlInfo(controlInfo);
00228
00229 tcpMain->send(tcpseg,"ipOut");
00230 }
00231 else
00232 {
00233
00234 IPv6ControlInfo *controlInfo = new IPv6ControlInfo();
00235 controlInfo->setProtocol(IP_PROT_TCP);
00236 controlInfo->setSrcAddr(localAddr.get6());
00237 controlInfo->setDestAddr(remoteAddr.get6());
00238 tcpseg->setControlInfo(controlInfo);
00239
00240 tcpMain->send(tcpseg,"ipv6Out");
00241 }
00242 }
00243
00244 void TCPConnection::sendToIP(TCPSegment *tcpseg, IPvXAddress src, IPvXAddress dest)
00245 {
00246 tcpEV << "Sending: ";
00247 printSegmentBrief(tcpseg);
00248
00249 if (!dest.isIPv6())
00250 {
00251
00252 IPControlInfo *controlInfo = new IPControlInfo();
00253 controlInfo->setProtocol(IP_PROT_TCP);
00254 controlInfo->setSrcAddr(src.get4());
00255 controlInfo->setDestAddr(dest.get4());
00256 tcpseg->setControlInfo(controlInfo);
00257
00258 check_and_cast<TCP *>(simulation.getContextModule())->send(tcpseg,"ipOut");
00259 }
00260 else
00261 {
00262
00263 IPv6ControlInfo *controlInfo = new IPv6ControlInfo();
00264 controlInfo->setProtocol(IP_PROT_TCP);
00265 controlInfo->setSrcAddr(src.get6());
00266 controlInfo->setDestAddr(dest.get6());
00267 tcpseg->setControlInfo(controlInfo);
00268
00269 check_and_cast<TCP *>(simulation.getContextModule())->send(tcpseg,"ipv6Out");
00270 }
00271 }
00272
00273 TCPSegment *TCPConnection::createTCPSegment(const char *name)
00274 {
00275 return new TCPSegment(name);
00276 }
00277
00278 void TCPConnection::signalConnectionTimeout()
00279 {
00280 sendIndicationToApp(TCP_I_TIMED_OUT);
00281 }
00282
00283 void TCPConnection::sendIndicationToApp(int code)
00284 {
00285 tcpEV << "Notifying app: " << indicationName(code) << "\n";
00286 cMessage *msg = new cMessage(indicationName(code));
00287 msg->setKind(code);
00288 TCPCommand *ind = new TCPCommand();
00289 ind->setConnId(connId);
00290 msg->setControlInfo(ind);
00291 tcpMain->send(msg, "appOut", appGateIndex);
00292 }
00293
00294 void TCPConnection::sendEstabIndicationToApp()
00295 {
00296 tcpEV << "Notifying app: " << indicationName(TCP_I_ESTABLISHED) << "\n";
00297 cMessage *msg = new cMessage(indicationName(TCP_I_ESTABLISHED));
00298 msg->setKind(TCP_I_ESTABLISHED);
00299
00300 TCPConnectInfo *ind = new TCPConnectInfo();
00301 ind->setConnId(connId);
00302 ind->setLocalAddr(localAddr);
00303 ind->setRemoteAddr(remoteAddr);
00304 ind->setLocalPort(localPort);
00305 ind->setRemotePort(remotePort);
00306
00307 msg->setControlInfo(ind);
00308 tcpMain->send(msg, "appOut", appGateIndex);
00309 }
00310
00311 void TCPConnection::sendToApp(cMessage *msg)
00312 {
00313 tcpMain->send(msg, "appOut", appGateIndex);
00314 }
00315
00316 void TCPConnection::initConnection(TCPOpenCommand *openCmd)
00317 {
00318
00319 const char *sendQueueClass = openCmd->getSendQueueClass();
00320 if (!sendQueueClass || !sendQueueClass[0])
00321 sendQueueClass = tcpMain->par("sendQueueClass");
00322 sendQueue = check_and_cast<TCPSendQueue *>(createOne(sendQueueClass));
00323 sendQueue->setConnection(this);
00324
00325
00326 const char *receiveQueueClass = openCmd->getReceiveQueueClass();
00327 if (!receiveQueueClass || !receiveQueueClass[0])
00328 receiveQueueClass = tcpMain->par("receiveQueueClass");
00329 receiveQueue = check_and_cast<TCPReceiveQueue *>(createOne(receiveQueueClass));
00330 receiveQueue->setConnection(this);
00331
00332
00333 rexmitQueue = new TCPSACKRexmitQueue();
00334 rexmitQueue->setConnection(this);
00335
00336
00337 const char *tcpAlgorithmClass = openCmd->getTcpAlgorithmClass();
00338 if (!tcpAlgorithmClass || !tcpAlgorithmClass[0])
00339 tcpAlgorithmClass = tcpMain->par("tcpAlgorithmClass");
00340 tcpAlgorithm = check_and_cast<TCPAlgorithm *>(createOne(tcpAlgorithmClass));
00341 tcpAlgorithm->setConnection(this);
00342
00343
00344 state = tcpAlgorithm->getStateVariables();
00345 configureStateVariables();
00346 tcpAlgorithm->initialize();
00347 }
00348
00349 void TCPConnection::configureStateVariables()
00350 {
00351 long advertisedWindowPar = tcpMain->par("advertisedWindow").longValue();
00352 state->ws_support = tcpMain->par("windowScalingSupport");
00353 if (!state->ws_support && (advertisedWindowPar > TCP_MAX_WIN || advertisedWindowPar <= 0))
00354 throw cRuntimeError("Invalid advertisedWindow parameter: %ld", advertisedWindowPar);
00355 state->rcv_wnd = advertisedWindowPar;
00356 state->rcv_adv = advertisedWindowPar;
00357 if (state->ws_support && advertisedWindowPar > TCP_MAX_WIN)
00358 {
00359 state->rcv_wnd = TCP_MAX_WIN;
00360 state->rcv_adv = TCP_MAX_WIN;
00361 }
00362 state->maxRcvBuffer = advertisedWindowPar;
00363 state->delayed_acks_enabled = tcpMain->par("delayedAcksEnabled");
00364 state->nagle_enabled = tcpMain->par("nagleEnabled");
00365 state->limited_transmit_enabled = tcpMain->par("limitedTransmitEnabled");
00366 state->increased_IW_enabled = tcpMain->par("increasedIWEnabled");
00367 state->snd_mss = tcpMain->par("mss").longValue();
00368 state->ts_support = tcpMain->par("timestampSupport");
00369 state->sack_support = tcpMain->par("sackSupport");
00370 if (state->sack_support)
00371 {
00372 std::string algorithmName1 = "TCPReno";
00373 std::string algorithmName2 = tcpMain->par("tcpAlgorithmClass");
00374 if (algorithmName1!=algorithmName2)
00375 {
00376 EV << "If you want to use TCP SACK please set tcpAlgorithmClass to TCPReno" << endl;
00377 ASSERT(false);
00378 }
00379 }
00380 }
00381
00382 void TCPConnection::selectInitialSeqNum()
00383 {
00384
00385 state->iss = (unsigned long)fmod(SIMTIME_DBL(simTime())*250000.0, 1.0+(double)(unsigned)0xffffffffUL) & 0xffffffffUL;
00386
00387 state->snd_una = state->snd_nxt = state->snd_max = state->iss;
00388
00389 sendQueue->init(state->iss+1);
00390 rexmitQueue->init(state->iss + 1);
00391 }
00392
00393 bool TCPConnection::isSegmentAcceptable(TCPSegment *tcpseg)
00394 {
00395
00396
00397
00398 uint32 len = tcpseg->getPayloadLength();
00399 uint32 seqNo = tcpseg->getSequenceNo();
00400 bool ret;
00401
00402 if (len == 0)
00403 {
00404 if (state->rcv_wnd == 0)
00405 ret = (seqNo == state->rcv_nxt);
00406 else
00407 ret = seqLE(state->rcv_nxt, seqNo) && seqLess(seqNo, state->rcv_nxt + state->rcv_wnd);
00408 }
00409 else
00410 {
00411 if (state->rcv_wnd == 0)
00412 ret = false;
00413 else
00414 ret = (seqLE(state->rcv_nxt, seqNo) && seqLess(seqNo, state->rcv_nxt + state->rcv_wnd))
00415 ||
00416 (seqLE(state->rcv_nxt, seqNo + len - 1) && seqLess(seqNo + len - 1, state->rcv_nxt + state->rcv_wnd));
00417 }
00418 if (!ret)
00419 {
00420 tcpEV << "Not Acceptable segment. seqNo:" << seqNo << ", len:" << len << ", rcv_nxt:" << state->rcv_nxt << ", rcv_wnd:" << state->rcv_wnd << endl;
00421 }
00422 return ret;
00423 }
00424
00425 void TCPConnection::sendSyn()
00426 {
00427 if (remoteAddr.isUnspecified() || remotePort==-1)
00428 opp_error("Error processing command OPEN_ACTIVE: foreign socket unspecified");
00429 if (localPort==-1)
00430 opp_error("Error processing command OPEN_ACTIVE: local port unspecified");
00431
00432
00433 TCPSegment *tcpseg = createTCPSegment("SYN");
00434 tcpseg->setSequenceNo(state->iss);
00435 tcpseg->setSynBit(true);
00436 updateRcvWnd();
00437 tcpseg->setWindow(state->rcv_wnd);
00438
00439 state->snd_max = state->snd_nxt = state->iss+1;
00440
00441
00442 writeHeaderOptions(tcpseg);
00443
00444
00445 sendToIP(tcpseg);
00446 }
00447
00448 void TCPConnection::sendSynAck()
00449 {
00450
00451 TCPSegment *tcpseg = createTCPSegment("SYN+ACK");
00452 tcpseg->setSequenceNo(state->iss);
00453 tcpseg->setAckNo(state->rcv_nxt);
00454 tcpseg->setSynBit(true);
00455 tcpseg->setAckBit(true);
00456 updateRcvWnd();
00457 tcpseg->setWindow(state->rcv_wnd);
00458
00459 state->snd_max = state->snd_nxt = state->iss+1;
00460
00461
00462 writeHeaderOptions(tcpseg);
00463
00464
00465 sendToIP(tcpseg);
00466
00467
00468 tcpAlgorithm->ackSent();
00469 }
00470
00471 void TCPConnection::sendRst(uint32 seqNo)
00472 {
00473 sendRst(seqNo, localAddr, remoteAddr, localPort, remotePort);
00474 }
00475
00476 void TCPConnection::sendRst(uint32 seq, IPvXAddress src, IPvXAddress dest, int srcPort, int destPort)
00477 {
00478 TCPSegment *tcpseg = createTCPSegment("RST");
00479
00480 tcpseg->setSrcPort(srcPort);
00481 tcpseg->setDestPort(destPort);
00482
00483 tcpseg->setRstBit(true);
00484 tcpseg->setSequenceNo(seq);
00485
00486
00487 sendToIP(tcpseg, src, dest);
00488 }
00489
00490 void TCPConnection::sendRstAck(uint32 seq, uint32 ack, IPvXAddress src, IPvXAddress dest, int srcPort, int destPort)
00491 {
00492 TCPSegment *tcpseg = createTCPSegment("RST+ACK");
00493
00494 tcpseg->setSrcPort(srcPort);
00495 tcpseg->setDestPort(destPort);
00496
00497 tcpseg->setRstBit(true);
00498 tcpseg->setAckBit(true);
00499 tcpseg->setSequenceNo(seq);
00500 tcpseg->setAckNo(ack);
00501
00502
00503 sendToIP(tcpseg, src, dest);
00504
00505
00506 tcpAlgorithm->ackSent();
00507 }
00508
00509 void TCPConnection::sendAck()
00510 {
00511 TCPSegment *tcpseg = createTCPSegment("ACK");
00512
00513 tcpseg->setAckBit(true);
00514 tcpseg->setSequenceNo(state->snd_nxt);
00515 tcpseg->setAckNo(state->rcv_nxt);
00516 tcpseg->setWindow(updateRcvWnd());
00517
00518
00519 writeHeaderOptions(tcpseg);
00520
00521
00522 sendToIP(tcpseg);
00523
00524
00525 tcpAlgorithm->ackSent();
00526 }
00527
00528 void TCPConnection::sendFin()
00529 {
00530 TCPSegment *tcpseg = createTCPSegment("FIN");
00531
00532
00533
00534 tcpseg->setFinBit(true);
00535 tcpseg->setAckBit(true);
00536 tcpseg->setAckNo(state->rcv_nxt);
00537 tcpseg->setSequenceNo(state->snd_nxt);
00538 tcpseg->setWindow(updateRcvWnd());
00539
00540
00541 sendToIP(tcpseg);
00542
00543
00544 tcpAlgorithm->ackSent();
00545 }
00546
00547 void TCPConnection::sendSegment(uint32 bytes)
00548 {
00549 if (state->sack_enabled && state->afterRto)
00550 {
00551
00552 uint32 forward = rexmitQueue->checkRexmitQueueForSackedOrRexmittedSegments(state->snd_nxt);
00553 state->snd_nxt = state->snd_nxt + forward;
00554 }
00555
00556 ulong buffered = sendQueue->getBytesAvailable(state->snd_nxt);
00557 if (bytes > buffered)
00558 bytes = buffered;
00559
00560
00561
00562
00563 TCPSegment *tcpseg_temp = createTCPSegment(NULL);
00564 tcpseg_temp->setAckBit(true);
00565 writeHeaderOptions(tcpseg_temp);
00566 uint options_len = tcpseg_temp->getHeaderLength() - TCP_HEADER_OCTETS;
00567 while (bytes + options_len > state->snd_mss)
00568 bytes--;
00569 state->sentBytes = bytes;
00570
00571
00572 TCPSegment *tcpseg = sendQueue->createSegmentWithBytes(state->snd_nxt, bytes);
00573
00574
00575 if (state->sack_enabled)
00576 rexmitQueue->enqueueSentData(state->snd_nxt, state->snd_nxt+bytes);
00577
00578 tcpseg->setAckNo(state->rcv_nxt);
00579 tcpseg->setAckBit(true);
00580 tcpseg->setWindow(updateRcvWnd());
00581
00582
00583
00584 ASSERT(bytes==tcpseg->getPayloadLength());
00585
00586 state->snd_nxt += bytes;
00587
00588
00589 if (state->afterRto && seqGE(state->snd_nxt, state->snd_max))
00590 state->afterRto = false;
00591
00592 if (state->send_fin && state->snd_nxt==state->snd_fin_seq)
00593 {
00594 tcpEV << "Setting FIN on segment\n";
00595 tcpseg->setFinBit(true);
00596 state->snd_nxt = state->snd_fin_seq+1;
00597 }
00598
00599
00600 tcpseg->setOptionsArraySize(tcpseg_temp->getOptionsArraySize());
00601 for (uint i=0; i<tcpseg_temp->getOptionsArraySize(); i++)
00602 tcpseg->setOptions(i, tcpseg_temp->getOptions(i));
00603 tcpseg->setHeaderLength(tcpseg_temp->getHeaderLength());
00604 delete tcpseg_temp;
00605
00606
00607 sendToIP(tcpseg);
00608 }
00609
00610 bool TCPConnection::sendData(bool fullSegmentsOnly, uint32 congestionWindow)
00611 {
00612 if (!state->afterRto)
00613 {
00614
00615 state->snd_nxt = state->snd_max;
00616 }
00617
00618 uint32 old_highRxt = 0;
00619 if (state->sack_enabled)
00620 old_highRxt = rexmitQueue->getHighestRexmittedSeqNum();
00621
00622
00623 ulong buffered = sendQueue->getBytesAvailable(state->snd_nxt);
00624 if (buffered==0)
00625 return false;
00626
00627
00628 ulong maxWindow = std::min(state->snd_wnd, congestionWindow);
00629
00630
00631 long effectiveWin = maxWindow - (state->snd_nxt - state->snd_una);
00632 if (effectiveWin <= 0)
00633 {
00634 tcpEV << "Effective window is zero (advertised window " << state->snd_wnd <<
00635 ", congestion window " << congestionWindow << "), cannot send.\n";
00636 return false;
00637 }
00638
00639 ulong bytesToSend = effectiveWin;
00640
00641 if (bytesToSend > buffered)
00642 bytesToSend = buffered;
00643
00644 uint32 effectiveMaxBytesSend = state->snd_mss;
00645 if (state->ts_enabled)
00646 effectiveMaxBytesSend -= TCP_OPTION_TS_SIZE;
00647
00648
00649 if (fullSegmentsOnly && buffered > (ulong)effectiveWin &&
00650 (bytesToSend < (effectiveMaxBytesSend)))
00651 {
00652 tcpEV << "Cannot send, not enough data for a full segment (SMSS=" << state->snd_mss
00653 << ", in buffer " << buffered << ")\n";
00654 return false;
00655 }
00656
00657
00658 tcpEV << "Will send " << bytesToSend << " bytes (effectiveWindow " << effectiveWin
00659 << ", in buffer " << buffered << " bytes)\n";
00660
00661 uint32 old_snd_nxt = state->snd_nxt;
00662 ASSERT(bytesToSend>0);
00663
00664 #ifdef TCP_SENDFRAGMENTS
00665
00666 while (bytesToSend>0)
00667 {
00668 ulong bytes = std::min(bytesToSend, state->snd_mss);
00669 sendSegment(bytes);
00670 bytesToSend -= state->sentBytes;
00671 }
00672 #else
00673
00674
00675 if (bytesToSend <= state->snd_mss)
00676 {
00677 sendSegment(bytesToSend);
00678 bytesToSend -= state->sentBytes;
00679 }
00680 else
00681 {
00682 while (bytesToSend >= effectiveMaxBytesSend)
00683 {
00684 sendSegment(state->snd_mss);
00685 bytesToSend -= state->sentBytes;
00686 }
00687 }
00688
00689 buffered = sendQueue->getBytesAvailable(state->snd_nxt);
00690 if (bytesToSend==buffered && buffered!=0)
00691 sendSegment(bytesToSend);
00692 else if (bytesToSend>0)
00693 tcpEV << bytesToSend << " bytes of space left in effectiveWindow\n";
00694 #endif
00695
00696
00697
00698
00699 if (seqGreater(state->snd_nxt, state->snd_max))
00700 state->snd_max = state->snd_nxt;
00701 if (unackedVector) unackedVector->record(state->snd_max - state->snd_una);
00702
00703
00704 tcpAlgorithm->ackSent();
00705 if (state->sack_enabled && state->lossRecovery && old_highRxt != state->highRxt)
00706 {
00707
00708 tcpEV << "Retransmission sent during recovery, restarting REXMIT timer.\n";
00709 tcpAlgorithm->restartRexmitTimer();
00710 }
00711 else
00712 tcpAlgorithm->dataSent(old_snd_nxt);
00713
00714 return true;
00715 }
00716
00717 bool TCPConnection::sendProbe()
00718 {
00719
00720 state->snd_nxt = state->snd_max;
00721
00722
00723 if (sendQueue->getBytesAvailable(state->snd_nxt)==0)
00724 {
00725 tcpEV << "Cannot send probe because send buffer is empty\n";
00726 return false;
00727 }
00728
00729 uint32 old_snd_nxt = state->snd_nxt;
00730
00731 tcpEV << "Sending 1 byte as probe, with seq=" << state->snd_nxt << "\n";
00732 sendSegment(1);
00733
00734
00735
00736
00737 state->snd_max = state->snd_nxt;
00738 if (unackedVector) unackedVector->record(state->snd_max - state->snd_una);
00739
00740
00741 tcpAlgorithm->ackSent();
00742 tcpAlgorithm->dataSent(old_snd_nxt);
00743
00744 return true;
00745 }
00746
00747 void TCPConnection::retransmitOneSegment(bool called_at_rto)
00748 {
00749 uint32 old_snd_nxt = state->snd_nxt;
00750
00751
00752 state->snd_nxt = state->snd_una;
00753
00754
00755 ulong bytes = std::min((ulong)std::min(state->snd_mss, state->snd_max - state->snd_nxt),
00756 sendQueue->getBytesAvailable(state->snd_nxt));
00757
00758 ASSERT(bytes!=0);
00759
00760 sendSegment(bytes);
00761 if (!called_at_rto)
00762 {
00763 if (seqGreater(old_snd_nxt, state->snd_nxt))
00764 state->snd_nxt = old_snd_nxt;
00765 }
00766
00767
00768 tcpAlgorithm->ackSent();
00769
00770 if (state->sack_enabled)
00771 {
00772
00773
00774
00775
00776 state->highRxt = rexmitQueue->getHighestRexmittedSeqNum();
00777 }
00778 }
00779
00780 void TCPConnection::retransmitData()
00781 {
00782
00783 state->snd_nxt = state->snd_una;
00784
00785 uint32 bytesToSend = state->snd_max - state->snd_nxt;
00786 ASSERT(bytesToSend!=0);
00787
00788
00789 while (bytesToSend>0)
00790 {
00791 uint32 bytes = std::min(bytesToSend, state->snd_mss);
00792 bytes = std::min(bytes, (uint32)(sendQueue->getBytesAvailable(state->snd_nxt)));
00793 sendSegment(bytes);
00794
00795
00796 if (state->send_fin && state->snd_nxt==state->snd_fin_seq+1)
00797 break;
00798 bytesToSend -= state->sentBytes;
00799 }
00800 }
00801
00802 void TCPConnection::readHeaderOptions(TCPSegment *tcpseg)
00803 {
00804 tcpEV << "TCP Header Option(s) received:\n";
00805
00806 for (uint i=0; i<tcpseg->getOptionsArraySize(); i++)
00807 {
00808 const TCPOption& option = tcpseg->getOptions(i);
00809 short kind = option.getKind();
00810 short length = option.getLength();
00811 tcpEV << "Option type " << kind << " (" << optionName(kind) << "), length " << length << "\n";
00812 bool ok = true;
00813 switch(kind)
00814 {
00815 case TCPOPTION_END_OF_OPTION_LIST:
00816 case TCPOPTION_NO_OPERATION:
00817 if (length != 1)
00818 {
00819 tcpEV << "ERROR: option length incorrect\n";
00820 ok = false;
00821 }
00822 break;
00823 case TCPOPTION_MAXIMUM_SEGMENT_SIZE:
00824 ok = processMSSOption(tcpseg, option);
00825 break;
00826 case TCPOPTION_WINDOW_SCALE:
00827 ok = processWSOption(tcpseg, option);
00828 break;
00829 case TCPOPTION_SACK_PERMITTED:
00830 ok = processSACKPermittedOption(tcpseg, option);
00831 break;
00832 case TCPOPTION_SACK:
00833 ok = processSACKOption(tcpseg, option);
00834 break;
00835 case TCPOPTION_TIMESTAMP:
00836 ok = processTSOption(tcpseg, option);
00837 break;
00838
00839
00840 default:
00841 tcpEV << "ERROR: Unsupported TCP option kind " << kind << "\n";
00842 break;
00843 }
00844 (void)ok;
00845 }
00846 }
00847
00848 bool TCPConnection::processMSSOption(TCPSegment *tcpseg, const TCPOption& option)
00849 {
00850 if (option.getLength() != 4)
00851 {
00852 tcpEV << "ERROR: option length incorrect\n";
00853 return false;
00854 }
00855
00856 if (fsm.getState() != TCP_S_LISTEN && fsm.getState() != TCP_S_SYN_SENT)
00857 {
00858 tcpEV << "ERROR: TCP Header Option MSS received, but in unexpected state\n";
00859 return false;
00860 }
00861
00862 if (option.getValuesArraySize() == 0)
00863 {
00864
00865 throw cRuntimeError("TCPOption for MSS does not contain the data its getLength() promises");
00866 }
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 state->snd_mss = std::min(state->snd_mss, (uint32) option.getValues(0));
00883 if (state->snd_mss==0)
00884 state->snd_mss = 536;
00885 tcpEV << "TCP Header Option MSS(=" << option.getValues(0) << ") received, SMSS is set to: " << state->snd_mss << "\n";
00886 return true;
00887 }
00888
00889 bool TCPConnection::processWSOption(TCPSegment *tcpseg, const TCPOption& option)
00890 {
00891 if (option.getLength() != 3)
00892 {
00893 tcpEV << "ERROR: length incorrect\n";
00894 return false;
00895 }
00896
00897 if (fsm.getState() != TCP_S_LISTEN && fsm.getState() != TCP_S_SYN_SENT)
00898 {
00899 tcpEV << "ERROR: TCP Header Option WS received, but in unexpected state\n";
00900 return false;
00901 }
00902
00903 if (option.getValuesArraySize() == 0)
00904 {
00905
00906 throw cRuntimeError("TCPOption for WS does not contain the data its getLength() promises");
00907 }
00908
00909 state->rcv_ws = true;
00910 state->ws_enabled = state->ws_support && state->snd_ws && state->rcv_ws;
00911 state->snd_wnd_scale = option.getValues(0);
00912 tcpEV << "TCP Header Option WS(=" << state->snd_wnd_scale << ") received, WS (ws_enabled) is set to: " << state->ws_enabled << "\n";
00913 if (state->snd_wnd_scale > 14)
00914 {
00915 tcpEV << "ERROR: TCP Header Option WS received but shift count value is exceeding 14\n";
00916 state->snd_wnd_scale = 14;
00917 }
00918 return true;
00919 }
00920
00921 bool TCPConnection::processTSOption(TCPSegment *tcpseg, const TCPOption& option)
00922 {
00923 if (option.getLength() != 10)
00924 {
00925 tcpEV << "ERROR: length incorrect\n";
00926 return false;
00927 }
00928
00929 if ((!state->ts_enabled && fsm.getState() != TCP_S_LISTEN && fsm.getState() != TCP_S_SYN_SENT) ||
00930 (state->ts_enabled && fsm.getState() != TCP_S_SYN_RCVD && fsm.getState() != TCP_S_ESTABLISHED &&
00931 fsm.getState() != TCP_S_FIN_WAIT_1 && fsm.getState() != TCP_S_FIN_WAIT_2))
00932 {
00933 tcpEV << "ERROR: TCP Header Option TS received, but in unexpected state\n";
00934 return false;
00935 }
00936
00937 if (option.getValuesArraySize() != 2)
00938 {
00939
00940 throw cRuntimeError("TCPOption for TS does not contain the data its getLength() promises");
00941 }
00942
00943 if (!state->ts_enabled)
00944 {
00945 state->rcv_initial_ts = true;
00946 state->ts_enabled = state->ts_support && state->snd_initial_ts && state->rcv_initial_ts;
00947 tcpEV << "TCP Header Option TS(TSval=" << option.getValues(0) << ", TSecr=" << option.getValues(1) << ") received, TS (ts_enabled) is set to: " << state->ts_enabled << "\n";
00948 }
00949 else
00950 tcpEV << "TCP Header Option TS(TSval=" << option.getValues(0) << ", TSecr=" << option.getValues(1) << ") received\n";
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961 if (state->ts_enabled)
00962 {
00963 if (seqLess(option.getValues(0), state->ts_recent))
00964 {
00965 if ((simTime() - state->time_last_data_sent) > PAWS_IDLE_TIME_THRESH)
00966 {
00967 tcpEV << "PAWS: Segment is not acceptable, TSval=" << option.getValues(0) << " in " << stateName(fsm.getState()) << " state received: dropping segment\n";
00968 return false;
00969 }
00970 }
00971 else if (seqLE(tcpseg->getSequenceNo(), state->last_ack_sent))
00972 {
00973 state->ts_recent = option.getValues(0);
00974 tcpEV << "Updating ts_recent from segment: new ts_recent=" << state->ts_recent << "\n";
00975 }
00976 }
00977
00978 return true;
00979 }
00980
00981 bool TCPConnection::processSACKPermittedOption(TCPSegment *tcpseg, const TCPOption& option)
00982 {
00983 if (option.getLength() != 2)
00984 {
00985 tcpEV << "ERROR: length incorrect\n";
00986 return false;
00987 }
00988
00989 if (fsm.getState() != TCP_S_LISTEN && fsm.getState() != TCP_S_SYN_SENT)
00990 {
00991 tcpEV << "ERROR: TCP Header Option SACK_PERMITTED received, but in unexpected state\n";
00992 return false;
00993 }
00994
00995 state->rcv_sack_perm = true;
00996 state->sack_enabled = state->sack_support && state->snd_sack_perm && state->rcv_sack_perm;
00997 tcpEV << "TCP Header Option SACK_PERMITTED received, SACK (sack_enabled) is set to: " << state->sack_enabled << "\n";
00998 return true;
00999 }
01000
01001 bool TCPConnection::processSACKOption(TCPSegment *tcpseg, const TCPOption& option)
01002 {
01003 if (option.getLength() % 8 != 2)
01004 {
01005 tcpEV << "ERROR: option length incorrect\n";
01006 return false;
01007 }
01008
01009 if (state->sack_enabled && fsm.getState() != TCP_S_SYN_RCVD && fsm.getState() != TCP_S_ESTABLISHED && fsm.getState() != TCP_S_FIN_WAIT_1 && fsm.getState() != TCP_S_FIN_WAIT_2)
01010 {
01011 tcpEV << "ERROR: TCP Header Option SACK received, but in unexpected state\n";
01012 return false;
01013 }
01014
01015 if (!state->sack_enabled)
01016 {
01017 tcpEV << "ERROR: " << (option.getLength()/2) << ". SACK(s) received, but sack_enabled is set to " << state->sack_enabled << "\n";
01018 return false;
01019 }
01020
01021 uint n = option.getValuesArraySize()/2;
01022 if (n > 0)
01023 {
01024 tcpEV << n << " SACK(s) received:\n";
01025 uint count=0;
01026 for (uint i=0; i<n; i++)
01027 {
01028 Sack tmp;
01029 tmp.setStart(option.getValues(count));
01030 count++;
01031 tmp.setEnd(option.getValues(count));
01032 count++;
01033
01034 tcpEV << (i+1) << ". SACK:" << " [" << tmp.getStart() << ".." << tmp.getEnd() << ")\n";
01035
01036
01037 if (i==0 && seqLess(tmp.getEnd(), tcpseg->getAckNo()))
01038 {
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050 tcpEV << "Received D-SACK below cumulative ACK=" << tcpseg->getAckNo() << " D-SACK:" << " [" << tmp.getStart() << ".." << tmp.getEnd() << ")\n";
01051 }
01052 else if (i==0 && seqGE(tmp.getEnd(), tcpseg->getAckNo()) && n>1)
01053 {
01054
01055
01056
01057
01058
01059
01060
01061 Sack tmp2;
01062 tmp2.setStart(option.getValues(2));
01063 tmp2.setEnd(option.getValues(3));
01064
01065 if (seqGE(tmp.getStart(), tmp2.getStart()) && seqLE(tmp.getEnd(), tmp2.getEnd()))
01066 {tcpEV << "Received D-SACK above cumulative ACK=" << tcpseg->getAckNo() << " D-SACK:" << " [" << tmp.getStart() << ".." << tmp.getEnd() << ") SACK:" << " [" << tmp2.getStart() << ".." << tmp2.getEnd() << ")\n";}
01067 }
01068
01069 if (seqGreater(tmp.getEnd(), tcpseg->getAckNo()))
01070 rexmitQueue->setSackedBit(tmp.getStart(), tmp.getEnd());
01071 }
01072 state->rcv_sacks = state->rcv_sacks + n;
01073 if (rcvSacksVector)
01074 rcvSacksVector->record(state->rcv_sacks);
01075
01076
01077 state->sackedBytes_old = state->sackedBytes;
01078 state->sackedBytes = rexmitQueue->getTotalAmountOfSackedBytes();
01079 if (sackedBytesVector)
01080 sackedBytesVector->record(state->sackedBytes);
01081 }
01082 return true;
01083 }
01084
01085 TCPSegment TCPConnection::writeHeaderOptions(TCPSegment *tcpseg)
01086 {
01087 TCPOption option;
01088 uint t = 0;
01089
01090 if (tcpseg->getSynBit() && (fsm.getState() == TCP_S_INIT || fsm.getState() == TCP_S_LISTEN || ((fsm.getState()==TCP_S_SYN_SENT || fsm.getState()==TCP_S_SYN_RCVD) && state->syn_rexmit_count>0)))
01091 {
01092
01093 if (state->snd_mss > 0)
01094 {
01095 option.setKind(TCPOPTION_MAXIMUM_SEGMENT_SIZE);
01096 option.setLength(4);
01097 option.setValuesArraySize(1);
01098
01099
01100 option.setValues(0,state->snd_mss);
01101 tcpEV << "TCP Header Option MSS(=" << state->snd_mss << ") sent\n";
01102 tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+1);
01103 tcpseg->setOptions(t,option);
01104 t++;
01105 }
01106
01107
01108 if (state->ws_support && (state->rcv_ws || (fsm.getState() == TCP_S_INIT || (fsm.getState()==TCP_S_SYN_SENT && state->syn_rexmit_count>0))))
01109 {
01110
01111 option.setKind(TCPOPTION_NO_OPERATION);
01112 option.setLength(1);
01113 option.setValuesArraySize(0);
01114 tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+1);
01115 tcpseg->setOptions(t,option);
01116 t++;
01117
01118 option.setKind(TCPOPTION_WINDOW_SCALE);
01119 option.setLength(3);
01120 option.setValuesArraySize(1);
01121
01122
01123 ulong scaled_rcv_wnd = receiveQueue->getAmountOfFreeBytes(state->maxRcvBuffer);
01124 state->rcv_wnd_scale = 0;
01125 while (scaled_rcv_wnd > TCP_MAX_WIN && state->rcv_wnd_scale < 14)
01126 {
01127 scaled_rcv_wnd = scaled_rcv_wnd >> 1;
01128 state->rcv_wnd_scale++;
01129 }
01130 option.setValues(0,state->rcv_wnd_scale);
01131 state->snd_ws = true;
01132 state->ws_enabled = state->ws_support && state->snd_ws && state->rcv_ws;
01133 tcpEV << "TCP Header Option WS(=" << option.getValues(0) << ") sent, WS (ws_enabled) is set to: " << state->ws_enabled << "\n";
01134 tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+1);
01135 tcpseg->setOptions(t,option);
01136 t++;
01137 }
01138
01139
01140 if (state->sack_support && (state->rcv_sack_perm || (fsm.getState() == TCP_S_INIT || (fsm.getState()==TCP_S_SYN_SENT && state->syn_rexmit_count>0))))
01141 {
01142 if (!state->ts_support)
01143 {
01144
01145 option.setKind(TCPOPTION_NO_OPERATION);
01146 option.setLength(1);
01147 option.setValuesArraySize(0);
01148 tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+2);
01149 tcpseg->setOptions(t,option);
01150 t++;
01151 tcpseg->setOptions(t,option);
01152 t++;
01153 }
01154
01155 option.setKind(TCPOPTION_SACK_PERMITTED);
01156 option.setLength(2);
01157 option.setValuesArraySize(0);
01158
01159
01160 state->snd_sack_perm = true;
01161 state->sack_enabled = state->sack_support && state->snd_sack_perm && state->rcv_sack_perm;
01162 tcpEV << "TCP Header Option SACK_PERMITTED sent, SACK (sack_enabled) is set to: " << state->sack_enabled << "\n";
01163 tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+1);
01164 tcpseg->setOptions(t,option);
01165 t++;
01166 }
01167
01168
01169 if (state->ts_support && (state->rcv_initial_ts || (fsm.getState() == TCP_S_INIT || (fsm.getState()==TCP_S_SYN_SENT && state->syn_rexmit_count>0))))
01170 {
01171 if (!state->sack_support)
01172 {
01173
01174 option.setKind(TCPOPTION_NO_OPERATION);
01175 option.setLength(1);
01176 option.setValuesArraySize(0);
01177 tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+2);
01178 tcpseg->setOptions(t,option);
01179 t++;
01180 tcpseg->setOptions(t,option);
01181 t++;
01182 }
01183
01184 option.setKind(TCPOPTION_TIMESTAMP);
01185 option.setLength(10);
01186 option.setValuesArraySize(2);
01187
01188
01189
01190 option.setValues(0,convertSimtimeToTS(simTime()));
01191
01192
01193
01194
01195
01196
01197
01198 if (tcpseg->getAckBit())
01199 option.setValues(1,state->ts_recent);
01200 else
01201 option.setValues(1,0);
01202 state->snd_initial_ts = true;
01203 state->ts_enabled = state->ts_support && state->snd_initial_ts && state->rcv_initial_ts;
01204 tcpEV << "TCP Header Option TS(TSval=" << option.getValues(0) << ", TSecr=" << option.getValues(1) << ") sent, TS (ts_enabled) is set to: " << state->ts_enabled << "\n";
01205 tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+1);
01206 tcpseg->setOptions(t,option);
01207 t++;
01208 }
01209
01210
01211 }
01212 else if (fsm.getState()==TCP_S_SYN_SENT || fsm.getState()==TCP_S_SYN_RCVD || fsm.getState()==TCP_S_ESTABLISHED || fsm.getState()==TCP_S_FIN_WAIT_1 || fsm.getState()==TCP_S_FIN_WAIT_2)
01213 {
01214
01215 if (state->ts_enabled)
01216 {
01217 if (!(state->sack_enabled && (state->snd_sack || state->snd_dsack)))
01218 {
01219
01220 option.setKind(TCPOPTION_NO_OPERATION);
01221 option.setLength(1);
01222 option.setValuesArraySize(0);
01223 tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+2);
01224 tcpseg->setOptions(t,option);
01225 t++;
01226 tcpseg->setOptions(t,option);
01227 t++;
01228 }
01229
01230 option.setKind(TCPOPTION_TIMESTAMP);
01231 option.setLength(10);
01232 option.setValuesArraySize(2);
01233
01234
01235
01236 option.setValues(0,convertSimtimeToTS(simTime()));
01237
01238
01239
01240
01241
01242
01243
01244 if (tcpseg->getAckBit())
01245 option.setValues(1,state->ts_recent);
01246 else
01247 option.setValues(1,0);
01248 tcpEV << "TCP Header Option TS(TSval=" << option.getValues(0) << ", TSecr=" << option.getValues(1) << ") sent\n";
01249 tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+1);
01250 tcpseg->setOptions(t,option);
01251 t++;
01252 }
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266 if (state->sack_enabled && (state->snd_sack || state->snd_dsack))
01267 {
01268 if (!state->ts_enabled)
01269 {
01270
01271 option.setKind(TCPOPTION_NO_OPERATION);
01272 option.setLength(1);
01273 option.setValuesArraySize(0);
01274 tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+2);
01275 tcpseg->setOptions(t,option);
01276 t++;
01277 tcpseg->setOptions(t,option);
01278 t++;
01279 }
01280
01281 addSacks(tcpseg);
01282 t++;
01283 }
01284
01285
01286
01287
01288 }
01289
01290 if (tcpseg->getOptionsArraySize() != 0)
01291 {
01292 uint options_len = 0;
01293 for (uint i=0; i<tcpseg->getOptionsArraySize(); i++)
01294 options_len = options_len + tcpseg->getOptions(i).getLength();
01295
01296 if (options_len <= 40)
01297 tcpseg->setHeaderLength(TCP_HEADER_OCTETS+options_len);
01298 else
01299 {
01300 tcpseg->setHeaderLength(TCP_HEADER_OCTETS);
01301 tcpseg->setOptionsArraySize(0);
01302 tcpEV << "ERROR: Options length exceeded! Segment will be sent without options" << "\n";
01303 }
01304 }
01305
01306 return *tcpseg;
01307 }
01308
01309 TCPSegment TCPConnection::addSacks(TCPSegment *tcpseg)
01310 {
01311 TCPOption option;
01312 uint options_len = 0;
01313 uint used_options_len = 0;
01314 uint m = 0;
01315 uint n = 0;
01316 bool skip_sacks_array = false;
01317 bool overlap = false;
01318
01319 uint32 start = state->start_seqno;
01320 uint32 end = state->end_seqno;
01321
01322 ASSERT(start!=0 || end!=0);
01323
01324
01325 tcpEV << "Previous status of sacks_array: \n";
01326 for (uint a=0; a<MAX_SACK_BLOCKS; a++)
01327 {
01328 if (state->sacks_array[a].getStart()!=0 && seqLE(state->sacks_array[a].getEnd(), state->rcv_nxt))
01329 {
01330 state->sacks_array[a].setStart(0);
01331 state->sacks_array[a].setEnd(0);
01332 }
01333 if (state->sacks_array[a].getStart()!=0 && state->sacks_array[a].getEnd()!=0)
01334 tcpEV << "\t" << (a+1) << ". SACK in sacks_array:" << " [" << state->sacks_array[a].getStart() << ".." << state->sacks_array[a].getEnd() << ")\n";
01335 else
01336 break;
01337 }
01338
01339 for (uint a=0; a<MAX_SACK_BLOCKS-1; a++)
01340 {
01341 if (state->sacks_array[a].getStart() != 0)
01342 m++;
01343 else
01344 break;
01345 }
01346 n = m + 1;
01347
01348
01349 if (tcpseg->getOptionsArraySize()>0)
01350 {
01351 for (uint i=0; i<tcpseg->getOptionsArraySize(); i++)
01352 used_options_len = used_options_len + tcpseg->getOptions(i).getLength();
01353 if (used_options_len>30)
01354 {
01355 tcpEV << "ERROR: Failed to addSacks - at least 10 free bytes needed for SACK - used_options_len=" << used_options_len << "\n";
01356
01357 skip_sacks_array = false;
01358 state->snd_sack = false;
01359 state->snd_dsack = false;
01360 state->start_seqno = 0;
01361 state->end_seqno = 0;
01362 return *tcpseg;
01363 }
01364 else
01365 {
01366 n = std::min (n, (((40-used_options_len)-2)/8));
01367 option.setValuesArraySize(n*2);
01368 }
01369 }
01370 else
01371 {
01372 n = std::min (n, MAX_SACK_ENTRIES);
01373 option.setValuesArraySize(n*2);
01374 }
01375
01376
01377 for (int a=(MAX_SACK_BLOCKS-1); a>=0; a--)
01378 state->sacks_array[a+1] = state->sacks_array[a];
01379
01380 if (state->snd_dsack)
01381 {
01382
01383
01384
01385
01386
01387 if (seqLess(start, state->rcv_nxt) && seqLess(state->rcv_nxt, end))
01388 end = state->rcv_nxt;
01389 }
01390 else if (start==0 && end==0)
01391 {
01392
01393
01394
01395
01396
01397
01398
01399
01400 start = state->sacks_array[0].getStart();
01401 end = state->sacks_array[0].getEnd();
01402 }
01403 else
01404 {
01405
01406
01407
01408
01409 start = receiveQueue->getLE(start);
01410 end = receiveQueue->getRE(end);
01411 }
01412
01413 state->sacks_array[0].setStart(start);
01414 state->sacks_array[0].setEnd(end);
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425 if (state->snd_dsack)
01426 {
01427 uint32 start_new = receiveQueue->getLE(start);
01428 uint32 end_new = receiveQueue->getRE(end);
01429 if (start_new != start || end_new != end)
01430 {
01431 skip_sacks_array = true;
01432 for (int a=(MAX_SACK_BLOCKS-1); a>=1; a--)
01433 state->sacks_array[a+1] = state->sacks_array[a];
01434 state->sacks_array[1].setStart(start_new);
01435 state->sacks_array[1].setEnd(end_new);
01436 }
01437 }
01438
01439
01440
01441
01442
01443
01444
01445
01446 for (uint a=0; a<MAX_SACK_BLOCKS-1; a++)
01447 {
01448 uint i = 1;
01449 bool matched = false;
01450
01451 if (a==0 && skip_sacks_array)
01452 a = 1;
01453
01454 if (state->sacks_array[a+i].getStart() == 0)
01455 break;
01456
01457 while ((state->sacks_array[a].getStart() == state->sacks_array[a+i].getStart() ||
01458 state->sacks_array[a].getEnd() == state->sacks_array[a+i].getStart() ||
01459 state->sacks_array[a].getEnd() == state->sacks_array[a+i].getEnd())
01460 && a+i < MAX_SACK_BLOCKS && state->sacks_array[a].getStart()!=0)
01461 {
01462 matched = true;
01463 i++;
01464 overlap = true;
01465 }
01466 if (matched)
01467 state->sacks_array[a+1] = state->sacks_array[a+i];
01468 }
01469
01470 if (!skip_sacks_array && overlap && m<4)
01471 n--;
01472
01473 option.setKind(TCPOPTION_SACK);
01474 option.setLength(8*n+2);
01475 option.setValuesArraySize(2*n);
01476
01477
01478 uint counter = 0;
01479 for (uint a=0; a<n; a++)
01480 {
01481 option.setValues(counter,state->sacks_array[a].getStart());
01482 counter++;
01483 option.setValues(counter,state->sacks_array[a].getEnd());
01484 counter++;
01485 }
01486
01487
01488 options_len = used_options_len + 8*n + 2;
01489
01490 if (options_len <= 40)
01491 {
01492 tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+1);
01493 tcpseg->setOptions((tcpseg->getOptionsArraySize()-1),option);
01494
01495
01496 state->snd_sacks = state->snd_sacks+n;
01497 if (sndSacksVector)
01498 sndSacksVector->record(state->snd_sacks);
01499
01500 uint counter = 0;
01501 tcpEV << n << " SACK(s) added to header:\n";
01502 for (uint t=0; t<(n*2); t++)
01503 {
01504 counter++;
01505 tcpEV << counter << ". SACK:" << " [" << option.getValues(t);
01506 t++;
01507 tcpEV << ".." << option.getValues(t) << ")";
01508 if (t==1)
01509 {
01510 if (state->snd_dsack)
01511 tcpEV << " (D-SACK)";
01512 else if (seqLE(option.getValues(t),state->rcv_nxt))
01513 {
01514 tcpEV << " (received segment filled out a gap)";
01515 state->snd_dsack = true;
01516 }
01517 }
01518 tcpEV << "\n";
01519 }
01520 }
01521 else
01522 tcpEV << "ERROR: Option length exceeded! Segment will be sent without SACK(s)" << "\n";
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534 if (state->snd_dsack)
01535 {
01536 for (int a=1; a<MAX_SACK_BLOCKS; a++)
01537 state->sacks_array[a-1] = state->sacks_array[a];
01538
01539
01540 state->sacks_array[MAX_SACK_BLOCKS-1].setStart(0);
01541 state->sacks_array[MAX_SACK_BLOCKS-1].setEnd(0);
01542 }
01543
01544
01545 skip_sacks_array = false;
01546 state->snd_sack = false;
01547 state->snd_dsack = false;
01548 state->start_seqno = 0;
01549 state->end_seqno = 0;
01550
01551 return *tcpseg;
01552 }
01553
01554 uint32 TCPConnection::getTSval(TCPSegment *tcpseg)
01555 {
01556 for (uint i=0; i<tcpseg->getOptionsArraySize(); i++)
01557 {
01558 const TCPOption& option = tcpseg->getOptions(i);
01559 short kind = option.getKind();
01560 if (kind == TCPOPTION_TIMESTAMP)
01561 return option.getValues(0);
01562 }
01563 return 0;
01564 }
01565
01566 uint32 TCPConnection::getTSecr(TCPSegment *tcpseg)
01567 {
01568 for (uint i=0; i<tcpseg->getOptionsArraySize(); i++)
01569 {
01570 const TCPOption& option = tcpseg->getOptions(i);
01571 short kind = option.getKind();
01572 if (kind == TCPOPTION_TIMESTAMP)
01573 return option.getValues(1);
01574 }
01575 return 0;
01576 }
01577
01578 void TCPConnection::updateRcvQueueVars()
01579 {
01580
01581 state->freeRcvBuffer = receiveQueue->getAmountOfFreeBytes(state->maxRcvBuffer);
01582 state->usedRcvBuffer = state->maxRcvBuffer - state->freeRcvBuffer;
01583
01584
01585 if (tcpRcvQueueBytesVector)
01586 tcpRcvQueueBytesVector->record(state->usedRcvBuffer);
01587
01588
01589 }
01590
01591 unsigned short TCPConnection::updateRcvWnd()
01592 {
01593 uint32 win = 0;
01594
01595
01596 updateRcvQueueVars();
01597 win = state->freeRcvBuffer;
01598
01599
01600
01601 if (win < (state->maxRcvBuffer / 4) && win < state->snd_mss)
01602 win = 0;
01603
01604
01605
01606 if (win < state->rcv_adv - state->rcv_nxt)
01607 win = state->rcv_adv - state->rcv_nxt;
01608
01609
01610 if (win > TCP_MAX_WIN && !state->ws_enabled)
01611 win = TCP_MAX_WIN;
01612
01613
01614
01615
01616 if (win > 0 && seqGE(state->rcv_nxt + win, state->rcv_adv))
01617 {
01618 state->rcv_adv = state->rcv_nxt + win;
01619 if (rcvAdvVector)
01620 rcvAdvVector->record(state->rcv_adv);
01621 }
01622
01623 state->rcv_wnd = win;
01624 if (rcvWndVector)
01625 rcvWndVector->record(state->rcv_wnd);
01626
01627
01628 uint32 scaled_rcv_wnd = state->rcv_wnd;
01629 state->rcv_wnd_scale = 0;
01630 if (state->ws_enabled)
01631 {
01632 while (scaled_rcv_wnd > TCP_MAX_WIN && state->rcv_wnd_scale < 14)
01633 {
01634 scaled_rcv_wnd = scaled_rcv_wnd >> 1;
01635 state->rcv_wnd_scale++;
01636 }
01637 }
01638 ASSERT(scaled_rcv_wnd == (unsigned short)scaled_rcv_wnd);
01639 return (unsigned short) scaled_rcv_wnd;
01640 }
01641
01642 void TCPConnection::updateWndInfo(TCPSegment *tcpseg, bool doAlways)
01643 {
01644 uint32 true_window = tcpseg->getWindow();
01645
01646
01647
01648
01649
01650 if (state->ws_enabled && !tcpseg->getSynBit())
01651 true_window = tcpseg->getWindow() << state->snd_wnd_scale;
01652
01653
01654 if (doAlways || (tcpseg->getAckBit()
01655 && (seqLess(state->snd_wl1, tcpseg->getSequenceNo()) ||
01656 (state->snd_wl1 == tcpseg->getSequenceNo() && seqLE(state->snd_wl2, tcpseg->getAckNo())) ||
01657 (state->snd_wl2 == tcpseg->getAckNo() && true_window > state->snd_wnd))))
01658 {
01659
01660 state->snd_wnd = true_window;
01661 tcpEV << "Updating send window from segment: new wnd=" << state->snd_wnd << "\n";
01662 state->snd_wl1 = tcpseg->getSequenceNo();
01663 state->snd_wl2 = tcpseg->getAckNo();
01664 if (sndWndVector)
01665 sndWndVector->record(state->snd_wnd);
01666 }
01667 }
01668
01669 bool TCPConnection::isLost(uint32 seqNum)
01670 {
01671 ASSERT (state->sack_enabled);
01672
01673
01674
01675
01676
01677
01678 bool isLost = false;
01679
01680 ASSERT(seqGE(seqNum,state->snd_una));
01681
01682 if (rexmitQueue->getNumOfDiscontiguousSacks(seqNum) >= DUPTHRESH ||
01683 rexmitQueue->getAmountOfSackedBytes(seqNum) >= (DUPTHRESH * state->snd_mss))
01684 isLost = true;
01685 else
01686 isLost = false;
01687
01688 return isLost;
01689 }
01690
01691 void TCPConnection::setPipe()
01692 {
01693 ASSERT (state->sack_enabled);
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713 state->highRxt = rexmitQueue->getHighestRexmittedSeqNum();
01714 state->pipe = 0;
01715
01716 uint32 shift = state->snd_mss;
01717 if (state->ts_enabled)
01718 shift -= TCP_OPTION_TS_SIZE;
01719
01720
01721
01722
01723
01724
01725
01726 for (uint32 s1=state->snd_una; s1<state->snd_max; s1=s1+shift)
01727 {
01728 if (rexmitQueue->getSackedBit(s1)==false)
01729 {
01730
01731
01732
01733
01734
01735
01736
01737
01738 if (isLost(s1)==false)
01739 state->pipe++;
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750 if (seqLE(s1,state->highRxt))
01751 state->pipe++;
01752 }
01753 }
01754
01755 state->pipe = state->pipe * shift;
01756 if (pipeVector)
01757 pipeVector->record(state->pipe);
01758 }
01759
01760 uint32 TCPConnection::nextSeg()
01761 {
01762 ASSERT (state->sack_enabled);
01763
01764
01765
01766
01767
01768
01769
01770 state->highRxt = rexmitQueue->getHighestRexmittedSeqNum();
01771 uint32 seqNum = 0;
01772 bool found = false;
01773 uint32 shift = state->snd_mss;
01774 if (state->ts_enabled)
01775 shift -= TCP_OPTION_TS_SIZE;
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788 for (uint32 s2=state->snd_una; s2<state->snd_max; s2=s2+shift)
01789 {
01790 if (rexmitQueue->getSackedBit(s2)==false)
01791 {
01792 if (seqGE(s2,state->highRxt) &&
01793 seqLE(s2,(rexmitQueue->getHighestSackedSeqNum())) &&
01794 isLost(s2))
01795 {
01796 seqNum = s2;
01797 found = true;
01798 return seqNum;
01799 }
01800 }
01801 }
01802
01803
01804
01805
01806
01807
01808 if (!found)
01809 {
01810
01811 ulong buffered = sendQueue->getBytesAvailable(state->snd_max);
01812 ulong maxWindow = state->snd_wnd;
01813
01814 ulong effectiveWin = maxWindow - state->pipe;
01815 if (buffered > 0 && effectiveWin >= state->snd_mss)
01816 {
01817 seqNum = state->snd_max;
01818 found = true;
01819 return seqNum;
01820 }
01821 }
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849 if (!found)
01850 {
01851 for (uint32 s3=state->snd_una; s3<state->snd_max; s3=s3+shift)
01852 {
01853 if (rexmitQueue->getSackedBit(s3)==false)
01854 {
01855 if (seqGE(s3,state->highRxt) &&
01856 seqLE(s3,(rexmitQueue->getHighestSackedSeqNum())))
01857 {
01858 seqNum = s3;
01859 found = true;
01860 return seqNum;
01861 }
01862 }
01863 }
01864 }
01865
01866
01867
01868
01869 if (!found)
01870 seqNum = 0;
01871
01872 return seqNum;
01873 }
01874
01875 void TCPConnection::sendDataDuringLossRecoveryPhase(uint32 congestionWindow)
01876 {
01877 ASSERT (state->sack_enabled && state->lossRecovery);
01878
01879
01880
01881
01882
01883
01884
01885 while (((int)congestionWindow - (int)state->pipe) >= (int)state->snd_mss)
01886 {
01887
01888
01889
01890
01891
01892 uint32 seqNum = nextSeg();
01893 if (seqNum != 0)
01894 {
01895 sendSegmentDuringLossRecoveryPhase(seqNum);
01896
01897
01898
01899 state->pipe += state->sentBytes;
01900 }
01901 else
01902 break;
01903 }
01904 }
01905
01906 void TCPConnection::sendSegmentDuringLossRecoveryPhase(uint32 seqNum)
01907 {
01908 ASSERT (state->sack_enabled && state->lossRecovery);
01909
01910 state->snd_nxt = seqNum;
01911
01912 uint32 old_highRxt = rexmitQueue->getHighestRexmittedSeqNum();
01913
01914
01915
01916 sendSegment(state->snd_mss);
01917
01918 uint32 sentSeqNum = seqNum + state->sentBytes;
01919
01920
01921
01922
01923 if (seqLE(sentSeqNum, state->snd_max))
01924 {
01925 ASSERT (sentSeqNum==rexmitQueue->getHighestRexmittedSeqNum());
01926 state->highRxt = rexmitQueue->getHighestRexmittedSeqNum();
01927 }
01928
01929
01930
01931 else if (seqGE(sentSeqNum, state->snd_max))
01932 state->snd_max = sentSeqNum;
01933
01934 if (unackedVector)
01935 unackedVector->record(state->snd_max - state->snd_una);
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959 tcpAlgorithm->ackSent();
01960 if (old_highRxt != state->highRxt)
01961 {
01962
01963 tcpEV << "Retransmission sent during recovery, restarting REXMIT timer.\n";
01964 tcpAlgorithm->restartRexmitTimer();
01965 }
01966 else
01967 tcpAlgorithm->dataSent(seqNum);
01968 }
01969
01970 void TCPConnection::sendOneNewSegment(bool fullSegmentsOnly, uint32 congestionWindow)
01971 {
01972 ASSERT (state->limited_transmit_enabled);
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002 if (!state->sack_enabled || (state->sack_enabled && state->sackedBytes_old!=state->sackedBytes))
02003 {
02004
02005 ulong buffered = sendQueue->getBytesAvailable(state->snd_max);
02006
02007 if (buffered >= state->snd_mss || (!fullSegmentsOnly && buffered > 0))
02008 {
02009 ulong outstandingData = state->snd_max - state->snd_una;
02010
02011 if (outstandingData + state->snd_mss <= state->snd_wnd &&
02012 outstandingData + state->snd_mss <= congestionWindow + 2*state->snd_mss)
02013 {
02014 uint32 effectiveWin = std::min (state->snd_wnd, congestionWindow) - outstandingData + 2*state->snd_mss;
02015
02016 uint32 bytes = std::min(effectiveWin, state->snd_mss);
02017 if (bytes >= state->snd_mss || (!fullSegmentsOnly && bytes > 0))
02018 {
02019 uint32 old_snd_nxt = state->snd_nxt;
02020
02021 state->snd_nxt = state->snd_max;
02022
02023 tcpEV << "Limited Transmit algorithm enabled. Sending one new segment.\n";
02024 sendSegment(bytes);
02025
02026 if (seqGreater(state->snd_nxt, state->snd_max))
02027 state->snd_max = state->snd_nxt;
02028
02029 if (unackedVector)
02030 unackedVector->record(state->snd_max - state->snd_una);
02031
02032
02033 if (state->afterRto)
02034 state->snd_nxt = old_snd_nxt + state->sentBytes;
02035
02036
02037 tcpAlgorithm->ackSent();
02038 tcpAlgorithm->dataSent(old_snd_nxt);
02039 }
02040 }
02041 }
02042 }
02043 }
02044
02045 uint32 TCPConnection::convertSimtimeToTS(simtime_t simtime)
02046 {
02047 ASSERT (SimTime::getScaleExp() <= -3);
02048 uint32 timestamp = (uint32) (simtime.dbl() * 1000);
02049 return timestamp;
02050 }
02051
02052 simtime_t TCPConnection::convertTSToSimtime(uint32 timestamp)
02053 {
02054 ASSERT (SimTime::getScaleExp() <= -3);
02055 simtime_t simtime = (simtime_t) ((double) timestamp * 0.001);
02056 return simtime;
02057 }
02058
02059 bool TCPConnection::isSendQueueEmpty()
02060 {
02061 return (sendQueue->getBytesAvailable(state->snd_nxt) == 0);
02062 }