From 077b54bbed63261d03cecb26eb8f38798c371fab Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Sun, 21 Apr 2013 13:22:15 -0300 Subject: [PATCH] Added STP root_id and bridge_id setters/getters. --- include/stp.h | 51 ++++++++++++++++++++++++++++++++++++++++++-- src/ipv6_address.cpp | 1 - src/stp.cpp | 40 ++++++++++++++++++++++++++++++++++ src/utils.cpp | 1 - tests/src/stp.cpp | 35 ++++++++++++++++++++++++++++++ 5 files changed, 124 insertions(+), 4 deletions(-) diff --git a/include/stp.h b/include/stp.h index fb11094..97974c1 100644 --- a/include/stp.h +++ b/include/stp.h @@ -32,6 +32,7 @@ #include "pdu.h" #include "endianness.h" +#include "hw_address.h" #include "small_uint.h" namespace Tins { @@ -41,6 +42,24 @@ public: * This PDU's flag. */ static const PDU::PDUType pdu_flag = PDU::STP; + + /** + * The type used to store BPDU identifier addresses. + */ + typedef HWAddress<6> address_type; + + /** + * The type used to store the BPDU identifiers. + */ + struct bpdu_id_type { + small_uint<4> priority; + small_uint<12> ext_id; + address_type id; + + bpdu_id_type(small_uint<4> priority=0, small_uint<12> ext_id=0, + const address_type& id=address_type()) + : priority(priority), ext_id(ext_id), id(id) { } + }; /** * \brief Default constructor. @@ -139,6 +158,18 @@ public: uint16_t fwd_delay() const { return Endian::be_to_host(_header.fwd_delay) / 256; } + + /** + * \brief Getter for the root id field. + * \return The stored root id field value. + */ + bpdu_id_type root_id() const; + + /** + * \brief Getter for the bridge id field. + * \return The stored bridge id field value. + */ + bpdu_id_type bridge_id() const; /** * \brief Getter for the PDU's type. @@ -221,13 +252,26 @@ public: * \param new_fwd_delay The new fwd_delay field value. */ void fwd_delay(uint16_t new_fwd_delay); + + /** + * \brief Setter for the root id field. + * \param new_fwd_delay The new root id field value. + */ + void root_id(const bpdu_id_type &id); + + /** + * \brief Setter for the bridge id field. + * \param new_fwd_delay The new bridge id field value. + */ + void bridge_id(const bpdu_id_type &id); private: TINS_BEGIN_PACK struct pvt_bpdu_id { #if TINS_IS_LITTLE_ENDIAN // fixme - uint16_t priority:4, - ext_id:12; + uint16_t ext_id:4, + priority:4, + ext_idL:8; #else uint16_t priority:4, ext_id:12; @@ -251,6 +295,9 @@ private: uint16_t fwd_delay; } TINS_END_PACK; + static bpdu_id_type convert(const pvt_bpdu_id &id); + static pvt_bpdu_id convert(const bpdu_id_type &id); + void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); stphdr _header; diff --git a/src/ipv6_address.cpp b/src/ipv6_address.cpp index 716d7d9..68d2d27 100644 --- a/src/ipv6_address.cpp +++ b/src/ipv6_address.cpp @@ -39,7 +39,6 @@ #include #endif #include -#include // borrame #include #include "ipv6_address.h" diff --git a/src/stp.cpp b/src/stp.cpp index dbea5d3..b58e2c5 100644 --- a/src/stp.cpp +++ b/src/stp.cpp @@ -29,6 +29,7 @@ #include #include +#include #include "stp.h" #include "exceptions.h" @@ -87,6 +88,22 @@ void STP::fwd_delay(uint16_t new_fwd_delay) { _header.fwd_delay = Endian::host_to_be(new_fwd_delay * 256); } +STP::bpdu_id_type STP::root_id() const { + return convert(_header.root_id); +} + +STP::bpdu_id_type STP::bridge_id() const { + return convert(_header.bridge_id); +} + +void STP::root_id(const bpdu_id_type &id) { + _header.root_id = convert(id); +} + +void STP::bridge_id(const bpdu_id_type &id) { + _header.bridge_id = convert(id); +} + void STP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) { #ifdef TINS_DEBUG assert(total_sz >= sizeof(_header)); @@ -97,5 +114,28 @@ void STP::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *) { uint32_t STP::header_size() const { return sizeof(_header); } + +STP::bpdu_id_type STP::convert(const pvt_bpdu_id &id) { + bpdu_id_type result(id.priority, 0, id.id); + #if TINS_IS_LITTLE_ENDIAN + result.ext_id = (id.ext_id << 8) | id.ext_idL; + #else + result.ext_id = id.ext_id; + #endif + return result; +} + +STP::pvt_bpdu_id STP::convert(const bpdu_id_type &id) { + pvt_bpdu_id result; + result.priority = id.priority; + std::copy(id.id.begin(), id.id.end(), result.id); + #if TINS_IS_LITTLE_ENDIAN + result.ext_id = (id.ext_id >> 8) & 0xf; + result.ext_idL = id.ext_id & 0xff; + #else + result.ext_id = id.ext_id; + #endif + return result; +} } diff --git a/src/utils.cpp b/src/utils.cpp index cf7402f..6fd2b38 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -31,7 +31,6 @@ #include #include #include -#include //borrame #include #include "utils.h" #ifndef WIN32 diff --git a/tests/src/stp.cpp b/tests/src/stp.cpp index d9ed7d1..8dbb3a1 100644 --- a/tests/src/stp.cpp +++ b/tests/src/stp.cpp @@ -12,6 +12,7 @@ using namespace Tins; class STPTest : public testing::Test { public: static const uint8_t expected_packet[]; + static void test_equals(const STP::bpdu_id_type &lhs, const STP::bpdu_id_type &rhs); }; const uint8_t STPTest::expected_packet[] = { @@ -20,6 +21,12 @@ const uint8_t STPTest::expected_packet[] = { 0 }; +void STPTest::test_equals(const STP::bpdu_id_type &lhs, const STP::bpdu_id_type &rhs) { + EXPECT_EQ(lhs.priority, rhs.priority); + EXPECT_EQ(lhs.ext_id, rhs.ext_id); + EXPECT_EQ(lhs.id, rhs.id); +} + TEST_F(STPTest, DefaultConstructor) { STP pdu; EXPECT_EQ(0, pdu.proto_id()); @@ -36,12 +43,15 @@ TEST_F(STPTest, DefaultConstructor) { TEST_F(STPTest, ConstructorFromBuffer) { STP pdu(expected_packet, sizeof(expected_packet)); + STP::bpdu_id_type bpdu(0x8, 0, "00:90:4c:08:17:b5"); EXPECT_EQ(0x9283, pdu.proto_id()); EXPECT_EQ(0x8a, pdu.proto_version()); EXPECT_EQ(0x92, pdu.bpdu_type()); EXPECT_EQ(0x92, pdu.bpdu_flags()); + test_equals(bpdu, pdu.root_id()); // root identifier(32768. 0, 00:90:4c:08:17:b5 EXPECT_EQ(0x928378, pdu.root_path_cost()); + test_equals(bpdu, pdu.bridge_id()); // bridge identifier(32768. 0, 00:90:4c:08:17:b5 EXPECT_EQ(0x8001, pdu.port_id()); EXPECT_EQ(15, pdu.msg_age()); @@ -50,6 +60,17 @@ TEST_F(STPTest, ConstructorFromBuffer) { EXPECT_EQ(0, pdu.fwd_delay()); } +TEST_F(STPTest, BPDUId) { + const uint8_t expected_packet[] = { + 0, 0, 0, 0, 0, 128, 100, 0, 28, 14, 135, 120, 0, 0, 0, 0, 4, 128, + 100, 0, 28, 14, 135, 133, 0, 128, 4, 1, 0, 20, 0, 2, 0, 15, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + }; + STP pdu(expected_packet, sizeof(expected_packet)); + STP::bpdu_id_type bpdu(0x8, 100, "00:1c:0e:87:78:00"); + test_equals(bpdu, pdu.root_id()); +} + TEST_F(STPTest, ChainedPDUs) { const uint8_t input[] = { 1, 128, 194, 0, 0, 0, 0, 144, 76, 8, 23, 181, 0, 38, 66, 66, 3, @@ -140,3 +161,17 @@ TEST_F(STPTest, HelloTime) { pdu.hello_time(15); EXPECT_EQ(15, pdu.hello_time()); } + +TEST_F(STPTest, RootID) { + STP pdu; + STP::bpdu_id_type bpdu(0x8, 100, "00:1c:0e:87:78:00"); + pdu.root_id(bpdu); + test_equals(bpdu, pdu.root_id()); +} + +TEST_F(STPTest, BridgeID) { + STP pdu; + STP::bpdu_id_type bpdu(0x8, 100, "00:1c:0e:87:78:00"); + pdu.bridge_id(bpdu); + test_equals(bpdu, pdu.bridge_id()); +}