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::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 handleOperationStage (LifecycleOperation *operation, int stage, IDoneCallback *doneCallback) override
 Perform one stage of a lifecycle operation. 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 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 port)
 Sends BPDU through a port. More...
 
virtual void handleMessage (cMessage *msg) override
 General processing. More...
 
virtual void handleIncomingFrame (BPDU *frame)
 BPDU processing. More...
 
virtual void processBPDU (BPDU *frame, unsigned int arrival)
 
virtual bool processBetterSource (BPDU *frame, unsigned int arrival)
 
virtual bool processSameSource (BPDU *frame, unsigned int arrival)
 
virtual void printState ()
 Prints current data base info. More...
 
virtual void updateInterfacedata (BPDU *frame, unsigned int portNum)
 Update Interfacedata with the content of the BDPU frame. More...
 
virtual CompareResult contestInterfacedata (BPDU *msg, unsigned int portNum)
 Compares the BPDU frame with the BPDU this module would send through that port. More...
 
virtual CompareResult contestInterfacedata (unsigned int portNum)
 Compares the port's best BPDU with the BPDU this module would send through that port. More...
 
virtual CompareResult compareInterfacedata (unsigned int portNum, BPDU *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 (BPDU *frame, int arrival)
 Checks the frame TC flag. More...
 
virtual void handleBackup (BPDU *frame, unsigned int arrival)
 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 portNum)
 flush all port expect one More...
 
- Protected Member Functions inherited from inet::STPBase
virtual void colorLink (unsigned int i, 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 getRootIndex () const
 Obtains the root gate index. More...
 
Ieee8021dInterfaceDatagetPortInterfaceData (unsigned int portNum)
 Gets Ieee8021dInterfaceData for port number. More...
 
const Ieee8021dInterfaceDatagetPortInterfaceData (unsigned int portNum) const
 
InterfaceEntrygetPortInterfaceEntry (unsigned int portNum)
 Gets InterfaceEntry for port number. More...
 
virtual InterfaceEntrychooseInterface ()
 

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
 
bool isOperational = false
 
unsigned int numPorts = 0
 
unsigned int bridgePriority = 0
 
MACAddress bridgeAddress
 
simtime_t maxAge
 
simtime_t helloTime
 
simtime_t forwardDelay
 
cModule * switchModule = nullptr
 
IMACAddressTablemacTable = nullptr
 
IInterfaceTableifTable = nullptr
 
InterfaceEntryie = nullptr
 

Detailed Description

Implements the Rapid Spanning Tree Protocol.

See the NED file for details.

Member Enumeration Documentation

enum inet::RSTP::CompareResult
protected
Enumerator
WORSE_PORT 
WORSE_SRC 
WORSE_RPC 
WORSE_ROOT 
SIMILAR 
BETTER_ROOT 
BETTER_RPC 
BETTER_SRC 
BETTER_PORT 
43  {
44  WORSE_PORT = -4, WORSE_SRC = -3, WORSE_RPC = -2, WORSE_ROOT = -1, SIMILAR = 0,
45  BETTER_ROOT = 1, BETTER_RPC = 2, BETTER_SRC = 3, BETTER_PORT = 4
46  };
Definition: RSTP.h:44
Definition: RSTP.h:45
Definition: RSTP.h:44
Definition: RSTP.h:45
Definition: RSTP.h:44
Definition: RSTP.h:44
Definition: RSTP.h:45
Definition: RSTP.h:45
Definition: RSTP.h:44
enum inet::RSTP::SelfKinds
protected
Enumerator
SELF_HELLOTIME 
SELF_UPGRADE 
Definition: RSTP.h:41
Definition: RSTP.h:41

Constructor & Destructor Documentation

inet::RSTP::RSTP ( )
32 {
33 }
inet::RSTP::~RSTP ( )
virtual
36 {
37  cancelAndDelete(helloTimer);
38  cancelAndDelete(upgradeTimer);
39 }
cMessage * upgradeTimer
Definition: RSTP.h:54
cMessage * helloTimer
Definition: RSTP.h:53

Member Function Documentation

void inet::RSTP::checkTC ( BPDU frame,
int  arrival 
)
protectedvirtual

Checks the frame TC flag.

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

Referenced by handleIncomingFrame().

214 {
215  Ieee8021dInterfaceData *port = getPortInterfaceData(arrival);
216  if ((frame->getTcFlag() == true) && (port->getState() == Ieee8021dInterfaceData::FORWARDING)) {
217  EV_DETAIL << "TCN received" << endl;
218  findContainingNode(this)->bubble("TCN received");
219  for (unsigned int i = 0; i < numPorts; i++) {
220  if ((int)i != arrival) {
221  Ieee8021dInterfaceData *port2 = getPortInterfaceData(i);
222  // flushing other ports
223  // TCN over other ports
224  macTable->flush(i);
225  port2->setTCWhile(simTime() + tcWhileTime);
226  }
227  }
228  }
229 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
IMACAddressTable * macTable
Definition: STPBase.h:47
cModule * findContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:56
simtime_t tcWhileTime
Definition: RSTP.h:50
virtual void flush(int portno)=0
Clears portno cache.
Definition: Ieee8021dInterfaceData.h:39
unsigned int numPorts
Definition: STPBase.h:37
RSTP::CompareResult inet::RSTP::compareInterfacedata ( unsigned int  portNum,
BPDU msg,
int  linkCost 
)
protectedvirtual

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

Returns
(<0 if vector better than frame)

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

771 {
772  Ieee8021dInterfaceData *ifd = getPortInterfaceData(portNum);
773 
774  return compareRSTPData(ifd->getRootPriority(), msg->getRootPriority(),
775  ifd->getRootAddress(), msg->getRootAddress(),
776  ifd->getRootPathCost(), msg->getRootPathCost() + linkCost,
777  ifd->getBridgePriority(), msg->getBridgePriority(),
778  ifd->getBridgeAddress(), msg->getBridgeAddress(),
779  ifd->getPortPriority(), msg->getPortPriority(),
780  ifd->getPortNum(), msg->getPortNum());
781 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
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:783
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)

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

790 {
791  if (rootPriority1 != rootPriority2)
792  return (rootPriority1 < rootPriority2) ? WORSE_ROOT : BETTER_ROOT;
793 
794  int c = rootAddress1.compareTo(rootAddress2);
795  if (c != 0)
796  return (c < 0) ? WORSE_ROOT : BETTER_ROOT;
797 
798  if (rootPathCost1 != rootPathCost2)
799  return (rootPathCost1 < rootPathCost2) ? WORSE_RPC : BETTER_RPC;
800 
801  if (bridgePriority1 != bridgePriority2)
802  return (bridgePriority1 < bridgePriority2) ? WORSE_SRC : BETTER_SRC;
803 
804  c = bridgeAddress1.compareTo(bridgeAddress2);
805  if (c != 0)
806  return (c < 0) ? WORSE_SRC : BETTER_SRC;
807 
808  if (portPriority1 != portPriority2)
809  return (portPriority1 < portPriority2) ? WORSE_PORT : BETTER_PORT;
810 
811  if (portNum1 != portNum2)
812  return (portNum1 < portNum2) ? WORSE_PORT : BETTER_PORT;
813 
814  return SIMILAR;
815 }
Definition: RSTP.h:44
Definition: RSTP.h:45
Definition: RSTP.h:44
Definition: RSTP.h:45
const value< double, compose< units::m, pow< units::s,-1 > > > c(299792458)
Definition: RSTP.h:44
Definition: RSTP.h:44
Definition: RSTP.h:45
Definition: RSTP.h:45
Definition: RSTP.h:44
RSTP::CompareResult inet::RSTP::contestInterfacedata ( BPDU msg,
unsigned int  portNum 
)
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)

Referenced by processBetterSource(), and processSameSource().

756 {
757  int r = getRootIndex();
758  Ieee8021dInterfaceData *rootPort = getPortInterfaceData(r);
759  Ieee8021dInterfaceData *ifd = getPortInterfaceData(portNum);
760 
761  return compareRSTPData(rootPort->getRootPriority(), msg->getRootPriority(),
762  rootPort->getRootAddress(), msg->getRootAddress(),
763  rootPort->getRootPathCost(), msg->getRootPathCost(),
764  bridgePriority, msg->getBridgePriority(),
765  bridgeAddress, msg->getBridgeAddress(),
766  ifd->getPortPriority(), msg->getPortPriority(),
767  portNum, msg->getPortNum());
768 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
unsigned int bridgePriority
Definition: STPBase.h:39
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:783
virtual int getRootIndex() const
Obtains the root gate index.
Definition: STPBase.cc:161
MACAddress bridgeAddress
Definition: STPBase.h:40
RSTP::CompareResult inet::RSTP::contestInterfacedata ( unsigned int  portNum)
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)
741 {
742  int r = getRootIndex();
743  Ieee8021dInterfaceData *rootPort = getPortInterfaceData(r);
744  Ieee8021dInterfaceData *ifd = getPortInterfaceData(portNum);
745 
746  return compareRSTPData(rootPort->getRootPriority(), ifd->getRootPriority(),
747  rootPort->getRootAddress(), ifd->getRootAddress(),
748  rootPort->getRootPathCost() + ifd->getLinkCost(), ifd->getRootPathCost(),
749  bridgePriority, ifd->getBridgePriority(),
750  bridgeAddress, ifd->getBridgeAddress(),
751  ifd->getPortPriority(), ifd->getPortPriority(),
752  portNum, ifd->getPortNum());
753 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
unsigned int bridgePriority
Definition: STPBase.h:39
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:783
virtual int getRootIndex() const
Obtains the root gate index.
Definition: STPBase.cc:161
MACAddress bridgeAddress
Definition: STPBase.h:40
virtual void inet::RSTP::finish ( )
inlineoverrideprotectedvirtual
64 {}
void inet::RSTP::flushOtherPorts ( unsigned int  portNum)
protectedvirtual

flush all port expect one

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

845 {
846  for (unsigned int i = 0; i < numPorts; i++) {
847  Ieee8021dInterfaceData *iPort = getPortInterfaceData(i);
848  iPort->setTCWhile(simTime() + tcWhileTime);
849  if (i != portNum)
850  macTable->flush(i);
851  }
852 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
IMACAddressTable * macTable
Definition: STPBase.h:47
simtime_t tcWhileTime
Definition: RSTP.h:50
virtual void flush(int portno)=0
Clears portno cache.
unsigned int numPorts
Definition: STPBase.h:37
int inet::RSTP::getBestAlternate ( )
protectedvirtual

Gets the best alternate port.

Returns
Best alternate gate index

Referenced by handleHelloTime(), and processSameSource().

818 {
819  int candidate = -1; // index of the best alternate found
820  for (unsigned int j = 0; j < numPorts; j++) {
821  Ieee8021dInterfaceData *jPort = getPortInterfaceData(j);
822  if (jPort->getRole() == Ieee8021dInterfaceData::ALTERNATE) { // just from alternates, others are not updated
823  if (candidate < 0)
824  candidate = j;
825  else {
826  Ieee8021dInterfaceData *candidatePort = getPortInterfaceData(candidate);
827  if (compareRSTPData(jPort->getRootPriority(), candidatePort->getRootPriority(),
828  jPort->getRootAddress(), candidatePort->getRootAddress(),
829  jPort->getRootPathCost(), candidatePort->getRootPathCost(),
830  jPort->getBridgePriority(), candidatePort->getBridgePriority(),
831  jPort->getBridgeAddress(), candidatePort->getBridgeAddress(),
832  jPort->getPortPriority(), candidatePort->getPortPriority(),
833  jPort->getPortNum(), candidatePort->getPortNum()) < 0)
834  {
835  // alternate better than the found one
836  candidate = j; // new candidate
837  }
838  }
839  }
840  }
841  return candidate;
842 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
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:783
Definition: Ieee8021dInterfaceData.h:37
unsigned int numPorts
Definition: STPBase.h:37
void inet::RSTP::handleBackup ( BPDU frame,
unsigned int  arrival 
)
protectedvirtual

Handles the switch to backup in one of the ports.

Referenced by handleIncomingFrame().

232 {
233  EV_DETAIL << "More than one port in the same LAN" << endl;
234  Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalPortNum);
235  if ((frame->getPortPriority() < port->getPortPriority())
236  || ((frame->getPortPriority() == port->getPortPriority()) && (frame->getPortNum() < arrivalPortNum)))
237  {
238  // flushing arrival port
239  macTable->flush(arrivalPortNum);
240  port->setRole(Ieee8021dInterfaceData::BACKUP);
241  port->setState(Ieee8021dInterfaceData::DISCARDING);
242  port->setLostBPDU(0);
243  EV_DETAIL << "Setting port " << arrivalPortNum << "to backup" << endl;
244  }
245  else if (frame->getPortPriority() > port->getPortPriority()
246  || (frame->getPortPriority() == port->getPortPriority() && frame->getPortNum() > arrivalPortNum))
247  {
248  Ieee8021dInterfaceData *port2 = getPortInterfaceData(frame->getPortNum());
249  // flushing sender port
250  macTable->flush(frame->getPortNum()); // portNum is sender port number, it is not arrival port
251  port2->setRole(Ieee8021dInterfaceData::BACKUP);
252  port2->setState(Ieee8021dInterfaceData::DISCARDING);
253  port2->setLostBPDU(0);
254  EV_DETAIL << "Setting port " << frame->getPortNum() << "to backup" << endl;
255  }
256  else {
257  Ieee8021dInterfaceData *port2 = getPortInterfaceData(frame->getPortNum());
258  // unavoidable loop, received its own message at the same port
259  // switch to disabled
260  EV_DETAIL << "Unavoidable loop. Received its own message at the same port. Setting port " << frame->getPortNum() << " to disabled." << endl;
261  // flushing that port
262  macTable->flush(frame->getPortNum()); // portNum is sender port number, it is not arrival port
263  port2->setRole(Ieee8021dInterfaceData::DISABLED);
264  port2->setState(Ieee8021dInterfaceData::DISCARDING);
265  }
266 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
Definition: Ieee8021dInterfaceData.h:39
Definition: Ieee8021dInterfaceData.h:37
unsigned int getPortNum() const
Definition: Ieee8021dInterfaceData.h:126
IMACAddressTable * macTable
Definition: STPBase.h:47
virtual void flush(int portno)=0
Clears portno cache.
Definition: Ieee8021dInterfaceData.h:37
void inet::RSTP::handleHelloTime ( cMessage *  msg)
protectedvirtual

HelloTime event handling.

Referenced by handleMessage().

148 {
149  EV_DETAIL << "Hello time." << endl;
150  for (unsigned int i = 0; i < numPorts; i++) {
151  // sends hello through all active (learning, forwarding or not assigned) ports
152  // increments LostBPDU just from ROOT, ALTERNATE and BACKUP
153  Ieee8021dInterfaceData *iPort = getPortInterfaceData(i);
154  if (!iPort->isEdge()
155  && (iPort->getRole() == Ieee8021dInterfaceData::ROOT
156  || iPort->getRole() == Ieee8021dInterfaceData::ALTERNATE
157  || iPort->getRole() == Ieee8021dInterfaceData::BACKUP))
158  {
159  iPort->setLostBPDU(iPort->getLostBPDU() + 1);
160  if (iPort->getLostBPDU() > 3) { // 3 HelloTime without the best BPDU.
161  EV_DETAIL << "3 HelloTime without the best BPDU" << endl;
162  // starts contest
163  if (iPort->getRole() == Ieee8021dInterfaceData::ROOT) {
164  // looking for the best ALTERNATE port
165  int candidate = getBestAlternate();
166  if (candidate != -1) {
167  // if an alternate gate has been found, switch to alternate
168  EV_DETAIL << "It was the root port. Alternate gate has been found. Setting port " << candidate << " to root. Setting current root port (port" << i << ") to designated." << endl;
169  // ALTERNATE->ROOT. DISCARDING->FORWARDING (immediately)
170  // old root gate goes to DESIGNATED and DISCARDING
171  // a new contest should be done to determine the new root path from this LAN
172  // updating root vector.
173  Ieee8021dInterfaceData *candidatePort = getPortInterfaceData(candidate);
174  iPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
175  iPort->setState(Ieee8021dInterfaceData::DISCARDING); // if there is not a better BPDU, that will become FORWARDING
176  iPort->setNextUpgrade(simTime() + forwardDelay);
178  initInterfacedata(i); // reset, then a new BPDU will be allowed to upgrade the best received info for this port
179  candidatePort->setRole(Ieee8021dInterfaceData::ROOT);
180  candidatePort->setState(Ieee8021dInterfaceData::FORWARDING);
181  candidatePort->setLostBPDU(0);
182  flushOtherPorts(candidate);
183  macTable->copyTable(i, candidate); // copy cache from old to new root
184  }
185  else {
186  // alternate not found, selects a new root
187  EV_DETAIL << "It was the root port. Alternate not found. Starts from beginning." << endl;
188  // initializing ports, start from the beginning
189  initPorts();
190  }
191  }
192  else if (iPort->getRole() == Ieee8021dInterfaceData::ALTERNATE
193  || iPort->getRole() == Ieee8021dInterfaceData::BACKUP)
194  {
195  EV_DETAIL << "Setting port " << i << " to designated." << endl;
196  // it should take care of this LAN, switching to designated
197  iPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
198  iPort->setState(Ieee8021dInterfaceData::DISCARDING); // a new content will start in case of another switch were in alternate
199  iPort->setNextUpgrade(simTime() + forwardDelay);
201  // if there is no problem, this will become forwarding in a few seconds
203  }
204  iPort->setLostBPDU(0); // reseting lost bpdu counter after a change.
205  }
206  }
207  }
208  sendBPDUs(); // generating and sending new BPDUs
209  sendTCNtoRoot();
210  scheduleAt(simTime() + helloTime, msg); // programming next hello time
211 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
Definition: Ieee8021dInterfaceData.h:39
virtual void copyTable(int portA, int portB)=0
Copy cache from portA to portB port.
Definition: Ieee8021dInterfaceData.h:37
Definition: Ieee8021dInterfaceData.h:37
virtual void scheduleNextUpgrade()
schedule next upgrade self-message
Definition: RSTP.cc:54
Definition: Ieee8021dInterfaceData.h:37
virtual void initInterfacedata(unsigned int portNum)
Definition: RSTP.cc:693
virtual void sendBPDUs()
Sends BPDUs through all ports, if they are required.
Definition: RSTP.cc:603
simtime_t forwardDelay
Definition: STPBase.h:44
virtual void sendTCNtoRoot()
If root TCWhile has not expired, sends a BPDU to the Root with TCFlag=true.
Definition: RSTP.cc:565
IMACAddressTable * macTable
Definition: STPBase.h:47
virtual void flushOtherPorts(unsigned int portNum)
flush all port expect one
Definition: RSTP.cc:844
Definition: Ieee8021dInterfaceData.h:39
Definition: Ieee8021dInterfaceData.h:37
simtime_t helloTime
Definition: STPBase.h:43
unsigned int numPorts
Definition: STPBase.h:37
virtual void initPorts()
initialize RSTP dynamic information
Definition: RSTP.cc:707
virtual int getBestAlternate()
Gets the best alternate port.
Definition: RSTP.cc:817
void inet::RSTP::handleIncomingFrame ( BPDU frame)
protectedvirtual

BPDU processing.

Updates port information. Handles port role changes.

Referenced by handleMessage().

269 {
270  // incoming BPDU handling
271  // checking message age
272  Ieee802Ctrl *etherctrl = check_and_cast<Ieee802Ctrl *>(frame->removeControlInfo());
273  int arrivalPortNum = etherctrl->getSwitchPort();
274  MACAddress src = etherctrl->getSrc();
275  delete etherctrl;
276  EV_INFO << "BPDU received at port " << arrivalPortNum << "." << endl;
277  if (frame->getMessageAge() < maxAge) {
278  // checking TC
279  checkTC(frame, arrivalPortNum); // sets TCWhile if arrival port was FORWARDING
280  // checking possible backup
281  if (src.compareTo(bridgeAddress) == 0) // more than one port in the same LAN
282  handleBackup(frame, arrivalPortNum);
283  else
284  processBPDU(frame, arrivalPortNum);
285  }
286  else
287  EV_DETAIL << "Expired BPDU" << endl;
288  delete frame;
289 }
virtual void handleBackup(BPDU *frame, unsigned int arrival)
Handles the switch to backup in one of the ports.
Definition: RSTP.cc:231
virtual void processBPDU(BPDU *frame, unsigned int arrival)
Definition: RSTP.cc:291
simtime_t maxAge
Definition: STPBase.h:42
virtual void checkTC(BPDU *frame, int arrival)
Checks the frame TC flag.
Definition: RSTP.cc:213
MACAddress bridgeAddress
Definition: STPBase.h:40
void inet::RSTP::handleMessage ( cMessage *  msg)
overrideprotectedvirtual

General processing.

88 {
89  // it can receive BPDU or self messages
90  if (!isOperational) {
91  if (msg->isSelfMessage())
92  throw cRuntimeError("Model error: self msg '%s' received when isOperational is false", msg->getName());
93  EV << "Message '" << msg << "' arrived when module status is down, dropped\n";
94  delete msg;
95  return;
96  }
97 
98  if (msg->isSelfMessage()) {
99  switch (msg->getKind()) {
100  case SELF_HELLOTIME:
101  handleHelloTime(msg);
102  break;
103 
104  case SELF_UPGRADE:
105  // designated ports state upgrading (discarding-->learning, learning-->forwarding)
106  handleUpgrade(msg);
107  break;
108 
109  default:
110  throw cRuntimeError("Unknown self message");
111  break;
112  }
113  }
114  else {
115  handleIncomingFrame(check_and_cast<BPDU *>(msg)); // handling BPDU
116  }
117 }
Definition: RSTP.h:41
virtual void handleHelloTime(cMessage *)
HelloTime event handling.
Definition: RSTP.cc:147
virtual void handleUpgrade(cMessage *)
Upgrade event handling.
Definition: RSTP.cc:119
bool isOperational
Definition: STPBase.h:36
virtual void handleIncomingFrame(BPDU *frame)
BPDU processing.
Definition: RSTP.cc:268
Definition: RSTP.h:41
void inet::RSTP::handleUpgrade ( cMessage *  msg)
protectedvirtual

Upgrade event handling.

Referenced by handleMessage().

120 {
121  for (unsigned int i = 0; i < numPorts; i++) {
122  Ieee8021dInterfaceData *iPort = getPortInterfaceData(i);
123  if (getPortInterfaceEntry(i)->hasCarrier() && iPort->getNextUpgrade() == simTime()) {
124  if (iPort->getRole() == Ieee8021dInterfaceData::NOTASSIGNED) {
125  EV_DETAIL << "MigrateTime. Setting port " << i << "to designated." << endl;
126  iPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
127  iPort->setState(Ieee8021dInterfaceData::DISCARDING); // contest to become forwarding.
128  iPort->setNextUpgrade(simTime() + forwardDelay);
129  }
130  else if (iPort->getRole() == Ieee8021dInterfaceData::DESIGNATED) {
131  if (iPort->getState() == Ieee8021dInterfaceData::DISCARDING) {
132  EV_INFO << "UpgradeTime. Setting port " << i << " state to learning." << endl;
133  iPort->setState(Ieee8021dInterfaceData::LEARNING);
134  iPort->setNextUpgrade(simTime() + forwardDelay);
135  }
136  else if (iPort->getState() == Ieee8021dInterfaceData::LEARNING) {
137  EV_INFO << "UpgradeTime. Setting port " << i << " state to forwarding." << endl;
138  iPort->setState(Ieee8021dInterfaceData::FORWARDING);
139  flushOtherPorts(i);
140  }
141  }
142  }
143  }
145 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
Definition: Ieee8021dInterfaceData.h:39
Definition: Ieee8021dInterfaceData.h:39
virtual void scheduleNextUpgrade()
schedule next upgrade self-message
Definition: RSTP.cc:54
InterfaceEntry * getPortInterfaceEntry(unsigned int portNum)
Gets InterfaceEntry for port number.
Definition: STPBase.cc:149
Definition: Ieee8021dInterfaceData.h:37
simtime_t forwardDelay
Definition: STPBase.h:44
virtual void flushOtherPorts(unsigned int portNum)
flush all port expect one
Definition: RSTP.cc:844
Definition: Ieee8021dInterfaceData.h:37
Definition: Ieee8021dInterfaceData.h:39
unsigned int numPorts
Definition: STPBase.h:37
void inet::RSTP::initialize ( int  stage)
overrideprotectedvirtual

Reimplemented from inet::STPBase.

42 {
43  STPBase::initialize(stage);
44 
45  if (stage == INITSTAGE_LOCAL) {
46  autoEdge = par("autoEdge");
47  tcWhileTime = par("tcWhileTime");
48  migrateTime = par("migrateTime");
49  helloTimer = new cMessage("itshellotime", SELF_HELLOTIME);
50  upgradeTimer = new cMessage("upgrade", SELF_UPGRADE);
51  }
52 }
Definition: RSTP.h:41
virtual void initialize(int stage) override
Definition: STPBase.cc:34
simtime_t migrateTime
Definition: RSTP.h:49
cMessage * upgradeTimer
Definition: RSTP.h:54
Local initializations.
Definition: InitStages.h:35
simtime_t tcWhileTime
Definition: RSTP.h:50
bool autoEdge
Definition: RSTP.h:51
cMessage * helloTimer
Definition: RSTP.h:53
Definition: RSTP.h:41
void inet::RSTP::initInterfacedata ( unsigned int  portNum)
protectedvirtual

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

694 {
695  Ieee8021dInterfaceData *ifd = getPortInterfaceData(portNum);
696  ifd->setRootPriority(bridgePriority);
697  ifd->setRootAddress(bridgeAddress);
698  ifd->setRootPathCost(0);
699  ifd->setAge(0);
700  ifd->setBridgePriority(bridgePriority);
701  ifd->setBridgeAddress(bridgeAddress);
702  ifd->setPortPriority(-1);
703  ifd->setPortNum(-1);
704  ifd->setLostBPDU(0);
705 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
unsigned int bridgePriority
Definition: STPBase.h:39
MACAddress bridgeAddress
Definition: STPBase.h:40
void inet::RSTP::initPorts ( )
protectedvirtual

initialize RSTP dynamic information

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

708 {
709  for (unsigned int j = 0; j < numPorts; j++) {
710  Ieee8021dInterfaceData *jPort = getPortInterfaceData(j);
711  if (!jPort->isEdge()) {
712  jPort->setRole(Ieee8021dInterfaceData::NOTASSIGNED);
713  jPort->setState(Ieee8021dInterfaceData::DISCARDING);
714  jPort->setNextUpgrade(simTime() + migrateTime);
715  }
716  else {
717  jPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
718  jPort->setState(Ieee8021dInterfaceData::FORWARDING);
719  }
721  macTable->flush(j);
722  }
724 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
Definition: Ieee8021dInterfaceData.h:39
simtime_t migrateTime
Definition: RSTP.h:49
virtual void scheduleNextUpgrade()
schedule next upgrade self-message
Definition: RSTP.cc:54
Definition: Ieee8021dInterfaceData.h:37
virtual void initInterfacedata(unsigned int portNum)
Definition: RSTP.cc:693
IMACAddressTable * macTable
Definition: STPBase.h:47
virtual void flush(int portno)=0
Clears portno cache.
Definition: Ieee8021dInterfaceData.h:37
Definition: Ieee8021dInterfaceData.h:39
unsigned int numPorts
Definition: STPBase.h:37
virtual int inet::RSTP::numInitStages ( ) const
inlineoverridevirtual

Reimplemented from inet::STPBase.

59 { return NUM_INIT_STAGES; }
The number of initialization stages.
Definition: InitStages.h:116
void inet::RSTP::printState ( )
protectedvirtual

Prints current data base info.

663 {
664  // prints current database info
665  EV_DETAIL << "Switch " << findContainingNode(this)->getFullName() << " state:" << endl;
666  int rootIndex = getRootIndex();
667  EV_DETAIL << " Priority: " << bridgePriority << endl;
668  EV_DETAIL << " Local MAC: " << bridgeAddress << endl;
669  if (rootIndex >= 0) {
670  Ieee8021dInterfaceData *rootPort = getPortInterfaceData(rootIndex);
671  EV_DETAIL << " Root Priority: " << rootPort->getRootPriority() << endl;
672  EV_DETAIL << " Root Address: " << rootPort->getRootAddress().str() << endl;
673  EV_DETAIL << " Cost: " << rootPort->getRootPathCost() << endl;
674  EV_DETAIL << " Age: " << rootPort->getAge() << endl;
675  EV_DETAIL << " Bridge Priority: " << rootPort->getBridgePriority() << endl;
676  EV_DETAIL << " Bridge Address: " << rootPort->getBridgeAddress().str() << endl;
677  EV_DETAIL << " Src TxGate Priority: " << rootPort->getPortPriority() << endl;
678  EV_DETAIL << " Src TxGate: " << rootPort->getPortNum() << endl;
679  }
680  EV_DETAIL << "Port State/Role:" << endl;
681  for (unsigned int i = 0; i < numPorts; i++) {
682  Ieee8021dInterfaceData *iPort = getPortInterfaceData(i);
683  EV_DETAIL << " " << i << ": " << iPort->getStateName() << "/" << iPort->getRoleName() << (iPort->isEdge() ? " (Client)" : "") << endl;
684  }
685  EV_DETAIL << "Per-port best sources, Root/Src:" << endl;
686  for (unsigned int i = 0; i < numPorts; i++) {
687  Ieee8021dInterfaceData *iPort = getPortInterfaceData(i);
688  EV_DETAIL << " " << i << ": " << iPort->getRootAddress().str() << "/" << iPort->getBridgeAddress().str() << endl;
689  }
690  EV_DETAIL << endl;
691 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
unsigned int bridgePriority
Definition: STPBase.h:39
virtual int getRootIndex() const
Obtains the root gate index.
Definition: STPBase.cc:161
cModule * findContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:56
MACAddress bridgeAddress
Definition: STPBase.h:40
unsigned int numPorts
Definition: STPBase.h:37
bool inet::RSTP::processBetterSource ( BPDU frame,
unsigned int  arrival 
)
protectedvirtual

Referenced by processBPDU().

313 {
314  EV_DETAIL << "Better BDPU received than the current best for this port." << endl;
315  // update that port rstp info
316  updateInterfacedata(frame, arrivalPortNum);
317  Ieee8021dInterfaceData *arrivalPort = getPortInterfaceData(arrivalPortNum);
318  int r = getRootIndex();
319  if (r == -1) {
320  EV_DETAIL << "There was no root. Setting the arrival port to root." << endl;
321  // there was no root
322  arrivalPort->setRole(Ieee8021dInterfaceData::ROOT);
323  arrivalPort->setState(Ieee8021dInterfaceData::FORWARDING);
324  arrivalPort->setLostBPDU(0);
325  flushOtherPorts(arrivalPortNum);
326  return true;
327  }
328  else {
329  Ieee8021dInterfaceData *rootPort = getPortInterfaceData(r);
330  // there was a Root -> challenge 2 (compare with the root)
331  int case2 = compareInterfacedata(r, frame, arrivalPort->getLinkCost()); // comparing with root port's BPDU
332  int case3 = 0;
333 
334  switch (case2) {
335  case SIMILAR: // double link to the same port of the root source -> Tie breaking (better local port first)
336  EV_DETAIL << "Double link to the same port of the root source." << endl;
337  if (rootPort->getPortPriority() < arrivalPort->getPortPriority()
338  || (rootPort->getPortPriority() == arrivalPort->getPortPriority() && (unsigned int)r < arrivalPortNum))
339  {
340  // flushing that port
341  EV_DETAIL << "The current root has better local port. Setting the arrival port to alternate." << endl;
342  macTable->flush(arrivalPortNum);
343  arrivalPort->setRole(Ieee8021dInterfaceData::ALTERNATE);
344  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
345  arrivalPort->setLostBPDU(0);
346  }
347  else {
348  if (arrivalPort->getState() != Ieee8021dInterfaceData::FORWARDING)
349  flushOtherPorts(arrivalPortNum);
350  else
351  macTable->flush(r); // flushing r, needed in case arrival were previously FORWARDING
352  EV_DETAIL << "This has better local port. Setting the arrival port to root. Setting current root port (port " << r << ") to alternate." << endl;
353  rootPort->setRole(Ieee8021dInterfaceData::ALTERNATE);
354  rootPort->setState(Ieee8021dInterfaceData::DISCARDING); // comes from root, preserve lostBPDU
355  arrivalPort->setRole(Ieee8021dInterfaceData::ROOT);
356  arrivalPort->setState(Ieee8021dInterfaceData::FORWARDING);
357  arrivalPort->setLostBPDU(0);
358  macTable->copyTable(r, arrivalPortNum); // copy cache from old to new root
359  // the change does not deserve flooding
360  }
361  break;
362 
363  case BETTER_ROOT: // new port rstp info is better than the root in another gate -> root change
364  EV_DETAIL << "Better root received than the current root. Setting the arrival port to root." << endl;
365  for (unsigned int i = 0; i < numPorts; i++) {
366  Ieee8021dInterfaceData *iPort = getPortInterfaceData(i);
367  if (!iPort->isEdge()) { // avoiding clients reseting
368  if (arrivalPort->getState() != Ieee8021dInterfaceData::FORWARDING)
369  iPort->setTCWhile(simTime() + tcWhileTime);
370  macTable->flush(i);
371  if (i != (unsigned)arrivalPortNum) {
372  iPort->setRole(Ieee8021dInterfaceData::NOTASSIGNED);
373  iPort->setState(Ieee8021dInterfaceData::DISCARDING);
374  iPort->setNextUpgrade(simTime() + migrateTime);
377  }
378  }
379  }
380  arrivalPort->setRole(Ieee8021dInterfaceData::ROOT);
381  arrivalPort->setState(Ieee8021dInterfaceData::FORWARDING);
382  arrivalPort->setLostBPDU(0);
383 
384  return true;
385 
386  case BETTER_RPC: // same that Root but better RPC
387  case BETTER_SRC: // same that Root RPC but better source
388  case BETTER_PORT: // same that root RPC and source but better port
389  if (arrivalPort->getState() != Ieee8021dInterfaceData::FORWARDING) {
390  EV_DETAIL << "Better route to the current root. Setting the arrival port to root." << endl;
391  flushOtherPorts(arrivalPortNum);
392  }
393  arrivalPort->setRole(Ieee8021dInterfaceData::ROOT);
394  arrivalPort->setState(Ieee8021dInterfaceData::FORWARDING);
395  arrivalPort->setLostBPDU(0);
396  rootPort->setRole(Ieee8021dInterfaceData::ALTERNATE); // temporary, just one port can be root at contest time
397  macTable->copyTable(r, arrivalPortNum); // copy cache from old to new root
398  case3 = contestInterfacedata(r);
399  if (case3 >= 0) {
400  EV_DETAIL << "Setting current root port (port " << r << ") to alternate." << endl;
401  rootPort->setRole(Ieee8021dInterfaceData::ALTERNATE);
402  rootPort->setState(Ieee8021dInterfaceData::DISCARDING);
403  // not lostBPDU reset
404  // flushing r
405  macTable->flush(r);
406  }
407  else {
408  EV_DETAIL << "Setting current root port (port " << r << ") to designated." << endl;
409  rootPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
410  rootPort->setState(Ieee8021dInterfaceData::DISCARDING);
411  rootPort->setNextUpgrade(simTime() + forwardDelay);
413  }
414  return true;
415 
416  case WORSE_ROOT:
417  EV_DETAIL << "Worse BDPU received than the current root. Sending BPDU to show him a better root as soon as possible." << endl;
418  sendBPDU(arrivalPortNum); // BPDU to show him a better root as soon as possible
419  break;
420 
421  case WORSE_RPC: // same Root but worse RPC
422  case WORSE_SRC: // same Root RPC but worse source
423  case WORSE_PORT: // same Root RPC and source but worse port
424  case3 = contestInterfacedata(frame, arrivalPortNum); // case 0 not possible
425  if (case3 < 0) {
426  EV_DETAIL << "Worse route to the current root. Setting the arrival port to designated." << endl;
427  arrivalPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
428  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
429  arrivalPort->setNextUpgrade(simTime() + forwardDelay);
431  sendBPDU(arrivalPortNum); // BPDU to show him a better root as soon as possible
432  }
433  else {
434  EV_DETAIL << "Worse route to the current root. Setting the arrival port to alternate." << endl;
435  // flush arrival
436  macTable->flush(arrivalPortNum);
437  arrivalPort->setRole(Ieee8021dInterfaceData::ALTERNATE);
438  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
439  arrivalPort->setLostBPDU(0);
440  }
441  break;
442  }
443  }
444  return false;
445 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
Definition: Ieee8021dInterfaceData.h:39
virtual void copyTable(int portA, int portB)=0
Copy cache from portA to portB port.
virtual int getRootIndex() const
Obtains the root gate index.
Definition: STPBase.cc:161
Definition: RSTP.h:44
simtime_t migrateTime
Definition: RSTP.h:49
Definition: RSTP.h:45
Definition: Ieee8021dInterfaceData.h:37
virtual void scheduleNextUpgrade()
schedule next upgrade self-message
Definition: RSTP.cc:54
Definition: Ieee8021dInterfaceData.h:37
virtual void initInterfacedata(unsigned int portNum)
Definition: RSTP.cc:693
Definition: RSTP.h:44
simtime_t forwardDelay
Definition: STPBase.h:44
Definition: RSTP.h:45
Definition: RSTP.h:44
IMACAddressTable * macTable
Definition: STPBase.h:47
Definition: RSTP.h:44
Definition: RSTP.h:45
virtual CompareResult contestInterfacedata(BPDU *msg, unsigned int portNum)
Compares the BPDU frame with the BPDU this module would send through that port.
Definition: RSTP.cc:755
Definition: RSTP.h:45
simtime_t tcWhileTime
Definition: RSTP.h:50
virtual void flush(int portno)=0
Clears portno cache.
virtual void flushOtherPorts(unsigned int portNum)
flush all port expect one
Definition: RSTP.cc:844
virtual void sendBPDU(int port)
Sends BPDU through a port.
Definition: RSTP.cc:617
Definition: Ieee8021dInterfaceData.h:37
virtual CompareResult compareInterfacedata(unsigned int portNum, BPDU *msg, int linkCost)
Compares a port&#39;s best BPDU with a BPDU frame.
Definition: RSTP.cc:770
Definition: Ieee8021dInterfaceData.h:39
Definition: Ieee8021dInterfaceData.h:37
unsigned int numPorts
Definition: STPBase.h:37
Definition: RSTP.h:44
virtual void updateInterfacedata(BPDU *frame, unsigned int portNum)
Update Interfacedata with the content of the BDPU frame.
Definition: RSTP.cc:726
void inet::RSTP::processBPDU ( BPDU frame,
unsigned int  arrival 
)
protectedvirtual

Referenced by handleIncomingFrame().

292 {
293  //three challenges.
294  //
295  //first: vs best received BPDU for that port --------->case
296  //second: vs root BPDU--------------------------------->case1
297  //third: vs BPDU that would be sent from this Bridge.->case2
298  Ieee8021dInterfaceData *arrivalPort = getPortInterfaceData(arrivalPortNum);
299  bool flood = false;
300  if (compareInterfacedata(arrivalPortNum, frame, arrivalPort->getLinkCost()) > 0 //better root
301  && frame->getRootAddress().compareTo(bridgeAddress) != 0) // root will not participate in a loop with its own address
302  flood = processBetterSource(frame, arrivalPortNum);
303  else if (frame->getBridgeAddress().compareTo(arrivalPort->getBridgeAddress()) == 0 // worse or similar, but the same source
304  && frame->getRootAddress().compareTo(bridgeAddress) != 0) // root will not participate
305  flood = processSameSource(frame, arrivalPortNum);
306  if (flood) {
307  sendBPDUs(); //expedited BPDU
308  sendTCNtoRoot();
309  }
310 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
virtual bool processSameSource(BPDU *frame, unsigned int arrival)
Definition: RSTP.cc:447
virtual void sendBPDUs()
Sends BPDUs through all ports, if they are required.
Definition: RSTP.cc:603
virtual void sendTCNtoRoot()
If root TCWhile has not expired, sends a BPDU to the Root with TCFlag=true.
Definition: RSTP.cc:565
MACAddress bridgeAddress
Definition: STPBase.h:40
virtual bool processBetterSource(BPDU *frame, unsigned int arrival)
Definition: RSTP.cc:312
virtual CompareResult compareInterfacedata(unsigned int portNum, BPDU *msg, int linkCost)
Compares a port&#39;s best BPDU with a BPDU frame.
Definition: RSTP.cc:770
bool inet::RSTP::processSameSource ( BPDU frame,
unsigned int  arrival 
)
protectedvirtual

Referenced by processBPDU().

448 {
449  EV_DETAIL << "BDPU received from the same source than the current best for this port" << endl;
450  Ieee8021dInterfaceData *arrivalPort = getPortInterfaceData(arrivalPortNum);
451  int case0 = compareInterfacedata(arrivalPortNum, frame, arrivalPort->getLinkCost());
452  // source has updated BPDU information
453  switch (case0) {
454  case SIMILAR:
455  arrivalPort->setLostBPDU(0); // same BPDU, not updated
456  break;
457 
458  case WORSE_ROOT:
459  EV_DETAIL << "Worse root received than the current best for this port." << endl;
460  if (arrivalPort->getRole() == Ieee8021dInterfaceData::ROOT) {
461  int alternative = getBestAlternate(); // searching for alternate
462  if (alternative >= 0) {
463  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;
464  Ieee8021dInterfaceData *alternativePort = getPortInterfaceData(alternative);
465  arrivalPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
466  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
467  arrivalPort->setNextUpgrade(simTime() + forwardDelay);
469  macTable->copyTable(arrivalPortNum, alternative); // copy cache from old to new root
470  flushOtherPorts(alternative);
471  alternativePort->setRole(Ieee8021dInterfaceData::ROOT);
472  alternativePort->setState(Ieee8021dInterfaceData::FORWARDING); // comes from alternate, preserves lostBPDU
473  updateInterfacedata(frame, arrivalPortNum);
474  sendBPDU(arrivalPortNum); // show him a better Root as soon as possible
475  }
476  else {
477  EV_DETAIL << "This port was the root and there no alternative. Initialize all ports" << endl;
478  int case2 = 0;
479  initPorts(); // allowing other ports to contest again
480  // flushing all ports
481  for (unsigned int j = 0; j < numPorts; j++)
482  macTable->flush(j);
483  case2 = compareInterfacedata(arrivalPortNum, frame, arrivalPort->getLinkCost());
484  if (case2 > 0) {
485  EV_DETAIL << "This switch is not better, keep arrival port as a ROOT" << endl;
486  updateInterfacedata(frame, arrivalPortNum); // if this module is not better, keep it as a ROOT
487  arrivalPort->setRole(Ieee8021dInterfaceData::ROOT);
488  arrivalPort->setState(Ieee8021dInterfaceData::FORWARDING);
489  }
490  // propagating new information
491  return true;
492  }
493  }
494  else if (arrivalPort->getRole() == Ieee8021dInterfaceData::ALTERNATE) {
495  EV_DETAIL << "This port was an alternate, setting to designated" << endl;
496  arrivalPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
497  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
498  arrivalPort->setNextUpgrade(simTime() + forwardDelay);
500  updateInterfacedata(frame, arrivalPortNum);
501  sendBPDU(arrivalPortNum); //Show him a better Root as soon as possible
502  }
503  break;
504 
505  case WORSE_RPC:
506  case WORSE_SRC:
507  case WORSE_PORT:
508  EV_DETAIL << "Worse route to the current root than the current best for this port." << endl;
509  if (arrivalPort->getRole() == Ieee8021dInterfaceData::ROOT) {
510  arrivalPort->setLostBPDU(0);
511  int alternative = getBestAlternate(); // searching for alternate
512  if (alternative >= 0) {
513  Ieee8021dInterfaceData *alternativePort = getPortInterfaceData(alternative);
514  int case2 = 0;
515  case2 = compareInterfacedata(alternative, frame, arrivalPort->getLinkCost());
516  if (case2 < 0) { // if alternate is better, change
517  alternativePort->setRole(Ieee8021dInterfaceData::ROOT);
518  alternativePort->setState(Ieee8021dInterfaceData::FORWARDING);
519  arrivalPort->setRole(Ieee8021dInterfaceData::DESIGNATED); // temporary, just one port can be root at contest time
520  int case3 = 0;
521  case3 = contestInterfacedata(frame, arrivalPortNum);
522  if (case3 < 0) {
523  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;
524  arrivalPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
525  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
526  arrivalPort->setNextUpgrade(simTime() + forwardDelay);
528  }
529  else {
530  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;
531  arrivalPort->setRole(Ieee8021dInterfaceData::ALTERNATE);
532  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
533  }
534  flushOtherPorts(alternative);
535  macTable->copyTable(arrivalPortNum, alternative); // copy cache from old to new root
536  }
537  }
538  updateInterfacedata(frame, arrivalPortNum);
539  // propagating new information
540  return true;
541  // if alternate is worse than root, or there is not alternate, keep old root as root
542  }
543  else if (arrivalPort->getRole() == Ieee8021dInterfaceData::ALTERNATE) {
544  int case2 = 0;
545  case2 = contestInterfacedata(frame, arrivalPortNum);
546  if (case2 < 0) {
547  EV_DETAIL << "This port was an alternate, setting to designated" << endl;
548  arrivalPort->setRole(Ieee8021dInterfaceData::DESIGNATED); // if the frame is worse than this module generated frame, switch to Designated/Discarding
549  arrivalPort->setState(Ieee8021dInterfaceData::DISCARDING);
550  arrivalPort->setNextUpgrade(simTime() + forwardDelay);
552  sendBPDU(arrivalPortNum); // show him a better BPDU as soon as possible
553  }
554  else {
555  arrivalPort->setLostBPDU(0); // if it is better than this module generated frame, keep it as alternate
556  // this does not deserve expedited BPDU
557  }
558  }
559  updateInterfacedata(frame, arrivalPortNum);
560  break;
561  }
562  return false;
563 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
Definition: Ieee8021dInterfaceData.h:39
virtual void copyTable(int portA, int portB)=0
Copy cache from portA to portB port.
Definition: RSTP.h:44
Definition: Ieee8021dInterfaceData.h:37
virtual void scheduleNextUpgrade()
schedule next upgrade self-message
Definition: RSTP.cc:54
Definition: Ieee8021dInterfaceData.h:37
Definition: RSTP.h:44
simtime_t forwardDelay
Definition: STPBase.h:44
Definition: RSTP.h:44
IMACAddressTable * macTable
Definition: STPBase.h:47
Definition: RSTP.h:44
virtual CompareResult contestInterfacedata(BPDU *msg, unsigned int portNum)
Compares the BPDU frame with the BPDU this module would send through that port.
Definition: RSTP.cc:755
virtual void flush(int portno)=0
Clears portno cache.
virtual void flushOtherPorts(unsigned int portNum)
flush all port expect one
Definition: RSTP.cc:844
virtual void sendBPDU(int port)
Sends BPDU through a port.
Definition: RSTP.cc:617
virtual CompareResult compareInterfacedata(unsigned int portNum, BPDU *msg, int linkCost)
Compares a port&#39;s best BPDU with a BPDU frame.
Definition: RSTP.cc:770
Definition: Ieee8021dInterfaceData.h:39
Definition: Ieee8021dInterfaceData.h:37
unsigned int numPorts
Definition: STPBase.h:37
virtual void initPorts()
initialize RSTP dynamic information
Definition: RSTP.cc:707
virtual int getBestAlternate()
Gets the best alternate port.
Definition: RSTP.cc:817
Definition: RSTP.h:44
virtual void updateInterfacedata(BPDU *frame, unsigned int portNum)
Update Interfacedata with the content of the BDPU frame.
Definition: RSTP.cc:726
void inet::RSTP::receiveSignal ( cComponent *  source,
simsignal_t  signalID,
cObject *  obj,
cObject *  details 
)
overridevirtual

Reimplemented from inet::STPBase.

856 {
857  Enter_Method_Silent();
858 
859  if (signalID == NF_INTERFACE_STATE_CHANGED) {
860  InterfaceEntry *changedIE = check_and_cast<const InterfaceEntryChangeDetails *>(obj)->getInterfaceEntry();
861  for (unsigned int i = 0; i < numPorts; i++) {
862  InterfaceEntry *gateIfEntry = getPortInterfaceEntry(i);
863  if (gateIfEntry == changedIE) {
864  if (gateIfEntry->hasCarrier()) {
865  Ieee8021dInterfaceData *iPort = getPortInterfaceData(i);
866  if (iPort->getRole() == Ieee8021dInterfaceData::NOTASSIGNED)
867  iPort->setNextUpgrade(simTime() + migrateTime);
868  else if (iPort->getRole() == Ieee8021dInterfaceData::DESIGNATED
869  && (iPort->getState() == Ieee8021dInterfaceData::DISCARDING || iPort->getState() == Ieee8021dInterfaceData::LEARNING))
870  iPort->setNextUpgrade(simTime() + forwardDelay);
872  }
873  }
874  }
875  }
876 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
Definition: Ieee8021dInterfaceData.h:39
simtime_t migrateTime
Definition: RSTP.h:49
Definition: Ieee8021dInterfaceData.h:39
virtual void scheduleNextUpgrade()
schedule next upgrade self-message
Definition: RSTP.cc:54
InterfaceEntry * getPortInterfaceEntry(unsigned int portNum)
Gets InterfaceEntry for port number.
Definition: STPBase.cc:149
Definition: Ieee8021dInterfaceData.h:37
simtime_t forwardDelay
Definition: STPBase.h:44
simsignal_t NF_INTERFACE_STATE_CHANGED
Definition: NotifierConsts.cc:50
Definition: Ieee8021dInterfaceData.h:37
unsigned int numPorts
Definition: STPBase.h:37
void inet::RSTP::scheduleNextUpgrade ( )
protectedvirtual

schedule next upgrade self-message

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

55 {
56  cancelEvent(upgradeTimer);
57  Ieee8021dInterfaceData *nextInterfaceData = nullptr;
58  for (unsigned int i = 0; i < numPorts; i++) {
59  if (getPortInterfaceEntry(i)->hasCarrier()) {
60  Ieee8021dInterfaceData *iPort = getPortInterfaceData(i);
61  if (iPort->getRole() == Ieee8021dInterfaceData::NOTASSIGNED) {
62  if (nextInterfaceData == nullptr)
63  nextInterfaceData = iPort;
64  else if (iPort->getNextUpgrade() < nextInterfaceData->getNextUpgrade())
65  nextInterfaceData = iPort;
66  }
67  else if (iPort->getRole() == Ieee8021dInterfaceData::DESIGNATED) {
68  if (iPort->getState() == Ieee8021dInterfaceData::DISCARDING) {
69  if (nextInterfaceData == nullptr)
70  nextInterfaceData = iPort;
71  else if (iPort->getNextUpgrade() < nextInterfaceData->getNextUpgrade())
72  nextInterfaceData = iPort;
73  }
74  else if (iPort->getState() == Ieee8021dInterfaceData::LEARNING) {
75  if (nextInterfaceData == nullptr)
76  nextInterfaceData = iPort;
77  else if (iPort->getNextUpgrade() < nextInterfaceData->getNextUpgrade())
78  nextInterfaceData = iPort;
79  }
80  }
81  }
82  }
83  if (nextInterfaceData != nullptr)
84  scheduleAt(nextInterfaceData->getNextUpgrade(), upgradeTimer);
85 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
Definition: Ieee8021dInterfaceData.h:39
Definition: Ieee8021dInterfaceData.h:39
InterfaceEntry * getPortInterfaceEntry(unsigned int portNum)
Gets InterfaceEntry for port number.
Definition: STPBase.cc:149
Definition: Ieee8021dInterfaceData.h:37
cMessage * upgradeTimer
Definition: RSTP.h:54
Definition: Ieee8021dInterfaceData.h:37
unsigned int numPorts
Definition: STPBase.h:37
void inet::RSTP::sendBPDU ( int  port)
protectedvirtual

Sends BPDU through a port.

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

618 {
619  // send a BPDU throuth port
620  Ieee8021dInterfaceData *iport = getPortInterfaceData(port);
621  int r = getRootIndex();
622  Ieee8021dInterfaceData *rootPort;
623  if (r != -1)
624  rootPort = getPortInterfaceData(r);
625  if (iport->getRole() != Ieee8021dInterfaceData::DISABLED) {
626  BPDU *frame = new BPDU();
627  Ieee802Ctrl *etherctrl = new Ieee802Ctrl();
628  if (r != -1) {
629  frame->setRootPriority(rootPort->getRootPriority());
630  frame->setRootAddress(rootPort->getRootAddress());
631  frame->setMessageAge(rootPort->getAge());
632  frame->setRootPathCost(rootPort->getRootPathCost());
633  }
634  else {
635  frame->setRootPriority(bridgePriority);
636  frame->setRootAddress(bridgeAddress);
637  frame->setMessageAge(0);
638  frame->setRootPathCost(0);
639  }
640  frame->setBridgePriority(bridgePriority);
641  frame->setTcaFlag(false);
642  frame->setPortNum(port);
643  frame->setBridgeAddress(bridgeAddress);
644  if (simTime() < iport->getTCWhile())
645  frame->setTcFlag(true);
646  else
647  frame->setTcFlag(false);
648  frame->setName("BPDU");
649  frame->setMaxAge(maxAge);
650  frame->setHelloTime(helloTime);
651  frame->setForwardDelay(forwardDelay);
652  if (frame->getByteLength() < MIN_ETHERNET_FRAME_BYTES)
653  frame->setByteLength(MIN_ETHERNET_FRAME_BYTES);
654  etherctrl->setSrc(bridgeAddress);
655  etherctrl->setDest(MACAddress::STP_MULTICAST_ADDRESS);
656  etherctrl->setSwitchPort(port);
657  frame->setControlInfo(etherctrl);
658  send(frame, "relayOut");
659  }
660 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
unsigned int bridgePriority
Definition: STPBase.h:39
virtual int getRootIndex() const
Obtains the root gate index.
Definition: STPBase.cc:161
simtime_t maxAge
Definition: STPBase.h:42
#define MIN_ETHERNET_FRAME_BYTES
Definition: Ethernet.h:31
simtime_t forwardDelay
Definition: STPBase.h:44
static const MACAddress STP_MULTICAST_ADDRESS
The spanning tree protocol bridge&#39;s multicast address, 01:80:C2:00:00:00.
Definition: MACAddress.h:66
MACAddress bridgeAddress
Definition: STPBase.h:40
Definition: Ieee8021dInterfaceData.h:37
simtime_t helloTime
Definition: STPBase.h:43
void inet::RSTP::sendBPDUs ( )
protectedvirtual

Sends BPDUs through all ports, if they are required.

Referenced by handleHelloTime(), and processBPDU().

604 {
605  // send BPDUs through all ports, if they are required
606  for (unsigned int i = 0; i < numPorts; i++) {
607  Ieee8021dInterfaceData *iPort = getPortInterfaceData(i);
608  if ((iPort->getRole() != Ieee8021dInterfaceData::ROOT)
609  && (iPort->getRole() != Ieee8021dInterfaceData::ALTERNATE)
610  && (iPort->getRole() != Ieee8021dInterfaceData::DISABLED) && (!iPort->isEdge()))
611  {
612  sendBPDU(i);
613  }
614  }
615 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
Definition: Ieee8021dInterfaceData.h:37
virtual void sendBPDU(int port)
Sends BPDU through a port.
Definition: RSTP.cc:617
Definition: Ieee8021dInterfaceData.h:37
Definition: Ieee8021dInterfaceData.h:37
unsigned int numPorts
Definition: STPBase.h:37
void inet::RSTP::sendTCNtoRoot ( )
protectedvirtual

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

Referenced by handleHelloTime(), and processBPDU().

566 {
567  // if TCWhile is not expired, sends BPDU with TC flag to the root
568  this->bubble("SendTCNtoRoot");
569  EV_DETAIL << "SendTCNtoRoot" << endl;
570  int r = getRootIndex();
571  if ((r >= 0) && ((unsigned int)r < numPorts)) {
572  Ieee8021dInterfaceData *rootPort = getPortInterfaceData(r);
573  if (rootPort->getRole() != Ieee8021dInterfaceData::DISABLED) {
574  if (simTime() < rootPort->getTCWhile()) {
575  BPDU *frame = new BPDU();
576  Ieee802Ctrl *etherctrl = new Ieee802Ctrl();
577 
578  frame->setRootPriority(rootPort->getRootPriority());
579  frame->setRootAddress(rootPort->getRootAddress());
580  frame->setMessageAge(rootPort->getAge());
581  frame->setRootPathCost(rootPort->getRootPathCost());
582  frame->setBridgePriority(bridgePriority);
583  frame->setTcaFlag(false);
584  frame->setPortNum(r);
585  frame->setBridgeAddress(bridgeAddress);
586  frame->setTcFlag(true);
587  frame->setName("BPDU");
588  frame->setMaxAge(maxAge);
589  frame->setHelloTime(helloTime);
590  frame->setForwardDelay(forwardDelay);
591  if (frame->getByteLength() < MIN_ETHERNET_FRAME_BYTES)
592  frame->setByteLength(MIN_ETHERNET_FRAME_BYTES);
593  etherctrl->setSrc(bridgeAddress);
594  etherctrl->setDest(MACAddress::STP_MULTICAST_ADDRESS);
595  etherctrl->setSwitchPort(r);
596  frame->setControlInfo(etherctrl);
597  send(frame, "relayOut");
598  }
599  }
600  }
601 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140
unsigned int bridgePriority
Definition: STPBase.h:39
virtual int getRootIndex() const
Obtains the root gate index.
Definition: STPBase.cc:161
simtime_t maxAge
Definition: STPBase.h:42
#define MIN_ETHERNET_FRAME_BYTES
Definition: Ethernet.h:31
simtime_t forwardDelay
Definition: STPBase.h:44
static const MACAddress STP_MULTICAST_ADDRESS
The spanning tree protocol bridge&#39;s multicast address, 01:80:C2:00:00:00.
Definition: MACAddress.h:66
MACAddress bridgeAddress
Definition: STPBase.h:40
Definition: Ieee8021dInterfaceData.h:37
simtime_t helloTime
Definition: STPBase.h:43
unsigned int numPorts
Definition: STPBase.h:37
void inet::RSTP::start ( )
overrideprotectedvirtual

Reimplemented from inet::STPBase.

879 {
880  STPBase::start();
881  initPorts();
882  scheduleAt(simTime(), helloTimer);
883 }
virtual void start()
Definition: STPBase.cc:65
cMessage * helloTimer
Definition: RSTP.h:53
virtual void initPorts()
initialize RSTP dynamic information
Definition: RSTP.cc:707
void inet::RSTP::stop ( )
overrideprotectedvirtual

Reimplemented from inet::STPBase.

886 {
887  STPBase::stop();
888  cancelEvent(helloTimer);
889  cancelEvent(upgradeTimer);
890 }
cMessage * upgradeTimer
Definition: RSTP.h:54
cMessage * helloTimer
Definition: RSTP.h:53
virtual void stop()
Definition: STPBase.cc:76
void inet::RSTP::updateInterfacedata ( BPDU frame,
unsigned int  portNum 
)
protectedvirtual

Update Interfacedata with the content of the BDPU frame.

Referenced by processBetterSource(), and processSameSource().

727 {
728  Ieee8021dInterfaceData *ifd = getPortInterfaceData(portNum);
729  ifd->setRootPriority(frame->getRootPriority());
730  ifd->setRootAddress(frame->getRootAddress());
731  ifd->setRootPathCost(frame->getRootPathCost() + ifd->getLinkCost());
732  ifd->setAge(frame->getMessageAge() + 1);
733  ifd->setBridgePriority(frame->getBridgePriority());
734  ifd->setBridgeAddress(frame->getBridgeAddress());
735  ifd->setPortPriority(frame->getPortPriority());
736  ifd->setPortNum(frame->getPortNum());
737  ifd->setLostBPDU(0);
738 }
Ieee8021dInterfaceData * getPortInterfaceData(unsigned int portNum)
Gets Ieee8021dInterfaceData for port number.
Definition: STPBase.cc:140

Member Data Documentation

bool inet::RSTP::autoEdge = false
protected

Referenced by initialize().

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

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

simtime_t inet::RSTP::migrateTime
protected
simtime_t inet::RSTP::tcWhileTime
protected
cMessage* inet::RSTP::upgradeTimer = nullptr
protected

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