#include <SCTP.h>
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 () |
SCTPAssociation * | getAssoc (int32 assocId) |
SCTPAssociation * | findAssocWithVTag (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 | |
SCTPAssociation * | findAssocForMessage (IPvXAddress srcAddr, IPvXAddress destAddr, uint32 srcPort, uint32 destPort, bool findListen) |
SCTPAssociation * | findAssocForApp (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 |
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] |
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 }
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] |
Referenced by SCTPAssociation::dequeueAckedChunks(), finish(), SCTPAssociation::pathStatusIndication(), SCTPAssociation::process_SEND(), SCTPAssociation::process_TIMEOUT_RTX(), SCTPAssociation::processDataArrived(), SCTPAssociation::processSackArrived(), removeAssociation(), SCTPAssociation::sendAll(), SCTPAssociation::stateEntered(), and ~SCTP().
Referenced by findAssocWithVTag(), getVTagMap(), SCTPAssociation::stateEntered(), and ~SCTP().
SctpAppConnMap SCTP::sctpAppConnMap [protected] |
Referenced by addForkedAssociation(), findAssocForApp(), getAssoc(), handleMessage(), removeAssociation(), and ~SCTP().
SctpConnMap SCTP::sctpConnMap [protected] |
Referenced by addForkedAssociation(), addLocalAddress(), addLocalAddressToAllRemoteAddresses(), addRemoteAddress(), findAssocForMessage(), finish(), handleMessage(), printInfoConnMap(), removeAssociation(), removeLocalAddressFromAllRemoteAddresses(), removeRemoteAddressFromAllConnections(), and updateSockPair().
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] |
Referenced by initialize(), and SCTPAssociation::processTimer().
bool SCTP::logverbose [static] |
simtime_t SCTP::testTimeout |
Referenced by initialize(), and SCTPAssociation::SCTPAssociation().
uint32 SCTP::numGapReports |
uint32 SCTP::numPacketsReceived |
Referenced by finish(), handleMessage(), and initialize().
uint32 SCTP::numPacketsDropped |
Referenced by finish(), handleMessage(), and initialize().