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