Skip to content

Commit

Permalink
Implement transit network functionality for service chaining
Browse files Browse the repository at this point in the history
Following changes have been implemented in control-node:

- Schema change to add allow-transit to VirtualNetworkType
- BGP instance config keeps track of allow-transit attribute
- RoutingInstance is updated with allow-transit from config
- Tweak service chaining code to re-originate routes that are
  in the dest routing instance, even if their OriginVn is not
  the same as dest instance.  This exception is made only if
  the VN of the dest instance is a transit VN. The OriginVn
  for such routes is set to be the VN for the dest instance.
- Handle changes in allow-transit attribute
- Add tests for the new functionality

Limitations (to be enforced in API server via follow-up commit):

- A VN cannot be connected directly to a transit VN - it must
  be connected via a chain of 1 or more services.
- The allow-transit attribtue can only be set when creating a
  VN, it cannot be updated later.

Change-Id: I9c81ba61a3bf0e8db04577b09ee26aa5aa60ad4d
Partial-Bug: 1365277
  • Loading branch information
Nischal Sheth committed Oct 6, 2014
1 parent 93b12df commit c296fa3
Show file tree
Hide file tree
Showing 10 changed files with 758 additions and 63 deletions.
19 changes: 18 additions & 1 deletion src/bgp/bgp_config.cc
Expand Up @@ -412,7 +412,10 @@ const string &BgpProtocolConfig::InstanceName() const {
// Constructor for BgpInstanceConfig.
//
BgpInstanceConfig::BgpInstanceConfig(const string &name)
: name_(name), protocol_(NULL), virtual_network_index_(0) {
: name_(name),
protocol_(NULL),
virtual_network_index_(0),
virtual_network_allow_transit_(false) {
}

//
Expand Down Expand Up @@ -504,6 +507,18 @@ static int GetVirtualNetworkIndex(DBGraph *graph, IFMapNode *node) {
return 0;
}

//
// Check if a virtual-network allows transit. The input IFMapNode represents
// the virtual-network.
//
static bool GetVirtualNetworkAllowTransit(DBGraph *graph, IFMapNode *node) {
const autogen::VirtualNetwork *vn =
static_cast<autogen::VirtualNetwork *>(node->GetObject());
if (vn && vn->IsPropertySet(autogen::VirtualNetwork::PROPERTIES))
return vn->properties().allow_transit;
return false;
}

//
// Update BgpInstanceConfig based on a new autogen::RoutingInstance object.
//
Expand Down Expand Up @@ -552,6 +567,8 @@ void BgpInstanceConfig::Update(BgpConfigManager *manager,
} else if (strcmp(adj->table()->Typename(), "virtual-network") == 0) {
virtual_network_ = adj->name();
virtual_network_index_ = GetVirtualNetworkIndex(graph, adj);
virtual_network_allow_transit_ =
GetVirtualNetworkAllowTransit(graph, adj);
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/bgp/bgp_config.h
Expand Up @@ -291,6 +291,9 @@ class BgpInstanceConfig {

const std::string &virtual_network() const { return virtual_network_; }
int virtual_network_index() const { return virtual_network_index_; }
bool virtual_network_allow_transit() const {
return virtual_network_allow_transit_;
}

IFMapNode *node() { return node_proxy_.node(); }
const std::string &name() const { return name_; }
Expand All @@ -313,6 +316,7 @@ class BgpInstanceConfig {
RouteTargetList export_list_;
std::string virtual_network_;
int virtual_network_index_;
bool virtual_network_allow_transit_;

boost::intrusive_ptr<const autogen::RoutingInstance> instance_config_;

Expand Down
25 changes: 23 additions & 2 deletions src/bgp/routing-instance/routing_instance.cc
Expand Up @@ -435,6 +435,7 @@ RoutingInstance::RoutingInstance(std::string name, BgpServer *server,
const BgpInstanceConfig *config)
: name_(name), index_(-1), mgr_(mgr), config_(config),
is_default_(false), virtual_network_index_(0),
virtual_network_allow_transit_(false),
deleter_(new DeleteActor(server, this)),
manager_delete_ref_(this, mgr->deleter()) {
peer_manager_.reset(BgpObjectFactory::Create<PeerManager>(this));
Expand All @@ -449,6 +450,7 @@ void RoutingInstance::ProcessConfig(BgpServer *server) {
// Initialize virtual network info.
virtual_network_ = config_->virtual_network();
virtual_network_index_ = config_->virtual_network_index();
virtual_network_allow_transit_ = config_->virtual_network_allow_transit();

std::vector<std::string> import_rt, export_rt;
BOOST_FOREACH(string irt, config_->import_list()) {
Expand Down Expand Up @@ -568,9 +570,24 @@ void RoutingInstance::UpdateConfig(BgpServer *server,
// new object.
config_ = cfg;

// Figure out if there's a significant configuration change that requires
// notifying routes to all listeners.
bool notify_routes = false;
if (virtual_network_allow_transit_ != cfg->virtual_network_allow_transit())
notify_routes = true;

// Trigger notification of all routes in each table.
if (notify_routes) {
BOOST_FOREACH(RouteTableList::value_type &entry, vrf_tables_) {
BgpTable *table = entry.second;
table->NotifyAllEntries();
}
}

// Update virtual network info.
virtual_network_ = cfg->virtual_network();
virtual_network_index_ = cfg->virtual_network_index();
virtual_network_allow_transit_ = cfg->virtual_network_allow_transit();

// Master routing instance doesn't have import & export list
// Master instance imports and exports all RT
Expand Down Expand Up @@ -777,6 +794,10 @@ int RoutingInstance::virtual_network_index() const {
return virtual_network_index_;
}

bool RoutingInstance::virtual_network_allow_transit() const {
return virtual_network_allow_transit_;
}

BgpServer *RoutingInstance::server() {
return mgr_->server();
}
Expand Down Expand Up @@ -917,7 +938,7 @@ BgpTable *RoutingInstance::ErmVpnTableCreate(BgpServer *server) {
}

void RoutingInstance::AddTable(BgpTable *tbl) {
vrf_table_.insert(std::make_pair(tbl->name(), tbl));
vrf_tables_.insert(std::make_pair(tbl->name(), tbl));
tbl->set_routing_instance(this);
RoutingInstanceInfo info = GetDataCollection("Add");
info.set_family(Address::FamilyToString(tbl->family()));
Expand All @@ -927,7 +948,7 @@ void RoutingInstance::AddTable(BgpTable *tbl) {
void RoutingInstance::RemoveTable(BgpTable *tbl) {
RoutingInstanceInfo info = GetDataCollection("Remove");
info.set_family(Address::FamilyToString(tbl->family()));
vrf_table_.erase(tbl->name());
vrf_tables_.erase(tbl->name());
ROUTING_INSTANCE_COLLECTOR_INFO(info);
}

Expand Down
7 changes: 5 additions & 2 deletions src/bgp/routing-instance/routing_instance.h
Expand Up @@ -53,7 +53,7 @@ class RoutingInstance {
virtual ~RoutingInstance();

const RouteTableList &GetTables() const {
return vrf_table_;
return vrf_tables_;
}

void ProcessConfig(BgpServer *server);
Expand Down Expand Up @@ -100,6 +100,7 @@ class RoutingInstance {
const BgpInstanceConfig *config() const { return config_; }
const std::string virtual_network() const;
int virtual_network_index() const;
bool virtual_network_allow_transit() const;

const RoutingInstanceMgr *manager() const { return mgr_; }
RoutingInstanceInfo GetDataCollection(const char *operation);
Expand Down Expand Up @@ -127,14 +128,15 @@ class RoutingInstance {
std::string name_;
int index_;
std::auto_ptr<RouteDistinguisher> rd_;
RouteTableList vrf_table_;
RouteTableList vrf_tables_;
RouteTargetList import_;
RouteTargetList export_;
RoutingInstanceMgr *mgr_;
const BgpInstanceConfig *config_;
bool is_default_;
std::string virtual_network_;
int virtual_network_index_;
bool virtual_network_allow_transit_;
boost::scoped_ptr<DeleteActor> deleter_;
LifetimeRef<RoutingInstance> manager_delete_ref_;
boost::scoped_ptr<StaticRouteMgr> static_route_mgr_;
Expand Down Expand Up @@ -243,6 +245,7 @@ class RoutingInstanceMgr {
size_t count() const { return instances_.count(); }
BgpServer *server() { return server_; }
LifetimeActor *deleter();

private:
friend class RoutingInstanceMgrTest;
class DeleteActor;
Expand Down
26 changes: 18 additions & 8 deletions src/bgp/routing-instance/service_chaining.cc
Expand Up @@ -114,10 +114,11 @@ bool ServiceChain::Match(BgpServer *server, BgpTable *table,
}
if (aggregate_enable() && is_more_specific(route, &aggregate_match)) {
// More specific
if (deleted)
if (deleted) {
type = ServiceChainRequest::MORE_SPECIFIC_DELETE;
else
} else {
type = ServiceChainRequest::MORE_SPECIFIC_ADD_CHG;
}
} else {
// External connecting routes
if (!deleted) {
Expand All @@ -130,15 +131,21 @@ bool ServiceChain::Match(BgpServer *server, BgpTable *table,
deleted = true;

int vn_index = GetOriginVnIndex(route);
if (!vn_index || dest_->virtual_network_index() != vn_index)
deleted = true;
int dest_vn_index = dest_->virtual_network_index();
if (!vn_index || dest_vn_index != vn_index) {
if (!dest_->virtual_network_allow_transit())
deleted = true;
if (!dest_vn_index)
deleted = true;
}
}
}

if (deleted)
if (deleted) {
type = ServiceChainRequest::EXT_CONNECT_ROUTE_DELETE;
else
} else {
type = ServiceChainRequest::EXT_CONNECT_ROUTE_ADD_CHG;
}
}
} else if ((table == connected_table()) &&
!connected_table_unregistered() &&
Expand All @@ -148,11 +155,13 @@ bool ServiceChain::Match(BgpServer *server, BgpTable *table,
deleted = true;
}
}

// Connected route for service chain
if (deleted)
if (deleted) {
type = ServiceChainRequest::CONNECTED_ROUTE_DELETE;
else
} else {
type = ServiceChainRequest::CONNECTED_ROUTE_ADD_CHG;
}
} else {
return false;
}
Expand Down Expand Up @@ -447,6 +456,7 @@ struct ServiceChainInfoComp {
if (lhs.service_instance != rhs.service_instance) {
return (lhs.service_instance < rhs.service_instance);
}

return false;
}
};
Expand Down
32 changes: 14 additions & 18 deletions src/bgp/routing-instance/service_chaining.h
Expand Up @@ -252,12 +252,13 @@ struct ServiceChainRequest {
ServiceChainRequest(RequestType type, BgpTable *table, BgpRoute *route,
Ip4Prefix aggregate_match, ServiceChainPtr info)
: type_(type), table_(table), rt_(route),
aggregate_match_(aggregate_match), info_(info) {
aggregate_match_(aggregate_match), info_(info), snh_resp_(NULL) {
}

ServiceChainRequest(RequestType type, SandeshResponse *resp)
: type_(type), snh_resp_(resp) {
: type_(type), table_(NULL), rt_(NULL), snh_resp_(resp) {
}

RequestType type_;
BgpTable *table_;
BgpRoute *rt_;
Expand All @@ -269,16 +270,12 @@ struct ServiceChainRequest {

class ServiceChainMgr {
public:
//
// 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 *> UnresolvedServiceChainList;

ServiceChainMgr(BgpServer *server);
Expand Down Expand Up @@ -331,33 +328,32 @@ class ServiceChainMgr {
void set_aggregate_host_route(bool value) {
aggregate_host_route_= value;
}

private:
//
// All service chain related actions are performed in the context
// of this task. This task has exclusion with DBTable task
//
friend class ServiceChainTest;

// All service chain related actions are performed in the context
// of this task. This task has exclusion with db::DBTable task.
static int service_chain_task_id_;

ServiceChainMap chain_set_;
int id_;
UnresolvedServiceChainList pending_chain_;
BgpServer *server_;
//
// Work Queue to handle requests posted from Match function(DBTable ctx)
// The actions are performed in the ServiceChain task ctx
//

// Work Queue to handle requests posted from Match function, called
// in the context of db::DBTable task.
// The actions are performed in the bgp::ServiceChain task context.
void DisableQueue() { process_queue_->set_disable(true); }
void EnableQueue() { process_queue_->set_disable(false); }

WorkQueue<ServiceChainRequest *> *process_queue_;

//
// Task trigger to resolve pending dependencies
//
// Task trigger to resolve pending dependencies.
boost::scoped_ptr<TaskTrigger> resolve_trigger_;

bool aggregate_host_route_;

DISALLOW_COPY_AND_ASSIGN(ServiceChainMgr);
};

#endif // ctrlplane_service_chaining_h

0 comments on commit c296fa3

Please sign in to comment.