Skip to content

Commit

Permalink
Support single-active BGPaaS object attached to multiple VMIs
Browse files Browse the repository at this point in the history
- updated the review comments
  - using IndexVector to allocate index dynamically.
  - Added test case for multiple add for same session and vmi

Change-Id: I1dfc3e1205b1be682ed59f484aafdf7bddd23fd8
Closes-Bug: #1649707
  • Loading branch information
srinivn committed Jul 20, 2017
1 parent 915ffda commit 81bf092
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 57 deletions.
33 changes: 29 additions & 4 deletions src/base/bgp_as_service_utils.cc
Expand Up @@ -4,19 +4,28 @@

#include <base/bgp_as_service_utils.h>
/*
* This utils apis will be used by BGP As A Service feature to map
* This utils apis will be used by BGP As A Service feature to map
* between the original service port allocated for the given BgpAsAService
* session and the derived service port for each VMI who is sharing the same
* session
* GetDerivedBgpaasServicePortRange - From the given config port range and max
* session, derive the internal port range
* session, derive the internal port range
* Port range and maximum number of VMIs who is sharing the given BgpAsAService
* session will be given by config
* session will be given by config
* EncodeBgpaasServicePort - For the given original service port and
* index, derive the service port which will be used by the corresponding
* flow which is associated with the corresponding VMI.
* DecodeBgpaasServicePort - For the given service port, decode the
* DecodeBgpaasServicePort - For the given service port, decode the
* original service port and the index for the given port.
* From the given range, the dervied port will be defined as follows,
* Ex : User Configured Range : 50000 - 50512
* Session:1 : config allocates : 50000 for VMI1
* Sharing the session-1 for VMI2: allocates 50513
* Sharing the session-1 for VMI3: allocates 51026
*
* Session:2 : config allocates : 50001 for VMI4
* Sharing the session-2 for VMI5: allocates 50514
* Sharing the session-2 for VMI6: allocates 51027
*/
using namespace std;
BGPaaSUtils::BgpAsServicePortIndexPair BGPaaSUtils::DecodeBgpaasServicePort(
Expand All @@ -32,6 +41,14 @@ BGPaaSUtils::BgpAsServicePortIndexPair BGPaaSUtils::DecodeBgpaasServicePort(
}

uint16_t port_range = port_range_end - port_range_start + 1;

/*
* From the given derived port, the original port will be
* calculated based on posisiton in the the given port range in
* addition to the port range start.
* Ex : given port is 51026 and the range is 50000-50512
* original port will be 50000 and index will be 2
*/
original_sport = (((sport - port_range_end) % port_range) - 1)
+ port_range_start;
index = ((sport - port_range_end) / port_range) + 1;
Expand All @@ -48,6 +65,14 @@ uint32_t BGPaaSUtils::EncodeBgpaasServicePort(const uint32_t sport,
}

uint16_t port_range = port_range_end - port_range_start + 1;
/*
* From the given original port and index, the derived port will be
* calculated based on selection of derived range which is the multiple
* of given port range by the given index in addition to the position of
* the original port with respect to port range start.
* Ex : given port, index : 50000, 2 and the range is 50000-50512
* derived port port will be 51026
*/
return (port_range_start + (port_range * index)
+ (sport - port_range_start));
}
4 changes: 4 additions & 0 deletions src/vnsw/agent/cmn/index_vector.h
Expand Up @@ -82,6 +82,10 @@ class IndexVector {
entries_[index] = NULL;
}

bool NoneIndexSet() {
return (bitmap_.count() == bitmap_.size());
}

private:
typedef boost::dynamic_bitset<> Bitmap;
Bitmap bitmap_;
Expand Down
38 changes: 15 additions & 23 deletions src/vnsw/agent/oper/bgp_as_service.cc
Expand Up @@ -177,17 +177,11 @@ void BgpAsAService::BuildBgpAsAServiceInfo(IFMapNode *bgp_as_a_service_node,
old_bgp_as_a_service_entry_list_iter->second->list_) {
source_port = bgp_router->parameters().source_port;
}
BgpAsAServiceEntryListIterator deleted_list_iter =
temp_bgp_as_a_service_entry_list.begin();
while (deleted_list_iter !=
temp_bgp_as_a_service_entry_list.end()) {
BgpAsAServiceEntryListIterator prev = deleted_list_iter++;
temp_bgp_as_a_service_entry_list.erase(prev);
}
}
if (!source_port) {
source_port = AddBgpVmiServicePortIndex(
bgp_router->parameters().source_port);
bgp_router->parameters().source_port,
vm_uuid);
}
if (source_port) {
new_list.insert(BgpAsAServiceEntry(peer_ip,
Expand Down Expand Up @@ -298,11 +292,11 @@ bool BgpAsAService::IsBgpService(const VmInterface *vm_intf,
}

void BgpAsAService::FreeBgpVmiServicePortIndex(const uint32_t sport) {
const std::vector<uint16_t> &ports =
agent_->oper_db()->global_system_config()->bgpaas_port_range();
BGPaaServiceParameters:: BGPaaServicePortRangePair ports =
agent_->oper_db()->global_system_config()->bgpaas_port_range();
BGPaaSUtils::BgpAsServicePortIndexPair portinfo =
BGPaaSUtils::DecodeBgpaasServicePort(sport,
ports[0], ports[1]);
ports.first, ports.second);

BgpAsAServicePortMapIterator port_map_it =
bgp_as_a_service_port_map_.find(portinfo.first);
Expand All @@ -312,7 +306,7 @@ void BgpAsAService::FreeBgpVmiServicePortIndex(const uint32_t sport) {

size_t vmi_service_port_index = portinfo.second;

port_map_it->second->FreeIndex(vmi_service_port_index);
port_map_it->second->Remove(vmi_service_port_index);

if (port_map_it->second->NoneIndexSet()) {
delete port_map_it->second;
Expand All @@ -321,24 +315,22 @@ void BgpAsAService::FreeBgpVmiServicePortIndex(const uint32_t sport) {
}

size_t BgpAsAService::AllocateBgpVmiServicePortIndex(const uint32_t sport,
const uint16_t max_shared_sessions) {
const boost::uuids::uuid vm_uuid) {
BgpAsAServicePortMapIterator port_map_it =
bgp_as_a_service_port_map_.find(sport);
if (port_map_it == bgp_as_a_service_port_map_.end()) {
bgp_as_a_service_port_map_[sport] = new IndexAllocator(
max_shared_sessions);
bgp_as_a_service_port_map_[sport] = new IndexVector<boost::uuids::uuid>();
}
return bgp_as_a_service_port_map_[sport]->AllocIndex();
return bgp_as_a_service_port_map_[sport]->Insert(NULL);
}

uint32_t BgpAsAService::AddBgpVmiServicePortIndex(const uint32_t source_port) {
const std::vector<uint16_t> &ports =
agent_->oper_db()->global_system_config()->bgpaas_port_range();
uint16_t port_range = ports[1] - ports[0] + 1;
uint16_t max_session = USHRT_MAX / port_range;
uint32_t BgpAsAService::AddBgpVmiServicePortIndex(const uint32_t source_port,
const boost::uuids::uuid vm_uuid) {
BGPaaServiceParameters:: BGPaaServicePortRangePair ports =
agent_->oper_db()->global_system_config()->bgpaas_port_range();

size_t vmi_service_port_index = AllocateBgpVmiServicePortIndex(source_port,
max_session);
vm_uuid);
if (vmi_service_port_index == BitSet::npos) {
std::stringstream ss;
ss << "Service Port Index is not available for ";
Expand All @@ -349,7 +341,7 @@ uint32_t BgpAsAService::AddBgpVmiServicePortIndex(const uint32_t source_port) {
return BGPaaSUtils::EncodeBgpaasServicePort(
source_port,
vmi_service_port_index,
ports[0], ports[1]);
ports.first, ports.second);
}

bool BgpAsAService::GetBgpRouterServiceDestination(const VmInterface *vm_intf,
Expand Down
7 changes: 4 additions & 3 deletions src/vnsw/agent/oper/bgp_as_service.h
Expand Up @@ -103,7 +103,7 @@ class BgpAsAService {
typedef BgpAsAServiceEntryMap::iterator BgpAsAServiceEntryMapIterator;
typedef BgpAsAServiceEntryMap::const_iterator BgpAsAServiceEntryMapConstIterator;

typedef std::map<uint32_t, IndexAllocator*> BgpAsAServicePortMap;
typedef std::map<uint32_t, IndexVector<boost::uuids::uuid>* > BgpAsAServicePortMap;
typedef BgpAsAServicePortMap::iterator BgpAsAServicePortMapIterator;
typedef BgpAsAServicePortMap::const_iterator BgpAsAServicePortMapConstIterator;

Expand All @@ -119,9 +119,10 @@ class BgpAsAService {
IpAddress *nat_server,
uint32_t *sport) const;
size_t AllocateBgpVmiServicePortIndex(const uint32_t sport,
const uint16_t max_shared_sessions);
const boost::uuids::uuid vm_uuid);
void FreeBgpVmiServicePortIndex(const uint32_t sport);
uint32_t AddBgpVmiServicePortIndex(const uint32_t source_port);
uint32_t AddBgpVmiServicePortIndex(const uint32_t source_port,
const boost::uuids::uuid vm_uuid);
void ProcessConfig(const std::string &vrf_name,
std::list<IFMapNode *> &node_list,
const boost::uuids::uuid &vmi_uuid);
Expand Down
12 changes: 6 additions & 6 deletions src/vnsw/agent/oper/global_system_config.cc
Expand Up @@ -29,14 +29,14 @@ void GlobalSystemConfig::GlobalSystemConfigHandler(DBTablePartBase *partition,
autogen::GlobalSystemConfig *cfg =
static_cast<autogen::GlobalSystemConfig *>(node->GetObject());
if (cfg) {
bgpaas_port_range_.push_back(
cfg->bgpaas_parameters().port_start);
bgpaas_port_range_.push_back(
cfg->bgpaas_parameters().port_end);
bgpaas_parameters_.port_start = cfg->bgpaas_parameters().port_start;
bgpaas_parameters_.port_end = cfg->bgpaas_parameters().port_end;
} else {
bgpaas_port_range_.clear();
bgpaas_parameters_.port_start = 0;
bgpaas_parameters_.port_end = 0;
}
} else {
bgpaas_port_range_.clear();
bgpaas_parameters_.port_start = 0;
bgpaas_parameters_.port_end = 0;
}
}
12 changes: 9 additions & 3 deletions src/vnsw/agent/oper/global_system_config.h
Expand Up @@ -9,6 +9,11 @@
#include <oper/oper_db.h>

class IFMapNode;
struct BGPaaServiceParameters {
typedef std::pair<uint16_t, uint16_t> BGPaaServicePortRangePair;
int port_start;
int port_end;
};
class GlobalSystemConfig {
public:
GlobalSystemConfig(OperDB *oper_db);
Expand All @@ -19,12 +24,13 @@ class GlobalSystemConfig {
OperDB* oper_db() const {
return oper_db_;
}
const std::vector<uint16_t> &bgpaas_port_range() const {
return bgpaas_port_range_;
BGPaaServiceParameters::BGPaaServicePortRangePair bgpaas_port_range() const {
return std::make_pair(bgpaas_parameters_.port_start,
bgpaas_parameters_.port_end);
}
private:
DBTableBase::ListenerId global_system_config_listener_id_;
OperDB *oper_db_;
std::vector<uint16_t> bgpaas_port_range_;
BGPaaServiceParameters bgpaas_parameters_;
};
#endif
60 changes: 42 additions & 18 deletions src/vnsw/agent/pkt/test/test_bgp_service.cc
Expand Up @@ -135,14 +135,12 @@ class BgpServiceTest : public ::testing::Test {

Agent *agent_;
FlowProto *flow_proto_;
BgpPeer *peer;
};

//TTL 1
TEST_F(BgpServiceTest, Test_ttl_1) {
AddAap("vnet1", 1, Ip4Address::from_string("10.10.10.10"), "00:00:01:01:01:01");

peer = CreateBgpPeer("127.0.0.1", "remote");
client->WaitForIdle();

TxTcpPacket(VmInterfaceGet(1)->id(), "10.10.10.10", "1.1.1.1", 10000, 179,
Expand All @@ -153,18 +151,17 @@ TEST_F(BgpServiceTest, Test_ttl_1) {
EXPECT_TRUE(fe != NULL);
EXPECT_TRUE(fe->reverse_flow_entry() != NULL);
EXPECT_TRUE(fe->is_flags_set(FlowEntry::BgpRouterService));
EXPECT_TRUE(fe->bgp_as_a_service_port() == 50000);
EXPECT_TRUE(fe->data().ttl == BGP_SERVICE_TTL_FWD_FLOW);
EXPECT_TRUE(fe->reverse_flow_entry()->data().ttl ==
BGP_SERVICE_TTL_REV_FLOW);

DeleteBgpPeer(peer);
client->WaitForIdle();
}

//TTL 64
TEST_F(BgpServiceTest, Test_ttl_2) {
AddAap("vnet1", 1, Ip4Address::from_string("10.10.10.10"), "00:00:01:01:01:01");
peer = CreateBgpPeer("127.0.0.1", "remote");
client->WaitForIdle();

TxTcpPacket(VmInterfaceGet(1)->id(), "10.10.10.10", "1.1.1.1", 10000, 179,
Expand All @@ -178,14 +175,10 @@ TEST_F(BgpServiceTest, Test_ttl_2) {
EXPECT_TRUE(fe->data().ttl == 0);
EXPECT_TRUE(fe->reverse_flow_entry()->data().ttl == 0);

DeleteBgpPeer(peer);
client->WaitForIdle();
}

TEST_F(BgpServiceTest, Test_1) {
peer = CreateBgpPeer("127.0.0.1", "remote");
client->WaitForIdle();

TxTcpPacket(VmInterfaceGet(1)->id(), "1.1.1.10", "1.1.1.1", 10000, 179,
false);
client->WaitForIdle();
Expand Down Expand Up @@ -242,14 +235,9 @@ TEST_F(BgpServiceTest, Test_1) {
EXPECT_TRUE(fe5->reverse_flow_entry() != NULL);
EXPECT_TRUE(fe5->is_flags_set(FlowEntry::BgpRouterService));

DeleteBgpPeer(peer);
client->WaitForIdle();
}

TEST_F(BgpServiceTest, Test_2) {
peer = CreateBgpPeer("127.0.0.1", "remote");
client->WaitForIdle();

TxTcpPacket(VmInterfaceGet(1)->id(), "1.1.1.10", "1.1.1.1", 10000, 179,
false);
client->WaitForIdle();
Expand All @@ -258,14 +246,12 @@ TEST_F(BgpServiceTest, Test_2) {
EXPECT_TRUE(fe != NULL);
EXPECT_TRUE(fe->reverse_flow_entry() != NULL);
EXPECT_TRUE(fe->is_flags_set(FlowEntry::BgpRouterService));
EXPECT_TRUE(fe->bgp_as_a_service_port() == 50000);

//Explicitly call deleteall on bgp service tree.
//agent_->pkt()->flow_mgmt_manager()->ControllerNotify(0);
//agent_->pkt()->flow_mgmt_manager()->ControllerNotify(1);
client->WaitForIdle();

DeleteBgpPeer(peer);
client->WaitForIdle();
}

TEST_F(BgpServiceTest, Test_3) {
Expand All @@ -275,7 +261,6 @@ TEST_F(BgpServiceTest, Test_3) {
AddAap("vnet4", 4, Ip4Address::from_string("40.40.40.40"), "00:00:04:04:04:04");
AddAap("vnet5", 5, Ip4Address::from_string("50.50.50.50"), "00:00:05:05:05:05");
AddAap("vnet6", 6, Ip4Address::from_string("60.60.60.60"), "00:00:06:06:06:06");
peer = CreateBgpPeer("127.0.0.1", "remote");
client->WaitForIdle();

TxTcpPacket(VmInterfaceGet(1)->id(), "10.10.10.10", "1.1.1.1", 10000, 179,
Expand All @@ -286,17 +271,56 @@ TEST_F(BgpServiceTest, Test_3) {
EXPECT_TRUE(fe != NULL);
EXPECT_TRUE(fe->reverse_flow_entry() != NULL);
EXPECT_TRUE(fe->is_flags_set(FlowEntry::BgpRouterService));
EXPECT_TRUE(fe->bgp_as_a_service_port() == 50000);
client->WaitForIdle();
}

DeleteBgpPeer(peer);
TEST_F(BgpServiceTest, Test_4) {
IFMapTable *table = IFMapTable::FindTable(agent_->db(),
"virtual-machine-interface");
IFMapNode *node = table->FindNode("vnet1");
if (node == NULL) {
assert(0);
}

InterfaceTable *intf_table = agent_->interface_table();

//simulate the same session add for the same vmi
DBRequest request1;
boost::uuids::uuid u;
intf_table->IFNodeToUuid(node, u);
intf_table->VmiProcessConfig(node, request1, u);

TaskScheduler *scheduler = TaskScheduler::GetInstance();
scheduler->Stop();
intf_table->Enqueue(&request1);

scheduler->Start();
client->WaitForIdle();

TxTcpPacket(VmInterfaceGet(1)->id(), "1.1.1.10", "1.1.1.1", 10000, 179,
false);
client->WaitForIdle();
FlowEntry *fe = FlowGet(VmInterfaceGet(1)->flow_key_nh()->id(),
"1.1.1.10", "1.1.1.1", 6, 10000, 179);
EXPECT_TRUE(fe != NULL);
EXPECT_TRUE(fe->reverse_flow_entry() != NULL);
EXPECT_TRUE(fe->is_flags_set(FlowEntry::BgpRouterService));
EXPECT_TRUE(fe->bgp_as_a_service_port() == 50000);
client->WaitForIdle();
}

int main(int argc, char *argv[]) {
int ret = 0;
BgpPeer *peer;
GETUSERARGS();
client = TestInit(init_file, ksync_init, true, true, true, 100*1000);
peer = CreateBgpPeer("127.0.0.1", "remote");
client->WaitForIdle();
ret = RUN_ALL_TESTS();
usleep(100000);
DeleteBgpPeer(peer);
client->WaitForIdle();
TestShutdown();
delete client;
return ret;
Expand Down

0 comments on commit 81bf092

Please sign in to comment.