From 58156b25443361585ef2b8cb83fcf6554cc5b741 Mon Sep 17 00:00:00 2001 From: Mani Amoozadeh Date: Sun, 8 Sep 2019 11:22:44 -0700 Subject: [PATCH 01/27] stp: reordering code to better reflect the execution flow --- src/inet/linklayer/ieee8021d/stp/Stp.cc | 588 ++++++++++++------------ 1 file changed, 295 insertions(+), 293 deletions(-) diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc index 1d039e99c56..cfdbc130f8e 100644 --- a/src/inet/linklayer/ieee8021d/stp/Stp.cc +++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc @@ -55,6 +55,28 @@ Stp::~Stp() cancelAndDelete(tick); } +void Stp::start() +{ + StpBase::start(); + + initPortTable(); + currentBridgePriority = bridgePriority; + isRoot = true; + topologyChangeNotification = true; + topologyChangeRecvd = true; + rootPriority = bridgePriority; + rootAddress = bridgeAddress; + rootPathCost = 0; + rootInterfaceId = ifTable->getInterface(0)->getInterfaceId(); + currentHelloTime = helloTime; + currentMaxAge = maxAge; + currentFwdDelay = forwardDelay; + helloTime = 0; + setAllDesignated(); + + scheduleAt(simTime() + tickInterval, tick); +} + void Stp::initPortTable() { EV_DEBUG << "IEE8021D Interface Data initialization. Setting port infos to the protocol defaults." << endl; @@ -63,6 +85,22 @@ void Stp::initPortTable() } } +void Stp::initInterfacedata(unsigned int interfaceId) +{ + Ieee8021dInterfaceData *ifd = getPortInterfaceData(interfaceId); + ifd->setRole(Ieee8021dInterfaceData::NOTASSIGNED); + ifd->setState(Ieee8021dInterfaceData::DISCARDING); + ifd->setRootPriority(bridgePriority); + ifd->setRootAddress(bridgeAddress); + ifd->setRootPathCost(0); + ifd->setAge(0); + ifd->setBridgePriority(bridgePriority); + ifd->setBridgeAddress(bridgeAddress); + ifd->setPortPriority(-1); + ifd->setPortNum(-1); + ifd->setLostBPDU(0); +} + void Stp::handleMessageWhenUp(cMessage *msg) { if (!msg->isSelfMessage()) { @@ -84,76 +122,114 @@ void Stp::handleMessageWhenUp(cMessage *msg) } } -void Stp::handleBPDU(Packet *packet, const Ptr& bpdu) +void Stp::handleTick() { - int arrivalGate = packet->getTag()->getInterfaceId(); - Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalGate); + // hello BDPU timer + if (isRoot) + helloTime = helloTime + 1; + else + helloTime = 0; - if (bpdu->getTcaFlag()) { - topologyChangeRecvd = true; - topologyChangeNotification = false; - } + for (unsigned int i = 0; i < numPorts; i++) { + int interfaceId = ifTable->getInterface(i)->getInterfaceId(); + Ieee8021dInterfaceData *port = getPortInterfaceData(interfaceId); - // get inferior BPDU, reply with superior - if (!isSuperiorBPDU(arrivalGate, bpdu)) { - if (port->getRole() == Ieee8021dInterfaceData::DESIGNATED) { - EV_DETAIL << "Inferior Configuration BPDU " << bpdu << " arrived on port=" << arrivalGate << " responding to it with a superior BPDU." << endl; - generateBPDU(arrivalGate); + // disabled ports don't count + if (port->getRole() == Ieee8021dInterfaceData::DISABLED) + continue; + + // increment the MessageAge and FdWhile timers + if (port->getRole() != Ieee8021dInterfaceData::DESIGNATED) { + EV_DEBUG << "Message Age timer incremented on port=" << interfaceId << endl; + port->setAge(port->getAge() + tickInterval); + } + + if (port->getRole() == Ieee8021dInterfaceData::ROOT || port->getRole() == Ieee8021dInterfaceData::DESIGNATED) { + EV_DEBUG << "Forward While timer incremented on port=" << interfaceId << endl; + port->setFdWhile(port->getFdWhile() + tickInterval); } } - // BPDU from root - else if (port->getRole() == Ieee8021dInterfaceData::ROOT) { - EV_INFO << "Configuration BPDU " << bpdu << " arrived from Root Switch." << endl; - if (bpdu->getTcFlag()) { - EV_DEBUG << "MacAddressTable aging time set to " << currentFwdDelay << "." << endl; - macTable->setAgingTime(currentFwdDelay); + checkTimers(); + checkParametersChange(); + generateTCN(); +} - // config BPDU with TC flag - for (auto & elem : desPorts) - generateBPDU(elem, MacAddress::STP_MULTICAST_ADDRESS, true, false); - } - else { - macTable->resetDefaultAging(); +void Stp::checkTimers() +{ + Ieee8021dInterfaceData *port; - EV_INFO << "Sending BPDUs on all designated ports." << endl; + // hello timer check + if (helloTime >= currentHelloTime) { + // only the root switch can generate Hello BPDUs + if (isRoot) + generateHelloBDPUs(); - // BPDUs are sent on all designated ports - for (auto & elem : desPorts) - generateBPDU(elem); + helloTime = 0; + } + + // information age check + for (unsigned int i = 0; i < numPorts; i++) { + int interfaceId = ifTable->getInterface(i)->getInterfaceId(); + port = getPortInterfaceData(interfaceId); + + if (port->getAge() >= currentMaxAge) { + EV_DETAIL << "Port=" << i << " reached its maximum age. Setting it to the default port info." << endl; + if (port->getRole() == Ieee8021dInterfaceData::ROOT) { + initInterfacedata(interfaceId); + lostRoot(); + } + else { + initInterfacedata(interfaceId); + lostAlternate(); + } } } - tryRoot(); - delete packet; -} + // fdWhile timer + for (unsigned int i = 0; i < numPorts; i++) { + int interfaceId = ifTable->getInterface(i)->getInterfaceId(); + port = getPortInterfaceData(interfaceId); -void Stp::handleTCN(Packet *packet, const Ptr& tcn) -{ - EV_INFO << "Topology Change Notification BDPU " << tcn << " arrived." << endl; - topologyChangeNotification = true; + // ROOT / DESIGNATED, can transition + if (port->getRole() == Ieee8021dInterfaceData::ROOT || port->getRole() == Ieee8021dInterfaceData::DESIGNATED) { + if (port->getFdWhile() >= currentFwdDelay) { + switch (port->getState()) { + case Ieee8021dInterfaceData::DISCARDING: + EV_DETAIL << "Port=" << interfaceId << " goes into learning state." << endl; + port->setState(Ieee8021dInterfaceData::LEARNING); + port->setFdWhile(0); + break; - int arrivalGate = packet->getTag()->getInterfaceId(); - MacAddressInd *addressInd = packet->getTag(); - MacAddress srcAddress = addressInd->getSrcAddress(); - MacAddress destAddress = addressInd->getDestAddress(); + case Ieee8021dInterfaceData::LEARNING: + EV_DETAIL << "Port=" << interfaceId << " goes into forwarding state." << endl; + port->setState(Ieee8021dInterfaceData::FORWARDING); + port->setFdWhile(0); + break; - // send ACK to the sender - EV_INFO << "Sending Topology Change Notification ACK." << endl; - generateBPDU(arrivalGate, srcAddress, false, true); + default: + port->setFdWhile(0); + break; + } + } + } + else { + EV_DETAIL << "Port=" << interfaceId << " goes into discarding state." << endl; + port->setFdWhile(0); + port->setState(Ieee8021dInterfaceData::DISCARDING); + } + } +} - if (!isRoot) { - Packet *outPacket = new Packet(packet->getName()); - outPacket->insertAtBack(tcn); - outPacket->addTag()->setInterfaceId(rootInterfaceId); - auto macAddressReq = outPacket->addTag(); - macAddressReq->setSrcAddress(bridgeAddress); - macAddressReq->setDestAddress(destAddress); - outPacket->addTag()->setProtocol(&Protocol::stp); - outPacket->addTag()->setProtocol(&Protocol::ethernetMac); - send(outPacket, "relayOut"); +void Stp::generateHelloBDPUs() +{ + EV_INFO << "It is hello time. Root switch sending hello BDPUs on all its ports." << endl; + + // send hello BDPUs on all ports + for (unsigned int i = 0; i < numPorts; i++) { + int interfaceId = ifTable->getInterface(i)->getInterfaceId(); + generateBPDU(interfaceId); } - delete packet; } void Stp::generateBPDU(int interfaceId, const MacAddress& address, bool tcFlag, bool tcaFlag) @@ -198,6 +274,19 @@ void Stp::generateBPDU(int interfaceId, const MacAddress& address, bool tcFlag, send(packet, "relayOut"); } +void Stp::checkParametersChange() +{ + if (isRoot) { + currentHelloTime = helloTime; + currentMaxAge = maxAge; + currentFwdDelay = forwardDelay; + } + if (currentBridgePriority != bridgePriority) { + currentBridgePriority = bridgePriority; + reset(); + } +} + void Stp::generateTCN() { // there is something to notify @@ -213,18 +302,161 @@ void Stp::generateTCN() // 1 if Topology Change Notification BPDU tcn->setBpduType(1); - auto macAddressReq = packet->addTag(); - macAddressReq->setSrcAddress(bridgeAddress); - macAddressReq->setDestAddress(MacAddress::STP_MULTICAST_ADDRESS); - packet->addTag()->setInterfaceId(rootInterfaceId); - packet->addTag()->setProtocol(&Protocol::stp); - packet->addTag()->setProtocol(&Protocol::ethernetMac); + auto macAddressReq = packet->addTag(); + macAddressReq->setSrcAddress(bridgeAddress); + macAddressReq->setDestAddress(MacAddress::STP_MULTICAST_ADDRESS); + packet->addTag()->setInterfaceId(rootInterfaceId); + packet->addTag()->setProtocol(&Protocol::stp); + packet->addTag()->setProtocol(&Protocol::ethernetMac); + + packet->insertAtBack(tcn); + EV_INFO << "The topology has changed. Sending Topology Change Notification BPDU " << tcn << " to the Root Switch." << endl; + send(packet, "relayOut"); + } + } +} + +void Stp::setAllDesignated() +{ + // all ports of the root switch are designated ports + EV_DETAIL << "All ports become designated." << endl; // todo + + desPorts.clear(); + for (unsigned int i = 0; i < numPorts; i++) { + InterfaceEntry *ie = ifTable->getInterface(i); + Ieee8021dInterfaceData *portData = ie->getProtocolData(); + ASSERT(portData != nullptr); + if (portData->getRole() == Ieee8021dInterfaceData::DISABLED) + continue; + + int interfaceId = ie->getInterfaceId(); + portData->setRole(Ieee8021dInterfaceData::DESIGNATED); + desPorts.push_back(interfaceId); + } +} + +void Stp::handleBPDU(Packet *packet, const Ptr& bpdu) +{ + int arrivalGate = packet->getTag()->getInterfaceId(); + Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalGate); + + if (bpdu->getTcaFlag()) { + topologyChangeRecvd = true; + topologyChangeNotification = false; + } + + // get inferior BPDU, reply with superior + if (!isSuperiorBPDU(arrivalGate, bpdu)) { + if (port->getRole() == Ieee8021dInterfaceData::DESIGNATED) { + EV_DETAIL << "Inferior Configuration BPDU " << bpdu << " arrived on port=" << arrivalGate << " responding to it with a superior BPDU." << endl; + generateBPDU(arrivalGate); + } + } + // BPDU from root + else if (port->getRole() == Ieee8021dInterfaceData::ROOT) { + EV_INFO << "Configuration BPDU " << bpdu << " arrived from Root Switch." << endl; + + if (bpdu->getTcFlag()) { + EV_DEBUG << "MacAddressTable aging time set to " << currentFwdDelay << "." << endl; + macTable->setAgingTime(currentFwdDelay); + + // config BPDU with TC flag + for (auto & elem : desPorts) + generateBPDU(elem, MacAddress::STP_MULTICAST_ADDRESS, true, false); + } + else { + macTable->resetDefaultAging(); + + EV_INFO << "Sending BPDUs on all designated ports." << endl; + + // BPDUs are sent on all designated ports + for (auto & elem : desPorts) + generateBPDU(elem); + } + } + + tryRoot(); + delete packet; +} + +void Stp::tryRoot() +{ + if (checkRootEligibility()) { + EV_DETAIL << "Switch is elected as root switch." << endl; + isRoot = true; + setAllDesignated(); + rootPriority = bridgePriority; + rootAddress = bridgeAddress; + rootPathCost = 0; + currentHelloTime = helloTime; + currentMaxAge = maxAge; + currentFwdDelay = forwardDelay; + } + else { + isRoot = false; + selectRootPort(); + selectDesignatedPorts(); + } +} + +bool Stp::checkRootEligibility() +{ + for (unsigned int i = 0; i < numPorts; i++) { + int interfaceId = ifTable->getInterface(i)->getInterfaceId(); + Ieee8021dInterfaceData *port = getPortInterfaceData(interfaceId); + + if (compareBridgeIDs(port->getRootPriority(), port->getRootAddress(), bridgePriority, bridgeAddress) > 0) + return false; + } + + return true; +} + +int Stp::compareBridgeIDs(unsigned int aPriority, MacAddress aAddress, unsigned int bPriority, MacAddress bAddress) +{ + if (aPriority < bPriority) + return 1; // A is superior + else if (aPriority > bPriority) + return -1; + + // APR == BPR + if (aAddress.compareTo(bAddress) == -1) + return 1; // A is superior + else if (aAddress.compareTo(bAddress) == 1) + return -1; + + // A==B + // (can happen if bridge have two port connected to one not bridged lan, + // "cable loopback" + return 0; +} + +void Stp::handleTCN(Packet *packet, const Ptr& tcn) +{ + EV_INFO << "Topology Change Notification BDPU " << tcn << " arrived." << endl; + topologyChangeNotification = true; + + int arrivalGate = packet->getTag()->getInterfaceId(); + MacAddressInd *addressInd = packet->getTag(); + MacAddress srcAddress = addressInd->getSrcAddress(); + MacAddress destAddress = addressInd->getDestAddress(); + + // send ACK to the sender + EV_INFO << "Sending Topology Change Notification ACK." << endl; + generateBPDU(arrivalGate, srcAddress, false, true); - packet->insertAtBack(tcn); - EV_INFO << "The topology has changed. Sending Topology Change Notification BPDU " << tcn << " to the Root Switch." << endl; - send(packet, "relayOut"); - } + if (!isRoot) { + Packet *outPacket = new Packet(packet->getName()); + outPacket->insertAtBack(tcn); + outPacket->addTag()->setInterfaceId(rootInterfaceId); + auto macAddressReq = outPacket->addTag(); + macAddressReq->setSrcAddress(bridgeAddress); + macAddressReq->setDestAddress(destAddress); + outPacket->addTag()->setProtocol(&Protocol::stp); + outPacket->addTag()->setProtocol(&Protocol::ethernetMac); + send(outPacket, "relayOut"); } + delete packet; } bool Stp::isSuperiorBPDU(int interfaceId, const Ptr& bpdu) @@ -287,179 +519,6 @@ void Stp::setSuperiorBPDU(int interfaceId, const Ptr& bpdu) portData->setAge(0); } -void Stp::generateHelloBDPUs() -{ - EV_INFO << "It is hello time. Root switch sending hello BDPUs on all its ports." << endl; - - // send hello BDPUs on all ports - for (unsigned int i = 0; i < numPorts; i++) { - int interfaceId = ifTable->getInterface(i)->getInterfaceId(); - generateBPDU(interfaceId); - } -} - -void Stp::handleTick() -{ - // hello BDPU timer - if (isRoot) - helloTime = helloTime + 1; - else - helloTime = 0; - - for (unsigned int i = 0; i < numPorts; i++) { - int interfaceId = ifTable->getInterface(i)->getInterfaceId(); - Ieee8021dInterfaceData *port = getPortInterfaceData(interfaceId); - - // disabled ports don't count - if (port->getRole() == Ieee8021dInterfaceData::DISABLED) - continue; - - // increment the MessageAge and FdWhile timers - if (port->getRole() != Ieee8021dInterfaceData::DESIGNATED) { - EV_DEBUG << "Message Age timer incremented on port=" << interfaceId << endl; - port->setAge(port->getAge() + tickInterval); - } - if (port->getRole() == Ieee8021dInterfaceData::ROOT || port->getRole() == Ieee8021dInterfaceData::DESIGNATED) { - EV_DEBUG << "Forward While timer incremented on port=" << interfaceId << endl; - port->setFdWhile(port->getFdWhile() + tickInterval); - } - } - checkTimers(); - checkParametersChange(); - generateTCN(); -} - -void Stp::checkTimers() -{ - Ieee8021dInterfaceData *port; - - // hello timer check - if (helloTime >= currentHelloTime) { - // only the root switch can generate Hello BPDUs - if (isRoot) - generateHelloBDPUs(); - - helloTime = 0; - } - - // information age check - for (unsigned int i = 0; i < numPorts; i++) { - int interfaceId = ifTable->getInterface(i)->getInterfaceId(); - port = getPortInterfaceData(interfaceId); - - if (port->getAge() >= currentMaxAge) { - EV_DETAIL << "Port=" << i << " reached its maximum age. Setting it to the default port info." << endl; - if (port->getRole() == Ieee8021dInterfaceData::ROOT) { - initInterfacedata(interfaceId); - lostRoot(); - } - else { - initInterfacedata(interfaceId); - lostAlternate(); - } - } - } - - // fdWhile timer - for (unsigned int i = 0; i < numPorts; i++) { - int interfaceId = ifTable->getInterface(i)->getInterfaceId(); - port = getPortInterfaceData(interfaceId); - - // ROOT / DESIGNATED, can transition - if (port->getRole() == Ieee8021dInterfaceData::ROOT || port->getRole() == Ieee8021dInterfaceData::DESIGNATED) { - if (port->getFdWhile() >= currentFwdDelay) { - switch (port->getState()) { - case Ieee8021dInterfaceData::DISCARDING: - EV_DETAIL << "Port=" << interfaceId << " goes into learning state." << endl; - port->setState(Ieee8021dInterfaceData::LEARNING); - port->setFdWhile(0); - break; - - case Ieee8021dInterfaceData::LEARNING: - EV_DETAIL << "Port=" << interfaceId << " goes into forwarding state." << endl; - port->setState(Ieee8021dInterfaceData::FORWARDING); - port->setFdWhile(0); - break; - - default: - port->setFdWhile(0); - break; - } - } - } - else { - EV_DETAIL << "Port=" << interfaceId << " goes into discarding state." << endl; - port->setFdWhile(0); - port->setState(Ieee8021dInterfaceData::DISCARDING); - } - } -} - -void Stp::checkParametersChange() -{ - if (isRoot) { - currentHelloTime = helloTime; - currentMaxAge = maxAge; - currentFwdDelay = forwardDelay; - } - if (currentBridgePriority != bridgePriority) { - currentBridgePriority = bridgePriority; - reset(); - } -} - -bool Stp::checkRootEligibility() -{ - for (unsigned int i = 0; i < numPorts; i++) { - int interfaceId = ifTable->getInterface(i)->getInterfaceId(); - Ieee8021dInterfaceData *port = getPortInterfaceData(interfaceId); - - if (compareBridgeIDs(port->getRootPriority(), port->getRootAddress(), bridgePriority, bridgeAddress) > 0) - return false; - } - - return true; -} - -void Stp::tryRoot() -{ - if (checkRootEligibility()) { - EV_DETAIL << "Switch is elected as root switch." << endl; - isRoot = true; - setAllDesignated(); - rootPriority = bridgePriority; - rootAddress = bridgeAddress; - rootPathCost = 0; - currentHelloTime = helloTime; - currentMaxAge = maxAge; - currentFwdDelay = forwardDelay; - } - else { - isRoot = false; - selectRootPort(); - selectDesignatedPorts(); - } -} - -int Stp::compareBridgeIDs(unsigned int aPriority, MacAddress aAddress, unsigned int bPriority, MacAddress bAddress) -{ - if (aPriority < bPriority) - return 1; // A is superior - else if (aPriority > bPriority) - return -1; - - // APR == BPR - if (aAddress.compareTo(bAddress) == -1) - return 1; // A is superior - else if (aAddress.compareTo(bAddress) == 1) - return -1; - - // A==B - // (can happen if bridge have two port connected to one not bridged lan, - // "cable loopback" - return 0; -} - int Stp::comparePortIDs(unsigned int aPriority, unsigned int aNum, unsigned int bPriority, unsigned int bNum) { if (aPriority < bPriority) @@ -600,25 +659,6 @@ void Stp::selectDesignatedPorts() delete bridgeGlobal; } -void Stp::setAllDesignated() -{ - // all ports of the root switch are designated ports - EV_DETAIL << "All ports become designated." << endl; // todo - - desPorts.clear(); - for (unsigned int i = 0; i < numPorts; i++) { - InterfaceEntry *ie = ifTable->getInterface(i); - Ieee8021dInterfaceData *portData = ie->getProtocolData(); - ASSERT(portData != nullptr); - if (portData->getRole() == Ieee8021dInterfaceData::DISABLED) - continue; - - int interfaceId = ie->getInterfaceId(); - portData->setRole(Ieee8021dInterfaceData::DESIGNATED); - desPorts.push_back(interfaceId); - } -} - void Stp::lostRoot() { topologyChangeNotification = true; @@ -644,28 +684,6 @@ void Stp::reset() setAllDesignated(); } -void Stp::start() -{ - StpBase::start(); - - initPortTable(); - currentBridgePriority = bridgePriority; - isRoot = true; - topologyChangeNotification = true; - topologyChangeRecvd = true; - rootPriority = bridgePriority; - rootAddress = bridgeAddress; - rootPathCost = 0; - rootInterfaceId = ifTable->getInterface(0)->getInterfaceId(); - currentHelloTime = helloTime; - currentMaxAge = maxAge; - currentFwdDelay = forwardDelay; - helloTime = 0; - setAllDesignated(); - - scheduleAt(simTime() + tickInterval, tick); -} - void Stp::stop() { StpBase::stop(); @@ -674,21 +692,5 @@ void Stp::stop() cancelEvent(tick); } -void Stp::initInterfacedata(unsigned int interfaceId) -{ - Ieee8021dInterfaceData *ifd = getPortInterfaceData(interfaceId); - ifd->setRole(Ieee8021dInterfaceData::NOTASSIGNED); - ifd->setState(Ieee8021dInterfaceData::DISCARDING); - ifd->setRootPriority(bridgePriority); - ifd->setRootAddress(bridgeAddress); - ifd->setRootPathCost(0); - ifd->setAge(0); - ifd->setBridgePriority(bridgePriority); - ifd->setBridgeAddress(bridgeAddress); - ifd->setPortPriority(-1); - ifd->setPortNum(-1); - ifd->setLostBPDU(0); -} - } // namespace inet From 6e4ff28fdbef7955a9372ff58f6b31e9909a3951 Mon Sep 17 00:00:00 2001 From: Mani Amoozadeh Date: Sun, 8 Sep 2019 11:26:37 -0700 Subject: [PATCH 02/27] mac: watch the address table --- src/inet/linklayer/ethernet/switch/MacAddressTable.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/inet/linklayer/ethernet/switch/MacAddressTable.cc b/src/inet/linklayer/ethernet/switch/MacAddressTable.cc index 47731404b97..1ce2678e467 100644 --- a/src/inet/linklayer/ethernet/switch/MacAddressTable.cc +++ b/src/inet/linklayer/ethernet/switch/MacAddressTable.cc @@ -170,6 +170,8 @@ bool MacAddressTable::updateTableWithAddress(int interfaceId, const MacAddress& if (vid == 0) addressTable = table; + WATCH_MAP(*addressTable); + vlanAddressTable[vid] = table; iter = table->end(); } From def034c4fed800bbf8095e5845299635a2e731c6 Mon Sep 17 00:00:00 2001 From: Mani Amoozadeh Date: Sun, 8 Sep 2019 11:28:13 -0700 Subject: [PATCH 03/27] mac: adding base MAC address to each switch --- src/inet/networklayer/common/InterfaceTable.cc | 16 ++++++++++++++++ src/inet/networklayer/common/InterfaceTable.h | 3 +++ src/inet/networklayer/contract/IInterfaceTable.h | 5 +++++ src/inet/node/ethernet/EtherSwitch.ned | 1 + 4 files changed, 25 insertions(+) diff --git a/src/inet/networklayer/common/InterfaceTable.cc b/src/inet/networklayer/common/InterfaceTable.cc index f2b59ded96a..3d7fcb5e8c7 100644 --- a/src/inet/networklayer/common/InterfaceTable.cc +++ b/src/inet/networklayer/common/InterfaceTable.cc @@ -72,6 +72,17 @@ void InterfaceTable::initialize(int stage) host = getContainingNode(this); WATCH_PTRVECTOR(idToInterface); } + else if (stage == INITSTAGE_NETWORK_INTERFACE_CONFIGURATION) { + if(host && host->hasPar("baseMacAddress")) { + std::string baseMac = host->par("baseMacAddress"); + if(baseMac.empty()) + baseMacAddr = MacAddress::generateAutoAddress(); + else + baseMacAddr.setAddress(baseMac.c_str()); + + WATCH(baseMacAddr); + } + } } void InterfaceTable::refreshDisplay() const @@ -553,5 +564,10 @@ MulticastGroupList InterfaceTable::collectMulticastGroups() const return mglist; } +MacAddress InterfaceTable::getBaseMacAddress() const +{ + return baseMacAddr; +} + } // namespace inet diff --git a/src/inet/networklayer/common/InterfaceTable.h b/src/inet/networklayer/common/InterfaceTable.h index ef6ff9c4978..2f5215e52f1 100644 --- a/src/inet/networklayer/common/InterfaceTable.h +++ b/src/inet/networklayer/common/InterfaceTable.h @@ -70,6 +70,7 @@ class INET_API InterfaceTable : public OperationalBase, public IInterfaceTable, { protected: cModule *host; // cached pointer + MacAddress baseMacAddr; // primary storage for interfaces: vector indexed by id; may contain NULLs; // slots are never reused to ensure id uniqueness @@ -241,6 +242,8 @@ class INET_API InterfaceTable : public OperationalBase, public IInterfaceTable, * Returns all multicast group address, with it's interfaceId */ virtual MulticastGroupList collectMulticastGroups() const override; + + virtual MacAddress getBaseMacAddress() const override; }; } // namespace inet diff --git a/src/inet/networklayer/contract/IInterfaceTable.h b/src/inet/networklayer/contract/IInterfaceTable.h index e0be417e489..51e94e147a4 100644 --- a/src/inet/networklayer/contract/IInterfaceTable.h +++ b/src/inet/networklayer/contract/IInterfaceTable.h @@ -168,6 +168,11 @@ class INET_API IInterfaceTable * Returns all multicast group address, with it's interfaceId */ virtual MulticastGroupList collectMulticastGroups() const = 0; + + /** + * Returns the base MAC address + */ + virtual MacAddress getBaseMacAddress() const = 0; }; } // namespace inet diff --git a/src/inet/node/ethernet/EtherSwitch.ned b/src/inet/node/ethernet/EtherSwitch.ned index a77b0aeb009..c6444124127 100644 --- a/src/inet/node/ethernet/EtherSwitch.ned +++ b/src/inet/node/ethernet/EtherSwitch.ned @@ -53,6 +53,7 @@ module EtherSwitch string spanningTreeProtocol = default("Stp"); int numEthInterfaces = default(0); // minimum number of ethernet interfaces int numExtInterfaces = default(0); + string baseMacAddress = default(""); eth[*].encap.typename = "EtherEncapDummy"; eth[*].csmacdSupport = csmacdSupport; eth[*].mac.typename = default(csmacdSupport ? "EtherMac" : "EtherMacFullDuplex"); From 7fa2cf2bff1efd899f90ee3cec979da87db40fe0 Mon Sep 17 00:00:00 2001 From: Mani Amoozadeh Date: Sun, 8 Sep 2019 12:20:31 -0700 Subject: [PATCH 04/27] stp: using the base mac address --- .../linklayer/ieee8021d/common/StpBase.cc | 24 +++---------------- src/inet/linklayer/ieee8021d/common/StpBase.h | 6 ----- 2 files changed, 3 insertions(+), 27 deletions(-) diff --git a/src/inet/linklayer/ieee8021d/common/StpBase.cc b/src/inet/linklayer/ieee8021d/common/StpBase.cc index 5bb73499582..f9bc0cbbb46 100644 --- a/src/inet/linklayer/ieee8021d/common/StpBase.cc +++ b/src/inet/linklayer/ieee8021d/common/StpBase.cc @@ -56,17 +56,13 @@ void StpBase::initialize(int stage) void StpBase::start() { - ie = chooseInterface(); - - if (ie) - bridgeAddress = ie->getMacAddress(); // get the bridge's MAC address - else - throw cRuntimeError("No non-loopback interface found!"); + bridgeAddress = ifTable->getBaseMacAddress(); + ASSERT(bridgeAddress != MacAddress::UNSPECIFIED_ADDRESS); } void StpBase::stop() { - ie = nullptr; + } void StpBase::colorLink(InterfaceEntry *ie, bool forwarding) const @@ -168,20 +164,6 @@ int StpBase::getRootInterfaceId() const return -1; } -InterfaceEntry *StpBase::chooseInterface() -{ - // TODO: Currently, we assume that the first non-loopback interface is an Ethernet interface - // since STP and RSTP work on EtherSwitches. - // NOTE that, we doesn't check if the returning interface is an Ethernet interface! - for (int i = 0; i < ifTable->getNumInterfaces(); i++) { - InterfaceEntry *current = ifTable->getInterface(i); - if (!current->isLoopback()) - return current; - } - - return nullptr; -} - void StpBase::handleStartOperation(LifecycleOperation *operation) { start(); diff --git a/src/inet/linklayer/ieee8021d/common/StpBase.h b/src/inet/linklayer/ieee8021d/common/StpBase.h index ac97f3e5cbf..d09e6bd22e4 100644 --- a/src/inet/linklayer/ieee8021d/common/StpBase.h +++ b/src/inet/linklayer/ieee8021d/common/StpBase.h @@ -46,7 +46,6 @@ class INET_API StpBase : public OperationalBase, public cListener cModule *switchModule = nullptr; IMacAddressTable *macTable = nullptr; IInterfaceTable *ifTable = nullptr; - InterfaceEntry *ie = nullptr; public: StpBase(); @@ -96,11 +95,6 @@ class INET_API StpBase : public OperationalBase, public cListener * @return The port's InterfaceEntry, throws error if it doesn't exist. */ InterfaceEntry *getPortInterfaceEntry(unsigned int interfaceId); - - /* - * Returns the first non-loopback interface. - */ - virtual InterfaceEntry *chooseInterface(); }; } // namespace inet From ad3cd3368b2a3a9c73e542400d1205b73fc6a5ba Mon Sep 17 00:00:00 2001 From: Mani Amoozadeh Date: Sun, 8 Sep 2019 12:25:15 -0700 Subject: [PATCH 05/27] stp; use enum for bpdu type --- src/inet/linklayer/ieee8021d/stp/Stp.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc index cfdbc130f8e..9f1ce3a8bd8 100644 --- a/src/inet/linklayer/ieee8021d/stp/Stp.cc +++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc @@ -245,7 +245,7 @@ void Stp::generateBPDU(int interfaceId, const MacAddress& address, bool tcFlag, bpdu->setProtocolIdentifier(0); bpdu->setProtocolVersionIdentifier(0); - bpdu->setBpduType(0); // 0 if configuration BPDU + bpdu->setBpduType(CONFIG_BDPU); bpdu->setBridgeAddress(bridgeAddress); bpdu->setBridgePriority(bridgePriority); From 693c5e92bdf7afb237698a8764fbc43663a6f9d7 Mon Sep 17 00:00:00 2001 From: Mani Amoozadeh Date: Sun, 8 Sep 2019 19:35:16 -0700 Subject: [PATCH 06/27] stp: fix the field names in the bpdu --- .../ieee8021d/common/Ieee8021dBpdu.msg | 49 +++--- src/inet/linklayer/ieee8021d/rstp/Rstp.cc | 153 +++++++++++------- src/inet/linklayer/ieee8021d/stp/Stp.cc | 87 ++++++---- 3 files changed, 180 insertions(+), 109 deletions(-) diff --git a/src/inet/linklayer/ieee8021d/common/Ieee8021dBpdu.msg b/src/inet/linklayer/ieee8021d/common/Ieee8021dBpdu.msg index 1a931816e39..de1c05904a5 100644 --- a/src/inet/linklayer/ieee8021d/common/Ieee8021dBpdu.msg +++ b/src/inet/linklayer/ieee8021d/common/Ieee8021dBpdu.msg @@ -19,6 +19,32 @@ import inet.linklayer.common.MacAddress; namespace inet; +struct BpduFlags // flags: 1 byte +{ + bool tcaFlag; // Topology Change Acknowledgment flag + uint8_t reserved = 0; // unused 6 bits of Flags + bool tcFlag; // Topology Change flag +} + +struct RootIdentifier +{ + uint16_t rootPriority; // 2 bytes, priority of the tree root + MacAddress rootAddress; // 6 bytes, address of the tree root +} + +struct BridgeIdentifier +{ + uint16_t bridgePriority; // 2 bytes, priority of sender bridge + MacAddress bridgeAddress; // 6 bytes, address of sender bridge +} + +struct PortIdentifier +{ + unsigned int portPriority; // 1 byte, priority of sender port + unsigned int portNum; // 1 byte, port number (ethg[] gate index) of sender port + // (or 4 bit priority (shifted with 4 bit) and 12 bit portnum (in 802.1D-2004)) +} + // // Represents a BPDU (Bridge PDU) used by the STP and RSTP protocols, // as defined in the 802.1D-1998 specification. @@ -26,30 +52,17 @@ namespace inet; class Bpdu extends FieldsChunk { chunkLength = B(35); + uint16_t protocolIdentifier; // 2 bytes, 0 for STP, 1 for RSTP (TODO use them) unsigned int protocolVersionIdentifier; // 1 byte, version ID, currently 0 - unsigned int bpduType; // 1 byte, 0 for Configuration BPDU, 1 for Topology Change Notification BPDU - - // flags: 1 byte - bool tcaFlag; // Topology Change Acknowledgment flag - uint8_t reserved = 0; // unused 6 bits of Flags - bool tcFlag; // Topology Change flag - - uint16_t rootPriority; // 2 bytes, priority of the tree root (part of Root Identifier) - MacAddress rootAddress; // 6 bytes, address of the tree root (part of Root Identifier) + BpduFlags bpduFlags; + RootIdentifier rootIdentifier; uint32_t rootPathCost; // 4 bytes, cost to the root - - uint16_t bridgePriority; // 2 bytes, priority of sender bridge (part of Bridge Identifier) - MacAddress bridgeAddress; // 6 bytes, address of sender bridge (part of Bridge Identifier) - - unsigned int portPriority; // 1 byte, priority of sender port (part of Port Identifier) - unsigned int portNum; // 1 byte, port number (ethg[] gate index) of sender port (part of Port Identifier) - // (or 4 bit priority (shifted with 4 bit) and 12 bit portnum (in 802.1D-2004)) - + BridgeIdentifier bridgeIdentifier; + PortIdentifier portIdentifier; simtime_t messageAge; // 2 bytes, Message Age (in 256ths of a second) simtime_t maxAge; // 2 bytes, maximum lifetime of the BPDU (in 256ths of a second) simtime_t helloTime; // 2 bytes, Hello Time of the sender bridge (in 256ths of a second) simtime_t forwardDelay; // 2 bytes, Forward Delay timer of the sender bridge (in 256ths of a second) } - diff --git a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc index 881e940dbf6..ae5ad670cc2 100644 --- a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc +++ b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc @@ -213,7 +213,7 @@ void Rstp::handleHelloTime(cMessage *msg) void Rstp::checkTC(const Ptr& frame, int arrivalInterfaceId) { Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalInterfaceId); - if ((frame->getTcFlag() == true) && (port->getState() == Ieee8021dInterfaceData::FORWARDING)) { + if ((frame->getBpduFlags().tcFlag == true) && (port->getState() == Ieee8021dInterfaceData::FORWARDING)) { EV_DETAIL << "TCN received" << endl; findContainingNode(this)->bubble("TCN received"); for (unsigned int i = 0; i < numPorts; i++) { @@ -233,8 +233,9 @@ void Rstp::handleBackup(const Ptr& frame, unsigned int arrivalInterf { EV_DETAIL << "More than one port in the same LAN" << endl; Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalInterfaceId); - if ((frame->getPortPriority() < port->getPortPriority()) - || ((frame->getPortPriority() == port->getPortPriority()) && (frame->getPortNum() < arrivalInterfaceId))) + if ((frame->getPortIdentifier().portPriority < port->getPortPriority()) + || ((frame->getPortIdentifier().portPriority == port->getPortPriority()) + && (frame->getPortIdentifier().portNum < arrivalInterfaceId))) { // flushing arrival port macTable->flush(arrivalInterfaceId); @@ -243,24 +244,33 @@ void Rstp::handleBackup(const Ptr& frame, unsigned int arrivalInterf port->setLostBPDU(0); EV_DETAIL << "Setting port " << arrivalInterfaceId << "to backup" << endl; } - else if (frame->getPortPriority() > port->getPortPriority() - || (frame->getPortPriority() == port->getPortPriority() && frame->getPortNum() > arrivalInterfaceId)) + else if (frame->getPortIdentifier().portPriority > port->getPortPriority() + || (frame->getPortIdentifier().portPriority == port->getPortPriority() + && frame->getPortIdentifier().portNum > arrivalInterfaceId)) { - Ieee8021dInterfaceData *port2 = getPortInterfaceData(frame->getPortNum()); - // flushing sender port - macTable->flush(frame->getPortNum()); // portNum is sender port number, it is not arrival port + // portNum is sender port number, it is not arrival port + unsigned int portNum = frame->getPortIdentifier().portNum; + + Ieee8021dInterfaceData *port2 = getPortInterfaceData(portNum); + macTable->flush(portNum); + + EV_DETAIL << "Setting port " << portNum << "to backup" << endl; + port2->setRole(Ieee8021dInterfaceData::BACKUP); port2->setState(Ieee8021dInterfaceData::DISCARDING); port2->setLostBPDU(0); - EV_DETAIL << "Setting port " << frame->getPortNum() << "to backup" << endl; } else { - Ieee8021dInterfaceData *port2 = getPortInterfaceData(frame->getPortNum()); - // unavoidable loop, received its own message at the same port - // switch to disabled - EV_DETAIL << "Unavoidable loop. Received its own message at the same port. Setting port " << frame->getPortNum() << " to disabled." << endl; - // flushing that port - macTable->flush(frame->getPortNum()); // portNum is sender port number, it is not arrival port + // portNum is sender port number, it is not arrival port + unsigned int portNum = frame->getPortIdentifier().portNum; + + Ieee8021dInterfaceData *port2 = getPortInterfaceData(portNum); + macTable->flush(portNum); + + // unavoidable loop, received its own message at the same port switch to disabled + EV_DETAIL << "Unavoidable loop. Received its own message at the same port. " + "Setting port " << portNum << " to disabled." << endl; + port2->setRole(Ieee8021dInterfaceData::DISABLED); port2->setState(Ieee8021dInterfaceData::DISCARDING); } @@ -295,16 +305,18 @@ void Rstp::processBPDU(const Ptr& frame, unsigned int arrivalInterfa //first: vs best received BPDU for that port --------->case //second: vs root BPDU--------------------------------->case1 //third: vs BPDU that would be sent from this Bridge.->case2 + Ieee8021dInterfaceData *arrivalPort = getPortInterfaceData(arrivalInterfaceId); bool flood = false; if (compareInterfacedata(arrivalInterfaceId, frame, arrivalPort->getLinkCost()) > 0 //better root - && frame->getRootAddress().compareTo(bridgeAddress) != 0) // root will not participate in a loop with its own address + && frame->getRootIdentifier().rootAddress.compareTo(bridgeAddress) != 0) // root will not participate in a loop with its own address flood = processBetterSource(frame, arrivalInterfaceId); - else if (frame->getBridgeAddress().compareTo(arrivalPort->getBridgeAddress()) == 0 // worse or similar, but the same source - && frame->getRootAddress().compareTo(bridgeAddress) != 0) // root will not participate + else if (frame->getBridgeIdentifier().bridgeAddress.compareTo(arrivalPort->getBridgeAddress()) == 0 // worse or similar, but the same source + && frame->getRootIdentifier().rootAddress.compareTo(bridgeAddress) != 0) // root will not participate flood = processSameSource(frame, arrivalInterfaceId); + if (flood) { - sendBPDUs(); //expedited BPDU + sendBPDUs(); // expedited BPDU sendTCNtoRoot(); } } @@ -577,15 +589,24 @@ void Rstp::sendTCNtoRoot() if (simTime() < rootPort->getTCWhile()) { Packet *packet = new Packet("BPDU"); const auto& frame = makeShared(); - frame->setRootPriority(rootPort->getRootPriority()); - frame->setRootAddress(rootPort->getRootAddress()); - frame->setMessageAge(rootPort->getAge()); + + BpduFlags bpduFlags; + bpduFlags.tcaFlag = false; + bpduFlags.tcFlag = true; + frame->setBpduFlags(bpduFlags); + RootIdentifier rootId; + rootId.rootPriority = rootPort->getRootPriority(); + rootId.rootAddress = rootPort->getRootAddress(); + frame->setRootIdentifier(rootId); frame->setRootPathCost(rootPort->getRootPathCost()); - frame->setBridgePriority(bridgePriority); - frame->setTcaFlag(false); - frame->setPortNum(r); - frame->setBridgeAddress(bridgeAddress); - frame->setTcFlag(true); + BridgeIdentifier bridgeId; + bridgeId.bridgePriority = bridgePriority; + bridgeId.bridgeAddress = bridgeAddress; + frame->setBridgeIdentifier(bridgeId); + PortIdentifier portId; + portId.portNum = r; + frame->setPortIdentifier(portId); + frame->setMessageAge(rootPort->getAge()); frame->setMaxAge(maxAge); frame->setHelloTime(helloTime); frame->setForwardDelay(forwardDelay); @@ -635,25 +656,38 @@ void Rstp::sendBPDU(int interfaceId) Packet *packet = new Packet("BPDU"); const auto& frame = makeShared(); if (r != -1) { - frame->setRootPriority(rootPort->getRootPriority()); - frame->setRootAddress(rootPort->getRootAddress()); + RootIdentifier rootId; + rootId.rootPriority = rootPort->getRootPriority(); + rootId.rootAddress = rootPort->getRootAddress(); + frame->setRootIdentifier(rootId); + frame->setMessageAge(rootPort->getAge()); frame->setRootPathCost(rootPort->getRootPathCost()); } else { - frame->setRootPriority(bridgePriority); - frame->setRootAddress(bridgeAddress); + RootIdentifier rootId; + rootId.rootPriority = bridgePriority; + rootId.rootAddress = bridgeAddress; + frame->setRootIdentifier(rootId); + frame->setMessageAge(0); frame->setRootPathCost(0); } - frame->setBridgePriority(bridgePriority); - frame->setTcaFlag(false); - frame->setPortNum(interfaceId); - frame->setBridgeAddress(bridgeAddress); - if (simTime() < iport->getTCWhile()) - frame->setTcFlag(true); - else - frame->setTcFlag(false); + + BridgeIdentifier bridgeId; + bridgeId.bridgePriority = bridgePriority; + bridgeId.bridgeAddress = bridgeAddress; + frame->setBridgeIdentifier(bridgeId); + + BpduFlags bpduFlags; + bpduFlags.tcaFlag = false; + bpduFlags.tcFlag = (simTime() < iport->getTCWhile()) ? true : false; + frame->setBpduFlags(bpduFlags); + + PortIdentifier portId; + portId.portNum = interfaceId; + frame->setPortIdentifier(portId); + frame->setMaxAge(maxAge); frame->setHelloTime(helloTime); frame->setForwardDelay(forwardDelay); @@ -743,14 +777,19 @@ void Rstp::initPorts() void Rstp::updateInterfacedata(const Ptr& frame, unsigned int portNum) { Ieee8021dInterfaceData *ifd = getPortInterfaceData(portNum); - ifd->setRootPriority(frame->getRootPriority()); - ifd->setRootAddress(frame->getRootAddress()); + + ifd->setRootPriority(frame->getRootIdentifier().rootPriority); + ifd->setRootAddress(frame->getRootIdentifier().rootAddress); + ifd->setRootPathCost(frame->getRootPathCost() + ifd->getLinkCost()); + + ifd->setBridgePriority(frame->getBridgeIdentifier().bridgePriority); + ifd->setBridgeAddress(frame->getBridgeIdentifier().bridgeAddress); + + ifd->setPortPriority(frame->getPortIdentifier().portPriority); + ifd->setPortNum(frame->getPortIdentifier().portNum); + ifd->setAge(frame->getMessageAge() + 1); - ifd->setBridgePriority(frame->getBridgePriority()); - ifd->setBridgeAddress(frame->getBridgeAddress()); - ifd->setPortPriority(frame->getPortPriority()); - ifd->setPortNum(frame->getPortNum()); ifd->setLostBPDU(0); } @@ -775,26 +814,26 @@ Rstp::CompareResult Rstp::contestInterfacedata(const Ptr& msg, unsig Ieee8021dInterfaceData *rootPort = getPortInterfaceData(r); Ieee8021dInterfaceData *ifd = getPortInterfaceData(interfaceId); - return compareRSTPData(rootPort->getRootPriority(), msg->getRootPriority(), - rootPort->getRootAddress(), msg->getRootAddress(), + return compareRSTPData(rootPort->getRootPriority(), msg->getRootIdentifier().rootPriority, + rootPort->getRootAddress(), msg->getRootIdentifier().rootAddress, rootPort->getRootPathCost(), msg->getRootPathCost(), - bridgePriority, msg->getBridgePriority(), - bridgeAddress, msg->getBridgeAddress(), - ifd->getPortPriority(), msg->getPortPriority(), - interfaceId, msg->getPortNum()); + bridgePriority, msg->getBridgeIdentifier().bridgePriority, + bridgeAddress, msg->getBridgeIdentifier().bridgeAddress, + ifd->getPortPriority(), msg->getPortIdentifier().portPriority, + interfaceId, msg->getPortIdentifier().portNum); } Rstp::CompareResult Rstp::compareInterfacedata(unsigned int interfaceId, const Ptr& msg, int linkCost) { Ieee8021dInterfaceData *ifd = getPortInterfaceData(interfaceId); - return compareRSTPData(ifd->getRootPriority(), msg->getRootPriority(), - ifd->getRootAddress(), msg->getRootAddress(), + return compareRSTPData(ifd->getRootPriority(), msg->getRootIdentifier().rootPriority, + ifd->getRootAddress(), msg->getRootIdentifier().rootAddress, ifd->getRootPathCost(), msg->getRootPathCost() + linkCost, - ifd->getBridgePriority(), msg->getBridgePriority(), - ifd->getBridgeAddress(), msg->getBridgeAddress(), - ifd->getPortPriority(), msg->getPortPriority(), - ifd->getPortNum(), msg->getPortNum()); + ifd->getBridgePriority(), msg->getBridgeIdentifier().bridgePriority, + ifd->getBridgeAddress(), msg->getBridgeIdentifier().bridgeAddress, + ifd->getPortPriority(), msg->getPortIdentifier().portPriority, + ifd->getPortNum(), msg->getPortIdentifier().portNum); } Rstp::CompareResult Rstp::compareRSTPData(int rootPriority1, int rootPriority2, diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc index 9f1ce3a8bd8..2b2dcf55a1f 100644 --- a/src/inet/linklayer/ieee8021d/stp/Stp.cc +++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc @@ -34,6 +34,7 @@ const double Stp::tickInterval = 1; Stp::Stp() { + } void Stp::initialize(int stage) @@ -247,29 +248,43 @@ void Stp::generateBPDU(int interfaceId, const MacAddress& address, bool tcFlag, bpdu->setProtocolVersionIdentifier(0); bpdu->setBpduType(CONFIG_BDPU); - bpdu->setBridgeAddress(bridgeAddress); - bpdu->setBridgePriority(bridgePriority); - bpdu->setRootPathCost(rootPathCost); - bpdu->setRootAddress(rootAddress); - bpdu->setRootPriority(rootPriority); - bpdu->setPortNum(interfaceId); - bpdu->setPortPriority(getPortInterfaceData(interfaceId)->getPriority()); - bpdu->setMessageAge(0); - bpdu->setMaxAge(currentMaxAge); - bpdu->setHelloTime(currentHelloTime); - bpdu->setForwardDelay(currentFwdDelay); - if (topologyChangeNotification) { if (isRoot || tcFlag) { - bpdu->setTcFlag(true); - bpdu->setTcaFlag(false); + BpduFlags bpduFlags; + bpduFlags.tcFlag = true; + bpduFlags.tcaFlag = false; + bpdu->setBpduFlags(bpduFlags); } else if (tcaFlag) { - bpdu->setTcFlag(false); - bpdu->setTcaFlag(true); + BpduFlags bpduFlags; + bpduFlags.tcFlag = false; + bpduFlags.tcaFlag = true; + bpdu->setBpduFlags(bpduFlags); } } + RootIdentifier rootId; + rootId.rootPriority = rootPriority; + rootId.rootAddress = rootAddress; + bpdu->setRootIdentifier(rootId); + + bpdu->setRootPathCost(rootPathCost); + + BridgeIdentifier bridgeId; + bridgeId.bridgePriority = bridgePriority; + bridgeId.bridgeAddress = bridgeAddress; + bpdu->setBridgeIdentifier(bridgeId); + + PortIdentifier portId; + portId.portPriority = getPortInterfaceData(interfaceId)->getPriority(); + portId.portNum = interfaceId; + bpdu->setPortIdentifier(portId); + + bpdu->setMessageAge(0); + bpdu->setMaxAge(currentMaxAge); + bpdu->setHelloTime(currentHelloTime); + bpdu->setForwardDelay(currentFwdDelay); + packet->insertAtBack(bpdu); send(packet, "relayOut"); } @@ -281,6 +296,7 @@ void Stp::checkParametersChange() currentMaxAge = maxAge; currentFwdDelay = forwardDelay; } + if (currentBridgePriority != bridgePriority) { currentBridgePriority = bridgePriority; reset(); @@ -340,7 +356,7 @@ void Stp::handleBPDU(Packet *packet, const Ptr& bpdu) int arrivalGate = packet->getTag()->getInterfaceId(); Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalGate); - if (bpdu->getTcaFlag()) { + if (bpdu->getBpduFlags().tcaFlag) { topologyChangeRecvd = true; topologyChangeNotification = false; } @@ -356,7 +372,7 @@ void Stp::handleBPDU(Packet *packet, const Ptr& bpdu) else if (port->getRole() == Ieee8021dInterfaceData::ROOT) { EV_INFO << "Configuration BPDU " << bpdu << " arrived from Root Switch." << endl; - if (bpdu->getTcFlag()) { + if (bpdu->getBpduFlags().tcFlag) { EV_DEBUG << "MacAddressTable aging time set to " << currentFwdDelay << "." << endl; macTable->setAgingTime(currentFwdDelay); @@ -456,6 +472,7 @@ void Stp::handleTCN(Packet *packet, const Ptr& tcn) outPacket->addTag()->setProtocol(&Protocol::ethernetMac); send(outPacket, "relayOut"); } + delete packet; } @@ -464,17 +481,15 @@ bool Stp::isSuperiorBPDU(int interfaceId, const Ptr& bpdu) Ieee8021dInterfaceData *port = getPortInterfaceData(interfaceId); Ieee8021dInterfaceData *xBpdu = new Ieee8021dInterfaceData(); - int result; - - xBpdu->setRootPriority(bpdu->getRootPriority()); - xBpdu->setRootAddress(bpdu->getRootAddress()); + xBpdu->setRootPriority(bpdu->getRootIdentifier().rootPriority); + xBpdu->setRootAddress(bpdu->getRootIdentifier().rootAddress); xBpdu->setRootPathCost(bpdu->getRootPathCost() + port->getLinkCost()); - xBpdu->setBridgePriority(bpdu->getBridgePriority()); - xBpdu->setBridgeAddress(bpdu->getBridgeAddress()); - xBpdu->setPortPriority(bpdu->getPortPriority()); - xBpdu->setPortNum(bpdu->getPortNum()); + xBpdu->setBridgePriority(bpdu->getBridgeIdentifier().bridgePriority); + xBpdu->setBridgeAddress(bpdu->getBridgeIdentifier().bridgeAddress); + xBpdu->setPortPriority(bpdu->getPortIdentifier().portPriority); + xBpdu->setPortNum(bpdu->getPortIdentifier().portNum); - result = comparePorts(port, xBpdu); + int result = comparePorts(port, xBpdu); // port is superior if (result > 0) { @@ -482,8 +497,8 @@ bool Stp::isSuperiorBPDU(int interfaceId, const Ptr& bpdu) return false; } + // BPDU is superior if (result < 0) { - // BPDU is superior port->setFdWhile(0); // renew info port->setState(Ieee8021dInterfaceData::DISCARDING); setSuperiorBPDU(interfaceId, bpdu); // renew information @@ -504,13 +519,13 @@ void Stp::setSuperiorBPDU(int interfaceId, const Ptr& bpdu) Ieee8021dInterfaceData *portData = getPortInterfaceData(interfaceId); - portData->setRootPriority(bpdu->getRootPriority()); - portData->setRootAddress(bpdu->getRootAddress()); + portData->setRootPriority(bpdu->getRootIdentifier().rootPriority); + portData->setRootAddress(bpdu->getRootIdentifier().rootAddress); portData->setRootPathCost(bpdu->getRootPathCost() + portData->getLinkCost()); - portData->setBridgePriority(bpdu->getBridgePriority()); - portData->setBridgeAddress(bpdu->getBridgeAddress()); - portData->setPortPriority(bpdu->getPortPriority()); - portData->setPortNum(bpdu->getPortNum()); + portData->setBridgePriority(bpdu->getBridgeIdentifier().bridgePriority); + portData->setBridgeAddress(bpdu->getBridgeIdentifier().bridgeAddress); + portData->setPortPriority(bpdu->getPortIdentifier().portPriority); + portData->setPortNum(bpdu->getPortIdentifier().portNum); portData->setMaxAge(bpdu->getMaxAge()); portData->setFwdDelay(bpdu->getForwardDelay()); portData->setHelloTime(bpdu->getHelloTime()); @@ -590,9 +605,11 @@ void Stp::selectRootPort() best = currentPort; continue; } + if (result < 0) { continue; } + if (currentPort->getPriority() < best->getPriority()) { xRootIdx = i; best = currentPort; @@ -605,6 +622,7 @@ void Stp::selectRootPort() EV_DETAIL << "Port=" << xRootInterfaceId << " selected as root port." << endl; topologyChangeNotification = true; } + rootInterfaceId = xRootInterfaceId; getPortInterfaceData(rootInterfaceId)->setRole(Ieee8021dInterfaceData::ROOT); rootPathCost = best->getRootPathCost(); @@ -656,6 +674,7 @@ void Stp::selectDesignatedPorts() continue; } } + delete bridgeGlobal; } From b576002e33cf297450d537d7f1a0622f3fcd1be1 Mon Sep 17 00:00:00 2001 From: Mani Amoozadeh Date: Sun, 8 Sep 2019 21:37:21 -0700 Subject: [PATCH 07/27] stp: adding protocol serializer --- .../common/Ieee8021dBpduSerializer.cc | 90 +++++++++++++++++++ .../common/Ieee8021dBpduSerializer.h | 38 ++++++++ 2 files changed, 128 insertions(+) create mode 100644 src/inet/linklayer/ieee8021d/common/Ieee8021dBpduSerializer.cc create mode 100644 src/inet/linklayer/ieee8021d/common/Ieee8021dBpduSerializer.h diff --git a/src/inet/linklayer/ieee8021d/common/Ieee8021dBpduSerializer.cc b/src/inet/linklayer/ieee8021d/common/Ieee8021dBpduSerializer.cc new file mode 100644 index 00000000000..59f6c08cd94 --- /dev/null +++ b/src/inet/linklayer/ieee8021d/common/Ieee8021dBpduSerializer.cc @@ -0,0 +1,90 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +#include "inet/common/packet/serializer/ChunkSerializerRegistry.h" +#include "inet/linklayer/ieee8021d/common/Ieee8021dBpdu_m.h" +#include "inet/linklayer/ieee8021d/common/Ieee8021dBpduSerializer.h" + +namespace inet { + +Register_Serializer(Bpdu, Ieee8021dBpduSerializer); + +void Ieee8021dBpduSerializer::serialize(MemoryOutputStream& stream, const Ptr& chunk) const +{ + B startPos = B(stream.getLength()); + const auto& bpdu = staticPtrCast(chunk); + stream.writeUint16Be(bpdu->getProtocolIdentifier()); + stream.writeByte(bpdu->getProtocolVersionIdentifier()); + stream.writeByte(bpdu->getBpduType()); + stream.writeBit(bpdu->getBpduFlags().tcaFlag); + stream.writeNBitsOfUint64Be(bpdu->getBpduFlags().reserved, 6); + stream.writeBit(bpdu->getBpduFlags().tcFlag); + stream.writeUint16Be(bpdu->getRootIdentifier().rootPriority); + stream.writeMacAddress(bpdu->getRootIdentifier().rootAddress); + stream.writeUint32Be(bpdu->getRootPathCost()); + stream.writeUint16Be(bpdu->getBridgeIdentifier().bridgePriority); + stream.writeMacAddress(bpdu->getBridgeIdentifier().bridgeAddress); + stream.writeByte(bpdu->getPortIdentifier().portPriority); + stream.writeByte(bpdu->getPortIdentifier().portNum); + stream.writeUint16Be(bpdu->getMessageAge().inUnit(SIMTIME_S) * 256); + stream.writeUint16Be(bpdu->getMaxAge().inUnit(SIMTIME_S) * 256); + stream.writeUint16Be(bpdu->getHelloTime().inUnit(SIMTIME_S) * 256); + stream.writeUint16Be(bpdu->getForwardDelay().inUnit(SIMTIME_S) * 256); + // because of the KLUDGE in Rstp.cc (line 593) padding is added + while (B(stream.getLength()) - startPos < B(bpdu->getChunkLength())) + stream.writeByte('?'); +} + +const Ptr Ieee8021dBpduSerializer::deserialize(MemoryInputStream& stream) const +{ + auto bpdu = makeShared(); + bpdu->setProtocolIdentifier(stream.readUint16Be()); + bpdu->setProtocolVersionIdentifier(stream.readByte()); + bpdu->setBpduType(stream.readByte()); + + BpduFlags bpduFlags; + bpduFlags.tcaFlag = stream.readBit(); + bpduFlags.reserved = stream.readNBitsToUint64Be(6); + bpduFlags.tcFlag = stream.readBit(); + bpdu->setBpduFlags(bpduFlags); + + RootIdentifier rootId; + rootId.rootPriority = stream.readUint16Be(); + rootId.rootAddress = stream.readMacAddress(); + bpdu->setRootIdentifier(rootId); + + bpdu->setRootPathCost(stream.readUint32Be()); + + BridgeIdentifier bridgeId; + bridgeId.bridgePriority = stream.readUint16Be(); + bridgeId.bridgeAddress = stream.readMacAddress(); + bpdu->setBridgeIdentifier(bridgeId); + + PortIdentifier portId; + portId.portPriority = stream.readByte(); + portId.portNum = stream.readByte(); + bpdu->setPortIdentifier(portId); + + bpdu->setMessageAge(SimTime(stream.readUint16Be() / 256, SIMTIME_S)); + bpdu->setMaxAge(SimTime(stream.readUint16Be() / 256, SIMTIME_S)); + bpdu->setHelloTime(SimTime(stream.readUint16Be() / 256, SIMTIME_S)); + bpdu->setForwardDelay(SimTime(stream.readUint16Be() / 256, SIMTIME_S)); + // because of the KLUDGE in Rstp.cc (line 593) padding is added + while (B(stream.getRemainingLength()) > B(0)) + stream.readByte(); + return bpdu; +} + +} // namespace inet diff --git a/src/inet/linklayer/ieee8021d/common/Ieee8021dBpduSerializer.h b/src/inet/linklayer/ieee8021d/common/Ieee8021dBpduSerializer.h new file mode 100644 index 00000000000..4eb19ccb45e --- /dev/null +++ b/src/inet/linklayer/ieee8021d/common/Ieee8021dBpduSerializer.h @@ -0,0 +1,38 @@ +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/. +// + +#ifndef INET_LINKLAYER_IEEE8021D_COMMON_IEEE8021DBPDUSERIALIZER_H_ +#define INET_LINKLAYER_IEEE8021D_COMMON_IEEE8021DBPDUSERIALIZER_H_ + +#include "inet/common/packet/serializer/FieldsChunkSerializer.h" + +namespace inet { + +/** + * Converts between Bpdu and binary (network byte order) Ieee 802.1d BPDU packets. + */ +class INET_API Ieee8021dBpduSerializer : public FieldsChunkSerializer +{ +protected: + virtual void serialize(MemoryOutputStream& stream, const Ptr& chunk) const override; + virtual const Ptr deserialize(MemoryInputStream& stream) const override; + +public: + Ieee8021dBpduSerializer() : FieldsChunkSerializer() {} +}; + +} // namespace inet + +#endif /* INET_LINKLAYER_IEEE8021D_COMMON_IEEE8021DBPDUSERIALIZER_H_ */ From 299a6161e0dcb325c835fe5b17a302381d89d14d Mon Sep 17 00:00:00 2001 From: Mani Amoozadeh Date: Sun, 8 Sep 2019 22:29:15 -0700 Subject: [PATCH 08/27] stp: adding important variables into WATCH --- src/inet/linklayer/ieee8021d/stp/Stp.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc index 2b2dcf55a1f..9724033f8cb 100644 --- a/src/inet/linklayer/ieee8021d/stp/Stp.cc +++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc @@ -43,7 +43,6 @@ void Stp::initialize(int stage) if (stage == INITSTAGE_LOCAL) { tick = new cMessage("STP_TICK", 0); - WATCH(bridgeAddress); } else if (stage == INITSTAGE_LINK_LAYER) { registerService(Protocol::stp, nullptr, gate("relayIn")); @@ -75,6 +74,13 @@ void Stp::start() helloTime = 0; setAllDesignated(); + WATCH(bridgePriority); + WATCH(bridgeAddress); + WATCH(isRoot); + WATCH(rootPriority); + WATCH(rootAddress); + WATCH(rootPathCost); + scheduleAt(simTime() + tickInterval, tick); } From ba00ebb1169f70ab2bfc4b4766d22175d738e37f Mon Sep 17 00:00:00 2001 From: Mani Amoozadeh Date: Sun, 8 Sep 2019 22:29:51 -0700 Subject: [PATCH 09/27] stp: using enum instead --- src/inet/linklayer/ieee8021d/stp/Stp.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc index 9724033f8cb..000abaaa887 100644 --- a/src/inet/linklayer/ieee8021d/stp/Stp.cc +++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc @@ -320,9 +320,7 @@ void Stp::generateTCN() const auto& tcn = makeShared(); tcn->setProtocolIdentifier(0); tcn->setProtocolVersionIdentifier(0); - - // 1 if Topology Change Notification BPDU - tcn->setBpduType(1); + tcn->setBpduType(TCN_BPDU); auto macAddressReq = packet->addTag(); macAddressReq->setSrcAddress(bridgeAddress); From 367a628b635329be3aa2be03c8c25c4b43fc8308 Mon Sep 17 00:00:00 2001 From: Mani Amoozadeh Date: Tue, 10 Sep 2019 12:54:49 -0700 Subject: [PATCH 10/27] stp: adding more debug --- src/inet/linklayer/configurator/Ieee8021dInterfaceData.h | 2 +- src/inet/linklayer/ieee8021d/stp/Stp.cc | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h index e79e7038a56..a9045cce686 100644 --- a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h +++ b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h @@ -34,7 +34,7 @@ namespace inet { class INET_API Ieee8021dInterfaceData : public InterfaceProtocolData { public: - enum PortRole { ALTERNATE, NOTASSIGNED, DISABLED, DESIGNATED, BACKUP, ROOT }; + enum PortRole { NOTASSIGNED, ROOT, DESIGNATED, ALTERNATE, DISABLED, BACKUP /*rstp only*/ }; enum PortState { DISCARDING, LEARNING, FORWARDING }; diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc index 000abaaa887..4133b363cb7 100644 --- a/src/inet/linklayer/ieee8021d/stp/Stp.cc +++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc @@ -360,6 +360,8 @@ void Stp::handleBPDU(Packet *packet, const Ptr& bpdu) int arrivalGate = packet->getTag()->getInterfaceId(); Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalGate); + EV_DETAIL << switchModule->getFullName() << " received a BPDU on port=" << port->getInterfaceEntry()->getFullName() << endl; + if (bpdu->getBpduFlags().tcaFlag) { topologyChangeRecvd = true; topologyChangeNotification = false; From aebff32f2fc5365ab1d39f25805480b0c8de85d7 Mon Sep 17 00:00:00 2001 From: Mani Amoozadeh Date: Tue, 10 Sep 2019 16:09:01 -0700 Subject: [PATCH 11/27] stp: adding a new disabledInterfaces parameter to stp --- src/inet/linklayer/ieee8021d/stp/Stp.cc | 39 +++++++++++++++++++++--- src/inet/linklayer/ieee8021d/stp/Stp.h | 2 ++ src/inet/linklayer/ieee8021d/stp/Stp.ned | 4 +++ 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc index 4133b363cb7..645ace13c6e 100644 --- a/src/inet/linklayer/ieee8021d/stp/Stp.cc +++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc @@ -43,6 +43,8 @@ void Stp::initialize(int stage) if (stage == INITSTAGE_LOCAL) { tick = new cMessage("STP_TICK", 0); + disabledInterfaces = par("disabledInterfaces").stdstringValue(); + disabledInterfaceMatcher.setPattern(disabledInterfaces.c_str(), false, true, false); } else if (stage == INITSTAGE_LINK_LAYER) { registerService(Protocol::stp, nullptr, gate("relayIn")); @@ -95,7 +97,15 @@ void Stp::initPortTable() void Stp::initInterfacedata(unsigned int interfaceId) { Ieee8021dInterfaceData *ifd = getPortInterfaceData(interfaceId); - ifd->setRole(Ieee8021dInterfaceData::NOTASSIGNED); + + if( disabledInterfaceMatcher.matches(ifd->getInterfaceEntry()->getInterfaceName()) || + disabledInterfaceMatcher.matches(ifd->getInterfaceEntry()->getInterfaceFullPath().c_str())) { + ifd->setRole(Ieee8021dInterfaceData::DISABLED); + } + else { + ifd->setRole(Ieee8021dInterfaceData::NOTASSIGNED); + } + ifd->setState(Ieee8021dInterfaceData::DISCARDING); ifd->setRootPriority(bridgePriority); ifd->setRootAddress(bridgeAddress); @@ -114,6 +124,16 @@ void Stp::handleMessageWhenUp(cMessage *msg) Packet *packet = check_and_cast(msg); const auto& bpdu = packet->peekAtFront(); + // IEEE 802.1D-1998 (Section 8.4.5) + // BPDUs received on a disabled port shall not be processed by the STP + int arrivalGate = packet->getTag()->getInterfaceId(); + Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalGate); + if(port->getRole() == Ieee8021dInterfaceData::DISABLED) { + EV_DETAIL << "Incoming port is disabled. Discarding the received BPDU." << endl; + delete packet; + return; + } + if (bpdu->getBpduType() == CONFIG_BDPU) handleBPDU(packet, bpdu); else if (bpdu->getBpduType() == TCN_BPDU) @@ -241,6 +261,10 @@ void Stp::generateHelloBDPUs() void Stp::generateBPDU(int interfaceId, const MacAddress& address, bool tcFlag, bool tcaFlag) { + Ieee8021dInterfaceData *ifd = getPortInterfaceData(interfaceId); + if(ifd && ifd->getRole() == Ieee8021dInterfaceData::DISABLED) + return; + Packet *packet = new Packet("BPDU"); const auto& bpdu = makeShared(); auto macAddressReq = packet->addTag(); @@ -360,7 +384,7 @@ void Stp::handleBPDU(Packet *packet, const Ptr& bpdu) int arrivalGate = packet->getTag()->getInterfaceId(); Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalGate); - EV_DETAIL << switchModule->getFullName() << " received a BPDU on port=" << port->getInterfaceEntry()->getFullName() << endl; + EV_DETAIL << switchModule->getFullName() << " received a CONFIG BPDU on port=" << port->getInterfaceEntry()->getFullName() << endl; if (bpdu->getBpduFlags().tcaFlag) { topologyChangeRecvd = true; @@ -455,10 +479,13 @@ int Stp::compareBridgeIDs(unsigned int aPriority, MacAddress aAddress, unsigned void Stp::handleTCN(Packet *packet, const Ptr& tcn) { - EV_INFO << "Topology Change Notification BDPU " << tcn << " arrived." << endl; + int arrivalGate = packet->getTag()->getInterfaceId(); + Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalGate); + + EV_DETAIL << switchModule->getFullName() << " received a TCN BPDU on port=" << port->getInterfaceEntry()->getFullName() << endl; + topologyChangeNotification = true; - int arrivalGate = packet->getTag()->getInterfaceId(); MacAddressInd *addressInd = packet->getTag(); MacAddress srcAddress = addressInd->getSrcAddress(); MacAddress destAddress = addressInd->getDestAddress(); @@ -604,6 +631,8 @@ void Stp::selectRootPort() for (unsigned int i = 0; i < numPorts; i++) { currentPort = ifTable->getInterface(i)->getProtocolData(); + if(currentPort->getRole() == Ieee8021dInterfaceData::DISABLED) + continue; currentPort->setRole(Ieee8021dInterfaceData::NOTASSIGNED); result = comparePorts(currentPort, best); if (result > 0) { @@ -625,7 +654,7 @@ void Stp::selectRootPort() unsigned int xRootInterfaceId = ifTable->getInterface(xRootIdx)->getInterfaceId(); if (rootInterfaceId != xRootInterfaceId) { - EV_DETAIL << "Port=" << xRootInterfaceId << " selected as root port." << endl; + EV_DETAIL << "Port=" << ifTable->getInterface(xRootIdx)->getFullName() << " selected as root port." << endl; topologyChangeNotification = true; } diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.h b/src/inet/linklayer/ieee8021d/stp/Stp.h index 1531f636adf..decb14c2edb 100644 --- a/src/inet/linklayer/ieee8021d/stp/Stp.h +++ b/src/inet/linklayer/ieee8021d/stp/Stp.h @@ -47,6 +47,8 @@ class INET_API Stp : public StpBase bool isRoot = false; unsigned int rootInterfaceId = 0; std::vector desPorts; // set of designated ports + std::string disabledInterfaces = ""; + cPatternMatcher disabledInterfaceMatcher; // Discovered values unsigned int rootPathCost = 0; diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.ned b/src/inet/linklayer/ieee8021d/stp/Stp.ned index d66a6bdc500..72ae1310a6b 100644 --- a/src/inet/linklayer/ieee8021d/stp/Stp.ned +++ b/src/inet/linklayer/ieee8021d/stp/Stp.ned @@ -65,6 +65,10 @@ simple Stp like ISpanningTree // Shows the spanning tree by coloring connections in the network graphics. // Label ethernet interface with port role and status. Mark root switch bool visualize = default(false); + + // excluded interfaces from the spanning tree algorithms. + // default is empty and all ports are included in the STP + string disabledInterfaces = default(""); @display("i=block/network2"); gates: From ae5fe33a82c4f437973f0d417f475d066ca45ee9 Mon Sep 17 00:00:00 2001 From: Mani Amoozadeh Date: Tue, 10 Sep 2019 17:44:51 -0700 Subject: [PATCH 12/27] stp: L2NetworkConfigurator is now working properly --- .../configurator/Ieee8021dInterfaceData.cc | 12 ++- .../configurator/Ieee8021dInterfaceData.h | 5 -- .../configurator/L2NetworkConfigurator.cc | 84 +++++++++++-------- .../configurator/L2NetworkConfigurator.h | 4 +- .../configurator/L2NetworkConfigurator.ned | 4 +- .../configurator/L2NodeConfigurator.cc | 7 +- src/inet/linklayer/ieee8021d/stp/Stp.cc | 9 +- src/inet/linklayer/ieee8021d/stp/Stp.h | 2 +- 8 files changed, 67 insertions(+), 60 deletions(-) diff --git a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc index 793a9df0353..32db0bd0458 100644 --- a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc +++ b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc @@ -23,7 +23,6 @@ namespace inet { Ieee8021dInterfaceData::PortInfo::PortInfo() { - priority = 0; linkCost = 1; edge = false; @@ -47,17 +46,16 @@ Ieee8021dInterfaceData::Ieee8021dInterfaceData() std::string Ieee8021dInterfaceData::str() const { - std::stringstream out; - out << "role:" << getRoleName() << " state:" << getStateName(); - return out.str(); + return detailedInfo(); } std::string Ieee8021dInterfaceData::detailedInfo() const { std::stringstream out; - out << "role:" << getRoleName() << "\tstate:" << getStateName() << "\n"; - out << "priority:" << getPriority() << "\n"; - out << "linkCost:" << getLinkCost() << "\n"; + out << "role:" << getRoleName(); + out << " state:" << getStateName(); + out << " priority:" << getPortPriority(); + out << " linkCost:" << getLinkCost(); return out.str(); } diff --git a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h index a9045cce686..bfc2195c3ff 100644 --- a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h +++ b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h @@ -44,7 +44,6 @@ class INET_API Ieee8021dInterfaceData : public InterfaceProtocolData /* The following values have same meaning in both STP and RSTP. * See Ieee8021dBDPU for more info. */ - unsigned int priority; unsigned int linkCost; bool edge; @@ -131,10 +130,6 @@ class INET_API Ieee8021dInterfaceData : public InterfaceProtocolData void setPortPriority(unsigned int portPriority) { portData.portPriority = portPriority; } - unsigned int getPriority() const { return portData.priority; } - - void setPriority(unsigned int priority) { portData.priority = priority; } - PortRole getRole() const { return portData.role; } void setRole(PortRole role) { portData.role = role; } diff --git a/src/inet/linklayer/configurator/L2NetworkConfigurator.cc b/src/inet/linklayer/configurator/L2NetworkConfigurator.cc index 06f8551509e..35a75a8e84d 100644 --- a/src/inet/linklayer/configurator/L2NetworkConfigurator.cc +++ b/src/inet/linklayer/configurator/L2NetworkConfigurator.cc @@ -46,15 +46,30 @@ void L2NetworkConfigurator::initialize(int stage) { if (stage == INITSTAGE_LOCAL) configuration = par("config"); - else if (stage == INITSTAGE_NETWORK_CONFIGURATION) + else if (stage == INITSTAGE_LINK_LAYER) ensureConfigurationComputed(topology); } -L2NetworkConfigurator::InterfaceInfo::InterfaceInfo(Node *node, Node *childNode, InterfaceEntry *interfaceEntry) +void L2NetworkConfigurator::ensureConfigurationComputed(L2Topology& topology) { - this->node = node; - this->interfaceEntry = interfaceEntry; - this->childNode = childNode; + if (topology.getNumNodes() == 0) + computeConfiguration(); +} + +void L2NetworkConfigurator::computeConfiguration() +{ + long initializeStartTime = clock(); + + // extract topology into the L2Topology object + TIME(extractTopology(topology)); + + // read the configuration from XML; it will serve as input for port assignment + TIME(readInterfaceConfiguration(rootNode)); + + for(auto &entry : interfaces) + configureInterface(entry); + + printElapsedTime("initialize", initializeStartTime); } void L2NetworkConfigurator::extractTopology(L2Topology& topology) @@ -113,6 +128,15 @@ void L2NetworkConfigurator::extractTopology(L2Topology& topology) } } +Topology::LinkOut *L2NetworkConfigurator::findLinkOut(Node *node, int gateId) +{ + for (int i = 0; i < node->getNumOutLinks(); i++) + if (node->getLinkOut(i)->getLocalGateId() == gateId) + return node->getLinkOut(i); + + return nullptr; +} + void L2NetworkConfigurator::readInterfaceConfiguration(Node *rootNode) { std::set matchedBefore; @@ -129,8 +153,8 @@ void L2NetworkConfigurator::readInterfaceConfiguration(Node *rootNode) const char *portsAttr = interfaceElement->getAttribute("ports"); // switch gate indices, like "0 1 2" // Begin RSTP properties, for more information see RSTP module - const char *cost = interfaceElement->getAttribute("cost"); - const char *priority = interfaceElement->getAttribute("priority"); + const char *cost = interfaceElement->getAttribute("portCost"); + const char *priority = interfaceElement->getAttribute("portPriority"); const char *edge = interfaceElement->getAttribute("edge"); // End RSTP properties @@ -186,11 +210,12 @@ void L2NetworkConfigurator::readInterfaceConfiguration(Node *rootNode) // priority if (isNotEmpty(priority)) - currentNode->interfaceInfos[i]->portData.priority = atoi(priority); + currentNode->interfaceInfos[i]->portData.portPriority = atoi(priority); - //edge + // edge if (isNotEmpty(edge)) currentNode->interfaceInfos[i]->portData.edge = strcmp(edge, "true") ? false : true; + EV_DEBUG << hostModule->getFullPath() << ":" << ifEntry->getInterfaceName() << endl; matchedBefore.insert(ifEntry); @@ -210,32 +235,6 @@ void L2NetworkConfigurator::readInterfaceConfiguration(Node *rootNode) } } -void L2NetworkConfigurator::computeConfiguration() -{ - long initializeStartTime = clock(); - // extract topology into the L2Topology object - TIME(extractTopology(topology)); - // read the configuration from XML; it will serve as input for port assignment - TIME(readInterfaceConfiguration(rootNode)); - printElapsedTime("initialize", initializeStartTime); -} - -void L2NetworkConfigurator::ensureConfigurationComputed(L2Topology& topology) -{ - if (topology.getNumNodes() == 0) - computeConfiguration(); -} - -Topology::LinkOut *L2NetworkConfigurator::findLinkOut(Node *node, int gateId) -{ - for (int i = 0; i < node->getNumOutLinks(); i++) - if (node->getLinkOut(i)->getLocalGateId() == gateId) - return node->getLinkOut(i); - - - return nullptr; -} - bool L2NetworkConfigurator::linkContainsMatchingHostExcept(InterfaceInfo *currentInfo, Matcher& hostMatcher, cModule *exceptModule) { @@ -258,6 +257,11 @@ bool L2NetworkConfigurator::linkContainsMatchingHostExcept(InterfaceInfo *curren return false; } +void L2NetworkConfigurator::addToConfigureInterface(InterfaceEntry *interfaceEntry) +{ + interfaces.push_back(interfaceEntry); +} + void L2NetworkConfigurator::configureInterface(InterfaceEntry *interfaceEntry) { ensureConfigurationComputed(topology); @@ -281,7 +285,7 @@ void L2NetworkConfigurator::configureInterface(InterfaceInfo *interfaceInfo) Ieee8021dInterfaceData *interfaceData = interfaceEntry->getProtocolData(); interfaceData->setLinkCost(interfaceInfo->portData.linkCost); - interfaceData->setPriority(interfaceInfo->portData.priority); + interfaceData->setPortPriority(interfaceInfo->portData.portPriority); interfaceData->setEdge(interfaceInfo->portData.edge); } @@ -313,9 +317,15 @@ bool L2NetworkConfigurator::Matcher::matches(const char *s) if (elem->matches(s)) return true; - return false; } +L2NetworkConfigurator::InterfaceInfo::InterfaceInfo(Node *node, Node *childNode, InterfaceEntry *interfaceEntry) +{ + this->node = node; + this->interfaceEntry = interfaceEntry; + this->childNode = childNode; +} + } // namespace inet diff --git a/src/inet/linklayer/configurator/L2NetworkConfigurator.h b/src/inet/linklayer/configurator/L2NetworkConfigurator.h index 5ef3de5418c..57255b081c6 100644 --- a/src/inet/linklayer/configurator/L2NetworkConfigurator.h +++ b/src/inet/linklayer/configurator/L2NetworkConfigurator.h @@ -108,6 +108,7 @@ class INET_API L2NetworkConfigurator : public cSimpleModule cXMLElement *configuration = nullptr; L2Topology topology; Node *rootNode = nullptr; + std::vector interfaces; protected: virtual void initialize(int stage) override; @@ -131,6 +132,7 @@ class INET_API L2NetworkConfigurator : public cSimpleModule virtual bool linkContainsMatchingHostExcept(InterfaceInfo *currentInfo, Matcher& hostMatcher, cModule *exceptModule); void ensureConfigurationComputed(L2Topology& topology); virtual Topology::LinkOut *findLinkOut(Node *node, int gateId); + virtual void configureInterface(InterfaceEntry *interfaceEntry); void configureInterface(InterfaceInfo *interfaceInfo); public: @@ -142,7 +144,7 @@ class INET_API L2NetworkConfigurator : public cSimpleModule /** * Configures the provided interface based on the current network configuration. */ - virtual void configureInterface(InterfaceEntry *interfaceEntry); + void addToConfigureInterface(InterfaceEntry *interfaceEntry); }; } // namespace inet diff --git a/src/inet/linklayer/configurator/L2NetworkConfigurator.ned b/src/inet/linklayer/configurator/L2NetworkConfigurator.ned index 5f4eedcd53b..d8057ef3cdf 100644 --- a/src/inet/linklayer/configurator/L2NetworkConfigurator.ned +++ b/src/inet/linklayer/configurator/L2NetworkConfigurator.ned @@ -29,7 +29,7 @@ package inet.linklayer.configurator; // priority 32768: //
 // 
-//   
+//   
 // 
 // 
 //
@@ -39,6 +39,6 @@ simple L2NetworkConfigurator
 {
     parameters:
         @display("i=block/cogwheel");
-        xml config = default(xml(""));
+        xml config = default(xml(""));
 }
 
diff --git a/src/inet/linklayer/configurator/L2NodeConfigurator.cc b/src/inet/linklayer/configurator/L2NodeConfigurator.cc
index 8aebabbe33e..e699b67033c 100644
--- a/src/inet/linklayer/configurator/L2NodeConfigurator.cc
+++ b/src/inet/linklayer/configurator/L2NodeConfigurator.cc
@@ -43,6 +43,7 @@ void L2NodeConfigurator::initialize(int stage)
 bool L2NodeConfigurator::handleOperationStage(LifecycleOperation *operation, IDoneCallback *doneCallback)
 {
     Enter_Method_Silent();
+
     if (dynamic_cast(operation)) {
         if (static_cast(operation->getCurrentStage()) == ModuleStartOperation::STAGE_LINK_LAYER) {
             prepareNode();
@@ -55,6 +56,7 @@ bool L2NodeConfigurator::handleOperationStage(LifecycleOperation *operation, IDo
         /*nothing to do*/;
     else
         throw cRuntimeError("Unsupported lifecycle operation '%s'", operation->getClassName());
+
     return true;
 }
 
@@ -73,9 +75,8 @@ void L2NodeConfigurator::prepareInterface(InterfaceEntry *interfaceEntry)
 void L2NodeConfigurator::configureNode()
 {
     ASSERT(networkConfigurator);
-    // std::cout << "configureNode(): " << interfaceTable->getNumInterfaces() << endl;
     for (int i = 0; i < interfaceTable->getNumInterfaces(); i++)
-        networkConfigurator->configureInterface(interfaceTable->getInterface(i));
+        networkConfigurator->addToConfigureInterface(interfaceTable->getInterface(i));
 }
 
 void L2NodeConfigurator::receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj, cObject *details)
@@ -87,7 +88,7 @@ void L2NodeConfigurator::receiveSignal(cComponent *source, simsignal_t signalID,
         InterfaceEntry *ie = check_and_cast(obj);
         prepareInterface(ie);
         if (networkConfigurator)
-            networkConfigurator->configureInterface(ie);
+            networkConfigurator->addToConfigureInterface(ie);
     }
 }
 
diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc
index 645ace13c6e..c6fac352fc4 100644
--- a/src/inet/linklayer/ieee8021d/stp/Stp.cc
+++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc
@@ -106,6 +106,8 @@ void Stp::initInterfacedata(unsigned int interfaceId)
         ifd->setRole(Ieee8021dInterfaceData::NOTASSIGNED);
     }
 
+    // note: port cost and port priority are configured by the L2NetworkConfigurator
+
     ifd->setState(Ieee8021dInterfaceData::DISCARDING);
     ifd->setRootPriority(bridgePriority);
     ifd->setRootAddress(bridgeAddress);
@@ -113,7 +115,6 @@ void Stp::initInterfacedata(unsigned int interfaceId)
     ifd->setAge(0);
     ifd->setBridgePriority(bridgePriority);
     ifd->setBridgeAddress(bridgeAddress);
-    ifd->setPortPriority(-1);
     ifd->setPortNum(-1);
     ifd->setLostBPDU(0);
 }
@@ -306,7 +307,7 @@ void Stp::generateBPDU(int interfaceId, const MacAddress& address, bool tcFlag,
     bpdu->setBridgeIdentifier(bridgeId);
 
     PortIdentifier portId;
-    portId.portPriority = getPortInterfaceData(interfaceId)->getPriority();
+    portId.portPriority = getPortInterfaceData(interfaceId)->getPortPriority();
     portId.portNum = interfaceId;
     bpdu->setPortIdentifier(portId);
 
@@ -645,7 +646,7 @@ void Stp::selectRootPort()
             continue;
         }
 
-        if (currentPort->getPriority() < best->getPriority()) {
+        if (currentPort->getPortPriority() < best->getPortPriority()) {
             xRootIdx = i;
             best = currentPort;
             continue;
@@ -689,7 +690,7 @@ void Stp::selectDesignatedPorts()
         if (portData->getRole() == Ieee8021dInterfaceData::ROOT || portData->getRole() == Ieee8021dInterfaceData::DISABLED)
             continue;
 
-        bridgeGlobal->setPortPriority(portData->getPriority());
+        bridgeGlobal->setPortPriority(portData->getPortPriority());
         int interfaceId = ie->getInterfaceId();
         bridgeGlobal->setPortNum(interfaceId);
 
diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.h b/src/inet/linklayer/ieee8021d/stp/Stp.h
index decb14c2edb..d6e4e877f93 100644
--- a/src/inet/linklayer/ieee8021d/stp/Stp.h
+++ b/src/inet/linklayer/ieee8021d/stp/Stp.h
@@ -228,7 +228,7 @@ inline std::ostream& operator<<(std::ostream& os, Ieee8021dInterfaceData *p)
 
     os << " " << p->getRole() << " " << p->getState() << " ";
     os << p->getLinkCost() << " ";
-    os << p->getPriority() << " ";
+    os << p->getPortPriority() << " ";
 
     return os;
 }

From 8ce04f8d3175b521e71839561857e791f4532cb8 Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Wed, 11 Sep 2019 00:15:00 -0700
Subject: [PATCH 13/27] stp: set port cost to recommended value from IEEE when
 not explicitly specified

---
 .../configurator/L2NetworkConfigurator.cc     | 36 +++++++++++++++++++
 .../configurator/L2NetworkConfigurator.h      |  1 +
 .../configurator/L2NetworkConfigurator.ned    |  2 +-
 3 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/src/inet/linklayer/configurator/L2NetworkConfigurator.cc b/src/inet/linklayer/configurator/L2NetworkConfigurator.cc
index 35a75a8e84d..fb5690433d0 100644
--- a/src/inet/linklayer/configurator/L2NetworkConfigurator.cc
+++ b/src/inet/linklayer/configurator/L2NetworkConfigurator.cc
@@ -207,14 +207,24 @@ void L2NetworkConfigurator::readInterfaceConfiguration(Node *rootNode)
                             // cost
                             if (isNotEmpty(cost))
                                 currentNode->interfaceInfos[i]->portData.linkCost = atoi(cost);
+                            else {
+                                unsigned int defaultPortCost = getRecommendedPortCost(currentNode, currentNode->interfaceInfos[i]->interfaceEntry);
+                                currentNode->interfaceInfos[i]->portData.linkCost = defaultPortCost;
+                            }
 
                             // priority
                             if (isNotEmpty(priority))
                                 currentNode->interfaceInfos[i]->portData.portPriority = atoi(priority);
+                            else {
+                                currentNode->interfaceInfos[i]->portData.portPriority = 128;
+                            }
 
                             // edge
                             if (isNotEmpty(edge))
                                 currentNode->interfaceInfos[i]->portData.edge = strcmp(edge, "true") ? false : true;
+                            else {
+                                currentNode->interfaceInfos[i]->portData.edge = false;
+                            }
 
                             EV_DEBUG << hostModule->getFullPath() << ":" << ifEntry->getInterfaceName() << endl;
 
@@ -289,6 +299,32 @@ void L2NetworkConfigurator::configureInterface(InterfaceInfo *interfaceInfo)
     interfaceData->setEdge(interfaceInfo->portData.edge);
 }
 
+unsigned int L2NetworkConfigurator::getRecommendedPortCost(Node *node, InterfaceEntry *ie)
+{
+    Topology::LinkOut *linkOut = findLinkOut(node, ie->getNodeOutputGateId());
+    double datarate = linkOut->getLocalGate()->getChannel()->getNominalDatarate(); // in bps
+
+    // based on Table 17-3 in IEEE 802.1D-2004
+    if(datarate <= 100000)
+        return 200000000;
+    else if(datarate > 100000 && datarate <= 1000000)
+        return 20000000;
+    else if(datarate > 1000000 && datarate <= 10000000)
+        return 2000000;
+    else if(datarate > 10000000 && datarate <= 100000000)
+        return 200000;
+    else if(datarate > 100000000 && datarate <= 1000000000)
+        return 20000;
+    else if(datarate > 1000000000 && datarate <= 10000000000)
+        return 2000;
+    else if(datarate > 10000000000 && datarate <= 100000000000)
+        return 200;
+    else if(datarate > 100000000000 && datarate <= 1000000000000)
+        return 20;
+
+    return 2;
+}
+
 L2NetworkConfigurator::Matcher::~Matcher()
 {
     for (auto & elem : matchers)
diff --git a/src/inet/linklayer/configurator/L2NetworkConfigurator.h b/src/inet/linklayer/configurator/L2NetworkConfigurator.h
index 57255b081c6..882e6910d93 100644
--- a/src/inet/linklayer/configurator/L2NetworkConfigurator.h
+++ b/src/inet/linklayer/configurator/L2NetworkConfigurator.h
@@ -134,6 +134,7 @@ class INET_API L2NetworkConfigurator : public cSimpleModule
     virtual Topology::LinkOut *findLinkOut(Node *node, int gateId);
     virtual void configureInterface(InterfaceEntry *interfaceEntry);
     void configureInterface(InterfaceInfo *interfaceInfo);
+    unsigned int getRecommendedPortCost(Node *node, InterfaceEntry *ie);
 
   public:
     /**
diff --git a/src/inet/linklayer/configurator/L2NetworkConfigurator.ned b/src/inet/linklayer/configurator/L2NetworkConfigurator.ned
index d8057ef3cdf..0516615ace8 100644
--- a/src/inet/linklayer/configurator/L2NetworkConfigurator.ned
+++ b/src/inet/linklayer/configurator/L2NetworkConfigurator.ned
@@ -39,6 +39,6 @@ simple L2NetworkConfigurator
 {
     parameters:
         @display("i=block/cogwheel");
-        xml config = default(xml(""));
+        xml config = default(xml("  "));
 }
 

From 960ce2155954ee32f806d66da977c0d07ed7c73e Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Wed, 11 Sep 2019 00:24:25 -0700
Subject: [PATCH 14/27] stp: set bridge mac address correctly

---
 .../ieee8021d/relay/Ieee8021dRelay.cc         | 23 ++-----------------
 .../ieee8021d/relay/Ieee8021dRelay.h          |  5 ----
 2 files changed, 2 insertions(+), 26 deletions(-)

diff --git a/src/inet/linklayer/ieee8021d/relay/Ieee8021dRelay.cc b/src/inet/linklayer/ieee8021d/relay/Ieee8021dRelay.cc
index bc3b0d902e2..8a93231ded4 100644
--- a/src/inet/linklayer/ieee8021d/relay/Ieee8021dRelay.cc
+++ b/src/inet/linklayer/ieee8021d/relay/Ieee8021dRelay.cc
@@ -262,32 +262,13 @@ Ieee8021dInterfaceData *Ieee8021dRelay::getPortInterfaceData(unsigned int interf
 
 void Ieee8021dRelay::start()
 {
-    ie = chooseInterface();
-    if (ie) {
-        bridgeAddress = ie->getMacAddress(); // get the bridge's MAC address
-        registerAddress(bridgeAddress); // register bridge's MAC address
-    }
-    else
-        throw cRuntimeError("No non-loopback interface found!");
+    bridgeAddress = ifTable->getBaseMacAddress();
+    registerAddress(bridgeAddress);
 }
 
 void Ieee8021dRelay::stop()
 {
-    ie = nullptr;
-}
-
-InterfaceEntry *Ieee8021dRelay::chooseInterface()
-{
-    // TODO: Currently, we assume that the first non-loopback interface is an Ethernet interface
-    //       since relays work on EtherSwitches.
-    //       NOTE that, we don't check if the returning interface is an Ethernet interface!
-    for (int i = 0; i < ifTable->getNumInterfaces(); i++) {
-        InterfaceEntry *current = ifTable->getInterface(i);
-        if (!current->isLoopback())
-            return current;
-    }
 
-    return nullptr;
 }
 
 void Ieee8021dRelay::finish()
diff --git a/src/inet/linklayer/ieee8021d/relay/Ieee8021dRelay.h b/src/inet/linklayer/ieee8021d/relay/Ieee8021dRelay.h
index dba1d127613..a07a87c5891 100644
--- a/src/inet/linklayer/ieee8021d/relay/Ieee8021dRelay.h
+++ b/src/inet/linklayer/ieee8021d/relay/Ieee8021dRelay.h
@@ -53,7 +53,6 @@ class INET_API Ieee8021dRelay : public LayeredProtocolBase
     MacAddress bridgeAddress;
     IInterfaceTable *ifTable = nullptr;
     IMacAddressTable *macTable = nullptr;
-    InterfaceEntry *ie = nullptr;
     bool isStpAware = false;
 
     typedef std::pair MacAddressPair;
@@ -127,10 +126,6 @@ class INET_API Ieee8021dRelay : public LayeredProtocolBase
 
     bool isForwardingInterface(InterfaceEntry *ie);
 
-    /*
-     * Returns the first non-loopback interface.
-     */
-    virtual InterfaceEntry *chooseInterface();
     virtual void finish() override;
 };
 

From 4a88844369263a91ef6d43121f7e091926e14fd5 Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Wed, 11 Sep 2019 00:35:22 -0700
Subject: [PATCH 15/27] stp: move color values to ned param

---
 .../linklayer/ieee8021d/common/StpBase.cc     | 29 ++++++++++---------
 src/inet/linklayer/ieee8021d/common/StpBase.h |  4 +++
 src/inet/linklayer/ieee8021d/stp/Stp.ned      |  5 ++++
 3 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/src/inet/linklayer/ieee8021d/common/StpBase.cc b/src/inet/linklayer/ieee8021d/common/StpBase.cc
index f9bc0cbbb46..782466924e4 100644
--- a/src/inet/linklayer/ieee8021d/common/StpBase.cc
+++ b/src/inet/linklayer/ieee8021d/common/StpBase.cc
@@ -23,12 +23,9 @@
 
 namespace inet {
 
-static const char *ENABLED_LINK_COLOR = "#000000";
-static const char *DISABLED_LINK_COLOR = "#bbbbbb";
-static const char *ROOT_SWITCH_COLOR = "#a5ffff";
-
 StpBase::StpBase()
 {
+
 }
 
 void StpBase::initialize(int stage)
@@ -42,6 +39,10 @@ void StpBase::initialize(int stage)
 
     if (stage == INITSTAGE_LOCAL) {
         visualize = par("visualize");
+        colorLinkEnabled = par("colorLinkEnabled").stdstringValue();
+        colorLinkDisabled = par("colorLinkDisabled").stdstringValue();
+        colorRootBridge = par("colorRootBridge").stdstringValue();
+
         bridgePriority = par("bridgePriority");
 
         maxAge = par("maxAge");
@@ -77,21 +78,21 @@ void StpBase::colorLink(InterfaceEntry *ie, bool forwarding) const
 
         if (outGate && inGate && inGatePrev && outGateNext && outGatePrev && inGatePrev2) {
             if (forwarding) {
-                outGatePrev->getDisplayString().setTagArg("ls", 0, ENABLED_LINK_COLOR);
-                inGate->getDisplayString().setTagArg("ls", 0, ENABLED_LINK_COLOR);
+                outGatePrev->getDisplayString().setTagArg("ls", 0, colorLinkEnabled.c_str());
+                inGate->getDisplayString().setTagArg("ls", 0, colorLinkEnabled.c_str());
             }
             else {
-                outGatePrev->getDisplayString().setTagArg("ls", 0, DISABLED_LINK_COLOR);
-                inGate->getDisplayString().setTagArg("ls", 0, DISABLED_LINK_COLOR);
+                outGatePrev->getDisplayString().setTagArg("ls", 0, colorLinkDisabled.c_str());
+                inGate->getDisplayString().setTagArg("ls", 0, colorLinkDisabled.c_str());
             }
 
-            if ((!inGatePrev2->getDisplayString().containsTag("ls") || strcmp(inGatePrev2->getDisplayString().getTagArg("ls", 0), ENABLED_LINK_COLOR) == 0) && forwarding) {
-                outGate->getDisplayString().setTagArg("ls", 0, ENABLED_LINK_COLOR);
-                inGatePrev->getDisplayString().setTagArg("ls", 0, ENABLED_LINK_COLOR);
+            if ((!inGatePrev2->getDisplayString().containsTag("ls") || strcmp(inGatePrev2->getDisplayString().getTagArg("ls", 0), colorLinkEnabled.c_str()) == 0) && forwarding) {
+                outGate->getDisplayString().setTagArg("ls", 0, colorLinkEnabled.c_str());
+                inGatePrev->getDisplayString().setTagArg("ls", 0, colorLinkEnabled.c_str());
             }
             else {
-                outGate->getDisplayString().setTagArg("ls", 0, DISABLED_LINK_COLOR);
-                inGatePrev->getDisplayString().setTagArg("ls", 0, DISABLED_LINK_COLOR);
+                outGate->getDisplayString().setTagArg("ls", 0, colorLinkDisabled.c_str());
+                inGatePrev->getDisplayString().setTagArg("ls", 0, colorLinkDisabled.c_str());
             }
         }
     }
@@ -129,7 +130,7 @@ void StpBase::refreshDisplay() const
 
         // mark root switch
         if (isUp() && getRootInterfaceId() == -1)
-            switchModule->getDisplayString().setTagArg("i", 1, ROOT_SWITCH_COLOR);
+            switchModule->getDisplayString().setTagArg("i", 1, colorRootBridge.c_str());
         else
             switchModule->getDisplayString().setTagArg("i", 1, "");
     }
diff --git a/src/inet/linklayer/ieee8021d/common/StpBase.h b/src/inet/linklayer/ieee8021d/common/StpBase.h
index d09e6bd22e4..e5c75ed395b 100644
--- a/src/inet/linklayer/ieee8021d/common/StpBase.h
+++ b/src/inet/linklayer/ieee8021d/common/StpBase.h
@@ -34,6 +34,10 @@ class INET_API StpBase : public OperationalBase, public cListener
 {
   protected:
     bool visualize = false;    // if true it visualize the spanning tree
+    std::string colorLinkEnabled = "";
+    std::string colorLinkDisabled = "";
+    std::string colorRootBridge = "";
+
     unsigned int numPorts = 0;    // number of ports
 
     unsigned int bridgePriority = 0;    // bridge's priority
diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.ned b/src/inet/linklayer/ieee8021d/stp/Stp.ned
index 72ae1310a6b..632e418264e 100644
--- a/src/inet/linklayer/ieee8021d/stp/Stp.ned
+++ b/src/inet/linklayer/ieee8021d/stp/Stp.ned
@@ -66,6 +66,11 @@ simple Stp like ISpanningTree
         // Label ethernet interface with port role and status. Mark root switch
         bool visualize = default(false);
         
+        // only when visualize is true
+        string colorLinkEnabled = default("#000000");
+        string colorLinkDisabled = default("#bbbbbb");
+        string colorRootBridge = default("#cc3300");
+        
         // excluded interfaces from the spanning tree algorithms.
         // default is empty and all ports are included in the STP
         string disabledInterfaces = default("");

From 7bcecdcf6e22da0ae63698572b2ee3e356b27246 Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Wed, 11 Sep 2019 17:09:25 -0700
Subject: [PATCH 16/27] rstp: adding link colors to ned

---
 src/inet/linklayer/ieee8021d/rstp/Rstp.ned | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/inet/linklayer/ieee8021d/rstp/Rstp.ned b/src/inet/linklayer/ieee8021d/rstp/Rstp.ned
index 606c6955f10..30990c8c0b2 100644
--- a/src/inet/linklayer/ieee8021d/rstp/Rstp.ned
+++ b/src/inet/linklayer/ieee8021d/rstp/Rstp.ned
@@ -75,6 +75,11 @@ simple Rstp like ISpanningTree
         // Label ethernet interface with port role and status. Mark root switch
         bool visualize = default(false);
 
+        // only when visualize is true
+        string colorLinkEnabled = default("#000000");
+        string colorLinkDisabled = default("#bbbbbb");
+        string colorRootBridge = default("#cc3300");
+        
         // If true, edge ports immediately become designated/forwarding, else it will have to wait to get designated.
         bool autoEdge = default(true);
 

From 5b85c2e6b05c582b091b148ff06dc2cbbf98ae51 Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Wed, 11 Sep 2019 17:44:14 -0700
Subject: [PATCH 17/27] rstp: reordering code to better reflect the execution
 flow

---
 src/inet/linklayer/ieee8021d/rstp/Rstp.cc | 266 ++++++++++++----------
 src/inet/linklayer/ieee8021d/stp/Stp.cc   |  10 +-
 2 files changed, 146 insertions(+), 130 deletions(-)

diff --git a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
index ae5ad670cc2..6522e60c5be 100644
--- a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
+++ b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
@@ -31,6 +31,7 @@ Define_Module(Rstp);
 
 Rstp::Rstp()
 {
+
 }
 
 Rstp::~Rstp()
@@ -56,9 +57,53 @@ void Rstp::initialize(int stage)
     }
 }
 
+void Rstp::start()
+{
+    StpBase::start();
+    initPorts();
+    scheduleAt(simTime(), helloTimer);
+}
+
+void Rstp::initPorts()
+{
+    for (unsigned int j = 0; j < numPorts; j++) {
+        int interfaceId = ifTable->getInterface(j)->getInterfaceId();
+        Ieee8021dInterfaceData *jPort = getPortInterfaceData(interfaceId);
+        if (!jPort->isEdge()) {
+            jPort->setRole(Ieee8021dInterfaceData::NOTASSIGNED);
+            jPort->setState(Ieee8021dInterfaceData::DISCARDING);
+            jPort->setNextUpgrade(simTime() + migrateTime);
+        }
+        else {
+            jPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
+            jPort->setState(Ieee8021dInterfaceData::FORWARDING);
+        }
+        initInterfacedata(interfaceId);
+        macTable->flush(interfaceId);
+    }
+
+    scheduleNextUpgrade();
+}
+
+void Rstp::initInterfacedata(unsigned int interfaceId)
+{
+    // note: port cost and port priority are configured by the L2NetworkConfigurator
+
+    Ieee8021dInterfaceData *ifd = getPortInterfaceData(interfaceId);
+    ifd->setRootPriority(bridgePriority);
+    ifd->setRootAddress(bridgeAddress);
+    ifd->setRootPathCost(0);
+    ifd->setAge(0);
+    ifd->setBridgePriority(bridgePriority);
+    ifd->setBridgeAddress(bridgeAddress);
+    ifd->setPortNum(-1);
+    ifd->setLostBPDU(0);
+}
+
 void Rstp::scheduleNextUpgrade()
 {
     cancelEvent(upgradeTimer);
+
     Ieee8021dInterfaceData *nextInterfaceData = nullptr;
     for (unsigned int i = 0; i < numPorts; i++) {
         int interfaceId = ifTable->getInterface(i)->getInterfaceId();
@@ -86,6 +131,7 @@ void Rstp::scheduleNextUpgrade()
             }
         }
     }
+
     if (nextInterfaceData != nullptr)
         scheduleAt(nextInterfaceData->getNextUpgrade(), upgradeTimer);
 }
@@ -114,38 +160,10 @@ void Rstp::handleMessageWhenUp(cMessage *msg)
     }
 }
 
-void Rstp::handleUpgrade(cMessage *msg)
-{
-    for (unsigned int i = 0; i < numPorts; i++) {
-        int interfaceId = ifTable->getInterface(i)->getInterfaceId();
-        Ieee8021dInterfaceData *iPort = getPortInterfaceData(interfaceId);
-        if (getPortInterfaceEntry(interfaceId)->hasCarrier() && iPort->getNextUpgrade() == simTime()) {
-            if (iPort->getRole() == Ieee8021dInterfaceData::NOTASSIGNED) {
-                EV_DETAIL << "MigrateTime. Setting port " << interfaceId << "to designated." << endl;
-                iPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
-                iPort->setState(Ieee8021dInterfaceData::DISCARDING);    // contest to become forwarding.
-                iPort->setNextUpgrade(simTime() + forwardDelay);
-            }
-            else if (iPort->getRole() == Ieee8021dInterfaceData::DESIGNATED) {
-                if (iPort->getState() == Ieee8021dInterfaceData::DISCARDING) {
-                    EV_INFO << "UpgradeTime. Setting port " << interfaceId << " state to learning." << endl;
-                    iPort->setState(Ieee8021dInterfaceData::LEARNING);
-                    iPort->setNextUpgrade(simTime() + forwardDelay);
-                }
-                else if (iPort->getState() == Ieee8021dInterfaceData::LEARNING) {
-                    EV_INFO << "UpgradeTime. Setting port " << interfaceId << " state to forwarding." << endl;
-                    iPort->setState(Ieee8021dInterfaceData::FORWARDING);
-                    flushOtherPorts(interfaceId);
-                }
-            }
-        }
-    }
-    scheduleNextUpgrade();
-}
-
 void Rstp::handleHelloTime(cMessage *msg)
 {
     EV_DETAIL << "Hello time." << endl;
+
     for (unsigned int i = 0; i < numPorts; i++) {
         // sends hello through all active (learning, forwarding or not assigned) ports
         // increments LostBPDU just from ROOT, ALTERNATE and BACKUP
@@ -205,11 +223,65 @@ void Rstp::handleHelloTime(cMessage *msg)
             }
         }
     }
+
     sendBPDUs();    // generating and sending new BPDUs
     sendTCNtoRoot();
     scheduleAt(simTime() + helloTime, msg);    // programming next hello time
 }
 
+void Rstp::handleUpgrade(cMessage *msg)
+{
+    for (unsigned int i = 0; i < numPorts; i++) {
+        int interfaceId = ifTable->getInterface(i)->getInterfaceId();
+        Ieee8021dInterfaceData *iPort = getPortInterfaceData(interfaceId);
+        if (getPortInterfaceEntry(interfaceId)->hasCarrier() && iPort->getNextUpgrade() == simTime()) {
+            if (iPort->getRole() == Ieee8021dInterfaceData::NOTASSIGNED) {
+                EV_DETAIL << "MigrateTime. Setting port " << interfaceId << "to designated." << endl;
+                iPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
+                iPort->setState(Ieee8021dInterfaceData::DISCARDING);    // contest to become forwarding.
+                iPort->setNextUpgrade(simTime() + forwardDelay);
+            }
+            else if (iPort->getRole() == Ieee8021dInterfaceData::DESIGNATED) {
+                if (iPort->getState() == Ieee8021dInterfaceData::DISCARDING) {
+                    EV_INFO << "UpgradeTime. Setting port " << interfaceId << " state to learning." << endl;
+                    iPort->setState(Ieee8021dInterfaceData::LEARNING);
+                    iPort->setNextUpgrade(simTime() + forwardDelay);
+                }
+                else if (iPort->getState() == Ieee8021dInterfaceData::LEARNING) {
+                    EV_INFO << "UpgradeTime. Setting port " << interfaceId << " state to forwarding." << endl;
+                    iPort->setState(Ieee8021dInterfaceData::FORWARDING);
+                    flushOtherPorts(interfaceId);
+                }
+            }
+        }
+    }
+
+    scheduleNextUpgrade();
+}
+
+void Rstp::handleIncomingFrame(Packet *packet)
+{
+    const Ptr& frame = packet->peekAtFront();
+    // incoming BPDU handling
+    // checking message age
+    int arrivalInterfaceId = packet->getTag()->getInterfaceId();
+    MacAddress src = packet->getTag()->getSrcAddress();
+    EV_INFO << "BPDU received at port " << arrivalInterfaceId << "." << endl;
+    if (frame->getMessageAge() < maxAge) {
+        // checking TC
+        checkTC(frame, arrivalInterfaceId);    // sets TCWhile if arrival port was FORWARDING
+        // checking possible backup
+        if (src.compareTo(bridgeAddress) == 0) // more than one port in the same LAN
+            handleBackup(frame, arrivalInterfaceId);
+        else
+            processBPDU(frame, arrivalInterfaceId);
+    }
+    else
+        EV_DETAIL << "Expired BPDU" << endl;
+
+    delete packet;
+}
+
 void Rstp::checkTC(const Ptr& frame, int arrivalInterfaceId)
 {
     Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalInterfaceId);
@@ -276,28 +348,6 @@ void Rstp::handleBackup(const Ptr& frame, unsigned int arrivalInterf
     }
 }
 
-void Rstp::handleIncomingFrame(Packet *packet)
-{
-    const Ptr& frame = packet->peekAtFront();
-    // incoming BPDU handling
-    // checking message age
-    int arrivalInterfaceId = packet->getTag()->getInterfaceId();
-    MacAddress src = packet->getTag()->getSrcAddress();
-    EV_INFO << "BPDU received at port " << arrivalInterfaceId << "." << endl;
-    if (frame->getMessageAge() < maxAge) {
-        // checking TC
-        checkTC(frame, arrivalInterfaceId);    // sets TCWhile if arrival port was FORWARDING
-        // checking possible backup
-        if (src.compareTo(bridgeAddress) == 0) // more than one port in the same LAN
-            handleBackup(frame, arrivalInterfaceId);
-        else
-            processBPDU(frame, arrivalInterfaceId);
-    }
-    else
-        EV_DETAIL << "Expired BPDU" << endl;
-    delete packet;
-}
-
 void Rstp::processBPDU(const Ptr& frame, unsigned int arrivalInterfaceId)
 {
     //three challenges.
@@ -454,6 +504,7 @@ bool Rstp::processBetterSource(const Ptr& frame, unsigned int arriva
                 break;
         }
     }
+
     return false;
 }
 
@@ -574,6 +625,7 @@ bool Rstp::processSameSource(const Ptr& frame, unsigned int arrivalI
             updateInterfacedata(frame, arrivalInterfaceId);
             break;
     }
+
     return false;
 }
 
@@ -646,12 +698,13 @@ void Rstp::sendBPDUs()
 
 void Rstp::sendBPDU(int interfaceId)
 {
-    // send a BPDU throuth port
+    // send a BPDU through port
     Ieee8021dInterfaceData *iport = getPortInterfaceData(interfaceId);
     int r = getRootInterfaceId();
     Ieee8021dInterfaceData *rootPort;
     if (r != -1)
         rootPort = getPortInterfaceData(r);
+
     if (iport->getRole() != Ieee8021dInterfaceData::DISABLED) {
         Packet *packet = new Packet("BPDU");
         const auto& frame = makeShared();
@@ -707,73 +760,6 @@ void Rstp::sendBPDU(int interfaceId)
     }
 }
 
-void Rstp::printState()
-{
-    //  prints current database info
-    EV_DETAIL << "Switch " << findContainingNode(this)->getFullName() << " state:" << endl;
-    int rootIndex = getRootInterfaceId();
-    EV_DETAIL << "  Priority: " << bridgePriority << endl;
-    EV_DETAIL << "  Local MAC: " << bridgeAddress << endl;
-    if (rootIndex >= 0) {
-        Ieee8021dInterfaceData *rootPort = getPortInterfaceData(rootIndex);
-        EV_DETAIL << "  Root Priority: " << rootPort->getRootPriority() << endl;
-        EV_DETAIL << "  Root Address: " << rootPort->getRootAddress().str() << endl;
-        EV_DETAIL << "  Cost: " << rootPort->getRootPathCost() << endl;
-        EV_DETAIL << "  Age:  " << rootPort->getAge() << endl;
-        EV_DETAIL << "  Bridge Priority: " << rootPort->getBridgePriority() << endl;
-        EV_DETAIL << "  Bridge Address: " << rootPort->getBridgeAddress().str() << endl;
-        EV_DETAIL << "  Src TxGate Priority: " << rootPort->getPortPriority() << endl;
-        EV_DETAIL << "  Src TxGate: " << rootPort->getPortNum() << endl;
-    }
-    EV_DETAIL << "Port State/Role:" << endl;
-    for (unsigned int i = 0; i < numPorts; i++) {
-        int interfaceId = ifTable->getInterface(i)->getInterfaceId();
-        Ieee8021dInterfaceData *iPort = getPortInterfaceData(interfaceId);
-        EV_DETAIL << "  " << i << ": " << iPort->getStateName() << "/" << iPort->getRoleName() << (iPort->isEdge() ? " (Client)" : "") << endl;
-    }
-    EV_DETAIL << "Per-port best sources, Root/Src:" << endl;
-    for (unsigned int i = 0; i < numPorts; i++) {
-        int interfaceId = ifTable->getInterface(i)->getInterfaceId();
-        Ieee8021dInterfaceData *iPort = getPortInterfaceData(interfaceId);
-        EV_DETAIL << "  " << interfaceId << ": " << iPort->getRootAddress().str() << "/" << iPort->getBridgeAddress().str() << endl;
-    }
-    EV_DETAIL << endl;
-}
-
-void Rstp::initInterfacedata(unsigned int interfaceId)
-{
-    Ieee8021dInterfaceData *ifd = getPortInterfaceData(interfaceId);
-    ifd->setRootPriority(bridgePriority);
-    ifd->setRootAddress(bridgeAddress);
-    ifd->setRootPathCost(0);
-    ifd->setAge(0);
-    ifd->setBridgePriority(bridgePriority);
-    ifd->setBridgeAddress(bridgeAddress);
-    ifd->setPortPriority(-1);
-    ifd->setPortNum(-1);
-    ifd->setLostBPDU(0);
-}
-
-void Rstp::initPorts()
-{
-    for (unsigned int j = 0; j < numPorts; j++) {
-        int interfaceId = ifTable->getInterface(j)->getInterfaceId();
-        Ieee8021dInterfaceData *jPort = getPortInterfaceData(interfaceId);
-        if (!jPort->isEdge()) {
-            jPort->setRole(Ieee8021dInterfaceData::NOTASSIGNED);
-            jPort->setState(Ieee8021dInterfaceData::DISCARDING);
-            jPort->setNextUpgrade(simTime() + migrateTime);
-        }
-        else {
-            jPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
-            jPort->setState(Ieee8021dInterfaceData::FORWARDING);
-        }
-        initInterfacedata(interfaceId);
-        macTable->flush(interfaceId);
-    }
-    scheduleNextUpgrade();
-}
-
 void Rstp::updateInterfacedata(const Ptr& frame, unsigned int portNum)
 {
     Ieee8021dInterfaceData *ifd = getPortInterfaceData(portNum);
@@ -909,7 +895,6 @@ void Rstp::flushOtherPorts(unsigned int portId)
     }
 }
 
-//void Rstp::receiveChangeNotification(int signalID, const cObject *obj)
 void Rstp::receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj, cObject *details)
 {
     Enter_Method_Silent();
@@ -934,11 +919,43 @@ void Rstp::receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj,
     }
 }
 
-void Rstp::start()
+void Rstp::printState()
 {
-    StpBase::start();
-    initPorts();
-    scheduleAt(simTime(), helloTimer);
+    //  prints current database info
+    EV_DETAIL << "Switch " << findContainingNode(this)->getFullName() << " state:" << endl;
+    EV_DETAIL << "  Priority: " << bridgePriority << endl;
+    EV_DETAIL << "  Local MAC: " << bridgeAddress << endl;
+
+    int rootIndex = getRootInterfaceId();
+    if (rootIndex >= 0) {
+        Ieee8021dInterfaceData *rootPort = getPortInterfaceData(rootIndex);
+        EV_DETAIL << "  Root Priority: " << rootPort->getRootPriority() << endl;
+        EV_DETAIL << "  Root Address: " << rootPort->getRootAddress().str() << endl;
+        EV_DETAIL << "  Cost: " << rootPort->getRootPathCost() << endl;
+        EV_DETAIL << "  Age:  " << rootPort->getAge() << endl;
+        EV_DETAIL << "  Bridge Priority: " << rootPort->getBridgePriority() << endl;
+        EV_DETAIL << "  Bridge Address: " << rootPort->getBridgeAddress().str() << endl;
+        EV_DETAIL << "  Src TxGate Priority: " << rootPort->getPortPriority() << endl;
+        EV_DETAIL << "  Src TxGate: " << rootPort->getPortNum() << endl;
+    }
+
+    EV_DETAIL << "Port State/Role:" << endl;
+
+    for (unsigned int i = 0; i < numPorts; i++) {
+        int interfaceId = ifTable->getInterface(i)->getInterfaceId();
+        Ieee8021dInterfaceData *iPort = getPortInterfaceData(interfaceId);
+        EV_DETAIL << "  " << i << ": " << iPort->getStateName() << "/" << iPort->getRoleName() << (iPort->isEdge() ? " (Client)" : "") << endl;
+    }
+
+    EV_DETAIL << "Per-port best sources, Root/Src:" << endl;
+
+    for (unsigned int i = 0; i < numPorts; i++) {
+        int interfaceId = ifTable->getInterface(i)->getInterfaceId();
+        Ieee8021dInterfaceData *iPort = getPortInterfaceData(interfaceId);
+        EV_DETAIL << "  " << interfaceId << ": " << iPort->getRootAddress().str() << "/" << iPort->getBridgeAddress().str() << endl;
+    }
+
+    EV_DETAIL << endl;
 }
 
 void Rstp::stop()
@@ -949,4 +966,3 @@ void Rstp::stop()
 }
 
 } // namespace inet
-
diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc
index c6fac352fc4..39445887a53 100644
--- a/src/inet/linklayer/ieee8021d/stp/Stp.cc
+++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc
@@ -37,6 +37,11 @@ Stp::Stp()
 
 }
 
+Stp::~Stp()
+{
+    cancelAndDelete(tick);
+}
+
 void Stp::initialize(int stage)
 {
     StpBase::initialize(stage);
@@ -52,11 +57,6 @@ void Stp::initialize(int stage)
     }
 }
 
-Stp::~Stp()
-{
-    cancelAndDelete(tick);
-}
-
 void Stp::start()
 {
     StpBase::start();

From 7d231ce9d59b40a14560fa1eb00f03f634624912 Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Wed, 11 Sep 2019 18:22:19 -0700
Subject: [PATCH 18/27] stp,rstp: fix protocol version and type in BPDUs

---
 src/inet/linklayer/ieee8021d/common/StpBase.h | 10 ++++++++++
 src/inet/linklayer/ieee8021d/rstp/Rstp.cc     | 15 +++++++++++++++
 src/inet/linklayer/ieee8021d/stp/Stp.cc       | 12 ++++++------
 src/inet/linklayer/ieee8021d/stp/Stp.h        |  1 -
 4 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/src/inet/linklayer/ieee8021d/common/StpBase.h b/src/inet/linklayer/ieee8021d/common/StpBase.h
index e5c75ed395b..88e53d0d3bb 100644
--- a/src/inet/linklayer/ieee8021d/common/StpBase.h
+++ b/src/inet/linklayer/ieee8021d/common/StpBase.h
@@ -32,6 +32,16 @@ namespace inet {
  */
 class INET_API StpBase : public OperationalBase, public cListener
 {
+public:
+    enum BdpuType { BDPU_TYPE_CONFIG = 0,
+        TBDPU_TYPE_CN = 1,
+        BDPU_TYPE_RSTP = 2 };
+
+    enum ProtocolVersion { PROTO_VERSION_STP = 0,
+        PROTO_VERSION_RSTP = 2,
+        PROTO_VERSION_MSTP = 3,
+        PROTO_VERSION_SPB = 4 };
+
   protected:
     bool visualize = false;    // if true it visualize the spanning tree
     std::string colorLinkEnabled = "";
diff --git a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
index 6522e60c5be..52e80ea94c8 100644
--- a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
+++ b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
@@ -642,22 +642,31 @@ void Rstp::sendTCNtoRoot()
                 Packet *packet = new Packet("BPDU");
                 const auto& frame = makeShared();
 
+                frame->setProtocolIdentifier(0);
+                frame->setProtocolVersionIdentifier(PROTO_VERSION_RSTP);
+                frame->setBpduType(BDPU_TYPE_RSTP); // todo: check
+
                 BpduFlags bpduFlags;
                 bpduFlags.tcaFlag = false;
                 bpduFlags.tcFlag = true;
                 frame->setBpduFlags(bpduFlags);
+
                 RootIdentifier rootId;
                 rootId.rootPriority = rootPort->getRootPriority();
                 rootId.rootAddress = rootPort->getRootAddress();
                 frame->setRootIdentifier(rootId);
+
                 frame->setRootPathCost(rootPort->getRootPathCost());
+
                 BridgeIdentifier bridgeId;
                 bridgeId.bridgePriority = bridgePriority;
                 bridgeId.bridgeAddress = bridgeAddress;
                 frame->setBridgeIdentifier(bridgeId);
+
                 PortIdentifier portId;
                 portId.portNum = r;
                 frame->setPortIdentifier(portId);
+
                 frame->setMessageAge(rootPort->getAge());
                 frame->setMaxAge(maxAge);
                 frame->setHelloTime(helloTime);
@@ -708,6 +717,11 @@ void Rstp::sendBPDU(int interfaceId)
     if (iport->getRole() != Ieee8021dInterfaceData::DISABLED) {
         Packet *packet = new Packet("BPDU");
         const auto& frame = makeShared();
+
+        frame->setProtocolIdentifier(0);
+        frame->setProtocolVersionIdentifier(PROTO_VERSION_RSTP);
+        frame->setBpduType(BDPU_TYPE_RSTP);
+
         if (r != -1) {
             RootIdentifier rootId;
             rootId.rootPriority = rootPort->getRootPriority();
@@ -738,6 +752,7 @@ void Rstp::sendBPDU(int interfaceId)
         frame->setBpduFlags(bpduFlags);
 
         PortIdentifier portId;
+        portId.portPriority = getPortInterfaceData(interfaceId)->getPortPriority();
         portId.portNum = interfaceId;
         frame->setPortIdentifier(portId);
 
diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc
index 39445887a53..28abdba80b0 100644
--- a/src/inet/linklayer/ieee8021d/stp/Stp.cc
+++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc
@@ -135,9 +135,9 @@ void Stp::handleMessageWhenUp(cMessage *msg)
             return;
         }
 
-        if (bpdu->getBpduType() == CONFIG_BDPU)
+        if (bpdu->getBpduType() == BDPU_TYPE_CONFIG)
             handleBPDU(packet, bpdu);
-        else if (bpdu->getBpduType() == TCN_BPDU)
+        else if (bpdu->getBpduType() == TBDPU_TYPE_CN)
             handleTCN(packet, bpdu);
     }
     else {
@@ -276,8 +276,8 @@ void Stp::generateBPDU(int interfaceId, const MacAddress& address, bool tcFlag,
     packet->addTag()->setProtocol(&Protocol::ethernetMac);
 
     bpdu->setProtocolIdentifier(0);
-    bpdu->setProtocolVersionIdentifier(0);
-    bpdu->setBpduType(CONFIG_BDPU);
+    bpdu->setProtocolVersionIdentifier(PROTO_VERSION_STP);
+    bpdu->setBpduType(BDPU_TYPE_CONFIG);
 
     if (topologyChangeNotification) {
         if (isRoot || tcFlag) {
@@ -344,8 +344,8 @@ void Stp::generateTCN()
             Packet *packet = new Packet("BPDU");
             const auto& tcn = makeShared();
             tcn->setProtocolIdentifier(0);
-            tcn->setProtocolVersionIdentifier(0);
-            tcn->setBpduType(TCN_BPDU);
+            tcn->setProtocolVersionIdentifier(PROTO_VERSION_STP);
+            tcn->setBpduType(TBDPU_TYPE_CN);
 
             auto macAddressReq = packet->addTag();
             macAddressReq->setSrcAddress(bridgeAddress);
diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.h b/src/inet/linklayer/ieee8021d/stp/Stp.h
index d6e4e877f93..f53cfab36de 100644
--- a/src/inet/linklayer/ieee8021d/stp/Stp.h
+++ b/src/inet/linklayer/ieee8021d/stp/Stp.h
@@ -40,7 +40,6 @@ class INET_API Stp : public StpBase
 {
   public:
     typedef Ieee8021dInterfaceData::PortInfo PortInfo;
-    enum BdpuType { CONFIG_BDPU = 0, TCN_BPDU = 1 };
 
   protected:
     static const double tickInterval;    // interval between two ticks

From 2b1b5c6245149389291396833036ff9b61afa71c Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Wed, 11 Sep 2019 18:28:52 -0700
Subject: [PATCH 19/27] stp: use better types

---
 .../ieee8021d/common/Ieee8021dBpdu.msg        | 22 +++++++++----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/src/inet/linklayer/ieee8021d/common/Ieee8021dBpdu.msg b/src/inet/linklayer/ieee8021d/common/Ieee8021dBpdu.msg
index de1c05904a5..ef73caab266 100644
--- a/src/inet/linklayer/ieee8021d/common/Ieee8021dBpdu.msg
+++ b/src/inet/linklayer/ieee8021d/common/Ieee8021dBpdu.msg
@@ -40,9 +40,9 @@ struct BridgeIdentifier
 
 struct PortIdentifier
 {
-    unsigned int portPriority;  // 1 byte, priority of sender port
-    unsigned int portNum;       // 1 byte, port number (ethg[] gate index) of sender port
-                                // (or 4 bit priority (shifted with 4 bit) and 12 bit portnum (in 802.1D-2004))
+    uint8_t portPriority;  // 1 byte, priority of sender port
+    uint8_t portNum;       // 1 byte, port number (ethg[] gate index) of sender port
+                           // (or 4 bit priority (shifted with 4 bit) and 12 bit portnum (in 802.1D-2004))
 }
 
 //
@@ -53,16 +53,16 @@ class Bpdu extends FieldsChunk
 {
     chunkLength = B(35);
     
-    uint16_t protocolIdentifier;              // 2 bytes, 0 for STP, 1 for RSTP (TODO use them)
-    unsigned int protocolVersionIdentifier;   // 1 byte, version ID, currently 0
-    unsigned int bpduType;                    // 1 byte, 0 for Configuration BPDU, 1 for Topology Change Notification BPDU
+    uint16_t protocolIdentifier;        // 2 bytes, 0 for STP, 1 for RSTP (TODO use them)
+    uint8_t protocolVersionIdentifier;  // 1 byte, version ID, currently 0
+    uint8_t bpduType;                   // 1 byte, 0 for Configuration BPDU, 1 for Topology Change Notification BPDU
 	BpduFlags bpduFlags;
     RootIdentifier rootIdentifier;    
-    uint32_t rootPathCost;                    // 4 bytes, cost to the root
+    uint32_t rootPathCost;              // 4 bytes, cost to the root
     BridgeIdentifier bridgeIdentifier;
     PortIdentifier portIdentifier;    
-    simtime_t messageAge;                     // 2 bytes, Message Age (in 256ths of a second)
-    simtime_t maxAge;                         // 2 bytes, maximum lifetime of the BPDU (in 256ths of a second)
-    simtime_t helloTime;                      // 2 bytes, Hello Time of the sender bridge (in 256ths of a second)
-    simtime_t forwardDelay;                   // 2 bytes, Forward Delay timer of the sender bridge (in 256ths of a second)
+    simtime_t messageAge;               // 2 bytes, Message Age (in 256ths of a second)
+    simtime_t maxAge;                   // 2 bytes, maximum lifetime of the BPDU (in 256ths of a second)
+    simtime_t helloTime;                // 2 bytes, Hello Time of the sender bridge (in 256ths of a second)
+    simtime_t forwardDelay;             // 2 bytes, Forward Delay timer of the sender bridge (in 256ths of a second)
 }

From 361c2671aebb8147ad01e85cb729cc356ef34acb Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Wed, 11 Sep 2019 20:10:26 -0700
Subject: [PATCH 20/27] stp: print isEdge information of an interface

---
 src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc
index 32db0bd0458..47bdda058d4 100644
--- a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc
+++ b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc
@@ -56,6 +56,7 @@ std::string Ieee8021dInterfaceData::detailedInfo() const
     out << " state:" << getStateName();
     out << " priority:" << getPortPriority();
     out << " linkCost:" << getLinkCost();
+    out << " isEdge:" << isEdge();
 
     return out.str();
 }

From 9b9ab6a2d0464adb2b1e64d34b112e899d3964c0 Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Wed, 11 Sep 2019 20:18:28 -0700
Subject: [PATCH 21/27] stp: refactoring

---
 src/inet/linklayer/ieee8021d/rstp/Rstp.cc |  1 +
 src/inet/linklayer/ieee8021d/stp/Stp.cc   | 42 ++++++++++++-----------
 2 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
index 52e80ea94c8..7469b40ae94 100644
--- a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
+++ b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
@@ -78,6 +78,7 @@ void Rstp::initPorts()
             jPort->setRole(Ieee8021dInterfaceData::DESIGNATED);
             jPort->setState(Ieee8021dInterfaceData::FORWARDING);
         }
+
         initInterfacedata(interfaceId);
         macTable->flush(interfaceId);
     }
diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc
index 28abdba80b0..eb0bed82c83 100644
--- a/src/inet/linklayer/ieee8021d/stp/Stp.cc
+++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc
@@ -62,6 +62,7 @@ void Stp::start()
     StpBase::start();
 
     initPortTable();
+
     currentBridgePriority = bridgePriority;
     isRoot = true;
     topologyChangeNotification = true;
@@ -74,6 +75,7 @@ void Stp::start()
     currentMaxAge = maxAge;
     currentFwdDelay = forwardDelay;
     helloTime = 0;
+
     setAllDesignated();
 
     WATCH(bridgePriority);
@@ -119,6 +121,25 @@ void Stp::initInterfacedata(unsigned int interfaceId)
     ifd->setLostBPDU(0);
 }
 
+void Stp::setAllDesignated()
+{
+    // all ports of the root switch are designated ports
+    EV_DETAIL << "All ports become designated." << endl;    // todo
+
+    desPorts.clear();
+    for (unsigned int i = 0; i < numPorts; i++) {
+        InterfaceEntry *ie = ifTable->getInterface(i);
+        Ieee8021dInterfaceData *portData = ie->getProtocolData();
+        ASSERT(portData != nullptr);
+        if (portData->getRole() == Ieee8021dInterfaceData::DISABLED)
+            continue;
+
+        int interfaceId = ie->getInterfaceId();
+        portData->setRole(Ieee8021dInterfaceData::DESIGNATED);
+        desPorts.push_back(interfaceId);
+    }
+}
+
 void Stp::handleMessageWhenUp(cMessage *msg)
 {
     if (!msg->isSelfMessage()) {
@@ -361,25 +382,6 @@ void Stp::generateTCN()
     }
 }
 
-void Stp::setAllDesignated()
-{
-    // all ports of the root switch are designated ports
-    EV_DETAIL << "All ports become designated." << endl;    // todo
-
-    desPorts.clear();
-    for (unsigned int i = 0; i < numPorts; i++) {
-        InterfaceEntry *ie = ifTable->getInterface(i);
-        Ieee8021dInterfaceData *portData = ie->getProtocolData();
-        ASSERT(portData != nullptr);
-        if (portData->getRole() == Ieee8021dInterfaceData::DISABLED)
-            continue;
-
-        int interfaceId = ie->getInterfaceId();
-        portData->setRole(Ieee8021dInterfaceData::DESIGNATED);
-        desPorts.push_back(interfaceId);
-    }
-}
-
 void Stp::handleBPDU(Packet *packet, const Ptr& bpdu)
 {
     int arrivalGate = packet->getTag()->getInterfaceId();
@@ -704,6 +706,7 @@ void Stp::selectDesignatedPorts()
             portData->setRole(Ieee8021dInterfaceData::DESIGNATED);
             continue;
         }
+
         if (result < 0) {
             EV_DETAIL << "Port=" << ie->getFullName() << " goes into alternate role." << endl;
             portData->setRole(Ieee8021dInterfaceData::ALTERNATE);
@@ -748,4 +751,3 @@ void Stp::stop()
 }
 
 } // namespace inet
-

From 4ba018e69da652730262ff2ff6d784fc038ca93e Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Thu, 12 Sep 2019 01:35:35 -0700
Subject: [PATCH 22/27] stp: stp does not have any DISCARDING states

---
 .../configurator/Ieee8021dInterfaceData.cc    | 47 ++++++++++---------
 .../configurator/Ieee8021dInterfaceData.h     |  2 +-
 src/inet/linklayer/ieee8021d/stp/Stp.cc       | 10 ++--
 3 files changed, 31 insertions(+), 28 deletions(-)

diff --git a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc
index 47bdda058d4..b0382a61541 100644
--- a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc
+++ b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc
@@ -64,43 +64,46 @@ std::string Ieee8021dInterfaceData::detailedInfo() const
 const char *Ieee8021dInterfaceData::getRoleName(PortRole role)
 {
     switch (role) {
-        case ALTERNATE:
-            return "ALTERNATE";
+    case NOTASSIGNED:
+        return "NOTASSIGNED";
 
-        case NOTASSIGNED:
-            return "NOTASSIGNED";
+    case ROOT:
+        return "ROOT";
 
-        case DISABLED:
-            return "DISABLED";
+    case DESIGNATED:
+        return "DESIGNATED";
 
-        case DESIGNATED:
-            return "DESIGNATED";
+    case ALTERNATE:
+        return "ALTERNATE";
 
-        case BACKUP:
-            return "BACKUP";
+    case DISABLED:
+        return "DISABLED";
 
-        case ROOT:
-            return "ROOT";
+    case BACKUP:
+        return "BACKUP";
 
-        default:
-            throw cRuntimeError("Unknown port role %d", role);
+    default:
+        throw cRuntimeError("Unknown port role %d", role);
     }
 }
 
 const char *Ieee8021dInterfaceData::getStateName(PortState state)
 {
     switch (state) {
-        case DISCARDING:
-            return "DISCARDING";
+    case BLOCKING:
+        return "BLOCKING";
 
-        case LEARNING:
-            return "LEARNING";
+    case LEARNING:
+        return "LEARNING";
 
-        case FORWARDING:
-            return "FORWARDING";
+    case FORWARDING:
+        return "FORWARDING";
 
-        default:
-            throw cRuntimeError("Unknown port state %d", state);
+    case DISCARDING:
+        return "DISCARDING";
+
+    default:
+        throw cRuntimeError("Unknown port state %d", state);
     }
 }
 
diff --git a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h
index bfc2195c3ff..00e9ea2cc31 100644
--- a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h
+++ b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h
@@ -36,7 +36,7 @@ class INET_API Ieee8021dInterfaceData : public InterfaceProtocolData
   public:
     enum PortRole { NOTASSIGNED, ROOT, DESIGNATED, ALTERNATE, DISABLED, BACKUP /*rstp only*/ };
 
-    enum PortState { DISCARDING, LEARNING, FORWARDING };
+    enum PortState { BLOCKING /*stp only*/, LEARNING, FORWARDING, DISCARDING /*rstp only*/ };
 
     class PortInfo
     {
diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc
index eb0bed82c83..ff4d6d74a80 100644
--- a/src/inet/linklayer/ieee8021d/stp/Stp.cc
+++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc
@@ -110,7 +110,7 @@ void Stp::initInterfacedata(unsigned int interfaceId)
 
     // note: port cost and port priority are configured by the L2NetworkConfigurator
 
-    ifd->setState(Ieee8021dInterfaceData::DISCARDING);
+    ifd->setState(Ieee8021dInterfaceData::BLOCKING);
     ifd->setRootPriority(bridgePriority);
     ifd->setRootAddress(bridgeAddress);
     ifd->setRootPathCost(0);
@@ -244,7 +244,7 @@ void Stp::checkTimers()
         if (port->getRole() == Ieee8021dInterfaceData::ROOT || port->getRole() == Ieee8021dInterfaceData::DESIGNATED) {
             if (port->getFdWhile() >= currentFwdDelay) {
                 switch (port->getState()) {
-                    case Ieee8021dInterfaceData::DISCARDING:
+                    case Ieee8021dInterfaceData::BLOCKING:
                         EV_DETAIL << "Port=" << interfaceId << " goes into learning state." << endl;
                         port->setState(Ieee8021dInterfaceData::LEARNING);
                         port->setFdWhile(0);
@@ -263,9 +263,9 @@ void Stp::checkTimers()
             }
         }
         else {
-            EV_DETAIL << "Port=" << interfaceId << " goes into discarding state." << endl;
+            EV_DETAIL << "Port=" << interfaceId << " goes into BLOCKING state." << endl;
             port->setFdWhile(0);
-            port->setState(Ieee8021dInterfaceData::DISCARDING);
+            port->setState(Ieee8021dInterfaceData::BLOCKING);
         }
     }
 }
@@ -536,7 +536,7 @@ bool Stp::isSuperiorBPDU(int interfaceId, const Ptr& bpdu)
     // BPDU is superior
     if (result < 0) {
         port->setFdWhile(0);    // renew info
-        port->setState(Ieee8021dInterfaceData::DISCARDING);
+        port->setState(Ieee8021dInterfaceData::BLOCKING);
         setSuperiorBPDU(interfaceId, bpdu);    // renew information
         delete xBpdu;
         return true;

From 97da4e0df53d4b135ecc43112e5724d926912244 Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Thu, 12 Sep 2019 15:14:09 -0700
Subject: [PATCH 23/27] stp: cosmetics

---
 src/inet/linklayer/ieee8021d/common/StpBase.h |  6 +-
 src/inet/linklayer/ieee8021d/rstp/Rstp.cc     |  4 +-
 src/inet/linklayer/ieee8021d/stp/Stp.cc       | 69 ++++++++-----------
 src/inet/linklayer/ieee8021d/stp/Stp.h        |  7 --
 4 files changed, 35 insertions(+), 51 deletions(-)

diff --git a/src/inet/linklayer/ieee8021d/common/StpBase.h b/src/inet/linklayer/ieee8021d/common/StpBase.h
index 88e53d0d3bb..6d81cf7dfcb 100644
--- a/src/inet/linklayer/ieee8021d/common/StpBase.h
+++ b/src/inet/linklayer/ieee8021d/common/StpBase.h
@@ -33,9 +33,9 @@ namespace inet {
 class INET_API StpBase : public OperationalBase, public cListener
 {
 public:
-    enum BdpuType { BDPU_TYPE_CONFIG = 0,
-        TBDPU_TYPE_CN = 1,
-        BDPU_TYPE_RSTP = 2 };
+    enum BdpuType { BPDU_TYPE_CONFIG = 0,
+        BPDU_TYPE_TCN = 1,
+        BPDU_TYPE_RSTP = 2 };
 
     enum ProtocolVersion { PROTO_VERSION_STP = 0,
         PROTO_VERSION_RSTP = 2,
diff --git a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
index 7469b40ae94..353df788ac6 100644
--- a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
+++ b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
@@ -645,7 +645,7 @@ void Rstp::sendTCNtoRoot()
 
                 frame->setProtocolIdentifier(0);
                 frame->setProtocolVersionIdentifier(PROTO_VERSION_RSTP);
-                frame->setBpduType(BDPU_TYPE_RSTP); // todo: check
+                frame->setBpduType(BPDU_TYPE_RSTP); // todo: check
 
                 BpduFlags bpduFlags;
                 bpduFlags.tcaFlag = false;
@@ -721,7 +721,7 @@ void Rstp::sendBPDU(int interfaceId)
 
         frame->setProtocolIdentifier(0);
         frame->setProtocolVersionIdentifier(PROTO_VERSION_RSTP);
-        frame->setBpduType(BDPU_TYPE_RSTP);
+        frame->setBpduType(BPDU_TYPE_RSTP);
 
         if (r != -1) {
             RootIdentifier rootId;
diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc
index ff4d6d74a80..7bb6921c18e 100644
--- a/src/inet/linklayer/ieee8021d/stp/Stp.cc
+++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc
@@ -84,6 +84,8 @@ void Stp::start()
     WATCH(rootPriority);
     WATCH(rootAddress);
     WATCH(rootPathCost);
+    WATCH(topologyChangeNotification);
+    WATCH(topologyChangeRecvd);
 
     scheduleAt(simTime() + tickInterval, tick);
 }
@@ -156,9 +158,9 @@ void Stp::handleMessageWhenUp(cMessage *msg)
             return;
         }
 
-        if (bpdu->getBpduType() == BDPU_TYPE_CONFIG)
+        if (bpdu->getBpduType() == BPDU_TYPE_CONFIG)
             handleBPDU(packet, bpdu);
-        else if (bpdu->getBpduType() == TBDPU_TYPE_CN)
+        else if (bpdu->getBpduType() == BPDU_TYPE_TCN)
             handleTCN(packet, bpdu);
     }
     else {
@@ -224,13 +226,14 @@ void Stp::checkTimers()
 
         if (port->getAge() >= currentMaxAge) {
             EV_DETAIL << "Port=" << i << " reached its maximum age. Setting it to the default port info." << endl;
+            initInterfacedata(interfaceId);
             if (port->getRole() == Ieee8021dInterfaceData::ROOT) {
-                initInterfacedata(interfaceId);
-                lostRoot();
+                topologyChangeNotification = true;
+                tryRoot();
             }
             else {
-                initInterfacedata(interfaceId);
-                lostAlternate();
+                selectDesignatedPorts();
+                topologyChangeNotification = true;
             }
         }
     }
@@ -298,7 +301,7 @@ void Stp::generateBPDU(int interfaceId, const MacAddress& address, bool tcFlag,
 
     bpdu->setProtocolIdentifier(0);
     bpdu->setProtocolVersionIdentifier(PROTO_VERSION_STP);
-    bpdu->setBpduType(BDPU_TYPE_CONFIG);
+    bpdu->setBpduType(BPDU_TYPE_CONFIG);
 
     if (topologyChangeNotification) {
         if (isRoot || tcFlag) {
@@ -351,7 +354,17 @@ void Stp::checkParametersChange()
 
     if (currentBridgePriority != bridgePriority) {
         currentBridgePriority = bridgePriority;
-        reset();
+
+        // upon booting all switches believe themselves to be the root
+        isRoot = true;
+        rootPriority = bridgePriority;
+        rootAddress = bridgeAddress;
+        rootPathCost = 0;
+        currentHelloTime = helloTime;
+        currentMaxAge = maxAge;
+        currentFwdDelay = forwardDelay;
+
+        setAllDesignated();
     }
 }
 
@@ -360,23 +373,26 @@ void Stp::generateTCN()
     // there is something to notify
     if (topologyChangeNotification || !topologyChangeRecvd) {
         if (getPortInterfaceData(rootInterfaceId)->getRole() == Ieee8021dInterfaceData::ROOT) {
-            // exist root port to notifying
+
+            EV_INFO << "The topology has changed. Sending TCN BPDU to the Root Switch." << endl;
             topologyChangeNotification = false;
+
             Packet *packet = new Packet("BPDU");
-            const auto& tcn = makeShared();
-            tcn->setProtocolIdentifier(0);
-            tcn->setProtocolVersionIdentifier(PROTO_VERSION_STP);
-            tcn->setBpduType(TBDPU_TYPE_CN);
 
             auto macAddressReq = packet->addTag();
             macAddressReq->setSrcAddress(bridgeAddress);
             macAddressReq->setDestAddress(MacAddress::STP_MULTICAST_ADDRESS);
+
             packet->addTag()->setInterfaceId(rootInterfaceId);
             packet->addTag()->setProtocol(&Protocol::stp);
             packet->addTag()->setProtocol(&Protocol::ethernetMac);
 
+            const auto& tcn = makeShared();
+            tcn->setProtocolIdentifier(0);
+            tcn->setProtocolVersionIdentifier(PROTO_VERSION_STP);
+            tcn->setBpduType(BPDU_TYPE_TCN);
+
             packet->insertAtBack(tcn);
-            EV_INFO << "The topology has changed. Sending Topology Change Notification BPDU " << tcn << " to the Root Switch." << endl;
             send(packet, "relayOut");
         }
     }
@@ -717,31 +733,6 @@ void Stp::selectDesignatedPorts()
     delete bridgeGlobal;
 }
 
-void Stp::lostRoot()
-{
-    topologyChangeNotification = true;
-    tryRoot();
-}
-
-void Stp::lostAlternate()
-{
-    selectDesignatedPorts();
-    topologyChangeNotification = true;
-}
-
-void Stp::reset()
-{
-    // upon booting all switches believe themselves to be the root
-    isRoot = true;
-    rootPriority = bridgePriority;
-    rootAddress = bridgeAddress;
-    rootPathCost = 0;
-    currentHelloTime = helloTime;
-    currentMaxAge = maxAge;
-    currentFwdDelay = forwardDelay;
-    setAllDesignated();
-}
-
 void Stp::stop()
 {
     StpBase::stop();
diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.h b/src/inet/linklayer/ieee8021d/stp/Stp.h
index f53cfab36de..e0f6846b430 100644
--- a/src/inet/linklayer/ieee8021d/stp/Stp.h
+++ b/src/inet/linklayer/ieee8021d/stp/Stp.h
@@ -136,13 +136,6 @@ class INET_API Stp : public StpBase
      */
     void setAllDesignated();
 
-    /*
-     * Helper functions to handle state changes
-     */
-    void lostRoot();
-    void lostAlternate();
-    void reset();
-
     /*
      * Determine who is eligible to become the root switch
      */

From eb6fbeea8361db7b3493d4223dcf59b669e82388 Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Fri, 13 Sep 2019 00:16:06 -0700
Subject: [PATCH 24/27] rtp: adding more debug output

---
 src/inet/linklayer/ieee8021d/rstp/Rstp.cc | 12 +++++++-----
 src/inet/linklayer/ieee8021d/stp/Stp.cc   | 20 +++++++++++++-------
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
index 353df788ac6..e1e848a36c5 100644
--- a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
+++ b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
@@ -262,15 +262,17 @@ void Rstp::handleUpgrade(cMessage *msg)
 
 void Rstp::handleIncomingFrame(Packet *packet)
 {
-    const Ptr& frame = packet->peekAtFront();
-    // incoming BPDU handling
-    // checking message age
     int arrivalInterfaceId = packet->getTag()->getInterfaceId();
-    MacAddress src = packet->getTag()->getSrcAddress();
     EV_INFO << "BPDU received at port " << arrivalInterfaceId << "." << endl;
+
+    MacAddress src = packet->getTag()->getSrcAddress();
+    const Ptr& frame = packet->peekAtFront();
+
+    // checking message age
     if (frame->getMessageAge() < maxAge) {
-        // checking TC
+
         checkTC(frame, arrivalInterfaceId);    // sets TCWhile if arrival port was FORWARDING
+
         // checking possible backup
         if (src.compareTo(bridgeAddress) == 0) // more than one port in the same LAN
             handleBackup(frame, arrivalInterfaceId);
diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc
index 7bb6921c18e..5bbfe223c84 100644
--- a/src/inet/linklayer/ieee8021d/stp/Stp.cc
+++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc
@@ -226,12 +226,13 @@ void Stp::checkTimers()
 
         if (port->getAge() >= currentMaxAge) {
             EV_DETAIL << "Port=" << i << " reached its maximum age. Setting it to the default port info." << endl;
-            initInterfacedata(interfaceId);
             if (port->getRole() == Ieee8021dInterfaceData::ROOT) {
+                initInterfacedata(interfaceId);
                 topologyChangeNotification = true;
                 tryRoot();
             }
             else {
+                initInterfacedata(interfaceId);
                 selectDesignatedPorts();
                 topologyChangeNotification = true;
             }
@@ -303,15 +304,18 @@ void Stp::generateBPDU(int interfaceId, const MacAddress& address, bool tcFlag,
     bpdu->setProtocolVersionIdentifier(PROTO_VERSION_STP);
     bpdu->setBpduType(BPDU_TYPE_CONFIG);
 
+    BpduFlags bpduFlags;
     if (topologyChangeNotification) {
         if (isRoot || tcFlag) {
-            BpduFlags bpduFlags;
+            EV_INFO << "Sending CONFIG BPDU with Topology Change (TC) flag to port "
+                    << ifd->getInterfaceEntry()->getFullName() << endl;
             bpduFlags.tcFlag = true;
             bpduFlags.tcaFlag = false;
             bpdu->setBpduFlags(bpduFlags);
         }
         else if (tcaFlag) {
-            BpduFlags bpduFlags;
+            EV_INFO << "Sending CONFIG BPDU with Topology Change ACK (TCA) flag to port "
+                    << ifd->getInterfaceEntry()->getFullName() << endl;
             bpduFlags.tcFlag = false;
             bpduFlags.tcaFlag = true;
             bpdu->setBpduFlags(bpduFlags);
@@ -374,7 +378,7 @@ void Stp::generateTCN()
     if (topologyChangeNotification || !topologyChangeRecvd) {
         if (getPortInterfaceData(rootInterfaceId)->getRole() == Ieee8021dInterfaceData::ROOT) {
 
-            EV_INFO << "The topology has changed. Sending TCN BPDU to the Root Switch." << endl;
+            EV_INFO << "Sending TCN BPDU to the root Switch (the topology has changed)." << endl;
             topologyChangeNotification = false;
 
             Packet *packet = new Packet("BPDU");
@@ -501,7 +505,8 @@ void Stp::handleTCN(Packet *packet, const Ptr& tcn)
     int arrivalGate = packet->getTag()->getInterfaceId();
     Ieee8021dInterfaceData *port = getPortInterfaceData(arrivalGate);
 
-    EV_DETAIL << switchModule->getFullName() << " received a TCN BPDU on port=" << port->getInterfaceEntry()->getFullName() << endl;
+    EV_DETAIL << switchModule->getFullName() << " received a TCN BPDU on port="
+            << port->getInterfaceEntry()->getFullName() << endl;
 
     topologyChangeNotification = true;
 
@@ -509,8 +514,7 @@ void Stp::handleTCN(Packet *packet, const Ptr& tcn)
     MacAddress srcAddress = addressInd->getSrcAddress();
     MacAddress destAddress = addressInd->getDestAddress();
 
-    // send ACK to the sender
-    EV_INFO << "Sending Topology Change Notification ACK." << endl;
+    // send TC/TCA to the sender
     generateBPDU(arrivalGate, srcAddress, false, true);
 
     if (!isRoot) {
@@ -522,6 +526,8 @@ void Stp::handleTCN(Packet *packet, const Ptr& tcn)
         macAddressReq->setDestAddress(destAddress);
         outPacket->addTag()->setProtocol(&Protocol::stp);
         outPacket->addTag()->setProtocol(&Protocol::ethernetMac);
+        EV_DETAIL << switchModule->getFullName() << " forwards the received TCN BPDU on port="
+                << getPortInterfaceData(rootInterfaceId)->getInterfaceEntry()->getFullName() << endl;
         send(outPacket, "relayOut");
     }
 

From 1a399ed88917196a7a2fd8eb80f93d5f2a3f43b8 Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Fri, 13 Sep 2019 02:24:39 -0700
Subject: [PATCH 25/27] stp: source MAC address is now set correctly

---
 src/inet/linklayer/ieee8021d/rstp/Rstp.cc | 20 +++++++++++++++++---
 src/inet/linklayer/ieee8021d/rstp/Rstp.h  |  5 +++++
 src/inet/linklayer/ieee8021d/stp/Stp.cc   |  6 +++---
 3 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
index e1e848a36c5..f4da1e2c92a 100644
--- a/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
+++ b/src/inet/linklayer/ieee8021d/rstp/Rstp.cc
@@ -274,7 +274,7 @@ void Rstp::handleIncomingFrame(Packet *packet)
         checkTC(frame, arrivalInterfaceId);    // sets TCWhile if arrival port was FORWARDING
 
         // checking possible backup
-        if (src.compareTo(bridgeAddress) == 0) // more than one port in the same LAN
+        if (sameSwitch(src)) // more than one port in the same LAN segment
             handleBackup(frame, arrivalInterfaceId);
         else
             processBPDU(frame, arrivalInterfaceId);
@@ -681,7 +681,7 @@ void Rstp::sendTCNtoRoot()
                 packet->insertAtBack(frame);
 
                 auto macAddressReq = packet->addTag();
-                macAddressReq->setSrcAddress(bridgeAddress);
+                macAddressReq->setSrcAddress(rootPort->getInterfaceEntry()->getMacAddress());
                 macAddressReq->setDestAddress(MacAddress::STP_MULTICAST_ADDRESS);
                 packet->addTag()->setInterfaceId(r);
 
@@ -769,7 +769,7 @@ void Rstp::sendBPDU(int interfaceId)
         packet->insertAtBack(frame);
 
         auto macAddressReq = packet->addTag();
-        macAddressReq->setSrcAddress(bridgeAddress);
+        macAddressReq->setSrcAddress(getPortInterfaceData(interfaceId)->getInterfaceEntry()->getMacAddress());
         macAddressReq->setDestAddress(MacAddress::STP_MULTICAST_ADDRESS);
         packet->addTag()->setInterfaceId(interfaceId);
         packet->addTag()->setProtocol(&Protocol::stp);
@@ -913,6 +913,20 @@ void Rstp::flushOtherPorts(unsigned int portId)
     }
 }
 
+bool Rstp::sameSwitch(MacAddress src)
+{
+    for (int i = 0; i < ifTable->getNumInterfaces(); i++) {
+        InterfaceEntry *current = ifTable->getInterface(i);
+        if (!current->isLoopback()) {
+            if(src.compareTo(current->getMacAddress()) == 0) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
 void Rstp::receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj, cObject *details)
 {
     Enter_Method_Silent();
diff --git a/src/inet/linklayer/ieee8021d/rstp/Rstp.h b/src/inet/linklayer/ieee8021d/rstp/Rstp.h
index c70b3277856..08e2295d00b 100644
--- a/src/inet/linklayer/ieee8021d/rstp/Rstp.h
+++ b/src/inet/linklayer/ieee8021d/rstp/Rstp.h
@@ -169,6 +169,11 @@ class INET_API Rstp : public StpBase
      */
     virtual void handleBackup(const Ptr& frame, unsigned int arrivalInterfaceId);
 
+    /**
+     * @brief checks if the src MAC address belongs to this switch
+     */
+    virtual bool sameSwitch(MacAddress src);
+
     /**
      * @brief schedule next upgrade self-message
      */
diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc
index 5bbfe223c84..62fa3848b47 100644
--- a/src/inet/linklayer/ieee8021d/stp/Stp.cc
+++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc
@@ -294,7 +294,7 @@ void Stp::generateBPDU(int interfaceId, const MacAddress& address, bool tcFlag,
     Packet *packet = new Packet("BPDU");
     const auto& bpdu = makeShared();
     auto macAddressReq = packet->addTag();
-    macAddressReq->setSrcAddress(bridgeAddress);
+    macAddressReq->setSrcAddress(ifd->getInterfaceEntry()->getMacAddress());
     macAddressReq->setDestAddress(address);
     packet->addTag()->setInterfaceId(interfaceId);
     packet->addTag()->setProtocol(&Protocol::stp);
@@ -384,7 +384,7 @@ void Stp::generateTCN()
             Packet *packet = new Packet("BPDU");
 
             auto macAddressReq = packet->addTag();
-            macAddressReq->setSrcAddress(bridgeAddress);
+            macAddressReq->setSrcAddress(getPortInterfaceData(rootInterfaceId)->getInterfaceEntry()->getMacAddress());
             macAddressReq->setDestAddress(MacAddress::STP_MULTICAST_ADDRESS);
 
             packet->addTag()->setInterfaceId(rootInterfaceId);
@@ -522,7 +522,7 @@ void Stp::handleTCN(Packet *packet, const Ptr& tcn)
         outPacket->insertAtBack(tcn);
         outPacket->addTag()->setInterfaceId(rootInterfaceId);
         auto macAddressReq = outPacket->addTag();
-        macAddressReq->setSrcAddress(bridgeAddress);
+        macAddressReq->setSrcAddress(getPortInterfaceData(rootInterfaceId)->getInterfaceEntry()->getMacAddress());
         macAddressReq->setDestAddress(destAddress);
         outPacket->addTag()->setProtocol(&Protocol::stp);
         outPacket->addTag()->setProtocol(&Protocol::ethernetMac);

From ee636c79ee4bca24ac80772238b924a5f2d0df91 Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Fri, 13 Sep 2019 17:59:26 -0700
Subject: [PATCH 26/27] rtp: fix tcn bpdu value

---
 src/inet/linklayer/ieee8021d/common/StpBase.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/inet/linklayer/ieee8021d/common/StpBase.h b/src/inet/linklayer/ieee8021d/common/StpBase.h
index 6d81cf7dfcb..94332e6d3d3 100644
--- a/src/inet/linklayer/ieee8021d/common/StpBase.h
+++ b/src/inet/linklayer/ieee8021d/common/StpBase.h
@@ -33,9 +33,9 @@ namespace inet {
 class INET_API StpBase : public OperationalBase, public cListener
 {
 public:
-    enum BdpuType { BPDU_TYPE_CONFIG = 0,
-        BPDU_TYPE_TCN = 1,
-        BPDU_TYPE_RSTP = 2 };
+    enum BdpuType { BPDU_TYPE_CONFIG = 0x00,
+        BPDU_TYPE_TCN = 0x80,
+        BPDU_TYPE_RSTP = 0x02 };
 
     enum ProtocolVersion { PROTO_VERSION_STP = 0,
         PROTO_VERSION_RSTP = 2,

From bd18b911672fe2ce534bc95b8dca6de932fabf56 Mon Sep 17 00:00:00 2001
From: Mani Amoozadeh 
Date: Fri, 13 Sep 2019 21:57:35 -0700
Subject: [PATCH 27/27] stp: adding more debugs

---
 .../configurator/Ieee8021dInterfaceData.h     | 14 +++++++++--
 src/inet/linklayer/ieee8021d/stp/Stp.cc       | 23 ++++++++-----------
 2 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h
index 00e9ea2cc31..9999f3bcdd1 100644
--- a/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h
+++ b/src/inet/linklayer/configurator/Ieee8021dInterfaceData.h
@@ -132,7 +132,12 @@ class INET_API Ieee8021dInterfaceData : public InterfaceProtocolData
 
     PortRole getRole() const { return portData.role; }
 
-    void setRole(PortRole role) { portData.role = role; }
+    void setRole(PortRole role) {
+        EV_DETAIL << getInterfaceEntry()->getFullName()
+                << ": role changed " << getRoleName(portData.role)
+                << " --> " << getRoleName(role) << std::endl;
+        portData.role = role;
+    }
 
     const MacAddress& getRootAddress() const { return portData.rootAddress; }
 
@@ -148,7 +153,12 @@ class INET_API Ieee8021dInterfaceData : public InterfaceProtocolData
 
     PortState getState() const { return portData.state; }
 
-    void setState(PortState state) { portData.state = state; }
+    void setState(PortState state) {
+        EV_DETAIL << getInterfaceEntry()->getFullName()
+                << ": state changed " << getStateName(portData.state)
+                << " --> " << getStateName(state) << std::endl;
+        portData.state = state;
+    }
 
     bool isEdge() const { return portData.edge; }
 
diff --git a/src/inet/linklayer/ieee8021d/stp/Stp.cc b/src/inet/linklayer/ieee8021d/stp/Stp.cc
index 62fa3848b47..d5e6b274c77 100644
--- a/src/inet/linklayer/ieee8021d/stp/Stp.cc
+++ b/src/inet/linklayer/ieee8021d/stp/Stp.cc
@@ -144,7 +144,15 @@ void Stp::setAllDesignated()
 
 void Stp::handleMessageWhenUp(cMessage *msg)
 {
-    if (!msg->isSelfMessage()) {
+    if (msg->isSelfMessage()) {
+        if (msg == tick) {
+            handleTick();
+            scheduleAt(simTime() + 1, tick);
+        }
+        else
+            throw cRuntimeError("Unknown self-message received");
+    }
+    else {
         Packet *packet = check_and_cast(msg);
         const auto& bpdu = packet->peekAtFront();
 
@@ -163,14 +171,6 @@ void Stp::handleMessageWhenUp(cMessage *msg)
         else if (bpdu->getBpduType() == BPDU_TYPE_TCN)
             handleTCN(packet, bpdu);
     }
-    else {
-        if (msg == tick) {
-            handleTick();
-            scheduleAt(simTime() + 1, tick);
-        }
-        else
-            throw cRuntimeError("Unknown self-message received");
-    }
 }
 
 void Stp::handleTick()
@@ -678,10 +678,8 @@ void Stp::selectRootPort()
     }
 
     unsigned int xRootInterfaceId = ifTable->getInterface(xRootIdx)->getInterfaceId();
-    if (rootInterfaceId != xRootInterfaceId) {
-        EV_DETAIL << "Port=" << ifTable->getInterface(xRootIdx)->getFullName() << " selected as root port." << endl;
+    if (rootInterfaceId != xRootInterfaceId)
         topologyChangeNotification = true;
-    }
 
     rootInterfaceId = xRootInterfaceId;
     getPortInterfaceData(rootInterfaceId)->setRole(Ieee8021dInterfaceData::ROOT);
@@ -723,7 +721,6 @@ void Stp::selectDesignatedPorts()
         result = comparePorts(bridgeGlobal, portData);
 
         if (result > 0) {
-            EV_DETAIL << "Port=" << ie->getFullName() << " is elected as designated portData." << endl;
             desPorts.push_back(interfaceId);
             portData->setRole(Ieee8021dInterfaceData::DESIGNATED);
             continue;