Classes | Public Types | Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Protected Member Functions | Protected Attributes | Static Protected Attributes

SCTP Class Reference

#include <SCTP.h>

List of all members.

Classes

struct  AppConnKey
struct  AssocStat
struct  SockPair
struct  VTagPair

Public Types

typedef std::map< int32,
AssocStat
AssocStatMap
typedef std::map< int32, VTagPairSctpVTagMap
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 ()
AssocStatgetAssocStat (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 ()
SCTPAssociationgetAssoc (int32 assocId)
SCTPAssociationfindAssocWithVTag (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

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

int32 sizeConnMap
uint16 nextEphemeralPort

Static Protected Attributes

static int32 nextConnId = 0

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.

Definition at line 84 of file SCTP.h.


Member Typedef Documentation

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

Definition at line 155 of file SCTP.h.

Definition at line 161 of file SCTP.h.

Definition at line 162 of file SCTP.h.

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

Definition at line 157 of file SCTP.h.


Constructor & Destructor Documentation

SCTP::~SCTP (  )  [virtual]

Definition at line 114 of file SCTP.cc.

{
    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";
}


Member Function Documentation

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).

Definition at line 709 of file SCTP.cc.

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 
)

Definition at line 546 of file SCTP.cc.

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 
)

Definition at line 580 of file SCTP.cc.

{

        //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 
)

Definition at line 680 of file SCTP.cc.

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 (  ) 

Definition at line 79 of file SCTP.cc.

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]

Definition at line 500 of file SCTP.cc.

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]

Definition at line 426 of file SCTP.cc.

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 
)

Definition at line 407 of file SCTP.cc.

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]

Definition at line 856 of file SCTP.cc.

{
    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  ) 

Definition at line 846 of file SCTP.cc.

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]

Definition at line 199 of file SCTP.h.

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.

Definition at line 510 of file SCTP.cc.

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).

Definition at line 231 of file SCTP.h.

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

{return ++nextConnId;}

SctpVTagMap SCTP::getVTagMap (  )  [inline]

Definition at line 235 of file SCTP.h.

{return sctpVTagMap;};

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

Definition at line 135 of file SCTP.cc.

{
    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]

Definition at line 91 of file SCTP.cc.

{
    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 (  ) 

Definition at line 37 of file SCTP.cc.

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 (  ) 

Definition at line 58 of file SCTP.cc.

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  ) 

Definition at line 740 of file SCTP.cc.

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 
)

Definition at line 618 of file SCTP.cc.

{

        //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 
)

Definition at line 649 of file SCTP.cc.

{

        //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]

Definition at line 320 of file SCTP.cc.

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]

Definition at line 368 of file SCTP.cc.

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]

Definition at line 395 of file SCTP.cc.

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

Definition at line 518 of file SCTP.cc.

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();
}


Member Data Documentation

bool SCTP::logverbose [static]

Definition at line 182 of file SCTP.h.

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

Definition at line 170 of file SCTP.h.

uint16 SCTP::nextEphemeralPort [protected]

Definition at line 172 of file SCTP.h.

Referenced by getEphemeralPort(), and initialize().

Definition at line 188 of file SCTP.h.

Definition at line 190 of file SCTP.h.

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

Definition at line 189 of file SCTP.h.

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

Definition at line 158 of file SCTP.h.

Referenced by findAssocWithVTag(), printVTagMap(), SCTPAssociation::stateEntered(), and ~SCTP().

int32 SCTP::sizeConnMap [protected]
bool SCTP::testing [static]

Definition at line 181 of file SCTP.h.

Referenced by initialize(), and SCTPAssociation::processTimer().

simtime_t SCTP::testTimeout

Definition at line 187 of file SCTP.h.

Referenced by initialize(), and SCTPAssociation::SCTPAssociation().


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