INET Framework for OMNeT++/OMNEST
|
#include <SCTP.h>
Classes | |
struct | AppConnKey |
struct | AssocStat |
struct | SockPair |
struct | VTagPair |
Public Types | |
typedef std::map< int32, AssocStat > | AssocStatMap |
typedef std::map< int32, VTagPair > | SctpVTagMap |
typedef std::map< AppConnKey, SCTPAssociation * > | SctpAppConnMap |
typedef std::map< SockPair, SCTPAssociation * > | SctpConnMap |
Public Member Functions | |
void | printInfoConnMap () |
void | printVTagMap () |
void | removeAssociation (SCTPAssociation *assoc) |
virtual | ~SCTP () |
virtual void | initialize () |
virtual void | handleMessage (cMessage *msg) |
virtual void | finish () |
AssocStat * | getAssocStat (uint32 assocId) |
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) |
uint16 | getEphemeralPort () |
SCTPAssociation * | getAssoc (int32 assocId) |
SCTPAssociation * | findAssocWithVTag (uint32 peerVTag, uint32 remotePort, uint32 localPort) |
SctpVTagMap | getVTagMap () |
void | bindPortForUDP () |
Static Public Member Functions | |
static int32 | getNewConnId () |
Public Attributes | |
AssocStatMap | assocStatMap |
SctpVTagMap | sctpVTagMap |
SctpAppConnMap | sctpAppConnMap |
SctpConnMap | sctpConnMap |
std::list< SCTPAssociation * > | assocList |
simtime_t | testTimeout |
uint32 | numGapReports |
uint32 | numPacketsReceived |
uint32 | numPacketsDropped |
Static Public Attributes | |
static bool | testing |
static bool | logverbose |
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 | |
int32 | sizeConnMap |
uint16 | nextEphemeralPort |
Static Protected Attributes | |
static int32 | nextConnId = 0 |
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.
typedef std::map<int32,AssocStat> SCTP::AssocStatMap |
typedef std::map<AppConnKey,SCTPAssociation*> SCTP::SctpAppConnMap |
typedef std::map<SockPair,SCTPAssociation*> SCTP::SctpConnMap |
typedef std::map<int32, VTagPair> SCTP::SctpVTagMap |
SCTP::~SCTP | ( | ) | [virtual] |
{ sctpEV3<<"delete SCTPMain\n"; if (!(sctpAppConnMap.empty())) { sctpEV3<<"clear appConnMap ptr="<<&sctpAppConnMap<<"\n"; sctpAppConnMap.clear(); } if (!(assocStatMap.empty())) { sctpEV3<<"clear assocStatMap ptr="<<&assocStatMap<<"\n"; assocStatMap.clear(); } if (!(sctpVTagMap.empty())) { sctpVTagMap.clear(); } sctpEV3<<"after clearing maps\n"; }
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().
{ SockPair keyAssoc; ev<<"addForkedConnection assocId="<<assoc->assocId<<" newId="<<newAssoc->assocId<<"\n"; for (SctpConnMap::iterator j=sctpConnMap.begin(); j!=sctpConnMap.end(); ++j) if (assoc->assocId==j->second->assocId) keyAssoc = j->first; // update conn's socket pair, and register newConn (which'll keep LISTENing) updateSockPair(assoc, localAddr, remoteAddr, localPort, remotePort); updateSockPair(newAssoc, keyAssoc.localAddr, keyAssoc.remoteAddr, keyAssoc.localPort, keyAssoc.remotePort); // conn will get a new assocId... AppConnKey key; key.appGateIndex = assoc->appGateIndex; key.assocId = assoc->assocId; sctpAppConnMap.erase(key); key.assocId = assoc->assocId = getNewConnId(); sctpAppConnMap[key] = assoc; // ...and newConn will live on with the old assocId key.appGateIndex = newAssoc->appGateIndex; key.assocId = newAssoc->assocId; sctpAppConnMap[key] = newAssoc; /*ev<<"assocId="<<assoc->assocId<<" remoteAddr="<<assoc->remoteAddr<<"\n"; assoc->removeOldPath();*/ printInfoConnMap(); }
void SCTP::addLocalAddress | ( | SCTPAssociation * | conn, |
IPvXAddress | address | ||
) |
Referenced by SCTPAssociation::processInitArrived(), and SCTPAssociation::sendInit().
{ //sctpEV3<<"Add local address: "<<address<<"\n"; SockPair key; key.localAddr = conn->localAddr; key.remoteAddr = conn->remoteAddr; key.localPort = conn->localPort; key.remotePort = conn->remotePort; SctpConnMap::iterator i = sctpConnMap.find(key); if (i!=sctpConnMap.end()) { ASSERT(i->second==conn); if (key.localAddr.isUnspecified()) { sctpConnMap.erase(i); sizeConnMap--; } } else sctpEV3<<"no actual sockPair found\n"; key.localAddr = address; //key.localAddr = address.get4().getInt(); // //sctpEV3<<"laddr="<<key.localAddr<<" lp="<<key.localPort<<" raddr="<<key.remoteAddr<<" rPort="<<key.remotePort<<"\n"; sctpConnMap[key] = conn; sizeConnMap = sctpConnMap.size(); sctpEV3<<"number of connections="<<sizeConnMap<<"\n"; printInfoConnMap(); }
void SCTP::addLocalAddressToAllRemoteAddresses | ( | SCTPAssociation * | conn, |
IPvXAddress | address, | ||
std::vector< IPvXAddress > | remAddresses | ||
) |
{ //sctpEV3<<"Add local address: "<<address<<"\n"; SockPair key; for (AddressVector::iterator i=remAddresses.begin(); i!=remAddresses.end(); ++i) { //sctpEV3<<"remote address="<<(*i)<<"\n"; key.localAddr = conn->localAddr; key.remoteAddr = (*i); key.localPort = conn->localPort; key.remotePort = conn->remotePort; SctpConnMap::iterator j = sctpConnMap.find(key); if (j!=sctpConnMap.end()) { ASSERT(j->second==conn); if (key.localAddr.isUnspecified()) { sctpConnMap.erase(j); sizeConnMap--; } } else sctpEV3<<"no actual sockPair found\n"; key.localAddr = address; sctpConnMap[key] = conn; sizeConnMap++; sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n"; printInfoConnMap(); } }
void SCTP::addRemoteAddress | ( | SCTPAssociation * | conn, |
IPvXAddress | localAddress, | ||
IPvXAddress | remoteAddress | ||
) |
Referenced by SCTPAssociation::processInitAckArrived(), and SCTPAssociation::processInitArrived().
{ sctpEV3<<"Add remote Address: "<<remoteAddress<<" to local Address "<<localAddress<<"\n"; SockPair key; key.localAddr = localAddress; key.remoteAddr = remoteAddress; key.localPort = conn->localPort; key.remotePort = conn->remotePort; SctpConnMap::iterator i = sctpConnMap.find(key); if (i!=sctpConnMap.end()) { ASSERT(i->second==conn); } else { //sctpEV3<<"no actual sockPair found\n"; sctpConnMap[key] = conn; sizeConnMap++; } //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n"; printInfoConnMap(); }
void SCTP::bindPortForUDP | ( | ) |
Referenced by initialize().
{ EV << "Binding to UDP port " << 9899 << endl; cMessage *msg = new cMessage("UDP_C_BIND", UDP_C_BIND); UDPControlInfo *ctrl = new UDPControlInfo(); ctrl->setSrcPort(9899); ctrl->setSockId(UDPSocket::generateSocketId()); msg->setControlInfo(ctrl); send(msg, "to_ip"); }
SCTPAssociation * SCTP::findAssocForApp | ( | int32 | appGateIndex, |
int32 | assocId | ||
) | [protected] |
Referenced by handleMessage().
{ AppConnKey key; key.appGateIndex = appGateIndex; key.assocId = assocId; sctpEV3<<"findAssoc for appGateIndex "<<appGateIndex<<" and assoc "<<assocId<<"\n"; SctpAppConnMap::iterator i = sctpAppConnMap.find(key); return i==sctpAppConnMap.end() ? NULL : i->second; }
SCTPAssociation * SCTP::findAssocForMessage | ( | IPvXAddress | srcAddr, |
IPvXAddress | destAddr, | ||
uint32 | srcPort, | ||
uint32 | destPort, | ||
bool | findListen | ||
) | [protected] |
Referenced by handleMessage().
{ SockPair key; key.localAddr = destAddr; key.remoteAddr = srcAddr; key.localPort = destPort; key.remotePort = srcPort; SockPair save = key; sctpEV3<<"findAssocForMessage: srcAddr="<<destAddr<<" destAddr="<<srcAddr<<" srcPort="<<destPort<<" destPort="<<srcPort<<"\n"; printInfoConnMap(); // try with fully qualified SockPair SctpConnMap::iterator i; i = sctpConnMap.find(key); if (i!=sctpConnMap.end()) return i->second; // try with localAddr missing (only localPort specified in passive/active open) key.localAddr.set("0.0.0.0"); i = sctpConnMap.find(key); if (i!=sctpConnMap.end()) { //sctpEV3<<"try with localAddr missing (only localPort specified in passive/active open)\n"; return i->second; } if (findListen==true) { /*key = save; key.localPort = 0; key.localAddr.set("0.0.0.0"); i = sctpConnMap.find(key); if (i!=sctpConnMap.end()) { return i->second; }*/ // try fully qualified local socket + blank remote socket (for incoming SYN) key = save; key.remoteAddr.set("0.0.0.0"); key.remotePort = 0; i = sctpConnMap.find(key); if (i!=sctpConnMap.end()) { //sctpEV3<<"try fully qualified local socket + blank remote socket \n"; return i->second; } // try with blank remote socket, and localAddr missing (for incoming SYN) key.localAddr.set("0.0.0.0"); i = sctpConnMap.find(key); if (i!=sctpConnMap.end()) { //sctpEV3<<"try with blank remote socket, and localAddr missing \n"; return i->second; } } // given up sctpEV3<<"giving up on trying to find assoc for localAddr="<<srcAddr<<" remoteAddr="<<destAddr<<" localPort="<<srcPort<<" remotePort="<<destPort<<"\n"; return NULL; }
SCTPAssociation * SCTP::findAssocWithVTag | ( | uint32 | peerVTag, |
uint32 | remotePort, | ||
uint32 | localPort | ||
) |
Referenced by handleMessage().
{ printVTagMap(); sctpEV3<<"findAssocWithVTag: peerVTag="<<peerVTag<<" srcPort="<<remotePort<<" destPort="<<localPort<<"\n"; printInfoConnMap(); // try with fully qualified SockPair for (SctpVTagMap::iterator i=sctpVTagMap.begin(); i!=sctpVTagMap.end();i++) { if ((i->second.peerVTag==peerVTag && i->second.localPort==localPort && i->second.remotePort==remotePort) || (i->second.localVTag==peerVTag && i->second.localPort==localPort && i->second.remotePort==remotePort)) return getAssoc(i->first); } return NULL; }
void SCTP::finish | ( | ) | [virtual] |
{ SctpConnMap::iterator connMapIterator = sctpConnMap.begin(); while (connMapIterator != sctpConnMap.end()) { removeAssociation(connMapIterator->second); connMapIterator = sctpConnMap.begin(); } ev << getFullPath() << ": finishing SCTP with " << sctpConnMap.size() << " connections open." << endl; for (AssocStatMap::const_iterator iterator = assocStatMap.begin(); iterator != assocStatMap.end(); iterator++) { const SCTP::AssocStat& assoc = iterator->second; ev << "Association " << assoc.assocId << ": started at " << assoc.start << " and finished at " << assoc.stop << " --> lifetime: " << assoc.lifeTime << endl; ev << "Association " << assoc.assocId << ": sent bytes=" << assoc.sentBytes << ", acked bytes=" << assoc.ackedBytes<< ", throughput=" << assoc.throughput<< " bit/s" << endl; ev << "Association " << assoc.assocId << ": transmitted Bytes=" << assoc.transmittedBytes<< ", retransmitted Bytes=" << assoc.transmittedBytes-assoc.ackedBytes<< endl; ev << "Association " << assoc.assocId << ": number of Fast RTX=" << assoc.numFastRtx << ", number of Timer-Based RTX=" << assoc.numT3Rtx << ", path failures=" << assoc.numPathFailures<< ", ForwardTsns=" << assoc.numForwardTsn<< endl; ev << "AllMessages=" <<numPacketsReceived<< " BadMessages=" <<numPacketsDropped<< endl; recordScalar("Association Lifetime", assoc.lifeTime); recordScalar("Acked Bytes", assoc.ackedBytes); recordScalar("Throughput [bit/s]", assoc.throughput); recordScalar("Transmitted Bytes", assoc.transmittedBytes); recordScalar("Fast RTX", assoc.numFastRtx); recordScalar("Timer-Based RTX", assoc.numT3Rtx); recordScalar("Duplicate Acks", assoc.numDups); recordScalar("Packets Received", numPacketsReceived); recordScalar("Packets Dropped", numPacketsDropped); } }
SCTPAssociation * SCTP::getAssoc | ( | int32 | assocId | ) |
Referenced by findAssocWithVTag().
{ for (SctpAppConnMap::iterator i = sctpAppConnMap.begin(); i!=sctpAppConnMap.end(); i++) { if (i->first.assocId==assocId) return i->second; } return NULL; }
AssocStat* SCTP::getAssocStat | ( | uint32 | assocId | ) | [inline] |
Referenced by SCTPAssociation::dequeueAckedChunks(), and SCTPAssociation::handleChunkReportedAsMissing().
{ SCTP::AssocStatMap::iterator found = assocStatMap.find(assocId); if(found != assocStatMap.end()) { return(&found->second); } return(NULL); }
uint16 SCTP::getEphemeralPort | ( | ) |
To be called from SCTPAssociation: reserves an ephemeral port for the connection.
Referenced by SCTPAssociation::process_ASSOCIATE().
{ if (nextEphemeralPort==5000) error("Ephemeral port range 1024..4999 exhausted (email SCTP model " "author that he should implement reuse of ephemeral ports!!!)"); return nextEphemeralPort++; }
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(), SCTPSocket::connect(), SCTPSocket::listen(), and SCTPSocket::SCTPSocket().
{return ++nextConnId;}
SctpVTagMap SCTP::getVTagMap | ( | ) | [inline] |
{return sctpVTagMap;};
void SCTP::handleMessage | ( | cMessage * | msg | ) | [virtual] |
{ IPvXAddress destAddr; IPvXAddress srcAddr; IPControlInfo *controlInfo =NULL; IPv6ControlInfo *controlInfoV6 =NULL; bool findListen = false; bool bitError = false; sctpEV3<<"\n\nSCTPMain handleMessage at "<<getFullPath()<<"\n"; if (msg->isSelfMessage()) { sctpEV3<<"selfMessage\n"; SCTPAssociation *assoc = (SCTPAssociation *) msg->getContextPointer(); bool ret = assoc->processTimer(msg); if (!ret) removeAssociation(assoc); } else if (msg->arrivedOn("from_ip") || msg->arrivedOn("from_ipv6")) { sctpEV3<<"Message from IP\n"; printInfoConnMap(); if (!dynamic_cast<SCTPMessage *>(msg)) { sctpEV3<<"no sctp message, delete it\n"; delete msg; return; } SCTPMessage *sctpmsg = check_and_cast<SCTPMessage *>(msg); numPacketsReceived++; if ((sctpmsg->hasBitError() || !(sctpmsg->getChecksumOk()))) { sctpEV3<<"Packet has bit-error. delete it\n"; bitError = true; numPacketsDropped++; delete msg; return; } if (msg->arrivedOn("from_ip")) { if (par("udpEncapsEnabled")) { std::cout<<"Laenge SCTPMSG="<<sctpmsg->getByteLength()<<"\n"; UDPControlInfo *ctrl = check_and_cast<UDPControlInfo *>(msg->removeControlInfo()); srcAddr = ctrl->getSrcAddr(); destAddr = ctrl->getDestAddr(); std::cout<<"controlInfo srcAddr="<<srcAddr<<" destAddr="<<destAddr<<"\n"; std::cout<<"VTag="<<sctpmsg->getTag()<<"\n"; } else { controlInfo = check_and_cast<IPControlInfo *>(msg->removeControlInfo()); IPDatagram *datagram = controlInfo->removeOrigDatagram(); delete datagram; sctpEV3<<"controlInfo srcAddr="<<controlInfo->getSrcAddr()<<" destAddr="<<controlInfo->getDestAddr()<<"\n"; srcAddr = controlInfo->getSrcAddr(); destAddr = controlInfo->getDestAddr(); } } else { controlInfoV6 = check_and_cast<IPv6ControlInfo *>(msg->removeControlInfo()); srcAddr = controlInfoV6->getSrcAddr(); destAddr = controlInfoV6->getDestAddr(); } sctpEV3<<"srcAddr="<<srcAddr<<" destAddr="<<destAddr<<"\n"; if (sctpmsg->getBitLength()>(SCTP_COMMON_HEADER*8)) { if (((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==INIT || ((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==INIT_ACK ) findListen = true; SCTPAssociation *assoc = findAssocForMessage(srcAddr, destAddr, sctpmsg->getSrcPort(),sctpmsg->getDestPort(), findListen); if (!assoc && sctpConnMap.size()>0) assoc = findAssocWithVTag(sctpmsg->getTag(),sctpmsg->getSrcPort(), sctpmsg->getDestPort()); if (!assoc) { sctpEV3<<"no assoc found msg="<<sctpmsg->getName()<<"\n"; if (bitError) { delete sctpmsg; return; } if (((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==SHUTDOWN_ACK) sendShutdownCompleteFromMain(sctpmsg, destAddr, srcAddr); else if (((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()!=ABORT && ((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()!=SHUTDOWN_COMPLETE) { sendAbortFromMain(sctpmsg, destAddr, srcAddr); } delete sctpmsg; } else { bool ret = assoc->processSCTPMessage(sctpmsg, srcAddr, destAddr); if (!ret) { sctpEV3<<"SCTPMain:: removeAssociation \n"; removeAssociation(assoc); delete sctpmsg; } else { delete sctpmsg; } } } else { delete sctpmsg; } } else // must be from app { sctpEV3<<"must be from app\n"; SCTPCommand *controlInfo = check_and_cast<SCTPCommand *>(msg->getControlInfo()); int32 appGateIndex; if (controlInfo->getGate()!=-1) appGateIndex = controlInfo->getGate(); else appGateIndex = msg->getArrivalGate()->getIndex(); int32 assocId = controlInfo->getAssocId(); sctpEV3<<"msg arrived from app for assoc "<<assocId<<"\n"; SCTPAssociation *assoc = findAssocForApp(appGateIndex, assocId); if (!assoc) { sctpEV3 << "no assoc found. msg="<<msg->getName()<<" number of assocs = "<<assocList.size()<<"\n"; if (strcmp(msg->getName(),"PassiveOPEN")==0 || strcmp(msg->getName(),"Associate")==0) { if (assocList.size()>0) { assoc = NULL; SCTPOpenCommand* open = check_and_cast<SCTPOpenCommand*>(controlInfo); sctpEV3<<"Looking for assoc with remoteAddr="<<open->getRemoteAddr()<<", remotePort="<<open->getRemotePort()<<", localPort="<<open->getLocalPort()<<"\n"; for (std::list<SCTPAssociation*>::iterator iter=assocList.begin(); iter!=assocList.end(); iter++) { sctpEV3<<"remoteAddr="<<(*iter)->remoteAddr<<", remotePort="<<(*iter)->remotePort<<", localPort="<<(*iter)->localPort<<"\n"; if ((*iter)->remoteAddr == open->getRemoteAddr() && (*iter)->localPort==open->getLocalPort() && (*iter)->remotePort==open->getRemotePort()) { assoc = (*iter); break; } } } if (assoc==NULL) { assoc = new SCTPAssociation(this,appGateIndex,assocId); AppConnKey key; key.appGateIndex = appGateIndex; key.assocId = assocId; sctpAppConnMap[key] = assoc; sctpEV3 << "SCTP association created for appGateIndex " << appGateIndex << " and assoc "<<assocId<<"\n"; bool ret = assoc->processAppCommand(PK(msg)); if (!ret) { removeAssociation(assoc); } } } } else { sctpEV3<<"assoc found\n"; bool ret = assoc->processAppCommand(PK(msg)); if (!ret) removeAssociation(assoc); } delete msg; } if (ev.isGUI()) updateDisplayString(); }
void SCTP::initialize | ( | ) | [virtual] |
{ nextEphemeralPort = (uint16)(intrand(10000) + 30000); //sctpEV3<<"SCTPMain initialize\n"; cModule *netw = simulation.getSystemModule(); testing = netw->hasPar("testing") && netw->par("testing").boolValue(); if(testing) { } if (netw->hasPar("testTimeout")) { testTimeout = (simtime_t)netw->par("testTimeout"); } numPacketsReceived = 0; numPacketsDropped = 0; sizeConnMap = 0; if ((bool)par("udpEncapsEnabled")) bindPortForUDP(); }
void SCTP::printInfoConnMap | ( | ) |
Referenced by addForkedAssociation(), addLocalAddress(), addLocalAddressToAllRemoteAddresses(), addRemoteAddress(), SCTPAssociation::cloneAssociation(), findAssocForMessage(), findAssocWithVTag(), handleMessage(), removeAssociation(), removeLocalAddressFromAllRemoteAddresses(), removeRemoteAddressFromAllConnections(), SCTPAssociation::sendInit(), and updateSockPair().
{ SCTPAssociation* assoc; SockPair key; sctpEV3<<"Number of Assocs: "<<sizeConnMap<<"\n"; if (sizeConnMap>0) { for (SctpConnMap::iterator i = sctpConnMap.begin(); i!=sctpConnMap.end(); ++i) { assoc = i->second; key = i->first; sctpEV3<<"assocId: "<<assoc->assocId<<" assoc: "<<assoc<<" src: "<<IPvXAddress(key.localAddr)<<" dst: "<<IPvXAddress(key.remoteAddr)<<" lPort: "<<key.localPort<<" rPort: "<<key.remotePort<<"\n"; } sctpEV3<<"\n"; } }
void SCTP::printVTagMap | ( | ) |
Referenced by findAssocWithVTag().
{ int32 assocId; VTagPair key; sctpEV3<<"Number of Assocs: "<<sctpVTagMap.size()<<"\n"; if (sctpVTagMap.size()>0) { for (SctpVTagMap::iterator i = sctpVTagMap.begin(); i!=sctpVTagMap.end(); ++i) { assocId = i->first; key = i->second; sctpEV3<<"assocId: "<<assocId<<" peerVTag: "<<key.peerVTag<< " localVTag: "<<key.localVTag<< " localPort: "<<key.localPort<<" rPort: "<<key.remotePort<<"\n"; } sctpEV3<<"\n"; } }
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().
{ bool ok = false; bool find = false; const int32 id = conn->assocId; sctpEV3 << "Deleting SCTP connection " << conn << " id= "<< id << endl; printInfoConnMap(); if (sizeConnMap > 0) { AssocStatMap::iterator assocStatMapIterator = assocStatMap.find(conn->assocId); if (assocStatMapIterator != assocStatMap.end()) { assocStatMapIterator->second.stop = simulation.getSimTime(); assocStatMapIterator->second.lifeTime = assocStatMapIterator->second.stop - assocStatMapIterator->second.start; assocStatMapIterator->second.throughput = assocStatMapIterator->second.ackedBytes*8 / assocStatMapIterator->second.lifeTime.dbl(); } while (!ok) { if (sizeConnMap == 0) { ok = true; } else { for (SctpConnMap::iterator sctpConnMapIterator = sctpConnMap.begin(); sctpConnMapIterator != sctpConnMap.end(); sctpConnMapIterator++) { if (sctpConnMapIterator->second != NULL) { SCTPAssociation* assoc = sctpConnMapIterator->second; if (assoc->assocId == conn->assocId) { if (assoc->T1_InitTimer) { assoc->stopTimer(assoc->T1_InitTimer); } if (assoc->T2_ShutdownTimer) { assoc->stopTimer(assoc->T2_ShutdownTimer); } if (assoc->T5_ShutdownGuardTimer) { assoc->stopTimer(assoc->T5_ShutdownGuardTimer); } if (assoc->SackTimer) { assoc->stopTimer(assoc->SackTimer); } sctpConnMap.erase(sctpConnMapIterator); sizeConnMap--; find = true; break; } } } } if (!find) { ok = true; } else { find = false; } } } // T.D. 26.11.09: Write statistics char str[128]; for (SCTPAssociation::SCTPPathMap::iterator pathMapIterator = conn->sctpPathMap.begin(); pathMapIterator != conn->sctpPathMap.end(); pathMapIterator++) { const SCTPPathVariables* path = pathMapIterator->second; snprintf((char*)&str, sizeof(str), "Number of Fast Retransmissions %d:%s", conn->assocId, path->remoteAddress.str().c_str()); recordScalar(str, path->numberOfFastRetransmissions); snprintf((char*)&str, sizeof(str), "Number of Timer-Based Retransmissions %d:%s", conn->assocId, path->remoteAddress.str().c_str()); recordScalar(str, path->numberOfTimerBasedRetransmissions); snprintf((char*)&str, sizeof(str), "Number of Heartbeats Sent %d:%s", conn->assocId, path->remoteAddress.str().c_str()); recordScalar(str, path->numberOfHeartbeatsSent); snprintf((char*)&str, sizeof(str), "Number of Heartbeats Received %d:%s", conn->assocId, path->remoteAddress.str().c_str()); recordScalar(str, path->numberOfHeartbeatsRcvd); snprintf((char*)&str, sizeof(str), "Number of Heartbeat ACKs Sent %d:%s", conn->assocId, path->remoteAddress.str().c_str()); recordScalar(str, path->numberOfHeartbeatAcksSent); snprintf((char*)&str, sizeof(str), "Number of Heartbeat ACKs Received %d:%s", conn->assocId, path->remoteAddress.str().c_str()); recordScalar(str, path->numberOfHeartbeatAcksRcvd); } conn->removePath(); conn->deleteStreams(); // TD 20.11.09: Chunks may be in the transmission and retransmission queues simultaneously. // Remove entry from transmission queue if it is already in the retransmission queue. for (SCTPQueue::PayloadQueue::iterator i = conn->getRetransmissionQueue()->payloadQueue.begin(); i != conn->getRetransmissionQueue()->payloadQueue.end(); i++) { SCTPQueue::PayloadQueue::iterator j = conn->getTransmissionQueue()->payloadQueue.find(i->second->tsn); if(j != conn->getTransmissionQueue()->payloadQueue.end()) { conn->getTransmissionQueue()->payloadQueue.erase(j); } } // TD 20.11.09: Now, both queues can be safely deleted. delete conn->getRetransmissionQueue(); delete conn->getTransmissionQueue(); AppConnKey key; key.appGateIndex = conn->appGateIndex; key.assocId = conn->assocId; sctpAppConnMap.erase(key); assocList.remove(conn); delete conn; }
void SCTP::removeLocalAddressFromAllRemoteAddresses | ( | SCTPAssociation * | conn, |
IPvXAddress | address, | ||
std::vector< IPvXAddress > | remAddresses | ||
) |
{ //sctpEV3<<"Remove local address: "<<address<<"\n"; SockPair key; for (AddressVector::iterator i=remAddresses.begin(); i!=remAddresses.end(); ++i) { //sctpEV3<<"remote address="<<(*i)<<"\n"; key.localAddr = address; key.remoteAddr = (*i); key.localPort = conn->localPort; key.remotePort = conn->remotePort; SctpConnMap::iterator j = sctpConnMap.find(key); if (j!=sctpConnMap.end()) { ASSERT(j->second==conn); sctpConnMap.erase(j); sizeConnMap--; } else sctpEV3<<"no actual sockPair found\n"; //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n"; printInfoConnMap(); } }
void SCTP::removeRemoteAddressFromAllConnections | ( | SCTPAssociation * | conn, |
IPvXAddress | address, | ||
std::vector< IPvXAddress > | locAddresses | ||
) |
{ //sctpEV3<<"Remove remote address: "<<address<<"\n"; SockPair key; for (AddressVector::iterator i=locAddresses.begin(); i!=locAddresses.end(); i++) { //sctpEV3<<"local address="<<(*i)<<"\n"; key.localAddr = (*i); key.remoteAddr = address; key.localPort = conn->localPort; key.remotePort = conn->remotePort; SctpConnMap::iterator j = sctpConnMap.find(key); if (j!=sctpConnMap.end()) { ASSERT(j->second==conn); sctpConnMap.erase(j); sizeConnMap--; } else sctpEV3<<"no actual sockPair found\n"; //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n"; printInfoConnMap(); } }
void SCTP::sendAbortFromMain | ( | SCTPMessage * | sctpmsg, |
IPvXAddress | srcAddr, | ||
IPvXAddress | destAddr | ||
) | [protected] |
Referenced by handleMessage().
{ SCTPMessage *msg = new SCTPMessage(); sctpEV3<<"\n\nSCTPMain:sendABORT \n"; msg->setSrcPort(sctpmsg->getDestPort()); msg->setDestPort(sctpmsg->getSrcPort()); msg->setBitLength(SCTP_COMMON_HEADER*8); msg->setChecksumOk(true); SCTPAbortChunk* abortChunk = new SCTPAbortChunk("ABORT"); abortChunk->setChunkType(ABORT); if (sctpmsg->getChunksArraySize()>0 && ((SCTPChunk*)(sctpmsg->getChunks(0)))->getChunkType()==INIT) { SCTPInitChunk* initChunk = check_and_cast<SCTPInitChunk *>(sctpmsg->getChunks(0)); abortChunk->setT_Bit(0); msg->setTag(initChunk->getInitTag()); } else { abortChunk->setT_Bit(1); msg->setTag(sctpmsg->getTag()); } abortChunk->setBitLength(SCTP_ABORT_CHUNK_LENGTH*8); msg->addChunk(abortChunk); if ((bool)par("udpEncapsEnabled")) { msg->setKind(UDP_C_DATA); std::cout<<"VTag="<<msg->getTag()<<"\n"; UDPControlInfo *ctrl = new UDPControlInfo(); ctrl->setSrcPort(9899); ctrl->setDestAddr(destAddr.get4()); ctrl->setDestPort(9899); msg->setControlInfo(ctrl); } else { IPControlInfo *controlInfo = new IPControlInfo(); controlInfo->setProtocol(IP_PROT_SCTP); controlInfo->setSrcAddr(srcAddr.get4()); controlInfo->setDestAddr(destAddr.get4()); msg->setControlInfo(controlInfo); } send(msg,"to_ip"); }
void SCTP::sendShutdownCompleteFromMain | ( | SCTPMessage * | sctpmsg, |
IPvXAddress | srcAddr, | ||
IPvXAddress | destAddr | ||
) | [protected] |
Referenced by handleMessage().
{ SCTPMessage *msg = new SCTPMessage(); sctpEV3<<"\n\nSCTP:sendABORT \n"; msg->setSrcPort(sctpmsg->getDestPort()); msg->setDestPort(sctpmsg->getSrcPort()); msg->setBitLength(SCTP_COMMON_HEADER*8); msg->setChecksumOk(true); SCTPShutdownCompleteChunk* scChunk = new SCTPShutdownCompleteChunk("SHUTDOWN_COMPLETE"); scChunk->setChunkType(SHUTDOWN_COMPLETE); scChunk->setTBit(1); msg->setTag(sctpmsg->getTag()); scChunk->setBitLength(SCTP_SHUTDOWN_ACK_LENGTH*8); msg->addChunk(scChunk); IPControlInfo *controlInfo = new IPControlInfo(); controlInfo->setProtocol(IP_PROT_SCTP); controlInfo->setSrcAddr(srcAddr.get4()); controlInfo->setDestAddr(destAddr.get4()); msg->setControlInfo(controlInfo); send(msg,"to_ip"); }
void SCTP::updateDisplayString | ( | ) | [protected] |
Referenced by handleMessage().
{ if (ev.disable_tracing) { // in express mode, we don't bother to update the display // (std::map's iteration is not very fast if map is large) getDisplayString().setTagArg("t",0,""); return; } }
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().
{ SockPair key; sctpEV3<<"updateSockPair: localAddr: "<<localAddr<<" remoteAddr="<<remoteAddr<<" localPort="<<localPort<<" remotePort="<<remotePort<<"\n"; key.localAddr = (conn->localAddr = localAddr); key.remoteAddr = (conn->remoteAddr = remoteAddr); key.localPort = conn->localPort = localPort; key.remotePort = conn->remotePort = remotePort; for (SctpConnMap::iterator i=sctpConnMap.begin(); i!=sctpConnMap.end(); i++) { if (i->second == conn) { sctpConnMap.erase(i); break; } } sctpEV3<<"updateSockPair conn="<<conn<<" localAddr="<<key.localAddr<<" remoteAddr="<<key.remoteAddr<<" localPort="<<key.localPort<<" remotePort="<<remotePort<<"\n"; sctpConnMap[key] = conn; sizeConnMap = sctpConnMap.size(); //sctpEV3<<"number of connections="<<sctpConnMap.size()<<"\n"; sctpEV3<<"assoc inserted in sctpConnMap\n"; printInfoConnMap(); }
std::list<SCTPAssociation*> SCTP::assocList |
Referenced by handleMessage(), removeAssociation(), SCTPAssociation::sendInit(), and SCTPAssociation::sendInitAck().
bool SCTP::logverbose [static] |
int32 SCTP::nextConnId = 0 [static, protected] |
uint16 SCTP::nextEphemeralPort [protected] |
Referenced by getEphemeralPort(), and initialize().
uint32 SCTP::numGapReports |
uint32 SCTP::numPacketsDropped |
Referenced by finish(), handleMessage(), and initialize().
uint32 SCTP::numPacketsReceived |
Referenced by finish(), handleMessage(), and initialize().
Referenced by addForkedAssociation(), findAssocForApp(), getAssoc(), handleMessage(), removeAssociation(), and ~SCTP().
Referenced by addForkedAssociation(), addLocalAddress(), addLocalAddressToAllRemoteAddresses(), addRemoteAddress(), findAssocForMessage(), finish(), handleMessage(), printInfoConnMap(), removeAssociation(), removeLocalAddressFromAllRemoteAddresses(), removeRemoteAddressFromAllConnections(), and updateSockPair().
Referenced by findAssocWithVTag(), printVTagMap(), SCTPAssociation::stateEntered(), and ~SCTP().
int32 SCTP::sizeConnMap [protected] |
bool SCTP::testing [static] |
Referenced by initialize(), and SCTPAssociation::processTimer().
simtime_t SCTP::testTimeout |
Referenced by initialize(), and SCTPAssociation::SCTPAssociation().