SCTP Class Reference

#include <SCTP.h>

List of all members.


Detailed Description

Implements the SCTP protocol. This section describes the internal architecture of the SCTP model.

You may want to check the SCTPSocket class which makes it easier to use SCTP from applications.

The SCTP protocol implementation is composed of several classes (discussion follows below):

SCTP subclassed from cSimpleModule. It manages socketpair-to-connection mapping, and dispatches segments and user commands to the appropriate SCTPAssociation object.

SCTPAssociation manages the connection, with the help of other objects. SCTPAssociation itself implements the basic SCTP "machinery": takes care of the state machine, stores the state variables (TCB), sends/receives etc.

SCTPAssociation internally relies on 3 objects. The first two are subclassed from SCTPSendQueue and SCTPReceiveQueue. They manage the actual data stream, so SCTPAssociation itself only works with sequence number variables. This makes it possible to easily accomodate need for various types of simulated data transfer: real byte stream, "virtual" bytes (byte counts only), and sequence of cMessage objects (where every message object is mapped to a SCTP sequence number range).

Currently implemented send queue and receive queue classes are SCTPVirtualDataSendQueue and SCTPVirtualDataRcvQueue which implement queues with "virtual" bytes (byte counts only).

The third object is subclassed from SCTPAlgorithm. Control over retransmissions, congestion control and ACK sending are "outsourced" from SCTPAssociation into SCTPAlgorithm: delayed acks, slow start, fast rexmit, etc. are all implemented in SCTPAlgorithm subclasses.

The concrete SCTPAlgorithm class to use can be chosen per connection (in OPEN) or in a module parameter.

Public Types

typedef std::map< int32,
AssocStat
AssocStatMap
typedef std::map< VTagPair, int32 > SctpVTagMap

Public Member Functions

void printInfoConnMap ()
void removeAssociation (SCTPAssociation *assoc)
virtual ~SCTP ()
virtual void initialize ()
virtual void handleMessage (cMessage *msg)
virtual void finish ()
void updateSockPair (SCTPAssociation *assoc, IPvXAddress localAddr, IPvXAddress remoteAddr, int32 localPort, int32 remotePort)
void addLocalAddress (SCTPAssociation *conn, IPvXAddress address)
void addLocalAddressToAllRemoteAddresses (SCTPAssociation *conn, IPvXAddress address, std::vector< IPvXAddress > remAddresses)
void addRemoteAddress (SCTPAssociation *conn, IPvXAddress localAddress, IPvXAddress remoteAddress)
void removeLocalAddressFromAllRemoteAddresses (SCTPAssociation *conn, IPvXAddress address, std::vector< IPvXAddress > remAddresses)
void removeRemoteAddressFromAllConnections (SCTPAssociation *conn, IPvXAddress address, std::vector< IPvXAddress > locAddresses)
void addForkedAssociation (SCTPAssociation *assoc, SCTPAssociation *newAssoc, IPvXAddress localAddr, IPvXAddress remoteAddr, int32 localPort, int32 remotePort)
int16 getEphemeralPort ()
SCTPAssociationgetAssoc (int32 assocId)
SCTPAssociationfindAssocWithVTag (uint32 peerVTag, uint32 remotePort, uint32 localPort)
SctpVTagMap getVTagMap ()

Static Public Member Functions

static int32 getNewConnId ()

Public Attributes

AssocStatMap assocStatMap
SctpVTagMap sctpVTagMap
simtime_t testTimeout
uint32 numGapReports
uint32 numPacketsReceived
uint32 numPacketsDropped

Static Public Attributes

static bool testing
static bool logverbose

Protected Types

typedef std::map< AppConnKey,
SCTPAssociation * > 
SctpAppConnMap
typedef std::map< SockPair,
SCTPAssociation * > 
SctpConnMap

Protected Member Functions

SCTPAssociationfindAssocForMessage (IPvXAddress srcAddr, IPvXAddress destAddr, uint32 srcPort, uint32 destPort, bool findListen)
SCTPAssociationfindAssocForApp (int32 appGateIndex, int32 assocId)
void sendAbortFromMain (SCTPMessage *sctpmsg, IPvXAddress srcAddr, IPvXAddress destAddr)
void sendShutdownCompleteFromMain (SCTPMessage *sctpmsg, IPvXAddress srcAddr, IPvXAddress destAddr)
void updateDisplayString ()

Protected Attributes

SctpAppConnMap sctpAppConnMap
SctpConnMap sctpConnMap
int32 sizeConnMap
uint16 nextEphemeralPort

Static Protected Attributes

static int32 nextConnId = 0

Classes

struct  AppConnKey
struct  AssocStat
struct  SockPair
struct  VTagPair


Member Typedef Documentation

typedef std::map<int32,AssocStat> SCTP::AssocStatMap

typedef std::map<VTagPair,int32> SCTP::SctpVTagMap

typedef std::map<AppConnKey,SCTPAssociation*> SCTP::SctpAppConnMap [protected]

typedef std::map<SockPair,SCTPAssociation*> SCTP::SctpConnMap [protected]


Constructor & Destructor Documentation

SCTP::~SCTP (  )  [virtual]

00122 {
00123         sctpEV3<<"delete SCTPMain\n";
00124         if (!(sctpAppConnMap.empty()))
00125         {
00126                 sctpEV3<<"clear appConnMap\n";
00127                 sctpAppConnMap.clear();
00128         }
00129         if (!(assocStatMap.empty()))
00130         {
00131                 assocStatMap.clear();
00132                 sctpEV3<<"clear assocStatMap\n";
00133         }
00134         sctpVTagMap.clear();
00135         sctpEV3<<"after clearing maps\n";
00136 }


Member Function Documentation

SCTPAssociation * SCTP::findAssocForMessage ( IPvXAddress  srcAddr,
IPvXAddress  destAddr,
uint32  srcPort,
uint32  destPort,
bool  findListen 
) [protected]

Referenced by handleMessage().

00431 {
00432         SockPair key;
00433 
00434         key.localAddr = destAddr;
00435         key.remoteAddr = srcAddr;
00436         key.localPort = destPort;
00437         key.remotePort = srcPort;
00438         SockPair save = key;
00439         sctpEV3<<"findAssocForMessage: srcAddr="<<destAddr<<" destAddr="<<srcAddr<<" srcPort="<<destPort<<"  destPort="<<srcPort<<"\n";
00440         printInfoConnMap();
00441 
00442         // try with fully qualified SockPair
00443         SctpConnMap::iterator i;
00444         i = sctpConnMap.find(key);
00445         if (i!=sctpConnMap.end())
00446                 return i->second;
00447 
00448 
00449         // try with localAddr missing (only localPort specified in passive/active open)
00450         key.localAddr.set("0.0.0.0");
00451 
00452         i = sctpConnMap.find(key);
00453         if (i!=sctpConnMap.end())
00454         {
00455 
00456                 //sctpEV3<<"try with localAddr missing (only localPort specified in passive/active open)\n";
00457 
00458                 return i->second;
00459         }
00460 
00461         if (findListen==true)
00462         {
00463                 /*key = save;
00464                 key.localPort = 0;
00465                 key.localAddr.set("0.0.0.0");
00466                 i = sctpConnMap.find(key);
00467                 if (i!=sctpConnMap.end())
00468                 {
00469                         return i->second;
00470                 }*/
00471 
00472 
00473                 // try fully qualified local socket + blank remote socket (for incoming SYN)
00474                 key = save;
00475                 key.remoteAddr.set("0.0.0.0");
00476                 key.remotePort = 0;
00477                 i = sctpConnMap.find(key);
00478                 if (i!=sctpConnMap.end())
00479                 {
00480 
00481                         //sctpEV3<<"try fully qualified local socket + blank remote socket \n";
00482 
00483                         return i->second;
00484                 }
00485 
00486 
00487                 // try with blank remote socket, and localAddr missing (for incoming SYN)
00488                 key.localAddr.set("0.0.0.0");
00489                 i = sctpConnMap.find(key);
00490                 if (i!=sctpConnMap.end())
00491                 {
00492 
00493                         //sctpEV3<<"try with blank remote socket, and localAddr missing \n";
00494 
00495                         return i->second;
00496                 }
00497         }
00498         // given up
00499 
00500         sctpEV3<<"giving up on trying to find assoc for localAddr="<<srcAddr<<" remoteAddr="<<destAddr<<" localPort="<<srcPort<<" remotePort="<<destPort<<"\n";
00501         return NULL;
00502 }

SCTPAssociation * SCTP::findAssocForApp ( int32  appGateIndex,
int32  assocId 
) [protected]

Referenced by handleMessage().

00505 {
00506         AppConnKey key;
00507         key.appGateIndex = appGateIndex;
00508         key.assocId = assocId;
00509         sctpEV3<<"findAssoc for appGateIndex "<<appGateIndex<<" and assoc "<<assocId<<"\n";
00510         SctpAppConnMap::iterator i = sctpAppConnMap.find(key);
00511         return i==sctpAppConnMap.end() ? NULL : i->second;
00512 }

void SCTP::sendAbortFromMain ( SCTPMessage sctpmsg,
IPvXAddress  srcAddr,
IPvXAddress  destAddr 
) [protected]

Referenced by handleMessage().

00296 {
00297         SCTPMessage *msg = new SCTPMessage();
00298 
00299         sctpEV3<<"\n\nSCTPMain:sendABORT \n";
00300 
00301         msg->setSrcPort(sctpmsg->getDestPort());
00302         msg->setDestPort(sctpmsg->getSrcPort());
00303         msg->setBitLength(SCTP_COMMON_HEADER*8);
00304         msg->setChecksumOk(true);
00305 
00306         SCTPAbortChunk* abortChunk = new SCTPAbortChunk("ABORT");
00307         abortChunk->setChunkType(ABORT);
00308         if (sctpmsg->getChunksArraySize()>0 && ((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==INIT)
00309         {
00310 
00311                 SCTPInitChunk* initChunk = check_and_cast<SCTPInitChunk *>(sctpmsg->getChunks(0));
00312                 abortChunk->setT_Bit(0);
00313                 msg->setTag(initChunk->getInitTag());
00314         }
00315         else
00316         {
00317                 abortChunk->setT_Bit(1);
00318                 msg->setTag(sctpmsg->getTag());
00319         }
00320         abortChunk->setBitLength(SCTP_ABORT_CHUNK_LENGTH*8);
00321         msg->addChunk(abortChunk);
00322         IPControlInfo *controlInfo = new IPControlInfo();
00323         controlInfo->setProtocol(IP_PROT_SCTP);
00324         controlInfo->setSrcAddr(srcAddr.get4());
00325         controlInfo->setDestAddr(destAddr.get4());
00326         msg->setControlInfo(controlInfo);
00327         send(msg,"to_ip");
00328 }

void SCTP::sendShutdownCompleteFromMain ( SCTPMessage sctpmsg,
IPvXAddress  srcAddr,
IPvXAddress  destAddr 
) [protected]

Referenced by handleMessage().

00331 {
00332         SCTPMessage *msg = new SCTPMessage();
00333 
00334         sctpEV3<<"\n\nSCTP:sendABORT \n";
00335 
00336         msg->setSrcPort(sctpmsg->getDestPort());
00337         msg->setDestPort(sctpmsg->getSrcPort());
00338         msg->setBitLength(SCTP_COMMON_HEADER*8);
00339         msg->setChecksumOk(true);
00340 
00341         SCTPShutdownCompleteChunk* scChunk = new SCTPShutdownCompleteChunk("SHUTDOWN_COMPLETE");
00342         scChunk->setChunkType(SHUTDOWN_COMPLETE);
00343         scChunk->setTBit(1);
00344         msg->setTag(sctpmsg->getTag());
00345 
00346         scChunk->setBitLength(SCTP_SHUTDOWN_ACK_LENGTH*8);
00347         msg->addChunk(scChunk);
00348         IPControlInfo *controlInfo = new IPControlInfo();
00349         controlInfo->setProtocol(IP_PROT_SCTP);
00350         controlInfo->setSrcAddr(srcAddr.get4());
00351         controlInfo->setDestAddr(destAddr.get4());
00352         msg->setControlInfo(controlInfo);
00353         send(msg,"to_ip");
00354 }

void SCTP::updateDisplayString (  )  [protected]

00358 {
00359         if (ev.disable_tracing)
00360         {
00361                 // in express mode, we don't bother to update the display
00362                 // (std::map's iteration is not very fast if map is large)
00363                 getDisplayString().setTagArg("t",0,"");
00364                 return;
00365         }
00366 
00367         //char buf[40];
00368         //sprintf(buf,"%d conns", sctpAppConnMap.size());
00369         //displayString().setTagArg("t",0,buf);
00370 
00371         /*int32 numCLOSED=0, numLISTEN=0, numSYN_SENT=0, numSYN_RCVD=0,
00372                 numESTABLISHED=0, numCLOSE_WAIT=0, numLAST_ACK=0, numFIN_WAIT_1=0,
00373                 numFIN_WAIT_2=0, numCLOSING=0, numTIME_WAIT=0;
00374 
00375         for (SctpAppConnMap::iterator i=sctpAppConnMap.begin(); i!=sctpAppConnMap.end(); ++i)
00376         {
00377                 int32 state = (*i).second->getFsmState();
00378                 switch(state)
00379                 {
00380                         // case SCTP_S_INIT:        numINIT++; break;
00381                         case SCTP_S_CLOSED:      numCLOSED++; break;
00382                         case SCTP_S_COOKIE_WAIT:      numLISTEN++; break;
00383                         case SCTP_S_COOKIE_ECHOED:    numSYN_SENT++; break;
00384                         case SCTP_S_ESTABLISHED: numESTABLISHED++; break;
00385                         case SCTP_S_SHUTDOWN_PENDING:  numCLOSE_WAIT++; break;
00386                         case SCTP_S_SHUTDOWN_SENT:    numLAST_ACK++; break;
00387                         case SCTP_S_SHUTDOWN_RECEIVED:  numFIN_WAIT_1++; break;
00388                         case SCTP_S_SHUTDOWN_ACK_SENT:  numFIN_WAIT_2++; break;
00389                 }
00390         }
00391         char buf2[200];
00392         buf2[0] = '\0';
00393         if (numCLOSED>0)     sprintf(buf2+strlen(buf2), "closed:%d ", numCLOSED);
00394         if (numLISTEN>0)     sprintf(buf2+strlen(buf2), "listen:%d ", numLISTEN);
00395         if (numSYN_SENT>0)   sprintf(buf2+strlen(buf2), "syn_sent:%d ", numSYN_SENT);
00396         if (numSYN_RCVD>0)   sprintf(buf2+strlen(buf2), "syn_rcvd:%d ", numSYN_RCVD);
00397         if (numESTABLISHED>0) sprintf(buf2+strlen(buf2),"estab:%d ", numESTABLISHED);
00398         if (numCLOSE_WAIT>0) sprintf(buf2+strlen(buf2), "close_wait:%d ", numCLOSE_WAIT);
00399         if (numLAST_ACK>0)   sprintf(buf2+strlen(buf2), "last_ack:%d ", numLAST_ACK);
00400         if (numFIN_WAIT_1>0) sprintf(buf2+strlen(buf2), "fin_wait_1:%d ", numFIN_WAIT_1);
00401         if (numFIN_WAIT_2>0) sprintf(buf2+strlen(buf2), "fin_wait_2:%d ", numFIN_WAIT_2);
00402         if (numCLOSING>0)    sprintf(buf2+strlen(buf2), "closing:%d ", numCLOSING);
00403         if (numTIME_WAIT>0)  sprintf(buf2+strlen(buf2), "time_wait:%d ", numTIME_WAIT);
00404         getDisplayString().setTagArg("t",0,buf2);*/
00405 }

void SCTP::printInfoConnMap (  ) 

Referenced by addForkedAssociation(), addLocalAddress(), addLocalAddressToAllRemoteAddresses(), addRemoteAddress(), SCTPAssociation::cloneAssociation(), findAssocForMessage(), findAssocWithVTag(), handleMessage(), removeAssociation(), removeLocalAddressFromAllRemoteAddresses(), removeRemoteAddressFromAllConnections(), SCTPAssociation::sendInit(), and updateSockPair().

00059 {
00060         SCTPAssociation* assoc;
00061         SockPair        key;
00062         sctpEV3<<"Number of Assocs: "<<sizeConnMap<<"\n";
00063         if (sizeConnMap>0)
00064         {
00065                 for (SctpConnMap::iterator i = sctpConnMap.begin(); i!=sctpConnMap.end(); ++i)
00066                 {
00067                         assoc = i->second;
00068                         key = i->first;
00069 
00070                                 sctpEV3<<"assocId: "<<assoc->assocId<<"  assoc: "<<assoc<<" src: "<<IPvXAddress(key.localAddr)<<" dst: "<<IPvXAddress(key.remoteAddr)<<" lPort: "<<key.localPort<<" rPort: "<<key.remotePort<<"\n";
00071 
00072                 }
00073 
00074                 sctpEV3<<"\n";
00075         }
00076 
00077 }

void SCTP::removeAssociation ( SCTPAssociation assoc  ) 

Referenced by finish(), handleMessage(), SCTPAssociation::process_RCV_Message(), SCTPAssociation::process_TIMEOUT_HEARTBEAT(), SCTPAssociation::process_TIMEOUT_INIT_REXMIT(), SCTPAssociation::process_TIMEOUT_RTX(), SCTPAssociation::process_TIMEOUT_SHUTDOWN(), SCTPAssociation::processTimer(), and SCTPAssociation::updateCounters().

00745 {
00746         SCTPAssociation *assoc;
00747         AppConnKey key;
00748         bool ok=false;
00749         bool find=false;
00750         int32 id;
00751         //SctpConnMap::iterator j;
00752 
00753 
00754         sctpEV3<< "Deleting SCTP connection "<<conn<<"  id="<<conn->assocId<<"\n";
00755 
00756         id = conn->assocId;
00757 
00758         printInfoConnMap();
00759         if (sizeConnMap > 0)
00760         {
00761                 AssocStatMap::iterator it=assocStatMap.find(conn->assocId);
00762                 if (it!=assocStatMap.end())
00763                 {
00764                         it->second.stop = simulation.getSimTime();
00765                         it->second.lifeTime = it->second.stop - it->second.start;
00766                         it->second.throughput = it->second.ackedBytes*8 / it->second.lifeTime.dbl();
00767                 }
00768                 while (!ok)
00769                 {
00770                         if (sizeConnMap == 0)
00771 
00772                                 ok=true;
00773                         else
00774                         {
00775                                 for (SctpConnMap::iterator j=sctpConnMap.begin(); j!=sctpConnMap.end(); j++)
00776                                 {
00777                                         if (j->second!=NULL)
00778                                         {
00779                                         assoc = j->second;
00780                                         if (assoc->assocId==conn->assocId)
00781                                         {
00782                                                 if (assoc->T1_InitTimer)
00783                                                         assoc->stopTimer(assoc->T1_InitTimer);
00784                                                 if (assoc->T2_ShutdownTimer)
00785                                                         assoc->stopTimer(assoc->T2_ShutdownTimer);
00786                                                 if (assoc->T5_ShutdownGuardTimer)
00787                                                         assoc->stopTimer(assoc->T5_ShutdownGuardTimer);
00788                                                 if (assoc->SackTimer)
00789                                                         assoc->stopTimer(assoc->SackTimer);
00790                                                 /*if (testTimeout > 0)
00791                                                         if (assoc->StartTesting)
00792                                                                 assoc->stopTimer(assoc->StartTesting);*/
00793                                                 /*if (!(sctpVTagMap.empty()))
00794                                                 for (SctpVTagMap::iterator k=sctpVTagMap.begin(); k!=sctpVTagMap.end(); k++)
00795                                                 {
00796                                                         assoc2 = k->second;
00797                                                         if (assoc2->assocId==id)
00798                                                         {
00799                                                                 sctpVTagMap.erase(k);
00800                                                                 break;
00801                                                         }
00802                                                 }*/
00803                                                 sctpConnMap.erase(j);
00804                                                 sizeConnMap--;
00805                                                 find=true;
00806                                                 break;
00807                                         }
00808                                         }
00809                                 }
00810                         }
00811 
00812                         if (!find)
00813                                 ok=true;
00814                         else
00815                                 find=false;
00816                 }
00817         }
00818                 //delete conn->StartAddIP;
00819         conn->removePath();
00820         conn->deleteStreams();
00821         delete conn->getRetransmissionQueue();
00822         key.appGateIndex = conn->appGateIndex;
00823         key.assocId = conn->assocId;
00824         sctpAppConnMap.erase(key);
00825         delete conn;
00826                 //printInfoConnMap();
00827         //}
00828 
00829 }

void SCTP::initialize (  )  [virtual]

00080 {
00081         nextEphemeralPort = (uint16)(rand()%10000 + 30000);
00082 
00083         //sctpEV3<<"SCTPMain initialize\n";
00084 
00085         cModule *netw = simulation.getSystemModule();
00086 
00087         testing = netw->hasPar("testing") && netw->par("testing").boolValue();
00088         if (netw->hasPar("testTimeout"))
00089         {
00090                 testTimeout = (simtime_t)netw->par("testTimeout");
00091         }
00092         numPacketsReceived = 0;
00093         numPacketsDropped = 0;
00094         sizeConnMap = 0;
00095 
00096         /*      double errorRate, delayTime;
00097         int32 dataRate;
00098          if (this->hasPar("errorRate"))
00099                 errorRate = (double)par("errorRate");
00100         if (this->hasPar("dataRate") && (int32)par("dataRate")>0)
00101                 dataRate = (int32)par("dataRate");
00102         if (this->hasPar("delayTime"))
00103                 delayTime = (double)par("delayTime");
00104         sctpEV3<<"errorRate="<<errorRate<<"\n";
00105         sctpEV3<<"dataRate = "<<dataRate<<"\n";
00106         sctpEV3<<"delayTime="<<delayTime<<"\n";
00107         cBasicChannel* chan = check_and_cast<cBasicChannel*>(netw->submodule("client")->gate("out",0)->channel());
00108         chan->setError(errorRate);
00109         chan->setDatarate(dataRate);
00110         chan->setDelay(delayTime);
00111         chan = check_and_cast<cBasicChannel*>(netw->submodule("server")->gate("out",0)->channel());
00112         chan->setError(errorRate);
00113         chan->setDatarate(dataRate);
00114         chan->setDelay(delayTime);
00115         recordScalar("errorRate", chan->error());
00116         recordScalar("delay",chan->delay());
00117         recordScalar("datarate",chan->datarate());*/
00118 }

void SCTP::handleMessage ( cMessage *  msg  )  [virtual]

00140 {
00141         IPvXAddress destAddr;
00142         IPvXAddress srcAddr;
00143         IPControlInfo *controlInfo =NULL;
00144         IPv6ControlInfo *controlInfoV6 =NULL;
00145         bool findListen = false;
00146         bool bitError = false;
00147 
00148         sctpEV3<<"\n\nSCTPMain handleMessage\n";
00149 
00150         if (msg->isSelfMessage())
00151         {
00152 
00153                 sctpEV3<<"selfMessage\n";
00154 
00155                 SCTPAssociation *assoc = (SCTPAssociation *) msg->getContextPointer();
00156                 bool ret = assoc->processTimer(msg);
00157 
00158                 if (!ret)
00159                         removeAssociation(assoc);
00160         }
00161         else if (msg->arrivedOn("from_ip") || msg->arrivedOn("from_ipv6"))
00162         {
00163                 sctpEV3<<"Message from IP\n";
00164                 printInfoConnMap();
00165                 if (!dynamic_cast<SCTPMessage *>(msg))
00166                 {
00167                         sctpEV3<<"no sctp message, delete it\n";
00168                         delete msg;
00169                         return;
00170                 }
00171                 SCTPMessage *sctpmsg = check_and_cast<SCTPMessage *>(msg);
00172 
00173                 numPacketsReceived++;
00174 
00175                 if ((sctpmsg->hasBitError() || !(sctpmsg->getChecksumOk())))
00176                 {
00177                         ev<<"Packet has bit-error. delete it\n";
00178 
00179                         bitError = true;
00180                         numPacketsDropped++;
00181                         delete msg;
00182                         return;
00183                 }
00184                 if (msg->arrivedOn("from_ip"))
00185                 {
00186                         controlInfo = check_and_cast<IPControlInfo *>(msg->removeControlInfo());
00187                         IPDatagram *datagram = controlInfo->removeOrigDatagram();
00188                         delete datagram;
00189                         sctpEV3<<"controlInfo srcAddr="<<controlInfo->getSrcAddr()<<"  destAddr="<<controlInfo->getDestAddr()<<"\n";
00190                         srcAddr = controlInfo->getSrcAddr();
00191                         destAddr = controlInfo->getDestAddr();
00192                 }
00193                 else
00194                 {
00195                         controlInfoV6 = check_and_cast<IPv6ControlInfo *>(msg->removeControlInfo());
00196                         srcAddr = controlInfoV6->getSrcAddr();
00197                         destAddr = controlInfoV6->getDestAddr();
00198                 }
00199 
00200 
00201                 sctpEV3<<"srcAddr="<<srcAddr<<"  destAddr="<<destAddr<<"\n";
00202                 if (sctpmsg->getBitLength()>(SCTP_COMMON_HEADER*8))
00203                 {
00204                         if (((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==INIT || ((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==INIT_ACK )
00205                                 findListen = true;
00206 
00207                         SCTPAssociation *assoc = findAssocForMessage(srcAddr, destAddr, sctpmsg->getSrcPort(),sctpmsg->getDestPort(), findListen);
00208                         if (!assoc && sctpConnMap.size()>0)
00209                                 assoc = findAssocWithVTag(sctpmsg->getTag(),sctpmsg->getSrcPort(), sctpmsg->getDestPort());
00210                         if (!assoc)
00211                         {
00212                                 sctpEV3<<"no assoc found msg="<<sctpmsg->getName()<<"\n";
00213                                 if (bitError)
00214                                 {
00215                                         delete sctpmsg;
00216                                         return;
00217                                 }
00218                                 if (((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==SHUTDOWN_ACK)
00219                                         sendShutdownCompleteFromMain(sctpmsg, destAddr, srcAddr);
00220                                 else if (((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()!=ABORT  &&
00221                                         ((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()!=SHUTDOWN_COMPLETE)
00222                                 {
00223                                         sendAbortFromMain(sctpmsg, destAddr, srcAddr);
00224                                 }
00225                                 delete sctpmsg;
00226                         }
00227                         else
00228                         {
00229                                 bool ret = assoc->processSCTPMessage(sctpmsg, srcAddr, destAddr);
00230                                 if (!ret)
00231                                 {
00232                                         sctpEV3<<"SCTPMain:: removeAssociation \n";
00233                                         removeAssociation(assoc);
00234                                         delete sctpmsg;
00235                                 }
00236                                 else
00237                                 {
00238                                         delete sctpmsg;
00239                                 }
00240                         }
00241                 }
00242                 else
00243                 {
00244                         delete sctpmsg;
00245                 }
00246         }
00247         else // must be from app
00248         {
00249                 sctpEV3<<"must be from app\n";
00250                 SCTPCommand *controlInfo = check_and_cast<SCTPCommand *>(msg->getControlInfo());
00251 
00252                 int32 appGateIndex;
00253                 if (controlInfo->getGate()!=-1)
00254                         appGateIndex = controlInfo->getGate();
00255                 else
00256                         appGateIndex = msg->getArrivalGate()->getIndex();
00257                 int32 assocId = controlInfo->getAssocId();
00258                 sctpEV3<<"msg arrived from app for assoc "<<assocId<<"\n";
00259                 SCTPAssociation *assoc = findAssocForApp(appGateIndex, assocId);
00260 
00261                 if (!assoc)
00262                 {
00263                         sctpEV3 << "no assoc found. msg="<<msg->getName()<<"\n";
00264 
00265                         if (strcmp(msg->getName(),"PassiveOPEN")==0 || strcmp(msg->getName(),"Associate")==0)
00266                         {
00267                                 assoc = new SCTPAssociation(this,appGateIndex,assocId);
00268 
00269                                 AppConnKey key;
00270                                 key.appGateIndex = appGateIndex;
00271                                 key.assocId = assocId;
00272                                 sctpAppConnMap[key] = assoc;
00273                                 sctpEV3 << "SCTP association created for appGateIndex " << appGateIndex << " and assoc "<<assocId<<"\n";
00274 
00275                                 bool ret = assoc->processAppCommand(PK(msg));
00276 
00277                                 if (!ret)
00278                                         removeAssociation(assoc);
00279                         }
00280                 }
00281                 else
00282                 {
00283                         sctpEV3<<"assoc found\n";
00284                         bool ret = assoc->processAppCommand(PK(msg));
00285 
00286                         if (!ret)
00287                                 removeAssociation(assoc);
00288                 }
00289                 delete msg;
00290         }
00291         /*if (ev.isGUI())
00292                 updateDisplayString();*/
00293 }

void SCTP::finish (  )  [virtual]

00842 {
00843 
00844         sctpEV3<<"SCTP::finish\n";
00845         sctpEV3<<" connMapSize="<<sizeConnMap<<"\n";
00846 
00847         if (sizeConnMap > 1)
00848 
00849         {
00850                 SctpConnMap::iterator j=sctpConnMap.begin();
00851                 while (j!=sctpConnMap.end())
00852                 {
00853                         removeAssociation(j->second);
00854                         if (j!=sctpConnMap.end())
00855                                 j=sctpConnMap.begin();
00856                 }
00857         }
00858         if (sizeConnMap==1)
00859         {
00860                 SctpConnMap::iterator j=sctpConnMap.begin();
00861                 if (j->second->T1_InitTimer)
00862                 {
00863                         j->second->stopTimer(j->second->T1_InitTimer);
00864                 }
00865                 if (j->second->T2_ShutdownTimer)
00866                 {
00867                         j->second->stopTimer(j->second->T2_ShutdownTimer);
00868                 }
00869                 if (j->second->T5_ShutdownGuardTimer)
00870                 {
00871                         j->second->stopTimer(j->second->T5_ShutdownGuardTimer);
00872                 }
00873                 if (j->second->SackTimer)
00874                 {
00875                         j->second->stopTimer(j->second->SackTimer);
00876                 }
00877                 //sctpConnMap.erase(j);
00878                 removeAssociation(j->second);
00879         }
00880         ev << getFullPath() << ": finishing SCTP with " << sctpConnMap.size() << " connections open.\n";
00881 
00882         for (AssocStatMap::iterator iter=assocStatMap.begin(); iter!=assocStatMap.end(); iter++)
00883         {
00884                 ev<<"Assoc "<<iter->second.assocId<<": started at "<<iter->second.start<<" and finished at "<<iter->second.stop<<" --> lifetime: "<<iter->second.lifeTime<<"\n";
00885                 recordScalar("lifetime", iter->second.lifeTime);
00886                 ev<<"Assoc "<<iter->second.assocId<<": sent Bytes="<<iter->second.sentBytes<<", acked Bytes="<<iter->second.ackedBytes<<", throughput="<<iter->second.throughput<<" Bit/sec\n";
00887                 recordScalar("acked Bytes", iter->second.ackedBytes);
00888                 recordScalar("throughput [Bit/sec]", iter->second.throughput);
00889                 ev<<"Assoc "<<iter->second.assocId<<": transmitted Bytes="<<iter->second.transmittedBytes<<", retransmitted Bytes="<<iter->second.transmittedBytes-iter->second.ackedBytes<<"\n";
00890                 recordScalar("transmitted Bytes", iter->second.transmittedBytes);
00891                 ev<<"Assoc "<<iter->second.assocId<<": Chunks Scheduled for Fast Retransmission="<<iter->second.numFastRtx<<", No timer based Rtx="<<iter->second.numT3Rtx<<", No path Failures="<<iter->second.numPathFailures<<", No ForwardTsn="<<iter->second.numForwardTsn<<"\n";
00892                 recordScalar("fast Rtx", iter->second.numFastRtx);
00893                 recordScalar("timer based Rtx", iter->second.numT3Rtx);
00894                 recordScalar("packets received", numPacketsReceived);
00895                 recordScalar("packets dropped", numPacketsDropped);
00896         }
00897         sctpEV3<<"Main was finished\n";
00898 }

void SCTP::updateSockPair ( SCTPAssociation assoc,
IPvXAddress  localAddr,
IPvXAddress  remoteAddr,
int32  localPort,
int32  remotePort 
)

To be called from SCTPAssociation when socket pair changes

Referenced by addForkedAssociation(), SCTPAssociation::process_ASSOCIATE(), SCTPAssociation::process_OPEN_PASSIVE(), and SCTPAssociation::processInitArrived().

00523 {
00524         SockPair key;
00525         sctpEV3<<"updateSockPair:  localAddr: "<<localAddr<<"  remoteAddr="<<remoteAddr<<"  localPort="<<localPort<<" remotePort="<<remotePort<<"\n";
00526 
00527         key.localAddr = (conn->localAddr = localAddr);
00528         key.remoteAddr = (conn->remoteAddr = remoteAddr);
00529         key.localPort = conn->localPort = localPort;
00530         key.remotePort = conn->remotePort = remotePort;
00531 
00532         for (SctpConnMap::iterator i=sctpConnMap.begin(); i!=sctpConnMap.end(); i++)
00533         {
00534                 if (i->second == conn)
00535                 {
00536                         sctpConnMap.erase(i);
00537                         break;
00538                 }
00539         }
00540 
00541         sctpEV3<<"updateSockPair conn="<<conn<<"  localAddr="<<key.localAddr<<"        remoteAddr="<<key.remoteAddr<<"  localPort="<<key.localPort<<"  remotePort="<<remotePort<<"\n";
00542 
00543         sctpConnMap[key] = conn;
00544         sizeConnMap = sctpConnMap.size();
00545         //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n";
00546         sctpEV3<<"assoc inserted in sctpConnMap\n";
00547         printInfoConnMap();
00548 }

void SCTP::addLocalAddress ( SCTPAssociation conn,
IPvXAddress  address 
)

Referenced by SCTPAssociation::processInitArrived(), and SCTPAssociation::sendInit().

00551 {
00552 
00553                 //sctpEV3<<"Add local address: "<<address<<"\n";
00554 
00555                 SockPair key;
00556 
00557                 key.localAddr = conn->localAddr;
00558                 key.remoteAddr = conn->remoteAddr;
00559                 key.localPort = conn->localPort;
00560                 key.remotePort = conn->remotePort;
00561 
00562                 SctpConnMap::iterator i = sctpConnMap.find(key);
00563                 if (i!=sctpConnMap.end())
00564                 {
00565                         ASSERT(i->second==conn);
00566                         if (key.localAddr.isUnspecified())
00567                         {
00568                                 sctpConnMap.erase(i);
00569                                 sizeConnMap--;
00570                         }
00571                 }
00572                 else
00573                         sctpEV3<<"no actual sockPair found\n";
00574                 key.localAddr = address;
00575                 //key.localAddr = address.get4().getInt();
00576                 // //sctpEV3<<"laddr="<<key.localAddr<<"  lp="<<key.localPort<<"  raddr="<<key.remoteAddr<<" rPort="<<key.remotePort<<"\n";
00577                 sctpConnMap[key] = conn;
00578                 sizeConnMap = sctpConnMap.size();
00579                 sctpEV3<<"number of connections="<<sizeConnMap<<"\n";
00580 
00581                 printInfoConnMap();
00582 }

void SCTP::addLocalAddressToAllRemoteAddresses ( SCTPAssociation conn,
IPvXAddress  address,
std::vector< IPvXAddress remAddresses 
)

00585 {
00586 
00587                 //sctpEV3<<"Add local address: "<<address<<"\n";
00588 
00589                 SockPair key;
00590 
00591                 for (AddressVector::iterator i=remAddresses.begin(); i!=remAddresses.end(); ++i)
00592                 {
00593                         //sctpEV3<<"remote address="<<(*i)<<"\n";
00594                         key.localAddr = conn->localAddr;
00595                         key.remoteAddr = (*i);
00596                         key.localPort = conn->localPort;
00597                         key.remotePort = conn->remotePort;
00598 
00599                         SctpConnMap::iterator j = sctpConnMap.find(key);
00600                         if (j!=sctpConnMap.end())
00601                         {
00602                         ASSERT(j->second==conn);
00603                         if (key.localAddr.isUnspecified())
00604                                         {
00605                                         sctpConnMap.erase(j);
00606                                         sizeConnMap--;
00607                                 }
00608 
00609                         }
00610                         else
00611                                 sctpEV3<<"no actual sockPair found\n";
00612                         key.localAddr = address;
00613                         sctpConnMap[key] = conn;
00614 
00615                         sizeConnMap++;
00616                         sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n";
00617 
00618                         printInfoConnMap();
00619                 }
00620 }

void SCTP::addRemoteAddress ( SCTPAssociation conn,
IPvXAddress  localAddress,
IPvXAddress  remoteAddress 
)

Referenced by SCTPAssociation::processInitAckArrived(), and SCTPAssociation::processInitArrived().

00685 {
00686 
00687         sctpEV3<<"Add remote Address: "<<remoteAddress<<" to local Address "<<localAddress<<"\n";
00688 
00689         SockPair key;
00690         key.localAddr = localAddress;
00691         key.remoteAddr = remoteAddress;
00692         key.localPort = conn->localPort;
00693         key.remotePort = conn->remotePort;
00694 
00695         SctpConnMap::iterator i = sctpConnMap.find(key);
00696         if (i!=sctpConnMap.end())
00697         {
00698                 ASSERT(i->second==conn);
00699         }
00700         else
00701         {
00702 
00703                 //sctpEV3<<"no actual sockPair found\n";
00704 
00705                 sctpConnMap[key] = conn;
00706                 sizeConnMap++;
00707         }
00708 
00709         //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n";
00710         printInfoConnMap();
00711 }

void SCTP::removeLocalAddressFromAllRemoteAddresses ( SCTPAssociation conn,
IPvXAddress  address,
std::vector< IPvXAddress remAddresses 
)

00623 {
00624 
00625                 //sctpEV3<<"Remove local address: "<<address<<"\n";
00626 
00627                 SockPair key;
00628 
00629                 for (AddressVector::iterator i=remAddresses.begin(); i!=remAddresses.end(); ++i)
00630                 {
00631                         //sctpEV3<<"remote address="<<(*i)<<"\n";
00632                         key.localAddr = address;
00633                         key.remoteAddr = (*i);
00634                         key.localPort = conn->localPort;
00635                         key.remotePort = conn->remotePort;
00636 
00637                         SctpConnMap::iterator j = sctpConnMap.find(key);
00638                         if (j!=sctpConnMap.end())
00639                         {
00640                                 ASSERT(j->second==conn);
00641                                 sctpConnMap.erase(j);
00642                                 sizeConnMap--;
00643                         }
00644                         else
00645                                 sctpEV3<<"no actual sockPair found\n";
00646 
00647                         //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n";
00648 
00649                         printInfoConnMap();
00650                 }
00651 }

void SCTP::removeRemoteAddressFromAllConnections ( SCTPAssociation conn,
IPvXAddress  address,
std::vector< IPvXAddress locAddresses 
)

00654 {
00655 
00656                 //sctpEV3<<"Remove remote address: "<<address<<"\n";
00657 
00658                 SockPair key;
00659 
00660                 for (AddressVector::iterator i=locAddresses.begin(); i!=locAddresses.end(); i++)
00661                 {
00662                         //sctpEV3<<"local address="<<(*i)<<"\n";
00663                         key.localAddr = (*i);
00664                         key.remoteAddr = address;
00665                         key.localPort = conn->localPort;
00666                         key.remotePort = conn->remotePort;
00667 
00668                         SctpConnMap::iterator j = sctpConnMap.find(key);
00669                         if (j!=sctpConnMap.end())
00670                         {
00671                                 ASSERT(j->second==conn);
00672                                 sctpConnMap.erase(j);
00673                                 sizeConnMap--;
00674                         }
00675                         else
00676                                 sctpEV3<<"no actual sockPair found\n";
00677 
00678                         //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n";
00679 
00680                         printInfoConnMap();
00681                 }
00682 }

void SCTP::addForkedAssociation ( SCTPAssociation assoc,
SCTPAssociation newAssoc,
IPvXAddress  localAddr,
IPvXAddress  remoteAddr,
int32  localPort,
int32  remotePort 
)

Update assocs socket pair, and register newAssoc (which'll keep LISTENing). Also, assoc will get a new assocId (and newAssoc will live on with its old assocId).

Referenced by SCTPAssociation::processInitArrived().

00714 {
00715 SockPair keyAssoc;
00716 
00717         ev<<"addForkedConnection assocId="<<assoc->assocId<<"  newId="<<newAssoc->assocId<<"\n";
00718 
00719         for (SctpConnMap::iterator j=sctpConnMap.begin(); j!=sctpConnMap.end(); ++j)
00720                 if (assoc->assocId==j->second->assocId)
00721                         keyAssoc = j->first;
00722         // update conn's socket pair, and register newConn (which'll keep LISTENing)
00723         updateSockPair(assoc, localAddr, remoteAddr, localPort, remotePort);
00724         updateSockPair(newAssoc, keyAssoc.localAddr, keyAssoc.remoteAddr, keyAssoc.localPort, keyAssoc.remotePort);
00725         // conn will get a new assocId...
00726         AppConnKey key;
00727         key.appGateIndex = assoc->appGateIndex;
00728         key.assocId = assoc->assocId;
00729         sctpAppConnMap.erase(key);
00730         key.assocId = assoc->assocId = getNewConnId();
00731         sctpAppConnMap[key] = assoc;
00732 
00733         // ...and newConn will live on with the old assocId
00734         key.appGateIndex = newAssoc->appGateIndex;
00735         key.assocId = newAssoc->assocId;
00736         sctpAppConnMap[key] = newAssoc;
00737         /*ev<<"assocId="<<assoc->assocId<<" remoteAddr="<<assoc->remoteAddr<<"\n";
00738         assoc->removeOldPath();*/
00739         printInfoConnMap();
00740 }

int16 SCTP::getEphemeralPort (  ) 

To be called from SCTPAssociation: reserves an ephemeral port for the connection.

Referenced by SCTPAssociation::process_ASSOCIATE().

00515 {
00516         if (nextEphemeralPort==5000)
00517                 error("Ephemeral port range 1024..4999 exhausted (email SCTP model "
00518                                 "author that he should implement reuse of ephemeral ports!!!)");
00519         return nextEphemeralPort++;
00520 }

static int32 SCTP::getNewConnId (  )  [inline, static]

Generates a new integer, to be used as assocId. (assocId is part of the key which associates connections with their apps).

Referenced by addForkedAssociation(), and SCTPSocket::SCTPSocket().

00215 {return ++nextConnId;}

SCTPAssociation * SCTP::getAssoc ( int32  assocId  ) 

Referenced by findAssocWithVTag().

00832 {
00833         for (SctpAppConnMap::iterator i = sctpAppConnMap.begin(); i!=sctpAppConnMap.end(); i++)
00834         {
00835                 if (i->first.assocId==assocId)
00836                         return i->second;
00837         }
00838         return NULL;
00839 }

SCTPAssociation * SCTP::findAssocWithVTag ( uint32  peerVTag,
uint32  remotePort,
uint32  localPort 
)

Referenced by handleMessage().

00408 {
00409         VTagPair key;
00410 
00411         key.peerVTag = peerVTag;
00412         key.localPort = localPort;
00413         key.remotePort = remotePort;
00414 
00415         sctpEV3<<"findAssocWithVTag: peerVTag="<<peerVTag<<" srcPort="<<remotePort<<"  destPort="<<localPort<<"\n";
00416         printInfoConnMap();
00417 
00418         // try with fully qualified SockPair
00419         SctpVTagMap::iterator i;
00420         i = sctpVTagMap.find(key);
00421         if (i!=sctpVTagMap.end())
00422         {
00423                 sctpEV3<<"assoc "<<i->second<<"\n";
00424                 return getAssoc(i->second);
00425         }
00426         else
00427                 return NULL;
00428 }

SctpVTagMap SCTP::getVTagMap (  )  [inline]

00219 {return sctpVTagMap;};


Member Data Documentation

int32 SCTP::sizeConnMap [protected]

int32 SCTP::nextConnId = 0 [static, protected]

Referenced by getNewConnId().

uint16 SCTP::nextEphemeralPort [protected]

Referenced by getEphemeralPort(), and initialize().

bool SCTP::testing [static]

bool SCTP::logverbose [static]

simtime_t SCTP::testTimeout

Referenced by finish(), handleMessage(), and initialize().

Referenced by finish(), handleMessage(), and initialize().


The documentation for this class was generated from the following files:

Generated on Fri Mar 20 18:51:21 2009 for INET Framework for OMNeT++/OMNEST by  doxygen 1.5.5