INET Framework for OMNeT++/OMNEST
inet::sctp::Sctp Class Reference

Implements the SCTP protocol. More...

#include <Sctp.h>

Inheritance diagram for inet::sctp::Sctp:

Classes

struct  AppAssocKey
 
struct  AssocStat
 
struct  SockPair
 
struct  VTagPair
 

Public Types

typedef std::map< int32_t, AssocStatAssocStatMap
 
typedef std::map< int32_t, VTagPairSctpVTagMap
 
typedef std::map< AppAssocKey, SctpAssociation * > SctpAppAssocMap
 
typedef std::map< SockPair, SctpAssociation * > SctpAssocMap
 

Public Member Functions

void printInfoAssocMap ()
 
void printVTagMap ()
 
void removeAssociation (SctpAssociation *assoc)
 
virtual ~Sctp ()
 
virtual void initialize (int stage) override
 
virtual int numInitStages () const override
 
virtual void handleMessage (cMessage *msg) override
 
virtual void finish () override
 
virtual void send_to_ip (Packet *msg)
 
AssocStatgetAssocStat (uint32_t assocId)
 
void updateSockPair (SctpAssociation *assoc, L3Address localAddr, L3Address remoteAddr, int32_t localPort, int32_t remotePort)
 To be called from SctpAssociation when socket pair changes. More...
 
void addLocalAddress (SctpAssociation *assoc, L3Address address)
 
void addLocalAddressToAllRemoteAddresses (SctpAssociation *assoc, L3Address address, std::vector< L3Address > remAddresses)
 
bool addRemoteAddress (SctpAssociation *assoc, L3Address localAddress, L3Address remoteAddress)
 
void removeLocalAddressFromAllRemoteAddresses (SctpAssociation *assoc, L3Address address, std::vector< L3Address > remAddresses)
 
void removeRemoteAddressFromAllAssociations (SctpAssociation *assoc, L3Address address, std::vector< L3Address > locAddresses)
 
void addForkedAssociation (SctpAssociation *assoc, SctpAssociation *newAssoc, L3Address localAddr, L3Address remoteAddr, int32_t localPort, int32_t remotePort)
 Update assocs socket pair, and register newAssoc (which'll keep LISTENing). More...
 
uint16_t getEphemeralPort ()
 To be called from SctpAssociation: reserves an ephemeral port for the connection. More...
 
SctpAssociationgetAssoc (int32_t assocId)
 
SctpAssociationfindAssocWithVTag (uint32_t peerVTag, uint32_t remotePort, uint32_t localPort)
 
SctpAssociationfindAssocForInitAck (SctpInitAckChunk *initack, L3Address srcAddr, L3Address destAddr, uint32_t srcPort, uint32_t destPort, bool findListen)
 
SctpVTagMap getVTagMap ()
 
void bindPortForUDP ()
 
SocketOptionscollectSocketOptions ()
 Getter and Setter for the socket options. More...
 
void setSocketOptions (SocketOptions *options)
 
int getMaxInitRetrans ()
 
int getMaxInitRetransTimeout ()
 
double getRtoInitial ()
 
double getRtoMin ()
 
double getRtoMax ()
 
int getSackFrequency ()
 
double getSackPeriod ()
 
int getMaxBurst ()
 
int getFragPoint ()
 
int getNagle ()
 
bool getEnableHeartbeats ()
 
int getPathMaxRetrans ()
 
int getAssocMaxRtx ()
 
double getHbInterval ()
 
void setRtoInitial (double rtoInitial)
 
void setRtoMin (double rtoMin)
 
void setRtoMax (double rtoMax)
 
void setInterfaceId (int id)
 
int getInterfaceId ()
 

Public Attributes

AssocStatMap assocStatMap
 
SctpVTagMap sctpVTagMap
 
SctpAppAssocMap sctpAppAssocMap
 
SctpAssocMap sctpAssocMap
 
std::list< SctpAssociation * > assocList
 
UdpSocket udpSocket
 
int udpSockId
 
SocketOptionssocketOptions
 
simtime_t testTimeout
 
uint32_t numGapReports
 
uint32_t numPacketsReceived
 
uint32_t numPacketsDropped
 
bool auth
 
bool addIP
 
bool pktdrop
 
bool sackNow
 
uint64_t numPktDropReports
 
int interfaceId = -1
 
CrcMode crcMode = CRC_MODE_UNDEFINED
 

Protected Member Functions

SctpAssociationfindAssocForMessage (L3Address srcAddr, L3Address destAddr, uint32_t srcPort, uint32_t destPort, bool findListen)
 
SctpAssociationfindAssocForApp (int32_t appGateIndex, int32_t assocId)
 
int32_t findAssocForFd (int32_t fd)
 
void sendAbortFromMain (Ptr< SctpHeader > &sctpMsg, L3Address fromAddr, L3Address toAddr)
 
void sendShutdownCompleteFromMain (Ptr< SctpHeader > &sctpMsg, L3Address fromAddr, L3Address toAddr)
 
virtual void refreshDisplay () const override
 

Protected Attributes

ModuleRefByPar< IRoutingTablert
 
ModuleRefByPar< IInterfaceTableift
 
int32_t sizeAssocMap
 
uint16_t nextEphemeralPort
 

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: the module class
  • SctpAssociation: manages an association
  • SctpSendQueue, SctpReceiveQueue: abstract base classes for various types of send and receive queues
  • SctpAlgorithm: abstract base class for SCTP algorithms

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

SctpAssociation manages the association, 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 association (in OPEN) or in a module parameter.

Member Typedef Documentation

◆ AssocStatMap

typedef std::map<int32_t, AssocStat> inet::sctp::Sctp::AssocStatMap

◆ SctpAppAssocMap

◆ SctpAssocMap

◆ SctpVTagMap

typedef std::map<int32_t, VTagPair> inet::sctp::Sctp::SctpVTagMap

Constructor & Destructor Documentation

◆ ~Sctp()

inet::sctp::Sctp::~Sctp ( )
virtual
149 {
150  EV_DEBUG << "delete SctpMain\n";
151  if (!(sctpAppAssocMap.empty())) {
152  EV_DEBUG << "clear appConnMap ptr=" << &sctpAppAssocMap << "\n";
153  sctpAppAssocMap.clear();
154  }
155  if (!(assocStatMap.empty())) {
156  EV_DEBUG << "clear assocStatMap ptr=" << &assocStatMap << "\n";
157  assocStatMap.clear();
158  }
159  if (!(sctpVTagMap.empty())) {
160  sctpVTagMap.clear();
161  }
162  EV_DEBUG << "after clearing maps\n";
163 }

Member Function Documentation

◆ addForkedAssociation()

void inet::sctp::Sctp::addForkedAssociation ( SctpAssociation assoc,
SctpAssociation newAssoc,
L3Address  localAddr,
L3Address  remoteAddr,
int32_t  localPort,
int32_t  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).

806 {
807  SockPair keyAssoc;
808  bool found = false;
809 
810  EV_INFO << "addForkedConnection assocId=" << assoc->assocId << " newId=" << newAssoc->assocId << "\n";
811 
812  for (auto& elem : sctpAssocMap) {
813  if (assoc->assocId == elem.second->assocId) {
814  keyAssoc = elem.first;
815  found = true;
816  break;
817  }
818  }
819 
820  ASSERT(found == true);
821 
822  // update assoc's socket pair, and register newAssoc (which'll keep LISTENing)
823  updateSockPair(assoc, localAddr, remoteAddr, localPort, remotePort);
824  updateSockPair(newAssoc, keyAssoc.localAddr, keyAssoc.remoteAddr, keyAssoc.localPort, keyAssoc.remotePort);
825 
826  // assoc will get a new assocId...
827  AppAssocKey key;
828  key.appGateIndex = assoc->appGateIndex;
829  key.assocId = assoc->assocId;
830  sctpAppAssocMap.erase(key);
831  assoc->listeningAssocId = assoc->assocId;
832  int id = SctpSocket::getNewAssocId();
833  EV_INFO << "id = " << id << endl;
834  key.assocId = assoc->assocId = id;
835  EV_INFO << "listeningAssocId set to " << assoc->listeningAssocId << " new assocId = " << assoc->assocId << endl;
836  sctpAppAssocMap[key] = assoc;
837 
838  // ...and newAssoc will live on with the old assocId
839  key.appGateIndex = newAssoc->appGateIndex;
840  key.assocId = newAssoc->assocId;
841  sctpAppAssocMap[key] = newAssoc;
842  sizeAssocMap = sctpAssocMap.size();
844 }

Referenced by inet::sctp::SctpAssociation::processInitArrived().

◆ addLocalAddress()

void inet::sctp::Sctp::addLocalAddress ( SctpAssociation assoc,
L3Address  address 
)
678 {
679  SockPair key;
680 
681  key.localAddr = assoc->localAddr;
682  key.remoteAddr = assoc->remoteAddr;
683  key.localPort = assoc->localPort;
684  key.remotePort = assoc->remotePort;
685 
686  auto i = sctpAssocMap.find(key);
687  if (i != sctpAssocMap.end()) {
688  ASSERT(i->second == assoc);
689  if (key.localAddr.isUnspecified()) {
690  sctpAssocMap.erase(i);
691  sizeAssocMap--;
692  }
693  }
694  else
695  EV_INFO << "no actual sockPair found\n";
696  key.localAddr = address;
697  sctpAssocMap[key] = assoc;
698  sizeAssocMap = sctpAssocMap.size();
699  EV_INFO << "addLocalAddress " << address << " number of connections now=" << sizeAssocMap << "\n";
700 
702 }

Referenced by inet::sctp::SctpAssociation::processInitArrived(), and inet::sctp::SctpAssociation::sendInit().

◆ addLocalAddressToAllRemoteAddresses()

void inet::sctp::Sctp::addLocalAddressToAllRemoteAddresses ( SctpAssociation assoc,
L3Address  address,
std::vector< L3Address remAddresses 
)
705 {
706  SockPair key;
707 
708  for (auto& remAddresse : remAddresses) {
709 // EV_DEBUG<<"remote address="<<(*i)<<"\n";
710  key.localAddr = assoc->localAddr;
711  key.remoteAddr = (remAddresse);
712  key.localPort = assoc->localPort;
713  key.remotePort = assoc->remotePort;
714 
715  auto j = sctpAssocMap.find(key);
716  if (j != sctpAssocMap.end()) {
717  ASSERT(j->second == assoc);
718  if (key.localAddr.isUnspecified()) {
719  sctpAssocMap.erase(j);
720  sizeAssocMap--;
721  }
722  }
723  else
724  EV_INFO << "no actual sockPair found\n";
725  key.localAddr = address;
726  sctpAssocMap[key] = assoc;
727 
728  sizeAssocMap++;
729  EV_DEBUG << "number of connections=" << sctpAssocMap.size() << "\n";
730 
732  }
733 }

Referenced by inet::sctp::SctpAssociation::processAsconfAckArrived(), and inet::sctp::SctpAssociation::sendAsconf().

◆ addRemoteAddress()

bool inet::sctp::Sctp::addRemoteAddress ( SctpAssociation assoc,
L3Address  localAddress,
L3Address  remoteAddress 
)
782 {
783  EV_INFO << "Add remote Address: " << remoteAddress << " to local Address " << localAddress << "\n";
784 
785  SockPair key;
786  key.localAddr = localAddress;
787  key.remoteAddr = remoteAddress;
788  key.localPort = assoc->localPort;
789  key.remotePort = assoc->remotePort;
790 
791  auto i = sctpAssocMap.find(key);
792  if (i != sctpAssocMap.end()) {
793  ASSERT(i->second == assoc);
794  return false;
795  }
796  else {
797  sctpAssocMap[key] = assoc;
798  sizeAssocMap++;
799  }
800 
802  return true;
803 }

Referenced by inet::sctp::SctpAssociation::processAsconfArrived(), inet::sctp::SctpAssociation::processInitAckArrived(), and inet::sctp::SctpAssociation::processInitArrived().

◆ bindPortForUDP()

void inet::sctp::Sctp::bindPortForUDP ( )
74 {
75  EV_INFO << "Binding to UDP port " << SCTP_UDP_PORT << endl;
76 
77  udpSocket.setOutputGate(gate("ipOut"));
78  udpSockId = getEnvir()->getUniqueNumber();
79  EV_INFO << "UDP socket Id is " << udpSocket.getSocketId() << endl;
80 // udpSocket.bind(SCTP_UDP_PORT);
81 }

◆ collectSocketOptions()

SocketOptions * inet::sctp::Sctp::collectSocketOptions ( )

Getter and Setter for the socket options.

354 {
355  SocketOptions *sockOptions = new SocketOptions();
356  sockOptions->maxInitRetrans = par("maxInitRetrans");
357  sockOptions->maxInitRetransTimeout = SCTP_TIMEOUT_INIT_REXMIT_MAX;
358  sockOptions->rtoInitial = par("rtoInitial");
359  sockOptions->rtoMin = par("rtoMin");
360  sockOptions->rtoMax = par("rtoMax");
361  sockOptions->sackFrequency = par("sackFrequency");
362  sockOptions->sackPeriod = par("sackPeriod");
363  sockOptions->maxBurst = par("maxBurst");
364  sockOptions->fragPoint = par("fragPoint");
365  sockOptions->nagle = par("nagleEnabled").boolValue() ? 1 : 0;
366  sockOptions->enableHeartbeats = par("enableHeartbeats");
367  sockOptions->pathMaxRetrans = par("pathMaxRetrans");
368  sockOptions->hbInterval = par("hbInterval");
369  sockOptions->assocMaxRtx = par("assocMaxRetrans");
370  return sockOptions;
371 }

Referenced by handleMessage().

◆ findAssocForApp()

SctpAssociation * inet::sctp::Sctp::findAssocForApp ( int32_t  appGateIndex,
int32_t  assocId 
)
protected
614 {
615  AppAssocKey key;
616  key.appGateIndex = appGateIndex;
617  key.assocId = assocId;
618  EV_INFO << "findAssoc for appGateIndex " << appGateIndex << " and assoc " << assocId << "\n";
619  auto i = sctpAppAssocMap.find(key);
620  return (i == sctpAppAssocMap.end()) ? nullptr : i->second;
621 }

Referenced by handleMessage().

◆ findAssocForFd()

int32_t inet::sctp::Sctp::findAssocForFd ( int32_t  fd)
protected
624 {
625  SctpAssociation *assoc = nullptr;
626  for (auto& elem : sctpAppAssocMap) {
627  assoc = elem.second;
628  if (assoc->fd == fd)
629  return assoc->assocId;
630  }
631  return -1;
632 }

Referenced by handleMessage().

◆ findAssocForInitAck()

SctpAssociation * inet::sctp::Sctp::findAssocForInitAck ( SctpInitAckChunk initack,
L3Address  srcAddr,
L3Address  destAddr,
uint32_t  srcPort,
uint32_t  destPort,
bool  findListen 
)
548 {
549  SctpAssociation *assoc = nullptr;
550  int numberAddresses = initAckChunk->getAddressesArraySize();
551  for (int32_t j = 0; j < numberAddresses; j++) {
552  if (initAckChunk->getAddresses(j).getType() == L3Address::IPv6)
553  continue;
554  assoc = findAssocForMessage(initAckChunk->getAddresses(j), destAddr, srcPort, destPort, findListen);
555  if (assoc) {
556  break;
557  }
558  }
559  return assoc;
560 }

Referenced by handleMessage().

◆ findAssocForMessage()

SctpAssociation * inet::sctp::Sctp::findAssocForMessage ( L3Address  srcAddr,
L3Address  destAddr,
uint32_t  srcPort,
uint32_t  destPort,
bool  findListen 
)
protected
563 {
564  SockPair key;
565 
566  key.localAddr = destAddr;
567  key.remoteAddr = srcAddr;
568  key.localPort = destPort;
569  key.remotePort = srcPort;
570  SockPair save = key;
571  EV_DEBUG << "findAssocForMessage: srcAddr=" << destAddr << " destAddr=" << srcAddr << " srcPort=" << destPort << " destPort=" << srcPort << "\n";
573 
574  // try with fully qualified SockPair
575  auto i = sctpAssocMap.find(key);
576  if (i != sctpAssocMap.end())
577  return i->second;
578 
579  // try with localAddr missing (only localPort specified in passive/active open)
580  key.localAddr = L3Address();
581 
582  i = sctpAssocMap.find(key);
583  if (i != sctpAssocMap.end()) {
584  // try with localAddr missing (only localPort specified in passive/active open)
585  return i->second;
586  }
587 
588  if (findListen == true) {
589  // try fully qualified local socket + blank remote socket (for incoming SYN)
590  key = save;
591  key.remoteAddr = L3Address();
592  key.remotePort = 0;
593  i = sctpAssocMap.find(key);
594  if (i != sctpAssocMap.end()) {
595  // try fully qualified local socket + blank remote socket
596  return i->second;
597  }
598 
599  // try with blank remote socket, and localAddr missing (for incoming SYN)
600  key.localAddr = L3Address();
601  i = sctpAssocMap.find(key);
602  if (i != sctpAssocMap.end()) {
603  // try with blank remote socket, and localAddr missing
604  return i->second;
605  }
606  }
607  // given up
608 
609  EV_INFO << "giving up on trying to find assoc for localAddr=" << srcAddr << " remoteAddr=" << destAddr << " localPort=" << srcPort << " remotePort=" << destPort << "\n";
610  return nullptr;
611 }

Referenced by findAssocForInitAck(), and handleMessage().

◆ findAssocWithVTag()

SctpAssociation * inet::sctp::Sctp::findAssocWithVTag ( uint32_t  peerVTag,
uint32_t  remotePort,
uint32_t  localPort 
)
531 {
532  printVTagMap();
533  EV_DEBUG << "findAssocWithVTag: peerVTag=" << peerVTag << " srcPort=" << remotePort << " destPort=" << localPort << "\n";
535 
536  // try with fully qualified SockPair
537  for (auto& elem : sctpVTagMap) {
538  if ((elem.second.peerVTag == peerVTag && elem.second.localPort == localPort
539  && elem.second.remotePort == remotePort)
540  || (elem.second.localVTag == peerVTag && elem.second.localPort == localPort
541  && elem.second.remotePort == remotePort))
542  return getAssoc(elem.first);
543  }
544  return nullptr;
545 }

Referenced by handleMessage().

◆ finish()

void inet::sctp::Sctp::finish ( )
overridevirtual
978 {
979  auto assocMapIterator = sctpAssocMap.begin();
980  while (assocMapIterator != sctpAssocMap.end()) {
981  removeAssociation(assocMapIterator->second);
982  assocMapIterator = sctpAssocMap.begin();
983  }
984  EV_INFO << getFullPath() << ": finishing SCTP with "
985  << sctpAssocMap.size() << " connections open." << endl;
986 
987  for (AssocStatMap::const_iterator iterator = assocStatMap.begin();
988  iterator != assocStatMap.end(); iterator++)
989  {
990  const Sctp::AssocStat& assoc = iterator->second;
991 
992  EV_DETAIL << "Association " << assoc.assocId << ": started at " << assoc.start
993  << " and finished at " << assoc.stop << " --> lifetime: " << assoc.lifeTime << endl;
994  EV_DETAIL << "Association " << assoc.assocId << ": sent bytes=" << assoc.sentBytes
995  << ", acked bytes=" << assoc.ackedBytes << ", throughput=" << assoc.throughput << " bit/s" << endl;
996  EV_DETAIL << "Association " << assoc.assocId << ": transmitted Bytes="
997  << assoc.transmittedBytes << ", retransmitted Bytes=" << assoc.transmittedBytes - assoc.ackedBytes << endl;
998  EV_DETAIL << "Association " << assoc.assocId << ": number of Fast RTX="
999  << assoc.numFastRtx << ", number of Timer-Based RTX=" << assoc.numT3Rtx
1000  << ", path failures=" << assoc.numPathFailures << ", ForwardTsns=" << assoc.numForwardTsn << endl;
1001  EV_DETAIL << "AllMessages=" << numPacketsReceived << " BadMessages=" << numPacketsDropped << endl;
1002 
1003  recordScalar("Association Lifetime", assoc.lifeTime);
1004  recordScalar("Acked Bytes", assoc.ackedBytes);
1005  recordScalar("Throughput [bit/s]", assoc.throughput);
1006  recordScalar("Transmitted Bytes", assoc.transmittedBytes);
1007  recordScalar("Fast RTX", assoc.numFastRtx);
1008  recordScalar("Timer-Based RTX", assoc.numT3Rtx);
1009  recordScalar("Duplicate Acks", assoc.numDups);
1010  recordScalar("Packets Received", numPacketsReceived);
1011  recordScalar("Packets Dropped", numPacketsDropped);
1012  recordScalar("Sum of R Gap Ranges", assoc.sumRGapRanges);
1013  recordScalar("Sum of NR Gap Ranges", assoc.sumNRGapRanges);
1014  recordScalar("Overfull SACKs", assoc.numOverfullSACKs);
1015  recordScalar("Drops Because New TSN Greater Than Highest TSN", assoc.numDropsBecauseNewTsnGreaterThanHighestTsn);
1016  recordScalar("Drops Because No Room In Buffer", assoc.numDropsBecauseNoRoomInBuffer);
1017  recordScalar("Chunks Reneged", assoc.numChunksReneged);
1018  recordScalar("sackPeriod", (simtime_t)socketOptions->sackPeriod);
1019  recordScalar("Number of AUTH chunks sent", assoc.numAuthChunksSent);
1020  recordScalar("Number of AUTH chunks accepted", assoc.numAuthChunksAccepted);
1021  recordScalar("Number of AUTH chunks rejected", assoc.numAuthChunksRejected);
1022  recordScalar("Number of StreamReset requests sent", assoc.numResetRequestsSent);
1023  recordScalar("Number of StreamReset requests performed", assoc.numResetRequestsPerformed);
1024  if (par("fairStart").doubleValue() > 0.0) {
1025  recordScalar("fair acked bytes", assoc.fairAckedBytes);
1026  recordScalar("fair start time", assoc.fairStart);
1027  recordScalar("fair stop time", assoc.fairStop);
1028  recordScalar("fair lifetime", assoc.fairLifeTime);
1029  recordScalar("fair throughput", assoc.fairThroughput);
1030  }
1031  recordScalar("Number of PacketDrop Reports", numPktDropReports);
1032 
1033  if (assoc.numEndToEndMessages > 0 && (assoc.cumEndToEndDelay / assoc.numEndToEndMessages) > 0) {
1034  uint32_t msgnum = assoc.numEndToEndMessages - assoc.startEndToEndDelay;
1035  if (assoc.stopEndToEndDelay > 0)
1036  msgnum -= (assoc.numEndToEndMessages - assoc.stopEndToEndDelay);
1037  recordScalar("Average End to End Delay", assoc.cumEndToEndDelay / msgnum);
1038  }
1039 
1040  recordScalar("RTXMethod", par("RTXMethod").intValue());
1041  }
1042 }

◆ getAssoc()

SctpAssociation * inet::sctp::Sctp::getAssoc ( int32_t  assocId)
969 {
970  for (auto& elem : sctpAppAssocMap) {
971  if (elem.first.assocId == assocId)
972  return elem.second;
973  }
974  return nullptr;
975 }

Referenced by findAssocWithVTag().

◆ getAssocMaxRtx()

◆ getAssocStat()

AssocStat* inet::sctp::Sctp::getAssocStat ( uint32_t  assocId)
inline

◆ getEnableHeartbeats()

◆ getEphemeralPort()

uint16_t inet::sctp::Sctp::getEphemeralPort ( )

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

635 {
636  if (nextEphemeralPort == 5000)
637  throw cRuntimeError("Ephemeral port range 1024..4999 exhausted (email SCTP model "
638  "author that he should implement reuse of ephemeral ports!!!)");
639  return nextEphemeralPort++;
640 }

Referenced by inet::sctp::SctpAssociation::process_ASSOCIATE().

◆ getFragPoint()

int inet::sctp::Sctp::getFragPoint ( )
inline

◆ getHbInterval()

◆ getInterfaceId()

int inet::sctp::Sctp::getInterfaceId ( )
inline
273 { return interfaceId; };

Referenced by inet::sctp::SctpAssociation::sendToIP().

◆ getMaxBurst()

int inet::sctp::Sctp::getMaxBurst ( )
inline

◆ getMaxInitRetrans()

int inet::sctp::Sctp::getMaxInitRetrans ( )
inline

◆ getMaxInitRetransTimeout()

int inet::sctp::Sctp::getMaxInitRetransTimeout ( )
inline

◆ getNagle()

int inet::sctp::Sctp::getNagle ( )
inline

◆ getPathMaxRetrans()

◆ getRtoInitial()

double inet::sctp::Sctp::getRtoInitial ( )
inline

◆ getRtoMax()

◆ getRtoMin()

double inet::sctp::Sctp::getRtoMin ( )
inline

◆ getSackFrequency()

int inet::sctp::Sctp::getSackFrequency ( )
inline

◆ getSackPeriod()

double inet::sctp::Sctp::getSackPeriod ( )
inline

◆ getVTagMap()

SctpVTagMap inet::sctp::Sctp::getVTagMap ( )
inline
247 { return sctpVTagMap; };

◆ handleMessage()

void inet::sctp::Sctp::handleMessage ( cMessage *  msg)
overridevirtual
166 {
167  L3Address destAddr;
168  L3Address srcAddr;
169  bool findListen = false;
170 
171  EV_INFO << "\n\nSctpMain handleMessage at " << getFullPath() << "\n";
172 
173  if (msg->isSelfMessage()) {
174  EV_DEBUG << "selfMessage\n";
175 
176  SctpAssociation *assoc = (SctpAssociation *)msg->getContextPointer();
177  if (assoc) {
178  bool ret = assoc->processTimer(msg);
179 
180  if (!ret)
181  removeAssociation(assoc);
182  }
183  }
184  else if (msg->arrivedOn("ipIn")) {
185  EV_INFO << "Message from IP\n";
187  Packet *packet = check_and_cast<Packet *>(msg);
188  auto protocol = packet->getTag<PacketProtocolTag>()->getProtocol();
189  if (protocol == &Protocol::sctp) {
190  // must be an SctpHeader
191  SctpHeader *sctpmsg = (packet->peekAtFront<SctpHeader>().get()->dup());
192  int chunkLength = B(sctpmsg->getChunkLength()).get();
194 
195  if (!pktdrop && (packet->hasBitError())) {
196  EV_WARN << "Packet has bit-error. delete it\n";
197 
199  delete msg;
200  return;
201  }
202 
203  if (pktdrop && packet->hasBitError()) {
204  EV_WARN << "Packet has bit-error. Call Pktdrop\n";
205  }
206 
207  srcAddr = packet->getTag<L3AddressInd>()->getSrcAddress();
208  destAddr = packet->getTag<L3AddressInd>()->getDestAddress();
209  EV_INFO << "srcAddr=" << srcAddr << " destAddr=" << destAddr << "\n";
210  if (chunkLength > SCTP_COMMON_HEADER) {
211  if (((sctpmsg->getSctpChunks(0)))->getSctpChunkType() == INIT || ((sctpmsg->getSctpChunks(0)))->getSctpChunkType() == INIT_ACK)
212  findListen = true;
213 
214  SctpAssociation *assoc = findAssocForMessage(srcAddr, destAddr, sctpmsg->getSrcPort(), sctpmsg->getDestPort(), findListen);
215  if (!assoc && sctpAssocMap.size() > 0 && (((sctpmsg->getSctpChunks(0)))->getSctpChunkType() == INIT_ACK)) {
216  SctpInitAckChunk *initack = check_and_cast<SctpInitAckChunk *>((SctpChunk *)(sctpmsg->getSctpChunks(0)));
217  assoc = findAssocForInitAck(initack, srcAddr, destAddr, sctpmsg->getSrcPort(), sctpmsg->getDestPort(), findListen);
218  }
219  if (!assoc && sctpAssocMap.size() > 0 && (((sctpmsg->getSctpChunks(0)))->getSctpChunkType() == ERRORTYPE
220  || (sctpmsg->getSctpChunksArraySize() > 1 &&
221  (((sctpmsg->getSctpChunks(1)))->getSctpChunkType() == ASCONF || ((sctpmsg->getSctpChunks(1)))->getSctpChunkType() == ASCONF_ACK))))
222  {
223  assoc = findAssocWithVTag(sctpmsg->getVTag(), sctpmsg->getSrcPort(), sctpmsg->getDestPort());
224  }
225  if (!assoc) {
226  EV_INFO << "no assoc found msg=" << sctpmsg->getName() << "\n";
227 
228  if (!pktdrop && packet->hasBitError()) {
229 // delete sctpmsg;
230  return;
231  }
232 
233  Ptr<SctpHeader> sctpmsgptr(sctpmsg);
234  if (((sctpmsg->getSctpChunks(0)))->getSctpChunkType() == SHUTDOWN_ACK)
235  sendShutdownCompleteFromMain(sctpmsgptr, destAddr, srcAddr);
236  else if (((sctpmsg->getSctpChunks(0)))->getSctpChunkType() != ABORT &&
237  ((sctpmsg->getSctpChunks(0)))->getSctpChunkType() != SHUTDOWN_COMPLETE)
238  {
239  sendAbortFromMain(sctpmsgptr, destAddr, srcAddr);
240  }
241  delete packet;
242  }
243  else {
244  EV_INFO << "assoc " << assoc->assocId << " found\n";
245  bool ret = assoc->processSctpMessage(sctpmsg, srcAddr, destAddr);
246  if (!ret) {
247  EV_DEBUG << "SctpMain:: removeAssociation \n";
248  removeAssociation(assoc);
249  delete packet;
250  }
251  else {
252  delete packet;
253  }
254  }
255  }
256  }
257  else {
258  delete packet;
259  }
260  }
261  else { // must be from app
262  EV_DEBUG << "must be from app\n";
263  auto& tags = check_and_cast<ITaggedObject *>(msg)->getTags();
264  int32_t assocId = tags.getTag<SocketReq>()->getSocketId();
265  EV_INFO << "assocId = " << assocId << endl;
266  if (msg->getKind() == SCTP_C_GETSOCKETOPTIONS) {
267  auto controlInfo = tags.getTag<SctpSendReq>();
268  Indication *cmsg = new Indication("SendSocketOptions", SCTP_I_SENDSOCKETOPTIONS);
269  auto indication = cmsg->addTag<SctpCommandReq>();
270  indication->setSocketId(controlInfo->getSocketId());
272  cmsg->setContextPointer((void *)socketOptions);
273  cmsg->addTag<SocketInd>()->setSocketId(assocId);
274  send(cmsg, "appOut");
275  delete msg;
276  }
277  else {
278  int32_t appGateIndex;
279  int32_t fd;
280  Ptr<const SctpCommandReq> controlInfo = tags.findTag<SctpOpenReq>();
281  if (!controlInfo) {
282  controlInfo = tags.findTag<SctpSendReq>();
283  if (!controlInfo) {
284  controlInfo = tags.findTag<SctpCommandReq>();
285  if (!controlInfo) {
286  controlInfo = tags.findTag<SctpAvailableReq>();
287  if (!controlInfo) {
288  controlInfo = tags.findTag<SctpResetReq>();
289  if (!controlInfo) {
290  controlInfo = tags.findTag<SctpInfoReq>();
291  if (!controlInfo) {
292  std::cout << "!!!!!!!!!Unknown Tag!!!!!!!!\n";
293  }
294  }
295  }
296  }
297  }
298  }
299  if (controlInfo->getGate() != -1)
300  appGateIndex = controlInfo->getGate();
301  else
302  appGateIndex = msg->getArrivalGate()->isVector() ? msg->getArrivalGate()->getIndex() : 0;
303  if (controlInfo && assocId == -1) {
304  fd = controlInfo->getFd();
305  assocId = findAssocForFd(fd);
306  }
307  EV_INFO << "msg arrived from app for assoc " << assocId << "\n";
308  SctpAssociation *assoc = findAssocForApp(appGateIndex, assocId);
309 
310  if (!assoc) {
311  EV_INFO << "no assoc found. msg=" << msg->getName() << " number of assocs = " << assocList.size() << "\n";
312 
313  if (strcmp(msg->getName(), "PassiveOPEN") == 0 || strcmp(msg->getName(), "Associate") == 0) {
314  if (assocList.size() > 0) {
315  assoc = nullptr;
316  const auto& open = tags.findTag<SctpOpenReq>();
317  EV_INFO << "Looking for assoc with remoteAddr=" << open->getRemoteAddr() << ", remotePort=" << open->getRemotePort() << ", localPort=" << open->getLocalPort() << "\n";
318  for (auto& elem : assocList) {
319  EV_DETAIL << "remoteAddr=" << (elem)->remoteAddr << ", remotePort=" << (elem)->remotePort << ", localPort=" << (elem)->localPort << "\n";
320  if ((elem)->remoteAddr == open->getRemoteAddr() && (elem)->localPort == open->getLocalPort() && (elem)->remotePort == open->getRemotePort()) {
321  assoc = (elem);
322  break;
323  }
324  }
325  }
326  if (assocList.size() == 0 || assoc == nullptr) {
327  assoc = new SctpAssociation(this, appGateIndex, assocId, rt, ift);
328 
329  AppAssocKey key;
330  key.appGateIndex = appGateIndex;
331  key.assocId = assocId;
332  sctpAppAssocMap[key] = assoc;
333  EV_INFO << "SCTP association created for appGateIndex " << appGateIndex << " and assoc " << assocId << "\n";
334  bool ret = assoc->processAppCommand(msg, const_cast<SctpCommandReq *>(controlInfo.get()));
335  if (!ret) {
336  removeAssociation(assoc);
337  }
338  }
339  }
340  }
341  else {
342  EV_INFO << "assoc found\n";
343  bool ret = assoc->processAppCommand(msg, const_cast<SctpCommandReq *>(controlInfo.get()));
344  if (!ret) {
345  removeAssociation(assoc);
346  }
347  }
348  delete msg;
349  }
350  }
351 }

◆ initialize()

void inet::sctp::Sctp::initialize ( int  stage)
overridevirtual
84 {
85  cSimpleModule::initialize(stage);
86 
87  if (stage == INITSTAGE_LOCAL) {
88  ift.reference(this, "interfaceTableModule", true);
89  rt.reference(this, "routingTableModule", true);
90  auth = par("auth");
91  pktdrop = par("packetDrop");
92  sackNow = par("sackNow");
96  sizeAssocMap = 0;
97  nextEphemeralPort = (uint16_t)(intrand(10000) + 30000);
98 
99  cModule *netw = getSimulation()->getSystemModule();
100  if (netw->hasPar("testTimeout")) {
101  testTimeout = netw->par("testTimeout");
102  }
103  const char *crcModeString = par("crcMode");
104  crcMode = parseCrcMode(crcModeString, false);
105  }
106  else if (stage == INITSTAGE_TRANSPORT_LAYER) {
107  registerService(Protocol::sctp, gate("appIn"), gate("appOut"));
108  registerProtocol(Protocol::sctp, gate("ipOut"), gate("ipIn"));
109  if (crcMode == CRC_COMPUTED) {
110  cModuleType *moduleType = cModuleType::get("inet.transportlayer.sctp.SctpCrcInsertion");
111  auto crcInsertion = check_and_cast<SctpCrcInsertion *>(moduleType->create("crcInsertion", this));
112  crcInsertion->finalizeParameters();
113  crcInsertion->callInitialize();
114  crcInsertion->setCrcMode(crcMode);
115 
116 #ifdef INET_WITH_IPv4
117  auto ipv4 = dynamic_cast<INetfilter *>(findModuleByPath("^.ipv4.ip"));
118  if (ipv4 != nullptr) {
119  ipv4->registerHook(0, crcInsertion);
120  }
121 #endif
122 #ifdef INET_WITH_IPv6
123  auto ipv6 = dynamic_cast<INetfilter *>(findModuleByPath("^.ipv6.ipv6"));
124  if (ipv6 != nullptr)
125  ipv6->registerHook(0, crcInsertion);
126 #endif
127  }
128  if (par("udpEncapsEnabled")) {
129  EV_INFO << "udpEncapsEnabled" << endl;
130  cModuleType *moduleType = cModuleType::get("inet.transportlayer.sctp.SctpUdpHook");
131  auto udpHook = check_and_cast<SctpUdpHook *>(moduleType->create("udpHook", this));
132  udpHook->finalizeParameters();
133  udpHook->callInitialize();
134 #ifdef INET_WITH_IPv4
135  auto ipv4 = dynamic_cast<INetfilter *>(findModuleByPath("^.ipv4.ip"));
136  if (ipv4 != nullptr)
137  ipv4->registerHook(0, udpHook);
138 #endif
139 #ifdef INET_WITH_IPv6
140  auto ipv6 = dynamic_cast<INetfilter *>(findModuleByPath("^.ipv6.ipv6"));
141  if (ipv6 != nullptr)
142  ipv6->registerHook(0, udpHook);
143 #endif
144  }
145  }
146 }

◆ numInitStages()

virtual int inet::sctp::Sctp::numInitStages ( ) const
inlineoverridevirtual
211 { return NUM_INIT_STAGES; }

◆ printInfoAssocMap()

void inet::sctp::Sctp::printInfoAssocMap ( )
38 {
39  SctpAssociation *assoc;
40  SockPair key;
41  EV_DETAIL << "Number of Assocs: " << sizeAssocMap << "\n";
42  if (sizeAssocMap > 0) {
43  for (auto& elem : sctpAssocMap) {
44  assoc = elem.second;
45  key = elem.first;
46 
47  EV_DETAIL << "assocId: " << assoc->assocId << " src: " << key.localAddr << " dst: " << key.remoteAddr << " lPort: " << key.localPort << " rPort: " << key.remotePort << " fd: " << assoc->fd << "\n";
48  }
49 
50  EV_DETAIL << "\n";
51  }
52 }

Referenced by addForkedAssociation(), addLocalAddress(), addLocalAddressToAllRemoteAddresses(), addRemoteAddress(), inet::sctp::SctpAssociation::cloneAssociation(), findAssocForMessage(), findAssocWithVTag(), handleMessage(), removeAssociation(), removeLocalAddressFromAllRemoteAddresses(), removeRemoteAddressFromAllAssociations(), inet::sctp::SctpAssociation::sendInit(), and updateSockPair().

◆ printVTagMap()

void inet::sctp::Sctp::printVTagMap ( )
55 {
56  int32_t assocId;
57  VTagPair key;
58  EV_DETAIL << "Number of Assocs: " << sctpVTagMap.size() << "\n";
59  if (sctpVTagMap.size() > 0) {
60  for (auto& elem : sctpVTagMap) {
61  assocId = elem.first;
62  key = elem.second;
63 
64  EV_DETAIL << "assocId: " << assocId << " peerVTag: " << key.peerVTag
65  << " localVTag: " << key.localVTag
66  << " localPort: " << key.localPort << " rPort: " << key.remotePort << "\n";
67  }
68 
69  EV_DETAIL << "\n";
70  }
71 }

Referenced by findAssocWithVTag().

◆ refreshDisplay()

void inet::sctp::Sctp::refreshDisplay ( ) const
overrideprotectedvirtual
448 {
449 #if 0
450  if (getEnvir()->disable_tracing) {
451  // in express mode, we don't bother to update the display
452  // (std::map's iteration is not very fast if map is large)
453  getDisplayString().setTagArg("t", 0, "");
454  return;
455  }
456 
457 // char buf[40];
458 // sprintf(buf,"%d conns", sctpAppConnMap.size());
459 // displayString().setTagArg("t",0,buf);
460 
461  int32_t numCLOSED = 0, numLISTEN = 0, numSYN_SENT = 0, numSYN_RCVD = 0,
462  numESTABLISHED = 0, numCLOSE_WAIT = 0, numLAST_ACK = 0, numFIN_WAIT_1 = 0,
463  numFIN_WAIT_2 = 0, numCLOSING = 0, numTIME_WAIT = 0;
464 
465  for (auto i = sctpAppConnMap.begin(); i != sctpAppConnMap.end(); ++i) {
466  int32_t state = (*i).second->getFsmState();
467  switch (state) {
468 // case SCTP_S_INIT: numINIT++; break;
469  case SCTP_S_CLOSED:
470  numCLOSED++;
471  break;
472 
473  case SCTP_S_COOKIE_WAIT:
474  numLISTEN++;
475  break;
476 
478  numSYN_SENT++;
479  break;
480 
481  case SCTP_S_ESTABLISHED:
482  numESTABLISHED++;
483  break;
484 
486  numCLOSE_WAIT++;
487  break;
488 
490  numLAST_ACK++;
491  break;
492 
494  numFIN_WAIT_1++;
495  break;
496 
498  numFIN_WAIT_2++;
499  break;
500  }
501  }
502  char buf2[300];
503  buf2[0] = '\0';
504  if (numCLOSED > 0)
505  sprintf(buf2 + strlen(buf2), "closed:%d ", numCLOSED);
506  if (numLISTEN > 0)
507  sprintf(buf2 + strlen(buf2), "listen:%d ", numLISTEN);
508  if (numSYN_SENT > 0)
509  sprintf(buf2 + strlen(buf2), "syn_sent:%d ", numSYN_SENT);
510  if (numSYN_RCVD > 0)
511  sprintf(buf2 + strlen(buf2), "syn_rcvd:%d ", numSYN_RCVD);
512  if (numESTABLISHED > 0)
513  sprintf(buf2 + strlen(buf2), "estab:%d ", numESTABLISHED);
514  if (numCLOSE_WAIT > 0)
515  sprintf(buf2 + strlen(buf2), "close_wait:%d ", numCLOSE_WAIT);
516  if (numLAST_ACK > 0)
517  sprintf(buf2 + strlen(buf2), "last_ack:%d ", numLAST_ACK);
518  if (numFIN_WAIT_1 > 0)
519  sprintf(buf2 + strlen(buf2), "fin_wait_1:%d ", numFIN_WAIT_1);
520  if (numFIN_WAIT_2 > 0)
521  sprintf(buf2 + strlen(buf2), "fin_wait_2:%d ", numFIN_WAIT_2);
522  if (numCLOSING > 0)
523  sprintf(buf2 + strlen(buf2), "closing:%d ", numCLOSING);
524  if (numTIME_WAIT > 0)
525  sprintf(buf2 + strlen(buf2), "time_wait:%d ", numTIME_WAIT);
526  getDisplayString().setTagArg("t", 0, buf2);
527 #endif // if 0
528 }

◆ removeAssociation()

void inet::sctp::Sctp::removeAssociation ( SctpAssociation assoc)
847 {
848  bool ok = false;
849  bool find = false;
850  const int32_t id = assoc->assocId;
851 
852  EV_INFO << "Deleting SCTP connection " << assoc << " id= " << id << endl;
853 
855  if (sizeAssocMap > 0) {
856  auto assocStatMapIterator = assocStatMap.find(assoc->assocId);
857  if (assocStatMapIterator != assocStatMap.end()) {
858  assocStatMapIterator->second.stop = simTime();
859  assocStatMapIterator->second.lifeTime = assocStatMapIterator->second.stop - assocStatMapIterator->second.start;
860  assocStatMapIterator->second.throughput = assocStatMapIterator->second.ackedBytes * 8 / assocStatMapIterator->second.lifeTime.dbl();
861  }
862  while (!ok) {
863  if (sizeAssocMap == 0) {
864  ok = true;
865  }
866  else {
867  for (auto sctpAssocMapIterator = sctpAssocMap.begin();
868  sctpAssocMapIterator != sctpAssocMap.end(); sctpAssocMapIterator++)
869  {
870  if (sctpAssocMapIterator->second != nullptr) {
871  SctpAssociation *myAssoc = sctpAssocMapIterator->second;
872  if (myAssoc->assocId == assoc->assocId) {
873  if (myAssoc->T1_InitTimer) {
874  myAssoc->stopTimer(myAssoc->T1_InitTimer);
875  }
876  if (myAssoc->T2_ShutdownTimer) {
877  myAssoc->stopTimer(myAssoc->T2_ShutdownTimer);
878  }
879  if (myAssoc->T5_ShutdownGuardTimer) {
880  myAssoc->stopTimer(myAssoc->T5_ShutdownGuardTimer);
881  }
882  if (myAssoc->SackTimer) {
883  myAssoc->stopTimer(myAssoc->SackTimer);
884  }
885  if (myAssoc->StartAddIP) {
886  myAssoc->stopTimer(myAssoc->StartAddIP);
887  }
888  sctpAssocMap.erase(sctpAssocMapIterator);
889  sizeAssocMap--;
890  find = true;
891  break;
892  }
893  }
894  }
895  }
896 
897  if (!find) {
898  ok = true;
899  }
900  else {
901  find = false;
902  }
903  }
904  }
905  // Write statistics
906  char str[128];
907  for (auto pathMapIterator = assoc->sctpPathMap.begin();
908  pathMapIterator != assoc->sctpPathMap.end(); pathMapIterator++)
909  {
910  const SctpPathVariables *path = pathMapIterator->second;
911  snprintf(str, sizeof(str), "Number of Fast Retransmissions %d:%s",
912  assoc->assocId, path->remoteAddress.str().c_str());
913  recordScalar(str, path->numberOfFastRetransmissions);
914  snprintf(str, sizeof(str), "Number of Timer-Based Retransmissions %d:%s",
915  assoc->assocId, path->remoteAddress.str().c_str());
916  recordScalar(str, path->numberOfTimerBasedRetransmissions);
917  snprintf(str, sizeof(str), "Number of Heartbeats Sent %d:%s",
918  assoc->assocId, path->remoteAddress.str().c_str());
919  recordScalar(str, path->numberOfHeartbeatsSent);
920  snprintf(str, sizeof(str), "Number of Heartbeats Received %d:%s",
921  assoc->assocId, path->remoteAddress.str().c_str());
922  recordScalar(str, path->numberOfHeartbeatsRcvd);
923  snprintf(str, sizeof(str), "Number of Heartbeat ACKs Sent %d:%s",
924  assoc->assocId, path->remoteAddress.str().c_str());
925  recordScalar(str, path->numberOfHeartbeatAcksSent);
926  snprintf(str, sizeof(str), "Number of Heartbeat ACKs Received %d:%s",
927  assoc->assocId, path->remoteAddress.str().c_str());
928  recordScalar(str, path->numberOfHeartbeatAcksRcvd);
929  snprintf(str, sizeof(str), "Number of Duplicates %d:%s",
930  assoc->assocId, path->remoteAddress.str().c_str());
931  recordScalar(str, path->numberOfDuplicates);
932  snprintf(str, sizeof(str), "Number of Bytes received from %d:%s",
933  assoc->assocId, path->remoteAddress.str().c_str());
934  recordScalar(str, path->numberOfBytesReceived);
935  }
936  for (uint16_t i = 0; i < assoc->inboundStreams; i++) {
937  snprintf(str, sizeof(str), "Bytes received on stream %d of assoc %d",
938  i, assoc->assocId);
939  recordScalar(str, assoc->getState()->streamThroughput[i]);
940  }
941  recordScalar("Blocking TSNs Moved", assoc->state->blockingTsnsMoved);
942 
943  assoc->removePath();
944  assoc->deleteStreams();
945 
946  // Chunks may be in the transmission and retransmission queues simultaneously.
947  // Remove entry from transmission queue if it is already in the retransmission queue.
948  for (auto i = assoc->getRetransmissionQueue()->payloadQueue.begin();
949  i != assoc->getRetransmissionQueue()->payloadQueue.end(); i++)
950  {
951  auto j = assoc->getTransmissionQueue()->payloadQueue.find(i->second->tsn);
952  if (j != assoc->getTransmissionQueue()->payloadQueue.end()) {
953  assoc->getTransmissionQueue()->payloadQueue.erase(j);
954  }
955  }
956  // Now, both queues can be safely deleted.
957  delete assoc->getRetransmissionQueue();
958  delete assoc->getTransmissionQueue();
959 
960  AppAssocKey key;
961  key.appGateIndex = assoc->appGateIndex;
962  key.assocId = assoc->assocId;
963  sctpAppAssocMap.erase(key);
964  assocList.remove(assoc);
965  delete assoc;
966 }

Referenced by finish(), handleMessage(), inet::sctp::SctpAssociation::process_RCV_Message(), inet::sctp::SctpAssociation::process_TIMEOUT_HEARTBEAT(), inet::sctp::SctpAssociation::process_TIMEOUT_RTX(), inet::sctp::SctpAssociation::process_TIMEOUT_SHUTDOWN(), inet::sctp::SctpAssociation::processTimer(), and inet::sctp::SctpAssociation::updateCounters().

◆ removeLocalAddressFromAllRemoteAddresses()

void inet::sctp::Sctp::removeLocalAddressFromAllRemoteAddresses ( SctpAssociation assoc,
L3Address  address,
std::vector< L3Address remAddresses 
)
736 {
737  SockPair key;
738 
739  for (auto& remAddresse : remAddresses) {
740  key.localAddr = address;
741  key.remoteAddr = (remAddresse);
742  key.localPort = assoc->localPort;
743  key.remotePort = assoc->remotePort;
744 
745  auto j = sctpAssocMap.find(key);
746  if (j != sctpAssocMap.end()) {
747  ASSERT(j->second == assoc);
748  sctpAssocMap.erase(j);
749  sizeAssocMap--;
750  }
751  else
752  EV_INFO << "no actual sockPair found\n";
753 
755  }
756 }

Referenced by inet::sctp::SctpAssociation::processAsconfAckArrived().

◆ removeRemoteAddressFromAllAssociations()

void inet::sctp::Sctp::removeRemoteAddressFromAllAssociations ( SctpAssociation assoc,
L3Address  address,
std::vector< L3Address locAddresses 
)
759 {
760  SockPair key;
761 
762  for (auto& locAddresse : locAddresses) {
763  key.localAddr = (locAddresse);
764  key.remoteAddr = address;
765  key.localPort = assoc->localPort;
766  key.remotePort = assoc->remotePort;
767 
768  auto j = sctpAssocMap.find(key);
769  if (j != sctpAssocMap.end()) {
770  ASSERT(j->second == assoc);
771  sctpAssocMap.erase(j);
772  sizeAssocMap--;
773  }
774  else
775  EV_INFO << "no actual sockPair found\n";
776 
778  }
779 }

Referenced by inet::sctp::SctpAssociation::processAsconfArrived().

◆ send_to_ip()

void inet::sctp::Sctp::send_to_ip ( Packet msg)
virtual
442 {
443  EV_INFO << "send packet " << msg << " to IP\n";
444  send(msg, "ipOut");
445 }

Referenced by sendAbortFromMain(), and sendShutdownCompleteFromMain().

◆ sendAbortFromMain()

void inet::sctp::Sctp::sendAbortFromMain ( Ptr< SctpHeader > &  sctpMsg,
L3Address  fromAddr,
L3Address  toAddr 
)
protected
374 {
375  const auto& msg = makeShared<SctpHeader>();
376 
377  EV_DEBUG << "\n\nSctp::sendAbortFromMain()\n";
378 
379  msg->setSrcPort(sctpmsg->getDestPort());
380  msg->setDestPort(sctpmsg->getSrcPort());
381  msg->setChunkLength(B(SCTP_COMMON_HEADER));
382  msg->setCrc(0);
383  msg->setCrcMode(crcMode);
384  msg->setChecksumOk(true);
385 
386  SctpAbortChunk *abortChunk = new SctpAbortChunk();
387  abortChunk->setSctpChunkType(ABORT);
388  if (sctpmsg->getSctpChunksArraySize() > 0 && ((sctpmsg->getSctpChunks(0)))->getSctpChunkType() == INIT) {
389  const SctpInitChunk *initChunk = check_and_cast<const SctpInitChunk *>(sctpmsg->getSctpChunks(0));
390  abortChunk->setT_Bit(0);
391  msg->setVTag(initChunk->getInitTag());
392  }
393  else {
394  abortChunk->setT_Bit(1);
395  msg->setVTag(sctpmsg->getVTag());
396  }
397  abortChunk->setByteLength(SCTP_ABORT_CHUNK_LENGTH);
398  msg->appendSctpChunks(abortChunk);
399  Packet *pkt = new Packet("ABORT");
400 
401  auto addresses = pkt->addTag<L3AddressReq>();
402  addresses->setSrcAddress(fromAddr);
403  addresses->setDestAddress(toAddr);
404  IL3AddressType *addressType = toAddr.getAddressType();
405  pkt->addTag<DispatchProtocolReq>()->setProtocol(addressType->getNetworkProtocol());
407  send_to_ip(pkt);
408 }

Referenced by handleMessage().

◆ sendShutdownCompleteFromMain()

void inet::sctp::Sctp::sendShutdownCompleteFromMain ( Ptr< SctpHeader > &  sctpMsg,
L3Address  fromAddr,
L3Address  toAddr 
)
protected
411 {
412  const auto& msg = makeShared<SctpHeader>();
413 
414  EV_DEBUG << "\n\nSCTP:sendShutdownCompleteFromMain \n";
415 
416  msg->setSrcPort(sctpmsg->getDestPort());
417  msg->setDestPort(sctpmsg->getSrcPort());
418  msg->setChunkLength(b(SCTP_COMMON_HEADER));
419  msg->setCrc(0);
420  msg->setCrcMode(crcMode);
421  msg->setChecksumOk(true);
422 
423  SctpShutdownCompleteChunk *scChunk = new SctpShutdownCompleteChunk();
424  scChunk->setSctpChunkType(SHUTDOWN_COMPLETE);
425  scChunk->setTBit(1);
426  msg->setVTag(sctpmsg->getVTag());
427 
428  scChunk->setByteLength(SCTP_SHUTDOWN_ACK_LENGTH);
429  msg->appendSctpChunks(scChunk);
430 
431  Packet *pkt = new Packet("SHUTDOWN_COMPLETE");
432  auto addresses = pkt->addTag<L3AddressReq>();
433  addresses->setSrcAddress(fromAddr);
434  addresses->setDestAddress(toAddr);
435  IL3AddressType *addressType = toAddr.getAddressType();
436  pkt->addTag<DispatchProtocolReq>()->setProtocol(addressType->getNetworkProtocol());
438  send_to_ip(pkt);
439 }

Referenced by handleMessage().

◆ setInterfaceId()

void inet::sctp::Sctp::setInterfaceId ( int  id)
inline

◆ setRtoInitial()

void inet::sctp::Sctp::setRtoInitial ( double  rtoInitial)
inline

◆ setRtoMax()

void inet::sctp::Sctp::setRtoMax ( double  rtoMax)
inline

◆ setRtoMin()

void inet::sctp::Sctp::setRtoMin ( double  rtoMin)
inline

◆ setSocketOptions()

void inet::sctp::Sctp::setSocketOptions ( SocketOptions options)
inline

◆ updateSockPair()

void inet::sctp::Sctp::updateSockPair ( SctpAssociation assoc,
L3Address  localAddr,
L3Address  remoteAddr,
int32_t  localPort,
int32_t  remotePort 
)

To be called from SctpAssociation when socket pair changes.

643 {
644  SockPair key;
645  EV_INFO << "updateSockPair: localAddr: " << localAddr << " remoteAddr=" << remoteAddr << " localPort=" << localPort << " remotePort=" << remotePort << "\n";
646 
647  key.localAddr = (assoc->localAddr = localAddr);
648  key.remoteAddr = (assoc->remoteAddr = remoteAddr);
649  key.localPort = assoc->localPort = localPort;
650  key.remotePort = assoc->remotePort = remotePort;
651 
652  // Do not update a sock pair that is already stored
653  for (auto& elem : sctpAssocMap) {
654  if (elem.second == assoc &&
655  elem.first.localAddr == key.localAddr &&
656  elem.first.remoteAddr == key.remoteAddr &&
657  elem.first.localPort == key.localPort
658  && elem.first.remotePort == key.remotePort)
659  return;
660  }
661 
662  for (auto i = sctpAssocMap.begin(); i != sctpAssocMap.end(); i++) {
663  if (i->second == assoc) {
664  sctpAssocMap.erase(i);
665  break;
666  }
667  }
668 
669  EV_INFO << "updateSockPair assoc=" << assoc->assocId << " localAddr=" << key.localAddr << " remoteAddr=" << key.remoteAddr << " localPort=" << key.localPort << " remotePort=" << remotePort << "\n";
670 
671  sctpAssocMap[key] = assoc;
672  sizeAssocMap = sctpAssocMap.size();
673  EV_DEBUG << "assoc inserted in sctpAssocMap\n";
675 }

Referenced by addForkedAssociation(), inet::sctp::SctpAssociation::process_ASSOCIATE(), inet::sctp::SctpAssociation::process_OPEN_PASSIVE(), and inet::sctp::SctpAssociation::processInitArrived().

Member Data Documentation

◆ addIP

bool inet::sctp::Sctp::addIP

◆ assocList

◆ assocStatMap

AssocStatMap inet::sctp::Sctp::assocStatMap

Referenced by inet::sctp::SctpAssociation::addAuthChunkIfNecessary(), inet::sctp::SctpAssociation::createForwardTsnChunk(), inet::sctp::SctpAssociation::createSack(), finish(), inet::sctp::SctpAssociation::makeRoomForTsn(), inet::sctp::SctpAssociation::pathStatusIndication(), inet::sctp::SctpAssociation::process_RCV_Message(), inet::sctp::SctpAssociation::process_SEND(), inet::sctp::SctpAssociation::process_TIMEOUT_RTX(), inet::sctp::SctpAssociation::processAddInAndOutResetRequestArrived(), inet::sctp::SctpAssociation::processAsconfArrived(), inet::sctp::SctpAssociation::processDataArrived(), inet::sctp::SctpAssociation::processOutAndResponseArrived(), inet::sctp::SctpAssociation::processResetResponseArrived(), inet::sctp::SctpAssociation::processTimer(), inet::sctp::SctpAssociation::pushUlp(), removeAssociation(), inet::sctp::SctpAssociation::retransmitAsconf(), inet::sctp::SctpAssociation::retransmitCookieEcho(), inet::sctp::SctpAssociation::sendAbort(), inet::sctp::SctpAssociation::sendAddOutgoingStreamsRequest(), inet::sctp::SctpAssociation::sendAsconf(), inet::sctp::SctpAssociation::sendAsconfAck(), inet::sctp::SctpAssociation::sendCookieAck(), inet::sctp::SctpAssociation::sendCookieEcho(), inet::sctp::SctpAssociation::sendHeartbeat(), inet::sctp::SctpAssociation::sendHeartbeatAck(), inet::sctp::SctpAssociation::sendInvalidStreamError(), inet::sctp::SctpAssociation::sendOnPath(), inet::sctp::SctpAssociation::sendOutgoingRequestAndResponse(), inet::sctp::SctpAssociation::sendSack(), inet::sctp::SctpAssociation::sendShutdown(), inet::sctp::SctpAssociation::sendStreamResetRequest(), inet::sctp::SctpAssociation::stateEntered(), and ~Sctp().

◆ auth

◆ crcMode

◆ ift

ModuleRefByPar<IInterfaceTable> inet::sctp::Sctp::ift
protected

Referenced by handleMessage(), and initialize().

◆ interfaceId

int inet::sctp::Sctp::interfaceId = -1

◆ nextEphemeralPort

uint16_t inet::sctp::Sctp::nextEphemeralPort
protected

Referenced by getEphemeralPort(), and initialize().

◆ numGapReports

uint32_t inet::sctp::Sctp::numGapReports

◆ numPacketsDropped

uint32_t inet::sctp::Sctp::numPacketsDropped

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

◆ numPacketsReceived

uint32_t inet::sctp::Sctp::numPacketsReceived

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

◆ numPktDropReports

uint64_t inet::sctp::Sctp::numPktDropReports

◆ pktdrop

◆ rt

ModuleRefByPar<IRoutingTable> inet::sctp::Sctp::rt
protected

Referenced by handleMessage(), and initialize().

◆ sackNow

◆ sctpAppAssocMap

◆ sctpAssocMap

◆ sctpVTagMap

◆ sizeAssocMap

◆ socketOptions

SocketOptions* inet::sctp::Sctp::socketOptions

Referenced by finish(), and handleMessage().

◆ testTimeout

simtime_t inet::sctp::Sctp::testTimeout

◆ udpSocket

UdpSocket inet::sctp::Sctp::udpSocket

Referenced by bindPortForUDP().

◆ udpSockId

int inet::sctp::Sctp::udpSockId

Referenced by bindPortForUDP().


The documentation for this class was generated from the following files:
inet::UdpSocket::setOutputGate
void setOutputGate(cGate *toUdp)
Sets the gate on which to send to UDP.
Definition: UdpSocket.h:117
inet::sctp::SCTP_S_SHUTDOWN_PENDING
@ SCTP_S_SHUTDOWN_PENDING
Definition: SctpAssociation.h:51
inet::SCTP_I_SENDSOCKETOPTIONS
@ SCTP_I_SENDSOCKETOPTIONS
Definition: SctpCommand_m.h:217
inet::SocketOptions::hbInterval
double hbInterval
Definition: SctpSocket.h:37
inet::sctp::Sctp::numPktDropReports
uint64_t numPktDropReports
Definition: Sctp.h:204
inet::sctp::Sctp::udpSockId
int udpSockId
Definition: Sctp.h:172
inet::sctp::SCTP_S_ESTABLISHED
@ SCTP_S_ESTABLISHED
Definition: SctpAssociation.h:50
inet::sctp::Sctp::udpSocket
UdpSocket udpSocket
Definition: Sctp.h:171
protocol
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down protocol
Definition: IUdp-gates.txt:25
inet::sctp::Sctp::sizeAssocMap
int32_t sizeAssocMap
Definition: Sctp.h:180
inet::sctp::SCTP_S_SHUTDOWN_RECEIVED
@ SCTP_S_SHUTDOWN_RECEIVED
Definition: SctpAssociation.h:53
inet::sctp::Sctp::printVTagMap
void printVTagMap()
Definition: Sctp.cc:54
inet::sctp::Sctp::testTimeout
simtime_t testTimeout
Definition: Sctp.h:196
inet::sctp::Sctp::numPacketsReceived
uint32_t numPacketsReceived
Definition: Sctp.h:198
inet::SocketOptions::fragPoint
int fragPoint
Definition: SctpSocket.h:33
inet::sctp::Sctp::printInfoAssocMap
void printInfoAssocMap()
Definition: Sctp.cc:37
inet::sctp::Sctp::sctpAssocMap
SctpAssocMap sctpAssocMap
Definition: Sctp.h:168
inet::sctp::Sctp::sendAbortFromMain
void sendAbortFromMain(Ptr< SctpHeader > &sctpMsg, L3Address fromAddr, L3Address toAddr)
Definition: Sctp.cc:373
inet::CRC_COMPUTED
@ CRC_COMPUTED
Definition: CrcMode_m.h:59
inet::SocketOptions::assocMaxRtx
int assocMaxRtx
Definition: SctpSocket.h:38
DispatchProtocolReq
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down DispatchProtocolReq
Definition: IUdp-gates.txt:25
L3AddressInd
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd L3AddressInd
Definition: IUdp-gates.txt:20
inet::SctpSocket::getNewAssocId
static int32_t getNewAssocId()
Generates a new integer, to be used as assocId.
Definition: SctpSocket.h:144
inet::find
std::vector< T >::iterator find(std::vector< T > &v, const Tk &a)
Definition: stlutils.h:44
inet::SocketOptions::maxInitRetransTimeout
int maxInitRetransTimeout
Definition: SctpSocket.h:26
inet::parseCrcMode
CrcMode parseCrcMode(const char *crcModeString, bool allowDisable)
Definition: CrcMode.cc:14
inet::sctp::ASCONF
@ ASCONF
Definition: SctpAssociation.h:121
SCTP_TIMEOUT_INIT_REXMIT_MAX
#define SCTP_TIMEOUT_INIT_REXMIT_MAX
Definition: SctpAssociation.h:238
inet::sctp::Sctp::assocStatMap
AssocStatMap assocStatMap
Definition: Sctp.h:160
inet::sctp::ABORT
@ ABORT
Definition: SctpAssociation.h:108
inet::registerService
void registerService(const Protocol &protocol, cGate *gate, ServicePrimitive servicePrimitive)
Registers a service primitive (SDU processing) at the given gate.
Definition: IProtocolRegistrationListener.cc:14
inet::sctp::Sctp::ift
ModuleRefByPar< IInterfaceTable > ift
Definition: Sctp.h:178
SCTP_UDP_PORT
#define SCTP_UDP_PORT
Definition: Sctp.h:31
PacketProtocolTag
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down PacketProtocolTag
Definition: IUdp-gates.txt:25
inet::sctp::Sctp::findAssocForMessage
SctpAssociation * findAssocForMessage(L3Address srcAddr, L3Address destAddr, uint32_t srcPort, uint32_t destPort, bool findListen)
Definition: Sctp.cc:562
inet::sctp::Sctp::interfaceId
int interfaceId
Definition: Sctp.h:205
inet::sctp::SCTP_S_SHUTDOWN_SENT
@ SCTP_S_SHUTDOWN_SENT
Definition: SctpAssociation.h:52
inet::sctp::ASCONF_ACK
@ ASCONF_ACK
Definition: SctpAssociation.h:117
SCTP_COMMON_HEADER
#define SCTP_COMMON_HEADER
Definition: SctpAssociation.h:203
inet::units::units::B
intscale< b, 1, 8 > B
Definition: Units.h:1168
inet::sctp::Sctp::nextEphemeralPort
uint16_t nextEphemeralPort
Definition: Sctp.h:182
inet::SocketOptions::nagle
int nagle
Definition: SctpSocket.h:34
inet::sctp::Sctp::crcMode
CrcMode crcMode
Definition: Sctp.h:206
inet::sctp::Sctp::collectSocketOptions
SocketOptions * collectSocketOptions()
Getter and Setter for the socket options.
Definition: Sctp.cc:353
inet::sctp::SHUTDOWN_ACK
@ SHUTDOWN_ACK
Definition: SctpAssociation.h:110
inet::SCTP_C_GETSOCKETOPTIONS
@ SCTP_C_GETSOCKETOPTIONS
Definition: SctpCommand_m.h:150
inet::sctp::INIT
@ INIT
Definition: SctpAssociation.h:103
inet::insertTransportProtocolHeader
void insertTransportProtocolHeader(Packet *packet, const Protocol &protocol, const Ptr< TransportHeaderBase > &header)
Definition: L4Tools.cc:77
inet::SocketOptions::rtoMin
double rtoMin
Definition: SctpSocket.h:28
inet::INITSTAGE_TRANSPORT_LAYER
INET_API InitStage INITSTAGE_TRANSPORT_LAYER
Initialization of transport-layer protocols.
inet::SocketOptions::pathMaxRetrans
int pathMaxRetrans
Definition: SctpSocket.h:36
inet::sctp::Sctp::socketOptions
SocketOptions * socketOptions
Definition: Sctp.h:174
inet::INITSTAGE_LOCAL
INET_API InitStage INITSTAGE_LOCAL
Initialization of local state that don't use or affect other modules includes:
inet::sctp::SCTP_S_COOKIE_ECHOED
@ SCTP_S_COOKIE_ECHOED
Definition: SctpAssociation.h:49
inet::sctp::Sctp::sctpAppAssocMap
SctpAppAssocMap sctpAppAssocMap
Definition: Sctp.h:167
inet::units::values::b
value< int64_t, units::b > b
Definition: Units.h:1241
inet::sctp::Sctp::removeAssociation
void removeAssociation(SctpAssociation *assoc)
Definition: Sctp.cc:846
inet::sctp::Sctp::findAssocForFd
int32_t findAssocForFd(int32_t fd)
Definition: Sctp.cc:623
NUM_INIT_STAGES
#define NUM_INIT_STAGES
Definition: InitStageRegistry.h:73
inet::sctp::Sctp::sctpVTagMap
SctpVTagMap sctpVTagMap
Definition: Sctp.h:162
SCTP_ABORT_CHUNK_LENGTH
#define SCTP_ABORT_CHUNK_LENGTH
Definition: SctpAssociation.h:209
inet::SocketOptions::sackPeriod
double sackPeriod
Definition: SctpSocket.h:31
inet::sctp::SCTP_S_SHUTDOWN_ACK_SENT
@ SCTP_S_SHUTDOWN_ACK_SENT
Definition: SctpAssociation.h:54
inet::sctp::SCTP_S_COOKIE_WAIT
@ SCTP_S_COOKIE_WAIT
Definition: SctpAssociation.h:48
inet::sctp::Sctp::findAssocForApp
SctpAssociation * findAssocForApp(int32_t appGateIndex, int32_t assocId)
Definition: Sctp.cc:613
inet::SocketOptions::maxInitRetrans
int maxInitRetrans
Definition: SctpSocket.h:25
inet::sctp::ERRORTYPE
@ ERRORTYPE
Definition: SctpAssociation.h:111
inet::SocketOptions::sackFrequency
int sackFrequency
Definition: SctpSocket.h:30
inet::sctp::Sctp::auth
bool auth
Definition: Sctp.h:200
inet::sctp::SCTP_S_CLOSED
@ SCTP_S_CLOSED
Definition: SctpAssociation.h:47
inet::L3Address::IPv6
@ IPv6
Definition: L3Address.h:36
inet::SocketOptions::enableHeartbeats
bool enableHeartbeats
Definition: SctpSocket.h:35
inet::sctp::Sctp::findAssocWithVTag
SctpAssociation * findAssocWithVTag(uint32_t peerVTag, uint32_t remotePort, uint32_t localPort)
Definition: Sctp.cc:530
inet::Protocol::sctp
static const Protocol sctp
Definition: Protocol.h:108
inet::sctp::Sctp::pktdrop
bool pktdrop
Definition: Sctp.h:202
tags
* tags
Definition: IUdp-gates.txt:3
inet::sctp::Sctp::sackNow
bool sackNow
Definition: Sctp.h:203
inet::sctp::Sctp::getAssoc
SctpAssociation * getAssoc(int32_t assocId)
Definition: Sctp.cc:968
inet::sctp::Sctp::updateSockPair
void updateSockPair(SctpAssociation *assoc, L3Address localAddr, L3Address remoteAddr, int32_t localPort, int32_t remotePort)
To be called from SctpAssociation when socket pair changes.
Definition: Sctp.cc:642
inet::sctp::Sctp::findAssocForInitAck
SctpAssociation * findAssocForInitAck(SctpInitAckChunk *initack, L3Address srcAddr, L3Address destAddr, uint32_t srcPort, uint32_t destPort, bool findListen)
Definition: Sctp.cc:547
inet::SocketOptions::maxBurst
int maxBurst
Definition: SctpSocket.h:32
inet::sctp::Sctp::numPacketsDropped
uint32_t numPacketsDropped
Definition: Sctp.h:199
inet::sctp::Sctp::assocList
std::list< SctpAssociation * > assocList
Definition: Sctp.h:169
inet::sctp::INIT_ACK
@ INIT_ACK
Definition: SctpAssociation.h:104
SCTP_SHUTDOWN_ACK_LENGTH
#define SCTP_SHUTDOWN_ACK_LENGTH
Definition: SctpAssociation.h:213
inet::registerProtocol
void registerProtocol(const Protocol &protocol, cGate *gate, ServicePrimitive servicePrimitive)
Registers a protocol primitive (PDU processing) at the given gate.
Definition: IProtocolRegistrationListener.cc:83
inet::UdpSocket::getSocketId
int getSocketId() const override
Returns the internal socket Id.
Definition: UdpSocket.h:108
inet::sctp::Sctp::send_to_ip
virtual void send_to_ip(Packet *msg)
Definition: Sctp.cc:441
inet::sctp::SHUTDOWN_COMPLETE
@ SHUTDOWN_COMPLETE
Definition: SctpAssociation.h:114
inet::sctp::Sctp::sendShutdownCompleteFromMain
void sendShutdownCompleteFromMain(Ptr< SctpHeader > &sctpMsg, L3Address fromAddr, L3Address toAddr)
Definition: Sctp.cc:410
inet::SocketOptions::rtoMax
double rtoMax
Definition: SctpSocket.h:29
inet::sctp::Sctp::rt
ModuleRefByPar< IRoutingTable > rt
Definition: Sctp.h:177
inet::SocketOptions::rtoInitial
double rtoInitial
Definition: SctpSocket.h:27