Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements to STP/RSTP #459

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
58156b2
stp: reordering code to better reflect the execution flow
ManiAm Sep 8, 2019
6e4ff28
mac: watch the address table
ManiAm Sep 8, 2019
def034c
mac: adding base MAC address to each switch
ManiAm Sep 8, 2019
7fa2cf2
stp: using the base mac address
ManiAm Sep 8, 2019
ad3cd33
stp; use enum for bpdu type
ManiAm Sep 8, 2019
693c5e9
stp: fix the field names in the bpdu
ManiAm Sep 9, 2019
b576002
stp: adding protocol serializer
ManiAm Sep 9, 2019
299a616
stp: adding important variables into WATCH
ManiAm Sep 9, 2019
ba00ebb
stp: using enum instead
ManiAm Sep 9, 2019
367a628
stp: adding more debug
ManiAm Sep 10, 2019
aebff32
stp: adding a new disabledInterfaces parameter to stp
ManiAm Sep 10, 2019
ae5fe33
stp: L2NetworkConfigurator is now working properly
ManiAm Sep 11, 2019
8ce04f8
stp: set port cost to recommended value from IEEE when not explicitly…
ManiAm Sep 11, 2019
960ce21
stp: set bridge mac address correctly
ManiAm Sep 11, 2019
4a88844
stp: move color values to ned param
ManiAm Sep 11, 2019
7bcecdc
rstp: adding link colors to ned
ManiAm Sep 12, 2019
5b85c2e
rstp: reordering code to better reflect the execution flow
ManiAm Sep 12, 2019
7d231ce
stp,rstp: fix protocol version and type in BPDUs
ManiAm Sep 12, 2019
2b1b5c6
stp: use better types
ManiAm Sep 12, 2019
361c267
stp: print isEdge information of an interface
ManiAm Sep 12, 2019
9b9ab6a
stp: refactoring
ManiAm Sep 12, 2019
4ba018e
stp: stp does not have any DISCARDING states
ManiAm Sep 12, 2019
97da4e0
stp: cosmetics
ManiAm Sep 12, 2019
eb6fbee
rtp: adding more debug output
ManiAm Sep 13, 2019
1a399ed
stp: source MAC address is now set correctly
ManiAm Sep 13, 2019
ee636c7
rtp: fix tcn bpdu value
ManiAm Sep 14, 2019
bd18b91
stp: adding more debugs
ManiAm Sep 14, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 31 additions & 29 deletions src/inet/linklayer/configurator/Ieee8021dInterfaceData.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ namespace inet {

Ieee8021dInterfaceData::PortInfo::PortInfo()
{
priority = 0;
linkCost = 1;
edge = false;

Expand All @@ -47,61 +46,64 @@ 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();
out << " isEdge:" << isEdge();

return out.str();
}

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";
case DISCARDING:
return "DISCARDING";

default:
throw cRuntimeError("Unknown port state %d", state);
default:
throw cRuntimeError("Unknown port state %d", state);
}
}

Expand Down
23 changes: 14 additions & 9 deletions src/inet/linklayer/configurator/Ieee8021dInterfaceData.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,16 @@ 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 };
enum PortState { BLOCKING /*stp only*/, LEARNING, FORWARDING, DISCARDING /*rstp only*/ };

class PortInfo
{
public:
/* The following values have same meaning in both STP and RSTP.
* See Ieee8021dBDPU for more info.
*/
unsigned int priority;
unsigned int linkCost;
bool edge;

Expand Down Expand Up @@ -131,13 +130,14 @@ 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; }
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; }

Expand All @@ -153,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; }

Expand Down
120 changes: 83 additions & 37 deletions src/inet/linklayer/configurator/L2NetworkConfigurator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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<InterfaceEntry *> matchedBefore;
Expand All @@ -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

Expand Down Expand Up @@ -183,14 +207,25 @@ 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.priority = atoi(priority);
currentNode->interfaceInfos[i]->portData.portPriority = atoi(priority);
else {
currentNode->interfaceInfos[i]->portData.portPriority = 128;
}

//edge
// 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;

matchedBefore.insert(ifEntry);
Expand All @@ -210,32 +245,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)
{
Expand All @@ -258,6 +267,11 @@ bool L2NetworkConfigurator::linkContainsMatchingHostExcept(InterfaceInfo *curren
return false;
}

void L2NetworkConfigurator::addToConfigureInterface(InterfaceEntry *interfaceEntry)
{
interfaces.push_back(interfaceEntry);
}

void L2NetworkConfigurator::configureInterface(InterfaceEntry *interfaceEntry)
{
ensureConfigurationComputed(topology);
Expand All @@ -281,10 +295,36 @@ void L2NetworkConfigurator::configureInterface(InterfaceInfo *interfaceInfo)
Ieee8021dInterfaceData *interfaceData = interfaceEntry->getProtocolData<Ieee8021dInterfaceData>();

interfaceData->setLinkCost(interfaceInfo->portData.linkCost);
interfaceData->setPriority(interfaceInfo->portData.priority);
interfaceData->setPortPriority(interfaceInfo->portData.portPriority);
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)
Expand Down Expand Up @@ -313,9 +353,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

5 changes: 4 additions & 1 deletion src/inet/linklayer/configurator/L2NetworkConfigurator.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class INET_API L2NetworkConfigurator : public cSimpleModule
cXMLElement *configuration = nullptr;
L2Topology topology;
Node *rootNode = nullptr;
std::vector<InterfaceEntry *> interfaces;

protected:
virtual void initialize(int stage) override;
Expand All @@ -131,7 +132,9 @@ 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);
unsigned int getRecommendedPortCost(Node *node, InterfaceEntry *ie);

public:
/**
Expand All @@ -142,7 +145,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
Expand Down
4 changes: 2 additions & 2 deletions src/inet/linklayer/configurator/L2NetworkConfigurator.ned
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ package inet.linklayer.configurator;
// priority 32768:
// <pre>
// <config>
// <interface hosts='**' ports='5' cost='19' priority='32768'/>
// <interface hosts='**' ports='5' portCost='19' portPriority='32768'/>
// </config>
// <pre>
//
Expand All @@ -39,6 +39,6 @@ simple L2NetworkConfigurator
{
parameters:
@display("i=block/cogwheel");
xml config = default(xml("<config><interface hosts='**' ports='**' cost='19' priority='128' edge='false'/></config>"));
xml config = default(xml("<config> <interface hosts='**'/> </config>"));
}

Loading