diff --git a/client/main.cpp b/client/main.cpp
index 65864f0..94d3baf 100644
--- a/client/main.cpp
+++ b/client/main.cpp
@@ -38,11 +38,23 @@ extern ProtocolWidgetFactory *OstProtocolWidgetFactory;
QSettings *appSettings;
QMainWindow *mainWindow;
+#if defined(Q_OS_WIN32)
+QString kGzipPathDefaultValue;
+QString kDiffPathDefaultValue;
+QString kAwkPathDefaultValue;
+#endif
+
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
int exitCode;
+#if defined(Q_OS_WIN32)
+ kGzipPathDefaultValue = app.applicationDirPath() + "/gzip.exe";
+ kDiffPathDefaultValue = app.applicationDirPath() + "/diff.exe";
+ kAwkPathDefaultValue = app.applicationDirPath() + "/gawk.exe";
+#endif
+
app.setApplicationName("Ostinato");
app.setOrganizationName("Ostinato");
app.setProperty("version", version);
diff --git a/common/ostproto.pro b/common/ostproto.pro
index e4467dc..8d14c1a 100644
--- a/common/ostproto.pro
+++ b/common/ostproto.pro
@@ -18,6 +18,7 @@ PROTOS = \
vlan.proto \
svlan.proto \
vlanstack.proto \
+ stp.proto \
arp.proto \
ip4.proto \
ip6.proto \
@@ -90,6 +91,7 @@ SOURCES += \
dot3.cpp \
llc.cpp \
snap.cpp \
+ stp.cpp \
arp.cpp \
ip4.cpp \
ip6.cpp \
diff --git a/common/ostprotogui.pro b/common/ostprotogui.pro
index dcbec0c..a91beea 100644
--- a/common/ostprotogui.pro
+++ b/common/ostprotogui.pro
@@ -15,6 +15,7 @@ FORMS += \
dot3.ui \
llc.ui \
snap.ui \
+ stp.ui \
arp.ui \
ip4.ui \
ip6.ui \
@@ -59,6 +60,7 @@ HEADERS += \
dot2llcconfig.h \
snapconfig.h \
dot2snapconfig.h \
+ stpconfig.h \
arpconfig.h \
ip4config.h \
ip6config.h \
@@ -94,6 +96,7 @@ SOURCES += \
dot3config.cpp \
llcconfig.cpp \
snapconfig.cpp \
+ stpconfig.cpp \
arpconfig.cpp \
ip4config.cpp \
ip6config.cpp \
@@ -112,6 +115,7 @@ SOURCES += \
SOURCES += \
vlanpdml.cpp \
svlanpdml.cpp \
+ stppdml.cpp \
eth2pdml.cpp \
llcpdml.cpp \
arppdml.cpp \
diff --git a/common/pdmlreader.cpp b/common/pdmlreader.cpp
index 7b5eb9d..8906520 100644
--- a/common/pdmlreader.cpp
+++ b/common/pdmlreader.cpp
@@ -35,6 +35,7 @@ along with this program. If not, see
#include "ip4pdml.h"
#include "ip6pdml.h"
#include "mldpdml.h"
+#include "stppdml.h"
#include "svlanpdml.h"
#include "tcppdml.h"
#include "textprotopdml.h"
@@ -77,6 +78,7 @@ PdmlReader::PdmlReader(OstProto::StreamConfigList *streams)
factory_.insert("udp", PdmlUdpProtocol::createInstance);
factory_.insert("udplite", PdmlUdpProtocol::createInstance);
factory_.insert("vlan", PdmlVlanProtocol::createInstance);
+ factory_.insert("stp", PdmlStpProtocol::createInstance);
}
PdmlReader::~PdmlReader()
diff --git a/common/protocol.proto b/common/protocol.proto
index deccf07..19d27b1 100644
--- a/common/protocol.proto
+++ b/common/protocol.proto
@@ -140,6 +140,7 @@ message Protocol {
kDot2LlcFieldNumber = 206;
kDot2SnapFieldNumber = 207;
kVlanStackFieldNumber = 208;
+ kStpFieldNumber = 210;
kArpFieldNumber = 300;
kIp4FieldNumber = 301;
diff --git a/common/protocolmanager.cpp b/common/protocolmanager.cpp
index 84e1e2d..9908d0c 100644
--- a/common/protocolmanager.cpp
+++ b/common/protocolmanager.cpp
@@ -34,6 +34,7 @@ along with this program. If not, see
#include "snap.h"
#include "dot2snap.h"
#include "eth2.h"
+#include "stp.h"
// L3 Protos
#include "arp.h"
@@ -89,6 +90,8 @@ ProtocolManager::ProtocolManager()
(void*) SnapProtocol::createInstance);
registerProtocol(OstProto::Protocol::kDot2SnapFieldNumber,
(void*) Dot2SnapProtocol::createInstance);
+ registerProtocol(OstProto::Protocol::kStpFieldNumber,
+ (void*) StpProtocol::createInstance);
// Layer 3 Protocols
registerProtocol(OstProto::Protocol::kArpFieldNumber,
diff --git a/common/protocolwidgetfactory.cpp b/common/protocolwidgetfactory.cpp
index 8c8e30a..cc78bbf 100644
--- a/common/protocolwidgetfactory.cpp
+++ b/common/protocolwidgetfactory.cpp
@@ -30,6 +30,7 @@ along with this program. If not, see
#include "dot2llcconfig.h"
#include "snapconfig.h"
#include "dot2snapconfig.h"
+#include "stpconfig.h"
// L3 Protocol Widgets
#include "arpconfig.h"
#include "ip4config.h"
@@ -93,7 +94,10 @@ ProtocolWidgetFactory::ProtocolWidgetFactory()
OstProtocolWidgetFactory->registerProtocolConfigWidget(
OstProto::Protocol::kDot2SnapFieldNumber,
(void*) Dot2SnapConfigForm::createInstance);
-
+ OstProtocolWidgetFactory->registerProtocolConfigWidget(
+ OstProto::Protocol::kStpFieldNumber,
+ (void*) StpConfigForm::createInstance);
+
// Layer 3 Protocols
OstProtocolWidgetFactory->registerProtocolConfigWidget(
OstProto::Protocol::kArpFieldNumber,
diff --git a/common/stp.cpp b/common/stp.cpp
new file mode 100644
index 0000000..69b7ff3
--- /dev/null
+++ b/common/stp.cpp
@@ -0,0 +1,548 @@
+/*
+Copyright (C) 2014 PLVision.
+
+This file is part of "Ostinato"
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+
+This module is developed by PLVision
+*/
+
+#include "stp.h"
+#include
+
+#define uintToMacStr(num) \
+ QString("%1").arg(num, 6 * 2, BASE_HEX, QChar('0')) \
+ .replace(QRegExp("([0-9a-fA-F]{2}\\B)"), "\\1:").toUpper()
+#define ONE_BIT(pos) ((unsigned int)(1 << (pos)))
+#define BITS(bit) (bit)
+#define BYTES(byte) (byte)
+#define BYTES_TO_BITS(byte) (byte * 8)
+
+#define STP_LLC 0x424203
+
+StpProtocol::StpProtocol(StreamBase *stream, AbstractProtocol *parent)
+ : AbstractProtocol(stream, parent)
+{
+}
+
+StpProtocol::~StpProtocol()
+{
+}
+
+AbstractProtocol* StpProtocol::createInstance(StreamBase *stream,
+ AbstractProtocol *parent)
+{
+ return new StpProtocol(stream, parent);
+}
+
+quint32 StpProtocol::protocolNumber() const
+{
+ return OstProto::Protocol::kStpFieldNumber;
+}
+
+void StpProtocol::protoDataCopyInto(OstProto::Protocol &protocol) const
+{
+ protocol.MutableExtension(OstProto::stp)->CopyFrom(data_);
+ protocol.mutable_protocol_id()->set_id(protocolNumber());
+}
+
+void StpProtocol::protoDataCopyFrom(const OstProto::Protocol &protocol)
+{
+ if (protocol.protocol_id().id() == protocolNumber() &&
+ protocol.HasExtension(OstProto::stp))
+ data_.MergeFrom(protocol.GetExtension(OstProto::stp));
+}
+
+QString StpProtocol::name() const
+{
+ return QString("Spanning Tree Protocol");
+}
+
+QString StpProtocol::shortName() const
+{
+ return QString("STP");
+}
+
+AbstractProtocol::ProtocolIdType StpProtocol::protocolIdType() const
+{
+ return ProtocolIdLlc;
+}
+
+quint32 StpProtocol::protocolId(ProtocolIdType type) const
+{
+ switch(type)
+ {
+ case ProtocolIdLlc:
+ return STP_LLC;
+ default:
+ break;
+ }
+
+ return AbstractProtocol::protocolId(type);
+}
+
+int StpProtocol::fieldCount() const
+{
+ return stp_fieldCount;
+}
+
+AbstractProtocol::FieldFlags StpProtocol::fieldFlags(int index) const
+{
+ AbstractProtocol::FieldFlags flags;
+
+ flags = AbstractProtocol::fieldFlags(index);
+
+ switch (index)
+ {
+ case stp_protocol_id:
+ case stp_version_id:
+ case stp_bpdu_type:
+ case stp_flags:
+ case stp_root_id:
+ case stp_root_path_cost:
+ case stp_bridge_id:
+ case stp_port_id:
+ case stp_message_age:
+ case stp_max_age:
+ case stp_hello_time:
+ case stp_forward_delay:
+ break;
+ default:
+ qFatal("%s: unimplemented case %d in switch", __PRETTY_FUNCTION__,
+ index);
+ break;
+ }
+ return flags;
+}
+
+QVariant StpProtocol::fieldData(int index, FieldAttrib attrib,
+ int streamIndex) const
+{
+ QString str[] = {"Topology Change", "Topology Change Acknowledgment"};
+
+ switch (index)
+ {
+ case stp_protocol_id:
+ {
+ switch (attrib)
+ {
+ case FieldName:
+ return QString("Protocol Identifier");
+ case FieldValue:
+ return data_.protocol_id();
+ case FieldTextValue:
+ return QString("0x%1").arg(data_.protocol_id(),
+ 4, BASE_HEX, QChar('0'));
+ case FieldFrameValue:
+ {
+ QByteArray fv;
+ fv.resize(BYTES(2));
+ qToBigEndian((quint16)data_.protocol_id(),
+ (uchar*)fv.data());
+ return fv;
+ }
+ case FieldBitSize:
+ return BYTES_TO_BITS(2);
+ default:
+ break;
+ }
+ break;
+ }
+ case stp_version_id:
+ {
+ switch (attrib)
+ {
+ case FieldName:
+ return QString("Version Identifier");
+ case FieldValue:
+ return data_.protocol_version_id();
+ case FieldTextValue:
+ return QString("%1").arg(
+ data_.protocol_version_id());
+ case FieldFrameValue:
+ return QByteArray(1,
+ (char)data_.protocol_version_id());
+ case FieldBitSize:
+ return BYTES_TO_BITS(1);
+ default:
+ break;
+ }
+ break;
+ }
+ case stp_bpdu_type:
+ {
+ switch (attrib)
+ {
+ case FieldName:
+ return QString("BPDU Type");
+ case FieldValue:
+ return data_.bpdu_type();
+ case FieldTextValue:
+ return QString("0x%1").arg(data_.bpdu_type(),
+ 2, BASE_HEX, QChar('0'));
+ case FieldFrameValue:
+ return QByteArray(1, (char)data_.bpdu_type());
+ case FieldBitSize:
+ return BYTES_TO_BITS(1);
+ default:
+ break;
+ }
+ break;
+ }
+ case stp_flags:
+ {
+ switch (attrib)
+ {
+ case FieldName:
+ return QString("BPDU Flags");
+ case FieldValue:
+ return data_.flags();
+ case FieldTextValue:
+ {
+ QString strTemp = "(";
+ if((data_.flags() & ONE_BIT(0))) strTemp += str[0] + ", ";
+ if((data_.flags() & ONE_BIT(7))) strTemp += str[1] + ", ";
+ strTemp += ")";
+ strTemp.replace(", )", ")");
+ return strTemp;
+ }
+ case FieldFrameValue:
+ return QByteArray(1, (char)data_.flags());
+ case FieldBitSize:
+ return BYTES_TO_BITS(1);
+ default:
+ break;
+ }
+ break;
+ }
+ case stp_root_id:
+ {
+ switch (attrib)
+ {
+ case FieldName:
+ return QString("Root Identifier");
+ case FieldValue:
+ return (qulonglong) data_.root_id();
+ case FieldTextValue:
+ {
+ // Root ID contain two value:
+ // Root ID Priority(first 2 bytes)
+ // and Root ID MAC (last 6 bytes). (IEEE802.1D-2008)
+ quint16 priority = (
+ data_.root_id() & 0xFFFF000000000000) >> (BYTES_TO_BITS(6));
+ quint64 mac = data_.root_id() & 0x0000FFFFFFFFFFFF;
+ return QString("Priority: %1 / MAC: %2")
+ .arg(QString::number(priority),
+ uintToMacStr(mac));
+ }
+ case FieldFrameValue:
+ {
+ QByteArray fv;
+ fv.resize(BYTES(8));
+ qToBigEndian((quint64)data_.root_id(), (uchar*)fv.data());
+ return fv;
+ }
+ case FieldBitSize:
+ return BYTES_TO_BITS(8);
+ default:
+ break;
+ }
+ break;
+ }
+ case stp_root_path_cost:
+ {
+ switch (attrib)
+ {
+ case FieldName:
+ return QString("Root Path Cost");
+ case FieldValue:
+ return data_.root_path_cost();
+ case FieldTextValue:
+ return QString("%1").arg(data_.root_path_cost());
+ case FieldFrameValue:
+ {
+ QByteArray fv;
+ fv.resize(BYTES(4));
+ qToBigEndian(data_.root_path_cost(), (uchar*)fv.data());
+ return fv;
+ }
+ case FieldBitSize:
+ return BYTES_TO_BITS(4);
+ default:
+ break;
+ }
+ break;
+ }
+ case stp_bridge_id:
+ {
+ switch (attrib)
+ {
+ case FieldName:
+ return QString("Bridge Identifier");
+ case FieldValue:
+ return (qulonglong) data_.bridge_id();
+ case FieldTextValue:
+ {
+ // Bridge ID contain two value:
+ // Bridge ID Priority(first 2 bytes)
+ // and Bridge ID MAC (last 6 bytes). (IEEE802.1D-2008)
+ quint16 priority = (data_.bridge_id() & 0xFFFF000000000000
+ ) >> (BYTES_TO_BITS(6));
+ quint64 mac = data_.bridge_id() & 0x0000FFFFFFFFFFFF;
+ return QString("Priority: %1 / MAC: %2").arg(QString::number(priority),
+ uintToMacStr(mac));
+ }
+ case FieldFrameValue:
+ {
+ QByteArray fv;
+ fv.resize(BYTES(8));
+ qToBigEndian((quint64)data_.bridge_id(), (uchar*)fv.data());
+ return fv;
+ }
+ case FieldBitSize:
+ return BYTES_TO_BITS(8);
+ default:
+ break;
+ }
+ break;
+ }
+ case stp_port_id:
+ {
+ switch (attrib)
+ {
+ case FieldName:
+ return QString("Port Identifier");
+ case FieldValue:
+ return data_.port_id();
+ case FieldTextValue:
+ return QString("0x%1").arg(data_.port_id(), 4,
+ BASE_HEX, QChar('0'));
+ case FieldFrameValue:
+ {
+ QByteArray fv;
+ fv.resize(BYTES(2));
+ qToBigEndian((quint16)data_.port_id(), (uchar*)fv.data());
+ return fv;
+ }
+ case FieldBitSize:
+ return BYTES_TO_BITS(2);
+ default:
+ break;
+ }
+ break;
+ }
+ case stp_message_age:
+ {
+ switch (attrib)
+ {
+ case FieldName:
+ return QString("Message Age");
+ case FieldValue:
+ return data_.message_age();
+ case FieldTextValue:
+ return QString("%1").arg(data_.message_age());
+ case FieldFrameValue:
+ {
+ QByteArray fv;
+ fv.resize(BYTES(2));
+ qToBigEndian((quint16)(data_.message_age()),
+ (uchar*)fv.data());
+ return fv;
+ }
+ case FieldBitSize:
+ return BYTES_TO_BITS(2);
+ default:
+ break;
+ }
+ break;
+ }
+ case stp_max_age:
+ {
+ switch (attrib)
+ {
+ case FieldName:
+ return QString("Max Age");
+ case FieldValue:
+ return data_.max_age();
+ case FieldTextValue:
+ return QString("%1").arg(data_.max_age());
+ case FieldFrameValue:
+ {
+ QByteArray fv;
+ fv.resize(BYTES(2));
+ qToBigEndian((quint16)data_.max_age(), (uchar*)fv.data());
+ return fv;
+ }
+ case FieldBitSize:
+ return BYTES_TO_BITS(2);
+ default:
+ break;
+ }
+ break;
+ }
+ case stp_hello_time:
+ {
+ switch (attrib)
+ {
+ case FieldName:
+ return QString("Hello Time");
+ case FieldValue:
+ return data_.hello_time();
+ case FieldTextValue:
+ return QString("%1").arg(data_.hello_time());
+ case FieldFrameValue:
+ {
+ QByteArray fv;
+ fv.resize(BYTES(2));
+ qToBigEndian((quint16)data_.hello_time(), (uchar*)fv.data());
+ return fv;
+ }
+ case FieldBitSize:
+ return BYTES_TO_BITS(2);
+ default:
+ break;
+ }
+ break;
+ }
+ case stp_forward_delay:
+ {
+ switch (attrib)
+ {
+ case FieldName:
+ return QString("Forward Delay");
+ case FieldValue:
+ return data_.forward_delay();
+ case FieldTextValue:
+ return QString("%1").arg(data_.forward_delay());
+ case FieldFrameValue:
+ {
+ QByteArray fv;
+ fv.resize(BYTES(2));
+ qToBigEndian((quint16)data_.forward_delay(),
+ (uchar*)fv.data());
+ return fv;
+ }
+ case FieldBitSize:
+ return BYTES_TO_BITS(2);
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return AbstractProtocol::fieldData(index, attrib, streamIndex);
+}
+
+bool StpProtocol::setFieldData(int index, const QVariant &value,
+ FieldAttrib attrib)
+{
+ bool isOk = false;
+
+ if (attrib != FieldValue)
+ return isOk;
+
+ switch (index)
+ {
+ case stp_protocol_id:
+ {
+ quint16 protoId = value.toUInt(&isOk);
+ if (isOk)
+ data_.set_protocol_id(protoId);
+ break;
+ }
+ case stp_version_id:
+ {
+ quint8 versionId = value.toUInt(&isOk);
+ if (isOk)
+ data_.set_protocol_version_id(versionId);
+ break;
+ }
+ case stp_bpdu_type:
+ {
+ quint8 bpdu = value.toUInt(&isOk);
+ if (isOk)
+ data_.set_bpdu_type(bpdu);
+ break;
+ }
+ case stp_flags:
+ {
+ quint8 flags = value.toUInt(&isOk);
+ if (isOk)
+ data_.set_flags(flags);
+ break;
+ }
+ case stp_root_id:
+ {
+ quint64 rootId = value.toULongLong(&isOk);
+ if (isOk)
+ data_.set_root_id(rootId);
+ break;
+ }
+ case stp_root_path_cost:
+ {
+ quint32 pathCost = value.toUInt(&isOk);
+ if (isOk)
+ data_.set_root_path_cost(pathCost);
+ break;
+ }
+ case stp_bridge_id:
+ {
+ quint64 bridgeId = value.toULongLong(&isOk);
+ if (isOk)
+ data_.set_bridge_id(bridgeId);
+ break;
+ }
+ case stp_port_id:
+ {
+ quint32 port_id = value.toUInt(&isOk);
+ if (isOk)
+ data_.set_port_id(port_id);
+ break;
+ }
+ case stp_message_age:
+ {
+ quint32 messageAge = value.toUInt(&isOk);
+ if (isOk)
+ data_.set_message_age(messageAge);
+ break;
+ }
+ case stp_max_age:
+ {
+ quint32 maxAge = value.toUInt(&isOk);
+ if (isOk)
+ data_.set_max_age(maxAge);
+ break;
+ }
+ case stp_hello_time:
+ {
+ quint32 helloTime = value.toUInt(&isOk);
+ if (isOk)
+ data_.set_hello_time(helloTime);
+ break;
+ }
+ case stp_forward_delay:
+ {
+ quint32 forwardDelay = value.toUInt(&isOk);
+ if (isOk)
+ data_.set_forward_delay(forwardDelay);
+ break;
+ }
+ default:
+ break;
+ }
+ return isOk;
+}
diff --git a/common/stp.h b/common/stp.h
new file mode 100644
index 0000000..9148e7c
--- /dev/null
+++ b/common/stp.h
@@ -0,0 +1,111 @@
+/*
+Copyright (C) 2014 PLVision.
+
+This file is part of "Ostinato"
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+
+This module is developed by PLVision
+*/
+
+#ifndef _STP_H
+#define _STP_H
+
+#include "abstractprotocol.h"
+#include "stp.pb.h"
+
+/*
+Stp Protocol Frame Format -
+ +------------------------------------+------------------+------------------+
+ | Protocol ID | Protocol VID | BPDU type |
+ | (16) | (8) | (8) |
+ +------------------+-----------------+------------------+------------------+
+ | Flags | Root Identifier ->|
+ | (8) | (64) ->|
+ +------------------+-------------------------------------------------------+
+ |-> Root Identifier ->|
+ |-> (64) ->|
+ +------------------+-------------------------------------------------------+
+ |-> Root Identifier| Root Path Cost ->|
+ |-> (8) | (32) ->|
+ +------------------+-------------------------------------------------------+
+ |-> Root Path Cost | Bridge Identifier ->|
+ |-> (32) | (64) ->|
+ +------------------+-------------------------------------------------------+
+ |-> Bridge Identifier ->|
+ |-> (64) ->|
+ +------------------+--------------------------------- --+------------------+
+ |-> Bridge Identif.| Port Identifier | Message Age ->|
+ |-> (64) | (16) | (16) ->|
+ +------------------+------------------------------------+------------------+
+ |-> Message Age | Max Age | Hello Time ->|
+ |-> (16) | (16) | (16) ->|
+ +------------------+------------------------------------+------------------+
+ |-> Hello Time | Forward delay |
+ |-> (16) | (16) |
+ +------------------+------------------------------------+
+Figures in brackets represent field width in bits
+*/
+
+class StpProtocol : public AbstractProtocol
+{
+public:
+ enum stpfield
+ {
+ stp_protocol_id = 0,
+ stp_version_id,
+ stp_bpdu_type,
+ stp_flags,
+ stp_root_id,
+ stp_root_path_cost,
+ stp_bridge_id,
+ stp_port_id,
+ stp_message_age,
+ stp_max_age,
+ stp_hello_time,
+ stp_forward_delay,
+
+ stp_fieldCount
+ };
+
+ StpProtocol(StreamBase *stream, AbstractProtocol *parent = 0);
+ virtual ~StpProtocol();
+
+ static AbstractProtocol* createInstance(StreamBase *stream,
+ AbstractProtocol *parent = 0);
+ virtual quint32 protocolNumber() const;
+
+ virtual void protoDataCopyInto(OstProto::Protocol &protocol) const;
+ virtual void protoDataCopyFrom(const OstProto::Protocol &protocol);
+
+ virtual ProtocolIdType protocolIdType() const;
+ virtual quint32 protocolId(ProtocolIdType type) const;
+
+ virtual QString name() const;
+ virtual QString shortName() const;
+
+ virtual int fieldCount() const;
+
+ virtual AbstractProtocol::FieldFlags fieldFlags(int index) const;
+ virtual QVariant fieldData(int index, FieldAttrib attrib,
+ int streamIndex = 0) const;
+ virtual bool setFieldData(int index, const QVariant &value,
+ FieldAttrib attrib = FieldValue);
+
+
+private:
+ OstProto::Stp data_;
+};
+
+#endif
diff --git a/common/stp.proto b/common/stp.proto
new file mode 100644
index 0000000..82d0e07
--- /dev/null
+++ b/common/stp.proto
@@ -0,0 +1,44 @@
+/*
+Copyright (C) 2014 PLVision.
+
+This file is part of "Ostinato"
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+
+This module is developed by PLVision
+*/
+
+import "protocol.proto";
+
+package OstProto;
+
+// Spanning Tree Protocol
+message Stp {
+ optional uint32 protocol_id = 1 [default = 0x0000];
+ optional uint32 protocol_version_id = 2 [default = 0x00];
+ optional uint32 bpdu_type = 3 [default = 0x00];
+ optional uint32 flags = 4;
+ optional uint64 root_id = 5;
+ optional uint32 root_path_cost = 6;
+ optional uint64 bridge_id = 7;
+ optional uint32 port_id = 8;
+ optional uint32 message_age = 9;
+ optional uint32 max_age = 10;
+ optional uint32 hello_time = 11;
+ optional uint32 forward_delay = 12;
+}
+
+extend Protocol {
+ optional Stp stp = 210;
+}
diff --git a/common/stp.ui b/common/stp.ui
new file mode 100644
index 0000000..741918d
--- /dev/null
+++ b/common/stp.ui
@@ -0,0 +1,510 @@
+
+
+ Stp
+
+
+
+ 0
+ 0
+ 615
+ 378
+
+
+
+ Form
+
+
+ -
+
+
+ 0
+
+
-
+
+
-
+
+
+ Protocol Identifier
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ -
+
+
+ true
+
+
+
+
+
+
+
+
+ 5
+
+
+ 0
+
+
+
+ -
+
+
+ Version Identifier
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ ui_version_id
+
+
+
+ -
+
+
+ true
+
+
+
+
+
+
+
+
+ 3
+
+
+ 0
+
+
+
+ -
+
+
+
+
+
+
+
+
+ 3
+
+
+
+ -
+
+
+ BPDU Type
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+
+ -
+
+
+ QLayout::SetDefaultConstraint
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ TC
+
+
+
+ -
+
+
+ TCA
+
+
+
+
+
+ -
+
+
+ Qt::LeftToRight
+
+
+ BPDU Flags
+
+
+
+
+
+ -
+
+
+ Root Identifier
+
+
+
+ 9
+
+
+ 9
+
+
-
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ >HH HH HH HH HH HH;
+
+
+
+
+
+ 17
+
+
+
+ -
+
+
+ Priority
+
+
+
+ -
+
+
+
+
+
+ 5
+
+
+
+ -
+
+
+ MAC Address
+
+
+
+ -
+
+
+ Path Cost
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+ 10
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Bridge Identifier
+
+
+
+ 0
+
+
+ 0
+
+
-
+
+
-
+
+
+ >HH HH HH HH HH HH;
+
+
+
+ -
+
+
+ Priority
+
+
+
+ -
+
+
+ MAC Address
+
+
+
+ -
+
+
+
+
+
+ 5
+
+
+
+
+
+
+
+
+ -
+
+
+ Port Identifier
+
+
+
+ 9
+
+
+ 9
+
+
-
+
+
-
+
+
+
+
+
+ 3
+
+
+
+ -
+
+
+ Number
+
+
+
+ -
+
+
+ Priority
+
+
+
+ -
+
+
+
+
+
+
+
+
+ 3
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Timers
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ false
+
+
+
+ 0
+
+
+ 9
+
+
-
+
+
+ 0
+
+
-
+
+
+ Message Age (1/256s)
+
+
+
+ -
+
+
+
+
+
+
+
+
+ 5
+
+
+
+ -
+
+
+ Max Age (1/256s)
+
+
+
+ -
+
+
+
+
+
+
+
+
+ 5
+
+
+
+
+
+ -
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Hello Time (1/256s)
+
+
+
+ -
+
+
+
+
+
+
+
+
+ 5
+
+
+
+ -
+
+
+ Forward Delay (1/256s)
+
+
+
+ -
+
+
+
+
+
+
+
+
+ 5
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+ groupBox_4
+
+ verticalSpacer_3
+
+
+ ui_protocol_id
+ ui_version_id
+ ui_bpdu_type
+ ui_flags_tc_check
+ ui_flags_tca_check
+ ui_root_id_priority
+ ui_root_id
+ ui_root_path_cost
+ ui_bridge_id_priority
+ ui_bridge_id
+ ui_port_id_priority
+ ui_port_id_number
+ ui_message_age
+ ui_max_age
+ ui_hello_time
+ ui_forward_delay
+
+
+
+
diff --git a/common/stpconfig.cpp b/common/stpconfig.cpp
new file mode 100644
index 0000000..6144b1a
--- /dev/null
+++ b/common/stpconfig.cpp
@@ -0,0 +1,257 @@
+/*
+Copyright (C) 2014 PLVision.
+
+This file is part of "Ostinato"
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+
+This module is developed by PLVision
+*/
+
+#include "stpconfig.h"
+#include "stp.h"
+
+#include
+#include
+
+#define ONE_BYTE_MAX 255
+#define TWO_BYTE_MAX 65535
+#define FOUR_BYTE_MAX 4294967295
+#define BIT_0 0
+#define BIT_7 7
+#define ONE_BIT(pos) ((unsigned int)(1 << (pos)))
+#define BYTES(byte) (byte * sizeof(unsigned char))
+#define STR_BYTES_LEN(len) (BYTES(len) * 2)
+
+class UNumberValidator : public QValidator
+{
+private:
+ quint64 min_;
+ quint64 max_;
+
+public:
+ UNumberValidator(quint64 min, quint64 max, QObject * parent = 0)
+ : QValidator(parent), min_(min), max_(max){}
+ virtual ~UNumberValidator(){}
+
+ virtual QValidator::State validate(QString& input, int& pos) const
+ {
+ QValidator::State state = QValidator::Acceptable;
+ quint64 val = input.toULongLong();
+ if(val < min_ || val > max_)
+ state = QValidator::Invalid;
+ return state;
+ }
+};
+
+
+StpConfigForm::StpConfigForm(QWidget *parent)
+ : AbstractProtocolConfigForm(parent)
+{
+ QRegExp reMac("([0-9,a-f,A-F]{2,2}[:-]){5,5}[0-9,a-f,A-F]{2,2}");
+ setupUi(this);
+
+ QRegExpValidator *validateMACAddress =
+ new QRegExpValidator(reMac, this);
+ UNumberValidator *validateByte =
+ new UNumberValidator(0, ONE_BYTE_MAX, this);
+ UNumberValidator *validate2Byte =
+ new UNumberValidator(0, TWO_BYTE_MAX, this);
+ UNumberValidator *validate4Byte =
+ new UNumberValidator(0, FOUR_BYTE_MAX, this);
+
+ ui_protocol_id->setValidator(validate2Byte);
+ ui_version_id->setValidator(validateByte);
+
+ ui_bpdu_type->setValidator(validateByte);
+
+ ui_root_id_priority->setValidator(validate2Byte);
+ ui_root_id->setValidator(validateMACAddress);
+
+ ui_root_path_cost->setValidator(validate4Byte);
+
+ ui_bridge_id_priority->setValidator(validate2Byte);
+ ui_bridge_id->setValidator(validateMACAddress);
+
+ ui_port_id_priority->setValidator(validateByte);
+ ui_port_id_number->setValidator(validateByte);
+
+ ui_message_age->setValidator(validate2Byte);
+ ui_max_age->setValidator(validate2Byte);
+ ui_hello_time->setValidator(validate2Byte);
+ ui_forward_delay->setValidator(validate2Byte);
+}
+
+StpConfigForm::~StpConfigForm()
+{
+}
+
+StpConfigForm* StpConfigForm::createInstance()
+{
+ return new StpConfigForm;
+}
+
+void StpConfigForm::loadWidget(AbstractProtocol *proto)
+{
+ bool isOk;
+
+ ui_protocol_id->setText(
+ proto->fieldData(
+ StpProtocol::stp_protocol_id,
+ AbstractProtocol::FieldValue
+ ).toString());
+ ui_version_id->setText(
+ proto->fieldData(
+ StpProtocol::stp_version_id,
+ AbstractProtocol::FieldValue
+ ).toString());
+ ui_bpdu_type->setText(
+ proto->fieldData(
+ StpProtocol::stp_bpdu_type,
+ AbstractProtocol::FieldValue
+ ).toString());
+
+ quint8 flags = proto->fieldData(
+ StpProtocol::stp_flags,
+ AbstractProtocol::FieldValue
+ ).toUInt();
+ ui_flags_tc_check->setChecked(flags & ONE_BIT(BIT_0));
+ ui_flags_tca_check->setChecked(flags & ONE_BIT(BIT_7));
+
+ // root priority value stored as the first two bytes of stp_root_id
+ // and the last 6 bytes are root MAC address (IEEE802.1D-2008)
+ quint64 rootId = proto->fieldData(
+ StpProtocol::stp_root_id,
+ AbstractProtocol::FieldValue
+ ).toULongLong(&isOk);
+
+ ui_root_id->setText(
+ QString::number(rootId & 0x0000FFFFFFFFFFFF, BASE_HEX));
+ ui_root_id_priority->setText(QString::number(rootId >> 48));
+
+ ui_root_path_cost->setText(
+ proto->fieldData(
+ StpProtocol::stp_root_path_cost,
+ AbstractProtocol::FieldValue
+ ).toString());
+
+ // bridge priority value stored as the first two bytes of stp_bridge_id
+ // and the last 6 bytes are bridge MAC address (IEEE802.1D-2008)
+ quint64 bridgeId = proto->fieldData(
+ StpProtocol::stp_bridge_id,
+ AbstractProtocol::FieldValue
+ ).toULongLong(&isOk);
+
+ ui_bridge_id->setText(
+ QString::number(bridgeId & 0x0000FFFFFFFFFFFF, BASE_HEX));
+ ui_bridge_id_priority->setText(QString::number(bridgeId >> 48));
+
+ // port priority is a first byte of stp_port_id field
+ // and port ID is a second byte (IEEE802.1D-2008)
+ uint portId = proto->fieldData(
+ StpProtocol::stp_port_id,
+ AbstractProtocol::FieldValue
+ ).toUInt(&isOk);
+
+ ui_port_id_priority->setText(QString::number(portId >> 8));
+ ui_port_id_number->setText(QString::number(portId & ONE_BYTE_MAX));
+
+ ui_message_age->setText(
+ proto->fieldData(
+ StpProtocol::stp_message_age,
+ AbstractProtocol::FieldValue
+ ).toString());
+ ui_max_age->setText(
+ proto->fieldData(
+ StpProtocol::stp_max_age,
+ AbstractProtocol::FieldValue
+ ).toString());
+ ui_hello_time->setText(
+ proto->fieldData(
+ StpProtocol::stp_hello_time,
+ AbstractProtocol::FieldValue
+ ).toString());
+ ui_forward_delay->setText(
+ proto->fieldData(
+ StpProtocol::stp_forward_delay,
+ AbstractProtocol::FieldValue
+ ).toString());
+}
+
+void StpConfigForm::storeWidget(AbstractProtocol *proto)
+{
+ bool isOk;
+
+ proto->setFieldData(
+ StpProtocol::stp_protocol_id,
+ QString("%1").arg(
+ ui_protocol_id->text().toUInt(&isOk) & TWO_BYTE_MAX));
+
+ proto->setFieldData(
+ StpProtocol::stp_version_id,
+ ui_version_id->text());
+ proto->setFieldData(
+ StpProtocol::stp_bpdu_type,
+ ui_bpdu_type->text());
+
+ char flags = 0;
+ if (ui_flags_tc_check->isChecked()) flags = flags | ONE_BIT(BIT_0);
+ if (ui_flags_tca_check->isChecked()) flags = flags | ONE_BIT(BIT_7);
+ proto->setFieldData(StpProtocol::stp_flags, flags);
+
+ // root priority value stored as the first two bytes of stp_root_id
+ // and the last 6 bytes are root MAC address (IEEE802.1D-2008)
+ quint64 rootIdPrio = ui_root_id_priority->text()
+ .toULongLong(&isOk) & TWO_BYTE_MAX;
+ quint64 rootId = hexStrToUInt64(
+ ui_root_id->text()) | rootIdPrio << 48;
+ proto->setFieldData(StpProtocol::stp_root_id, rootId);
+
+ proto->setFieldData(
+ StpProtocol::stp_root_path_cost,
+ ui_root_path_cost->text());
+
+ // bridge priority value stored as the first two bytes of stp_bridge_id
+ // and the last 6 bytes are bridge MAC address (IEEE802.1D-2008)
+ quint64 bridgeIdPrio =
+ ui_bridge_id_priority->text().toULongLong(&isOk) & TWO_BYTE_MAX;
+ quint64 bridgeId =
+ hexStrToUInt64(ui_bridge_id->text()) | bridgeIdPrio << 48;
+ proto->setFieldData(StpProtocol::stp_bridge_id, bridgeId);
+
+ // port priority is a first byte of stp_port_id field
+ // and port ID is a second byte (IEEE802.1D-2008)
+ ushort portIdPrio =
+ ui_port_id_priority->text().toUInt(&isOk, BASE_DEC) & ONE_BYTE_MAX;
+ ushort portId =
+ ui_port_id_number->text().toUInt(&isOk, BASE_DEC) & ONE_BYTE_MAX;
+ proto->setFieldData(StpProtocol::stp_port_id, portIdPrio << 8 | portId);
+ // timers
+ proto->setFieldData(
+ StpProtocol::stp_message_age,
+ ui_message_age->text().toUInt(&isOk, BASE_DEC) & TWO_BYTE_MAX);
+ proto->setFieldData(
+ StpProtocol::stp_max_age,
+ QString("%1").arg(
+ ui_max_age->text().toUInt(&isOk, BASE_DEC) & TWO_BYTE_MAX));
+ proto->setFieldData(
+ StpProtocol::stp_hello_time,
+ QString("%1").arg(
+ ui_hello_time->text().toUInt(&isOk, BASE_DEC) & TWO_BYTE_MAX));
+ proto->setFieldData(
+ StpProtocol::stp_forward_delay,
+ QString("%1").arg(
+ ui_forward_delay->text().toUInt(&isOk, BASE_DEC) & TWO_BYTE_MAX));
+}
+
diff --git a/common/stpconfig.h b/common/stpconfig.h
new file mode 100644
index 0000000..f64b111
--- /dev/null
+++ b/common/stpconfig.h
@@ -0,0 +1,43 @@
+/*
+Copyright (C) 2014 PLVision.
+
+This file is part of "Ostinato"
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+
+This module is developed by PLVision
+*/
+
+#ifndef _STP_CONFIG_H
+#define _STP_CONFIG_H
+
+#include "abstractprotocolconfig.h"
+#include "ui_stp.h"
+
+class StpConfigForm :
+ public AbstractProtocolConfigForm,
+ private Ui::Stp
+{
+ Q_OBJECT
+public:
+ StpConfigForm(QWidget *parent = 0);
+ virtual ~StpConfigForm();
+
+ static StpConfigForm* createInstance();
+
+ virtual void loadWidget(AbstractProtocol *proto);
+ virtual void storeWidget(AbstractProtocol *proto);
+};
+
+#endif
diff --git a/common/stppdml.cpp b/common/stppdml.cpp
new file mode 100644
index 0000000..c2cffa7
--- /dev/null
+++ b/common/stppdml.cpp
@@ -0,0 +1,76 @@
+/*
+Copyright (C) 2014 PLVision.
+
+This file is part of "Ostinato"
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+
+This module is developed by PLVision
+*/
+
+#include "stppdml.h"
+
+#include "stp.pb.h"
+
+#define ROOT_IDENTIFIER_POS 22
+#define BRIDGE_IDENTIFIER_POS 34
+#define BASE_DEC 10
+#define BASE_HEX 16
+
+PdmlStpProtocol::PdmlStpProtocol()
+{
+ ostProtoId_ = OstProto::Protocol::kStpFieldNumber;
+
+ fieldMap_.insert("stp.protocol",
+ OstProto::Stp::kProtocolIdFieldNumber);
+ fieldMap_.insert("stp.version",
+ OstProto::Stp::kProtocolVersionIdFieldNumber);
+ fieldMap_.insert("stp.type", OstProto::Stp::kBpduTypeFieldNumber);
+ fieldMap_.insert("stp.flags", OstProto::Stp::kFlagsFieldNumber);
+ fieldMap_.insert("stp.root.cost", OstProto::Stp::kRootPathCostFieldNumber);
+ fieldMap_.insert("stp.port", OstProto::Stp::kPortIdFieldNumber);
+ fieldMap_.insert("stp.msg_age", OstProto::Stp::kMessageAgeFieldNumber);
+ fieldMap_.insert("stp.max_age", OstProto::Stp::kMaxAgeFieldNumber);
+ fieldMap_.insert("stp.hello", OstProto::Stp::kHelloTimeFieldNumber);
+ fieldMap_.insert("stp.forward", OstProto::Stp::kForwardDelayFieldNumber);
+}
+
+PdmlStpProtocol::~PdmlStpProtocol()
+{
+}
+
+PdmlProtocol* PdmlStpProtocol::createInstance()
+{
+ return new PdmlStpProtocol();
+}
+
+void PdmlStpProtocol::unknownFieldHandler(
+ QString name, int pos, int /*size*/,
+ const QXmlStreamAttributes &attributes, OstProto::Protocol *pbProto,
+ OstProto::Stream* /*stream*/)
+{
+ bool isOk;
+ OstProto::Stp *stp = pbProto->MutableExtension(OstProto::stp);
+
+ if ((name == "") && (pos == ROOT_IDENTIFIER_POS))
+ {
+ stp->set_root_id(attributes.value("value").toString().
+ toULongLong(&isOk, BASE_HEX));
+ }
+ if ((name == "") && (pos == BRIDGE_IDENTIFIER_POS))
+ {
+ stp->set_bridge_id(attributes.value("value").toString().
+ toULongLong(&isOk, BASE_HEX));
+ }
+}
diff --git a/common/stppdml.h b/common/stppdml.h
new file mode 100644
index 0000000..5305e57
--- /dev/null
+++ b/common/stppdml.h
@@ -0,0 +1,42 @@
+/*
+Copyright (C) 2014 PLVision.
+
+This file is part of "Ostinato"
+
+This is free software: you can redistribute it and/or modify
+it under the terms of the GNU 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+
+This module is developed by PLVision
+*/
+
+#ifndef _STP_PDML_H
+#define _STP_PDML_H
+
+#include "pdmlprotocol.h"
+
+class PdmlStpProtocol : public PdmlProtocol
+{
+public:
+ virtual ~PdmlStpProtocol();
+
+ static PdmlProtocol *createInstance();
+
+ void unknownFieldHandler(QString name, int pos, int size,
+ const QXmlStreamAttributes &attributes,
+ OstProto::Protocol *pbProto, OstProto::Stream* stream);
+
+protected:
+ PdmlStpProtocol();
+};
+
+#endif