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

Implements the Spanning Tree Protocol. More...

#include <Stp.h>

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

Public Types

typedef Ieee8021dInterfaceData::PortInfo PortInfo
 

Public Member Functions

 Stp ()
 
virtual ~Stp ()
 
void handleBPDU (Packet *packet, const Ptr< const BpduCfg > &bpdu)
 
virtual void initInterfacedata (unsigned int interfaceId)
 
void handleTCN (Packet *packet, const Ptr< const BpduTcn > &tcn)
 Topology change handling. More...
 
virtual void handleMessageWhenUp (cMessage *msg) override
 
virtual void initialize (int stage) override
 
virtual int numInitStages () const override
 
void generateBPDU (int interfaceId, const MacAddress &address=MacAddress::STP_MULTICAST_ADDRESS, bool tcFlag=false, bool tcaFlag=false)
 
void generateHelloBPDUs ()
 
void generateTCN ()
 
int comparePorts (const Ieee8021dInterfaceData *portA, const Ieee8021dInterfaceData *portB)
 
int compareBridgeIDs (unsigned int aPriority, MacAddress aAddress, unsigned int bPriority, MacAddress bAddress)
 
int comparePortIDs (unsigned int aPriority, unsigned int aNum, unsigned int bPriority, unsigned int bNum)
 
bool isSuperiorBPDU (int interfaceId, const Ptr< const BpduCfg > &bpdu)
 
void setSuperiorBPDU (int interfaceId, const Ptr< const BpduCfg > &bpdu)
 
void handleTick ()
 
void checkTimers ()
 
void checkParametersChange ()
 
void initPortTable ()
 
void selectRootPort ()
 
void selectDesignatedPorts ()
 
void setAllDesignated ()
 
void lostRoot ()
 
void lostAlternate ()
 
void reset ()
 
bool checkRootEligibility ()
 
void tryRoot ()
 
- 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
 
virtual void receiveSignal (cComponent *source, simsignal_t signalID, cObject *obj, cObject *details) override
 
- Public Member Functions inherited from inet::OperationalMixin< cSimpleModule >
virtual ~OperationalMixin ()
 }@ More...
 
- Public Member Functions inherited from inet::ILifecycle
virtual ~ILifecycle ()
 

Protected Member Functions

virtual void start () override
 
virtual void stop () override
 
- 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

bool isRoot = false
 
unsigned int rootInterfaceId = 0
 
std::vector< unsigned int > desPorts
 
unsigned int rootPathCost = 0
 
unsigned int rootPriority = 0
 
MacAddress rootAddress
 
simtime_t currentMaxAge
 
simtime_t currentFwdDelay
 
simtime_t currentHelloTime
 
simtime_t helloTime
 
unsigned int currentBridgePriority = 0
 
bool topologyChangeNotification = false
 
bool topologyChangeRecvd = false
 
PortInfo defaultPort
 
cMessage * tick = 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
 

Static Protected Attributes

static const double tickInterval = 1
 

Friends

std::ostream & operator<< (std::ostream &os, const Ieee8021dInterfaceData::PortRole r)
 
std::ostream & operator<< (std::ostream &os, const Ieee8021dInterfaceData::PortState s)
 
std::ostream & operator<< (std::ostream &os, Ieee8021dInterfaceData *p)
 
std::ostream & operator<< (std::ostream &os, Stp i)
 

Additional Inherited Members

- Protected Types inherited from inet::OperationalMixin< cSimpleModule >
enum  State
 

Detailed Description

Implements the Spanning Tree Protocol.

See the NED file for details.

Member Typedef Documentation

◆ PortInfo

Constructor & Destructor Documentation

◆ Stp()

inet::Stp::Stp ( )
26 {
27 }

◆ ~Stp()

inet::Stp::~Stp ( )
virtual
50 {
51  cancelAndDelete(tick);
52 }

Member Function Documentation

◆ checkParametersChange()

void inet::Stp::checkParametersChange ( )
400 {
401  if (isRoot) {
405  }
408  reset();
409  }
410 }

Referenced by handleTick().

◆ checkRootEligibility()

bool inet::Stp::checkRootEligibility ( )
413 {
414  for (unsigned int i = 0; i < numPorts; i++) {
415  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
416  const Ieee8021dInterfaceData *port = getPortInterfaceData(interfaceId);
417 
418  if (compareBridgeIDs(port->getRootPriority(), port->getRootAddress(), bridgePriority, bridgeAddress) > 0)
419  return false;
420  }
421 
422  return true;
423 }

Referenced by tryRoot().

◆ checkTimers()

void inet::Stp::checkTimers ( )
334 {
335  Ieee8021dInterfaceData *port;
336 
337  // hello timer check
338  if (helloTime >= currentHelloTime) {
339  // only the root switch can generate Hello BPDUs
340  if (isRoot)
342 
343  helloTime = 0;
344  }
345 
346  // information age check
347  for (unsigned int i = 0; i < numPorts; i++) {
348  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
349  port = getPortInterfaceDataForUpdate(interfaceId);
350 
351  if (port->getAge() >= currentMaxAge) {
352  EV_DETAIL << "Port=" << i << " reached its maximum age. Setting it to the default port info." << endl;
353  if (port->getRole() == Ieee8021dInterfaceData::ROOT) {
354  initInterfacedata(interfaceId);
355  lostRoot();
356  }
357  else {
358  initInterfacedata(interfaceId);
359  lostAlternate();
360  }
361  }
362  }
363 
364  // fdWhile timer
365  for (unsigned int i = 0; i < numPorts; i++) {
366  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
367  port = getPortInterfaceDataForUpdate(interfaceId);
368 
369  // ROOT / DESIGNATED, can transition
370  if (port->getRole() == Ieee8021dInterfaceData::ROOT || port->getRole() == Ieee8021dInterfaceData::DESIGNATED) {
371  if (port->getFdWhile() >= currentFwdDelay) {
372  switch (port->getState()) {
374  EV_DETAIL << "Port=" << interfaceId << " goes into learning state." << endl;
375  port->setState(Ieee8021dInterfaceData::LEARNING);
376  port->setFdWhile(0);
377  break;
378 
380  EV_DETAIL << "Port=" << interfaceId << " goes into forwarding state." << endl;
381  port->setState(Ieee8021dInterfaceData::FORWARDING);
382  port->setFdWhile(0);
383  break;
384 
385  default:
386  port->setFdWhile(0);
387  break;
388  }
389  }
390  }
391  else {
392  EV_DETAIL << "Port=" << interfaceId << " goes into discarding state." << endl;
393  port->setFdWhile(0);
394  port->setState(Ieee8021dInterfaceData::DISCARDING);
395  }
396  }
397 }

Referenced by handleTick().

◆ compareBridgeIDs()

int inet::Stp::compareBridgeIDs ( unsigned int  aPriority,
MacAddress  aAddress,
unsigned int  bPriority,
MacAddress  bAddress 
)
446 {
447  if (aPriority < bPriority)
448  return 1; // A is superior
449  else if (aPriority > bPriority)
450  return -1;
451 
452  // APR == BPR
453  if (aAddress.compareTo(bAddress) == -1)
454  return 1; // A is superior
455  else if (aAddress.compareTo(bAddress) == 1)
456  return -1;
457 
458  // A==B
459  // (can happen if bridge have two port connected to one not bridged lan,
460  // "cable loopback"
461  return 0;
462 }

Referenced by checkRootEligibility(), and comparePorts().

◆ comparePortIDs()

int inet::Stp::comparePortIDs ( unsigned int  aPriority,
unsigned int  aNum,
unsigned int  bPriority,
unsigned int  bNum 
)
465 {
466  if (aPriority < bPriority)
467  return 1; // A is superior
468 
469  else if (aPriority > bPriority)
470  return -1;
471 
472  // APR == BPR
473  if (aNum < bNum)
474  return 1; // A is superior
475 
476  else if (aNum > bNum)
477  return -1;
478 
479  // A==B
480  return 0;
481 }

Referenced by comparePorts().

◆ comparePorts()

int inet::Stp::comparePorts ( const Ieee8021dInterfaceData portA,
const Ieee8021dInterfaceData portB 
)
484 {
485  int result;
486 
487  result = compareBridgeIDs(portA->getRootPriority(), portA->getRootAddress(), portB->getRootPriority(),
488  portB->getRootAddress());
489 
490  // not same, so pass result
491  if (result != 0)
492  return result;
493 
494  if (portA->getRootPathCost() < portB->getRootPathCost())
495  return 1;
496 
497  if (portA->getRootPathCost() > portB->getRootPathCost())
498  return -1;
499 
500  // designated bridge
501  result = compareBridgeIDs(portA->getBridgePriority(), portA->getBridgeAddress(), portB->getBridgePriority(),
502  portB->getBridgeAddress());
503 
504  // not same, so pass result
505  if (result != 0)
506  return result;
507 
508  // designated port of designated Bridge
509  result = comparePortIDs(portA->getPortPriority(), portA->getPortNum(), portB->getPortPriority(), portB->getPortNum());
510 
511  // not same, so pass result
512  if (result != 0)
513  return result;
514 
515  return 0; // same
516 }

Referenced by isSuperiorBPDU(), selectDesignatedPorts(), and selectRootPort().

◆ generateBPDU()

void inet::Stp::generateBPDU ( int  interfaceId,
const MacAddress address = MacAddress::STP_MULTICAST_ADDRESS,
bool  tcFlag = false,
bool  tcaFlag = false 
)
165 {
166  Packet *packet = new Packet("BPDU");
167  const auto& bpdu = makeShared<BpduCfg>();
168  auto macAddressReq = packet->addTag<MacAddressReq>();
169  macAddressReq->setSrcAddress(bridgeAddress);
170  macAddressReq->setDestAddress(address);
171  packet->addTag<InterfaceReq>()->setInterfaceId(interfaceId);
172  packet->addTag<PacketProtocolTag>()->setProtocol(&Protocol::stp);
173  packet->addTag<DispatchProtocolReq>()->setProtocol(&Protocol::ieee8022llc);
174 
175  bpdu->setProtocolIdentifier(SPANNING_TREE_PROTOCOL);
176  bpdu->setProtocolVersionIdentifier(SPANNING_TREE);
177 
178  bpdu->setBridgeAddress(bridgeAddress);
179  bpdu->setBridgePriority(bridgePriority);
180  bpdu->setRootPathCost(rootPathCost);
181  bpdu->setRootAddress(rootAddress);
182  bpdu->setRootPriority(rootPriority);
183  bpdu->setPortNum(interfaceId);
184  bpdu->setPortPriority(getPortInterfaceData(interfaceId)->getPriority());
185  bpdu->setMessageAge(0);
186  bpdu->setMaxAge(currentMaxAge);
187  bpdu->setHelloTime(currentHelloTime);
188  bpdu->setForwardDelay(currentFwdDelay);
189 
191  if (isRoot || tcFlag) {
192  bpdu->setTcFlag(true);
193  bpdu->setTcaFlag(false);
194  }
195  else if (tcaFlag) {
196  bpdu->setTcFlag(false);
197  bpdu->setTcaFlag(true);
198  }
199  }
200 
201  packet->insertAtBack(bpdu);
202  send(packet, "relayOut");
203 }

Referenced by generateHelloBPDUs(), handleBPDU(), and handleTCN().

◆ generateHelloBPDUs()

void inet::Stp::generateHelloBPDUs ( )
292 {
293  EV_INFO << "It is hello time. Root switch sending hello BPDUs on all its ports." << endl;
294 
295  // send hello BPDUs on all ports
296  for (unsigned int i = 0; i < numPorts; i++) {
297  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
298  generateBPDU(interfaceId);
299  }
300 }

Referenced by checkTimers().

◆ generateTCN()

void inet::Stp::generateTCN ( )
206 {
207  // there is something to notify
210  // exist root port to notifying
212  Packet *packet = new Packet("BPDU-TCN");
213  const auto& tcn = makeShared<BpduTcn>();
214  tcn->setProtocolIdentifier(SPANNING_TREE_PROTOCOL);
215  tcn->setProtocolVersionIdentifier(SPANNING_TREE);
216 
217  auto macAddressReq = packet->addTag<MacAddressReq>();
218  macAddressReq->setSrcAddress(bridgeAddress);
219  macAddressReq->setDestAddress(MacAddress::STP_MULTICAST_ADDRESS);
220  packet->addTag<InterfaceReq>()->setInterfaceId(rootInterfaceId);
221  packet->addTag<PacketProtocolTag>()->setProtocol(&Protocol::stp);
222  packet->addTag<DispatchProtocolReq>()->setProtocol(&Protocol::ieee8022llc);
223 
224  packet->insertAtBack(tcn);
225  EV_INFO << "The topology has changed. Sending Topology Change Notification BPDU " << tcn << " to the Root Switch." << endl;
226  send(packet, "relayOut");
227  }
228  }
229 }

Referenced by handleTick().

◆ handleBPDU()

void inet::Stp::handleBPDU ( Packet packet,
const Ptr< const BpduCfg > &  bpdu 
)
93 {
94  int arrivalGate = packet->getTag<InterfaceInd>()->getInterfaceId();
95  const Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalGate);
96 
97  if (bpdu->getTcaFlag()) {
98  topologyChangeRecvd = true;
100  }
101 
102  // get inferior BPDU, reply with superior
103  if (!isSuperiorBPDU(arrivalGate, bpdu)) {
104  if (port->getRole() == Ieee8021dInterfaceData::DESIGNATED) {
105  EV_DETAIL << "Inferior Configuration BPDU " << bpdu << " arrived on port=" << arrivalGate << " responding to it with a superior BPDU." << endl;
106  generateBPDU(arrivalGate);
107  }
108  }
109  // BPDU from root
110  else if (port->getRole() == Ieee8021dInterfaceData::ROOT) {
111  EV_INFO << "Configuration BPDU " << bpdu << " arrived from Root Switch." << endl;
112 
113  if (bpdu->getTcFlag()) {
114  EV_DEBUG << "MacForwardingTable aging time set to " << currentFwdDelay << "." << endl;
115  macTable->setAgingTime(currentFwdDelay);
116 
117  // config BPDU with TC flag
118  for (auto& elem : desPorts)
120  }
121  else {
122  macTable->setAgingTime(-1);
123 
124  EV_INFO << "Sending BPDUs on all designated ports." << endl;
125 
126  // BPDUs are sent on all designated ports
127  for (auto& elem : desPorts)
128  generateBPDU(elem);
129  }
130  }
131 
132  tryRoot();
133  delete packet;
134 }

Referenced by handleMessageWhenUp().

◆ handleMessageWhenUp()

void inet::Stp::handleMessageWhenUp ( cMessage *  msg)
overridevirtual

Implements inet::OperationalMixin< cSimpleModule >.

66 {
67  if (!msg->isSelfMessage()) {
68  Packet *packet = check_and_cast<Packet *>(msg);
69  const auto& bpdu = packet->peekAtFront<BpduBase>();
70 
71  switch (bpdu->getBpduType()) {
72  case BPDU_CFG:
73  handleBPDU(packet, CHK(dynamicPtrCast<const BpduCfg>(bpdu)));
74  break;
75  case BPDU_TCN:
76  handleTCN(packet, CHK(dynamicPtrCast<const BpduTcn>(bpdu)));
77  break;
78  default:
79  throw cRuntimeError("unknown BPDU TYPE: %d", bpdu->getBpduType());
80  }
81  }
82  else {
83  if (msg == tick) {
84  handleTick();
85  scheduleAfter(1, tick);
86  }
87  else
88  throw cRuntimeError("Unknown self-message received");
89  }
90 }

◆ handleTCN()

void inet::Stp::handleTCN ( Packet packet,
const Ptr< const BpduTcn > &  tcn 
)

Topology change handling.

137 {
138  EV_INFO << "Topology Change Notification BPDU " << tcn << " arrived." << endl;
140 
141  int arrivalGate = packet->getTag<InterfaceInd>()->getInterfaceId();
142  const auto& addressInd = packet->getTag<MacAddressInd>();
143  MacAddress srcAddress = addressInd->getSrcAddress();
144  MacAddress destAddress = addressInd->getDestAddress();
145 
146  // send ACK to the sender
147  EV_INFO << "Sending Topology Change Notification ACK." << endl;
148  generateBPDU(arrivalGate, srcAddress, false, true);
149 
150  if (!isRoot) {
151  Packet *outPacket = new Packet(packet->getName());
152  outPacket->insertAtBack(tcn);
153  outPacket->addTag<InterfaceReq>()->setInterfaceId(rootInterfaceId);
154  auto macAddressReq = outPacket->addTag<MacAddressReq>();
155  macAddressReq->setSrcAddress(bridgeAddress);
156  macAddressReq->setDestAddress(destAddress);
157  outPacket->addTag<PacketProtocolTag>()->setProtocol(&Protocol::stp);
158  outPacket->addTag<DispatchProtocolReq>()->setProtocol(&Protocol::ieee8022llc);
159  send(outPacket, "relayOut");
160  }
161  delete packet;
162 }

Referenced by handleMessageWhenUp().

◆ handleTick()

void inet::Stp::handleTick ( )
303 {
304  // hello BPDU timer
305  if (isRoot)
306  helloTime = helloTime + 1;
307  else
308  helloTime = 0;
309 
310  for (unsigned int i = 0; i < numPorts; i++) {
311  int interfaceId = ifTable->getInterface(i)->getInterfaceId();
312  auto port = getPortInterfaceDataForUpdate(interfaceId);
313 
314  // disabled ports don't count
315  if (port->getRole() == Ieee8021dInterfaceData::DISABLED)
316  continue;
317 
318  // increment the MessageAge and FdWhile timers
319  if (port->getRole() != Ieee8021dInterfaceData::DESIGNATED) {
320  EV_DEBUG << "Message Age timer incremented on port=" << interfaceId << endl;
321  port->setAge(port->getAge() + tickInterval);
322  }
323  if (port->getRole() == Ieee8021dInterfaceData::ROOT || port->getRole() == Ieee8021dInterfaceData::DESIGNATED) {
324  EV_DEBUG << "Forward While timer incremented on port=" << interfaceId << endl;
325  port->setFdWhile(port->getFdWhile() + tickInterval);
326  }
327  }
328  checkTimers();
330  generateTCN();
331 }

Referenced by handleMessageWhenUp().

◆ initialize()

void inet::Stp::initialize ( int  stage)
overridevirtual

Reimplemented from inet::StpBase.

30 {
31  StpBase::initialize(stage);
32 
33  if (stage == INITSTAGE_LOCAL) {
34  tick = new cMessage("STP_TICK", 0);
35  WATCH(bridgeAddress);
36  }
37  else if (stage == INITSTAGE_LINK_LAYER) {
38  registerProtocol(Protocol::stp, gate("relayOut"), gate("relayIn"));
39 
40  for (int i = 0; i < ifTable->getNumInterfaces(); i++) {
41  auto ie = ifTable->getInterface(i);
42  if (!ie->isLoopback() && ie->isWired() && ie->isMulticast() /* && ie->getProtocol() == &Protocol::ethernetMac */) { // TODO check protocol
43  ie->addMulticastMacAddress(MacAddress::STP_MULTICAST_ADDRESS);
44  }
45  }
46  }
47 }

◆ initInterfacedata()

void inet::Stp::initInterfacedata ( unsigned int  interfaceId)
virtual
679 {
680  auto ifd = getPortInterfaceDataForUpdate(interfaceId);
682  ifd->setState(Ieee8021dInterfaceData::DISCARDING);
683  ifd->setRootPriority(bridgePriority);
684  ifd->setRootAddress(bridgeAddress);
685  ifd->setRootPathCost(0);
686  ifd->setAge(0);
687  ifd->setBridgePriority(bridgePriority);
688  ifd->setBridgeAddress(bridgeAddress);
689  ifd->setPortPriority(-1);
690  ifd->setPortNum(-1);
691  ifd->setLostBPDU(0);
692 }

Referenced by checkTimers(), and initPortTable().

◆ initPortTable()

void inet::Stp::initPortTable ( )
55 {
56  EV_DEBUG << "IEE8021D Interface Data initialization. Setting port infos to the protocol defaults." << endl;
57  for (unsigned int i = 0; i < numPorts; i++) {
58  auto ie = ifTable->getInterface(i);
59  if (!ie->isLoopback() && ie->isWired() && ie->isMulticast() /* && ie->getProtocol() == &Protocol::ethernetMac */) { // TODO check protocol
60  initInterfacedata(ie->getInterfaceId());
61  }
62  }
63 }

Referenced by start().

◆ isSuperiorBPDU()

bool inet::Stp::isSuperiorBPDU ( int  interfaceId,
const Ptr< const BpduCfg > &  bpdu 
)
232 {
233  auto port = getPortInterfaceDataForUpdate(interfaceId);
234  Ieee8021dInterfaceData *xBpdu = new Ieee8021dInterfaceData();
235 
236  int result;
237 
238  xBpdu->setRootPriority(bpdu->getRootPriority());
239  xBpdu->setRootAddress(bpdu->getRootAddress());
240  xBpdu->setRootPathCost(bpdu->getRootPathCost() + port->getLinkCost());
241  xBpdu->setBridgePriority(bpdu->getBridgePriority());
242  xBpdu->setBridgeAddress(bpdu->getBridgeAddress());
243  xBpdu->setPortPriority(bpdu->getPortPriority());
244  xBpdu->setPortNum(bpdu->getPortNum());
245 
246  result = comparePorts(port, xBpdu);
247 
248  // port is superior
249  if (result > 0) {
250  delete xBpdu;
251  return false;
252  }
253 
254  if (result < 0) {
255  // BPDU is superior
256  port->setFdWhile(0); // renew info
257  port->setState(Ieee8021dInterfaceData::DISCARDING);
258  setSuperiorBPDU(interfaceId, bpdu); // renew information
259  delete xBpdu;
260  return true;
261  }
262 
263  setSuperiorBPDU(interfaceId, bpdu); // renew information
264  delete xBpdu;
265  return true;
266 }

Referenced by handleBPDU().

◆ lostAlternate()

void inet::Stp::lostAlternate ( )
630 {
633 }

Referenced by checkTimers().

◆ lostRoot()

void inet::Stp::lostRoot ( )
624 {
626  tryRoot();
627 }

Referenced by checkTimers().

◆ numInitStages()

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

Reimplemented from inet::StpBase.

74 { return NUM_INIT_STAGES; }

◆ reset()

void inet::Stp::reset ( )
636 {
637  // upon booting all switches believe themselves to be the root
638  isRoot = true;
641  rootPathCost = 0;
646 }

Referenced by checkParametersChange().

◆ selectDesignatedPorts()

void inet::Stp::selectDesignatedPorts ( )
562 {
563  // select designated ports
564  desPorts.clear();
565  Ieee8021dInterfaceData *bridgeGlobal = new Ieee8021dInterfaceData();
566  int result;
567 
568  bridgeGlobal->setBridgePriority(bridgePriority);
569  bridgeGlobal->setBridgeAddress(bridgeAddress);
570  bridgeGlobal->setRootAddress(rootAddress);
571  bridgeGlobal->setRootPriority(rootPriority);
572 
573  for (unsigned int i = 0; i < numPorts; i++) {
574  NetworkInterface *ie = ifTable->getInterface(i);
575  auto portData = ie->getProtocolDataForUpdate<Ieee8021dInterfaceData>();
576  ASSERT(portData != nullptr);
577 
578  if (portData->getRole() == Ieee8021dInterfaceData::ROOT || portData->getRole() == Ieee8021dInterfaceData::DISABLED)
579  continue;
580 
581  bridgeGlobal->setPortPriority(portData->getPriority());
582  int interfaceId = ie->getInterfaceId();
583  bridgeGlobal->setPortNum(interfaceId);
584 
585  bridgeGlobal->setRootPathCost(rootPathCost + portData->getLinkCost());
586 
587  result = comparePorts(bridgeGlobal, portData);
588 
589  if (result > 0) {
590  EV_DETAIL << "Port=" << ie->getFullName() << " is elected as designated portData." << endl;
591  desPorts.push_back(interfaceId);
592  portData->setRole(Ieee8021dInterfaceData::DESIGNATED);
593  continue;
594  }
595  if (result < 0) {
596  EV_DETAIL << "Port=" << ie->getFullName() << " goes into alternate role." << endl;
597  portData->setRole(Ieee8021dInterfaceData::ALTERNATE);
598  continue;
599  }
600  }
601  delete bridgeGlobal;
602 }

Referenced by lostAlternate(), and tryRoot().

◆ selectRootPort()

void inet::Stp::selectRootPort ( )
519 {
520  desPorts.clear();
521  unsigned int xRootIdx = 0;
522  int result;
523  auto best = ifTable->getInterface(0)->getProtocolData<Ieee8021dInterfaceData>();
524  Ieee8021dInterfaceData *currentPort = nullptr;
525 
526  for (unsigned int i = 0; i < numPorts; i++) {
527  currentPort = ifTable->getInterface(i)->getProtocolDataForUpdate<Ieee8021dInterfaceData>();
528  currentPort->setRole(Ieee8021dInterfaceData::NOTASSIGNED);
529  result = comparePorts(currentPort, best);
530  if (result > 0) {
531  xRootIdx = i;
532  best = currentPort;
533  continue;
534  }
535  if (result < 0) {
536  continue;
537  }
538  if (currentPort->getPriority() < best->getPriority()) {
539  xRootIdx = i;
540  best = currentPort;
541  continue;
542  }
543  }
544 
545  unsigned int xRootInterfaceId = ifTable->getInterface(xRootIdx)->getInterfaceId();
546  if (rootInterfaceId != xRootInterfaceId) {
547  EV_DETAIL << "Port=" << xRootInterfaceId << " selected as root port." << endl;
549  }
550  rootInterfaceId = xRootInterfaceId;
552  rootPathCost = best->getRootPathCost();
553  rootAddress = best->getRootAddress();
554  rootPriority = best->getRootPriority();
555 
556  currentMaxAge = best->getMaxAge();
557  currentFwdDelay = best->getFwdDelay();
558  currentHelloTime = best->getHelloTime();
559 }

Referenced by tryRoot().

◆ setAllDesignated()

void inet::Stp::setAllDesignated ( )
605 {
606  // all ports of the root switch are designated ports
607  EV_DETAIL << "All ports become designated." << endl; // todo
608 
609  desPorts.clear();
610  for (unsigned int i = 0; i < numPorts; i++) {
611  NetworkInterface *ie = ifTable->getInterface(i);
612  auto portData = ie->getProtocolDataForUpdate<Ieee8021dInterfaceData>();
613  ASSERT(portData != nullptr);
614  if (portData->getRole() == Ieee8021dInterfaceData::DISABLED)
615  continue;
616 
617  int interfaceId = ie->getInterfaceId();
618  portData->setRole(Ieee8021dInterfaceData::DESIGNATED);
619  desPorts.push_back(interfaceId);
620  }
621 }

Referenced by reset(), start(), and tryRoot().

◆ setSuperiorBPDU()

void inet::Stp::setSuperiorBPDU ( int  interfaceId,
const Ptr< const BpduCfg > &  bpdu 
)
269 {
270  // BPDU is out-of-date
271  if (bpdu->getMessageAge() >= bpdu->getMaxAge())
272  return;
273 
274  auto portData = getPortInterfaceDataForUpdate(interfaceId);
275 
276  portData->setRootPriority(bpdu->getRootPriority());
277  portData->setRootAddress(bpdu->getRootAddress());
278  portData->setRootPathCost(bpdu->getRootPathCost() + portData->getLinkCost());
279  portData->setBridgePriority(bpdu->getBridgePriority());
280  portData->setBridgeAddress(bpdu->getBridgeAddress());
281  portData->setPortPriority(bpdu->getPortPriority());
282  portData->setPortNum(bpdu->getPortNum());
283  portData->setMaxAge(bpdu->getMaxAge());
284  portData->setFwdDelay(bpdu->getForwardDelay());
285  portData->setHelloTime(bpdu->getHelloTime());
286 
287  // we just set new port info so reset the age timer
288  portData->setAge(0);
289 }

Referenced by isSuperiorBPDU().

◆ start()

void inet::Stp::start ( )
overrideprotectedvirtual

Reimplemented from inet::StpBase.

649 {
650  StpBase::start();
651 
652  initPortTable();
654  isRoot = true;
656  topologyChangeRecvd = true;
659  rootPathCost = 0;
660  rootInterfaceId = ifTable->getInterface(0)->getInterfaceId();
664  helloTime = 0;
666 
667  scheduleAfter(tickInterval, tick);
668 }

◆ stop()

void inet::Stp::stop ( )
overrideprotectedvirtual

Reimplemented from inet::StpBase.

671 {
672  StpBase::stop();
673  isRoot = false;
675  cancelEvent(tick);
676 }

◆ tryRoot()

void inet::Stp::tryRoot ( )
426 {
427  if (checkRootEligibility()) {
428  EV_DETAIL << "Switch is elected as root switch." << endl;
429  isRoot = true;
433  rootPathCost = 0;
437  }
438  else {
439  isRoot = false;
440  selectRootPort();
442  }
443 }

Referenced by handleBPDU(), and lostRoot().

Friends And Related Function Documentation

◆ operator<< [1/4]

std::ostream& operator<< ( std::ostream &  os,
const Ieee8021dInterfaceData::PortRole  r 
)
friend
153 {
154  switch (r) {
156  os << "Unkn";
157  break;
158 
160  os << "Altr";
161  break;
162 
164  os << "Desg";
165  break;
166 
168  os << "Root";
169  break;
170 
171  default:
172  os << "<?>";
173  break;
174  }
175 
176  return os;
177 }

◆ operator<< [2/4]

std::ostream& operator<< ( std::ostream &  os,
const Ieee8021dInterfaceData::PortState  s 
)
friend
180 {
181  switch (s) {
183  os << "DIS";
184  break;
185 
187  os << "LRN";
188  break;
189 
191  os << "FWD";
192  break;
193 
194  default:
195  os << "<?>";
196  break;
197  }
198 
199  return os;
200 }

◆ operator<< [3/4]

std::ostream& operator<< ( std::ostream &  os,
Ieee8021dInterfaceData p 
)
friend
203 {
204  os << "[";
205  if (p->isLearning())
206  os << "L";
207  else
208  os << "_";
209  if (p->isForwarding())
210  os << "F";
211  else
212  os << "_";
213  os << "]";
214 
215  os << " " << p->getRole() << " " << p->getState() << " ";
216  os << p->getLinkCost() << " ";
217  os << p->getPriority() << " ";
218 
219  return os;
220 }

◆ operator<< [4/4]

std::ostream& operator<< ( std::ostream &  os,
Stp  i 
)
friend
223 {
224  os << "RootID Priority: " << i.rootPriority << " \n";
225  os << " Address: " << i.rootAddress << " \n";
226  if (i.isRoot)
227  os << " This bridge is the Root. \n";
228  else {
229  os << " Cost: " << i.rootPathCost << " \n";
230  os << " Port: " << i.rootInterfaceId << " \n";
231  }
232  os << " Hello Time: " << i.currentHelloTime << " \n";
233  os << " Max Age: " << i.currentMaxAge << " \n";
234  os << " Forward Delay: " << i.currentFwdDelay << " \n";
235  os << "BridgeID Priority: " << i.bridgePriority << "\n";
236  os << " Address: " << i.bridgeAddress << " \n";
237  os << " Hello Time: " << i.helloTime << " \n";
238  os << " Max Age: " << i.maxAge << " \n";
239  os << " Forward Delay: " << i.forwardDelay << " \n";
240  os << "Port Flag Role State Cost Priority \n";
241  os << "-----------------------------------------\n";
242 
243  for (unsigned int x = 0; x < i.numPorts; x++)
244  os << x << " " << i.getPortInterfaceData(x) << " \n";
245 
246  return os;
247 }

Member Data Documentation

◆ currentBridgePriority

unsigned int inet::Stp::currentBridgePriority = 0
protected

Referenced by checkParametersChange(), and start().

◆ currentFwdDelay

simtime_t inet::Stp::currentFwdDelay
protected

◆ currentHelloTime

simtime_t inet::Stp::currentHelloTime
protected

◆ currentMaxAge

simtime_t inet::Stp::currentMaxAge
protected

◆ defaultPort

PortInfo inet::Stp::defaultPort
protected

◆ desPorts

std::vector<unsigned int> inet::Stp::desPorts
protected

◆ helloTime

simtime_t inet::Stp::helloTime
protected

◆ isRoot

bool inet::Stp::isRoot = false
protected

◆ rootAddress

◆ rootInterfaceId

unsigned int inet::Stp::rootInterfaceId = 0
protected

◆ rootPathCost

unsigned int inet::Stp::rootPathCost = 0
protected

◆ rootPriority

unsigned int inet::Stp::rootPriority = 0
protected

◆ tick

cMessage* inet::Stp::tick = nullptr
protected

◆ tickInterval

const double inet::Stp::tickInterval = 1
staticprotected

Referenced by handleTick(), and start().

◆ topologyChangeNotification

bool inet::Stp::topologyChangeNotification = false
protected

◆ topologyChangeRecvd

bool inet::Stp::topologyChangeRecvd = false
protected

Referenced by generateTCN(), handleBPDU(), and start().


The documentation for this class was generated from the following files:
CHK
#define CHK(x)
Definition: INETDefs.h:87
inet::Stp::currentHelloTime
simtime_t currentHelloTime
Definition: Stp.h:46
inet::Stp::comparePorts
int comparePorts(const Ieee8021dInterfaceData *portA, const Ieee8021dInterfaceData *portB)
Definition: Stp.cc:483
inet::Protocol::stp
static const Protocol stp
Definition: Protocol.h:111
inet::Stp::initPortTable
void initPortTable()
Definition: Stp.cc:54
inet::StpBase::ie
opp_component_ptr< NetworkInterface > ie
Definition: StpBase.h:39
inet::Stp::handleTCN
void handleTCN(Packet *packet, const Ptr< const BpduTcn > &tcn)
Topology change handling.
Definition: Stp.cc:136
inet::StpBase::bridgePriority
unsigned int bridgePriority
Definition: StpBase.h:29
inet::StpBase::getPortInterfaceDataForUpdate
Ieee8021dInterfaceData * getPortInterfaceDataForUpdate(unsigned int interfaceId)
Definition: StpBase.cc:140
inet::Stp::helloTime
simtime_t helloTime
Definition: Stp.h:47
inet::Ieee8021dInterfaceData::DESIGNATED
@ DESIGNATED
Definition: Ieee8021dInterfaceData.h:24
inet::Ieee8021dInterfaceData::ROOT
@ ROOT
Definition: Ieee8021dInterfaceData.h:24
inet::Stp::generateTCN
void generateTCN()
Definition: Stp.cc:205
inet::Stp::rootInterfaceId
unsigned int rootInterfaceId
Definition: Stp.h:36
inet::Stp::desPorts
std::vector< unsigned int > desPorts
Definition: Stp.h:37
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::Stp::isRoot
bool isRoot
Definition: Stp.h:35
inet::Stp::selectRootPort
void selectRootPort()
Definition: Stp.cc:518
inet::Stp::reset
void reset()
Definition: Stp.cc:635
inet::Stp::initInterfacedata
virtual void initInterfacedata(unsigned int interfaceId)
Definition: Stp.cc:678
inet::Stp::lostRoot
void lostRoot()
Definition: Stp.cc:623
inet::Stp::generateBPDU
void generateBPDU(int interfaceId, const MacAddress &address=MacAddress::STP_MULTICAST_ADDRESS, bool tcFlag=false, bool tcaFlag=false)
Definition: Stp.cc:164
inet::Stp::rootPathCost
unsigned int rootPathCost
Definition: Stp.h:40
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::Stp::compareBridgeIDs
int compareBridgeIDs(unsigned int aPriority, MacAddress aAddress, unsigned int bPriority, MacAddress bAddress)
Definition: Stp.cc:445
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::Stp::handleTick
void handleTick()
Definition: Stp.cc:302
PacketProtocolTag
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down PacketProtocolTag
Definition: IUdp-gates.txt:25
inet::Ieee8021dInterfaceData::setRole
void setRole(PortRole role)
Definition: Ieee8021dInterfaceData.h:126
inet::Stp::tryRoot
void tryRoot()
Definition: Stp.cc:425
inet::units::values::s
value< double, units::s > s
Definition: Units.h:1235
inet::Stp::tickInterval
static const double tickInterval
Definition: Stp.h:34
inet::Stp::handleBPDU
void handleBPDU(Packet *packet, const Ptr< const BpduCfg > &bpdu)
Definition: Stp.cc:92
inet::StpBase::bridgeAddress
MacAddress bridgeAddress
Definition: StpBase.h:30
inet::StpBase::ifTable
ModuleRefByPar< IInterfaceTable > ifTable
Definition: StpBase.h:38
inet::SPANNING_TREE
@ SPANNING_TREE
Definition: Ieee8021dBpdu_m.h:76
inet::Stp::tick
cMessage * tick
Definition: Stp.h:56
inet::Ieee8021dInterfaceData::FORWARDING
@ FORWARDING
Definition: Ieee8021dInterfaceData.h:26
inet::Stp::topologyChangeNotification
bool topologyChangeNotification
Definition: Stp.h:52
inet::Stp::setSuperiorBPDU
void setSuperiorBPDU(int interfaceId, const Ptr< const BpduCfg > &bpdu)
Definition: Stp.cc:268
inet::Stp::topologyChangeRecvd
bool topologyChangeRecvd
Definition: Stp.h:53
inet::BPDU_CFG
@ BPDU_CFG
Definition: Ieee8021dBpdu_m.h:96
inet::INITSTAGE_LOCAL
INET_API InitStage INITSTAGE_LOCAL
Initialization of local state that don't use or affect other modules includes:
inet::Ieee8021dInterfaceData::DISABLED
@ DISABLED
Definition: Ieee8021dInterfaceData.h:24
inet::StpBase::getPortInterfaceData
const Ieee8021dInterfaceData * getPortInterfaceData(unsigned int interfaceId) const
Gets Ieee8021dInterfaceData for interface ID.
Definition: StpBase.cc:135
inet::Stp::checkParametersChange
void checkParametersChange()
Definition: Stp.cc:399
NUM_INIT_STAGES
#define NUM_INIT_STAGES
Definition: InitStageRegistry.h:73
inet::Stp::currentBridgePriority
unsigned int currentBridgePriority
Definition: Stp.h:50
inet::Stp::checkTimers
void checkTimers()
Definition: Stp.cc:333
inet::Stp::currentMaxAge
simtime_t currentMaxAge
Definition: Stp.h:44
inet::Stp::setAllDesignated
void setAllDesignated()
Definition: Stp.cc:604
inet::StpBase::start
virtual void start()
Definition: StpBase.cc:48
inet::Stp::lostAlternate
void lostAlternate()
Definition: Stp.cc:629
inet::Ieee8021dInterfaceData::NOTASSIGNED
@ NOTASSIGNED
Definition: Ieee8021dInterfaceData.h:24
inet::StpBase::initialize
virtual void initialize(int stage) override
Definition: StpBase.cc:25
inet::Stp::isSuperiorBPDU
bool isSuperiorBPDU(int interfaceId, const Ptr< const BpduCfg > &bpdu)
Definition: Stp.cc:231
inet::Stp::rootAddress
MacAddress rootAddress
Definition: Stp.h:42
inet::Stp::currentFwdDelay
simtime_t currentFwdDelay
Definition: Stp.h:45
inet::Ieee8021dInterfaceData::ALTERNATE
@ ALTERNATE
Definition: Ieee8021dInterfaceData.h:24
inet::StpBase::maxAge
simtime_t maxAge
Definition: StpBase.h:32
inet::SPANNING_TREE_PROTOCOL
@ SPANNING_TREE_PROTOCOL
Definition: Ieee8021dBpdu_m.h:58
inet::Stp::comparePortIDs
int comparePortIDs(unsigned int aPriority, unsigned int aNum, unsigned int bPriority, unsigned int bNum)
Definition: Stp.cc:464
inet::Stp::rootPriority
unsigned int rootPriority
Definition: Stp.h:41
inet::StpBase::macTable
ModuleRefByPar< IMacForwardingTable > macTable
Definition: StpBase.h:37
inet::Stp::selectDesignatedPorts
void selectDesignatedPorts()
Definition: Stp.cc:561
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::BPDU_TCN
@ BPDU_TCN
Definition: Ieee8021dBpdu_m.h:97
inet::Stp::checkRootEligibility
bool checkRootEligibility()
Definition: Stp.cc:412
inet::INITSTAGE_LINK_LAYER
INET_API InitStage INITSTAGE_LINK_LAYER
Initialization of link-layer protocols.
inet::Ieee8021dInterfaceData::LEARNING
@ LEARNING
Definition: Ieee8021dInterfaceData.h:26
inet::Stp::generateHelloBPDUs
void generateHelloBPDUs()
Definition: Stp.cc:291
inet::StpBase::stop
virtual void stop()
Definition: StpBase.cc:58