Skip to content

Commit

Permalink
Add more information to ShowServiceChain introspect output
Browse files Browse the repository at this point in the history
Add the following information to output of ShowServiceChain:

- Address family to distinguish between inet and inet6
- Service chain address (even if service chain is pending)
- Pending reason (for pending service chains)

Change-Id: Ia4a044ecef43efccf8123367eac9de93043aef9b
Closes-Bug: 1637659
  • Loading branch information
Nischal Sheth committed Oct 28, 2016
1 parent aa7af80 commit 44a737a
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 32 deletions.
5 changes: 4 additions & 1 deletion src/bgp/routing-instance/iservice_chain_mgr.h
Expand Up @@ -8,6 +8,8 @@
#include <stddef.h>
#include <stdint.h>

#include <string>

class RoutingInstance;
class ServiceChainConfig;
class ShowServicechainInfo;
Expand All @@ -25,7 +27,8 @@ class IServiceChainMgr {
virtual bool IsQueueEmpty() const = 0;
virtual bool FillServiceChainInfo(RoutingInstance *rtinstance,
ShowServicechainInfo *info) const = 0;
virtual bool IsPending(RoutingInstance *rtinstance) const = 0;
virtual bool IsPending(RoutingInstance *rtinstance,
std::string *reason = NULL) const = 0;

private:
template <typename U> friend class ServiceChainIntegrationTest;
Expand Down
76 changes: 52 additions & 24 deletions src/bgp/routing-instance/service_chaining.cc
Expand Up @@ -947,15 +947,25 @@ void ServiceChainMgr<T>::Enqueue(ServiceChainRequestT *req) {
}

template <typename T>
bool ServiceChainMgr<T>::IsPending(RoutingInstance *rtinstance) const {
return pending_chains_.find(rtinstance) != pending_chains_.end();
bool ServiceChainMgr<T>::IsPending(RoutingInstance *rtinstance,
string *reason) const {
PendingServiceChainList::const_iterator loc =
pending_chains_.find(rtinstance);
if (loc != pending_chains_.end()) {
if (reason)
*reason = loc->second;
return true;
}
return false;
}

template <typename T>
bool ServiceChainMgr<T>::FillServiceChainInfo(RoutingInstance *rtinstance,
ShowServicechainInfo *info) const {
if (IsPending(rtinstance)) {
string pending_reason;
if (IsPending(rtinstance, &pending_reason)) {
info->set_state("pending");
info->set_pending_reason(pending_reason);
return true;
}
const ServiceChain<T> *service_chain = FindServiceChain(rtinstance);
Expand All @@ -970,7 +980,7 @@ bool ServiceChainMgr<T>::LocateServiceChain(RoutingInstance *rtinstance,
const ServiceChainConfig &config) {
CHECK_CONCURRENCY("bgp::Config", "bgp::ConfigHelper");

// Verify whether the entry already exists
// Verify whether the entry already exists.
tbb::mutex::scoped_lock lock(mutex_);
ServiceChainMap::iterator it = chain_set_.find(rtinstance);
if (it != chain_set_.end()) {
Expand All @@ -981,10 +991,11 @@ bool ServiceChainMgr<T>::LocateServiceChain(RoutingInstance *rtinstance,
return true;
}

// Entry already exists. Update of match condition
// The routing instance to pending resolve such that
// service chain is created after stop done cb
AddPendingServiceChain(rtinstance);
// Update of match condition.
// Add the routing instance to pending list so that service chain is
// created after stop done callback.
string reason = "Waiting for deletion of previous incarnation";
AddPendingServiceChain(rtinstance, reason);

if (it->second->deleted()) {
// Wait for the delete complete cb
Expand All @@ -1005,15 +1016,24 @@ bool ServiceChainMgr<T>::LocateServiceChain(RoutingInstance *rtinstance,
RoutingInstanceMgr *mgr = server_->routing_instance_mgr();
RoutingInstance *dest = mgr->GetRoutingInstance(config.routing_instance);

//
// Destination routing instance is not yet created.
// Or Destination routing instance is deleted Or
// virtual network index is not yet calculated (due missing virtual network
// link)
//
if (dest == NULL || dest->deleted() || !dest->virtual_network_index()) {
// Wait for the creation of RoutingInstance
AddPendingServiceChain(rtinstance);
// Destination routing instance does not exist.
if (!dest) {
string reason = "Destination routing instance does not exist";
AddPendingServiceChain(rtinstance, reason);
return false;
}

// Destination routing instance is being deleted.
if (dest->deleted()) {
string reason = "Destination routing instance is being deleted";
AddPendingServiceChain(rtinstance, reason);
return false;
}

// Destination virtual network index is unknown.
if (!dest->virtual_network_index()) {
string reason = "Destination virtual network index is unknown";
AddPendingServiceChain(rtinstance, reason);
return false;
}

Expand All @@ -1024,11 +1044,18 @@ bool ServiceChainMgr<T>::LocateServiceChain(RoutingInstance *rtinstance,
} else {
connected_ri = mgr->GetRoutingInstance(config.source_routing_instance);
}
// routing instance to search for connected route is not yet created.
if (connected_ri == NULL || connected_ri->deleted()) {
// Wait for the creation of RoutingInstance where connected route
// will be published
AddPendingServiceChain(rtinstance);

// Connected routing instance does not exist.
if (!connected_ri) {
string reason = "Connected routing instance does not exist";
AddPendingServiceChain(rtinstance, reason);
return false;
}

// Connected routing instance is being deleted.
if (connected_ri->deleted()) {
string reason = "Connected routing instance is being deleted";
AddPendingServiceChain(rtinstance, reason);
return false;
}

Expand All @@ -1037,7 +1064,8 @@ bool ServiceChainMgr<T>::LocateServiceChain(RoutingInstance *rtinstance,
AddressT chain_addr =
AddressT::from_string(config.service_chain_address, ec);
if (ec != 0) {
AddPendingServiceChain(rtinstance);
string reason = "Service chain address is invalid";
AddPendingServiceChain(rtinstance, reason);
return false;
}

Expand Down Expand Up @@ -1103,7 +1131,7 @@ bool ServiceChainMgr<T>::ResolvePendingServiceChain() {
it != pending_chains_.end(); it = next) {
next = it;
++next;
RoutingInstance *rtinstance = *it;
RoutingInstance *rtinstance = it->first;
pending_chains_.erase(it);
const ServiceChainConfig *sc_config =
rtinstance->config()->service_chain_info(GetFamily());
Expand Down
18 changes: 11 additions & 7 deletions src/bgp/routing-instance/service_chaining.h
Expand Up @@ -252,7 +252,8 @@ class ServiceChainMgr : public IServiceChainMgr {
virtual size_t ResolvedQueueSize() const { return chain_set_.size(); }
virtual uint32_t GetDownServiceChainCount() const;
virtual bool IsQueueEmpty() const { return process_queue_->IsQueueEmpty(); }
virtual bool IsPending(RoutingInstance *rtinstance) const;
virtual bool IsPending(RoutingInstance *rtinstance,
std::string *reason = NULL) const;

Address::Family GetFamily() const;
void Enqueue(ServiceChainRequestT *req);
Expand All @@ -270,18 +271,21 @@ class ServiceChainMgr : public IServiceChainMgr {
// Set of service chains created in the system
typedef std::map<RoutingInstance *, ServiceChainPtr> ServiceChainMap;

// At the time of processing, service chain request, all required
// routing instance may not be created. Create a list of service chain
// waiting for a routing instance to get created
typedef std::set<RoutingInstance *> PendingServiceChainList;
// At the time of processing, service chain request, all required info
// may not be available (e.g. dest routing instance may not be created,
// or marked deleted etc). Create a list of pending service chains that
// are waiting to get created and maintain a reason string for why the
// service chain is on the pending list.
typedef std::map<RoutingInstance *, std::string> PendingServiceChainList;

bool RequestHandler(ServiceChainRequestT *req);
void StopServiceChainDone(BgpTable *table, ConditionMatch *info);
ServiceChainT *FindServiceChain(const std::string &instance) const;
ServiceChainT *FindServiceChain(RoutingInstance *rtinstance) const;

void AddPendingServiceChain(RoutingInstance *rtinstance) {
pending_chains_.insert(rtinstance);
void AddPendingServiceChain(RoutingInstance *rtinstance,
std::string reason) {
pending_chains_.insert(std::make_pair(rtinstance, reason));
}
void DeletePendingServiceChain(RoutingInstance *rtinstance) {
pending_chains_.erase(rtinstance);
Expand Down
3 changes: 3 additions & 0 deletions src/bgp/routing-instance/service_chaining.sandesh
Expand Up @@ -29,10 +29,13 @@ struct ShowServicechainInfo {
7: string src_virtual_network;
8: string dest_virtual_network;
9: string service_instance;
12: string family;
1: string src_rt_instance;
11: string connected_rt_instance;
2: string dest_rt_instance;
13: string service_chain_addr;
10: string state;
14: string pending_reason;
3: ConnectedRouteInfo connected_route;
4: list<PrefixToRouteListInfo> more_specifics;
5: list<ExtConnectRouteInfo> ext_connecting_rt_info_list;
Expand Down
2 changes: 2 additions & 0 deletions src/bgp/routing-instance/show_service_chaining.cc
Expand Up @@ -39,6 +39,7 @@ static bool FillServiceChainInfo(Address::Family family,
if (!sc_config)
return false;

info.set_family(Address::FamilyToString(family));
info.set_src_virtual_network(rtinstance->GetVirtualNetworkName());
info.set_dest_virtual_network(GetVNFromRoutingInstance(
sc_config->routing_instance));
Expand All @@ -50,6 +51,7 @@ static bool FillServiceChainInfo(Address::Family family,
} else {
info.set_connected_rt_instance(sc_config->source_routing_instance);
}
info.set_service_chain_addr(sc_config->service_chain_address);

return service_chain_mgr->FillServiceChainInfo(rtinstance, &info);
}
Expand Down

0 comments on commit 44a737a

Please sign in to comment.