TCPConnection.h

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2004 Andras Varga
00003 // Copyright (C) 2009-2010 Thomas Reschka
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public License
00016 // along with this program; if not, see <http://www.gnu.org/licenses/>.
00017 //
00018 
00019 #ifndef __INET_TCPCONNECTION_H
00020 #define __INET_TCPCONNECTION_H
00021 
00022 #include <omnetpp.h>
00023 #include "INETDefs.h"
00024 #include "IPvXAddress.h"
00025 #include "TCP.h"
00026 #include "TCPSegment.h"
00027 
00028 class TCPSegment;
00029 class TCPCommand;
00030 class TCPOpenCommand;
00031 class TCPSendQueue;
00032 class TCPSACKRexmitQueue;
00033 class TCPReceiveQueue;
00034 class TCPAlgorithm;
00035 
00036 
00037 //
00038 // TCP FSM states
00039 //
00040 // Brief descriptions (cf RFC 793, page 20):
00041 //
00042 // LISTEN - waiting for a connection request
00043 // SYN-SENT - part of 3-way handshake (waiting for peer's SYN+ACK or SYN)
00044 // SYN-RECEIVED - part of 3-way handshake (we sent SYN too, waiting for it to be acked)
00045 // ESTABLISHED - normal data transfer
00046 // FIN-WAIT-1 - FIN sent, waiting for its ACK (or peer's FIN)
00047 // FIN-WAIT-2 - our side of the connection closed (our FIN acked), waiting for peer's FIN
00048 // CLOSE-WAIT - FIN received and acked, waiting for local user to close
00049 // LAST-ACK - remote side closed, FIN sent, waiting for its ACK
00050 // CLOSING - simultaneous close: sent FIN, then got peer's FIN
00051 // TIME-WAIT - both FIN's acked, waiting for some time to be sure remote TCP received our ACK
00052 // CLOSED - represents no connection state at all.
00053 //
00054 // Note: FIN-WAIT-1, FIN-WAIT-2, CLOSING, TIME-WAIT represents active close (that is,
00055 // local user closes first), and CLOSE-WAIT and LAST-ACK represents passive close.
00056 //
00057 enum TcpState
00058 {
00059     TCP_S_INIT        = 0,
00060     TCP_S_CLOSED      = FSM_Steady(1),
00061     TCP_S_LISTEN      = FSM_Steady(2),
00062     TCP_S_SYN_SENT    = FSM_Steady(3),
00063     TCP_S_SYN_RCVD    = FSM_Steady(4),
00064     TCP_S_ESTABLISHED = FSM_Steady(5),
00065     TCP_S_CLOSE_WAIT  = FSM_Steady(6),
00066     TCP_S_LAST_ACK    = FSM_Steady(7),
00067     TCP_S_FIN_WAIT_1  = FSM_Steady(8),
00068     TCP_S_FIN_WAIT_2  = FSM_Steady(9),
00069     TCP_S_CLOSING     = FSM_Steady(10),
00070     TCP_S_TIME_WAIT   = FSM_Steady(11)
00071 };
00072 
00073 
00074 //
00075 // Event, strictly for the FSM state transition purposes.
00076 // DO NOT USE outside performStateTransition()!
00077 //
00078 enum TCPEventCode
00079 {
00080     TCP_E_IGNORE,
00081 
00082     // app commands
00083     // (Note: no RECEIVE command, data are automatically passed up)
00084     TCP_E_OPEN_ACTIVE,
00085     TCP_E_OPEN_PASSIVE,
00086     TCP_E_SEND,
00087     TCP_E_CLOSE,
00088     TCP_E_ABORT,
00089     TCP_E_STATUS,
00090 
00091     // TPDU types
00092     TCP_E_RCV_DATA,
00093     TCP_E_RCV_ACK,
00094     TCP_E_RCV_SYN,
00095     TCP_E_RCV_SYN_ACK,
00096     TCP_E_RCV_FIN,
00097     TCP_E_RCV_FIN_ACK,
00098     TCP_E_RCV_RST, // covers RST+ACK too
00099 
00100     TCP_E_RCV_UNEXP_SYN, // unexpected SYN
00101 
00102     // timers
00103     TCP_E_TIMEOUT_2MSL,     // RFC 793, a.k.a. TIME-WAIT timer
00104     TCP_E_TIMEOUT_CONN_ESTAB,
00105     TCP_E_TIMEOUT_FIN_WAIT_2,
00106 
00107     // All other timers (REXMT, PERSIST, DELAYED-ACK, KEEP-ALIVE, etc.),
00108     // are handled in TCPAlgorithm.
00109 };
00110 
00111 
00114 #define TCP_TIMEOUT_CONN_ESTAB    75    // 75 seconds
00115 #define TCP_TIMEOUT_FIN_WAIT_2   600    // 10 minutes
00116 #define TCP_TIMEOUT_2MSL         240    // 2 * 2 minutes
00117 #define TCP_TIMEOUT_SYN_REXMIT     3    // initially 3 seconds
00118 #define TCP_TIMEOUT_SYN_REXMIT_MAX 240  // 4 mins (will only be used with SYN+ACK: with SYN CONN_ESTAB occurs sooner)
00119 
00120 
00121 #define MAX_SYN_REXMIT_COUNT     12     // will only be used with SYN+ACK: with SYN CONN_ESTAB occurs sooner
00122 
00123 #define MAX_SACK_BLOCKS           60    // will only be used with SACK
00124 #define DUPTHRESH                  3    // used for TCPTahoe, TCPReno and SACK (RFC 3517)
00125 
00126 #define TCP_MAX_WIN            65535    // largest value (16 bit) for (unscaled) window size
00127 
00128 #define PAWS_IDLE_TIME_THRESH 24*24*3600 // 24 days in seconds (RFC 1323)
00129 
00130 #define TCP_OPTION_TS_SIZE  12
00131 
00144 class INET_API TCPStateVariables : public cPolymorphic
00145 {
00146   public:
00147     TCPStateVariables();
00148     virtual std::string info() const;
00149     virtual std::string detailedInfo() const;
00150   public:
00151     bool active;         // set if the connection was initiated by an active open
00152     bool fork;           // if passive and in LISTEN: whether to fork on an incoming connection
00153 
00154     uint32 snd_mss;      // sender maximum segment size (without headers, i.e. only segment text); see RFC 2581, page 1.
00155                          // This will be set to the minimum of the local smss parameter and the value specified in the
00156                          // MSS option received during connection setup.
00157 
00158     // send sequence number variables (see RFC 793, "3.2. Terminology")
00159     uint32 snd_una;      // send unacknowledged
00160     uint32 snd_nxt;      // send next (drops back on retransmission)
00161     uint32 snd_max;      // max seq number sent (needed because snd_nxt is re-set on retransmission)
00162     uint32 snd_wnd;      // send window
00163     uint32 snd_up;       // send urgent pointer
00164     uint32 snd_wl1;      // segment sequence number used for last window update
00165     uint32 snd_wl2;      // segment ack. number used for last window update
00166     uint32 iss;          // initial sequence number (ISS)
00167 
00168     // receive sequence number variables
00169     uint32 rcv_nxt;      // receive next
00170     uint32 rcv_wnd;      // receive window
00171     uint32 rcv_up;       // receive urgent pointer;
00172     uint32 irs;          // initial receive sequence number
00173     uint32 rcv_adv;      // advertised window
00174 
00175     // SYN, SYN+ACK retransmission variables (handled separately
00176     // because normal rexmit belongs to TCPAlgorithm)
00177     int syn_rexmit_count; // number of SYN/SYN+ACK retransmissions (=1 after first rexmit)
00178     simtime_t syn_rexmit_timeout; // current SYN/SYN+ACK retransmission timeout
00179 
00180     // whether ACK of our FIN has been received. Needed in FIN bit processing
00181     // to decide between transition to TIME-WAIT and CLOSING (set event code
00182     // TCP_E_RCV_FIN or TCP_E_RCV_FIN_ACK).
00183     bool fin_ack_rcvd;
00184 
00185     bool send_fin;       // true if a user CLOSE command has been "queued"
00186     uint32 snd_fin_seq;  // if send_fin==true: FIN should be sent just before this sequence number
00187 
00188     bool fin_rcvd;       // whether FIN received or not
00189     uint32 rcv_fin_seq;  // if fin_rcvd: sequence number of received FIN
00190 
00191     uint32 sentBytes;    // amount of user data (in bytes) sent in last segment
00192 
00193     bool nagle_enabled;         // set if Nagle's algorithm (RFC 896) is enabled
00194     bool delayed_acks_enabled;  // set if delayed ACK algorithm (RFC 1122) is enabled
00195     bool limited_transmit_enabled; // set if Limited Transmit algorithm (RFC 3042) is enabled
00196     bool increased_IW_enabled;  // set if Increased Initial Window (RFC 3390) is enabled
00197 
00198     uint32 full_sized_segment_counter; // this counter is needed for delayed ACK
00199     bool ack_now;               // send ACK immediately, needed if delayed_acks_enabled is set
00200                                 // Based on [Stevens, W.R.: TCP/IP Illustrated, Volume 2, page 861].
00201                                 // ack_now should be set when:
00202                                 //   - delayed ACK timer expires
00203                                 //   - an out-of-order segment is received
00204                                 //   - SYN is received during the three-way handshake
00205                                 //   - a persist probe is received
00206                                 //   - FIN is received
00207 
00208     bool afterRto;              // set at RTO, reset when snd_nxt == snd_max or snd_una == snd_max
00209 
00210     // WINDOW_SCALE related variables
00211     bool ws_support;         // set if the host supports Window Scale (header option) (RFC 1322)
00212     bool ws_enabled;         // set if the connection uses Window Scale (header option)
00213     bool snd_ws;             // set if initial WINDOW_SCALE has been sent
00214     bool rcv_ws;             // set if initial WINDOW_SCALE has been received
00215     uint rcv_wnd_scale;      // RFC 1323, page 31: "Receive window scale power"
00216     uint snd_wnd_scale;      // RFC 1323, page 31: "Send window scale power"
00217 
00218     // TIMESTAMP related variables
00219     bool ts_support;         // set if the host supports Timestamps (header option) (RFC 1322)
00220     bool ts_enabled;         // set if the connection uses Window Scale (header option)
00221     bool snd_initial_ts;     // set if initial TIMESTAMP has been sent
00222     bool rcv_initial_ts;     // set if initial TIMESTAMP has been received
00223     uint32 ts_recent;        // RFC 1323, page 31: "Latest received Timestamp"
00224     uint32 last_ack_sent;    // RFC 1323, page 31: "Last ACK field sent"
00225     simtime_t time_last_data_sent; // time at which the last data segment was sent (needed to compute the IDLE time for PAWS)
00226 
00227     // SACK related variables
00228     bool sack_support;       // set if the host supports selective acknowledgment (header option) (RFC 2018, 2883, 3517)
00229     bool sack_enabled;       // set if the connection uses selective acknowledgment (header option)
00230     bool snd_sack_perm;      // set if SACK_PERMITTED has been sent
00231     bool rcv_sack_perm;      // set if SACK_PERMITTED has been received
00232     uint32 start_seqno;      // start sequence number of last received out-of-order segment
00233     uint32 end_seqno;        // end sequence number of last received out-of-order segment
00234     bool snd_sack;           // set if received vaild out-of-order segment or rcv_nxt changed, but receivedQueue is not empty
00235     bool snd_dsack;          // set if received duplicated segment (sequenceNo+PLength < rcv_nxt) or (segment is not acceptable)
00236     Sack sacks_array[MAX_SACK_BLOCKS]; // MAX_SACK_BLOCKS is set to 60
00237     uint32 highRxt;          // RFC 3517, page 3: ""HighRxt" is the highest sequence number which has been retransmitted during the current loss recovery phase."
00238     uint32 pipe;             // RFC 3517, page 3: ""Pipe" is a sender's estimate of the number of bytes outstanding in the network."
00239     uint32 recoveryPoint;    // RFC 3517
00240     uint32 sackedBytes;      // number of sackedBytes
00241     uint32 sackedBytes_old;  // old number of sackedBytes - needed for RFC 3042 to check if last dupAck contained new sack information
00242     bool lossRecovery;       // indicates if algorithm is in loss recovery phase
00243 
00244     // those counters would logically belong to TCPAlgorithm, but it's a lot easier to manage them here
00245     uint32 dupacks;          // current number of received consecutive duplicate ACKs
00246     uint32 snd_sacks;        // number of sent sacks
00247     uint32 rcv_sacks;        // number of received sacks
00248     uint32 rcv_oooseg;       // number of received out-of-order segments
00249 
00250     // receiver buffer / receiver queue related variables
00251     uint32 maxRcvBuffer;     // maximal amount of bytes in tcp receive queue
00252     uint32 usedRcvBuffer;    // current amount of used bytes in tcp receive queue
00253     uint32 freeRcvBuffer;    // current amount of free bytes in tcp receive queue
00254     uint32 tcpRcvQueueDrops; // number of drops in tcp receive queue
00255 };
00256 
00257 
00258 
00307 class INET_API TCPConnection
00308 {
00309   public:
00310     // connection identification by apps: appgateIndex+connId
00311     int appGateIndex; // application gate index
00312     int connId;       // identifies connection within the app
00313 
00314     // socket pair
00315     IPvXAddress localAddr;
00316     IPvXAddress remoteAddr;
00317     int localPort;
00318     int remotePort;
00319 
00320   protected:
00321     TCP *tcpMain; // TCP module
00322 
00323     // TCP state machine
00324     cFSM fsm;
00325 
00326     // variables associated with TCP state
00327     TCPStateVariables *state;
00328 
00329     // TCP queues
00330     TCPSendQueue *sendQueue;
00331     TCPReceiveQueue *receiveQueue;
00332  public:
00333 
00334     TCPSACKRexmitQueue *rexmitQueue;
00335 
00336  protected:
00337     // TCP behavior in data transfer state
00338     TCPAlgorithm *tcpAlgorithm;
00339 
00340     // timers
00341     cMessage *the2MSLTimer;
00342     cMessage *connEstabTimer;
00343     cMessage *finWait2Timer;
00344     cMessage *synRexmitTimer; // for retransmitting SYN and SYN+ACK
00345 
00346     // statistics
00347     cOutVector *sndWndVector;   // snd_wnd
00348     cOutVector *rcvWndVector;   // rcv_wnd
00349     cOutVector *rcvAdvVector;   // current advertised window (=rcv_avd)
00350     cOutVector *sndNxtVector;   // sent seqNo
00351     cOutVector *sndAckVector;   // sent ackNo
00352     cOutVector *rcvSeqVector;   // received seqNo
00353     cOutVector *rcvAckVector;   // received ackNo (= snd_una)
00354     cOutVector *unackedVector;  // number of bytes unacknowledged
00355 
00356     cOutVector *dupAcksVector;   // current number of received dupAcks
00357     cOutVector *pipeVector;      // current sender's estimate of bytes outstanding in the network
00358     cOutVector *sndSacksVector;  // number of sent Sacks
00359     cOutVector *rcvSacksVector;  // number of received Sacks
00360     cOutVector *rcvOooSegVector; // number of received out-of-order segments
00361 
00362     cOutVector *sackedBytesVector;        // current number of received sacked bytes
00363     cOutVector *tcpRcvQueueBytesVector;   // current amount of used bytes in tcp receive queue
00364     cOutVector *tcpRcvQueueDropsVector;   // number of drops in tcp receive queue
00365 
00366   protected:
00370     virtual TCPEventCode preanalyseAppCommandEvent(int commandCode);
00372     virtual bool performStateTransition(const TCPEventCode& event);
00374     virtual void stateEntered(int state);
00376 
00379     virtual void process_OPEN_ACTIVE(TCPEventCode& event, TCPCommand *tcpCommand, cMessage *msg);
00380     virtual void process_OPEN_PASSIVE(TCPEventCode& event, TCPCommand *tcpCommand, cMessage *msg);
00381     virtual void process_SEND(TCPEventCode& event, TCPCommand *tcpCommand, cMessage *msg);
00382     virtual void process_CLOSE(TCPEventCode& event, TCPCommand *tcpCommand, cMessage *msg);
00383     virtual void process_ABORT(TCPEventCode& event, TCPCommand *tcpCommand, cMessage *msg);
00384     virtual void process_STATUS(TCPEventCode& event, TCPCommand *tcpCommand, cMessage *msg);
00386 
00393     virtual bool tryFastRoute(TCPSegment *tcpseg);
00398     virtual TCPEventCode process_RCV_SEGMENT(TCPSegment *tcpseg, IPvXAddress src, IPvXAddress dest);
00399     virtual TCPEventCode processSegmentInListen(TCPSegment *tcpseg, IPvXAddress src, IPvXAddress dest);
00400     virtual TCPEventCode processSegmentInSynSent(TCPSegment *tcpseg, IPvXAddress src, IPvXAddress dest);
00401     virtual TCPEventCode processSegment1stThru8th(TCPSegment *tcpseg);
00402     virtual TCPEventCode processRstInSynReceived(TCPSegment *tcpseg);
00403     virtual bool processAckInEstabEtc(TCPSegment *tcpseg);
00405 
00408     virtual bool processMSSOption(TCPSegment *tcpseg, const TCPOption& option);
00409     virtual bool processWSOption(TCPSegment *tcpseg, const TCPOption& option);
00410     virtual bool processSACKPermittedOption(TCPSegment *tcpseg, const TCPOption& option);
00411     virtual bool processSACKOption(TCPSegment *tcpseg, const TCPOption& option);
00412     virtual bool processTSOption(TCPSegment *tcpseg, const TCPOption& option);
00414 
00417     virtual void process_TIMEOUT_2MSL();
00418     virtual void process_TIMEOUT_CONN_ESTAB();
00419     virtual void process_TIMEOUT_FIN_WAIT_2();
00420     virtual void process_TIMEOUT_SYN_REXMIT(TCPEventCode& event);
00422 
00424     virtual TCPConnection *cloneListeningConnection();
00425 
00427     virtual void initConnection(TCPOpenCommand *openCmd);
00428 
00430     virtual void configureStateVariables();
00431 
00433     virtual void selectInitialSeqNum();
00434 
00436     virtual bool isSegmentAcceptable(TCPSegment *tcpseg);
00437 
00439     virtual void sendSyn();
00440 
00442     virtual void sendSynAck();
00443 
00445     virtual void readHeaderOptions(TCPSegment *tcpseg);
00446 
00448     virtual TCPSegment writeHeaderOptions(TCPSegment *tcpseg);
00449 
00451     virtual TCPSegment addSacks(TCPSegment *tcpseg);
00452 
00454     virtual uint32 getTSval(TCPSegment *tcpseg);
00455 
00457     virtual uint32 getTSecr(TCPSegment *tcpseg);
00458   public:
00460     virtual void sendAck();
00461 
00467     virtual bool sendData(bool fullSegmentsOnly, uint32 congestionWindow);
00468 
00470     virtual bool sendProbe();
00471 
00473     virtual void retransmitOneSegment(bool called_at_rto);
00474 
00476     virtual void retransmitData();
00477 
00479     virtual void sendRst(uint32 seqNo);
00481     virtual void sendRst(uint32 seq, IPvXAddress src, IPvXAddress dest, int srcPort, int destPort);
00483     virtual void sendRstAck(uint32 seq, uint32 ack, IPvXAddress src, IPvXAddress dest, int srcPort, int destPort);
00484 
00486     virtual void sendFin();
00487 
00492     virtual void sendSegment(uint32 bytes);
00493 
00495     virtual void sendToIP(TCPSegment *tcpseg);
00496 
00501     virtual TCPSegment *createTCPSegment(const char *name);
00502 
00504     virtual void startSynRexmitTimer();
00505 
00507     virtual void signalConnectionTimeout();
00508 
00510     void scheduleTimeout(cMessage *msg, simtime_t timeout)
00511         {tcpMain->scheduleAt(simTime()+timeout, msg);}
00512 
00513   protected:
00515     cMessage *cancelEvent(cMessage *msg) {return tcpMain->cancelEvent(msg);}
00516 
00518     static void sendToIP(TCPSegment *tcpseg, IPvXAddress src, IPvXAddress dest);
00519 
00521     virtual void sendToApp(cMessage *msg);
00522 
00524     virtual void sendIndicationToApp(int code);
00525 
00527     virtual void sendEstabIndicationToApp();
00528 
00529   public:
00531     virtual void printConnBrief();
00533     static void printSegmentBrief(TCPSegment *tcpseg);
00535     static const char *stateName(int state);
00537     static const char *eventName(int event);
00539     static const char *indicationName(int code);
00541     static const char *optionName(int option);
00543     virtual void updateRcvQueueVars();
00544 
00548     virtual unsigned short updateRcvWnd();
00549 
00551     virtual void updateWndInfo(TCPSegment *tcpseg, bool doAlways=false);
00552 
00553   public:
00557     TCPConnection(TCP *mod, int appGateIndex, int connId);
00558 
00563     TCPConnection();
00564 
00568     virtual ~TCPConnection();
00569 
00576     virtual void segmentArrivalWhileClosed(TCPSegment *tcpseg, IPvXAddress src, IPvXAddress dest);
00577 
00580     int getFsmState() const {return fsm.getState();}
00581     TCPStateVariables *getState() {return state;}
00582     TCPSendQueue *getSendQueue() {return sendQueue;}
00583     TCPSACKRexmitQueue *getRexmitQueue() {return rexmitQueue;}
00584     TCPReceiveQueue *getReceiveQueue() {return receiveQueue;}
00585     TCPAlgorithm *getTcpAlgorithm() {return tcpAlgorithm;}
00586     TCP *getTcpMain() {return tcpMain;}
00588 
00594     virtual bool processTimer(cMessage *msg);
00595 
00601     virtual bool processTCPSegment(TCPSegment *tcpSeg, IPvXAddress srcAddr, IPvXAddress destAddr);
00602 
00608     virtual bool processAppCommand(cMessage *msg);
00609 
00618     virtual bool isLost(uint32 seqNum);
00619 
00626     virtual void setPipe();
00627 
00636     virtual uint32 nextSeg();
00637 
00641     virtual void sendDataDuringLossRecoveryPhase(uint32 congestionWindow);
00642 
00646     virtual void sendSegmentDuringLossRecoveryPhase(uint32 seqNum);
00647 
00651     virtual void sendOneNewSegment(bool fullSegmentsOnly, uint32 congestionWindow);
00652 
00656     virtual uint32 convertSimtimeToTS(simtime_t simtime);
00657 
00661     virtual simtime_t convertTSToSimtime(uint32 timestamp);
00662 
00666     virtual bool isSendQueueEmpty();
00667 
00668 };
00669 
00670 #endif