From 6743e06d11432bed854bb125e0081ff822d283b7 Mon Sep 17 00:00:00 2001 From: Prakash Bailkeri Date: Thu, 8 Dec 2016 16:25:22 +0530 Subject: [PATCH] Extended community for etree-leaf Add support for etree extended community Add sticky bit to MacMobility community Add tests for etree Add/Modify tests for MacMobility Change-Id: I4c167ab12a79e89f3e4bcc4b7998cf20814e2a91 Related-bug: #1645092 --- src/bgp/extended-community/SConscript | 1 + src/bgp/extended-community/etree.cc | 55 +++++++++++++++ src/bgp/extended-community/etree.h | 41 ++++++++++++ src/bgp/extended-community/mac_mobility.cc | 19 ++++-- src/bgp/extended-community/mac_mobility.h | 5 +- src/bgp/extended-community/test/SConscript | 5 ++ src/bgp/extended-community/test/etree_test.cc | 67 +++++++++++++++++++ .../test/mac_mobility_test.cc | 30 +++++++-- src/bgp/extended-community/types.h | 1 + 9 files changed, 215 insertions(+), 9 deletions(-) create mode 100644 src/bgp/extended-community/etree.cc create mode 100644 src/bgp/extended-community/etree.h create mode 100644 src/bgp/extended-community/test/etree_test.cc diff --git a/src/bgp/extended-community/SConscript b/src/bgp/extended-community/SConscript index 5cd6adfbbbe..14be9303f41 100644 --- a/src/bgp/extended-community/SConscript +++ b/src/bgp/extended-community/SConscript @@ -16,6 +16,7 @@ libextended_community = env.Library('extended_community', ['default_gateway.cc', 'es_import.cc', 'esi_label.cc', + 'etree.cc', 'load_balance.cc', 'mac_mobility.cc', 'router_mac.cc', diff --git a/src/bgp/extended-community/etree.cc b/src/bgp/extended-community/etree.cc new file mode 100644 index 00000000000..fa33dac74b8 --- /dev/null +++ b/src/bgp/extended-community/etree.cc @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved. + */ + +#include "bgp/extended-community/etree.h" + +#include + +#include +#include + + +using std::copy; +using std::string; + +ETree::ETree(bool leaf, int label) { + data_[0] = BgpExtendedCommunityType::Evpn; + data_[1] = BgpExtendedCommunityEvpnSubType::ETree; + data_[2] = leaf ? 0x01 : 0x0; // Leaf Indication + data_[3] = 0x00; // Reserved + data_[4] = 0x00; // Reserved + put_value(&data_[5], 3, (label<<4)); // leaf label +} + +ETree::ETree(const bytes_type &data) { + copy(data.begin(), data.end(), data_.begin()); +} + +bool ETree::leaf() const { + uint8_t data[ETree::kSize]; + copy(data_.begin(), data_.end(), &data[0]); + if (data[0] == BgpExtendedCommunityType::Evpn && + data[1] == BgpExtendedCommunityEvpnSubType::ETree) { + return (data[2] & 0x1); + } + return false; +} + +int ETree::label() const { + uint8_t data[ETree::kSize]; + copy(data_.begin(), data_.end(), &data[0]); + if (data[0] == BgpExtendedCommunityType::Evpn && + data[1] == BgpExtendedCommunityEvpnSubType::ETree) { + uint32_t value = get_value(data + 5, 3); + return value >> 4; + } + return false; +} + +std::string ETree::ToString() { + char temp[50]; + snprintf(temp, sizeof(temp), "etree:%s:%d", + (leaf() ? "leaf":"root"), label()); + return string(temp); +} diff --git a/src/bgp/extended-community/etree.h b/src/bgp/extended-community/etree.h new file mode 100644 index 00000000000..80f9b280eaa --- /dev/null +++ b/src/bgp/extended-community/etree.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved. + */ + +#ifndef SRC_BGP_EXTENDED_COMMUNITY_ETREE_H_ +#define SRC_BGP_EXTENDED_COMMUNITY_ETREE_H_ + +#include +#include + +#include + +#include "base/parse_object.h" +#include "bgp/extended-community/types.h" + +class ETree { +public: + static const int kSize = 8; + typedef boost::array bytes_type; + + explicit ETree(bool leaf, int label=0); + explicit ETree(const bytes_type &data); + + bool leaf() const; + int label() const; + + const bytes_type &GetExtCommunity() const { + return data_; + } + + const uint64_t GetExtCommunityValue() const { + return get_value(data_.begin(), 8); + } + + std::string ToString(); + +private: + bytes_type data_; +}; + +#endif // SRC_BGP_EXTENDED_COMMUNITY_ETREE_H_ diff --git a/src/bgp/extended-community/mac_mobility.cc b/src/bgp/extended-community/mac_mobility.cc index 154747b5d53..613c85afeb1 100644 --- a/src/bgp/extended-community/mac_mobility.cc +++ b/src/bgp/extended-community/mac_mobility.cc @@ -13,11 +13,11 @@ using std::copy; using std::string; -MacMobility::MacMobility(uint32_t seq) { +MacMobility::MacMobility(uint32_t seq, bool sticky) { data_[0] = BgpExtendedCommunityType::Evpn; data_[1] = BgpExtendedCommunityEvpnSubType::MacMobility; - data_[2] = 0x01; // Flags - data_[3] = 0x00; // Reserved + data_[2] = (sticky ? 0x01 : 0x0); // sticky + data_[3] = 0x00; // Reserved put_value(&data_[4], 4, seq); } @@ -25,6 +25,16 @@ MacMobility::MacMobility(const bytes_type &data) { copy(data.begin(), data.end(), data_.begin()); } +bool MacMobility::sticky() const { + uint8_t data[MacMobility::kSize]; + copy(data_.begin(), data_.end(), &data[0]); + if (data[0] == BgpExtendedCommunityType::Evpn && + data[1] == BgpExtendedCommunityEvpnSubType::MacMobility) { + return (data[2] & 0x1); + } + return false; +} + uint32_t MacMobility::sequence_number() const { uint8_t data[MacMobility::kSize]; copy(data_.begin(), data_.end(), &data[0]); @@ -38,6 +48,7 @@ uint32_t MacMobility::sequence_number() const { std::string MacMobility::ToString() { char temp[50]; - snprintf(temp, sizeof(temp), "mobility:%d", sequence_number()); + snprintf(temp, sizeof(temp), "mobility:%s:%d", + (sticky() ? "sticky" : "non-sticky"), sequence_number()); return string(temp); } diff --git a/src/bgp/extended-community/mac_mobility.h b/src/bgp/extended-community/mac_mobility.h index cba1beb20ac..d867307f084 100644 --- a/src/bgp/extended-community/mac_mobility.h +++ b/src/bgp/extended-community/mac_mobility.h @@ -18,10 +18,11 @@ class MacMobility { static const int kSize = 8; typedef boost::array bytes_type; - explicit MacMobility(uint32_t seq); + explicit MacMobility(uint32_t seq, bool sticky=false); explicit MacMobility(const bytes_type &data); uint32_t sequence_number() const; + bool sticky() const; const bytes_type &GetExtCommunity() const { return data_; @@ -30,7 +31,9 @@ class MacMobility { const uint64_t GetExtCommunityValue() const { return get_value(data_.begin(), 8); } + std::string ToString(); + private: bytes_type data_; }; diff --git a/src/bgp/extended-community/test/SConscript b/src/bgp/extended-community/test/SConscript index 0629782db1e..19b0fdaa56b 100644 --- a/src/bgp/extended-community/test/SConscript +++ b/src/bgp/extended-community/test/SConscript @@ -47,10 +47,15 @@ load_balance_test = env.UnitTest('load_balance_test', ['load_balance_test.cc']) env.Alias('src/bgp/extended-community:load_balance_test', load_balance_test) +etree_test = env.UnitTest('etree_test', + ['etree_test.cc']) +env.Alias('src/bgp/extended-community:etree_test', etree_test) + test_suite = [ default_gateway_test, es_import_test, esi_label_test, + etree_test, load_balance_test, mac_mobility_test, router_mac_test, diff --git a/src/bgp/extended-community/test/etree_test.cc b/src/bgp/extended-community/test/etree_test.cc new file mode 100644 index 00000000000..00d1ea8dd48 --- /dev/null +++ b/src/bgp/extended-community/test/etree_test.cc @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016 Juniper Networks, Inc. All rights reserved. + */ + +#include "bgp/extended-community/etree.h" + +#include "testing/gunit.h" + +using namespace std; + +class ETreeTest : public ::testing::Test { +}; + +TEST_F(ETreeTest, ByteArray_1) { + ETree::bytes_type data = { { + BgpExtendedCommunityType::Evpn, + BgpExtendedCommunityEvpnSubType::ETree, + 0x01, 0x00, 0x0, 0x0, 0x0, 0x0 + } }; + ETree etree(data); + EXPECT_EQ("etree:leaf:0", etree.ToString()); +} + +TEST_F(ETreeTest, ByteArray_2) { + ETree::bytes_type data = { { + BgpExtendedCommunityType::Evpn, + BgpExtendedCommunityEvpnSubType::ETree, + 0x00, 0x00, 0x0, 0x1, 0x0, 0x0 + } }; + ETree etree(data); + EXPECT_EQ("etree:root:4096", etree.ToString()); +} + +TEST_F(ETreeTest, ByteArray_3) { + ETree::bytes_type data = { { + BgpExtendedCommunityType::Evpn, + BgpExtendedCommunityEvpnSubType::ETree, + 0x00, 0x00, 0x0, 0x0, 0x1, 0x0 + } }; + ETree etree(data); + EXPECT_EQ("etree:root:16", etree.ToString()); +} + + +TEST_F(ETreeTest, Init) { + boost::system::error_code ec; + ETree etree(true); + EXPECT_EQ(etree.ToString(), "etree:leaf:0"); +} + +TEST_F(ETreeTest, Init_2) { + boost::system::error_code ec; + ETree etree(false); + EXPECT_EQ(etree.ToString(), "etree:root:0"); +} + +TEST_F(ETreeTest, Init_3) { + boost::system::error_code ec; + ETree etree(false, 100); + EXPECT_EQ(etree.ToString(), "etree:root:100"); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + int result = RUN_ALL_TESTS(); + return result; +} diff --git a/src/bgp/extended-community/test/mac_mobility_test.cc b/src/bgp/extended-community/test/mac_mobility_test.cc index 82863e47d88..5d3bb28f158 100644 --- a/src/bgp/extended-community/test/mac_mobility_test.cc +++ b/src/bgp/extended-community/test/mac_mobility_test.cc @@ -18,7 +18,7 @@ TEST_F(MacMobilityTest, ByteArray_1) { 0x01, 0x00, 0x0, 0x0, 0x0, 0x1 } }; MacMobility mac_mobility(data); - EXPECT_EQ("mobility:1", mac_mobility.ToString()); + EXPECT_EQ("mobility:sticky:1", mac_mobility.ToString()); } TEST_F(MacMobilityTest, ByteArray_2) { @@ -28,21 +28,43 @@ TEST_F(MacMobilityTest, ByteArray_2) { 0x01, 0x00, 0x0, 0x1, 0x0, 0x0 } }; MacMobility mac_mobility(data); - EXPECT_EQ("mobility:65536", mac_mobility.ToString()); + EXPECT_EQ("mobility:sticky:65536", mac_mobility.ToString()); } +TEST_F(MacMobilityTest, ByteArray_3) { + MacMobility::bytes_type data = { { + BgpExtendedCommunityType::Evpn, + BgpExtendedCommunityEvpnSubType::MacMobility, + 0x00, 0x00, 0x0, 0x0, 0x0, 0x1 + } }; + MacMobility mac_mobility(data); + EXPECT_EQ("mobility:non-sticky:1", mac_mobility.ToString()); +} + + TEST_F(MacMobilityTest, Init) { boost::system::error_code ec; MacMobility mac_mobility(0x1); - EXPECT_EQ(mac_mobility.ToString(), "mobility:1"); + EXPECT_EQ(mac_mobility.ToString(), "mobility:non-sticky:1"); } TEST_F(MacMobilityTest, Init_2) { boost::system::error_code ec; MacMobility mac_mobility(0x10000); - EXPECT_EQ(mac_mobility.ToString(), "mobility:65536"); + EXPECT_EQ(mac_mobility.ToString(), "mobility:non-sticky:65536"); +} + +TEST_F(MacMobilityTest, Init_3) { + boost::system::error_code ec; + MacMobility mac_mobility(0x10000, true); + EXPECT_EQ(mac_mobility.ToString(), "mobility:sticky:65536"); } +TEST_F(MacMobilityTest, Init_4) { + boost::system::error_code ec; + MacMobility mac_mobility(0x10000, false); + EXPECT_EQ(mac_mobility.ToString(), "mobility:non-sticky:65536"); +} int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); diff --git a/src/bgp/extended-community/types.h b/src/bgp/extended-community/types.h index e72e44ab2c9..907141c8650 100644 --- a/src/bgp/extended-community/types.h +++ b/src/bgp/extended-community/types.h @@ -37,6 +37,7 @@ struct BgpExtendedCommunityEvpnSubType { EsiMplsLabel = 0x01, EsImport = 0x02, RouterMac = 0x03, + ETree = 0x05, }; };