INET Framework for OMNeT++/OMNEST
inet::Rstp Class Reference

Implements the Rapid Spanning Tree Protocol. More...

#include <Rstp.h>

Inheritance diagram for inet::Rstp:
inet::StpBase inet::OperationalBase inet::OperationalMixin< cSimpleModule > inet::ILifecycle

Public Member Functions

 Rstp ()
 
virtual ~Rstp ()
 
virtual int numInitStages () const override
 
virtual void receiveSignal (cComponent *source, simsignal_t signalID, cObject *obj, cObject *details) override
 
- Public Member Functions inherited from inet::StpBase
 StpBase ()
 
virtual bool isInitializeStage (int stage) const override
 
virtual bool isModuleStartStage (int stage) const override
 
virtual bool isModuleStopStage (int stage) const override
 
virtual void handleStartOperation (LifecycleOperation *operation) override
 
virtual void handleStopOperation (LifecycleOperation *operation) override
 
virtual void handleCrashOperation (LifecycleOperation *operation) override
 
- Public Member Functions inherited from inet::OperationalMixin< cSimpleModule >
virtual ~OperationalMixin ()
 }@ More...
 
- Public Member Functions inherited from inet::ILifecycle
virtual ~ILifecycle ()
 

Protected Types

enum  SelfKinds { SELF_HELLOTIME = 1, SELF_UPGRADE }
 
enum  CompareResult {
  WORSE_PORT = -4, WORSE_SRC = -3, WORSE_RPC = -2, WORSE_ROOT = -1,
  SIMILAR = 0, BETTER_ROOT = 1, BETTER_RPC = 2, BETTER_SRC = 3,
  BETTER_PORT = 4
}
 
- Protected Types inherited from inet::OperationalMixin< cSimpleModule >
enum  State
 

Protected Member Functions

virtual void initialize (int stage) override
 
virtual void finish () override
 
virtual void initInterfacedata (unsigned int portNum)
 
virtual void start () override
 
virtual void stop () override
 
virtual void initPorts ()
 initialize RSTP dynamic information More...
 
virtual int getBestAlternate ()
 Gets the best alternate port. More...
 
virtual void sendBPDUs ()
 Sends BPDUs through all ports, if they are required. More...
 
virtual void sendBPDU (int interfaceId)
 Sends BPDU through a port. More...
 
virtual void handleMessageWhenUp (cMessage *msg) override
 General processing. More...
 
virtual void handleIncomingFrame (Packet *packet)
 BPDU processing. More...
 
virtual void processBPDU (const Ptr< const BpduCfg > &frame, unsigned int arrivalInterfaceId)
 
virtual bool processBetterSource (const Ptr< const BpduCfg > &frame, unsigned int arrivalInterfaceId)
 
virtual bool processSameSource (const Ptr< const BpduCfg > &frame, unsigned int arrivalInterfaceId)
 
virtual void printState ()
 Prints current data base info. More...
 
virtual void updateInterfacedata (const Ptr< const BpduCfg > &frame, unsigned int interfaceId)
 Update Interfacedata with the content of the BPDU frame. More...
 
virtual CompareResult contestInterfacedata (const Ptr< const BpduCfg > &msg, unsigned int interfaceId)
 Compares the BPDU frame with the BPDU this module would send through that port. More...
 
virtual CompareResult contestInterfacedata (unsigned int interfaceId)
 Compares the port's best BPDU with the BPDU this module would send through that port. More...
 
virtual CompareResult compareInterfacedata (unsigned int interfaceId, const Ptr< const BpduCfg > &msg, int linkCost)
 Compares a port's best BPDU with a BPDU frame. More...
 
virtual CompareResult compareRSTPData (int rootPriority1, int rootPriority2, MacAddress rootAddress1, MacAddress rootAddress2, int rootPathCost1, int rootPathCost2, int bridgePriority1, int bridgePriority2, MacAddress bridgeAddress1, MacAddress bridgeAddress2, int portPriority1, int portPriority2, int portNum1, int portNum2)
 Compares two RSTP data. More...
 
virtual void sendTCNtoRoot ()
 If root TCWhile has not expired, sends a BPDU to the Root with TCFlag=true. More...
 
virtual void handleHelloTime (cMessage *)
 HelloTime event handling. More...
 
virtual void handleUpgrade (cMessage *)
 Upgrade event handling. More...
 
virtual void checkTC (const Ptr< const BpduCfg > &frame, int arrivalInterfaceId)
 Checks the frame TC flag. More...
 
virtual void handleBackup (const Ptr< const BpduCfg > &frame, unsigned int arrivalInterfaceId)
 Handles the switch to backup in one of the ports. More...
 
virtual void scheduleNextUpgrade ()
 schedule next upgrade self-message More...
 
virtual void flushOtherPorts (unsigned int interfaceId)
 flush all port expect one More...
 
- Protected Member Functions inherited from inet::StpBase
virtual void colorLink (NetworkInterface *ie, bool forwarding) const
 Adds effects to be represented by Tkenv. More...
 
virtual void refreshDisplay () const override
 Adds effects to be represented by Tkenv. More...
 
virtual int getRootInterfaceId () const
 Obtains the root interface ID. More...
 
const Ieee8021dInterfaceDatagetPortInterfaceData (unsigned int interfaceId) const
 Gets Ieee8021dInterfaceData for interface ID. More...
 
Ieee8021dInterfaceDatagetPortInterfaceDataForUpdate (unsigned int interfaceId)
 
NetworkInterfacegetPortNetworkInterface (unsigned int interfaceId) const
 Gets NetworkInterface for interface ID. More...
 
virtual NetworkInterfacechooseInterface ()
 
- Protected Member Functions inherited from inet::OperationalMixin< cSimpleModule >
virtual int numInitStages () const override
 
virtual void refreshDisplay () const override
 
virtual void handleMessage (cMessage *msg) override
 
virtual void handleMessageWhenDown (cMessage *msg)
 
virtual bool handleOperationStage (LifecycleOperation *operation, IDoneCallback *doneCallback) override
 Perform one stage of a lifecycle operation. More...
 
virtual State getInitialOperationalState () const
 Returns initial operational state: OPERATING or NOT_OPERATING. More...
 
virtual void handleActiveOperationTimeout (cMessage *message)
 
virtual bool isUp () const
 utility functions More...
 
virtual bool isDown () const
 
virtual void setOperationalState (State newState)
 
virtual void scheduleOperationTimeout (simtime_t timeout)
 
virtual void setupActiveOperation (LifecycleOperation *operation, IDoneCallback *doneCallback, State)
 
virtual void delayActiveOperationFinish (simtime_t timeout)
 
virtual void startActiveOperationExtraTime (simtime_t delay=SIMTIME_ZERO)
 
virtual void startActiveOperationExtraTimeOrFinish (simtime_t extraTime)
 
virtual void finishActiveOperation ()
 

Protected Attributes

simtime_t migrateTime
 
simtime_t tcWhileTime
 
bool autoEdge = false
 
cMessage * helloTimer = nullptr
 
cMessage * upgradeTimer = nullptr
 
- Protected Attributes inherited from inet::StpBase
bool visualize = false
 
unsigned int numPorts = 0
 
unsigned int bridgePriority = 0
 
MacAddress bridgeAddress
 
simtime_t maxAge
 
simtime_t helloTime
 
simtime_t forwardDelay
 
opp_component_ptr< cModule > switchModule
 
ModuleRefByPar< IMacForwardingTablemacTable
 
ModuleRefByPar< IInterfaceTableifTable
 
opp_component_ptr< NetworkInterfaceie
 
- Protected Attributes inherited from inet::OperationalMixin< cSimpleModule >
State operationalState
 
simtime_t lastChange
 
Operation activeOperation
 
cMessage * activeOperationTimeout
 
cMessage * activeOperationExtraTimer
 

Detailed Description

Implements the Rapid Spanning Tree Protocol.

See the NED file for details.

Member Enumeration Documentation

◆ CompareResult

enum inet::Rstp::CompareResult
protected
Enumerator
WORSE_PORT 
WORSE_SRC 
WORSE_RPC 
WORSE_ROOT 
SIMILAR 
BETTER_ROOT 
BETTER_RPC 
BETTER_SRC 
BETTER_PORT 
31  {
32  WORSE_PORT = -4, WORSE_SRC = -3, WORSE_RPC = -2, WORSE_ROOT = -1, SIMILAR = 0,
33  BETTER_ROOT = 1, BETTER_RPC = 2, BETTER_SRC = 3, BETTER_PORT = 4
34  };

◆ SelfKinds

enum inet::Rstp::SelfKinds
protected
Enumerator
SELF_HELLOTIME 
SELF_UPGRADE 

Constructor & Destructor Documentation

◆ Rstp()

inet::Rstp::Rstp ( )
23 {
24 }

◆ ~Rstp()

inet::Rstp::~Rstp ( )
virtual
27 {
28  cancelAndDelete(helloTimer);
29  cancelAndDelete(upgradeTimer);
30 }

Member Function Documentation

◆ checkTC()

void inet::Rstp::checkTC ( const Ptr< const BpduCfg > &  frame,
int  arrivalInterfaceId 
)
protectedvirtual

Checks the frame TC flag.

Sets TCWhile if the port was forwarding and the flag is true.

210 {
211  const Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalInterfaceId);
212  if ((frame->getTcFlag() == true) && (port->getState() == Ieee8021dInterfaceData::FORWARDING)) {
213  EV_DETAIL << "TCN received" << endl;
214  findContainingNode(this)->bubble("TCN received");
215  for (unsigned int i = 0; i < numPorts; i++) {
216  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
217  if (interfaceId != arrivalInterfaceId) {
218  auto port2 = getPortInterfaceDataForUpdate(interfaceId);
219  // flushing other ports
220  // TCN over other ports
221  macTable->removeForwardingInterface(interfaceId);
222  port2->setTCWhile(simTime() + tcWhileTime);
223  }
224  }
225  }
226 }

Referenced by handleIncomingFrame().

◆ compareInterfacedata()

Rstp::CompareResult inet::Rstp::compareInterfacedata ( unsigned int  interfaceId,
const Ptr< const BpduCfg > &  msg,
int  linkCost 
)
protectedvirtual

Compares a port's best BPDU with a BPDU frame.

Returns
(<0 if vector better than frame)
778 {
779  const Ieee8021dInterfaceData *ifd = getPortInterfaceData(interfaceId);
780 
781  return compareRSTPData(ifd->getRootPriority(), msg->getRootPriority(),
782  ifd->getRootAddress(), msg->getRootAddress(),
783  ifd->getRootPathCost(), msg->getRootPathCost() + linkCost,
784  ifd->getBridgePriority(), msg->getBridgePriority(),
785  ifd->getBridgeAddress(), msg->getBridgeAddress(),
786  ifd->getPortPriority(), msg->getPortPriority(),
787  ifd->getPortNum(), msg->getPortNum());
788 }

Referenced by processBetterSource(), processBPDU(), and processSameSource().

◆ compareRSTPData()

Rstp::CompareResult inet::Rstp::compareRSTPData ( int  rootPriority1,
int  rootPriority2,
MacAddress  rootAddress1,
MacAddress  rootAddress2,
int  rootPathCost1,
int  rootPathCost2,
int  bridgePriority1,
int  bridgePriority2,
MacAddress  bridgeAddress1,
MacAddress  bridgeAddress2,
int  portPriority1,
int  portPriority2,
int  portNum1,
int  portNum2 
)
protectedvirtual

Compares two RSTP data.

Returns
(<0 if vector better than frame)
797 {
798  if (rootPriority1 != rootPriority2)
799  return (rootPriority1 < rootPriority2) ? WORSE_ROOT : BETTER_ROOT;
800 
801  int c = rootAddress1.compareTo(rootAddress2);
802  if (c != 0)
803  return (c < 0) ? WORSE_ROOT : BETTER_ROOT;
804 
805  if (rootPathCost1 != rootPathCost2)
806  return (rootPathCost1 < rootPathCost2) ? WORSE_RPC : BETTER_RPC;
807 
808  if (bridgePriority1 != bridgePriority2)
809  return (bridgePriority1 < bridgePriority2) ? WORSE_SRC : BETTER_SRC;
810 
811  c = bridgeAddress1.compareTo(bridgeAddress2);
812  if (c != 0)
813  return (c < 0) ? WORSE_SRC : BETTER_SRC;
814 
815  if (portPriority1 != portPriority2)
816  return (portPriority1 < portPriority2) ? WORSE_PORT : BETTER_PORT;
817 
818  if (portNum1 != portNum2)
819  return (portNum1 < portNum2) ? WORSE_PORT : BETTER_PORT;
820 
821  return SIMILAR;
822 }

Referenced by compareInterfacedata(), contestInterfacedata(), and getBestAlternate().

◆ contestInterfacedata() [1/2]

Rstp::CompareResult inet::Rstp::contestInterfacedata ( const Ptr< const BpduCfg > &  msg,
unsigned int  interfaceId 
)
protectedvirtual

Compares the BPDU frame with the BPDU this module would send through that port.

Returns
(<0 if the root BPDU is better than BPDU)
763 {
764  int r = getRootInterfaceId();
765  const Ieee8021dInterfaceData *rootPort = getPortInterfaceData(r);
766  const Ieee8021dInterfaceData *ifd = getPortInterfaceData(interfaceId);
767 
768  return compareRSTPData(rootPort->getRootPriority(), msg->getRootPriority(),
769  rootPort->getRootAddress(), msg->getRootAddress(),
770  rootPort->getRootPathCost(), msg->getRootPathCost(),
771  bridgePriority, msg->getBridgePriority(),
772  bridgeAddress, msg->getBridgeAddress(),
773  ifd->getPortPriority(), msg->getPortPriority(),
774  interfaceId, msg->getPortNum());
775 }

Referenced by processBetterSource(), and processSameSource().

◆ contestInterfacedata() [2/2]

Rstp::CompareResult inet::Rstp::contestInterfacedata ( unsigned int  interfaceId)
protectedvirtual

Compares the port's best BPDU with the BPDU this module would send through that port.

Returns
(<0 if the root BPDU is better than port's best BPDU)
748 {
749  int r = getRootInterfaceId();
750  const Ieee8021dInterfaceData *rootPort = getPortInterfaceData(r);
751  const Ieee8021dInterfaceData *ifd = getPortInterfaceData(portNum);
752 
753  return compareRSTPData(rootPort->getRootPriority(), ifd->getRootPriority(),
754  rootPort->getRootAddress(), ifd->getRootAddress(),
755  rootPort->getRootPathCost() + ifd->getLinkCost(), ifd->getRootPathCost(),
756  bridgePriority, ifd->getBridgePriority(),
757  bridgeAddress, ifd->getBridgeAddress(),
758  ifd->getPortPriority(), ifd->getPortPriority(),
759  portNum, ifd->getPortNum());
760 }

◆ finish()

virtual void inet::Rstp::finish ( )
inlineoverrideprotectedvirtual
52 {}

◆ flushOtherPorts()

void inet::Rstp::flushOtherPorts ( unsigned int  interfaceId)
protectedvirtual

flush all port expect one

853 {
854  for (unsigned int i = 0; i < numPorts; i++) {
855  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
856  auto iPort = getPortInterfaceDataForUpdate(interfaceId);
857  iPort->setTCWhile(simTime() + tcWhileTime);
858  if ((unsigned int)interfaceId != portId)
859  macTable->removeForwardingInterface(interfaceId);
860  }
861 }

Referenced by handleHelloTime(), handleUpgrade(), processBetterSource(), and processSameSource().

◆ getBestAlternate()

int inet::Rstp::getBestAlternate ( )
protectedvirtual

Gets the best alternate port.

Returns
Best alternate gate index
825 {
826  int candidate = -1; // index of the best alternate found
827  for (unsigned int j = 0; j < numPorts; j++) {
828  int interfaceId = ifTable->getInterface(j)->getInterfaceId();
829  const Ieee8021dInterfaceData *jPort = getPortInterfaceData(interfaceId);
830  if (jPort->getRole() == Ieee8021dInterfaceData::ALTERNATE) { // just from alternates, others are not updated
831  if (candidate < 0)
832  candidate = interfaceId;
833  else {
834  const Ieee8021dInterfaceData *candidatePort = getPortInterfaceData(candidate);
835  if (compareRSTPData(jPort->getRootPriority(), candidatePort->getRootPriority(),
836  jPort->getRootAddress(), candidatePort->getRootAddress(),
837  jPort->getRootPathCost(), candidatePort->getRootPathCost(),
838  jPort->getBridgePriority(), candidatePort->getBridgePriority(),
839  jPort->getBridgeAddress(), candidatePort->getBridgeAddress(),
840  jPort->getPortPriority(), candidatePort->getPortPriority(),
841  jPort->getPortNum(), candidatePort->getPortNum()) < 0)
842  {
843  // alternate better than the found one
844  candidate = interfaceId; // new candidate
845  }
846  }
847  }
848  }
849  return candidate;
850 }

Referenced by handleHelloTime(), and processSameSource().

◆ handleBackup()

void inet::Rstp::handleBackup ( const Ptr< const BpduCfg > &  frame,
unsigned int  arrivalInterfaceId 
)
protectedvirtual

Handles the switch to backup in one of the ports.

229 {
230  EV_DETAIL << "More than one port in the same LAN" << endl;
231  auto port = getPortInterfaceDataForUpdate(arrivalInterfaceId);
232  if ((frame->getPortPriority() < port->getPortPriority())
233  || ((frame->getPortPriority() == port->getPortPriority()) && (frame->getPortNum() < arrivalInterfaceId)))
234  {
235  // flushing arrival port
236  macTable->removeForwardingInterface(arrivalInterfaceId);
237  port->setRole(Ieee8021dInterfaceData::BACKUP);
238  port->setState(Ieee8021dInterfaceData::DISCARDING);
239  port->setLostBPDU(0);
240  EV_DETAIL << "Setting port " << arrivalInterfaceId << "to backup" << endl;
241  }
242  else if (frame->getPortPriority() > port->getPortPriority()
243  || (frame->getPortPriority() == port->getPortPriority() && frame->getPortNum() > arrivalInterfaceId))
244  {
245  auto port2 = getPortInterfaceDataForUpdate(frame->getPortNum());
246  // flushing sender port
247  macTable->removeForwardingInterface(frame->getPortNum()); // portNum is sender port number, it is not arrival port
248  port2->setRole(Ieee8021dInterfaceData::BACKUP);
249  port2->setState(Ieee8021dInterfaceData::DISCARDING);
250  port2->setLostBPDU(0);
251  EV_DETAIL << "Setting port " << frame->getPortNum() << "to backup" << endl;
252  }
253  else {
254  auto port2 = getPortInterfaceDataForUpdate(frame->getPortNum());
255  // unavoidable loop, received its own message at the same port
256  // switch to disabled
257  EV_DETAIL << "Unavoidable loop. Received its own message at the same port. Setting port " << frame->getPortNum() << " to disabled." << endl;
258  // flushing that port
259  macTable->removeForwardingInterface(frame->getPortNum()); // portNum is sender port number, it is not arrival port
260  port2->setRole(Ieee8021dInterfaceData::DISABLED);
261  port2->setState(Ieee8021dInterfaceData::DISCARDING);
262  }
263 }

Referenced by handleIncomingFrame().

◆ handleHelloTime()

void inet::Rstp::handleHelloTime ( cMessage *  msg)
protectedvirtual

HelloTime event handling.

143 {
144  EV_DETAIL << "Hello time." << endl;
145  for (unsigned int i = 0; i < numPorts; i++) {
146  // sends hello through all active (learning, forwarding or not assigned) ports
147  // increments LostBPDU just from ROOT, ALTERNATE and BACKUP
148  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
149  auto iPort = getPortInterfaceDataForUpdate(interfaceId);
150  if (!iPort->isEdge()
151  && (iPort->getRole() == Ieee8021dInterfaceData::ROOT
152  || iPort->getRole() == Ieee8021dInterfaceData::ALTERNATE
153  || iPort->getRole() == Ieee8021dInterfaceData::BACKUP))
154  {
155  iPort->setLostBPDU(iPort->getLostBPDU() + 1);
156  if (iPort->getLostBPDU() > 3) { // 3 HelloTime without the best BPDU.
157  EV_DETAIL << "3 HelloTime without the best BPDU" << endl;
158  // starts contest
159  if (iPort->getRole() == Ieee8021dInterfaceData::ROOT) {
160  // looking for the best ALTERNATE port
161  int candidate = getBestAlternate();
162  if (candidate != -1) {
163  // if an alternate gate has been found, switch to alternate
164  EV_DETAIL << "It was the root port. Alternate gate has been found. Setting port " << candidate << " to root. Setting current root port (port" << interfaceId << ") to designated." << endl;
165  // ALTERNATE->ROOT. DISCARDING->FORWARDING (immediately)
166  // old root gate goes to DESIGNATED and DISCARDING
167  // a new contest should be done to determine the new root path from this LAN
168  // updating root vector.
169  auto candidatePort = getPortInterfaceDataForUpdate(candidate);
170  iPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
171  iPort->setState(Ieee8021dInterfaceData::DISCARDING); // if there is not a better BPDU, that will become FORWARDING
172  iPort->setNextUpgrade(simTime() + forwardDelay);
174  initInterfacedata(interfaceId); // reset, then a new BPDU will be allowed to upgrade the best received info for this port
175  candidatePort->setRole(Ieee8021dInterfaceData::ROOT);
176  candidatePort->setState(Ieee8021dInterfaceData::FORWARDING);
177  candidatePort->setLostBPDU(0);
178  flushOtherPorts(candidate);
179  macTable->replaceForwardingInterface(interfaceId, candidate); // copy cache from old to new root
180  }
181  else {
182  // alternate not found, selects a new root
183  EV_DETAIL << "It was the root port. Alternate not found. Starts from beginning." << endl;
184  // initializing ports, start from the beginning
185  initPorts();
186  }
187  }
188  else if (iPort->getRole() == Ieee8021dInterfaceData::ALTERNATE
189  || iPort->getRole() == Ieee8021dInterfaceData::BACKUP)
190  {
191  EV_DETAIL << "Setting port " << interfaceId << " to designated." << endl;
192  // it should take care of this LAN, switching to designated
193  iPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
194  iPort->setState(Ieee8021dInterfaceData::DISCARDING); // a new content will start in case of another switch were in alternate
195  iPort->setNextUpgrade(simTime() + forwardDelay);
197  // if there is no problem, this will become forwarding in a few seconds
198  initInterfacedata(interfaceId);
199  }
200  iPort->setLostBPDU(0); // reseting lost bpdu counter after a change.
201  }
202  }
203  }
204  sendBPDUs(); // generating and sending new BPDUs
205  sendTCNtoRoot();
206  scheduleAfter(helloTime, msg); // programming next hello time
207 }

Referenced by handleMessageWhenUp().

◆ handleIncomingFrame()

void inet::Rstp::handleIncomingFrame ( Packet packet)
protectedvirtual

BPDU processing.

Updates port information. Handles port role changes.

266 {
267  const auto& frame = packet->peekAtFront<BpduCfg>();
268  // incoming BPDU handling
269  // checking message age
270  int arrivalInterfaceId = packet->getTag<InterfaceInd>()->getInterfaceId();
271  MacAddress src = packet->getTag<MacAddressInd>()->getSrcAddress();
272  EV_INFO << "BPDU received at port " << arrivalInterfaceId << "." << endl;
273  if (frame->getMessageAge() < maxAge) {
274  // checking TC
275  checkTC(frame, arrivalInterfaceId); // sets TCWhile if arrival port was FORWARDING
276  // checking possible backup
277  if (src.compareTo(bridgeAddress) == 0) // more than one port in the same LAN
278  handleBackup(frame, arrivalInterfaceId);
279  else
280  processBPDU(frame, arrivalInterfaceId);
281  }
282  else
283  EV_DETAIL << "Expired BPDU" << endl;
284  delete packet;
285 }

Referenced by handleMessageWhenUp().

◆ handleMessageWhenUp()

void inet::Rstp::handleMessageWhenUp ( cMessage *  msg)
overrideprotectedvirtual

General processing.

Implements inet::OperationalMixin< cSimpleModule >.

90 {
91  // it can receive BPDU or self messages
92  if (msg->isSelfMessage()) {
93  switch (msg->getKind()) {
94  case SELF_HELLOTIME:
95  handleHelloTime(msg);
96  break;
97 
98  case SELF_UPGRADE:
99  // designated ports state upgrading (discarding-->learning, learning-->forwarding)
100  handleUpgrade(msg);
101  break;
102 
103  default:
104  throw cRuntimeError("Unknown self message");
105  break;
106  }
107  }
108  else {
109  handleIncomingFrame(check_and_cast<Packet *>(msg)); // handling BPDU
110  }
111 }

◆ handleUpgrade()

void inet::Rstp::handleUpgrade ( cMessage *  msg)
protectedvirtual

Upgrade event handling.

114 {
115  for (unsigned int i = 0; i < numPorts; i++) {
116  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
117  auto iPort = getPortInterfaceDataForUpdate(interfaceId);
118  if (getPortNetworkInterface(interfaceId)->hasCarrier() && iPort->getNextUpgrade() == simTime()) {
119  if (iPort->getRole() == Ieee8021dInterfaceData::NOTASSIGNED) {
120  EV_DETAIL << "MigrateTime. Setting port " << interfaceId << "to designated." << endl;
121  iPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
122  iPort->setState(Ieee8021dInterfaceData::DISCARDING); // contest to become forwarding.
123  iPort->setNextUpgrade(simTime() + forwardDelay);
124  }
125  else if (iPort->getRole() == Ieee8021dInterfaceData::DESIGNATED) {
126  if (iPort->getState() == Ieee8021dInterfaceData::DISCARDING) {
127  EV_INFO << "UpgradeTime. Setting port " << interfaceId << " state to learning." << endl;
128  iPort->setState(Ieee8021dInterfaceData::LEARNING);
129  iPort->setNextUpgrade(simTime() + forwardDelay);
130  }
131  else if (iPort->getState() == Ieee8021dInterfaceData::LEARNING) {
132  EV_INFO << "UpgradeTime. Setting port " << interfaceId << " state to forwarding." << endl;
133  iPort->setState(Ieee8021dInterfaceData::FORWARDING);
134  flushOtherPorts(interfaceId);
135  }
136  }
137  }
138  }
140 }

Referenced by handleMessageWhenUp().

◆ initialize()

void inet::Rstp::initialize ( int  stage)
overrideprotectedvirtual

Reimplemented from inet::StpBase.

33 {
34  StpBase::initialize(stage);
35 
36  if (stage == INITSTAGE_LOCAL) {
37  autoEdge = par("autoEdge");
38  tcWhileTime = par("tcWhileTime");
39  migrateTime = par("migrateTime");
40  helloTimer = new cMessage("itshellotime", SELF_HELLOTIME);
41  upgradeTimer = new cMessage("upgrade", SELF_UPGRADE);
42  }
43  else if (stage == INITSTAGE_LINK_LAYER) {
44  registerProtocol(Protocol::stp, gate("relayOut"), gate("relayIn"));
45 
46  for (int i = 0; i < ifTable->getNumInterfaces(); i++) {
47  auto ie = ifTable->getInterface(i);
48  if (!ie->isLoopback() && ie->isWired() /* && ie->getProtocol() == &Protocol::ethernetMac */) { // TODO check protocol
49  ie->addMulticastMacAddress(MacAddress::STP_MULTICAST_ADDRESS);
50  }
51  }
52  }
53 }

◆ initInterfacedata()

void inet::Rstp::initInterfacedata ( unsigned int  portNum)
protectedvirtual
700 {
701  auto ifd = getPortInterfaceDataForUpdate(interfaceId);
702  ifd->setRootPriority(bridgePriority);
703  ifd->setRootAddress(bridgeAddress);
704  ifd->setRootPathCost(0);
705  ifd->setAge(0);
706  ifd->setBridgePriority(bridgePriority);
707  ifd->setBridgeAddress(bridgeAddress);
708  ifd->setPortPriority(-1);
709  ifd->setPortNum(-1);
710  ifd->setLostBPDU(0);
711 }

Referenced by handleHelloTime(), initPorts(), and processBetterSource().

◆ initPorts()

void inet::Rstp::initPorts ( )
protectedvirtual

initialize RSTP dynamic information

714 {
715  for (unsigned int j = 0; j < numPorts; j++) {
716  int interfaceId = ifTable->getInterface(j)->getInterfaceId();
717  auto jPort = getPortInterfaceDataForUpdate(interfaceId);
718  if (!jPort->isEdge()) {
719  jPort->setRole(Ieee8021dInterfaceData::NOTASSIGNED);
720  jPort->setState(Ieee8021dInterfaceData::DISCARDING);
721  jPort->setNextUpgrade(simTime() + migrateTime);
722  }
723  else {
724  jPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
725  jPort->setState(Ieee8021dInterfaceData::FORWARDING);
726  }
727  initInterfacedata(interfaceId);
728  macTable->removeForwardingInterface(interfaceId);
729  }
731 }

Referenced by handleHelloTime(), processSameSource(), and start().

◆ numInitStages()

virtual int inet::Rstp::numInitStages ( ) const
inlineoverridevirtual

Reimplemented from inet::StpBase.

47 { return NUM_INIT_STAGES; }

◆ printState()

void inet::Rstp::printState ( )
protectedvirtual

Prints current data base info.

667 {
668  // prints current database info
669  EV_DETAIL << "Switch " << findContainingNode(this)->getFullName() << " state:" << endl;
670  int rootIndex = getRootInterfaceId();
671  EV_DETAIL << " Priority: " << bridgePriority << endl;
672  EV_DETAIL << " Local MAC: " << bridgeAddress << endl;
673  if (rootIndex >= 0) {
674  const Ieee8021dInterfaceData *rootPort = getPortInterfaceData(rootIndex);
675  EV_DETAIL << " Root Priority: " << rootPort->getRootPriority() << endl;
676  EV_DETAIL << " Root Address: " << rootPort->getRootAddress().str() << endl;
677  EV_DETAIL << " Cost: " << rootPort->getRootPathCost() << endl;
678  EV_DETAIL << " Age: " << rootPort->getAge() << endl;
679  EV_DETAIL << " Bridge Priority: " << rootPort->getBridgePriority() << endl;
680  EV_DETAIL << " Bridge Address: " << rootPort->getBridgeAddress().str() << endl;
681  EV_DETAIL << " Src TxGate Priority: " << rootPort->getPortPriority() << endl;
682  EV_DETAIL << " Src TxGate: " << rootPort->getPortNum() << endl;
683  }
684  EV_DETAIL << "Port State/Role:" << endl;
685  for (unsigned int i = 0; i < numPorts; i++) {
686  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
687  const Ieee8021dInterfaceData *iPort = getPortInterfaceData(interfaceId);
688  EV_DETAIL << " " << i << ": " << iPort->getStateName() << "/" << iPort->getRoleName() << (iPort->isEdge() ? " (Client)" : "") << endl;
689  }
690  EV_DETAIL << "Per-port best sources, Root/Src:" << endl;
691  for (unsigned int i = 0; i < numPorts; i++) {
692  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
693  const Ieee8021dInterfaceData *iPort = getPortInterfaceData(interfaceId);
694  EV_DETAIL << " " << interfaceId << ": " << iPort->getRootAddress().str() << "/" << iPort->getBridgeAddress().str() << endl;
695  }
696  EV_DETAIL << endl;
697 }

◆ processBetterSource()

bool inet::Rstp::processBetterSource ( const Ptr< const BpduCfg > &  frame,
unsigned int  arrivalInterfaceId 
)
protectedvirtual
309 {
310  EV_DETAIL << "Better BPDU received than the current best for this port." << endl;
311  // update that port rstp info
312  updateInterfacedata(frame, arrivalInterfaceId);
313  auto arrivalPort = getPortInterfaceDataForUpdate(arrivalInterfaceId);
314  int r = getRootInterfaceId();
315  if (r == -1) {
316  EV_DETAIL << "There was no root. Setting the arrival port to root." << endl;
317  // there was no root
318  arrivalPort->setRole(Ieee8021dInterfaceData::ROOT);
319  arrivalPort->setState(Ieee8021dInterfaceData::FORWARDING);
320  arrivalPort->setLostBPDU(0);
321  flushOtherPorts(arrivalInterfaceId);
322  return true;
323  }
324  else {
325  auto rootPort = getPortInterfaceDataForUpdate(r);
326  // there was a Root -> challenge 2 (compare with the root)
327  int case2 = compareInterfacedata(r, frame, arrivalPort->getLinkCost()); // comparing with root port's BPDU
328  int case3 = 0;
329 
330  switch (case2) {
331  case SIMILAR: // double link to the same port of the root source -> Tie breaking (better local port first)
332  EV_DETAIL << "Double link to the same port of the root source." << endl;
333  if (rootPort->getPortPriority() < arrivalPort->getPortPriority()
334  || (rootPort->getPortPriority() == arrivalPort->getPortPriority() && (unsigned int)r < arrivalInterfaceId))
335  {
336  // flushing that port
337  EV_DETAIL << "The current root has better local port. Setting the arrival port to alternate." << endl;
338  macTable->removeForwardingInterface(arrivalInterfaceId);
339  arrivalPort->setRole(Ieee8021dInterfaceData::ALTERNATE);
340  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
341  arrivalPort->setLostBPDU(0);
342  }
343  else {
344  if (arrivalPort->getState() != Ieee8021dInterfaceData::FORWARDING)
345  flushOtherPorts(arrivalInterfaceId);
346  else
347  macTable->removeForwardingInterface(r); // flushing r, needed in case arrival were previously FORWARDING
348  EV_DETAIL << "This has better local port. Setting the arrival port to root. Setting current root port (port " << r << ") to alternate." << endl;
349  rootPort->setRole(Ieee8021dInterfaceData::ALTERNATE);
350  rootPort->setState(Ieee8021dInterfaceData::DISCARDING); // comes from root, preserve lostBPDU
351  arrivalPort->setRole(Ieee8021dInterfaceData::ROOT);
352  arrivalPort->setState(Ieee8021dInterfaceData::FORWARDING);
353  arrivalPort->setLostBPDU(0);
354  macTable->replaceForwardingInterface(r, arrivalInterfaceId); // copy cache from old to new root
355  // the change does not deserve flooding
356  }
357  break;
358 
359  case BETTER_ROOT: // new port rstp info is better than the root in another gate -> root change
360  EV_DETAIL << "Better root received than the current root. Setting the arrival port to root." << endl;
361  for (unsigned int i = 0; i < numPorts; i++) {
362  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
363  auto iPort = getPortInterfaceDataForUpdate(interfaceId);
364  if (!iPort->isEdge()) { // avoiding clients reseting
365  if (arrivalPort->getState() != Ieee8021dInterfaceData::FORWARDING)
366  iPort->setTCWhile(simTime() + tcWhileTime);
367  macTable->removeForwardingInterface(interfaceId);
368  if ((unsigned int)interfaceId != arrivalInterfaceId) {
369  iPort->setRole(Ieee8021dInterfaceData::NOTASSIGNED);
370  iPort->setState(Ieee8021dInterfaceData::DISCARDING);
371  iPort->setNextUpgrade(simTime() + migrateTime);
373  initInterfacedata(interfaceId);
374  }
375  }
376  }
377  arrivalPort->setRole(Ieee8021dInterfaceData::ROOT);
378  arrivalPort->setState(Ieee8021dInterfaceData::FORWARDING);
379  arrivalPort->setLostBPDU(0);
380 
381  return true;
382 
383  case BETTER_RPC: // same that Root but better RPC
384  case BETTER_SRC: // same that Root RPC but better source
385  case BETTER_PORT: // same that root RPC and source but better port
386  if (arrivalPort->getState() != Ieee8021dInterfaceData::FORWARDING) {
387  EV_DETAIL << "Better route to the current root. Setting the arrival port to root." << endl;
388  flushOtherPorts(arrivalInterfaceId);
389  }
390  arrivalPort->setRole(Ieee8021dInterfaceData::ROOT);
391  arrivalPort->setState(Ieee8021dInterfaceData::FORWARDING);
392  arrivalPort->setLostBPDU(0);
393  rootPort->setRole(Ieee8021dInterfaceData::ALTERNATE); // temporary, just one port can be root at contest time
394  macTable->replaceForwardingInterface(r, arrivalInterfaceId); // copy cache from old to new root
395  case3 = contestInterfacedata(r);
396  if (case3 >= 0) {
397  EV_DETAIL << "Setting current root port (port " << r << ") to alternate." << endl;
398  rootPort->setRole(Ieee8021dInterfaceData::ALTERNATE);
399  rootPort->setState(Ieee8021dInterfaceData::DISCARDING);
400  // not lostBPDU reset
401  // flushing r
402  macTable->removeForwardingInterface(r);
403  }
404  else {
405  EV_DETAIL << "Setting current root port (port " << r << ") to designated." << endl;
406  rootPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
407  rootPort->setState(Ieee8021dInterfaceData::DISCARDING);
408  rootPort->setNextUpgrade(simTime() + forwardDelay);
410  }
411  return true;
412 
413  case WORSE_ROOT:
414  EV_DETAIL << "Worse BPDU received than the current root. Sending BPDU to show him a better root as soon as possible." << endl;
415  sendBPDU(arrivalInterfaceId); // BPDU to show him a better root as soon as possible
416  break;
417 
418  case WORSE_RPC: // same Root but worse RPC
419  case WORSE_SRC: // same Root RPC but worse source
420  case WORSE_PORT: // same Root RPC and source but worse port
421  case3 = contestInterfacedata(frame, arrivalInterfaceId); // case 0 not possible
422  if (case3 < 0) {
423  EV_DETAIL << "Worse route to the current root. Setting the arrival port to designated." << endl;
424  arrivalPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
425  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
426  arrivalPort->setNextUpgrade(simTime() + forwardDelay);
428  sendBPDU(arrivalInterfaceId); // BPDU to show him a better root as soon as possible
429  }
430  else {
431  EV_DETAIL << "Worse route to the current root. Setting the arrival port to alternate." << endl;
432  // flush arrival
433  macTable->removeForwardingInterface(arrivalInterfaceId);
434  arrivalPort->setRole(Ieee8021dInterfaceData::ALTERNATE);
435  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
436  arrivalPort->setLostBPDU(0);
437  }
438  break;
439  }
440  }
441  return false;
442 }

Referenced by processBPDU().

◆ processBPDU()

void inet::Rstp::processBPDU ( const Ptr< const BpduCfg > &  frame,
unsigned int  arrivalInterfaceId 
)
protectedvirtual
288 {
289  // three challenges.
290  //
291  // first: vs best received BPDU for that port --------->case
292  // second: vs root BPDU--------------------------------->case1
293  // third: vs BPDU that would be sent from this Bridge.->case2
294  const Ieee8021dInterfaceData *arrivalPort = getPortInterfaceData(arrivalInterfaceId);
295  bool flood = false;
296  if (compareInterfacedata(arrivalInterfaceId, frame, arrivalPort->getLinkCost()) > 0 // better root
297  && frame->getRootAddress().compareTo(bridgeAddress) != 0) // root will not participate in a loop with its own address
298  flood = processBetterSource(frame, arrivalInterfaceId);
299  else if (frame->getBridgeAddress().compareTo(arrivalPort->getBridgeAddress()) == 0 // worse or similar, but the same source
300  && frame->getRootAddress().compareTo(bridgeAddress) != 0) // root will not participate
301  flood = processSameSource(frame, arrivalInterfaceId);
302  if (flood) {
303  sendBPDUs(); // expedited BPDU
304  sendTCNtoRoot();
305  }
306 }

Referenced by handleIncomingFrame().

◆ processSameSource()

bool inet::Rstp::processSameSource ( const Ptr< const BpduCfg > &  frame,
unsigned int  arrivalInterfaceId 
)
protectedvirtual
445 {
446  EV_DETAIL << "BPDU received from the same source than the current best for this port" << endl;
447  auto arrivalPort = getPortInterfaceDataForUpdate(arrivalInterfaceId);
448  int case0 = compareInterfacedata(arrivalInterfaceId, frame, arrivalPort->getLinkCost());
449  // source has updated BPDU information
450  switch (case0) {
451  case SIMILAR:
452  arrivalPort->setLostBPDU(0); // same BPDU, not updated
453  break;
454 
455  case WORSE_ROOT:
456  EV_DETAIL << "Worse root received than the current best for this port." << endl;
457  if (arrivalPort->getRole() == Ieee8021dInterfaceData::ROOT) {
458  int alternative = getBestAlternate(); // searching for alternate
459  if (alternative >= 0) {
460  EV_DETAIL << "This port was the root, but there is a better alternative. Setting the arrival port to designated and port " << alternative << "to root." << endl;
461  auto alternativePort = getPortInterfaceDataForUpdate(alternative);
462  arrivalPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
463  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
464  arrivalPort->setNextUpgrade(simTime() + forwardDelay);
466  macTable->replaceForwardingInterface(arrivalInterfaceId, alternative); // copy cache from old to new root
467  flushOtherPorts(alternative);
468  alternativePort->setRole(Ieee8021dInterfaceData::ROOT);
469  alternativePort->setState(Ieee8021dInterfaceData::FORWARDING); // comes from alternate, preserves lostBPDU
470  updateInterfacedata(frame, arrivalInterfaceId);
471  sendBPDU(arrivalInterfaceId); // show him a better Root as soon as possible
472  }
473  else {
474  EV_DETAIL << "This port was the root and there no alternative. Initialize all ports" << endl;
475  int case2 = 0;
476  initPorts(); // allowing other ports to contest again
477  // flushing all ports
478  for (unsigned int j = 0; j < numPorts; j++) {
479  int interfaceId = ifTable->getInterface(j)->getInterfaceId();
480  macTable->removeForwardingInterface(interfaceId);
481  }
482  case2 = compareInterfacedata(arrivalInterfaceId, frame, arrivalPort->getLinkCost());
483  if (case2 > 0) {
484  EV_DETAIL << "This switch is not better, keep arrival port as a ROOT" << endl;
485  updateInterfacedata(frame, arrivalInterfaceId); // if this module is not better, keep it as a ROOT
486  arrivalPort->setRole(Ieee8021dInterfaceData::ROOT);
487  arrivalPort->setState(Ieee8021dInterfaceData::FORWARDING);
488  }
489  // propagating new information
490  return true;
491  }
492  }
493  else if (arrivalPort->getRole() == Ieee8021dInterfaceData::ALTERNATE) {
494  EV_DETAIL << "This port was an alternate, setting to designated" << endl;
495  arrivalPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
496  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
497  arrivalPort->setNextUpgrade(simTime() + forwardDelay);
499  updateInterfacedata(frame, arrivalInterfaceId);
500  sendBPDU(arrivalInterfaceId); // Show him a better Root as soon as possible
501  }
502  break;
503 
504  case WORSE_RPC:
505  case WORSE_SRC:
506  case WORSE_PORT:
507  EV_DETAIL << "Worse route to the current root than the current best for this port." << endl;
508  if (arrivalPort->getRole() == Ieee8021dInterfaceData::ROOT) {
509  arrivalPort->setLostBPDU(0);
510  int alternative = getBestAlternate(); // searching for alternate
511  if (alternative >= 0) {
512  auto alternativePort = getPortInterfaceDataForUpdate(alternative);
513  int case2 = 0;
514  case2 = compareInterfacedata(alternative, frame, arrivalPort->getLinkCost());
515  if (case2 < 0) { // if alternate is better, change
516  alternativePort->setRole(Ieee8021dInterfaceData::ROOT);
517  alternativePort->setState(Ieee8021dInterfaceData::FORWARDING);
518  arrivalPort->setRole(Ieee8021dInterfaceData::DESIGNATED); // temporary, just one port can be root at contest time
519  int case3 = 0;
520  case3 = contestInterfacedata(frame, arrivalInterfaceId);
521  if (case3 < 0) {
522  EV_DETAIL << "This port was the root, but there is a better alternative. Setting the arrival port to designated and port " << alternative << "to root." << endl;
523  arrivalPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
524  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
525  arrivalPort->setNextUpgrade(simTime() + forwardDelay);
527  }
528  else {
529  EV_DETAIL << "This port was the root, but there is a better alternative. Setting the arrival port to alternate and port " << alternative << "to root." << endl;
530  arrivalPort->setRole(Ieee8021dInterfaceData::ALTERNATE);
531  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
532  }
533  flushOtherPorts(alternative);
534  macTable->replaceForwardingInterface(arrivalInterfaceId, alternative); // copy cache from old to new root
535  }
536  }
537  updateInterfacedata(frame, arrivalInterfaceId);
538  // propagating new information
539  return true;
540  // if alternate is worse than root, or there is not alternate, keep old root as root
541  }
542  else if (arrivalPort->getRole() == Ieee8021dInterfaceData::ALTERNATE) {
543  int case2 = 0;
544  case2 = contestInterfacedata(frame, arrivalInterfaceId);
545  if (case2 < 0) {
546  EV_DETAIL << "This port was an alternate, setting to designated" << endl;
547  arrivalPort->setRole(Ieee8021dInterfaceData::DESIGNATED); // if the frame is worse than this module generated frame, switch to Designated/Discarding
548  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
549  arrivalPort->setNextUpgrade(simTime() + forwardDelay);
551  sendBPDU(arrivalInterfaceId); // show him a better BPDU as soon as possible
552  }
553  else {
554  arrivalPort->setLostBPDU(0); // if it is better than this module generated frame, keep it as alternate
555  // this does not deserve expedited BPDU
556  }
557  }
558  updateInterfacedata(frame, arrivalInterfaceId);
559  break;
560  }
561  return false;
562 }

Referenced by processBPDU().

◆ receiveSignal()

void inet::Rstp::receiveSignal ( cComponent *  source,
simsignal_t  signalID,
cObject *  obj,
cObject *  details 
)
overridevirtual

Reimplemented from inet::StpBase.

865 {
866  Enter_Method("%s", cComponent::getSignalName(signalID));
867 
868  if (signalID == interfaceStateChangedSignal) {
869  NetworkInterface *changedIE = check_and_cast<const NetworkInterfaceChangeDetails *>(obj)->getNetworkInterface();
870  for (unsigned int i = 0; i < numPorts; i++) {
871  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
872  NetworkInterface *gateIfEntry = getPortNetworkInterface(interfaceId);
873  if (gateIfEntry == changedIE) {
874  if (gateIfEntry->hasCarrier()) {
875  auto iPort = getPortInterfaceDataForUpdate(interfaceId);
876  if (iPort->getRole() == Ieee8021dInterfaceData::NOTASSIGNED)
877  iPort->setNextUpgrade(simTime() + migrateTime);
878  else if (iPort->getRole() == Ieee8021dInterfaceData::DESIGNATED
879  && (iPort->getState() == Ieee8021dInterfaceData::DISCARDING || iPort->getState() == Ieee8021dInterfaceData::LEARNING))
880  iPort->setNextUpgrade(simTime() + forwardDelay);
882  }
883  }
884  }
885  }
886 }

◆ scheduleNextUpgrade()

void inet::Rstp::scheduleNextUpgrade ( )
protectedvirtual

schedule next upgrade self-message

56 {
57  cancelEvent(upgradeTimer);
58  const Ieee8021dInterfaceData *nextInterfaceData = nullptr;
59  for (unsigned int i = 0; i < numPorts; i++) {
60  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
61  if (getPortNetworkInterface(interfaceId)->hasCarrier()) {
62  const Ieee8021dInterfaceData *iPort = getPortInterfaceData(interfaceId);
63  if (iPort->getRole() == Ieee8021dInterfaceData::NOTASSIGNED) {
64  if (nextInterfaceData == nullptr)
65  nextInterfaceData = iPort;
66  else if (iPort->getNextUpgrade() < nextInterfaceData->getNextUpgrade())
67  nextInterfaceData = iPort;
68  }
69  else if (iPort->getRole() == Ieee8021dInterfaceData::DESIGNATED) {
70  if (iPort->getState() == Ieee8021dInterfaceData::DISCARDING) {
71  if (nextInterfaceData == nullptr)
72  nextInterfaceData = iPort;
73  else if (iPort->getNextUpgrade() < nextInterfaceData->getNextUpgrade())
74  nextInterfaceData = iPort;
75  }
76  else if (iPort->getState() == Ieee8021dInterfaceData::LEARNING) {
77  if (nextInterfaceData == nullptr)
78  nextInterfaceData = iPort;
79  else if (iPort->getNextUpgrade() < nextInterfaceData->getNextUpgrade())
80  nextInterfaceData = iPort;
81  }
82  }
83  }
84  }
85  if (nextInterfaceData != nullptr)
86  scheduleAt(nextInterfaceData->getNextUpgrade(), upgradeTimer);
87 }

Referenced by handleHelloTime(), handleUpgrade(), initPorts(), processBetterSource(), processSameSource(), and receiveSignal().

◆ sendBPDU()

void inet::Rstp::sendBPDU ( int  interfaceId)
protectedvirtual

Sends BPDU through a port.

620 {
621  // send a BPDU throuth port
622  const Ieee8021dInterfaceData *iport = getPortInterfaceData(interfaceId);
623  int r = getRootInterfaceId();
624  const Ieee8021dInterfaceData *rootPort;
625  if (r != -1)
626  rootPort = getPortInterfaceData(r);
627  if (iport->getRole() != Ieee8021dInterfaceData::DISABLED) {
628  Packet *packet = new Packet("BPDU");
629  const auto& frame = makeShared<BpduCfg>();
630  if (r != -1) {
631  frame->setRootPriority(rootPort->getRootPriority());
632  frame->setRootAddress(rootPort->getRootAddress());
633  frame->setMessageAge(rootPort->getAge());
634  frame->setRootPathCost(rootPort->getRootPathCost());
635  }
636  else {
637  frame->setRootPriority(bridgePriority);
638  frame->setRootAddress(bridgeAddress);
639  frame->setMessageAge(0);
640  frame->setRootPathCost(0);
641  }
642  frame->setBridgePriority(bridgePriority);
643  frame->setTcaFlag(false);
644  frame->setPortNum(interfaceId);
645  frame->setBridgeAddress(bridgeAddress);
646  if (simTime() < iport->getTCWhile())
647  frame->setTcFlag(true);
648  else
649  frame->setTcFlag(false);
650  frame->setMaxAge(maxAge);
651  frame->setHelloTime(helloTime);
652  frame->setForwardDelay(forwardDelay);
653 
654  packet->insertAtBack(frame);
655 
656  auto macAddressReq = packet->addTag<MacAddressReq>();
657  macAddressReq->setSrcAddress(bridgeAddress);
658  macAddressReq->setDestAddress(MacAddress::STP_MULTICAST_ADDRESS);
659  packet->addTag<InterfaceReq>()->setInterfaceId(interfaceId);
660  packet->addTag<PacketProtocolTag>()->setProtocol(&Protocol::stp);
661  packet->addTag<DispatchProtocolReq>()->setProtocol(&Protocol::ieee8022llc);
662  send(packet, "relayOut");
663  }
664 }

Referenced by processBetterSource(), processSameSource(), and sendBPDUs().

◆ sendBPDUs()

void inet::Rstp::sendBPDUs ( )
protectedvirtual

Sends BPDUs through all ports, if they are required.

605 {
606  // send BPDUs through all ports, if they are required
607  for (unsigned int i = 0; i < numPorts; i++) {
608  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
609  const Ieee8021dInterfaceData *iPort = getPortInterfaceData(interfaceId);
610  if ((iPort->getRole() != Ieee8021dInterfaceData::ROOT)
611  && (iPort->getRole() != Ieee8021dInterfaceData::ALTERNATE)
612  && (iPort->getRole() != Ieee8021dInterfaceData::DISABLED) && (!iPort->isEdge()))
613  {
614  sendBPDU(interfaceId);
615  }
616  }
617 }

Referenced by handleHelloTime(), and processBPDU().

◆ sendTCNtoRoot()

void inet::Rstp::sendTCNtoRoot ( )
protectedvirtual

If root TCWhile has not expired, sends a BPDU to the Root with TCFlag=true.

565 {
566  // if TCWhile is not expired, sends BPDU with TC flag to the root
567  this->bubble("SendTCNtoRoot");
568  EV_DETAIL << "SendTCNtoRoot" << endl;
569  int r = getRootInterfaceId();
570  if (r >= 0) {
571  const Ieee8021dInterfaceData *rootPort = getPortInterfaceData(r);
572  if (rootPort->getRole() != Ieee8021dInterfaceData::DISABLED) {
573  if (simTime() < rootPort->getTCWhile()) {
574  Packet *packet = new Packet("BPDU");
575  const auto& frame = makeShared<BpduCfg>();
576  frame->setRootPriority(rootPort->getRootPriority());
577  frame->setRootAddress(rootPort->getRootAddress());
578  frame->setMessageAge(rootPort->getAge());
579  frame->setRootPathCost(rootPort->getRootPathCost());
580  frame->setBridgePriority(bridgePriority);
581  frame->setTcaFlag(false);
582  frame->setPortNum(r);
583  frame->setBridgeAddress(bridgeAddress);
584  frame->setTcFlag(true);
585  frame->setMaxAge(maxAge);
586  frame->setHelloTime(helloTime);
587  frame->setForwardDelay(forwardDelay);
588 
589  packet->insertAtBack(frame);
590 
591  auto macAddressReq = packet->addTag<MacAddressReq>();
592  macAddressReq->setSrcAddress(bridgeAddress);
593  macAddressReq->setDestAddress(MacAddress::STP_MULTICAST_ADDRESS);
594  packet->addTag<InterfaceReq>()->setInterfaceId(r);
595 
596  packet->addTag<PacketProtocolTag>()->setProtocol(&Protocol::stp);
597  packet->addTag<DispatchProtocolReq>()->setProtocol(&Protocol::ieee8022llc);
598  send(packet, "relayOut");
599  }
600  }
601  }
602 }

Referenced by handleHelloTime(), and processBPDU().

◆ start()

void inet::Rstp::start ( )
overrideprotectedvirtual

Reimplemented from inet::StpBase.

889 {
890  StpBase::start();
891  initPorts();
892  scheduleAfter(SIMTIME_ZERO, helloTimer);
893 }

◆ stop()

void inet::Rstp::stop ( )
overrideprotectedvirtual

Reimplemented from inet::StpBase.

896 {
897  StpBase::stop();
898  cancelEvent(helloTimer);
899  cancelEvent(upgradeTimer);
900 }

◆ updateInterfacedata()

void inet::Rstp::updateInterfacedata ( const Ptr< const BpduCfg > &  frame,
unsigned int  interfaceId 
)
protectedvirtual

Update Interfacedata with the content of the BPDU frame.

734 {
735  auto ifd = getPortInterfaceDataForUpdate(portNum);
736  ifd->setRootPriority(frame->getRootPriority());
737  ifd->setRootAddress(frame->getRootAddress());
738  ifd->setRootPathCost(frame->getRootPathCost() + ifd->getLinkCost());
739  ifd->setAge(frame->getMessageAge() + 1);
740  ifd->setBridgePriority(frame->getBridgePriority());
741  ifd->setBridgeAddress(frame->getBridgeAddress());
742  ifd->setPortPriority(frame->getPortPriority());
743  ifd->setPortNum(frame->getPortNum());
744  ifd->setLostBPDU(0);
745 }

Referenced by processBetterSource(), and processSameSource().

Member Data Documentation

◆ autoEdge

bool inet::Rstp::autoEdge = false
protected

Referenced by initialize().

◆ helloTimer

cMessage* inet::Rstp::helloTimer = nullptr
protected

Referenced by initialize(), start(), stop(), and ~Rstp().

◆ migrateTime

simtime_t inet::Rstp::migrateTime
protected

◆ tcWhileTime

simtime_t inet::Rstp::tcWhileTime
protected

◆ upgradeTimer

cMessage* inet::Rstp::upgradeTimer = nullptr
protected

The documentation for this class was generated from the following files:
inet::findContainingNode
cModule * findContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:31
inet::Rstp::processBPDU
virtual void processBPDU(const Ptr< const BpduCfg > &frame, unsigned int arrivalInterfaceId)
Definition: Rstp.cc:287
inet::units::constants::c
const value< double, compose< units::m, pow< units::s, -1 > > > c(299792458)
inet::Rstp::sendBPDUs
virtual void sendBPDUs()
Sends BPDUs through all ports, if they are required.
Definition: Rstp.cc:604
inet::Protocol::stp
static const Protocol stp
Definition: Protocol.h:111
inet::StpBase::ie
opp_component_ptr< NetworkInterface > ie
Definition: StpBase.h:39
inet::StpBase::bridgePriority
unsigned int bridgePriority
Definition: StpBase.h:29
inet::Rstp::sendBPDU
virtual void sendBPDU(int interfaceId)
Sends BPDU through a port.
Definition: Rstp.cc:619
inet::StpBase::getPortInterfaceDataForUpdate
Ieee8021dInterfaceData * getPortInterfaceDataForUpdate(unsigned int interfaceId)
Definition: StpBase.cc:140
inet::Ieee8021dInterfaceData::DESIGNATED
@ DESIGNATED
Definition: Ieee8021dInterfaceData.h:24
inet::Ieee8021dInterfaceData::ROOT
@ ROOT
Definition: Ieee8021dInterfaceData.h:24
inet::Rstp::updateInterfacedata
virtual void updateInterfacedata(const Ptr< const BpduCfg > &frame, unsigned int interfaceId)
Update Interfacedata with the content of the BPDU frame.
Definition: Rstp.cc:733
inet::Rstp::flushOtherPorts
virtual void flushOtherPorts(unsigned int interfaceId)
flush all port expect one
Definition: Rstp.cc:852
inet::Rstp::SELF_HELLOTIME
@ SELF_HELLOTIME
Definition: Rstp.h:29
inet::Rstp::compareInterfacedata
virtual CompareResult compareInterfacedata(unsigned int interfaceId, const Ptr< const BpduCfg > &msg, int linkCost)
Compares a port's best BPDU with a BPDU frame.
Definition: Rstp.cc:777
InterfaceReq
removed InterfaceReq
Definition: IUdp-gates.txt:11
DispatchProtocolReq
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down DispatchProtocolReq
Definition: IUdp-gates.txt:25
inet::Rstp::helloTimer
cMessage * helloTimer
Definition: Rstp.h:41
inet::Rstp::WORSE_PORT
@ WORSE_PORT
Definition: Rstp.h:32
inet::Rstp::SELF_UPGRADE
@ SELF_UPGRADE
Definition: Rstp.h:29
inet::Rstp::autoEdge
bool autoEdge
Definition: Rstp.h:39
inet::Rstp::BETTER_PORT
@ BETTER_PORT
Definition: Rstp.h:33
inet::MacAddress::STP_MULTICAST_ADDRESS
static const MacAddress STP_MULTICAST_ADDRESS
The spanning tree protocol bridge's multicast address, 01:80:C2:00:00:00.
Definition: MacAddress.h:40
inet::Rstp::handleIncomingFrame
virtual void handleIncomingFrame(Packet *packet)
BPDU processing.
Definition: Rstp.cc:265
inet::Rstp::SIMILAR
@ SIMILAR
Definition: Rstp.h:32
inet::Rstp::getBestAlternate
virtual int getBestAlternate()
Gets the best alternate port.
Definition: Rstp.cc:824
inet::StpBase::forwardDelay
simtime_t forwardDelay
Definition: StpBase.h:34
inet::Ieee8021dInterfaceData::DISCARDING
@ DISCARDING
Definition: Ieee8021dInterfaceData.h:26
inet::Protocol::ieee8022llc
static const Protocol ieee8022llc
Definition: Protocol.h:88
inet::Rstp::tcWhileTime
simtime_t tcWhileTime
Definition: Rstp.h:38
inet::Rstp::processSameSource
virtual bool processSameSource(const Ptr< const BpduCfg > &frame, unsigned int arrivalInterfaceId)
Definition: Rstp.cc:444
PacketProtocolTag
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down PacketProtocolTag
Definition: IUdp-gates.txt:25
inet::Rstp::WORSE_RPC
@ WORSE_RPC
Definition: Rstp.h:32
inet::Rstp::initPorts
virtual void initPorts()
initialize RSTP dynamic information
Definition: Rstp.cc:713
inet::Rstp::WORSE_SRC
@ WORSE_SRC
Definition: Rstp.h:32
inet::Rstp::BETTER_ROOT
@ BETTER_ROOT
Definition: Rstp.h:33
inet::StpBase::bridgeAddress
MacAddress bridgeAddress
Definition: StpBase.h:30
inet::StpBase::ifTable
ModuleRefByPar< IInterfaceTable > ifTable
Definition: StpBase.h:38
inet::Rstp::scheduleNextUpgrade
virtual void scheduleNextUpgrade()
schedule next upgrade self-message
Definition: Rstp.cc:55
inet::Ieee8021dInterfaceData::FORWARDING
@ FORWARDING
Definition: Ieee8021dInterfaceData.h:26
inet::Rstp::initInterfacedata
virtual void initInterfacedata(unsigned int portNum)
Definition: Rstp.cc:699
inet::StpBase::helloTime
simtime_t helloTime
Definition: StpBase.h:33
inet::interfaceStateChangedSignal
simsignal_t interfaceStateChangedSignal
Definition: Simsignals.cc:32
inet::INITSTAGE_LOCAL
INET_API InitStage INITSTAGE_LOCAL
Initialization of local state that don't use or affect other modules includes:
inet::Rstp::contestInterfacedata
virtual CompareResult contestInterfacedata(const Ptr< const BpduCfg > &msg, unsigned int interfaceId)
Compares the BPDU frame with the BPDU this module would send through that port.
Definition: Rstp.cc:762
inet::Ieee8021dInterfaceData::DISABLED
@ DISABLED
Definition: Ieee8021dInterfaceData.h:24
inet::Rstp::WORSE_ROOT
@ WORSE_ROOT
Definition: Rstp.h:32
inet::StpBase::getPortInterfaceData
const Ieee8021dInterfaceData * getPortInterfaceData(unsigned int interfaceId) const
Gets Ieee8021dInterfaceData for interface ID.
Definition: StpBase.cc:135
NUM_INIT_STAGES
#define NUM_INIT_STAGES
Definition: InitStageRegistry.h:73
inet::StpBase::getRootInterfaceId
virtual int getRootInterfaceId() const
Obtains the root interface ID.
Definition: StpBase.cc:154
inet::StpBase::start
virtual void start()
Definition: StpBase.cc:48
inet::Ieee8021dInterfaceData::NOTASSIGNED
@ NOTASSIGNED
Definition: Ieee8021dInterfaceData.h:24
inet::StpBase::getPortNetworkInterface
NetworkInterface * getPortNetworkInterface(unsigned int interfaceId) const
Gets NetworkInterface for interface ID.
Definition: StpBase.cc:145
inet::StpBase::initialize
virtual void initialize(int stage) override
Definition: StpBase.cc:25
inet::Ieee8021dInterfaceData::BACKUP
@ BACKUP
Definition: Ieee8021dInterfaceData.h:24
inet::Rstp::processBetterSource
virtual bool processBetterSource(const Ptr< const BpduCfg > &frame, unsigned int arrivalInterfaceId)
Definition: Rstp.cc:308
inet::Rstp::checkTC
virtual void checkTC(const Ptr< const BpduCfg > &frame, int arrivalInterfaceId)
Checks the frame TC flag.
Definition: Rstp.cc:209
inet::Ieee8021dInterfaceData::ALTERNATE
@ ALTERNATE
Definition: Ieee8021dInterfaceData.h:24
inet::StpBase::maxAge
simtime_t maxAge
Definition: StpBase.h:32
Enter_Method
#define Enter_Method(...)
Definition: SelfDoc.h:71
inet::Rstp::compareRSTPData
virtual CompareResult compareRSTPData(int rootPriority1, int rootPriority2, MacAddress rootAddress1, MacAddress rootAddress2, int rootPathCost1, int rootPathCost2, int bridgePriority1, int bridgePriority2, MacAddress bridgeAddress1, MacAddress bridgeAddress2, int portPriority1, int portPriority2, int portNum1, int portNum2)
Compares two RSTP data.
Definition: Rstp.cc:790
inet::Rstp::BETTER_RPC
@ BETTER_RPC
Definition: Rstp.h:33
inet::Rstp::migrateTime
simtime_t migrateTime
Definition: Rstp.h:37
inet::Rstp::handleUpgrade
virtual void handleUpgrade(cMessage *)
Upgrade event handling.
Definition: Rstp.cc:113
inet::StpBase::macTable
ModuleRefByPar< IMacForwardingTable > macTable
Definition: StpBase.h:37
inet::StpBase::numPorts
unsigned int numPorts
Definition: StpBase.h:27
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::Rstp::sendTCNtoRoot
virtual void sendTCNtoRoot()
If root TCWhile has not expired, sends a BPDU to the Root with TCFlag=true.
Definition: Rstp.cc:564
inet::Rstp::upgradeTimer
cMessage * upgradeTimer
Definition: Rstp.h:42
inet::Rstp::BETTER_SRC
@ BETTER_SRC
Definition: Rstp.h:33
inet::Rstp::handleHelloTime
virtual void handleHelloTime(cMessage *)
HelloTime event handling.
Definition: Rstp.cc:142
inet::INITSTAGE_LINK_LAYER
INET_API InitStage INITSTAGE_LINK_LAYER
Initialization of link-layer protocols.
inet::Ieee8021dInterfaceData::LEARNING
@ LEARNING
Definition: Ieee8021dInterfaceData.h:26
inet::StpBase::stop
virtual void stop()
Definition: StpBase.cc:58
inet::Rstp::handleBackup
virtual void handleBackup(const Ptr< const BpduCfg > &frame, unsigned int arrivalInterfaceId)
Handles the switch to backup in one of the ports.
Definition: Rstp.cc:228