Skip to content

Commit

Permalink
Merged 'develop' into 'master'.
Browse files Browse the repository at this point in the history
  • Loading branch information
adigostin committed Jun 23, 2019
2 parents 990c263 + b028c34 commit 065e5c3
Show file tree
Hide file tree
Showing 32 changed files with 921 additions and 435 deletions.
13 changes: 6 additions & 7 deletions _help/STP_CreateBridge.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ <h4>Summary</h4>
<h4>Parameters</h4>
<dl>
<dt>portCount</dt>
<dd>The maximum number of ports this bridge will have. Usually equal to the number of physical ports
present on the device.<br /><br />
<dd>The maximum number of ports this bridge will have. Usually equal to the number
of physical ports present on the device, minus the management port.<br /><br />
See the Remarks section for information about changing the number
of ports at runtime.</dd>
<dt>mstiCount</dt>
<dd>Maximum number of MSTIs for when the device runs MSTP (this is in addition to the CIST, which is always present).
Should be zero if your device supports only STP/RSTP, or 2..64 if your device supports also MSTP
(See Annex A.18, Item MSTP-1 in 802.1Q-2018). Passing an invalid value will cause an assertion failure in the function.
Should be zero if your device supports only STP/RSTP, or 0..64 if your device supports also MSTP.
Passing an invalid value will cause an assertion failure in the function.
</dd>
<dt>maxVlanNumber</dt>
<dd>The maximum VLAN number your device supports, or otherwise zero. The library uses this to determine the size of an&nbsp;
Expand Down Expand Up @@ -84,7 +84,7 @@ <h4>Remarks</h4>
</p>
<p>
Logging of debug text is disabled when this function returns.
The application can explicitly enable it
The application can enable it
with <a href="STP_EnableLogging.html">STP_EnableLogging</a>.</p>
<p>
This function creates a default MST Configuration Identifier as
Expand All @@ -94,8 +94,7 @@ <h4>Remarks</h4>
<li><em>ConfigurationName</em> is generated from the <code>bridgeAddress</code> parameter and has the
format aa:bb:cc:dd:ee:ff. The library will <em>not</em> update this default name if the
application later changes the MAC address of the bridge with <a href="STP_SetBridgeAddress.html">STP_SetBridgeAddress</a>.
If the application needs MSTP functionality, it should change this default name to
something meaningful by calling
The application can later change this name by calling
<a href="STP_SetMstConfigName.html">STP_SetMstConfigName</a>.&nbsp; </li>
<li><em>RevisionLevel</em> is zero.</li>
<li><em>ConfigurationDigest</em> is 0xAC36177F50283CD4B83821D8AB26DE62, which corresponds to
Expand Down
8 changes: 6 additions & 2 deletions edge/edge.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@
<ClInclude Include="win32\pch.h">
<Filter>win32</Filter>
</ClInclude>
<ClInclude Include="win32\xml_serializer.h" />
<ClInclude Include="reflection.h" />
<ClInclude Include="span.hpp" />
<ClInclude Include="win32\xml_serializer.h">
<Filter>win32</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="object.cpp" />
Expand Down Expand Up @@ -76,8 +78,10 @@
<ClCompile Include="win32\pch.cpp">
<Filter>win32</Filter>
</ClCompile>
<ClCompile Include="win32\xml_serializer.cpp" />
<ClCompile Include="reflection.cpp" />
<ClCompile Include="win32\xml_serializer.cpp">
<Filter>win32</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="win32">
Expand Down
2 changes: 2 additions & 0 deletions edge/reflection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,6 @@ namespace edge
to = value;
return true;
}

const char unknown_enum_value_str[] = "(unknown)";
}
10 changes: 6 additions & 4 deletions edge/reflection.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ namespace edge
}
};

template<typename enum_t, const char* type_name_, const NVP* nvps, bool serialize_as_integer = false>
template<typename enum_t, const char* type_name_, const NVP* nvps, bool serialize_as_integer, const char* unknown_str>
struct enum_property_traits
{
static constexpr const char* type_name = type_name_;
Expand All @@ -183,7 +183,7 @@ namespace edge
return nvp->first;
}

return "(unknown)";
return unknown_str;
}

static bool from_string (std::string_view from, enum_t& to, const object* obj)
Expand Down Expand Up @@ -212,8 +212,10 @@ namespace edge
}
};

template<typename enum_t, const char* type_name, const NVP* nvps, bool serialize_as_integer = false>
using enum_property = typed_property<enum_property_traits<enum_t, type_name, nvps, serialize_as_integer>, nvps>;
extern const char unknown_enum_value_str[];

template<typename enum_t, const char* type_name, const NVP* nvps, bool serialize_as_integer = false, const char* unknown_str = unknown_enum_value_str>
using enum_property = typed_property<enum_property_traits<enum_t, type_name, nvps, serialize_as_integer, unknown_str>, nvps>;

// ===========================================

Expand Down
7 changes: 7 additions & 0 deletions edge/win32/xml_serializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ namespace edge

static void deserialize_to_internal (IXMLDOMElement* element, object* obj, bool ignore_index_attribute)
{
auto deserializable = dynamic_cast<deserialize_i*>(obj);
if (deserializable != nullptr)
deserializable->on_deserializing();

com_ptr<IXMLDOMNamedNodeMap> attrs;
auto hr = element->get_attributes (&attrs); assert(SUCCEEDED(hr));
long attr_count;
Expand Down Expand Up @@ -332,6 +336,9 @@ namespace edge

hr = child_node->get_nextSibling(&child_node); assert(SUCCEEDED(hr));
}

if (deserializable != nullptr)
deserializable->on_deserialized();
}

void deserialize_to (IXMLDOMElement* element, object* obj)
Expand Down
6 changes: 6 additions & 0 deletions edge/win32/xml_serializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,10 @@ namespace edge
{
com_ptr<IXMLDOMElement> serialize (IXMLDOMDocument* doc, const object* o, bool force_serialize_unchanged);
void deserialize_to (IXMLDOMElement* element, object* o);

struct deserialize_i
{
virtual void on_deserializing() = 0;
virtual void on_deserialized() = 0;
};
}
76 changes: 64 additions & 12 deletions mstp-lib/internal/stp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ STP_BRIDGE* STP_CreateBridge (unsigned int portCount,
assert (port->trees[treeIndex] != NULL);
port->trees[treeIndex]->portId.Set (0x80, (unsigned short) portIndex + 1);
port->trees[treeIndex]->portTimes = bridge->trees[treeIndex]->BridgeTimes;
port->trees[treeIndex]->InternalPortPathCost = 200000; // TODO: remove this hardcoded value and calculate the actual value in STP_OnPortEnabled
port->trees[treeIndex]->pseudoRootId = bridge->trees[treeIndex]->GetBridgeIdentifier();
}

Expand Down Expand Up @@ -282,12 +281,20 @@ void STP_OnPortEnabled (STP_BRIDGE* bridge, unsigned int portIndex, unsigned int
port->operPointToPointMAC = detectedPointToPointMAC;

port->detectedPortPathCost = GetDefaultPortPathCost(speedMegabitsPerSecond);

if (port->adminExternalPortPathCost != 0)
port->ExternalPortPathCost = port->adminExternalPortPathCost;
else
port->ExternalPortPathCost = port->detectedPortPathCost;

// TODO: calculate also InternalPortPathCost and remove its hardcoded value from STP_CreateBridge
for (unsigned int treeIndex = 0; treeIndex < bridge->treeCount(); treeIndex++)
{
PORT_TREE* portTree = port->trees[treeIndex];
if (portTree->adminInternalPortPathCost != 0)
portTree->InternalPortPathCost = portTree->adminInternalPortPathCost;
else
portTree->InternalPortPathCost = port->detectedPortPathCost;
}

if (bridge->started)
RunStateMachines (bridge, timestamp);
Expand Down Expand Up @@ -1198,18 +1205,46 @@ void STP_SetAdminExternalPortPathCost (struct STP_BRIDGE* bridge, unsigned int p

PORT* port = bridge->ports[portIndex];

port->adminExternalPortPathCost = adminExternalPortPathCost;

if (port->portEnabled)
if (port->adminExternalPortPathCost != adminExternalPortPathCost)
{
unsigned int newCost = (port->adminExternalPortPathCost != 0) ? port->adminExternalPortPathCost : port->detectedPortPathCost;
if (port->ExternalPortPathCost != newCost)
port->adminExternalPortPathCost = adminExternalPortPathCost;

if (port->portEnabled)
{
port->ExternalPortPathCost = newCost;
LOG (bridge, -1, -1, " ExternalPortPathCost is now {D}.\r\n", port->ExternalPortPathCost);
unsigned int newCost = (port->adminExternalPortPathCost != 0) ? port->adminExternalPortPathCost : port->detectedPortPathCost;
if (port->ExternalPortPathCost != newCost)
{
port->ExternalPortPathCost = newCost;
if (bridge->started)
RecomputePrioritiesAndPortRoles (bridge, CIST_INDEX, timestamp);
}
}
}

if (bridge->started)
RecomputePrioritiesAndPortRoles (bridge, CIST_INDEX, timestamp);
LOG (bridge, -1, -1, "------------------------------------\r\n");
FLUSH_LOG (bridge);
}

void STP_SetAdminInternalPortPathCost (struct STP_BRIDGE* bridge, unsigned int portIndex, unsigned int treeIndex, unsigned int adminInternalPortPathCost, unsigned int timestamp)
{
LOG (bridge, -1, -1, "{T}: Setting Port {D} {TN} AdminInternalPortPathCost to {D}...\r\n", timestamp, 1 + portIndex, treeIndex, adminInternalPortPathCost);

PORT* port = bridge->ports[portIndex];
PORT_TREE* portTree = port->trees[treeIndex];

if (portTree->adminInternalPortPathCost != adminInternalPortPathCost)
{
portTree->adminInternalPortPathCost = adminInternalPortPathCost;

if (port->portEnabled)
{
unsigned int newCost = (portTree->adminInternalPortPathCost != 0) ? portTree->adminInternalPortPathCost : port->detectedPortPathCost;
if (portTree->InternalPortPathCost != newCost)
{
portTree->InternalPortPathCost = newCost;
if (bridge->started)
RecomputePrioritiesAndPortRoles (bridge, treeIndex, timestamp);
}
}
}

Expand All @@ -1230,7 +1265,24 @@ unsigned int STP_GetDetectedPortPathCost (const struct STP_BRIDGE* bridge, unsig
unsigned int STP_GetExternalPortPathCost (const struct STP_BRIDGE* bridge, unsigned int portIndex)
{
const PORT* port = bridge->ports[portIndex];
return port->portEnabled ? port->ExternalPortPathCost : 0;
if (!port->portEnabled)
return 0;

return port->ExternalPortPathCost;
}

unsigned int STP_GetInternalPortPathCost (const struct STP_BRIDGE* bridge, unsigned int portIndex, unsigned treeIndex)
{
const PORT* port = bridge->ports[portIndex];
if (!port->portEnabled)
return 0;

return port->trees[treeIndex]->InternalPortPathCost;
}

unsigned int STP_GetAdminInternalPortPathCost (const struct STP_BRIDGE* bridge, unsigned int portIndex, unsigned int treeIndex)
{
return bridge->ports[portIndex]->trees[treeIndex]->adminInternalPortPathCost;
}

// ============================================================================
Expand Down
5 changes: 4 additions & 1 deletion mstp-lib/internal/stp_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ struct PORT_TREE
unsigned short rcvdInfoWhile; // i) - 13.25.6
unsigned short tcDetected; // j) - 13.25.8

// Not in the standard. Used by STP_Get/SetAdminInternalPortPathCost.
unsigned int adminInternalPortPathCost;

PortInformation::State portInformationState;
PortRoleTransitions::State portRoleTransitionsState;
PortStateTransition::State portStateTransitionState;
Expand Down Expand Up @@ -173,7 +176,7 @@ struct PORT
// See also detectedPointToPointMAC.
unsigned int detectedPortPathCost;

// Not in the standard. Stores ieee8021SpanningTreeRstpPortAdminPathCost / ieee8021MstpCistPortAdminPathCost
// Not in the standard. Used by STP_Get/SetAdminExternalPortPathCost.
unsigned int adminExternalPortPathCost;

PortTimers::State portTimersState;
Expand Down
5 changes: 2 additions & 3 deletions mstp-lib/internal/stp_procedures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1119,7 +1119,7 @@ void updtRcvdInfoWhile (STP_BRIDGE* bridge, PortIndex givenPort, TreeIndex given

// ============================================================================

static void CalculateRootPathPriorityForPort (STP_BRIDGE* bridge, unsigned int givenPort, TreeIndex givenTree, PRIORITY_VECTOR* rootPathPriorityOut)
static void CalculateRootPathPriorityForPort (const STP_BRIDGE* bridge, unsigned int givenPort, TreeIndex givenTree, PRIORITY_VECTOR* rootPathPriorityOut)
{
PORT* port = bridge->ports [givenPort];
PORT_TREE* portTree = port->trees [givenTree];
Expand All @@ -1134,7 +1134,7 @@ static void CalculateRootPathPriorityForPort (STP_BRIDGE* bridge, unsigned int g

// Note AG: The standard references 13.29.8 (fromSameRegion), but that function tries to read the received BPDU
// outside of STP_OnBpduReceived. I replaced fromSameRegion with rcvdInternal in the "if" below.
if (port->rcvdInternal == false)
if (!port->rcvdInternal)
{
// If the port priority vector was received from a Bridge in a different region (13.29.8), the External Port Path
// Cost EPCPB is added to the External Root Path Cost component, and the Regional Root Identifier is set to
Expand All @@ -1160,7 +1160,6 @@ static void CalculateRootPathPriorityForPort (STP_BRIDGE* bridge, unsigned int g
// vector from a bridge in the same region by adding the Internal Port Path Cost IPCPB to the Internal Root
// Path Cost component.
// root path priority vector = {RRD : IRCD + IPCPB : D : PD : PB)
assert (port->rcvdInternal);
rootPathPriorityOut->InternalRootPathCost += portTree->InternalPortPathCost;
}
}
Expand Down
26 changes: 15 additions & 11 deletions mstp-lib/stp.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,24 +171,28 @@ bool STP_GetOperPointToPointMAC (const struct STP_BRIDGE* bridge, unsigned int p

// ----------------------------------------------------------------------------

// dot1dStpPortAdminPathCost / ieee8021SpanningTreeRstpPortAdminPathCost / ieee8021MstpCistPortAdminPathCost (ExternalPortPathCost)
void STP_SetAdminExternalPortPathCost (struct STP_BRIDGE* bridge, unsigned int portIndex, unsigned int adminPortPathCost, unsigned int debugTimestamp);
unsigned int STP_GetAdminExternalPortPathCost (const struct STP_BRIDGE* bridge, unsigned int portIndex);

// ieee8021MstpPortAdminPathCost (13.27.33 in 802.1Q-2018)
//void STP_SetAdminInternalPortPathCost (struct STP_BRIDGE* bridge, unsigned int portIndex, unsigned int treeIndex, unsigned int adminPortPathCost, unsigned int debugTimestamp);

// Returns the port path cost calculated from the link speed passed to STP_OnPortEnabled,
// which the library uses for path cost calculations while the admin cost is not set or
// after it is reset back to zero. Useful for troubleshooting.
unsigned int STP_GetDetectedPortPathCost (const struct STP_BRIDGE* bridge, unsigned int portIndex);

// dot1dStpPortPathCost / ieee8021SpanningTreePortPathCost / ieee8021MstpCistPortCistPathCost (ExternalPortPathCost)
// Returns the port path cost currently used for calculations (AdminExternalPortPathCost if non-zero, otherwise DetectedPortPathCost).
unsigned int STP_GetExternalPortPathCost (const struct STP_BRIDGE* bridge, unsigned int portIndex);

// dot1dStpPortAdminPathCost / ieee8021SpanningTreeRstpPortAdminPathCost / ieee8021MstpCistPortAdminPathCost
void STP_SetAdminExternalPortPathCost (struct STP_BRIDGE* bridge, unsigned int portIndex, unsigned int adminPortPathCost, unsigned int debugTimestamp);
unsigned int STP_GetAdminExternalPortPathCost (const struct STP_BRIDGE* bridge, unsigned int portIndex);

// ieee8021MstpPortPathCost (13.27.33 in 802.1Q-2018)
//unsigned int STP_GetInternalPortPathCost (const struct STP_BRIDGE* bridge, unsigned int portIndex, unsigned treeIndex);
// Returns the port path cost currently used for calculations (AdminInternalPortPathCost if non-zero, otherwise DetectedPortPathCost).
unsigned int STP_GetInternalPortPathCost (const struct STP_BRIDGE* bridge, unsigned int portIndex, unsigned treeIndex);

// ieee8021MstpPortAdminPathCost (13.27.33 in 802.1Q-2018)
void STP_SetAdminInternalPortPathCost (struct STP_BRIDGE* bridge, unsigned int portIndex, unsigned int treeIndex, unsigned int adminInternalPortPathCost, unsigned int debugTimestamp);
unsigned int STP_GetAdminInternalPortPathCost (const struct STP_BRIDGE* bridge, unsigned int portIndex, unsigned int treeIndex);

// for treeIndex = 0: ieee8021MstpCistPathCost - path cost to CIST Regional Root (13.9 d) CIST Internal Root Path Cost)
// for treeIndex > 0: ieee8021MstpRootPathCost - path cost to Root Bridge for the MSTI (13.27.20 designatedPriority)
//unsigned int STP_GetPathCostToRootBridge (const struct STP_BRIDGE* bridge, unsigned int portIndex, unsigned int treeIndex);
// TODO: ieee8021MstpCistPathCost, ieee8021MstpRootPathCost (path costs to the root bridge)

// ----------------------------------------------------------------------------

Expand Down
Loading

0 comments on commit 065e5c3

Please sign in to comment.