Skip to content

Commit

Permalink
Merge "Route present wih no paths." into R2.22.x
Browse files Browse the repository at this point in the history
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Apr 15, 2016
2 parents b0516d1 + 00f724f commit 0f1b569
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 20 deletions.
55 changes: 36 additions & 19 deletions src/vnsw/agent/oper/agent_route.cc
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ bool AgentRouteTable::DeleteAllBgpPath(DBTablePartBase *part,
DeletePathFromPeer(part, route, path);
to_be_deleted_path_list_it++;
}
route->SquashStalePaths(NULL);
SquashStalePaths(route, NULL);
}
return true;
}
Expand Down Expand Up @@ -255,7 +255,10 @@ void AgentRouteTable::DeletePathFromPeer(DBTablePartBase *part,
// For active peers reflector will remove the route but for
// non active peers explicitly squash the paths.
if (peer && (peer->GetType() != Peer::BGP_PEER)) {
rt->SquashStalePaths(NULL);
path = rt->FindStalePath();
if (path) {
rt->RemovePath(path);
}
}

// Delete route if no more paths
Expand Down Expand Up @@ -519,6 +522,24 @@ void AgentRouteTable::NotifyEntry(AgentRoute *e) {
tpart->Notify(e);
}

void AgentRouteTable::SquashStalePaths(AgentRoute *route,
const AgentPath *exception_path) {
Route::PathList::iterator it = route->GetPathList().begin();
AgentPath *path = NULL;
while (it != route->GetPathList().end()) {
path = static_cast<AgentPath *>(it.operator->());
// Delete all stale path except for the path sent(exception_path)
if (path->is_stale() && (path != exception_path)) {
// Since we squash stales, at any point of time there should be only
// one stale other than exception_path in list
break;
}
it++;
}
DeletePathFromPeer(route->get_table_partition(), route, path);
return;
}

uint32_t AgentRoute::GetActiveLabel() const {
return GetActivePath()->label();
};
Expand Down Expand Up @@ -581,6 +602,18 @@ AgentPath *AgentRoute::FindLocalVmPortPath() const {
return NULL;
}

AgentPath *AgentRoute::FindStalePath() {
Route::PathList::iterator it = GetPathList().begin();
while (it != GetPathList().end()) {
AgentPath *path = static_cast<AgentPath *>(it.operator->());
if (path->is_stale()) {
return path;
}
it++;
}
return NULL;
}

void AgentRoute::DeletePathInternal(AgentPath *path) {
AgentRouteTable *table = static_cast<AgentRouteTable *>(get_table());
table->DeletePathFromPeer(get_table_partition(), this, path);
Expand Down Expand Up @@ -616,22 +649,6 @@ AgentPath *AgentRoute::FindPath(const Peer *peer) const {
return NULL;
}

void AgentRoute::SquashStalePaths(const AgentPath *exception_path) {
Route::PathList::iterator it = GetPathList().begin();

while (it != GetPathList().end()) {
// Delete all stale path except for the path sent(exception_path)
AgentPath *path = static_cast<AgentPath *>(it.operator->());
if (path->is_stale() && (path != exception_path)) {
// Since we squash stales, at any point of time there should be only
// one stale other than exception_path in list
RemovePath(path);
return;
}
it++;
}
}

// First path in list is always treated as active path.
const AgentPath *AgentRoute::GetActivePath() const {
return static_cast<const AgentPath *>(front());
Expand Down Expand Up @@ -753,7 +770,7 @@ void AgentRouteTable::StalePathFromPeer(DBTablePartBase *part, AgentRoute *rt,
if (rt && (rt->IsDeleted() == false)) {
path->set_is_stale(true);
// Remove all stale path except the path received
rt->SquashStalePaths(path);
SquashStalePaths(rt, path);
rt->GetPathList().sort(&AgentRouteTable::PathSelection);
rt->Sync();
part->Notify(rt);
Expand Down
3 changes: 2 additions & 1 deletion src/vnsw/agent/oper/agent_route.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ class AgentRouteTable : public RouteTable {
//Stale path handling
void StalePathFromPeer(DBTablePartBase *part, AgentRoute *rt,
const Peer *peer);
void SquashStalePaths(AgentRoute *rt, const AgentPath *path);

private:
class DeleteActor;
Expand Down Expand Up @@ -253,6 +254,7 @@ class AgentRoute : public Route {
uint32_t vrf_id() const;

AgentPath *FindLocalVmPortPath() const;
AgentPath *FindStalePath();
const AgentPath *GetActivePath() const;
const NextHop *GetActiveNextHop() const;
const std::string &dest_vn_name() const;
Expand All @@ -262,7 +264,6 @@ class AgentRoute : public Route {
void ResyncTunnelNextHop();
bool HasUnresolvedPath();
bool Sync(void);
void SquashStalePaths(const AgentPath *path);

//TODO Move dependantroutes and nh to inet4
void UpdateDependantRoutes();// analogous to updategatewayroutes
Expand Down
40 changes: 40 additions & 0 deletions src/vnsw/agent/test/test_l2route.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1545,6 +1545,46 @@ TEST_F(RouteTest, add_local_peer_and_then_vm) {
bgp_peer.reset();
}

//Bug# 1562961
TEST_F(RouteTest, StalePathDeleteRouteDelete) {
struct PortInfo input[] = {
{"vnet1", 1, "1.1.1.10", "00:00:01:01:01:10", 1, 1},
};

client->Reset();
CreateVmportEnv(input, 1);
client->WaitForIdle();

//Add a peer and keep a reference of same.
BgpPeer *bgp_peer_ptr = CreateBgpPeer(Ip4Address(1), "BGP Peer1");
boost::shared_ptr<BgpPeer> bgp_peer =
bgp_peer_ptr->GetBgpXmppPeer()->bgp_peer_id_ref();

BridgeTunnelRouteAdd(bgp_peer_ptr, vrf_name_, TunnelType::MplsType(),
server1_ip_, MplsTable::kStartLabel + 10,
remote_vm_mac_, remote_vm_ip4_, 32);
client->WaitForIdle();

EvpnRouteEntry *rt = EvpnRouteGet(vrf_name_, remote_vm_mac_,
remote_vm_ip4_, 0);
EXPECT_TRUE(rt != NULL);
AgentPath *path = rt->FindPath(bgp_peer_ptr);
path->set_is_stale(true);
DelVrf(vrf_name_.c_str());
client->WaitForIdle();
rt = EvpnRouteGet(vrf_name_, remote_vm_mac_,
remote_vm_ip4_, 0);
EXPECT_TRUE(rt == NULL);

DeleteBgpPeer(bgp_peer.get());
client->WaitForIdle();
DeleteVmportEnv(input, 1, true);
client->WaitForIdle();
//Release VRF reference
bgp_peer.reset();
client->WaitForIdle();
}

int main(int argc, char *argv[]) {
::testing::InitGoogleTest(&argc, argv);
GETUSERARGS();
Expand Down

0 comments on commit 0f1b569

Please sign in to comment.